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