/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/devel-api/object/property-helper-devel.h>
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/public-api/object/type-registry-helper.h>
-#include <dali/integration-api/adaptors/adaptor.h>
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-field-devel.h>
#include <dali-toolkit/public-api/visuals/visual-properties.h>
-#include <dali-toolkit/internal/controls/control/control-data-impl.h>
-#include <dali-toolkit/internal/controls/text-controls/autofill-container-impl.h>
#include <dali-toolkit/internal/text/text-enumerations-impl.h>
#include <dali-toolkit/internal/text/rendering/text-backend.h>
#include <dali-toolkit/internal/text/text-effects-style.h>
#include <dali-toolkit/internal/text/text-view.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
using namespace Dali::Toolkit::Text;
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandle", BOOLEAN, ENABLE_GRAB_HANDLE )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "matchSystemLanguageDirection", BOOLEAN, MATCH_SYSTEM_LANGUAGE_DIRECTION )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableGrabHandlePopup", BOOLEAN, ENABLE_GRAB_HANDLE_POPUP )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "textBackground", VECTOR4, BACKGROUND )
DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED )
}
case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
{
- if (impl.mController)
+ if( impl.mController )
{
const bool grabHandlePopupEnabled = value.Get<bool>();
DALI_LOG_INFO(gLogFilter, Debug::General, "TextField %p ENABLE_GRAB_HANDLE_POPUP %d\n", impl.mController.Get(), grabHandlePopupEnabled);
break;
}
}
+ case Toolkit::DevelTextField::Property::BACKGROUND:
+ {
+ if( impl.mController )
+ {
+ const Vector4 backgroundColor = value.Get< Vector4 >();
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p BACKGROUND %f,%f,%f,%f\n", impl.mController.Get(), backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a );
+
+ impl.mController->SetBackgroundEnabled( true );
+ impl.mController->SetBackgroundColor( backgroundColor );
+ }
+ break;
+ }
} // switch
} // textfield
}
}
case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
{
- if (impl.mController)
+ if( impl.mController )
{
value = impl.mController->IsGrabHandlePopupEnabled();
}
break;
}
+ case Toolkit::DevelTextField::Property::BACKGROUND:
+ {
+ if( impl.mController )
+ {
+ value = impl.mController->GetBackgroundColor();
+ }
+ break;
+ }
} //switch
}
}
}
-Text::ControllerPtr TextField::getController() { return mController; }
-
void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
{
Actor renderableActor;
if( renderableActor != mRenderableActor )
{
+ UnparentAndReset( mBackgroundActor );
UnparentAndReset( mRenderableActor );
mRenderableActor = renderableActor;
+
+ if ( mRenderableActor )
+ {
+ mBackgroundActor = mController->CreateBackgroundActor();
+ }
}
}
{
const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
+ float renderableActorPositionX, renderableActorPositionY;
+
if( mStencil )
{
- mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset, scrollOffset.y );
+ renderableActorPositionX = scrollOffset.x + mAlignmentOffset;
+ renderableActorPositionY = scrollOffset.y;
}
else
{
std::swap( padding.start, padding.end );
}
- mRenderableActor.SetPosition( scrollOffset.x + mAlignmentOffset + padding.start, scrollOffset.y + padding.top );
+ renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start;
+ renderableActorPositionY = scrollOffset.y + padding.top;
}
+ mRenderableActor.SetPosition( renderableActorPositionX, renderableActorPositionY );
// Make sure the actors are parented correctly with/without clipping
Actor self = mStencil ? mStencil : Self();
+ Actor highlightActor;
+
for( std::vector<Actor>::iterator it = mClippingDecorationActors.begin(),
endIt = mClippingDecorationActors.end();
it != endIt;
{
self.Add( *it );
it->LowerToBottom();
+
+ if ( it->GetName() == "HighlightActor" )
+ {
+ highlightActor = *it;
+ }
}
mClippingDecorationActors.clear();
self.Add( mRenderableActor );
+
+ if ( mBackgroundActor )
+ {
+ if ( mDecorator && mDecorator->IsHighlightVisible() )
+ {
+ self.Add( mBackgroundActor );
+ mBackgroundActor.SetPosition( renderableActorPositionX, renderableActorPositionY); // In text field's coords.
+ mBackgroundActor.LowerBelow( highlightActor );
+ }
+ else
+ {
+ mRenderableActor.Add( mBackgroundActor );
+ mBackgroundActor.SetPosition( 0.0f, 0.0f ); // In renderable actor's coords.
+ mBackgroundActor.LowerToBottom();
+ }
+ }
}
}
void TextField::OnKeyInputFocusGained()
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnKeyInputFocusGained %p\n", mController.Get() );
- if( mInputMethodContext )
+ if ( mInputMethodContext )
{
mInputMethodContext.ApplyOptions( mInputMethodOptions );
// When window gain lost focus, the inputMethodContext is deactivated. Thus when window gain focus again, the inputMethodContext must be activated.
mInputMethodContext.SetRestoreAfterFocusLost( true );
}
-
ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
- if( notifier )
+
+ if ( notifier )
{
notifier.ContentSelectedSignal().Connect( this, &TextField::OnClipboardTextSelected );
}
- Toolkit::Control control = Toolkit::Control::DownCast( Self() );
- Internal::Control& controlImpl = GetImplementation( control );
- Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
- bool enableAutofill = controlDataImpl.IsAutofillEnabled();
- if( enableAutofill )
- {
- Toolkit::AutofillContainer container = controlDataImpl.GetAutofillContainer();
- container.SetFocusedControl( control );
-
- Internal::AutofillContainer& containerImpl = GetImpl( container );
- Dali::AutofillGroup containerGroup = containerImpl.GetAutofillGroup();
- if( containerGroup != nullptr )
- {
- containerGroup.RequestAuthentication();
- }
-
- }
mController->KeyboardFocusGainEvent(); // Called in the case of no virtual keyboard to trigger this event
EmitKeyInputFocusSignal( true ); // Calls back into the Control hence done last.
RelayoutRequest();
}
-void TextField::TextInserted( unsigned int position, unsigned int length, const std::string &content )
-{
- if( Accessibility::IsUp() )
- {
- Control::Impl::GetAccessibilityObject( Self() )->EmitTextInserted( position, length, content );
- }
-}
-
-void TextField::TextDeleted( unsigned int position, unsigned int length, const std::string &content )
-{
- if( Accessibility::IsUp() )
- {
- Control::Impl::GetAccessibilityObject( Self() )->EmitTextDeleted( position, length, content );
- }
-}
-
-void TextField::CaretMoved( unsigned int position )
-{
- if( Accessibility::IsUp() )
- {
- Control::Impl::GetAccessibilityObject( Self() )->EmitTextCaretMoved( position );
- }
-}
-
void TextField::TextChanged()
{
Dali::Toolkit::TextField handle( GetOwner() );
mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ),
mHasBeenStaged( false )
{
- DevelControl::SetAccessibilityConstructor( Self(), []( Dali::Actor actor ) {
- return std::unique_ptr< Dali::Accessibility::Accessible >(
- new AccessibleImpl( actor, Dali::Accessibility::Role::ENTRY ) );
- } );
}
TextField::~TextField()
}
}
-std::string TextField::AccessibleImpl::GetName()
-{
- auto slf = Toolkit::TextField::DownCast( self );
- return slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get< std::string >();
-}
-
-std::string TextField::AccessibleImpl::GetText( size_t startOffset,
- size_t endOffset )
-{
- if( endOffset <= startOffset )
- return {};
-
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt =
- slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get< std::string >();
-
- if( startOffset > txt.size() || endOffset > txt.size() )
- return {};
-
- return txt.substr( startOffset, endOffset - startOffset );
-}
-
-size_t TextField::AccessibleImpl::GetCharacterCount()
-{
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt =
- slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get< std::string >();
-
- return txt.size();
-}
-
-size_t TextField::AccessibleImpl::GetCaretOffset()
-{
- auto slf = Toolkit::TextField::DownCast( self );
- return Dali::Toolkit::GetImpl( slf ).getController()->GetCursorPosition();
-}
-
-bool TextField::AccessibleImpl::SetCaretOffset(size_t offset)
-{
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt = slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get< std::string >();
- if (offset > txt.size())
- return false;
-
- auto& slfImpl = Dali::Toolkit::GetImpl( slf );
- slfImpl.getController()->ResetCursorPosition( offset );
- slfImpl.RequestTextRelayout();
- return true;
-}
-
-Dali::Accessibility::Range TextField::AccessibleImpl::GetTextAtOffset(
- size_t offset, Dali::Accessibility::TextBoundary boundary )
-{
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt = slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get< std::string >();
- auto txt_size = txt.size();
-
- auto range = Dali::Accessibility::Range{};
-
- switch(boundary)
- {
- case Dali::Accessibility::TextBoundary::CHARACTER:
- {
- if (offset < txt_size)
- {
- range.content = txt[offset];
- range.startOffset = offset;
- range.endOffset = offset + 1;
- }
- }
- break;
- case Dali::Accessibility::TextBoundary::WORD:
- case Dali::Accessibility::TextBoundary::LINE:
- {
- auto txt_c_string = txt.c_str();
- auto breaks = std::vector< char >( txt_size, 0 );
- if(boundary == Dali::Accessibility::TextBoundary::WORD)
- Accessibility::Accessible::FindWordSeparationsUtf8((const utf8_t *) txt_c_string, txt_size, "", breaks.data());
- else
- Accessibility::Accessible::FindLineSeparationsUtf8((const utf8_t *) txt_c_string, txt_size, "", breaks.data());
- auto index = 0u;
- auto counter = 0u;
- while( index < txt_size && counter <= offset )
- {
- auto start = index;
- if(breaks[index])
- {
- while(breaks[index])
- index++;
- counter++;
- }
- else
- {
- if (boundary == Dali::Accessibility::TextBoundary::WORD)
- index++;
- if (boundary == Dali::Accessibility::TextBoundary::LINE)
- counter++;
- }
- if ((counter - 1) == offset)
- {
- range.content = txt.substr(start, index - start + 1);
- range.startOffset = start;
- range.endOffset = index + 1;
- }
- if (boundary == Dali::Accessibility::TextBoundary::LINE)
- index++;
- }
- }
- break;
- case Dali::Accessibility::TextBoundary::SENTENCE:
- {
- /* not supported by efl */
- }
- break;
- case Dali::Accessibility::TextBoundary::PARAGRAPH:
- {
- /* Paragraph is not supported by libunibreak library */
- }
- break;
- default:
- break;
- }
-
- return range;
-}
-
-Dali::Accessibility::Range
-TextField::AccessibleImpl::GetSelection( size_t selectionNum )
-{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if( selectionNum > 0 )
- return {};
-
- auto slf = Toolkit::TextField::DownCast( self );
- auto ctrl = Dali::Toolkit::GetImpl( slf ).getController();
- std::string ret;
- ctrl->RetrieveSelection( ret );
- auto r = ctrl->GetSelectionIndexes();
-
- return { static_cast<size_t>(r.first), static_cast<size_t>(r.second), ret };
-}
-
-bool TextField::AccessibleImpl::RemoveSelection( size_t selectionNum )
-{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if( selectionNum > 0 )
- return false;
-
- auto slf = Toolkit::TextField::DownCast( self );
- Dali::Toolkit::GetImpl( slf ).getController()->SetSelection( 0, 0 );
- return true;
-}
-
-bool TextField::AccessibleImpl::SetSelection( size_t selectionNum,
- size_t startOffset,
- size_t endOffset )
-{
- // Since DALi supports only one selection indexes higher than 0 are ignored
- if( selectionNum > 0 )
- return false;
-
- auto slf = Toolkit::TextField::DownCast( self );
- Dali::Toolkit::GetImpl( slf ).getController()->SetSelection( startOffset,
- endOffset );
- return true;
-}
-
-bool TextField::AccessibleImpl::CopyText( size_t startPosition,
- size_t endPosition )
-{
- if( endPosition <= startPosition )
- return false;
-
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt = slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get<std::string>();
- Dali::Toolkit::GetImpl( slf ).getController()->CopyStringToClipboard( txt.substr(startPosition, endPosition - startPosition) );
-
- return true;
-}
-
-bool TextField::AccessibleImpl::CutText( size_t startPosition,
- size_t endPosition )
-{
- if( endPosition <= startPosition )
- return false;
-
- auto slf = Toolkit::TextField::DownCast( self );
- auto txt = slf.GetProperty( Toolkit::TextField::Property::TEXT ).Get<std::string>();
- Dali::Toolkit::GetImpl( slf ).getController()->CopyStringToClipboard( txt.substr(startPosition, endPosition - startPosition) );
-
- slf.SetProperty( Toolkit::TextField::Property::TEXT,
- txt.substr( 0, startPosition ) + txt.substr( endPosition - startPosition, txt.size()));
-
- return true;
-}
-
-Dali::Accessibility::States TextField::AccessibleImpl::CalculateStates()
-{
- auto states = Control::Impl::AccessibleImpl::CalculateStates();
- using namespace Dali::Accessibility;
- states[State::EDITABLE] = true;
- return states;
-}
-
} // namespace Internal
} // namespace Toolkit