001package plugins.kernel.canvas; 002 003import icy.gui.component.IcyTextField; 004import icy.gui.component.IcyTextField.TextChangeListener; 005import icy.gui.component.NumberTextField; 006import icy.gui.component.button.ColorChooserButton; 007import icy.gui.component.button.ColorChooserButton.ColorChangeListener; 008import icy.gui.component.button.IcyToggleButton; 009import icy.resource.ResourceUtil; 010import icy.resource.icon.IcyIcon; 011import icy.vtk.VtkImageVolume; 012import icy.vtk.VtkImageVolume.VtkVolumeBlendType; 013 014import java.awt.Color; 015import java.awt.GridBagConstraints; 016import java.awt.GridBagLayout; 017import java.awt.Image; 018import java.awt.Insets; 019import java.awt.event.ActionEvent; 020import java.awt.event.ActionListener; 021import java.beans.PropertyChangeEvent; 022import java.util.EventListener; 023 024import javax.swing.DefaultComboBoxModel; 025import javax.swing.JCheckBox; 026import javax.swing.JComboBox; 027import javax.swing.JLabel; 028import javax.swing.JPanel; 029import javax.swing.border.EmptyBorder; 030 031public class VtkSettingPanel extends JPanel implements ActionListener, TextChangeListener, ColorChangeListener 032 033{ 034 /** 035 * 036 */ 037 private static final long serialVersionUID = 6433369095311474470L; 038 039 protected static final Image ICON_GPU = ResourceUtil.getAlphaIconAsImage("gpu.png"); 040 protected static final Image ICON_SHADING = ResourceUtil.getColorIconAsImage("shading.png"); 041 042 public static final String PROPERTY_BG_COLOR = "renderBGColor"; 043 public static final String PROPERTY_MAPPER = "volumeMapper"; 044 public static final String PROPERTY_BLENDING = "volumeBlending"; 045 public static final String PROPERTY_SAMPLE = "volumeSample"; 046 public static final String PROPERTY_INTERPOLATION = "volumeInterpolation"; 047 public static final String PROPERTY_SHADING = "shading"; 048 public static final String PROPERTY_AMBIENT = "volumeAmbient"; 049 public static final String PROPERTY_DIFFUSE = "volumeDiffuse"; 050 public static final String PROPERTY_SPECULAR = "volumeSpecular"; 051 052 /** 053 * GUI 054 */ 055 private ColorChooserButton bgColorButton; 056 private JCheckBox gpuMapperCheckBox; 057 private JComboBox volumeBlendingComboBox; 058 private JComboBox volumeSampleComboBox; 059 private JComboBox volumeInterpolationComboBox; 060 private IcyToggleButton shadingButton; 061 private NumberTextField volumeAmbientField; 062 private NumberTextField volumeSpecularField; 063 private NumberTextField volumeDiffuseField; 064 065 /** 066 * Create the panel. 067 */ 068 public VtkSettingPanel() 069 { 070 super(); 071 072 initialize(); 073 074 updateState(); 075 076 bgColorButton.addColorChangeListener(this); 077 gpuMapperCheckBox.addActionListener(this); 078 volumeBlendingComboBox.addActionListener(this); 079 volumeInterpolationComboBox.addActionListener(this); 080 volumeSampleComboBox.addActionListener(this); 081 shadingButton.addActionListener(this); 082 083 volumeAmbientField.addTextChangeListener(this); 084 volumeDiffuseField.addTextChangeListener(this); 085 volumeSpecularField.addTextChangeListener(this); 086 } 087 088 protected void initialize() 089 { 090 setBorder(new EmptyBorder(2, 0, 2, 0)); 091 GridBagLayout gridBagLayout = new GridBagLayout(); 092 gridBagLayout.columnWidths = new int[] {0, 0, 0, 0, 0}; 093 gridBagLayout.rowHeights = new int[] {0, 0, 0, 0, 0, 0}; 094 gridBagLayout.columnWeights = new double[] {0.0, 1.0, 1.0, 1.0, Double.MIN_VALUE}; 095 gridBagLayout.rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; 096 setLayout(gridBagLayout); 097 098 final JLabel lblBackground = new JLabel("Background color "); 099 lblBackground.setToolTipText("Change background color"); 100 GridBagConstraints gbc_lblBackground = new GridBagConstraints(); 101 gbc_lblBackground.anchor = GridBagConstraints.WEST; 102 gbc_lblBackground.insets = new Insets(0, 0, 5, 5); 103 gbc_lblBackground.gridx = 0; 104 gbc_lblBackground.gridy = 0; 105 add(lblBackground, gbc_lblBackground); 106 107 bgColorButton = new ColorChooserButton(); 108 bgColorButton.setToolTipText("Change background color"); 109 GridBagConstraints gbc_bgColorButton = new GridBagConstraints(); 110 gbc_bgColorButton.anchor = GridBagConstraints.WEST; 111 gbc_bgColorButton.insets = new Insets(0, 0, 5, 5); 112 gbc_bgColorButton.gridx = 1; 113 gbc_bgColorButton.gridy = 0; 114 add(bgColorButton, gbc_bgColorButton); 115 116 gpuMapperCheckBox = new JCheckBox("New check box"); 117 gpuMapperCheckBox.setFocusable(false); 118 gpuMapperCheckBox.setIconTextGap(8); 119 gpuMapperCheckBox.setText("GPU rendering"); 120 gpuMapperCheckBox.setToolTipText("Enable GPU volume rendering"); 121 GridBagConstraints gbc_gpuMapperCheckBox = new GridBagConstraints(); 122 gbc_gpuMapperCheckBox.anchor = GridBagConstraints.EAST; 123 gbc_gpuMapperCheckBox.gridwidth = 2; 124 gbc_gpuMapperCheckBox.insets = new Insets(0, 0, 5, 0); 125 gbc_gpuMapperCheckBox.gridx = 2; 126 gbc_gpuMapperCheckBox.gridy = 0; 127 add(gpuMapperCheckBox, gbc_gpuMapperCheckBox); 128 129 final JLabel lblInterpolation = new JLabel("Interpolation "); 130 lblInterpolation.setToolTipText("Select volume rendering interpolation method"); 131 GridBagConstraints gbc_lblInterpolation = new GridBagConstraints(); 132 gbc_lblInterpolation.anchor = GridBagConstraints.WEST; 133 gbc_lblInterpolation.insets = new Insets(0, 0, 5, 5); 134 gbc_lblInterpolation.gridx = 0; 135 gbc_lblInterpolation.gridy = 1; 136 add(lblInterpolation, gbc_lblInterpolation); 137 138 volumeInterpolationComboBox = new JComboBox(); 139 volumeInterpolationComboBox.setToolTipText("Select volume rendering interpolation method"); 140 volumeInterpolationComboBox.setMaximumRowCount(7); 141 volumeInterpolationComboBox.setModel(new DefaultComboBoxModel(new String[] {"Nearest (Fast)", "Linear", 142 "Cubic (Slow)"})); 143 volumeInterpolationComboBox.setSelectedIndex(1); 144 GridBagConstraints gbc_volumeInterpolationComboBox = new GridBagConstraints(); 145 gbc_volumeInterpolationComboBox.fill = GridBagConstraints.HORIZONTAL; 146 gbc_volumeInterpolationComboBox.gridwidth = 3; 147 gbc_volumeInterpolationComboBox.insets = new Insets(0, 0, 5, 0); 148 gbc_volumeInterpolationComboBox.gridx = 1; 149 gbc_volumeInterpolationComboBox.gridy = 1; 150 add(volumeInterpolationComboBox, gbc_volumeInterpolationComboBox); 151 152 JLabel lblBlending = new JLabel("Blending"); 153 lblBlending.setToolTipText("Select volume rendering blending method"); 154 GridBagConstraints gbc_lblBlending = new GridBagConstraints(); 155 gbc_lblBlending.anchor = GridBagConstraints.WEST; 156 gbc_lblBlending.insets = new Insets(0, 0, 5, 5); 157 gbc_lblBlending.gridx = 0; 158 gbc_lblBlending.gridy = 2; 159 add(lblBlending, gbc_lblBlending); 160 161 volumeBlendingComboBox = new JComboBox(); 162 volumeBlendingComboBox.setToolTipText("Select volume rendering blending method"); 163 volumeBlendingComboBox.setModel(new DefaultComboBoxModel(VtkVolumeBlendType.values())); 164 GridBagConstraints gbc_volumeBlendingComboBox = new GridBagConstraints(); 165 gbc_volumeBlendingComboBox.fill = GridBagConstraints.HORIZONTAL; 166 gbc_volumeBlendingComboBox.gridwidth = 3; 167 gbc_volumeBlendingComboBox.insets = new Insets(0, 0, 5, 0); 168 gbc_volumeBlendingComboBox.gridx = 1; 169 gbc_volumeBlendingComboBox.gridy = 2; 170 add(volumeBlendingComboBox, gbc_volumeBlendingComboBox); 171 172 final JLabel lblSample = new JLabel("Sample"); 173 lblSample.setToolTipText("Set volume sample resolution (raycaster mapper only)"); 174 GridBagConstraints gbc_lblSample = new GridBagConstraints(); 175 gbc_lblSample.anchor = GridBagConstraints.WEST; 176 gbc_lblSample.insets = new Insets(0, 0, 5, 5); 177 gbc_lblSample.gridx = 0; 178 gbc_lblSample.gridy = 3; 179 add(lblSample, gbc_lblSample); 180 181 volumeSampleComboBox = new JComboBox(); 182 volumeSampleComboBox 183 .setToolTipText("Use low value for fine (but slow) rendering and high value for fast (but coarse) rendering"); 184 volumeSampleComboBox.setMaximumRowCount(11); 185 volumeSampleComboBox.setModel(new DefaultComboBoxModel(new String[] {"Auto", "1 (Slow)", "2", "3", "4", "5", 186 "6", "7", "8", "9", "10 (Fast)"})); 187 volumeSampleComboBox.setSelectedIndex(0); 188 GridBagConstraints gbc_volumeSampleComboBox = new GridBagConstraints(); 189 gbc_volumeSampleComboBox.fill = GridBagConstraints.HORIZONTAL; 190 gbc_volumeSampleComboBox.gridwidth = 3; 191 gbc_volumeSampleComboBox.insets = new Insets(0, 0, 5, 0); 192 gbc_volumeSampleComboBox.gridx = 1; 193 gbc_volumeSampleComboBox.gridy = 3; 194 add(volumeSampleComboBox, gbc_volumeSampleComboBox); 195 196 shadingButton = new IcyToggleButton(new IcyIcon(ICON_SHADING, false)); 197 shadingButton.setIconTextGap(8); 198 shadingButton.setText("Shading"); 199 shadingButton.setFocusable(false); 200 shadingButton.setToolTipText("Enable volume shading"); 201 GridBagConstraints gbc_shadingBtn = new GridBagConstraints(); 202 gbc_shadingBtn.anchor = GridBagConstraints.WEST; 203 gbc_shadingBtn.insets = new Insets(0, 0, 0, 5); 204 gbc_shadingBtn.gridx = 0; 205 gbc_shadingBtn.gridy = 4; 206 add(shadingButton, gbc_shadingBtn); 207 208 volumeAmbientField = new NumberTextField(); 209 volumeAmbientField.setToolTipText("Ambient lighting coefficient"); 210 GridBagConstraints gbc_volumeAmbientField = new GridBagConstraints(); 211 gbc_volumeAmbientField.fill = GridBagConstraints.HORIZONTAL; 212 gbc_volumeAmbientField.insets = new Insets(0, 0, 0, 5); 213 gbc_volumeAmbientField.gridx = 1; 214 gbc_volumeAmbientField.gridy = 4; 215 add(volumeAmbientField, gbc_volumeAmbientField); 216 volumeAmbientField.setColumns(3); 217 218 volumeDiffuseField = new NumberTextField(); 219 volumeDiffuseField.setToolTipText("Diffuse lighting coefficient"); 220 GridBagConstraints gbc_volumeDiffuseField = new GridBagConstraints(); 221 gbc_volumeDiffuseField.insets = new Insets(0, 0, 0, 5); 222 gbc_volumeDiffuseField.fill = GridBagConstraints.HORIZONTAL; 223 gbc_volumeDiffuseField.gridx = 2; 224 gbc_volumeDiffuseField.gridy = 4; 225 add(volumeDiffuseField, gbc_volumeDiffuseField); 226 volumeDiffuseField.setColumns(3); 227 228 volumeSpecularField = new NumberTextField(); 229 volumeSpecularField.setToolTipText("Specular lighting coefficient"); 230 GridBagConstraints gbc_volumeSpecularField = new GridBagConstraints(); 231 gbc_volumeSpecularField.fill = GridBagConstraints.HORIZONTAL; 232 gbc_volumeSpecularField.gridx = 3; 233 gbc_volumeSpecularField.gridy = 4; 234 add(volumeSpecularField, gbc_volumeSpecularField); 235 volumeSpecularField.setColumns(3); 236 } 237 238 protected void updateState() 239 { 240 // if (isBoundingBoxVisible()) 241 // { 242 // boundingBoxGridCheckBox.setEnabled(true); 243 // boundingBoxRulerCheckBox.setEnabled(true); 244 // } 245 // else 246 // { 247 // boundingBoxGridCheckBox.setEnabled(false); 248 // boundingBoxRulerCheckBox.setEnabled(false); 249 // } 250 251 // switch (getVolumeMapperType()) 252 // { 253 // case RAYCAST_CPU_FIXEDPOINT: 254 // case RAYCAST_GPU_OPENGL: 255 // volumeSampleComboBox.setEnabled(true); 256 // volumeBlendingComboBox.setEnabled(true); 257 // break; 258 // case TEXTURE2D_OPENGL: 259 // case TEXTURE3D_OPENGL: 260 // volumeSampleComboBox.setEnabled(false); 261 // volumeBlendingComboBox.setEnabled(false); 262 // break; 263 // } 264 } 265 266 public Color getBackgroundColor() 267 { 268 return bgColorButton.getColor(); 269 } 270 271 public void setBackgroundColor(Color value) 272 { 273 bgColorButton.setColor(value); 274 } 275 276 public boolean getGPURendering() 277 { 278 return gpuMapperCheckBox.isSelected(); 279 } 280 281 public void setGPURendering(boolean value) 282 { 283 gpuMapperCheckBox.setSelected(value); 284 } 285 286 public int getVolumeInterpolation() 287 { 288 return volumeInterpolationComboBox.getSelectedIndex(); 289 } 290 291 public void setVolumeInterpolation(int value) 292 { 293 volumeInterpolationComboBox.setSelectedIndex(value); 294 } 295 296 public VtkVolumeBlendType getVolumeBlendingMode() 297 { 298 if (volumeBlendingComboBox.getSelectedIndex() == -1) 299 return null; 300 301 return (VtkVolumeBlendType) volumeBlendingComboBox.getSelectedItem(); 302 } 303 304 public void setVolumeBlendingMode(VtkVolumeBlendType value) 305 { 306 volumeBlendingComboBox.setSelectedItem(value); 307 } 308 309 public int getVolumeSample() 310 { 311 return volumeSampleComboBox.getSelectedIndex(); 312 } 313 314 public void setVolumeSample(int value) 315 { 316 volumeSampleComboBox.setSelectedIndex(value); 317 } 318 319 public double getVolumeAmbient() 320 { 321 return volumeAmbientField.getNumericValue(); 322 } 323 324 public void setVolumeAmbient(double value) 325 { 326 volumeAmbientField.setNumericValue(value); 327 } 328 329 public double getVolumeDiffuse() 330 { 331 return volumeDiffuseField.getNumericValue(); 332 } 333 334 public void setVolumeDiffuse(double value) 335 { 336 volumeDiffuseField.setNumericValue(value); 337 } 338 339 public double getVolumeSpecular() 340 { 341 return volumeSpecularField.getNumericValue(); 342 } 343 344 public void setVolumeSpecular(double value) 345 { 346 volumeSpecularField.setNumericValue(value); 347 } 348 349 /** 350 * @see VtkImageVolume#getShade() 351 */ 352 public boolean getVolumeShading() 353 { 354 return shadingButton.isSelected(); 355 } 356 357 /** 358 * @see VtkImageVolume#setShade(boolean) 359 */ 360 public void setVolumeShading(boolean value) 361 { 362 if (shadingButton.isSelected() != value) 363 shadingButton.doClick(); 364 } 365 366 /** 367 * Add a SettingChange listener 368 */ 369 public void addSettingChangeListener(SettingChangeListener listener) 370 { 371 listenerList.add(SettingChangeListener.class, listener); 372 } 373 374 /** 375 * Remove a SettingChange listener 376 */ 377 public void removeSettingChangeListener(SettingChangeListener listener) 378 { 379 listenerList.remove(SettingChangeListener.class, listener); 380 } 381 382 public void fireSettingChange(Object source, String propertyName, Object oldValue, Object newValue) 383 { 384 if ((oldValue != null) && (newValue != null) && oldValue.equals(newValue)) 385 return; 386 387 final PropertyChangeEvent event = new PropertyChangeEvent(source, propertyName, oldValue, newValue); 388 final SettingChangeListener[] listeners = getListeners(SettingChangeListener.class); 389 390 for (int i = 0; i < listeners.length; i++) 391 listeners[i].settingChange(event); 392 } 393 394 @Override 395 public void colorChanged(ColorChooserButton source) 396 { 397 if (source == bgColorButton) 398 fireSettingChange(source, PROPERTY_BG_COLOR, null, source.getColor()); 399 } 400 401 @Override 402 public void actionPerformed(ActionEvent e) 403 { 404 final Object source = e.getSource(); 405 406 if (source == gpuMapperCheckBox) 407 fireSettingChange(source, PROPERTY_MAPPER, Boolean.valueOf(!gpuMapperCheckBox.isSelected()), 408 Boolean.valueOf(gpuMapperCheckBox.isSelected())); 409 else if (source == volumeBlendingComboBox) 410 fireSettingChange(source, PROPERTY_BLENDING, null, volumeBlendingComboBox.getSelectedItem()); 411 else if (source == volumeSampleComboBox) 412 fireSettingChange(source, PROPERTY_SAMPLE, Integer.valueOf(-1), 413 Integer.valueOf(volumeSampleComboBox.getSelectedIndex())); 414 else if (source == volumeInterpolationComboBox) 415 fireSettingChange(source, PROPERTY_INTERPOLATION, Integer.valueOf(-1), 416 Integer.valueOf(volumeInterpolationComboBox.getSelectedIndex())); 417 else if (source == shadingButton) 418 fireSettingChange(source, PROPERTY_SHADING, Integer.valueOf(-1), 419 Boolean.valueOf(shadingButton.isSelected())); 420 421 updateState(); 422 } 423 424 @Override 425 public void textChanged(IcyTextField source, boolean validate) 426 { 427 if (!validate) 428 return; 429 430 if (source == volumeAmbientField) 431 fireSettingChange(source, PROPERTY_AMBIENT, Double.valueOf(-1d), 432 Double.valueOf(volumeAmbientField.getNumericValue())); 433 else if (source == volumeDiffuseField) 434 fireSettingChange(source, PROPERTY_DIFFUSE, Double.valueOf(-1d), 435 Double.valueOf(volumeDiffuseField.getNumericValue())); 436 else if (source == volumeSpecularField) 437 fireSettingChange(source, PROPERTY_SPECULAR, Double.valueOf(-1d), 438 Double.valueOf(volumeSpecularField.getNumericValue())); 439 440 updateState(); 441 } 442 443 public static interface SettingChangeListener extends EventListener 444 { 445 public void settingChange(PropertyChangeEvent evt); 446 } 447}