From: Nick Holland Date: Fri, 3 Oct 2014 06:02:18 +0000 (+0100) Subject: [dali_1.0.11] Merge branch 'tizen' X-Git-Tag: dali_1.0.14~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=9fd41afd0f3485f39fe161c28efdc88e1aa737f6;hp=ad9e64505734ea0a7b6f58198b8dd192e613ee6d [dali_1.0.11] Merge branch 'tizen' Change-Id: Ic0755bdcdfe5797697eece62d30aaa5f170d05c3 --- diff --git a/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt b/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt index a4ad16f..c58d7f2 100644 --- a/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-unmanaged/CMakeLists.txt @@ -50,6 +50,7 @@ SET(TC_SOURCES utc-Dali-ScrollViewEffect.cpp utc-Dali-TextInput.cpp utc-Dali-StyleManager.cpp + utc-Dali-RadioButton.cpp ) # Append list of test harness files (Won't get parsed for test cases) diff --git a/automated-tests/src/dali-toolkit-unmanaged/utc-Dali-RadioButton.cpp b/automated-tests/src/dali-toolkit-unmanaged/utc-Dali-RadioButton.cpp new file mode 100644 index 0000000..f39ce42 --- /dev/null +++ b/automated-tests/src/dali-toolkit-unmanaged/utc-Dali-RadioButton.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + + +using namespace Dali; +using namespace Dali::Toolkit; + +void dali_radio_button_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void dali_radio_button_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +static bool gObjectCreatedCallBackCalled; + +static void TestCallback(BaseHandle handle) +{ + gObjectCreatedCallBackCalled = true; +} + +} + +int UtcDaliRadioButtonNew(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliRadioButtonNew"); + + // Create the Slider actor + RadioButton radioButton; + + DALI_TEST_CHECK( !radioButton ); + + radioButton = RadioButton::New(); + + DALI_TEST_CHECK( radioButton ); + + RadioButton radioButton2(radioButton); + + DALI_TEST_CHECK( radioButton2 == radioButton ); + + //Additional check to ensure object is created by checking if it's registered + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + DALI_TEST_CHECK( registry ); + + gObjectCreatedCallBackCalled = false; + registry.ObjectCreatedSignal().Connect( &TestCallback ); + { + RadioButton radioButton = RadioButton::New(); + } + DALI_TEST_CHECK( gObjectCreatedCallBackCalled ); + END_TEST; +} + +int UtcDaliRadioButtonDestructor(void) +{ + ToolkitTestApplication application; + + RadioButton* radioButton = new RadioButton(); + delete radioButton; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +int UtcDaliRadioButtonDownCast(void) +{ + ToolkitTestApplication application; + + Handle handle = RadioButton::New(); + + RadioButton radioButton = RadioButton::DownCast( handle ); + + DALI_TEST_CHECK( radioButton == handle ); + END_TEST; +} + +int UtcDaliRadioButtonLabelActor(void) +{ + ToolkitTestApplication application; + + TextView actor1 = TextView::New( "test actor 1" ); + + RadioButton radioButton = RadioButton::New( actor1 ); + DALI_TEST_CHECK( actor1 == radioButton.GetLabel() ); + + TextView actor2 = TextView::New( "test actor 2" ); + radioButton.SetLabel( actor2 ); + DALI_TEST_CHECK( actor2 == radioButton.GetLabel() ); + + END_TEST; +} + +int UtcDaliRadioButtonActive(void) +{ + ToolkitTestApplication application; + + RadioButton radioButton = RadioButton::New(); + + // Default active + DALI_TEST_CHECK( radioButton.IsActive() == false ); + + // False to true + radioButton.ToggleState(); + DALI_TEST_CHECK( radioButton.IsActive() == true ); + + // True to false + radioButton.ToggleState(); + DALI_TEST_CHECK( radioButton.IsActive() == false ); + + // False + radioButton.SetActive( false ); + DALI_TEST_CHECK( radioButton.IsActive() == false ); + + // True + radioButton.SetActive( true ); + DALI_TEST_CHECK( radioButton.IsActive() == true ); + + // False + radioButton.SetActive( false ); + DALI_TEST_CHECK( radioButton.IsActive() == false ); + + END_TEST; +} + +int UtcDaliRadioButtonActiveProperty(void) +{ + ToolkitTestApplication application; // Exceptions require ToolkitTestApplication + tet_infoline(" UtcDaliRadioButtonActiveProperty"); + + // Create the RadioButton actor + RadioButton radioButton = RadioButton::New(); + Stage::GetCurrent().Add( radioButton ); + radioButton.SetParentOrigin(ParentOrigin::TOP_LEFT); + radioButton.SetAnchorPoint(ParentOrigin::TOP_LEFT); + radioButton.SetPosition( 0.0f, 0.0f ); + + // Default active + DALI_TEST_CHECK( radioButton.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + + // Setting false active + radioButton.SetProperty( RadioButton::PROPERTY_ACTIVE, false ); + DALI_TEST_CHECK( radioButton.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + + // Setting true active + radioButton.SetProperty( RadioButton::PROPERTY_ACTIVE, true ); + DALI_TEST_CHECK( radioButton.GetProperty( RadioButton::PROPERTY_ACTIVE ) == true ); + + // Setting false again + radioButton.SetProperty( RadioButton::PROPERTY_ACTIVE, false ); + DALI_TEST_CHECK( radioButton.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + + // Test selecting radio buttons + RadioButton radioButton2 = RadioButton::New( "label" ); + radioButton2.SetParentOrigin(ParentOrigin::TOP_LEFT); + radioButton2.SetAnchorPoint(ParentOrigin::TOP_LEFT); + radioButton2.SetPosition( 0.0f, 0.0f ); + + RadioButton radioButton3 = RadioButton::New( "label" ); + radioButton3.SetParentOrigin(ParentOrigin::TOP_LEFT); + radioButton3.SetAnchorPoint(ParentOrigin::TOP_LEFT); + radioButton3.SetPosition( 0.0f, 40.0f ); + + Actor radioGroup = Actor::New(); + Stage::GetCurrent().Add( radioGroup ); + radioGroup.SetParentOrigin(ParentOrigin::TOP_LEFT); + radioGroup.SetAnchorPoint(ParentOrigin::TOP_LEFT); + radioGroup.SetPosition( 0.0f, 0.0f ); + radioGroup.SetSize( 400.0f, 400.0 ); + + radioGroup.Add( radioButton2 ); + radioGroup.Add( radioButton3 ); + + application.SendNotification(); + application.Render(); + + // Simulate touch events + DALI_TEST_CHECK( radioButton2.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + DALI_TEST_CHECK( radioButton3.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + + // Select first radio + { + Dali::Integration::TouchEvent event = Dali::Integration::TouchEvent(); + + const Dali::TouchPoint pointUp( 0, TouchPoint::Up, 10.0f, 10.0f ); + event.AddPoint( pointUp ); + + application.ProcessEvent( event ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( radioButton2.GetProperty( RadioButton::PROPERTY_ACTIVE ) == true ); + DALI_TEST_CHECK( radioButton3.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + } + + // Select an already selected radio + { + Dali::Integration::TouchEvent event = Dali::Integration::TouchEvent(); + + const Dali::TouchPoint pointDown( 0, TouchPoint::Up, 10.0f, 10.0f ); + event.AddPoint( pointDown ); + + application.ProcessEvent( event ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( radioButton2.GetProperty( RadioButton::PROPERTY_ACTIVE ) == true ); + DALI_TEST_CHECK( radioButton3.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + } + + // Select second radio + { + Dali::Integration::TouchEvent event = Dali::Integration::TouchEvent(); + + const Dali::TouchPoint pointDown( 0, TouchPoint::Up, 10.0f, 50.0f ); + event.AddPoint( pointDown ); + + application.ProcessEvent( event ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( radioButton2.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + DALI_TEST_CHECK( radioButton3.GetProperty( RadioButton::PROPERTY_ACTIVE ) == true ); + } + + // Select outside radio group + { + Dali::Integration::TouchEvent event = Dali::Integration::TouchEvent(); + + const Dali::TouchPoint pointDown( 0, TouchPoint::Up, 10.0f, 500.0f ); + event.AddPoint( pointDown ); + + application.ProcessEvent( event ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( radioButton2.GetProperty( RadioButton::PROPERTY_ACTIVE ) == false ); + DALI_TEST_CHECK( radioButton3.GetProperty( RadioButton::PROPERTY_ACTIVE ) == true ); + } + + END_TEST; +} diff --git a/base/dali-toolkit/images/radio-button-active.png b/base/dali-toolkit/images/radio-button-active.png index a59c438..d49cbb5 100644 Binary files a/base/dali-toolkit/images/radio-button-active.png and b/base/dali-toolkit/images/radio-button-active.png differ diff --git a/base/dali-toolkit/images/radio-button-inactive.png b/base/dali-toolkit/images/radio-button-inactive.png index 04b05da..6f647e8 100644 Binary files a/base/dali-toolkit/images/radio-button-inactive.png and b/base/dali-toolkit/images/radio-button-inactive.png differ diff --git a/base/dali-toolkit/internal/builder/builder-animations.cpp b/base/dali-toolkit/internal/builder/builder-animations.cpp index 72911b8..de6b380 100644 --- a/base/dali-toolkit/internal/builder/builder-animations.cpp +++ b/base/dali-toolkit/internal/builder/builder-animations.cpp @@ -201,19 +201,19 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D } } - if( OptionalString endAction = constant.IsString( IsChild(child, "destroy-action" ) ) ) + if( OptionalString endAction = constant.IsString( IsChild(child, "disconnect-action" ) ) ) { if("BAKE" == *endAction) { - animation.SetDestroyAction( Animation::Bake ); + animation.SetDisconnectAction( Animation::Bake ); } else if("DISCARD" == *endAction) { - animation.SetDestroyAction( Animation::Discard ); + animation.SetDisconnectAction( Animation::Discard ); } else if("BAKE_FINAL" == *endAction) { - animation.SetDestroyAction( Animation::BakeFinal ); + animation.SetDisconnectAction( Animation::BakeFinal ); } } diff --git a/base/dali-toolkit/internal/controls/buttons/button-impl.cpp b/base/dali-toolkit/internal/controls/buttons/button-impl.cpp index ec78cba..90a741a 100644 --- a/base/dali-toolkit/internal/controls/buttons/button-impl.cpp +++ b/base/dali-toolkit/internal/controls/buttons/button-impl.cpp @@ -47,6 +47,7 @@ BaseHandle Create() TypeRegistration typeRegistration( typeid(Toolkit::Button), typeid(Toolkit::Control), Create ); SignalConnectorType signalConnector1( typeRegistration, Toolkit::Button::SIGNAL_CLICKED, &Button::DoConnectSignal ); +SignalConnectorType signalConnector2( typeRegistration, Toolkit::Button::SIGNAL_TOGGLED, &Button::DoConnectSignal ); PropertyRegistration property1( typeRegistration, "dimmed", Toolkit::Button::PROPERTY_DIMMED, Property::BOOLEAN, &Button::SetProperty, &Button::GetProperty ); @@ -106,6 +107,11 @@ Toolkit::Button::ClickedSignalV2& Button::ClickedSignal() return mClickedSignalV2; } +Toolkit::Button::ToggledSignalV2& Button::ToggledSignal() +{ + return mToggledSignalV2; +} + bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { Dali::BaseHandle handle( object ); @@ -117,6 +123,10 @@ bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tr { button.ClickedSignal().Connect( tracker, functor ); } + else if( Dali::Toolkit::Button::SIGNAL_TOGGLED == signalName ) + { + button.ToggledSignal().Connect( tracker, functor ); + } else { // signalName does not match any signal diff --git a/base/dali-toolkit/internal/controls/buttons/button-impl.h b/base/dali-toolkit/internal/controls/buttons/button-impl.h index e3763e4..2c45d7f 100644 --- a/base/dali-toolkit/internal/controls/buttons/button-impl.h +++ b/base/dali-toolkit/internal/controls/buttons/button-impl.h @@ -144,6 +144,11 @@ public: Toolkit::Button::ClickedSignalV2& ClickedSignal(); /** + * @copydoc Dali::Toolkit::Button::ToggledSignal() + */ + Toolkit::Button::ToggledSignalV2& ToggledSignal(); + + /** * Connects a callback function with the object's signals. * @param[in] object The object providing the signal. * @param[in] tracker Used to disconnect the signal. @@ -232,6 +237,7 @@ protected: // Signals ButtonPainterPtr mPainter; ///< Pointer to a ButtonPainter base class. Toolkit::Button::ClickedSignalV2 mClickedSignalV2; ///< Signal emitted when the button is clicked. + Toolkit::Button::ToggledSignalV2 mToggledSignalV2; ///< Signal emitted when the button is toggled. TapGestureDetector mTapDetector; }; diff --git a/base/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp b/base/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp index ea4909d..e252ea5 100644 --- a/base/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp +++ b/base/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp @@ -86,8 +86,8 @@ void CheckBoxButton::SetChecked( bool checked ) // Notifies the painter the checkbox has been checked. GetCheckBoxButtonPainter( mPainter )->Checked( handle ); - // Emit signal. - mClickedSignalV2.Emit( handle ); + // Raise toggled signal + mToggledSignalV2.Emit( handle, mChecked ); } } diff --git a/base/dali-toolkit/internal/controls/buttons/push-button-impl.cpp b/base/dali-toolkit/internal/controls/buttons/push-button-impl.cpp index 9d758b0..34245c2 100644 --- a/base/dali-toolkit/internal/controls/buttons/push-button-impl.cpp +++ b/base/dali-toolkit/internal/controls/buttons/push-button-impl.cpp @@ -59,9 +59,8 @@ BaseHandle Create() TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create ); -SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_TOGGLED , &PushButton::DoConnectSignal ); -SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal ); -SignalConnectorType signalConnector3( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal ); +SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal ); +SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal ); TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction ); @@ -356,11 +355,6 @@ Actor& PushButton::GetFadeOutButtonImage() return mFadeOutButtonImage; } -Toolkit::PushButton::ToggledSignalV2& PushButton::ToggledSignal() -{ - return mToggledSignalV2; -} - Toolkit::PushButton::PressedSignalV2& PushButton::PressedSignal() { return mPressedSignalV2; @@ -584,7 +578,7 @@ void PushButton::OnButtonUp() // Notifies the painter the button has been toggled. GetPushButtonPainter( mPainter )->Toggled( handle ); - //Emit signal. + // Emit signal. mToggledSignalV2.Emit( handle, mToggled ); } else diff --git a/base/dali-toolkit/internal/controls/buttons/push-button-impl.h b/base/dali-toolkit/internal/controls/buttons/push-button-impl.h index b4acfaf..a021683 100644 --- a/base/dali-toolkit/internal/controls/buttons/push-button-impl.h +++ b/base/dali-toolkit/internal/controls/buttons/push-button-impl.h @@ -242,11 +242,6 @@ public: // Signals /** - * @copydoc Dali::Toolkit::PushButton::ToggledSignal() - */ - Toolkit::PushButton::ToggledSignalV2& ToggledSignal(); - - /** * @copydoc Dali::Toolkit::PushButton::PressedSignal() */ Toolkit::PushButton::PressedSignalV2& PressedSignal(); @@ -399,7 +394,6 @@ private: bool mToggled; ///< Stores the toggle state. // Signals - Toolkit::PushButton::ToggledSignalV2 mToggledSignalV2; ///< Signal emitted when the button is toggled. Toolkit::PushButton::PressedSignalV2 mPressedSignalV2; ///< Signal emitted when the button is pressed. Toolkit::PushButton::ReleasedSignalV2 mReleasedSignalV2; ///< Signal emitted when the button is released. diff --git a/base/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp b/base/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp index 669394a..41e4a6f 100644 --- a/base/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp +++ b/base/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp @@ -40,18 +40,15 @@ BaseHandle Create() return Toolkit::RadioButton::New(); } -TypeRegistration typeRegistration(typeid (Toolkit::RadioButton ), typeid (Toolkit::Button ), Create); +TypeRegistration typeRegistration( typeid( Toolkit::RadioButton ), typeid( Toolkit::Button ), Create); PropertyRegistration property1(typeRegistration, "active", Toolkit::RadioButton::PROPERTY_ACTIVE, Property::BOOLEAN, &RadioButton::SetProperty, &RadioButton::GetProperty); PropertyRegistration property2(typeRegistration, "label-actor", Toolkit::RadioButton::PROPERTY_LABEL_ACTOR, Property::MAP, &RadioButton::SetProperty, &RadioButton::GetProperty); -} -namespace -{ const char* const INACTIVE_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "radio-button-inactive.png"; const char* const ACTIVE_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "radio-button-active.png"; -const Vector3 IMAGE_WIDTH(16.f, 0.f, 0.f); -const Vector3 DISTANCE_BETWEEN_IMAGE_AND_LABEL(5.f, 0.f, 0.f); + +const Vector3 DISTANCE_BETWEEN_IMAGE_AND_LABEL(5.0f, 0.0f, 0.0f); } Dali::Toolkit::RadioButton RadioButton::New() @@ -70,14 +67,12 @@ Dali::Toolkit::RadioButton RadioButton::New() } RadioButton::RadioButton() - : Button(), - mActive(false) + : mActive(false) { - mInactiveImage = Dali::Image::New(INACTIVE_BUTTON_IMAGE_DIR); - mActiveImage = Dali::Image::New(ACTIVE_BUTTON_IMAGE_DIR); + mInactiveImage = Dali::Image::New( INACTIVE_BUTTON_IMAGE_DIR ); + mActiveImage = Dali::Image::New( ACTIVE_BUTTON_IMAGE_DIR ); - mImageActor = Dali::ImageActor::New(mInactiveImage); - mLabel = Actor::New(); + mRadioIcon = Dali::ImageActor::New( mInactiveImage ); } RadioButton::~RadioButton() @@ -86,23 +81,40 @@ RadioButton::~RadioButton() void RadioButton::SetLabel(const std::string& label) { - mLabel.Reset(); - mLabel = Actor::New(); - - Toolkit::TextView textView = Toolkit::TextView::New(label); - textView.SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); // Make sure our text always fits inside the button - textView.SetAnchorPoint(AnchorPoint::TOP_LEFT); + TextActor textActor = TextActor::DownCast( mLabel ); + if( textActor ) + { + textActor.SetText( label ); + } + else + { + Toolkit::TextView newTextView = Toolkit::TextView::New( label ); + SetLabel( newTextView ); + } - mLabel.Add(textView); + RelayoutRequest(); } void RadioButton::SetLabel(Actor label) { if( mLabel != label ) { - Self().Remove(mLabel); + if( mLabel ) + { + mRadioIcon.Remove( mLabel ); + } + + if( label ) + { + label.SetParentOrigin( ParentOrigin::CENTER_RIGHT ); + label.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); + label.MoveBy( DISTANCE_BETWEEN_IMAGE_AND_LABEL ); + mRadioIcon.Add( label ); + } + mLabel = label; - Self().Add(mLabel); + + RelayoutRequest(); } } @@ -118,7 +130,6 @@ void RadioButton::SetActive(bool active) if( active ) { Actor parent = Self().GetParent(); - if( parent ) { for( unsigned int i = 0; i < parent.GetChildCount(); ++i ) @@ -131,14 +142,21 @@ void RadioButton::SetActive(bool active) } } } + mActive = true; - mImageActor.SetImage(mActiveImage); + mRadioIcon.SetImage(mActiveImage); } else { mActive = false; - mImageActor.SetImage(mInactiveImage); + mRadioIcon.SetImage(mInactiveImage); } + + // Raise toggled signal + Toolkit::RadioButton handle( GetOwner() ); + mToggledSignalV2.Emit( handle, mActive ); + + RelayoutRequest(); } } @@ -152,39 +170,63 @@ void RadioButton::ToggleState() SetActive(!mActive); } +void RadioButton::OnRelaidOut( Vector2 /*size*/, ActorSizeContainer& container ) +{ + Vector3 newSize( mRadioIcon.GetNaturalSize() ); + + if( mLabel ) + { + // Offset the label from the radio button image + newSize.width += DISTANCE_BETWEEN_IMAGE_AND_LABEL.width; + + // Find the size of the control using size negotiation + Vector3 actorNaturalSize( mLabel.GetNaturalSize() ); + Control::Relayout( mLabel, Vector2( actorNaturalSize.width, actorNaturalSize.height ), container ); + + Vector3 actorSize( mLabel.GetSize() ); + newSize.width += actorSize.width; + newSize.height = std::max( newSize.height, actorSize.height ); + } + + Self().SetSize( newSize ); +} + void RadioButton::OnInitialize() { - mImageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); - Self().Add(mImageActor); + mRadioIcon.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); + mRadioIcon.SetParentOrigin( ParentOrigin::CENTER_LEFT ); + Self().Add( mRadioIcon ); - mLabel.SetAnchorPoint(AnchorPoint::TOP_LEFT); - mLabel.MoveBy(IMAGE_WIDTH + DISTANCE_BETWEEN_IMAGE_AND_LABEL); - Self().Add(mLabel); + RelayoutRequest(); } void RadioButton::OnButtonUp() { - ToggleState(); + // Don't allow selection on an already active radio button + if( !mActive ) + { + ToggleState(); + } } void RadioButton::SetProperty(BaseObject* object, Property::Index propertyIndex, const Property::Value& value) { - Toolkit::RadioButton radioButton = Toolkit::RadioButton::DownCast(Dali::BaseHandle(object)); + Toolkit::RadioButton radioButton = Toolkit::RadioButton::DownCast( Dali::BaseHandle( object ) ); if( radioButton ) { - RadioButton & radioButtonImpl(GetImplementation(radioButton)); + RadioButton& radioButtonImpl( GetImplementation( radioButton ) ); switch ( propertyIndex ) { case Toolkit::RadioButton::PROPERTY_ACTIVE: { - radioButtonImpl.SetActive(value.Get< bool >( )); + radioButtonImpl.SetActive( value.Get< bool >( ) ); break; } case Toolkit::RadioButton::PROPERTY_LABEL_ACTOR: { - radioButtonImpl.SetLabel(Scripting::NewActor(value.Get< Property::Map >( ))); + radioButtonImpl.SetLabel( Scripting::NewActor( value.Get< Property::Map >( ) ) ); break; } } @@ -195,11 +237,11 @@ Property::Value RadioButton::GetProperty(BaseObject* object, Property::Index pro { Property::Value value; - Toolkit::RadioButton radioButton = Toolkit::RadioButton::DownCast(Dali::BaseHandle(object)); + Toolkit::RadioButton radioButton = Toolkit::RadioButton::DownCast( Dali::BaseHandle(object) ); if( radioButton ) { - RadioButton & radioButtonImpl(GetImplementation(radioButton)); + RadioButton& radioButtonImpl( GetImplementation( radioButton ) ); switch ( propertyIndex ) { @@ -211,7 +253,7 @@ Property::Value RadioButton::GetProperty(BaseObject* object, Property::Index pro case Toolkit::RadioButton::PROPERTY_LABEL_ACTOR: { Property::Map map; - Scripting::CreatePropertyMap(radioButtonImpl.mLabel, map); + Scripting::CreatePropertyMap( radioButtonImpl.mLabel, map ); value = map; break; } @@ -219,4 +261,4 @@ Property::Value RadioButton::GetProperty(BaseObject* object, Property::Index pro } return value; -} \ No newline at end of file +} diff --git a/base/dali-toolkit/internal/controls/buttons/radio-button-impl.h b/base/dali-toolkit/internal/controls/buttons/radio-button-impl.h index 1ee813f..5afa145 100644 --- a/base/dali-toolkit/internal/controls/buttons/radio-button-impl.h +++ b/base/dali-toolkit/internal/controls/buttons/radio-button-impl.h @@ -102,6 +102,11 @@ class RadioButton: public Button */ void ToggleState(); + /** + * @copydoc Dali::Toolkit::Control::OnRelaidOut(Vector2 size, ActorSizeContainer& container) + */ + virtual void OnRelaidOut( Vector2 size, ActorSizeContainer& container ); + public: // Properties @@ -138,7 +143,7 @@ class RadioButton: public Button Image mInactiveImage; ///< Stores the inactive image Image mActiveImage; ///< Stores the active image - ImageActor mImageActor; ///< Stores the current image + ImageActor mRadioIcon; ///< Stores the current image Actor mLabel; ///< Stores the button label bool mActive; ///< Stores the active state } ; @@ -168,4 +173,4 @@ inline const Toolkit::Internal::RadioButton& GetImplementation(const Toolkit::Ra } // namespace Toolkit } // namespace Dali -#endif // __DALI_TOOLKIT_INTERNAL_RADIO_BUTTON_H__ \ No newline at end of file +#endif // __DALI_TOOLKIT_INTERNAL_RADIO_BUTTON_H__ diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp index 69e02a8..d2c6c86 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp +++ b/base/dali-toolkit/internal/controls/text-input/text-input-impl.cpp @@ -100,7 +100,7 @@ std::size_t FindVisibleCharacterLeft( std::size_t cursorPosition, const Toolkit: --cursorPosition; } - return 0; + return 0u; } std::size_t FindVisibleCharacterRight( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable ) @@ -1851,7 +1851,7 @@ void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPo // Updates the cursor and grab handle position and visibility. if( mGrabHandle || mCursor ) { - cursorSize.height = GetRowRectFromCharacterPosition( GetVisualPosition( mCursorPosition ) ).height; + cursorSize.height = GetRowRectFromCharacterPosition( mCursorPosition ).height; const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition); mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( cursorPosition, cursorSize, controlSize ); @@ -1901,7 +1901,7 @@ void TextInput::ScrollTextViewToMakeCursorVisible( const Vector3& cursorPosition { // Scroll the text to make the cursor visible. const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( GetVisualPosition( mCursorPosition ) ).height ); + GetRowRectFromCharacterPosition( mCursorPosition ).height ); // Need to scroll the text to make the cursor visible and to cover the whole text-input area. @@ -2848,13 +2848,15 @@ void TextInput::AdvanceCursor(bool reverse, std::size_t places) } } -void TextInput::DrawCursor(const std::size_t nthChar) +void TextInput::DrawCursor() { + const Size rowRect = GetRowRectFromCharacterPosition( mCursorPosition ); + // Get height of cursor and set its size Size size( CURSOR_THICKNESS, 0.0f ); if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) { - size.height = GetRowRectFromCharacterPosition( GetVisualPosition( mCursorPosition ) ).height; + size.height = rowRect.height; } else { @@ -2869,7 +2871,7 @@ void TextInput::DrawCursor(const std::size_t nthChar) DALI_ASSERT_DEBUG( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - if ( ( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ) + if( ( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ) { Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. bool altPositionValid; // Alternate cursor validity flag. @@ -2878,7 +2880,7 @@ void TextInput::DrawCursor(const std::size_t nthChar) SetAltCursorEnabled( altPositionValid ); - if(!altPositionValid) + if( !altPositionValid ) { mCursor.SetPosition( position + UI_OFFSET ); } @@ -2886,13 +2888,12 @@ void TextInput::DrawCursor(const std::size_t nthChar) { size.height *= 0.5f; mCursor.SetSize(size); - mCursor.SetPosition( position + UI_OFFSET - Vector3(0.0f, directionRTL ? 0.0f : size.height, 0.0f) ); + mCursor.SetPosition( position + UI_OFFSET - Vector3( 0.0f, directionRTL ? 0.0f : size.height, 0.0f ) ); // TODO: change this cursor pos, to be the one where the cursor is sourced from. - Size rowSize = GetRowRectFromCharacterPosition( GetVisualPosition( mCursorPosition ) ); - size.height = rowSize.height * 0.5f; + size.height = rowRect.height * 0.5f; mCursorRTL.SetSize(size); - mCursorRTL.SetPosition( altPosition + UI_OFFSET - Vector3(0.0f, directionRTL ? size.height : 0.0f, 0.0f) ); + mCursorRTL.SetPosition( altPosition + UI_OFFSET - Vector3( 0.0f, directionRTL ? size.height : 0.0f, 0.0f ) ); } if( IsScrollEnabled() ) @@ -2970,14 +2971,26 @@ Vector3 TextInput::MoveGrabHandle( const Vector2& displacement ) std::size_t newCursorPosition = 0; ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY(), newCursorPosition ); - actualHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition ); + Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. + bool altPositionValid; // Alternate cursor validity flag. + bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) + actualHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition, directionRTL, altPosition, altPositionValid ); + + if( altPositionValid ) + { + // Check which of the positions is the closest. + if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( actualHandlePosition.x - mActualGrabHandlePosition.x ) ) + { + actualHandlePosition = altPosition; + } + } bool handleVisible = true; if( IsScrollEnabled() ) { const Vector3 controlSize = GetControlSize(); - const Size cursorSize = GetRowRectFromCharacterPosition( GetVisualPosition( newCursorPosition ) ); + const Size cursorSize = GetRowRectFromCharacterPosition( newCursorPosition ); // Scrolls the text if the handle is not in a visible position handleVisible = IsPositionInsideBoundaries( actualHandlePosition, cursorSize, @@ -3270,7 +3283,7 @@ Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector { mCurrentSelectionId = handleId; - cursorSize.height = GetRowRectFromCharacterPosition( GetVisualPosition( newHandlePosition ) ).height; + cursorSize.height = GetRowRectFromCharacterPosition( newHandlePosition ).height; // Restricts the movement of the grab handle inside the boundaries of the text-input. handleVisible = IsPositionInsideBoundaries( actualHandlePosition, cursorSize, @@ -3341,7 +3354,6 @@ Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) { - const std::size_t selectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; ImageActor selectionHandleActor = ( handleId == HandleOne ) ? mSelectionHandleOne : mSelectionHandleTwo; @@ -3354,7 +3366,7 @@ void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) if( IsScrollEnabled() ) { const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( GetVisualPosition( selectionHandlePosition ) ).height ); + GetRowRectFromCharacterPosition( selectionHandlePosition ).height ); selectionHandleActor.SetVisible( IsPositionInsideBoundaries( actualHandlePosition, cursorSize, GetControlSize() ) ); @@ -3362,15 +3374,6 @@ void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) } } -std::size_t TextInput::GetVisualPosition(std::size_t logicalPosition) const -{ - // Note: we're allowing caller to request a logical position of size (i.e. end of string) - // For now the visual position of end of logical string will be end of visual string. - DALI_ASSERT_DEBUG( logicalPosition <= mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ); - - return logicalPosition != mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ? mTextLayoutInfo.mCharacterLogicalToVisualMap[logicalPosition] : mTextLayoutInfo.mCharacterLogicalToVisualMap.size(); -} - void TextInput::GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection) { std::vector::iterator it = mTextLayoutInfo.mCharacterLogicalToVisualMap.begin(); @@ -3790,7 +3793,7 @@ void TextInput::ShowPopupCutCopyPaste() mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); } - if ( !mStyledText.empty() ) + if ( !mStyledText.empty() && IsTextSelected() ) { mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCopy, true ); mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, true ); @@ -3817,7 +3820,7 @@ void TextInput::SetUpPopupSelection( bool showCutButton ) { mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelect, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, showCutButton ); + mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, ( showCutButton && IsTextSelected() ) ); } // if clipboard has valid contents then offer paste option if( mClipboard && mClipboard.NumberOfItems() ) @@ -3895,15 +3898,16 @@ bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIn } else { - std::vector::const_iterator it = matchedCharacters.begin(); - std::vector::const_iterator endIt = matchedCharacters.end(); + // 2 Iterate through matching list of y positions and find closest matching X position. bool matched( false ); - // 2 Iterate through matching list of y positions and find closest matching X position. - for( ; it != endIt; ++it ) + // Traverse the characters in the visual order. VCC TODO: check for more than one line. + std::size_t visualIndex = 0u; + const std::size_t matchedCharactersSize = matchedCharacters.size(); + for( ; visualIndex < matchedCharactersSize; ++visualIndex ) { - const Toolkit::TextView::CharacterLayoutInfo& info( *it ); + const Toolkit::TextView::CharacterLayoutInfo& info( *( matchedCharacters.begin() + mTextLayoutInfo.mCharacterVisualToLogicalMap[visualIndex] ) ); if( info.mIsVisible ) { @@ -3924,16 +3928,15 @@ bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIn } } - if( it == endIt ) + if( visualIndex == matchedCharactersSize ) { rightToLeftChar = lastRightToLeftChar; } - std::size_t matchCharacterIndex = it - matchedCharacters.begin(); - closestIndex = lineOffset + matchCharacterIndex; + closestIndex = lineOffset + visualIndex; mClosestCursorPositionEOL = false; // reset - if ( it == endIt && !matched ) + if( ( visualIndex == matchedCharactersSize ) && !matched ) { mClosestCursorPositionEOL = true; // Reached end of matched characters in closest line but no match so cursor should be after last character. } @@ -4072,104 +4075,132 @@ Vector3 TextInput::PositionCursorAfterWordWrap( std::size_t characterPosition ) /* Word wrap occurs automatically in TextView when the exceed policy moves a word to the next line when not enough space on current. A newline character is not inserted in this case */ - DALI_ASSERT_DEBUG( !(characterPosition <= 0 )); - Vector3 cursorPosition; - Toolkit::TextView::CharacterLayoutInfo currentCharInfo; - - if ( characterPosition == mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - // end character so use - currentCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition - 1 ]; - cursorPosition = Vector3(currentCharInfo.mPosition.x + currentCharInfo.mSize.width, currentCharInfo.mPosition.y, currentCharInfo.mPosition.z) ; - } - else - { - currentCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - } + Toolkit::TextView::CharacterLayoutInfo currentCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - Toolkit::TextView::CharacterLayoutInfo previousCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition - 1]; + bool noWrap = true; - // If previous character on a different line then use current characters position - if ( fabsf( (currentCharInfo.mPosition.y - currentCharInfo.mDescender ) - ( previousCharInfo.mPosition.y - previousCharInfo.mDescender) ) > Math::MACHINE_EPSILON_1000 ) + if( characterPosition > 0u ) { - if ( mClosestCursorPositionEOL ) - { - cursorPosition = Vector3(previousCharInfo.mPosition.x + previousCharInfo.mSize.width, previousCharInfo.mPosition.y, previousCharInfo.mPosition.z) ; - } - else + Toolkit::TextView::CharacterLayoutInfo previousCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition - 1u ]; + + // If previous character on a different line then use current characters position + if( fabsf( (currentCharInfo.mPosition.y - currentCharInfo.mDescender ) - ( previousCharInfo.mPosition.y - previousCharInfo.mDescender) ) > Math::MACHINE_EPSILON_1000 ) { - cursorPosition = Vector3(currentCharInfo.mPosition); + // VCC TODO: PositionCursorAfterWordWrap currently doesn't work for multiline. Need to check this branch. + if ( mClosestCursorPositionEOL ) + { + cursorPosition = Vector3( previousCharInfo.mPosition.x + previousCharInfo.mSize.width, previousCharInfo.mPosition.y, previousCharInfo.mPosition.z ) ; + } + else + { + cursorPosition = Vector3( currentCharInfo.mPosition ); + } + + noWrap = false; } } - else + + if( noWrap ) { - // Previous character is on same line so use position of previous character plus it's width. - cursorPosition = Vector3(previousCharInfo.mPosition.x + previousCharInfo.mSize.width, previousCharInfo.mPosition.y, previousCharInfo.mPosition.z) ; + // If the character is left to right, the position is the character's position plus its width. + const float ltrOffset = !currentCharInfo.mIsRightToLeftCharacter ? currentCharInfo.mSize.width : 0.f; + + cursorPosition.x = currentCharInfo.mPosition.x + ltrOffset; + cursorPosition.y = currentCharInfo.mPosition.y; } return cursorPosition; } -Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterPosition) const +Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition ) const { - bool direction(false); + bool direction = false; Vector3 alternatePosition; - bool alternatePositionValid(false); + bool alternatePositionValid = false; return GetActualPositionFromCharacterPosition( characterPosition, direction, alternatePosition, alternatePositionValid ); } -Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const +Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const { + DALI_ASSERT_DEBUG( ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) && + ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterVisualToLogicalMap.size() ) && + "TextInput::GetActualPositionFromCharacterPosition. All layout tables must have the same size." ); + Vector3 cursorPosition( 0.f, 0.f, 0.f ); alternatePositionValid = false; directionRTL = false; - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) + if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) { - std::size_t visualCharacterPosition; + if( characterPosition == 0u ) + { + // When the cursor position is at the beginning, it should be at the start of the current character. + // If the current character is LTR, then the start is on the right side of the glyph. + // If the current character is RTL, then the start is on the left side of the glyph. + + if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() ) ).mIsVisible ) + { + characterPosition = FindVisibleCharacter( Right, 0u ); + } - // When cursor is not at beginning, consider possibility of - // showing 2 cursors. (whereas at beginning we only ever show one cursor) - if(characterPosition > 0) + const Toolkit::TextView::CharacterLayoutInfo& info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; + const float rtlOffset = info.mIsRightToLeftCharacter ? info.mSize.width : 0.0f; + + cursorPosition.x = info.mPosition.x + rtlOffset; + cursorPosition.y = info.mPosition.y; + directionRTL = info.mIsRightToLeftCharacter; + } + else if( characterPosition > 0u ) { + // Get the direction of the paragraph. + const std::size_t startCharacterPosition = GetRowStartFromCharacterPosition( characterPosition ); + const bool isParagraphRightToLeft = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + startCharacterPosition ) ).mIsRightToLeftCharacter; + + // When cursor is not at beginning, consider possibility of + // showing 2 cursors. (whereas at beginning we only ever show one cursor) + // Cursor position should be the end of the last character. // If the last character is LTR, then the end is on the right side of the glyph. // If the last character is RTL, then the end is on the left side of the glyph. - visualCharacterPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[ characterPosition - 1 ]; - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + visualCharacterPosition ) ).mIsVisible ) + --characterPosition; + + if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition ) ).mIsVisible ) { - visualCharacterPosition = FindVisibleCharacter( Left, visualCharacterPosition ); + characterPosition = FindVisibleCharacter( Left, characterPosition ); } - Toolkit::TextView::CharacterLayoutInfo info = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterPosition ]; - if( ( visualCharacterPosition > 0 ) && info.mIsNewParagraphChar && !IsScrollEnabled() ) + Toolkit::TextView::CharacterLayoutInfo info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; + if( ( characterPosition > 0u ) && info.mIsNewParagraphChar && !IsScrollEnabled() ) { + // VCC TODO : check for a new paragraph character. + // Prevents the cursor to exceed the boundary if the last visible character is a 'new line character' and the scroll is not enabled. const Vector3& size = GetControlSize(); if( info.mPosition.y + info.mSize.height - mDisplayedTextView.GetLineHeightOffset() > size.height ) { - --visualCharacterPosition; + --characterPosition; } - info = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterPosition ]; + info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; } - if(!info.mIsNewParagraphChar) + if( !info.mIsNewParagraphChar ) { cursorPosition = PositionCursorAfterWordWrap( characterPosition ); // Get position of cursor/handles taking in account auto word wrap. } else { + // VCC TODO : check for a new paragraph character. + // When cursor points to first character on new line, position cursor at the start of this glyph. - if(characterPosition < mTextLayoutInfo.mCharacterLogicalToVisualMap.size()) + if( characterPosition < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) { - std::size_t visualCharacterNextPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[ characterPosition ]; - const Toolkit::TextView::CharacterLayoutInfo& infoNext = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterNextPosition ]; + const Toolkit::TextView::CharacterLayoutInfo& infoNext = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; const float start( infoNext.mIsRightToLeftCharacter ? infoNext.mSize.width : 0.0f ); cursorPosition.x = infoNext.mPosition.x + start; @@ -4181,12 +4212,12 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterP // cursor where the new line starts based on the line-justification position. cursorPosition.x = GetLineJustificationPosition(); - if(characterPosition == mTextLayoutInfo.mCharacterLogicalToVisualMap.size()) + if( characterPosition == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) { // If this is after the last character, then we can assume that the new cursor // should be exactly one row below the current row. - const Size rowRect(GetRowRectFromCharacterPosition(characterPosition - 1)); + const Size rowRect = GetRowRectFromCharacterPosition( characterPosition - 1u ); cursorPosition.y = info.mPosition.y + rowRect.height; } else @@ -4194,7 +4225,7 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterP // If this is not after last character, then we can use this row's height. // should be exactly one row below the current row. - const Size rowRect(GetRowRectFromCharacterPosition(characterPosition)); + const Size rowRect = GetRowRectFromCharacterPosition( characterPosition ); cursorPosition.y = info.mPosition.y + rowRect.height; } } @@ -4202,104 +4233,87 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterP directionRTL = info.mIsRightToLeftCharacter; - // 1. When the cursor is neither at the beginning or the end, - // we can show multiple cursors under situations when the cursor is - // between RTL and LTR text... - if(characterPosition != mTextLayoutInfo.mCharacterLogicalToVisualMap.size()) + if( 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) { - std::size_t visualCharacterAltPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[characterPosition]; // VCC TODO: find why in the previous patch it was a -1 here. + // 1. When the cursor is neither at the beginning or the end, + // we can show multiple cursors under situations when the cursor is + // between RTL and LTR text... + if( characterPosition + 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) + { + std::size_t characterAltPosition = characterPosition + 1u; - DALI_ASSERT_ALWAYS(visualCharacterAltPosition < mTextLayoutInfo.mCharacterLayoutInfoTable.size()); - const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterAltPosition ]; + const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterAltPosition ]; - if(!info.mIsRightToLeftCharacter && infoAlt.mIsRightToLeftCharacter) - { - // Stuation occurs when cursor is at the end of English text (LTR) and beginning of Arabic (RTL) - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x + infoAlt.mSize.width; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; + if(!info.mIsRightToLeftCharacter && infoAlt.mIsRightToLeftCharacter) + { + // Stuation occurs when cursor is at the end of English text (LTR) and beginning of Arabic (RTL) + // Text: [...LTR...]|[...RTL...] + // Cursor pos: ^ + // Alternate cursor pos: ^ + // In which case we need to display an alternate cursor for the RTL text. + + alternatePosition.x = infoAlt.mPosition.x + infoAlt.mSize.width; + alternatePosition.y = infoAlt.mPosition.y; + alternatePositionValid = true; + } + else if(info.mIsRightToLeftCharacter && !infoAlt.mIsRightToLeftCharacter) + { + // Situation occurs when cursor is at end of the Arabic text (LTR) and beginning of English (RTL) + // Text: |[...RTL...] [...LTR....] + // Cursor pos: ^ + // Alternate cursor pos: ^ + // In which case we need to display an alternate cursor for the RTL text. + + alternatePosition.x = infoAlt.mPosition.x; + alternatePosition.y = infoAlt.mPosition.y; + alternatePositionValid = true; + } } - else if(info.mIsRightToLeftCharacter && !infoAlt.mIsRightToLeftCharacter) + else { - // Situation occurs when cursor is at end of the Arabic text (LTR) and beginning of English (RTL) - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - } - else - { - // 2. When the cursor is at the end of the text, - // and we have multi-directional text, - // we can also consider showing mulitple cursors. - // The rule here is: - // If first and last characters on row are different - // Directions, then two cursors need to be displayed. - - // Get first logical glyph on row - std::size_t startCharacterPosition = GetRowStartFromCharacterPosition( characterPosition - 1 ); + // 2. When the cursor is at the end of the text, + // and we have multi-directional text, + // we can also consider showing mulitple cursors. + // The rule here is: + // If first and last characters on row are different + // Directions, then two cursors need to be displayed. + + if( info.mIsRightToLeftCharacter != isParagraphRightToLeft ) + { + // The last character's direction is differernt than the first one of current paragraph. - std::size_t visualCharacterStartPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[ startCharacterPosition ]; - const Toolkit::TextView::CharacterLayoutInfo& infoStart= mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterStartPosition ]; + // Get first + const Toolkit::TextView::CharacterLayoutInfo& infoStart= mTextLayoutInfo.mCharacterLayoutInfoTable[ GetFirstCharacterWithSameDirection( characterPosition ) ]; - if(info.mIsRightToLeftCharacter && !infoStart.mIsRightToLeftCharacter) - { - // For text Starting as LTR and ending as RTL. End cursor position is as follows: - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text, this cursor - // should be at the end of the given line. - - const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1 ]; - alternatePosition.x = infoAlt.mPosition.x + infoAlt.mSize.width; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - else if(!info.mIsRightToLeftCharacter && infoStart.mIsRightToLeftCharacter) // starting RTL - { - // For text Starting as RTL and ending as LTR. End cursor position is as follows: - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ startCharacterPosition ]; - alternatePosition.x = infoAlt.mPosition.x; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; + if(info.mIsRightToLeftCharacter) + { + // For text Starting as LTR and ending as RTL. End cursor position is as follows: + // Text: [...LTR...]|[...RTL...] + // Cursor pos: ^ + // Alternate cursor pos: ^ + // In which case we need to display an alternate cursor for the RTL text, this cursor + // should be at the end of the given line. + + alternatePosition.x = infoStart.mPosition.x + infoStart.mSize.width; + alternatePosition.y = infoStart.mPosition.y; + alternatePositionValid = true; + } + else if(!info.mIsRightToLeftCharacter) // starting RTL + { + // For text Starting as RTL and ending as LTR. End cursor position is as follows: + // Text: |[...RTL...] [...LTR....] + // Cursor pos: ^ + // Alternate cursor pos: ^ + // In which case we need to display an alternate cursor for the RTL text. + + alternatePosition.x = infoStart.mPosition.x; + alternatePosition.y = infoStart.mPosition.y; + alternatePositionValid = true; + } + } } } } // characterPosition > 0 - else if(characterPosition == 0) - { - // When the cursor position is at the beginning, it should be at the start of the current character. - // If the current character is LTR, then the start is on the right side of the glyph. - // If the current character is RTL, then the start is on the left side of the glyph. - visualCharacterPosition = mTextLayoutInfo.mCharacterLogicalToVisualMap[ characterPosition ]; - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + visualCharacterPosition ) ).mIsVisible ) - { - visualCharacterPosition = FindVisibleCharacter( Right, visualCharacterPosition ); - } - - const Toolkit::TextView::CharacterLayoutInfo& info = mTextLayoutInfo.mCharacterLayoutInfoTable[ visualCharacterPosition ]; - const float start(info.mIsRightToLeftCharacter ? info.mSize.width : 0.0f); - - cursorPosition.x = info.mPosition.x + start; - cursorPosition.y = info.mPosition.y; - directionRTL = info.mIsRightToLeftCharacter; - } } else { @@ -4352,14 +4366,30 @@ Vector3 TextInput::GetActualPositionFromCharacterPosition(std::size_t characterP return cursorPosition; } -std::size_t TextInput::GetRowStartFromCharacterPosition(std::size_t logicalPosition) const +std::size_t TextInput::GetRowStartFromCharacterPosition( std::size_t logicalPosition ) const { // scan string from current position to beginning of current line to note direction of line - while(logicalPosition) + while( logicalPosition ) + { + logicalPosition--; + if( mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsNewParagraphChar ) + { + logicalPosition++; + break; + } + } + + return logicalPosition; +} + +std::size_t TextInput::GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const +{ + const bool isRightToLeft = mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter; + + while( logicalPosition ) { logicalPosition--; - std::size_t visualPosition = GetVisualPosition(logicalPosition); - if(mTextLayoutInfo.mCharacterLayoutInfoTable[visualPosition].mIsNewParagraphChar) + if( isRightToLeft != mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter ) { logicalPosition++; break; @@ -4376,7 +4406,7 @@ Size TextInput::GetRowRectFromCharacterPosition(std::size_t characterPosition) c return GetRowRectFromCharacterPosition( characterPosition, min, max ); } -Size TextInput::GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const +Size TextInput::GetRowRectFromCharacterPosition( std::size_t characterPosition, Vector2& min, Vector2& max ) const { // if we have no text content, then return position 0,0 with width 0, and height the same as cursor height. if( mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) @@ -4386,85 +4416,55 @@ Size TextInput::GetRowRectFromCharacterPosition(std::size_t characterPosition, V return max; } - // TODO: This info should be readily available from text-view, we should not have to search hard for it. - Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator begin = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); + DALI_ASSERT_DEBUG( characterPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - // If cursor is pointing to end of line, then start from last character. - characterPosition = std::min( characterPosition, static_cast(mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1) ); + // Initializes the min and max position. + const std::size_t initialPosition = ( characterPosition == mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ? characterPosition - 1u : characterPosition; + min = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + initialPosition ) ).mPosition.GetVectorXY(); + max = min; - Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition; - - // 0. Find first a visible character. Draw a cursor beyound text-input bounds is not wanted. - if( !it->mIsVisible ) + bool found = false; + // 1) Find the line where the character is laid-out. + for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineIt = mTextLayoutInfo.mLines.begin(), lineEndIt = mTextLayoutInfo.mLines.end(); + !found && ( lineIt != mTextLayoutInfo.mLines.end() ); + ++lineIt ) { - characterPosition = FindVisibleCharacter( Left, characterPosition ); - it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition; - } - - // Scan characters left and right of cursor, stopping when end of line/string reached or - // y position greater than threshold of reference line. + const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineIt ); - // 1. scan left until we reach the beginning or a different line. - Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator validCharIt = it; - float referenceLine = it->mPosition.y - CHARACTER_THRESHOLD; - // min-x position is the left-most char's left (x) - // max-x position is the right-most char's right (x) - // min-y position is the minimum of all character's top (y) - // max-y position is the maximum of all character's bottom (y+height) - min.y = validCharIt->mPosition.y; - max.y = validCharIt->mPosition.y + validCharIt->mSize.y; + // Index within the whole text to the last character of the current line. + std::size_t lastCharacterOfLine = 0u; - while(true) - { - validCharIt = it; - min.y = std::min(min.y, validCharIt->mPosition.y); - max.y = std::max(max.y, validCharIt->mPosition.y + validCharIt->mSize.y); - - if(it == begin) + Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineNextIt = lineIt + 1u; + if( lineNextIt != lineEndIt ) { - break; + lastCharacterOfLine = (*lineNextIt).mCharacterGlobalIndex - 1u; } - - --it; - - if( (it->mPosition.y < referenceLine) || - (it->mIsNewParagraphChar) || - (!it->mIsVisible) ) + else { - break; + lastCharacterOfLine = mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1u; } - } - // info refers to the first character on this line. - min.x = validCharIt->mPosition.x; - - // 2. scan right until we reach end or a different line - it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition; - referenceLine = it->mPosition.y + CHARACTER_THRESHOLD; - - while(it != end) - { - if( (it->mPosition.y > referenceLine) || - (it->mIsNewParagraphChar) || - (!it->mIsVisible) ) + // Check if the given chracter position is within the line. + if( ( lineInfo.mCharacterGlobalIndex <= initialPosition ) && ( initialPosition <= lastCharacterOfLine ) ) { - break; - } - - validCharIt = it; - min.y = std::min(min.y, validCharIt->mPosition.y); - max.y = std::max(max.y, validCharIt->mPosition.y + validCharIt->mSize.y); + // 2) Get the row rect of all laid-out characters on the line. - ++it; - } + // Need to scan all characters of the line because they are in the logical position. + for( Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lineInfo.mCharacterGlobalIndex, + endIt = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lastCharacterOfLine + 1u; + it != endIt; + ++it ) + { + const Toolkit::TextView::CharacterLayoutInfo& characterInfo( *it ); - DALI_ASSERT_DEBUG ( validCharIt != end && "validCharIt invalid") + min.x = std::min( min.x, characterInfo.mPosition.x ); + min.y = std::min( min.y, characterInfo.mPosition.y ); + max.x = std::max( max.x, characterInfo.mPosition.x + characterInfo.mSize.width ); + max.y = std::max( max.y, characterInfo.mPosition.y + characterInfo.mSize.height ); + } - if ( validCharIt != end ) - { - // info refers to the last character on this line. - max.x = validCharIt->mPosition.x + validCharIt->mSize.x; + found = true; + } } return Size( max.x - min.x, max.y - min.y ); @@ -4831,9 +4831,10 @@ void TextInput::UpdateLineHeight() } } -std::size_t TextInput::FindVisibleCharacter( const FindVisibleCharacterDirection direction , const std::size_t cursorPosition ) const +std::size_t TextInput::FindVisibleCharacter( FindVisibleCharacterDirection direction , std::size_t cursorPosition ) const { - std::size_t position = 0; + // VCC check if we need do this in the visual order ... + std::size_t position = 0u; const std::size_t tableSize = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); @@ -4843,7 +4844,7 @@ std::size_t TextInput::FindVisibleCharacter( const FindVisibleCharacterDirection { position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1 : position ) ) ).mIsVisible ) + if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) { position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); } @@ -4852,7 +4853,7 @@ std::size_t TextInput::FindVisibleCharacter( const FindVisibleCharacterDirection case Right: { position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1 : position ) ) ).mIsVisible ) + if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) { position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); } @@ -4860,7 +4861,7 @@ std::size_t TextInput::FindVisibleCharacter( const FindVisibleCharacterDirection } case ByEnd: { - position = FindVisibleCharacterLeft( 0, mTextLayoutInfo.mCharacterLayoutInfoTable ); + position = FindVisibleCharacterLeft( 0u, mTextLayoutInfo.mCharacterLayoutInfoTable ); break; } default: diff --git a/base/dali-toolkit/internal/controls/text-input/text-input-impl.h b/base/dali-toolkit/internal/controls/text-input/text-input-impl.h index c9e3b18..a410205 100644 --- a/base/dali-toolkit/internal/controls/text-input/text-input-impl.h +++ b/base/dali-toolkit/internal/controls/text-input/text-input-impl.h @@ -880,9 +880,8 @@ public: // Public to allow internal testing. /** * Draw a cursor / caret at position where new text should appear - * @param[in] nthChar the position along the text string in which new text should appear. */ - void DrawCursor(const std::size_t nthChar = 0); + void DrawCursor(); /** * Sets cursor visibility @@ -1017,15 +1016,6 @@ public: // Public to allow internal testing. void SetSelectionHandlePosition(SelectionHandleId handleId); /** - * Gets the visual position of a logical position. - * @note This is preferred over directly accessing the Map, as it resolves visual - * positions outside of the character map range. - * @param[in] logicalPosition The logical position - * @return Visual position is returned. - */ - std::size_t GetVisualPosition(std::size_t logicalPosition) const; - - /** * Gets a table of the visual text positions which has a flag * for each Character. The flag is either true (character selected) * or false (character deselected) @@ -1154,6 +1144,15 @@ public: // Public to allow internal testing. std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const; /** + * Retrieves the first character of a group of characters with the same direction. + * + * @param[in] logicalPosition Index to a character. + * + * @return Index to the character. + */ + std::size_t GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const; + + /** * Retrieve the dimensions of this row of text that the character resides on. * @param[in] characterPosition the position in the 'string' of characters. * @return The size of the rectangle representing this row diff --git a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp index 23c943c..c21cccf 100644 --- a/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp +++ b/base/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp @@ -384,9 +384,13 @@ void SetCharacter( const TextViewProcessor::WordLayoutInfoContainer& wordsLayout * * Uses the visual to logical conversion table to order the text, styles and character's layout (metrics). * + * @param[in] characterGlobalIndex Index within the whole text of the first character of the paragraph. * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text. + * @param[in,out] relayoutData The text-view's data structures. */ -void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph ) +void ReorderLayout( std::size_t characterGlobalIndex, + TextViewProcessor::ParagraphLayoutInfo& paragraph, + TextView::RelayoutData& relayoutData ) { // Clear any previous right to left layout. if( NULL != paragraph.mRightToLeftLayout ) @@ -446,12 +450,20 @@ void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph ) } // Sets the new 'x' position for each character. + // Updates the text-view's layout info table with the new position of the character. float xPosition = 0.f; - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it ) + std::size_t index = 0u; + for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it, ++index ) { TextViewProcessor::CharacterLayoutInfo& character( *it ); + // Set the 'x' position. character.mPosition.x = xPosition; + + // Update layout info table. + relayoutData.mCharacterLayoutInfoTable[characterGlobalIndex + info->mVisualToLogicalMap[index]].mPosition = character.mPosition; + + // Update the position for the next character. xPosition += character.mSize.width; } @@ -460,8 +472,13 @@ void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph ) Vector positions; TextProcessor::SplitInWords( info->mText, positions ); + // Whether last character is a word or a paragraph separator. + const std::size_t lastCharacterIndex = info->mText.GetLength() - 1u; + const bool isLastCharacterParagraphSeparator = info->mText.IsNewLine( lastCharacterIndex ); + const bool isLastCharacterWordSeparator = info->mText.IsWhiteSpace( lastCharacterIndex ); + // Sets the characters into the words they belong to. - for( Vector::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it ) + for( Vector::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it ) { const std::size_t position = *it; @@ -480,10 +497,13 @@ void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph ) // white space or new paragraph. TextViewProcessor::WordLayoutInfo space; + space.mCharactersLayoutInfo.insert( space.mCharactersLayoutInfo.end(), characters.begin() + position, characters.begin() + position + 1u ); + space.mType = TextViewProcessor::WordSeparator; + TextViewProcessor::UpdateLayoutInfo( space ); paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( space ); @@ -499,6 +519,14 @@ void ReorderLayout( TextViewProcessor::ParagraphLayoutInfo& paragraph ) characters.begin() + previousPosition, characters.end() ); + if( isLastCharacterParagraphSeparator ) + { + word.mType = TextViewProcessor::ParagraphSeparator; + } + else if( isLastCharacterWordSeparator ) + { + word.mType = TextViewProcessor::WordSeparator; + } TextViewProcessor::UpdateLayoutInfo( word ); paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word ); @@ -525,6 +553,47 @@ void CreateBidirectionalInfoForLines( TextView::RelayoutData& relayoutData, // Clear previously created bidirectional info. paragraph.ClearBidirectionalInfo(); + // For each character, it sets the character's direction. + + // Initialize the paragraph direction. Used to set the direction of weak characters. + const bool isParagraphRightToLeft = paragraph.mBidirectionalParagraphInfo->IsRightToLeftParagraph(); + bool isPreviousRightToLeft = isParagraphRightToLeft; + + for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) + { + // Get the character's layout information (the one is shared with text-input) + Toolkit::TextView::CharacterLayoutInfo& info = *( relayoutData.mCharacterLayoutInfoTable.begin() + ( characterGlobalIndex + index ) ); + + // Gets the character's direction. + const Character::CharacterDirection direction = paragraph.mText[index].GetCharacterDirection(); + if( Character::RightToLeft == direction ) + { + info.mIsRightToLeftCharacter = true; + } + else if( Character::Neutral == direction ) + { + // For neutral characters it check's the next and previous directions. + // If they are equals set that direction. If they are not, sets the paragraph direction. + // If there is no next, sets the previous direction. + + // Check next character's direction. + bool isNextRightToLeft = isPreviousRightToLeft; + if( index < paragraph.mNumberOfCharacters - 1u ) + { + const Character::CharacterDirection nextDirection = paragraph.mText[index + 1u].GetCharacterDirection(); + isNextRightToLeft = Character::RightToLeft == nextDirection; + } + + info.mIsRightToLeftCharacter = isPreviousRightToLeft == isNextRightToLeft ? isPreviousRightToLeft : isParagraphRightToLeft; + } + else + { + info.mIsRightToLeftCharacter = false; + } + + isPreviousRightToLeft = info.mIsRightToLeftCharacter; + } + std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); wordIt != wordEndIt; @@ -597,6 +666,9 @@ void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ) { // There is right to left text in this paragraph. + // Stores the current global character index as is needed in both functions. + const std::size_t currentGlobalIndex = characterGlobalIndex; + // Creates the bidirectional info needed to reorder each line of the paragraph. CreateBidirectionalInfoForLines( relayoutData, paragraph, @@ -604,7 +676,7 @@ void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ) lineLayoutInfoIndex ); // Reorder each line of the paragraph - ReorderLayout( paragraph ); + ReorderLayout( currentGlobalIndex, paragraph, relayoutData ); } else { @@ -856,7 +928,8 @@ void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, // Updates the size and position table for text-input with the alignment offset. Vector3 positionOffset( characterLayoutInfo.mPosition ); - std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + characterGlobalIndex; + // Update layout info table. + std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[characterGlobalIndex]; Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt ); characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x; @@ -937,7 +1010,7 @@ void UpdateLayoutInfoTable( Vector4& minMaxXY, characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ), positionOffset, ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ), - characterLayoutInfo.mIsRightToLeft, // whether the character is right to left. + false, // whether the character is right to left. The value is set in a next step in the CreateBidirectionalInfoForLines function true, // whether the character is visible. descender ); @@ -1627,7 +1700,7 @@ void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters relayoutData ); // Updates the visibility for text-input.. - std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + infoTableCharacterIndex; + std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[infoTableCharacterIndex]; Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it ); @@ -1643,6 +1716,8 @@ void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParam const TextView::VisualParameters& visualParameters, TextView::RelayoutData& relayoutData ) { + // TODO check ellipsis with rtl text. + // Traverses the lines and checks which ones doesn't fit in the text-view's boundary. for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end(); lineInfoIt != endLineInfoIt; @@ -1830,21 +1905,27 @@ void CreateEmoticon( const TextView::VisualParameters& visualParameters, * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. * @param[in,out] paragraph Layout info for the paragraph. + * @param[in,out] wordLayout Layout info for the word. * @param[in,out] characterLayout Layout info for the character. * @param[in] character The character. * @param[in] style The character's style. * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set. * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. + * @param[in,out] textActorCreated Whether a text-actor */ void CreateTextActor( const TextView::VisualParameters& visualParameters, TextView::RelayoutData& relayoutData, const TextViewProcessor::ParagraphLayoutInfo& paragraph, + TextViewProcessor::WordLayoutInfo& wordLayout, TextViewProcessor::CharacterLayoutInfo& characterLayout, const Character& character, const TextStyle& style, CurrentTextActorInfo& currentTextActorInfo, - bool createGlyphActors ) + bool createGlyphActors, + bool& textActorCreated ) { + textActorCreated = false; + // Set the text-actor for the current traversed text. if( currentTextActorInfo.textActor ) { @@ -1873,7 +1954,18 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, rightToLeftOffset = characterLayout.mSize.width * relayoutData.mShrinkFactor; } - currentTextActorInfo.text = Text( character ); + // Whether this word is not a white space or if it is, it is underlined. + // Don't want to create text-actors for white spaces unless they are underlined. + bool isNotWhiteSpace = ( TextViewProcessor::NoSeparator == wordLayout.mType ) || ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ); + + if( isNotWhiteSpace ) + { + currentTextActorInfo.text = Text( character ); + } + else + { + currentTextActorInfo.text = Text(); + } currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x - rightToLeftOffset, characterLayout.mPosition.y + characterLayout.mOffset.y, characterLayout.mPosition.z ); @@ -1884,8 +1976,9 @@ void CreateTextActor( const TextView::VisualParameters& visualParameters, TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( createGlyphActors ) + if( createGlyphActors && isNotWhiteSpace ) { + textActorCreated = true; if( textActor ) { // Try to reuse first the text-actor of this character. @@ -1938,10 +2031,10 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa currentTextActorInfo.characterLayout = NULL; const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. - bool glyphActorCreatedForLine = false; // Whether a renderable actor has been created for this line. + bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. + bool textActorCreated = false; // Whether a text actor has been created for this the current group of characters traversed. - TextStyle currentStyle; // style for the current text-actor. + TextStyle currentStyle; // style for the current text-actor. TextViewProcessor::GradientInfo* currentGradientInfo = NULL; // gradient color for the current text-actor. // start point for the current text-actor. @@ -1959,7 +2052,7 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa Vector& textStyles = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mTextStyles : paragraphLayout.mTextStyles; // In case the previous right to left layout has been cleared, all text-actors have been removed as well. If this bool is set to true, text-actors will be created again. - const bool previousRightToLeftLayoutCleared = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false; + createGlyphActors = createGlyphActors || ( ( isRightToLeftLayout ) ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false ); std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); @@ -1986,104 +2079,77 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa // Arrived at last line. lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. } - glyphActorCreatedForLine = false; + textActorCreated = false; } // Do not create a glyph-actor if there is no text. const Character character = text[characterParagraphIndex]; const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) ); - bool appendCharacter = false; - - if( characterLayout.mIsColorGlyph || - ( TextViewProcessor::NoSeparator == wordLayout.mType ) || - ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ) ) + // Check if the character has the same gradient info than the current one. + bool differentGradientInfo = false; + if( characterLayout.mGradientInfo && currentGradientInfo ) + { + differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) || + ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) || + ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint ); + } + else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) ) { - // Do not create a glyph-actor if it's a white space (without underline) or a new paragraph character. + differentGradientInfo = true; + } - // Check if the character has the same gradient info than the current one. - bool differentGradientInfo = false; - if( characterLayout.mGradientInfo && currentGradientInfo ) - { - differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) || - ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) || - ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint ); - } - else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) ) - { - differentGradientInfo = true; - } + if( ( createGlyphActors && !textActorCreated ) || + characterLayout.mIsColorGlyph || + differentGradientInfo || + ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || + ( style != currentStyle ) ) + { + characterLayout.mSetText = false; + characterLayout.mSetStyle = false; - // Creates one glyph-actor for each counsecutive group of characters, with the same style, per line, or if it's an emoticon. - if( !glyphActorCreatedForLine || - characterLayout.mIsColorGlyph || - differentGradientInfo || - ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || - ( style != currentStyle ) ) + if( characterLayout.mIsColorGlyph ) { - characterLayout.mSetText = false; - characterLayout.mSetStyle = false; - - if( characterLayout.mIsColorGlyph ) - { - CreateEmoticon( visualParameters, - characterLayout, - character ); - } - else - { - CreateTextActor( visualParameters, - relayoutData, - paragraphLayout, - characterLayout, - character, - style, - currentTextActorInfo, - createGlyphActors || previousRightToLeftLayoutCleared ); - } - - // There is a new style or a new line. - glyphActorCreatedForLine = true; - - // Update style to be checked with next characters. - currentStyle = style; - currentGradientInfo = characterLayout.mGradientInfo; - currentIsColorGlyph = characterLayout.mIsColorGlyph; + CreateEmoticon( visualParameters, + characterLayout, + character ); characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); } else { - DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." ); - - // Same style than previous one. - - // Add the character to the current text-actor and update the size. - appendCharacter = true; - - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - // There is a previously created text-actor for this character. - // If this character has another one put it into the cache. - textActor.SetText( "" ); - textActorsToRemove.push_back( textActor ); - } + // There is a new style or a new line. - if( characterLayout.mGlyphActor ) + CreateTextActor( visualParameters, + relayoutData, + paragraphLayout, + wordLayout, + characterLayout, + character, + style, + currentTextActorInfo, + createGlyphActors, + textActorCreated ); + + if( textActorCreated ) { - characterLayout.mGlyphActor.Reset(); + characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); } } - } // no white space / new paragraph char + + // Update style to be checked with next characters. + currentStyle = style; + currentGradientInfo = characterLayout.mGradientInfo; + currentIsColorGlyph = characterLayout.mIsColorGlyph; + } else { - appendCharacter = true; - } + DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." ); + + // Same style than previous one. - if( appendCharacter ) - { // Add the character to the current text-actor and update the size. if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) ) { @@ -2095,6 +2161,24 @@ void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualPa } } + if( ( createGlyphActors ) && + !characterLayout.mIsColorGlyph && + !textActorCreated ) + { + TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); + if( textActor ) + { + // There is a previously created text-actor for this character. + // If this character has another one put it into the cache. + textActor.SetText( "" ); + textActorsToRemove.push_back( textActor ); + } + + if( characterLayout.mGlyphActor ) + { + characterLayout.mGlyphActor.Reset(); + } + } ++characterGlobalIndex; ++characterParagraphIndex; } // characters diff --git a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp index 8131b47..d6b4146 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp +++ b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp @@ -63,6 +63,30 @@ BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const Bidirec return *this; } +bool BidirectionalParagraphInfo::IsRightToLeftParagraph() const +{ + bool isRightToLeft = false; + + switch( mDirection ) + { + case FRIBIDI_PAR_LTR: // Left-To-Right paragraph. + case FRIBIDI_PAR_ON: // DirectiOn-Neutral paragraph. + case FRIBIDI_PAR_WLTR: // Weak Left To Right paragraph. + { + isRightToLeft = false; + break; + } + case FRIBIDI_PAR_RTL: // Right-To-Left paragraph. + case FRIBIDI_PAR_WRTL: // Weak Right To Left paragraph. + { + isRightToLeft = true; + break; + } + } + + return isRightToLeft; +} + BidirectionalLineInfo::BidirectionalLineInfo() : mCharacterParagraphIndex(), mNumberOfCharacters(), diff --git a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h index 77d6ee9..1ed24cd 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h +++ b/base/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h @@ -64,6 +64,12 @@ struct BidirectionalParagraphInfo */ BidirectionalParagraphInfo& operator=( const BidirectionalParagraphInfo& info ); + + /** + * @return Whether the paragraph is right to left. + */ + bool IsRightToLeftParagraph() const; + FriBidiParType mDirection; ///< The paragraph direction. std::vector mCharactersTypeBuffer; ///< Character type buffer. std::vector mLevelsBuffer; ///< Levels buffer. diff --git a/base/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp b/base/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp index a3a8ced..ddcf00f 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp +++ b/base/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp @@ -78,8 +78,7 @@ CharacterLayoutInfo::CharacterLayoutInfo() mIsVisible( true ), mSetText( false ), mSetStyle( false ), - mIsColorGlyph( false ), - mIsRightToLeft( false ) + mIsColorGlyph( false ) { } @@ -103,8 +102,7 @@ CharacterLayoutInfo::CharacterLayoutInfo( const CharacterLayoutInfo& character ) mIsVisible( character.mIsVisible ), mSetText( character.mSetText ), mSetStyle( character.mSetStyle ), - mIsColorGlyph( character.mIsColorGlyph ), - mIsRightToLeft( character.mIsRightToLeft ) + mIsColorGlyph( character.mIsColorGlyph ) { } @@ -149,7 +147,6 @@ CharacterLayoutInfo& CharacterLayoutInfo::operator=( const CharacterLayoutInfo& mSetText = character.mSetText; mSetStyle = character.mSetStyle; mIsColorGlyph = character.mIsColorGlyph; - mIsRightToLeft = character.mIsRightToLeft; return *this; } diff --git a/base/dali-toolkit/internal/controls/text-view/text-view-processor-types.h b/base/dali-toolkit/internal/controls/text-view/text-view-processor-types.h index 8cb689b..15005cc 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-view-processor-types.h +++ b/base/dali-toolkit/internal/controls/text-view/text-view-processor-types.h @@ -161,25 +161,24 @@ struct CharacterLayoutInfo CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character ); // Metrics of the glyph. - Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one). - float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box. - float mAscender; ///< Distance from the base line to the top of the line. - float mUnderlineThickness; ///< The underline's thickness. - float mUnderlinePosition; ///< The underline's position. + Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one). + float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box. + float mAscender; ///< Distance from the base line to the top of the line. + float mUnderlineThickness; ///< The underline's thickness. + float mUnderlinePosition; ///< The underline's position. // Position and alignment offset. It depends on the lay-out. - Vector3 mPosition; ///< Position within the text-view - Vector2 mOffset; ///< Alignment and justification offset. - - RenderableActor mGlyphActor; ///< Handle to a text-actor. - float mColorAlpha; ///< Alpha component for the initial text color when text is faded. - GradientInfo* mGradientInfo; ///< Stores gradient info. - - bool mIsVisible:1; ///< Whether the text-actor is visible. - bool mSetText:1; ///< Whether a new text needs to be set in the text-actor. - bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor. - bool mIsColorGlyph:1; ///< Whether this character is an emoticon. - bool mIsRightToLeft:1; ///< Whether this character is right to left. + Vector3 mPosition; ///< Position within the text-view + Vector2 mOffset; ///< Alignment and justification offset. + + RenderableActor mGlyphActor; ///< Handle to a text-actor. + float mColorAlpha; ///< Alpha component for the initial text color when text is faded. + GradientInfo* mGradientInfo; ///< Stores gradient info. + + bool mIsVisible:1; ///< Whether the text-actor is visible. + bool mSetText:1; ///< Whether a new text needs to be set in the text-actor. + bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor. + bool mIsColorGlyph:1; ///< Whether this character is an emoticon. }; typedef std::vector CharacterLayoutInfoContainer; diff --git a/base/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp b/base/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp index eba4f52..800a96b 100644 --- a/base/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp +++ b/base/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp @@ -113,11 +113,6 @@ void CreateWordTextInfo( const Text& paragraph, ChooseFontFamilyName( character, *textStyle ); } - // Checks whether the charcter is right to left. - const Character::CharacterDirection direction = character.GetCharacterDirection(); - characterLayoutInfo.mIsRightToLeft = ( ( direction == Character::RightToLeft ) || - ( direction == Character::RightToLeftWeak ) ); - // Gets the metrics of the font. const Font font = Font::New( FontParameters( textStyle->GetFontName(), textStyle->GetFontStyle(), textStyle->GetFontPointSize() ) ); const Font::Metrics metrics = font.GetMetrics( character ); diff --git a/base/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp b/base/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp index 8d90de6..31cb43a 100644 --- a/base/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp +++ b/base/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp @@ -94,7 +94,7 @@ bool IsActorFocusableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType FocusManager::FocusManager() : mIsWrapped(false), mIsFocusWithinGroup(false), - mIsEndcapFeedbackEnabled(true), + mIsEndcapFeedbackEnabled(false), mIsEndcapFeedbackPlayed(false), mCurrentFocusActor(FocusIDPair(0, 0)), mFocusIndicatorActor(Actor()), diff --git a/base/dali-toolkit/public-api/controls/buttons/button.cpp b/base/dali-toolkit/public-api/controls/buttons/button.cpp index 55764a2..cd0bf52 100644 --- a/base/dali-toolkit/public-api/controls/buttons/button.cpp +++ b/base/dali-toolkit/public-api/controls/buttons/button.cpp @@ -30,6 +30,7 @@ namespace Toolkit { const char* const Button::SIGNAL_CLICKED = "clicked"; +const char* const Button::SIGNAL_TOGGLED = "toggled"; Button::Button() {} @@ -82,6 +83,11 @@ Button::ClickedSignalV2& Button::ClickedSignal() return Dali::Toolkit::GetImplementation( *this ).ClickedSignal(); } +Button::ToggledSignalV2& Button::ToggledSignal() +{ + return Dali::Toolkit::GetImplementation( *this ).ToggledSignal(); +} + Button::Button( Internal::Button& implementation ) : Control( implementation ) { diff --git a/base/dali-toolkit/public-api/controls/buttons/button.h b/base/dali-toolkit/public-api/controls/buttons/button.h index 8d95226..980ddbd 100644 --- a/base/dali-toolkit/public-api/controls/buttons/button.h +++ b/base/dali-toolkit/public-api/controls/buttons/button.h @@ -53,6 +53,7 @@ public: // Signal Names static const char* const SIGNAL_CLICKED; ///< name "clicked" + static const char* const SIGNAL_TOGGLED; ///< name "toggled" // Properties static const Property::Index PROPERTY_DIMMED; ///< name "dimmed", @see SetDimmed(), type BOOLEAN @@ -131,10 +132,20 @@ public: //Signals typedef SignalV2< bool ( Button ) > ClickedSignalV2; /** + * @brief Button toggled signal type + */ + typedef SignalV2< bool ( Button, bool ) > ToggledSignalV2; + + /** * @brief Signal emitted when the button is touched and the touch point doesn't leave the boundary of the button. */ ClickedSignalV2& ClickedSignal(); + /** + * @brief Signal emitted when the button's state is toggled. + */ + ToggledSignalV2& ToggledSignal(); + public: // Not intended for application developers /** diff --git a/base/dali-toolkit/public-api/controls/buttons/push-button.cpp b/base/dali-toolkit/public-api/controls/buttons/push-button.cpp index 24da5ee..f6e2775 100644 --- a/base/dali-toolkit/public-api/controls/buttons/push-button.cpp +++ b/base/dali-toolkit/public-api/controls/buttons/push-button.cpp @@ -29,7 +29,6 @@ namespace Dali namespace Toolkit { -const char* const PushButton::SIGNAL_TOGGLED = "toggled"; const char* const PushButton::SIGNAL_PRESSED = "pressed"; const char* const PushButton::SIGNAL_RELEASED = "released"; @@ -219,11 +218,6 @@ Actor PushButton::GetLabelText() const return Dali::Toolkit::GetImplementation( *this ).GetLabelText(); } -PushButton::ToggledSignalV2& PushButton::ToggledSignal() -{ - return Dali::Toolkit::GetImplementation( *this ).ToggledSignal(); -} - PushButton::PressedSignalV2& PushButton::PressedSignal() { return Dali::Toolkit::GetImplementation( *this ).PressedSignal(); diff --git a/base/dali-toolkit/public-api/controls/buttons/push-button.h b/base/dali-toolkit/public-api/controls/buttons/push-button.h index 5bebddd..658dbae 100644 --- a/base/dali-toolkit/public-api/controls/buttons/push-button.h +++ b/base/dali-toolkit/public-api/controls/buttons/push-button.h @@ -80,7 +80,6 @@ class PushButton : public Button public: //Signal Names - static const char* const SIGNAL_TOGGLED; ///< name "toggled" static const char* const SIGNAL_PRESSED; ///< name "pressed" static const char* const SIGNAL_RELEASED; ///< name "released" @@ -333,9 +332,6 @@ public: public: //Signals - /// @brief PushButton Toggled signal type. - typedef SignalV2< bool ( Button, bool ) > ToggledSignalV2; - /// @brief PushButton Pressed signal type. typedef SignalV2< bool ( Button ) > PressedSignalV2; @@ -343,11 +339,6 @@ public: //Signals typedef SignalV2< bool ( Button ) > ReleasedSignalV2; /** - * @brief Signal emitted when the \e toggle property is set and the button is touched. - */ - ToggledSignalV2& ToggledSignal(); - - /** * @brief Signal emitted when the button is touched. */ PressedSignalV2& PressedSignal(); diff --git a/base/dali-toolkit/public-api/controls/buttons/radio-button.h b/base/dali-toolkit/public-api/controls/buttons/radio-button.h index 37f3860..23c370b 100644 --- a/base/dali-toolkit/public-api/controls/buttons/radio-button.h +++ b/base/dali-toolkit/public-api/controls/buttons/radio-button.h @@ -41,7 +41,7 @@ class RadioButton; * * Radio buttons are designed to select one of many option at the same time. * - * Every button have its own \e label and \e state, which can be modified by RadioButton::SetLabel and RadioBUtton::SetActive. + * Every button have its own \e label and \e state, which can be modified by RadioButton::SetLabel and RadioButton::SetActive. * * RadioButton can change its current state using RadioButton::ToggleState. * @@ -177,7 +177,8 @@ class RadioButton: public Button * @param[in] internal A pointer to the internal CustomActor. */ RadioButton(Dali::Internal::CustomActor* internal); -} ; + +}; } // namespace Toolkit diff --git a/base/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp b/base/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp index 17aa375..a2fef08 100644 --- a/base/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp +++ b/base/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp @@ -623,7 +623,6 @@ void GridLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 s // so that we can avoid the actors overlapping during orientation change. animation.Resize( actor, shrink, AlphaFunctions::EaseOut, 0.0f, durationSeconds * 0.5f ); animation.Resize( actor, size, AlphaFunctions::EaseIn, 0.0f, durationSeconds ); - animation.SetDestroyAction( Animation::Bake ); } } diff --git a/optional/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp b/optional/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp index 7a04ae9..2ad6931 100644 --- a/optional/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp +++ b/optional/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp @@ -253,7 +253,6 @@ void NavigationControl::OrientationChanged( int angle ) } Animation animation = Animation::New( mOrientationAnimationDuration ); - animation.SetDestroyAction( Animation::Bake ); animation.RotateTo( Self(), Degree( -angle ), Vector3::ZAXIS, mOrientationAnimationAlphaFunc ); animation.Play(); diff --git a/optional/dali-toolkit/internal/controls/view/view-impl.cpp b/optional/dali-toolkit/internal/controls/view/view-impl.cpp index fa2a9d6..8bf9811 100644 --- a/optional/dali-toolkit/internal/controls/view/view-impl.cpp +++ b/optional/dali-toolkit/internal/controls/view/view-impl.cpp @@ -231,8 +231,6 @@ void View::OrientationChanged( Dali::Orientation orientation ) } } - mRotateAnimation.SetDestroyAction( Animation::Bake ); - Toolkit::View handle( GetOwner() ); mOrientationAnimationStartedSignalV2.Emit( handle, mRotateAnimation, orientation ); diff --git a/optional/dali-toolkit/public-api/dali-toolkit-version.cpp b/optional/dali-toolkit/public-api/dali-toolkit-version.cpp index 10125c7..4fd1edb 100644 --- a/optional/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/optional/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -31,7 +31,7 @@ namespace Toolkit const unsigned int TOOLKIT_MAJOR_VERSION = 1; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 10; +const unsigned int TOOLKIT_MICRO_VERSION = 11; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index aa12918..973b020 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit Summary: The OpenGLES Canvas Core Library Toolkit -Version: 1.0.10 +Version: 1.0.11 Release: 1 Group: System/Libraries License: Apache-2.0