logicalModel->mFontDescriptionRuns,
logicalModel->mEmbeddedItems,
logicalModel->mAnchors,
- logicalModel->mUnderlinedCharacterRuns);
+ logicalModel->mUnderlinedCharacterRuns,
+ logicalModel->mBackgroundColorRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
// Enable the text elide.
controller->SetTextElideEnabled( true );
+
+ // Disable match system language direction
+ controller->SetMatchSystemLanguageDirection(false);
}
void ConfigureTextField( ControllerPtr controller )
// Disable the text elide.
controller->SetTextElideEnabled( false );
+
+ // Disable match system language direction
+ controller->SetMatchSystemLanguageDirection(false);
}
void ConfigureTextEditor( ControllerPtr controller )
// Disable the text elide.
controller->SetTextElideEnabled( false );
+
+ // Disable match system language direction
+ controller->SetMatchSystemLanguageDirection(false);
}
} // namespace Text
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
Vector<EmbeddedItem> items;
Vector<Anchor> anchors;
Vector<UnderlinedCharacterRun> underlinedCharacterRuns;
- MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns );
+ Vector<ColorRun> backgroundColorRuns;
+ MarkupProcessData markupProcessData( colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns );
ProcessMarkupString( data.xHTMLEntityString, markupProcessData );
for( Vector<EmbeddedItem>::Iterator it = items.Begin(),
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
DALI_TEST_EQUALS( countAtlas, 1, TEST_LOCATION );
END_TEST;
+}
+
+int UtcDaliTextEditorBackgroundTag(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliTextEditorBackgroundTag\n");
+
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK( editor );
+
+ editor.SetProperty( TextEditor ::Property::ENABLE_MARKUP, true );
+ editor.SetProperty( TextEditor::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+ application.GetScene().Add( editor );
+ application.SendNotification();
+ application.Render();
+
+ Toolkit::Internal::TextEditor& editorImpl = GetImpl( editor );
+ const ColorIndex* const backgroundColorIndicesBuffer = editorImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+ DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+ //default color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+ //red color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+ //yellow color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+ END_TEST;
}
\ No newline at end of file
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
END_TEST;
+}
+
+int UtcDaliTextFieldBackgroundTag(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliTextFieldBackgroundTag\n");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ field.SetProperty( TextField ::Property::ENABLE_MARKUP, true );
+ field.SetProperty( TextField::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+ application.GetScene().Add( field );
+ application.SendNotification();
+ application.Render();
+
+ Toolkit::Internal::TextField& fieldImpl = GetImpl( field );
+ const ColorIndex* const backgroundColorIndicesBuffer = fieldImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+ DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+ //default color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+ //red color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+ //yellow color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+ END_TEST;
}
\ No newline at end of file
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
END_TEST;
+}
+
+int UtcDaliTextLabelBackgroundTag(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliTextLabelBackgroundTag\n");
+
+ TextLabel label = TextLabel::New();
+ DALI_TEST_CHECK( label );
+
+ label.SetProperty( TextLabel ::Property::ENABLE_MARKUP, true );
+ label.SetProperty( TextLabel::Property::TEXT, "H<background color='red'>e</background> Worl<background color='yellow'>d</background>" );
+ application.GetScene().Add( label );
+ application.SendNotification();
+ application.Render();
+
+ Toolkit::Internal::TextLabel& labelImpl = GetImpl( label );
+ const ColorIndex* const backgroundColorIndicesBuffer = labelImpl.getController()->GetTextModel()->GetBackgroundColorIndices();
+
+ DALI_TEST_CHECK( backgroundColorIndicesBuffer );
+
+ //default color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[0], 0u, TEST_LOCATION);
+
+ //red color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[1], 1u, TEST_LOCATION);
+
+ //yellow color
+ DALI_TEST_EQUALS( backgroundColorIndicesBuffer[7], 2u, TEST_LOCATION);
+
+ END_TEST;
}
\ No newline at end of file
utc-Dali-ConfirmationPopup.cpp
utc-Dali-CubeTransitionEffect.cpp
utc-Dali-EffectsView.cpp
+ utc-Dali-Fade.cpp
utc-Dali-FlexContainer.cpp
utc-Dali-FlexNode.cpp
utc-Dali-GaussianBlurView.cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 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 <iostream>
+#include <stdlib.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/public-api/transition/transition-set.h>
+#include <dali-toolkit/public-api/transition/transition-base.h>
+#include <dali-toolkit/public-api/transition/fade.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+// Functor to test whether a Finish signal is emitted
+struct TransitionFinishCheck
+{
+ TransitionFinishCheck(bool& signalReceived)
+ : mSignalReceived(signalReceived)
+ {
+ }
+
+ void operator()(TransitionSet& transitionSet)
+ {
+ mSignalReceived = true;
+ }
+
+ void Reset()
+ {
+ mSignalReceived = false;
+ }
+
+ void CheckSignalReceived()
+ {
+ if(!mSignalReceived)
+ {
+ tet_printf("Expected Finish signal was not received\n");
+ tet_result(TET_FAIL);
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
+ }
+
+ void CheckSignalNotReceived()
+ {
+ if(mSignalReceived)
+ {
+ tet_printf("Unexpected Finish signal was received\n");
+ tet_result(TET_FAIL);
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
+ }
+
+ bool& mSignalReceived; // owned by individual tests
+};
+
+int UtcDaliFadeSetGetProperty(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliFadeSetGetProperty");
+
+ Control control = Control::New();
+
+ Fade fade = Fade::New(control, 0.5, TimePeriod(-0.5f, -0.5f));
+
+ TimePeriod timePeriod = fade.GetTimePeriod();
+ DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
+ DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliFadeWithOffScene(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliFadeWithOffScene");
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+ control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+ control.SetProperty(Actor::Property::OPACITY, 1.0f);
+ Property::Map controlProperty;
+ controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+ controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+ control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+ fade.SetAppearingTransition(false); // set fade out
+ TransitionSet transitionSet = TransitionSet::New();
+ transitionSet.AddTransition(fade);
+ transitionSet.Play();
+
+ bool signalReceived(false);
+ TransitionFinishCheck finishCheck(signalReceived);
+ transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(400);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(200);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliFadeOut(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliFadeOut");
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+ control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+ control.SetProperty(Actor::Property::OPACITY, 1.0f);
+ Property::Map controlProperty;
+ controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+ controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+ control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+ application.GetScene().Add(control);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+ fade.SetAppearingTransition(false); // set fade out
+ TransitionSet transitionSet = TransitionSet::New();
+ transitionSet.AddTransition(fade);
+ transitionSet.Play();
+
+ bool signalReceived(false);
+ TransitionFinishCheck finishCheck(signalReceived);
+ transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(400);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ float currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+ DALI_TEST_CHECK(currentOpacity <= 0.7 && currentOpacity >= 0.5);
+
+ application.SendNotification();
+ application.Render(200);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ application.SendNotification();
+ application.Render(20);
+
+ // Property is reset after animation.
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliFadeIn(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliFadeIn");
+
+ Control control = Control::New();
+ control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ control.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ control.SetProperty(Actor::Property::POSITION, Vector3(100, 200, 0));
+ control.SetProperty(Actor::Property::SIZE, Vector3(150, 150, 0));
+ control.SetProperty(Actor::Property::OPACITY, 1.0f);
+ Property::Map controlProperty;
+ controlProperty.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+ controlProperty.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+ control.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty);
+
+ application.GetScene().Add(control);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ Fade fade = Fade::New(control, 0.5, TimePeriod(0.5f));
+ fade.SetAppearingTransition(true); // set fade in
+ TransitionSet transitionSet = TransitionSet::New();
+ transitionSet.AddTransition(fade);
+ transitionSet.Play();
+
+ bool signalReceived(false);
+ TransitionFinishCheck finishCheck(signalReceived);
+ transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(400);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ float currentOpacity = control.GetCurrentProperty<float>(Actor::Property::OPACITY);
+ DALI_TEST_CHECK(currentOpacity <= 1.0 && currentOpacity >= 0.8);
+
+ application.SendNotification();
+ application.Render(200);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS(1.0f, control.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ END_TEST;
+}
PushButton button4 = PushButton::New();
PushButton button5 = PushButton::New();
- button1.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
- button2.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
- button3.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
- button4.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
- button5.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) );
-
- button1.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
- button2.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
- button3.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
- button4.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
- button5.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
+ button1.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+ button2.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+ button3.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+ button4.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+ button5.SetProperty(Actor::Property::SIZE, Vector2(50, 50));
+
+ button1.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+ button2.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+ button3.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+ button4.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
+ button5.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE,true);
application.GetScene().Add(button1);
application.GetScene().Add(button2);
application.GetScene().Add(button3);
- application.GetScene().Add(button4);
+ button5.Add(button4);
application.GetScene().Add(button5);
// set position
// | |
// | button5|
// button3 -- button4
- button1.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 0.0f));
- button2.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 0.0f));
- button3.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 100.0f));
- button4.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 100.0f));
- button5.SetProperty( Actor::Property::POSITION, Vector2(60.0f, 60.0f));
+ button1.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
+ button2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 0.0f));
+ button3.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 100.0f));
+ button4.SetProperty(Actor::Property::POSITION, Vector2(40.0f, 40.0f));
+ button5.SetProperty(Actor::Property::POSITION, Vector2(60.0f, 60.0f));
// flush the queue and render once
application.SendNotification();
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
// Confirm whether focus is moved to button2
- DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button2.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button1);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button2);
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::DOWN) == true);
// Confirm whether focus is moved to button5
- DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
// Confirm whether focus is moved to button4
- DALI_TEST_EQUALS(button4.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button4.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button4);
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
// Confirm whether focus is moved to button5
- DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button4);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
// Confirm whether focus is moved to button3
- DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+ DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+ DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
+ DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button3);
+ focusChangedCallback.Reset();
+
+ // Move the focus towards right
+ // button1 -- button2
+ // | |
+ // | [button5]|
+ // button3 -- button4
+ DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true);
+
+ // Confirm whether focus is moved to button5
+ DALI_TEST_EQUALS(button5.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
+ DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
+ DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button3);
+ DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5);
+ focusChangedCallback.Reset();
+
+ // Move the focus towards left
+ // button1 -- button2
+ // | |
+ // | button5|
+ //[button3] -- button4
+ DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true);
+
+ // Confirm whether focus is moved to button3
+ DALI_TEST_EQUALS(button3.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button3);
DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == true);
// Confirm whether focus is moved to button1
- DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION );
+ DALI_TEST_EQUALS(button1.GetProperty<int>(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION);
DALI_TEST_CHECK(focusChangedCallback.mSignalVerified);
DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button3);
DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1);
application.SendNotification();
application.Render();
- // The default value of MATCH_SYSTEM_LANGUAGE_DIRECTION is 'false'.
- DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), false, TEST_LOCATION );
-
- // Check the enable match system language direction property
- editor.SetProperty( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, true );
+ // The default value of MATCH_SYSTEM_LANGUAGE_DIRECTION is 'true'.
DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), true, TEST_LOCATION );
+ // Check the disable match system language direction property
+ editor.SetProperty( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, false );
+ DALI_TEST_EQUALS( editor.GetProperty<bool>( DevelTextEditor::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), false, TEST_LOCATION );
+
application.SendNotification();
application.Render();
application.SendNotification();
application.Render();
- // The default value of MATCH_SYSTEM_LANGUAGE_DIRECTION is 'false'.
- DALI_TEST_EQUALS( field.GetProperty<bool>( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), false, TEST_LOCATION );
+ // The default value of MATCH_SYSTEM_LANGUAGE_DIRECTION is 'true'.
+ DALI_TEST_EQUALS( field.GetProperty<bool>( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), true, TEST_LOCATION );
// Check the match system language direction property
- field.SetProperty( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, true );
- DALI_TEST_EQUALS( field.GetProperty<bool>( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), true, TEST_LOCATION );
+ field.SetProperty( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, false );
+ DALI_TEST_EQUALS( field.GetProperty<bool>( DevelTextField::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION ), false, TEST_LOCATION );
application.SendNotification();
application.Render();
label.SetProperty( TextLabel::Property::TEXT, "Hello world" );
label.SetProperty( TextLabel::Property::POINT_SIZE, 20 );
+ label.SetProperty( DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, false );
application.GetScene().Add( label );
// Test LTR text
*\r
*/\r
\r
+/*\r
+ * Copyright (C) 2017 The Android Open Source Project\r
+ *\r
+ * Modified by joogab yun(joogab.yun@samsung.com)\r
+ */\r
+\r
// CLASS HEADER\r
#include "focus-finder.h"\r
\r
// EXTERNAL INCLUDES\r
-#include <dali/devel-api/common/singleton-service.h>\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali-toolkit/internal/focus-manager/focus-finder-impl.h>\r
+#include <dali/devel-api/actors/actor-devel.h>\r
+#include <dali/integration-api/adaptor-framework/scene-holder.h>\r
+#include <dali/public-api/actors/layer.h>\r
\r
namespace Dali\r
{\r
namespace Toolkit\r
{\r
-FocusFinder::FocusFinder()\r
+namespace FocusFinder\r
+{\r
+namespace\r
+{\r
+static int MajorAxisDistanceRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ return source.left - dest.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return dest.left - source.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ return source.top - dest.bottom;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return dest.top - source.bottom;\r
+ }\r
+ default:\r
+ {\r
+ return 0;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * @return The distance from the edge furthest in the given direction\r
+ * of source to the edge nearest in the given direction of dest.\r
+ * If the dest is not in the direction from source, return 0.\r
+ */\r
+static int MajorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
{\r
+ return std::max(0, MajorAxisDistanceRaw(direction, source, dest));\r
}\r
\r
-FocusFinder::~FocusFinder()\r
+static int MajorAxisDistanceToFarEdgeRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ return source.left - dest.left;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return dest.right - source.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ return source.top - dest.top;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return dest.bottom - source.bottom;\r
+ }\r
+ default:\r
+ {\r
+ return 0;\r
+ }\r
+ }\r
}\r
\r
-FocusFinder FocusFinder::Get()\r
+/**\r
+ * @return The distance along the major axis w.r.t the direction from the\r
+ * edge of source to the far edge of dest.\r
+ * If the dest is not in the direction from source, return 1\r
+ */\r
+static int MajorAxisDistanceToFarEdge(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
{\r
- FocusFinder finder;\r
+ return std::max(1, MajorAxisDistanceToFarEdgeRaw(direction, source, dest));\r
+}\r
\r
- // Check whether the focus finder is already created\r
- SingletonService singletonService(SingletonService::Get());\r
- if(singletonService)\r
+/**\r
+ * Find the distance on the minor axis w.r.t the direction to the nearest\r
+ * edge of the destination rectangle.\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param source The source rect.\r
+ * @param dest The destination rect.\r
+ * @return The distance.\r
+ */\r
+static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
+{\r
+ switch(direction)\r
{\r
- Dali::BaseHandle handle = singletonService.GetSingleton(typeid(FocusFinder));\r
- if(handle)\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ // the distance between the center verticals\r
+ return std::abs(\r
+ (((source.top + source.bottom) * 0.5f) -\r
+ (((dest.top + dest.bottom) * 0.5f))));\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
{\r
- // If so, downcast the handle of singleton to focus finder\r
- finder = FocusFinder(dynamic_cast<Internal::FocusFinder*>(handle.GetObjectPtr()));\r
+ // the distance between the center horizontals\r
+ return std::abs(\r
+ (((source.left + source.right) * 0.5f) -\r
+ (((dest.left + dest.right) * 0.5f))));\r
}\r
+ default:\r
+ {\r
+ return 0;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * Calculate distance given major and minor axis distances.\r
+ * @param majorAxisDistance The majorAxisDistance\r
+ * @param minorAxisDistance The minorAxisDistance\r
+ * @return The distance\r
+ */\r
+static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
+{\r
+ return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;\r
+}\r
+\r
+/**\r
+ * Convert x,y,width,height coordinates into left, right, bottom, top coordinates.\r
+ * @param[in,out] rect The rect\r
+ */\r
+static void ConvertCoordinate(Dali::Rect<float>& rect)\r
+{\r
+ // convert x, y, width, height -> left, right, bottom, top\r
+ float left = rect.x;\r
+ float right = rect.x + rect.width;\r
+ float bottom = rect.y + rect.height;\r
+ float top = rect.y;\r
+\r
+ rect.left = left;\r
+ rect.right = right;\r
+ rect.bottom = bottom;\r
+ rect.top = top;\r
+}\r
\r
- if(!finder)\r
+/**\r
+ * Is destRect a candidate for the next focus given the direction?\r
+ * @param srcRect The source rect.\r
+ * @param destRect The dest rect.\r
+ * @param direction The direction (up, down, left, right)\r
+ * @return Whether destRect is a candidate.\r
+ */\r
+static bool IsCandidate(Dali::Rect<float> srcRect, Dali::Rect<float> destRect, Dali::Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ return (srcRect.right > destRect.right || srcRect.left >= destRect.right) && srcRect.left > destRect.left;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return (srcRect.left < destRect.left || srcRect.right <= destRect.left) && srcRect.right < destRect.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) && srcRect.top > destRect.top;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
{\r
- // If not, create the focus finder and register it as a singleton\r
- finder = FocusFinder(new Internal::FocusFinder());\r
- singletonService.Register(typeid(finder), finder);\r
+ return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) && srcRect.bottom < destRect.bottom;\r
+ }\r
+ default:\r
+ {\r
+ return false;\r
}\r
}\r
+ return false;\r
+}\r
\r
- return finder;\r
+/**\r
+ * Is dest in a given direction from src?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param src The source rect\r
+ * @param dest The dest rect\r
+ */\r
+static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> src, Dali::Rect<float> dest)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ return src.left >= dest.right;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return src.right <= dest.left;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ return src.top >= dest.bottom;\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return src.bottom <= dest.top;\r
+ }\r
+ default:\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ * Do the given direction's axis of rect1 and rect2 overlap?\r
+ * @param direction the direction (up, down, left, right)\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return whether the beams overlap\r
+ */\r
+static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
+{\r
+ switch(direction)\r
+ {\r
+ case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
+ case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);\r
+ }\r
+ case Dali::Toolkit::Control::KeyboardFocus::UP:\r
+ case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);\r
+ }\r
+ default:\r
+ {\r
+ return false;\r
+ }\r
+ }\r
}\r
\r
-FocusFinder::FocusFinder(Internal::FocusFinder* impl)\r
-: BaseHandle(impl)\r
+/**\r
+ * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect.\r
+ * @param direction The direction (up, down, left, right)\r
+ * @param source The source rect\r
+ * @param rect1 The first rect\r
+ * @param rect2 The second rect\r
+ * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam\r
+ */\r
+static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
{\r
+ const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1);\r
+ const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2);\r
+ // if rect1 isn't exclusively in the src beam, it doesn't win\r
+ if(rect2InSrcBeam || !rect1InSrcBeam)\r
+ {\r
+ return false;\r
+ }\r
+ // we know rect1 is in the beam, and rect2 is not\r
+ // if rect1 is to the direction of, and rect2 is not, rect1 wins.\r
+ // for example, for direction left, if rect1 is to the left of the source\r
+ // and rect2 is below, then we always prefer the in beam rect1, since rect2\r
+ // could be reached by going down.\r
+ if(!IsToDirectionOf(direction, source, rect2))\r
+ {\r
+ return true;\r
+ }\r
+ // for horizontal directions, being exclusively in beam always wins\r
+ if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT))\r
+ {\r
+ return true;\r
+ }\r
+ // for vertical directions, beams only beat up to a point:\r
+ // now, as long as rect2 isn't completely closer, rect1 wins\r
+ // e.g for direction down, completely closer means for rect2's top\r
+ // edge to be closer to the source's top edge than rect1's bottom edge.\r
+ return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2));\r
}\r
\r
-Actor FocusFinder::GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
+bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect)\r
{\r
- return GetImpl(*this).GetNearestFocusableActor(focusedActor, direction);\r
+ // to be a better candidate, need to at least be a candidate in the first place\r
+ if(!IsCandidate(focusedRect, candidateRect, direction))\r
+ {\r
+ return false;\r
+ }\r
+ // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate,\r
+ // candidateRect is better\r
+ if(!IsCandidate(focusedRect, bestCandidateRect, direction))\r
+ {\r
+ return true;\r
+ }\r
+ // if candidateRect is better by beam, it wins\r
+ if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect))\r
+ {\r
+ return true;\r
+ }\r
+ // if bestCandidateRect is better, then candidateRect cant' be :)\r
+ if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect))\r
+ {\r
+ return false;\r
+ }\r
+\r
+ // otherwise, do fudge-tastic comparison of the major and minor axis\r
+ return (GetWeightedDistanceFor(\r
+ MajorAxisDistance(direction, focusedRect, candidateRect),\r
+ MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect),\r
+ MinorAxisDistance(direction, focusedRect, bestCandidateRect)));\r
}\r
\r
+Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+ Actor nearestActor;\r
+ if(actor)\r
+ {\r
+ // Recursively children\r
+ const auto childCount = actor.GetChildCount();\r
+ for(auto i = 0u; i < childCount; ++i)\r
+ {\r
+ Dali::Actor child = actor.GetChildAt(i);\r
+ if(child && child != focusedActor && child.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))\r
+ {\r
+ Rect<float> candidateRect = DevelActor::CalculateScreenExtents(child);\r
+\r
+ // convert x, y, width, height -> left, right, bottom, top\r
+ ConvertCoordinate(candidateRect);\r
+\r
+ if(IsBetterCandidate(direction, focusedRect, candidateRect, bestCandidateRect))\r
+ {\r
+ bestCandidateRect = candidateRect;\r
+ nearestActor = child;\r
+ }\r
+ }\r
+ Actor nextActor = FindNextFocus(child, focusedActor, focusedRect, bestCandidateRect, direction);\r
+ if(nextActor)\r
+ {\r
+ nearestActor = nextActor;\r
+ }\r
+ }\r
+ }\r
+ return nearestActor;\r
+}\r
+\r
+} // unnamed namespace\r
+\r
+Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
+{\r
+ Actor nearestActor;\r
+ if(!focusedActor)\r
+ {\r
+ return nearestActor;\r
+ }\r
+\r
+ Rect<float> focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
+\r
+ // initialize the best candidate to something impossible\r
+ // (so the first plausible actor will become the best choice)\r
+ Rect<float> bestCandidateRect = focusedRect;\r
+ switch(direction)\r
+ {\r
+ case Toolkit::Control::KeyboardFocus::LEFT:\r
+ {\r
+ bestCandidateRect.x += 1;\r
+ break;\r
+ }\r
+ case Toolkit::Control::KeyboardFocus::RIGHT:\r
+ {\r
+ bestCandidateRect.x -= 1;\r
+ break;\r
+ }\r
+ case Toolkit::Control::KeyboardFocus::UP:\r
+ {\r
+ bestCandidateRect.y += 1;\r
+ break;\r
+ }\r
+ case Toolkit::Control::KeyboardFocus::DOWN:\r
+ {\r
+ bestCandidateRect.y -= 1;\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ ConvertCoordinate(bestCandidateRect);\r
+\r
+ ConvertCoordinate(focusedRect);\r
+\r
+ Integration::SceneHolder window = Integration::SceneHolder::Get(focusedActor);\r
+ if(window)\r
+ {\r
+ Actor rootActor = window.GetRootLayer();\r
+ nearestActor = FindNextFocus(rootActor, focusedActor, focusedRect, bestCandidateRect, direction);\r
+ }\r
+ return nearestActor;\r
+}\r
+\r
+} // namespace FocusFinder\r
+\r
} // namespace Toolkit\r
\r
} // namespace Dali\r
{\r
namespace Toolkit\r
{\r
-namespace Internal DALI_INTERNAL\r
+namespace FocusFinder\r
{\r
-class FocusFinder;\r
-}\r
-\r
/**\r
- * FocusFinder\r
- * This class used for finding the next focusable actor in a given direction\r
- * from a actor that currently has focus.\r
+ * Get the nearest focusable actor.\r
+ * @param [in] focusedActor The current focused actor.\r
+ * @param [in] direction The direction.\r
+ * @return The nearest focusable actor, or an empty handle if none exists.\r
*/\r
-class DALI_TOOLKIT_API FocusFinder : public BaseHandle\r
-{\r
-public:\r
- /**\r
- * Create a FocusFinder handle; this can be initialised with FocusFinder::Get()\r
- * Calling member functions with an uninitialised handle is not allowed.\r
- */\r
- FocusFinder();\r
-\r
- /**\r
- * @brief Destructor\r
- *\r
- * This is non-virtual since derived Handle types must not contain data or virtual methods.\r
- */\r
- ~FocusFinder();\r
-\r
- /**\r
- * @brief Get the singleton of FocusFinder object.\r
- * @return A handle to the FocusFinder control.\r
- */\r
- static FocusFinder Get();\r
-\r
- /**\r
- * Get the nearest focusable actor.\r
- * @param [in] focusedActor The current focused actor.\r
- * @param [in] direction The direction.\r
- * @return The nearest focusable actor, or null if none exists.\r
- */\r
- Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
-private:\r
- explicit DALI_INTERNAL FocusFinder(Internal::FocusFinder* impl);\r
+DALI_TOOLKIT_API Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
\r
-}; // class FocusFinder\r
+} // namespace FocusFinder\r
\r
} // namespace Toolkit\r
\r
fontDescriptionRuns,
textModel->mLogicalModel->mEmbeddedItems,
textModel->mLogicalModel->mAnchors,
- textModel->mLogicalModel->mUnderlinedCharacterRuns);
+ textModel->mLogicalModel->mUnderlinedCharacterRuns,
+ textModel->mLogicalModel->mBackgroundColorRuns);
if(textParameters.markupEnabled)
{
#define DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_PROPERTIES_DEVEL_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
* @details Name "cornerRadius", type Property::FLOAT or Prooperty::VECTOR4, animatable
* @note By default, it is Vector::ZERO.
* @note Only Property::Vector4 can be animated.
+ * @note Each radius will clamp internally to the half of smaller of the visual width and visual height.
+ * @note Their may exist some alias when you use it as ClippingMode::CLIP_CHILDREN
* @note Radius value are used in clockwise order from top-left-corner to bottom-left-corner.
* When radius is Vector4(x, y, z, w)
* x y
* @brief The offset from the visual borderline (recommend [-1.0f to 1.0f]).
* @details Name "borderlineOffset", type Property::FLOAT, animatable
* @note Default value is 0.0f.
- * @note This value will be clipped by [-1.0f to 1.0f].
+ * @note This value will clamp internally to [-1.0f to 1.0f].
*/
BORDERLINE_OFFSET = OPACITY + 6,
};
else
{
Dali::Accessibility::ReadingInfoTypes types;
- types[Dali::Accessibility::ReadingInfoType::NAME] = true;
- types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
+ types[Dali::Accessibility::ReadingInfoType::NAME] = true;
+ types[Dali::Accessibility::ReadingInfoType::ROLE] = true;
types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
- types[Dali::Accessibility::ReadingInfoType::STATE] = true;
+ types[Dali::Accessibility::ReadingInfoType::STATE] = true;
return types;
}
Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
- Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
- Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
+ Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
+ Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
if(!destinationMap.Empty())
{
- mixColor = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
- cornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+ static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+ Property::Value* propertyValue = map.Find(index);
+ if(propertyValue)
+ {
+ return propertyValue->Get<Vector4>();
+ }
+ return Vector4{};
+ };
+
+ mixColor = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+ cornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
if(sourceMap.Empty())
{
sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
}
- Vector4 sourceMixColor = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
- Vector4 sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+ Vector4 sourceMixColor = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+ Vector4 sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
- std::vector<Dali::Property> properties;
+ std::vector<Dali::Property> properties;
std::vector<std::pair<Property::Value, Property::Value>> values;
if(Vector3(sourceMixColor) != Vector3(mixColor))
destinationVisual.CreatePropertyMap(destinationMap);
+ static auto findValue = [](const Property::Map& map, Property::Index index) -> Vector4 {
+ Property::Value* propertyValue = map.Find(index);
+ if(propertyValue)
+ {
+ return propertyValue->Get<Vector4>();
+ }
+ return Vector4{};
+ };
+
Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f);
Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
- Vector4 destinationMixColor = destinationMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
- Vector4 destinationCornerRadius = destinationMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+ Vector4 destinationMixColor = findValue(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+ Vector4 destinationCornerRadius = findValue(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source);
Toolkit::Visual::Base sourceVisual;
if(sourceVisual)
{
sourceVisual.CreatePropertyMap(sourceMap);
- sourceMixColor = sourceMap.Find(Dali::Toolkit::Visual::Property::MIX_COLOR)->Get<Vector4>();
- sourceCornerRadius = sourceMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+ sourceMixColor = findValue(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR);
+ sourceCornerRadius = findValue(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS);
}
- std::vector<Dali::Property> properties;
+ std::vector<Dali::Property> properties;
std::vector<std::pair<Property::Value, Property::Value>> values;
if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
if(renderableActor != mRenderableActor)
{
+ UnparentAndReset(mBackgroundActor);
UnparentAndReset(mRenderableActor);
mRenderableActor = renderableActor;
+
+ if(mRenderableActor)
+ {
+ mBackgroundActor = mController->CreateBackgroundActor();
+ }
}
}
if(mRenderableActor)
{
+ const Vector2& scrollOffset = mController->GetTextModel()->GetScrollPosition();
+
+ float renderableActorPositionX, renderableActorPositionY;
+
+ if(mStencil)
+ {
+ renderableActorPositionX = scrollOffset.x + mAlignmentOffset;
+ renderableActorPositionY = scrollOffset.y;
+ }
+ else
+ {
+ Extents padding;
+ padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
+
+ // Support Right-To-Left of padding
+ Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
+ {
+ std::swap(padding.start, padding.end);
+ }
+
+ renderableActorPositionX = scrollOffset.x + mAlignmentOffset + padding.start;
+ renderableActorPositionY = scrollOffset.y + padding.top;
+ }
+
+ mRenderableActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY));
// Make sure the actors are parented correctly with/without clipping
Actor self = mStencil ? mStencil : Self();
+ Actor highlightActor;
+
for(std::vector<Actor>::iterator it = mClippingDecorationActors.begin(),
endIt = mClippingDecorationActors.end();
it != endIt;
{
self.Add(*it);
it->LowerToBottom();
+
+ if(it->GetProperty<std::string>(Dali::Actor::Property::NAME) == "HighlightActor")
+ {
+ highlightActor = *it;
+ }
}
mClippingDecorationActors.clear();
self.Add(mRenderableActor);
+ if(mBackgroundActor)
+ {
+ if(mDecorator && mDecorator->IsHighlightVisible())
+ {
+ self.Add(mBackgroundActor);
+ mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(renderableActorPositionX, renderableActorPositionY)); // In text field's coords.
+ mBackgroundActor.LowerBelow(highlightActor);
+ }
+ else
+ {
+ mRenderableActor.Add(mBackgroundActor);
+ mBackgroundActor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f)); // In renderable actor's coords.
+ mBackgroundActor.LowerToBottom();
+ }
+ }
+
ApplyScrollPosition();
}
UpdateScrollBar();
return states;
}
-bool TextEditor::AccessibleImpl::InsertText(size_t startPosition,
+bool TextEditor::AccessibleImpl::InsertText(size_t startPosition,
std::string text)
{
auto slf = Toolkit::TextEditor::DownCast(Self());
Actor mRenderableActor;
Actor mActiveLayer;
+ Actor mBackgroundActor;
CallbackBase* mIdleCallback;
float mAlignmentOffset;
${toolkit_src_dir}/focus-manager/keyboard-focus-manager-impl.cpp
${toolkit_src_dir}/focus-manager/keyinput-focus-manager-impl.cpp
- ${toolkit_src_dir}/focus-manager/focus-finder-impl.cpp
${toolkit_src_dir}/helpers/color-conversion.cpp
${toolkit_src_dir}/helpers/property-helper.cpp
${toolkit_src_dir}/filters/blur-two-pass-filter.cpp
${toolkit_src_dir}/text/markup-processor-embedded-item.cpp
${toolkit_src_dir}/text/markup-processor-anchor.cpp
${toolkit_src_dir}/text/markup-processor-font.cpp
+ ${toolkit_src_dir}/text/markup-processor-background.cpp
${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
${toolkit_src_dir}/text/multi-language-support.cpp
${toolkit_src_dir}/text/hidden-text.cpp
${toolkit_src_dir}/text/rendering/text-backend-impl.cpp
${toolkit_src_dir}/text/rendering/text-typesetter.cpp
${toolkit_src_dir}/text/rendering/view-model.cpp
+ ${toolkit_src_dir}/transition/fade-impl.cpp
${toolkit_src_dir}/transition/transition-base-impl.cpp
${toolkit_src_dir}/transition/transition-impl.cpp
${toolkit_src_dir}/transition/transition-lifecycle-controller.cpp
+++ /dev/null
-/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- */\r
-\r
-/*\r
- * Copyright (C) 2017 The Android Open Source Project\r
- *\r
- * Modified by joogab yun(joogab.yun@samsung.com)\r
- */\r
-\r
-// CLASS HEADER\r
-#include "focus-finder-impl.h"\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali/devel-api/actors/actor-devel.h>\r
-\r
-// EXTERNAL INCLUDES\r
-#include <dali/integration-api/adaptor-framework/adaptor.h>\r
-#include <dali/integration-api/adaptor-framework/scene-holder.h>\r
-#include <dali/integration-api/debug.h>\r
-#include <dali/public-api/actors/layer.h>\r
-#include <math.h>\r
-\r
-namespace\r
-{\r
-static int MajorAxisDistanceRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- {\r
- return source.left - dest.right;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- return dest.left - source.right;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- {\r
- return source.top - dest.bottom;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- return dest.top - source.bottom;\r
- }\r
- default:\r
- {\r
- return 0;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * @return The distance from the edge furthest in the given direction\r
- * of source to the edge nearest in the given direction of dest.\r
- * If the dest is not in the direction from source, return 0.\r
- */\r
-static int MajorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
- return std::max(0, MajorAxisDistanceRaw(direction, source, dest));\r
-}\r
-\r
-static int MajorAxisDistanceToFarEdgeRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- {\r
- return source.left - dest.left;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- return dest.right - source.right;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- {\r
- return source.top - dest.top;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- return dest.bottom - source.bottom;\r
- }\r
- default:\r
- {\r
- return 0;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * @return The distance along the major axis w.r.t the direction from the\r
- * edge of source to the far edge of dest.\r
- * If the dest is not in the direction from source, return 1\r
- */\r
-static int MajorAxisDistanceToFarEdge(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
- return std::max(1, MajorAxisDistanceToFarEdgeRaw(direction, source, dest));\r
-}\r
-\r
-/**\r
- * Find the distance on the minor axis w.r.t the direction to the nearest\r
- * edge of the destination rectangle.\r
- * @param direction the direction (up, down, left, right)\r
- * @param source The source rect.\r
- * @param dest The destination rect.\r
- * @return The distance.\r
- */\r
-static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> dest)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- // the distance between the center verticals\r
- return std::abs(\r
- (((source.top + source.bottom) * 0.5f) -\r
- (((dest.top + dest.bottom) * 0.5f))));\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- // the distance between the center horizontals\r
- return std::abs(\r
- (((source.left + source.right) * 0.5f) -\r
- (((dest.left + dest.right) * 0.5f))));\r
- }\r
- default:\r
- {\r
- return 0;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * Calculate distance given major and minor axis distances.\r
- * @param majorAxisDistance The majorAxisDistance\r
- * @param minorAxisDistance The minorAxisDistance\r
- * @return The distance\r
- */\r
-static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance)\r
-{\r
- return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;\r
-}\r
-\r
-/**\r
- * Convert x,y,width,height coordinates into left, right, bottom, top coordinates.\r
- * @param[in,out] rect The rect\r
- */\r
-static void ConvertCoordinate(Dali::Rect<float>& rect)\r
-{\r
- // convert x, y, width, height -> left, right, bottom, top\r
- float left = rect.x;\r
- float right = rect.x + rect.width;\r
- float bottom = rect.y + rect.height;\r
- float top = rect.y;\r
-\r
- rect.left = left;\r
- rect.right = right;\r
- rect.bottom = bottom;\r
- rect.top = top;\r
-}\r
-\r
-/**\r
- * Is destRect a candidate for the next focus given the direction?\r
- * @param srcRect The source rect.\r
- * @param destRect The dest rect.\r
- * @param direction The direction (up, down, left, right)\r
- * @return Whether destRect is a candidate.\r
- */\r
-static bool IsCandidate(Dali::Rect<float> srcRect, Dali::Rect<float> destRect, Dali::Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- {\r
- return (srcRect.right > destRect.right || srcRect.left >= destRect.right) && srcRect.left > destRect.left;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- return (srcRect.left < destRect.left || srcRect.right <= destRect.left) && srcRect.right < destRect.right;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- {\r
- return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) && srcRect.top > destRect.top;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) && srcRect.bottom < destRect.bottom;\r
- }\r
- default:\r
- {\r
- return false;\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-/**\r
- * Is dest in a given direction from src?\r
- * @param direction the direction (up, down, left, right)\r
- * @param src The source rect\r
- * @param dest The dest rect\r
- */\r
-static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> src, Dali::Rect<float> dest)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- {\r
- return src.left >= dest.right;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- return src.right <= dest.left;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- {\r
- return src.top >= dest.bottom;\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- return src.bottom <= dest.top;\r
- }\r
- default:\r
- {\r
- return false;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * Do the given direction's axis of rect1 and rect2 overlap?\r
- * @param direction the direction (up, down, left, right)\r
- * @param rect1 The first rect\r
- * @param rect2 The second rect\r
- * @return whether the beams overlap\r
- */\r
-static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
-{\r
- switch(direction)\r
- {\r
- case Dali::Toolkit::Control::KeyboardFocus::LEFT:\r
- case Dali::Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);\r
- }\r
- case Dali::Toolkit::Control::KeyboardFocus::UP:\r
- case Dali::Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);\r
- }\r
- default:\r
- {\r
- return false;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect.\r
- * @param direction The direction (up, down, left, right)\r
- * @param source The source rect\r
- * @param rect1 The first rect\r
- * @param rect2 The second rect\r
- * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam\r
- */\r
-static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect<float> source, Dali::Rect<float> rect1, Dali::Rect<float> rect2)\r
-{\r
- const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1);\r
- const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2);\r
- // if rect1 isn't exclusively in the src beam, it doesn't win\r
- if(rect2InSrcBeam || !rect1InSrcBeam)\r
- {\r
- return false;\r
- }\r
- // we know rect1 is in the beam, and rect2 is not\r
- // if rect1 is to the direction of, and rect2 is not, rect1 wins.\r
- // for example, for direction left, if rect1 is to the left of the source\r
- // and rect2 is below, then we always prefer the in beam rect1, since rect2\r
- // could be reached by going down.\r
- if(!IsToDirectionOf(direction, source, rect2))\r
- {\r
- return true;\r
- }\r
- // for horizontal directions, being exclusively in beam always wins\r
- if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT))\r
- {\r
- return true;\r
- }\r
- // for vertical directions, beams only beat up to a point:\r
- // now, as long as rect2 isn't completely closer, rect1 wins\r
- // e.g for direction down, completely closer means for rect2's top\r
- // edge to be closer to the source's top edge than rect1's bottom edge.\r
- return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2));\r
-}\r
-\r
-} // unnamed namespace\r
-\r
-namespace Dali\r
-{\r
-namespace Toolkit\r
-{\r
-namespace Internal\r
-{\r
-FocusFinder::FocusFinder()\r
-{\r
-}\r
-\r
-FocusFinder::~FocusFinder()\r
-{\r
-}\r
-\r
-Actor FocusFinder::GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
- Actor nearestActor;\r
- if(!focusedActor)\r
- {\r
- return nearestActor;\r
- }\r
-\r
- Rect<float> focusedRect = DevelActor::CalculateScreenExtents(focusedActor);\r
-\r
- // initialize the best candidate to something impossible\r
- // (so the first plausible actor will become the best choice)\r
- Rect<float> bestCandidateRect = focusedRect;\r
- switch(direction)\r
- {\r
- case Toolkit::Control::KeyboardFocus::LEFT:\r
- {\r
- bestCandidateRect.x += 1;\r
- break;\r
- }\r
- case Toolkit::Control::KeyboardFocus::RIGHT:\r
- {\r
- bestCandidateRect.x -= 1;\r
- break;\r
- }\r
- case Toolkit::Control::KeyboardFocus::UP:\r
- {\r
- bestCandidateRect.y += 1;\r
- break;\r
- }\r
- case Toolkit::Control::KeyboardFocus::DOWN:\r
- {\r
- bestCandidateRect.y -= 1;\r
- break;\r
- }\r
- default:\r
- {\r
- break;\r
- }\r
- }\r
-\r
- ConvertCoordinate(bestCandidateRect);\r
-\r
- ConvertCoordinate(focusedRect);\r
-\r
- Integration::SceneHolder window = Integration::SceneHolder::Get(focusedActor);\r
- if(window)\r
- {\r
- Actor rootActor = window.GetRootLayer();\r
- nearestActor = FindNextFocus(rootActor, focusedActor, focusedRect, bestCandidateRect, direction);\r
- }\r
- return nearestActor;\r
-}\r
-\r
-Actor FocusFinder::FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction)\r
-{\r
- Actor nearestActor;\r
- if(actor)\r
- {\r
- // Recursively children\r
- const auto childCount = actor.GetChildCount();\r
- for(auto i = 0u; i < childCount; ++i)\r
- {\r
- Dali::Actor child = actor.GetChildAt(i);\r
- if(child && child != focusedActor && child.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE))\r
- {\r
- Rect<float> candidateRect = DevelActor::CalculateScreenExtents(child);\r
-\r
- // convert x, y, width, height -> left, right, bottom, top\r
- ConvertCoordinate(candidateRect);\r
-\r
- if(IsBetterCandidate(direction, focusedRect, candidateRect, bestCandidateRect))\r
- {\r
- bestCandidateRect = candidateRect;\r
- nearestActor = child;\r
- }\r
- }\r
- Actor nextActor = FindNextFocus(child, focusedActor, focusedRect, bestCandidateRect, direction);\r
- if(nextActor)\r
- {\r
- nearestActor = nextActor;\r
- }\r
- }\r
- }\r
- return nearestActor;\r
-}\r
-\r
-bool FocusFinder::IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect) const\r
-{\r
- // to be a better candidate, need to at least be a candidate in the first place\r
- if(!IsCandidate(focusedRect, candidateRect, direction))\r
- {\r
- return false;\r
- }\r
- // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate,\r
- // candidateRect is better\r
- if(!IsCandidate(focusedRect, bestCandidateRect, direction))\r
- {\r
- return true;\r
- }\r
- // if candidateRect is better by beam, it wins\r
- if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect))\r
- {\r
- return true;\r
- }\r
- // if bestCandidateRect is better, then candidateRect cant' be :)\r
- if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect))\r
- {\r
- return false;\r
- }\r
-\r
- // otherwise, do fudge-tastic comparison of the major and minor axis\r
- return (GetWeightedDistanceFor(\r
- MajorAxisDistance(direction, focusedRect, candidateRect),\r
- MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect),\r
- MinorAxisDistance(direction, focusedRect, bestCandidateRect)));\r
-}\r
-\r
-} // namespace Internal\r
-\r
-} // namespace Toolkit\r
-\r
-} // namespace Dali\r
+++ /dev/null
-#ifndef DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
-#define DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
-\r
-/*\r
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- *\r
- */\r
-\r
-// EXTERNAL INCLUDES\r
-#include <dali/public-api/object/base-object.h>\r
-\r
-// INTERNAL INCLUDES\r
-#include <dali-toolkit/devel-api/focus-manager/focus-finder.h>\r
-\r
-namespace Dali\r
-{\r
-namespace Integration\r
-{\r
-class SceneHolder;\r
-\r
-} // namespace Integration\r
-\r
-namespace Toolkit\r
-{\r
-namespace Internal\r
-{\r
-class FocusFinder;\r
-\r
-/**\r
- * @copydoc Toolkit::FocusFinder\r
- */\r
-class FocusFinder : public Dali::BaseObject\r
-{\r
-public:\r
- /**\r
- * Construct a new FocusFinder.\r
- */\r
- FocusFinder();\r
-\r
- /**\r
- * @copydoc Toolkit::GetNearestFocusableActor\r
- */\r
- Actor GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
-protected:\r
- /**\r
- * Destructor\r
- */\r
- virtual ~FocusFinder();\r
-\r
-private:\r
- /**\r
- * Find the next actor to take focus in root's descendants, starting from the actor.\r
- * @param[in] actor The root actor.\r
- * @param[in] focusedActor The current focused actor.\r
- * @param[in] focusedRect The rect of current focused actor.\r
- * @param[in] bestCandidateRect The current best candidate.\r
- * @param[in] direction The direction.\r
- * @return nearest Actor.\r
- */\r
- Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect<float>& focusedRect, Rect<float>& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction);\r
-\r
- /**\r
- * Is rect1 a better candidate than rect2 for a focus search in a particular\r
- * direction from a source rect? This is the core routine that determines\r
- * the order of focus searching.\r
- * @param direction The direction (up, down, left, right)\r
- * @param candidateRect The candidate rectangle\r
- * @param bestCandidateRect The current best candidate.\r
- * @return Whether the candidate is the new best.\r
- */\r
- bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect<float>& focusedRect, Rect<float>& candidateRect, Rect<float>& bestCandidateRect) const;\r
-\r
-private:\r
- // Undefined\r
- FocusFinder(const FocusFinder&);\r
-\r
- FocusFinder& operator=(const FocusFinder& rhs);\r
-};\r
-\r
-} // namespace Internal\r
-\r
-inline Internal::FocusFinder& GetImpl(Dali::Toolkit::FocusFinder& obj)\r
-{\r
- DALI_ASSERT_ALWAYS(obj);\r
-\r
- Dali::BaseObject& handle = obj.GetBaseObject();\r
-\r
- return static_cast<Internal::FocusFinder&>(handle);\r
-}\r
-\r
-inline const Internal::FocusFinder& GetImpl(const Dali::Toolkit::FocusFinder& obj)\r
-{\r
- DALI_ASSERT_ALWAYS(obj);\r
-\r
- const Dali::BaseObject& handle = obj.GetBaseObject();\r
-\r
- return static_cast<const Internal::FocusFinder&>(handle);\r
-}\r
-\r
-} // namespace Toolkit\r
-\r
-} // namespace Dali\r
-\r
-#endif // DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H\r
else
{
// We should find it among the actors nearby.
- nextFocusableActor = Toolkit::FocusFinder::Get().GetNearestFocusableActor(currentFocusActor, direction);
+ nextFocusableActor = Toolkit::FocusFinder::GetNearestFocusableActor(currentFocusActor, direction);
}
}
// calculate borderline opacity by potential
if(potential > gMaxOutlinePotential)
{
- // potential is out of borderline range
- opacity = 0.0;
+ // potential is out of borderline range. just discard here
+ discard;
}
else if(potential > gMinOutlinePotential)
{
// calculate borderline opacity by potential
if(potential > gMaxOutlinePotential)
{
- // potential is out of borderline range
- opacity = 0.0;
+ // potential is out of borderline range. just discard here
+ discard;
}
else if(potential > gMinOutlinePotential)
{
// calculate borderline opacity by potential
if(potential > gMaxOutlinePotential)
{
- // potential is out of borderline range
- opacity = 0.0;
+ // potential is out of borderline range. just discard here
+ discard;
}
else if(potential > gMinOutlinePotential)
{
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor-background.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string XHTML_COLOR_ATTRIBUTE("color");
+} // namespace
+
+void ProcessBackground(const Tag& tag, ColorRun& colorRun)
+{
+ for(auto&& attribute : tag.attributes)
+ {
+ if(TokenComparison(XHTML_COLOR_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+ }
+ }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
\ No newline at end of file
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct ColorRun;
+
+/**
+ * @brief Retrieves the @e background from the @p tag.
+ *
+ * @param[in] tag The background tag and its attributes.
+ * @param[in,out] colorRun The color run to be filled.
+ */
+void ProcessBackground(const Tag& tag, ColorRun& colorRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
\ No newline at end of file
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/markup-processor-anchor.h>
+#include <dali-toolkit/internal/text/markup-processor-background.h>
#include <dali-toolkit/internal/text/markup-processor-color.h>
#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
#include <dali-toolkit/internal/text/markup-processor-font.h>
const std::string XHTML_OUTLINE_TAG("outline");
const std::string XHTML_ITEM_TAG("item");
const std::string XHTML_ANCHOR_TAG("a");
+const std::string XHTML_BACKGROUND_TAG("background");
const char LESS_THAN = '<';
const char GREATER_THAN = '>';
* @param[in] fontRunIndex The font run index
* @param[in] colorRunIndex The color run index
* @param[in] underlinedCharacterRunIndex The underlined character run index
+ * @param[in] backgroundRunIndex The background run index
*/
-void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex)
+void ResizeModelVectors(MarkupProcessData& markupProcessData, const StyleStack::RunIndex fontRunIndex, const StyleStack::RunIndex colorRunIndex, const StyleStack::RunIndex underlinedCharacterRunIndex, const StyleStack::RunIndex backgroundRunIndex)
{
markupProcessData.fontRuns.Resize(fontRunIndex);
markupProcessData.colorRuns.Resize(colorRunIndex);
markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
+ markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
#ifdef DEBUG_ENABLED
for(unsigned int i = 0; i < colorRunIndex; ++i)
StyleStack styleStack;
// Points the next free position in the vector of runs.
- StyleStack::RunIndex colorRunIndex = 0u;
- StyleStack::RunIndex fontRunIndex = 0u;
- StyleStack::RunIndex underlinedCharacterRunIndex = 0u;
+ StyleStack::RunIndex colorRunIndex = 0u;
+ StyleStack::RunIndex fontRunIndex = 0u;
+ StyleStack::RunIndex underlinedCharacterRunIndex = 0u;
+ StyleStack::RunIndex backgroundRunIndex = 0u;
// check tag reference
- int colorTagReference = 0u;
- int fontTagReference = 0u;
- int iTagReference = 0u;
- int bTagReference = 0u;
- int uTagReference = 0u;
+ int colorTagReference = 0u;
+ int fontTagReference = 0u;
+ int iTagReference = 0u;
+ int bTagReference = 0u;
+ int uTagReference = 0u;
+ int backgroundTagReference = 0u;
// Give an initial default value to the model's vectors.
markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+ markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
// Get the mark-up string buffer.
const char* markupStringBuffer = markupString.c_str();
else if(TokenComparison(XHTML_U_TAG, tag.buffer, tag.length))
{
ProcessTagForRun<UnderlinedCharacterRun>(
- markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { });
- } // <u></u>
+ markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {});
+ } // <u></u>
else if(TokenComparison(XHTML_B_TAG, tag.buffer, tag.length))
{
ProcessTagForRun<FontDescriptionRun>(
{
ProcessItemTag(markupProcessData, tag, characterIndex);
}
+ else if(TokenComparison(XHTML_BACKGROUND_TAG, tag.buffer, tag.length))
+ {
+ ProcessTagForRun<ColorRun>(
+ markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
+ }
} // end if( IsTag() )
else if(markupStringBuffer < markupStringEndBuffer)
{
}
// Resize the model's vectors.
- ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex);
+ ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, backgroundRunIndex);
}
} // namespace Text
*/
struct MarkupProcessData
{
- MarkupProcessData(Vector<ColorRun>& colorRuns,
- Vector<FontDescriptionRun>& fontRuns,
- Vector<EmbeddedItem>& items,
- Vector<Anchor>& anchors,
- Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
+ MarkupProcessData(Vector<ColorRun>& colorRuns,
+ Vector<FontDescriptionRun>& fontRuns,
+ Vector<EmbeddedItem>& items,
+ Vector<Anchor>& anchors,
+ Vector<UnderlinedCharacterRun>& underlinedCharacterRuns,
+ Vector<ColorRun>& backgroundColorRuns)
: colorRuns(colorRuns),
fontRuns(fontRuns),
items(items),
anchors(anchors),
underlinedCharacterRuns(underlinedCharacterRuns),
+ backgroundColorRuns(backgroundColorRuns),
markupProcessedText()
{
}
Vector<EmbeddedItem>& items; ///< The embedded items.
Vector<Anchor>& anchors; ///< The anchors.
Vector<UnderlinedCharacterRun>& underlinedCharacterRuns; ///< The underlined character runs.
+ Vector<ColorRun>& backgroundColorRuns; ///< The background color runs.
std::string markupProcessedText; ///< The mark-up string.
};
}
}
+Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, int horizontalOffset, int verticalOffset)
+{
+ // Retrieve lines, glyphs, positions and colors from the view model.
+ const Length modelNumberOfLines = model->GetNumberOfLines();
+ const LineRun* const modelLinesBuffer = model->GetLines();
+ const Length numberOfGlyphs = model->GetNumberOfGlyphs();
+ const GlyphInfo* const glyphsBuffer = model->GetGlyphs();
+ const Vector2* const positionBuffer = model->GetLayout();
+ const Vector4* const backgroundColorsBuffer = model->GetBackgroundColors();
+ const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices();
+
+ // Create and initialize the pixel buffer.
+ GlyphData glyphData;
+ glyphData.verticalOffset = verticalOffset;
+ glyphData.width = bufferWidth;
+ glyphData.height = bufferHeight;
+ glyphData.bitmapBuffer = buffer;
+ glyphData.horizontalOffset = 0;
+
+ ColorIndex prevBackgroundColorIndex = 0;
+ ColorIndex backgroundColorIndex = 0;
+
+ // Traverses the lines of the text.
+ for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex)
+ {
+ const LineRun& line = *(modelLinesBuffer + lineIndex);
+
+ // Sets the horizontal offset of the line.
+ glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast<int>(line.alignmentOffset);
+ glyphData.horizontalOffset += horizontalOffset;
+
+ // Increases the vertical offset with the line's ascender.
+ glyphData.verticalOffset += static_cast<int>(line.ascender);
+
+ // Include line spacing after first line
+ if(lineIndex > 0u)
+ {
+ glyphData.verticalOffset += static_cast<int>(line.lineSpacing);
+ }
+
+ float left = bufferWidth;
+ float right = 0.0f;
+ float baseline = 0.0f;
+
+ // Traverses the glyphs of the line.
+ const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs);
+ for(GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex)
+ {
+ // Retrieve the glyph's info.
+ const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex;
+
+ if((glyphInfo->width < Math::MACHINE_EPSILON_1000) ||
+ (glyphInfo->height < Math::MACHINE_EPSILON_1000))
+ {
+ // Nothing to do if default background color, the glyph's width or height is zero.
+ continue;
+ }
+
+ backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + glyphIndex);
+
+ if((backgroundColorIndex != prevBackgroundColorIndex) &&
+ (prevBackgroundColorIndex != 0u))
+ {
+ const Vector4& backgroundColor = *(backgroundColorsBuffer + prevBackgroundColorIndex - 1u);
+ DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right);
+ }
+
+ if(backgroundColorIndex == 0u)
+ {
+ prevBackgroundColorIndex = backgroundColorIndex;
+ //if background color is the default do nothing
+ continue;
+ }
+
+ // Retrieves the glyph's position.
+ const Vector2* const position = positionBuffer + glyphIndex;
+
+ if(baseline < position->y + glyphInfo->yBearing)
+ {
+ baseline = position->y + glyphInfo->yBearing;
+ }
+
+ // Calculate the positions of leftmost and rightmost glyphs in the current line
+ if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex))
+ {
+ left = position->x - glyphInfo->xBearing;
+ }
+
+ if(position->x + glyphInfo->width > right)
+ {
+ right = position->x - glyphInfo->xBearing + glyphInfo->advance;
+ }
+
+ prevBackgroundColorIndex = backgroundColorIndex;
+ }
+
+ //draw last background at line end if not default
+ if(backgroundColorIndex != 0u)
+ {
+ const Vector4& backgroundColor = *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+ DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right);
+ }
+
+ // Increases the vertical offset with the line's descender.
+ glyphData.verticalOffset += static_cast<int>(-line.descender);
+ }
+
+ return glyphData.bitmapBuffer;
+}
+
} // namespace
TypesetterPtr Typesetter::New(const ModelInterface* const model)
}
// Generate the background if enabled
- const bool backgroundEnabled = mModel->IsBackgroundEnabled();
- if(backgroundEnabled)
+ const bool backgroundEnabled = mModel->IsBackgroundEnabled();
+ const bool backgroundMarkupSet = mModel->IsMarkupBackgroundColorSet();
+ if(backgroundEnabled || backgroundMarkupSet)
{
- Devel::PixelBuffer backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+ Devel::PixelBuffer backgroundImageBuffer;
+
+ if(backgroundEnabled)
+ {
+ backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1);
+ }
+ else
+ {
+ backgroundImageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat);
+ }
+
+ if(backgroundMarkupSet)
+ {
+ DrawGlyphsBackground(mModel, backgroundImageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, penX, penY);
+ }
// Combine the two buffers
imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight);
return mModel->GetBackgroundColorIndices();
}
+bool const ViewModel::IsMarkupBackgroundColorSet() const
+{
+ return mModel->IsMarkupBackgroundColorSet();
+}
+
const Vector4& ViewModel::GetDefaultColor() const
{
return mModel->GetDefaultColor();
const ColorIndex* const GetBackgroundColorIndices() const override;
/**
+ * @copydoc ModelInterface::IsMarkupBackgroundColorSet()
+ */
+ bool const IsMarkupBackgroundColorSet() const override;
+
+ /**
* @copydoc ModelInterface::GetDefaultColor()
*/
const Vector4& GetDefaultColor() const override;
mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
- updated = true;
+ updated = true;
}
const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
colorRun.color = backgroundColor;
colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit;
colorRun.characterRun.numberOfCharacters = numberOfIndices;
-
mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
+
+ //Mark-up processor case
+ if(mModel->mVisualModel->IsMarkupProcessorEnabled())
+ {
+ CopyUnderlinedFromLogicalToVisualModels(false);
+ }
break;
}
case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
backgroundColorRun.color = LIGHT_BLUE;
mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+ //Mark-up processor case
+ if(mModel->mVisualModel->IsMarkupProcessorEnabled())
+ {
+ CopyUnderlinedFromLogicalToVisualModels(false);
+ }
break;
}
case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
}
if((NO_OPERATION != (SHAPE_TEXT & operations)) &&
- ! ((nullptr != mEventData) &&
- mEventData->mPreEditFlag &&
- (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
+ !((nullptr != mEventData) &&
+ mEventData->mPreEditFlag &&
+ (0u != mModel->mVisualModel->mCharactersToGlyph.Count())))
{
//Mark-up processor case
if(mModel->mVisualModel->IsMarkupProcessorEnabled())
updated = true;
}
-
// The estimated number of lines. Used to avoid reallocations when layouting.
mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count());
Actor Controller::Impl::CreateBackgroundActor()
{
- // NOTE: Currently we only support background color for one line left-to-right text,
- // so the following calculation is based on one line left-to-right text only!
+ // NOTE: Currently we only support background color for left-to-right text.
Actor actor;
const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices();
const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
- Vector4 quad;
- uint32_t numberOfQuads = 0u;
+ Vector4 quad;
+ uint32_t numberOfQuads = 0u;
+ Length yLineOffset = 0;
+ Length prevLineIndex = 0;
+ LineIndex lineIndex;
+ Length numberOfLines;
for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
{
const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i);
const Vector4& backgroundColor = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+ mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines);
+ Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing;
+
+ if(lineIndex != prevLineIndex)
+ {
+ yLineOffset += lineHeight;
+ }
+
// Only create quads for glyphs with a background color
if(backgroundColor != Color::TRANSPARENT)
{
if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
{
quad.x = position.x;
- quad.y = 0.0f;
+ quad.y = yLineOffset;
quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
- quad.w = textSize.height;
+ quad.w = lineHeight;
}
- else if(i == 0u) // The first glyph in the whole text
+ else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
{
quad.x = position.x;
- quad.y = 0.0f;
+ quad.y = yLineOffset;
quad.z = quad.x - glyph.xBearing + glyph.advance;
- quad.w = textSize.height;
+ quad.w = quad.y + lineHeight;
}
else if(i == glyphSize - 1u) // The last glyph in the whole text
{
quad.x = position.x - glyph.xBearing;
- quad.y = 0.0f;
+ quad.y = yLineOffset;
quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width);
- quad.w = textSize.height;
+ quad.w = quad.y + lineHeight;
}
else // The glyph in the middle of the text
{
quad.x = position.x - glyph.xBearing;
- quad.y = 0.0f;
+ quad.y = yLineOffset;
quad.z = quad.x + glyph.advance;
- quad.w = textSize.height;
+ quad.w = quad.y + lineHeight;
}
BackgroundVertex vertex;
numberOfQuads++;
}
+
+ if(lineIndex != prevLineIndex)
+ {
+ prevLineIndex = lineIndex;
+ }
}
// Only create the background actor if there are glyphs with background color
void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
{
- //Underlined character runs for markup-processor
- const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
- const Vector<GlyphIndex>& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph;
- const Vector<Length>& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter;
+ //Underlined character runs for markup-processor
+ const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
+ const Vector<GlyphIndex>& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph;
+ const Vector<Length>& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter;
- if(shouldClearPreUnderlineRuns)
- {
- mModel->mVisualModel->mUnderlineRuns.Clear();
- }
+ if(shouldClearPreUnderlineRuns)
+ {
+ mModel->mVisualModel->mUnderlineRuns.Clear();
+ }
- for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+ for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+ {
+ CharacterIndex characterIndex = it->characterRun.characterIndex;
+ Length numberOfCharacters = it->characterRun.numberOfCharacters;
+ for(Length index = 0u; index < numberOfCharacters; index++)
{
- CharacterIndex characterIndex = it->characterRun.characterIndex;
- Length numberOfCharacters = it->characterRun.numberOfCharacters;
- for(Length index=0u; index<numberOfCharacters; index++)
- {
- GlyphRun underlineGlyphRun;
- underlineGlyphRun.glyphIndex = charactersToGlyph[characterIndex + index];
- underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
- mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
- }
+ GlyphRun underlineGlyphRun;
+ underlineGlyphRun.glyphIndex = charactersToGlyph[characterIndex + index];
+ underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index];
+ mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
}
+ }
}
} // namespace Text
logicalModel->mFontDescriptionRuns,
logicalModel->mEmbeddedItems,
logicalModel->mAnchors,
- logicalModel->mUnderlinedCharacterRuns);
+ logicalModel->mUnderlinedCharacterRuns,
+ logicalModel->mBackgroundColorRuns);
Length textSize = 0u;
const uint8_t* utf8 = NULL;
if(EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState)
{
- const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
+ if(EventData::SELECTING == mImpl->mEventData->mState)
+ {
+ const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
+
+ // Get start and end position of selection
+ const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
+ const Length lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
- // Get start and end position of selection
- const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
- const Length lengthOfSelectedText = (handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
+ // Add the color run.
+ const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
+ mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
- // Add the color run.
- const VectorBase::SizeType numberOfRuns = mImpl->mModel->mLogicalModel->mColorRuns.Count();
- mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
+ ColorRun& colorRun = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
+ colorRun.color = color;
+ colorRun.characterRun.characterIndex = startOfSelectedText;
+ colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
- ColorRun& colorRun = *(mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
- colorRun.color = color;
- colorRun.characterRun.characterIndex = startOfSelectedText;
- colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
+ mImpl->mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = lengthOfSelectedText;
+ }
+ else
+ {
+ mImpl->mTextUpdateInfo.mCharacterIndex = 0;
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+ mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mModel->mLogicalModel->mText.Count();
+ }
// Request to relayout.
mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
mImpl->RequestRelayout();
-
- mImpl->mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
- mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = lengthOfSelectedText;
}
}
}
virtual const ColorIndex* const GetBackgroundColorIndices() const = 0;
/**
+ * @brief checks if there is background colors set using markup.
+ *
+ * @return boolean if there is background colors set using markup .
+ */
+ virtual bool const IsMarkupBackgroundColorSet() const = 0;
+
+ /**
* @brief Retrieves the text's default color.
*
* @return The default color.
// CLASS HEADER
#include <dali-toolkit/internal/text/text-model.h>
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+
namespace Dali
{
namespace Toolkit
{
namespace Text
{
+namespace
+{
+const char* DALI_ENV_MATCH_SYSTEM_LANGUAGE_DIRECTION("DALI_MATCH_SYSTEM_LANGUAGE_DIRECTION");
+}
+
ModelPtr Model::New()
{
return ModelPtr(new Model());
return mVisualModel->mBackgroundColorIndices.Begin();
}
+bool const Model::IsMarkupBackgroundColorSet() const
+{
+ return (mVisualModel->mBackgroundColorIndices.Count() > 0);
+}
+
const Vector4& Model::GetDefaultColor() const
{
return mVisualModel->mTextColor;
mAlignmentOffset(0.0f),
mElideEnabled(false),
mIgnoreSpacesAfterText(true),
- mMatchSystemLanguageDirection(false)
+ mMatchSystemLanguageDirection(true)
{
mLogicalModel = LogicalModel::New();
mVisualModel = VisualModel::New();
+
+ // Check environment variable for DALI_MATCH_SYSTEM_LANGUAGE_DIRECTION
+ auto match = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_MATCH_SYSTEM_LANGUAGE_DIRECTION);
+ mMatchSystemLanguageDirection = match ? (std::atoi(match) == 0 ? false : true) : mMatchSystemLanguageDirection;
}
Model::~Model()
const ColorIndex* const GetBackgroundColorIndices() const override;
/**
+ * @copydoc ModelInterface::IsMarkupBackgroundColorSet()
+ */
+ bool const IsMarkupBackgroundColorSet() const override;
+
+ /**
* @copydoc ModelInterface::GetDefaultColor()
*/
const Vector4& GetDefaultColor() const override;
virtual const ColorIndex* const GetBackgroundColorIndices() const = 0;
/**
+ * @brief checks if there is background colors set using markup.
+ *
+ * @return boolean if there is background colors set using markup .
+ */
+ virtual bool const IsMarkupBackgroundColorSet() const = 0;
+
+ /**
* @brief Retrieves the text color
*
* @return The text color
return nullptr;
}
+bool const View::IsMarkupBackgroundColorSet() const
+{
+ if(mImpl->mVisualModel)
+ {
+ return (mImpl->mVisualModel->mBackgroundColorIndices.Count() > 0);
+ }
+
+ return false;
+}
+
const Vector4& View::GetTextColor() const
{
if(mImpl->mVisualModel)
const ColorIndex* const GetBackgroundColorIndices() const override;
/**
+ * @copydoc Dali::Toolkit::Text::ViewInterface::IsMarkupBackgroundColorSet()
+ */
+ bool const IsMarkupBackgroundColorSet() const;
+
+ /**
* @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor()
*/
const Vector4& GetTextColor() const override;
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/transition/fade-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
+
+} // anonymous namespace
+
+FadePtr Fade::New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+{
+ float delaySeconds = timePeriod.delaySeconds;
+ if(delaySeconds < 0.0f)
+ {
+ DALI_LOG_WARNING("delay should be greater than 0.0f.\n");
+ delaySeconds = 0.0f;
+ }
+
+ float durationSeconds = timePeriod.durationSeconds;
+ if(durationSeconds < 0.0f)
+ {
+ DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
+ durationSeconds = 0.0f;
+ }
+
+ FadePtr fade = new Fade(control, Dali::Clamp(opacity, 0.0f, 1.0f), TimePeriod(delaySeconds, durationSeconds));
+
+ // Second-phase construction
+ fade->Initialize();
+
+ return fade;
+}
+
+Fade::Fade(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+: TransitionBase(),
+ mTargetControl(control),
+ mOpacity(opacity)
+{
+ SetTarget(control);
+ SetTimePeriod(timePeriod);
+}
+
+Fade::~Fade()
+{
+}
+
+void Fade::OnPlay()
+{
+ Dali::Toolkit::Control targetControl = mTargetControl.GetHandle();
+ if(!targetControl || !targetControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
+ {
+ DALI_LOG_ERROR("The Control is not added on the window\n");
+ return;
+ }
+
+ Property::Map initialPropertyMap;
+ Property::Map startPropertyMap;
+ Property::Map finishPropertyMap;
+
+ if(IsAppearingTransition())
+ {
+ initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, 0.0f);
+ startPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
+ finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+ }
+ else
+ {
+ initialPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+ startPropertyMap.Insert(Dali::Actor::Property::OPACITY, targetControl[Dali::Actor::Property::OPACITY]);
+ finishPropertyMap.Insert(Dali::Actor::Property::OPACITY, mOpacity);
+ }
+
+ SetInitialPropertyMap(initialPropertyMap);
+ SetStartPropertyMap(startPropertyMap);
+ SetFinishPropertyMap(finishPropertyMap);
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_INTERNAL_FADE_H
+#define DALI_TOOLKIT_INTERNAL_FADE_H
+
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/transition/transition-base-impl.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/transition/fade.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/weak-handle.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+using FadePtr = IntrusivePtr<Fade>;
+
+class Fade : public TransitionBase
+{
+public:
+ /**
+ * @brief Create a new Fade object.
+ * @param[in] control A control of this transition.
+ * @param[in] opacity opacity value the control Opacity property will be changed from/to.
+ * @param[in] timePeriod The duration of the animation.
+ * @return A smart-pointer to the newly allocated Fade.
+ */
+ static FadePtr New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod);
+
+protected:
+ /**
+ * @copydoc Dali::Toolkit::Fade::OnPlay()
+ */
+ void OnPlay() override;
+
+protected:
+ /**
+ * @brief Construct a new Fade.
+ */
+ Fade(Dali::Toolkit::Control control,
+ float opacity,
+ TimePeriod timePeriod);
+
+ /**
+ * @brief A reference counted object may only be deleted by calling Unreference()
+ */
+ ~Fade() override;
+
+private:
+ // Undefined
+ Fade(const Fade&);
+
+ // Undefined
+ Fade& operator=(const Fade& rhs);
+
+private:
+ WeakHandle<Dali::Toolkit::Control> mTargetControl;
+ float mOpacity;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Fade& GetImplementation(Dali::Toolkit::Fade& fade)
+{
+ DALI_ASSERT_ALWAYS(fade && "Fade handle is empty");
+
+ BaseObject& handle = fade.GetBaseObject();
+
+ return static_cast<Internal::Fade&>(handle);
+}
+
+inline const Internal::Fade& GetImplementation(const Dali::Toolkit::Fade& fade)
+{
+ DALI_ASSERT_ALWAYS(fade && "Fade handle is empty");
+
+ const BaseObject& handle = fade.GetBaseObject();
+
+ return static_cast<const Internal::Fade&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_FADE_H
: mAlphaFunction(DEFAULT_ALPHA_FUNCTION),
mTimePeriod(TimePeriod(0.0f)),
mTransitionWithChild(false),
- mMoveTargetChildren(false)
+ mMoveTargetChildren(false),
+ mIsAppearingTransition(true)
{
}
*/
void TransitionFinished();
+ /**
+ * @brief Set this transition is appearing transition or not.
+ * @param[in] appearingTransition True if this transition is appearing transition.
+ */
+ void SetAppearingTransition(bool appearingTransition)
+ {
+ mIsAppearingTransition = appearingTransition;
+ }
+
protected:
/**
* @brief Set property map which will be used as a initial properties.
/**
* @brief Returns whether this transition will be applied to children of target or not.
*/
- bool IsTransitionWithChild()
+ bool IsTransitionWithChild() const
{
return mTransitionWithChild;
}
+ /**
+ * @brief Returns whether this transition is appearing transition or not
+ */
+ bool IsAppearingTransition() const
+ {
+ return mIsAppearingTransition;
+ }
+
protected:
/**
* Construct a new TransitionBase.
bool mTransitionWithChild; ///< True, if mTarget transition is inherit to its child Actors.
///< If this is false, the child Actors are moved to the child of mCopiedActor that will have original properties of target Actor during Transition.
bool mMoveTargetChildren; ///< Flag, if mTransitionWithChild is false and mTarget has children than True.
+ bool mIsAppearingTransition; ///< True, if this transition is appearing transition.
};
} // namespace Internal
void Transition::OnPlay()
{
- if(!mSourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] ||
- !mDestinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
+ Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
+ Dali::Toolkit::Control destinationControl = mDestinationControl.GetHandle();
+ if(!sourceControl || !sourceControl[Dali::Actor::Property::CONNECTED_TO_SCENE] ||
+ !destinationControl || !destinationControl[Dali::Actor::Property::CONNECTED_TO_SCENE])
{
DALI_LOG_ERROR("The source or destination is not added on the window\n");
return;
}
//Make startPropertyMap and finishPropertyMap to use for property animation.
- Matrix sourceWorldTransform = mSourceControl[Dali::Actor::Property::WORLD_MATRIX];
+ Matrix sourceWorldTransform = sourceControl[Dali::Actor::Property::WORLD_MATRIX];
Vector3 sourcePosition, sourceScale;
Quaternion sourceOrientation;
sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale);
- Matrix destinationWorldTransform = GetWorldTransform(mDestinationControl);
+ Matrix destinationWorldTransform = GetWorldTransform(destinationControl);
Vector3 destinationPosition, destinationScale;
Quaternion destinationOrientation;
destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale);
- Vector3 targetSize = mDestinationControl[Dali::Actor::Property::SIZE];
- Vector4 targetColor = GetWorldColor(mDestinationControl);
+ Vector3 targetSize = destinationControl[Dali::Actor::Property::SIZE];
+ Vector4 targetColor = GetWorldColor(destinationControl);
Property::Map startPropertyMap;
Property::Map finishPropertyMap;
// Use world transform if this transition requires animation of transform.
- mDestinationControl[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
- mDestinationControl[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
- mDestinationControl[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
- mDestinationControl[Dali::Actor::Property::INHERIT_POSITION] = false;
- mDestinationControl[Dali::Actor::Property::INHERIT_ORIENTATION] = false;
- mDestinationControl[Dali::Actor::Property::INHERIT_SCALE] = false;
- mDestinationControl[Dali::Actor::Property::COLOR_MODE] = Dali::ColorMode::USE_OWN_COLOR;
+ destinationControl[Dali::Actor::Property::ANCHOR_POINT] = AnchorPoint::CENTER;
+ destinationControl[Dali::Actor::Property::PARENT_ORIGIN] = ParentOrigin::CENTER;
+ destinationControl[Dali::Actor::Property::POSITION_USES_ANCHOR_POINT] = true;
+ destinationControl[Dali::Actor::Property::INHERIT_POSITION] = false;
+ destinationControl[Dali::Actor::Property::INHERIT_ORIENTATION] = false;
+ destinationControl[Dali::Actor::Property::INHERIT_SCALE] = false;
+ destinationControl[Dali::Actor::Property::COLOR_MODE] = Dali::ColorMode::USE_OWN_COLOR;
// Set animation of Transform
startPropertyMap.Insert(Dali::Actor::Property::POSITION, sourcePosition);
startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale);
finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale);
- Vector4 sourceColor = mSourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
+ Vector4 sourceColor = sourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor);
finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor);
// Set animation for other properties if source and destination is different.
- Vector3 sourceSize = mSourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
+ Vector3 sourceSize = sourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
if(sourceSize != targetSize)
{
startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize);
// source View becomes transparent during transition.
if(IsTransitionWithChild())
{
- mSourceControl[Dali::Actor::Property::VISIBLE] = false;
+ sourceControl[Dali::Actor::Property::VISIBLE] = false;
}
else
{
- GetImplementation(mSourceControl).SetTransparent(true);
+ GetImplementation(sourceControl).SetTransparent(true);
}
Dali::Animation animation = GetAnimation();
DALI_LOG_ERROR("animation is still not initialized\n");
return;
}
- Dali::Toolkit::DevelControl::CreateTransitions(mDestinationControl, animation, mSourceControl, GetAlphaFunction(), GetTimePeriod());
+ Dali::Toolkit::DevelControl::CreateTransitions(destinationControl, animation, sourceControl, GetAlphaFunction(), GetTimePeriod());
}
void Transition::OnFinished()
{
+ Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
+ if(!sourceControl)
+ {
+ return;
+ }
+
if(IsTransitionWithChild())
{
- mSourceControl[Dali::Actor::Property::VISIBLE] = true;
+ sourceControl[Dali::Actor::Property::VISIBLE] = true;
}
else
{
- GetImplementation(mSourceControl).SetTransparent(false);
+ GetImplementation(sourceControl).SetTransparent(false);
}
}
#include <dali-toolkit/public-api/controls/control.h>
#include <dali-toolkit/public-api/transition/transition.h>
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/weak-handle.h>
+
namespace Dali
{
namespace Toolkit
* @brief Create a new Transition object.
* @param[in] source A source control of this transition.
* @param[in] destination A destination control of this transition.
- * @param[in] durationSeconds The duration of the animation.
+ * @param[in] timePeriod The timePeriod of the animation.
* @return A smart-pointer to the newly allocated Transition.
*/
static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
Transition& operator=(const Transition& rhs);
private:
- Dali::Toolkit::Control mSourceControl;
- Dali::Toolkit::Control mDestinationControl;
+ WeakHandle<Dali::Toolkit::Control> mSourceControl;
+ WeakHandle<Dali::Toolkit::Control> mDestinationControl;
};
} // namespace Internal
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 31;
+const unsigned int TOOLKIT_MICRO_VERSION = 32;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
${public_api_src_dir}/image-loader/async-image-loader.cpp
${public_api_src_dir}/image-loader/sync-image-loader.cpp
${public_api_src_dir}/styling/style-manager.cpp
+ ${public_api_src_dir}/transition/fade.cpp
${public_api_src_dir}/transition/transition-base.cpp
${public_api_src_dir}/transition/transition-set.cpp
${public_api_src_dir}/transition/transition.cpp
)
SET( public_api_transition_header_files
+ ${public_api_src_dir}/transition/fade.h
${public_api_src_dir}/transition/transition-base.h
${public_api_src_dir}/transition/transition-set.h
${public_api_src_dir}/transition/transition.h
--- /dev/null
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/public-api/transition/fade.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/transition/fade-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+Fade::Fade() = default;
+
+Fade::Fade(Internal::Fade* fade)
+: TransitionBase(fade)
+{
+}
+
+Fade Fade::New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod)
+{
+ Internal::FadePtr internal = Dali::Toolkit::Internal::Fade::New(control, opacity, timePeriod);
+
+ return Fade(internal.Get());
+}
+
+Fade Fade::DownCast(BaseHandle handle)
+{
+ return Fade(dynamic_cast<Dali::Toolkit::Internal::Fade*>(handle.GetObjectPtr()));
+}
+
+Fade::~Fade() = default;
+
+Fade::Fade(const Fade& handle) = default;
+
+Fade& Fade::operator=(const Fade& rhs) = default;
+
+Fade::Fade(Fade&& rhs) = default;
+
+Fade& Fade::operator=(Fade&& rhs) = default;
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_FADE_H
+#define DALI_TOOLKIT_FADE_H
+
+/*
+ * Copyright (c) 2021 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/transition/transition-base.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal DALI_INTERNAL
+{
+class Fade;
+}
+
+/**
+ * @brief Fade provides smoothly appearing/disappearing effects for target Control.
+ */
+class DALI_TOOLKIT_API Fade : public TransitionBase
+{
+public:
+ /**
+ * @brief Creates an uninitialized Fade; this can be initialized with Fade::New().
+ *
+ * Calling member functions with an uninitialized Fade handle is not allowed.
+ */
+ Fade();
+
+ /**
+ * @brief Creates an initialized Fade.
+ *
+ * @param[in] control A control of this transition.
+ * @param[in] opacity opacity value the control Opacity property will be changed from/to. Opacity must be between [0, 1].
+ * @param[in] timePeriod The duration of the animation.
+ * @return A handle to a newly allocated Dali resource
+ */
+ static Fade New(Dali::Toolkit::Control control, float opacity, TimePeriod timePeriod);
+
+ /**
+ * @brief Downcasts a handle to Fade handle.
+ *
+ * If handle points to an Fade object, the downcast produces valid handle.
+ * If not, the returned handle is left uninitialized.
+ *
+ * @param[in] handle Handle to an object
+ * @return Handle to an Fade object or an uninitialized handle
+ */
+ static Fade DownCast(BaseHandle handle);
+
+ /**
+ * @brief Destructor.
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~Fade();
+
+ /**
+ * @brief This copy constructor is required for (smart) pointer semantics.
+ *
+ * @param[in] handle A reference to the copied handle
+ */
+ Fade(const Fade& handle);
+
+ /**
+ * @brief This assignment operator is required for (smart) pointer semantics.
+ *
+ * @param[in] rhs A reference to the copied handle
+ * @return A reference to this
+ */
+ Fade& operator=(const Fade& rhs);
+
+ /**
+ * @brief Move constructor.
+ *
+ * @param[in] rhs A reference to the moved handle
+ */
+ Fade(Fade&& rhs);
+
+ /**
+ * @brief Move assignment operator.
+ *
+ * @param[in] rhs A reference to the moved handle
+ * @return A reference to this handle
+ */
+ Fade& operator=(Fade&& rhs);
+
+public: // Not intended for use by Application developers
+ /// @cond internal
+ /**
+ * @brief This constructor is used by Fade::New() methods.
+ * @param[in] fade A pointer to a newly allocated Dali resource
+ */
+ explicit DALI_INTERNAL Fade(Internal::Fade* fade);
+ /// @endcond
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_FADE_H
void TransitionBase::TransitionWithChild(bool transitionWithChild)
{
- return GetImplementation(*this).TransitionWithChild(transitionWithChild);
+ GetImplementation(*this).TransitionWithChild(transitionWithChild);
+}
+
+void TransitionBase::SetAppearingTransition(bool appearingTransition)
+{
+ GetImplementation(*this).SetAppearingTransition(appearingTransition);
}
} // namespace Toolkit
AlphaFunction GetAlphaFunction() const;
/**
- * @brief A View could be transition with its child Views or without them.
+ * @brief A Control could be transition with its child Controls or without them.
+ * @param[in] transitionWithChild True if the Control is transitioned with children.
*/
void TransitionWithChild(bool transitionWithChild);
+ /**
+ * @brief Set this transition is appearing transition or not.
+ * @param[in] appearingTransition True if this transition is appearing transition.
+ */
+ void SetAppearingTransition(bool appearingTransition);
+
public: // Not intended for use by Application developers
/// @cond internal
/**
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.0.31
+Version: 2.0.32
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT