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 ),
133 mStyleMask(TextStyle::NONE)
137 Toolkit::TextView TextView::New()
139 // Create the implementation, temporarily owned on stack
140 IntrusivePtr<TextView> textView = new TextView();
142 // Pass ownership to CustomActor
143 Toolkit::TextView handle( *textView );
145 // Second-phase init of the implementation
146 // This can only be done after the CustomActor connection has been made...
147 textView->Initialize();
149 // Disables by default the offscreen rendering.
150 textView->SetSnapshotModeEnabled( false );
155 void TextView::SetText( const std::string& text )
157 // Creates a styled text with the markup or plain string.
158 MarkupProcessor::StyledTextArray styledText;
159 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
161 // Calls SetText() with the styled text array.
162 SetText( styledText );
165 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
167 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
168 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
170 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
171 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
173 // Creates metadata with the Set operation.
174 TextViewProcessorMetadata metadata;
175 metadata.mType = TextView::TextSet;
176 metadata.mText = text;
179 mTextViewProcessorOperations.push_back( metadata );
181 // Updates current styled text.
182 mCurrentStyledText = text;
184 // Request to be relaid out
187 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
188 mRelayoutOperations = RELAYOUT_ALL;
191 void TextView::InsertTextAt( std::size_t position, const std::string& text )
193 // Creates a styled text with the markup or plain string.
194 MarkupProcessor::StyledTextArray styledText;
195 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
197 // Calls InsertTextAt() with the styled text array.
198 InsertTextAt( position, styledText );
201 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
204 MarkupProcessor::GetPlainString( text, textStr );
206 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
207 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
209 // Temporary fix. Creates the whole layout if there is rtl text.
211 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
212 textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
213 SetText( textToSet );
217 // Creates metadata with the Insert operation.
218 TextViewProcessorMetadata metadata;
219 metadata.mType = TextView::TextInserted;
220 metadata.mPosition = position;
221 metadata.mText = text;
224 mTextViewProcessorOperations.push_back( metadata );
226 // Updates current styled text.
227 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
229 // Request to be relaid out
232 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
233 mRelayoutOperations = RELAYOUT_ALL;
237 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
239 // Creates a styled text with the markup or plain string.
240 MarkupProcessor::StyledTextArray styledText;
241 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
243 // Calls ReplaceTextFromTo() with the styled text array.
244 ReplaceTextFromTo( position, numberOfCharacters, styledText );
247 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
250 MarkupProcessor::GetPlainString( text, textStr );
252 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
253 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
255 // Temporary fix. Creates the whole layout if there is rtl text.
257 // Updates current styled text.
258 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
260 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
261 textToSet.erase( it, it + numberOfCharacters );
262 it = textToSet.begin() + position;
263 textToSet.insert( it, text.begin(), text.end() );
265 SetText( textToSet );
269 // Creates metadata with the Insert operation.
270 TextViewProcessorMetadata metadata;
271 metadata.mType = TextView::TextReplaced;
272 metadata.mPosition = position;
273 metadata.mNumberOfCharacters = numberOfCharacters;
274 metadata.mText = text;
277 mTextViewProcessorOperations.push_back( metadata );
279 // Updates current styled text.
280 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
281 mCurrentStyledText.erase( it, it + numberOfCharacters );
282 it = mCurrentStyledText.begin() + position;
283 mCurrentStyledText.insert( it, text.begin(), text.end() );
285 // Request to be relaid out
288 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
289 mRelayoutOperations = RELAYOUT_ALL;
293 void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
295 if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
297 // Temporary fix. Creates the whole layout if there is rtl text.
299 // Updates current styled text.
300 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
301 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
302 textToSet.erase( it, it + numberOfCharacters );
304 SetText( textToSet );
308 // Creates metadata with the Remove operation.
309 TextViewProcessorMetadata metadata;
310 metadata.mType = TextView::TextRemoved;
311 metadata.mPosition = position;
312 metadata.mNumberOfCharacters = numberOfCharacters;
315 mTextViewProcessorOperations.push_back( metadata );
317 // Updates current styled text.
318 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
319 mCurrentStyledText.erase( it, it + numberOfCharacters );
321 // Request to be relaid out
324 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
325 mRelayoutOperations = RELAYOUT_ALL;
329 std::string TextView::GetText() const
331 // Traverses the styled text array getting only the text.
332 // Note that for some languages a 'character' could be represented by more than one 'char'
335 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
337 text.append( (*it).mText.GetText() );
343 void TextView::SetLineHeightOffset( PointSize offset )
345 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
347 // Removes any previous operation which modifies the line height offset.
348 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
349 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
351 // Creates metadata with the new line height operation.
352 TextViewProcessorMetadata metadata;
353 metadata.mType = TextView::NewLineHeight;
355 mTextViewProcessorOperations.push_back( metadata );
357 // Updates line height offset.
358 mLayoutParameters.mLineHeightOffset = offset;
362 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
363 if( RELAYOUT_ALL != mRelayoutOperations )
365 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
366 RELAYOUT_REMOVE_TEXT_ACTORS |
367 RELAYOUT_SIZE_POSITION |
369 RELAYOUT_VISIBILITY |
370 RELAYOUT_TEXT_ACTOR_UPDATE |
371 RELAYOUT_INSERT_TO_TEXT_VIEW );
376 PointSize TextView::GetLineHeightOffset() const
378 return PointSize( mLayoutParameters.mLineHeightOffset );
381 void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask )
383 if( !mCurrentStyledText.empty() )
385 const bool checkFontName = mask & TextStyle::FONT;
386 const bool checkFontSize = mask & TextStyle::SIZE;
387 const bool checkFontStyle = mask & TextStyle::STYLE;
389 // Check first if metrics have changed.
390 bool metricsChanged = false;
391 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
393 const MarkupProcessor::StyledText& styledText( *it );
395 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
396 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
397 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
402 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
404 // If metrics change, new text measurements are needed.
405 SetText( mCurrentStyledText );
409 // Deletes any previous operation which sets a new style.
410 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
411 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
413 // Creates metadata with the new style operation.
414 TextViewProcessorMetadata metadata;
415 metadata.mType = TextView::NewStyle;
417 MarkupProcessor::StyledText text;
419 metadata.mText.push_back( text );
420 metadata.mStyleMask = mask;
422 mTextViewProcessorOperations.push_back( metadata );
424 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
428 if( RELAYOUT_ALL != mRelayoutOperations )
430 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
431 RELAYOUT_TEXT_ACTOR_UPDATE );
436 // Sets the new style to the ellipsize text
437 // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
438 if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
440 for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
441 endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
445 (*it)->Copy( style, mask );
448 SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
452 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
454 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
456 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
457 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
458 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
459 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
460 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
461 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
463 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
464 mLayoutParameters.mVerticalAlignment = verticalAlignment;
468 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
469 if( RELAYOUT_ALL != mRelayoutOperations )
471 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
472 RELAYOUT_TEXT_ACTOR_UPDATE |
474 RELAYOUT_VISIBILITY );
479 Toolkit::Alignment::Type TextView::GetTextAlignment() const
481 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
484 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
486 if( policy != mLayoutParameters.mMultilinePolicy )
488 mLayoutParameters.mMultilinePolicy = policy;
490 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
491 mRelayoutOperations = RELAYOUT_ALL;
497 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
499 return mLayoutParameters.mMultilinePolicy;
502 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
504 // The layout info could be invalid depending on the current exceed policy and the new one.
505 // i.e. if the current policy is Split and the new one is ShrinkToFit then
506 // the layout info generated for each char is not needed.
507 if( policy != mLayoutParameters.mWidthExceedPolicy )
509 mLayoutParameters.mWidthExceedPolicy = policy;
511 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
512 mRelayoutOperations = RELAYOUT_ALL;
518 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
520 return mLayoutParameters.mWidthExceedPolicy;
523 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
525 if( policy != mLayoutParameters.mHeightExceedPolicy )
527 mLayoutParameters.mHeightExceedPolicy = policy;
531 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
532 if( RELAYOUT_ALL != mRelayoutOperations )
534 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
535 RELAYOUT_REMOVE_TEXT_ACTORS |
536 RELAYOUT_SIZE_POSITION |
538 RELAYOUT_VISIBILITY |
539 RELAYOUT_TEXT_ACTOR_UPDATE |
540 RELAYOUT_INSERT_TO_TEXT_VIEW );
545 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
547 return mLayoutParameters.mHeightExceedPolicy;
550 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
552 if( justification != mLayoutParameters.mLineJustification )
554 mLayoutParameters.mLineJustification = justification;
558 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
559 if( RELAYOUT_ALL != mRelayoutOperations )
561 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
562 RELAYOUT_REMOVE_TEXT_ACTORS |
563 RELAYOUT_SIZE_POSITION |
565 RELAYOUT_VISIBILITY |
566 RELAYOUT_TEXT_ACTOR_UPDATE |
567 RELAYOUT_INSERT_TO_TEXT_VIEW );
572 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
574 return mLayoutParameters.mLineJustification;
577 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
579 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
580 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
581 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
582 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
584 mVisualParameters.mFadeBoundary = fadeBoundary;
588 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
589 if( RELAYOUT_ALL != mRelayoutOperations )
591 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
592 RELAYOUT_REMOVE_TEXT_ACTORS |
593 RELAYOUT_VISIBILITY |
594 RELAYOUT_TEXT_ACTOR_UPDATE |
595 RELAYOUT_INSERT_TO_TEXT_VIEW );
600 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
602 return mVisualParameters.mFadeBoundary;
605 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
607 // Creates a styled text with the markup or plain string.
608 MarkupProcessor::StyledTextArray styledText;
609 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
611 // Creates the ellipsis layout info and sets the text and styles.
612 SetEllipsizeText( styledText );
615 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
617 // Converts the styled text array into a Text and a vector of TextStyles.
619 Vector<TextStyle*> styles;
620 for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
622 const MarkupProcessor::StyledText& styledText( *it );
624 text.Append( styledText.mText );
625 styles.PushBack( new TextStyle( styledText.mStyle ) );
628 // Creates the ellipsis layout info and sets the text and styles.
629 SetEllipsizeText( text, styles );
632 void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
634 // Sets the text and styles for the ellipsis text.
635 mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
636 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
638 // Creates the ellipsis layout info.
639 CreateEllipsizeLayout();
641 // Request to be relaid out
644 mRelayoutOperations = RELAYOUT_ALL;
647 std::string TextView::GetEllipsizeText() const
649 return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
652 void TextView::GetTextLayoutInfo()
654 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
655 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
656 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
658 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
660 Vector3 textViewSize = GetControlSize();
662 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
663 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
664 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
665 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
666 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
668 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
669 // the text natural size can be used.
670 textViewSize = GetNaturalSize();
673 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
674 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
676 // Check if the text-view has glyph-actors.
677 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
679 RelayoutOperationMask mask = NO_RELAYOUT;
680 if( relayoutSizeAndPositionNeeded )
682 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
684 if( relayoutAlignmentNeeded )
686 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
688 if( relayoutVisibilityNeeded )
690 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
695 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
696 // add them to the text-actor cache.
697 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
698 mRelayoutData.mGlyphActors.clear();
701 // Relays-out but doesn't add glyph-actors to the text-view.
702 DoRelayOut( textViewSize.GetVectorXY(), mask );
706 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
712 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
716 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
717 textLayoutInfo.mLines = mRelayoutData.mLines;
719 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
720 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
722 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
724 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
727 void TextView::SetSortModifier( float depthOffset )
729 mVisualParameters.mSortModifier = depthOffset;
731 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
735 ( *it ).SetSortModifier( depthOffset );
738 if( mOffscreenImageActor )
740 mOffscreenImageActor.SetSortModifier( depthOffset );
744 void TextView::SetSnapshotModeEnabled( bool enable )
746 if( enable != mVisualParameters.mSnapshotModeEnabled )
748 // Remove first all glyph-actors
749 if( !mRelayoutData.mGlyphActors.empty() )
751 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
754 mVisualParameters.mSnapshotModeEnabled = enable;
755 if( !mLockPreviousSnapshotMode )
757 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
758 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
760 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
761 // to smash the stored value.
762 mPreviousSnapshotModeEnabled = enable;
765 if( mVisualParameters.mSnapshotModeEnabled )
767 // Create a root actor and an image actor for offscreen rendering.
768 mOffscreenRootActor = Layer::New();
769 mOffscreenImageActor = ImageActor::New();
771 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
772 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
773 mOffscreenRootActor.SetInheritRotation( false );
774 mOffscreenRootActor.SetInheritScale( false );
775 mOffscreenRootActor.SetDepthTestDisabled( true );
777 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
779 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
780 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
781 mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
782 BlendingFactor::ONE, BlendingFactor::ONE );
785 self.Add( mOffscreenRootActor );
786 self.Add( mOffscreenImageActor );
787 mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) );
793 if( mOffscreenRootActor )
795 self.Remove( mOffscreenRootActor );
798 if( mOffscreenImageActor )
800 self.Remove( mOffscreenImageActor );
803 DestroyOffscreenRenderingResources();
806 if( RELAYOUT_ALL != mRelayoutOperations )
808 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
809 RELAYOUT_REMOVE_TEXT_ACTORS |
810 RELAYOUT_TEXT_ACTOR_UPDATE |
811 RELAYOUT_INSERT_TO_TEXT_VIEW );
817 bool TextView::IsSnapshotModeEnabled() const
819 return mVisualParameters.mSnapshotModeEnabled;
822 void TextView::SetMarkupProcessingEnabled( bool enable )
824 mMarkUpEnabled = enable;
827 bool TextView::IsMarkupProcessingEnabled() const
829 return mMarkUpEnabled;
832 void TextView::SetScrollEnabled( bool enable )
834 if( enable != mVisualParameters.mScrollEnabled )
836 mVisualParameters.mScrollEnabled = enable;
838 if( mVisualParameters.mScrollEnabled )
840 // Offscreen rendering is needed to enable text scroll.
842 // Stores previous value of the snapshot mode.
843 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
846 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
847 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
848 Lock lock( mLockPreviousSnapshotMode );
849 SetSnapshotModeEnabled( true );
852 // Creates the pan gesture detector and attach the text-view.
853 mPanGestureDetector = PanGestureDetector::New();
854 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
855 mPanGestureDetector.Attach( Self() );
859 // Removes the pan gesture detector.
860 if( mPanGestureDetector )
862 mPanGestureDetector.Detach( Self() );
863 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
864 mPanGestureDetector.Reset();
867 // Restores the previous state for snapshot mode.
868 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
873 bool TextView::IsScrollEnabled() const
875 return mVisualParameters.mScrollEnabled;
878 void TextView::SetScrollPosition( const Vector2& position )
880 if( position != mVisualParameters.mCameraScrollPosition )
882 // Guard against destruction during signal emission
883 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
884 Toolkit::TextView handle( GetOwner() );
886 DoSetScrollPosition( position );
888 // Check if the new scroll position has been trimmed.
889 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
893 const Vector2& TextView::GetScrollPosition() const
895 return mVisualParameters.mCameraScrollPosition;
898 bool TextView::IsScrollPositionTrimmed() const
900 return mVisualParameters.mScrollPositionTrimmed;
903 Toolkit::TextView::ScrolledSignalType& TextView::ScrolledSignal()
905 return mScrolledSignal;
908 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
910 Dali::BaseHandle handle( object );
912 bool connected( true );
913 Toolkit::TextView textView = Toolkit::TextView::DownCast(handle);
915 if( Dali::Toolkit::TextView::SIGNAL_TEXT_SCROLLED == signalName )
917 textView.ScrolledSignal().Connect( tracker, functor );
921 // signalName does not match any signal
928 TextView::LayoutParameters::LayoutParameters()
929 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
930 mExceedPolicy( TextView::Original ),
931 mWidthExceedPolicy( Toolkit::TextView::Original ),
932 mHeightExceedPolicy( Toolkit::TextView::Original ),
933 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
934 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
935 mLineJustification( Toolkit::TextView::Left ),
936 mLineHeightOffset( 0.f ),
937 mMarkUpEnabled( false )
941 TextView::LayoutParameters::~LayoutParameters()
945 TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy,
946 Toolkit::TextView::ExceedPolicy widthExceedPolicy,
947 Toolkit::TextView::ExceedPolicy heightExceedPolicy,
948 Toolkit::Alignment::Type alignmentType,
949 Toolkit::TextView::LineJustification lineJustification,
950 float lineHeightOffset,
952 : mMultilinePolicy( multilinePolicy ),
953 mExceedPolicy( TextView::Original ),
954 mWidthExceedPolicy( widthExceedPolicy ),
955 mHeightExceedPolicy( heightExceedPolicy ),
956 mHorizontalAlignment(),
957 mVerticalAlignment(),
958 mLineJustification( lineJustification ),
959 mLineHeightOffset( lineHeightOffset ),
960 mMarkUpEnabled( markUpEnabled )
963 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
964 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
965 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
966 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
967 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
968 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
970 mHorizontalAlignment = horizontalAlignment;
971 mVerticalAlignment = verticalAlignment;
974 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
975 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
976 mExceedPolicy( TextView::Original ),
977 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
978 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
979 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
980 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
981 mLineJustification( layoutParameters.mLineJustification ),
982 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
983 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
987 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
989 mMultilinePolicy = layoutParameters.mMultilinePolicy;
990 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
991 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
992 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
993 mVerticalAlignment = layoutParameters.mVerticalAlignment;
994 mLineJustification = layoutParameters.mLineJustification;
995 mLineHeightOffset = layoutParameters.mLineHeightOffset;
996 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
1001 TextView::VisualParameters::VisualParameters()
1003 mSortModifier( 0.f ),
1004 mCameraScrollPosition( 0.f, 0.f ),
1005 mSnapshotModeEnabled( false ),
1006 mScrollEnabled( false ),
1007 mScrollPositionTrimmed( false )
1011 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
1012 : mFadeBoundary( visualParameters.mFadeBoundary ),
1013 mSortModifier( visualParameters.mSortModifier ),
1014 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
1015 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
1016 mScrollEnabled( visualParameters.mScrollEnabled ),
1017 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
1021 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters )
1023 mFadeBoundary = visualParameters.mFadeBoundary;
1024 mSortModifier = visualParameters.mSortModifier;
1025 mCameraScrollPosition = visualParameters.mCameraScrollPosition;
1026 mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled;
1027 mScrollEnabled = visualParameters.mScrollEnabled;
1028 mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed;
1033 TextView::RelayoutData::RelayoutData()
1035 mShrinkFactor( 1.f ),
1037 mCharacterLogicalToVisualMap(),
1038 mCharacterVisualToLogicalMap(),
1040 mCharacterLayoutInfoTable(),
1042 mTextSizeForRelayoutOption()
1046 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
1047 : mTextViewSize( relayoutData.mTextViewSize ),
1048 mShrinkFactor( relayoutData.mShrinkFactor ),
1049 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
1050 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
1051 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
1052 mGlyphActors( relayoutData.mGlyphActors ),
1053 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
1054 mLines( relayoutData.mLines ),
1055 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
1059 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
1061 mTextViewSize = relayoutData.mTextViewSize;
1062 mShrinkFactor = relayoutData.mShrinkFactor;
1063 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
1064 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
1065 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
1066 mGlyphActors = relayoutData.mGlyphActors;
1067 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
1068 mLines = relayoutData.mLines;
1069 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1074 TextView::TextView()
1075 : Control( REQUIRES_STYLE_CHANGE_SIGNALS ),
1076 mCurrentStyledText(),
1077 mTextViewProcessorOperations(),
1078 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1079 Toolkit::TextView::Original,
1080 Toolkit::TextView::Original,
1081 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1082 Toolkit::TextView::Left,
1085 mVisualParameters(),
1087 mRelayoutOperations( NO_RELAYOUT ),
1088 mOffscreenRootActor(),
1089 mOffscreenImageActor(),
1090 mOffscreenCameraActor(),
1091 mCurrentOffscreenSize(),
1092 mFrameBufferImage(),
1094 mPanGestureDetector(),
1095 mLockPreviousSnapshotMode( false ),
1096 mPreviousSnapshotModeEnabled( false ),
1097 mMarkUpEnabled( false )
1099 // Creates the ellipsis layout info.
1100 CreateEllipsizeLayout();
1103 TextView::~TextView()
1105 // Destroys offscreen rendering resources.
1106 DestroyOffscreenRenderingResources();
1108 // Destroys scroll pan gesture detector.
1109 if( mPanGestureDetector )
1111 mPanGestureDetector.Reset();
1115 Vector3 TextView::GetNaturalSize()
1117 if( !mTextViewProcessorOperations.empty() )
1119 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1121 if( !mRelayoutData.mGlyphActors.empty() )
1123 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1124 // add them to the text-actor cache.
1125 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1126 mRelayoutData.mGlyphActors.clear();
1128 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1131 PerformTextViewProcessorOperations();
1134 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1137 float TextView::GetHeightForWidth( float width )
1141 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1142 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1143 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1145 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1146 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1147 height = GetNaturalSize().height;
1151 // Check if the given width is different than the current one.
1152 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1154 // Check if the text-view has glyph-actors.
1155 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1157 // Check which layout operations need to be done.
1158 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1160 if( relayoutSizeAndPositionNeeded )
1162 if( hasGlyphActors )
1164 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1165 // add them to the text-actor cache.
1166 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1167 mRelayoutData.mGlyphActors.clear();
1170 // Use the given width.
1171 const Vector2 textViewSize( width, GetControlSize().height );
1173 // Relays-out but doesn't add glyph-actors to the text-view.
1174 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1177 // Retrieve the text height after relayout the text.
1178 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1180 if( differentWidth )
1182 // Revert the relayout operation mask
1183 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1186 if( hasGlyphActors )
1188 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1191 if( differentWidth || hasGlyphActors )
1200 float TextView::GetWidthForHeight( float height )
1202 // TODO: Needs implementing properly, for now just return the natural width.
1203 return GetNaturalSize().width;
1207 void TextView::OnInitialize()
1212 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1214 // Creates the ellipsis layout info.
1215 CreateEllipsizeLayout();
1217 SetText( mCurrentStyledText );
1220 void TextView::OnControlSizeSet( const Vector3& size )
1222 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1224 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1225 mRelayoutOperations = RELAYOUT_ALL;
1227 // Request to be relaid out
1232 void TextView::OnRelayout( const Vector2& size, ActorSizeContainer& container )
1234 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1236 // Not worth to relayout if width or height is equal to zero.
1240 if( size != mRelayoutData.mTextViewSize )
1242 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1243 if( RELAYOUT_ALL != mRelayoutOperations )
1245 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1246 RELAYOUT_REMOVE_TEXT_ACTORS |
1247 RELAYOUT_SIZE_POSITION |
1248 RELAYOUT_ALIGNMENT |
1249 RELAYOUT_VISIBILITY |
1250 RELAYOUT_TEXT_ACTOR_UPDATE |
1251 RELAYOUT_INSERT_TO_TEXT_VIEW );
1255 if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
1256 ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
1258 if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
1260 // If the text of the alignment changes and a fade exceed policy is set,
1261 // some characters may need new TextActor.
1262 mRelayoutOperations = RELAYOUT_ALL;
1266 // Remove glyph-actors from text-view
1267 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1269 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1270 mRelayoutData.mGlyphActors.clear();
1273 if( NO_RELAYOUT != mRelayoutOperations )
1275 // Relays-out and add glyph-actors to the text-view.
1276 DoRelayOut( size, mRelayoutOperations );
1277 ProcessSnapshot( size );
1280 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1281 mRelayoutData.mTextActorCache.ClearTexts();
1284 void TextView::PerformTextViewProcessorOperations()
1286 // Traverse the relayout operation vector ...
1288 // Optimizes some operations.
1289 OptimizeTextViewProcessorOperations();
1291 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1293 const TextViewProcessorMetadata& relayoutMetadata( *it );
1295 switch( relayoutMetadata.mType )
1297 case TextView::TextSet:
1299 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1304 case TextView::TextInserted:
1306 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1307 relayoutMetadata.mText,
1312 case TextView::TextReplaced:
1314 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1315 relayoutMetadata.mNumberOfCharacters,
1316 relayoutMetadata.mText,
1321 case TextView::TextRemoved:
1323 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1324 relayoutMetadata.mNumberOfCharacters,
1327 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1330 case TextView::NewLineHeight:
1332 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1333 mRelayoutData.mTextLayoutInfo );
1336 case TextView::NewStyle:
1338 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1339 relayoutMetadata.mStyleMask,
1346 // Clear all operations when they are done.
1347 mTextViewProcessorOperations.clear();
1350 void TextView::OptimizeTextViewProcessorOperations()
1352 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1354 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1355 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1356 // use the cache without clearing the text-actors.
1358 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1360 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1362 const TextViewProcessorMetadata& relayoutMetadata( *it );
1364 switch( relayoutMetadata.mType )
1366 case TextView::TextRemoved:
1368 bool optimizationDone = false;
1370 if( it + 1u != endIt )
1372 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) );
1373 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1375 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1377 optimizationDone = true;
1378 TextViewProcessorMetadata newRelayoutMetadata;
1379 newRelayoutMetadata.mType = TextView::TextReplaced;
1380 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1381 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1382 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1383 textViewProcessorOperations.push_back( newRelayoutMetadata );
1385 // do not access the TextInserted operation in next iteration.
1391 if( !optimizationDone )
1393 textViewProcessorOperations.push_back( relayoutMetadata );
1399 textViewProcessorOperations.push_back( relayoutMetadata );
1404 mTextViewProcessorOperations = textViewProcessorOperations;
1407 void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask )
1409 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1410 if( !mTextViewProcessorOperations.empty() )
1412 PerformTextViewProcessorOperations();
1415 CombineExceedPolicies();
1418 if( mVisualParameters.mSnapshotModeEnabled )
1420 rootActor = mOffscreenRootActor;
1427 mRelayoutData.mTextViewSize = textViewSize;
1428 switch( mLayoutParameters.mMultilinePolicy )
1430 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1432 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1434 } // SplitByNewLineChar
1436 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1438 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1442 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1444 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1447 } // switch( mMultilinePolicy )
1449 // Remove done operations from the mask.
1450 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1453 void TextView::ProcessSnapshot( const Size& textViewSize )
1455 if( mVisualParameters.mSnapshotModeEnabled )
1457 // If layout options change, it's needed generate a new image.
1459 if( mOffscreenRootActor )
1461 // Set the root actor visible.
1462 // The root actor is set to non visible after the render task is processed.
1463 mOffscreenRootActor.SetVisible( true );
1465 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1466 mOffscreenRootActor.SetSize( textViewSize );
1469 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1470 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1472 // Set the image actor visible.
1473 // The image actor is set to non visible if there is no text to render.
1474 mOffscreenImageActor.SetVisible( true );
1476 // Calculates the offscreen image's size. It takes into account different points:
1477 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1478 // * There is a maximum texture size the graphic subsystem can load on the memory.
1479 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1481 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1482 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1483 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1484 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1486 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1490 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1491 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1492 offscreenSize.height,
1495 // Stores current text-view size to avoid create new Dali resources if text changes.
1496 mCurrentOffscreenSize = offscreenSize;
1498 if( !mOffscreenCameraActor )
1500 // Creates a new camera actor.
1501 mOffscreenCameraActor = CameraActor::New();
1502 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1503 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1504 mOffscreenCameraActor.SetRotation(Degree(180.f), Vector3::YAXIS);
1506 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1508 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1511 // Calculate camera parameters for current text size.
1512 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1515 if( mVisualParameters.mScrollEnabled )
1517 // Updates the offscreen camera position with the new scroll offset.
1518 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1519 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1523 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1524 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1529 // Creates a new render task.
1530 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1532 mRenderTask.SetSourceActor( mOffscreenRootActor );
1533 mRenderTask.SetInputEnabled( false );
1534 mRenderTask.SetClearColor( Color::TRANSPARENT );
1535 mRenderTask.SetClearEnabled( true );
1536 mRenderTask.SetExclusive( true );
1538 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1539 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1544 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1545 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1548 // Process the render task only once every time the text changes or the text-view's size canges.
1549 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1553 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1554 mOffscreenImageActor.SetVisible( false );
1559 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1561 float xPosition = 0.f;
1562 float yPosition = 0.f;
1563 Vector3 parentOrigin = ParentOrigin::CENTER;
1564 Vector3 anchorPoint = AnchorPoint::CENTER;
1566 switch( mLayoutParameters.mHorizontalAlignment )
1568 case Toolkit::Alignment::HorizontalLeft:
1570 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1571 parentOrigin.x = 0.f;
1572 anchorPoint.x = 0.f;
1575 case Toolkit::Alignment::HorizontalCenter:
1580 case Toolkit::Alignment::HorizontalRight:
1582 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1583 parentOrigin.x = 1.f;
1584 anchorPoint.x = 1.f;
1589 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1593 switch( mLayoutParameters.mVerticalAlignment )
1595 case Toolkit::Alignment::VerticalTop:
1597 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1598 parentOrigin.y = 0.f;
1599 anchorPoint.y = 0.f;
1602 case Toolkit::Alignment::VerticalCenter:
1607 case Toolkit::Alignment::VerticalBottom:
1609 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1610 parentOrigin.y = 1.f;
1611 anchorPoint.y = 1.f;
1616 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1620 mOffscreenCameraActor.SetX( xPosition );
1621 mOffscreenCameraActor.SetY( yPosition );
1623 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1624 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1627 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1629 // not to process the offscreen root actor by setting its visibility to false.
1630 mOffscreenRootActor.SetVisible( false );
1632 // Sets the new size and the new frame buffer to the image actor.
1633 // Image actor must have same size as text. Otherwise text can be truncated.
1634 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1635 mOffscreenImageActor.SetImage( mFrameBufferImage );
1638 void TextView::DestroyOffscreenRenderingResources()
1642 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1644 if( Stage::IsInstalled() )
1646 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1649 mRenderTask.Reset();
1652 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1653 if( mOffscreenCameraActor )
1655 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1657 mOffscreenCameraActor.Reset();
1660 if( mOffscreenRootActor )
1662 mOffscreenRootActor.Reset();
1665 if( mOffscreenImageActor )
1667 mOffscreenImageActor.Reset();
1670 mCurrentOffscreenSize = Size( 0.f, 0.f );
1672 if( mFrameBufferImage )
1674 mFrameBufferImage.Reset();
1678 void TextView::OnTextPan( Actor actor, const PanGesture& gesture )
1680 if( 1u == gesture.numberOfTouches )
1682 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1686 void TextView::TrimScrollPosition()
1688 const Vector3& textViewSize = GetControlSize();
1690 // Before use the text's size, relayout the text is needed to get the actual text size.
1691 GetTextLayoutInfo();
1693 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1694 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1695 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1696 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1697 float minVerticalDisplacement = -maxVerticalDisplacement;
1699 // Updates the range if the text is aligned on the right or left.
1700 switch( mLayoutParameters.mHorizontalAlignment )
1702 case Toolkit::Alignment::HorizontalLeft:
1704 maxHorizontalDisplacement *= 2.f;
1705 minHorizontalDisplacement = 0.f;
1708 case Toolkit::Alignment::HorizontalCenter:
1713 case Toolkit::Alignment::HorizontalRight:
1715 maxHorizontalDisplacement = 0.f;
1716 minHorizontalDisplacement *= 2.f;
1721 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1725 // Updates the range if the text is aligned on the top or bottom.
1726 switch( mLayoutParameters.mVerticalAlignment )
1728 case Toolkit::Alignment::VerticalTop:
1730 maxVerticalDisplacement *= 2.f;
1731 minVerticalDisplacement = 0.f;
1734 case Toolkit::Alignment::VerticalCenter:
1739 case Toolkit::Alignment::VerticalBottom:
1741 maxVerticalDisplacement = 0.f;
1742 minVerticalDisplacement *= 2.f;
1747 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1751 // Trims the scroll position to be within the range.
1752 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1753 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1755 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1756 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1759 void TextView::DoSetScrollPosition( const Vector2& position )
1761 // Stores old scroll position.
1762 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1764 // Updates the scroll position
1765 mVisualParameters.mCameraScrollPosition = position;
1767 // Ensures the text-view is covered with text.
1768 TrimScrollPosition();
1770 // Calculate the difference with the previous scroll position
1771 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1772 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1774 if( mOffscreenRootActor )
1776 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1778 mOffscreenRootActor.SetVisible( true );
1781 if( mOffscreenCameraActor )
1783 // Update the offscreen camera with the new scroll position.
1784 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1785 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1790 // Refresh the render-task.
1791 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1795 Toolkit::TextView handle( GetOwner() );
1796 mScrolledSignal.Emit( handle, delta );
1799 void TextView::CombineExceedPolicies()
1801 // Calculates the combination of exceed policies.
1803 switch( mLayoutParameters.mWidthExceedPolicy )
1805 case Toolkit::TextView::Original:
1807 switch( mLayoutParameters.mHeightExceedPolicy )
1809 case Toolkit::TextView::Original:
1811 mLayoutParameters.mExceedPolicy = Original;
1814 case Toolkit::TextView::Fade:
1816 mLayoutParameters.mExceedPolicy = OriginalFade;
1819 case Toolkit::TextView::ShrinkToFit:
1821 mLayoutParameters.mExceedPolicy = OriginalShrink;
1826 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1831 case Toolkit::TextView::Split:
1833 switch( mLayoutParameters.mHeightExceedPolicy )
1835 case Toolkit::TextView::Original:
1837 mLayoutParameters.mExceedPolicy = SplitOriginal;
1840 case Toolkit::TextView::Fade:
1842 mLayoutParameters.mExceedPolicy = SplitFade;
1845 case Toolkit::TextView::ShrinkToFit:
1847 mLayoutParameters.mExceedPolicy = SplitShrink;
1850 case Toolkit::TextView::EllipsizeEnd:
1852 mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd;
1857 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1862 case Toolkit::TextView::Fade:
1864 switch( mLayoutParameters.mHeightExceedPolicy )
1866 case Toolkit::TextView::Original:
1868 mLayoutParameters.mExceedPolicy = FadeOriginal;
1871 case Toolkit::TextView::Fade:
1873 mLayoutParameters.mExceedPolicy = Fade;
1878 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1883 case Toolkit::TextView::ShrinkToFit:
1885 switch( mLayoutParameters.mHeightExceedPolicy )
1887 case Toolkit::TextView::Original:
1889 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1892 case Toolkit::TextView::Fade:
1894 mLayoutParameters.mExceedPolicy = ShrinkFade;
1897 case Toolkit::TextView::ShrinkToFit:
1899 mLayoutParameters.mExceedPolicy = Shrink;
1904 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1909 case Toolkit::TextView::EllipsizeEnd:
1911 switch( mLayoutParameters.mHeightExceedPolicy )
1913 case Toolkit::TextView::Original:
1915 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1918 case Toolkit::TextView::EllipsizeEnd:
1920 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1925 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1932 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1937 Actor TextView::GetRootActor() const
1939 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1943 if( mVisualParameters.mSnapshotModeEnabled )
1945 rootActor = mOffscreenRootActor;
1955 void TextView::CreateEllipsizeLayout()
1957 // Creates the ellipsis layout info for the ellipsis text and styles.
1958 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1959 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
1960 TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
1961 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
1962 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1965 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
1967 bool newValue( propertyValue.Get<bool>() );
1968 if( newValue != IsMarkupProcessingEnabled() )
1970 SetMarkupProcessingEnabled( newValue );
1973 // If markup processing has been enabled, Ensure current text is reprocessed.
1974 const std::string& currentText( GetText() );
1975 if( ! currentText.empty() )
1977 SetText( currentText );
1983 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1985 std::string policyName( propertyValue.Get<std::string>() );
1986 if(policyName == "SplitByNewLineChar")
1988 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1990 else if(policyName == "SplitByWord")
1992 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1994 else if(policyName == "SplitByChar")
1996 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
2000 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
2004 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
2006 std::string policyName( propertyValue.Get<std::string>() );
2007 if(policyName == "Original")
2009 SetWidthExceedPolicy(Toolkit::TextView::Original);
2011 else if(policyName == "Fade")
2013 SetWidthExceedPolicy(Toolkit::TextView::Fade);
2015 else if(policyName == "Split")
2017 SetWidthExceedPolicy(Toolkit::TextView::Split);
2019 else if(policyName == "ShrinkToFit")
2021 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
2023 else if(policyName == "EllipsizeEnd")
2025 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
2029 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
2033 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
2035 std::string policyName( propertyValue.Get<std::string>() );
2036 if(policyName == "Original")
2038 SetHeightExceedPolicy(Toolkit::TextView::Original);
2040 else if(policyName == "Fade")
2042 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2044 else if(policyName == "Split")
2046 SetHeightExceedPolicy(Toolkit::TextView::Split);
2048 else if(policyName == "ShrinkToFit")
2050 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2054 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2058 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2060 std::string policyName( propertyValue.Get<std::string>() );
2061 if(policyName == "Left")
2063 SetLineJustification(Toolkit::TextView::Left);
2065 else if(policyName == "Center")
2067 SetLineJustification(Toolkit::TextView::Center);
2069 else if(policyName == "Right")
2071 SetLineJustification(Toolkit::TextView::Right);
2073 else if(policyName == "Justified")
2075 SetLineJustification(Toolkit::TextView::Justified);
2079 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2083 void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue )
2085 Vector4 value( propertyValue.Get<Vector4>() );
2086 DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f )
2087 && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " );
2089 Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast<unsigned int>( value.x ) ),
2090 PixelSize( static_cast<unsigned int>( value.y ) ),
2091 PixelSize( static_cast<unsigned int>( value.z ) ),
2092 PixelSize( static_cast<unsigned int>( value.w ) ) );
2094 SetFadeBoundary( fadeBoundary );
2097 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2099 std::string value( propertyValue.Get<std::string>() );
2101 if( propertyIndex == Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT )
2103 if(value == "HorizontalLeft")
2105 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2107 else if( value == "HorizontalCenter")
2109 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2111 else if( value == "HorizontalRight")
2113 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2117 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2120 else if( propertyIndex == Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT )
2122 if( value == "VerticalTop" )
2124 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2126 else if( value == "VerticalCenter")
2128 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2130 else if( value == "VerticalBottom")
2132 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2136 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2142 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
2143 if( RELAYOUT_ALL != mRelayoutOperations )
2145 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
2146 RELAYOUT_TEXT_ACTOR_UPDATE |
2147 RELAYOUT_ALIGNMENT |
2148 RELAYOUT_VISIBILITY );
2152 std::string TextView::OnHorizontalAlignmentPropertyGet()
2154 if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft )
2156 return "HorizontalLeft";
2158 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter )
2160 return "HorizontalCenter";
2162 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight )
2164 return "HorizontalRight";
2168 DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." );
2172 std::string TextView::OnVerticalAlignmentPropertyGet()
2174 if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop )
2176 return "VerticalTop";
2178 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter )
2180 return "VerticalCenter";
2182 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom )
2184 return "VerticalBottom";
2188 DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." );
2192 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2194 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2198 TextView& textViewImpl( GetImpl( textView ) );
2201 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2203 textViewImpl.OnMarkupEnabledPeopertySet( value );
2206 case Toolkit::TextView::PROPERTY_TEXT:
2208 textViewImpl.SetText( value.Get<std::string>() );
2211 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2213 textViewImpl.OnMultilinePolicyPropertySet( value );
2216 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2218 textViewImpl.OnWidthExceedPolicyPropertySet( value );
2221 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2223 textViewImpl.OnHeightExceedPolicyPropertySet( value );
2226 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2228 textViewImpl.OnLineJustificationPropertySet( value );
2231 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2233 textViewImpl.OnFadeBoundaryPropertySet( value );
2236 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2238 Dali::PointSize pointSize( value.Get<float>() );
2239 textViewImpl.SetLineHeightOffset(pointSize);
2242 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2243 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2245 textViewImpl.OnAlignmentPropertySet( index, value );
2252 Property::Value TextView::GetProperty( BaseObject* object, Property::Index index )
2254 Property::Value value;
2256 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2260 TextView& textViewImpl( GetImpl( textView ) );
2263 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2265 value = textViewImpl.IsMarkupProcessingEnabled();
2268 case Toolkit::TextView::PROPERTY_TEXT:
2270 value = textViewImpl.GetText();
2273 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2275 value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ];
2278 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2280 value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ];
2283 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2285 value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ];
2288 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2290 value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ];
2293 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2295 Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary();
2296 value = Vector4( static_cast<float>( boundary.mLeft.value ),
2297 static_cast<float>( boundary.mRight.value ),
2298 static_cast<float>( boundary.mTop.value ),
2299 static_cast<float>( boundary.mBottom.value ) );
2302 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2304 value = textViewImpl.GetLineHeightOffset().value;
2307 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2309 value = textViewImpl.OnHorizontalAlignmentPropertyGet();
2312 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2314 value = textViewImpl.OnVerticalAlignmentPropertyGet();
2322 } // namespace Internal
2324 } // namespace Toolkit