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 );
60 const char* const SIGNAL_TEXT_SCROLLED = "scrolled";
62 const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"};
63 const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"};
64 const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"};
66 // Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
67 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
72 return Toolkit::TextView::New();
75 TypeRegistration typeRegistration( typeid( Toolkit::TextView ), typeid( Toolkit::Control ), Create );
77 SignalConnectorType signalConnector1( typeRegistration, SIGNAL_TEXT_SCROLLED , &TextView::DoConnectSignal );
79 PropertyRegistration property1( typeRegistration, "markup-enabled", Toolkit::TextView::PROPERTY_MARKUP_ENABLED, Property::BOOLEAN, &TextView::SetProperty, &TextView::GetProperty );
80 PropertyRegistration property2( typeRegistration, "text", Toolkit::TextView::PROPERTY_TEXT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
81 PropertyRegistration property3( typeRegistration, "multiline-policy", Toolkit::TextView::PROPERTY_MULTILINE_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
82 PropertyRegistration property4( typeRegistration, "width-exceed-policy", Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
83 PropertyRegistration property5( typeRegistration, "height-exceed-policy", Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
84 PropertyRegistration property6( typeRegistration, "line-justification", Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
85 PropertyRegistration property7( typeRegistration, "fade-boundary", Toolkit::TextView::PROPERTY_FADE_BOUNDARY, Property::VECTOR4, &TextView::SetProperty, &TextView::GetProperty );
86 PropertyRegistration property8( typeRegistration, "line-height-offset", Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET, Property::FLOAT, &TextView::SetProperty, &TextView::GetProperty );
87 PropertyRegistration property9( typeRegistration, "horizontal-alignment", Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
88 PropertyRegistration property10( typeRegistration, "vertical-alignment", Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT, Property::STRING, &TextView::SetProperty, &TextView::GetProperty );
91 * Whether the text-view-processor operation sets, inserts, replaces, removes text.
93 * @param[in] metadata The text-view-processor operation.
95 * @return \e true if the given text-view-processor operation is modifying the text.
97 bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata )
99 return ( ( metadata.mType == TextView::TextSet ) ||
100 ( metadata.mType == TextView::TextInserted ) ||
101 ( metadata.mType == TextView::TextReplaced ) ||
102 ( metadata.mType == TextView::TextRemoved ) ||
103 ( metadata.mType == TextView::NewStyle ));
107 * Whether the text-view-processor operation sets a new line height offset.
109 * @param[in] metadata The text-view-processor operation.
111 * @return \e true if the given text-view-processor operation sets a new line height offset.
113 bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata )
115 return ( metadata.mType == TextView::NewLineHeight );
119 * Whether the text-view-processor operation sets a new style.
121 * @param[in] metadata The text-view-processor operation.
123 * @return \e true if the given text-view-processor operation sets a new style.
125 bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata )
127 return ( metadata.mType == TextView::NewStyle );
132 TextView::TextViewProcessorMetadata::TextViewProcessorMetadata()
133 : mType( TextView::TextSet ),
135 mNumberOfCharacters( 0u ),
137 mStyleMask(TextStyle::NONE)
141 Toolkit::TextView TextView::New()
143 // Create the implementation, temporarily owned on stack
144 IntrusivePtr<TextView> textView = new TextView();
146 // Pass ownership to CustomActor
147 Toolkit::TextView handle( *textView );
149 // Second-phase init of the implementation
150 // This can only be done after the CustomActor connection has been made...
151 textView->Initialize();
153 // Disables by default the offscreen rendering.
154 textView->SetSnapshotModeEnabled( false );
159 void TextView::SetText( const std::string& text )
161 // Creates a styled text with the markup or plain string.
162 MarkupProcessor::StyledTextArray styledText;
163 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
165 // Calls SetText() with the styled text array.
166 SetText( styledText );
169 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
171 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
172 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
174 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
175 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
177 // Creates metadata with the Set operation.
178 TextViewProcessorMetadata metadata;
179 metadata.mType = TextView::TextSet;
180 metadata.mText = text;
183 mTextViewProcessorOperations.push_back( metadata );
185 // Updates current styled text.
186 mCurrentStyledText = text;
188 // Request to be relaid out
191 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
192 mRelayoutOperations = RELAYOUT_ALL;
195 void TextView::InsertTextAt( std::size_t position, const std::string& text )
197 // Creates a styled text with the markup or plain string.
198 MarkupProcessor::StyledTextArray styledText;
199 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
201 // Calls InsertTextAt() with the styled text array.
202 InsertTextAt( position, styledText );
205 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
208 MarkupProcessor::GetPlainString( text, textStr );
210 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
211 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
213 // Temporary fix. Creates the whole layout if there is rtl text.
215 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
216 textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
217 SetText( textToSet );
221 // Creates metadata with the Insert operation.
222 TextViewProcessorMetadata metadata;
223 metadata.mType = TextView::TextInserted;
224 metadata.mPosition = position;
225 metadata.mText = text;
228 mTextViewProcessorOperations.push_back( metadata );
230 // Updates current styled text.
231 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
233 // Request to be relaid out
236 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
237 mRelayoutOperations = RELAYOUT_ALL;
241 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
243 // Creates a styled text with the markup or plain string.
244 MarkupProcessor::StyledTextArray styledText;
245 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
247 // Calls ReplaceTextFromTo() with the styled text array.
248 ReplaceTextFromTo( position, numberOfCharacters, styledText );
251 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
254 MarkupProcessor::GetPlainString( text, textStr );
256 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
257 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
259 // Temporary fix. Creates the whole layout if there is rtl text.
261 // Updates current styled text.
262 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
264 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
265 textToSet.erase( it, it + numberOfCharacters );
266 it = textToSet.begin() + position;
267 textToSet.insert( it, text.begin(), text.end() );
269 SetText( textToSet );
273 // Creates metadata with the Insert operation.
274 TextViewProcessorMetadata metadata;
275 metadata.mType = TextView::TextReplaced;
276 metadata.mPosition = position;
277 metadata.mNumberOfCharacters = numberOfCharacters;
278 metadata.mText = text;
281 mTextViewProcessorOperations.push_back( metadata );
283 // Updates current styled text.
284 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
285 mCurrentStyledText.erase( it, it + numberOfCharacters );
286 it = mCurrentStyledText.begin() + position;
287 mCurrentStyledText.insert( it, text.begin(), text.end() );
289 // Request to be relaid out
292 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
293 mRelayoutOperations = RELAYOUT_ALL;
297 void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
299 if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
301 // Temporary fix. Creates the whole layout if there is rtl text.
303 // Updates current styled text.
304 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
305 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
306 textToSet.erase( it, it + numberOfCharacters );
308 SetText( textToSet );
312 // Creates metadata with the Remove operation.
313 TextViewProcessorMetadata metadata;
314 metadata.mType = TextView::TextRemoved;
315 metadata.mPosition = position;
316 metadata.mNumberOfCharacters = numberOfCharacters;
319 mTextViewProcessorOperations.push_back( metadata );
321 // Updates current styled text.
322 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
323 mCurrentStyledText.erase( it, it + numberOfCharacters );
325 // Request to be relaid out
328 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
329 mRelayoutOperations = RELAYOUT_ALL;
333 std::string TextView::GetText() const
335 // Traverses the styled text array getting only the text.
336 // Note that for some languages a 'character' could be represented by more than one 'char'
339 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
341 text.append( (*it).mText.GetText() );
347 void TextView::SetLineHeightOffset( PointSize offset )
349 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
351 // Removes any previous operation which modifies the line height offset.
352 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
353 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
355 // Creates metadata with the new line height operation.
356 TextViewProcessorMetadata metadata;
357 metadata.mType = TextView::NewLineHeight;
359 mTextViewProcessorOperations.push_back( metadata );
361 // Updates line height offset.
362 mLayoutParameters.mLineHeightOffset = offset;
366 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
367 if( RELAYOUT_ALL != mRelayoutOperations )
369 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
370 RELAYOUT_REMOVE_TEXT_ACTORS |
371 RELAYOUT_SIZE_POSITION |
373 RELAYOUT_VISIBILITY |
374 RELAYOUT_TEXT_ACTOR_UPDATE |
375 RELAYOUT_INSERT_TO_TEXT_VIEW );
380 PointSize TextView::GetLineHeightOffset() const
382 return PointSize( mLayoutParameters.mLineHeightOffset );
385 void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask )
387 if( !mCurrentStyledText.empty() )
389 const bool checkFontName = mask & TextStyle::FONT;
390 const bool checkFontSize = mask & TextStyle::SIZE;
391 const bool checkFontStyle = mask & TextStyle::STYLE;
393 // Check first if metrics have changed.
394 bool metricsChanged = false;
395 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
397 const MarkupProcessor::StyledText& styledText( *it );
399 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
400 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
401 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
406 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
408 // If metrics change, new text measurements are needed.
409 SetText( mCurrentStyledText );
413 // Deletes any previous operation which sets a new style.
414 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
415 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
417 // Creates metadata with the new style operation.
418 TextViewProcessorMetadata metadata;
419 metadata.mType = TextView::NewStyle;
421 MarkupProcessor::StyledText text;
423 metadata.mText.push_back( text );
424 metadata.mStyleMask = mask;
426 mTextViewProcessorOperations.push_back( metadata );
428 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
432 if( RELAYOUT_ALL != mRelayoutOperations )
434 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
435 RELAYOUT_TEXT_ACTOR_UPDATE );
440 // Sets the new style to the ellipsize text
441 // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
442 if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
444 for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
445 endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
449 (*it)->Copy( style, mask );
452 SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
456 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
458 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
460 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
461 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
462 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
463 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
464 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
465 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
467 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
468 mLayoutParameters.mVerticalAlignment = verticalAlignment;
472 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
473 if( RELAYOUT_ALL != mRelayoutOperations )
475 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
476 RELAYOUT_TEXT_ACTOR_UPDATE |
478 RELAYOUT_VISIBILITY );
483 Toolkit::Alignment::Type TextView::GetTextAlignment() const
485 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
488 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
490 if( policy != mLayoutParameters.mMultilinePolicy )
492 mLayoutParameters.mMultilinePolicy = policy;
494 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
495 mRelayoutOperations = RELAYOUT_ALL;
501 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
503 return mLayoutParameters.mMultilinePolicy;
506 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
508 // The layout info could be invalid depending on the current exceed policy and the new one.
509 // i.e. if the current policy is Split and the new one is ShrinkToFit then
510 // the layout info generated for each char is not needed.
511 if( policy != mLayoutParameters.mWidthExceedPolicy )
513 mLayoutParameters.mWidthExceedPolicy = policy;
515 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
516 mRelayoutOperations = RELAYOUT_ALL;
522 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
524 return mLayoutParameters.mWidthExceedPolicy;
527 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
529 if( policy != mLayoutParameters.mHeightExceedPolicy )
531 mLayoutParameters.mHeightExceedPolicy = policy;
535 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
536 if( RELAYOUT_ALL != mRelayoutOperations )
538 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
539 RELAYOUT_REMOVE_TEXT_ACTORS |
540 RELAYOUT_SIZE_POSITION |
542 RELAYOUT_VISIBILITY |
543 RELAYOUT_TEXT_ACTOR_UPDATE |
544 RELAYOUT_INSERT_TO_TEXT_VIEW );
549 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
551 return mLayoutParameters.mHeightExceedPolicy;
554 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
556 if( justification != mLayoutParameters.mLineJustification )
558 mLayoutParameters.mLineJustification = justification;
562 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
563 if( RELAYOUT_ALL != mRelayoutOperations )
565 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
566 RELAYOUT_REMOVE_TEXT_ACTORS |
567 RELAYOUT_SIZE_POSITION |
569 RELAYOUT_VISIBILITY |
570 RELAYOUT_TEXT_ACTOR_UPDATE |
571 RELAYOUT_INSERT_TO_TEXT_VIEW );
576 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
578 return mLayoutParameters.mLineJustification;
581 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
583 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
584 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
585 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
586 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
588 mVisualParameters.mFadeBoundary = fadeBoundary;
592 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
593 if( RELAYOUT_ALL != mRelayoutOperations )
595 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
596 RELAYOUT_REMOVE_TEXT_ACTORS |
597 RELAYOUT_VISIBILITY |
598 RELAYOUT_TEXT_ACTOR_UPDATE |
599 RELAYOUT_INSERT_TO_TEXT_VIEW );
604 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
606 return mVisualParameters.mFadeBoundary;
609 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
611 // Creates a styled text with the markup or plain string.
612 MarkupProcessor::StyledTextArray styledText;
613 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
615 // Creates the ellipsis layout info and sets the text and styles.
616 SetEllipsizeText( styledText );
619 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
621 // Converts the styled text array into a Text and a vector of TextStyles.
623 Vector<TextStyle*> styles;
624 for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
626 const MarkupProcessor::StyledText& styledText( *it );
628 text.Append( styledText.mText );
629 styles.PushBack( new TextStyle( styledText.mStyle ) );
632 // Creates the ellipsis layout info and sets the text and styles.
633 SetEllipsizeText( text, styles );
636 void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
638 // Sets the text and styles for the ellipsis text.
639 mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
640 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
642 // Creates the ellipsis layout info.
643 CreateEllipsizeLayout();
645 // Request to be relaid out
648 mRelayoutOperations = RELAYOUT_ALL;
651 std::string TextView::GetEllipsizeText() const
653 return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
656 void TextView::GetTextLayoutInfo()
658 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
659 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
660 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
662 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
664 Vector3 textViewSize = GetControlSize();
666 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
667 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
668 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
669 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
670 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
672 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
673 // the text natural size can be used.
674 textViewSize = GetNaturalSize();
677 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
678 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
680 // Check if the text-view has glyph-actors.
681 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
683 RelayoutOperationMask mask = NO_RELAYOUT;
684 if( relayoutSizeAndPositionNeeded )
686 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
688 if( relayoutAlignmentNeeded )
690 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
692 if( relayoutVisibilityNeeded )
694 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
699 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
700 // add them to the text-actor cache.
701 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
702 mRelayoutData.mGlyphActors.clear();
705 // Relays-out but doesn't add glyph-actors to the text-view.
706 DoRelayOut( textViewSize.GetVectorXY(), mask );
710 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
716 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
720 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
721 textLayoutInfo.mLines = mRelayoutData.mLines;
723 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
724 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
726 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
728 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
731 void TextView::SetSortModifier( float depthOffset )
733 mVisualParameters.mSortModifier = depthOffset;
735 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
739 ( *it ).SetSortModifier( depthOffset );
742 if( mOffscreenImageActor )
744 mOffscreenImageActor.SetSortModifier( depthOffset );
748 void TextView::SetSnapshotModeEnabled( bool enable )
750 if( enable != mVisualParameters.mSnapshotModeEnabled )
752 // Remove first all glyph-actors
753 if( !mRelayoutData.mGlyphActors.empty() )
755 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
758 mVisualParameters.mSnapshotModeEnabled = enable;
759 if( !mLockPreviousSnapshotMode )
761 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
762 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
764 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
765 // to smash the stored value.
766 mPreviousSnapshotModeEnabled = enable;
769 if( mVisualParameters.mSnapshotModeEnabled )
771 // Create a root actor and an image actor for offscreen rendering.
772 mOffscreenRootActor = Layer::New();
773 mOffscreenImageActor = ImageActor::New();
775 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
776 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
777 mOffscreenRootActor.SetInheritRotation( false );
778 mOffscreenRootActor.SetInheritScale( false );
779 mOffscreenRootActor.SetDepthTestDisabled( true );
781 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
783 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
784 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
785 mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
786 BlendingFactor::ONE, BlendingFactor::ONE );
789 self.Add( mOffscreenRootActor );
790 self.Add( mOffscreenImageActor );
791 mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) );
797 if( mOffscreenRootActor )
799 self.Remove( mOffscreenRootActor );
802 if( mOffscreenImageActor )
804 self.Remove( mOffscreenImageActor );
807 DestroyOffscreenRenderingResources();
810 if( RELAYOUT_ALL != mRelayoutOperations )
812 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
813 RELAYOUT_REMOVE_TEXT_ACTORS |
814 RELAYOUT_TEXT_ACTOR_UPDATE |
815 RELAYOUT_INSERT_TO_TEXT_VIEW );
821 bool TextView::IsSnapshotModeEnabled() const
823 return mVisualParameters.mSnapshotModeEnabled;
826 void TextView::SetMarkupProcessingEnabled( bool enable )
828 mMarkUpEnabled = enable;
831 bool TextView::IsMarkupProcessingEnabled() const
833 return mMarkUpEnabled;
836 void TextView::SetScrollEnabled( bool enable )
838 if( enable != mVisualParameters.mScrollEnabled )
840 mVisualParameters.mScrollEnabled = enable;
842 if( mVisualParameters.mScrollEnabled )
844 // Offscreen rendering is needed to enable text scroll.
846 // Stores previous value of the snapshot mode.
847 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
850 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
851 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
852 Lock lock( mLockPreviousSnapshotMode );
853 SetSnapshotModeEnabled( true );
856 // Creates the pan gesture detector and attach the text-view.
857 mPanGestureDetector = PanGestureDetector::New();
858 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
859 mPanGestureDetector.Attach( Self() );
863 // Removes the pan gesture detector.
864 if( mPanGestureDetector )
866 mPanGestureDetector.Detach( Self() );
867 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
868 mPanGestureDetector.Reset();
871 // Restores the previous state for snapshot mode.
872 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
877 bool TextView::IsScrollEnabled() const
879 return mVisualParameters.mScrollEnabled;
882 void TextView::SetScrollPosition( const Vector2& position )
884 if( position != mVisualParameters.mCameraScrollPosition )
886 // Guard against destruction during signal emission
887 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
888 Toolkit::TextView handle( GetOwner() );
890 DoSetScrollPosition( position );
892 // Check if the new scroll position has been trimmed.
893 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
897 const Vector2& TextView::GetScrollPosition() const
899 return mVisualParameters.mCameraScrollPosition;
902 bool TextView::IsScrollPositionTrimmed() const
904 return mVisualParameters.mScrollPositionTrimmed;
907 Toolkit::TextView::ScrolledSignalType& TextView::ScrolledSignal()
909 return mScrolledSignal;
912 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
914 Dali::BaseHandle handle( object );
916 bool connected( true );
917 Toolkit::TextView textView = Toolkit::TextView::DownCast( handle );
919 if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_SCROLLED ) )
921 textView.ScrolledSignal().Connect( tracker, functor );
925 // signalName does not match any signal
932 TextView::LayoutParameters::LayoutParameters()
933 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
934 mExceedPolicy( TextView::Original ),
935 mWidthExceedPolicy( Toolkit::TextView::Original ),
936 mHeightExceedPolicy( Toolkit::TextView::Original ),
937 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
938 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
939 mLineJustification( Toolkit::TextView::Left ),
940 mLineHeightOffset( 0.f ),
941 mMarkUpEnabled( false )
945 TextView::LayoutParameters::~LayoutParameters()
949 TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy,
950 Toolkit::TextView::ExceedPolicy widthExceedPolicy,
951 Toolkit::TextView::ExceedPolicy heightExceedPolicy,
952 Toolkit::Alignment::Type alignmentType,
953 Toolkit::TextView::LineJustification lineJustification,
954 float lineHeightOffset,
956 : mMultilinePolicy( multilinePolicy ),
957 mExceedPolicy( TextView::Original ),
958 mWidthExceedPolicy( widthExceedPolicy ),
959 mHeightExceedPolicy( heightExceedPolicy ),
960 mHorizontalAlignment(),
961 mVerticalAlignment(),
962 mLineJustification( lineJustification ),
963 mLineHeightOffset( lineHeightOffset ),
964 mMarkUpEnabled( markUpEnabled )
967 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
968 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
969 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
970 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
971 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
972 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
974 mHorizontalAlignment = horizontalAlignment;
975 mVerticalAlignment = verticalAlignment;
978 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
979 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
980 mExceedPolicy( TextView::Original ),
981 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
982 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
983 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
984 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
985 mLineJustification( layoutParameters.mLineJustification ),
986 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
987 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
991 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
993 mMultilinePolicy = layoutParameters.mMultilinePolicy;
994 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
995 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
996 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
997 mVerticalAlignment = layoutParameters.mVerticalAlignment;
998 mLineJustification = layoutParameters.mLineJustification;
999 mLineHeightOffset = layoutParameters.mLineHeightOffset;
1000 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
1005 TextView::VisualParameters::VisualParameters()
1007 mSortModifier( 0.f ),
1008 mCameraScrollPosition( 0.f, 0.f ),
1009 mSnapshotModeEnabled( false ),
1010 mScrollEnabled( false ),
1011 mScrollPositionTrimmed( false )
1015 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
1016 : mFadeBoundary( visualParameters.mFadeBoundary ),
1017 mSortModifier( visualParameters.mSortModifier ),
1018 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
1019 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
1020 mScrollEnabled( visualParameters.mScrollEnabled ),
1021 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
1025 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters )
1027 mFadeBoundary = visualParameters.mFadeBoundary;
1028 mSortModifier = visualParameters.mSortModifier;
1029 mCameraScrollPosition = visualParameters.mCameraScrollPosition;
1030 mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled;
1031 mScrollEnabled = visualParameters.mScrollEnabled;
1032 mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed;
1037 TextView::RelayoutData::RelayoutData()
1039 mShrinkFactor( 1.f ),
1041 mCharacterLogicalToVisualMap(),
1042 mCharacterVisualToLogicalMap(),
1044 mCharacterLayoutInfoTable(),
1046 mTextSizeForRelayoutOption()
1050 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
1051 : mTextViewSize( relayoutData.mTextViewSize ),
1052 mShrinkFactor( relayoutData.mShrinkFactor ),
1053 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
1054 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
1055 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
1056 mGlyphActors( relayoutData.mGlyphActors ),
1057 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
1058 mLines( relayoutData.mLines ),
1059 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
1063 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
1065 mTextViewSize = relayoutData.mTextViewSize;
1066 mShrinkFactor = relayoutData.mShrinkFactor;
1067 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
1068 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
1069 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
1070 mGlyphActors = relayoutData.mGlyphActors;
1071 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
1072 mLines = relayoutData.mLines;
1073 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1078 TextView::TextView()
1079 : Control( REQUIRES_STYLE_CHANGE_SIGNALS ),
1080 mCurrentStyledText(),
1081 mTextViewProcessorOperations(),
1082 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1083 Toolkit::TextView::Original,
1084 Toolkit::TextView::Original,
1085 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1086 Toolkit::TextView::Left,
1089 mVisualParameters(),
1091 mRelayoutOperations( NO_RELAYOUT ),
1092 mOffscreenRootActor(),
1093 mOffscreenImageActor(),
1094 mOffscreenCameraActor(),
1095 mCurrentOffscreenSize(),
1096 mFrameBufferImage(),
1098 mPanGestureDetector(),
1099 mLockPreviousSnapshotMode( false ),
1100 mPreviousSnapshotModeEnabled( false ),
1101 mMarkUpEnabled( false )
1103 // Creates the ellipsis layout info.
1104 CreateEllipsizeLayout();
1107 TextView::~TextView()
1109 // Destroys offscreen rendering resources.
1110 DestroyOffscreenRenderingResources();
1112 // Destroys scroll pan gesture detector.
1113 if( mPanGestureDetector )
1115 mPanGestureDetector.Reset();
1119 Vector3 TextView::GetNaturalSize()
1121 if( !mTextViewProcessorOperations.empty() )
1123 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1125 if( !mRelayoutData.mGlyphActors.empty() )
1127 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1128 // add them to the text-actor cache.
1129 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1130 mRelayoutData.mGlyphActors.clear();
1132 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1135 PerformTextViewProcessorOperations();
1138 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1141 float TextView::GetHeightForWidth( float width )
1145 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1146 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1147 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1149 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1150 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1151 height = GetNaturalSize().height;
1155 // Check if the given width is different than the current one.
1156 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1158 // Check if the text-view has glyph-actors.
1159 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1161 // Check which layout operations need to be done.
1162 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1164 if( relayoutSizeAndPositionNeeded )
1166 if( hasGlyphActors )
1168 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1169 // add them to the text-actor cache.
1170 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1171 mRelayoutData.mGlyphActors.clear();
1174 // Use the given width.
1175 const Vector2 textViewSize( width, GetControlSize().height );
1177 // Relays-out but doesn't add glyph-actors to the text-view.
1178 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1181 // Retrieve the text height after relayout the text.
1182 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1184 if( differentWidth )
1186 // Revert the relayout operation mask
1187 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1190 if( hasGlyphActors )
1192 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1195 if( differentWidth || hasGlyphActors )
1204 float TextView::GetWidthForHeight( float height )
1206 // TODO: Needs implementing properly, for now just return the natural width.
1207 return GetNaturalSize().width;
1211 void TextView::OnInitialize()
1216 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1218 // Creates the ellipsis layout info.
1219 CreateEllipsizeLayout();
1221 SetText( mCurrentStyledText );
1224 void TextView::OnControlSizeSet( const Vector3& size )
1226 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1228 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1229 mRelayoutOperations = RELAYOUT_ALL;
1231 // Request to be relaid out
1236 void TextView::OnRelayout( const Vector2& size, ActorSizeContainer& container )
1238 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1240 // Not worth to relayout if width or height is equal to zero.
1244 if( size != mRelayoutData.mTextViewSize )
1246 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1247 if( RELAYOUT_ALL != mRelayoutOperations )
1249 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1250 RELAYOUT_REMOVE_TEXT_ACTORS |
1251 RELAYOUT_SIZE_POSITION |
1252 RELAYOUT_ALIGNMENT |
1253 RELAYOUT_VISIBILITY |
1254 RELAYOUT_TEXT_ACTOR_UPDATE |
1255 RELAYOUT_INSERT_TO_TEXT_VIEW );
1259 if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
1260 ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
1262 if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
1264 // If the text of the alignment changes and a fade exceed policy is set,
1265 // some characters may need new TextActor.
1266 mRelayoutOperations = RELAYOUT_ALL;
1270 // Remove glyph-actors from text-view
1271 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1273 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1274 mRelayoutData.mGlyphActors.clear();
1277 if( NO_RELAYOUT != mRelayoutOperations )
1279 // Relays-out and add glyph-actors to the text-view.
1280 DoRelayOut( size, mRelayoutOperations );
1281 ProcessSnapshot( size );
1284 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1285 mRelayoutData.mTextActorCache.ClearTexts();
1288 void TextView::PerformTextViewProcessorOperations()
1290 // Traverse the relayout operation vector ...
1292 // Optimizes some operations.
1293 OptimizeTextViewProcessorOperations();
1295 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1297 const TextViewProcessorMetadata& relayoutMetadata( *it );
1299 switch( relayoutMetadata.mType )
1301 case TextView::TextSet:
1303 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1308 case TextView::TextInserted:
1310 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1311 relayoutMetadata.mText,
1316 case TextView::TextReplaced:
1318 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1319 relayoutMetadata.mNumberOfCharacters,
1320 relayoutMetadata.mText,
1325 case TextView::TextRemoved:
1327 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1328 relayoutMetadata.mNumberOfCharacters,
1331 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1334 case TextView::NewLineHeight:
1336 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1337 mRelayoutData.mTextLayoutInfo );
1340 case TextView::NewStyle:
1342 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1343 relayoutMetadata.mStyleMask,
1350 // Clear all operations when they are done.
1351 mTextViewProcessorOperations.clear();
1354 void TextView::OptimizeTextViewProcessorOperations()
1356 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1358 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1359 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1360 // use the cache without clearing the text-actors.
1362 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1364 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1366 const TextViewProcessorMetadata& relayoutMetadata( *it );
1368 switch( relayoutMetadata.mType )
1370 case TextView::TextRemoved:
1372 bool optimizationDone = false;
1374 if( it + 1u != endIt )
1376 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) );
1377 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1379 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1381 optimizationDone = true;
1382 TextViewProcessorMetadata newRelayoutMetadata;
1383 newRelayoutMetadata.mType = TextView::TextReplaced;
1384 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1385 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1386 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1387 textViewProcessorOperations.push_back( newRelayoutMetadata );
1389 // do not access the TextInserted operation in next iteration.
1395 if( !optimizationDone )
1397 textViewProcessorOperations.push_back( relayoutMetadata );
1403 textViewProcessorOperations.push_back( relayoutMetadata );
1408 mTextViewProcessorOperations = textViewProcessorOperations;
1411 void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask )
1413 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1414 if( !mTextViewProcessorOperations.empty() )
1416 PerformTextViewProcessorOperations();
1419 CombineExceedPolicies();
1422 if( mVisualParameters.mSnapshotModeEnabled )
1424 rootActor = mOffscreenRootActor;
1431 mRelayoutData.mTextViewSize = textViewSize;
1432 switch( mLayoutParameters.mMultilinePolicy )
1434 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1436 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1438 } // SplitByNewLineChar
1440 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1442 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1446 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1448 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1451 } // switch( mMultilinePolicy )
1453 // Remove done operations from the mask.
1454 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1457 void TextView::ProcessSnapshot( const Size& textViewSize )
1459 if( mVisualParameters.mSnapshotModeEnabled )
1461 // If layout options change, it's needed generate a new image.
1463 if( mOffscreenRootActor )
1465 // Set the root actor visible.
1466 // The root actor is set to non visible after the render task is processed.
1467 mOffscreenRootActor.SetVisible( true );
1469 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1470 mOffscreenRootActor.SetSize( textViewSize );
1473 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1474 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1476 // Set the image actor visible.
1477 // The image actor is set to non visible if there is no text to render.
1478 mOffscreenImageActor.SetVisible( true );
1480 // Calculates the offscreen image's size. It takes into account different points:
1481 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1482 // * There is a maximum texture size the graphic subsystem can load on the memory.
1483 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1485 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1486 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1487 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1488 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1490 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1494 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1495 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1496 offscreenSize.height,
1499 // Stores current text-view size to avoid create new Dali resources if text changes.
1500 mCurrentOffscreenSize = offscreenSize;
1502 if( !mOffscreenCameraActor )
1504 // Creates a new camera actor.
1505 mOffscreenCameraActor = CameraActor::New();
1506 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1507 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1508 mOffscreenCameraActor.SetRotation(Degree(180.f), Vector3::YAXIS);
1510 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1512 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1515 // Calculate camera parameters for current text size.
1516 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1519 if( mVisualParameters.mScrollEnabled )
1521 // Updates the offscreen camera position with the new scroll offset.
1522 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1523 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1527 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1528 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1533 // Creates a new render task.
1534 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1536 mRenderTask.SetSourceActor( mOffscreenRootActor );
1537 mRenderTask.SetInputEnabled( false );
1538 mRenderTask.SetClearColor( Color::TRANSPARENT );
1539 mRenderTask.SetClearEnabled( true );
1540 mRenderTask.SetExclusive( true );
1542 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1543 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1548 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1549 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1552 // Process the render task only once every time the text changes or the text-view's size canges.
1553 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1557 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1558 mOffscreenImageActor.SetVisible( false );
1563 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1565 float xPosition = 0.f;
1566 float yPosition = 0.f;
1567 Vector3 parentOrigin = ParentOrigin::CENTER;
1568 Vector3 anchorPoint = AnchorPoint::CENTER;
1570 switch( mLayoutParameters.mHorizontalAlignment )
1572 case Toolkit::Alignment::HorizontalLeft:
1574 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1575 parentOrigin.x = 0.f;
1576 anchorPoint.x = 0.f;
1579 case Toolkit::Alignment::HorizontalCenter:
1584 case Toolkit::Alignment::HorizontalRight:
1586 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1587 parentOrigin.x = 1.f;
1588 anchorPoint.x = 1.f;
1593 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1597 switch( mLayoutParameters.mVerticalAlignment )
1599 case Toolkit::Alignment::VerticalTop:
1601 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1602 parentOrigin.y = 0.f;
1603 anchorPoint.y = 0.f;
1606 case Toolkit::Alignment::VerticalCenter:
1611 case Toolkit::Alignment::VerticalBottom:
1613 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1614 parentOrigin.y = 1.f;
1615 anchorPoint.y = 1.f;
1620 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1624 mOffscreenCameraActor.SetX( xPosition );
1625 mOffscreenCameraActor.SetY( yPosition );
1627 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1628 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1631 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1633 // not to process the offscreen root actor by setting its visibility to false.
1634 mOffscreenRootActor.SetVisible( false );
1636 // Sets the new size and the new frame buffer to the image actor.
1637 // Image actor must have same size as text. Otherwise text can be truncated.
1638 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1639 mOffscreenImageActor.SetImage( mFrameBufferImage );
1642 void TextView::DestroyOffscreenRenderingResources()
1646 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1648 if( Stage::IsInstalled() )
1650 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1653 mRenderTask.Reset();
1656 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1657 if( mOffscreenCameraActor )
1659 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1661 mOffscreenCameraActor.Reset();
1664 if( mOffscreenRootActor )
1666 mOffscreenRootActor.Reset();
1669 if( mOffscreenImageActor )
1671 mOffscreenImageActor.Reset();
1674 mCurrentOffscreenSize = Size( 0.f, 0.f );
1676 if( mFrameBufferImage )
1678 mFrameBufferImage.Reset();
1682 void TextView::OnTextPan( Actor actor, const PanGesture& gesture )
1684 if( 1u == gesture.numberOfTouches )
1686 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1690 void TextView::TrimScrollPosition()
1692 const Vector3& textViewSize = GetControlSize();
1694 // Before use the text's size, relayout the text is needed to get the actual text size.
1695 GetTextLayoutInfo();
1697 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1698 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1699 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1700 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1701 float minVerticalDisplacement = -maxVerticalDisplacement;
1703 // Updates the range if the text is aligned on the right or left.
1704 switch( mLayoutParameters.mHorizontalAlignment )
1706 case Toolkit::Alignment::HorizontalLeft:
1708 maxHorizontalDisplacement *= 2.f;
1709 minHorizontalDisplacement = 0.f;
1712 case Toolkit::Alignment::HorizontalCenter:
1717 case Toolkit::Alignment::HorizontalRight:
1719 maxHorizontalDisplacement = 0.f;
1720 minHorizontalDisplacement *= 2.f;
1725 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1729 // Updates the range if the text is aligned on the top or bottom.
1730 switch( mLayoutParameters.mVerticalAlignment )
1732 case Toolkit::Alignment::VerticalTop:
1734 maxVerticalDisplacement *= 2.f;
1735 minVerticalDisplacement = 0.f;
1738 case Toolkit::Alignment::VerticalCenter:
1743 case Toolkit::Alignment::VerticalBottom:
1745 maxVerticalDisplacement = 0.f;
1746 minVerticalDisplacement *= 2.f;
1751 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1755 // Trims the scroll position to be within the range.
1756 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1757 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1759 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1760 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1763 void TextView::DoSetScrollPosition( const Vector2& position )
1765 // Stores old scroll position.
1766 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1768 // Updates the scroll position
1769 mVisualParameters.mCameraScrollPosition = position;
1771 // Ensures the text-view is covered with text.
1772 TrimScrollPosition();
1774 // Calculate the difference with the previous scroll position
1775 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1776 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1778 if( mOffscreenRootActor )
1780 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1782 mOffscreenRootActor.SetVisible( true );
1785 if( mOffscreenCameraActor )
1787 // Update the offscreen camera with the new scroll position.
1788 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1789 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1794 // Refresh the render-task.
1795 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1799 Toolkit::TextView handle( GetOwner() );
1800 mScrolledSignal.Emit( handle, delta );
1803 void TextView::CombineExceedPolicies()
1805 // Calculates the combination of exceed policies.
1807 switch( mLayoutParameters.mWidthExceedPolicy )
1809 case Toolkit::TextView::Original:
1811 switch( mLayoutParameters.mHeightExceedPolicy )
1813 case Toolkit::TextView::Original:
1815 mLayoutParameters.mExceedPolicy = Original;
1818 case Toolkit::TextView::Fade:
1820 mLayoutParameters.mExceedPolicy = OriginalFade;
1823 case Toolkit::TextView::ShrinkToFit:
1825 mLayoutParameters.mExceedPolicy = OriginalShrink;
1830 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1835 case Toolkit::TextView::Split:
1837 switch( mLayoutParameters.mHeightExceedPolicy )
1839 case Toolkit::TextView::Original:
1841 mLayoutParameters.mExceedPolicy = SplitOriginal;
1844 case Toolkit::TextView::Fade:
1846 mLayoutParameters.mExceedPolicy = SplitFade;
1849 case Toolkit::TextView::ShrinkToFit:
1851 mLayoutParameters.mExceedPolicy = SplitShrink;
1854 case Toolkit::TextView::EllipsizeEnd:
1856 mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd;
1861 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1866 case Toolkit::TextView::Fade:
1868 switch( mLayoutParameters.mHeightExceedPolicy )
1870 case Toolkit::TextView::Original:
1872 mLayoutParameters.mExceedPolicy = FadeOriginal;
1875 case Toolkit::TextView::Fade:
1877 mLayoutParameters.mExceedPolicy = Fade;
1882 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1887 case Toolkit::TextView::ShrinkToFit:
1889 switch( mLayoutParameters.mHeightExceedPolicy )
1891 case Toolkit::TextView::Original:
1893 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1896 case Toolkit::TextView::Fade:
1898 mLayoutParameters.mExceedPolicy = ShrinkFade;
1901 case Toolkit::TextView::ShrinkToFit:
1903 mLayoutParameters.mExceedPolicy = Shrink;
1908 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1913 case Toolkit::TextView::EllipsizeEnd:
1915 switch( mLayoutParameters.mHeightExceedPolicy )
1917 case Toolkit::TextView::Original:
1919 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1922 case Toolkit::TextView::EllipsizeEnd:
1924 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1929 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1936 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1941 Actor TextView::GetRootActor() const
1943 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1947 if( mVisualParameters.mSnapshotModeEnabled )
1949 rootActor = mOffscreenRootActor;
1959 void TextView::CreateEllipsizeLayout()
1961 // Creates the ellipsis layout info for the ellipsis text and styles.
1962 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1963 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
1964 TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
1965 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
1966 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1969 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
1971 bool newValue( propertyValue.Get<bool>() );
1972 if( newValue != IsMarkupProcessingEnabled() )
1974 SetMarkupProcessingEnabled( newValue );
1977 // If markup processing has been enabled, Ensure current text is reprocessed.
1978 const std::string& currentText( GetText() );
1979 if( ! currentText.empty() )
1981 SetText( currentText );
1987 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1989 std::string policyName( propertyValue.Get<std::string>() );
1990 if(policyName == "SplitByNewLineChar")
1992 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1994 else if(policyName == "SplitByWord")
1996 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1998 else if(policyName == "SplitByChar")
2000 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
2004 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
2008 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
2010 std::string policyName( propertyValue.Get<std::string>() );
2011 if(policyName == "Original")
2013 SetWidthExceedPolicy(Toolkit::TextView::Original);
2015 else if(policyName == "Fade")
2017 SetWidthExceedPolicy(Toolkit::TextView::Fade);
2019 else if(policyName == "Split")
2021 SetWidthExceedPolicy(Toolkit::TextView::Split);
2023 else if(policyName == "ShrinkToFit")
2025 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
2027 else if(policyName == "EllipsizeEnd")
2029 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
2033 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
2037 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
2039 std::string policyName( propertyValue.Get<std::string>() );
2040 if(policyName == "Original")
2042 SetHeightExceedPolicy(Toolkit::TextView::Original);
2044 else if(policyName == "Fade")
2046 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2048 else if(policyName == "Split")
2050 SetHeightExceedPolicy(Toolkit::TextView::Split);
2052 else if(policyName == "ShrinkToFit")
2054 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2058 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2062 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2064 std::string policyName( propertyValue.Get<std::string>() );
2065 if(policyName == "Left")
2067 SetLineJustification(Toolkit::TextView::Left);
2069 else if(policyName == "Center")
2071 SetLineJustification(Toolkit::TextView::Center);
2073 else if(policyName == "Right")
2075 SetLineJustification(Toolkit::TextView::Right);
2077 else if(policyName == "Justified")
2079 SetLineJustification(Toolkit::TextView::Justified);
2083 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2087 void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue )
2089 Vector4 value( propertyValue.Get<Vector4>() );
2090 DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f )
2091 && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " );
2093 Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast<unsigned int>( value.x ) ),
2094 PixelSize( static_cast<unsigned int>( value.y ) ),
2095 PixelSize( static_cast<unsigned int>( value.z ) ),
2096 PixelSize( static_cast<unsigned int>( value.w ) ) );
2098 SetFadeBoundary( fadeBoundary );
2101 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2103 std::string value( propertyValue.Get<std::string>() );
2105 if( propertyIndex == Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT )
2107 if(value == "HorizontalLeft")
2109 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2111 else if( value == "HorizontalCenter")
2113 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2115 else if( value == "HorizontalRight")
2117 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2121 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2124 else if( propertyIndex == Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT )
2126 if( value == "VerticalTop" )
2128 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2130 else if( value == "VerticalCenter")
2132 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2134 else if( value == "VerticalBottom")
2136 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2140 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2146 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
2147 if( RELAYOUT_ALL != mRelayoutOperations )
2149 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
2150 RELAYOUT_TEXT_ACTOR_UPDATE |
2151 RELAYOUT_ALIGNMENT |
2152 RELAYOUT_VISIBILITY );
2156 std::string TextView::OnHorizontalAlignmentPropertyGet()
2158 if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft )
2160 return "HorizontalLeft";
2162 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter )
2164 return "HorizontalCenter";
2166 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight )
2168 return "HorizontalRight";
2172 DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." );
2176 std::string TextView::OnVerticalAlignmentPropertyGet()
2178 if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop )
2180 return "VerticalTop";
2182 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter )
2184 return "VerticalCenter";
2186 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom )
2188 return "VerticalBottom";
2192 DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." );
2196 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2198 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2202 TextView& textViewImpl( GetImpl( textView ) );
2205 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2207 textViewImpl.OnMarkupEnabledPeopertySet( value );
2210 case Toolkit::TextView::PROPERTY_TEXT:
2212 textViewImpl.SetText( value.Get<std::string>() );
2215 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2217 textViewImpl.OnMultilinePolicyPropertySet( value );
2220 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2222 textViewImpl.OnWidthExceedPolicyPropertySet( value );
2225 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2227 textViewImpl.OnHeightExceedPolicyPropertySet( value );
2230 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2232 textViewImpl.OnLineJustificationPropertySet( value );
2235 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2237 textViewImpl.OnFadeBoundaryPropertySet( value );
2240 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2242 Dali::PointSize pointSize( value.Get<float>() );
2243 textViewImpl.SetLineHeightOffset(pointSize);
2246 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2247 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2249 textViewImpl.OnAlignmentPropertySet( index, value );
2256 Property::Value TextView::GetProperty( BaseObject* object, Property::Index index )
2258 Property::Value value;
2260 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2264 TextView& textViewImpl( GetImpl( textView ) );
2267 case Toolkit::TextView::PROPERTY_MARKUP_ENABLED:
2269 value = textViewImpl.IsMarkupProcessingEnabled();
2272 case Toolkit::TextView::PROPERTY_TEXT:
2274 value = textViewImpl.GetText();
2277 case Toolkit::TextView::PROPERTY_MULTILINE_POLICY:
2279 value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ];
2282 case Toolkit::TextView::PROPERTY_WIDTH_EXCEED_POLICY:
2284 value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ];
2287 case Toolkit::TextView::PROPERTY_HEIGHT_EXCEED_POLICY:
2289 value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ];
2292 case Toolkit::TextView::PROPERTY_LINE_JUSTIFICATION:
2294 value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ];
2297 case Toolkit::TextView::PROPERTY_FADE_BOUNDARY:
2299 Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary();
2300 value = Vector4( static_cast<float>( boundary.mLeft.value ),
2301 static_cast<float>( boundary.mRight.value ),
2302 static_cast<float>( boundary.mTop.value ),
2303 static_cast<float>( boundary.mBottom.value ) );
2306 case Toolkit::TextView::PROPERTY_LINE_HEIGHT_OFFSET:
2308 value = textViewImpl.GetLineHeightOffset().value;
2311 case Toolkit::TextView::PROPERTY_HORIZONTAL_ALIGNMENT:
2313 value = textViewImpl.OnHorizontalAlignmentPropertyGet();
2316 case Toolkit::TextView::PROPERTY_VERTICAL_ALIGNMENT:
2318 value = textViewImpl.OnVerticalAlignmentPropertyGet();
2326 } // namespace Internal
2328 } // namespace Toolkit