[dali_2.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / image-view / image-view-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 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
20 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
21 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
22 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
23 #include <dali/dali.h>
24 #include <string>
25 #include "shared/view.h"
26
27 using namespace Dali;
28
29 namespace
30 {
31 const char* BACKGROUND_IMAGE(DEMO_IMAGE_DIR "background-gradient.jpg");
32 const char* TOOLBAR_IMAGE(DEMO_IMAGE_DIR "top-bar.png");
33 const char* APPLICATION_TITLE("Image view");
34
35 const char* IMAGE_PATH[] = {
36   DEMO_IMAGE_DIR "gallery-small-23.jpg",
37   DEMO_IMAGE_DIR "woodEffect.jpg",
38   DEMO_IMAGE_DIR "wood.png", // 32bits image
39   DEMO_IMAGE_DIR "heartsframe.9.png",
40   DEMO_IMAGE_DIR "World.svg"};
41
42 const unsigned int NUMBER_OF_IMAGES = 3;
43
44 enum CellPlacement
45 {
46   TOP_BUTTON,
47   MID_BUTTON,
48   LOWER_BUTTON,
49   IMAGE,
50   NUMBER_OF_ROWS
51 };
52
53 unsigned int GetButtonIndex(Toolkit::Button button)
54 {
55   std::string  buttonName = button.GetProperty<std::string>(Dali::Actor::Property::NAME);
56   unsigned int index      = 0;
57
58   if(buttonName != "")
59   {
60     index = std::stoul(buttonName);
61   }
62
63   return index;
64 }
65
66 const unsigned int NUMBER_OF_RESOURCES = sizeof(IMAGE_PATH) / sizeof(char*);
67
68 std::string EXAMPLE_INSTRUCTIONS =
69   "Instructions: Change button cycles through different image visuals, "
70   "on/off takes the ImageView and it's current visual on or off window.";
71
72 const float CORNER_RADIUS_VALUE(20.0f);
73 const float BORDERLINE_WIDTH_VALUE(10.0f);
74 const float BORDERLINE_OFFSET_VALUE(-1.0f); ///< draw borderline inside of imageview.
75 enum {
76   STATUS_NORMAL             = 0,
77   STATUS_ROUND              = 1,
78   STATUS_BORDERLINE         = 2,
79   STATUS_ROUNDED_BORDERLINE = STATUS_ROUND | STATUS_BORDERLINE,
80   NUMBER_OF_STATUS,
81 };
82 const char* BUTTON_LABEL[NUMBER_OF_STATUS] = {
83   "Normal",
84   "Round",
85   "Borderline",
86   "RoundBorderline",
87 };
88
89 } // namespace
90
91 class ImageViewController : public ConnectionTracker
92 {
93 public:
94   ImageViewController(Application& application)
95   : mApplication(application),
96     mCurrentPositionToggle(0, 0),
97     mCurrentPositionImage(0, 0)
98   {
99     // Connect to the Application's Init signal
100     mApplication.InitSignal().Connect(this, &ImageViewController::Create);
101   }
102
103   ~ImageViewController()
104   {
105     // Nothing to do here
106   }
107
108   void Create(Application& application)
109   {
110     // The Init signal is received once (only) during the Application lifetime
111
112     // Creates a default view with a default tool bar.
113     // The view is added to the window.
114     mContentLayer = DemoHelper::CreateView(application,
115                                            mView,
116                                            mToolBar,
117                                            BACKGROUND_IMAGE,
118                                            TOOLBAR_IMAGE,
119                                            APPLICATION_TITLE);
120
121     // Create a table view to show a pair of buttons above each image.
122     mTable = Toolkit::TableView::New(CellPlacement::NUMBER_OF_ROWS, NUMBER_OF_IMAGES);
123     mTable.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
124     mTable.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
125     mTable.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
126     Vector3 offset(0.9f, 0.70f, 0.0f);
127     mTable.SetProperty(Actor::Property::SIZE_MODE_FACTOR, offset);
128     mTable.SetFitHeight(CellPlacement::TOP_BUTTON);
129     mTable.SetFitHeight(CellPlacement::MID_BUTTON);
130     mTable.SetFitHeight(CellPlacement::LOWER_BUTTON);
131     mContentLayer.Add(mTable);
132
133     Toolkit::TextLabel instructions = Toolkit::TextLabel::New(EXAMPLE_INSTRUCTIONS);
134     instructions.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
135     instructions.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
136     instructions.SetProperty(Actor::Property::POSITION_Y, -50.0f);
137     instructions.SetProperty(Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL, true);
138     instructions.SetProperty(Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 10);
139     mContentLayer.Add(instructions);
140
141     for(unsigned int x = 0; x < NUMBER_OF_IMAGES; x++)
142     {
143       Toolkit::PushButton button = Toolkit::PushButton::New();
144       button.SetProperty(Toolkit::Button::Property::LABEL, "on/off");
145       button.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER);
146       button.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
147       button.ClickedSignal().Connect(this, &ImageViewController::ToggleImageOnWindow);
148       button.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
149       button.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT);
150       std::string s = std::to_string(x);
151       button.SetProperty(Dali::Actor::Property::NAME, s);
152       mTable.AddChild(button, Toolkit::TableView::CellPosition(CellPlacement::TOP_BUTTON, x));
153
154       Toolkit::PushButton button2 = Toolkit::PushButton::New();
155       button2.SetProperty(Toolkit::Button::Property::LABEL, "Change");
156       button2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
157       button2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
158       button2.ClickedSignal().Connect(this, &ImageViewController::ChangeImageClicked);
159       button2.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
160       button2.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT);
161       button2.SetProperty(Dali::Actor::Property::NAME, s);
162       mTable.AddChild(button2, Toolkit::TableView::CellPosition(CellPlacement::MID_BUTTON, x));
163
164       Toolkit::PushButton button3 = Toolkit::PushButton::New();
165       button3.SetProperty(Toolkit::Button::Property::LABEL, BUTTON_LABEL[STATUS_NORMAL]);
166       button3.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
167       button3.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
168       button3.ClickedSignal().Connect(this, &ImageViewController::RoundedCornerClicked);
169       button3.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
170       button3.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT);
171       button3.SetProperty(Dali::Actor::Property::NAME, s);
172       mTable.AddChild(button3, Toolkit::TableView::CellPosition(CellPlacement::LOWER_BUTTON, x));
173
174       mImageViews[x] = Toolkit::ImageView::New();
175       Property::Map imagePropertyMap;
176       imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
177       imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, IMAGE_PATH[0]);
178       mImageViews[x].SetProperty(Toolkit::ImageView::Property::IMAGE, imagePropertyMap);
179
180       mImageViews[x].SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
181       mImageViews[x].SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
182       mImageViews[x].SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
183       mTable.AddChild(mImageViews[x], Toolkit::TableView::CellPosition(CellPlacement::IMAGE, x));
184
185       // Set changeable counter and toggle for each ImageView
186       mImageViewImageIndexStatus[x]    = 0;
187       mImageViewToggleStatus[x]        = true;
188       mImageViewRoundedCornerStatus[x] = STATUS_NORMAL;
189     }
190
191     application.GetWindow().KeyEventSignal().Connect(this, &ImageViewController::OnKeyEvent);
192   }
193
194 private:
195   void ImmediateLoadImage(const char* urlToLoad)
196   {
197     Property::Map imagePropertyMap;
198     imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
199     imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, urlToLoad);
200     Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);
201     visual.Reset();
202   }
203
204   bool ToggleImageOnWindow(Toolkit::Button button)
205   {
206     unsigned int buttonIndex = GetButtonIndex(button);
207
208     Toolkit::ImageView imageView = mImageViews[buttonIndex];
209
210     if(mImageViewToggleStatus[buttonIndex])
211     {
212       imageView.Unparent();
213     }
214     else
215     {
216       mTable.AddChild(imageView, Toolkit::TableView::CellPosition(CellPlacement::IMAGE, GetButtonIndex(button)));
217     }
218
219     mImageViewToggleStatus[buttonIndex] = !mImageViewToggleStatus[buttonIndex];
220
221     return true;
222   }
223
224   bool ChangeImageClicked(Toolkit::Button button)
225   {
226     unsigned int buttonIndex = GetButtonIndex(button);
227
228     if(mImageViews[buttonIndex].GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
229     {
230       ++mImageViewImageIndexStatus[buttonIndex];
231
232       if(mImageViewImageIndexStatus[buttonIndex] == NUMBER_OF_RESOURCES)
233       {
234         mImageViewImageIndexStatus[buttonIndex] = 0;
235       }
236
237       Property::Map imagePropertyMap;
238       imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
239       imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, IMAGE_PATH[mImageViewImageIndexStatus[buttonIndex]]);
240       if(mImageViewRoundedCornerStatus[buttonIndex] & STATUS_ROUND)
241       {
242         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS_VALUE);
243       }
244       if(mImageViewRoundedCornerStatus[buttonIndex] & STATUS_BORDERLINE)
245       {
246         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH_VALUE);
247         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET_VALUE);
248       }
249
250       mImageViews[buttonIndex].SetProperty(Toolkit::ImageView::Property::IMAGE, imagePropertyMap);
251     }
252     return true;
253   }
254
255   bool RoundedCornerClicked(Toolkit::Button button)
256   {
257     unsigned int buttonIndex = GetButtonIndex(button);
258
259     if(mImageViews[buttonIndex].GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
260     {
261       mImageViewRoundedCornerStatus[buttonIndex] = (mImageViewRoundedCornerStatus[buttonIndex] + 1) % NUMBER_OF_STATUS;
262
263       button.SetProperty(Toolkit::Button::Property::LABEL, BUTTON_LABEL[mImageViewRoundedCornerStatus[buttonIndex]]);
264
265       Property::Map imagePropertyMap;
266       imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
267       imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, IMAGE_PATH[mImageViewImageIndexStatus[buttonIndex]]);
268       if(mImageViewRoundedCornerStatus[buttonIndex] & STATUS_ROUND)
269       {
270         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS_VALUE);
271       }
272       if(mImageViewRoundedCornerStatus[buttonIndex] & STATUS_BORDERLINE)
273       {
274         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH_VALUE);
275         imagePropertyMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET_VALUE);
276       }
277
278       mImageViews[buttonIndex].SetProperty(Toolkit::ImageView::Property::IMAGE, imagePropertyMap);
279     }
280     return true;
281   }
282
283   /**
284    * Main key event handler
285    */
286   void OnKeyEvent(const KeyEvent& event)
287   {
288     if(event.GetState() == KeyEvent::DOWN)
289     {
290       if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
291       {
292         mApplication.Quit();
293       }
294     }
295   }
296
297 private:
298   Application& mApplication;
299
300   Toolkit::Control   mView;         ///< The View instance.
301   Toolkit::ToolBar   mToolBar;      ///< The View's Toolbar.
302   Layer              mContentLayer; ///< Content layer
303   Toolkit::TableView mTable;
304   Toolkit::ImageView mImageViews[NUMBER_OF_IMAGES];
305   bool               mImageViewToggleStatus[NUMBER_OF_IMAGES];
306   unsigned int       mImageViewRoundedCornerStatus[NUMBER_OF_IMAGES];
307   unsigned int       mImageViewImageIndexStatus[NUMBER_OF_IMAGES];
308
309   Toolkit::TableView::CellPosition mCurrentPositionToggle;
310   Toolkit::TableView::CellPosition mCurrentPositionImage;
311 };
312
313 int DALI_EXPORT_API main(int argc, char** argv)
314 {
315   Application         application = Application::New(&argc, &argv, DEMO_THEME_PATH);
316   ImageViewController test(application);
317   application.MainLoop();
318   return 0;
319 }