Mercurial > hg > orthanc-stone
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 { |