comparison OrthancStone/Sources/Deprecated/Widgets/LayoutWidget.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Deprecated/Widgets/LayoutWidget.cpp@30deba7bc8e2
children
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
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-2020 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 #include "LayoutWidget.h"
23
24 #include <Logging.h>
25 #include <OrthancException.h>
26
27 #include <boost/math/special_functions/round.hpp>
28
29 namespace Deprecated
30 {
31 class LayoutWidget::LayoutMouseTracker : public IMouseTracker
32 {
33 private:
34 std::unique_ptr<IMouseTracker> tracker_;
35 int left_;
36 int top_;
37 unsigned int width_;
38 unsigned int height_;
39
40 public:
41 LayoutMouseTracker(IMouseTracker* tracker,
42 int left,
43 int top,
44 unsigned int width,
45 unsigned int height) :
46 tracker_(tracker),
47 left_(left),
48 top_(top),
49 width_(width),
50 height_(height)
51 {
52 if (tracker == NULL)
53 {
54 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
55 }
56 }
57
58 virtual void Render(Orthanc::ImageAccessor& surface)
59 {
60 Orthanc::ImageAccessor accessor;
61 surface.GetRegion(accessor, left_, top_, width_, height_);
62 tracker_->Render(accessor);
63 }
64
65 virtual void MouseUp()
66 {
67 tracker_->MouseUp();
68 }
69
70 virtual void MouseMove(int x,
71 int y,
72 const std::vector<Touch>& displayTouches)
73 {
74 std::vector<Touch> relativeTouches;
75 for (size_t t = 0; t < displayTouches.size(); t++)
76 {
77 relativeTouches.push_back(Touch(displayTouches[t].x - left_, displayTouches[t].y - top_));
78 }
79
80 tracker_->MouseMove(x - left_, y - top_, relativeTouches);
81 }
82 };
83
84
85 class LayoutWidget::ChildWidget : public boost::noncopyable
86 {
87 private:
88 boost::shared_ptr<IWidget> widget_;
89 int left_;
90 int top_;
91 unsigned int width_;
92 unsigned int height_;
93
94 public:
95 ChildWidget(boost::shared_ptr<IWidget> widget) :
96 widget_(widget)
97 {
98 assert(widget != NULL);
99 SetEmpty();
100 }
101
102 void DoAnimation()
103 {
104 if (widget_->HasAnimation())
105 {
106 widget_->DoAnimation();
107 }
108 }
109
110 IWidget& GetWidget() const
111 {
112 return *widget_;
113 }
114
115 void SetRectangle(unsigned int left,
116 unsigned int top,
117 unsigned int width,
118 unsigned int height)
119 {
120 left_ = left;
121 top_ = top;
122 width_ = width;
123 height_ = height;
124
125 widget_->SetSize(width, height);
126 }
127
128 void SetEmpty()
129 {
130 SetRectangle(0, 0, 0, 0);
131 }
132
133 bool Contains(int x,
134 int y) const
135 {
136 return (x >= left_ &&
137 y >= top_ &&
138 x < left_ + static_cast<int>(width_) &&
139 y < top_ + static_cast<int>(height_));
140 }
141
142 bool Render(Orthanc::ImageAccessor& target)
143 {
144 if (width_ == 0 ||
145 height_ == 0)
146 {
147 return true;
148 }
149 else
150 {
151 Orthanc::ImageAccessor accessor;
152 target.GetRegion(accessor, left_, top_, width_, height_);
153 return widget_->Render(accessor);
154 }
155 }
156
157 IMouseTracker* CreateMouseTracker(OrthancStone::MouseButton button,
158 int x,
159 int y,
160 OrthancStone::KeyboardModifiers modifiers,
161 const std::vector<Touch>& touches)
162 {
163 if (Contains(x, y))
164 {
165 IMouseTracker* tracker = widget_->CreateMouseTracker(button,
166 x - left_,
167 y - top_,
168 modifiers,
169 touches);
170 if (tracker)
171 {
172 return new LayoutMouseTracker(tracker, left_, top_, width_, height_);
173 }
174 }
175
176 return NULL;
177 }
178
179 void RenderMouseOver(Orthanc::ImageAccessor& target,
180 int x,
181 int y)
182 {
183 if (Contains(x, y))
184 {
185 Orthanc::ImageAccessor accessor;
186 target.GetRegion(accessor, left_, top_, width_, height_);
187
188 widget_->RenderMouseOver(accessor, x - left_, y - top_);
189 }
190 }
191
192 void MouseWheel(OrthancStone::MouseWheelDirection direction,
193 int x,
194 int y,
195 OrthancStone::KeyboardModifiers modifiers)
196 {
197 if (Contains(x, y))
198 {
199 widget_->MouseWheel(direction, x - left_, y - top_, modifiers);
200 }
201 }
202
203 bool HasRenderMouseOver()
204 {
205 return widget_->HasRenderMouseOver();
206 }
207 };
208
209
210 void LayoutWidget::ComputeChildrenExtents()
211 {
212 if (children_.size() == 0)
213 {
214 return;
215 }
216
217 float internal = static_cast<float>(paddingInternal_);
218
219 if (width_ <= paddingLeft_ + paddingRight_ ||
220 height_ <= paddingTop_ + paddingBottom_)
221 {
222 for (size_t i = 0; i < children_.size(); i++)
223 {
224 children_[i]->SetEmpty();
225 }
226 }
227 else if (isHorizontal_)
228 {
229 unsigned int padding = paddingLeft_ + paddingRight_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_;
230 float childWidth = ((static_cast<float>(width_) - static_cast<float>(padding)) /
231 static_cast<float>(children_.size()));
232
233 for (size_t i = 0; i < children_.size(); i++)
234 {
235 float left = static_cast<float>(paddingLeft_) + static_cast<float>(i) * (childWidth + internal);
236 float right = left + childWidth;
237
238 if (left >= right)
239 {
240 children_[i]->SetEmpty();
241 }
242 else
243 {
244 children_[i]->SetRectangle(static_cast<unsigned int>(left),
245 paddingTop_,
246 boost::math::iround(right - left),
247 height_ - paddingTop_ - paddingBottom_);
248 }
249 }
250 }
251 else
252 {
253 unsigned int padding = paddingTop_ + paddingBottom_ + (static_cast<unsigned int>(children_.size()) - 1) * paddingInternal_;
254 float childHeight = ((static_cast<float>(height_) - static_cast<float>(padding)) /
255 static_cast<float>(children_.size()));
256
257 for (size_t i = 0; i < children_.size(); i++)
258 {
259 float top = static_cast<float>(paddingTop_) + static_cast<float>(i) * (childHeight + internal);
260 float bottom = top + childHeight;
261
262 if (top >= bottom)
263 {
264 children_[i]->SetEmpty();
265 }
266 else
267 {
268 children_[i]->SetRectangle(paddingTop_,
269 static_cast<unsigned int>(top),
270 width_ - paddingLeft_ - paddingRight_,
271 boost::math::iround(bottom - top));
272 }
273 }
274 }
275
276 NotifyContentChanged(*this);
277 }
278
279
280 LayoutWidget::LayoutWidget(const std::string& name) :
281 WidgetBase(name),
282 isHorizontal_(true),
283 width_(0),
284 height_(0),
285 paddingLeft_(0),
286 paddingTop_(0),
287 paddingRight_(0),
288 paddingBottom_(0),
289 paddingInternal_(0)
290 {
291 }
292
293
294 LayoutWidget::~LayoutWidget()
295 {
296 for (size_t i = 0; i < children_.size(); i++)
297 {
298 delete children_[i];
299 }
300 }
301
302
303 void LayoutWidget::FitContent()
304 {
305 for (size_t i = 0; i < children_.size(); i++)
306 {
307 children_[i]->GetWidget().FitContent();
308 }
309 }
310
311
312 void LayoutWidget::NotifyContentChanged(const IWidget& widget)
313 {
314 // One of the children has changed
315 WidgetBase::NotifyContentChanged();
316 }
317
318
319 void LayoutWidget::SetHorizontal()
320 {
321 isHorizontal_ = true;
322 ComputeChildrenExtents();
323 }
324
325
326 void LayoutWidget::SetVertical()
327 {
328 isHorizontal_ = false;
329 ComputeChildrenExtents();
330 }
331
332
333 void LayoutWidget::SetPadding(unsigned int left,
334 unsigned int top,
335 unsigned int right,
336 unsigned int bottom,
337 unsigned int spacing)
338 {
339 paddingLeft_ = left;
340 paddingTop_ = top;
341 paddingRight_ = right;
342 paddingBottom_ = bottom;
343 paddingInternal_ = spacing;
344 }
345
346
347 void LayoutWidget::SetPadding(unsigned int padding)
348 {
349 paddingLeft_ = padding;
350 paddingTop_ = padding;
351 paddingRight_ = padding;
352 paddingBottom_ = padding;
353 paddingInternal_ = padding;
354 }
355
356
357 void LayoutWidget::AddWidget(boost::shared_ptr<IWidget> widget) // Takes ownership
358 {
359 if (widget == NULL)
360 {
361 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
362 }
363
364 if (GetStatusBar() != NULL)
365 {
366 widget->SetStatusBar(*GetStatusBar());
367 }
368
369 children_.push_back(new ChildWidget(widget));
370 widget->SetParent(*this);
371
372 ComputeChildrenExtents();
373
374 if (widget->HasAnimation())
375 {
376 hasAnimation_ = true;
377 }
378 }
379
380
381 void LayoutWidget::SetStatusBar(IStatusBar& statusBar)
382 {
383 WidgetBase::SetStatusBar(statusBar);
384
385 for (size_t i = 0; i < children_.size(); i++)
386 {
387 children_[i]->GetWidget().SetStatusBar(statusBar);
388 }
389 }
390
391
392 void LayoutWidget::SetSize(unsigned int width,
393 unsigned int height)
394 {
395 width_ = width;
396 height_ = height;
397 ComputeChildrenExtents();
398 }
399
400
401 bool LayoutWidget::Render(Orthanc::ImageAccessor& surface)
402 {
403 if (!WidgetBase::Render(surface))
404 {
405 return false;
406 }
407
408 for (size_t i = 0; i < children_.size(); i++)
409 {
410 if (!children_[i]->Render(surface))
411 {
412 return false;
413 }
414 }
415
416 return true;
417 }
418
419
420 IMouseTracker* LayoutWidget::CreateMouseTracker(OrthancStone::MouseButton button,
421 int x,
422 int y,
423 OrthancStone::KeyboardModifiers modifiers,
424 const std::vector<Touch>& touches)
425 {
426 for (size_t i = 0; i < children_.size(); i++)
427 {
428 IMouseTracker* tracker = children_[i]->CreateMouseTracker(button, x, y, modifiers, touches);
429 if (tracker != NULL)
430 {
431 return tracker;
432 }
433 }
434
435 return NULL;
436 }
437
438
439 void LayoutWidget::RenderMouseOver(Orthanc::ImageAccessor& target,
440 int x,
441 int y)
442 {
443 for (size_t i = 0; i < children_.size(); i++)
444 {
445 children_[i]->RenderMouseOver(target, x, y);
446 }
447 }
448
449
450 void LayoutWidget::MouseWheel(OrthancStone::MouseWheelDirection direction,
451 int x,
452 int y,
453 OrthancStone::KeyboardModifiers modifiers)
454 {
455 for (size_t i = 0; i < children_.size(); i++)
456 {
457 children_[i]->MouseWheel(direction, x, y, modifiers);
458 }
459 }
460
461
462 void LayoutWidget::KeyPressed(OrthancStone::KeyboardKeys key,
463 char keyChar,
464 OrthancStone::KeyboardModifiers modifiers)
465 {
466 for (size_t i = 0; i < children_.size(); i++)
467 {
468 children_[i]->GetWidget().KeyPressed(key, keyChar, modifiers);
469 }
470 }
471
472
473 void LayoutWidget::DoAnimation()
474 {
475 if (hasAnimation_)
476 {
477 for (size_t i = 0; i < children_.size(); i++)
478 {
479 children_[i]->DoAnimation();
480 }
481 }
482 else
483 {
484 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
485 }
486 }
487
488
489 bool LayoutWidget::HasRenderMouseOver()
490 {
491 for (size_t i = 0; i < children_.size(); i++)
492 {
493 if (children_[i]->HasRenderMouseOver())
494 {
495 return true;
496 }
497 }
498
499 return false;
500 }
501 }