[dali_1.3.39] Merge branch 'devel/master' 12/188112/1
authorRichard Huang <r.huang@samsung.com>
Fri, 31 Aug 2018 09:40:52 +0000 (10:40 +0100)
committerRichard Huang <r.huang@samsung.com>
Fri, 31 Aug 2018 09:40:52 +0000 (10:40 +0100)
Change-Id: I0e4da2f93bcade105cff4a67382d2e07d06f9eeb

34 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Cursor.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
dali-toolkit/devel-api/controls/text-controls/text-label-devel.h
dali-toolkit/devel-api/layouting/layout-group-impl.cpp
dali-toolkit/devel-api/layouting/layout-group-impl.h
dali-toolkit/devel-api/layouting/layout-group.cpp
dali-toolkit/devel-api/layouting/layout-group.h
dali-toolkit/devel-api/layouting/layout-item-impl.cpp
dali-toolkit/devel-api/layouting/linear-layout.cpp
dali-toolkit/devel-api/layouting/linear-layout.h
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/layouting/absolute-layout-impl.cpp
dali-toolkit/internal/layouting/grid-impl.cpp
dali-toolkit/internal/layouting/layout-controller-impl.cpp
dali-toolkit/internal/layouting/linear-layout-impl.cpp
dali-toolkit/internal/layouting/linear-layout-impl.h
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-parameters.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/public-api/controls/text-controls/placeholder-properties.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/styles/1920x1080/dali-toolkit-default-theme.json
packaging/dali-toolkit.spec

index b977ec3..08f2c63 100755 (executable)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/markup-processor.h>
 
 namespace Dali
 {
@@ -100,31 +101,52 @@ void CreateTextModel( const std::string& text,
                       Size& layoutSize,
                       LogicalModelPtr& logicalModel,
                       VisualModelPtr& visualModel,
-                      MetricsPtr& metrics )
+                      MetricsPtr& metrics,
+                      bool markupProcessorEnabled )
 {
   logicalModel = LogicalModel::New();
   visualModel = VisualModel::New();
 
+  MarkupProcessData markupProcessData( logicalModel->mColorRuns,
+                                       logicalModel->mFontDescriptionRuns );
+
+  Length textSize = 0u;
+  const uint8_t* utf8 = NULL;
+  if( markupProcessorEnabled )
+  {
+    ProcessMarkupString( text, markupProcessData );
+    textSize = markupProcessData.markupProcessedText.size();
+
+    // This is a bit horrible but std::string returns a (signed) char*
+    utf8 = reinterpret_cast<const uint8_t*>( markupProcessData.markupProcessedText.c_str() );
+  }
+  else
+  {
+    textSize = text.size();
+
+    // This is a bit horrible but std::string returns a (signed) char*
+    utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+  }
+
   // 1) Convert to utf32
   Vector<Character>& utf32Characters = logicalModel->mText;
-  utf32Characters.Resize( text.size() );
+  utf32Characters.Resize( textSize );
 
-  const uint32_t numberOfCharacters = ( text.size() == 0) ? 0 :
-    Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( text.c_str() ),
-                                                   text.size(),
-                                                   &utf32Characters[0u] );
-  utf32Characters.Resize( numberOfCharacters );
+  // Transform a text array encoded in utf8 into an array encoded in utf32.
+  // It returns the actual number of characters.
+  Length characterCount = Utf8ToUtf32( utf8, textSize, utf32Characters.Begin() );
+  utf32Characters.Resize( characterCount );
 
   // 2) Set the break and paragraph info.
   Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
-  lineBreakInfo.Resize( numberOfCharacters );
+  lineBreakInfo.Resize( characterCount );
 
   SetLineBreakInfo( utf32Characters,
                     0u,
-                    numberOfCharacters,
+                    characterCount,
                     lineBreakInfo );
 
-  if( 0u == numberOfCharacters )
+  if( 0u == characterCount )
   {
     // Nothing else to do if the number of characters is zero.
     return;
@@ -132,11 +154,11 @@ void CreateTextModel( const std::string& text,
 
   // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines).
   Vector<WordBreakInfo>& wordBreakInfo = logicalModel->mWordBreakInfo;
-  wordBreakInfo.Resize( numberOfCharacters );
+  wordBreakInfo.Resize( characterCount );
 
   SetWordBreakInfo( utf32Characters,
                     0u,
-                    numberOfCharacters,
+                    characterCount,
                     wordBreakInfo );
 
   // 3) Set the script info.
@@ -145,7 +167,7 @@ void CreateTextModel( const std::string& text,
   Vector<ScriptRun>& scripts = logicalModel->mScriptRuns;
   multilanguageSupport.SetScripts( utf32Characters,
                                    0u,
-                                   numberOfCharacters,
+                                   characterCount,
                                    scripts );
 
   // 4) Set the font info
@@ -167,7 +189,7 @@ void CreateTextModel( const std::string& text,
                                       fontDescription,
                                       TextAbstraction::FontClient::DEFAULT_POINT_SIZE,
                                       0u,
-                                      numberOfCharacters,
+                                      characterCount,
                                       validFonts );
 
   // 5) Set the bidirectional info per paragraph.
@@ -182,12 +204,12 @@ void CreateTextModel( const std::string& text,
                         scripts,
                         lineBreakInfo,
                         0u,
-                        numberOfCharacters,
+                        characterCount,
                         bidirectionalInfo );
 
   // Create the paragraph info.
   logicalModel->CreateParagraphInfo( 0u,
-                                     numberOfCharacters );
+                                     characterCount );
 
   // 6) Set character directions.
   Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
@@ -195,9 +217,9 @@ void CreateTextModel( const std::string& text,
   {
     // Only set the character directions if there is right to left characters.
     GetCharactersDirection( bidirectionalInfo,
-                            numberOfCharacters,
+                            characterCount,
                             0u,
-                            numberOfCharacters,
+                            characterCount,
                             characterDirections );
 
 
@@ -206,7 +228,7 @@ void CreateTextModel( const std::string& text,
                                     characterDirections,
                                     bidirectionalInfo,
                                     0u,
-                                    numberOfCharacters,
+                                    characterCount,
                                     mirroredUtf32Characters );
   }
   else
@@ -230,15 +252,15 @@ void CreateTextModel( const std::string& text,
              validFonts,
              0u,
              0u,
-             numberOfCharacters,
+             characterCount,
              glyphs,
              glyphsToCharactersMap,
              charactersPerGlyph,
              newParagraphGlyphs );
 
   // Create the 'number of glyphs' per character and the glyph to character conversion tables.
-  visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
-  visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
+  visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, characterCount );
+  visualModel->CreateCharacterToGlyphTable( 0u, 0u, characterCount );
 
   const Length numberOfGlyphs = glyphs.Count();
 
@@ -284,14 +306,15 @@ void CreateTextModel( const std::string& text,
                                        numberOfGlyphs,
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
-                                       outlineWidth );
+                                       outlineWidth,
+                                       true );
 
   Vector<LineRun>& lines = visualModel->mLines;
 
   Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
   glyphPositions.Resize( numberOfGlyphs );
 
-  layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) );
+  layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( characterCount - 1u ) ) );
 
   // The initial glyph and the number of glyphs to layout.
   layoutParameters.startGlyphIndex = 0u;
@@ -317,7 +340,7 @@ void CreateTextModel( const std::string& text,
     bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
     ReorderLines( bidirectionalInfo,
                   0u,
-                  numberOfCharacters,
+                  characterCount,
                   lines,
                   bidirectionalLineInfo );
 
@@ -330,7 +353,7 @@ void CreateTextModel( const std::string& text,
       // Re-layout the text. Reorder those lines with right to left characters.
       layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
                                              0u,
-                                             numberOfCharacters,
+                                             characterCount,
                                              glyphPositions );
     }
   }
@@ -340,7 +363,7 @@ void CreateTextModel( const std::string& text,
     float alignmentOffset = 0.f;
     layoutEngine.Align( textArea,
                         0u,
-                        numberOfCharacters,
+                        characterCount,
                         Text::HorizontalAlignment::BEGIN,
                         lines,
                         alignmentOffset );
index 2391cb1..8ba7306 100644 (file)
@@ -59,6 +59,7 @@ struct LayoutOptions
  * @param[out] logicalModel Pointer to a logical text model instance.
  * @param[out] visualModel Pointer to a visual text model instance.
  * @param[out] metrics Pointer to a wrapper around FontClient used to get metrics.
+ * @param[in] markupProcessorEnabled Enable markup processor to use markup text.
  */
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
@@ -67,7 +68,8 @@ void CreateTextModel( const std::string& text,
                       Size& layoutSize,
                       LogicalModelPtr& logicalModel,
                       VisualModelPtr& visualModel,
-                      MetricsPtr& metrics );
+                      MetricsPtr& metrics,
+                      bool markupProcessorEnabled );
 
 /**
  * @brief Configures the text @p controller similarly to the one configured by the text-label.
index cb33f00..191ead1 100644 (file)
@@ -101,11 +101,12 @@ struct GetMirroredTextData
 
 struct GetCharactersDirectionData
 {
-  std::string  description;         ///< Description of the test.
-  std::string  text;                ///< Input text.
-  unsigned int startIndex;          ///< The index from where the model is updated.
-  unsigned int numberOfCharacters;  ///< The number of characters.
-  bool*        directions;          ///< The expected directions.
+  std::string  description;            ///< Description of the test.
+  std::string  text;                   ///< Input text.
+  unsigned int startIndex;             ///< The index from where the model is updated.
+  unsigned int numberOfCharacters;     ///< The number of characters.
+  bool*        directions;             ///< The expected directions.
+  bool         markupProcessorEnabled; ///< Enable markup processor to use markup text.
 };
 
 bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
@@ -127,7 +128,8 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Clear the bidirectional paragraph info data.
   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
@@ -233,7 +235,8 @@ bool ReorderLinesTest( const ReorderLinesData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Clear the bidirectional line info data.
   uint32_t startRemoveIndex = logicalModel->mBidirectionalLineInfo.Count();
@@ -358,7 +361,8 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Call the GetMirroredText() function for the whole text
   Vector<Character> mirroredText;
@@ -432,7 +436,8 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   data.markupProcessorEnabled );
 
   Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo;
 
@@ -930,6 +935,11 @@ int UtcDaliGetCharactersDirection(void)
     true,  true,  true,  true,  true,  true,  true,  true,  true,  true,
     true,  true,  false, false, false, false, false };
 
+    bool directions06[] = {
+    true,  true,  true,  true,  true,  true,  true,  true,  true, true,
+    false, false, false, false, false, false, false, false, false, false,
+    false, false, false, false, false, false };
+
   struct GetCharactersDirectionData data[] =
   {
     {
@@ -937,28 +947,32 @@ int UtcDaliGetCharactersDirection(void)
       "",
       0u,
       0u,
-      directions01
+      directions01,
+      false
     },
     {
       "Left to right characters only",
       "Hello world\nhello world demo",
       0u,
       28u,
-      directions02
+      directions02,
+      false
     },
     {
       "Right to left characters only",
       "שלום עולם\nשלום עולם",
       0u,
       19u,
-      directions03
+      directions03,
+      false
     },
     {
       "Mix of bidirectional text",
       "Hello world\nhello world שלום עולם\nשלום עולם hello world",
       0u,
       55u,
-      directions04
+      directions04,
+      false
     },
     {
       "Mix of bidirectional text. With more paragraphs.",
@@ -966,7 +980,8 @@ int UtcDaliGetCharactersDirection(void)
       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
       0u,
       227u,
-      directions05
+      directions05,
+      false
     },
     {
       "Mix of bidirectional text. With more paragraphs. Update first paragraph.",
@@ -974,7 +989,8 @@ int UtcDaliGetCharactersDirection(void)
       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
       0u,
       17u,
-      directions05
+      directions05,
+      false
     },
     {
       "Mix of bidirectional text. With more paragraphs. Update from character 29",
@@ -982,7 +998,8 @@ int UtcDaliGetCharactersDirection(void)
       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
       29u,
       134u,
-      directions05
+      directions05,
+      false
     },
     {
       "Mix of bidirectional text. With more paragraphs. Update from character 163",
@@ -990,10 +1007,19 @@ int UtcDaliGetCharactersDirection(void)
       " مرحبا بالعالم שלום עולם hello world hello world\nبالعالم שלום hello world demo עולם\nשלום مرحبا بالعالم עולם hello",
       163u,
       35u,
-      directions05
+      directions05,
+      false
+    },
+    {
+      "Mix of bidirectional text. With brackets and LRM",
+      "שלום עולם &lrm;(hello)[world]&lrm;",
+      0u,
+      26u,
+      directions06,
+      true
     }
   };
-  const unsigned int numberOfTests = 8u;
+  const unsigned int numberOfTests = 9u;
 
   for( unsigned int index = 0u; index < numberOfTests; ++index )
   {
index f8df615..d43e3e5 100644 (file)
@@ -115,7 +115,8 @@ bool CreateParagraphTest( const CreateParagraphData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Clear the paragraphs.
   Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
@@ -175,7 +176,8 @@ bool FindParagraphTest( const FindParagraphData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Find the paragraphs.
   Vector<ParagraphRunIndex> paragraphs;
@@ -224,7 +226,8 @@ bool FetchBidirectionalLineInfoTest( const FetchBidirectionalLineInfoData& data
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0; index < data.numberOfTests; ++index )
   {
@@ -268,7 +271,8 @@ bool GetLogicalCharacterIndexTest( const GetLogicalCharacterIndexData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
@@ -310,7 +314,8 @@ bool GetLogicalCursorIndexTest( const GetLogicalCursorIndexData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0u; index < data.numberOfIndices; ++index )
   {
index 2a5ae46..cba35a3 100644 (file)
@@ -112,7 +112,8 @@ bool GetClosestLineTest( const GetClosestLineData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0; index < data.numberOfTests; ++index )
   {
@@ -156,7 +157,8 @@ bool GetClosestCursorIndexTest( const GetClosestCursorIndexData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0; index < data.numberOfTests; ++index )
   {
@@ -204,7 +206,8 @@ bool GetCursorPositionTest( const GetCursorPositionData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   GetCursorPositionParameters parameters;
   parameters.visualModel = visualModel;
@@ -255,7 +258,8 @@ bool FindSelectionIndicesTest( const FindSelectionIndicesData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   for( unsigned int index = 0; index < data.numberOfTests; ++index )
   {
index 86edead..ab15b46 100644 (file)
@@ -109,7 +109,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Clear the layout.
   Vector<LineRun>& lines = visualModel->mLines;
@@ -172,7 +173,8 @@ bool LayoutTextTest( const LayoutTextData& data )
                                        totalNumberOfGlyphs,
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
-                                       outlineWidth );
+                                       outlineWidth,
+                                       true );
 
   layoutParameters.isLastNewParagraph = isLastNewParagraph;
 
@@ -370,7 +372,8 @@ bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Call the ReLayoutRightToLeftLines() method.
   Layout::Engine engine;
@@ -390,7 +393,8 @@ bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
                                        visualModel->mGlyphs.Count(),
                                        Text::HorizontalAlignment::BEGIN,
                                        Text::LineWrap::WORD,
-                                       outlineWidth );
+                                       outlineWidth,
+                                       true );
 
   layoutParameters.numberOfBidirectionalInfoRuns = logicalModel->mBidirectionalLineInfo.Count();
   layoutParameters.lineBidirectionalInfoRunsBuffer = logicalModel->mBidirectionalLineInfo.Begin();
@@ -482,7 +486,8 @@ bool AlignTest( const AlignData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // Call the Align method.
   Layout::Engine engine;
index 0b7ca02..b5bf653 100644 (file)
@@ -138,7 +138,8 @@ bool ShapeInfoTest( const ShapeInfoData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   // 2) Clear the model.
 
index a13b4d8..c36fed6 100644 (file)
@@ -80,7 +80,8 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
@@ -162,7 +163,8 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
                    layoutSize,
                    logicalModel,
                    visualModel,
-                   metrics );
+                   metrics,
+                   false );
 
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
index 29e3726..9206215 100644 (file)
@@ -35,6 +35,9 @@
 using namespace Dali;
 using namespace Toolkit;
 
+namespace
+{
+
 void TestLayoutItemOrder( std::vector< Control >& controls, LayoutGroup& layoutGroup )
 {
   for( auto&& iter : controls )
@@ -44,6 +47,19 @@ void TestLayoutItemOrder( std::vector< Control >& controls, LayoutGroup& layoutG
   }
 }
 
+// Turns the given control into a Root layout control and adds it to the stage.
+void SetupRootLayoutControl( Control& rootControl )
+{
+  rootControl = Control::New();
+  auto absoluteLayout = AbsoluteLayout::New();
+  DevelControl::SetLayout( rootControl, absoluteLayout );
+  rootControl.SetName( "RootAbsoluteLayout" );
+  Stage stage = Stage::GetCurrent();
+  stage.Add( rootControl );
+}
+
+} // unnamed namespace
+
 void utc_dali_toolkit_layouting_startup(void)
 {
   test_return_value = TET_UNDEF;
@@ -76,6 +92,7 @@ int UtcDaliLayouting_HboxLayout01(void)
   {
     hbox.Add( iter );
   }
+
   hbox.SetParentOrigin( ParentOrigin::CENTER );
   hbox.SetAnchorPoint( AnchorPoint::CENTER );
   stage.Add( hbox );
@@ -623,6 +640,7 @@ int UtcDaliLayouting_HboxLayout08(void)
 
   Control control1 = CreateLeafControl( 40, 40 );
   rootControl.Add( control1 );
+
   auto hbox = Control::New();
   auto hboxLayout = LinearLayout::New();
   hboxLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
@@ -641,7 +659,9 @@ int UtcDaliLayouting_HboxLayout08(void)
   DALI_TEST_EQUALS( hboxLayout.IsLayoutAnimated(), false, TEST_LOCATION );
   DALI_TEST_EQUALS( DevelControl::GetLayout( control2 ).IsLayoutAnimated(), false, TEST_LOCATION );
 
+  tet_infoline(" Set hBoxLayout to animate");
   hboxLayout.SetAnimateLayout( true );
+  tet_infoline(" Set absoluteLayout not to animate");
   absoluteLayout.SetAnimateLayout( false );
 
   DALI_TEST_EQUALS( absoluteLayout.IsLayoutAnimated(), false, TEST_LOCATION );
@@ -652,6 +672,278 @@ int UtcDaliLayouting_HboxLayout08(void)
   END_TEST;
 }
 
+int UtcDaliLayouting_HboxLayout09(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout07 - Set alignment");
+
+  Stage stage = Stage::GetCurrent();
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+  }
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( hbox );
+
+  // Check default orientation
+  DALI_TEST_EQUALS( static_cast<unsigned int>( hboxLayout.GetOrientation() ), static_cast<unsigned int>( LinearLayout::Orientation::HORIZONTAL ), TEST_LOCATION );
+  // Check default alignment
+  DALI_TEST_EQUALS( hboxLayout.GetAlignment(), ( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL ), TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 380.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 230.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 380.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 230.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 760.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 380.0f, 760.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 760.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 230.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 230.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 390.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 440.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 390.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 390.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 440.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::TOP );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 700.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::END | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 440.0f, 700.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 700.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 390.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
 namespace
 {
 const char* TEST_IMAGE_FILE_NAME =  TEST_RESOURCE_DIR  "/broken.png";
@@ -1336,6 +1628,7 @@ int UtcDaliLayouting_VboxLayout01(void)
   auto vbox = Control::New();
   auto vboxLayout = LinearLayout::New();
   vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
+  vboxLayout.SetAlignment( LinearLayout::Alignment::TOP | LinearLayout::Alignment::CENTER_HORIZONTAL );
   DevelControl::SetLayout( vbox, vboxLayout );
   vbox.SetName( "Vbox");
 
@@ -1396,6 +1689,7 @@ int UtcDaliLayouting_VboxLayout02(void)
   auto vbox = Control::New();
   auto vboxLayout = LinearLayout::New();
   vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
+  vboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::TOP | Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL );
   DevelControl::SetLayout( vbox, vboxLayout );
   vbox.SetName( "Vbox");
   rootControl.Add( vbox );
@@ -1468,6 +1762,7 @@ int UtcDaliLayouting_VboxLayout03(void)
   auto vboxLayout = LinearLayout::New();
   vboxLayout.SetCellPadding( LayoutSize( 0, 10 ) );
   vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
+  vboxLayout.SetAlignment( Dali::Toolkit::LinearLayout::Alignment::TOP | Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL );
 
   DALI_TEST_EQUALS( vboxLayout.GetCellPadding(), LayoutSize( 0, 10 ), TEST_LOCATION );
 
@@ -2028,3 +2323,235 @@ int UtcDaliLayouting_SetLayoutOrder02(void)
 
   END_TEST;
 }
+
+int UtcDaliLayouting_LayoutGroup01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliLayouting_LayoutGroup01 - Test adding a control to a layout then adding a TextLabel to that control");
+
+  Control rootControl;
+  SetupRootLayoutControl( rootControl );
+
+  // Create a parent layout
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hbox.SetName( "HBox");
+  rootControl.Add( hbox );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 600 );
+  hbox.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+  hbox.SetAnchorPoint( AnchorPoint::TOP_LEFT );  // LinearLayout will eventually do this internally.
+
+  tet_infoline("Add a control without SetLayout being called");
+
+  auto control = Control::New();
+  control.SetName("Control1");
+  hbox.Add( control );
+  control.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  control.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+
+  tet_infoline("Add a Textlabel to the control");
+  auto textLabel = TextLabel::New("Test text");
+  textLabel.SetName("TextLabel");
+  control.Add( textLabel );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Test text is it's natural size");
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  tet_infoline("Test control is width of it's parent and height of it's child");
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 600.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutGroup02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliLayouting_LayoutGroup02 - Test control is the size of it's largest child");
+
+  Control rootControl;
+  SetupRootLayoutControl( rootControl );
+
+  // Create a parent layout
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hbox.SetName( "HBox");
+  rootControl.Add( hbox );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 600 );
+  hbox.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+  hbox.SetAnchorPoint( AnchorPoint::TOP_LEFT );  // LinearLayout will eventually do this internally.
+
+  tet_infoline("Add a control without SetLayout being called");
+
+  auto control = Control::New();
+  control.SetName("Control1");
+  hbox.Add( control );
+  control.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  control.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+
+  tet_infoline("Add a Textlabel to the control");
+  auto textLabel = TextLabel::New("Test text");
+  textLabel.SetName("TextLabel");
+  control.Add( textLabel );
+
+  tet_infoline("Add another  Textlabel to the control");
+  auto largeTextLabel = TextLabel::New("Test large text");
+  largeTextLabel.SetName("TextLabel-Large");
+  control.Add( largeTextLabel );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Test text is it's natural size");
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  tet_infoline("Test text is centered in the control, the control is the size of the largest child");
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  tet_infoline("Test large text is it's natural size");
+  DALI_TEST_EQUALS( largeTextLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 382.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  tet_infoline("Test text is aligned to start as is the size of the control");
+  DALI_TEST_EQUALS( largeTextLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  tet_infoline("Test control is width of it's parent and height of it's largest child");
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 382.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutGroup03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliLayouting_LayoutGroup03 - Test control witha LayoutGroup as a leaf");
+
+  Control rootControl;
+  SetupRootLayoutControl( rootControl );
+
+  // Create a parent layout
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hbox.SetName( "HBox");
+  rootControl.Add( hbox );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 600 );
+  hbox.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+  hbox.SetAnchorPoint( AnchorPoint::TOP_LEFT );  // LinearLayout will eventually do this internally.
+
+  tet_infoline("Add a control without SetLayout being called");
+
+  auto control = Control::New();
+  control.SetName("Control1");
+  hbox.Add( control );
+  control.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  control.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  100 );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Test control is width of it's parent and exact given height");
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 600.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutGroupWithPadding01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliLayouting_LayoutGroupWithPadding01 - Test adding a control to a layout that has padding");
+
+  Control rootControl;
+  SetupRootLayoutControl( rootControl );
+
+  // Create a parent layout
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hbox.SetName( "HBox");
+  rootControl.Add( hbox );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 600 );
+  hbox.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+  hbox.SetAnchorPoint( AnchorPoint::TOP_LEFT );  // LinearLayout will eventually do this internally.
+
+  tet_infoline("Add a control without SetLayout being called");
+
+  auto control = Control::New();
+  control.SetName("Control1");
+  hbox.Add( control );
+  control.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  control.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+
+  const Extents CONTROL_PADDING = Extents(5, 10, 20, 2 );
+  tet_printf( "Adding Padding to control");
+  control.SetProperty( Toolkit::Control::Property::PADDING, CONTROL_PADDING );
+
+  tet_infoline("Add a Textlabel to the control");
+  auto textLabel = TextLabel::New("Test text");
+  textLabel.SetName("TextLabel");
+  control.Add( textLabel );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Test text is it's natural size");
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  tet_infoline("Test control is size of it's child and control it's own padding");
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 245.0f, 86.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutGroupWithChildMargin01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliLayouting_LayoutGroupWithChildMargin01 - Test adding a control with padding to a layout that has padding");
+
+  Control rootControl;
+  SetupRootLayoutControl( rootControl );
+
+  // Create a parent layout
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hbox.SetName( "HBox");
+  rootControl.Add( hbox );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 600 );
+  hbox.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+  hbox.SetAnchorPoint( AnchorPoint::TOP_LEFT );  // LinearLayout will eventually do this internally.
+
+  tet_infoline("Add a control without SetLayout being called");
+
+  auto control = Control::New();
+  control.SetName("Control1");
+  hbox.Add( control );
+  control.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  control.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,  ChildLayoutData::WRAP_CONTENT );
+
+  const Extents CONTROL_PADDING = Extents(5, 10, 20, 2 );
+  tet_printf( "Adding Padding to control");
+  control.SetProperty( Toolkit::Control::Property::PADDING, CONTROL_PADDING );
+
+  tet_infoline("Add a Textlabel to the control");
+  auto textLabel = TextLabel::New("Test text");
+  const Extents CHILD_MARGIN = Extents( 10, 0, 5, 0 );
+  textLabel.SetProperty( Toolkit::Control::Property::MARGIN, CHILD_MARGIN );
+  textLabel.SetName("TextLabel");
+  control.Add( textLabel );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  tet_infoline("Test text is it's natural size");
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  tet_infoline("Test control is width of it's parent and height of it's child");
+  DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 255.0f, 91.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
index b134179..f19cb12 100644 (file)
@@ -1047,6 +1047,21 @@ int UtcDaliToolkitTextlabelEllipsis(void)
     tet_result(TET_FAIL);
   }
 
+  label.SetProperty( TextLabel::Property::TEXT, "Hello world                                        " );
+  label.SetProperty( DevelTextLabel::Property::IGNORE_SPACES_AFTER_TEXT, false );
+  label.SetSize( 400.0f, 10.f );
+
+  try
+  {
+    // Render the text.
+    application.SendNotification();
+    application.Render();
+  }
+  catch( ... )
+  {
+    tet_result(TET_FAIL);
+  }
+
   END_TEST;
 }
 
index 939c08d..0b16273 100644 (file)
@@ -94,6 +94,13 @@ namespace Property
      * | color                | VECTOR4  | No       | The color of the background (the default value is Color::CYAN)                                                     |
      */
     BACKGROUND,
+
+    /**
+     * @brief Ignore spaces after text.
+     * @details Name "ignoreSpacesAfterText", type (Property::BOLEAN), Read/Write
+     * @note The default value is true
+     */
+    IGNORE_SPACES_AFTER_TEXT,
   };
 
 } // namespace Property
index 69d268d..9f54f56 100644 (file)
@@ -48,6 +48,12 @@ LayoutGroup::LayoutGroup()
 {
 }
 
+LayoutGroupPtr LayoutGroup::New( Handle& owner )
+{
+  LayoutGroupPtr layoutPtr = new LayoutGroup();
+  return layoutPtr;
+}
+
 LayoutGroup::~LayoutGroup()
 {
   // An object with a unique_ptr to an opaque structure must define it's destructor in the translation unit
@@ -333,7 +339,8 @@ void LayoutGroup::MeasureChild( LayoutItemPtr child,
 #if defined( DEBUG_ENABLED )
   if ( control )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild natural size(%f, %f)\n",  control.GetNaturalSize().width, control.GetNaturalSize().height );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild(%s) natural size(%f, %f)\n",
+                   control.GetName().c_str(), control.GetNaturalSize().width, control.GetNaturalSize().height );
   }
 #endif
 
@@ -568,7 +575,10 @@ void LayoutGroup::ChildAddedToOwner( Actor child )
   LayoutItemPtr childLayout;
   Toolkit::Control control = Toolkit::Control::DownCast( child );
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner control(%s)\n", control?control.GetName().c_str():"Invalid" );
+#if defined(DEBUG_ENABLED)
+  auto parent = Toolkit::Control::DownCast( GetOwner() );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner control(%s) owner(%s)\n", control?control.GetName().c_str():"Invalid", parent?parent.GetName().c_str():"Invalid" );
+#endif
 
   if( control ) // Can only support adding Controls, not Actors to layout
   {
@@ -579,7 +589,7 @@ void LayoutGroup::ChildAddedToOwner( Actor child )
     if( ! childLayout )
     {
       // If the child doesn't already have a layout, then create a LayoutItem for it.
-      childLayout = LayoutItem::New( control );
+      childLayout = LayoutGroup::New( control );
       childLayout->SetAnimateLayout( IsLayoutAnimated() ); // @todo this essentially forces animation inheritance. Bad?
 #if defined(DEBUG_ENABLED)
       auto desiredSize = control.GetNaturalSize();
@@ -688,7 +698,7 @@ void LayoutGroup::OnAnimationStateChanged( bool animateLayout )
   for( auto&& child : mImpl->mChildren )
   {
     LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( child.child.Get() ) );
-    if( !parentGroup )
+    if( parentGroup && ( 0 == parentGroup->GetChildCount() ) ) // A leaf LayoutGroup will have no children.
     {
       // Change state only in case of leaf children
       child.child->SetAnimateLayout( animateLayout );
@@ -696,6 +706,146 @@ void LayoutGroup::OnAnimationStateChanged( bool animateLayout )
   }
 }
 
+void LayoutGroup::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+  DALI_LOG_STREAM( gLogFilter, Debug::Verbose,
+                  "LayoutGroup::OnMeasure Actor Id:" <<  Actor::DownCast(GetOwner()).GetId() <<
+                  " Owner:" <<  Actor::DownCast(GetOwner()).GetName() <<
+                  " MeasureSpecs( width:"<<widthMeasureSpec<<", height:"<<heightMeasureSpec );
+
+  auto childCount = GetChildCount();
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnMeasure child count(%u)\n", childCount);
+
+  auto widthMode = widthMeasureSpec.GetMode();
+  auto heightMode = heightMeasureSpec.GetMode();
+  LayoutLength widthSpecSize = widthMeasureSpec.GetSize();
+  LayoutLength heightSpecSize = heightMeasureSpec.GetSize();
+
+  bool exactWidth ( false );
+  bool exactHeight ( false );
+
+  // Default Layouting behaviour if not overridden
+  // EXACT, width and height as provided.
+  // MATCH_PARENT, width and hewidthSpecSizeight that of parent
+
+  // WRAP_CONTENT, take width of widest child and height size of longest child (within given limit)
+  // UNSPECIFIED, take width of widest child and height size of longest child.
+
+  LayoutLength layoutWidth( 0 );
+  LayoutLength layoutHeight( 0 );
+
+  // If LayoutGroup has children then measure children to get max dimensions
+  if ( childCount > 0 )
+  {
+    for( unsigned int i=0; i<childCount; ++i )
+    {
+      auto childLayout = GetChildAt( i );
+      if( childLayout )
+      {
+        auto childOwner = childLayout->GetOwner();
+
+        // Get size of child
+        MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+        auto childWidth = childLayout->GetMeasuredWidth();
+        auto childHeight = childLayout->GetMeasuredHeight();
+        auto childMargin = childLayout->GetMargin();
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnMeasure child width[%d] height(%d)\n", childWidth.mValue, childHeight.mValue );
+
+        layoutWidth = std::max( layoutWidth, childWidth + childMargin.start + childMargin.end );
+        layoutHeight = std::max( layoutHeight, childHeight + childMargin.top + childMargin.bottom );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnMeasure calculated child width[%d] calculated height(%d)\n", layoutWidth.mValue, layoutHeight.mValue );
+      }
+    }
+
+    Extents padding = GetPadding();
+    layoutWidth += padding.start + padding.end;
+    layoutHeight += padding.top + padding.bottom;
+  }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnMeasure Getting default size as a leaf\n" );
+    // LayoutGroup does not contain any children so must be a leaf
+    layoutWidth = GetDefaultSize( GetSuggestedMinimumWidth(), widthMeasureSpec );
+    layoutHeight = GetDefaultSize( GetSuggestedMinimumHeight(), heightMeasureSpec );
+  }
+
+  // Can't exceed specified width
+  if( widthMode == MeasureSpec::Mode::EXACTLY )
+  {
+    exactWidth = true;
+  }
+  else if ( widthMode == MeasureSpec::Mode::AT_MOST )
+  {
+    layoutWidth = std::min( layoutWidth, widthSpecSize );
+  }
+
+  // Can't exceed specified height
+  if( heightMode == MeasureSpec::Mode::EXACTLY )
+  {
+    exactHeight = true;
+  }
+  else if ( heightMode == MeasureSpec::Mode::AT_MOST )
+  {
+    layoutHeight = std::min( layoutHeight, heightSpecSize );
+  }
+
+  layoutWidth = std::max( layoutWidth, GetSuggestedMinimumWidth() );
+  layoutHeight = std::max( layoutHeight, GetSuggestedMinimumHeight() );
+
+  if( exactWidth )
+  {
+    layoutWidth = widthSpecSize;
+  }
+
+  if( exactHeight )
+  {
+    layoutHeight = heightSpecSize;
+  }
+
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnMeasure Measured size(%d,%d) for : %s \n", layoutWidth.mValue, layoutHeight.mValue, Actor::DownCast(GetOwner()).GetName().c_str() );
+  SetMeasuredDimensions( MeasuredSize( layoutWidth ), MeasuredSize( layoutHeight ) );
+}
+
+void LayoutGroup::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnLayout\n");
+
+  auto count = GetChildCount();
+
+  for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+
+      auto childOwner = childLayout->GetOwner();
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+      auto childMargin = childLayout->GetMargin();
+      auto control = Toolkit::Control::DownCast( childOwner );
+      Extents padding = GetPadding();
+
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnLayout child width[%d] height(%d)\n", childWidth.mValue, childHeight.mValue );
+
+      auto childPosition = control.GetProperty< Vector3 >( Actor::Property::POSITION );
+      auto anchorPoint = control.GetProperty< Vector3 >( Actor::Property::ANCHOR_POINT );
+
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnLayout child[%s] position(%f,%f)\n", control.GetName().c_str(), childPosition.x, childPosition.y );
+
+      // Margin and Padding only supported when child anchor point is TOP_LEFT.
+      int paddingAndMarginOffsetX = ( AnchorPoint::TOP_LEFT == anchorPoint ) ? ( padding.top + childMargin.top ) : 0;
+      int paddingAndMarginOffsetY = ( AnchorPoint::TOP_LEFT == anchorPoint ) ? ( padding.start + childMargin.start ) : 0;
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnLayout paddingMargin offset(%d,%d)\n", paddingAndMarginOffsetX, paddingAndMarginOffsetY );
+
+      LayoutLength childLeft = childPosition.x + paddingAndMarginOffsetX;
+      LayoutLength childTop = childPosition.y + paddingAndMarginOffsetY;
+
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+    }
+  }
+}
+
+
 } // namespace Internal
 } // namespace Toolkit
 } // namespace Dali
index 3039125..ee73c88 100644 (file)
@@ -65,6 +65,14 @@ public:
    */
   LayoutGroup();
 
+  /**
+   * @brief Construct
+   *
+   * @param[in] owner The owner (container view / child view / visual ) of this layout
+   * @return a new LayoutGroup object
+   */
+  static LayoutGroupPtr New( Handle& owner );
+
 protected:
   /**
    * Virtual destructor may only be called by Unreference()
@@ -248,6 +256,15 @@ protected:
                                         LayoutLength widthUsed,
                                         MeasureSpec parentHeightMeasureSpec,
                                         LayoutLength heightUsed );
+  /**
+   * @copydoc LayoutItem::OnMeasure
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
+
+  /**
+   * @copydoc LayoutItem::OnLayout
+   */
+  virtual void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) override;
 
 private:
   /**
index b13da31..50ed913 100644 (file)
@@ -27,6 +27,12 @@ LayoutGroup::LayoutGroup()
 {
 }
 
+LayoutGroup LayoutGroup::New( Handle& handle )
+{
+  Internal::LayoutGroupPtr layout = Internal::LayoutGroup::New( handle );
+  return LayoutGroup( layout.Get() );
+}
+
 LayoutGroup LayoutGroup::DownCast( BaseHandle handle )
 {
   return LayoutGroup( dynamic_cast< Dali::Toolkit::Internal::LayoutGroup* >( handle.GetObjectPtr() ) );
index 1d9ad5d..9d0e684 100644 (file)
@@ -80,6 +80,13 @@ public:
   ~LayoutGroup() = default;
 
   /**
+   * @brief Create an initialized LayoutGroup
+   *
+   * @param[in] handle A handle to the object that this layout for, e.g. a Control or a Visual::Base
+   */
+  static LayoutGroup New( Handle& handle );
+
+  /**
    * @brief Copy constructor
    */
   LayoutGroup(const LayoutGroup& copy) = default;
index a0350e3..71c0d46 100644 (file)
@@ -95,6 +95,16 @@ void LayoutItem::Unparent()
 
 void LayoutItem::SetAnimateLayout( bool animateLayout )
 {
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetAnimateLayout animateLayout(%s)\n", (animateLayout)?"true":"false" );
+
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+
+  if( actor )
+  {
+      DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetAnimateLayout animateLayout(%s) owner(%s)\n", (animateLayout)?"true":"false", actor.GetName().c_str() );
+  }
+
   mImpl->mAnimated = animateLayout;
 
   OnAnimationStateChanged( animateLayout );
@@ -163,14 +173,14 @@ void LayoutItem::Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasur
 #if defined(DEBUG_ENABLED)
     std::ostringstream o;
     o<<widthMeasureSpec<<","<<heightMeasureSpec;
-    DALI_LOG_INFO( gLayoutFilter, Debug::Concise, "Calling %s OnMeasure( %s )\n", Actor::DownCast(GetOwner()).GetName().c_str(), o.str().c_str());
+    DALI_LOG_INFO( gLayoutFilter, Debug::Concise, "LayoutItem::Measure Calling %s OnMeasure( %s )\n", Actor::DownCast(GetOwner()).GetName().c_str(), o.str().c_str());
 #endif
     OnMeasure( widthMeasureSpec, heightMeasureSpec );
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
 
     // flag not set, setMeasuredDimension() was not invoked, we raise an exception to warn the developer
     DALI_ASSERT_ALWAYS( mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET ) &&
-                        "Layout's OnMeasure() did not set the measured dimension by calling setMeasuredDimension()" );
+                        "Layout's OnMeasure() mension()" );
     mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED );
   }
 
@@ -180,6 +190,8 @@ void LayoutItem::Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasur
 
 void LayoutItem::Layout( LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b )
 {
+  DALI_LOG_TRACE_METHOD( gLayoutFilter );
+
   if( mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT ) )
   {
     OnMeasure( mImpl->mOldWidthMeasureSpec, mImpl->mOldHeightMeasureSpec );
@@ -227,7 +239,7 @@ Extents LayoutItem::GetPadding() const
   {
     Extents padding = control.GetProperty<Extents>( Toolkit::Control::Property::PADDING );
 
-    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutBase::Padding for %s : (%d,%d,%d,%d) \n",
+    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::Padding for %s : (%d,%d,%d,%d) \n",
                    control.GetName().c_str(),
                    padding.start, padding.end, padding.top, padding.bottom
                  );
@@ -289,6 +301,8 @@ LayoutLength LayoutItem::GetDefaultSize( LayoutLength size, MeasureSpec measureS
 
 void LayoutItem::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec)
 {
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::OnMeasure\n");
+
   SetMeasuredDimensions( GetDefaultSize( GetSuggestedMinimumWidth(), widthMeasureSpec ),
                          GetDefaultSize( GetSuggestedMinimumHeight(), heightMeasureSpec ) );
 }
@@ -332,7 +346,7 @@ void LayoutItem::SetLayoutRequested()
 
 void LayoutItem::SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
 {
-  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutBase::SetMeasuredDimensions width(%d) height(%d) \n",
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetMeasuredDimensions width(%d) height(%d) \n",
                                                  MeasureSpec::IntType( measuredWidth.GetSize() ),
                                                  MeasureSpec::IntType( measuredHeight.GetSize() )
                );
@@ -450,6 +464,8 @@ bool LayoutItem::SetFrame( LayoutLength left, LayoutLength top, LayoutLength rig
     auto actor = Actor::DownCast(owner);
     if( actor )
     {
+      DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame owner(%s) (%d, %d, %d, %d)\n",  actor.GetName().c_str(),
+                                    left.mValue, top.mValue, right.mValue, bottom.mValue );
       if( mImpl->mAnimated )
       {
         auto animation = Animation::New( 0.5f );
index 4a63036..25e88ab 100644 (file)
@@ -59,7 +59,7 @@ void LinearLayout::SetCellPadding( LayoutSize size )
   GetImplementation(*this).SetCellPadding( size );
 }
 
-LayoutSize LinearLayout::GetCellPadding()
+LayoutSize LinearLayout::GetCellPadding() const
 {
   return GetImplementation(*this).GetCellPadding();
 }
@@ -69,11 +69,21 @@ void LinearLayout::SetOrientation( LinearLayout::Orientation orientation )
   GetImplementation(*this).SetOrientation( orientation );
 }
 
-LinearLayout::Orientation LinearLayout::GetOrientation()
+LinearLayout::Orientation LinearLayout::GetOrientation() const
 {
   return GetImplementation(*this).GetOrientation();
 }
 
+void LinearLayout::SetAlignment( unsigned int alignment )
+{
+  GetImplementation(*this).SetAlignment( alignment );
+}
+
+unsigned int LinearLayout::GetAlignment() const
+{
+  return GetImplementation(*this).GetAlignment();
+}
+
 LinearLayout::LinearLayout( Dali::Toolkit::Internal::LinearLayout* object )
 : LayoutGroup( object )
 {
index f30911b..07924db 100644 (file)
@@ -57,6 +57,22 @@ public:
   };
 
   /**
+   * @brief Enumeration for the alignment of the linear layout items.
+   */
+  struct Alignment
+  {
+    enum Type
+    {
+      BEGIN                     = 0x1,  ///< At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation)
+      END                       = 0x2,  ///< At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation)
+      CENTER_HORIZONTAL         = 0x4,  ///< At the horizontal center of the container
+      TOP                       = 0x8,  ///< At the top edge of the container
+      BOTTOM                    = 0x10, ///< At the bottom edge of the container
+      CENTER_VERTICAL           = 0x20  ///< At the vertical center of the container
+    };
+  };
+
+  /**
    * @brief Creates an uninitialized LinearLayout handle.
    *
    * Initialize it using LinearLayout::New().
@@ -109,7 +125,7 @@ public:
    *
    * @return The padding between cells.
    */
-  LayoutSize GetCellPadding();
+  LayoutSize GetCellPadding() const;
 
   /**
    * @brief Set the orientation in the layout
@@ -123,7 +139,21 @@ public:
    *
    * @return The orientation.
    */
-  Orientation GetOrientation();
+  Orientation GetOrientation() const;
+
+  /**
+   * @brief Set the alignment in the layout
+   *
+   * @param[in] alignment The alignment.
+   */
+  void SetAlignment( unsigned int alignment );
+
+  /**
+   * @brief Get the alignment in the layout
+   *
+   * @return The alignment.
+   */
+  unsigned int GetAlignment() const;
 
 public: // Not intended for application developers
 
index 7c6ef25..bb40d00 100644 (file)
@@ -131,6 +131,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit,           TextLabel, "lineWrapMode",
 DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextLabel, "textDirection",       INTEGER, TEXT_DIRECTION             )
 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_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  )
@@ -533,6 +534,11 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::DevelTextLabel::Property::IGNORE_SPACES_AFTER_TEXT:
+      {
+        impl.mController->SetIgnoreSpacesAfterText(value.Get< bool >());
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -831,6 +837,11 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde
         GetBackgroundProperties( impl.mController, value, Text::EffectStyle::DEFAULT );
         break;
       }
+      case Toolkit::DevelTextLabel::Property::IGNORE_SPACES_AFTER_TEXT:
+      {
+        value = impl.mController->IsIgnoreSpacesAfterText();
+        break;
+      }
     }
   }
 
index 3f499ef..14fed57 100644 (file)
@@ -106,7 +106,7 @@ void AbsoluteLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec height
       // Store current width and height needed to contain all children.
       totalWidth = maxPosition.x - minPosition.x;
       totalHeight = maxPosition.y - minPosition.y;
-      DALI_LOG_INFO( gLogFilter, Debug::Concise, "AbsoluteLayout::OnMeasure child width(%f) height(%f) \n", (float)totalWidth, (float)totalHeight  );
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AbsoluteLayout::OnMeasure child width(%f) height(%f) \n", (float)totalWidth, (float)totalHeight  );
 
       if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
       {
@@ -141,6 +141,7 @@ void AbsoluteLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top
   // Absolute layout positions it's children at their Actor positions.
   // Children could overlap or spill outside the parent, as is the nature of absolute positions.
   auto count = GetChildCount();
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "AbsoluteLayout::OnLayout child count(%d)\n", count  );
 
   for( unsigned int i = 0; i < count; i++)
   {
index a83ed99..b8e2b22 100644 (file)
@@ -50,8 +50,8 @@ Grid::Grid()
 : LayoutGroup(),
   mTotalHeight( 0 ),
   mTotalWidth( 0 ),
-  mNumColumns( AUTO_FIT ),
-  mNumRows( AUTO_FIT ),
+  mNumColumns( 1 ),
+  mNumRows( 1 ),
   mRequestedColumnWidth( 0 ),
   mRequestedNumColumns( AUTO_FIT )
 {
index 1f12c3f..0e8d925 100644 (file)
@@ -110,7 +110,7 @@ void LayoutController::MeasureHierarchy( Actor root, MeasureSpec widthSpec, Meas
   Toolkit::Control control = Toolkit::Control::DownCast( root );
   if( control )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::Measuring leaf\n" );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::Measuring control\n" );
     Internal::Control& controlImpl = GetImplementation( control );
 
     Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
@@ -138,7 +138,7 @@ void LayoutController::PerformLayout( Actor root, int left, int top, int right,
   Toolkit::Control control = Toolkit::Control::DownCast( root );
   if( control )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayout on leaf\n" );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayout on control[%s]\n", control.GetName().c_str() );
     Internal::Control& controlImpl = GetImplementation( control );
     Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
     LayoutItemPtr layout = controlDataImpl.GetLayout();
index f989a54..c85c5fe 100644 (file)
@@ -41,6 +41,9 @@ namespace Toolkit
 namespace Internal
 {
 
+const int HORIZONTAL_ALIGNMENT_MASK  = ( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL | Dali::Toolkit::LinearLayout::Alignment::END );
+const int VERTICAL_ALIGNMENT_MASK = ( Dali::Toolkit::LinearLayout::Alignment::TOP | Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL | Dali::Toolkit::LinearLayout::Alignment::BOTTOM );
+
 LinearLayoutPtr LinearLayout::New()
 {
   LinearLayoutPtr layout( new LinearLayout() );
@@ -51,6 +54,7 @@ LinearLayout::LinearLayout()
 : LayoutGroup(),
   mCellPadding( 0, 0 ),
   mOrientation( Dali::Toolkit::LinearLayout::Orientation::HORIZONTAL ),
+  mAlignment( Dali::Toolkit::LinearLayout::Alignment::BEGIN | Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL ),
   mTotalLength( 0 )
 {
 }
@@ -68,7 +72,7 @@ void LinearLayout::SetCellPadding( LayoutSize size )
   }
 }
 
-LayoutSize LinearLayout::GetCellPadding()
+LayoutSize LinearLayout::GetCellPadding() const
 {
   return mCellPadding;
 }
@@ -82,11 +86,25 @@ void LinearLayout::SetOrientation( Dali::Toolkit::LinearLayout::Orientation orie
   }
 }
 
-Dali::Toolkit::LinearLayout::Orientation LinearLayout::GetOrientation()
+Dali::Toolkit::LinearLayout::Orientation LinearLayout::GetOrientation() const
 {
   return mOrientation;
 }
 
+void LinearLayout::SetAlignment( unsigned int alignment )
+{
+  if ( mAlignment != alignment )
+  {
+    mAlignment = alignment;
+    RequestLayout();
+  }
+}
+
+unsigned int LinearLayout::GetAlignment() const
+{
+  return mAlignment;
+}
+
 void LinearLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
 {
 #if defined(DEBUG_ENABLED)
@@ -284,15 +302,48 @@ void LinearLayout::LayoutHorizontal( LayoutLength left, LayoutLength top, Layout
 
   auto count = GetChildCount();
 
+  switch ( mAlignment & HORIZONTAL_ALIGNMENT_MASK )
+  {
+    case Dali::Toolkit::LinearLayout::Alignment::BEGIN:
+    default:
+    {
+      // mTotalLength contains the padding already
+      // In case of RTL map BEGIN alignment to the right edge
+      if ( isLayoutRtl ) {
+        childLeft = LayoutLength( padding.start ) + right - left - mTotalLength;
+      }
+      else {
+        childLeft = LayoutLength( padding.start );
+      }
+      break;
+    }
+    case Dali::Toolkit::LinearLayout::Alignment::END:
+    {
+      // mTotalLength contains the padding already
+      // In case of RTL map END alignment to the left edge
+      if ( isLayoutRtl ) {
+        childLeft = LayoutLength( padding.start );
+      }
+      else {
+        childLeft = LayoutLength( padding.start ) + right - left - mTotalLength;
+      }
+      break;
+    }
+    case Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL:
+    {
+      // mTotalLength contains the padding already
+      childLeft = LayoutLength( padding.start ) + ( right - left - mTotalLength ) / 2;
+      break;
+    }
+  }
+
   int start = 0;
   int dir = 1;
 
-  // In case of RTL, start drawing from the last child and apply right alignment.
-  // @TODO Should we have also support Actor HorizontalAlignment|VerticalAlignment in general for LinearLayout?
+  // In case of RTL, start drawing from the last child.
   if( isLayoutRtl ) {
     start = count - 1;
     dir = -1;
-    childLeft = padding.start + right - left - mTotalLength;
   }
 
   for( unsigned int i = 0; i < count; i++)
@@ -305,8 +356,25 @@ void LinearLayout::LayoutHorizontal( LayoutLength left, LayoutLength top, Layout
       auto childHeight = childLayout->GetMeasuredHeight();
       auto childMargin = childLayout->GetMargin();
 
-      childTop = LayoutLength(padding.top) + ((childSpace - childHeight) / 2) + childMargin.top - childMargin.bottom;
-
+      switch ( mAlignment & VERTICAL_ALIGNMENT_MASK )
+      {
+        case Dali::Toolkit::LinearLayout::Alignment::TOP:
+        {
+          childTop = LayoutLength( padding.top ) + childMargin.top;
+          break;
+        }
+        case Dali::Toolkit::LinearLayout::Alignment::BOTTOM:
+        {
+          childTop = height - padding.bottom - childHeight - childMargin.bottom;
+          break;
+        }
+        case Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL:
+        default:
+        {
+          childTop = LayoutLength( padding.top ) + ( ( childSpace - childHeight ) / 2 ) + childMargin.top - childMargin.bottom;
+          break;
+        }
+      }
       childLeft += childMargin.start;
       childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
       childLeft += childWidth + childMargin.end + mCellPadding.width;
@@ -436,13 +504,36 @@ void LinearLayout::LayoutVertical( LayoutLength left, LayoutLength top, LayoutLe
   LayoutLength childTop( padding.top );
   LayoutLength childLeft( padding.start );
 
-  // Where bottom of child should go
+  // Where end of child should go
   auto width = right - left;
 
   // Space available for child
   auto childSpace = width - padding.start - padding.end;
   auto count = GetChildCount();
 
+  switch ( mAlignment & VERTICAL_ALIGNMENT_MASK )
+  {
+    case Dali::Toolkit::LinearLayout::Alignment::TOP:
+    {
+      // mTotalLength contains the padding already
+      childTop = LayoutLength( padding.top );
+      break;
+    }
+    case Dali::Toolkit::LinearLayout::Alignment::BOTTOM:
+    {
+      // mTotalLength contains the padding already
+      childTop = LayoutLength( padding.top ) + bottom - top - mTotalLength;
+      break;
+    }
+    case Dali::Toolkit::LinearLayout::Alignment::CENTER_VERTICAL:
+    default:
+    {
+      // mTotalLength contains the padding already
+      childTop = LayoutLength( padding.top ) + ( bottom - top - mTotalLength ) / 2;
+      break;
+    }
+  }
+
   for( unsigned int childIndex = 0; childIndex < count; childIndex++)
   {
     LayoutItemPtr childLayout = GetChildAt( childIndex );
@@ -453,8 +544,25 @@ void LinearLayout::LayoutVertical( LayoutLength left, LayoutLength top, LayoutLe
       auto childMargin = childLayout->GetMargin();
 
       childTop += childMargin.top;
-      childLeft = LayoutLength( padding.start ) + ( childSpace - childWidth ) / 2 + childMargin.start - childMargin.end;
-
+      switch ( mAlignment & HORIZONTAL_ALIGNMENT_MASK )
+      {
+        case Dali::Toolkit::LinearLayout::Alignment::BEGIN:
+        default:
+        {
+          childLeft = LayoutLength( padding.start ) + childMargin.start;
+          break;
+        }
+        case Dali::Toolkit::LinearLayout::Alignment::END:
+        {
+          childLeft = width - padding.end - childWidth - childMargin.end;
+          break;
+        }
+        case Dali::Toolkit::LinearLayout::Alignment::CENTER_HORIZONTAL:
+        {
+          childLeft = LayoutLength( padding.start ) + ( childSpace - childWidth ) / 2 + childMargin.start - childMargin.end;
+          break;
+        }
+      }
       childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
       childTop += childHeight + childMargin.bottom + mCellPadding.height;
     }
index d9fb90a..23f3184 100644 (file)
@@ -35,16 +35,63 @@ using LinearLayoutPtr = IntrusivePtr<LinearLayout>;
 class LinearLayout final : public LayoutGroup
 {
 public:
+  /**
+   * Creates a pointer to a LinearLayout implementation.
+   */
   static LinearLayoutPtr New();
 
 public:
+  /**
+   * @brief Set the padding between cells in the layout
+   *
+   * @param[in] size The padding between cells.
+   */
   void SetCellPadding( LayoutSize size );
-  LayoutSize GetCellPadding();
+
+  /**
+   * @brief Get the padding between cells in the layout
+   *
+   * @return The padding between cells.
+   */
+  LayoutSize GetCellPadding() const;
+
+  /**
+   * @brief Set the orientation in the layout
+   *
+   * @param[in] orientation The orientation.
+   */
   void SetOrientation( Dali::Toolkit::LinearLayout::Orientation orientation );
-  Dali::Toolkit::LinearLayout::Orientation GetOrientation();
+
+  /**
+   * @brief Get the orientation in the layout
+   *
+   * @return The orientation.
+   */
+  Dali::Toolkit::LinearLayout::Orientation GetOrientation() const;
+
+  /**
+   * @brief Set the alignment in the layout
+   *
+   * @param[in] alignment The alignment.
+   */
+  void SetAlignment( unsigned int alignment );
+
+  /**
+   * @brief Get the alignment in the layout
+   *
+   * @return The alignment.
+   */
+  unsigned int GetAlignment() const;
 
 protected:
+  /**
+   * Default Constructor
+   */
   LinearLayout();
+
+  /**
+   * Destructor
+   */
   virtual ~LinearLayout();
 
   /**
@@ -94,6 +141,7 @@ private:
 private:
   LayoutSize mCellPadding;
   Dali::Toolkit::LinearLayout::Orientation mOrientation;
+  unsigned int mAlignment;
   LayoutLength mTotalLength;
 };
 
index af257ff..061707a 100644 (file)
@@ -281,9 +281,6 @@ struct Engine::Impl
       // Get the line break info for the current character.
       const LineBreakInfo lineBreakInfo = hasCharacters ? *( parameters.lineBreakInfoBuffer + characterLastIndex ) : TextAbstraction::LINE_NO_BREAK;
 
-      // Get the word break info for the current character.
-      const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
-
       // Increase the number of characters.
       tmpLineLayout.numberOfCharacters += charactersPerGlyph;
 
@@ -397,11 +394,19 @@ struct Engine::Impl
         tmpLineLayout.wsLengthEndOfLine = 0.f;
       }
 
+      // If calculation is end but wsLengthEndOfLine is exist, it means end of text is space.
+      // Merge remained length.
+      if ( !parameters.ignoreSpaceAfterText && glyphIndex == lastGlyphOfParagraphPlusOne-1 && tmpLineLayout.wsLengthEndOfLine > 0 )
+      {
+        tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine;
+        tmpLineLayout.wsLengthEndOfLine = 0u;
+      }
+
       // Save the current extra width to compare with the next one
       mPreviousCharacterExtraWidth = tmpExtraWidth;
 
       // Check if the accumulated length fits in the width of the box.
-      if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
+      if( ( completelyFill || isMultiline )  && !(parameters.ignoreSpaceAfterText && isWhiteSpace) &&
           ( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
       {
         // Current word does not fit in the box's width.
@@ -458,7 +463,7 @@ struct Engine::Impl
       }
 
       if( isMultiline &&
-          ( TextAbstraction::WORD_BREAK == wordBreakInfo ) )
+          ( TextAbstraction::LINE_ALLOW_BREAK == lineBreakInfo ) )
       {
         oneWordLaidOut = isWordLaidOut;
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  One word laid-out\n" );
index 7f3e169..5a77d86 100644 (file)
@@ -74,7 +74,8 @@ struct Parameters
               Length totalNumberOfGlyphs,
               Text::HorizontalAlignment::Type horizontalAlignment,
               Text::LineWrap::Mode lineWrapMode,
-              float outlineWidth )
+              float outlineWidth,
+              bool ignoreSpaceAfterText )
   : boundingBox( boundingBox ),
     textBuffer( textBuffer ),
     lineBreakInfoBuffer( lineBreakInfoBuffer ),
@@ -94,8 +95,9 @@ struct Parameters
     startLineIndex( 0u ),
     estimatedNumberOfLines( 0u ),
     lineWrapMode( lineWrapMode ),
+    outlineWidth( outlineWidth ),
     isLastNewParagraph( false ),
-    outlineWidth( outlineWidth )
+    ignoreSpaceAfterText( ignoreSpaceAfterText )
   {}
 
   Vector2                         boundingBox;                     ///< The size of the box containing the text.
@@ -117,8 +119,9 @@ struct Parameters
   LineIndex                       startLineIndex;                  ///< The line index where to insert the new lines.
   Length                          estimatedNumberOfLines;          ///< The estimated number of lines.
   Text::LineWrap::Mode            lineWrapMode;                    ///< The line wrap mode for moving to next line.
-  bool                            isLastNewParagraph;              ///< Whether the last character is a new paragraph character.
   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.
 };
 
 } // namespace Layout
index 4ce4b5a..227760f 100755 (executable)
@@ -407,6 +407,16 @@ VerticalAlignment::Type Controller::GetVerticalAlignment() const
   return mImpl->mModel->mVerticalAlignment;
 }
 
+bool Controller::IsIgnoreSpacesAfterText() const
+{
+  return mImpl->mModel->mIgnoreSpacesAfterText;
+}
+
+void Controller::SetIgnoreSpacesAfterText( bool ignore )
+{
+  mImpl->mModel->mIgnoreSpacesAfterText = ignore;
+}
+
 void Controller::SetLineWrapMode( Text::LineWrap::Mode lineWrapMode )
 {
   if( lineWrapMode != mImpl->mModel->mLineWrapMode )
@@ -3533,7 +3543,8 @@ bool Controller::DoRelayout( const Size& size,
                                          totalNumberOfGlyphs,
                                          mImpl->mModel->mHorizontalAlignment,
                                          mImpl->mModel->mLineWrapMode,
-                                         outlineWidth );
+                                         outlineWidth,
+                                         mImpl->mModel->mIgnoreSpacesAfterText );
 
     // Resize the vector of positions to have the same size than the vector of glyphs.
     Vector<Vector2>& glyphPositions = mImpl->mModel->mVisualModel->mGlyphPositions;
index 92677f2..25bb13b 100755 (executable)
@@ -1231,6 +1231,18 @@ public: // Queries & retrieves.
    */
   void SetVerticalLineAlignment( Toolkit::DevelText::VerticalLineAlignment::Type alignment );
 
+  /**
+   * @brief Retrieves ignoreSpaceAfterText value from model
+   * @return The value of ignoreSpaceAfterText
+   */
+  bool IsIgnoreSpacesAfterText() const;
+
+  /**
+   * @brief Sets ignoreSpaceAfterText value to model
+   * @param[in] ignore The value of ignoreSpacesAfterText for the text
+   */
+  void SetIgnoreSpacesAfterText( bool ignore );
+
 public: // Relayout.
 
   /**
index 84b0428..65494e5 100755 (executable)
@@ -187,7 +187,8 @@ Model::Model()
   mVerticalLineAlignment( DevelText::VerticalLineAlignment::TOP ),
   mLineWrapMode( Text::LineWrap::WORD ),
   mAlignmentOffset( 0.0f ),
-  mElideEnabled( false )
+  mElideEnabled( false ),
+  mIgnoreSpacesAfterText( true )
 {
   mLogicalModel = LogicalModel::New();
   mVisualModel = VisualModel::New();
index cb8d77c..1ea725c 100755 (executable)
@@ -230,14 +230,15 @@ public:
    * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
    * Typically this will have a negative value with scrolling occurs.
    */
-  Vector2                                   mScrollPosition;        ///< The text is offset by this position when scrolling.
-  Vector2                                   mScrollPositionLast;    ///< The last offset value of mScrollPosition
-  HorizontalAlignment::Type                 mHorizontalAlignment;   ///< The layout's horizontal alignment.
-  VerticalAlignment::Type                   mVerticalAlignment;     ///< The layout's vertical alignment.
-  DevelText::VerticalLineAlignment::Type    mVerticalLineAlignment; ///< The layout's vertical line alignment.
-  Text::LineWrap::Mode                      mLineWrapMode;          ///< The text wrap mode
-  float                                     mAlignmentOffset;       ///< The alignment offset.
-  bool                                      mElideEnabled:1;        ///< Whether the text's elide is enabled.
+  Vector2                                   mScrollPosition;          ///< The text is offset by this position when scrolling.
+  Vector2                                   mScrollPositionLast;      ///< The last offset value of mScrollPosition
+  HorizontalAlignment::Type                 mHorizontalAlignment;     ///< The layout's horizontal alignment.
+  VerticalAlignment::Type                   mVerticalAlignment;       ///< The layout's vertical alignment.
+  DevelText::VerticalLineAlignment::Type    mVerticalLineAlignment;   ///< The layout's vertical line alignment.
+  Text::LineWrap::Mode                      mLineWrapMode;            ///< The text wrap mode
+  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.
 };
 
 } // namespace Text
index d102d4f..53d54a9 100644 (file)
@@ -41,7 +41,7 @@ namespace PlaceHolder
 {
 
 /**
- * @brief Placeholder text Propeties used by Text controls to show placeholder
+ * @brief Placeholder text Properties used by Text controls to show placeholder
  * @SINCE_1_2.62
  *
  */
index 88d0d95..106d56d 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 38;
+const unsigned int TOOLKIT_MICRO_VERSION = 39;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index fa8c6f8..43bd4e5 100644 (file)
@@ -66,7 +66,8 @@
       "enableAutoScroll":false,
       "autoScrollLoopCount":2,
       "autoScrollGap":50,
-      "autoScrollSpeed":80
+      "autoScrollSpeed":80,
+      "ignoreSpacesAfterText":false
     },
 
     "TextLabelFontSize0":
index aba76f5..938a776 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.3.38
+Version:    1.3.39
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT