comparison Samples/Sdl/RadiographyEditor.cpp @ 848:80829436ce0c am-mainline

starting to re-implement radiography editor with latest framework
author Alain Mazy <alain@mazy.be>
date Thu, 13 Jun 2019 16:47:02 +0200
parents
children 2d8ab34c8c91
comparison
equal deleted inserted replaced
842:2b245953b44b 848:80829436ce0c
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-2019 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 #include "../Shared/RadiographyEditorApp.h"
22
23 // From Stone
24 #include "../../Framework/Oracle/SleepOracleCommand.h"
25 #include "../../Framework/Oracle/ThreadedOracle.h"
26 #include "../../Applications/Sdl/SdlOpenGLWindow.h"
27 #include "../../Framework/Scene2D/OpenGLCompositor.h"
28 #include "../../Framework/Scene2D/CairoCompositor.h"
29 #include "../../Framework/Scene2D/ColorTextureSceneLayer.h"
30 #include "../../Framework/Scene2D/OpenGLCompositor.h"
31 #include "../../Framework/StoneInitialization.h"
32
33 #include <Core/Logging.h>
34 #include <Core/OrthancException.h>
35
36
37 #include <boost/shared_ptr.hpp>
38 #include <boost/weak_ptr.hpp>
39
40 #include <SDL.h>
41 #include <stdio.h>
42
43 using namespace OrthancStone;
44
45 namespace OrthancStone
46 {
47 class NativeApplicationContext : public IMessageEmitter
48 {
49 private:
50 boost::shared_mutex mutex_;
51 MessageBroker broker_;
52 IObservable oracleObservable_;
53
54 public:
55 NativeApplicationContext() :
56 oracleObservable_(broker_)
57 {
58 }
59
60
61 virtual void EmitMessage(const IObserver& observer,
62 const IMessage& message) ORTHANC_OVERRIDE
63 {
64 try
65 {
66 boost::unique_lock<boost::shared_mutex> lock(mutex_);
67 oracleObservable_.EmitMessage(observer, message);
68 }
69 catch (Orthanc::OrthancException& e)
70 {
71 LOG(ERROR) << "Exception while emitting a message: " << e.What();
72 }
73 }
74
75
76 class ReaderLock : public boost::noncopyable
77 {
78 private:
79 NativeApplicationContext& that_;
80 boost::shared_lock<boost::shared_mutex> lock_;
81
82 public:
83 ReaderLock(NativeApplicationContext& that) :
84 that_(that),
85 lock_(that.mutex_)
86 {
87 }
88 };
89
90
91 class WriterLock : public boost::noncopyable
92 {
93 private:
94 NativeApplicationContext& that_;
95 boost::unique_lock<boost::shared_mutex> lock_;
96
97 public:
98 WriterLock(NativeApplicationContext& that) :
99 that_(that),
100 lock_(that.mutex_)
101 {
102 }
103
104 MessageBroker& GetBroker()
105 {
106 return that_.broker_;
107 }
108
109 IObservable& GetOracleObservable()
110 {
111 return that_.oracleObservable_;
112 }
113 };
114 };
115 }
116
117 class OpenGlSdlCompositorFactory : public ICompositorFactory
118 {
119 OpenGL::IOpenGLContext& openGlContext_;
120
121 public:
122 OpenGlSdlCompositorFactory(OpenGL::IOpenGLContext& openGlContext) :
123 openGlContext_(openGlContext)
124 {}
125
126 ICompositor* GetCompositor(const Scene2D& scene)
127 {
128
129 OpenGLCompositor* compositor = new OpenGLCompositor(openGlContext_, scene);
130 compositor->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT,
131 FONT_SIZE_0, Orthanc::Encoding_Latin1);
132 compositor->SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT,
133 FONT_SIZE_1, Orthanc::Encoding_Latin1);
134 return compositor;
135 }
136 };
137
138 static void GLAPIENTRY
139 OpenGLMessageCallback(GLenum source,
140 GLenum type,
141 GLuint id,
142 GLenum severity,
143 GLsizei length,
144 const GLchar* message,
145 const void* userParam)
146 {
147 if (severity != GL_DEBUG_SEVERITY_NOTIFICATION)
148 {
149 fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
150 (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
151 type, severity, message);
152 }
153 }
154
155
156 /**
157 * IMPORTANT: The full arguments to "main()" are needed for SDL on
158 * Windows. Otherwise, one gets the linking error "undefined reference
159 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows
160 **/
161 int main(int argc, char* argv[])
162 {
163 using namespace OrthancStone;
164
165 StoneInitialize();
166 Orthanc::Logging::EnableInfoLevel(true);
167 // Orthanc::Logging::EnableTraceLevel(true);
168
169 try
170 {
171 OrthancStone::NativeApplicationContext context;
172 OrthancStone::NativeApplicationContext::WriterLock lock(context);
173 OrthancStone::ThreadedOracle oracle(context);
174
175 // False means we do NOT let Windows treat this as a legacy application
176 // that needs to be scaled
177 SdlOpenGLWindow window("Hello", 1024, 1024, false);
178
179 glEnable(GL_DEBUG_OUTPUT);
180 glDebugMessageCallback(OpenGLMessageCallback, 0);
181
182 std::auto_ptr<OpenGlSdlCompositorFactory> compositorFactory(new OpenGlSdlCompositorFactory(window));
183 boost::shared_ptr<RadiographyEditorApp> app(new RadiographyEditorApp(oracle, lock.GetOracleObservable(), compositorFactory.release()));
184 app->PrepareScene();
185 app->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight());
186
187 bool stopApplication = false;
188
189 while (!stopApplication)
190 {
191 app->Refresh();
192
193 SDL_Event event;
194 while (!stopApplication && SDL_PollEvent(&event))
195 {
196 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None;
197 if (event.key.keysym.mod & KMOD_CTRL)
198 modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Control));
199 if (event.key.keysym.mod & KMOD_ALT)
200 modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Alt));
201 if (event.key.keysym.mod & KMOD_SHIFT)
202 modifiers = static_cast<OrthancStone::KeyboardModifiers>(static_cast<int>(modifiers) | static_cast<int>(OrthancStone::KeyboardModifiers_Shift));
203
204 OrthancStone::MouseButton button;
205 if (event.button.button == SDL_BUTTON_LEFT)
206 button = OrthancStone::MouseButton_Left;
207 else if (event.button.button == SDL_BUTTON_MIDDLE)
208 button = OrthancStone::MouseButton_Middle;
209 else if (event.button.button == SDL_BUTTON_RIGHT)
210 button = OrthancStone::MouseButton_Right;
211
212 if (event.type == SDL_QUIT)
213 {
214 stopApplication = true;
215 break;
216 }
217 else if (event.type == SDL_WINDOWEVENT &&
218 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
219 {
220 app->DisableTracker(); // was: tracker.reset(NULL);
221 app->UpdateSize();
222 }
223 else if (event.type == SDL_KEYDOWN &&
224 event.key.repeat == 0 /* Ignore key bounce */)
225 {
226 switch (event.key.keysym.sym)
227 {
228 case SDLK_f:
229 window.GetWindow().ToggleMaximize();
230 break;
231
232 case SDLK_q:
233 stopApplication = true;
234 break;
235 default:
236 {
237 app->OnKeyPressed(event.key.keysym.sym, modifiers);
238 }
239 }
240 }
241 else if (event.type == SDL_MOUSEBUTTONDOWN)
242 {
243 app->OnMouseDown(event.button.x, event.button.y, modifiers, button);
244 }
245 else if (event.type == SDL_MOUSEMOTION)
246 {
247 app->OnMouseMove(event.button.x, event.button.y, modifiers);
248 }
249 else if (event.type == SDL_MOUSEBUTTONUP)
250 {
251 app->OnMouseUp(event.button.x, event.button.y, modifiers, button);
252 }
253 }
254 SDL_Delay(1);
255 }
256 }
257 catch (Orthanc::OrthancException& e)
258 {
259 LOG(ERROR) << "EXCEPTION: " << e.What();
260 }
261
262 StoneFinalize();
263
264 return 0;
265 }
266
267