2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/controls/text-view/text-view-impl.h>
22 #include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
23 #include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
24 #include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
25 #include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
26 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
27 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
28 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
36 const Property::Index TextView::PROPERTY_MARKUP_ENABLED( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX );
37 const Property::Index TextView::PROPERTY_TEXT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 1 );
38 const Property::Index TextView::PROPERTY_MULTILINE_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 2 );
39 const Property::Index TextView::PROPERTY_WIDTH_EXCEED_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 3 );
40 const Property::Index TextView::PROPERTY_HEIGHT_EXCEED_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 4 );
41 const Property::Index TextView::PROPERTY_LINE_JUSTIFICATION( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 5 );
42 const Property::Index TextView::PROPERTY_FADE_BOUNDARY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 6 );
43 const Property::Index TextView::PROPERTY_LINE_HEIGHT_OFFSET( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 7 );
44 const Property::Index TextView::PROPERTY_HORIZONTAL_ALIGNMENT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 8 );
45 const Property::Index TextView::PROPERTY_VERTICAL_ALIGNMENT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 9 );
53 const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"};
54 const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"};
55 const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"};
57 // Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
58 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
63 return Toolkit::TextView::New();
66 TypeRegistration typeRegistration( typeid(Toolkit::TextView), typeid(Toolkit::Control), Create );
68 SignalConnectorType signalConnector1( typeRegistration, Toolkit::TextView::SIGNAL_TEXT_SCROLLED , &TextView::DoConnectSignal );
70 PropertyRegistration property1( typeRegistration, "markup-enabled", Toolkit::TextView::PROPERTY_MARKUP_ENABLED, Property::BOOLEAN, &TextView::SetProperty, &TextView::GetProperty );
71 PropertyRegistration property2( typeRegistration, "text", Toolkit::TextView::PROPERTY_TEXT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
72 PropertyRegistration property3( typeRegistration, "multiline-policy", Toolkit::TextView::PROPERTY_MULTILINE_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
73 PropertyRegistration property4( typeRegistration, "width-exceed-policy", Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
74 PropertyRegistration property5( typeRegistration, "height-exceed-policy", Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
75 PropertyRegistration property6( typeRegistration, "line-justification", Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
76 PropertyRegistration property7( typeRegistration, "fade-boundary", Toolkit::TextView::PROPERTY_FADE_BOUNDARY, Property::VECTOR4, &TextView::SetProperty, &TextView::GetProperty );
77 PropertyRegistration property8( typeRegistration, "line-height-offset", Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET, Property::FLOAT, &TextView::SetProperty, &TextView::GetProperty );
78 PropertyRegistration property9( typeRegistration, "horizontal-alignment", Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
79 PropertyRegistration property10( typeRegistration, "vertical-alignment", Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
82 * Whether the text-view-processor operation sets, inserts, replaces, removes text.
84 * @param[in] metadata The text-view-processor operation.
86 * @return \e true if the given text-view-processor operation is modifying the text.
88 bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata )
90 return ( ( metadata.mType == TextView::TextSet ) ||
91 ( metadata.mType == TextView::TextInserted ) ||
92 ( metadata.mType == TextView::TextReplaced ) ||
93 ( metadata.mType == TextView::TextRemoved ) ||
94 ( metadata.mType == TextView::NewStyle ));
98 * Whether the text-view-processor operation sets a new line height offset.
100 * @param[in] metadata The text-view-processor operation.
102 * @return \e true if the given text-view-processor operation sets a new line height offset.
104 bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata )
106 return ( metadata.mType == TextView::NewLineHeight );
110 * Whether the text-view-processor operation sets a new style.
112 * @param[in] metadata The text-view-processor operation.
114 * @return \e true if the given text-view-processor operation sets a new style.
116 bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata )
118 return ( metadata.mType == TextView::NewStyle );
123 TextView::TextViewProcessorMetadata::TextViewProcessorMetadata()
124 : mType( TextView::TextSet ),
126 mNumberOfCharacters( 0u ),
131 Toolkit::TextView TextView::New()
133 // Create the implementation, temporarily owned on stack
134 IntrusivePtr<TextView> textView = new TextView();
136 // Pass ownership to CustomActor
137 Toolkit::TextView handle( *textView );
139 // Second-phase init of the implementation
140 // This can only be done after the CustomActor connection has been made...
141 textView->Initialize();
143 // Disables by default the offscreen rendering.
144 textView->SetSnapshotModeEnabled( false );
149 void TextView::SetText( const std::string& text )
151 // Creates a styled text with the markup or plain string.
152 MarkupProcessor::StyledTextArray styledText;
153 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
155 // Calls SetText() with the styled text array.
156 SetText( styledText );
159 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
161 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
162 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
164 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
165 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
167 // Creates metadata with the Set operation.
168 TextViewProcessorMetadata metadata;
169 metadata.mType = TextView::TextSet;
170 metadata.mText = text;
173 mTextViewProcessorOperations.push_back( metadata );
175 // Updates current styled text.
176 mCurrentStyledText = text;
178 // Request to be relaid out
181 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
182 mRelayoutOperations = RELAYOUT_ALL;
185 void TextView::InsertTextAt( std::size_t position, const std::string& text )
187 // Creates a styled text with the markup or plain string.
188 MarkupProcessor::StyledTextArray styledText;
189 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
191 // Calls InsertTextAt() with the styled text array.
192 InsertTextAt( position, styledText );
195 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
198 MarkupProcessor::GetPlainString( text, textStr );
200 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
201 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
203 // Temporary fix. Creates the whole layout if there is rtl text.
205 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
206 textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
207 SetText( textToSet );
211 // Creates metadata with the Insert operation.
212 TextViewProcessorMetadata metadata;
213 metadata.mType = TextView::TextInserted;
214 metadata.mPosition = position;
215 metadata.mText = text;
218 mTextViewProcessorOperations.push_back( metadata );
220 // Updates current styled text.
221 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
223 // Request to be relaid out
226 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
227 mRelayoutOperations = RELAYOUT_ALL;
231 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
233 // Creates a styled text with the markup or plain string.
234 MarkupProcessor::StyledTextArray styledText;
235 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
237 // Calls ReplaceTextFromTo() with the styled text array.
238 ReplaceTextFromTo( position, numberOfCharacters, styledText );
241 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
244 MarkupProcessor::GetPlainString( text, textStr );
246 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
247 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
249 // Temporary fix. Creates the whole layout if there is rtl text.
251 // Updates current styled text.
252 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
254 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
255 textToSet.erase( it, it + numberOfCharacters );
256 it = textToSet.begin() + position;
257 textToSet.insert( it, text.begin(), text.end() );
259 SetText( textToSet );
263 // Creates metadata with the Insert operation.
264 TextViewProcessorMetadata metadata;
265 metadata.mType = TextView::TextReplaced;
266 metadata.mPosition = position;
267 metadata.mNumberOfCharacters = numberOfCharacters;
268 metadata.mText = text;
271 mTextViewProcessorOperations.push_back( metadata );
273 // Updates current styled text.
274 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
275 mCurrentStyledText.erase( it, it + numberOfCharacters );
276 it = mCurrentStyledText.begin() + position;
277 mCurrentStyledText.insert( it, text.begin(), text.end() );
279 // Request to be relaid out
282 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
283 mRelayoutOperations = RELAYOUT_ALL;
287 void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
289 if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
291 // Temporary fix. Creates the whole layout if there is rtl text.
293 // Updates current styled text.
294 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
295 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
296 textToSet.erase( it, it + numberOfCharacters );
298 SetText( textToSet );
302 // Creates metadata with the Remove operation.
303 TextViewProcessorMetadata metadata;
304 metadata.mType = TextView::TextRemoved;
305 metadata.mPosition = position;
306 metadata.mNumberOfCharacters = numberOfCharacters;
309 mTextViewProcessorOperations.push_back( metadata );
311 // Updates current styled text.
312 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
313 mCurrentStyledText.erase( it, it + numberOfCharacters );
315 // Request to be relaid out
318 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
319 mRelayoutOperations = RELAYOUT_ALL;
323 std::string TextView::GetText() const
325 // Traverses the styled text array getting only the text.
326 // Note that for some languages a 'character' could be represented by more than one 'char'
329 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
331 text.append( (*it).mText.GetText() );
337 void TextView::SetLineHeightOffset( PointSize offset )
339 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
341 // Removes any previous operation which modifies the line height offset.
342 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
343 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
345 // Creates metadata with the new line height operation.
346 TextViewProcessorMetadata metadata;
347 metadata.mType = TextView::NewLineHeight;
349 mTextViewProcessorOperations.push_back( metadata );
351 // Updates line height offset.
352 mLayoutParameters.mLineHeightOffset = offset;
356 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
357 if( RELAYOUT_ALL != mRelayoutOperations )
359 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
360 RELAYOUT_REMOVE_TEXT_ACTORS |
361 RELAYOUT_SIZE_POSITION |
363 RELAYOUT_VISIBILITY |
364 RELAYOUT_TEXT_ACTOR_UPDATE |
365 RELAYOUT_INSERT_TO_TEXT_VIEW );
370 PointSize TextView::GetLineHeightOffset() const
372 return PointSize( mLayoutParameters.mLineHeightOffset );
375 void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask )
377 if( !mCurrentStyledText.empty() )
379 const bool checkFontName = mask & TextStyle::FONT;
380 const bool checkFontSize = mask & TextStyle::SIZE;
381 const bool checkFontStyle = mask & TextStyle::STYLE;
383 // Check first if metrics have changed.
384 bool metricsChanged = false;
385 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
387 const MarkupProcessor::StyledText& styledText( *it );
389 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
390 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
391 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
396 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
398 // If metrics change, new text measurements are needed.
399 SetText( mCurrentStyledText );
403 // Deletes any previous operation which sets a new style.
404 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
405 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
407 // Creates metadata with the new style operation.
408 TextViewProcessorMetadata metadata;
409 metadata.mType = TextView::NewStyle;
411 MarkupProcessor::StyledText text;
413 metadata.mText.push_back( text );
414 metadata.mStyleMask = mask;
416 mTextViewProcessorOperations.push_back( metadata );
418 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
422 if( RELAYOUT_ALL != mRelayoutOperations )
424 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
425 RELAYOUT_TEXT_ACTOR_UPDATE );
430 // Sets the new style to the ellipsize text
431 // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
432 if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
434 for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
435 endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
439 (*it)->Copy( style, mask );
442 SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
446 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
448 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
450 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
451 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
452 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
453 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
454 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
455 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
457 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
458 mLayoutParameters.mVerticalAlignment = verticalAlignment;
462 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
463 if( RELAYOUT_ALL != mRelayoutOperations )
465 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
466 RELAYOUT_TEXT_ACTOR_UPDATE |
468 RELAYOUT_VISIBILITY );
473 Toolkit::Alignment::Type TextView::GetTextAlignment() const
475 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
478 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
480 if( policy != mLayoutParameters.mMultilinePolicy )
482 mLayoutParameters.mMultilinePolicy = policy;
484 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
485 mRelayoutOperations = RELAYOUT_ALL;
491 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
493 return mLayoutParameters.mMultilinePolicy;
496 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
498 // The layout info could be invalid depending on the current exceed policy and the new one.
499 // i.e. if the current policy is Split and the new one is ShrinkToFit then
500 // the layout info generated for each char is not needed.
501 if( policy != mLayoutParameters.mWidthExceedPolicy )
503 mLayoutParameters.mWidthExceedPolicy = policy;
505 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
506 mRelayoutOperations = RELAYOUT_ALL;
512 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
514 return mLayoutParameters.mWidthExceedPolicy;
517 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
519 if( policy != mLayoutParameters.mHeightExceedPolicy )
521 mLayoutParameters.mHeightExceedPolicy = policy;
525 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
526 if( RELAYOUT_ALL != mRelayoutOperations )
528 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
529 RELAYOUT_REMOVE_TEXT_ACTORS |
530 RELAYOUT_SIZE_POSITION |
532 RELAYOUT_VISIBILITY |
533 RELAYOUT_TEXT_ACTOR_UPDATE |
534 RELAYOUT_INSERT_TO_TEXT_VIEW );
539 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
541 return mLayoutParameters.mHeightExceedPolicy;
544 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
546 if( justification != mLayoutParameters.mLineJustification )
548 mLayoutParameters.mLineJustification = justification;
552 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
553 if( RELAYOUT_ALL != mRelayoutOperations )
555 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
556 RELAYOUT_REMOVE_TEXT_ACTORS |
557 RELAYOUT_SIZE_POSITION |
559 RELAYOUT_VISIBILITY |
560 RELAYOUT_TEXT_ACTOR_UPDATE |
561 RELAYOUT_INSERT_TO_TEXT_VIEW );
566 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
568 return mLayoutParameters.mLineJustification;
571 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
573 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
574 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
575 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
576 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
578 mVisualParameters.mFadeBoundary = fadeBoundary;
582 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
583 if( RELAYOUT_ALL != mRelayoutOperations )
585 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
586 RELAYOUT_REMOVE_TEXT_ACTORS |
587 RELAYOUT_VISIBILITY |
588 RELAYOUT_TEXT_ACTOR_UPDATE |
589 RELAYOUT_INSERT_TO_TEXT_VIEW );
594 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
596 return mVisualParameters.mFadeBoundary;
599 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
601 // Creates a styled text with the markup or plain string.
602 MarkupProcessor::StyledTextArray styledText;
603 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
605 // Creates the ellipsis layout info and sets the text and styles.
606 SetEllipsizeText( styledText );
609 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
611 // Converts the styled text array into a Text and a vector of TextStyles.
613 Vector<TextStyle*> styles;
614 for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
616 const MarkupProcessor::StyledText& styledText( *it );
618 text.Append( styledText.mText );
619 styles.PushBack( new TextStyle( styledText.mStyle ) );
622 // Creates the ellipsis layout info and sets the text and styles.
623 SetEllipsizeText( text, styles );
626 void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
628 // Sets the text and styles for the ellipsis text.
629 mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
630 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
632 // Creates the ellipsis layout info.
633 CreateEllipsizeLayout();
635 // Request to be relaid out
638 mRelayoutOperations = RELAYOUT_ALL;
641 std::string TextView::GetEllipsizeText() const
643 return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
646 void TextView::GetTextLayoutInfo()
648 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
649 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
650 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
652 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
654 Vector3 textViewSize = GetControlSize();
656 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
657 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
658 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
659 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
660 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
662 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
663 // the text natural size can be used.
664 textViewSize = GetNaturalSize();
667 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
668 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
670 // Check if the text-view has glyph-actors.
671 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
673 RelayoutOperationMask mask = NO_RELAYOUT;
674 if( relayoutSizeAndPositionNeeded )
676 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
678 if( relayoutAlignmentNeeded )
680 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
682 if( relayoutVisibilityNeeded )
684 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
689 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
690 // add them to the text-actor cache.
691 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
692 mRelayoutData.mGlyphActors.clear();
695 // Relays-out but doesn't add glyph-actors to the text-view.
696 DoRelayOut( textViewSize.GetVectorXY(), mask );
700 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
706 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
710 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
711 textLayoutInfo.mLines = mRelayoutData.mLines;
713 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
714 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
716 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
718 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
721 void TextView::SetSortModifier( float depthOffset )
723 mVisualParameters.mSortModifier = depthOffset;
725 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
729 ( *it ).SetSortModifier( depthOffset );
732 if( mOffscreenImageActor )
734 mOffscreenImageActor.SetSortModifier( depthOffset );
738 void TextView::SetSnapshotModeEnabled( bool enable )
740 if( enable != mVisualParameters.mSnapshotModeEnabled )
742 // Remove first all glyph-actors
743 if( !mRelayoutData.mGlyphActors.empty() )
745 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
748 mVisualParameters.mSnapshotModeEnabled = enable;
749 if( !mLockPreviousSnapshotMode )
751 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
752 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
754 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
755 // to smash the stored value.
756 mPreviousSnapshotModeEnabled = enable;
759 if( mVisualParameters.mSnapshotModeEnabled )
761 // Create a root actor and an image actor for offscreen rendering.
762 mOffscreenRootActor = Layer::New();
763 mOffscreenImageActor = ImageActor::New();
765 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
766 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
767 mOffscreenRootActor.SetInheritRotation( false );
768 mOffscreenRootActor.SetInheritScale( false );
769 mOffscreenRootActor.SetDepthTestDisabled( true );
771 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
773 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
774 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
775 mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
776 BlendingFactor::ONE, BlendingFactor::ONE );
779 self.Add( mOffscreenRootActor );
780 self.Add( mOffscreenImageActor );
781 mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) );
787 if( mOffscreenRootActor )
789 self.Remove( mOffscreenRootActor );
792 if( mOffscreenImageActor )
794 self.Remove( mOffscreenImageActor );
797 DestroyOffscreenRenderingResources();
800 if( RELAYOUT_ALL != mRelayoutOperations )
802 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
803 RELAYOUT_REMOVE_TEXT_ACTORS |
804 RELAYOUT_TEXT_ACTOR_UPDATE |
805 RELAYOUT_INSERT_TO_TEXT_VIEW );
811 bool TextView::IsSnapshotModeEnabled() const
813 return mVisualParameters.mSnapshotModeEnabled;
816 void TextView::SetMarkupProcessingEnabled( bool enable )
818 mMarkUpEnabled = enable;
821 bool TextView::IsMarkupProcessingEnabled() const
823 return mMarkUpEnabled;
826 void TextView::SetScrollEnabled( bool enable )
828 if( enable != mVisualParameters.mScrollEnabled )
830 mVisualParameters.mScrollEnabled = enable;
832 if( mVisualParameters.mScrollEnabled )
834 // Offscreen rendering is needed to enable text scroll.
836 // Stores previous value of the snapshot mode.
837 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
840 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
841 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
842 Lock lock( mLockPreviousSnapshotMode );
843 SetSnapshotModeEnabled( true );
846 // Creates the pan gesture detector and attach the text-view.
847 mPanGestureDetector = PanGestureDetector::New();
848 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
849 mPanGestureDetector.Attach( Self() );
853 // Removes the pan gesture detector.
854 if( mPanGestureDetector )
856 mPanGestureDetector.Detach( Self() );
857 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
858 mPanGestureDetector.Reset();
861 // Restores the previous state for snapshot mode.
862 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
867 bool TextView::IsScrollEnabled() const
869 return mVisualParameters.mScrollEnabled;
872 void TextView::SetScrollPosition( const Vector2& position )
874 if( position != mVisualParameters.mCameraScrollPosition )
876 // Guard against destruction during signal emission
877 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
878 Toolkit::TextView handle( GetOwner() );
880 DoSetScrollPosition( position );
882 // Check if the new scroll position has been trimmed.
883 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
887 const Vector2& TextView::GetScrollPosition() const
889 return mVisualParameters.mCameraScrollPosition;
892 bool TextView::IsScrollPositionTrimmed() const
894 return mVisualParameters.mScrollPositionTrimmed;
897 Toolkit::TextView::ScrolledSignalV2& TextView::ScrolledSignal()
899 return mScrolledSignalV2;
902 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
904 Dali::BaseHandle handle( object );
906 bool connected( true );
907 Toolkit::TextView textView = Toolkit::TextView::DownCast(handle);
909 if( Dali::Toolkit::TextView::SIGNAL_TEXT_SCROLLED == signalName )
911 textView.ScrolledSignal().Connect( tracker, functor );
915 // signalName does not match any signal
922 TextView::LayoutParameters::LayoutParameters()
923 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
924 mWidthExceedPolicy( Toolkit::TextView::Original ),
925 mHeightExceedPolicy( Toolkit::TextView::Original ),
926 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
927 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
928 mLineJustification( Toolkit::TextView::Left ),
929 mLineHeightOffset( 0.f ),
930 mMarkUpEnabled( false )
934 TextView::LayoutParameters::~LayoutParameters()
938 TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy,
939 Toolkit::TextView::ExceedPolicy widthExceedPolicy,
940 Toolkit::TextView::ExceedPolicy heightExceedPolicy,
941 Toolkit::Alignment::Type alignmentType,
942 Toolkit::TextView::LineJustification lineJustification,
943 float lineHeightOffset,
945 : mMultilinePolicy( multilinePolicy ),
946 mWidthExceedPolicy( widthExceedPolicy ),
947 mHeightExceedPolicy( heightExceedPolicy ),
948 mHorizontalAlignment(),
949 mVerticalAlignment(),
950 mLineJustification( lineJustification ),
951 mLineHeightOffset( lineHeightOffset ),
952 mMarkUpEnabled( markUpEnabled )
955 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
956 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
957 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
958 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
959 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
960 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
962 mHorizontalAlignment = horizontalAlignment;
963 mVerticalAlignment = verticalAlignment;
966 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
967 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
968 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
969 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
970 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
971 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
972 mLineJustification( layoutParameters.mLineJustification ),
973 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
974 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
978 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
980 mMultilinePolicy = layoutParameters.mMultilinePolicy;
981 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
982 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
983 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
984 mVerticalAlignment = layoutParameters.mVerticalAlignment;
985 mLineJustification = layoutParameters.mLineJustification;
986 mLineHeightOffset = layoutParameters.mLineHeightOffset;
987 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
992 TextView::VisualParameters::VisualParameters()
994 mSortModifier( 0.f ),
995 mCameraScrollPosition( 0.f, 0.f ),
996 mSnapshotModeEnabled( false ),
997 mScrollEnabled( false ),
998 mScrollPositionTrimmed( false )
1002 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
1003 : mFadeBoundary( visualParameters.mFadeBoundary ),
1004 mSortModifier( visualParameters.mSortModifier ),
1005 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
1006 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
1007 mScrollEnabled( visualParameters.mScrollEnabled ),
1008 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
1012 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters )
1014 mFadeBoundary = visualParameters.mFadeBoundary;
1015 mSortModifier = visualParameters.mSortModifier;
1016 mCameraScrollPosition = visualParameters.mCameraScrollPosition;
1017 mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled;
1018 mScrollEnabled = visualParameters.mScrollEnabled;
1019 mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed;
1024 TextView::RelayoutData::RelayoutData()
1026 mShrinkFactor( 1.f ),
1028 mCharacterLogicalToVisualMap(),
1029 mCharacterVisualToLogicalMap(),
1031 mCharacterLayoutInfoTable(),
1033 mTextSizeForRelayoutOption()
1037 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
1038 : mTextViewSize( relayoutData.mTextViewSize ),
1039 mShrinkFactor( relayoutData.mShrinkFactor ),
1040 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
1041 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
1042 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
1043 mGlyphActors( relayoutData.mGlyphActors ),
1044 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
1045 mLines( relayoutData.mLines ),
1046 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
1050 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
1052 mTextViewSize = relayoutData.mTextViewSize;
1053 mShrinkFactor = relayoutData.mShrinkFactor;
1054 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
1055 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
1056 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
1057 mGlyphActors = relayoutData.mGlyphActors;
1058 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
1059 mLines = relayoutData.mLines;
1060 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1065 TextView::TextView()
1066 : Control( REQUIRES_STYLE_CHANGE_SIGNALS ),
1067 mCurrentStyledText(),
1068 mTextViewProcessorOperations(),
1069 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1070 Toolkit::TextView::Original,
1071 Toolkit::TextView::Original,
1072 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1073 Toolkit::TextView::Left,
1076 mVisualParameters(),
1078 mRelayoutOperations( NO_RELAYOUT ),
1079 mOffscreenRootActor(),
1080 mOffscreenImageActor(),
1081 mOffscreenCameraActor(),
1082 mCurrentOffscreenSize(),
1083 mFrameBufferImage(),
1085 mPanGestureDetector(),
1086 mLockPreviousSnapshotMode( false ),
1087 mPreviousSnapshotModeEnabled( false ),
1088 mMarkUpEnabled( false )
1090 // Creates the ellipsis layout info.
1091 CreateEllipsizeLayout();
1094 TextView::~TextView()
1096 // Destroys offscreen rendering resources.
1097 DestroyOffscreenRenderingResources();
1099 // Destroys scroll pan gesture detector.
1100 if( mPanGestureDetector )
1102 mPanGestureDetector.Reset();
1106 Vector3 TextView::GetNaturalSize()
1108 if( !mTextViewProcessorOperations.empty() )
1110 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1112 if( !mRelayoutData.mGlyphActors.empty() )
1114 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1115 // add them to the text-actor cache.
1116 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1117 mRelayoutData.mGlyphActors.clear();
1119 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1122 PerformTextViewProcessorOperations();
1125 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1128 float TextView::GetHeightForWidth( float width )
1132 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1133 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1134 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1136 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1137 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1138 height = GetNaturalSize().height;
1142 // Check if the given width is different than the current one.
1143 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1145 // Check if the text-view has glyph-actors.
1146 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1148 // Check which layout operations need to be done.
1149 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1151 if( relayoutSizeAndPositionNeeded )
1153 if( hasGlyphActors )
1155 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1156 // add them to the text-actor cache.
1157 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1158 mRelayoutData.mGlyphActors.clear();
1161 // Use the given width.
1162 const Vector2 textViewSize( width, GetControlSize().height );
1164 // Relays-out but doesn't add glyph-actors to the text-view.
1165 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1168 // Retrieve the text height after relayout the text.
1169 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1171 if( differentWidth )
1173 // Revert the relayout operation mask
1174 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1177 if( hasGlyphActors )
1179 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1182 if( differentWidth || hasGlyphActors )
1191 float TextView::GetWidthForHeight( float height )
1193 // TODO: Needs implementing properly, for now just return the natural width.
1194 return GetNaturalSize().width;
1198 void TextView::OnInitialize()
1203 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1205 // Creates the ellipsis layout info.
1206 CreateEllipsizeLayout();
1208 SetText( mCurrentStyledText );
1211 void TextView::OnControlSizeSet( const Vector3& size )
1213 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1215 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1216 mRelayoutOperations = RELAYOUT_ALL;
1218 // Request to be relaid out
1223 void TextView::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1225 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1227 // Not worth to relayout if width or height is equal to zero.
1231 if( size != mRelayoutData.mTextViewSize )
1233 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1234 if( RELAYOUT_ALL != mRelayoutOperations )
1236 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1237 RELAYOUT_REMOVE_TEXT_ACTORS |
1238 RELAYOUT_SIZE_POSITION |
1239 RELAYOUT_ALIGNMENT |
1240 RELAYOUT_VISIBILITY |
1241 RELAYOUT_TEXT_ACTOR_UPDATE |
1242 RELAYOUT_INSERT_TO_TEXT_VIEW );
1246 if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
1247 ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
1249 if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
1251 // If the text of the alignment changes and a fade exceed policy is set,
1252 // some characters may need new TextActor.
1253 mRelayoutOperations = RELAYOUT_ALL;
1257 // Remove glyph-actors from text-view
1258 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1260 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1261 mRelayoutData.mGlyphActors.clear();
1264 if( NO_RELAYOUT != mRelayoutOperations )
1266 // Relays-out and add glyph-actors to the text-view.
1267 DoRelayOut( size, mRelayoutOperations );
1268 ProcessSnapshot( size );
1271 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1272 mRelayoutData.mTextActorCache.ClearTexts();
1275 void TextView::PerformTextViewProcessorOperations()
1277 // Traverse the relayout operation vector ...
1279 // Optimizes some operations.
1280 OptimizeTextViewProcessorOperations();
1282 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1284 const TextViewProcessorMetadata& relayoutMetadata( *it );
1286 switch( relayoutMetadata.mType )
1288 case TextView::TextSet:
1290 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1295 case TextView::TextInserted:
1297 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1298 relayoutMetadata.mText,
1303 case TextView::TextReplaced:
1305 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1306 relayoutMetadata.mNumberOfCharacters,
1307 relayoutMetadata.mText,
1312 case TextView::TextRemoved:
1314 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1315 relayoutMetadata.mNumberOfCharacters,
1318 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1321 case TextView::NewLineHeight:
1323 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1324 mRelayoutData.mTextLayoutInfo );
1327 case TextView::NewStyle:
1329 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1330 relayoutMetadata.mStyleMask,
1337 // Clear all operations when they are done.
1338 mTextViewProcessorOperations.clear();
1341 void TextView::OptimizeTextViewProcessorOperations()
1343 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1345 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1346 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1347 // use the cache without clearing the text-actors.
1349 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1351 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1353 const TextViewProcessorMetadata& relayoutMetadata( *it );
1355 switch( relayoutMetadata.mType )
1357 case TextView::TextRemoved:
1359 bool optimizationDone = false;
1361 if( it + 1u != endIt )
1363 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) );
1364 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1366 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1368 optimizationDone = true;
1369 TextViewProcessorMetadata newRelayoutMetadata;
1370 newRelayoutMetadata.mType = TextView::TextReplaced;
1371 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1372 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1373 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1374 textViewProcessorOperations.push_back( newRelayoutMetadata );
1376 // do not access the TextInserted operation in next iteration.
1382 if( !optimizationDone )
1384 textViewProcessorOperations.push_back( relayoutMetadata );
1390 textViewProcessorOperations.push_back( relayoutMetadata );
1395 mTextViewProcessorOperations = textViewProcessorOperations;
1398 void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask )
1400 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1401 if( !mTextViewProcessorOperations.empty() )
1403 PerformTextViewProcessorOperations();
1406 CombineExceedPolicies();
1409 if( mVisualParameters.mSnapshotModeEnabled )
1411 rootActor = mOffscreenRootActor;
1418 mRelayoutData.mTextViewSize = textViewSize;
1419 switch( mLayoutParameters.mMultilinePolicy )
1421 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1423 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1425 } // SplitByNewLineChar
1427 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1429 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1433 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1435 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1438 } // switch( mMultilinePolicy )
1440 // Remove done operations from the mask.
1441 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1444 void TextView::ProcessSnapshot( const Size& textViewSize )
1446 if( mVisualParameters.mSnapshotModeEnabled )
1448 // If layout options change, it's needed generate a new image.
1450 if( mOffscreenRootActor )
1452 // Set the root actor visible.
1453 // The root actor is set to non visible after the render task is processed.
1454 mOffscreenRootActor.SetVisible( true );
1456 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1457 mOffscreenRootActor.SetSize( textViewSize );
1460 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1461 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1463 // Set the image actor visible.
1464 // The image actor is set to non visible if there is no text to render.
1465 mOffscreenImageActor.SetVisible( true );
1467 // Calculates the offscreen image's size. It takes into account different points:
1468 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1469 // * There is a maximum texture size the graphic subsystem can load on the memory.
1470 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1472 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1473 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1474 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1475 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1477 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1481 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1482 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1483 offscreenSize.height,
1486 // Stores current text-view size to avoid create new Dali resources if text changes.
1487 mCurrentOffscreenSize = offscreenSize;
1489 if( !mOffscreenCameraActor )
1491 // Creates a new camera actor.
1492 mOffscreenCameraActor = CameraActor::New();
1493 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1494 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1495 mOffscreenCameraActor.SetRotation(Degree(180.f), Vector3::YAXIS);
1497 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1499 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1502 // Calculate camera parameters for current text size.
1503 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1506 if( mVisualParameters.mScrollEnabled )
1508 // Updates the offscreen camera position with the new scroll offset.
1509 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1510 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1514 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1515 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1520 // Creates a new render task.
1521 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1523 mRenderTask.SetSourceActor( mOffscreenRootActor );
1524 mRenderTask.SetInputEnabled( false );
1525 mRenderTask.SetClearColor( Color::TRANSPARENT );
1526 mRenderTask.SetClearEnabled( true );
1527 mRenderTask.SetExclusive( true );
1529 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1530 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1535 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1536 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1539 // Process the render task only once every time the text changes or the text-view's size canges.
1540 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1544 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1545 mOffscreenImageActor.SetVisible( false );
1550 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1552 float xPosition = 0.f;
1553 float yPosition = 0.f;
1554 Vector3 parentOrigin = ParentOrigin::CENTER;
1555 Vector3 anchorPoint = AnchorPoint::CENTER;
1557 switch( mLayoutParameters.mHorizontalAlignment )
1559 case Toolkit::Alignment::HorizontalLeft:
1561 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1562 parentOrigin.x = 0.f;
1563 anchorPoint.x = 0.f;
1566 case Toolkit::Alignment::HorizontalCenter:
1571 case Toolkit::Alignment::HorizontalRight:
1573 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1574 parentOrigin.x = 1.f;
1575 anchorPoint.x = 1.f;
1580 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1584 switch( mLayoutParameters.mVerticalAlignment )
1586 case Toolkit::Alignment::VerticalTop:
1588 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1589 parentOrigin.y = 0.f;
1590 anchorPoint.y = 0.f;
1593 case Toolkit::Alignment::VerticalCenter:
1598 case Toolkit::Alignment::VerticalBottom:
1600 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1601 parentOrigin.y = 1.f;
1602 anchorPoint.y = 1.f;
1607 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1611 mOffscreenCameraActor.SetX( xPosition );
1612 mOffscreenCameraActor.SetY( yPosition );
1614 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1615 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1618 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1620 // not to process the offscreen root actor by setting its visibility to false.
1621 mOffscreenRootActor.SetVisible( false );
1623 // Sets the new size and the new frame buffer to the image actor.
1624 // Image actor must have same size as text. Otherwise text can be truncated.
1625 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1626 mOffscreenImageActor.SetImage( mFrameBufferImage );
1629 void TextView::DestroyOffscreenRenderingResources()
1633 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1635 if( Stage::IsInstalled() )
1637 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1640 mRenderTask.Reset();
1643 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1644 if( mOffscreenCameraActor )
1646 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1648 mOffscreenCameraActor.Reset();
1651 if( mOffscreenRootActor )
1653 mOffscreenRootActor.Reset();
1656 if( mOffscreenImageActor )
1658 mOffscreenImageActor.Reset();
1661 mCurrentOffscreenSize = Size( 0.f, 0.f );
1663 if( mFrameBufferImage )
1665 mFrameBufferImage.Reset();
1669 void TextView::OnTextPan( Actor actor, PanGesture gesture )
1671 if( 1u == gesture.numberOfTouches )
1673 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1677 void TextView::TrimScrollPosition()
1679 const Vector3& textViewSize = GetControlSize();
1681 // Before use the text's size, relayout the text is needed to get the actual text size.
1682 GetTextLayoutInfo();
1684 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1685 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1686 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1687 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1688 float minVerticalDisplacement = -maxVerticalDisplacement;
1690 // Updates the range if the text is aligned on the right or left.
1691 switch( mLayoutParameters.mHorizontalAlignment )
1693 case Toolkit::Alignment::HorizontalLeft:
1695 maxHorizontalDisplacement *= 2.f;
1696 minHorizontalDisplacement = 0.f;
1699 case Toolkit::Alignment::HorizontalCenter:
1704 case Toolkit::Alignment::HorizontalRight:
1706 maxHorizontalDisplacement = 0.f;
1707 minHorizontalDisplacement *= 2.f;
1712 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1716 // Updates the range if the text is aligned on the top or bottom.
1717 switch( mLayoutParameters.mVerticalAlignment )
1719 case Toolkit::Alignment::VerticalTop:
1721 maxVerticalDisplacement *= 2.f;
1722 minVerticalDisplacement = 0.f;
1725 case Toolkit::Alignment::VerticalCenter:
1730 case Toolkit::Alignment::VerticalBottom:
1732 maxVerticalDisplacement = 0.f;
1733 minVerticalDisplacement *= 2.f;
1738 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1742 // Trims the scroll position to be within the range.
1743 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1744 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1746 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1747 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1750 void TextView::DoSetScrollPosition( const Vector2& position )
1752 // Stores old scroll position.
1753 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1755 // Updates the scroll position
1756 mVisualParameters.mCameraScrollPosition = position;
1758 // Ensures the text-view is covered with text.
1759 TrimScrollPosition();
1761 // Calculate the difference with the previous scroll position
1762 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1763 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1765 if( mOffscreenRootActor )
1767 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1769 mOffscreenRootActor.SetVisible( true );
1772 if( mOffscreenCameraActor )
1774 // Update the offscreen camera with the new scroll position.
1775 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1776 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1781 // Refresh the render-task.
1782 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1786 Toolkit::TextView handle( GetOwner() );
1787 mScrolledSignalV2.Emit( handle, delta );
1790 void TextView::CombineExceedPolicies()
1792 // Calculates the combination of exceed policies.
1794 switch( mLayoutParameters.mWidthExceedPolicy )
1796 case Toolkit::TextView::Original:
1798 switch( mLayoutParameters.mHeightExceedPolicy )
1800 case Toolkit::TextView::Original:
1802 mLayoutParameters.mExceedPolicy = Original;
1805 case Toolkit::TextView::Fade:
1807 mLayoutParameters.mExceedPolicy = OriginalFade;
1810 case Toolkit::TextView::ShrinkToFit:
1812 mLayoutParameters.mExceedPolicy = OriginalShrink;
1817 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1822 case Toolkit::TextView::Split:
1824 switch( mLayoutParameters.mHeightExceedPolicy )
1826 case Toolkit::TextView::Original:
1828 mLayoutParameters.mExceedPolicy = SplitOriginal;
1831 case Toolkit::TextView::Fade:
1833 mLayoutParameters.mExceedPolicy = SplitFade;
1836 case Toolkit::TextView::ShrinkToFit:
1838 mLayoutParameters.mExceedPolicy = SplitShrink;
1841 case Toolkit::TextView::EllipsizeEnd:
1843 mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd;
1848 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1853 case Toolkit::TextView::Fade:
1855 switch( mLayoutParameters.mHeightExceedPolicy )
1857 case Toolkit::TextView::Original:
1859 mLayoutParameters.mExceedPolicy = FadeOriginal;
1862 case Toolkit::TextView::Fade:
1864 mLayoutParameters.mExceedPolicy = Fade;
1869 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1874 case Toolkit::TextView::ShrinkToFit:
1876 switch( mLayoutParameters.mHeightExceedPolicy )
1878 case Toolkit::TextView::Original:
1880 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1883 case Toolkit::TextView::Fade:
1885 mLayoutParameters.mExceedPolicy = ShrinkFade;
1888 case Toolkit::TextView::ShrinkToFit:
1890 mLayoutParameters.mExceedPolicy = Shrink;
1895 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1900 case Toolkit::TextView::EllipsizeEnd:
1902 switch( mLayoutParameters.mHeightExceedPolicy )
1904 case Toolkit::TextView::Original:
1906 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1909 case Toolkit::TextView::EllipsizeEnd:
1911 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1916 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1923 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1928 Actor TextView::GetRootActor() const
1930 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1934 if( mVisualParameters.mSnapshotModeEnabled )
1936 rootActor = mOffscreenRootActor;
1946 void TextView::CreateEllipsizeLayout()
1948 // Creates the ellipsis layout info for the ellipsis text and styles.
1949 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1950 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
1951 TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
1952 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
1953 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1956 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
1958 bool newValue( propertyValue.Get<bool>() );
1959 if( newValue != IsMarkupProcessingEnabled() )
1961 SetMarkupProcessingEnabled( newValue );
1964 // If markup processing has been enabled, Ensure current text is reprocessed.
1965 const std::string& currentText( GetText() );
1966 if( ! currentText.empty() )
1968 SetText( currentText );
1974 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1976 std::string policyName( propertyValue.Get<std::string>() );
1977 if(policyName == "SplitByNewLineChar")
1979 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1981 else if(policyName == "SplitByWord")
1983 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1985 else if(policyName == "SplitByChar")
1987 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
1991 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
1995 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
1997 std::string policyName( propertyValue.Get<std::string>() );
1998 if(policyName == "Original")
2000 SetWidthExceedPolicy(Toolkit::TextView::Original);
2002 else if(policyName == "Fade")
2004 SetWidthExceedPolicy(Toolkit::TextView::Fade);
2006 else if(policyName == "Split")
2008 SetWidthExceedPolicy(Toolkit::TextView::Split);
2010 else if(policyName == "ShrinkToFit")
2012 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
2014 else if(policyName == "EllipsizeEnd")
2016 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
2020 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
2024 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
2026 std::string policyName( propertyValue.Get<std::string>() );
2027 if(policyName == "Original")
2029 SetHeightExceedPolicy(Toolkit::TextView::Original);
2031 else if(policyName == "Fade")
2033 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2035 else if(policyName == "Split")
2037 SetHeightExceedPolicy(Toolkit::TextView::Split);
2039 else if(policyName == "ShrinkToFit")
2041 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2045 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2049 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2051 std::string policyName( propertyValue.Get<std::string>() );
2052 if(policyName == "Left")
2054 SetLineJustification(Toolkit::TextView::Left);
2056 else if(policyName == "Center")
2058 SetLineJustification(Toolkit::TextView::Center);
2060 else if(policyName == "Right")
2062 SetLineJustification(Toolkit::TextView::Right);
2064 else if(policyName == "Justified")
2066 SetLineJustification(Toolkit::TextView::Justified);
2070 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2074 void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue )
2076 Vector4 value( propertyValue.Get<Vector4>() );
2077 DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f )
2078 && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " );
2080 Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast<unsigned int>( value.x ) ),
2081 PixelSize( static_cast<unsigned int>( value.y ) ),
2082 PixelSize( static_cast<unsigned int>( value.z ) ),
2083 PixelSize( static_cast<unsigned int>( value.w ) ) );
2085 SetFadeBoundary( fadeBoundary );
2088 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2090 std::string value( propertyValue.Get<std::string>() );
2092 if( propertyIndex == Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT )
2094 if(value == "HorizontalLeft")
2096 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2098 else if( value == "HorizontalCenter")
2100 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2102 else if( value == "HorizontalRight")
2104 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2108 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2111 else if( propertyIndex == Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT )
2113 if( value == "VerticalTop" )
2115 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2117 else if( value == "VerticalCenter")
2119 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2121 else if( value == "VerticalBottom")
2123 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2127 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2133 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
2134 if( RELAYOUT_ALL != mRelayoutOperations )
2136 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
2137 RELAYOUT_TEXT_ACTOR_UPDATE |
2138 RELAYOUT_ALIGNMENT |
2139 RELAYOUT_VISIBILITY );
2143 std::string TextView::OnHorizontalAlignmentPropertyGet()
2145 if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft )
2147 return "HorizontalLeft";
2149 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter )
2151 return "HorizontalCenter";
2153 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight )
2155 return "HorizontalRight";
2159 DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." );
2163 std::string TextView::OnVerticalAlignmentPropertyGet()
2165 if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop )
2167 return "VerticalTop";
2169 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter )
2171 return "VerticalCenter";
2173 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom )
2175 return "VerticalBottom";
2179 DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." );
2183 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2185 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2189 TextView& textViewImpl( GetImpl( textView ) );
2192 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2194 textViewImpl.OnMarkupEnabledPeopertySet( value );
2197 case Toolkit::TextView::PROPERTY_TEXT:
2199 textViewImpl.SetText( value.Get<std::string>() );
2202 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2204 textViewImpl.OnMultilinePolicyPropertySet( value );
2207 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2209 textViewImpl.OnWidthExceedPolicyPropertySet( value );
2212 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2214 textViewImpl.OnHeightExceedPolicyPropertySet( value );
2217 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2219 textViewImpl.OnLineJustificationPropertySet( value );
2222 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2224 textViewImpl.OnFadeBoundaryPropertySet( value );
2227 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2229 Dali::PointSize pointSize( value.Get<float>() );
2230 textViewImpl.SetLineHeightOffset(pointSize);
2233 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2234 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2236 textViewImpl.OnAlignmentPropertySet( index, value );
2243 Property::Value TextView::GetProperty( BaseObject* object, Property::Index index )
2245 Property::Value value;
2247 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2251 TextView& textViewImpl( GetImpl( textView ) );
2254 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2256 value = textViewImpl.IsMarkupProcessingEnabled();
2259 case Toolkit::TextView::PROPERTY_TEXT:
2261 value = textViewImpl.GetText();
2264 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2266 value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ];
2269 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2271 value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ];
2274 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2276 value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ];
2279 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2281 value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ];
2284 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2286 Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary();
2287 value = Vector4( static_cast<float>( boundary.mLeft.value ),
2288 static_cast<float>( boundary.mRight.value ),
2289 static_cast<float>( boundary.mTop.value ),
2290 static_cast<float>( boundary.mBottom.value ) );
2293 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2295 value = textViewImpl.GetLineHeightOffset().value;
2298 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2300 value = textViewImpl.OnHorizontalAlignmentPropertyGet();
2303 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2305 value = textViewImpl.OnVerticalAlignmentPropertyGet();
2313 } // namespace Internal
2315 } // namespace Toolkit