Mercurial > hg > orthanc-stone
annotate Platforms/Wasm/Defaults.cpp @ 385:6cc3ce74dc05
using message broker in widgets
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 07 Nov 2018 20:49:41 +0100 |
parents | 8716176ff7f0 |
children | e33659decec5 |
rev | line source |
---|---|
222 | 1 #include "Defaults.h" |
2 | |
223 | 3 #include "WasmWebService.h" |
4 #include <Framework/dev.h> | |
5 #include "Framework/Widgets/TestCairoWidget.h" | |
6 #include <Framework/Viewport/WidgetViewport.h> | |
7 #include <Framework/Widgets/LayerWidget.h> | |
228 | 8 #include <algorithm> |
242 | 9 #include "Applications/Wasm/StartupParametersBuilder.h" |
307 | 10 #include "Platforms/Wasm/WasmPlatformApplicationAdapter.h" |
223 | 11 |
12 static unsigned int width_ = 0; | |
13 static unsigned int height_ = 0; | |
14 | |
15 /**********************************/ | |
16 | |
288 | 17 static std::unique_ptr<OrthancStone::IStoneApplication> application; |
307 | 18 static std::unique_ptr<OrthancStone::WasmPlatformApplicationAdapter> applicationWasmAdapter = NULL; |
288 | 19 static std::unique_ptr<OrthancStone::StoneApplicationContext> context; |
242 | 20 static OrthancStone::StartupParametersBuilder startupParametersBuilder; |
253 | 21 static OrthancStone::MessageBroker broker; |
242 | 22 |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
23 static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); |
223 | 24 static OrthancStone::StatusBar statusBar_; |
25 | |
227 | 26 static std::list<std::shared_ptr<OrthancStone::WidgetViewport>> viewports_; |
27 | |
228 | 28 std::shared_ptr<OrthancStone::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { |
29 for (const auto& v : viewports_) { | |
30 if (v.get() == viewport) { | |
31 return v; | |
32 } | |
33 } | |
229 | 34 assert(false); |
35 return std::shared_ptr<OrthancStone::WidgetViewport>(); | |
228 | 36 } |
37 | |
223 | 38 #ifdef __cplusplus |
39 extern "C" { | |
40 #endif | |
41 | |
42 using namespace OrthancStone; | |
227 | 43 |
44 // when WASM needs a C++ viewport | |
45 ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { | |
46 | |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
47 std::shared_ptr<OrthancStone::WidgetViewport> viewport(new OrthancStone::WidgetViewport(broker)); |
287 | 48 printf("viewport %x\n", (int)viewport.get()); |
227 | 49 |
50 viewports_.push_back(viewport); | |
51 | |
52 printf("There are now %d viewports in C++\n", viewports_.size()); | |
53 | |
54 viewport->SetStatusBar(statusBar_); | |
385
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
55 |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
56 viewport->RegisterObserverCallback( |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
57 new Callable<ViewportContentChangedObserver, IViewport::ViewportChangedMessage> |
6cc3ce74dc05
using message broker in widgets
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
327
diff
changeset
|
58 (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); |
227 | 59 |
60 return viewport.get(); | |
61 } | |
62 | |
63 // when WASM does not need a viewport anymore, it should release it | |
64 void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { | |
65 viewports_.remove_if([viewport](const std::shared_ptr<OrthancStone::WidgetViewport>& v) { return v.get() == viewport;}); | |
66 | |
67 printf("There are now %d viewports in C++\n", viewports_.size()); | |
68 } | |
69 | |
70 void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle viewport) { | |
223 | 71 |
72 printf("CreateWasmApplication\n"); | |
73 | |
253 | 74 application.reset(CreateUserApplication(broker)); |
307 | 75 applicationWasmAdapter.reset(CreateWasmApplicationAdapter(broker, application.get())); |
255 | 76 WasmWebService::SetBroker(broker); |
223 | 77 |
242 | 78 startupParametersBuilder.Clear(); |
223 | 79 } |
80 | |
81 void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, | |
82 const char* value) { | |
242 | 83 startupParametersBuilder.SetStartupParameter(keyc, value); |
223 | 84 } |
85 | |
231
5027cb2feb51
viewport is now part of the Application itself and not global anymore
am@osimis.io
parents:
229
diff
changeset
|
86 void EMSCRIPTEN_KEEPALIVE StartWasmApplication() { |
223 | 87 |
88 printf("StartWasmApplication\n"); | |
89 | |
90 // recreate a command line from uri arguments and parse it | |
91 boost::program_options::variables_map parameters; | |
242 | 92 boost::program_options::options_description options; |
93 application->DeclareStartupOptions(options); | |
94 startupParametersBuilder.GetStartupParameters(parameters, options); | |
223 | 95 |
288 | 96 context.reset(new OrthancStone::StoneApplicationContext()); |
272 | 97 context->SetWebService(OrthancStone::WasmWebService::GetInstance()); |
242 | 98 application->Initialize(context.get(), statusBar_, parameters); |
99 application->InitializeWasm(); | |
223 | 100 |
231
5027cb2feb51
viewport is now part of the Application itself and not global anymore
am@osimis.io
parents:
229
diff
changeset
|
101 // viewport->SetSize(width_, height_); |
223 | 102 printf("StartWasmApplication - completed\n"); |
103 } | |
104 | |
105 void EMSCRIPTEN_KEEPALIVE NotifyUpdateContent() | |
106 { | |
228 | 107 for (auto viewport : viewports_) { |
108 // TODO Only launch the JavaScript timer if "HasUpdateContent()" | |
109 if (viewport->HasUpdateContent()) | |
110 { | |
111 viewport->UpdateContent(); | |
112 } | |
113 | |
223 | 114 } |
115 | |
116 } | |
117 | |
118 | |
228 | 119 void EMSCRIPTEN_KEEPALIVE ViewportSetSize(ViewportHandle viewport, unsigned int width, unsigned int height) |
223 | 120 { |
121 width_ = width; | |
122 height_ = height; | |
123 | |
228 | 124 viewport->SetSize(width, height); |
223 | 125 } |
126 | |
228 | 127 int EMSCRIPTEN_KEEPALIVE ViewportRender(ViewportHandle viewport, |
227 | 128 unsigned int width, |
223 | 129 unsigned int height, |
130 uint8_t* data) | |
131 { | |
278 | 132 viewportContentChangedObserver_.Reset(); |
223 | 133 |
134 //printf("ViewportRender called %dx%d\n", width, height); | |
135 if (width == 0 || | |
136 height == 0) | |
137 { | |
138 return 1; | |
139 } | |
140 | |
141 Orthanc::ImageAccessor surface; | |
142 surface.AssignWritable(Orthanc::PixelFormat_BGRA32, width, height, 4 * width, data); | |
143 | |
227 | 144 viewport->Render(surface); |
223 | 145 |
146 // Convert from BGRA32 memory layout (only color mode supported by | |
147 // Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32 (as | |
148 // expected by HTML5 canvas). This simply amounts to swapping the | |
149 // B and R channels. | |
150 uint8_t* p = data; | |
151 for (unsigned int y = 0; y < height; y++) { | |
152 for (unsigned int x = 0; x < width; x++) { | |
153 uint8_t tmp = p[0]; | |
154 p[0] = p[2]; | |
155 p[2] = tmp; | |
156 | |
157 p += 4; | |
158 } | |
159 } | |
160 | |
161 return 1; | |
162 } | |
163 | |
164 | |
228 | 165 void EMSCRIPTEN_KEEPALIVE ViewportMouseDown(ViewportHandle viewport, |
166 unsigned int rawButton, | |
223 | 167 int x, |
168 int y, | |
169 unsigned int rawModifiers) | |
170 { | |
171 OrthancStone::MouseButton button; | |
172 switch (rawButton) | |
173 { | |
174 case 0: | |
175 button = OrthancStone::MouseButton_Left; | |
176 break; | |
177 | |
178 case 1: | |
179 button = OrthancStone::MouseButton_Middle; | |
180 break; | |
181 | |
182 case 2: | |
183 button = OrthancStone::MouseButton_Right; | |
184 break; | |
185 | |
186 default: | |
187 return; // Unknown button | |
188 } | |
189 | |
228 | 190 viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None /* TODO */); |
223 | 191 } |
192 | |
193 | |
228 | 194 void EMSCRIPTEN_KEEPALIVE ViewportMouseWheel(ViewportHandle viewport, |
195 int deltaY, | |
223 | 196 int x, |
197 int y, | |
198 int isControl) | |
199 { | |
228 | 200 if (deltaY != 0) |
223 | 201 { |
202 OrthancStone::MouseWheelDirection direction = (deltaY < 0 ? | |
203 OrthancStone::MouseWheelDirection_Up : | |
204 OrthancStone::MouseWheelDirection_Down); | |
205 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; | |
206 | |
207 if (isControl != 0) | |
208 { | |
209 modifiers = OrthancStone::KeyboardModifiers_Control; | |
210 } | |
211 | |
228 | 212 viewport->MouseWheel(direction, x, y, modifiers); |
223 | 213 } |
214 } | |
215 | |
216 | |
228 | 217 void EMSCRIPTEN_KEEPALIVE ViewportMouseMove(ViewportHandle viewport, |
218 int x, | |
223 | 219 int y) |
220 { | |
228 | 221 viewport->MouseMove(x, y); |
223 | 222 } |
223 | |
228 | 224 void EMSCRIPTEN_KEEPALIVE ViewportKeyPressed(ViewportHandle viewport, |
327 | 225 int key, |
226 const char* keyChar, | |
223 | 227 bool isShiftPressed, |
228 bool isControlPressed, | |
229 bool isAltPressed) | |
230 | |
231 { | |
228 | 232 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; |
233 if (isShiftPressed) { | |
234 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Shift); | |
223 | 235 } |
228 | 236 if (isControlPressed) { |
237 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Control); | |
238 } | |
239 if (isAltPressed) { | |
240 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Alt); | |
241 } | |
327 | 242 |
243 char c = 0; | |
244 if (keyChar != NULL && key == OrthancStone::KeyboardKeys_Generic) { | |
245 c = keyChar[0]; | |
246 } | |
247 viewport->KeyPressed(static_cast<OrthancStone::KeyboardKeys>(key), c, modifiers); | |
223 | 248 } |
249 | |
250 | |
228 | 251 void EMSCRIPTEN_KEEPALIVE ViewportMouseUp(ViewportHandle viewport) |
223 | 252 { |
228 | 253 viewport->MouseUp(); |
223 | 254 } |
255 | |
256 | |
228 | 257 void EMSCRIPTEN_KEEPALIVE ViewportMouseEnter(ViewportHandle viewport) |
223 | 258 { |
228 | 259 viewport->MouseEnter(); |
223 | 260 } |
261 | |
262 | |
228 | 263 void EMSCRIPTEN_KEEPALIVE ViewportMouseLeave(ViewportHandle viewport) |
223 | 264 { |
228 | 265 viewport->MouseLeave(); |
223 | 266 } |
267 | |
287 | 268 const char* EMSCRIPTEN_KEEPALIVE SendMessageToStoneApplication(const char* message) |
269 { | |
270 static std::string output; // we don't want the string to be deallocated when we return to JS code so we always use the same string (this is fine since JS is single-thread) | |
271 | |
307 | 272 printf("SendMessageToStoneApplication\n"); |
309 | 273 printf("%s", message); |
307 | 274 |
275 if (applicationWasmAdapter.get() != NULL) { | |
276 printf("sending message to C++\n"); | |
277 applicationWasmAdapter->HandleMessageFromWeb(output, std::string(message)); | |
287 | 278 return output.c_str(); |
279 } | |
307 | 280 printf("This stone application does not have a Web Adapter"); |
281 return NULL; | |
287 | 282 } |
283 | |
223 | 284 |
285 #ifdef __cplusplus | |
286 } | |
287 #endif |