2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 //------------------------------------------------------------------------------
19 // Run a json script layout file
21 // - watches an named file and reloads actor tree if the file changes
23 // builder-run layout.json
25 // and edit layout.json in a text editor saving to trigger the reload
27 //------------------------------------------------------------------------------
29 #include <dali/dali.h>
30 #include <dali/devel-api/adaptor-framework/file-loader.h>
31 #include <dali-toolkit/dali-toolkit.h>
32 #include <dali-toolkit/devel-api/builder/builder.h>
33 #include <dali-toolkit/devel-api/builder/tree-node.h>
43 #include <dali/integration-api/debug.h>
45 #define TOKEN_STRING(x) #x
48 using namespace Dali::Toolkit;
53 std::string JSON_BROKEN(" \
60 'parentOrigin': 'CENTER', \
61 'text':'COULD NOT LOAD JSON FILE' \
67 std::string ReplaceQuotes(const std::string &single_quoted)
69 std::string s(single_quoted);
71 // wrong as no embedded quote but had regex link problems
72 std::replace(s.begin(), s.end(), '\'', '"');
80 //------------------------------------------------------------------------------
84 //------------------------------------------------------------------------------
90 explicit FileWatcher(const std::string &fn): mLastTime(0) { SetFilename(fn) ; };
92 void SetFilename(const std::string &fn);
93 std::string GetFilename();
95 bool FileHasChanged(void);
96 std::string GetFileContents(void) { return GetFileContents(mstringPath) ; };
100 // FileWatcher(const FileWatcher&);
101 // FileWatcher &operator=(const FileWatcher &);
103 std::time_t mLastTime;
104 std::string mstringPath;
106 std::string GetFileContents(const std::string &filename)
108 std::streampos bufferSize = 0;
109 Dali::Vector<char> fileBuffer;
110 if( !Dali::FileLoader::ReadFile( filename, bufferSize, fileBuffer, FileLoader::FileType::BINARY ) )
112 return std::string();
115 return std::string( &fileBuffer[0], bufferSize );
119 FileWatcher::FileWatcher(void) : mLastTime(0)
123 bool FileWatcher::FileHasChanged(void)
127 if(0 != stat(mstringPath.c_str(), &buf))
129 DALI_LOG_WARNING("File does not exist '%s'\n", mstringPath.c_str());
134 if(buf.st_mtime > mLastTime)
136 mLastTime = buf.st_mtime;
141 mLastTime = buf.st_mtime;
149 FileWatcher::~FileWatcher()
153 void FileWatcher::SetFilename(const std::string &fn)
158 std::string FileWatcher::GetFilename(void)
164 //------------------------------------------------------------------------------
168 //------------------------------------------------------------------------------
169 class ExampleApp : public ConnectionTracker
172 ExampleApp(Application &app) : mApp(app)
174 app.InitSignal().Connect(this, &ExampleApp::Create);
181 void SetJSONFilename(std::string const &fn) { fw.SetFilename(fn) ; };
183 void Create(Application& app)
185 mTimer = Timer::New( 500 ); // ms
186 mTimer.TickSignal().Connect( this, &ExampleApp::OnTimer);
189 // Connect to key events in order to exit
190 Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleApp::OnKeyEvent);
200 void ReloadJsonFile(Builder& builder, Layer& layer)
202 Stage stage = Stage::GetCurrent();
203 stage.SetBackgroundColor( Color::WHITE );
205 builder = Builder::New();
206 builder.QuitSignal().Connect( this, &ExampleApp::OnBuilderQuit );
208 Property::Map defaultDirs;
209 defaultDirs[ TOKEN_STRING(DEMO_IMAGE_DIR) ] = DEMO_IMAGE_DIR;
210 defaultDirs[ TOKEN_STRING(DEMO_MODEL_DIR) ] = DEMO_MODEL_DIR;
211 defaultDirs[ TOKEN_STRING(DEMO_SCRIPT_DIR) ] = DEMO_SCRIPT_DIR;
213 builder.AddConstants( defaultDirs );
217 layer = Layer::New();
218 layer.SetParentOrigin(ParentOrigin::CENTER);
219 layer.SetAnchorPoint(AnchorPoint::CENTER);
220 layer.SetSize( stage.GetRootLayer().GetCurrentSize() );
221 stage.GetRootLayer().Add(layer);
223 // render tasks may have been setup last load so remove them
224 RenderTaskList taskList = stage.GetRenderTaskList();
225 if( taskList.GetTaskCount() > 1 )
227 typedef std::vector<RenderTask> Collection;
228 typedef Collection::iterator ColIter;
231 for(unsigned int i = 1; i < taskList.GetTaskCount(); ++i)
233 tasks.push_back( taskList.GetTask(i) );
236 for(ColIter iter = tasks.begin(); iter != tasks.end(); ++iter)
238 taskList.RemoveTask(*iter);
241 RenderTask defaultTask = taskList.GetTask(0);
242 defaultTask.SetSourceActor( stage.GetRootLayer() );
243 defaultTask.SetTargetFrameBuffer( FrameBufferImage() );
247 unsigned int numChildren = layer.GetChildCount();
249 for(unsigned int i=0; i<numChildren; ++i)
251 layer.Remove( layer.GetChildAt(0) );
254 std::string data(fw.GetFileContents());
258 builder.LoadFromString(data);
262 builder.LoadFromString(ReplaceQuotes(JSON_BROKEN));
265 builder.AddActors( layer );
272 if(fw.FileHasChanged())
274 ReloadJsonFile( mBuilder, mRootLayer );
280 // Process Key events to Quit on back-key
281 void OnKeyEvent( const KeyEvent& event )
283 if( event.state == KeyEvent::Down )
285 if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
300 //------------------------------------------------------------------------------
304 //------------------------------------------------------------------------------
305 int DALI_EXPORT_API main(int argc, char **argv)
308 Application dali_app = Application::New(&argc, &argv, DEMO_THEME_PATH);
309 ExampleApp app(dali_app);
313 std::cout << "Loading file:" << argc << " " << argv[1] << std::endl;
314 app.SetJSONFilename(argv[1]);
318 DALI_ASSERT_ALWAYS(!"Specify JSON file on command line\n");