]> Creatis software - bbtk.git/blob - packages/kw/src/vtkKWSlicer.cxx
0e14bb138fc69d8c03a1568960c18bf3f901446e
[bbtk.git] / packages / kw / src / vtkKWSlicer.cxx
1 #ifdef USE_KWWIDGETS
2
3 #include "vtkKWSlicer.h"
4
5 #include "vtkCornerAnnotation.h"
6 #include "vtkImageData.h"
7 #include "vtkImageViewer2.h"
8 #include "vtkKWApplication.h"
9 #include "vtkKWFrame.h"
10 #include "vtkKWSplitFrame.h"
11 #include "vtkKWFrameWithLabel.h"
12 #include "vtkKWMenu.h"
13 #include "vtkKWMenuButton.h"
14 #include "vtkKWMenuButtonWithSpinButtons.h"
15 #include "vtkKWMenuButtonWithSpinButtonsWithLabel.h"
16 #include "vtkKWNotebook.h"
17 #include "vtkKWRenderWidget.h"
18 #include "vtkKWScale.h"
19 #include "vtkKWSimpleAnimationWidget.h"
20 #include "vtkKWWindow.h"
21 #include "vtkKWWindowLevelPresetSelector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkRenderWindow.h"
24 #include "vtkRenderWindowInteractor.h"
25 #include "vtkXMLImageDataReader.h"
26
27 #include "vtkKWCornerAnnotationEditor.h"
28
29 //#include "vtkKWWidgetsPaths.h" 
30 #include "vtkToolkits.h"
31
32 #include <vtksys/SystemTools.hxx>
33
34 extern "C" int Bbkw_Init(Tcl_Interp *interp);
35
36 //namespace bbkw {
37
38 //----------------------------------------------------------------------------
39 vtkStandardNewMacro( vtkKWSlicer );
40 vtkCxxRevisionMacro(vtkKWSlicer, "$Revision: 1.4 $");
41
42 //----------------------------------------------------------------------------
43 vtkKWSlicer::vtkKWSlicer()
44 {
45
46   Bbkw_Init(vtkKWApplication::GetMainInterp ());
47
48   this->Frame = NULL;
49   this->RenderWidget = NULL;
50   this->Image = NULL;
51   this->ImageViewer = NULL;
52   this->SliceScale = NULL;
53   this->WindowLevelPresetSelector = NULL;
54   this->AnimationWidget = NULL;
55 }
56
57 //----------------------------------------------------------------------------
58 vtkKWSlicer::~vtkKWSlicer()
59 {
60  if (this->Frame)
61     {
62     this->Frame->Delete();
63     }
64   if (this->SliceScale)
65     {
66     this->SliceScale->Delete();
67     }
68   if (this->ImageViewer)
69     {
70     this->ImageViewer->Delete();
71     }
72   if (this->RenderWidget)
73     {
74     this->RenderWidget->Delete();
75     }
76   if (this->WindowLevelPresetSelector)
77     {
78     this->WindowLevelPresetSelector->Delete();
79     }
80   if (this->AnnotationEditor)
81     {
82       this->AnnotationEditor->Delete();
83     }
84   if (this->AnimationWidget)
85     {
86     this->AnimationWidget->Delete();
87     }
88 }
89
90 //----------------------------------------------------------------------------
91 void vtkKWSlicer::CreateWidget()
92 {
93   // Check if already created
94
95   if (this->IsCreated())
96     {
97     vtkErrorMacro("class already created");
98     return;
99     }
100
101   // Call the superclass to create the whole widget
102
103   this->Superclass::CreateWidget();
104
105   vtkKWApplication *app = this->GetApplication();
106
107   // Add a SplitFrame
108   /*
109   Frame =  vtkKWSplitFrame::New();
110   Frame->SetFrame1MinimumSize(150);
111   Frame->SetFrame2MinimumSize(250);     
112   Frame->SetOrientationToVertical ();
113   Frame->SetExpandableFrameToFrame2();
114   Frame->SetParent(this);
115   Frame->Create();
116   app->Script("pack %s -side top -expand yes",// -fill both",
117               this->Frame->GetWidgetName());
118   // Add a render widget, attach it to the view frame, and pack
119   */
120
121   if (!this->RenderWidget)
122     {
123     this->RenderWidget = vtkKWRenderWidget::New();
124     }
125   this->RenderWidget->SetParent(this); //Frame->GetFrame2());
126   this->RenderWidget->Create();
127   this->RenderWidget->CornerAnnotationVisibilityOn();
128
129   //  app->Script("grid %s -row 0 -column 0 -columnspan 2  -sticky nsew -padx 8 -pady 8",
130   app->Script("pack %s -side top -expand y -fill both -padx 2 -pady 2",
131               //  app->Script("pack %s -expand y -fill both -anchor c -expand y", 
132               this->RenderWidget->GetWidgetName());
133   //  this->Script("grid rowconfigure %s 1 -weight 1 -minsize 100",
134   //               this->RenderWidget->GetWidgetName());
135
136  
137   // Create an image viewer
138   // Use the render window and renderer of the renderwidget
139
140   if (!this->ImageViewer)
141     {
142     this->ImageViewer = vtkImageViewer2::New();
143     }
144   this->ImageViewer->SetRenderWindow(this->RenderWidget->GetRenderWindow());
145   this->ImageViewer->SetRenderer(this->RenderWidget->GetRenderer());
146   //  this->ImageViewer->SetInput(reader->GetOutput());
147   this->ImageViewer->SetupInteractor(
148     this->RenderWidget->GetRenderWindow()->GetInteractor());
149
150
151   // The corner annotation has the ability to parse "tags" and fill
152   // them with information gathered from other objects.
153   // For example, let's display the slice and window/level in one corner
154   // by connecting the corner annotation to our image actor and
155   // image mapper
156
157   vtkCornerAnnotation *ca = this->RenderWidget->GetCornerAnnotation();
158   ca->SetImageActor(this->ImageViewer->GetImageActor());
159   ca->SetWindowLevel(this->ImageViewer->GetWindowLevel());
160   ca->SetText(2, "<slice>");
161   ca->SetText(3, "<window>\n<level>");
162
163
164
165   // Create a scale to control the slice
166
167   if (!this->SliceScale)
168     {
169     this->SliceScale = vtkKWScale::New();
170     }
171   this->SliceScale->SetParent(this); //Frame->GetFrame1());
172   this->SliceScale->Create();
173   //  this->SliceScale->SetCommand(this, "SetSliceFromScaleCallback");
174
175   app->Script("pack %s -side top -expand n -fill x",
176               this->SliceScale->GetWidgetName());
177   //app->Script("grid %s -row 1 -column 1 -sticky nsew -padx 8",
178               //app->Script("pack %s -side right -expand n -fill x -padx 2 -pady 2",
179   //          this->SliceScale->GetWidgetName());
180   //  this->Script("grid rowconfigure %s 0 -weight 1",
181   //               this->SliceScale->GetWidgetName());
182
183   // Create a menu button to control the orientation
184
185   vtkKWMenuButtonWithSpinButtonsWithLabel *orientation_menubutton =
186     vtkKWMenuButtonWithSpinButtonsWithLabel::New();
187
188   orientation_menubutton->SetParent(this); //Frame->GetFrame1());
189   orientation_menubutton->Create();
190   orientation_menubutton->SetLabelText("Orientation:");
191   orientation_menubutton->SetPadX(2);
192   orientation_menubutton->SetPadY(2);
193   orientation_menubutton->SetBorderWidth(2);
194   orientation_menubutton->SetReliefToGroove();
195
196   app->Script("pack %s -side top -expand n -fill x",
197               orientation_menubutton->GetWidgetName());
198
199   //  this->Script("grid %s -row 1 -column 0",
200               //app->Script("pack %s -side left -anchor nw -expand n -fill x",
201   //              orientation_menubutton->GetWidgetName());
202   //  this->Script("grid rowconfigure %s 1 -weight 1",
203   //             orientation_menubutton->GetWidgetName());
204
205   vtkKWMenuButton *mb = orientation_menubutton->GetWidget()->GetWidget();
206   vtkKWMenu *menu = OrientationMenu = mb->GetMenu();
207
208   menu->AddRadioButton("X-Y"); //, this, "SetSliceOrientationToXYCallback");
209   menu->AddRadioButton("X-Z"); //, this, "SetSliceOrientationToXZCallback");
210   menu->AddRadioButton("Y-Z"); //, this, "SetSliceOrientationToYZCallback");
211
212   mb->SetValue("X-Y");
213
214
215   
216   // Create a window/level preset selector
217   vtkKWFrameWithLabel *wl_frame = vtkKWFrameWithLabel::New();
218   wl_frame->SetParent(this); //Frame->GetFrame1());
219   wl_frame->Create();
220   wl_frame->SetLabelText("Window/Level Presets");
221   wl_frame->CollapseFrame ();
222   app->Script("pack %s -side top -anchor nw -expand n -fill x -pady 2",
223               wl_frame->GetWidgetName());
224
225   if (!this->WindowLevelPresetSelector)
226     {
227     this->WindowLevelPresetSelector = vtkKWWindowLevelPresetSelector::New();
228     }
229   this->WindowLevelPresetSelector->SetParent(wl_frame->GetFrame());
230   this->WindowLevelPresetSelector->Create();
231   this->WindowLevelPresetSelector->ThumbnailColumnVisibilityOn();
232     
233  
234
235   app->Script("pack %s -side top -anchor nw -expand n -fill x",
236               this->WindowLevelPresetSelector->GetWidgetName());
237
238   // Create a corner annotation editor
239   this->AnnotationEditor = vtkKWCornerAnnotationEditor::New();
240   this->AnnotationEditor->SetParent(this);
241   this->AnnotationEditor->Create();
242   this->AnnotationEditor->SetRenderWidget(this->RenderWidget);
243   this->AnnotationEditor->GetFrame()->CollapseFrame ();
244   app->Script("pack %s -side top -anchor nw -expand n -fill x", 
245               this->AnnotationEditor->GetWidgetName());
246
247
248   // Create a simple animation widget
249   /*
250   vtkKWFrameWithLabel *animation_frame = vtkKWFrameWithLabel::New();
251   animation_frame->SetParent(this); //->GetMainPanelFrame());
252   animation_frame->Create();
253   animation_frame->SetLabelText("Movie Creator");
254
255   app->Script("pack %s -side top -anchor nw -expand n -fill x -pady 2",
256               animation_frame->GetWidgetName());
257
258   if (!this->AnimationWidget)
259     {
260     this->AnimationWidget = vtkKWSimpleAnimationWidget::New();
261     }
262   this->AnimationWidget->SetParent(animation_frame->GetFrame());
263   this->AnimationWidget->Create();
264   this->AnimationWidget->SetRenderWidget(this->RenderWidget);
265   this->AnimationWidget->SetAnimationTypeToSlice();
266   //  this->AnimationWidget->SetSliceSetCommand(this, "SetSliceCallback");
267   //  this->AnimationWidget->SetSliceGetCommand(this, "GetSliceCallback");
268
269   app->Script("pack %s -side top -anchor nw -expand n -fill x",
270               this->AnimationWidget->GetWidgetName());
271   */
272
273   this->UpdateSliceRanges();
274
275   // Callbacks
276   this->AddCallbackCommandObserver( this->SliceScale, 
277                                     vtkKWScale::ScaleValueChangingEvent);
278   this->AddCallbackCommandObserver( menu, 
279                                     vtkKWMenu::MenuItemInvokedEvent);
280
281   //  this->AddCallbackCommandObserver( this->WindowLevelPresetSelector,
282   
283   this->WindowLevelPresetSelector->SetPresetAddCommand(this, 
284                                                        "WindowLevelPresetAddCallback");
285   this->WindowLevelPresetSelector->SetPresetApplyCommand(this,
286                                                          "WindowLevelPresetApplyCallback");
287   this->WindowLevelPresetSelector->SetPresetUpdateCommand(
288     this, "WindowLevelPresetUpdateCallback");
289   this->WindowLevelPresetSelector->SetPresetHasChangedCommand(
290     this, "WindowLevelPresetHasChangedCallback");
291
292
293
294   // Deallocate local objects
295
296   //  reader->Delete();
297   orientation_menubutton->Delete();
298   //  wl_frame->Delete();
299   //  animation_frame->Delete();
300   UpdateImage();
301 }
302
303
304 //----------------------------------------------------------------------------
305 void vtkKWSlicer::ProcessCallbackCommandEvents(
306   vtkObject *caller, unsigned long event, void *calldata)
307 {
308   //  std::cout << "###### vtkKWSlicer::ProcessCallbackCommandEvents" << std::endl;
309   if (caller == this->SliceScale && 
310       event == vtkKWScale::ScaleValueChangingEvent)
311     {
312       this->SetSliceFromScaleCallback(*((double*)calldata));
313     }
314   if (caller == this->OrientationMenu && 
315       event == vtkKWMenu::MenuItemInvokedEvent)
316     {
317       int i = *((int*)calldata);
318       //      std::cout << i << std::endl;
319       if (i==0) this->SetSliceOrientationToXYCallback();
320       else if (i==1) this->SetSliceOrientationToXZCallback();
321       else if (i==2) this->SetSliceOrientationToYZCallback();
322           
323
324       //      this->SetSliceFromScaleCallback(*((double*)calldata));
325     }
326
327   /*
328   // We received a notification from the application that its value was
329   // changed. Let's propagate that value to our scale widget
330
331   if (caller == myapp && event == vtkCommand::ModifiedEvent)
332     {
333     this->Scale->SetValue(myapp->GetMyValue());
334     }
335   */
336   this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata);
337 }
338  //----------------------------------------------------------------------------
339
340  //----------------------------------------------------------------------------
341 void vtkKWSlicer::SetImage(vtkImageData* image)
342 {
343   Image = vtkImageData::New();
344   Image->ShallowCopy(image);
345   UpdateImage();
346 }
347 //----------------------------------------------------------------------------
348
349 //----------------------------------------------------------------------------
350 void vtkKWSlicer::UpdateImage()
351 {
352   if (!Image) return;
353   if (!this->IsCreated()) return;
354   this->ImageViewer->SetInput(Image);
355   double *range = Image->GetScalarRange();
356   this->ImageViewer->SetColorWindow(range[1] - range[0]);
357   this->ImageViewer->SetColorLevel(0.5 * (range[1] + range[0]));
358   this->RenderWidget->ResetCamera(); 
359   this->UpdateSliceRanges();
360   Image->Delete();
361 }
362 //----------------------------------------------------------------------------
363
364 //----------------------------------------------------------------------------
365 void vtkKWSlicer::SetSliceFromScaleCallback(double value)
366 {
367   this->ImageViewer->SetSlice((int)value);
368   this->ImageViewer->Render();
369 }
370
371 //----------------------------------------------------------------------------
372 void vtkKWSlicer::SetSliceCallback(int slice)
373 {
374   this->ImageViewer->SetSlice(slice);
375 }
376
377 //----------------------------------------------------------------------------
378 int vtkKWSlicer::GetSliceCallback()
379 {
380   return this->ImageViewer->GetSlice();
381 }
382
383 //----------------------------------------------------------------------------
384 int vtkKWSlicer::GetSliceMinCallback()
385 {
386   return this->ImageViewer->GetSliceMin();
387 }
388
389 //----------------------------------------------------------------------------
390 int vtkKWSlicer::GetSliceMaxCallback()
391 {
392   return this->ImageViewer->GetSliceMax();
393 }
394
395 //----------------------------------------------------------------------------
396 void vtkKWSlicer::UpdateSliceRanges()
397 {
398   this->SliceScale->SetRange(
399     this->ImageViewer->GetSliceMin(), this->ImageViewer->GetSliceMax());
400   this->SliceScale->SetValue(this->ImageViewer->GetSlice());
401
402   /*
403   this->AnimationWidget->SetSliceRange(
404     this->ImageViewer->GetSliceMin(), this->ImageViewer->GetSliceMax());
405   */
406 }
407
408 //----------------------------------------------------------------------------
409 void vtkKWSlicer::SetSliceOrientationToXYCallback()
410 {
411   this->ImageViewer->SetSliceOrientationToXY();
412   this->UpdateSliceRanges();
413 }
414
415 //----------------------------------------------------------------------------
416 void vtkKWSlicer::SetSliceOrientationToXZCallback()
417 {
418   this->ImageViewer->SetSliceOrientationToXZ();
419   this->UpdateSliceRanges();
420 }
421
422 //----------------------------------------------------------------------------
423 void vtkKWSlicer::SetSliceOrientationToYZCallback()
424 {
425   this->ImageViewer->SetSliceOrientationToYZ();
426   this->UpdateSliceRanges();
427 }
428
429 //----------------------------------------------------------------------------
430 void vtkKWSlicer::WindowLevelPresetApplyCallback(int id)
431 {
432   if (this->WindowLevelPresetSelector->HasPreset(id))
433     {
434     this->ImageViewer->SetColorWindow(
435       this->WindowLevelPresetSelector->GetPresetWindow(id));
436     this->ImageViewer->SetColorLevel(
437       this->WindowLevelPresetSelector->GetPresetLevel(id));
438     this->ImageViewer->Render();
439     }
440 }
441 //----------------------------------------------------------------------------
442 int vtkKWSlicer::WindowLevelPresetAddCallback()
443 {
444   int id = this->WindowLevelPresetSelector->AddPreset();
445   this->WindowLevelPresetUpdateCallback(id);
446   this->WindowLevelPresetSelector->SelectPreset(id);
447   return id;
448 }
449
450 //----------------------------------------------------------------------------
451 void vtkKWSlicer::WindowLevelPresetUpdateCallback(int id)
452 {
453   this->WindowLevelPresetSelector->SetPresetWindow(
454     id, this->ImageViewer->GetColorWindow());
455   this->WindowLevelPresetSelector->SetPresetLevel(
456     id, this->ImageViewer->GetColorLevel());
457   this->WindowLevelPresetHasChangedCallback(id);
458 }
459
460 //----------------------------------------------------------------------------
461 void vtkKWSlicer::WindowLevelPresetHasChangedCallback(int id)
462 {
463   this->WindowLevelPresetSelector->
464     BuildPresetThumbnailAndScreenshotFromRenderWindow(
465       id, this->RenderWidget->GetRenderWindow());
466 }
467
468
469 //} // namespace kw
470 #endif // USE_KWWIDGETS