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