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/object/type-registry-helper.h>
25 #include <dali/public-api/render-tasks/render-task-list.h>
28 #include <dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h>
29 #include <dali-toolkit/internal/controls/text-view/split-by-word-policies.h>
30 #include <dali-toolkit/internal/controls/text-view/split-by-char-policies.h>
31 #include <dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h>
32 #include <dali-toolkit/internal/controls/text-view/text-view-processor.h>
33 #include <dali-toolkit/internal/controls/text-view/text-view-word-processor.h>
34 #include <dali-toolkit/internal/controls/text-view/relayout-utilities.h>
48 const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"};
49 const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"};
50 const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"};
52 // Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
53 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
58 return Toolkit::TextView::New();
61 // Setup properties, signals and actions using the type-registry.
62 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextView, Toolkit::Control, Create );
64 DALI_PROPERTY_REGISTRATION( TextView, "markup-enabled", BOOLEAN, MARKUP_ENABLED )
65 DALI_PROPERTY_REGISTRATION( TextView, "text", STRING, TEXT )
66 DALI_PROPERTY_REGISTRATION( TextView, "multiline-policy", STRING, MULTILINE_POLICY )
67 DALI_PROPERTY_REGISTRATION( TextView, "width-exceed-policy", STRING, WIDTH_EXCEED_POLICY )
68 DALI_PROPERTY_REGISTRATION( TextView, "height-exceed-policy", STRING, HEIGHT_EXCEED_POLICY )
69 DALI_PROPERTY_REGISTRATION( TextView, "line-justification", STRING, LINE_JUSTIFICATION )
70 DALI_PROPERTY_REGISTRATION( TextView, "fade-boundary", VECTOR4, FADE_BOUNDARY )
71 DALI_PROPERTY_REGISTRATION( TextView, "line-height-offset", FLOAT, LINE_HEIGHT_OFFSET )
72 DALI_PROPERTY_REGISTRATION( TextView, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT )
73 DALI_PROPERTY_REGISTRATION( TextView, "vertical-alignment", STRING, VERTICAL_ALIGNMENT )
75 DALI_SIGNAL_REGISTRATION( TextView, "scrolled", SIGNAL_TEXT_SCROLLED )
77 DALI_TYPE_REGISTRATION_END()
80 * Whether the text-view-processor operation sets, inserts, replaces, removes text.
82 * @param[in] metadata The text-view-processor operation.
84 * @return \e true if the given text-view-processor operation is modifying the text.
86 bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata )
88 return ( ( metadata.mType == TextView::TextSet ) ||
89 ( metadata.mType == TextView::TextInserted ) ||
90 ( metadata.mType == TextView::TextReplaced ) ||
91 ( metadata.mType == TextView::TextRemoved ) ||
92 ( metadata.mType == TextView::NewStyle ));
96 * Whether the text-view-processor operation sets a new line height offset.
98 * @param[in] metadata The text-view-processor operation.
100 * @return \e true if the given text-view-processor operation sets a new line height offset.
102 bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata )
104 return ( metadata.mType == TextView::NewLineHeight );
108 * Whether the text-view-processor operation sets a new style.
110 * @param[in] metadata The text-view-processor operation.
112 * @return \e true if the given text-view-processor operation sets a new style.
114 bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata )
116 return ( metadata.mType == TextView::NewStyle );
121 TextView::TextViewProcessorMetadata::TextViewProcessorMetadata()
122 : mType( TextView::TextSet ),
124 mNumberOfCharacters( 0u ),
126 mStyleMask(TextStyle::NONE)
130 Toolkit::TextView TextView::New()
132 // Create the implementation, temporarily owned on stack
133 IntrusivePtr<TextView> textView = new TextView();
135 // Pass ownership to CustomActor
136 Toolkit::TextView handle( *textView );
138 // Second-phase init of the implementation
139 // This can only be done after the CustomActor connection has been made...
140 textView->Initialize();
142 // Disables by default the offscreen rendering.
143 textView->SetSnapshotModeEnabled( false );
148 void TextView::SetText( const std::string& text )
150 // Creates a styled text with the markup or plain string.
151 MarkupProcessor::StyledTextArray styledText;
152 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
154 // Calls SetText() with the styled text array.
155 SetText( styledText );
158 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
160 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
161 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
163 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
164 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
166 // Creates metadata with the Set operation.
167 TextViewProcessorMetadata metadata;
168 metadata.mType = TextView::TextSet;
169 metadata.mText = text;
172 mTextViewProcessorOperations.push_back( metadata );
174 // Updates current styled text.
175 mCurrentStyledText = text;
177 // Request to be relaid out
180 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
181 mRelayoutOperations = RELAYOUT_ALL;
184 void TextView::InsertTextAt( std::size_t position, const std::string& text )
186 // Creates a styled text with the markup or plain string.
187 MarkupProcessor::StyledTextArray styledText;
188 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
190 // Calls InsertTextAt() with the styled text array.
191 InsertTextAt( position, styledText );
194 void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text )
197 MarkupProcessor::GetPlainString( text, textStr );
199 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
200 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
202 // Temporary fix. Creates the whole layout if there is rtl text.
204 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
205 textToSet.insert( textToSet.begin() + position, text.begin(), text.end() );
206 SetText( textToSet );
210 // Creates metadata with the Insert operation.
211 TextViewProcessorMetadata metadata;
212 metadata.mType = TextView::TextInserted;
213 metadata.mPosition = position;
214 metadata.mText = text;
217 mTextViewProcessorOperations.push_back( metadata );
219 // Updates current styled text.
220 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
222 // Request to be relaid out
225 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
226 mRelayoutOperations = RELAYOUT_ALL;
230 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text )
232 // Creates a styled text with the markup or plain string.
233 MarkupProcessor::StyledTextArray styledText;
234 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
236 // Calls ReplaceTextFromTo() with the styled text array.
237 ReplaceTextFromTo( position, numberOfCharacters, styledText );
240 void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
243 MarkupProcessor::GetPlainString( text, textStr );
245 if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) ||
246 TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
248 // Temporary fix. Creates the whole layout if there is rtl text.
250 // Updates current styled text.
251 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
253 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
254 textToSet.erase( it, it + numberOfCharacters );
255 it = textToSet.begin() + position;
256 textToSet.insert( it, text.begin(), text.end() );
258 SetText( textToSet );
262 // Creates metadata with the Insert operation.
263 TextViewProcessorMetadata metadata;
264 metadata.mType = TextView::TextReplaced;
265 metadata.mPosition = position;
266 metadata.mNumberOfCharacters = numberOfCharacters;
267 metadata.mText = text;
270 mTextViewProcessorOperations.push_back( metadata );
272 // Updates current styled text.
273 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
274 mCurrentStyledText.erase( it, it + numberOfCharacters );
275 it = mCurrentStyledText.begin() + position;
276 mCurrentStyledText.insert( it, text.begin(), text.end() );
278 // Request to be relaid out
281 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
282 mRelayoutOperations = RELAYOUT_ALL;
286 void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters )
288 if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) )
290 // Temporary fix. Creates the whole layout if there is rtl text.
292 // Updates current styled text.
293 MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText;
294 MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position;
295 textToSet.erase( it, it + numberOfCharacters );
297 SetText( textToSet );
301 // Creates metadata with the Remove operation.
302 TextViewProcessorMetadata metadata;
303 metadata.mType = TextView::TextRemoved;
304 metadata.mPosition = position;
305 metadata.mNumberOfCharacters = numberOfCharacters;
308 mTextViewProcessorOperations.push_back( metadata );
310 // Updates current styled text.
311 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
312 mCurrentStyledText.erase( it, it + numberOfCharacters );
314 // Request to be relaid out
317 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
318 mRelayoutOperations = RELAYOUT_ALL;
322 std::string TextView::GetText() const
324 // Traverses the styled text array getting only the text.
325 // Note that for some languages a 'character' could be represented by more than one 'char'
328 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
330 text.append( (*it).mText.GetText() );
336 void TextView::SetLineHeightOffset( PointSize offset )
338 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
340 // Removes any previous operation which modifies the line height offset.
341 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
342 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
344 // Creates metadata with the new line height operation.
345 TextViewProcessorMetadata metadata;
346 metadata.mType = TextView::NewLineHeight;
348 mTextViewProcessorOperations.push_back( metadata );
350 // Updates line height offset.
351 mLayoutParameters.mLineHeightOffset = offset;
355 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
356 if( RELAYOUT_ALL != mRelayoutOperations )
358 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
359 RELAYOUT_REMOVE_TEXT_ACTORS |
360 RELAYOUT_SIZE_POSITION |
362 RELAYOUT_VISIBILITY |
363 RELAYOUT_TEXT_ACTOR_UPDATE |
364 RELAYOUT_INSERT_TO_TEXT_VIEW );
369 PointSize TextView::GetLineHeightOffset() const
371 return PointSize( mLayoutParameters.mLineHeightOffset );
374 void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask )
376 if( !mCurrentStyledText.empty() )
378 const bool checkFontName = mask & TextStyle::FONT;
379 const bool checkFontSize = mask & TextStyle::SIZE;
380 const bool checkFontStyle = mask & TextStyle::STYLE;
382 // Check first if metrics have changed.
383 bool metricsChanged = false;
384 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
386 const MarkupProcessor::StyledText& styledText( *it );
388 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
389 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
390 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
395 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
397 // If metrics change, new text measurements are needed.
398 SetText( mCurrentStyledText );
402 // Deletes any previous operation which sets a new style.
403 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
404 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
406 // Creates metadata with the new style operation.
407 TextViewProcessorMetadata metadata;
408 metadata.mType = TextView::NewStyle;
410 MarkupProcessor::StyledText text;
412 metadata.mText.push_back( text );
413 metadata.mStyleMask = mask;
415 mTextViewProcessorOperations.push_back( metadata );
417 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
421 if( RELAYOUT_ALL != mRelayoutOperations )
423 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
424 RELAYOUT_TEXT_ACTOR_UPDATE );
429 // Sets the new style to the ellipsize text
430 // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors.
431 if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() )
433 for( Vector<TextStyle*>::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(),
434 endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End();
438 (*it)->Copy( style, mask );
441 SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles );
445 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
447 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
449 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
450 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
451 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
452 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
453 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
454 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
456 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
457 mLayoutParameters.mVerticalAlignment = verticalAlignment;
461 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
462 if( RELAYOUT_ALL != mRelayoutOperations )
464 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
465 RELAYOUT_TEXT_ACTOR_UPDATE |
467 RELAYOUT_VISIBILITY );
472 Toolkit::Alignment::Type TextView::GetTextAlignment() const
474 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
477 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
479 if( policy != mLayoutParameters.mMultilinePolicy )
481 mLayoutParameters.mMultilinePolicy = policy;
483 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
484 mRelayoutOperations = RELAYOUT_ALL;
490 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
492 return mLayoutParameters.mMultilinePolicy;
495 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
497 // The layout info could be invalid depending on the current exceed policy and the new one.
498 // i.e. if the current policy is Split and the new one is ShrinkToFit then
499 // the layout info generated for each char is not needed.
500 if( policy != mLayoutParameters.mWidthExceedPolicy )
502 mLayoutParameters.mWidthExceedPolicy = policy;
504 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
505 mRelayoutOperations = RELAYOUT_ALL;
511 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
513 return mLayoutParameters.mWidthExceedPolicy;
516 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
518 if( policy != mLayoutParameters.mHeightExceedPolicy )
520 mLayoutParameters.mHeightExceedPolicy = policy;
524 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
525 if( RELAYOUT_ALL != mRelayoutOperations )
527 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
528 RELAYOUT_REMOVE_TEXT_ACTORS |
529 RELAYOUT_SIZE_POSITION |
531 RELAYOUT_VISIBILITY |
532 RELAYOUT_TEXT_ACTOR_UPDATE |
533 RELAYOUT_INSERT_TO_TEXT_VIEW );
538 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
540 return mLayoutParameters.mHeightExceedPolicy;
543 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
545 if( justification != mLayoutParameters.mLineJustification )
547 mLayoutParameters.mLineJustification = justification;
551 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
552 if( RELAYOUT_ALL != mRelayoutOperations )
554 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
555 RELAYOUT_REMOVE_TEXT_ACTORS |
556 RELAYOUT_SIZE_POSITION |
558 RELAYOUT_VISIBILITY |
559 RELAYOUT_TEXT_ACTOR_UPDATE |
560 RELAYOUT_INSERT_TO_TEXT_VIEW );
565 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
567 return mLayoutParameters.mLineJustification;
570 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
572 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
573 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
574 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
575 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
577 mVisualParameters.mFadeBoundary = fadeBoundary;
581 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
582 if( RELAYOUT_ALL != mRelayoutOperations )
584 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
585 RELAYOUT_REMOVE_TEXT_ACTORS |
586 RELAYOUT_VISIBILITY |
587 RELAYOUT_TEXT_ACTOR_UPDATE |
588 RELAYOUT_INSERT_TO_TEXT_VIEW );
593 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
595 return mVisualParameters.mFadeBoundary;
598 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
600 // Creates a styled text with the markup or plain string.
601 MarkupProcessor::StyledTextArray styledText;
602 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
604 // Creates the ellipsis layout info and sets the text and styles.
605 SetEllipsizeText( styledText );
608 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
610 // Converts the styled text array into a Text and a vector of TextStyles.
612 Vector<TextStyle*> styles;
613 for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it )
615 const MarkupProcessor::StyledText& styledText( *it );
617 text.Append( styledText.mText );
618 styles.PushBack( new TextStyle( styledText.mStyle ) );
621 // Creates the ellipsis layout info and sets the text and styles.
622 SetEllipsizeText( text, styles );
625 void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector<TextStyle*>& ellipsizeStyles )
627 // Sets the text and styles for the ellipsis text.
628 mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText;
629 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles;
631 // Creates the ellipsis layout info.
632 CreateEllipsizeLayout();
634 // Request to be relaid out
637 mRelayoutOperations = RELAYOUT_ALL;
640 std::string TextView::GetEllipsizeText() const
642 return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText();
645 void TextView::GetTextLayoutInfo()
647 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
648 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
649 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
651 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
653 Vector3 textViewSize = GetControlSize();
655 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
656 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
657 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
658 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
659 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
661 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
662 // the text natural size can be used.
663 textViewSize = GetNaturalSize();
666 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
667 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
669 // Check if the text-view has glyph-actors.
670 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
672 RelayoutOperationMask mask = NO_RELAYOUT;
673 if( relayoutSizeAndPositionNeeded )
675 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
677 if( relayoutAlignmentNeeded )
679 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
681 if( relayoutVisibilityNeeded )
683 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
688 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
689 // add them to the text-actor cache.
690 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
691 mRelayoutData.mGlyphActors.clear();
694 // Relays-out but doesn't add glyph-actors to the text-view.
695 DoRelayOut( textViewSize.GetVectorXY(), mask );
699 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
705 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
709 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
710 textLayoutInfo.mLines = mRelayoutData.mLines;
712 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
713 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
715 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
717 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
720 void TextView::SetSortModifier( float depthOffset )
722 mVisualParameters.mSortModifier = depthOffset;
724 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
728 ( *it ).SetSortModifier( depthOffset );
731 if( mOffscreenImageActor )
733 mOffscreenImageActor.SetSortModifier( depthOffset );
737 void TextView::SetSnapshotModeEnabled( bool enable )
739 if( enable != mVisualParameters.mSnapshotModeEnabled )
741 // Remove first all glyph-actors
742 if( !mRelayoutData.mGlyphActors.empty() )
744 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
747 mVisualParameters.mSnapshotModeEnabled = enable;
748 if( !mLockPreviousSnapshotMode )
750 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
751 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
753 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
754 // to smash the stored value.
755 mPreviousSnapshotModeEnabled = enable;
758 if( mVisualParameters.mSnapshotModeEnabled )
760 // Create a root actor and an image actor for offscreen rendering.
761 mOffscreenRootActor = Layer::New();
762 mOffscreenImageActor = ImageActor::New();
764 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
765 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
766 mOffscreenRootActor.SetInheritOrientation( false );
767 mOffscreenRootActor.SetInheritScale( false );
768 mOffscreenRootActor.SetDepthTestDisabled( true );
770 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
772 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
773 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
774 mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA,
775 BlendingFactor::ONE, BlendingFactor::ONE );
778 self.Add( mOffscreenRootActor );
779 self.Add( mOffscreenImageActor );
780 mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) );
786 if( mOffscreenRootActor )
788 self.Remove( mOffscreenRootActor );
791 if( mOffscreenImageActor )
793 self.Remove( mOffscreenImageActor );
796 DestroyOffscreenRenderingResources();
799 if( RELAYOUT_ALL != mRelayoutOperations )
801 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
802 RELAYOUT_REMOVE_TEXT_ACTORS |
803 RELAYOUT_TEXT_ACTOR_UPDATE |
804 RELAYOUT_INSERT_TO_TEXT_VIEW );
810 bool TextView::IsSnapshotModeEnabled() const
812 return mVisualParameters.mSnapshotModeEnabled;
815 void TextView::SetMarkupProcessingEnabled( bool enable )
817 mMarkUpEnabled = enable;
820 bool TextView::IsMarkupProcessingEnabled() const
822 return mMarkUpEnabled;
825 void TextView::SetScrollEnabled( bool enable )
827 if( enable != mVisualParameters.mScrollEnabled )
829 mVisualParameters.mScrollEnabled = enable;
831 if( mVisualParameters.mScrollEnabled )
833 // Offscreen rendering is needed to enable text scroll.
835 // Stores previous value of the snapshot mode.
836 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
839 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
840 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
841 Lock lock( mLockPreviousSnapshotMode );
842 SetSnapshotModeEnabled( true );
845 // Creates the pan gesture detector and attach the text-view.
846 mPanGestureDetector = PanGestureDetector::New();
847 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
848 mPanGestureDetector.Attach( Self() );
852 // Removes the pan gesture detector.
853 if( mPanGestureDetector )
855 mPanGestureDetector.Detach( Self() );
856 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
857 mPanGestureDetector.Reset();
860 // Restores the previous state for snapshot mode.
861 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
866 bool TextView::IsScrollEnabled() const
868 return mVisualParameters.mScrollEnabled;
871 void TextView::SetScrollPosition( const Vector2& position )
873 if( position != mVisualParameters.mCameraScrollPosition )
875 // Guard against destruction during signal emission
876 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
877 Toolkit::TextView handle( GetOwner() );
879 DoSetScrollPosition( position );
881 // Check if the new scroll position has been trimmed.
882 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
886 const Vector2& TextView::GetScrollPosition() const
888 return mVisualParameters.mCameraScrollPosition;
891 bool TextView::IsScrollPositionTrimmed() const
893 return mVisualParameters.mScrollPositionTrimmed;
896 Toolkit::TextView::ScrolledSignalType& TextView::ScrolledSignal()
898 return mScrolledSignal;
901 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
903 Dali::BaseHandle handle( object );
905 bool connected( true );
906 Toolkit::TextView textView = Toolkit::TextView::DownCast( handle );
908 if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_SCROLLED ) )
910 textView.ScrolledSignal().Connect( tracker, functor );
914 // signalName does not match any signal
921 TextView::LayoutParameters::LayoutParameters()
922 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
923 mExceedPolicy( TextView::Original ),
924 mWidthExceedPolicy( Toolkit::TextView::Original ),
925 mHeightExceedPolicy( Toolkit::TextView::Original ),
926 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
927 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
928 mLineJustification( Toolkit::TextView::Left ),
929 mLineHeightOffset( 0.f ),
930 mMarkUpEnabled( false )
934 TextView::LayoutParameters::~LayoutParameters()
938 TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy,
939 Toolkit::TextView::ExceedPolicy widthExceedPolicy,
940 Toolkit::TextView::ExceedPolicy heightExceedPolicy,
941 Toolkit::Alignment::Type alignmentType,
942 Toolkit::TextView::LineJustification lineJustification,
943 float lineHeightOffset,
945 : mMultilinePolicy( multilinePolicy ),
946 mExceedPolicy( TextView::Original ),
947 mWidthExceedPolicy( widthExceedPolicy ),
948 mHeightExceedPolicy( heightExceedPolicy ),
949 mHorizontalAlignment(),
950 mVerticalAlignment(),
951 mLineJustification( lineJustification ),
952 mLineHeightOffset( lineHeightOffset ),
953 mMarkUpEnabled( markUpEnabled )
956 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
957 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
958 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
959 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
960 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
961 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
963 mHorizontalAlignment = horizontalAlignment;
964 mVerticalAlignment = verticalAlignment;
967 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
968 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
969 mExceedPolicy( TextView::Original ),
970 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
971 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
972 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
973 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
974 mLineJustification( layoutParameters.mLineJustification ),
975 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
976 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
980 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
982 mMultilinePolicy = layoutParameters.mMultilinePolicy;
983 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
984 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
985 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
986 mVerticalAlignment = layoutParameters.mVerticalAlignment;
987 mLineJustification = layoutParameters.mLineJustification;
988 mLineHeightOffset = layoutParameters.mLineHeightOffset;
989 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
994 TextView::VisualParameters::VisualParameters()
996 mSortModifier( 0.f ),
997 mCameraScrollPosition( 0.f, 0.f ),
998 mSnapshotModeEnabled( false ),
999 mScrollEnabled( false ),
1000 mScrollPositionTrimmed( false )
1004 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
1005 : mFadeBoundary( visualParameters.mFadeBoundary ),
1006 mSortModifier( visualParameters.mSortModifier ),
1007 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
1008 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
1009 mScrollEnabled( visualParameters.mScrollEnabled ),
1010 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
1014 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::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;
1026 TextView::RelayoutData::RelayoutData()
1028 mShrinkFactor( 1.f ),
1030 mCharacterLogicalToVisualMap(),
1031 mCharacterVisualToLogicalMap(),
1033 mCharacterLayoutInfoTable(),
1035 mTextSizeForRelayoutOption()
1039 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
1040 : mTextViewSize( relayoutData.mTextViewSize ),
1041 mShrinkFactor( relayoutData.mShrinkFactor ),
1042 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
1043 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
1044 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
1045 mGlyphActors( relayoutData.mGlyphActors ),
1046 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
1047 mLines( relayoutData.mLines ),
1048 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
1052 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
1054 mTextViewSize = relayoutData.mTextViewSize;
1055 mShrinkFactor = relayoutData.mShrinkFactor;
1056 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
1057 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
1058 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
1059 mGlyphActors = relayoutData.mGlyphActors;
1060 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
1061 mLines = relayoutData.mLines;
1062 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1067 TextView::TextView()
1068 : Control( REQUIRES_STYLE_CHANGE_SIGNALS ),
1069 mCurrentStyledText(),
1070 mTextViewProcessorOperations(),
1071 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1072 Toolkit::TextView::Original,
1073 Toolkit::TextView::Original,
1074 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1075 Toolkit::TextView::Left,
1078 mVisualParameters(),
1080 mRelayoutOperations( NO_RELAYOUT ),
1081 mOffscreenRootActor(),
1082 mOffscreenImageActor(),
1083 mOffscreenCameraActor(),
1084 mCurrentOffscreenSize(),
1085 mFrameBufferImage(),
1087 mPanGestureDetector(),
1088 mLockPreviousSnapshotMode( false ),
1089 mPreviousSnapshotModeEnabled( false ),
1090 mMarkUpEnabled( false )
1092 // Creates the ellipsis layout info.
1093 CreateEllipsizeLayout();
1096 TextView::~TextView()
1098 // Destroys offscreen rendering resources.
1099 DestroyOffscreenRenderingResources();
1101 // Destroys scroll pan gesture detector.
1102 if( mPanGestureDetector )
1104 mPanGestureDetector.Reset();
1108 Vector3 TextView::GetNaturalSize()
1110 if( !mTextViewProcessorOperations.empty() )
1112 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1114 if( !mRelayoutData.mGlyphActors.empty() )
1116 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1117 // add them to the text-actor cache.
1118 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1119 mRelayoutData.mGlyphActors.clear();
1121 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1124 PerformTextViewProcessorOperations();
1127 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1130 float TextView::GetHeightForWidth( float width )
1134 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1135 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1136 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1138 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1139 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1140 height = GetNaturalSize().height;
1144 // Check if the given width is different than the current one.
1145 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1147 // Check if the text-view has glyph-actors.
1148 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1150 // Check which layout operations need to be done.
1151 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1153 if( relayoutSizeAndPositionNeeded )
1155 if( hasGlyphActors )
1157 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1158 // add them to the text-actor cache.
1159 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1160 mRelayoutData.mGlyphActors.clear();
1163 // Use the given width.
1164 const Vector2 textViewSize( width, GetControlSize().height );
1166 // Relays-out but doesn't add glyph-actors to the text-view.
1167 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1170 // Retrieve the text height after relayout the text.
1171 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1173 if( differentWidth )
1175 // Revert the relayout operation mask
1176 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1179 if( hasGlyphActors )
1181 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1184 if( differentWidth || hasGlyphActors )
1193 float TextView::GetWidthForHeight( float height )
1195 // TODO: Needs implementing properly, for now just return the natural width.
1196 return GetNaturalSize().width;
1200 void TextView::OnInitialize()
1202 // The actor handle needs to be inialised for this to work
1203 Self().SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS );
1207 void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
1209 // Creates the ellipsis layout info.
1210 CreateEllipsizeLayout();
1212 SetText( mCurrentStyledText );
1215 void TextView::OnControlSizeSet( const Vector3& size )
1217 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1219 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1220 mRelayoutOperations = RELAYOUT_ALL;
1222 // Request to be relaid out
1227 void TextView::OnRelayout( const Vector2& size, RelayoutContainer& container )
1229 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1231 // Not worth to relayout if width or height is equal to zero.
1235 if( size != mRelayoutData.mTextViewSize )
1237 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1238 if( RELAYOUT_ALL != mRelayoutOperations )
1240 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1241 RELAYOUT_REMOVE_TEXT_ACTORS |
1242 RELAYOUT_SIZE_POSITION |
1243 RELAYOUT_ALIGNMENT |
1244 RELAYOUT_VISIBILITY |
1245 RELAYOUT_TEXT_ACTOR_UPDATE |
1246 RELAYOUT_INSERT_TO_TEXT_VIEW );
1250 if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) ||
1251 ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) )
1253 if( mRelayoutOperations & RELAYOUT_ALIGNMENT )
1255 // If the text of the alignment changes and a fade exceed policy is set,
1256 // some characters may need new TextActor.
1257 mRelayoutOperations = RELAYOUT_ALL;
1261 // Remove glyph-actors from text-view
1262 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1264 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1265 mRelayoutData.mGlyphActors.clear();
1268 if( NO_RELAYOUT != mRelayoutOperations )
1270 // Relays-out and add glyph-actors to the text-view.
1271 DoRelayOut( size, mRelayoutOperations );
1272 ProcessSnapshot( size );
1275 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1276 mRelayoutData.mTextActorCache.ClearTexts();
1279 void TextView::PerformTextViewProcessorOperations()
1281 // Traverse the relayout operation vector ...
1283 // Optimizes some operations.
1284 OptimizeTextViewProcessorOperations();
1286 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1288 const TextViewProcessorMetadata& relayoutMetadata( *it );
1290 switch( relayoutMetadata.mType )
1292 case TextView::TextSet:
1294 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1299 case TextView::TextInserted:
1301 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1302 relayoutMetadata.mText,
1307 case TextView::TextReplaced:
1309 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1310 relayoutMetadata.mNumberOfCharacters,
1311 relayoutMetadata.mText,
1316 case TextView::TextRemoved:
1318 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1319 relayoutMetadata.mNumberOfCharacters,
1322 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1325 case TextView::NewLineHeight:
1327 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1328 mRelayoutData.mTextLayoutInfo );
1331 case TextView::NewStyle:
1333 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1334 relayoutMetadata.mStyleMask,
1341 // Clear all operations when they are done.
1342 mTextViewProcessorOperations.clear();
1345 void TextView::OptimizeTextViewProcessorOperations()
1347 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1349 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1350 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1351 // use the cache without clearing the text-actors.
1353 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1355 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1357 const TextViewProcessorMetadata& relayoutMetadata( *it );
1359 switch( relayoutMetadata.mType )
1361 case TextView::TextRemoved:
1363 bool optimizationDone = false;
1365 if( it + 1u != endIt )
1367 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) );
1368 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1370 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1372 optimizationDone = true;
1373 TextViewProcessorMetadata newRelayoutMetadata;
1374 newRelayoutMetadata.mType = TextView::TextReplaced;
1375 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1376 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1377 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1378 textViewProcessorOperations.push_back( newRelayoutMetadata );
1380 // do not access the TextInserted operation in next iteration.
1386 if( !optimizationDone )
1388 textViewProcessorOperations.push_back( relayoutMetadata );
1394 textViewProcessorOperations.push_back( relayoutMetadata );
1399 mTextViewProcessorOperations = textViewProcessorOperations;
1402 void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask )
1404 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1405 if( !mTextViewProcessorOperations.empty() )
1407 PerformTextViewProcessorOperations();
1410 CombineExceedPolicies();
1413 if( mVisualParameters.mSnapshotModeEnabled )
1415 rootActor = mOffscreenRootActor;
1422 mRelayoutData.mTextViewSize = textViewSize;
1423 switch( mLayoutParameters.mMultilinePolicy )
1425 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1427 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1429 } // SplitByNewLineChar
1431 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1433 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1437 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1439 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1442 } // switch( mMultilinePolicy )
1444 // Remove done operations from the mask.
1445 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1448 void TextView::ProcessSnapshot( const Size& textViewSize )
1450 if( mVisualParameters.mSnapshotModeEnabled )
1452 // If layout options change, it's needed generate a new image.
1454 if( mOffscreenRootActor )
1456 // Set the root actor visible.
1457 // The root actor is set to non visible after the render task is processed.
1458 mOffscreenRootActor.SetVisible( true );
1460 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1461 mOffscreenRootActor.SetSize( textViewSize );
1464 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1465 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1467 // Set the image actor visible.
1468 // The image actor is set to non visible if there is no text to render.
1469 mOffscreenImageActor.SetVisible( true );
1471 // Calculates the offscreen image's size. It takes into account different points:
1472 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1473 // * There is a maximum texture size the graphic subsystem can load on the memory.
1474 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1476 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1477 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1478 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1479 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1481 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1485 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1486 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1487 offscreenSize.height,
1490 // Stores current text-view size to avoid create new Dali resources if text changes.
1491 mCurrentOffscreenSize = offscreenSize;
1493 if( !mOffscreenCameraActor )
1495 // Creates a new camera actor.
1496 mOffscreenCameraActor = CameraActor::New();
1497 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1498 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1499 mOffscreenCameraActor.SetOrientation(Degree(180.f), Vector3::YAXIS);
1501 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1503 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1506 // Calculate camera parameters for current text size.
1507 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1510 if( mVisualParameters.mScrollEnabled )
1512 // Updates the offscreen camera position with the new scroll offset.
1513 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1514 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1518 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1519 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1524 // Creates a new render task.
1525 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1527 mRenderTask.SetSourceActor( mOffscreenRootActor );
1528 mRenderTask.SetInputEnabled( false );
1529 mRenderTask.SetClearColor( Color::TRANSPARENT );
1530 mRenderTask.SetClearEnabled( true );
1531 mRenderTask.SetExclusive( true );
1533 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1534 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1539 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1540 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1543 // Process the render task only once every time the text changes or the text-view's size canges.
1544 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1548 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1549 mOffscreenImageActor.SetVisible( false );
1554 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1556 float xPosition = 0.f;
1557 float yPosition = 0.f;
1558 Vector3 parentOrigin = ParentOrigin::CENTER;
1559 Vector3 anchorPoint = AnchorPoint::CENTER;
1561 switch( mLayoutParameters.mHorizontalAlignment )
1563 case Toolkit::Alignment::HorizontalLeft:
1565 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1566 parentOrigin.x = 0.f;
1567 anchorPoint.x = 0.f;
1570 case Toolkit::Alignment::HorizontalCenter:
1575 case Toolkit::Alignment::HorizontalRight:
1577 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1578 parentOrigin.x = 1.f;
1579 anchorPoint.x = 1.f;
1584 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1588 switch( mLayoutParameters.mVerticalAlignment )
1590 case Toolkit::Alignment::VerticalTop:
1592 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1593 parentOrigin.y = 0.f;
1594 anchorPoint.y = 0.f;
1597 case Toolkit::Alignment::VerticalCenter:
1602 case Toolkit::Alignment::VerticalBottom:
1604 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1605 parentOrigin.y = 1.f;
1606 anchorPoint.y = 1.f;
1611 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1615 mOffscreenCameraActor.SetX( xPosition );
1616 mOffscreenCameraActor.SetY( yPosition );
1618 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1619 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1622 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1624 // not to process the offscreen root actor by setting its visibility to false.
1625 mOffscreenRootActor.SetVisible( false );
1627 // Sets the new size and the new frame buffer to the image actor.
1628 // Image actor must have same size as text. Otherwise text can be truncated.
1629 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1630 mOffscreenImageActor.SetImage( mFrameBufferImage );
1633 void TextView::DestroyOffscreenRenderingResources()
1637 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1639 if( Stage::IsInstalled() )
1641 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1644 mRenderTask.Reset();
1647 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1648 if( mOffscreenCameraActor )
1650 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1652 mOffscreenCameraActor.Reset();
1655 if( mOffscreenRootActor )
1657 mOffscreenRootActor.Reset();
1660 if( mOffscreenImageActor )
1662 mOffscreenImageActor.Reset();
1665 mCurrentOffscreenSize = Size( 0.f, 0.f );
1667 if( mFrameBufferImage )
1669 mFrameBufferImage.Reset();
1673 void TextView::OnTextPan( Actor actor, const PanGesture& gesture )
1675 if( 1u == gesture.numberOfTouches )
1677 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1681 void TextView::TrimScrollPosition()
1683 const Vector3& textViewSize = GetControlSize();
1685 // Before use the text's size, relayout the text is needed to get the actual text size.
1686 GetTextLayoutInfo();
1688 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1689 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1690 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1691 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1692 float minVerticalDisplacement = -maxVerticalDisplacement;
1694 // Updates the range if the text is aligned on the right or left.
1695 switch( mLayoutParameters.mHorizontalAlignment )
1697 case Toolkit::Alignment::HorizontalLeft:
1699 maxHorizontalDisplacement *= 2.f;
1700 minHorizontalDisplacement = 0.f;
1703 case Toolkit::Alignment::HorizontalCenter:
1708 case Toolkit::Alignment::HorizontalRight:
1710 maxHorizontalDisplacement = 0.f;
1711 minHorizontalDisplacement *= 2.f;
1716 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1720 // Updates the range if the text is aligned on the top or bottom.
1721 switch( mLayoutParameters.mVerticalAlignment )
1723 case Toolkit::Alignment::VerticalTop:
1725 maxVerticalDisplacement *= 2.f;
1726 minVerticalDisplacement = 0.f;
1729 case Toolkit::Alignment::VerticalCenter:
1734 case Toolkit::Alignment::VerticalBottom:
1736 maxVerticalDisplacement = 0.f;
1737 minVerticalDisplacement *= 2.f;
1742 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1746 // Trims the scroll position to be within the range.
1747 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1748 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1750 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1751 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1754 void TextView::DoSetScrollPosition( const Vector2& position )
1756 // Stores old scroll position.
1757 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1759 // Updates the scroll position
1760 mVisualParameters.mCameraScrollPosition = position;
1762 // Ensures the text-view is covered with text.
1763 TrimScrollPosition();
1765 // Calculate the difference with the previous scroll position
1766 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1767 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1769 if( mOffscreenRootActor )
1771 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1773 mOffscreenRootActor.SetVisible( true );
1776 if( mOffscreenCameraActor )
1778 // Update the offscreen camera with the new scroll position.
1779 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1780 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1785 // Refresh the render-task.
1786 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1790 Toolkit::TextView handle( GetOwner() );
1791 mScrolledSignal.Emit( handle, delta );
1794 void TextView::CombineExceedPolicies()
1796 // Calculates the combination of exceed policies.
1798 switch( mLayoutParameters.mWidthExceedPolicy )
1800 case Toolkit::TextView::Original:
1802 switch( mLayoutParameters.mHeightExceedPolicy )
1804 case Toolkit::TextView::Original:
1806 mLayoutParameters.mExceedPolicy = Original;
1809 case Toolkit::TextView::Fade:
1811 mLayoutParameters.mExceedPolicy = OriginalFade;
1814 case Toolkit::TextView::ShrinkToFit:
1816 mLayoutParameters.mExceedPolicy = OriginalShrink;
1821 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1826 case Toolkit::TextView::Split:
1828 switch( mLayoutParameters.mHeightExceedPolicy )
1830 case Toolkit::TextView::Original:
1832 mLayoutParameters.mExceedPolicy = SplitOriginal;
1835 case Toolkit::TextView::Fade:
1837 mLayoutParameters.mExceedPolicy = SplitFade;
1840 case Toolkit::TextView::ShrinkToFit:
1842 mLayoutParameters.mExceedPolicy = SplitShrink;
1845 case Toolkit::TextView::EllipsizeEnd:
1847 mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd;
1852 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1857 case Toolkit::TextView::Fade:
1859 switch( mLayoutParameters.mHeightExceedPolicy )
1861 case Toolkit::TextView::Original:
1863 mLayoutParameters.mExceedPolicy = FadeOriginal;
1866 case Toolkit::TextView::Fade:
1868 mLayoutParameters.mExceedPolicy = Fade;
1873 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1878 case Toolkit::TextView::ShrinkToFit:
1880 switch( mLayoutParameters.mHeightExceedPolicy )
1882 case Toolkit::TextView::Original:
1884 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1887 case Toolkit::TextView::Fade:
1889 mLayoutParameters.mExceedPolicy = ShrinkFade;
1892 case Toolkit::TextView::ShrinkToFit:
1894 mLayoutParameters.mExceedPolicy = Shrink;
1899 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1904 case Toolkit::TextView::EllipsizeEnd:
1906 switch( mLayoutParameters.mHeightExceedPolicy )
1908 case Toolkit::TextView::Original:
1910 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1913 case Toolkit::TextView::EllipsizeEnd:
1915 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1920 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1927 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1932 Actor TextView::GetRootActor() const
1934 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1938 if( mVisualParameters.mSnapshotModeEnabled )
1940 rootActor = mOffscreenRootActor;
1950 void TextView::CreateEllipsizeLayout()
1952 // Creates the ellipsis layout info for the ellipsis text and styles.
1953 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1954 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() );
1955 TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText,
1956 mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles,
1957 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1960 void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue )
1962 bool newValue( propertyValue.Get<bool>() );
1963 if( newValue != IsMarkupProcessingEnabled() )
1965 SetMarkupProcessingEnabled( newValue );
1968 // If markup processing has been enabled, Ensure current text is reprocessed.
1969 const std::string& currentText( GetText() );
1970 if( ! currentText.empty() )
1972 SetText( currentText );
1978 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1980 std::string policyName( propertyValue.Get<std::string>() );
1981 if(policyName == "SplitByNewLineChar")
1983 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1985 else if(policyName == "SplitByWord")
1987 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1989 else if(policyName == "SplitByChar")
1991 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
1995 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
1999 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
2001 std::string policyName( propertyValue.Get<std::string>() );
2002 if(policyName == "Original")
2004 SetWidthExceedPolicy(Toolkit::TextView::Original);
2006 else if(policyName == "Fade")
2008 SetWidthExceedPolicy(Toolkit::TextView::Fade);
2010 else if(policyName == "Split")
2012 SetWidthExceedPolicy(Toolkit::TextView::Split);
2014 else if(policyName == "ShrinkToFit")
2016 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
2018 else if(policyName == "EllipsizeEnd")
2020 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
2024 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
2028 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
2030 std::string policyName( propertyValue.Get<std::string>() );
2031 if(policyName == "Original")
2033 SetHeightExceedPolicy(Toolkit::TextView::Original);
2035 else if(policyName == "Fade")
2037 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2039 else if(policyName == "Split")
2041 SetHeightExceedPolicy(Toolkit::TextView::Split);
2043 else if(policyName == "ShrinkToFit")
2045 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2049 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2053 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2055 std::string policyName( propertyValue.Get<std::string>() );
2056 if(policyName == "Left")
2058 SetLineJustification(Toolkit::TextView::Left);
2060 else if(policyName == "Center")
2062 SetLineJustification(Toolkit::TextView::Center);
2064 else if(policyName == "Right")
2066 SetLineJustification(Toolkit::TextView::Right);
2068 else if(policyName == "Justified")
2070 SetLineJustification(Toolkit::TextView::Justified);
2074 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2078 void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue )
2080 Vector4 value( propertyValue.Get<Vector4>() );
2081 DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f )
2082 && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " );
2084 Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast<unsigned int>( value.x ) ),
2085 PixelSize( static_cast<unsigned int>( value.y ) ),
2086 PixelSize( static_cast<unsigned int>( value.z ) ),
2087 PixelSize( static_cast<unsigned int>( value.w ) ) );
2089 SetFadeBoundary( fadeBoundary );
2092 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2094 std::string value( propertyValue.Get<std::string>() );
2096 if( propertyIndex == Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT )
2098 if(value == "HorizontalLeft")
2100 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2102 else if( value == "HorizontalCenter")
2104 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2106 else if( value == "HorizontalRight")
2108 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2112 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2115 else if( propertyIndex == Toolkit::TextView::Property::VERTICAL_ALIGNMENT )
2117 if( value == "VerticalTop" )
2119 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2121 else if( value == "VerticalCenter")
2123 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2125 else if( value == "VerticalBottom")
2127 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2131 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2137 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
2138 if( RELAYOUT_ALL != mRelayoutOperations )
2140 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
2141 RELAYOUT_TEXT_ACTOR_UPDATE |
2142 RELAYOUT_ALIGNMENT |
2143 RELAYOUT_VISIBILITY );
2147 std::string TextView::OnHorizontalAlignmentPropertyGet()
2149 if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft )
2151 return "HorizontalLeft";
2153 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter )
2155 return "HorizontalCenter";
2157 else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight )
2159 return "HorizontalRight";
2163 DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." );
2167 std::string TextView::OnVerticalAlignmentPropertyGet()
2169 if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop )
2171 return "VerticalTop";
2173 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter )
2175 return "VerticalCenter";
2177 else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom )
2179 return "VerticalBottom";
2183 DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." );
2187 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2189 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2193 TextView& textViewImpl( GetImpl( textView ) );
2196 case Toolkit::TextView::Property::MARKUP_ENABLED:
2198 textViewImpl.OnMarkupEnabledPeopertySet( value );
2201 case Toolkit::TextView::Property::TEXT:
2203 textViewImpl.SetText( value.Get<std::string>() );
2206 case Toolkit::TextView::Property::MULTILINE_POLICY:
2208 textViewImpl.OnMultilinePolicyPropertySet( value );
2211 case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY:
2213 textViewImpl.OnWidthExceedPolicyPropertySet( value );
2216 case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY:
2218 textViewImpl.OnHeightExceedPolicyPropertySet( value );
2221 case Toolkit::TextView::Property::LINE_JUSTIFICATION:
2223 textViewImpl.OnLineJustificationPropertySet( value );
2226 case Toolkit::TextView::Property::FADE_BOUNDARY:
2228 textViewImpl.OnFadeBoundaryPropertySet( value );
2231 case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET:
2233 Dali::PointSize pointSize( value.Get<float>() );
2234 textViewImpl.SetLineHeightOffset(pointSize);
2237 case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT:
2238 case Toolkit::TextView::Property::VERTICAL_ALIGNMENT:
2240 textViewImpl.OnAlignmentPropertySet( index, value );
2247 Property::Value TextView::GetProperty( BaseObject* object, Property::Index index )
2249 Property::Value value;
2251 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2255 TextView& textViewImpl( GetImpl( textView ) );
2258 case Toolkit::TextView::Property::MARKUP_ENABLED:
2260 value = textViewImpl.IsMarkupProcessingEnabled();
2263 case Toolkit::TextView::Property::TEXT:
2265 value = textViewImpl.GetText();
2268 case Toolkit::TextView::Property::MULTILINE_POLICY:
2270 value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ];
2273 case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY:
2275 value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ];
2278 case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY:
2280 value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ];
2283 case Toolkit::TextView::Property::LINE_JUSTIFICATION:
2285 value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ];
2288 case Toolkit::TextView::Property::FADE_BOUNDARY:
2290 Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary();
2291 value = Vector4( static_cast<float>( boundary.mLeft.value ),
2292 static_cast<float>( boundary.mRight.value ),
2293 static_cast<float>( boundary.mTop.value ),
2294 static_cast<float>( boundary.mBottom.value ) );
2297 case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET:
2299 value = textViewImpl.GetLineHeightOffset().value;
2302 case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT:
2304 value = textViewImpl.OnHorizontalAlignmentPropertyGet();
2307 case Toolkit::TextView::Property::VERTICAL_ALIGNMENT:
2309 value = textViewImpl.OnVerticalAlignmentPropertyGet();
2317 } // namespace Internal
2319 } // namespace Toolkit