b6651d8f5b23d1083a3c8a0a434af5e5fb44c5a0
[platform/core/uifw/dali-demo.git] / examples / text-scrolling / text-scrolling-example.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 /**
19  * @file text-scrolling-example.cpp
20  * @brief Shows text labels with scrolling text and allows a text label and text field control to be scrolled vertically
21  */
22
23 // EXTERNAL INCLUDES
24 #include <dali-toolkit/dali-toolkit.h>
25
26 using namespace Dali;
27 using namespace Dali::Toolkit;
28
29 namespace
30 {
31 const float STAGE_HEIGHT_MULTIPLIER( 1.5f );
32 const Vector2 BOX_SIZE( Vector2(330.0f, 80.0f ) );
33 const Vector2 SCROLLING_BOX_SIZE( Vector2(330.0f, 40.0f ) );
34 const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f;
35 const float SCREEN_BORDER = 5.0f; // Border around screen that Popups and handles will not exceed
36
37 const char * ALIGNMENT_TABLE[] =
38 {
39   "BEGIN",
40   "CENTER",
41   "END"
42 };
43 const unsigned int ALIGNMENT_TABLE_COUNT = sizeof( ALIGNMENT_TABLE ) / sizeof( ALIGNMENT_TABLE[ 0 ] );
44
45 enum Labels
46 {
47   SMALL = 1u,
48   RTL = 1u << 1,
49   LARGE = 1u << 2,
50   RTL_LONG = 1u << 4,
51   NONE = 1u << 6,
52 };
53 }
54 /**
55  * @brief The main class of the demo.
56  */
57 class TextScrollingExample : public ConnectionTracker
58 {
59 public:
60
61   TextScrollingExample( Application& application )
62   : mApplication( application ),
63     mTargetActorPosition(),
64     mTargetActorSize(),
65     mToggleColor( false )
66   {
67     // Connect to the Application's Init signal
68     mApplication.InitSignal().Connect( this, &TextScrollingExample::Create );
69   }
70
71   ~TextScrollingExample()
72   {
73     // Nothing to do here.
74   }
75
76
77   void CreateBox( const std::string& name, Actor& box, Actor parent, const Vector2& size )
78   {
79     box.SetProperty( Dali::Actor::Property::NAME,name);
80     box.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
81     box.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
82     box.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT );
83     box.SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
84     box.SetSize( size.width, 0.f );
85     parent.Add( box );
86
87     Dali::Property::Map border;
88     border.Insert( Toolkit::Visual::Property::TYPE,  Visual::BORDER );
89     border.Insert( BorderVisual::Property::COLOR,  Color::BLUE );
90     border.Insert( BorderVisual::Property::SIZE,  1.f );
91     box.SetProperty( Control::Property::BACKGROUND, border );
92   }
93
94   void CreateLabel( Actor& label, const std::string text, Actor parent, bool scrollOnStart, PushButton button )
95   {
96     label = TextLabel::New( text );
97     label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
98     label.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
99     label.SetProperty( Actor::Property::PADDING, Padding( 1.0f, 1.0f, 1.0f, 1.0f ) );
100     label.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
101     label.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
102     parent.Add( label );
103
104     if ( scrollOnStart )
105     {
106       label.SetProperty(TextLabel::Property::ENABLE_AUTO_SCROLL, true);
107     }
108
109     button.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
110     button.SetSize(BOX_SIZE.height,BOX_SIZE.height);
111     button.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT );
112     button.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
113     parent.Add(button);
114   }
115
116
117   /**
118    * One-time setup in response to Application InitSignal.
119    */
120   void Create( Application& application )
121   {
122     Stage stage = Stage::GetCurrent();
123     mStageSize = stage.GetSize();
124
125     stage.KeyEventSignal().Connect(this, &TextScrollingExample::OnKeyEvent);
126
127     // Create Root actor
128     Actor rootActor = Actor::New();
129     rootActor.SetProperty( Dali::Actor::Property::NAME,"rootActor");
130     rootActor.SetResizePolicy( ResizePolicy::FIXED,  Dimension::ALL_DIMENSIONS );
131     rootActor.SetSize( mStageSize );
132     rootActor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
133
134     stage.Add( rootActor );
135
136     mAnimation = Animation::New( 1.0f );
137
138     const Size mTargetActorSize( mStageSize.width, mStageSize.height * STAGE_HEIGHT_MULTIPLIER );
139
140     // Create Desktop
141     Control desktop = Control::New();
142     desktop.SetBackgroundColor( Color::WHITE );
143     desktop.SetProperty( Dali::Actor::Property::NAME,"desktopActor");
144     desktop.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
145     desktop.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
146     desktop.SetSize( mTargetActorSize );
147
148     rootActor.Add( desktop ); // Add desktop (content) to offscreen actor
149
150     // Create Boxes
151     Control boxA = Control::New();
152     Control boxB = Control::New();
153     Control boxC = Control::New();
154     Control boxD = Control::New();
155     Control boxE = Control::New();
156
157     CreateBox( "boxA", boxA, desktop, BOX_SIZE );
158     boxA.SetPosition( 0.0f, -500.0f, 1.0f );
159
160     // Create TextField
161     TextField field = TextField::New();
162     field.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
163     field.SetProperty( Actor::Property::PADDING, Padding( 1.0f, 1.0f, 1.0f, 1.0f ) );
164     field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
165     field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "Enter Folder Name" );
166     field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect<int>( SCREEN_BORDER, SCREEN_BORDER, mStageSize.width - SCREEN_BORDER*2, mStageSize.height - SCREEN_BORDER*2 ) );
167     boxA.Add( field );
168     boxA.SetSize(BOX_SIZE);
169
170     CreateBox( "boxB", boxB, desktop, SCROLLING_BOX_SIZE );
171     boxB.SetPosition( 0.0f, -400.0f, 1.0f );
172     Toolkit::PushButton scrollLargeButton = Toolkit::PushButton::New();
173     scrollLargeButton.ClickedSignal().Connect( this, &TextScrollingExample::OnButtonClickedLarge );
174     CreateLabel( mLargeLabel, "A Quick Brown Fox Jumps Over The Lazy Dog", boxB, false ,scrollLargeButton );
175
176     CreateBox( "boxC", boxC, desktop, SCROLLING_BOX_SIZE );
177     boxC.SetPosition( 0.0f, -300.0f, 1.0f );
178     Toolkit::PushButton scrollSmallButton = Toolkit::PushButton::New();
179     scrollSmallButton.ClickedSignal().Connect( this, &TextScrollingExample::OnButtonClickedSmall );
180     CreateLabel( mSmallLabel, "Hello Text", boxC , true, scrollSmallButton );
181     mSmallLabel.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLACK );
182     Property::Map shadowMap;
183     shadowMap.Insert( "color", Color::CYAN );
184     shadowMap.Insert( "offset", Vector2( 1.0f, 1.0f ) );
185     mSmallLabel.SetProperty( TextLabel::Property::SHADOW, shadowMap );
186
187     CreateBox( "boxD", boxD, desktop, SCROLLING_BOX_SIZE );
188     boxD.SetPosition( 0.0f, -200.0f, 1.0f );
189     Toolkit::PushButton scrollRtlButton = Toolkit::PushButton::New();
190     scrollRtlButton.ClickedSignal().Connect( this, &TextScrollingExample::OnButtonClickedRtl );
191     CreateLabel( mRtlLabel, "مرحبا بالعالم", boxD , true, scrollRtlButton );
192     mRtlLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_STOP_MODE, TextLabel::AutoScrollStopMode::IMMEDIATE );
193     mRtlLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_LOOP_DELAY, 0.3f );
194
195     CreateBox( "boxE", boxE, desktop, SCROLLING_BOX_SIZE );
196     boxE.SetPosition( 0.0f, -100.0f, 1.0f );
197     Toolkit::PushButton scrollRtlLongButton = Toolkit::PushButton::New();
198     scrollRtlLongButton.ClickedSignal().Connect( this, &TextScrollingExample::OnButtonClickedRtlLong );
199     CreateLabel( mRtlLongLabel, " مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم مرحبا بالعالم", boxE , false, scrollRtlLongButton );
200     mRtlLongLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_SPEED, 500);
201     mRtlLongLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_GAP, 500);
202     mRtlLongLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3);
203     mRtlLongLabel.SetProperty(TextLabel::Property::AUTO_SCROLL_STOP_MODE, TextLabel::AutoScrollStopMode::FINISH_LOOP );
204
205     mPanGestureDetector = PanGestureDetector::New();
206     mPanGestureDetector.DetectedSignal().Connect(this, &TextScrollingExample::OnPanGesture );
207     mPanGestureDetector.Attach( desktop );
208
209     Toolkit::PushButton colorButton = Toolkit::PushButton::New();
210     colorButton.SetProperty( Button::Property::TOGGLABLE, true );
211     colorButton.SetProperty( Button::Property::UNSELECTED_BACKGROUND_VISUAL, Property::Map().Add ( Toolkit::Visual::Property::TYPE, Visual::COLOR ).Add( ColorVisual::Property::MIX_COLOR, Color::RED ) );
212     colorButton.SetProperty( Button::Property::SELECTED_BACKGROUND_VISUAL, Property::Map().Add ( Toolkit::Visual::Property::TYPE, Visual::COLOR ).Add( ColorVisual::Property::MIX_COLOR, Color::BLACK ) );
213     colorButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER );
214     colorButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER );
215     colorButton.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
216     colorButton.SetSize(BOX_SIZE.height,BOX_SIZE.height);
217     colorButton.ClickedSignal().Connect( this, &TextScrollingExample::OnColorButtonClicked );
218     rootActor.Add( colorButton );
219
220     for( unsigned int i = 0; i < ALIGNMENT_TABLE_COUNT; ++i )
221     {
222       Toolkit::RadioButton alignButton = Toolkit::RadioButton::New( ALIGNMENT_TABLE[ i ] );
223       alignButton.ClickedSignal().Connect( this, &TextScrollingExample::OnAlignButtonClicked );
224       alignButton.SetProperty( Dali::Actor::Property::NAME, ALIGNMENT_TABLE[ i ] );
225
226       // Place first button to left aligned, second center aligned and third right aligned
227       alignButton.SetProperty( Actor::Property::ANCHOR_POINT, Vector3( i * 0.5f, 0.0f, 0.5f ) );
228       alignButton.SetProperty( Actor::Property::PARENT_ORIGIN, Vector3( i * 0.5f, 0.0f, 0.5f ) );
229
230       rootActor.Add( alignButton );
231
232       if( i == 0 )
233       {
234         // Set the first button as selected
235         alignButton.SetProperty( Button::Property::SELECTED, true );
236       }
237     }
238   }
239
240   void EnableScrolling( Labels labels )
241     {
242       Actor label;
243       switch( labels )
244       {
245         case LARGE:
246         {
247           label = mLargeLabel;
248           break;
249         }
250         case RTL:
251         {
252           label = mRtlLabel;
253           break;
254         }
255         case SMALL:
256         {
257           label = mSmallLabel;
258           break;
259         }
260         case RTL_LONG:
261         {
262           label = mRtlLongLabel;
263           break;
264         }
265         case NONE:
266         {
267           return;
268         }
269       }
270
271       if ( labels != NONE )
272       {
273         Property::Value value = label.GetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL);
274         if (value.Get< bool >())
275         {
276           label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, false  );
277         }
278         else
279         {
280           label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true  );
281         }
282       }
283     }
284
285   bool OnButtonClickedSmall( Toolkit::Button button )
286   {
287     EnableScrolling( SMALL );
288     return true;
289   }
290
291   bool OnButtonClickedLarge( Toolkit::Button button )
292   {
293     EnableScrolling( LARGE );
294     return true;
295   }
296
297   bool OnButtonClickedRtl( Toolkit::Button button )
298   {
299     EnableScrolling( RTL );
300     return true;
301   }
302
303   bool OnButtonClickedRtlLong( Toolkit::Button button )
304   {
305     EnableScrolling( RTL_LONG );
306     return true;
307   }
308
309   bool OnColorButtonClicked( Toolkit::Button button )
310   {
311     Vector4 color = Color::RED;
312
313     if ( mToggleColor )
314     {
315       color = Color::BLACK;
316       mToggleColor = false;
317     }
318     else
319     {
320       mToggleColor = true;
321     }
322
323     Property::Map shadowMap;
324     shadowMap.Insert( "color", Color::BLACK );
325     mSmallLabel.SetProperty( TextLabel::Property::SHADOW, shadowMap );
326     mSmallLabel.SetProperty( TextLabel::Property::TEXT_COLOR, color );
327     mRtlLabel.SetProperty( TextLabel::Property::TEXT_COLOR, color );
328     mLargeLabel.SetProperty( TextLabel::Property::TEXT_COLOR, color );
329     mRtlLongLabel.SetProperty( TextLabel::Property::TEXT_COLOR, color );
330
331     return true;
332   }
333
334   bool OnAlignButtonClicked( Toolkit::Button button )
335   {
336     for( unsigned int index = 0; index < ALIGNMENT_TABLE_COUNT; ++index )
337     {
338       const std::string& buttonName = button.GetProperty< std::string >( Dali::Actor::Property::NAME );
339       if( buttonName == ALIGNMENT_TABLE[ index ] )
340       {
341         mSmallLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, ALIGNMENT_TABLE[ index ] );
342         mRtlLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, ALIGNMENT_TABLE[ index ] );
343         mLargeLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, ALIGNMENT_TABLE[ index ] );
344         mRtlLongLabel.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, ALIGNMENT_TABLE[ index ] );
345         break;
346       }
347     }
348
349     return true;
350   }
351
352   /**
353    * Main key event handler
354    */
355   void OnKeyEvent(const KeyEvent& event)
356   {
357     if(event.state == KeyEvent::Down)
358     {
359       if( IsKey( event, DALI_KEY_ESCAPE) || IsKey( event, DALI_KEY_BACK ) )
360       {
361         mApplication.Quit();
362       }
363       else
364       {
365         if ( event.keyPressedName == "2" )
366         {
367           mAnimation.AnimateTo( Property( mSmallLabel, Actor::Property::SCALE ), Vector3(1.2f, 1.2f, 0.0f), AlphaFunction::BOUNCE, TimePeriod( 1.0f, 1.0f ) );
368           mAnimation.AnimateTo( Property( mLargeLabel, Actor::Property::SCALE ), Vector3(1.2f, 1.2f, 0.0f), AlphaFunction::BOUNCE, TimePeriod( 1.0f, 1.0f ) );
369           mAnimation.AnimateTo( Property( mRtlLabel, Actor::Property::SCALE ), Vector3(1.2f, 1.2f, 0.0f), AlphaFunction::BOUNCE, TimePeriod( 1.0f, 1.0f ) );
370           mAnimation.AnimateTo( Property( mRtlLongLabel, Actor::Property::SCALE ), Vector3(1.2f, 1.2f, 0.0f), AlphaFunction::BOUNCE, TimePeriod( 1.0f, 1.0f ) );
371
372           mAnimation.Play();
373         }
374       }
375     }
376   }
377
378   void OnPanGesture( Actor actor, const PanGesture& gesture )
379   {
380     if( gesture.state == Gesture::Continuing )
381     {
382       Vector2 position = Vector2( gesture.displacement );
383       mTargetActorPosition.y = mTargetActorPosition.y + position.y;
384       mTargetActorPosition.y = std::min( mTargetActorPosition.y, -mTargetActorSize.height );
385       mTargetActorPosition.y = std::max( mTargetActorPosition.y, ( mTargetActorSize.height - mStageSize.height*0.25f ) );
386       actor.SetPosition( 0.0f, mTargetActorPosition.y );
387     }
388   }
389
390 private:
391
392   Application& mApplication;
393   PanGestureDetector mPanGestureDetector;
394
395   Vector2 mTargetActorPosition;
396   Vector2 mTargetActorSize;
397   Vector2 mStageSize;
398
399   TextLabel mLargeLabel;
400   TextLabel mSmallLabel;
401   TextLabel mRtlLabel;
402   TextLabel mRtlLongLabel;
403
404   Animation mAnimation;
405
406   bool mToggleColor;
407 };
408
409 int DALI_EXPORT_API main( int argc, char **argv )
410 {
411   Application application = Application::New( &argc, &argv, DEMO_THEME_PATH );
412   TextScrollingExample test( application );
413   application.MainLoop();
414   return 0;
415 }