Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / clipping / clipping-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 #include <dali/devel-api/actors/actor-devel.h>
22
23 // INTERNAL INCLUDES
24 #include "clipping-item-factory.h"
25 #include "item-view-orientation-constraint.h"
26
27 using namespace Dali;
28 using namespace Dali::Toolkit;
29
30 namespace
31 {
32 const char* const APPLICATION_TITLE("Clipping Controls");
33 const Vector3     APPLICATION_TITLE_PARENT_ORIGIN(0.5f, 0.03f, 0.5f); // Set the parent origin to a small percentage below the top (so the demo will scale for different resolutions).
34
35 const Vector3 ITEM_VIEW_LAYOUT_SIZE_SCALE(0.75f, 0.5f, 0.75f);
36 const float   ITEM_VIEW_BORDER_SIZE                       = 2.0f;
37 const float   ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES       = 20.0f;
38 const float   ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER = 3.0f;
39 const float   ITEM_VIEW_ROTATION_ANIMATION_TIME           = 0.2f;
40
41 const char* const BUTTON_LABEL("Toggle Clipping Mode");
42 } // unnamed namespace
43
44 /**
45  * @brief Demonstrates the control clipping of a UI Control.
46  *
47  * When an Actor is set to clip its children, the renderers have to be added manually in order to specify what its children
48  * need to clip to. UI Controls automate the creation of the renderers/visuals when they are set to clip their children.
49  *
50  * This example displays an item-view whose clipping mode is toggled without the need for adding any renderers to it.
51  *
52  * Additionally, a constraint is used to modify the item-view's orientation.
53  */
54 class ClippingExample : public ConnectionTracker
55 {
56 public:
57   /**
58    * @brief Constructor.
59    * @param[in] application A reference to the Application class.
60    */
61   ClippingExample(Application& application)
62   : mApplication(application)
63   {
64     // Connect to the Application's Init signal
65     mApplication.InitSignal().Connect(this, &ClippingExample::Create);
66   }
67
68 private:
69   /**
70    * @brief Called to initialise the application content.
71    * @param[in] application A reference to the Application class.
72    */
73   void Create(Application& application)
74   {
75     // Connect to the window's key signal to allow Back and Escape to exit.
76     Window window = application.GetWindow();
77     window.KeyEventSignal().Connect(this, &ClippingExample::OnKeyEvent);
78
79     // Create a TextLabel for the application title.
80     Toolkit::TextLabel label = Toolkit::TextLabel::New(APPLICATION_TITLE);
81     label.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER);
82     label.SetProperty(Actor::Property::PARENT_ORIGIN, APPLICATION_TITLE_PARENT_ORIGIN);
83     label.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER");
84     label.SetProperty(Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER");
85     label.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::WHITE);
86     window.Add(label);
87
88     // Create an item-view which clips its children.
89     mItemView = ItemView::New(mClippingItemFactory);
90     mItemView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
91     mItemView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
92     mItemView.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN); // Enable clipping. No need to create any renderers.
93     window.Add(mItemView);
94
95     // Create a Spiral Layout and add it to the Item View.
96     mItemView.AddLayout(*DefaultItemLayout::New(DefaultItemLayout::SPIRAL));
97     window.GetRootLayer().SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D); // The item-view spiral layout requires Layer 3D behaviour.
98
99     // Calculate the size we would like our item-view layout to be, and then activate the layout.
100     const Vector2 windowSize = window.GetSize();
101     const Vector3 itemViewLayoutSize(ITEM_VIEW_LAYOUT_SIZE_SCALE.x * windowSize.x, ITEM_VIEW_LAYOUT_SIZE_SCALE.y * windowSize.y, ITEM_VIEW_LAYOUT_SIZE_SCALE.z * windowSize.x);
102     mItemView.ActivateLayout(0, itemViewLayoutSize, 0.0f);
103
104     // Connect to the scroll started and completed signals to apply orientation constraints & animations.
105     mItemView.ScrollStartedSignal().Connect(this, &ClippingExample::ScrollStarted);
106     mItemView.ScrollCompletedSignal().Connect(this, &ClippingExample::ScrollCompleted);
107
108     // Create a constraint for the item-view which we apply when we start scrolling and remove when we stop.
109     mItemViewOrientationConstraint = Constraint::New<Quaternion>(mItemView, Actor::Property::ORIENTATION, ItemViewOrientationConstraint(ITEM_VIEW_MAXIMUM_ROTATION_IN_DEGREES, ITEM_VIEW_LAYOUT_POSITION_CHANGE_MULTIPLIER));
110     mItemViewOrientationConstraint.AddSource(LocalSource(ItemView::Property::LAYOUT_POSITION));
111
112     // Create a border around item-view (as item-view is clipping its children, we should NOT add this as a child of item-view).
113     Control border = Control::New();
114     border.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
115     border.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
116     border.SetProperty(Control::Property::BACKGROUND,
117                        Property::Map().Add(Toolkit::Visual::Property::TYPE, Visual::BORDER).Add(BorderVisual::Property::COLOR, Color::WHITE).Add(BorderVisual::Property::SIZE, 2.0f).Add(BorderVisual::Property::ANTI_ALIASING, true));
118     border.SetProperty(Actor::Property::SIZE, Vector3(itemViewLayoutSize.x + ITEM_VIEW_BORDER_SIZE * 2.0f, itemViewLayoutSize.y + ITEM_VIEW_BORDER_SIZE * 2.0f, itemViewLayoutSize.z + ITEM_VIEW_BORDER_SIZE * 2.0f));
119     window.Add(border);
120
121     // Constrain the border's orientation to the orientation of item-view.
122     Constraint constraint = Constraint::New<Quaternion>(border, Actor::Property::ORIENTATION, EqualToConstraint());
123     constraint.AddSource(Source(mItemView, Actor::Property::ORIENTATION));
124     constraint.Apply();
125
126     // Create a button to toggle the clipping mode
127     PushButton button = Toolkit::PushButton::New();
128     button.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::BOTTOM_CENTER);
129     button.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_CENTER);
130     button.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH);
131     button.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT);
132     button.SetProperty(Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D);
133     button.SetProperty(Button::Property::LABEL, BUTTON_LABEL);
134     button.ClickedSignal().Connect(this, &ClippingExample::OnButtonClicked);
135     window.Add(button);
136   }
137
138   /**
139    * @brief Called when the item-view starts to scroll.
140    *
141    * Here we want to apply the item-view constraint.
142    */
143   void ScrollStarted(const Vector2& /* currentScrollPosition */)
144   {
145     mItemViewOrientationConstraint.Apply();
146   }
147
148   /**
149    * @brief Called when the item-view scrolling completes.
150    *
151    * Here we remove the item-view orientation constraint and perform an animation to return the item-view back to base-rotation.
152    */
153   void ScrollCompleted(const Vector2& /* currentScrollPosition */)
154   {
155     Animation animation = Animation::New(ITEM_VIEW_ROTATION_ANIMATION_TIME);
156     animation.AnimateTo(Property(mItemView, Actor::Property::ORIENTATION), Quaternion(Degree(0.0f), Vector3::XAXIS), AlphaFunction::EASE_IN_SINE);
157     animation.Play();
158
159     mItemViewOrientationConstraint.Remove();
160   }
161
162   /**
163    * @brief Called when any key event is received
164    *
165    * Will use this to quit the application if Back or the Escape key is received
166    * @param[in] event The key event information
167    */
168   void OnKeyEvent(const KeyEvent& event)
169   {
170     if(event.GetState() == KeyEvent::DOWN)
171     {
172       if(IsKey(event, DALI_KEY_ESCAPE) || IsKey(event, DALI_KEY_BACK))
173       {
174         mApplication.Quit();
175       }
176     }
177   }
178
179   /**
180    * @brief Called when the button is clicked.
181    *
182    * Will use this to toggle between the clipping modes.
183    * @param[in] button The button that has been clicked.
184    */
185   bool OnButtonClicked(Toolkit::Button button)
186   {
187     if(mItemView)
188     {
189       ClippingMode::Type currentMode = static_cast<ClippingMode::Type>(mItemView.GetProperty(Actor::Property::CLIPPING_MODE).Get<int>());
190       mItemView.SetProperty(Actor::Property::CLIPPING_MODE, (currentMode == ClippingMode::CLIP_CHILDREN) ? ClippingMode::DISABLED : ClippingMode::CLIP_CHILDREN);
191     }
192     return true;
193   }
194
195   // Data
196
197   Application&        mApplication;                   ///< Reference to the application class.
198   ItemView            mItemView;                      ///< The item view which whose children we would like to clip.
199   ClippingItemFactory mClippingItemFactory;           ///< The ItemFactory used to create our items.
200   Constraint          mItemViewOrientationConstraint; ///< The constraint used to control the orientation of item-view.
201 };
202
203 int DALI_EXPORT_API main(int argc, char** argv)
204 {
205   Application     app = Application::New(&argc, &argv, DEMO_THEME_PATH);
206   ClippingExample test(app);
207   app.MainLoop();
208   return 0;
209 }