Add AnchorColor Property 84/302984/4
authorBowon Ryu <bowon.ryu@samsung.com>
Mon, 18 Dec 2023 09:44:11 +0000 (18:44 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Tue, 19 Dec 2023 03:41:02 +0000 (12:41 +0900)
AnchorColor(or AnchorClickedColor) property is
used as the default color of the markup anchor tag.

If there is a color attribute in the markup anchor tag,
the markup attribute takes precedence.

Change-Id: Idc938495036319f74764b9ddadc2441d46eed159
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
18 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.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/text/text-utils-devel.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/text/anchor.h
dali-toolkit/internal/text/controller/text-controller-event-handler.cpp
dali-toolkit/internal/text/controller/text-controller-impl.cpp
dali-toolkit/internal/text/controller/text-controller-impl.h
dali-toolkit/internal/text/controller/text-controller-text-updater.cpp
dali-toolkit/internal/text/controller/text-controller.cpp
dali-toolkit/internal/text/controller/text-controller.h
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/markup-processor/markup-processor-anchor.cpp
dali-toolkit/internal/text/markup-processor/markup-processor.cpp
dali-toolkit/internal/text/markup-processor/markup-processor.h

index 8f3c69e51bc1b1c55a0073e6aafca47052093bc5..7db463268ac85acebdd6ab7743fd72091b10bf69 100644 (file)
@@ -124,7 +124,9 @@ void CreateTextModel(const std::string&                text,
   const uint8_t* utf8     = NULL;
   if(markupProcessorEnabled)
   {
-    ProcessMarkupString(text, markupProcessData);
+    MarkupPropertyData markupPropertyData(Color::MEDIUM_BLUE, Color::DARK_MAGENTA);
+
+    ProcessMarkupString(text, markupPropertyData, markupProcessData);
     textSize = markupProcessData.markupProcessedText.size();
 
     // This is a bit horrible but std::string returns a (signed) char*
index 3efd9aa1bf7f72cc595beb163b2c288b837c3a44..3cc13553bddab9f26108635ea8c33cf1e4bcb411 100644 (file)
@@ -188,7 +188,9 @@ bool XHTMLEntityToUTF8Test(const XHTMLEntityToUTF8Data& data)
   Vector<BoundedParagraphRun>          boundedParagraphRuns;
   Vector<CharacterSpacingCharacterRun> characterSpacingCharacterRuns;
   MarkupProcessData                    markupProcessData(colorRuns, fontRuns, items, anchors, underlinedCharacterRuns, backgroundColorRuns, strikethroughCharacterRuns, boundedParagraphRuns, characterSpacingCharacterRuns);
-  ProcessMarkupString(data.xHTMLEntityString, markupProcessData);
+
+  MarkupPropertyData markupPropertyData(Color::MEDIUM_BLUE, Color::DARK_MAGENTA);
+  ProcessMarkupString(data.xHTMLEntityString, markupPropertyData, markupProcessData);
 
   for(Vector<EmbeddedItem>::Iterator it    = items.Begin(),
                                      endIt = items.End();
index b7ddaa74aff7ac8088e5d617e586726867cd19e3..cf57bc083d713507f91ea2d645210a4a5f3d4706 100644 (file)
@@ -76,7 +76,9 @@ const char* const PROPERTY_NAME_AUTO_SCROLL_LOOP_DELAY = "autoScrollLoopDelay";
 const char* const PROPERTY_NAME_FONT_SIZE_SCALE        = "fontSizeScale";
 const char* const PROPERTY_NAME_ENABLE_FONT_SIZE_SCALE = "enableFontSizeScale";
 
-const char* const PROPERTY_NAME_ELLIPSIS_POSITION = "ellipsisPosition";
+const char* const PROPERTY_NAME_ELLIPSIS_POSITION    = "ellipsisPosition";
+const char* const PROPERTY_NAME_ANCHOR_COLOR         = "anchorColor";
+const char* const PROPERTY_NAME_ANCHOR_CLICKED_COLOR = "anchorClickedColor";
 
 const std::string  DEFAULT_FONT_DIR("/resources/fonts");
 const unsigned int EMOJI_FONT_SIZE = 3840u; // 60 * 64
@@ -356,6 +358,8 @@ int UtcDaliToolkitTextLabelGetPropertyP(void)
   DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_ENABLE_FONT_SIZE_SCALE) == DevelTextLabel::Property::ENABLE_FONT_SIZE_SCALE);
   DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_ELLIPSIS_POSITION) == DevelTextLabel::Property::ELLIPSIS_POSITION);
   DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_STRIKETHROUGH) == DevelTextLabel::Property::STRIKETHROUGH);
+  DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_ANCHOR_COLOR) == DevelTextLabel::Property::ANCHOR_COLOR);
+  DALI_TEST_CHECK(label.GetPropertyIndex(PROPERTY_NAME_ANCHOR_CLICKED_COLOR) == DevelTextLabel::Property::ANCHOR_CLICKED_COLOR);
 
   END_TEST;
 }
@@ -464,6 +468,13 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   label.SetProperty(TextLabel::Property::TEXT_COLOR, Color::BLUE);
   DALI_TEST_EQUALS(label.GetProperty<Vector4>(TextLabel::Property::TEXT_COLOR), Color::BLUE, TEST_LOCATION);
 
+  // Check that anchor color can be properly set
+  label.SetProperty(DevelTextLabel::Property::ANCHOR_COLOR, Color::BLUE);
+  DALI_TEST_EQUALS(label.GetProperty<Vector4>(DevelTextLabel::Property::ANCHOR_COLOR), Color::BLUE, TEST_LOCATION);
+
+  label.SetProperty(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR, Color::RED);
+  DALI_TEST_EQUALS(label.GetProperty<Vector4>(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR), Color::RED, TEST_LOCATION);
+
   Property::Map strikethroughMapSet;
   Property::Map strikethroughMapGet;
 
@@ -2440,6 +2451,56 @@ int UtcDaliToolkitTextlabelFontSizeScale(void)
   END_TEST;
 }
 
+int UtcDaliToolkitTextlabelAnchorColor(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextlabelAnchorColor");
+  TextLabel label = TextLabel::New();
+  DALI_TEST_CHECK(label);
+
+  application.GetScene().Add(label);
+
+  // connect to the anchor clicked signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  DevelTextLabel::AnchorClickedSignal(label).Connect(&TestAnchorClickedCallback);
+  bool anchorClickedSignal = false;
+  label.ConnectSignal(testTracker, "anchorClicked", CallbackFunctor(&anchorClickedSignal));
+
+  gAnchorClickedCallBackCalled = false;
+  label.SetProperty(TextLabel::Property::TEXT, "<a href='https://www.tizen.org'>TIZEN</a>");
+  label.SetProperty(TextLabel::Property::ENABLE_MARKUP, true);
+  label.SetProperty(Actor::Property::SIZE, Vector2(100.f, 50.f));
+  label.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  label.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  // Check that anchor color can be properly set
+  label.SetProperty(DevelTextLabel::Property::ANCHOR_COLOR, Color::BLUE);
+  DALI_TEST_EQUALS(label.GetProperty<Vector4>(DevelTextLabel::Property::ANCHOR_COLOR), Color::BLUE, TEST_LOCATION);
+
+  label.SetProperty(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR, Color::RED);
+  DALI_TEST_EQUALS(label.GetProperty<Vector4>(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR), Color::RED, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  // Create a tap event to touch the text label.
+  TestGenerateTap(application, 5.0f, 25.0f, 100);
+  application.SendNotification();
+  application.Render();
+
+  // Update clicked color
+  label.SetProperty(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR, Color::BLUE);
+  DALI_TEST_EQUALS(label.GetProperty<Vector4>(DevelTextLabel::Property::ANCHOR_CLICKED_COLOR), Color::BLUE, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(gAnchorClickedCallBackCalled);
+  DALI_TEST_CHECK(anchorClickedSignal);
+
+  END_TEST;
+}
+
 // Positive test for the anchorClicked signal.
 int UtcDaliToolkitTextlabelAnchorClicked(void)
 {
index 379fba55d8dc2de0447ff745380fce2bd5758231..877125502b1c073f08b95e1bf971d89e1b13885d 100644 (file)
@@ -204,6 +204,20 @@ enum Type
    * @note If the value is less than 1, the lines could to be overlapped.
    */
   RELATIVE_LINE_SIZE,
+
+  /**
+   * @brief The anchor color that will be used by default in markup processing.
+   * @details Name "anchorColor", type Property::VECTOR4.
+   * @note If there is a color attribute in the anchor tag, the markup attribute takes precedence.
+   */
+  ANCHOR_COLOR,
+
+  /**
+   * @brief The anchor clicked color that will be used by default in markup processing.
+   * @details Name "anchorClickedColor", type Property::VECTOR4.
+   * @note If there is a color attribute in the anchor tag, the markup attribute takes precedence.
+   */
+  ANCHOR_CLICKED_COLOR,
 };
 
 } // namespace Property
index e779fe904e95166df493346daa95bc0599af9718..98c37abf2be09adad711e57f5473965673c1a4d7 100644 (file)
@@ -184,7 +184,9 @@ void ShapeTextPreprocess(const RendererParameters& textParameters, TextAbstracti
 
   if(textParameters.markupEnabled)
   {
-    ProcessMarkupString(textParameters.text, markupProcessData);
+    MarkupPropertyData markupPropertyData(Color::MEDIUM_BLUE, Color::DARK_MAGENTA);
+
+    ProcessMarkupString(textParameters.text, markupPropertyData, markupProcessData);
     textSize = markupProcessData.markupProcessedText.size();
 
     // This is a bit horrible but std::string returns a (signed) char*
index f1034f28a6aa354d257960d2ead68fc0e587e94c..aeb2a5e07c6f68c17a8841f2b33385e23a3e3707 100644 (file)
@@ -141,6 +141,8 @@ DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "ellipsisPosition
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "strikethrough",                MAP,     STRIKETHROUGH                  )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "characterSpacing",             FLOAT,   CHARACTER_SPACING              )
 DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "relativeLineSize",             FLOAT,   RELATIVE_LINE_SIZE             )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "anchorColor",                  VECTOR4, ANCHOR_COLOR                   )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit,           TextLabel, "anchorClickedColor",           VECTOR4, ANCHOR_CLICKED_COLOR           )
 
 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)
@@ -567,6 +569,26 @@ void TextLabel::SetProperty(BaseObject* object, Property::Index index, const Pro
         impl.mController->SetRelativeLineSize(relativeLineSize);
         break;
       }
+      case Toolkit::DevelTextLabel::Property::ANCHOR_COLOR:
+      {
+        const Vector4& anchorColor = value.Get<Vector4>();
+        if(impl.mController->GetAnchorColor() != anchorColor)
+        {
+          impl.mController->SetAnchorColor(anchorColor);
+          impl.mTextUpdateNeeded = true;
+        }
+        break;
+      }
+      case Toolkit::DevelTextLabel::Property::ANCHOR_CLICKED_COLOR:
+      {
+        const Vector4& anchorClickedColor = value.Get<Vector4>();
+        if(impl.mController->GetAnchorClickedColor() != anchorClickedColor)
+        {
+          impl.mController->SetAnchorClickedColor(anchorClickedColor);
+          impl.mTextUpdateNeeded = true;
+        }
+        break;
+      }
     }
 
     // Request relayout when text update is needed. It's necessary to call it
@@ -831,6 +853,16 @@ Property::Value TextLabel::GetProperty(BaseObject* object, Property::Index index
         value = impl.mController->GetRelativeLineSize();
         break;
       }
+      case Toolkit::DevelTextLabel::Property::ANCHOR_COLOR:
+      {
+        value = impl.mController->GetAnchorColor();
+        break;
+      }
+      case Toolkit::DevelTextLabel::Property::ANCHOR_CLICKED_COLOR:
+      {
+        value = impl.mController->GetAnchorClickedColor();
+        break;
+      }
     }
   }
 
index f23f08a7c8b4bfe7b2e12c7c1b9b769ca4a91037..0538f44c01806d08191b3feca7c8f4d6f170c984 100644 (file)
@@ -36,10 +36,14 @@ struct Anchor
   CharacterIndex endIndex;   ///< The character's end index of the anchor within the string.
   char*          href;       ///< The url path
 
-  bool     isClicked    = false;               ///< Whether the anchor is clicked or not.
-  Vector4  clickedColor = Color::DARK_MAGENTA; ///< The color of the anchor when clicked.
-  uint32_t colorRunIndex;                      ///< RunIndex of color run, used to change color when clicked.
-  uint32_t underlinedCharacterRunIndex;        ///< RunIndex of underline run, used to change color when clicked.
+  uint32_t colorRunIndex;               ///< RunIndex of color run, used to change color when property updated or clicked.
+  uint32_t underlinedCharacterRunIndex; ///< RunIndex of underline run, used to change color when property updated or clicked.
+
+  Vector4 markupClickedColor; ///< The markup color of the anchor when clicked. if there is no markup attribute, the default color stored in the controller is used.
+
+  bool     isClicked               = false; ///< Whether the anchor is clicked or not.
+  bool     isMarkupColorSet        = false; ///< Whether the markup color has been set or not.
+  bool     isMarkupClickedColorSet = false; ///< Whether the markup clicked color has been set or not.
 };
 
 } // namespace Text
index 8e175b1e181752fbd1bb02b618e587548d44f250..8d6d556cb0b82314a8c6cbf3010f2b274a0458c8 100644 (file)
@@ -405,15 +405,16 @@ void Controller::EventHandler::AnchorEvent(Controller& controller, float x, floa
           // TODO: in mutable text, the anchor color and underline run index should be able to be updated.
           if(!controller.IsEditable())
           {
+            // If there is a markup clicked color attribute, use it. Otherwise, use the property color.
             if(controller.mImpl->mModel->mLogicalModel->mColorRuns.Count() > anchor.colorRunIndex)
             {
               ColorRun& colorRun = *(controller.mImpl->mModel->mLogicalModel->mColorRuns.Begin() + anchor.colorRunIndex);
-              colorRun.color = anchor.clickedColor;
+              colorRun.color = anchor.isMarkupClickedColorSet ? anchor.markupClickedColor : controller.mImpl->mAnchorClickedColor;
             }
             if(controller.mImpl->mModel->mLogicalModel->mUnderlinedCharacterRuns.Count() > anchor.underlinedCharacterRunIndex)
             {
               UnderlinedCharacterRun& underlineRun = *(controller.mImpl->mModel->mLogicalModel->mUnderlinedCharacterRuns.Begin() + anchor.underlinedCharacterRunIndex);
-              underlineRun.properties.color = anchor.clickedColor;
+              underlineRun.properties.color = anchor.isMarkupClickedColorSet ? anchor.markupClickedColor : controller.mImpl->mAnchorClickedColor;
             }
 
             controller.mImpl->ClearFontData();
index eb85c8378c233c7ec9bcd4e4a58ab04ced8b8b20..eb24eb93acde7dce2de9100b83b8697aa3c74331 100644 (file)
@@ -440,6 +440,83 @@ bool Controller::Impl::ProcessInputEvents()
   return ControllerImplEventHandler::ProcessInputEvents(*this);
 }
 
+void Controller::Impl::SetAnchorColor(const Vector4& color)
+{
+  mAnchorColor = color;
+  UpdateAnchorColor();
+}
+
+const Vector4& Controller::Impl::GetAnchorColor() const
+{
+  return mAnchorColor;
+}
+
+void Controller::Impl::SetAnchorClickedColor(const Vector4& color)
+{
+  mAnchorClickedColor = color;
+  UpdateAnchorColor();
+}
+
+const Vector4& Controller::Impl::GetAnchorClickedColor() const
+{
+  return mAnchorClickedColor;
+}
+
+void Controller::Impl::UpdateAnchorColor()
+{
+  if(!mAnchorControlInterface ||
+     !mMarkupProcessorEnabled ||
+     !mModel->mLogicalModel->mAnchors.Count() ||
+     !IsShowingRealText())
+  {
+    return;
+  }
+
+  bool updateNeeded = false;
+
+  // The anchor color & clicked color needs to be updated with the property's color.
+  for(auto& anchor : mModel->mLogicalModel->mAnchors)
+  {
+    if(!anchor.isMarkupColorSet && !anchor.isClicked)
+    {
+      if(mModel->mLogicalModel->mColorRuns.Count() > anchor.colorRunIndex)
+      {
+        ColorRun& colorRun = *(mModel->mLogicalModel->mColorRuns.Begin() + anchor.colorRunIndex);
+        colorRun.color = mAnchorColor;
+        updateNeeded = true;
+      }
+      if(mModel->mLogicalModel->mUnderlinedCharacterRuns.Count() > anchor.underlinedCharacterRunIndex)
+      {
+        UnderlinedCharacterRun& underlineRun = *(mModel->mLogicalModel->mUnderlinedCharacterRuns.Begin() + anchor.underlinedCharacterRunIndex);
+        underlineRun.properties.color = mAnchorColor;
+        updateNeeded = true;
+      }
+    }
+    else if(!anchor.isMarkupClickedColorSet && anchor.isClicked)
+    {
+      if(mModel->mLogicalModel->mColorRuns.Count() > anchor.colorRunIndex)
+      {
+        ColorRun& colorRun = *(mModel->mLogicalModel->mColorRuns.Begin() + anchor.colorRunIndex);
+        colorRun.color = mAnchorClickedColor;
+        updateNeeded = true;
+      }
+      if(mModel->mLogicalModel->mUnderlinedCharacterRuns.Count() > anchor.underlinedCharacterRunIndex)
+      {
+        UnderlinedCharacterRun& underlineRun = *(mModel->mLogicalModel->mUnderlinedCharacterRuns.Begin() + anchor.underlinedCharacterRunIndex);
+        underlineRun.properties.color = mAnchorClickedColor;
+        updateNeeded = true;
+      }
+    }
+  }
+
+  if(updateNeeded)
+  {
+    ClearFontData();
+    mOperationsPending = static_cast<OperationsMask>(mOperationsPending | COLOR);
+    RequestRelayout();
+  }
+}
+
 void Controller::Impl::NotifyInputMethodContext()
 {
   if(mEventData && mEventData->mInputMethodContext)
@@ -1971,6 +2048,7 @@ void Controller::Impl::ClearStyleData()
   mModel->mLogicalModel->mColorRuns.Clear();
   mModel->mLogicalModel->ClearFontDescriptionRuns();
   mModel->mLogicalModel->ClearStrikethroughRuns();
+  mModel->mLogicalModel->ClearUnderlineRuns();
 }
 
 void Controller::Impl::ResetScrollPosition()
index b15f31ee0736a01debc25d8804997284df715b9e..c6d8b8c5889032511da1f8d27482776af558ecb5 100644 (file)
@@ -336,6 +336,8 @@ struct Controller::Impl
     mMetrics(),
     mModifyEvents(),
     mTextColor(Color::BLACK),
+    mAnchorColor(Color::MEDIUM_BLUE),
+    mAnchorClickedColor(Color::DARK_MAGENTA),
     mTextUpdateInfo(),
     mOperationsPending(NO_OPERATION),
     mMaximumNumberOfCharacters(50u),
@@ -514,6 +516,31 @@ struct Controller::Impl
     return mFontSizeScaleEnabled ? mFontSizeScale : 1.0f;
   }
 
+  /**
+   * @copydoc Controller::SetAnchorColor()
+   */
+  void SetAnchorColor(const Vector4& color);
+
+  /**
+   * @copydoc Controller::GetAnchorColor()
+   */
+  const Vector4& GetAnchorColor() const;
+
+  /**
+   * @copydoc Controller::SetAnchorClickedColor()
+   */
+  void SetAnchorClickedColor(const Vector4& color);
+
+  /**
+   * @copydoc Controller::GetAnchorClickedColor()
+   */
+  const Vector4& GetAnchorClickedColor() const;
+
+  /**
+   * @brief Updates the color of anchors.
+   */
+  void UpdateAnchorColor();
+
   /**
    * @brief Helper to notify InputMethodContext with surrounding text & cursor changes.
    */
@@ -1022,6 +1049,8 @@ public:
   Layout::Engine               mLayoutEngine;               ///< The layout engine.
   Vector<ModifyEvent>          mModifyEvents;               ///< Temporary stores the text set until the next relayout.
   Vector4                      mTextColor;                  ///< The regular text color
+  Vector4                      mAnchorColor;                ///< The anchor color
+  Vector4                      mAnchorClickedColor;         ///< The anchor clicked color
   TextUpdateInfo               mTextUpdateInfo;             ///< Info of the characters updated.
   OperationsMask               mOperationsPending;          ///< Operations pending to be done to layout the text.
   Length                       mMaximumNumberOfCharacters;  ///< Maximum number of characters that can be inserted.
index 30355f8fb92fe03119a0066d5a47077a3a9ebb01..2ceee77f66f97f252a33a71acd2ba567668217fe 100644 (file)
@@ -102,7 +102,9 @@ void Controller::TextUpdater::SetText(Controller& controller, const std::string&
     const uint8_t* utf8     = NULL;
     if(impl.mMarkupProcessorEnabled)
     {
-      ProcessMarkupString(text, markupProcessData);
+      MarkupPropertyData markupPropertyData(impl.mAnchorColor, impl.mAnchorClickedColor);
+
+      ProcessMarkupString(text, markupPropertyData, markupProcessData);
       textSize = markupProcessData.markupProcessedText.size();
 
       // This is a bit horrible but std::string returns a (signed) char*
index 129a3d9898559237dbfa00466ae72ba488aea99a..8f7a99e4cea5af7f8a5e999c4fc685e1b5080bc2 100644 (file)
@@ -808,6 +808,26 @@ const Vector4& Controller::GetDefaultColor() const
   return mImpl->mTextColor;
 }
 
+void Controller::SetAnchorColor(const Vector4& color)
+{
+  mImpl->SetAnchorColor(color);
+}
+
+const Vector4& Controller::GetAnchorColor() const
+{
+  return mImpl->GetAnchorColor();
+}
+
+void Controller::SetAnchorClickedColor(const Vector4& color)
+{
+  mImpl->SetAnchorClickedColor(color);
+}
+
+const Vector4& Controller::GetAnchorClickedColor() const
+{
+  return mImpl->GetAnchorClickedColor();
+}
+
 void Controller::SetDisabledColorOpacity(float opacity)
 {
   mImpl->mDisabledColorOpacity = opacity;
index 9276807c12b4f63565d8c71ab2baf547cac7b79a..7612b2d1214287994123c2cc8366f03b51386ef6 100644 (file)
@@ -1093,6 +1093,34 @@ public: // Default style & Input style
    */
   const Vector4& GetDefaultColor() const;
 
+  /**
+   * @brief Sets the anchor's default color.
+   *
+   * @param color The anchor color.
+   */
+  void SetAnchorColor(const Vector4& color);
+
+  /**
+   * @brief Retrieves the anchor's default color.
+   *
+   * @return The anchor color.
+   */
+  const Vector4& GetAnchorColor() const;
+
+  /**
+   * @brief Sets the anchor's clicked color.
+   *
+   * @param color The anchor color.
+   */
+  void SetAnchorClickedColor(const Vector4& color);
+
+  /**
+   * @brief Retrieves the anchor's clicked color.
+   *
+   * @return The anchor color.
+   */
+  const Vector4& GetAnchorClickedColor() const;
+
   /**
    * @brief Sets the user interaction enabled.
    *
index dcad0735e31274c4c4a51f2b29193d1e8dcf0ea2..85026297fdcf6e67c4da978c6038420d1b615817 100644 (file)
@@ -497,6 +497,11 @@ void LogicalModel::ClearStrikethroughRuns()
   mStrikethroughCharacterRuns.Clear();
 }
 
+void LogicalModel::ClearUnderlineRuns()
+{
+  mUnderlinedCharacterRuns.Clear();
+}
+
 void LogicalModel::CreateParagraphInfo(CharacterIndex startIndex,
                                        Length         numberOfCharacters)
 {
index 2db64a22b4abcf3040fc9ff5b0f080ad45360225..af4510f90f003c5f2b33242cdaa74cbea6452c7f 100644 (file)
@@ -160,6 +160,11 @@ public:
    */
   void ClearStrikethroughRuns();
 
+  /**
+   * @brief Clears the underline runs.
+   */
+  void ClearUnderlineRuns();
+
   // Paragraphs
 
   /**
index d958d1979cc16ba7b7d3beabf5d840486f15df19..ed80c40ebb415a881678f443c4a6f567a847ef13 100644 (file)
@@ -53,12 +53,18 @@ void ProcessAnchorTag(const Tag&              tag,
     }
     else if(TokenComparison(MARKUP::ANCHOR_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
     {
+      // The markup anchor color is set on the text and underline color runs.
+      // This takes precedence over the anchor color property of the text-label.
       ProcessColor(attribute, colorRun);
       ProcessColorAttribute(attribute, underlinedCharacterRun);
+      anchor.isMarkupColorSet = true;
     }
     else if(TokenComparison(MARKUP::ANCHOR_ATTRIBUTES::CLICKED_COLOR, attribute.nameBuffer, attribute.nameLength))
     {
-      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, anchor.clickedColor);
+      // The markup anchor clicked color is stored here.
+      // This is later used when the anchor's click event occurs.
+      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, anchor.markupClickedColor);
+      anchor.isMarkupClickedColorSet = true;
     }
   }
 }
index 67037e4af8a36200ad2e44ea01767a1615d6c4b6..654a44b88e1dee35fe74f3f1e3afd86a7ee92301 100644 (file)
@@ -343,8 +343,15 @@ void ParseAttributes(Tag& tag)
     }
     else if(EQUAL == character) // '='
     {
-      addToNameValue = false; // next read characters will be added to the value.
-      SkipWhiteSpace(tagBuffer, tagEndBuffer);
+      if(isQuotationOpen)
+      {
+        ++valueLength;
+      }
+      else
+      {
+        addToNameValue = false; // next read characters will be added to the value.
+        SkipWhiteSpace(tagBuffer, tagEndBuffer);
+      }
     }
     else if(QUOTATION_MARK == character) // '\''
     {
@@ -902,6 +909,7 @@ void ProcessSpanForRun(
  * @brief Processes anchor tag for the color-run & underline-run.
  *
  * @param[in,out] markupProcessData The markup process data
+ * @param[in] markupPropertyData The markup property data
  * @param[in] tag The tag we are currently processing
  * @param[in,out] anchorStack The anchors stack
  * @param[in,out] colorRuns The container containing all the color runs
@@ -913,6 +921,7 @@ void ProcessSpanForRun(
  */
 void ProcessAnchorForRun(
   MarkupProcessData&                    markupProcessData,
+  MarkupPropertyData&                   markupPropertyData,
   const Tag&                            tag,
   StyleStack<AnchorForStack>&           anchorStack,
   Vector<ColorRun>&                     colorRuns,
@@ -931,6 +940,7 @@ void ProcessAnchorForRun(
     anchor.endIndex                    = 0u;
     anchor.colorRunIndex               = colorRunIndex;
     anchor.underlinedCharacterRunIndex = underlinedCharacterRunIndex;
+    anchor.markupClickedColor          = markupPropertyData.anchorClickedColor;
 
     // Create a new run.
     ColorRun colorRun;
@@ -950,8 +960,8 @@ void ProcessAnchorForRun(
     anchorForStack.underlinedCharacterRunIndex = underlinedCharacterRunIndex;
 
     // Init default color
-    colorRun.color                                 = Color::MEDIUM_BLUE;
-    underlinedCharacterRun.properties.color        = Color::MEDIUM_BLUE;
+    colorRun.color                                 = markupPropertyData.anchorColor;
+    underlinedCharacterRun.properties.color        = markupPropertyData.anchorColor;
     underlinedCharacterRun.properties.colorDefined = true;
 
     ProcessAnchorTag(tag, anchor, colorRun, underlinedCharacterRun);
@@ -1133,7 +1143,7 @@ void ProcessMarkupStringBuffer(
 
 } // namespace
 
-void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData)
+void ProcessMarkupString(const std::string& markupString, MarkupPropertyData& markupPropertyData, MarkupProcessData& markupProcessData)
 {
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "markupString: %s\n", markupString.c_str());
 
@@ -1226,6 +1236,7 @@ void ProcessMarkupString(const std::string& markupString, MarkupProcessData& mar
       else if(TokenComparison(MARKUP::TAG::ANCHOR, tag.buffer, tag.length))
       {
         ProcessAnchorForRun(markupProcessData,
+                            markupPropertyData,
                             tag,
                             anchorStack,
                             markupProcessData.colorRuns,
index f751843e85c242366cd06eb2ecb2cfd2c5d4c9f8..1ee520da0935550769d76ff884dd5d0057c8cf4c 100644 (file)
@@ -78,13 +78,27 @@ struct MarkupProcessData
   std::string markupProcessedText; ///< The mark-up string.
 };
 
+struct MarkupPropertyData
+{
+  MarkupPropertyData(Vector4 anchorColor,
+                     Vector4 anchorClickedColor)
+  : anchorColor(anchorColor),
+    anchorClickedColor(anchorClickedColor)
+  {
+  }
+
+  Vector4 anchorColor;        ///< The anchor color
+  Vector4 anchorClickedColor; ///< The anchor clicked color
+};
+
 /**
  * @brief Process the mark-up string.
  *
  * @param[in] markupString The mark-up string.
+ * @param[in] markupPropertyData The property data that will be used by default in markup processing.
  * @param[out] markupProcessData The plain text and the style.
  */
-void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData);
+void ProcessMarkupString(const std::string& markupString, MarkupPropertyData& markupPropertyData, MarkupProcessData& markupProcessData);
 
 } // namespace Text