Mercurial > hg > orthanc-stone
annotate Applications/Samples/SimpleViewerApplication.h @ 266:c9cf95b49a86 am-2
removed OrthancSlicesLoader::ISliceLoaderObserver; now using standard messages instead
author | am@osimis.io |
---|---|
date | Tue, 21 Aug 2018 18:14:22 +0200 |
parents | e5a9b3d03478 |
children | 89d02de83c03 |
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. | |
249 | 16 * |
235 | 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" | |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
29 #include "../../Framework/Messages/IObserver.h" |
258 | 30 #include "../../Framework/SmartLoader.h" |
235 | 31 |
32 #include <Core/Logging.h> | |
33 | |
34 namespace OrthancStone | |
35 { | |
36 namespace Samples | |
37 { | |
38 class SimpleViewerApplication : | |
249 | 39 public SampleApplicationBase, |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
40 public IObserver |
235 | 41 { |
42 private: | |
43 class Interactor : public IWorldSceneInteractor | |
44 { | |
45 private: | |
46 SimpleViewerApplication& application_; | |
47 | |
48 public: | |
49 Interactor(SimpleViewerApplication& application) : | |
50 application_(application) | |
51 { | |
52 } | |
53 | |
54 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, | |
55 const ViewportGeometry& view, | |
56 MouseButton button, | |
57 double x, | |
58 double y, | |
59 IStatusBar* statusBar) | |
60 { | |
61 return NULL; | |
62 } | |
63 | |
64 virtual void MouseOver(CairoContext& context, | |
65 WorldSceneWidget& widget, | |
66 const ViewportGeometry& view, | |
67 double x, | |
68 double y, | |
69 IStatusBar* statusBar) | |
70 { | |
71 if (statusBar != NULL) | |
72 { | |
73 Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); | |
74 | |
75 char buf[64]; | |
249 | 76 sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", |
235 | 77 p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); |
78 statusBar->SetMessage(buf); | |
79 } | |
80 } | |
81 | |
82 virtual void MouseWheel(WorldSceneWidget& widget, | |
83 MouseWheelDirection direction, | |
84 KeyboardModifiers modifiers, | |
85 IStatusBar* statusBar) | |
86 { | |
249 | 87 // int scale = (modifiers & KeyboardModifiers_Control ? 10 : 1); |
235 | 88 |
249 | 89 // switch (direction) |
90 // { | |
91 // case MouseWheelDirection_Up: | |
92 // application_.OffsetSlice(-scale); | |
93 // break; | |
235 | 94 |
249 | 95 // case MouseWheelDirection_Down: |
96 // application_.OffsetSlice(scale); | |
97 // break; | |
235 | 98 |
249 | 99 // default: |
100 // break; | |
101 // } | |
235 | 102 } |
103 | |
104 virtual void KeyPressed(WorldSceneWidget& widget, | |
105 char key, | |
106 KeyboardModifiers modifiers, | |
107 IStatusBar* statusBar) | |
108 { | |
109 switch (key) | |
110 { | |
249 | 111 case 's': |
112 widget.SetDefaultView(); | |
113 break; | |
114 case 'n': | |
115 application_.NextImage(widget); | |
116 break; | |
235 | 117 |
249 | 118 default: |
119 break; | |
235 | 120 } |
121 } | |
122 }; | |
123 | |
124 | |
249 | 125 // void OffsetSlice(int offset) |
126 // { | |
127 // if (source_ != NULL) | |
128 // { | |
129 // int slice = static_cast<int>(slice_) + offset; | |
235 | 130 |
249 | 131 // if (slice < 0) |
132 // { | |
133 // slice = 0; | |
134 // } | |
235 | 135 |
249 | 136 // if (slice >= static_cast<int>(source_->GetSliceCount())) |
137 // { | |
138 // slice = source_->GetSliceCount() - 1; | |
139 // } | |
235 | 140 |
249 | 141 // if (slice != static_cast<int>(slice_)) |
142 // { | |
143 // SetSlice(slice); | |
144 // } | |
145 // } | |
146 // } | |
235 | 147 |
148 | |
249 | 149 // void SetSlice(size_t index) |
150 // { | |
151 // if (source_ != NULL && | |
152 // index < source_->GetSliceCount()) | |
153 // { | |
154 // slice_ = index; | |
155 | |
156 //#if 1 | |
157 // widget_->SetSlice(source_->GetSlice(slice_).GetGeometry()); | |
158 //#else | |
159 // // TEST for scene extents - Rotate the axes | |
160 // double a = 15.0 / 180.0 * M_PI; | |
235 | 161 |
249 | 162 //#if 1 |
163 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
164 // Vector y; GeometryToolbox::AssignVector(y, -sin(a), cos(a), 0); | |
165 //#else | |
166 // // Flip the normal | |
167 // Vector x; GeometryToolbox::AssignVector(x, cos(a), sin(a), 0); | |
168 // Vector y; GeometryToolbox::AssignVector(y, sin(a), -cos(a), 0); | |
169 //#endif | |
170 | |
171 // SliceGeometry s(source_->GetSlice(slice_).GetGeometry().GetOrigin(), x, y); | |
172 // widget_->SetSlice(s); | |
173 //#endif | |
174 // } | |
175 // } | |
176 | |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
177 |
266
c9cf95b49a86
removed OrthancSlicesLoader::ISliceLoaderObserver; now using standard messages instead
am@osimis.io
parents:
258
diff
changeset
|
178 virtual void HandleMessage(const IObservable& from, const IMessage& message) { |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
179 switch (message.GetType()) { |
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
180 case MessageType_GeometryReady: |
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
181 mainLayout_->SetDefaultView(); |
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
182 break; |
253 | 183 default: |
184 VLOG("unhandled message type" << message.GetType()); | |
235 | 185 } |
186 } | |
187 | |
242 | 188 std::unique_ptr<Interactor> interactor_; |
235 | 189 LayoutWidget* mainLayout_; |
190 LayoutWidget* thumbnailsLayout_; | |
191 LayerWidget* mainViewport_; | |
192 std::vector<LayerWidget*> thumbnails_; | |
193 std::vector<std::string> instances_; | |
194 unsigned int currentInstanceIndex_; | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
195 OrthancStone::WidgetViewport* wasmViewport1_; |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
196 OrthancStone::WidgetViewport* wasmViewport2_; |
235 | 197 |
254 | 198 IStatusBar* statusBar_; |
235 | 199 unsigned int slice_; |
258 | 200 std::unique_ptr<SmartLoader> smartLoader_; |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
201 |
235 | 202 public: |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
203 SimpleViewerApplication(MessageBroker& broker) : |
258 | 204 IObserver(broker), |
235 | 205 mainLayout_(NULL), |
206 currentInstanceIndex_(0), | |
242 | 207 wasmViewport1_(NULL), |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
208 wasmViewport2_(NULL), |
258 | 209 slice_(0) |
235 | 210 { |
211 } | |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
212 |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
213 virtual void Finalize() {} |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
214 virtual IWidget* GetCentralWidget() {return mainLayout_;} |
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
215 |
235 | 216 virtual void DeclareStartupOptions(boost::program_options::options_description& options) |
217 { | |
218 boost::program_options::options_description generic("Sample options"); | |
219 generic.add_options() | |
249 | 220 // ("study", boost::program_options::value<std::string>(), |
221 // "Orthanc ID of the study") | |
222 ("instance1", boost::program_options::value<std::string>(), | |
223 "Orthanc ID of the instances") | |
235 | 224 ("instance2", boost::program_options::value<std::string>(), |
225 "Orthanc ID of the instances") | |
249 | 226 ; |
235 | 227 |
249 | 228 options.add(generic); |
235 | 229 } |
230 | |
242 | 231 virtual void Initialize(BasicApplicationContext* context, |
232 IStatusBar& statusBar, | |
235 | 233 const boost::program_options::variables_map& parameters) |
234 { | |
235 using namespace OrthancStone; | |
236 | |
242 | 237 context_ = context; |
254 | 238 statusBar_ = &statusBar; |
235 | 239 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); |
254 | 240 statusBar.SetMessage("Use the key \"n\" to go to next image in the main viewport"); |
235 | 241 |
242 if (parameters.count("instance1") < 1) | |
243 { | |
244 LOG(ERROR) << "The instance ID is missing"; | |
245 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
246 } | |
247 if (parameters.count("instance2") < 1) | |
248 { | |
249 LOG(ERROR) << "The instance ID is missing"; | |
250 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
251 } | |
252 instances_.push_back(parameters["instance1"].as<std::string>()); | |
253 instances_.push_back(parameters["instance2"].as<std::string>()); | |
254 | |
255 mainLayout_ = new LayoutWidget(); | |
256 mainLayout_->SetPadding(10); | |
257 mainLayout_->SetBackgroundCleared(true); | |
258 mainLayout_->SetBackgroundColor(0, 0, 0); | |
259 mainLayout_->SetHorizontal(); | |
260 | |
261 thumbnailsLayout_ = new LayoutWidget(); | |
262 thumbnailsLayout_->SetPadding(10); | |
263 thumbnailsLayout_->SetBackgroundCleared(true); | |
264 thumbnailsLayout_->SetBackgroundColor(50, 50, 50); | |
265 thumbnailsLayout_->SetVertical(); | |
266 | |
251
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
267 mainViewport_ = new LayerWidget(broker_); |
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
268 thumbnails_.push_back(new LayerWidget(broker_)); |
192e6e349e69
first usage of new message system (in SDL only)
am@osimis.io
parents:
249
diff
changeset
|
269 thumbnails_.push_back(new LayerWidget(broker_)); |
235 | 270 |
271 // hierarchy | |
272 mainLayout_->AddWidget(thumbnailsLayout_); | |
273 mainLayout_->AddWidget(mainViewport_); | |
274 thumbnailsLayout_->AddWidget(thumbnails_[0]); | |
275 thumbnailsLayout_->AddWidget(thumbnails_[1]); | |
276 | |
277 // sources | |
258 | 278 smartLoader_.reset(new SmartLoader(broker_, context_->GetWebService())); |
279 smartLoader_->SetImageQuality(SliceImageQuality_FullPam); | |
280 smartLoader_->RegisterObserver(*this); | |
235 | 281 |
258 | 282 mainViewport_->AddLayer(smartLoader_->GetFrame(instances_[currentInstanceIndex_], 0)); |
283 thumbnails_[0]->AddLayer(smartLoader_->GetFrame(instances_[0], 0)); | |
284 thumbnails_[1]->AddLayer(smartLoader_->GetFrame(instances_[1], 0)); | |
235 | 285 |
286 mainLayout_->SetTransmitMouseOver(true); | |
242 | 287 interactor_.reset(new Interactor(*this)); |
288 mainViewport_->SetInteractor(*interactor_); | |
289 } | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
290 |
242 | 291 #if ORTHANC_ENABLE_SDL==0 |
292 virtual void InitializeWasm() { | |
293 | |
294 AttachWidgetToWasmViewport("canvas", thumbnailsLayout_); | |
295 AttachWidgetToWasmViewport("canvas2", mainViewport_); | |
296 } | |
237
b4642964c355
SimpleViewer demo running both with SDL and Wasm
am@osimis.io
parents:
235
diff
changeset
|
297 #endif |
249 | 298 |
299 void NextImage(WorldSceneWidget& widget) { | |
300 assert(context_); | |
254 | 301 statusBar_->SetMessage("displaying next image"); |
249 | 302 |
303 currentInstanceIndex_ = (currentInstanceIndex_ + 1) % instances_.size(); | |
304 | |
258 | 305 mainViewport_->ReplaceLayer(0, smartLoader_->GetFrame(instances_[currentInstanceIndex_], 0)); |
249 | 306 |
307 } | |
235 | 308 }; |
249 | 309 |
310 | |
235 | 311 } |
312 } |