Fix the problem that other dynamic box is disappeared after opening pd
[platform/framework/web/web-provider.git] / src / Core / Box.cpp
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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  * @file    Box.cpp
18  * @author  Yunchan Cho (yunchan.cho@samsung.com)
19  */
20 #include <string>
21 #include <Ecore.h>
22 #include <Plugin/IBoxPluginFactory.h>
23 #include "Buffer/IRenderBuffer.h"
24 #include "Buffer/RenderBuffer.h"
25 #include "Buffer/RenderBufferFactory.h"
26 #include "Util/Log.h"
27 #include "BoxData.h"
28 #include "IBoxState.h"
29 #include "BoxState.h"
30 #include "Util/ITimer.h"
31 #include "BoxUpdateTimer.h"
32 #include "BoxSchemeHandler.h"
33 #include "Box.h"
34
35 // This is used for informing context of box to web content as value of url parameter
36 static const std::string renderTypeCreate("create");
37 static const std::string renderTypeResize("resize");
38 static const std::string renderTypeOpenPd("pdopen");
39 static const std::string renderTypeUpdate("update");
40
41 Box::Box(BoxInfoPtr boxInfo, IBoxPluginFactoryPtr factory, EwkContextPtr ewkContext)
42     : m_boxInfo(boxInfo)
43     , m_factory(factory)
44     , m_currentTab(true)
45     , m_paused(false)
46     , m_updateNeeded(false)
47 {
48     LogD("enter");
49     try {
50         m_boxBuffer = m_factory->createBoxRenderBuffer(
51                             boxInfo->boxId,
52                             boxInfo->instanceId,
53                             boxInfo->boxWidth,
54                             boxInfo->boxHeight,
55                             boxInfo->contentInfo);
56         m_boxBuffer->allocate();
57         m_view = m_factory->createRenderView(
58                 boxInfo->boxId, boxInfo->instanceId,
59                 m_boxBuffer->getWindow(),
60                 ewkContext);
61         m_updateTimer = BoxUpdateTimer::create(
62                 boxInfo->period,
63                 Box::updateCallback,
64                 this);
65         BoxSchemeHandler::Instance()->registerBox(boxInfo->instanceId, this);
66
67         // TODO code regarding state needs more testing
68         //m_state = BoxInitState::create(
69         //           IBoxContextPtr(dynamic_cast<IBoxContext*>(this)));
70     } catch (...) {
71         throw;
72     }
73 }
74
75 Box::~Box()
76 {
77     LogD("enter");
78     BoxSchemeHandler::Instance()->unregisterBox(m_boxInfo->instanceId);
79 }
80
81 bool Box::show()
82 {
83     LogD("enter");
84     CHECK_BOX_STATE(m_state, permitShow);
85
86     try {
87         m_updateTimer->start();
88         RenderInfoPtr renderInfo = makeRenderInfo(renderTypeCreate);
89         m_boxBuffer->stopCanvasUpdate();
90         m_view->showBox(renderInfo);
91         ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_boxBuffer.get());
92     } catch (...) {
93         return false;
94     }
95
96     SWITCH_BOX_STATE();
97     return true;
98 }
99
100 bool Box::hide()
101 {
102     LogD("enter");
103     CHECK_BOX_STATE(m_state, permitHide);
104
105     try {
106         m_updateTimer->stop();
107         m_boxBuffer->stopCanvasUpdate();
108         m_view->hideBox();
109         m_boxBuffer->free();
110         m_boxBuffer.reset();
111     } catch (...) {
112         return false;
113     }
114
115     SWITCH_BOX_STATE();
116     return true;
117 }
118
119 bool Box::resize(int width, int height)
120 {
121     LogD("enter");
122     CHECK_BOX_STATE(m_state, permitShow);
123
124     // reset box info to new width, height
125     m_boxInfo->boxWidth = width;
126     m_boxInfo->boxHeight = height;
127
128     try {
129         m_updateTimer->restart();
130         m_boxBuffer->reallocate(
131                 m_boxInfo->boxWidth, m_boxInfo->boxHeight);
132         RenderInfoPtr renderInfo = makeRenderInfo(renderTypeResize);
133         m_view->showBox(renderInfo);
134     } catch (...) {
135         LogD("resize exception");
136         return false;
137     }
138
139     SWITCH_BOX_STATE();
140     return true; 
141 }
142
143 bool Box::resume()
144 {
145     LogD("enter"); 
146     CHECK_BOX_STATE(m_state, permitResume);
147
148     try {
149         m_currentTab = true;
150         m_paused = false;
151
152         if (m_updateNeeded) {
153             m_updateNeeded = false;
154             return update();
155         } else {
156             m_view->resumeBox();
157         }
158     } catch (...) {
159         return false;
160     }
161
162     SWITCH_BOX_STATE();
163     return true;
164 }
165
166 bool Box::pause(bool background)
167 {
168     LogD("enter");
169     CHECK_BOX_STATE(m_state, permitPause);
170
171     try {
172         if (!background) {
173             m_currentTab = false;
174         }
175         m_paused = true;
176         m_view->pauseBox();
177     } catch (...) {
178         return false;
179     }
180
181     SWITCH_BOX_STATE();
182     return true;
183 }
184
185 bool Box::openPd(int width, int height, double x, double y)
186 {
187     LogD("enter");
188     CHECK_BOX_STATE(m_state, permitOpenPd);
189
190     m_boxInfo->pdWidth = width;
191     m_boxInfo->pdHeight = height;
192     m_boxInfo->pdX = x;
193     m_boxInfo->pdY = y;
194
195     try {
196         m_updateTimer->stop();
197         m_pdBuffer = RenderBufferFactory::create(
198                             RenderBufferFactory::RENDER_BUFFER_TYPE_PD,
199                             m_boxInfo->boxId,
200                             m_boxInfo->instanceId,
201                             m_boxInfo->pdWidth,
202                             m_boxInfo->pdHeight);
203         m_pdBuffer->allocate();
204         m_pdBuffer->stopCanvasUpdate();
205         RenderInfoPtr renderInfo = makeRenderInfo(renderTypeOpenPd);
206         m_view->showPd(m_pdBuffer->getWindow(), renderInfo);
207         ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_pdBuffer.get());
208     } catch (...) {
209         return false;
210     }
211
212     SWITCH_BOX_STATE();
213     return true;
214 }
215
216 bool Box::closePd()
217 {
218     LogD("enter");
219     CHECK_BOX_STATE(m_state, permitClosePd);
220
221     try {
222         m_pdBuffer->stopCanvasUpdate();
223         m_view->hidePd();
224         m_pdBuffer->free();
225         m_pdBuffer.reset();
226         m_updateTimer->restart();
227     } catch (...) {
228         return false;
229     }
230
231     SWITCH_BOX_STATE();
232     return true;
233 }
234
235 bool Box::update()
236 {
237     LogD("enter");
238
239     if (m_paused) {
240         // update is dalayed until this box goes to current tab
241         m_updateNeeded = true;
242         return true;
243     }
244
245     try {
246         RenderInfoPtr renderInfo = makeRenderInfo(renderTypeUpdate);
247         m_boxBuffer->stopCanvasUpdate();
248         m_view->showBox(renderInfo);
249         ecore_idler_add(startUpdateRenderBufferIdlerCallback, m_boxBuffer.get());
250     } catch (...) {
251         return false;
252     }
253
254     return true;
255 }
256
257 bool Box::changePeriod(float period)
258 {
259     LogD("enter");
260
261     // reset period
262     m_boxInfo->period = period;
263     m_updateTimer->setPeriod(m_boxInfo->period);
264
265     return true;
266 }
267
268 bool Box::isCurrentTab()
269 {
270     return m_currentTab;
271 }
272
273 RenderInfoPtr Box::makeRenderInfo(const std::string& renderType) const
274 {
275     LogD("enter");
276     RenderInfoPtr renderInfo(new RenderInfo);
277
278     // add width, height, operation type
279     renderInfo->defaultUrlParams = "?type=" + renderType;
280
281     // set width, height
282     if (renderType == renderTypeOpenPd) {
283         renderInfo->width = m_boxInfo->pdWidth;
284         renderInfo->height = m_boxInfo->pdHeight;
285     } else {
286         renderInfo->width = m_boxInfo->boxWidth;
287         renderInfo->height = m_boxInfo->boxHeight;
288     }
289     char buff[32];
290     sprintf(buff, "&width=%d&height=%d", renderInfo->width, renderInfo->height);
291     renderInfo->defaultUrlParams += buff;
292
293     // if needed, set pd information
294     if (renderType == renderTypeOpenPd) {
295         renderInfo->defaultUrlParams += "&pdopen-direction=";
296         if (m_boxInfo->pdY == 0.0f) {
297             renderInfo->defaultUrlParams += "down";
298         } else {
299             renderInfo->defaultUrlParams += "up";
300         }
301
302         char buff[32];
303         sprintf(buff, "&pdopen-arrow-xpos=%d",
304                 static_cast<int>((m_boxInfo->pdX) * (m_boxInfo->pdWidth)));
305         renderInfo->defaultUrlParams += buff;
306     }
307
308
309     // add content info
310     if (!m_boxInfo->contentInfo.empty()) {
311         renderInfo->defaultUrlParams += "&" + m_boxInfo->contentInfo;
312     }
313
314     LogD("default url param string: %s", renderInfo->defaultUrlParams.c_str());
315     return renderInfo;
316 }
317
318 void Box::setState(IBoxStatePtr state)
319 {
320     // assign new state
321     //m_state = state;
322 }
323
324 Eina_Bool Box::updateCallback(void* data)
325 {
326     LogD("enter");
327     Box* This = static_cast<Box*>(data);
328
329     This->update();
330     return ECORE_CALLBACK_RENEW;
331 }
332
333 Eina_Bool Box::startUpdateRenderBufferIdlerCallback(void* data)
334 {
335     LogD("enter");
336     RenderBuffer* buffer = static_cast<RenderBuffer*>(data);
337     if (!buffer) {
338         LogD("no buffer");
339     } else {
340         buffer->startCanvasUpdate();
341     }
342
343     return ECORE_CALLBACK_CANCEL;
344 }