#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>
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "verticalAlignment", STRING, VERTICAL_ALIGNMENT )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "textColor", VECTOR4, TEXT_COLOR )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholderTextColor", VECTOR4, PLACEHOLDER_TEXT_COLOR )
-DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowOffset", VECTOR2, SHADOW_OFFSET )
-DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowColor", VECTOR4, SHADOW_COLOR )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "reservedProperty01", STRING, RESERVED_PROPERTY_01 )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "reservedProperty02", STRING, RESERVED_PROPERTY_02 )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "primaryCursorColor", VECTOR4, PRIMARY_CURSOR_COLOR )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "secondaryCursorColor", VECTOR4, SECONDARY_CURSOR_COLOR )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "enableCursorBlink", BOOLEAN, ENABLE_CURSOR_BLINK )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "ellipsis", BOOLEAN, ELLIPSIS )
DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextField, "enableShiftSelection", BOOLEAN, ENABLE_SHIFT_SELECTION )
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_SIGNAL_REGISTRATION( Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED )
}
break;
}
- case Toolkit::TextField::Property::SHADOW_OFFSET:
- {
- if( impl.mController )
- {
- const Vector2& shadowOffset = value.Get< Vector2 >();
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_OFFSET %f,%f\n", impl.mController.Get(), shadowOffset.x, shadowOffset.y );
-
- if ( impl.mController->GetShadowOffset() != shadowOffset )
- {
- impl.mController->SetShadowOffset( shadowOffset );
- impl.mRenderer.Reset();
- }
- }
- break;
- }
- case Toolkit::TextField::Property::SHADOW_COLOR:
- {
- if( impl.mController )
- {
- const Vector4& shadowColor = value.Get< Vector4 >();
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p SHADOW_COLOR %f,%f,%f,%f\n", impl.mController.Get(), shadowColor.r, shadowColor.g, shadowColor.b, shadowColor.a );
-
- if ( impl.mController->GetShadowColor() != shadowColor )
- {
- impl.mController->SetShadowColor( shadowColor );
- impl.mRenderer.Reset();
- }
- }
- break;
- }
case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
{
if( impl.mDecorator )
}
break;
}
+ case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
+ {
+ if( impl.mController )
+ {
+ impl.mController->SetMatchSystemLanguageDirection(value.Get< bool >());
+ }
+ break;
+ }
+ case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
+ {
+ 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);
+
+ impl.mController->SetGrabHandlePopupEnabled(grabHandlePopupEnabled);
+ break;
+ }
+ }
} // switch
} // textfield
}
}
break;
}
- case Toolkit::TextField::Property::SHADOW_OFFSET:
- {
- if ( impl.mController )
- {
- value = impl.mController->GetShadowOffset();
- }
- break;
- }
- case Toolkit::TextField::Property::SHADOW_COLOR:
- {
- if ( impl.mController )
- {
- value = impl.mController->GetShadowColor();
- }
- break;
- }
case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR:
{
if( impl.mDecorator )
}
break;
}
+ case Toolkit::DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
+ {
+ if( impl.mController )
+ {
+ value = impl.mController->IsMatchSystemLanguageDirection();
+ }
+ break;
+ }
+ case Toolkit::DevelTextField::Property::ENABLE_GRAB_HANDLE_POPUP:
+ {
+ if (impl.mController)
+ {
+ value = impl.mController->IsGrabHandlePopupEnabled();
+ }
+ break;
+ }
} //switch
}
return value;
}
+void TextField::SelectWholeText()
+{
+ if( mController && mController->IsShowingRealText() )
+ {
+ mController->SelectEvent( 0.f, 0.f, true );
+ SetKeyInputFocus();
+ }
+}
+
InputMethodContext TextField::GetInputMethodContext()
{
return mInputMethodContext;
mDecorator = Text::Decorator::New( *mController,
*mController );
- mInputMethodContext = InputMethodContext::New();
+ mInputMethodContext = InputMethodContext::New( self );
mController->GetLayoutEngine().SetLayout( Layout::Engine::SINGLE_LINE_BOX );
mController->SetNoTextDoubleTapAction( Controller::NoTextTap::HIGHLIGHT );
mController->SetNoTextLongPressAction( Controller::NoTextTap::HIGHLIGHT );
+ // Sets layoutDirection value
+ Dali::Stage stage = Dali::Stage::GetCurrent();
+ Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( stage.GetRootLayer().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
+ mController->SetLayoutDirection( layoutDirection );
+
// Forward input events to controller
EnableGestureDetection( static_cast<Gesture::Type>( Gesture::Tap | Gesture::Pan | Gesture::LongPress ) );
GetTapGestureDetector().SetMaximumTapsRequired( 2 );
}
}
+Text::ControllerPtr TextField::getController() { return mController; }
+
void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
{
Actor renderableActor;
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 )
+ ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() );
+ 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