Mercurial > hg > orthanc-stone
comparison Applications/Samples/SingleFrameEditorApplication.h @ 325:37ab9d83dc9b am-2
reactivate SingleFrameApplication sample + Added SingleFrameEditorApplication (SDL only)
author | am@osimis.io |
---|---|
date | Tue, 16 Oct 2018 11:30:00 +0200 |
parents | |
children | 612238b3f3e8 |
comparison
equal
deleted
inserted
replaced
324:29a79b8c3d39 | 325:37ab9d83dc9b |
---|---|
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 | |
29 #include <Core/Logging.h> | |
30 | |
31 namespace OrthancStone | |
32 { | |
33 namespace Samples | |
34 { | |
35 class SingleFrameEditorApplication : | |
36 public SampleApplicationBase, | |
37 public IObserver | |
38 { | |
39 enum Tools | |
40 { | |
41 Tools_Crop, | |
42 Tools_Windowing, | |
43 Tools_Zoom, | |
44 Tools_Pan | |
45 }; | |
46 | |
47 enum Actions | |
48 { | |
49 Actions_Invert, | |
50 Actions_RotateLeft, | |
51 Actions_RotateRight | |
52 }; | |
53 | |
54 private: | |
55 class Interactor : public IWorldSceneInteractor | |
56 { | |
57 private: | |
58 SingleFrameEditorApplication& application_; | |
59 | |
60 public: | |
61 Interactor(SingleFrameEditorApplication& application) : | |
62 application_(application) | |
63 { | |
64 } | |
65 | |
66 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, | |
67 const ViewportGeometry& view, | |
68 MouseButton button, | |
69 KeyboardModifiers modifiers, | |
70 double x, | |
71 double y, | |
72 IStatusBar* statusBar) | |
73 { | |
74 switch (application_.currentTool_) { | |
75 case Tools_Crop: | |
76 case Tools_Windowing: | |
77 case Tools_Zoom: | |
78 case Tools_Pan: | |
79 // TODO return the right mouse tracker | |
80 return NULL; | |
81 } | |
82 | |
83 return NULL; | |
84 } | |
85 | |
86 virtual void MouseOver(CairoContext& context, | |
87 WorldSceneWidget& widget, | |
88 const ViewportGeometry& view, | |
89 double x, | |
90 double y, | |
91 IStatusBar* statusBar) | |
92 { | |
93 if (statusBar != NULL) | |
94 { | |
95 Vector p = dynamic_cast<LayerWidget&>(widget).GetSlice().MapSliceToWorldCoordinates(x, y); | |
96 | |
97 char buf[64]; | |
98 sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", | |
99 p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); | |
100 statusBar->SetMessage(buf); | |
101 } | |
102 } | |
103 | |
104 virtual void MouseWheel(WorldSceneWidget& widget, | |
105 MouseWheelDirection direction, | |
106 KeyboardModifiers modifiers, | |
107 IStatusBar* statusBar) | |
108 { | |
109 } | |
110 | |
111 virtual void KeyPressed(WorldSceneWidget& widget, | |
112 char key, | |
113 KeyboardModifiers modifiers, | |
114 IStatusBar* statusBar) | |
115 { | |
116 switch (key) | |
117 { | |
118 case 's': | |
119 widget.SetDefaultView(); | |
120 break; | |
121 case 'p': | |
122 application_.currentTool_ = Tools_Pan; | |
123 break; | |
124 case 'z': | |
125 application_.currentTool_ = Tools_Zoom; | |
126 break; | |
127 case 'c': | |
128 application_.currentTool_ = Tools_Crop; | |
129 break; | |
130 case 'w': | |
131 application_.currentTool_ = Tools_Windowing; | |
132 break; | |
133 case 'i': | |
134 application_.Invert(); | |
135 break; | |
136 case 'r': | |
137 if (modifiers == KeyboardModifiers_None) | |
138 application_.Rotate(90); | |
139 else | |
140 application_.Rotate(-90); | |
141 break; | |
142 case 'e': | |
143 application_.Export(); | |
144 break; | |
145 default: | |
146 break; | |
147 } | |
148 } | |
149 }; | |
150 | |
151 void OnMainWidgetGeometryReady(const ILayerSource::GeometryReadyMessage& message) | |
152 { | |
153 mainWidget_->SetDefaultView(); | |
154 } | |
155 | |
156 LayerWidget* mainWidget_; // ownership is transfered to the application context | |
157 std::unique_ptr<Interactor> mainWidgetInteractor_; | |
158 std::unique_ptr<OrthancApiClient> orthancApiClient_; | |
159 Tools currentTool_; | |
160 | |
161 const OrthancFrameLayerSource* source_; | |
162 unsigned int slice_; | |
163 | |
164 public: | |
165 SingleFrameEditorApplication(MessageBroker& broker) : | |
166 IObserver(broker), | |
167 currentTool_(Tools_Zoom), | |
168 source_(NULL), | |
169 slice_(0) | |
170 { | |
171 } | |
172 | |
173 virtual void DeclareStartupOptions(boost::program_options::options_description& options) | |
174 { | |
175 boost::program_options::options_description generic("Sample options"); | |
176 generic.add_options() | |
177 ("instance", boost::program_options::value<std::string>(), | |
178 "Orthanc ID of the instance") | |
179 ("frame", boost::program_options::value<unsigned int>()->default_value(0), | |
180 "Number of the frame, for multi-frame DICOM instances") | |
181 ; | |
182 | |
183 options.add(generic); | |
184 } | |
185 | |
186 virtual void Initialize(StoneApplicationContext* context, | |
187 IStatusBar& statusBar, | |
188 const boost::program_options::variables_map& parameters) | |
189 { | |
190 using namespace OrthancStone; | |
191 | |
192 context_ = context; | |
193 | |
194 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout, \"p\" to pan, \"z\" to zoom, \"c\" to crop, \"i\" to invert, \"w\" to change windowing, \"r\" to rotate cw, \"shift+r\" to rotate ccw"); | |
195 | |
196 if (parameters.count("instance") != 1) | |
197 { | |
198 LOG(ERROR) << "The instance ID is missing"; | |
199 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
200 } | |
201 | |
202 std::string instance = parameters["instance"].as<std::string>(); | |
203 int frame = parameters["frame"].as<unsigned int>(); | |
204 | |
205 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService())); | |
206 mainWidget_ = new LayerWidget(broker_, "main-widget"); | |
207 | |
208 std::auto_ptr<OrthancFrameLayerSource> layer(new OrthancFrameLayerSource(broker_, *orthancApiClient_)); | |
209 source_ = layer.get(); | |
210 layer->LoadFrame(instance, frame); | |
211 layer->RegisterObserverCallback(new Callable<SingleFrameEditorApplication, ILayerSource::GeometryReadyMessage>(*this, &SingleFrameEditorApplication::OnMainWidgetGeometryReady)); | |
212 mainWidget_->AddLayer(layer.release()); | |
213 | |
214 mainWidget_->SetTransmitMouseOver(true); | |
215 | |
216 mainWidgetInteractor_.reset(new Interactor(*this)); | |
217 mainWidget_->SetInteractor(*mainWidgetInteractor_); | |
218 } | |
219 | |
220 virtual void Finalize() {} | |
221 virtual IWidget* GetCentralWidget() {return mainWidget_;} | |
222 | |
223 void Invert() | |
224 { | |
225 // TODO | |
226 } | |
227 | |
228 void Rotate(int degrees) | |
229 { | |
230 // TODO | |
231 } | |
232 | |
233 void Export() | |
234 { | |
235 // TODO: export dicom file to a temporary file | |
236 } | |
237 }; | |
238 | |
239 | |
240 } | |
241 } |