Refactoring Gestures Class
[platform/core/uifw/dali-demo.git] / examples / image-view-svg / image-view-svg-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/devel-api/actors/actor-devel.h>
20 #include <string.h>
21
22 using namespace Dali;
23
24 namespace
25 {
26 const float MIN_SCALE = 0.6f;
27 const float MAX_SCALE = 6.f;
28
29 const char* SVG_IMAGES[] =
30 {
31     DEMO_IMAGE_DIR "Camera.svg",
32     DEMO_IMAGE_DIR "Contacts.svg",
33     DEMO_IMAGE_DIR "Mail.svg",
34     DEMO_IMAGE_DIR "Message.svg",
35     DEMO_IMAGE_DIR "Phone.svg",
36     DEMO_IMAGE_DIR "Settings.svg",
37     DEMO_IMAGE_DIR "World.svg",
38     DEMO_IMAGE_DIR "Kid1.svg"
39 };
40 const unsigned int NUM_SVG_IMAGES( sizeof( SVG_IMAGES ) / sizeof( SVG_IMAGES[0] ) );
41 const unsigned int NUM_IMAGES_DISPLAYED = 4u;
42 } // unnamed namespace
43
44 // This example shows how to display svg images with ImageView.
45 //
46 class ImageSvgController : public ConnectionTracker
47 {
48 public:
49
50   ImageSvgController( Application& application )
51   : mApplication( application ),
52     mScale( 1.f ),
53     mIndex( 0 )
54   {
55     // Connect to the Application's Init signal
56     mApplication.InitSignal().Connect( this, &ImageSvgController::Create );
57   }
58
59   ~ImageSvgController()
60   {
61   }
62
63   // The Init signal is received once (only) during the Application lifetime
64   void Create( Application& application )
65   {
66     // Get a handle to the window
67     Window window = application.GetWindow();
68     window.SetBackgroundColor( Color::WHITE );
69     Vector2 windowSize = window.GetSize();
70     mActorSize = windowSize/2.f;
71
72     window.KeyEventSignal().Connect(this, &ImageSvgController::OnKeyEvent);
73
74     // Background, for receiving gestures
75     mWindowBackground = Actor::New();
76     mWindowBackground.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER );
77     mWindowBackground.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER );
78     mWindowBackground.SetProperty( Actor::Property::SIZE, Vector2( windowSize.x, windowSize.y ) );
79     window.Add(mWindowBackground);
80
81     // Push button,  for changing the image set for displaying
82     Toolkit::PushButton changeButton = Toolkit::PushButton::New();
83     changeButton.SetProperty( Toolkit::Button::Property::LABEL, "Next" );
84     changeButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT );
85     changeButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_RIGHT );
86     window.Add( changeButton );
87     changeButton.ClickedSignal().Connect( this, &ImageSvgController::OnChangeButtonClicked );
88
89     // Push button, for resetting the actor size and position
90     Toolkit::PushButton resetButton = Toolkit::PushButton::New();
91     resetButton.SetProperty( Toolkit::Button::Property::LABEL, "Reset" );
92     resetButton.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
93     resetButton.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
94     window.Add( resetButton );
95     resetButton.ClickedSignal().Connect( this, &ImageSvgController::OnResetButtonClicked );
96
97     // Create and put imageViews to window
98     for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
99     {
100       mSvgActor[i] = Toolkit::ImageView::New(SVG_IMAGES[mIndex+i]);
101       mSvgActor[i].SetProperty( Actor::Property::SIZE, mActorSize );
102       mSvgActor[i].TranslateBy( Vector3( 0.0, windowSize.height * 0.05, 0.0f ) );
103       window.Add( mSvgActor[i] );
104     }
105     mSvgActor[0].SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
106     mSvgActor[0].SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_RIGHT );
107     mSvgActor[1].SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
108     mSvgActor[1].SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::BOTTOM_LEFT );
109     mSvgActor[2].SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
110     mSvgActor[2].SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_RIGHT );
111     mSvgActor[3].SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
112     mSvgActor[3].SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
113
114     // Connect pan gesture for moving the actors
115     mPanGestureDetector = PanGestureDetector::New();
116     mPanGestureDetector.DetectedSignal().Connect( this, &ImageSvgController::OnPanGesture );
117     mPanGestureDetector.Attach( mWindowBackground );
118
119     // Connect pinch gesture for resizing the actors
120     mPinchGestureDetector = PinchGestureDetector::New();
121     mPinchGestureDetector.Attach( mWindowBackground);
122     mPinchGestureDetector.DetectedSignal().Connect(this, &ImageSvgController::OnPinch);
123
124     changeButton.RaiseToTop();
125     resetButton.RaiseToTop();
126   }
127
128   // Callback of push button, for changing image set
129   bool OnChangeButtonClicked( Toolkit::Button button )
130   {
131     mIndex = ( mIndex + NUM_IMAGES_DISPLAYED ) % NUM_SVG_IMAGES;
132     for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
133     {
134       mSvgActor[i].SetImage(SVG_IMAGES[mIndex+i]);
135     }
136
137     return true;
138   }
139
140   // Callback of push button, for resetting image size and position
141   bool OnResetButtonClicked( Toolkit::Button button )
142   {
143     for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED ; i++ )
144     {
145       mSvgActor[i].SetProperty( Actor::Property::SIZE, mActorSize);
146       mSvgActor[i].SetProperty( Actor::Property::POSITION, Vector3::ZERO );
147       mScale = 1.f;
148     }
149
150     return true;
151   }
152
153   // Callback of pan gesture, for moving the actors
154   void OnPanGesture( Actor actor, const PanGesture& gesture )
155   {
156     if( gesture.GetState() == Gesture::Continuing )
157     {
158       for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
159       {
160         mSvgActor[i].TranslateBy(Vector3(gesture.GetDisplacement()));
161       }
162     }
163   }
164
165   // Callback of pinch gesture, for resizing the actors
166   void OnPinch(Actor actor, const PinchGesture& gesture)
167   {
168     switch( gesture.GetState() )
169     {
170       // Only scale the image when we start or continue pinching
171
172       case Gesture::Started:
173       case Gesture::Continuing:
174       {
175         float scale = std::max( gesture.GetScale(), MIN_SCALE / mScale );
176         scale = std::min( MAX_SCALE / mScale, scale );
177
178         for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
179         {
180           mSvgActor[i].SetProperty( Actor::Property::SCALE, scale );
181         }
182         break;
183       }
184
185       case Gesture::Finished:
186       {
187         // Resize the image when pinching is complete, this will rasterize the SVG to the new size
188
189         mScale = mScale * gesture.GetScale();
190         mScale = mScale > MAX_SCALE ? MAX_SCALE : mScale;
191         mScale = mScale < MIN_SCALE ? MIN_SCALE : mScale;
192         for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
193         {
194           mSvgActor[i].SetProperty( Actor::Property::SIZE, mActorSize * mScale );
195           mSvgActor[i].SetProperty( Actor::Property::SCALE, 1.0f );
196         }
197         break;
198       }
199
200       case Gesture::Cancelled:
201       case Gesture::Clear:
202       case Gesture::Possible:
203         break;
204     }
205   }
206
207   /**
208     * Main key event handler
209     */
210    void OnKeyEvent(const KeyEvent& event)
211    {
212      if(event.GetState() == KeyEvent::DOWN)
213      {
214        if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
215        {
216          mApplication.Quit();
217        }
218        else
219        {
220          const char* keyName = event.GetKeyName().c_str();
221          if( strcmp(keyName, "Left") == 0 )
222          {
223            if( mScale > MIN_SCALE )
224            {
225              mScale /= 1.1f;
226            }
227            for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
228            {
229              mSvgActor[i].SetProperty( Actor::Property::SIZE, mActorSize * mScale );
230            }
231          }
232          else if( strcmp(keyName, "Right") == 0 )
233          {
234            if( mScale < MAX_SCALE )
235            {
236              mScale *= 1.1f;
237            }
238            for( unsigned int i = 0; i < NUM_IMAGES_DISPLAYED; i++ )
239            {
240              mSvgActor[i].SetProperty( Actor::Property::SIZE, mActorSize * mScale );
241            }
242          }
243        }
244      }
245    }
246
247 private:
248   Application&         mApplication;
249   Actor                mWindowBackground;
250   PanGestureDetector   mPanGestureDetector;
251   PinchGestureDetector mPinchGestureDetector;
252
253   Toolkit::ImageView  mSvgActor[4];
254   Vector2             mActorSize;
255   float               mScale;
256   unsigned int        mIndex;
257 };
258
259 int DALI_EXPORT_API main( int argc, char **argv )
260 {
261   Application application = Application::New( &argc, &argv );
262   ImageSvgController test( application );
263   application.MainLoop();
264   return 0;
265 }