Merge "Fixed SVACE error in WebView" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Mon, 8 Oct 2018 09:27:25 +0000 (09:27 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Mon, 8 Oct 2018 09:27:25 +0000 (09:27 +0000)
23 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp [changed mode: 0644->0755]
automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp [changed mode: 0644->0755]
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h [changed mode: 0644->0755]
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp [changed mode: 0644->0755]
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.h
dali-toolkit/internal/text/layouts/layout-engine.cpp [changed mode: 0644->0755]
dali-toolkit/internal/text/layouts/layout-engine.h [changed mode: 0644->0755]
dali-toolkit/internal/text/layouts/layout-parameters.h [changed mode: 0644->0755]
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json
docs/content/images/text-controls/HelloWorld-Default-END.png [new file with mode: 0755]
docs/content/images/text-controls/HelloWorld-System-END.png [new file with mode: 0755]
docs/content/shared-javascript-and-cpp-documentation/text-label.md [changed mode: 0644->0755]

index 08f2c63..ccd24b5 100755 (executable)
@@ -307,7 +307,8 @@ void CreateTextModel( const std::string& text,
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
                                        outlineWidth,
-                                       true );
+                                       true,
+                                       false );
 
   Vector<LineRun>& lines = visualModel->mLines;
 
@@ -366,7 +367,9 @@ void CreateTextModel( const std::string& text,
                         characterCount,
                         Text::HorizontalAlignment::BEGIN,
                         lines,
-                        alignmentOffset );
+                        alignmentOffset,
+                        Dali::LayoutDirection::LEFT_TO_RIGHT,
+                        false );
   }
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index ab15b46..bc9d08b
@@ -174,7 +174,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
                                        outlineWidth,
-                                       true );
+                                       true,
+                                       false );
 
   layoutParameters.isLastNewParagraph = isLastNewParagraph;
 
@@ -394,7 +395,8 @@ bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
                                        outlineWidth,
-                                       true );
+                                       true,
+                                       false );
 
   layoutParameters.numberOfBidirectionalInfoRuns = logicalModel->mBidirectionalLineInfo.Count();
   layoutParameters.lineBidirectionalInfoRunsBuffer = logicalModel->mBidirectionalLineInfo.Begin();
@@ -447,6 +449,8 @@ struct AlignData
   unsigned int                      numberOfCharacters;
   unsigned int                      numberOfLines;
   float*                            lineOffsets;
+  Dali::LayoutDirection::Type       layoutDirection;
+  bool                              matchSystemLanguageDirection;
 };
 
 bool AlignTest( const AlignData& data )
@@ -499,7 +503,9 @@ bool AlignTest( const AlignData& data )
                 data.numberOfCharacters,
                 data.horizontalAlignment,
                 visualModel->mLines,
-                alignmentOffset );
+                alignmentOffset,
+                data.layoutDirection,
+                data.matchSystemLanguageDirection );
 
   // Compare results.
   if( data.numberOfLines != visualModel->mLines.Count() )
@@ -519,7 +525,6 @@ bool AlignTest( const AlignData& data )
       return false;
     }
   }
-
   return true;
 }
 
@@ -4237,7 +4242,9 @@ int UtcDaliTextAlign01(void)
     0u,
     22u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4356,7 +4363,9 @@ int UtcDaliTextAlign02(void)
     22u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4475,7 +4484,9 @@ int UtcDaliTextAlign03(void)
     48u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4594,7 +4605,9 @@ int UtcDaliTextAlign04(void)
     0u,
     22u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4713,7 +4726,9 @@ int UtcDaliTextAlign05(void)
     22u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4832,7 +4847,9 @@ int UtcDaliTextAlign06(void)
     48u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -4951,7 +4968,9 @@ int UtcDaliTextAlign07(void)
     0u,
     22u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -5070,7 +5089,9 @@ int UtcDaliTextAlign08(void)
     22u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
   };
 
   if( !AlignTest( data ) )
@@ -5189,7 +5210,130 @@ int UtcDaliTextAlign09(void)
     48u,
     26u,
     6u,
-    positions
+    positions,
+    Dali::LayoutDirection::LEFT_TO_RIGHT,
+    false
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign10(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign10");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { -4.f, 0.f, 0.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Begin alignment for the first paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    Text::HorizontalAlignment::END,
+    Text::VerticalAlignment::TOP,
+    0u,
+    22u,
+    6u,
+    positions,
+    Dali::LayoutDirection::RIGHT_TO_LEFT,
+    true
   };
 
   if( !AlignTest( data ) )
index 1b82c49..5822102 100755 (executable)
@@ -1182,10 +1182,68 @@ int UtcDaliKeyboardFocusManagerChangeFocusDirectionByKeyEvents(void)
   DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor());
   DALI_TEST_CHECK(preFocusChangeCallback.mDirection == Control::KeyboardFocus::RIGHT);
 
+  // Clear the focus again
+  manager.ClearFocus();
+
+  // Send the up event for line coverage, but nothing was focued so focus manager will try the initial focus
+  preFocusChangeCallback.Reset();
+  application.ProcessEvent(upEvent);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified);
+  DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor());
+
+  // Clear the focus again
+  manager.ClearFocus();
+
+  // Send the down event for line coverage, but nothing was focued so focus manager will try the initial focus
+  preFocusChangeCallback.Reset();
+  application.ProcessEvent(downEvent);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified);
+  DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor());
+
   END_TEST;
 }
 
+int UtcDaliKeyboardFocusManagerSignalChangedBySpaceKeyEvent(void)
+{
+  ToolkitTestApplication application;
+
+  tet_infoline(" UtcDaliKeyboardFocusManagerSignalChangedBySpaceKeyEvent");
+
+  KeyboardFocusManager manager = KeyboardFocusManager::Get();
+  DALI_TEST_CHECK(manager);
+
+  bool preFocusChangeSignalVerified = false;
+  PreFocusChangeCallback preFocusChangeCallback(preFocusChangeSignalVerified);
+  manager.PreFocusChangeSignal().Connect( &preFocusChangeCallback, &PreFocusChangeCallback::Callback );
+
+  Integration::KeyEvent spaceEvent( "space", "", 0, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE );
+
+  // Press Any key to notice physical keyboard event is comming to KeyboardFocusManager
+  // It makes mIsFocusIndicatorEnabled true
+  application.ProcessEvent(spaceEvent);
+
+  // Send the space event
+  application.ProcessEvent(spaceEvent);
+  DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified);
+  DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == Actor());
+
+  // Clear the focus again
+  manager.ClearFocus();
+
+  // Send the space event again for line coverage
+  preFocusChangeCallback.Reset();
+  application.ProcessEvent(spaceEvent);
+  DALI_TEST_CHECK(manager.GetCurrentFocusActor() == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mSignalVerified);
+  DALI_TEST_CHECK(preFocusChangeCallback.mCurrentFocusedActor == Actor());
+  DALI_TEST_CHECK(preFocusChangeCallback.mProposedActorToFocus == Actor());
 
+  END_TEST;
+}
 
 
 
old mode 100644 (file)
new mode 100755 (executable)
index f19cb12..ffa0a61
@@ -1062,6 +1062,22 @@ int UtcDaliToolkitTextlabelEllipsis(void)
     tet_result(TET_FAIL);
   }
 
+
+  label.SetProperty( TextLabel::Property::TEXT, "Hello world" );
+  label.SetProperty( DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, true );
+  label.SetSize( 400.0f, 10.f );
+
+  try
+  {
+    // Render the text.
+    application.SendNotification();
+    application.Render();
+  }
+  catch( ... )
+  {
+    tet_result(TET_FAIL);
+  }
+
   END_TEST;
 }
 
@@ -1334,4 +1350,4 @@ int UtcDaliToolkitTextlabelVerticalLineAlignment(void)
   DALI_TEST_EQUALS( label.GetProperty< int >( DevelTextLabel::Property::VERTICAL_LINE_ALIGNMENT ), static_cast< int >( Toolkit::DevelText::VerticalLineAlignment::BOTTOM ), TEST_LOCATION );
 
   END_TEST;
-}
\ No newline at end of file
+}
old mode 100644 (file)
new mode 100755 (executable)
index 0b16273..ec6b935
@@ -101,6 +101,27 @@ namespace Property
      * @note The default value is true
      */
     IGNORE_SPACES_AFTER_TEXT,
+
+    /**
+     * @brief Modifies the default text alignment to match the direction of the system language.
+     * @details Name "matchSystemLanguageDirection", type (Property::BOLEAN), Read/Write
+     * @note The default value is false
+     *
+     * If MATCH_SYSTEM_LANGUAGE_DIRECTION property set true, the default text alignment to match the direction of the system language.
+     *
+     * ex) Current system language direction LTR.
+     *     TextLabel::New("Hello world \n  ﻡﺮﺤﺑﺍ. ");
+     *     TextLabel::Property::HORIZONTAL_ALIGNMENT, "END"
+     *
+     * | TextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION                 |
+     * |-----------------------------------------------------------------------
+     * |        false (default)            |                true              |
+     * |-----------------------------------|----------------------------------|
+     * |                     Hello world   |                  Hello world     |
+     * |   ﻡﺮﺤﺑﺍ.                          |                      ﻡﺮﺤﺑﺍ.      |
+     *
+     */
+    MATCH_SYSTEM_LANGUAGE_DIRECTION,
   };
 
 } // namespace Property
index 94d0f20..af57128 100755 (executable)
@@ -1351,7 +1351,7 @@ void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
     mActiveLayer.SetPosition( padding.start, padding.top );
   }
 
-  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize );
+  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize, layoutDirection );
 
   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
       !mRenderer )
index 95e4765..d4485ba 100755 (executable)
@@ -1397,7 +1397,7 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
     mActiveLayer.SetPosition( padding.start, padding.top );
   }
 
-  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize );
+  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize, layoutDirection );
 
   if( ( Text::Controller::NONE_UPDATED != updateTextType ) ||
       !mRenderer )
old mode 100644 (file)
new mode 100755 (executable)
index bb40d00..7a8c283
@@ -132,6 +132,7 @@ DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextLabel, "textDirection",
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit,     TextLabel, "verticalLineAlignment",     INTEGER, VERTICAL_LINE_ALIGNMENT    )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit,     TextLabel, "textBackground",            MAP,     BACKGROUND                 )
 DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit,     TextLabel, "ignoreSpacesAfterText",     BOOLEAN, IGNORE_SPACES_AFTER_TEXT   )
+DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit,     TextLabel, "matchSystemLanguageDirection", BOOLEAN, MATCH_SYSTEM_LANGUAGE_DIRECTION )
 DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, TextLabel, "textColor",      Color::BLACK,     TEXT_COLOR     )
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorRed",   TEXT_COLOR_RED,   TEXT_COLOR, 0  )
 DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( Toolkit,    TextLabel, "textColorGreen", TEXT_COLOR_GREEN, TEXT_COLOR, 1  )
@@ -539,6 +540,11 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
         impl.mController->SetIgnoreSpacesAfterText(value.Get< bool >());
         break;
       }
+      case Toolkit::DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
+      {
+        impl.mController->SetMatchSystemLanguageDirection(value.Get< bool >());
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -842,6 +848,11 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
         value = impl.mController->IsIgnoreSpacesAfterText();
         break;
       }
+      case Toolkit::DevelTextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION:
+      {
+        value = impl.mController->IsMatchSystemLanguageDirection();
+        break;
+      }
     }
   }
 
@@ -962,7 +973,10 @@ void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
 
   Vector2 contentSize( size.x - ( padding.start + padding.end ), size.y - ( padding.top + padding.bottom ) );
 
-  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize );
+  // Support Right-To-Left
+  Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( Self().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
+
+  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( contentSize, layoutDirection );
 
   if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) )
      || mTextUpdateNeeded )
@@ -973,7 +987,6 @@ void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container )
     TextVisual::EnableRendererUpdate( mVisual );
 
     // 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 );
index 3555b3c..3653f5f 100644 (file)
@@ -119,16 +119,17 @@ KeyboardFocusManager::KeyboardFocusManager()
   mFocusedActorEnterKeySignal(),
   mCurrentFocusActor(),
   mFocusIndicatorActor(),
-  mIsFocusIndicatorEnabled( -1 ),
+  mIsFocusIndicatorShown( -1 ),
   mFocusGroupLoopEnabled( false ),
   mIsWaitingKeyboardFocusChangeCommit( false ),
   mClearFocusOnTouch( true ),
   mEnableFocusIndicator( true ),
+  mAlwaysShowIndicator( true ),
   mFocusHistory(),
   mSlotDelegate( this ),
   mCustomAlgorithmInterface(NULL)
 {
-  // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorEnabled.
+  // TODO: Get FocusIndicatorEnable constant from stylesheet to set mIsFocusIndicatorShown.
   Stage::GetCurrent().KeyEventSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnKeyEvent);
   Stage::GetCurrent().TouchSignal().Connect( mSlotDelegate, &KeyboardFocusManager::OnTouch );
 }
@@ -143,8 +144,9 @@ void KeyboardFocusManager::GetConfigurationFromStyleManger()
     if( styleManager )
     {
       Property::Map config = Toolkit::DevelStyleManager::GetConfigurations( styleManager );
-      mIsFocusIndicatorEnabled = static_cast<int>(config["alwaysShowFocus"].Get<bool>());
-      mClearFocusOnTouch = mIsFocusIndicatorEnabled ? false : true;
+      mAlwaysShowIndicator = config["alwaysShowFocus"].Get<bool>();
+      mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
+      mClearFocusOnTouch = mIsFocusIndicatorShown ? false : true;
     }
 }
 
@@ -152,7 +154,7 @@ bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
 {
   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
 
-  if( mIsFocusIndicatorEnabled == -1 )
+  if( mIsFocusIndicatorShown == -1 )
   {
     GetConfigurationFromStyleManger();
   }
@@ -179,7 +181,7 @@ bool KeyboardFocusManager::DoSetCurrentFocusActor( Actor actor )
   // Check whether the actor is in the stage and is keyboard focusable.
   if( actor && actor.IsKeyboardFocusable() && actor.OnStage() )
   {
-    if( mIsFocusIndicatorEnabled && mEnableFocusIndicator )
+    if( mIsFocusIndicatorShown && mEnableFocusIndicator )
     {
       actor.Add( GetFocusIndicatorActor() );
     }
@@ -555,7 +557,7 @@ void KeyboardFocusManager::ClearFocus()
   }
 
   mCurrentFocusActor.Reset();
-  mIsFocusIndicatorEnabled = 0;
+  mIsFocusIndicatorShown = static_cast<int>(mAlwaysShowIndicator);
 }
 
 void KeyboardFocusManager::SetFocusGroupLoop(bool enabled)
@@ -655,7 +657,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 
   std::string keyName = event.keyPressedName;
 
-  if( mIsFocusIndicatorEnabled == -1 )
+  if( mIsFocusIndicatorShown == -1 )
   {
     GetConfigurationFromStyleManger();
   }
@@ -668,10 +670,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       if(!isAccessibilityEnabled)
       {
-        if(!mIsFocusIndicatorEnabled)
+        if(!mIsFocusIndicatorShown)
         {
           // Show focus indicator
-          mIsFocusIndicatorEnabled = 1;
+          mIsFocusIndicatorShown = 1;
         }
         else
         {
@@ -691,10 +693,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     {
       if(!isAccessibilityEnabled)
       {
-        if(!mIsFocusIndicatorEnabled)
+        if(!mIsFocusIndicatorShown)
         {
           // Show focus indicator
-          mIsFocusIndicatorEnabled = 1;
+          mIsFocusIndicatorShown = 1;
         }
         else
         {
@@ -712,10 +714,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Up" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -727,10 +729,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Down" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -742,10 +744,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Prior" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -757,10 +759,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Next" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -772,10 +774,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "Tab" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -788,10 +790,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
     else if (keyName == "space" && !isAccessibilityEnabled)
     {
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
 
       isFocusStartableKey = true;
@@ -799,10 +801,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     else if (keyName == "" && !isAccessibilityEnabled)
     {
       // Check the fake key event for evas-plugin case
-      if(!mIsFocusIndicatorEnabled)
+      if(!mIsFocusIndicatorShown)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
 
       isFocusStartableKey = true;
@@ -819,10 +821,10 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
   {
     if (keyName == "Return")
     {
-      if(!mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
+      if(!mIsFocusIndicatorShown && !isAccessibilityEnabled)
       {
         // Show focus indicator
-        mIsFocusIndicatorEnabled = 1;
+        mIsFocusIndicatorShown = 1;
       }
       else
       {
@@ -847,7 +849,7 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
     }
   }
 
-  if(isFocusStartableKey && mIsFocusIndicatorEnabled && !isAccessibilityEnabled)
+  if(isFocusStartableKey && mIsFocusIndicatorShown && !isAccessibilityEnabled)
   {
     Actor actor = GetCurrentFocusActor();
     if( actor )
@@ -869,9 +871,9 @@ void KeyboardFocusManager::OnKeyEvent(const KeyEvent& event)
 
 void KeyboardFocusManager::OnTouch(const TouchData& touch)
 {
-  // if mIsFocusIndicatorEnabled is -1, it means Configuration is not loaded.
+  // if mIsFocusIndicatorShown is -1, it means Configuration is not loaded.
   // Try to load configuration.
-  if( mIsFocusIndicatorEnabled == -1 )
+  if( mIsFocusIndicatorShown == -1 )
   {
     GetConfigurationFromStyleManger();
   }
index be69ce0..9e4d96e 100644 (file)
@@ -269,7 +269,7 @@ private:
 
   Actor mFocusIndicatorActor; ///< The focus indicator actor shared by all the keyboard focusable actors for highlight
 
-  int mIsFocusIndicatorEnabled; ///< Whether indicator should be shown / hidden when getting focus. It could be enabled when keyboard focus feature is enabled and navigation keys or 'Tab' key are pressed.
+  int mIsFocusIndicatorShown; ///< Whether indicator should be shown / hidden when getting focus. It could be enabled when keyboard focus feature is enabled and navigation keys or 'Tab' key are pressed.
 
   bool mFocusGroupLoopEnabled:1; ///< Whether the focus movement is looped within the same focus group
 
@@ -279,6 +279,8 @@ private:
 
   bool mEnableFocusIndicator;  ///< Whether use focus indicator
 
+  bool mAlwaysShowIndicator; ///< Whether always show indicator. If true, the indicator would be directly shown when focused.
+
   FocusStack mFocusHistory; ///< Stack to contain pre-focused actor's BaseObject*
 
   SlotDelegate< KeyboardFocusManager > mSlotDelegate;
old mode 100644 (file)
new mode 100755 (executable)
index 061707a..0c3d9df
@@ -1104,7 +1104,9 @@ struct Engine::Impl
               Length numberOfCharacters,
               Text::HorizontalAlignment::Type horizontalAlignment,
               Vector<LineRun>& lines,
-              float& alignmentOffset )
+              float& alignmentOffset,
+              Dali::LayoutDirection::Type layoutDirection,
+              bool matchSystemLanguageDirection )
   {
     const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
 
@@ -1132,7 +1134,9 @@ struct Engine::Impl
       // the box width, line length, and the paragraph's direction.
       CalculateHorizontalAlignment( size.width,
                                     horizontalAlignment,
-                                    line );
+                                    line,
+                                    layoutDirection,
+                                    matchSystemLanguageDirection );
 
       // Updates the alignment offset.
       alignmentOffset = std::min( alignmentOffset, line.alignmentOffset );
@@ -1141,16 +1145,24 @@ struct Engine::Impl
 
   void CalculateHorizontalAlignment( float boxWidth,
                                      HorizontalAlignment::Type horizontalAlignment,
-                                     LineRun& line )
+                                     LineRun& line,
+                                     Dali::LayoutDirection::Type layoutDirection,
+                                     bool matchSystemLanguageDirection )
   {
     line.alignmentOffset = 0.f;
-    const bool isRTL = RTL == line.direction;
+    bool isRTL = RTL == line.direction;
     float lineLength = line.width;
-
     HorizontalAlignment::Type alignment = horizontalAlignment;
+
+    // match align for system language direction
+    if( matchSystemLanguageDirection )
+    {
+      isRTL = layoutDirection == LayoutDirection::RIGHT_TO_LEFT;
+    }
+
+    // Swap the alignment type if the line is right to left.
     if( isRTL )
     {
-      // Swap the alignment type if the line is right to left.
       switch( alignment )
       {
         case HorizontalAlignment::BEGIN:
@@ -1169,6 +1181,7 @@ struct Engine::Impl
           break;
         }
       }
+
     }
 
     // Calculate the horizontal line offset.
@@ -1300,14 +1313,18 @@ void Engine::Align( const Size& size,
                     Length numberOfCharacters,
                     Text::HorizontalAlignment::Type horizontalAlignment,
                     Vector<LineRun>& lines,
-                    float& alignmentOffset )
+                    float& alignmentOffset,
+                    Dali::LayoutDirection::Type layoutDirection,
+                    bool matchSystemLanguageDirection )
 {
   mImpl->Align( size,
                 startIndex,
                 numberOfCharacters,
                 horizontalAlignment,
                 lines,
-                alignmentOffset );
+                alignmentOffset,
+                layoutDirection,
+                matchSystemLanguageDirection );
 }
 
 void Engine::SetDefaultLineSpacing( float lineSpacing )
old mode 100644 (file)
new mode 100755 (executable)
index 66525d1..5e80d8c
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDE
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/math/vector2.h>
+#include <dali/public-api/actors/actor-enumerations.h>
 
 // INTERNAL INCLUDE
 #include <dali-toolkit/public-api/text/text-enumerations.h>
@@ -140,13 +141,17 @@ public:
    * @param[in] horizontalAlignment The horizontal alignment.
    * @param[in,out] lines The laid-out lines.
    * @param[out] alignmentOffset The alignment offset.
+   * @param[in] layoutDirection The direction of the system language.
+   * @param[in] matchSystemLanguageDirection Whether match align for system language direction or not.
    */
   void Align( const Size& size,
               CharacterIndex startIndex,
               Length numberOfCharacters,
               Text::HorizontalAlignment::Type horizontalAlignment,
               Vector<LineRun>& lines,
-              float& alignmentOffset );
+              float& alignmentOffset,
+              Dali::LayoutDirection::Type layoutDirection,
+              bool matchSystemLanguageDirection );
 
   /**
    * @brief Sets the default line spacing.
old mode 100644 (file)
new mode 100755 (executable)
index 5a77d86..ecd1f6b
@@ -60,6 +60,9 @@ struct Parameters
    * @param[in] totalNumberOfGlyphs The number of glyphs.
    * @param[in] horizontalAlignment The horizontal alignment.
    * @param[in] lineWrapMode The text wrap mode.
+   * @param[in] outlineWidth The outline width.
+   * @param[in] ignoreSpaceAfterText Whether ignoring spaces after text or not.
+   * @param[in] matchSystemLanguageDirection Whether match align for system language direction or not..
    */
   Parameters( const Vector2& boundingBox,
               const Character* const textBuffer,
@@ -75,7 +78,8 @@ struct Parameters
               Text::HorizontalAlignment::Type horizontalAlignment,
               Text::LineWrap::Mode lineWrapMode,
               float outlineWidth,
-              bool ignoreSpaceAfterText )
+              bool ignoreSpaceAfterText,
+              bool matchSystemLanguageDirection )
   : boundingBox( boundingBox ),
     textBuffer( textBuffer ),
     lineBreakInfoBuffer( lineBreakInfoBuffer ),
@@ -97,7 +101,8 @@ struct Parameters
     lineWrapMode( lineWrapMode ),
     outlineWidth( outlineWidth ),
     isLastNewParagraph( false ),
-    ignoreSpaceAfterText( ignoreSpaceAfterText )
+    ignoreSpaceAfterText( ignoreSpaceAfterText ),
+    matchSystemLanguageDirection ( matchSystemLanguageDirection )
   {}
 
   Vector2                         boundingBox;                     ///< The size of the box containing the text.
@@ -122,6 +127,7 @@ struct Parameters
   float                           outlineWidth;                    ///< The outline width.
   bool                            isLastNewParagraph:1;            ///< Whether the last character is a new paragraph character.
   bool                            ignoreSpaceAfterText:1;          ///< Whether ignoring spaces after text or not. Default is true.
+  bool                            matchSystemLanguageDirection:1;  ///< Whether match align for system language direction or not. Default is false.
 };
 
 } // namespace Layout
index 34601f5..3e50faf 100755 (executable)
@@ -329,7 +329,8 @@ struct Controller::Impl
     mShadowSetByString( false ),
     mOutlineSetByString( false ),
     mFontStyleSetByString( false ),
-    mShouldClearFocusOnEscape( true )
+    mShouldClearFocusOnEscape( true ),
+    mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT )
   {
     mModel = Model::New();
 
@@ -765,6 +766,7 @@ public:
   bool mOutlineSetByString:1;              ///< Set when outline is set by string (legacy) instead of map
   bool mFontStyleSetByString:1;            ///< Set when font style is set by string (legacy) instead of map
   bool mShouldClearFocusOnEscape:1;        ///< Whether text control should clear key input focus
+  LayoutDirection::Type mLayoutDirection;  ///< Current system language direction
 };
 
 } // namespace Text
index 033433b..f0b496f 100755 (executable)
@@ -417,6 +417,17 @@ void Controller::SetIgnoreSpacesAfterText( bool ignore )
   mImpl->mModel->mIgnoreSpacesAfterText = ignore;
 }
 
+bool Controller::IsMatchSystemLanguageDirection() const
+{
+  return mImpl->mModel->mMatchSystemLanguageDirection;
+}
+
+void Controller::SetMatchSystemLanguageDirection( bool match )
+{
+  mImpl->mModel->mMatchSystemLanguageDirection = match;
+}
+
+
 void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode )
 {
   if( lineWrapMode != mImpl->mModel->mLineWrapMode )
@@ -2228,12 +2239,13 @@ void Controller::SetVerticalLineAlignment( Toolkit::DevelText::VerticalLineAlign
 
 // public : Relayout.
 
-Controller::UpdateTextType Controller::Relayout( const Size& size )
+Controller::UpdateTextType Controller::Relayout( const Size& size, Dali::LayoutDirection::Type layoutDirection )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ?"true":"false"  );
 
   UpdateTextType updateTextType = NONE_UPDATED;
 
+  mImpl->mLayoutDirection = layoutDirection;
   if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
   {
     if( 0u != mImpl->mModel->mVisualModel->mGlyphPositions.Count() )
@@ -3543,7 +3555,8 @@ bool Controller::DoRelayout( const Size& size,
                                          mImpl->mModel->mHorizontalAlignment,
                                          mImpl->mModel->mLineWrapMode,
                                          outlineWidth,
-                                         mImpl->mModel->mIgnoreSpacesAfterText );
+                                         mImpl->mModel->mIgnoreSpacesAfterText,
+                                         mImpl->mModel->mMatchSystemLanguageDirection );
 
     // Resize the vector of positions to have the same size than the vector of glyphs.
     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
@@ -3661,7 +3674,9 @@ bool Controller::DoRelayout( const Size& size,
                                 requestedNumberOfCharacters,
                                 mImpl->mModel->mHorizontalAlignment,
                                 lines,
-                                mImpl->mModel->mAlignmentOffset );
+                                mImpl->mModel->mAlignmentOffset,
+                                mImpl->mLayoutDirection,
+                                mImpl->mModel->mMatchSystemLanguageDirection );
 
     viewUpdated = true;
   }
index 25bb13b..f92a69d 100755 (executable)
@@ -1243,6 +1243,18 @@ public: // Queries & retrieves.
    */
   void SetIgnoreSpacesAfterText( bool ignore );
 
+  /**
+   * @brief Retrieves matchSystemLanguageDirection value from model
+   * @return The value of matchSystemLanguageDirection
+   */
+  bool IsMatchSystemLanguageDirection() const;
+
+  /**
+   * @brief Sets matchSystemLanguageDirection value to model
+   * @param[in] match The value of matchSystemLanguageDirection for the text
+   */
+  void SetMatchSystemLanguageDirection( bool match );
+
 public: // Relayout.
 
   /**
@@ -1250,10 +1262,11 @@ public: // Relayout.
    *
    * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation.
    * @param[in] size A the size of a bounding box to layout text within.
+   * @param[in] layoutDirection The direction of the system language.
    *
    * @return Whether the text model or decorations were updated.
    */
-  UpdateTextType Relayout( const Size& size );
+  UpdateTextType Relayout( const Size& size, Dali::LayoutDirection::Type layoutDirection = Dali::LayoutDirection::LEFT_TO_RIGHT );
 
   /**
    * @brief Request a relayout using the ControlInterface.
index 65494e5..474b3ae 100755 (executable)
@@ -188,7 +188,8 @@ Model::Model()
   mLineWrapMode( Text::LineWrap::WORD ),
   mAlignmentOffset( 0.0f ),
   mElideEnabled( false ),
-  mIgnoreSpacesAfterText( true )
+  mIgnoreSpacesAfterText( true ),
+  mMatchSystemLanguageDirection( false )
 {
   mLogicalModel = LogicalModel::New();
   mVisualModel = VisualModel::New();
index 1ea725c..688eac4 100755 (executable)
@@ -239,6 +239,7 @@ public:
   float                                     mAlignmentOffset;         ///< The alignment offset.
   bool                                      mElideEnabled:1;          ///< Whether the text's elide is enabled.
   bool                                      mIgnoreSpacesAfterText:1; ///< Whether ignoring spaces after text or not. Default is true.
+  bool                                      mMatchSystemLanguageDirection:1; ///< Whether match align for system language direction or not. Default is false.
 };
 
 } // namespace Text
index b8edc7a..4b3176c 100755 (executable)
@@ -634,7 +634,9 @@ void TextVisual::UpdateRenderer()
     return;
   }
 
-  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( relayoutSize );
+  Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( control.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
+
+  const Text::Controller::UpdateTextType updateTextType = mController->Relayout( relayoutSize, layoutDirection );
 
   if( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType )
    || mRendererUpdateNeeded )
index 43bd4e5..842a568 100644 (file)
@@ -67,7 +67,8 @@
       "autoScrollLoopCount":2,
       "autoScrollGap":50,
       "autoScrollSpeed":80,
-      "ignoreSpacesAfterText":false
+      "ignoreSpacesAfterText":false,
+      "matchSystemLanguageDirection":true
     },
 
     "TextLabelFontSize0":
diff --git a/docs/content/images/text-controls/HelloWorld-Default-END.png b/docs/content/images/text-controls/HelloWorld-Default-END.png
new file mode 100755 (executable)
index 0000000..3302d08
Binary files /dev/null and b/docs/content/images/text-controls/HelloWorld-Default-END.png differ
diff --git a/docs/content/images/text-controls/HelloWorld-System-END.png b/docs/content/images/text-controls/HelloWorld-System-END.png
new file mode 100755 (executable)
index 0000000..2794090
Binary files /dev/null and b/docs/content/images/text-controls/HelloWorld-System-END.png differ
old mode 100644 (file)
new mode 100755 (executable)
index f1c3b77..9b463e4
@@ -89,6 +89,30 @@ label.HorizontalAlignment = "BEGIN"; // "CENTER" or "END"
 | ![ ](../assets/img/text-controls/LatinEnd.png) ![ ](LatinEnd.png) | ![ ](../assets/img/text-controls/ArabicEnd.png) ![ ](ArabicEnd.png) |
 
 
+
+The text's alignment can be modified to match the direction of the system language.
+
+If the MATCH_SYSTEM_LANGUAGE_DIRECTION property is set to true then the direction of the text is ignored, instead the text is aligned as the system default language.
+
+~~~{.cpp}
+// C++
+
+label.SetProperty( TextLabel::Property::MATCH_SYSTEM_LANGUAGE_DIRECTION, true );
+~~~
+
+~~~{.js}
+// JavaScript
+
+label.matchSystemLanguageDirection = true;
+~~~
+
+|  |  |
+|--|--|
+| Current system language direction left-to-right | |
+| END alignment and MATCH_SYSTEM_LANGUAGE_DIRECTION set to TRUE. | END alignment and MATCH_SYSTEM_LANGUAGE_DIRECTION set to FALSE (default). |
+| ![ ](HelloWorld-System-END.png) | ![ ](HelloWorld-Default-END.png) |
+
+
 The examples above assume that the TextLabel size greater than the minimum required.  
 The next section provides details about the other size related options.