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/public-api/common/stage.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/render-tasks/render-task-list.h>
27 #include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
28 #include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
29 #include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
30 #include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
31 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
32 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
33 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
41 const Property::Index TextView::PROPERTY_MARKUP_ENABLED( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX );
42 const Property::Index TextView::PROPERTY_TEXT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 1 );
43 const Property::Index TextView::PROPERTY_MULTILINE_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 2 );
44 const Property::Index TextView::PROPERTY_WIDTH_EXCEED_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 3 );
45 const Property::Index TextView::PROPERTY_HEIGHT_EXCEED_POLICY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 4 );
46 const Property::Index TextView::PROPERTY_LINE_JUSTIFICATION( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 5 );
47 const Property::Index TextView::PROPERTY_FADE_BOUNDARY( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 6 );
48 const Property::Index TextView::PROPERTY_LINE_HEIGHT_OFFSET( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 7 );
49 const Property::Index TextView::PROPERTY_HORIZONTAL_ALIGNMENT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 8 );
50 const Property::Index TextView::PROPERTY_VERTICAL_ALIGNMENT( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX + 9 );
58 const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"};
59 const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"};
60 const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"};
62 // Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
63 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
68 return Toolkit::TextView::New();
71 TypeRegistration typeRegistration( typeid(Toolkit::TextView), typeid(Toolkit::Control), Create );
73 SignalConnectorType signalConnector1( typeRegistration, Toolkit::TextView::SIGNAL_TEXT_SCROLLED , &TextView::DoConnectSignal );
75 PropertyRegistration property1( typeRegistration, "markup-enabled", Toolkit::TextView::PROPERTY_MARKUP_ENABLED, Property::BOOLEAN, &TextView::SetProperty, &TextView::GetProperty );
76 PropertyRegistration property2( typeRegistration, "text", Toolkit::TextView::PROPERTY_TEXT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
77 PropertyRegistration property3( typeRegistration, "multiline-policy", Toolkit::TextView::PROPERTY_MULTILINE_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
78 PropertyRegistration property4( typeRegistration, "width-exceed-policy", Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
79 PropertyRegistration property5( typeRegistration, "height-exceed-policy", Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
80 PropertyRegistration property6( typeRegistration, "line-justification", Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
81 PropertyRegistration property7( typeRegistration, "fade-boundary", Toolkit::TextView::PROPERTY_FADE_BOUNDARY, Property::VECTOR4, &TextView::SetProperty, &TextView::GetProperty );
82 PropertyRegistration property8( typeRegistration, "line-height-offset", Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET, Property::FLOAT, &TextView::SetProperty, &TextView::GetProperty );
83 PropertyRegistration property9( typeRegistration, "horizontal-alignment", Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
84 PropertyRegistration property10( typeRegistration, "vertical-alignment", Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
87 * Whether the text-view-processor operation sets, inserts, replaces, removes text.
89 * @param[in] metadata The text-view-processor operation.
91 * @return \e true if the given text-view-processor operation is modifying the text.
93 bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata )
95 return ( ( metadata.mType == TextView::TextSet ) ||
96 ( metadata.mType == TextView::TextInserted ) ||
97 ( metadata.mType == TextView::TextReplaced ) ||
98 ( metadata.mType == TextView::TextRemoved ) ||
99 ( metadata.mType == TextView::NewStyle ));
103 * Whether the text-view-processor operation sets a new line height offset.
105 * @param[in] metadata The text-view-processor operation.
107 * @return \e true if the given text-view-processor operation sets a new line height offset.
109 bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata )
111 return ( metadata.mType == TextView::NewLineHeight );
115 * Whether the text-view-processor operation sets a new style.
117 * @param[in] metadata The text-view-processor operation.
119 * @return \e true if the given text-view-processor operation sets a new style.
121 bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata )
123 return ( metadata.mType == TextView::NewStyle );
128 TextView::TextViewProcessorMetadata::TextViewProcessorMetadata()
129 : mType( TextView::TextSet ),
131 mNumberOfCharacters( 0u ),
136 Toolkit::TextView TextView::New()
138 // Create the implementation, temporarily owned on stack
139 IntrusivePtr<TextView> textView = new TextView();
141 // Pass ownership to CustomActor
142 Toolkit::TextView handle( *textView );
144 // Second-phase init of the implementation
145 // This can only be done after the CustomActor connection has been made...
146 textView->Initialize();
148 // Disables by default the offscreen rendering.
149 textView->SetSnapshotModeEnabled( false );
154 void TextView::SetText( const std::string& text )
156 // Creates a styled text with the markup or plain string.
157 MarkupProcessor::StyledTextArray styledText;
158 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
160 // Calls SetText() with the styled text array.
161 SetText( styledText );
164 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
166 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
167 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
169 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
170 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
172 // Creates metadata with the Set operation.
173 TextViewProcessorMetadata metadata;
174 metadata.mType = TextView::TextSet;
175 metadata.mText = text;
178 mTextViewProcessorOperations.push_back( metadata );
180 // Updates current styled text.
181 mCurrentStyledText = text;
183 // Request to be relaid out
186 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
187 mRelayoutOperations = RELAYOUT_ALL;
190 void TextView::InsertTextAt( std::size_t position, const std::string& text )
192 // Creates a styled text with the markup or plain string.
193 MarkupProcessor::StyledTextArray styledText;
194 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
196 // Calls InsertTextAt() with the styled text array.
197 InsertTextAt( position, styledText );
200 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
203 MarkupProcessor::GetPlainString( text, textStr );
205 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
206 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
208 // Temporary fix. Creates the whole layout if there is rtl text.
210 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
211 textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
212 SetText( textToSet );
216 // Creates metadata with the Insert operation.
217 TextViewProcessorMetadata metadata;
218 metadata.mType = TextView::TextInserted;
219 metadata.mPosition = position;
220 metadata.mText = text;
223 mTextViewProcessorOperations.push_back( metadata );
225 // Updates current styled text.
226 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
228 // Request to be relaid out
231 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
232 mRelayoutOperations = RELAYOUT_ALL;
236 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
238 // Creates a styled text with the markup or plain string.
239 MarkupProcessor::StyledTextArray styledText;
240 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
242 // Calls ReplaceTextFromTo() with the styled text array.
243 ReplaceTextFromTo( position, numberOfCharacters, styledText );
246 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
249 MarkupProcessor::GetPlainString( text, textStr );
251 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
252 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
254 // Temporary fix. Creates the whole layout if there is rtl text.
256 // Updates current styled text.
257 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
259 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
260 textToSet.erase( it, it + numberOfCharacters );
261 it = textToSet.begin() + position;
262 textToSet.insert( it, text.begin(), text.end() );
264 SetText( textToSet );
268 // Creates metadata with the Insert operation.
269 TextViewProcessorMetadata metadata;
270 metadata.mType = TextView::TextReplaced;
271 metadata.mPosition = position;
272 metadata.mNumberOfCharacters = numberOfCharacters;
273 metadata.mText = text;
276 mTextViewProcessorOperations.push_back( metadata );
278 // Updates current styled text.
279 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
280 mCurrentStyledText.erase( it, it + numberOfCharacters );
281 it = mCurrentStyledText.begin() + position;
282 mCurrentStyledText.insert( it, text.begin(), text.end() );
284 // Request to be relaid out
287 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
288 mRelayoutOperations = RELAYOUT_ALL;
292 void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
294 if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
296 // Temporary fix. Creates the whole layout if there is rtl text.
298 // Updates current styled text.
299 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
300 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
301 textToSet.erase( it, it + numberOfCharacters );
303 SetText( textToSet );
307 // Creates metadata with the Remove operation.
308 TextViewProcessorMetadata metadata;
309 metadata.mType = TextView::TextRemoved;
310 metadata.mPosition = position;
311 metadata.mNumberOfCharacters = numberOfCharacters;
314 mTextViewProcessorOperations.push_back( metadata );
316 // Updates current styled text.
317 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
318 mCurrentStyledText.erase( it, it + numberOfCharacters );
320 // Request to be relaid out
323 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
324 mRelayoutOperations = RELAYOUT_ALL;
328 std::string TextView::GetText() const
330 // Traverses the styled text array getting only the text.
331 // Note that for some languages a 'character' could be represented by more than one 'char'
334 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
336 text.append( (*it).mText.GetText() );
342 void TextView::SetLineHeightOffset( PointSize offset )
344 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
346 // Removes any previous operation which modifies the line height offset.
347 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
348 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
350 // Creates metadata with the new line height operation.
351 TextViewProcessorMetadata metadata;
352 metadata.mType = TextView::NewLineHeight;
354 mTextViewProcessorOperations.push_back( metadata );
356 // Updates line height offset.
357 mLayoutParameters.mLineHeightOffset = offset;
361 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
362 if( RELAYOUT_ALL != mRelayoutOperations )
364 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
365 RELAYOUT_REMOVE_TEXT_ACTORS |
366 RELAYOUT_SIZE_POSITION |
368 RELAYOUT_VISIBILITY |
369 RELAYOUT_TEXT_ACTOR_UPDATE |
370 RELAYOUT_INSERT_TO_TEXT_VIEW );
375 PointSize TextView::GetLineHeightOffset() const
377 return PointSize( mLayoutParameters.mLineHeightOffset );
380 void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask )
382 if( !mCurrentStyledText.empty() )
384 const bool checkFontName = mask & TextStyle::FONT;
385 const bool checkFontSize = mask & TextStyle::SIZE;
386 const bool checkFontStyle = mask & TextStyle::STYLE;
388 // Check first if metrics have changed.
389 bool metricsChanged = false;
390 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
392 const MarkupProcessor::StyledText& styledText( *it );
394 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
395 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
396 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
401 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
403 // If metrics change, new text measurements are needed.
404 SetText( mCurrentStyledText );
408 // Deletes any previous operation which sets a new style.
409 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
410 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
412 // Creates metadata with the new style operation.
413 TextViewProcessorMetadata metadata;
414 metadata.mType = TextView::NewStyle;
416 MarkupProcessor::StyledText text;
418 metadata.mText.push_back( text );
419 metadata.mStyleMask = mask;
421 mTextViewProcessorOperations.push_back( metadata );
423 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
427 if( RELAYOUT_ALL != mRelayoutOperations )
429 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
430 RELAYOUT_TEXT_ACTOR_UPDATE );
435 // Sets the new style to the ellipsize text
436 // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
437 if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
439 for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
440 endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
444 (*it)->Copy( style, mask );
447 SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
451 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
453 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
455 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
456 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
457 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
458 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
459 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
460 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
462 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
463 mLayoutParameters.mVerticalAlignment = verticalAlignment;
467 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
468 if( RELAYOUT_ALL != mRelayoutOperations )
470 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
471 RELAYOUT_TEXT_ACTOR_UPDATE |
473 RELAYOUT_VISIBILITY );
478 Toolkit::Alignment::Type TextView::GetTextAlignment() const
480 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
483 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
485 if( policy != mLayoutParameters.mMultilinePolicy )
487 mLayoutParameters.mMultilinePolicy = policy;
489 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
490 mRelayoutOperations = RELAYOUT_ALL;
496 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
498 return mLayoutParameters.mMultilinePolicy;
501 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
503 // The layout info could be invalid depending on the current exceed policy and the new one.
504 // i.e. if the current policy is Split and the new one is ShrinkToFit then
505 // the layout info generated for each char is not needed.
506 if( policy != mLayoutParameters.mWidthExceedPolicy )
508 mLayoutParameters.mWidthExceedPolicy = policy;
510 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
511 mRelayoutOperations = RELAYOUT_ALL;
517 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
519 return mLayoutParameters.mWidthExceedPolicy;
522 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
524 if( policy != mLayoutParameters.mHeightExceedPolicy )
526 mLayoutParameters.mHeightExceedPolicy = policy;
530 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
531 if( RELAYOUT_ALL != mRelayoutOperations )
533 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
534 RELAYOUT_REMOVE_TEXT_ACTORS |
535 RELAYOUT_SIZE_POSITION |
537 RELAYOUT_VISIBILITY |
538 RELAYOUT_TEXT_ACTOR_UPDATE |
539 RELAYOUT_INSERT_TO_TEXT_VIEW );
544 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
546 return mLayoutParameters.mHeightExceedPolicy;
549 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
551 if( justification != mLayoutParameters.mLineJustification )
553 mLayoutParameters.mLineJustification = justification;
557 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
558 if( RELAYOUT_ALL != mRelayoutOperations )
560 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
561 RELAYOUT_REMOVE_TEXT_ACTORS |
562 RELAYOUT_SIZE_POSITION |
564 RELAYOUT_VISIBILITY |
565 RELAYOUT_TEXT_ACTOR_UPDATE |
566 RELAYOUT_INSERT_TO_TEXT_VIEW );
571 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
573 return mLayoutParameters.mLineJustification;
576 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
578 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
579 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
580 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
581 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
583 mVisualParameters.mFadeBoundary = fadeBoundary;
587 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
588 if( RELAYOUT_ALL != mRelayoutOperations )
590 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
591 RELAYOUT_REMOVE_TEXT_ACTORS |
592 RELAYOUT_VISIBILITY |
593 RELAYOUT_TEXT_ACTOR_UPDATE |
594 RELAYOUT_INSERT_TO_TEXT_VIEW );
599 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
601 return mVisualParameters.mFadeBoundary;
604 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
606 // Creates a styled text with the markup or plain string.
607 MarkupProcessor::StyledTextArray styledText;
608 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
610 // Creates the ellipsis layout info and sets the text and styles.
611 SetEllipsizeText( styledText );
614 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
616 // Converts the styled text array into a Text and a vector of TextStyles.
618 Vector<TextStyle*> styles;
619 for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
621 const MarkupProcessor::StyledText& styledText( *it );
623 text.Append( styledText.mText );
624 styles.PushBack( new TextStyle( styledText.mStyle ) );
627 // Creates the ellipsis layout info and sets the text and styles.
628 SetEllipsizeText( text, styles );
631 void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
633 // Sets the text and styles for the ellipsis text.
634 mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
635 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
637 // Creates the ellipsis layout info.
638 CreateEllipsizeLayout();
640 // Request to be relaid out
643 mRelayoutOperations = RELAYOUT_ALL;
646 std::string TextView::GetEllipsizeText() const
648 return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
651 void TextView::GetTextLayoutInfo()
653 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
654 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
655 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
657 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
659 Vector3 textViewSize = GetControlSize();
661 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
662 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
663 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
664 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
665 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
667 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
668 // the text natural size can be used.
669 textViewSize = GetNaturalSize();
672 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
673 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
675 // Check if the text-view has glyph-actors.
676 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
678 RelayoutOperationMask mask = NO_RELAYOUT;
679 if( relayoutSizeAndPositionNeeded )
681 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
683 if( relayoutAlignmentNeeded )
685 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
687 if( relayoutVisibilityNeeded )
689 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
694 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
695 // add them to the text-actor cache.
696 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
697 mRelayoutData.mGlyphActors.clear();
700 // Relays-out but doesn't add glyph-actors to the text-view.
701 DoRelayOut( textViewSize.GetVectorXY(), mask );
705 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
711 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
715 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
716 textLayoutInfo.mLines = mRelayoutData.mLines;
718 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
719 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
721 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
723 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
726 void TextView::SetSortModifier( float depthOffset )
728 mVisualParameters.mSortModifier = depthOffset;
730 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
734 ( *it ).SetSortModifier( depthOffset );
737 if( mOffscreenImageActor )
739 mOffscreenImageActor.SetSortModifier( depthOffset );
743 void TextView::SetSnapshotModeEnabled( bool enable )
745 if( enable != mVisualParameters.mSnapshotModeEnabled )
747 // Remove first all glyph-actors
748 if( !mRelayoutData.mGlyphActors.empty() )
750 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
753 mVisualParameters.mSnapshotModeEnabled = enable;
754 if( !mLockPreviousSnapshotMode )
756 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
757 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
759 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
760 // to smash the stored value.
761 mPreviousSnapshotModeEnabled = enable;
764 if( mVisualParameters.mSnapshotModeEnabled )
766 // Create a root actor and an image actor for offscreen rendering.
767 mOffscreenRootActor = Layer::New();
768 mOffscreenImageActor = ImageActor::New();
770 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
771 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
772 mOffscreenRootActor.SetInheritRotation( false );
773 mOffscreenRootActor.SetInheritScale( false );
774 mOffscreenRootActor.SetDepthTestDisabled( true );
776 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
778 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
779 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
780 mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
781 BlendingFactor::ONE, BlendingFactor::ONE );
784 self.Add( mOffscreenRootActor );
785 self.Add( mOffscreenImageActor );
786 mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) );
792 if( mOffscreenRootActor )
794 self.Remove( mOffscreenRootActor );
797 if( mOffscreenImageActor )
799 self.Remove( mOffscreenImageActor );
802 DestroyOffscreenRenderingResources();
805 if( RELAYOUT_ALL != mRelayoutOperations )
807 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
808 RELAYOUT_REMOVE_TEXT_ACTORS |
809 RELAYOUT_TEXT_ACTOR_UPDATE |
810 RELAYOUT_INSERT_TO_TEXT_VIEW );
816 bool TextView::IsSnapshotModeEnabled() const
818 return mVisualParameters.mSnapshotModeEnabled;
821 void TextView::SetMarkupProcessingEnabled( bool enable )
823 mMarkUpEnabled = enable;
826 bool TextView::IsMarkupProcessingEnabled() const
828 return mMarkUpEnabled;
831 void TextView::SetScrollEnabled( bool enable )
833 if( enable != mVisualParameters.mScrollEnabled )
835 mVisualParameters.mScrollEnabled = enable;
837 if( mVisualParameters.mScrollEnabled )
839 // Offscreen rendering is needed to enable text scroll.
841 // Stores previous value of the snapshot mode.
842 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
845 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
846 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
847 Lock lock( mLockPreviousSnapshotMode );
848 SetSnapshotModeEnabled( true );
851 // Creates the pan gesture detector and attach the text-view.
852 mPanGestureDetector = PanGestureDetector::New();
853 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
854 mPanGestureDetector.Attach( Self() );
858 // Removes the pan gesture detector.
859 if( mPanGestureDetector )
861 mPanGestureDetector.Detach( Self() );
862 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
863 mPanGestureDetector.Reset();
866 // Restores the previous state for snapshot mode.
867 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
872 bool TextView::IsScrollEnabled() const
874 return mVisualParameters.mScrollEnabled;
877 void TextView::SetScrollPosition( const Vector2& position )
879 if( position != mVisualParameters.mCameraScrollPosition )
881 // Guard against destruction during signal emission
882 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
883 Toolkit::TextView handle( GetOwner() );
885 DoSetScrollPosition( position );
887 // Check if the new scroll position has been trimmed.
888 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
892 const Vector2& TextView::GetScrollPosition() const
894 return mVisualParameters.mCameraScrollPosition;
897 bool TextView::IsScrollPositionTrimmed() const
899 return mVisualParameters.mScrollPositionTrimmed;
902 Toolkit::TextView::ScrolledSignalV2& TextView::ScrolledSignal()
904 return mScrolledSignalV2;
907 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
909 Dali::BaseHandle handle( object );
911 bool connected( true );
912 Toolkit::TextView textView = Toolkit::TextView::DownCast(handle);
914 if( Dali::Toolkit::TextView::SIGNAL_TEXT_SCROLLED == signalName )
916 textView.ScrolledSignal().Connect( tracker, functor );
920 // signalName does not match any signal
927 TextView::LayoutParameters::LayoutParameters()
928 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
929 mWidthExceedPolicy( Toolkit::TextView::Original ),
930 mHeightExceedPolicy( Toolkit::TextView::Original ),
931 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
932 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
933 mLineJustification( Toolkit::TextView::Left ),
934 mLineHeightOffset( 0.f ),
935 mMarkUpEnabled( false )
939 TextView::LayoutParameters::~LayoutParameters()
943 TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy,
944 Toolkit::TextView::ExceedPolicy widthExceedPolicy,
945 Toolkit::TextView::ExceedPolicy heightExceedPolicy,
946 Toolkit::Alignment::Type alignmentType,
947 Toolkit::TextView::LineJustification lineJustification,
948 float lineHeightOffset,
950 : mMultilinePolicy( multilinePolicy ),
951 mWidthExceedPolicy( widthExceedPolicy ),
952 mHeightExceedPolicy( heightExceedPolicy ),
953 mHorizontalAlignment(),
954 mVerticalAlignment(),
955 mLineJustification( lineJustification ),
956 mLineHeightOffset( lineHeightOffset ),
957 mMarkUpEnabled( markUpEnabled )
960 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
961 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
962 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
963 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
964 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
965 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
967 mHorizontalAlignment = horizontalAlignment;
968 mVerticalAlignment = verticalAlignment;
971 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
972 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
973 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
974 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
975 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
976 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
977 mLineJustification( layoutParameters.mLineJustification ),
978 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
979 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
983 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
985 mMultilinePolicy = layoutParameters.mMultilinePolicy;
986 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
987 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
988 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
989 mVerticalAlignment = layoutParameters.mVerticalAlignment;
990 mLineJustification = layoutParameters.mLineJustification;
991 mLineHeightOffset = layoutParameters.mLineHeightOffset;
992 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
997 TextView::VisualParameters::VisualParameters()
999 mSortModifier( 0.f ),
1000 mCameraScrollPosition( 0.f, 0.f ),
1001 mSnapshotModeEnabled( false ),
1002 mScrollEnabled( false ),
1003 mScrollPositionTrimmed( false )
1007 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
1008 : mFadeBoundary( visualParameters.mFadeBoundary ),
1009 mSortModifier( visualParameters.mSortModifier ),
1010 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
1011 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
1012 mScrollEnabled( visualParameters.mScrollEnabled ),
1013 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
1017 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters )
1019 mFadeBoundary = visualParameters.mFadeBoundary;
1020 mSortModifier = visualParameters.mSortModifier;
1021 mCameraScrollPosition = visualParameters.mCameraScrollPosition;
1022 mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled;
1023 mScrollEnabled = visualParameters.mScrollEnabled;
1024 mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed;
1029 TextView::RelayoutData::RelayoutData()
1031 mShrinkFactor( 1.f ),
1033 mCharacterLogicalToVisualMap(),
1034 mCharacterVisualToLogicalMap(),
1036 mCharacterLayoutInfoTable(),
1038 mTextSizeForRelayoutOption()
1042 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
1043 : mTextViewSize( relayoutData.mTextViewSize ),
1044 mShrinkFactor( relayoutData.mShrinkFactor ),
1045 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
1046 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
1047 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
1048 mGlyphActors( relayoutData.mGlyphActors ),
1049 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
1050 mLines( relayoutData.mLines ),
1051 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
1055 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
1057 mTextViewSize = relayoutData.mTextViewSize;
1058 mShrinkFactor = relayoutData.mShrinkFactor;
1059 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
1060 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
1061 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
1062 mGlyphActors = relayoutData.mGlyphActors;
1063 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
1064 mLines = relayoutData.mLines;
1065 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1070 TextView::TextView()
1071 : Control( REQUIRES_STYLE_CHANGE_SIGNALS ),
1072 mCurrentStyledText(),
1073 mTextViewProcessorOperations(),
1074 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1075 Toolkit::TextView::Original,
1076 Toolkit::TextView::Original,
1077 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1078 Toolkit::TextView::Left,
1081 mVisualParameters(),
1083 mRelayoutOperations( NO_RELAYOUT ),
1084 mOffscreenRootActor(),
1085 mOffscreenImageActor(),
1086 mOffscreenCameraActor(),
1087 mCurrentOffscreenSize(),
1088 mFrameBufferImage(),
1090 mPanGestureDetector(),
1091 mLockPreviousSnapshotMode( false ),
1092 mPreviousSnapshotModeEnabled( false ),
1093 mMarkUpEnabled( false )
1095 // Creates the ellipsis layout info.
1096 CreateEllipsizeLayout();
1099 TextView::~TextView()
1101 // Destroys offscreen rendering resources.
1102 DestroyOffscreenRenderingResources();
1104 // Destroys scroll pan gesture detector.
1105 if( mPanGestureDetector )
1107 mPanGestureDetector.Reset();
1111 Vector3 TextView::GetNaturalSize()
1113 if( !mTextViewProcessorOperations.empty() )
1115 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1117 if( !mRelayoutData.mGlyphActors.empty() )
1119 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1120 // add them to the text-actor cache.
1121 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1122 mRelayoutData.mGlyphActors.clear();
1124 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1127 PerformTextViewProcessorOperations();
1130 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1133 float TextView::GetHeightForWidth( float width )
1137 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1138 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1139 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1141 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1142 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1143 height = GetNaturalSize().height;
1147 // Check if the given width is different than the current one.
1148 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1150 // Check if the text-view has glyph-actors.
1151 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1153 // Check which layout operations need to be done.
1154 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1156 if( relayoutSizeAndPositionNeeded )
1158 if( hasGlyphActors )
1160 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1161 // add them to the text-actor cache.
1162 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1163 mRelayoutData.mGlyphActors.clear();
1166 // Use the given width.
1167 const Vector2 textViewSize( width, GetControlSize().height );
1169 // Relays-out but doesn't add glyph-actors to the text-view.
1170 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1173 // Retrieve the text height after relayout the text.
1174 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1176 if( differentWidth )
1178 // Revert the relayout operation mask
1179 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1182 if( hasGlyphActors )
1184 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1187 if( differentWidth || hasGlyphActors )
1196 float TextView::GetWidthForHeight( float height )
1198 // TODO: Needs implementing properly, for now just return the natural width.
1199 return GetNaturalSize().width;
1203 void TextView::OnInitialize()
1208 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1210 // Creates the ellipsis layout info.
1211 CreateEllipsizeLayout();
1213 SetText( mCurrentStyledText );
1216 void TextView::OnControlSizeSet( const Vector3& size )
1218 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1220 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1221 mRelayoutOperations = RELAYOUT_ALL;
1223 // Request to be relaid out
1228 void TextView::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1230 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1232 // Not worth to relayout if width or height is equal to zero.
1236 if( size != mRelayoutData.mTextViewSize )
1238 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1239 if( RELAYOUT_ALL != mRelayoutOperations )
1241 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1242 RELAYOUT_REMOVE_TEXT_ACTORS |
1243 RELAYOUT_SIZE_POSITION |
1244 RELAYOUT_ALIGNMENT |
1245 RELAYOUT_VISIBILITY |
1246 RELAYOUT_TEXT_ACTOR_UPDATE |
1247 RELAYOUT_INSERT_TO_TEXT_VIEW );
1251 if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
1252 ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
1254 if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
1256 // If the text of the alignment changes and a fade exceed policy is set,
1257 // some characters may need new TextActor.
1258 mRelayoutOperations = RELAYOUT_ALL;
1262 // Remove glyph-actors from text-view
1263 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1265 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1266 mRelayoutData.mGlyphActors.clear();
1269 if( NO_RELAYOUT != mRelayoutOperations )
1271 // Relays-out and add glyph-actors to the text-view.
1272 DoRelayOut( size, mRelayoutOperations );
1273 ProcessSnapshot( size );
1276 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1277 mRelayoutData.mTextActorCache.ClearTexts();
1280 void TextView::PerformTextViewProcessorOperations()
1282 // Traverse the relayout operation vector ...
1284 // Optimizes some operations.
1285 OptimizeTextViewProcessorOperations();
1287 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1289 const TextViewProcessorMetadata& relayoutMetadata( *it );
1291 switch( relayoutMetadata.mType )
1293 case TextView::TextSet:
1295 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1300 case TextView::TextInserted:
1302 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1303 relayoutMetadata.mText,
1308 case TextView::TextReplaced:
1310 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1311 relayoutMetadata.mNumberOfCharacters,
1312 relayoutMetadata.mText,
1317 case TextView::TextRemoved:
1319 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1320 relayoutMetadata.mNumberOfCharacters,
1323 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1326 case TextView::NewLineHeight:
1328 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1329 mRelayoutData.mTextLayoutInfo );
1332 case TextView::NewStyle:
1334 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1335 relayoutMetadata.mStyleMask,
1342 // Clear all operations when they are done.
1343 mTextViewProcessorOperations.clear();
1346 void TextView::OptimizeTextViewProcessorOperations()
1348 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1350 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1351 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1352 // use the cache without clearing the text-actors.
1354 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1356 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1358 const TextViewProcessorMetadata& relayoutMetadata( *it );
1360 switch( relayoutMetadata.mType )
1362 case TextView::TextRemoved:
1364 bool optimizationDone = false;
1366 if( it + 1u != endIt )
1368 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) );
1369 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1371 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1373 optimizationDone = true;
1374 TextViewProcessorMetadata newRelayoutMetadata;
1375 newRelayoutMetadata.mType = TextView::TextReplaced;
1376 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1377 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1378 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1379 textViewProcessorOperations.push_back( newRelayoutMetadata );
1381 // do not access the TextInserted operation in next iteration.
1387 if( !optimizationDone )
1389 textViewProcessorOperations.push_back( relayoutMetadata );
1395 textViewProcessorOperations.push_back( relayoutMetadata );
1400 mTextViewProcessorOperations = textViewProcessorOperations;
1403 void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask )
1405 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1406 if( !mTextViewProcessorOperations.empty() )
1408 PerformTextViewProcessorOperations();
1411 CombineExceedPolicies();
1414 if( mVisualParameters.mSnapshotModeEnabled )
1416 rootActor = mOffscreenRootActor;
1423 mRelayoutData.mTextViewSize = textViewSize;
1424 switch( mLayoutParameters.mMultilinePolicy )
1426 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1428 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1430 } // SplitByNewLineChar
1432 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1434 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1438 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1440 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1443 } // switch( mMultilinePolicy )
1445 // Remove done operations from the mask.
1446 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1449 void TextView::ProcessSnapshot( const Size& textViewSize )
1451 if( mVisualParameters.mSnapshotModeEnabled )
1453 // If layout options change, it's needed generate a new image.
1455 if( mOffscreenRootActor )
1457 // Set the root actor visible.
1458 // The root actor is set to non visible after the render task is processed.
1459 mOffscreenRootActor.SetVisible( true );
1461 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1462 mOffscreenRootActor.SetSize( textViewSize );
1465 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1466 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1468 // Set the image actor visible.
1469 // The image actor is set to non visible if there is no text to render.
1470 mOffscreenImageActor.SetVisible( true );
1472 // Calculates the offscreen image's size. It takes into account different points:
1473 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1474 // * There is a maximum texture size the graphic subsystem can load on the memory.
1475 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1477 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1478 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1479 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1480 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1482 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1486 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1487 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1488 offscreenSize.height,
1491 // Stores current text-view size to avoid create new Dali resources if text changes.
1492 mCurrentOffscreenSize = offscreenSize;
1494 if( !mOffscreenCameraActor )
1496 // Creates a new camera actor.
1497 mOffscreenCameraActor = CameraActor::New();
1498 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1499 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1500 mOffscreenCameraActor.SetRotation(Degree(180.f), Vector3::YAXIS);
1502 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1504 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1507 // Calculate camera parameters for current text size.
1508 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1511 if( mVisualParameters.mScrollEnabled )
1513 // Updates the offscreen camera position with the new scroll offset.
1514 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1515 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1519 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1520 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1525 // Creates a new render task.
1526 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1528 mRenderTask.SetSourceActor( mOffscreenRootActor );
1529 mRenderTask.SetInputEnabled( false );
1530 mRenderTask.SetClearColor( Color::TRANSPARENT );
1531 mRenderTask.SetClearEnabled( true );
1532 mRenderTask.SetExclusive( true );
1534 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1535 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1540 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1541 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1544 // Process the render task only once every time the text changes or the text-view's size canges.
1545 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1549 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1550 mOffscreenImageActor.SetVisible( false );
1555 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1557 float xPosition = 0.f;
1558 float yPosition = 0.f;
1559 Vector3 parentOrigin = ParentOrigin::CENTER;
1560 Vector3 anchorPoint = AnchorPoint::CENTER;
1562 switch( mLayoutParameters.mHorizontalAlignment )
1564 case Toolkit::Alignment::HorizontalLeft:
1566 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1567 parentOrigin.x = 0.f;
1568 anchorPoint.x = 0.f;
1571 case Toolkit::Alignment::HorizontalCenter:
1576 case Toolkit::Alignment::HorizontalRight:
1578 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1579 parentOrigin.x = 1.f;
1580 anchorPoint.x = 1.f;
1585 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1589 switch( mLayoutParameters.mVerticalAlignment )
1591 case Toolkit::Alignment::VerticalTop:
1593 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1594 parentOrigin.y = 0.f;
1595 anchorPoint.y = 0.f;
1598 case Toolkit::Alignment::VerticalCenter:
1603 case Toolkit::Alignment::VerticalBottom:
1605 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1606 parentOrigin.y = 1.f;
1607 anchorPoint.y = 1.f;
1612 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1616 mOffscreenCameraActor.SetX( xPosition );
1617 mOffscreenCameraActor.SetY( yPosition );
1619 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1620 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1623 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1625 // not to process the offscreen root actor by setting its visibility to false.
1626 mOffscreenRootActor.SetVisible( false );
1628 // Sets the new size and the new frame buffer to the image actor.
1629 // Image actor must have same size as text. Otherwise text can be truncated.
1630 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1631 mOffscreenImageActor.SetImage( mFrameBufferImage );
1634 void TextView::DestroyOffscreenRenderingResources()
1638 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1640 if( Stage::IsInstalled() )
1642 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1645 mRenderTask.Reset();
1648 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1649 if( mOffscreenCameraActor )
1651 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1653 mOffscreenCameraActor.Reset();
1656 if( mOffscreenRootActor )
1658 mOffscreenRootActor.Reset();
1661 if( mOffscreenImageActor )
1663 mOffscreenImageActor.Reset();
1666 mCurrentOffscreenSize = Size( 0.f, 0.f );
1668 if( mFrameBufferImage )
1670 mFrameBufferImage.Reset();
1674 void TextView::OnTextPan( Actor actor, PanGesture gesture )
1676 if( 1u == gesture.numberOfTouches )
1678 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1682 void TextView::TrimScrollPosition()
1684 const Vector3& textViewSize = GetControlSize();
1686 // Before use the text's size, relayout the text is needed to get the actual text size.
1687 GetTextLayoutInfo();
1689 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1690 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1691 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1692 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1693 float minVerticalDisplacement = -maxVerticalDisplacement;
1695 // Updates the range if the text is aligned on the right or left.
1696 switch( mLayoutParameters.mHorizontalAlignment )
1698 case Toolkit::Alignment::HorizontalLeft:
1700 maxHorizontalDisplacement *= 2.f;
1701 minHorizontalDisplacement = 0.f;
1704 case Toolkit::Alignment::HorizontalCenter:
1709 case Toolkit::Alignment::HorizontalRight:
1711 maxHorizontalDisplacement = 0.f;
1712 minHorizontalDisplacement *= 2.f;
1717 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1721 // Updates the range if the text is aligned on the top or bottom.
1722 switch( mLayoutParameters.mVerticalAlignment )
1724 case Toolkit::Alignment::VerticalTop:
1726 maxVerticalDisplacement *= 2.f;
1727 minVerticalDisplacement = 0.f;
1730 case Toolkit::Alignment::VerticalCenter:
1735 case Toolkit::Alignment::VerticalBottom:
1737 maxVerticalDisplacement = 0.f;
1738 minVerticalDisplacement *= 2.f;
1743 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1747 // Trims the scroll position to be within the range.
1748 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1749 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1751 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1752 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1755 void TextView::DoSetScrollPosition( const Vector2& position )
1757 // Stores old scroll position.
1758 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1760 // Updates the scroll position
1761 mVisualParameters.mCameraScrollPosition = position;
1763 // Ensures the text-view is covered with text.
1764 TrimScrollPosition();
1766 // Calculate the difference with the previous scroll position
1767 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1768 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1770 if( mOffscreenRootActor )
1772 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1774 mOffscreenRootActor.SetVisible( true );
1777 if( mOffscreenCameraActor )
1779 // Update the offscreen camera with the new scroll position.
1780 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1781 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1786 // Refresh the render-task.
1787 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1791 Toolkit::TextView handle( GetOwner() );
1792 mScrolledSignalV2.Emit( handle, delta );
1795 void TextView::CombineExceedPolicies()
1797 // Calculates the combination of exceed policies.
1799 switch( mLayoutParameters.mWidthExceedPolicy )
1801 case Toolkit::TextView::Original:
1803 switch( mLayoutParameters.mHeightExceedPolicy )
1805 case Toolkit::TextView::Original:
1807 mLayoutParameters.mExceedPolicy = Original;
1810 case Toolkit::TextView::Fade:
1812 mLayoutParameters.mExceedPolicy = OriginalFade;
1815 case Toolkit::TextView::ShrinkToFit:
1817 mLayoutParameters.mExceedPolicy = OriginalShrink;
1822 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1827 case Toolkit::TextView::Split:
1829 switch( mLayoutParameters.mHeightExceedPolicy )
1831 case Toolkit::TextView::Original:
1833 mLayoutParameters.mExceedPolicy = SplitOriginal;
1836 case Toolkit::TextView::Fade:
1838 mLayoutParameters.mExceedPolicy = SplitFade;
1841 case Toolkit::TextView::ShrinkToFit:
1843 mLayoutParameters.mExceedPolicy = SplitShrink;
1846 case Toolkit::TextView::EllipsizeEnd:
1848 mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd;
1853 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1858 case Toolkit::TextView::Fade:
1860 switch( mLayoutParameters.mHeightExceedPolicy )
1862 case Toolkit::TextView::Original:
1864 mLayoutParameters.mExceedPolicy = FadeOriginal;
1867 case Toolkit::TextView::Fade:
1869 mLayoutParameters.mExceedPolicy = Fade;
1874 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1879 case Toolkit::TextView::ShrinkToFit:
1881 switch( mLayoutParameters.mHeightExceedPolicy )
1883 case Toolkit::TextView::Original:
1885 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1888 case Toolkit::TextView::Fade:
1890 mLayoutParameters.mExceedPolicy = ShrinkFade;
1893 case Toolkit::TextView::ShrinkToFit:
1895 mLayoutParameters.mExceedPolicy = Shrink;
1900 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1905 case Toolkit::TextView::EllipsizeEnd:
1907 switch( mLayoutParameters.mHeightExceedPolicy )
1909 case Toolkit::TextView::Original:
1911 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1914 case Toolkit::TextView::EllipsizeEnd:
1916 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1921 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1928 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1933 Actor TextView::GetRootActor() const
1935 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1939 if( mVisualParameters.mSnapshotModeEnabled )
1941 rootActor = mOffscreenRootActor;
1951 void TextView::CreateEllipsizeLayout()
1953 // Creates the ellipsis layout info for the ellipsis text and styles.
1954 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1955 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
1956 TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
1957 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
1958 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1961 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
1963 bool newValue( propertyValue.Get<bool>() );
1964 if( newValue != IsMarkupProcessingEnabled() )
1966 SetMarkupProcessingEnabled( newValue );
1969 // If markup processing has been enabled, Ensure current text is reprocessed.
1970 const std::string& currentText( GetText() );
1971 if( ! currentText.empty() )
1973 SetText( currentText );
1979 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1981 std::string policyName( propertyValue.Get<std::string>() );
1982 if(policyName == "SplitByNewLineChar")
1984 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1986 else if(policyName == "SplitByWord")
1988 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1990 else if(policyName == "SplitByChar")
1992 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
1996 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
2000 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
2002 std::string policyName( propertyValue.Get<std::string>() );
2003 if(policyName == "Original")
2005 SetWidthExceedPolicy(Toolkit::TextView::Original);
2007 else if(policyName == "Fade")
2009 SetWidthExceedPolicy(Toolkit::TextView::Fade);
2011 else if(policyName == "Split")
2013 SetWidthExceedPolicy(Toolkit::TextView::Split);
2015 else if(policyName == "ShrinkToFit")
2017 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
2019 else if(policyName == "EllipsizeEnd")
2021 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
2025 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
2029 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
2031 std::string policyName( propertyValue.Get<std::string>() );
2032 if(policyName == "Original")
2034 SetHeightExceedPolicy(Toolkit::TextView::Original);
2036 else if(policyName == "Fade")
2038 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2040 else if(policyName == "Split")
2042 SetHeightExceedPolicy(Toolkit::TextView::Split);
2044 else if(policyName == "ShrinkToFit")
2046 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2050 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2054 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2056 std::string policyName( propertyValue.Get<std::string>() );
2057 if(policyName == "Left")
2059 SetLineJustification(Toolkit::TextView::Left);
2061 else if(policyName == "Center")
2063 SetLineJustification(Toolkit::TextView::Center);
2065 else if(policyName == "Right")
2067 SetLineJustification(Toolkit::TextView::Right);
2069 else if(policyName == "Justified")
2071 SetLineJustification(Toolkit::TextView::Justified);
2075 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2079 void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue )
2081 Vector4 value( propertyValue.Get<Vector4>() );
2082 DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f )
2083 && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " );
2085 Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast<unsigned int>( value.x ) ),
2086 PixelSize( static_cast<unsigned int>( value.y ) ),
2087 PixelSize( static_cast<unsigned int>( value.z ) ),
2088 PixelSize( static_cast<unsigned int>( value.w ) ) );
2090 SetFadeBoundary( fadeBoundary );
2093 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2095 std::string value( propertyValue.Get<std::string>() );
2097 if( propertyIndex == Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT )
2099 if(value == "HorizontalLeft")
2101 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2103 else if( value == "HorizontalCenter")
2105 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2107 else if( value == "HorizontalRight")
2109 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2113 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2116 else if( propertyIndex == Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT )
2118 if( value == "VerticalTop" )
2120 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2122 else if( value == "VerticalCenter")
2124 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2126 else if( value == "VerticalBottom")
2128 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2132 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2138 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
2139 if( RELAYOUT_ALL != mRelayoutOperations )
2141 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
2142 RELAYOUT_TEXT_ACTOR_UPDATE |
2143 RELAYOUT_ALIGNMENT |
2144 RELAYOUT_VISIBILITY );
2148 std::string TextView::OnHorizontalAlignmentPropertyGet()
2150 if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft )
2152 return "HorizontalLeft";
2154 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter )
2156 return "HorizontalCenter";
2158 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight )
2160 return "HorizontalRight";
2164 DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." );
2168 std::string TextView::OnVerticalAlignmentPropertyGet()
2170 if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop )
2172 return "VerticalTop";
2174 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter )
2176 return "VerticalCenter";
2178 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom )
2180 return "VerticalBottom";
2184 DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." );
2188 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2190 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2194 TextView& textViewImpl( GetImpl( textView ) );
2197 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2199 textViewImpl.OnMarkupEnabledPeopertySet( value );
2202 case Toolkit::TextView::PROPERTY_TEXT:
2204 textViewImpl.SetText( value.Get<std::string>() );
2207 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2209 textViewImpl.OnMultilinePolicyPropertySet( value );
2212 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2214 textViewImpl.OnWidthExceedPolicyPropertySet( value );
2217 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2219 textViewImpl.OnHeightExceedPolicyPropertySet( value );
2222 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2224 textViewImpl.OnLineJustificationPropertySet( value );
2227 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2229 textViewImpl.OnFadeBoundaryPropertySet( value );
2232 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2234 Dali::PointSize pointSize( value.Get<float>() );
2235 textViewImpl.SetLineHeightOffset(pointSize);
2238 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2239 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2241 textViewImpl.OnAlignmentPropertySet( index, value );
2248 Property::Value TextView::GetProperty( BaseObject* object, Property::Index index )
2250 Property::Value value;
2252 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2256 TextView& textViewImpl( GetImpl( textView ) );
2259 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2261 value = textViewImpl.IsMarkupProcessingEnabled();
2264 case Toolkit::TextView::PROPERTY_TEXT:
2266 value = textViewImpl.GetText();
2269 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2271 value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ];
2274 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2276 value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ];
2279 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2281 value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ];
2284 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2286 value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ];
2289 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2291 Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary();
2292 value = Vector4( static_cast<float>( boundary.mLeft.value ),
2293 static_cast<float>( boundary.mRight.value ),
2294 static_cast<float>( boundary.mTop.value ),
2295 static_cast<float>( boundary.mBottom.value ) );
2298 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2300 value = textViewImpl.GetLineHeightOffset().value;
2303 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2305 value = textViewImpl.OnHorizontalAlignmentPropertyGet();
2308 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2310 value = textViewImpl.OnVerticalAlignmentPropertyGet();
2318 } // namespace Internal
2320 } // namespace Toolkit