Merge branch 'devel/new_mesh' into devel/master
[platform/core/uifw/dali-demo.git] / examples / page-turn-view / page-turn-view-example.cpp
1 /*
2  * Copyright (c) 2014 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/dali.h>
19 #include <dali-toolkit/dali-toolkit.h>
20 #include <dali-toolkit/devel-api/controls/page-turn-view/page-factory.h>
21 #include <dali-toolkit/devel-api/controls/page-turn-view/page-turn-landscape-view.h>
22 #include <dali-toolkit/devel-api/controls/page-turn-view/page-turn-portrait-view.h>
23 #include <dali-toolkit/devel-api/controls/page-turn-view/page-turn-view.h>
24
25 #include <assert.h>
26 #include <cstdlib>
27 #include <string.h>
28 #include <iostream>
29
30 #include "shared/view.h"
31
32 using namespace Dali;
33 using namespace Dali::Toolkit;
34
35 // LOCAL STUFF
36 namespace
37 {
38 // The content amount of one page between portrait and landscape view are different
39 // set a ratio to modify the current page number when the rotation is changed
40 const float PAGE_NUMBER_CORRESPONDING_RATIO(1.25f);
41
42 const char* BOOK_COVER_PORTRAIT = ( DALI_IMAGE_DIR "book-portrait-cover.jpg" );
43 const char* BOOK_COVER_LANDSCAPE = ( DALI_IMAGE_DIR "book-landscape-cover.jpg" );
44 const char* BOOK_COVER_BACK_LANDSCAPE = ( DALI_IMAGE_DIR "book-landscape-cover-back.jpg" );
45
46 const char* PAGE_IMAGES_PORTRAIT[] =
47 {
48   DALI_IMAGE_DIR "book-portrait-p1.jpg",
49   DALI_IMAGE_DIR "book-portrait-p2.jpg",
50   DALI_IMAGE_DIR "book-portrait-p3.jpg",
51   DALI_IMAGE_DIR "book-portrait-p4.jpg",
52   DALI_IMAGE_DIR "book-portrait-p5.jpg"
53 };
54 const unsigned int NUMBER_OF_PORTRAIT_IMAGE( sizeof(PAGE_IMAGES_PORTRAIT) / sizeof(PAGE_IMAGES_PORTRAIT[0]) );
55
56 const char* PAGE_IMAGES_LANDSCAPE[] =
57 {
58   DALI_IMAGE_DIR "book-landscape-p1.jpg",
59   DALI_IMAGE_DIR "book-landscape-p2.jpg",
60   DALI_IMAGE_DIR "book-landscape-p3.jpg",
61   DALI_IMAGE_DIR "book-landscape-p4.jpg",
62   DALI_IMAGE_DIR "book-landscape-p5.jpg",
63   DALI_IMAGE_DIR "book-landscape-p6.jpg",
64   DALI_IMAGE_DIR "book-landscape-p7.jpg",
65   DALI_IMAGE_DIR "book-landscape-p8.jpg"
66 };
67 const unsigned int NUMBER_OF_LANDSCAPE_IMAGE( sizeof(PAGE_IMAGES_LANDSCAPE) / sizeof(PAGE_IMAGES_LANDSCAPE[0]) );
68
69 }// end LOCAL STUFF
70
71 class PortraitPageFactory : public PageFactory
72 {
73   /**
74    * Query the number of pages available from the factory.
75    * The maximum available page has an ID of GetNumberOfPages()-1.
76    */
77   virtual unsigned int GetNumberOfPages()
78   {
79     return 5*NUMBER_OF_PORTRAIT_IMAGE + 1;
80   }
81   /**
82    * Create an image actor to represent a page.
83    * @param[in] pageId The ID of the page to create.
84    * @return An image actor, or an uninitialized pointer if the ID is out of range.
85    */
86   virtual Actor NewPage( unsigned int pageId )
87   {
88     ImageActor page;
89
90     if( pageId == 0 )
91     {
92       page = ImageActor::New( ResourceImage::New( BOOK_COVER_PORTRAIT ) );
93     }
94     else
95     {
96       page = ImageActor::New( ResourceImage::New( PAGE_IMAGES_PORTRAIT[ (pageId-1) % NUMBER_OF_PORTRAIT_IMAGE ] ) );
97     }
98
99     return page;
100   }
101 };
102
103 class LandscapePageFactory : public PageFactory
104 {
105   /**
106    * Query the number of pages available from the factory.
107    * The maximum available page has an ID of GetNumberOfPages()-1.
108    */
109   virtual unsigned int GetNumberOfPages()
110   {
111     return 5*NUMBER_OF_LANDSCAPE_IMAGE / 2 + 1;
112   }
113   /**
114    * Create an image actor to represent a page.
115    * @param[in] pageId The ID of the page to create.
116    * @return An image actor, or an uninitialized pointer if the ID is out of range.
117    */
118   virtual Actor NewPage( unsigned int pageId )
119   {
120     ImageActor pageFront;
121     ImageActor pageBack;
122     if( pageId == 0 )
123     {
124        pageFront = ImageActor::New( ResourceImage::New( BOOK_COVER_LANDSCAPE ) );
125        pageBack = ImageActor::New( ResourceImage::New( BOOK_COVER_BACK_LANDSCAPE ) );
126     }
127     else
128     {
129       unsigned int imageId = (pageId-1)*2;
130       pageFront = ImageActor::New( ResourceImage::New( PAGE_IMAGES_LANDSCAPE[ imageId % NUMBER_OF_LANDSCAPE_IMAGE ] ) );
131       pageBack = ImageActor::New( ResourceImage::New( PAGE_IMAGES_LANDSCAPE[ (imageId+1) % NUMBER_OF_LANDSCAPE_IMAGE ] ) );
132     }
133     pageFront.Add(pageBack);
134
135     return pageFront;
136   }
137 };
138
139 /**
140  * This example shows how to use the page turn UI control to implement the page-turn demo
141  * The effect follows the pan gesture to animate the page
142  * Pan the image inwards, the page will bent,
143  * Depends on the distance of the panning, the image might turn over or slide back
144  * Also, in portrait view, the pan gesture outwards from position near the spine could turn the previous page back
145  * Allows to turn multiple pages one by one quickly towards the same direction, multiple animations are launched in this case
146 */
147 class PageTurnController : public ConnectionTracker
148 {
149 public:
150   PageTurnController( Application &app );
151   ~PageTurnController();
152
153   //This method gets called once the main loop of application is up and running
154   void OnInit( Application& app );
155
156 private:
157
158   /**
159    * This method gets called when the screen is rotated, switch between portrait and landscape views
160    * param [in] orientation The current screen orientation
161    */
162   void OnOrientationAnimationStarted( Orientation orientation );
163
164   /**
165    * Main key event handler
166    */
167   void OnKeyEvent(const KeyEvent& event);
168
169   /**
170    * Callback function of page turned signal
171    * @param[in] pageTurnView The handle of the PageTurnPortraitView or PageTurnLandscapeView
172    * @param[in] pageIndex The index of the page turned over
173    * @param[in] isTurningForward The turning direction, forwards or backwards
174    */
175   void OnPageStartedTurn( PageTurnView pageTurnView, unsigned int pageIndex, bool isTurningForward );
176
177   /**
178    * Callback function of page turned signal
179    * @param[in] pageTurnView The handle of the PageTurnPortraitView or PageTurnLandscapeView
180    * @param[in] pageIndex The index of the page turned over
181    * @param[in] isTurningForward The turning direction, forwards or backwards
182    */
183   void OnPageFinishedTurn( PageTurnView pageTurnView, unsigned int pageIndex, bool isTurningForward );
184
185   /**
186    * Callback function of page started pan signal
187    *
188    * @param[in] pageTurnView The calling page turn view
189    */
190   void OnPageStartedPan( PageTurnView pageTurnView );
191
192   /**
193    * Callback function of page finished pan signal
194    *
195    * @param[in] pageTurnView The calling page turn view
196    */
197   void OnPageFinishedPan( PageTurnView pageTurnView );
198
199 private:
200
201   Application&                mApplication;
202   Actor                       mView;
203
204   PageTurnView                mPageTurnPortraitView;
205   PageTurnView                mPageTurnLandscapeView;
206   PortraitPageFactory         mPortraitPageFactory;
207   LandscapePageFactory        mLandscapePageFactory;
208
209   bool                        mIsPortrait;
210 };
211
212 PageTurnController::PageTurnController( Application &app )
213 :mApplication( app ),
214  mIsPortrait( true )
215 {
216   // Connect to the Application's Init signal
217   app.InitSignal().Connect( this, &PageTurnController::OnInit );
218 }
219
220 PageTurnController::~PageTurnController()
221 {
222 }
223
224
225 void PageTurnController::OnInit( Application& app )
226 {
227   // The Init signal is received once ( only ) during the Application lifetime
228
229   Stage::GetCurrent().KeyEventSignal().Connect(this, &PageTurnController::OnKeyEvent);
230
231   Stage stage = Stage::GetCurrent();
232   Vector2 stageSize =  stage.GetSize();
233
234   // Create default View.
235   mView = Actor::New();
236   mView.SetAnchorPoint( Dali::AnchorPoint::CENTER );
237   mView.SetParentOrigin( Dali::ParentOrigin::CENTER );
238   mView.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
239   stage.Add( mView );
240
241   Dali::Window winHandle = app.GetWindow();
242   winHandle.AddAvailableOrientation( Dali::Window::PORTRAIT );
243   winHandle.AddAvailableOrientation( Dali::Window::LANDSCAPE );
244   winHandle.AddAvailableOrientation( Dali::Window::PORTRAIT_INVERSE  );
245   winHandle.AddAvailableOrientation( Dali::Window::LANDSCAPE_INVERSE );
246
247   // view will response to orientation change to display portrait or landscape views
248   //app.GetWindow().GetOrientation().ChangedSignal().Connect( this, &PageTurnController::OnOrientationAnimationStarted );
249
250   mPageTurnPortraitView = PageTurnPortraitView::New( mPortraitPageFactory, stageSize );
251   mPageTurnPortraitView.SetSpineShadowParameter( Vector2(70.f, 30.f) );
252   mPageTurnPortraitView.PageTurnStartedSignal().Connect( this, &PageTurnController::OnPageStartedTurn );
253   mPageTurnPortraitView.PageTurnFinishedSignal().Connect( this, &PageTurnController::OnPageFinishedTurn );
254   mPageTurnPortraitView.PagePanStartedSignal().Connect( this, &PageTurnController::OnPageStartedPan );
255   mPageTurnPortraitView.PagePanFinishedSignal().Connect( this, &PageTurnController::OnPageFinishedPan );
256   mPageTurnPortraitView.SetPositionInheritanceMode( USE_PARENT_POSITION );
257
258   mPageTurnLandscapeView = PageTurnLandscapeView::New( mLandscapePageFactory, Vector2(stageSize.y*0.5f, stageSize.x) );
259   mPageTurnLandscapeView.PageTurnStartedSignal().Connect( this, &PageTurnController::OnPageStartedTurn );
260   mPageTurnLandscapeView.PageTurnFinishedSignal().Connect( this, &PageTurnController::OnPageFinishedTurn );
261   mPageTurnLandscapeView.PagePanStartedSignal().Connect( this, &PageTurnController::OnPageStartedPan );
262   mPageTurnLandscapeView.PagePanFinishedSignal().Connect( this, &PageTurnController::OnPageFinishedPan );
263   mPageTurnLandscapeView.SetPositionInheritanceMode( USE_PARENT_POSITION );
264
265   mView.Add(mPageTurnPortraitView);
266 }
267
268 void PageTurnController::OnOrientationAnimationStarted( Orientation orientation )
269 {
270   switch( orientation.GetDegrees() )
271   {
272     // portrait view, display page in the right side only
273     case 0:
274     case 180:
275     {
276       if( !mIsPortrait )
277       {
278         mView.Remove( mPageTurnLandscapeView );
279         mView.Add( mPageTurnPortraitView );
280         int currentPage = floor( static_cast<float>(mPageTurnLandscapeView.GetCurrentPage()) * PAGE_NUMBER_CORRESPONDING_RATIO );
281         mPageTurnPortraitView.GoToPage( currentPage );
282         mIsPortrait = true;
283       }
284       break;
285     }
286     // display pages in both sides
287     case 90:
288     case 270:
289     {
290       if( mIsPortrait )
291       {
292         mView.Remove( mPageTurnPortraitView );
293         mView.Add( mPageTurnLandscapeView );
294         int currentPage = ceil( static_cast<float>(mPageTurnPortraitView.GetCurrentPage()) / PAGE_NUMBER_CORRESPONDING_RATIO );
295         mPageTurnLandscapeView.GoToPage( currentPage );
296         mIsPortrait = false;
297       }
298       break;
299     }
300     default:
301     break;
302   }
303 }
304
305 /**
306  * Main key event handler
307  */
308 void PageTurnController::OnKeyEvent(const KeyEvent& event)
309 {
310   if(event.state == KeyEvent::Down)
311   {
312     if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
313     {
314       mApplication.Quit();
315     }
316   }
317 }
318
319 void PageTurnController::OnPageStartedTurn( PageTurnView pageTurnView, unsigned int pageIndex, bool isTurningForward )
320 {
321   std::cout<< ( ( pageTurnView == mPageTurnPortraitView ) ? " portrait: " : " Landscape: " )
322            << " page " << pageIndex
323            << ( isTurningForward ? " is starting to turn forward" : " is starting to turn backward" )
324            << std::endl;
325 }
326
327 void PageTurnController::OnPageFinishedTurn( PageTurnView pageTurnView, unsigned int pageIndex, bool isTurningForward )
328 {
329   std::cout<< ( ( pageTurnView == mPageTurnPortraitView ) ? " portrait: " : " Landscape: " )
330            << " page " << pageIndex
331            << ( isTurningForward ? " has finished turning forward" : " has finished turning backward" )
332            << std::endl;
333 }
334
335 void PageTurnController::OnPageStartedPan( PageTurnView pageTurnView )
336 {
337   std::cout<< "Starting to pan" << std::endl;
338 }
339
340 void PageTurnController::OnPageFinishedPan( PageTurnView pageTurnView )
341 {
342   std::cout<< "Finished panning" << std::endl;
343 }
344
345 // Entry point for applications
346 int main( int argc, char **argv )
347 {
348   Application app = Application::New(&argc, &argv, DALI_DEMO_THEME_PATH);
349   PageTurnController test ( app );
350
351   app.MainLoop();
352
353   return 0;
354 }
355