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