2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include "text-view-impl.h"
21 #include "split-by-new-line-char-policies.h"
22 #include "split-by-word-policies.h"
23 #include "split-by-char-policies.h"
24 #include "text-view-processor.h"
25 #include "text-view-word-processor.h"
26 #include "relayout-utilities.h"
27 #include "text-view-processor-dbg.h"
35 const Property::Index TextView::PROPERTY_MARKUP_ENABLED( Internal::TextView::TEXTVIEW_PROPERTY_START_INDEX );
43 const char* const PROPERTY_TEXT = "text";
44 const char* const PROPERTY_MULTILINE_POLICY = "multiline-policy";
45 const char* const PROPERTY_WIDTH_EXCEED_POLICY = "width-exceed-policy";
46 const char* const PROPERTY_HEIGHT_EXCEED_POLICY = "height-exceed-policy";
47 const char* const PROPERTY_LINE_JUSTIFICATION = "line-justification";
48 const char* const PROPERTY_FADE_BOUNDARY_LEFT = "fade-boundary-left";
49 const char* const PROPERTY_FADE_BOUNDARY_RIGHT = "fade-boundary-right";
50 const char* const PROPERTY_FADE_BOUNDARY_TOP = "fade-boundary-top";
51 const char* const PROPERTY_FADE_BOUNDARY_BOTTOM = "fade-boundary-bottom";
52 const char* const PROPERTY_LINE_HEIGHT_OFFSET = "line-height-offset";
53 const char* const PROPERTY_HORIZONTAL_ALIGNMENT = "horizontal-alignment";
54 const char* const PROPERTY_VERTICAL_ALIGNMENT = "vertical-alignment";
56 // Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k.
57 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
62 return Toolkit::TextView::New();
65 TypeRegistration typeRegistration( typeid(Toolkit::TextView), typeid(Toolkit::Control), Create );
67 SignalConnectorType signalConnector1( typeRegistration, Toolkit::TextView::SIGNAL_TEXT_SCROLLED , &TextView::DoConnectSignal );
69 PropertyRegistration property1( typeRegistration, "markup-enabled", Toolkit::TextView::PROPERTY_MARKUP_ENABLED, Property::BOOLEAN, &TextView::SetProperty, &TextView::GetProperty );
72 * Whether the text-view-processor operation sets, inserts, replaces, removes text.
74 * @param[in] metadata The text-view-processor operation.
76 * @return \e true if the given text-view-processor operation is modifying the text.
78 bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata )
80 return ( ( metadata.mType == TextView::TextSet ) ||
81 ( metadata.mType == TextView::TextInserted ) ||
82 ( metadata.mType == TextView::TextReplaced ) ||
83 ( metadata.mType == TextView::TextRemoved ) ||
84 ( metadata.mType == TextView::NewStyle ));
88 * Whether the text-view-processor operation sets a new line height offset.
90 * @param[in] metadata The text-view-processor operation.
92 * @return \e true if the given text-view-processor operation sets a new line height offset.
94 bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata )
96 return ( metadata.mType == TextView::NewLineHeight );
100 * Whether the text-view-processor operation sets a new style.
102 * @param[in] metadata The text-view-processor operation.
104 * @return \e true if the given text-view-processor operation sets a new style.
106 bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata )
108 return ( metadata.mType == TextView::NewStyle );
113 TextView::TextViewProcessorMetadata::TextViewProcessorMetadata()
114 : mType( TextView::TextSet ),
116 mNumberOfCharacters( 0 ),
121 Toolkit::TextView TextView::New()
123 // Create the implementation, temporarily owned on stack
124 IntrusivePtr<TextView> textView = new TextView();
126 // Pass ownership to CustomActor
127 Toolkit::TextView handle( *textView );
129 // Second-phase init of the implementation
130 // This can only be done after the CustomActor connection has been made...
131 textView->Initialize();
133 // Enables by default the offscreen rendering.
134 textView->SetSnapshotModeEnabled( false ); /// @note Temporary disabled due to some issues with text quality and glyph loading.
139 void TextView::SetText( const std::string& text )
141 // Creates a styled text with the markup or plain string.
142 MarkupProcessor::StyledTextArray styledText;
143 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
145 // Calls SetText() with the styled text array.
146 SetText( styledText );
149 void TextView::SetText( const MarkupProcessor::StyledTextArray& text )
151 // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText.
152 // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted.
154 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation );
155 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
157 // Creates metadata with the Set operation.
158 TextViewProcessorMetadata metadata;
159 metadata.mType = TextView::TextSet;
160 metadata.mText = text;
163 mTextViewProcessorOperations.push_back( metadata );
165 // Updates current styled text.
166 mCurrentStyledText = text;
168 // Request to be relaid out
171 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
172 mRelayoutOperations = RELAYOUT_ALL;
175 void TextView::InsertTextAt( std::size_t position, const std::string& text )
177 // Creates a styled text with the markup or plain string.
178 MarkupProcessor::StyledTextArray styledText;
179 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
181 // Calls InsertTextAt() with the styled text array.
182 InsertTextAt( position, styledText );
185 void TextView::InsertTextAt( const std::size_t position, const MarkupProcessor::StyledTextArray& text )
187 // Creates metadata with the Insert operation.
188 TextViewProcessorMetadata metadata;
189 metadata.mType = TextView::TextInserted;
190 metadata.mPosition = position;
191 metadata.mText = text;
194 mTextViewProcessorOperations.push_back( metadata );
196 // Updates current styled text.
197 mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() );
199 // Request to be relaid out
202 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
203 mRelayoutOperations = RELAYOUT_ALL;
206 void TextView::ReplaceTextFromTo( const std::size_t position, const std::size_t numberOfCharacters, const std::string& text )
208 // Creates a styled text with the markup or plain string.
209 MarkupProcessor::StyledTextArray styledText;
210 MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() );
212 // Calls ReplaceTextFromTo() with the styled text array.
213 ReplaceTextFromTo( position, numberOfCharacters, styledText );
216 void TextView::ReplaceTextFromTo( const std::size_t position, const std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text )
218 // Creates metadata with the Insert operation.
219 TextViewProcessorMetadata metadata;
220 metadata.mType = TextView::TextReplaced;
221 metadata.mPosition = position;
222 metadata.mNumberOfCharacters = numberOfCharacters;
223 metadata.mText = text;
226 mTextViewProcessorOperations.push_back( metadata );
228 // Updates current styled text.
229 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
230 mCurrentStyledText.erase( it, it + numberOfCharacters );
231 it = mCurrentStyledText.begin() + position;
232 mCurrentStyledText.insert( it, text.begin(), text.end() );
234 // Request to be relaid out
237 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
238 mRelayoutOperations = RELAYOUT_ALL;
241 void TextView::RemoveTextFrom( const std::size_t position, const std::size_t numberOfCharacters )
243 // Creates metadata with the Remove operation.
244 TextViewProcessorMetadata metadata;
245 metadata.mType = TextView::TextRemoved;
246 metadata.mPosition = position;
247 metadata.mNumberOfCharacters = numberOfCharacters;
250 mTextViewProcessorOperations.push_back( metadata );
252 // Updates current styled text.
253 MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position;
254 mCurrentStyledText.erase( it, it + numberOfCharacters );
256 // Request to be relaid out
259 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
260 mRelayoutOperations = RELAYOUT_ALL;
263 std::string TextView::GetText() const
265 // Traverses the styled text array getting only the text.
266 // Note that for some languages a 'character' could be represented by more than one 'char'
269 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it )
271 text.append( (*it).mText.GetText() );
277 void TextView::SetLineHeightOffset( const PointSize offset )
279 if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 )
281 // Removes any previous operation which modifies the line height offset.
282 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation );
283 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
285 // Creates metadata with the new line height operation.
286 TextViewProcessorMetadata metadata;
287 metadata.mType = TextView::NewLineHeight;
289 mTextViewProcessorOperations.push_back( metadata );
291 // Updates line height offset.
292 mLayoutParameters.mLineHeightOffset = offset;
296 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
297 if( RELAYOUT_ALL != mRelayoutOperations )
299 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
300 RELAYOUT_REMOVE_TEXT_ACTORS |
301 RELAYOUT_SIZE_POSITION |
303 RELAYOUT_VISIBILITY |
304 RELAYOUT_TEXT_ACTOR_UPDATE |
305 RELAYOUT_INSERT_TO_TEXT_VIEW |
306 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
311 PointSize TextView::GetLineHeightOffset() const
313 return PointSize( mLayoutParameters.mLineHeightOffset );
316 void TextView::SetStyleToCurrentText( const TextStyle& style, const TextStyle::Mask mask )
318 if( !mCurrentStyledText.empty() )
320 const bool checkFontName = mask & TextStyle::FONT;
321 const bool checkFontSize = mask & TextStyle::SIZE;
322 const bool checkFontStyle = mask & TextStyle::STYLE;
324 // Check first if metrics have changed.
325 bool metricsChanged = false;
326 for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it )
328 const MarkupProcessor::StyledText& styledText( *it );
330 metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) ||
331 ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) ||
332 ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) );
337 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
339 // If metrics change, new text measurements are needed.
340 SetText( mCurrentStyledText );
344 // Deletes any previous operation which sets a new style.
345 std::vector<TextViewProcessorMetadata>::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation );
346 mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() );
348 // Creates metadata with the new style operation.
349 TextViewProcessorMetadata metadata;
350 metadata.mType = TextView::NewStyle;
352 MarkupProcessor::StyledText text;
354 metadata.mText.push_back( text );
355 metadata.mStyleMask = mask;
357 mTextViewProcessorOperations.push_back( metadata );
359 MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask );
363 if( RELAYOUT_ALL != mRelayoutOperations )
365 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
366 RELAYOUT_TEXT_ACTOR_UPDATE );
371 // Sets the new style to the ellipsize text
372 if( !mLayoutParameters.mEllipsizeText.empty() )
374 for( MarkupProcessor::StyledTextArray::iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
376 (*it).mStyle.Copy( style, mask );
379 SetEllipsizeText( mLayoutParameters.mEllipsizeText );
383 void TextView::SetTextAlignment( Toolkit::Alignment::Type align )
385 if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) )
387 Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
388 ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
389 ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
390 Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
391 ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
392 ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
394 mLayoutParameters.mHorizontalAlignment = horizontalAlignment;
395 mLayoutParameters.mVerticalAlignment = verticalAlignment;
399 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
400 if( RELAYOUT_ALL != mRelayoutOperations )
402 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
403 RELAYOUT_TEXT_ACTOR_UPDATE |
405 RELAYOUT_VISIBILITY );
410 Toolkit::Alignment::Type TextView::GetTextAlignment() const
412 return static_cast<Toolkit::Alignment::Type>( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment );
415 void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy )
417 if( policy != mLayoutParameters.mMultilinePolicy )
419 mLayoutParameters.mMultilinePolicy = policy;
421 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values.
422 mRelayoutOperations = RELAYOUT_ALL;
428 Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const
430 return mLayoutParameters.mMultilinePolicy;
433 void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
435 // The layout info could be invalid depending on the current exceed policy and the new one.
436 // i.e. if the current policy is Split and the new one is ShrinkToFit then
437 // the layout info generated for each char is not needed.
438 if( policy != mLayoutParameters.mWidthExceedPolicy )
440 mLayoutParameters.mWidthExceedPolicy = policy;
442 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
443 mRelayoutOperations = RELAYOUT_ALL;
449 Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const
451 return mLayoutParameters.mWidthExceedPolicy;
454 void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy )
456 if( policy != mLayoutParameters.mHeightExceedPolicy )
458 mLayoutParameters.mHeightExceedPolicy = policy;
462 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
463 if( RELAYOUT_ALL != mRelayoutOperations )
465 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
466 RELAYOUT_REMOVE_TEXT_ACTORS |
467 RELAYOUT_SIZE_POSITION |
469 RELAYOUT_VISIBILITY |
470 RELAYOUT_TEXT_ACTOR_UPDATE |
471 RELAYOUT_INSERT_TO_TEXT_VIEW |
472 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
477 Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const
479 return mLayoutParameters.mHeightExceedPolicy;
482 void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification )
484 if( justification != mLayoutParameters.mLineJustification )
486 mLayoutParameters.mLineJustification = justification;
490 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
491 if( RELAYOUT_ALL != mRelayoutOperations )
493 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
494 RELAYOUT_REMOVE_TEXT_ACTORS |
495 RELAYOUT_SIZE_POSITION |
497 RELAYOUT_VISIBILITY |
498 RELAYOUT_TEXT_ACTOR_UPDATE |
499 RELAYOUT_INSERT_TO_TEXT_VIEW |
500 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
505 Toolkit::TextView::LineJustification TextView::GetLineJustification() const
507 return mLayoutParameters.mLineJustification;
510 void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary )
512 if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) ||
513 ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) ||
514 ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) ||
515 ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) )
517 mVisualParameters.mFadeBoundary = fadeBoundary;
521 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
522 if( RELAYOUT_ALL != mRelayoutOperations )
524 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
525 RELAYOUT_REMOVE_TEXT_ACTORS |
526 RELAYOUT_VISIBILITY |
527 RELAYOUT_TEXT_ACTOR_UPDATE |
528 RELAYOUT_INSERT_TO_TEXT_VIEW |
529 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
534 const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const
536 return mVisualParameters.mFadeBoundary;
539 void TextView::SetEllipsizeText( const std::string& ellipsizeText )
541 // Creates a styled text with the markup or plain string.
542 MarkupProcessor::StyledTextArray styledText;
543 MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() );
545 SetEllipsizeText( styledText );
548 void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText )
550 mLayoutParameters.mEllipsizeText = ellipsizeText;
552 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
554 TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
555 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
557 // Request to be relaid out
560 mRelayoutOperations = RELAYOUT_ALL;
563 std::string TextView::GetEllipsizeText() const
566 for( MarkupProcessor::StyledTextArray::const_iterator it = mLayoutParameters.mEllipsizeText.begin(), endIt = mLayoutParameters.mEllipsizeText.end(); it != endIt; ++it )
568 text.append( (*it).mText.GetText() );
574 void TextView::GetTextLayoutInfo()
576 const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION;
577 const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT;
578 const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY;
580 if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded )
582 Vector3 textViewSize = GetControlSize();
584 if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) ||
585 ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) &&
586 ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
587 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
588 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) )
590 // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies)
591 // the text natural size can be used.
592 textViewSize = GetNaturalSize();
595 if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) &&
596 ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) )
598 // Check if the text-view has glyph-actors.
599 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
601 RelayoutOperationMask mask = NO_RELAYOUT;
602 if( relayoutSizeAndPositionNeeded )
604 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_SIZE_POSITION );
606 if( relayoutAlignmentNeeded )
608 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_ALIGNMENT );
610 if( relayoutVisibilityNeeded )
612 mask = static_cast<RelayoutOperationMask>( mask | RELAYOUT_VISIBILITY );
617 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
618 // add them to the text-actor cache.
619 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
620 mRelayoutData.mGlyphActors.clear();
623 // Relays-out but doesn't add glyph-actors to the text-view.
624 DoRelayOut( textViewSize.GetVectorXY(), mask );
628 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
629 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
636 void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo )
640 textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable;
641 textLayoutInfo.mLines = mRelayoutData.mLines;
643 textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap;
644 textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap;
646 textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption;
648 textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition;
651 void TextView::SetSortModifier( float depthOffset )
653 mVisualParameters.mSortModifier = depthOffset;
655 for( std::vector<RenderableActor>::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end();
659 ( *it ).SetSortModifier( depthOffset );
662 if( mOffscreenImageActor )
664 mOffscreenImageActor.SetSortModifier( depthOffset );
668 void TextView::SetSnapshotModeEnabled( bool enable )
670 if( enable != mVisualParameters.mSnapshotModeEnabled )
672 // Remove first all glyph-actors
673 if( !mRelayoutData.mGlyphActors.empty() )
675 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
678 mVisualParameters.mSnapshotModeEnabled = enable;
679 if( !mLockPreviousSnapshotMode )
681 // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is
682 // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value
684 // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents
685 // to smash the stored value.
686 mPreviousSnapshotModeEnabled = enable;
689 if( mVisualParameters.mSnapshotModeEnabled )
691 // Create a root actor and an image actor for offscreen rendering.
692 mOffscreenRootActor = Layer::New();
693 mOffscreenImageActor = ImageActor::New();
695 mOffscreenRootActor.SetColorMode( USE_OWN_COLOR );
696 mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION );
697 mOffscreenRootActor.SetInheritRotation( false );
698 mOffscreenRootActor.SetInheritScale( false );
699 mOffscreenRootActor.SetDepthTestDisabled( true );
701 mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f );
703 mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER );
704 mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER );
707 self.Add( mOffscreenRootActor );
708 self.Add( mOffscreenImageActor );
709 mOffscreenImageActor.SetScale(Vector3(1.f, -1.f, 1.f));
715 if( mOffscreenRootActor )
717 self.Remove( mOffscreenRootActor );
720 if( mOffscreenImageActor )
722 self.Remove( mOffscreenImageActor );
725 DestroyOffscreenRenderingResources();
728 if( RELAYOUT_ALL != mRelayoutOperations )
730 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
731 RELAYOUT_REMOVE_TEXT_ACTORS |
732 RELAYOUT_TEXT_ACTOR_UPDATE |
733 RELAYOUT_INSERT_TO_TEXT_VIEW |
734 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
740 bool TextView::IsSnapshotModeEnabled() const
742 return mVisualParameters.mSnapshotModeEnabled;
745 void TextView::SetMarkupProcessingEnabled( bool enable )
747 mMarkUpEnabled = enable;
750 bool TextView::IsMarkupProcessingEnabled() const
752 return mMarkUpEnabled;
755 void TextView::SetScrollEnabled( const bool enable )
757 if( enable != mVisualParameters.mScrollEnabled )
759 mVisualParameters.mScrollEnabled = enable;
761 if( mVisualParameters.mScrollEnabled )
763 // Offscreen rendering is needed to enable text scroll.
765 // Stores previous value of the snapshot mode.
766 mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled();
769 // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(),
770 // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method.
771 Lock lock( mLockPreviousSnapshotMode );
772 SetSnapshotModeEnabled( true );
775 // Creates the pan gesture detector and attach the text-view.
776 mPanGestureDetector = PanGestureDetector::New();
777 mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan );
778 mPanGestureDetector.Attach( Self() );
782 // Removes the pan gesture detector.
783 if( mPanGestureDetector )
785 mPanGestureDetector.Detach( Self() );
786 mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan );
787 mPanGestureDetector.Reset();
790 // Restores the previous state for snapshot mode.
791 SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled );
796 bool TextView::IsScrollEnabled() const
798 return mVisualParameters.mScrollEnabled;
801 void TextView::SetScrollPosition( const Vector2& position )
803 if( position != mVisualParameters.mCameraScrollPosition )
805 // Guard against destruction during signal emission
806 // Note that Emit() methods are called indirectly from within DoSetScrollPosition()
807 Toolkit::TextView handle( GetOwner() );
809 DoSetScrollPosition( position );
811 // Check if the new scroll position has been trimmed.
812 mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition );
816 const Vector2& TextView::GetScrollPosition() const
818 return mVisualParameters.mCameraScrollPosition;
821 bool TextView::IsScrollPositionTrimmed() const
823 return mVisualParameters.mScrollPositionTrimmed;
826 Toolkit::TextView::ScrolledSignalV2& TextView::ScrolledSignal()
828 return mScrolledSignalV2;
831 bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
833 Dali::BaseHandle handle( object );
835 bool connected( true );
836 Toolkit::TextView textView = Toolkit::TextView::DownCast(handle);
838 if( Dali::Toolkit::TextView::SIGNAL_TEXT_SCROLLED == signalName )
840 textView.ScrolledSignal().Connect( tracker, functor );
844 // signalName does not match any signal
851 TextView::LayoutParameters::LayoutParameters()
852 : mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ),
853 mWidthExceedPolicy( Toolkit::TextView::Original ),
854 mHeightExceedPolicy( Toolkit::TextView::Original ),
855 mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ),
856 mVerticalAlignment( Toolkit::Alignment::VerticalCenter ),
857 mLineJustification( Toolkit::TextView::Left ),
858 mLineHeightOffset( 0.f ),
860 mMarkUpEnabled( false )
862 // Sets ellipsize text
863 MarkupProcessor::StyledTextArray styledEllipsize;
864 MarkupProcessor::GetStyledTextArray( std::string( "..." ), mEllipsizeText, false );
867 TextView::LayoutParameters::LayoutParameters( const Toolkit::TextView::MultilinePolicy multilinePolicy,
868 const Toolkit::TextView::ExceedPolicy widthExceedPolicy,
869 const Toolkit::TextView::ExceedPolicy heightExceedPolicy,
870 const Toolkit::Alignment::Type alignmentType,
871 const Toolkit::TextView::LineJustification lineJustification,
872 const float lineHeightOffset,
873 const std::string& ellipsizeText,
874 const bool markUpEnabled )
875 : mMultilinePolicy( multilinePolicy ),
876 mWidthExceedPolicy( widthExceedPolicy ),
877 mHeightExceedPolicy( heightExceedPolicy ),
878 mHorizontalAlignment(),
879 mVerticalAlignment(),
880 mLineJustification( lineJustification ),
881 mLineHeightOffset( lineHeightOffset ),
883 mMarkUpEnabled( markUpEnabled )
886 Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft :
887 ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter :
888 ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) );
889 Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop :
890 ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter :
891 ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) );
893 mHorizontalAlignment = horizontalAlignment;
894 mVerticalAlignment = verticalAlignment;
896 // Sets ellipsize text
897 MarkupProcessor::StyledTextArray styledEllipsize;
898 MarkupProcessor::GetStyledTextArray( ellipsizeText, mEllipsizeText, mMarkUpEnabled );
901 TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters )
902 : mMultilinePolicy( layoutParameters.mMultilinePolicy ),
903 mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ),
904 mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ),
905 mHorizontalAlignment( layoutParameters.mHorizontalAlignment ),
906 mVerticalAlignment( layoutParameters.mVerticalAlignment ),
907 mLineJustification( layoutParameters.mLineJustification ),
908 mLineHeightOffset( layoutParameters.mLineHeightOffset ),
909 mEllipsizeText( layoutParameters.mEllipsizeText ),
910 mMarkUpEnabled( layoutParameters.mMarkUpEnabled )
914 TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters )
916 mMultilinePolicy = layoutParameters.mMultilinePolicy;
917 mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy;
918 mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy;
919 mHorizontalAlignment = layoutParameters.mHorizontalAlignment;
920 mVerticalAlignment = layoutParameters.mVerticalAlignment;
921 mLineJustification = layoutParameters.mLineJustification;
922 mLineHeightOffset = layoutParameters.mLineHeightOffset;
923 mEllipsizeText = layoutParameters.mEllipsizeText;
924 mMarkUpEnabled = layoutParameters.mMarkUpEnabled;
929 TextView::VisualParameters::VisualParameters()
931 mSortModifier( 0.f ),
932 mCameraScrollPosition( 0.f, 0.f ),
933 mSnapshotModeEnabled( false ),
934 mScrollEnabled( false ),
935 mScrollPositionTrimmed( false )
939 TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters )
940 : mFadeBoundary( visualParameters.mFadeBoundary ),
941 mSortModifier( visualParameters.mSortModifier ),
942 mCameraScrollPosition( visualParameters.mCameraScrollPosition ),
943 mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ),
944 mScrollEnabled( visualParameters.mScrollEnabled ),
945 mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed )
949 TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters )
951 mFadeBoundary = visualParameters.mFadeBoundary;
952 mSortModifier = visualParameters.mSortModifier;
953 mCameraScrollPosition = visualParameters.mCameraScrollPosition;
954 mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled;
955 mScrollEnabled = visualParameters.mScrollEnabled;
956 mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed;
961 TextView::RelayoutData::RelayoutData()
963 mShrinkFactor( 1.f ),
965 mCharacterLogicalToVisualMap(),
966 mCharacterVisualToLogicalMap(),
968 mCharacterLayoutInfoTable(),
970 mTextSizeForRelayoutOption()
974 TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData )
975 : mTextViewSize( relayoutData.mTextViewSize ),
976 mShrinkFactor( relayoutData.mShrinkFactor ),
977 mTextLayoutInfo( relayoutData.mTextLayoutInfo ),
978 mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ),
979 mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ),
980 mGlyphActors( relayoutData.mGlyphActors ),
981 mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ),
982 mLines( relayoutData.mLines ),
983 mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption )
987 TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData )
989 mTextViewSize = relayoutData.mTextViewSize;
990 mShrinkFactor = relayoutData.mShrinkFactor;
991 mTextLayoutInfo = relayoutData.mTextLayoutInfo;
992 mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap;
993 mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap;
994 mGlyphActors = relayoutData.mGlyphActors;
995 mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable;
996 mLines = relayoutData.mLines;
997 mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption;
1002 TextView::TextView()
1003 : ControlImpl( false ), // doesn't require touch events
1004 mCurrentStyledText(),
1005 mTextViewProcessorOperations(),
1006 mLayoutParameters( Toolkit::TextView::SplitByNewLineChar,
1007 Toolkit::TextView::Original,
1008 Toolkit::TextView::Original,
1009 static_cast<Toolkit::Alignment::Type>( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ),
1010 Toolkit::TextView::Left,
1012 std::string( "..." ),
1014 mVisualParameters(),
1016 mRelayoutOperations( NO_RELAYOUT ),
1017 mOffscreenRootActor(),
1018 mOffscreenImageActor(),
1019 mOffscreenCameraActor(),
1020 mCurrentOffscreenSize(),
1021 mFrameBufferImage(),
1023 mPanGestureDetector(),
1024 mLockPreviousSnapshotMode( false ),
1025 mPreviousSnapshotModeEnabled( false ),
1026 mMarkUpEnabled( false )
1028 TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
1029 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1032 TextView::~TextView()
1034 // Destroys offscreen rendering resources.
1035 DestroyOffscreenRenderingResources();
1037 // Destroys scroll pan gesture detector.
1038 if( mPanGestureDetector )
1040 mPanGestureDetector.Reset();
1044 Vector3 TextView::GetNaturalSize()
1046 if( !mTextViewProcessorOperations.empty() )
1048 // There are SetText, Inserts or Removes to do. It means the current layout info is not updated.
1050 if( !mRelayoutData.mGlyphActors.empty() )
1052 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1053 // add them to the text-actor cache.
1054 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1055 mRelayoutData.mGlyphActors.clear();
1057 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1058 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
1061 PerformTextViewProcessorOperations();
1064 return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f );
1067 float TextView::GetHeightForWidth( float width )
1071 if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) &&
1072 ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) &&
1073 ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) )
1075 // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the
1076 // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut().
1077 height = GetNaturalSize().height;
1081 // Check if the given width is different than the current one.
1082 const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 );
1084 // Check if the text-view has glyph-actors.
1085 const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty();
1087 // Check which layout operations need to be done.
1088 const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth;
1090 if( relayoutSizeAndPositionNeeded )
1092 if( hasGlyphActors )
1094 // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo()
1095 // add them to the text-actor cache.
1096 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1097 mRelayoutData.mGlyphActors.clear();
1100 // Use the given width.
1101 const Vector2 textViewSize( width, GetControlSize().height );
1103 // Relays-out but doesn't add glyph-actors to the text-view.
1104 DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION );
1107 // Retrieve the text height after relayout the text.
1108 height = mRelayoutData.mTextSizeForRelayoutOption.height;
1110 if( differentWidth )
1112 // Revert the relayout operation mask
1113 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_SIZE_POSITION );
1116 if( hasGlyphActors )
1118 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW );
1119 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
1122 if( differentWidth || hasGlyphActors )
1131 float TextView::GetWidthForHeight( float height )
1133 // TODO: Needs implementing properly, for now just return the natural width.
1134 return GetNaturalSize().width;
1137 void TextView::OnPropertySet( Property::Index index, Property::Value propertyValue )
1139 if( index == mPropertyText )
1141 SetText(propertyValue.Get<std::string>());
1143 else if( index == mPropertyMultilinePolicy )
1145 OnMultilinePolicyPropertySet(propertyValue);
1147 else if( index == mPropertyWidthExceedPolicy )
1149 OnWidthExceedPolicyPropertySet(propertyValue);
1151 else if( index == mPropertyHeightExceedPolicy )
1153 OnHeightExceedPolicyPropertySet(propertyValue);
1155 else if( index == mPropertyLineJustification )
1157 OnLineJustificationPropertySet(propertyValue);
1159 else if( ( index == mPropertyFadeBoundaryLeft ) ||
1160 ( index == mPropertyFadeBoundaryRight ) ||
1161 ( index == mPropertyFadeBoundaryTop ) ||
1162 ( index == mPropertyFadeBoundaryBottom ) )
1164 OnFadeBoundaryPropertySet( index, propertyValue );
1166 else if( index == mPropertyLineHeightOffset )
1168 Dali::PointSize pointSize( propertyValue.Get<float>() );
1169 SetLineHeightOffset(pointSize);
1171 else if ( ( index == mPropertyHorizontalAlignment ) ||
1172 ( index == mPropertyVerticalAlignment ) )
1174 OnAlignmentPropertySet( index, propertyValue );
1178 void TextView::OnInitialize()
1180 Actor self = Self();
1182 mPropertyText = self.RegisterProperty( PROPERTY_TEXT, "", Property::READ_WRITE );
1184 mPropertyMultilinePolicy = self.RegisterProperty( PROPERTY_MULTILINE_POLICY, "SplitByNewLineChar", Property::READ_WRITE );
1186 mPropertyWidthExceedPolicy = self.RegisterProperty( PROPERTY_WIDTH_EXCEED_POLICY, "Original", Property::READ_WRITE );
1188 mPropertyHeightExceedPolicy = self.RegisterProperty( PROPERTY_HEIGHT_EXCEED_POLICY, "Original", Property::READ_WRITE );
1190 mPropertyLineJustification = self.RegisterProperty( PROPERTY_LINE_JUSTIFICATION, "Left", Property::READ_WRITE );
1192 mPropertyFadeBoundaryLeft = self.RegisterProperty( PROPERTY_FADE_BOUNDARY_LEFT, static_cast< int >( 0 ), Property::READ_WRITE );
1194 mPropertyFadeBoundaryRight = self.RegisterProperty( PROPERTY_FADE_BOUNDARY_RIGHT, static_cast< int >( 0 ), Property::READ_WRITE );
1196 mPropertyFadeBoundaryTop = self.RegisterProperty( PROPERTY_FADE_BOUNDARY_TOP, static_cast< int >( 0 ), Property::READ_WRITE );
1198 mPropertyFadeBoundaryBottom = self.RegisterProperty( PROPERTY_FADE_BOUNDARY_BOTTOM, static_cast< int >( 0 ), Property::READ_WRITE );
1200 mPropertyLineHeightOffset = self.RegisterProperty( PROPERTY_LINE_HEIGHT_OFFSET, 0.0f, Property::READ_WRITE );
1202 mPropertyHorizontalAlignment = self.RegisterProperty( PROPERTY_HORIZONTAL_ALIGNMENT, "HorizontalCenter", Property::READ_WRITE );
1204 mPropertyVerticalAlignment = self.RegisterProperty( PROPERTY_VERTICAL_ALIGNMENT, "VerticalCenter", Property::READ_WRITE );
1209 void TextView::OnStyleChange( StyleChange change )
1211 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo();
1212 TextViewProcessor::CreateWordTextInfo( mLayoutParameters.mEllipsizeText,
1213 mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo );
1215 SetText( mCurrentStyledText );
1218 void TextView::OnControlSizeSet( const Vector3& size )
1220 if( size.GetVectorXY() != mRelayoutData.mTextViewSize )
1222 // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values.
1223 mRelayoutOperations = RELAYOUT_ALL;
1225 // Request to be relaid out
1230 void TextView::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
1232 if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
1234 // Not worth to relayout if width or height is equal to zero.
1238 if( size != mRelayoutData.mTextViewSize )
1240 // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed.
1241 if( RELAYOUT_ALL != mRelayoutOperations )
1243 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations |
1244 RELAYOUT_REMOVE_TEXT_ACTORS |
1245 RELAYOUT_SIZE_POSITION |
1246 RELAYOUT_ALIGNMENT |
1247 RELAYOUT_VISIBILITY |
1248 RELAYOUT_TEXT_ACTOR_UPDATE |
1249 RELAYOUT_INSERT_TO_TEXT_VIEW |
1250 RELAYOUT_INSERT_TO_TEXT_ACTOR_LIST );
1254 // Remove glyph-actors from text-view
1255 if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) )
1257 TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors );
1258 mRelayoutData.mGlyphActors.clear();
1261 if( NO_RELAYOUT != mRelayoutOperations )
1263 // Relays-out and add glyph-actors to the text-view.
1264 DoRelayOut( size, mRelayoutOperations );
1265 ProcessSnapshot( size );
1268 // Quite likely the texts of the text-actors are not going to be reused, so clear them.
1269 mRelayoutData.mTextActorCache.ClearTexts();
1272 void TextView::PerformTextViewProcessorOperations()
1274 // Traverse the relayout operation vector ...
1276 // Optimizes some operations.
1277 OptimizeTextViewProcessorOperations();
1279 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1281 const TextViewProcessorMetadata& relayoutMetadata( *it );
1283 switch( relayoutMetadata.mType )
1285 case TextView::TextSet:
1287 TextViewProcessor::CreateTextInfo( relayoutMetadata.mText,
1292 case TextView::TextInserted:
1294 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1295 relayoutMetadata.mText,
1300 case TextView::TextReplaced:
1302 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1303 relayoutMetadata.mNumberOfCharacters,
1304 relayoutMetadata.mText,
1309 case TextView::TextRemoved:
1311 TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition,
1312 relayoutMetadata.mNumberOfCharacters,
1315 TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors.
1318 case TextView::NewLineHeight:
1320 TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset,
1321 mRelayoutData.mTextLayoutInfo );
1324 case TextView::NewStyle:
1326 TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle,
1327 relayoutMetadata.mStyleMask,
1334 // Clear all operations when they are done.
1335 mTextViewProcessorOperations.clear();
1338 void TextView::OptimizeTextViewProcessorOperations()
1340 // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 );
1342 // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation.
1343 // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to
1344 // use the cache without clearing the text-actors.
1346 std::vector<TextViewProcessorMetadata> textViewProcessorOperations;
1348 for( std::vector<TextViewProcessorMetadata>::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it )
1350 const TextViewProcessorMetadata& relayoutMetadata( *it );
1352 switch( relayoutMetadata.mType )
1354 case TextView::TextRemoved:
1356 bool optimizationDone = false;
1358 if( it + 1 != endIt )
1360 const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1 ) );
1361 if( TextView::TextInserted == nextRelayoutMetadata.mType )
1363 if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition )
1365 optimizationDone = true;
1366 TextViewProcessorMetadata newRelayoutMetadata;
1367 newRelayoutMetadata.mType = TextView::TextReplaced;
1368 newRelayoutMetadata.mPosition = relayoutMetadata.mPosition;
1369 newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters;
1370 newRelayoutMetadata.mText = nextRelayoutMetadata.mText;
1371 textViewProcessorOperations.push_back( newRelayoutMetadata );
1373 // do not access the TextInserted operation in next iteration.
1379 if( !optimizationDone )
1381 textViewProcessorOperations.push_back( relayoutMetadata );
1387 textViewProcessorOperations.push_back( relayoutMetadata );
1392 mTextViewProcessorOperations = textViewProcessorOperations;
1395 void TextView::DoRelayOut( const Size& textViewSize, const RelayoutOperationMask relayoutOperationMask )
1397 // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures.
1398 if( !mTextViewProcessorOperations.empty() )
1400 PerformTextViewProcessorOperations();
1403 CombineExceedPolicies();
1406 if( mVisualParameters.mSnapshotModeEnabled )
1408 rootActor = mOffscreenRootActor;
1415 mRelayoutData.mTextViewSize = textViewSize;
1416 switch( mLayoutParameters.mMultilinePolicy )
1418 case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar.
1420 SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1422 } // SplitByNewLineChar
1424 case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord.
1426 SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1430 case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar.
1432 SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData );
1435 } // switch( mMultilinePolicy )
1437 // Remove done operations from the mask.
1438 mRelayoutOperations = static_cast<RelayoutOperationMask>( mRelayoutOperations & ~relayoutOperationMask );
1441 void TextView::ProcessSnapshot( const Size& textViewSize )
1443 if( mVisualParameters.mSnapshotModeEnabled )
1445 // If layout options change, it's needed generate a new image.
1447 if( mOffscreenRootActor )
1449 // Set the root actor visible.
1450 // The root actor is set to non visible after the render task is processed.
1451 mOffscreenRootActor.SetVisible( true );
1453 // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work.
1454 mOffscreenRootActor.SetSize( textViewSize );
1457 if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) &&
1458 ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) )
1460 // Set the image actor visible.
1461 // The image actor is set to non visible if there is no text to render.
1462 mOffscreenImageActor.SetVisible( true );
1464 // Calculates the offscreen image's size. It takes into account different points:
1465 // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge.
1466 // * There is a maximum texture size the graphic subsystem can load on the memory.
1467 // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size.
1469 const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1470 mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ),
1471 std::min( MAX_OFFSCREEN_RENDERING_SIZE,
1472 mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) );
1474 const bool sizeChanged = offscreenSize != mCurrentOffscreenSize;
1478 // Creates a frame buffer for offscreen rendering when the size is negotiated.
1479 mFrameBufferImage = FrameBufferImage::New( offscreenSize.width,
1480 offscreenSize.height,
1483 // Stores current text-view size to avoid create new Dali resources if text changes.
1484 mCurrentOffscreenSize = offscreenSize;
1486 if( !mOffscreenCameraActor )
1488 // Creates a new camera actor.
1489 mOffscreenCameraActor = CameraActor::New();
1490 mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER );
1491 mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
1492 mOffscreenCameraActor.SetRotation(Degree(180.f), Vector3::YAXIS);
1494 mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor.
1496 mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text
1499 // Calculate camera parameters for current text size.
1500 mOffscreenCameraActor.SetOrthographicProjection( offscreenSize );
1503 if( mVisualParameters.mScrollEnabled )
1505 // Updates the offscreen camera position with the new scroll offset.
1506 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1507 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1511 // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text.
1512 AlignOffscreenCameraActor( textViewSize, offscreenSize );
1517 // Creates a new render task.
1518 mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask();
1520 mRenderTask.SetSourceActor( mOffscreenRootActor );
1521 mRenderTask.SetInputEnabled( false );
1522 mRenderTask.SetClearColor( Color::TRANSPARENT );
1523 mRenderTask.SetClearEnabled( true );
1524 mRenderTask.SetExclusive( true );
1526 // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed.
1527 mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished );
1532 mRenderTask.SetCameraActor( mOffscreenCameraActor );
1533 mRenderTask.SetTargetFrameBuffer( mFrameBufferImage );
1536 // Process the render task only once every time the text changes or the text-view's size canges.
1537 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1541 // If there is no text just make any previous generated image invisible instead to process a render task with no text.
1542 mOffscreenImageActor.SetVisible( false );
1547 void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize )
1549 float xPosition = 0.f;
1550 float yPosition = 0.f;
1551 Vector3 parentOrigin = ParentOrigin::CENTER;
1552 Vector3 anchorPoint = AnchorPoint::CENTER;
1554 switch( mLayoutParameters.mHorizontalAlignment )
1556 case Toolkit::Alignment::HorizontalLeft:
1558 xPosition = 0.5f * ( offscreenSize.width - textViewSize.width );
1559 parentOrigin.x = 0.f;
1560 anchorPoint.x = 0.f;
1563 case Toolkit::Alignment::HorizontalCenter:
1568 case Toolkit::Alignment::HorizontalRight:
1570 xPosition = 0.5f * ( textViewSize.width - offscreenSize.width );
1571 parentOrigin.x = 1.f;
1572 anchorPoint.x = 1.f;
1577 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1581 switch( mLayoutParameters.mVerticalAlignment )
1583 case Toolkit::Alignment::VerticalTop:
1585 yPosition = 0.5f * ( offscreenSize.height - textViewSize.height );
1586 parentOrigin.y = 0.f;
1587 anchorPoint.y = 0.f;
1590 case Toolkit::Alignment::VerticalCenter:
1595 case Toolkit::Alignment::VerticalBottom:
1597 yPosition = 0.5f * ( textViewSize.height - offscreenSize.height );
1598 parentOrigin.y = 1.f;
1599 anchorPoint.y = 1.f;
1604 DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." )
1608 mOffscreenCameraActor.SetX( xPosition );
1609 mOffscreenCameraActor.SetY( yPosition );
1611 mOffscreenImageActor.SetParentOrigin( parentOrigin );
1612 mOffscreenImageActor.SetAnchorPoint( anchorPoint );
1615 void TextView::RenderTaskFinished( Dali::RenderTask& renderTask )
1617 // not to process the offscreen root actor by setting its visibility to false.
1618 mOffscreenRootActor.SetVisible( false );
1620 // Sets the new size and the new frame buffer to the image actor.
1621 // Image actor must have same size as text. Otherwise text can be truncated.
1622 mOffscreenImageActor.SetSize( mCurrentOffscreenSize );
1623 mOffscreenImageActor.SetImage( mFrameBufferImage );
1626 void TextView::DestroyOffscreenRenderingResources()
1630 mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished );
1632 if( Stage::IsInstalled() )
1634 Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask );
1637 mRenderTask.Reset();
1640 // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen.
1641 if( mOffscreenCameraActor )
1643 mOffscreenRootActor.Remove( mOffscreenCameraActor );
1645 mOffscreenCameraActor.Reset();
1648 if( mOffscreenRootActor )
1650 mOffscreenRootActor.Reset();
1653 if( mOffscreenImageActor )
1655 mOffscreenImageActor.Reset();
1658 mCurrentOffscreenSize = Size( 0.f, 0.f );
1660 if( mFrameBufferImage )
1662 mFrameBufferImage.Reset();
1666 void TextView::OnTextPan( Actor actor, PanGesture gesture )
1668 if( 1u == gesture.numberOfTouches )
1670 DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement );
1674 void TextView::TrimScrollPosition()
1676 const Vector3& textViewSize = GetControlSize();
1678 // Before use the text's size, relayout the text is needed to get the actual text size.
1679 GetTextLayoutInfo();
1681 // Calculates the range within the text could be scrolled. (When the text is aligned in the center).
1682 float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) );
1683 float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) );
1684 float minHorizontalDisplacement = -maxHorizontalDisplacement;
1685 float minVerticalDisplacement = -maxVerticalDisplacement;
1687 // Updates the range if the text is aligned on the right or left.
1688 switch( mLayoutParameters.mHorizontalAlignment )
1690 case Toolkit::Alignment::HorizontalLeft:
1692 maxHorizontalDisplacement *= 2.f;
1693 minHorizontalDisplacement = 0.f;
1696 case Toolkit::Alignment::HorizontalCenter:
1701 case Toolkit::Alignment::HorizontalRight:
1703 maxHorizontalDisplacement = 0.f;
1704 minHorizontalDisplacement *= 2.f;
1709 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1713 // Updates the range if the text is aligned on the top or bottom.
1714 switch( mLayoutParameters.mVerticalAlignment )
1716 case Toolkit::Alignment::VerticalTop:
1718 maxVerticalDisplacement *= 2.f;
1719 minVerticalDisplacement = 0.f;
1722 case Toolkit::Alignment::VerticalCenter:
1727 case Toolkit::Alignment::VerticalBottom:
1729 maxVerticalDisplacement = 0.f;
1730 minVerticalDisplacement *= 2.f;
1735 DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." )
1739 // Trims the scroll position to be within the range.
1740 mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1741 mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x );
1743 mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1744 mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y );
1747 void TextView::DoSetScrollPosition( const Vector2& position )
1749 // Stores old scroll position.
1750 Vector2 delta( mVisualParameters.mCameraScrollPosition );
1752 // Updates the scroll position
1753 mVisualParameters.mCameraScrollPosition = position;
1755 // Ensures the text-view is covered with text.
1756 TrimScrollPosition();
1758 // Calculate the difference with the previous scroll position
1759 delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x;
1760 delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y;
1762 if( mOffscreenRootActor )
1764 // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be
1766 mOffscreenRootActor.SetVisible( true );
1769 if( mOffscreenCameraActor )
1771 // Update the offscreen camera with the new scroll position.
1772 mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x );
1773 mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y );
1778 // Refresh the render-task.
1779 mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
1783 Toolkit::TextView handle( GetOwner() );
1784 mScrolledSignalV2.Emit( handle, delta );
1787 void TextView::CombineExceedPolicies()
1789 // Calculates the combination of exceed policies.
1791 switch( mLayoutParameters.mWidthExceedPolicy )
1793 case Toolkit::TextView::Original:
1795 switch( mLayoutParameters.mHeightExceedPolicy )
1797 case Toolkit::TextView::Original:
1799 mLayoutParameters.mExceedPolicy = Original;
1802 case Toolkit::TextView::Fade:
1804 mLayoutParameters.mExceedPolicy = OriginalFade;
1807 case Toolkit::TextView::ShrinkToFit:
1809 mLayoutParameters.mExceedPolicy = OriginalShrink;
1814 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1819 case Toolkit::TextView::Split:
1821 switch( mLayoutParameters.mHeightExceedPolicy )
1823 case Toolkit::TextView::Original:
1825 mLayoutParameters.mExceedPolicy = SplitOriginal;
1828 case Toolkit::TextView::Fade:
1830 mLayoutParameters.mExceedPolicy = SplitFade;
1833 case Toolkit::TextView::ShrinkToFit:
1835 mLayoutParameters.mExceedPolicy = SplitShrink;
1840 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1845 case Toolkit::TextView::Fade:
1847 switch( mLayoutParameters.mHeightExceedPolicy )
1849 case Toolkit::TextView::Original:
1851 mLayoutParameters.mExceedPolicy = FadeOriginal;
1854 case Toolkit::TextView::Fade:
1856 mLayoutParameters.mExceedPolicy = Fade;
1861 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1866 case Toolkit::TextView::ShrinkToFit:
1868 switch( mLayoutParameters.mHeightExceedPolicy )
1870 case Toolkit::TextView::Original:
1872 mLayoutParameters.mExceedPolicy = ShrinkOriginal;
1875 case Toolkit::TextView::Fade:
1877 mLayoutParameters.mExceedPolicy = ShrinkFade;
1880 case Toolkit::TextView::ShrinkToFit:
1882 mLayoutParameters.mExceedPolicy = Shrink;
1887 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1892 case Toolkit::TextView::EllipsizeEnd:
1894 switch( mLayoutParameters.mHeightExceedPolicy )
1896 case Toolkit::TextView::Original:
1898 mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal;
1901 case Toolkit::TextView::EllipsizeEnd:
1903 mLayoutParameters.mExceedPolicy = EllipsizeEnd;
1908 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" );
1915 DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" );
1920 Actor TextView::GetRootActor() const
1922 // Get the root actor, if text-view was rendering offscreen, or the text-view itself.
1926 if( mVisualParameters.mSnapshotModeEnabled )
1928 rootActor = mOffscreenRootActor;
1938 void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue )
1940 std::string policyName( propertyValue.Get<std::string>() );
1941 if(policyName == "SplitByNewLineChar")
1943 SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar);
1945 else if(policyName == "SplitByWord")
1947 SetMultilinePolicy(Toolkit::TextView::SplitByWord);
1949 else if(policyName == "SplitByChar")
1951 SetMultilinePolicy(Toolkit::TextView::SplitByChar);
1955 DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." );
1959 void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue )
1961 std::string policyName( propertyValue.Get<std::string>() );
1962 if(policyName == "Original")
1964 SetWidthExceedPolicy(Toolkit::TextView::Original);
1966 else if(policyName == "Truncate")
1968 SetWidthExceedPolicy(Toolkit::TextView::Truncate);
1970 else if(policyName == "Fade")
1972 SetWidthExceedPolicy(Toolkit::TextView::Fade);
1974 else if(policyName == "Split")
1976 SetWidthExceedPolicy(Toolkit::TextView::Split);
1978 else if(policyName == "ShrinkToFit")
1980 SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit);
1982 else if(policyName == "EllipsizeEnd")
1984 SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd);
1988 DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." );
1992 void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue )
1994 std::string policyName( propertyValue.Get<std::string>() );
1995 if(policyName == "Original")
1997 SetHeightExceedPolicy(Toolkit::TextView::Original);
1999 else if(policyName == "Truncate")
2001 SetHeightExceedPolicy(Toolkit::TextView::Truncate);
2003 else if(policyName == "Fade")
2005 SetHeightExceedPolicy(Toolkit::TextView::Fade);
2007 else if(policyName == "Split")
2009 SetHeightExceedPolicy(Toolkit::TextView::Split);
2011 else if(policyName == "ShrinkToFit")
2013 SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit);
2017 DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." );
2021 void TextView::OnLineJustificationPropertySet( Property::Value propertyValue )
2023 std::string policyName( propertyValue.Get<std::string>() );
2024 if(policyName == "Left")
2026 SetLineJustification(Toolkit::TextView::Left);
2028 else if(policyName == "Center")
2030 SetLineJustification(Toolkit::TextView::Center);
2032 else if(policyName == "Right")
2034 SetLineJustification(Toolkit::TextView::Right);
2036 else if(policyName == "Justified")
2038 SetLineJustification(Toolkit::TextView::Justified);
2042 DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." );
2046 void TextView::OnFadeBoundaryPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2048 PixelSize boundary( propertyValue.Get<unsigned int>() );
2050 if ( propertyIndex == mPropertyFadeBoundaryLeft )
2052 mVisualParameters.mFadeBoundary.mLeft = boundary;
2054 else if ( propertyIndex == mPropertyFadeBoundaryRight )
2056 mVisualParameters.mFadeBoundary.mRight = boundary;
2058 else if ( propertyIndex == mPropertyFadeBoundaryTop )
2060 mVisualParameters.mFadeBoundary.mTop = boundary;
2062 else if ( propertyIndex == mPropertyFadeBoundaryBottom )
2064 mVisualParameters.mFadeBoundary.mBottom = boundary;
2068 DALI_ASSERT_ALWAYS( !"TextView::OnFadeBoundaryPropertySet(). Invalid Property value." );
2072 void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue )
2074 std::string value( propertyValue.Get<std::string>() );
2076 if( propertyIndex == mPropertyHorizontalAlignment )
2078 if(value == "HorizontalLeft")
2080 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft;
2082 else if( value == "HorizontalCenter")
2084 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter;
2086 else if( value == "HorizontalRight")
2088 mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight;
2092 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2095 else if( propertyIndex == mPropertyVerticalAlignment )
2097 if( value == "VerticalTop" )
2099 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop;
2101 else if( value == "VerticalCenter")
2103 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter;
2105 else if( value == "VerticalBottom")
2107 mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom;
2111 DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." );
2116 void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
2118 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2120 if ( textView && ( index == Toolkit::TextView::PROPERTY_MARKUP_ENABLED ) )
2122 Internal::TextView& textViewImpl( GetImpl( textView ) );
2123 bool newValue( value.Get<bool>() );
2124 textViewImpl.SetMarkupProcessingEnabled( newValue );
2127 const std::string& currentText( textViewImpl.GetText() );
2128 if( ! currentText.empty() )
2130 textViewImpl.SetText( currentText );
2136 Property::Value TextView::GetProperty( BaseObject* object, Property::Index propertyIndex )
2138 Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) );
2140 if ( textView && ( propertyIndex == Toolkit::TextView::PROPERTY_MARKUP_ENABLED ) )
2142 return Property::Value( GetImpl( textView ).mMarkUpEnabled );
2145 return Property::Value();
2148 } // namespace Internal
2150 } // namespace Toolkit