1a01c445c8a7bf765a2ad6854b62e6559f9f5d63
[platform/core/uifw/dali-demo.git] / examples / simple-scroll-view / simple-scroll-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 // EXTERNAL INCLUDES
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali/dali.h>
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24
25 namespace
26 {
27 const int NUMBER_OF_PAGES = 9; ///< Number of Pages going across
28 const int ROWS_PER_PAGE   = 5; ///< Number of Images going down (rows) within a Page
29
30 const float DISTANCE_BETWEEN_IMAGES = 6.0f; ///< The distance between the images
31
32 } // unnamed namespace
33
34 /**
35  * An example showing how to create a very simple scroll view
36  */
37 class ExampleController : public ConnectionTracker
38 {
39 public:
40   /**
41    * Constructor
42    * @param application class, stored as reference
43    */
44   ExampleController(Application& application)
45   : mApplication(application)
46   {
47     // Connect to the Application's Init and orientation changed signal
48     mApplication.InitSignal().Connect(this, &ExampleController::OnInit);
49   }
50
51   ~ExampleController() = default;
52
53 private:
54   /**
55    * This method gets called once the main loop of application is up and running
56    */
57   void OnInit(Application& app)
58   {
59     Window  window     = app.GetWindow();
60     Vector2 windowSize = window.GetSize();
61     window.SetBackgroundColor(Color::WHITE);
62     window.KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
63
64     // Make the scroll view's size a certain percentage of the window
65     const Vector2 pageSize = windowSize * 0.75f;
66
67     // Create a scroll view and set our desired properties
68     ScrollView scrollView = ScrollView::New();
69     scrollView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
70     scrollView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
71     scrollView.SetProperty(Actor::Property::SIZE, pageSize);
72     scrollView.SetAxisAutoLock(true);
73     window.Add(scrollView);
74
75     // We want to the scroll-view so only one page is shown
76     scrollView.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX);
77
78     // Create rulers for the X and Y domains, we want to disable vertical scrolling but enable horizontal scrolling
79     RulerPtr rulerX = new FixedRuler(pageSize.width); // Snaps to a multiple of this when flicking
80     RulerPtr rulerY = new DefaultRuler;
81     rulerX->SetDomain(RulerDomain(0.0f, pageSize.width * NUMBER_OF_PAGES, true)); // Set the domain to equal the number of pages used
82     rulerY->Disable();
83
84     scrollView.SetRulerX(rulerX);
85     scrollView.SetRulerY(rulerY);
86
87     // Populate the Pages
88     for(int column = 0, textNumber = 0; column < NUMBER_OF_PAGES; column++)
89     {
90       Actor page = CreatePage(pageSize, textNumber);
91       page.SetProperty(Actor::Property::POSITION, Vector2(column * pageSize.x, 0.0f));
92       scrollView.Add(page);
93     }
94
95     // Do a little animation from the last page to the first page on load
96     scrollView.ScrollTo(NUMBER_OF_PAGES - 1, 0.0f);
97     scrollView.ScrollTo(0);
98   }
99
100   /**
101    * Creates a page using a source of images.
102    */
103   Actor CreatePage(const Vector2& pageSize, int& textNumber)
104   {
105     Actor page = Actor::New();
106     page.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
107     page.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
108     page.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
109
110     Window window = mApplication.GetWindow();
111
112     // Calculate the number of images going across (columns) within a page, the image size and the size of the text
113     const int     imageColumns = round(ROWS_PER_PAGE * (pageSize.width) / (pageSize.height));
114     const Vector3 imageSize((pageSize.width / imageColumns) - DISTANCE_BETWEEN_IMAGES,
115                             (pageSize.height / ROWS_PER_PAGE) - DISTANCE_BETWEEN_IMAGES,
116                             0.0f);
117     const float   textPixelSize = imageSize.width / 3.0f;
118
119     // Populate the page
120     for(int row = 0; row < ROWS_PER_PAGE; row++)
121     {
122       for(int column = 0; column < imageColumns; column++)
123       {
124         const Vector3 position(DISTANCE_BETWEEN_IMAGES * 0.5f + (imageSize.x + DISTANCE_BETWEEN_IMAGES) * column - pageSize.width * 0.5f,
125                                DISTANCE_BETWEEN_IMAGES * 0.5f + (imageSize.y + DISTANCE_BETWEEN_IMAGES) * row - pageSize.height * 0.5f,
126                                0.0f);
127
128         Control item = TextLabel::New(std::to_string(textNumber++));
129         item.SetProperty(Actor::Property::POSITION, position + imageSize * 0.5f);
130         item.SetProperty(Actor::Property::SIZE, imageSize);
131         item.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
132         item.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
133         item.SetProperty(TextLabel::Property::TEXT_COLOR, Color::BLACK);
134         item.SetProperty(TextLabel::Property::PIXEL_SIZE, textPixelSize);
135         item.SetProperty(TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER);
136         item.SetProperty(TextLabel::Property::VERTICAL_ALIGNMENT, VerticalAlignment::CENTER);
137         item.SetProperty(TextLabel::Property::OUTLINE, Property::Map{{"width", 2}, {"color", Color::WHITE}});
138         item.SetProperty(Control::Property::BACKGROUND, Vector4(Random::Range(0.0f, 1.0f), Random::Range(0.0f, 1.0f), Random::Range(0.0f, 1.0f), 0.7f));
139         page.Add(item);
140       }
141     }
142
143     return page;
144   }
145
146   /**
147    * Main key event handler
148    */
149   void OnKeyEvent(const KeyEvent& event)
150   {
151     if(event.GetState() == KeyEvent::DOWN)
152     {
153       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
154       {
155         mApplication.Quit();
156       }
157     }
158   }
159
160 private:
161   Application& mApplication; ///< Application instance
162 };
163
164 int DALI_EXPORT_API main(int argc, char** argv)
165 {
166   Application       app = Application::New(&argc, &argv, DEMO_THEME_PATH);
167   ExampleController test(app);
168   app.MainLoop();
169   return 0;
170 }