comparison Applications/Samples/SingleFrameEditorApplication.h @ 358:b8eeb49f3e65 am-2

cleaning up
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 30 Oct 2018 07:55:08 +0100
parents ec4ad6c5eb99
children 100df90bf0ea
comparison
equal deleted inserted replaced
357:ec4ad6c5eb99 358:b8eeb49f3e65
865 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]); 865 SetPixelSpacing(pixelSpacing[0], pixelSpacing[1]);
866 } 866 }
867 867
868 //SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY()); 868 //SetPan(-0.5 * GetPixelSpacingX(), -0.5 * GetPixelSpacingY());
869 869
870 static unsigned int c = 0;
871 if (c == 0)
872 {
873 SetPan(400, 0);
874 c ++;
875 }
876
877 OrthancPlugins::DicomDatasetReader reader(dataset); 870 OrthancPlugins::DicomDatasetReader reader(dataset);
878 871
879 unsigned int width, height; 872 unsigned int width, height;
880 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) || 873 if (!reader.GetUnsignedIntegerValue(width, ConvertTag(Orthanc::DICOM_TAG_COLUMNS)) ||
881 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS))) 874 !reader.GetUnsignedIntegerValue(height, ConvertTag(Orthanc::DICOM_TAG_ROWS)))
1164 1157
1165 1158
1166 void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) 1159 void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message)
1167 { 1160 {
1168 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue(); 1161 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue();
1169 1162
1170 printf("JSON received: [%s] (%ld bytes) for bitmap %ld\n", 1163 LOG(INFO) << "JSON received: " << message.Uri.c_str()
1171 message.Uri.c_str(), message.AnswerSize, index); 1164 << " (" << message.AnswerSize << " bytes) for bitmap " << index;
1172 1165
1173 Bitmaps::iterator bitmap = bitmaps_.find(index); 1166 Bitmaps::iterator bitmap = bitmaps_.find(index);
1174 if (bitmap != bitmaps_.end()) 1167 if (bitmap != bitmaps_.end())
1175 { 1168 {
1176 assert(bitmap->second != NULL); 1169 assert(bitmap->second != NULL);
1177 1170
1194 1187
1195 void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) 1188 void OnFrameReceived(const OrthancApiClient::BinaryResponseReadyMessage& message)
1196 { 1189 {
1197 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue(); 1190 size_t index = dynamic_cast<Orthanc::SingleValueObject<size_t>*>(message.Payload.get())->GetValue();
1198 1191
1199 printf("Frame received: [%s] (%ld bytes) for bitmap %ld\n", 1192 LOG(INFO) << "DICOM frame received: " << message.Uri.c_str()
1200 message.Uri.c_str(), message.AnswerSize, index); 1193 << " (" << message.AnswerSize << " bytes) for bitmap " << index;
1201 1194
1202 Bitmaps::iterator bitmap = bitmaps_.find(index); 1195 Bitmaps::iterator bitmap = bitmaps_.find(index);
1203 if (bitmap != bitmaps_.end()) 1196 if (bitmap != bitmaps_.end())
1204 { 1197 {
1205 assert(bitmap->second != NULL); 1198 assert(bitmap->second != NULL);
2202 stack_.SetWindowing(newCenter, newWidth); 2195 stack_.SetWindowing(newCenter, newWidth);
2203 } 2196 }
2204 }; 2197 };
2205 2198
2206 2199
2207 class BitmapStackInteractor : public IWorldSceneInteractor
2208 {
2209 private:
2210 enum Tool
2211 {
2212 Tool_Move,
2213 Tool_Rotate,
2214 Tool_Crop,
2215 Tool_Resize,
2216 Tool_Windowing
2217 };
2218
2219 static double GetHandleSize()
2220 {
2221 return 10.0;
2222 }
2223
2224
2225 BitmapStack& stack_;
2226 UndoRedoStack undoRedoStack_;
2227 Tool tool_;
2228
2229
2230 public:
2231 BitmapStackInteractor(BitmapStack& stack) :
2232 stack_(stack),
2233 tool_(Tool_Move)
2234 {
2235 }
2236
2237 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
2238 const ViewportGeometry& view,
2239 MouseButton button,
2240 KeyboardModifiers modifiers,
2241 int viewportX,
2242 int viewportY,
2243 double x,
2244 double y,
2245 IStatusBar* statusBar)
2246 {
2247 if (button == MouseButton_Left)
2248 {
2249 size_t selected;
2250
2251 if (tool_ == Tool_Windowing)
2252 {
2253 return new WindowingTracker(undoRedoStack_, stack_,
2254 viewportX, viewportY,
2255 WindowingTracker::Action_DecreaseWidth,
2256 WindowingTracker::Action_IncreaseWidth,
2257 WindowingTracker::Action_DecreaseCenter,
2258 WindowingTracker::Action_IncreaseCenter);
2259 }
2260 else if (!stack_.GetSelectedBitmap(selected))
2261 {
2262 size_t bitmap;
2263 if (stack_.LookupBitmap(bitmap, x, y))
2264 {
2265 printf("CLICK on bitmap %ld\n", bitmap);
2266 stack_.Select(bitmap);
2267 }
2268
2269 return NULL;
2270 }
2271 else if (tool_ == Tool_Crop ||
2272 tool_ == Tool_Resize)
2273 {
2274 BitmapStack::BitmapAccessor accessor(stack_, selected);
2275 BitmapStack::Corner corner;
2276 if (accessor.GetBitmap().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize()))
2277 {
2278 switch (tool_)
2279 {
2280 case Tool_Crop:
2281 return new CropBitmapTracker(undoRedoStack_, stack_, view, selected, x, y, corner);
2282
2283 case Tool_Resize:
2284 return new ResizeBitmapTracker(undoRedoStack_, stack_, selected, x, y, corner,
2285 (modifiers & KeyboardModifiers_Shift));
2286
2287 default:
2288 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
2289 }
2290 }
2291 else
2292 {
2293 size_t bitmap;
2294
2295 if (!stack_.LookupBitmap(bitmap, x, y) ||
2296 bitmap != selected)
2297 {
2298 stack_.Unselect();
2299 }
2300
2301 return NULL;
2302 }
2303 }
2304 else
2305 {
2306 size_t bitmap;
2307
2308 if (stack_.LookupBitmap(bitmap, x, y) &&
2309 bitmap == selected)
2310 {
2311 switch (tool_)
2312 {
2313 case Tool_Move:
2314 return new MoveBitmapTracker(undoRedoStack_, stack_, bitmap, x, y,
2315 (modifiers & KeyboardModifiers_Shift));
2316
2317 case Tool_Rotate:
2318 return new RotateBitmapTracker(undoRedoStack_, stack_, view, bitmap, x, y,
2319 (modifiers & KeyboardModifiers_Shift));
2320
2321 default:
2322 break;
2323 }
2324
2325 return NULL;
2326 }
2327 else
2328 {
2329 printf("CLICK outside\n");
2330 stack_.Unselect();
2331 return NULL;
2332 }
2333 }
2334 }
2335 else
2336 {
2337 return NULL;
2338 }
2339 }
2340
2341 virtual void MouseOver(CairoContext& context,
2342 WorldSceneWidget& widget,
2343 const ViewportGeometry& view,
2344 double x,
2345 double y,
2346 IStatusBar* statusBar)
2347 {
2348 size_t selected;
2349 if (stack_.GetSelectedBitmap(selected) &&
2350 (tool_ == Tool_Crop ||
2351 tool_ == Tool_Resize))
2352 {
2353 BitmapStack::BitmapAccessor accessor(stack_, selected);
2354
2355 BitmapStack::Corner corner;
2356 if (accessor.GetBitmap().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize()))
2357 {
2358 accessor.GetBitmap().GetCorner(x, y, corner);
2359
2360 double z = 1.0 / view.GetZoom();
2361
2362 context.SetSourceColor(255, 0, 0);
2363 cairo_t* cr = context.GetObject();
2364 cairo_set_line_width(cr, 2.0 * z);
2365 cairo_move_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z);
2366 cairo_line_to(cr, x + GetHandleSize() * z, y - GetHandleSize() * z);
2367 cairo_line_to(cr, x + GetHandleSize() * z, y + GetHandleSize() * z);
2368 cairo_line_to(cr, x - GetHandleSize() * z, y + GetHandleSize() * z);
2369 cairo_line_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z);
2370 cairo_stroke(cr);
2371 }
2372 }
2373 }
2374
2375 virtual void MouseWheel(WorldSceneWidget& widget,
2376 MouseWheelDirection direction,
2377 KeyboardModifiers modifiers,
2378 IStatusBar* statusBar)
2379 {
2380 }
2381
2382 virtual void KeyPressed(WorldSceneWidget& widget,
2383 KeyboardKeys key,
2384 char keyChar,
2385 KeyboardModifiers modifiers,
2386 IStatusBar* statusBar)
2387 {
2388 switch (keyChar)
2389 {
2390 case 'c':
2391 tool_ = Tool_Crop;
2392 break;
2393
2394 case 'a':
2395 widget.FitContent();
2396 break;
2397
2398 case 'm':
2399 tool_ = Tool_Move;
2400 break;
2401
2402 case 'r':
2403 tool_ = Tool_Rotate;
2404 break;
2405
2406 case 's':
2407 tool_ = Tool_Resize;
2408 break;
2409
2410 case 'w':
2411 tool_ = Tool_Windowing;
2412 break;
2413
2414 case 'z':
2415 if (modifiers & KeyboardModifiers_Control)
2416 {
2417 undoRedoStack_.Undo();
2418 widget.NotifyContentChanged();
2419 }
2420 break;
2421
2422 case 'y':
2423 if (modifiers & KeyboardModifiers_Control)
2424 {
2425 undoRedoStack_.Redo();
2426 widget.NotifyContentChanged();
2427 }
2428 break;
2429
2430 default:
2431 break;
2432 }
2433 }
2434 };
2435
2436
2437
2438 class BitmapStackWidget : 2200 class BitmapStackWidget :
2439 public WorldSceneWidget, 2201 public WorldSceneWidget,
2440 public IObservable, 2202 public IObservable,
2441 public IObserver 2203 public IObserver
2442 { 2204 {
2443 private: 2205 private:
2444 BitmapStack& stack_; 2206 BitmapStack& stack_;
2445 BitmapStackInteractor myInteractor_;
2446 std::auto_ptr<Orthanc::Image> floatBuffer_; 2207 std::auto_ptr<Orthanc::Image> floatBuffer_;
2447 std::auto_ptr<CairoSurface> cairoBuffer_; 2208 std::auto_ptr<CairoSurface> cairoBuffer_;
2209 bool invert_;
2448 2210
2449 virtual bool RenderInternal(unsigned int width, 2211 virtual bool RenderInternal(unsigned int width,
2450 unsigned int height, 2212 unsigned int height,
2451 ImageInterpolation interpolation) 2213 ImageInterpolation interpolation)
2452 { 2214 {
2506 // https://en.wikipedia.org/wiki/Linear_interpolation 2268 // https://en.wikipedia.org/wiki/Linear_interpolation
2507 v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); // (*) 2269 v = static_cast<uint8_t>(255.0f * (*p - x0) / (x1 - x0)); // (*)
2508 } 2270 }
2509 2271
2510 // TODO MONOCHROME1 2272 // TODO MONOCHROME1
2511 /*if (invert_) 2273 if (invert_)
2512 { 2274 {
2513 v = 255 - v; 2275 v = 255 - v;
2514 }*/ 2276 }
2515 2277
2516 q[0] = v; 2278 q[0] = v;
2517 q[1] = v; 2279 q[1] = v;
2518 q[2] = v; 2280 q[2] = v;
2519 q[3] = 255; 2281 q[3] = 255;
2565 const std::string& name) : 2327 const std::string& name) :
2566 WorldSceneWidget(name), 2328 WorldSceneWidget(name),
2567 IObservable(broker), 2329 IObservable(broker),
2568 IObserver(broker), 2330 IObserver(broker),
2569 stack_(stack), 2331 stack_(stack),
2570 myInteractor_(stack_) 2332 invert_(false)
2571 { 2333 {
2572 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged)); 2334 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::GeometryChangedMessage>(*this, &BitmapStackWidget::OnGeometryChanged));
2573 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged)); 2335 stack.RegisterObserverCallback(new Callable<BitmapStackWidget, BitmapStack::ContentChangedMessage>(*this, &BitmapStackWidget::OnContentChanged));
2574 2336 }
2575 SetInteractor(myInteractor_); 2337
2338 BitmapStack& GetStack() const
2339 {
2340 return stack_;
2576 } 2341 }
2577 2342
2578 void OnGeometryChanged(const BitmapStack::GeometryChangedMessage& message) 2343 void OnGeometryChanged(const BitmapStack::GeometryChangedMessage& message)
2579 { 2344 {
2580 printf("Geometry has changed\n"); 2345 LOG(INFO) << "Geometry has changed";
2581 FitContent(); 2346 FitContent();
2582 } 2347 }
2583 2348
2584 void OnContentChanged(const BitmapStack::ContentChangedMessage& message) 2349 void OnContentChanged(const BitmapStack::ContentChangedMessage& message)
2585 { 2350 {
2586 printf("Content has changed\n"); 2351 LOG(INFO) << "Content has changed";
2587 NotifyContentChanged(); 2352 NotifyContentChanged();
2588 } 2353 }
2589 2354
2355 void SetInvert(bool invert)
2356 {
2357 invert_ = invert;
2358 NotifyContentChanged();
2359 }
2360
2361 void SwitchInvert()
2362 {
2363 invert_ = !invert_;
2364 NotifyContentChanged();
2365 }
2366
2367 bool IsInvert() const
2368 {
2369 return invert_;
2370 }
2371 };
2372
2373
2374 class BitmapStackInteractor : public IWorldSceneInteractor
2375 {
2376 private:
2377 enum Tool
2378 {
2379 Tool_Move,
2380 Tool_Rotate,
2381 Tool_Crop,
2382 Tool_Resize,
2383 Tool_Windowing
2384 };
2385
2386
2387 UndoRedoStack undoRedoStack_;
2388 Tool tool_;
2389
2390
2391 static double GetHandleSize()
2392 {
2393 return 10.0;
2394 }
2395
2396
2397 static BitmapStackWidget& GetWidget(WorldSceneWidget& widget)
2398 {
2399 return dynamic_cast<BitmapStackWidget&>(widget);
2400 }
2401
2402
2403 static BitmapStack& GetStack(WorldSceneWidget& widget)
2404 {
2405 return GetWidget(widget).GetStack();
2406 }
2407
2408
2409 public:
2410 BitmapStackInteractor() :
2411 tool_(Tool_Move)
2412 {
2413 }
2414
2415 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
2416 const ViewportGeometry& view,
2417 MouseButton button,
2418 KeyboardModifiers modifiers,
2419 int viewportX,
2420 int viewportY,
2421 double x,
2422 double y,
2423 IStatusBar* statusBar)
2424 {
2425 if (button == MouseButton_Left)
2426 {
2427 size_t selected;
2428
2429 if (tool_ == Tool_Windowing)
2430 {
2431 return new WindowingTracker(undoRedoStack_, GetStack(widget),
2432 viewportX, viewportY,
2433 WindowingTracker::Action_DecreaseWidth,
2434 WindowingTracker::Action_IncreaseWidth,
2435 WindowingTracker::Action_DecreaseCenter,
2436 WindowingTracker::Action_IncreaseCenter);
2437 }
2438 else if (!GetStack(widget).GetSelectedBitmap(selected))
2439 {
2440 size_t bitmap;
2441 if (GetStack(widget).LookupBitmap(bitmap, x, y))
2442 {
2443 LOG(INFO) << "Click on bitmap " << bitmap;
2444 GetStack(widget).Select(bitmap);
2445 }
2446
2447 return NULL;
2448 }
2449 else if (tool_ == Tool_Crop ||
2450 tool_ == Tool_Resize)
2451 {
2452 BitmapStack::BitmapAccessor accessor(GetStack(widget), selected);
2453 BitmapStack::Corner corner;
2454 if (accessor.GetBitmap().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize()))
2455 {
2456 switch (tool_)
2457 {
2458 case Tool_Crop:
2459 return new CropBitmapTracker(undoRedoStack_, GetStack(widget), view, selected, x, y, corner);
2460
2461 case Tool_Resize:
2462 return new ResizeBitmapTracker(undoRedoStack_, GetStack(widget), selected, x, y, corner,
2463 (modifiers & KeyboardModifiers_Shift));
2464
2465 default:
2466 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
2467 }
2468 }
2469 else
2470 {
2471 size_t bitmap;
2472
2473 if (!GetStack(widget).LookupBitmap(bitmap, x, y) ||
2474 bitmap != selected)
2475 {
2476 GetStack(widget).Unselect();
2477 }
2478
2479 return NULL;
2480 }
2481 }
2482 else
2483 {
2484 size_t bitmap;
2485
2486 if (GetStack(widget).LookupBitmap(bitmap, x, y) &&
2487 bitmap == selected)
2488 {
2489 switch (tool_)
2490 {
2491 case Tool_Move:
2492 return new MoveBitmapTracker(undoRedoStack_, GetStack(widget), bitmap, x, y,
2493 (modifiers & KeyboardModifiers_Shift));
2494
2495 case Tool_Rotate:
2496 return new RotateBitmapTracker(undoRedoStack_, GetStack(widget), view, bitmap, x, y,
2497 (modifiers & KeyboardModifiers_Shift));
2498
2499 default:
2500 break;
2501 }
2502
2503 return NULL;
2504 }
2505 else
2506 {
2507 LOG(INFO) << "Click out of any bitmap";
2508 GetStack(widget).Unselect();
2509 return NULL;
2510 }
2511 }
2512 }
2513 else
2514 {
2515 return NULL;
2516 }
2517 }
2518
2519 virtual void MouseOver(CairoContext& context,
2520 WorldSceneWidget& widget,
2521 const ViewportGeometry& view,
2522 double x,
2523 double y,
2524 IStatusBar* statusBar)
2525 {
2590 #if 0 2526 #if 0
2591 virtual bool Render(Orthanc::ImageAccessor& target) 2527 if (statusBar != NULL)
2592 { 2528 {
2593 if (RenderInternal(target.GetWidth(), target.GetHeight(), ImageInterpolation_Nearest)) 2529 char buf[64];
2594 { 2530 sprintf(buf, "X = %.02f Y = %.02f (in cm)", x / 10.0, y / 10.0);
2595 assert(cairoBuffer_.get() != NULL); 2531 statusBar->SetMessage(buf);
2596 2532 }
2597 Orthanc::ImageAccessor source;
2598 cairoBuffer_->GetAccessor(source);
2599 Orthanc::ImageProcessing::Copy(target, source);
2600 }
2601 else
2602 {
2603 Orthanc::ImageProcessing::Set(target, 0, 0, 0, 255);
2604 }
2605
2606 {
2607 // TODO => REFACTOR
2608 CairoSurface surface(target);
2609 CairoContext context(surface);
2610 GetView().ApplyTransform(context);
2611 stack_.DrawControls(context, GetView().GetZoom());
2612 }
2613
2614 return true;
2615 }
2616 #endif 2533 #endif
2534
2535 size_t selected;
2536 if (GetStack(widget).GetSelectedBitmap(selected) &&
2537 (tool_ == Tool_Crop ||
2538 tool_ == Tool_Resize))
2539 {
2540 BitmapStack::BitmapAccessor accessor(GetStack(widget), selected);
2541
2542 BitmapStack::Corner corner;
2543 if (accessor.GetBitmap().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize()))
2544 {
2545 accessor.GetBitmap().GetCorner(x, y, corner);
2546
2547 double z = 1.0 / view.GetZoom();
2548
2549 context.SetSourceColor(255, 0, 0);
2550 cairo_t* cr = context.GetObject();
2551 cairo_set_line_width(cr, 2.0 * z);
2552 cairo_move_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z);
2553 cairo_line_to(cr, x + GetHandleSize() * z, y - GetHandleSize() * z);
2554 cairo_line_to(cr, x + GetHandleSize() * z, y + GetHandleSize() * z);
2555 cairo_line_to(cr, x - GetHandleSize() * z, y + GetHandleSize() * z);
2556 cairo_line_to(cr, x - GetHandleSize() * z, y - GetHandleSize() * z);
2557 cairo_stroke(cr);
2558 }
2559 }
2560 }
2561
2562 virtual void MouseWheel(WorldSceneWidget& widget,
2563 MouseWheelDirection direction,
2564 KeyboardModifiers modifiers,
2565 IStatusBar* statusBar)
2566 {
2567 }
2568
2569 virtual void KeyPressed(WorldSceneWidget& widget,
2570 KeyboardKeys key,
2571 char keyChar,
2572 KeyboardModifiers modifiers,
2573 IStatusBar* statusBar)
2574 {
2575 switch (keyChar)
2576 {
2577 case 'a':
2578 widget.FitContent();
2579 break;
2580
2581 case 'c':
2582 tool_ = Tool_Crop;
2583 break;
2584
2585 case 'i':
2586 dynamic_cast<BitmapStackWidget&>(widget).SwitchInvert();
2587 break;
2588
2589 case 'm':
2590 tool_ = Tool_Move;
2591 break;
2592
2593 case 'r':
2594 tool_ = Tool_Rotate;
2595 break;
2596
2597 case 's':
2598 tool_ = Tool_Resize;
2599 break;
2600
2601 case 'w':
2602 tool_ = Tool_Windowing;
2603 break;
2604
2605 case 'y':
2606 if (modifiers & KeyboardModifiers_Control)
2607 {
2608 undoRedoStack_.Redo();
2609 widget.NotifyContentChanged();
2610 }
2611 break;
2612
2613 case 'z':
2614 if (modifiers & KeyboardModifiers_Control)
2615 {
2616 undoRedoStack_.Undo();
2617 widget.NotifyContentChanged();
2618 }
2619 break;
2620
2621 default:
2622 break;
2623 }
2624 }
2617 }; 2625 };
2618 2626
2627
2619 2628
2620 namespace Samples 2629 namespace Samples
2621 { 2630 {
2622 class SingleFrameEditorApplication : 2631 class SingleFrameEditorApplication :
2623 public SampleSingleCanvasApplicationBase, 2632 public SampleSingleCanvasApplicationBase,
2624 public IObserver 2633 public IObserver
2625 { 2634 {
2626 enum Tools
2627 {
2628 Tools_Crop,
2629 Tools_Windowing,
2630 Tools_Zoom,
2631 Tools_Pan
2632 };
2633
2634 enum Actions
2635 {
2636 Actions_Invert,
2637 Actions_RotateLeft,
2638 Actions_RotateRight
2639 };
2640
2641 private: 2635 private:
2642 class Interactor : public IWorldSceneInteractor
2643 {
2644 private:
2645 SingleFrameEditorApplication& application_;
2646
2647 public:
2648 Interactor(SingleFrameEditorApplication& application) :
2649 application_(application)
2650 {
2651 }
2652
2653 virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget,
2654 const ViewportGeometry& view,
2655 MouseButton button,
2656 KeyboardModifiers modifiers,
2657 int viewportX,
2658 int viewportY,
2659 double x,
2660 double y,
2661 IStatusBar* statusBar)
2662 {
2663 switch (application_.currentTool_) {
2664 case Tools_Zoom:
2665 printf("ZOOM\n");
2666
2667 case Tools_Crop:
2668 case Tools_Windowing:
2669 case Tools_Pan:
2670 // TODO return the right mouse tracker
2671 return NULL;
2672 }
2673
2674 return NULL;
2675 }
2676
2677 virtual void MouseOver(CairoContext& context,
2678 WorldSceneWidget& widget,
2679 const ViewportGeometry& view,
2680 double x,
2681 double y,
2682 IStatusBar* statusBar)
2683 {
2684 if (statusBar != NULL)
2685 {
2686 char buf[64];
2687 sprintf(buf, "X = %.02f Y = %.02f (in cm)", x / 10.0, y / 10.0);
2688 statusBar->SetMessage(buf);
2689 }
2690 }
2691
2692 virtual void MouseWheel(WorldSceneWidget& widget,
2693 MouseWheelDirection direction,
2694 KeyboardModifiers modifiers,
2695 IStatusBar* statusBar)
2696 {
2697 }
2698
2699 virtual void KeyPressed(WorldSceneWidget& widget,
2700 KeyboardKeys key,
2701 char keyChar,
2702 KeyboardModifiers modifiers,
2703 IStatusBar* statusBar)
2704 {
2705 switch (keyChar)
2706 {
2707 case 's':
2708 widget.FitContent();
2709 break;
2710 case 'p':
2711 application_.currentTool_ = Tools_Pan;
2712 break;
2713 case 'z':
2714 application_.currentTool_ = Tools_Zoom;
2715 break;
2716 case 'c':
2717 application_.currentTool_ = Tools_Crop;
2718 break;
2719 case 'w':
2720 application_.currentTool_ = Tools_Windowing;
2721 break;
2722 case 'i':
2723 application_.Invert();
2724 break;
2725 case 'r':
2726 if (modifiers == KeyboardModifiers_None)
2727 application_.Rotate(90);
2728 else
2729 application_.Rotate(-90);
2730 break;
2731 case 'e':
2732 application_.Export();
2733 break;
2734 default:
2735 break;
2736 }
2737 }
2738 };
2739
2740 std::auto_ptr<Interactor> mainWidgetInteractor_;
2741 std::auto_ptr<OrthancApiClient> orthancApiClient_; 2636 std::auto_ptr<OrthancApiClient> orthancApiClient_;
2742 std::auto_ptr<BitmapStack> stack_; 2637 std::auto_ptr<BitmapStack> stack_;
2743 Tools currentTool_; 2638 BitmapStackInteractor interactor_;
2744 const OrthancFrameLayerSource* source_;
2745 unsigned int slice_;
2746 2639
2747 public: 2640 public:
2748 SingleFrameEditorApplication(MessageBroker& broker) : 2641 SingleFrameEditorApplication(MessageBroker& broker) :
2749 IObserver(broker), 2642 IObserver(broker)
2750 currentTool_(Tools_Zoom),
2751 source_(NULL),
2752 slice_(0)
2753 { 2643 {
2754 } 2644 }
2755 2645
2756 virtual void DeclareStartupOptions(boost::program_options::options_description& options) 2646 virtual void DeclareStartupOptions(boost::program_options::options_description& options)
2757 { 2647 {
2772 { 2662 {
2773 using namespace OrthancStone; 2663 using namespace OrthancStone;
2774 2664
2775 context_ = context; 2665 context_ = context;
2776 2666
2777 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"); 2667 statusBar.SetMessage("Use the key \"a\" to reinitialize the layout");
2668 statusBar.SetMessage("Use the key \"c\" to crop");
2669 statusBar.SetMessage("Use the key \"f\" to switch full screen");
2670 statusBar.SetMessage("Use the key \"i\" to invert contrast");
2671 statusBar.SetMessage("Use the key \"m\" to move objects");
2672 statusBar.SetMessage("Use the key \"r\" to rotate objects");
2673 statusBar.SetMessage("Use the key \"s\" to resize objects (not applicable to DICOM bitmaps)");
2674 statusBar.SetMessage("Use the key \"w\" to change windowing");
2675
2676 statusBar.SetMessage("Use the key \"ctrl-z\" to undo action");
2677 statusBar.SetMessage("Use the key \"ctrl-y\" to redo action");
2778 2678
2779 if (parameters.count("instance") != 1) 2679 if (parameters.count("instance") != 1)
2780 { 2680 {
2781 LOG(ERROR) << "The instance ID is missing"; 2681 LOG(ERROR) << "The instance ID is missing";
2782 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); 2682 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
2789 2689
2790 Orthanc::FontRegistry fonts; 2690 Orthanc::FontRegistry fonts;
2791 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); 2691 fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16);
2792 2692
2793 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_)); 2693 stack_.reset(new BitmapStack(IObserver::broker_, *orthancApiClient_));
2794 stack_->LoadFrame(instance, frame, false); 2694 stack_->LoadFrame(instance, frame, false).SetPan(200, 0);
2795 stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", frame, false); 2695 //stack_->LoadFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false);
2796 2696
2797 { 2697 {
2798 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain"); 2698 BitmapStack::Bitmap& bitmap = stack_->LoadText(fonts.GetFont(0), "Hello\nworld\nBonjour, Alain");
2799 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); 2699 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256);
2800 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); 2700 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true);
2802 2702
2803 { 2703 {
2804 BitmapStack::Bitmap& bitmap = stack_->LoadTestBlock(100, 50); 2704 BitmapStack::Bitmap& bitmap = stack_->LoadTestBlock(100, 50);
2805 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256); 2705 //dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetForegroundValue(256);
2806 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true); 2706 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetResizeable(true);
2707 dynamic_cast<BitmapStack::AlphaBitmap&>(bitmap).SetPan(0, 200);
2807 } 2708 }
2808 2709
2809 2710
2810 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget"); 2711 mainWidget_ = new BitmapStackWidget(IObserver::broker_, *stack_, "main-widget");
2811 mainWidget_->SetTransmitMouseOver(true); 2712 mainWidget_->SetTransmitMouseOver(true);
2713 mainWidget_->SetInteractor(interactor_);
2812 2714
2813 //stack_->SetWindowing(128, 256); 2715 //stack_->SetWindowing(128, 256);
2814
2815 mainWidgetInteractor_.reset(new Interactor(*this));
2816 //mainWidget_->SetInteractor(*mainWidgetInteractor_);
2817 } 2716 }
2818 2717
2819 2718
2820 void Invert() 2719 void Invert()
2821 { 2720 {