Reorganised folders & examples automatically built
[platform/core/uifw/dali-demo.git] / builder / dali-builder.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 //
19 // Run a json script layout file
20 //
21 //  - watches an named file and reloads actor tree if the file changes
22 //    ie run
23 //       builder-run layout.json
24 //
25 //       and edit layout.json in a text editor saving to trigger the reload
26 //
27 //------------------------------------------------------------------------------
28
29 #include <dali/dali.h>
30 #include <dali-toolkit/dali-toolkit.h>
31 #include <dali-toolkit/public-api/builder/builder.h>
32 #include <dali-toolkit/public-api/builder/tree-node.h>
33 #include <iostream>
34 #include <map>
35 #include <string>
36 #include <fstream>
37 #include <streambuf>
38 #include <boost/scoped_ptr.hpp>
39
40 //#include <boost/regex.hpp>
41 #include "sys/stat.h"
42 #include <ctime>
43
44 #include <dali/integration-api/debug.h>
45
46 #define TOKEN_STRING(x) #x
47
48 using namespace Dali;
49 using namespace Dali::Toolkit;
50
51 namespace
52 {
53
54 std::string JSON_BROKEN("                                      \
55 {                                                              \
56   'stage':                                                     \
57   [                                                            \
58     {                                                          \
59       'type':'TextActor',                                      \
60       'size': [50,50,1],                                       \
61       'parent-origin': 'CENTER',                               \
62       'text':'COULD NOT LOAD JSON FILE'                        \
63     }                                                          \
64   ]                                                            \
65 }                                                              \
66 ");
67
68 std::string ReplaceQuotes(const std::string &single_quoted)
69 {
70   std::string s(single_quoted);
71
72   // wrong as no embedded quote but had regex link problems
73   std::replace(s.begin(), s.end(), '\'', '"');
74
75   return s;
76 }
77
78 } // anon namespace
79
80
81 //------------------------------------------------------------------------------
82 //
83 //
84 //
85 //------------------------------------------------------------------------------
86 class FileWatcher
87 {
88 public:
89   FileWatcher(void);
90   ~FileWatcher(void);
91   explicit FileWatcher(const std::string &fn): mLastTime(0) { SetFilename(fn) ; };
92
93   void SetFilename(const std::string &fn);
94   std::string GetFilename();
95
96   bool FileHasChanged(void);
97   std::string GetFileContents(void) { return GetFileContents(mstringPath) ; };
98
99 private:
100   // compiler does
101   // FileWatcher(const FileWatcher&);
102   // FileWatcher &operator=(const FileWatcher &);
103
104   std::time_t mLastTime;
105   std::string mstringPath;
106
107   std::string GetFileContents(const std::string &fn)
108   {
109     std::ifstream t(fn.c_str());
110     return std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
111   };
112 };
113
114 FileWatcher::FileWatcher(void) : mLastTime(0)
115 {
116 }
117
118 bool FileWatcher::FileHasChanged(void)
119 {
120   struct stat buf;
121
122   if(0 != stat(mstringPath.c_str(), &buf))
123   {
124     DALI_LOG_WARNING("File does not exist '%s'\n", mstringPath.c_str());
125     return false;
126   }
127   else
128   {
129     if(buf.st_mtime > mLastTime)
130     {
131       mLastTime = buf.st_mtime;
132       return true;
133     }
134     else
135     {
136       mLastTime = buf.st_mtime;
137       return false;
138     }
139   }
140
141   return false;
142 }
143
144 FileWatcher::~FileWatcher()
145 {
146 }
147
148 void FileWatcher::SetFilename(const std::string &fn)
149 {
150   mstringPath = fn;
151 }
152
153 std::string FileWatcher::GetFilename(void)
154 {
155   return mstringPath;
156 }
157
158
159 //------------------------------------------------------------------------------
160 //
161 //
162 //
163 //------------------------------------------------------------------------------
164 class ExampleApp : public ConnectionTracker
165 {
166 public:
167   ExampleApp(Application &app) : mApp(app)
168   {
169     app.InitSignal().Connect(this, &ExampleApp::Create);
170
171   }
172
173   ~ExampleApp() {}
174
175 public:
176   void SetJSONFilename(std::string const &fn) { fw.SetFilename(fn) ; };
177
178   void Create(Application& app)
179   {
180     mTimer = Timer::New( 500 ); // ms
181     mTimer.TickSignal().Connect( this, &ExampleApp::OnTimer);
182     mTimer.Start();
183
184     // Connect to key events in order to exit
185     Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleApp::OnKeyEvent);
186   }
187
188 private:
189   Application& mApp;
190   Layer mRootLayer;
191
192   FileWatcher fw;
193   Timer mTimer;
194
195   void ReloadJsonFile(Builder& builder, Layer& layer)
196   {
197     Stage stage = Stage::GetCurrent();
198
199     builder = Builder::New();
200     builder.QuitSignal().Connect( this, &ExampleApp::OnBuilderQuit );
201
202     Property::Map defaultDirs;
203     defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]  = DALI_IMAGE_DIR;
204     defaultDirs[ TOKEN_STRING(DALI_MODEL_DIR) ]  = DALI_MODEL_DIR;
205     defaultDirs[ TOKEN_STRING(DALI_SCRIPT_DIR) ] = DALI_SCRIPT_DIR;
206
207     builder.AddConstants( defaultDirs );
208
209     if(!layer)
210     {
211       layer = Layer::New();
212       layer.SetParentOrigin(ParentOrigin::CENTER);
213       layer.SetAnchorPoint(AnchorPoint::CENTER);
214       layer.SetSize( stage.GetRootLayer().GetCurrentSize() );
215       stage.GetRootLayer().Add(layer);
216
217       // render tasks may have been setup last load so remove them
218       RenderTaskList taskList = stage.GetRenderTaskList();
219       if( taskList.GetTaskCount() > 1 )
220       {
221         typedef std::vector<RenderTask> Collection;
222         typedef Collection::iterator ColIter;
223         Collection tasks;
224
225         for(unsigned int i = 1; i < taskList.GetTaskCount(); ++i)
226         {
227           tasks.push_back( taskList.GetTask(i) );
228         }
229
230         for(ColIter iter = tasks.begin(); iter != tasks.end(); ++iter)
231         {
232           taskList.RemoveTask(*iter);
233         }
234
235         RenderTask defaultTask = taskList.GetTask(0);
236         defaultTask.SetSourceActor( stage.GetRootLayer() );
237         defaultTask.SetTargetFrameBuffer( FrameBufferImage() );
238       }
239     }
240
241     unsigned int numChildren = layer.GetChildCount();
242
243     for(unsigned int i=0; i<numChildren; ++i)
244     {
245       layer.Remove( layer.GetChildAt(0) );
246     }
247
248     std::string data(fw.GetFileContents());
249
250     try
251     {
252       builder.LoadFromString(data);
253     }
254     catch(...)
255     {
256       builder.LoadFromString(ReplaceQuotes(JSON_BROKEN));
257     }
258
259     builder.AddActors( layer );
260
261   }
262
263
264   bool OnTimer(void)
265   {
266     if(fw.FileHasChanged())
267     {
268       ReloadJsonFile( mBuilder, mRootLayer );
269     }
270
271     return true;
272   }
273
274   // Process Key events to Quit on back-key
275   void OnKeyEvent( const KeyEvent& event )
276   {
277     if( event.state == KeyEvent::Down )
278     {
279       if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
280       {
281         mApp.Quit();
282       }
283     }
284   }
285
286   void OnBuilderQuit()
287   {
288     mApp.Quit();
289   }
290
291   Builder mBuilder;
292 };
293
294 //------------------------------------------------------------------------------
295 //
296 //
297 //
298 //------------------------------------------------------------------------------
299 int main(int argc, char **argv)
300 {
301   Application dali_app = Application::New(&argc, &argv);
302
303   ExampleApp app(dali_app);
304
305
306   if(argc > 1)
307   {
308     std::cout << "Loading file:" << argc << " " << argv[1] << std::endl;
309     app.SetJSONFilename(argv[1]);
310   }
311   else
312   {
313     DALI_ASSERT_ALWAYS(!"Specify JSON file on command line\n");
314   }
315
316   dali_app.MainLoop();
317
318   return 0;
319 }