2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
30 #include "vtkKWSlicer.h"
32 #include "vtkCornerAnnotation.h"
33 #include "vtkImageData.h"
34 #include "vtkImageViewer2.h"
35 #include "vtkKWApplication.h"
36 #include "vtkKWFrame.h"
37 #include "vtkKWSplitFrame.h"
38 #include "vtkKWFrameWithLabel.h"
39 #include "vtkKWMenu.h"
40 #include "vtkKWMenuButton.h"
41 #include "vtkKWMenuButtonWithSpinButtons.h"
42 #include "vtkKWMenuButtonWithSpinButtonsWithLabel.h"
43 #include "vtkKWNotebook.h"
44 #include "vtkKWRenderWidget.h"
45 #include "vtkKWScale.h"
46 #include "vtkKWSimpleAnimationWidget.h"
47 #include "vtkKWWindow.h"
48 #include "vtkKWWindowLevelPresetSelector.h"
49 #include "vtkObjectFactory.h"
50 #include "vtkRenderWindow.h"
51 #include "vtkRenderWindowInteractor.h"
52 #include "vtkXMLImageDataReader.h"
54 #include "vtkKWCornerAnnotationEditor.h"
56 //#include "vtkKWWidgetsPaths.h"
57 #include "vtkToolkits.h"
59 #include <vtksys/SystemTools.hxx>
61 extern "C" int Bbkw_Init(Tcl_Interp *interp);
65 //----------------------------------------------------------------------------
66 vtkStandardNewMacro( vtkKWSlicer );
67 vtkCxxRevisionMacro(vtkKWSlicer, "$Revision: 1.5 $");
69 //----------------------------------------------------------------------------
70 vtkKWSlicer::vtkKWSlicer()
73 Bbkw_Init(vtkKWApplication::GetMainInterp ());
76 this->RenderWidget = NULL;
78 this->ImageViewer = NULL;
79 this->SliceScale = NULL;
80 this->WindowLevelPresetSelector = NULL;
81 this->AnimationWidget = NULL;
84 //----------------------------------------------------------------------------
85 vtkKWSlicer::~vtkKWSlicer()
89 this->Frame->Delete();
93 this->SliceScale->Delete();
95 if (this->ImageViewer)
97 this->ImageViewer->Delete();
99 if (this->RenderWidget)
101 this->RenderWidget->Delete();
103 if (this->WindowLevelPresetSelector)
105 this->WindowLevelPresetSelector->Delete();
107 if (this->AnnotationEditor)
109 this->AnnotationEditor->Delete();
111 if (this->AnimationWidget)
113 this->AnimationWidget->Delete();
117 //----------------------------------------------------------------------------
118 void vtkKWSlicer::CreateWidget()
120 // Check if already created
122 if (this->IsCreated())
124 vtkErrorMacro("class already created");
128 // Call the superclass to create the whole widget
130 this->Superclass::CreateWidget();
132 vtkKWApplication *app = this->GetApplication();
136 Frame = vtkKWSplitFrame::New();
137 Frame->SetFrame1MinimumSize(150);
138 Frame->SetFrame2MinimumSize(250);
139 Frame->SetOrientationToVertical ();
140 Frame->SetExpandableFrameToFrame2();
141 Frame->SetParent(this);
143 app->Script("pack %s -side top -expand yes",// -fill both",
144 this->Frame->GetWidgetName());
145 // Add a render widget, attach it to the view frame, and pack
148 if (!this->RenderWidget)
150 this->RenderWidget = vtkKWRenderWidget::New();
152 this->RenderWidget->SetParent(this); //Frame->GetFrame2());
153 this->RenderWidget->Create();
154 this->RenderWidget->CornerAnnotationVisibilityOn();
156 // app->Script("grid %s -row 0 -column 0 -columnspan 2 -sticky nsew -padx 8 -pady 8",
157 app->Script("pack %s -side top -expand y -fill both -padx 2 -pady 2",
158 // app->Script("pack %s -expand y -fill both -anchor c -expand y",
159 this->RenderWidget->GetWidgetName());
160 // this->Script("grid rowconfigure %s 1 -weight 1 -minsize 100",
161 // this->RenderWidget->GetWidgetName());
164 // Create an image viewer
165 // Use the render window and renderer of the renderwidget
167 if (!this->ImageViewer)
169 this->ImageViewer = vtkImageViewer2::New();
171 this->ImageViewer->SetRenderWindow(this->RenderWidget->GetRenderWindow());
172 this->ImageViewer->SetRenderer(this->RenderWidget->GetRenderer());
173 // this->ImageViewer->SetInput(reader->GetOutput());
174 this->ImageViewer->SetupInteractor(
175 this->RenderWidget->GetRenderWindow()->GetInteractor());
178 // The corner annotation has the ability to parse "tags" and fill
179 // them with information gathered from other objects.
180 // For example, let's display the slice and window/level in one corner
181 // by connecting the corner annotation to our image actor and
184 vtkCornerAnnotation *ca = this->RenderWidget->GetCornerAnnotation();
185 ca->SetImageActor(this->ImageViewer->GetImageActor());
186 ca->SetWindowLevel(this->ImageViewer->GetWindowLevel());
187 ca->SetText(2, "<slice>");
188 ca->SetText(3, "<window>\n<level>");
192 // Create a scale to control the slice
194 if (!this->SliceScale)
196 this->SliceScale = vtkKWScale::New();
198 this->SliceScale->SetParent(this); //Frame->GetFrame1());
199 this->SliceScale->Create();
200 // this->SliceScale->SetCommand(this, "SetSliceFromScaleCallback");
202 app->Script("pack %s -side top -expand n -fill x",
203 this->SliceScale->GetWidgetName());
204 //app->Script("grid %s -row 1 -column 1 -sticky nsew -padx 8",
205 //app->Script("pack %s -side right -expand n -fill x -padx 2 -pady 2",
206 // this->SliceScale->GetWidgetName());
207 // this->Script("grid rowconfigure %s 0 -weight 1",
208 // this->SliceScale->GetWidgetName());
210 // Create a menu button to control the orientation
212 vtkKWMenuButtonWithSpinButtonsWithLabel *orientation_menubutton =
213 vtkKWMenuButtonWithSpinButtonsWithLabel::New();
215 orientation_menubutton->SetParent(this); //Frame->GetFrame1());
216 orientation_menubutton->Create();
217 orientation_menubutton->SetLabelText("Orientation:");
218 orientation_menubutton->SetPadX(2);
219 orientation_menubutton->SetPadY(2);
220 orientation_menubutton->SetBorderWidth(2);
221 orientation_menubutton->SetReliefToGroove();
223 app->Script("pack %s -side top -expand n -fill x",
224 orientation_menubutton->GetWidgetName());
226 // this->Script("grid %s -row 1 -column 0",
227 //app->Script("pack %s -side left -anchor nw -expand n -fill x",
228 // orientation_menubutton->GetWidgetName());
229 // this->Script("grid rowconfigure %s 1 -weight 1",
230 // orientation_menubutton->GetWidgetName());
232 vtkKWMenuButton *mb = orientation_menubutton->GetWidget()->GetWidget();
233 vtkKWMenu *menu = OrientationMenu = mb->GetMenu();
235 menu->AddRadioButton("X-Y"); //, this, "SetSliceOrientationToXYCallback");
236 menu->AddRadioButton("X-Z"); //, this, "SetSliceOrientationToXZCallback");
237 menu->AddRadioButton("Y-Z"); //, this, "SetSliceOrientationToYZCallback");
243 // Create a window/level preset selector
244 vtkKWFrameWithLabel *wl_frame = vtkKWFrameWithLabel::New();
245 wl_frame->SetParent(this); //Frame->GetFrame1());
247 wl_frame->SetLabelText("Window/Level Presets");
248 wl_frame->CollapseFrame ();
249 app->Script("pack %s -side top -anchor nw -expand n -fill x -pady 2",
250 wl_frame->GetWidgetName());
252 if (!this->WindowLevelPresetSelector)
254 this->WindowLevelPresetSelector = vtkKWWindowLevelPresetSelector::New();
256 this->WindowLevelPresetSelector->SetParent(wl_frame->GetFrame());
257 this->WindowLevelPresetSelector->Create();
258 this->WindowLevelPresetSelector->ThumbnailColumnVisibilityOn();
262 app->Script("pack %s -side top -anchor nw -expand n -fill x",
263 this->WindowLevelPresetSelector->GetWidgetName());
265 // Create a corner annotation editor
266 this->AnnotationEditor = vtkKWCornerAnnotationEditor::New();
267 this->AnnotationEditor->SetParent(this);
268 this->AnnotationEditor->Create();
269 this->AnnotationEditor->SetRenderWidget(this->RenderWidget);
270 this->AnnotationEditor->GetFrame()->CollapseFrame ();
271 app->Script("pack %s -side top -anchor nw -expand n -fill x",
272 this->AnnotationEditor->GetWidgetName());
275 // Create a simple animation widget
277 vtkKWFrameWithLabel *animation_frame = vtkKWFrameWithLabel::New();
278 animation_frame->SetParent(this); //->GetMainPanelFrame());
279 animation_frame->Create();
280 animation_frame->SetLabelText("Movie Creator");
282 app->Script("pack %s -side top -anchor nw -expand n -fill x -pady 2",
283 animation_frame->GetWidgetName());
285 if (!this->AnimationWidget)
287 this->AnimationWidget = vtkKWSimpleAnimationWidget::New();
289 this->AnimationWidget->SetParent(animation_frame->GetFrame());
290 this->AnimationWidget->Create();
291 this->AnimationWidget->SetRenderWidget(this->RenderWidget);
292 this->AnimationWidget->SetAnimationTypeToSlice();
293 // this->AnimationWidget->SetSliceSetCommand(this, "SetSliceCallback");
294 // this->AnimationWidget->SetSliceGetCommand(this, "GetSliceCallback");
296 app->Script("pack %s -side top -anchor nw -expand n -fill x",
297 this->AnimationWidget->GetWidgetName());
300 this->UpdateSliceRanges();
303 this->AddCallbackCommandObserver( this->SliceScale,
304 vtkKWScale::ScaleValueChangingEvent);
305 this->AddCallbackCommandObserver( menu,
306 vtkKWMenu::MenuItemInvokedEvent);
308 // this->AddCallbackCommandObserver( this->WindowLevelPresetSelector,
310 this->WindowLevelPresetSelector->SetPresetAddCommand(this,
311 "WindowLevelPresetAddCallback");
312 this->WindowLevelPresetSelector->SetPresetApplyCommand(this,
313 "WindowLevelPresetApplyCallback");
314 this->WindowLevelPresetSelector->SetPresetUpdateCommand(
315 this, "WindowLevelPresetUpdateCallback");
316 this->WindowLevelPresetSelector->SetPresetHasChangedCommand(
317 this, "WindowLevelPresetHasChangedCallback");
321 // Deallocate local objects
324 orientation_menubutton->Delete();
325 // wl_frame->Delete();
326 // animation_frame->Delete();
331 //----------------------------------------------------------------------------
332 void vtkKWSlicer::ProcessCallbackCommandEvents(
333 vtkObject *caller, unsigned long event, void *calldata)
335 // std::cout << "###### vtkKWSlicer::ProcessCallbackCommandEvents" << std::endl;
336 if (caller == this->SliceScale &&
337 event == vtkKWScale::ScaleValueChangingEvent)
339 this->SetSliceFromScaleCallback(*((double*)calldata));
341 if (caller == this->OrientationMenu &&
342 event == vtkKWMenu::MenuItemInvokedEvent)
344 int i = *((int*)calldata);
345 // std::cout << i << std::endl;
346 if (i==0) this->SetSliceOrientationToXYCallback();
347 else if (i==1) this->SetSliceOrientationToXZCallback();
348 else if (i==2) this->SetSliceOrientationToYZCallback();
351 // this->SetSliceFromScaleCallback(*((double*)calldata));
355 // We received a notification from the application that its value was
356 // changed. Let's propagate that value to our scale widget
358 if (caller == myapp && event == vtkCommand::ModifiedEvent)
360 this->Scale->SetValue(myapp->GetMyValue());
363 this->Superclass::ProcessCallbackCommandEvents(caller, event, calldata);
365 //----------------------------------------------------------------------------
367 //----------------------------------------------------------------------------
368 void vtkKWSlicer::SetImage(vtkImageData* image)
370 Image = vtkImageData::New();
371 Image->ShallowCopy(image);
374 //----------------------------------------------------------------------------
376 //----------------------------------------------------------------------------
377 void vtkKWSlicer::UpdateImage()
380 if (!this->IsCreated()) return;
381 this->ImageViewer->SetInput(Image);
382 double *range = Image->GetScalarRange();
383 this->ImageViewer->SetColorWindow(range[1] - range[0]);
384 this->ImageViewer->SetColorLevel(0.5 * (range[1] + range[0]));
385 this->RenderWidget->ResetCamera();
386 this->UpdateSliceRanges();
389 //----------------------------------------------------------------------------
391 //----------------------------------------------------------------------------
392 void vtkKWSlicer::SetSliceFromScaleCallback(double value)
394 this->ImageViewer->SetSlice((int)value);
395 this->ImageViewer->Render();
398 //----------------------------------------------------------------------------
399 void vtkKWSlicer::SetSliceCallback(int slice)
401 this->ImageViewer->SetSlice(slice);
404 //----------------------------------------------------------------------------
405 int vtkKWSlicer::GetSliceCallback()
407 return this->ImageViewer->GetSlice();
410 //----------------------------------------------------------------------------
411 int vtkKWSlicer::GetSliceMinCallback()
413 return this->ImageViewer->GetSliceMin();
416 //----------------------------------------------------------------------------
417 int vtkKWSlicer::GetSliceMaxCallback()
419 return this->ImageViewer->GetSliceMax();
422 //----------------------------------------------------------------------------
423 void vtkKWSlicer::UpdateSliceRanges()
425 this->SliceScale->SetRange(
426 this->ImageViewer->GetSliceMin(), this->ImageViewer->GetSliceMax());
427 this->SliceScale->SetValue(this->ImageViewer->GetSlice());
430 this->AnimationWidget->SetSliceRange(
431 this->ImageViewer->GetSliceMin(), this->ImageViewer->GetSliceMax());
435 //----------------------------------------------------------------------------
436 void vtkKWSlicer::SetSliceOrientationToXYCallback()
438 this->ImageViewer->SetSliceOrientationToXY();
439 this->UpdateSliceRanges();
442 //----------------------------------------------------------------------------
443 void vtkKWSlicer::SetSliceOrientationToXZCallback()
445 this->ImageViewer->SetSliceOrientationToXZ();
446 this->UpdateSliceRanges();
449 //----------------------------------------------------------------------------
450 void vtkKWSlicer::SetSliceOrientationToYZCallback()
452 this->ImageViewer->SetSliceOrientationToYZ();
453 this->UpdateSliceRanges();
456 //----------------------------------------------------------------------------
457 void vtkKWSlicer::WindowLevelPresetApplyCallback(int id)
459 if (this->WindowLevelPresetSelector->HasPreset(id))
461 this->ImageViewer->SetColorWindow(
462 this->WindowLevelPresetSelector->GetPresetWindow(id));
463 this->ImageViewer->SetColorLevel(
464 this->WindowLevelPresetSelector->GetPresetLevel(id));
465 this->ImageViewer->Render();
468 //----------------------------------------------------------------------------
469 int vtkKWSlicer::WindowLevelPresetAddCallback()
471 int id = this->WindowLevelPresetSelector->AddPreset();
472 this->WindowLevelPresetUpdateCallback(id);
473 this->WindowLevelPresetSelector->SelectPreset(id);
477 //----------------------------------------------------------------------------
478 void vtkKWSlicer::WindowLevelPresetUpdateCallback(int id)
480 this->WindowLevelPresetSelector->SetPresetWindow(
481 id, this->ImageViewer->GetColorWindow());
482 this->WindowLevelPresetSelector->SetPresetLevel(
483 id, this->ImageViewer->GetColorLevel());
484 this->WindowLevelPresetHasChangedCallback(id);
487 //----------------------------------------------------------------------------
488 void vtkKWSlicer::WindowLevelPresetHasChangedCallback(int id)
490 this->WindowLevelPresetSelector->
491 BuildPresetThumbnailAndScreenshotFromRenderWindow(
492 id, this->RenderWidget->GetRenderWindow());
497 #endif // USE_KWWIDGETS