Mercurial > hg > orthanc-stone
annotate Applications/Samples/SimpleViewerApplication.h @ 245:e802578e1554 am
register observer
author | am@osimis.io |
---|---|
date | Wed, 20 Jun 2018 15:59:52 +0200 |
parents | 092db46c6291 |
children | 5470b15f7cf2 54c7284b0eff |
rev | line source |
---|---|
235 | 1 /** |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #pragma once | |
23 | |
24 #include "SampleApplicationBase.h" | |
25 | |
26 #include "../../Framework/Layers/OrthancFrameLayerSource.h" | |
27 #include "../../Framework/Widgets/LayerWidget.h" | |
28 #include "../../Framework/Widgets/LayoutWidget.h" | |
29 | |
30 #include <Core/Logging.h> | |
31 | |
32 namespace OrthancStone | |
33 { | |
34 namespace Samples | |
35 { | |
36 class SimpleViewerApplication : | |
37 public SampleApplicationBase, | |
38 private ILayerSource::IObserver | |
39 { | |
40 private: | |
41 class Interactor : public IWorldSceneInteractor | |
42 { | |
43 private: | |
44 SimpleViewerApplication& application_; | |
45 | |
46 public: | |
47 Interactor(SimpleViewerApplication& application) : | |
48 application_(application) | |
49 { | |
50 } | |
51 | |
52 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, | |
53 const ViewportGeometry& view, | |
54 MouseButton button, | |
55 double x, | |
56 double y, | |
57 IStatusBar* statusBar) | |
58 { | |
59 return NULL; | |
60 } | |
61 | |
62 virtual void MouseOver(CairoContext& context, | |
63 WorldSceneWidget& widget, | |
64 const ViewportGeometry& view, | |
65 double x, | |
66 double y, | |
67 IStatusBar* statusBar) | |
68 { | |
69 if (statusBar != NULL) | |
70 { | |
71 Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); | |
72 | |
73 char buf[64]; | |
74 sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", | |
75 p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); | |
76 statusBar->SetMessage(buf); | |
77 } | |
78 } | |
79 | |
80 virtual void MouseWheel(WorldSceneWidget& widget, | |
81 MouseWheelDirection direction, | |
82 KeyboardModifiers modifiers, | |
83 IStatusBar* statusBar) | |
84 { | |
85 // int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); | |
86 | |
87 // switch (direction) | |
88 // { | |
89 // case MouseWheelDirection_Up: | |
90 // application_.OffsetSlice(-scale); | |
91 // break; | |
92 | |
93 // case MouseWheelDirection_Down: | |
94 // application_.OffsetSlice(scale); | |
95 // break; | |
96 | |
97 // default: | |
98 // break; | |
99 // } | |
100 } | |
101 | |
102 virtual void KeyPressed(WorldSceneWidget& widget, | |
103 char key, | |
104 KeyboardModifiers modifiers, | |
105 IStatusBar* statusBar) | |
106 { | |
107 switch (key) | |
108 { | |
109 case 's': | |
110 widget.SetDefaultView(); | |
111 break; | |
112 | |
113 default: | |
114 break; | |
115 } | |
116 } | |
117 }; | |
118 | |
119 | |
120 // void OffsetSlice(int offset) | |
121 // { | |
122 // if (source_ != NULL) | |
123 // { | |
124 // int slice = static_cast<int>(slice_) + offset; | |
125 | |
126 // if (slice < 0) | |
127 // { | |
128 // slice = 0; | |
129 // } | |
130 | |
131 // if (slice >= static_cast<int>(source_->GetSliceCount())) | |
132 // { | |
133 // slice = source_->GetSliceCount() - 1; | |
134 // } | |
135 | |
136 // if (slice != static_cast<int>(slice_)) | |
137 // { | |
138 // SetSlice(slice); | |
139 // } | |
140 // } | |
141 // } | |
142 | |
143 | |
144 // void SetSlice(size_t index) | |
145 // { | |
146 // if (source_ != NULL && | |
147 // index < source_->GetSliceCount()) | |
148 // { | |
149 // slice_ = index; | |
150 | |
151 //#if 1 | |
152 // widget_->SetSlice(source_->GetSlice(slice_).GetGeometry()); | |
153 //#else | |
154 // // TEST for scene extents - Rotate the axes | |
155 // double a = 15.0 / 180.0 * M_PI; | |
156 | |
157 //#if 1 | |
158 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
159 // Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0); | |
160 //#else | |
161 // // Flip the normal | |
162 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
163 // Vector y; GeometryToolbox::AssignVector(y, sin(a), -cos(a), 0); | |
164 //#endif | |
165 | |
166 // SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y); | |
167 // widget_->SetSlice(s); | |
168 //#endif | |
169 // } | |
170 // } | |
171 | |
172 | |
173 virtual void NotifyGeometryReady(const ILayerSource& source) | |
174 { | |
175 // Once the geometry of the series is downloaded from Orthanc, | |
176 // display its first slice, and adapt the viewport to fit this | |
177 // slice | |
178 if (source_ == &source) | |
179 { | |
180 //SetSlice(source_->GetSliceCount() / 2); | |
181 } | |
182 | |
183 mainLayout_->SetDefaultView(); | |
184 } | |
185 | |
186 virtual void NotifyGeometryError(const ILayerSource& source) | |
187 { | |
188 } | |
189 | |
190 virtual void NotifyContentChange(const ILayerSource& source) | |
191 { | |
192 } | |
193 | |
194 virtual void NotifySliceChange(const ILayerSource& source, | |
195 const Slice& slice) | |
196 { | |
197 } | |
198 | |
199 virtual void NotifyLayerReady(std::auto_ptr<ILayerRenderer>& layer, | |
200 const ILayerSource& source, | |
201 const CoordinateSystem3D& slice, | |
202 bool isError) | |
203 { | |
204 } | |
205 | |
242 | 206 std::unique_ptr<Interactor> interactor_; |
235 | 207 LayoutWidget* mainLayout_; |
208 LayoutWidget* thumbnailsLayout_; | |
209 LayerWidget* mainViewport_; | |
210 std::vector<LayerWidget*> thumbnails_; | |
211 std::vector<std::string> instances_; | |
212 unsigned int currentInstanceIndex_; | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
213 OrthancStone::WidgetViewport* wasmViewport1_; |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
214 OrthancStone::WidgetViewport* wasmViewport2_; |
235 | 215 |
216 OrthancFrameLayerSource* source_; | |
217 unsigned int slice_; | |
218 | |
219 public: | |
242 | 220 SimpleViewerApplication() : |
235 | 221 mainLayout_(NULL), |
222 currentInstanceIndex_(0), | |
223 source_(NULL), | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
224 slice_(0), |
242 | 225 wasmViewport1_(NULL), |
226 wasmViewport2_(NULL) | |
235 | 227 { |
228 } | |
229 | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
230 virtual void Finalize() {} |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
231 virtual IWidget* GetCentralWidget() {return mainLayout_;} |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
232 |
235 | 233 virtual void DeclareStartupOptions(boost::program_options::options_description& options) |
234 { | |
235 boost::program_options::options_description generic("Sample options"); | |
236 generic.add_options() | |
237 // ("study", boost::program_options::value<std::string>(), | |
238 // "Orthanc ID of the study") | |
239 ("instance1", boost::program_options::value<std::string>(), | |
240 "Orthanc ID of the instances") | |
241 ("instance2", boost::program_options::value<std::string>(), | |
242 "Orthanc ID of the instances") | |
243 ; | |
244 | |
245 options.add(generic); | |
246 } | |
247 | |
242 | 248 virtual void Initialize(BasicApplicationContext* context, |
249 IStatusBar& statusBar, | |
235 | 250 const boost::program_options::variables_map& parameters) |
251 { | |
252 using namespace OrthancStone; | |
253 | |
242 | 254 context_ = context; |
235 | 255 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); |
256 | |
257 if (parameters.count("instance1") < 1) | |
258 { | |
259 LOG(ERROR) << "The instance ID is missing"; | |
260 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
261 } | |
262 if (parameters.count("instance2") < 1) | |
263 { | |
264 LOG(ERROR) << "The instance ID is missing"; | |
265 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
266 } | |
267 instances_.push_back(parameters["instance1"].as<std::string>()); | |
268 instances_.push_back(parameters["instance2"].as<std::string>()); | |
269 | |
270 mainLayout_ = new LayoutWidget(); | |
271 mainLayout_->SetPadding(10); | |
272 mainLayout_->SetBackgroundCleared(true); | |
273 mainLayout_->SetBackgroundColor(0, 0, 0); | |
274 mainLayout_->SetHorizontal(); | |
275 | |
276 thumbnailsLayout_ = new LayoutWidget(); | |
277 thumbnailsLayout_->SetPadding(10); | |
278 thumbnailsLayout_->SetBackgroundCleared(true); | |
279 thumbnailsLayout_->SetBackgroundColor(50, 50, 50); | |
280 thumbnailsLayout_->SetVertical(); | |
281 | |
282 mainViewport_ = new LayerWidget(); | |
283 thumbnails_.push_back(new LayerWidget()); | |
284 thumbnails_.push_back(new LayerWidget()); | |
285 | |
286 // hierarchy | |
287 mainLayout_->AddWidget(thumbnailsLayout_); | |
288 mainLayout_->AddWidget(mainViewport_); | |
289 thumbnailsLayout_->AddWidget(thumbnails_[0]); | |
290 thumbnailsLayout_->AddWidget(thumbnails_[1]); | |
291 | |
292 // sources | |
293 source_ = new OrthancFrameLayerSource(context_->GetWebService()); | |
294 source_->LoadFrame(instances_[currentInstanceIndex_], 0); | |
245 | 295 source_->Register(*this); |
235 | 296 |
297 mainViewport_->AddLayer(source_); | |
298 | |
299 OrthancFrameLayerSource* thumb0 = new OrthancFrameLayerSource(context_->GetWebService()); | |
300 thumb0->LoadFrame(instances_[0], 0); | |
301 OrthancFrameLayerSource* thumb1 = new OrthancFrameLayerSource(context_->GetWebService()); | |
302 thumb1->LoadFrame(instances_[1], 0); | |
303 | |
304 thumbnails_[0]->AddLayer(thumb0); | |
305 thumbnails_[1]->AddLayer(thumb1); | |
306 | |
307 mainLayout_->SetTransmitMouseOver(true); | |
242 | 308 interactor_.reset(new Interactor(*this)); |
309 mainViewport_->SetInteractor(*interactor_); | |
310 } | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
311 |
242 | 312 #if ORTHANC_ENABLE_SDL==0 |
313 virtual void InitializeWasm() { | |
314 | |
315 AttachWidgetToWasmViewport("canvas", thumbnailsLayout_); | |
316 AttachWidgetToWasmViewport("canvas2", mainViewport_); | |
317 } | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
318 #endif |
235 | 319 }; |
320 } | |
321 } |