1 /* 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.oracle.javafx.scenebuilder.kit.util.control.effectpicker; 33 34 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.CheckBoxControl; 35 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.EnumControl; 36 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.ImageControl; 37 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.DoubleTextFieldControl; 38 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.LightControl; 39 import com.oracle.javafx.scenebuilder.kit.util.control.effectpicker.editors.SliderControl; 40 import com.oracle.javafx.scenebuilder.kit.util.control.paintpicker.PaintPicker; 41 import com.oracle.javafx.scenebuilder.kit.util.control.paintpicker.PaintPicker.Mode; 42 import java.net.URL; 43 import javafx.beans.property.BooleanProperty; 44 import javafx.beans.property.ObjectProperty; 45 import javafx.beans.property.ReadOnlyIntegerProperty; 46 import javafx.beans.property.SimpleBooleanProperty; 47 import javafx.beans.property.SimpleIntegerProperty; 48 import javafx.beans.property.SimpleObjectProperty; 49 import javafx.beans.value.ChangeListener; 50 import javafx.beans.value.ObservableValue; 51 import javafx.fxml.FXML; 52 import javafx.scene.control.Slider; 53 import javafx.scene.control.ToggleButton; 54 import javafx.scene.control.ToggleGroup; 55 import javafx.scene.effect.Blend; 56 import javafx.scene.effect.BlendMode; 57 import javafx.scene.effect.Bloom; 58 import javafx.scene.effect.BlurType; 59 import javafx.scene.effect.BoxBlur; 60 import javafx.scene.effect.ColorAdjust; 61 import javafx.scene.effect.ColorInput; 62 import javafx.scene.effect.DisplacementMap; 63 import javafx.scene.effect.DropShadow; 64 import javafx.scene.effect.Effect; 65 import javafx.scene.effect.GaussianBlur; 66 import javafx.scene.effect.Glow; 67 import javafx.scene.effect.ImageInput; 68 import javafx.scene.effect.InnerShadow; 69 import javafx.scene.effect.Lighting; 70 import javafx.scene.effect.MotionBlur; 71 import javafx.scene.effect.PerspectiveTransform; 72 import javafx.scene.effect.Reflection; 73 import javafx.scene.effect.SepiaTone; 74 import javafx.scene.effect.Shadow; 75 import javafx.scene.image.Image; 76 import javafx.scene.image.ImageView; 77 import javafx.scene.layout.HBox; 78 import javafx.scene.layout.VBox; 79 import javafx.scene.paint.Color; 80 import javafx.scene.paint.Paint; 81 82 /** 83 * Controller class for the effects editor. 84 */ 85 public class EffectPickerController { 86 87 @FXML 88 private VBox root_vbox; 89 @FXML 90 private VBox props_vbox; 91 @FXML 92 private HBox effects_path_hbox; 93 94 private final ToggleGroup effectToggleGroup = new ToggleGroup(); 95 private final Image selectionChevronImage; 96 private EffectPicker.Delegate effectPickerDelegate; 97 private PaintPicker.Delegate paintPickerDelegate; 98 99 private final ObjectProperty<Effect> rootEffect = new SimpleObjectProperty<>(); 100 // The revision property is used when a change occurs on the root effect inputs 101 private final SimpleIntegerProperty revision = new SimpleIntegerProperty(); 102 private final BooleanProperty liveUpdate = new SimpleBooleanProperty(); 103 104 public EffectPickerController() { 105 // Initialize selection chevron image 106 final URL selectionChevronURL = EffectPickerController.class.getResource("images/selection-chevron.png"); //NOI18N 107 assert selectionChevronURL != null; 108 selectionChevronImage = new Image(selectionChevronURL.toExternalForm()); 109 } 110 111 public final ObjectProperty<Effect> rootEffectProperty() { 112 return rootEffect; 113 } 114 115 public final Effect getRootEffectProperty() { 116 return rootEffect.get(); 117 } 118 119 public final void setRootEffectProperty(Effect value) { 120 rootEffect.setValue(value); 121 } 122 123 public ReadOnlyIntegerProperty revisionProperty() { 124 return revision; 125 } 126 127 public final BooleanProperty liveUpdateProperty() { 128 return liveUpdate; 129 } 130 131 public boolean isLiveUpdate() { 132 return liveUpdate.get(); 133 } 134 135 public void setLiveUpdate(boolean value) { 136 liveUpdate.setValue(value); 137 } 138 139 public EffectPicker.Delegate getEffectPickerDelegate() { 140 return effectPickerDelegate; 141 } 142 143 void setEffectPickerDelegate(EffectPicker.Delegate delegate) { 144 this.effectPickerDelegate = delegate; 145 } 146 147 public PaintPicker.Delegate getPaintPickerDelegate() { 148 return paintPickerDelegate; 149 } 150 151 void setPaintPickerDelegate(PaintPicker.Delegate delegate) { 152 this.paintPickerDelegate = delegate; 153 } 154 155 /** 156 * Update the effect path items starting from the root effect path item. 157 */ 158 public void updateUI() { 159 effects_path_hbox.getChildren().clear(); 160 if (getRootEffectProperty() != null) { 161 final EffectPathItem rootEffectPathItem = makeEffectPathItem(getRootEffectProperty(), null); 162 assert rootEffectPathItem != null; 163 EffectPathItem epi = rootEffectPathItem; 164 while (epi != null) { 165 effects_path_hbox.getChildren().add(epi); 166 if (epi.getSelectedInputPathItem() != null) { 167 final ImageView img = new ImageView(selectionChevronImage); 168 effects_path_hbox.getChildren().add(img); 169 epi = epi.getSelectedInputPathItem(); 170 } else { 171 epi = null; 172 } 173 } 174 selectEffectPathItem(rootEffectPathItem); 175 } 176 } 177 178 /** 179 * Update the effect path items starting from the specified effect path item. 180 * 181 * @param effectPathItem 182 */ 183 public void updateUI(EffectPathItem effectPathItem) { 184 assert effectPathItem != null; 185 int index = effects_path_hbox.getChildren().indexOf(effectPathItem); 186 // Remove sub items if any 187 if (index + 1 < effects_path_hbox.getChildren().size()) { 188 effects_path_hbox.getChildren().remove(index + 1, effects_path_hbox.getChildren().size()); 189 } 190 // Add new sub items if any 191 EffectPathItem epi = effectPathItem.getSelectedInputPathItem(); 192 while (epi != null) { 193 effects_path_hbox.getChildren().add(epi); 194 if (epi.getSelectedInputPathItem() != null) { 195 final ImageView img = new ImageView(selectionChevronImage); 196 effects_path_hbox.getChildren().add(img); 197 epi = epi.getSelectedInputPathItem(); 198 } else { 199 epi = null; 200 } 201 } 202 } 203 204 public ToggleGroup getEffectToggleGroup() { 205 return effectToggleGroup; 206 } 207 208 public String getEffectPath() { 209 final EffectPathItem rootEffectPathItem = makeEffectPathItem(getRootEffectProperty(), null); 210 if (rootEffectPathItem == null) { 211 return "+"; //NOI18N 212 } else { 213 final StringBuilder sb = new StringBuilder(); 214 EffectPathItem epi = rootEffectPathItem; 215 while (epi != null) { 216 sb.append(epi.getSimpleName()); 217 if (epi.getSelectedInputPathItem() != null) { 218 sb.append(", "); //NOI18N 219 epi = epi.getSelectedInputPathItem(); 220 } else { 221 epi = null; 222 } 223 } 224 return sb.toString(); 225 } 226 } 227 228 @FXML 229 void initialize() { 230 assert root_vbox != null; 231 assert effects_path_hbox != null; 232 assert props_vbox != null; 233 } 234 235 public void incrementRevision() { 236 revision.set(revision.get() + 1); 237 } 238 239 private EffectPathItem makeEffectPathItem(Effect effect, EffectPathItem hostPathItem) { 240 final EffectPathItem epi; 241 if (effect == null) { 242 return null; 243 } 244 if (effect instanceof Blend) { 245 epi = makeBlendPathItem(effect, hostPathItem); 246 } else if (effect instanceof ColorInput) { 247 epi = makeColorInputPathItem(effect, hostPathItem); 248 } else if (effect instanceof ImageInput) { 249 epi = makeImageInputPathItem(effect, hostPathItem); 250 } else if (effect instanceof Lighting) { 251 epi = makeLightingPathItem(effect, hostPathItem); 252 } else { 253 epi = makeSingleInputPathItem(effect, hostPathItem); 254 } 255 return epi; 256 } 257 258 private EffectPathItem makeBlendPathItem(Effect effect, EffectPathItem hostPathItem) { 259 assert effect != null; 260 final BlendPathItem epi = new BlendPathItem(this, effect, hostPathItem); 261 final Effect topInput = epi.getTopInput(); 262 final EffectPathItem topInputPathItem 263 = topInput == null ? null : makeEffectPathItem(topInput, epi); 264 epi.setTopInputPathItem(topInputPathItem); 265 final Effect bottomInput = epi.getBottomInput(); 266 final EffectPathItem bottomInputPathItem 267 = bottomInput == null ? null : makeEffectPathItem(bottomInput, epi); 268 epi.setBottomInputPathItem(bottomInputPathItem); 269 return epi; 270 } 271 272 private EffectPathItem makeColorInputPathItem(Effect effect, EffectPathItem hostPathItem) { 273 assert effect != null; 274 final ColorInputPathItem epi = new ColorInputPathItem(this, effect, hostPathItem); 275 return epi; 276 } 277 278 private EffectPathItem makeImageInputPathItem(Effect effect, EffectPathItem hostPathItem) { 279 assert effect != null; 280 final ImageInputPathItem epi = new ImageInputPathItem(this, effect, hostPathItem); 281 return epi; 282 } 283 284 private EffectPathItem makeLightingPathItem(Effect effect, EffectPathItem hostPathItem) { 285 assert effect != null; 286 final LightingPathItem epi = new LightingPathItem(this, effect, hostPathItem); 287 final Effect bumpInput = epi.getBumpInput(); 288 final EffectPathItem bumpInputPathItem 289 = bumpInput == null ? null : makeEffectPathItem(bumpInput, epi); 290 epi.setBumpInputPathItem(bumpInputPathItem); 291 final Effect contentInput = epi.getContentInput(); 292 final EffectPathItem contentInputPathItem 293 = contentInput == null ? null : makeEffectPathItem(contentInput, epi); 294 epi.setContentInputPathItem(contentInputPathItem); 295 return epi; 296 } 297 298 private EffectPathItem makeSingleInputPathItem(Effect effect, EffectPathItem hostPathItem) { 299 assert effect != null; 300 final SingleInputPathItem epi = new SingleInputPathItem(this, effect, hostPathItem); 301 final Effect input = epi.getInput(); 302 final EffectPathItem inputPathItem 303 = input == null ? null : makeEffectPathItem(input, epi); 304 epi.setInputPathItem(inputPathItem); 305 return epi; 306 } 307 308 public void selectEffectPathItem(EffectPathItem epi) { 309 assert epi != null; 310 final ToggleButton tb = epi.getToggleButton(); 311 final Effect effect = epi.getValue(); 312 tb.setSelected(true); 313 props_vbox.getChildren().clear(); 314 if (effect != null) { 315 makeEffectUI(effect); 316 } 317 } 318 319 //////////////////////////////////////////////////////////////////////////// 320 //////////////////////////////// Effects UI //////////////////////////////// 321 //////////////////////////////////////////////////////////////////////////// 322 private void makeEffectUI(Effect effect) { 323 if (effect instanceof Blend) { 324 makeBlendUI(effect); 325 } else if (effect instanceof Bloom) { 326 makeBloomUI(effect); 327 } else if (effect instanceof BoxBlur) { 328 makeBoxBlurUI(effect); 329 } else if (effect instanceof ColorAdjust) { 330 makeColorAdjustUI(effect); 331 } else if (effect instanceof ColorInput) { 332 makeColorInputUI(effect); 333 } else if (effect instanceof DisplacementMap) { 334 makeDisplacementMapUI(effect); 335 } else if (effect instanceof DropShadow) { 336 makeDropShadowUI(effect); 337 } else if (effect instanceof GaussianBlur) { 338 makeGaussianBlurUI(effect); 339 } else if (effect instanceof Glow) { 340 makeGlowUI(effect); 341 } else if (effect instanceof ImageInput) { 342 makeImageInputUI(effect); 343 } else if (effect instanceof InnerShadow) { 344 makeInnerShadowUI(effect); 345 } else if (effect instanceof Lighting) { 346 makeLightingUI(effect); 347 } else if (effect instanceof MotionBlur) { 348 makeMotionBlurUI(effect); 349 } else if (effect instanceof PerspectiveTransform) { 350 makePerspectiveTransformUI(effect); 351 } else if (effect instanceof Reflection) { 352 makeReflectionUI(effect); 353 } else if (effect instanceof SepiaTone) { 354 makeSepiaToneUI(effect); 355 } else { 356 assert effect instanceof Shadow; 357 makeShadowUI(effect); 358 } 359 } 360 361 private void makeBlendUI(Effect effect) { 362 assert effect instanceof Blend; 363 final Blend blend = (Blend) effect; 364 final VBox vBox = new VBox(8.0); 365 366 final EnumControl<BlendMode> modeEditor = new EnumControl<>( 367 this, "mode", BlendMode.values(), blend.getMode()); //NOI18N 368 blend.modeProperty().bind(modeEditor.valueProperty()); 369 vBox.getChildren().add(modeEditor); 370 371 final SliderControl opacityEditor = new SliderControl( 372 this, "opacity", 0, 1.0, blend.getOpacity(), 0.1, false); //NOI18N 373 blend.opacityProperty().bind(opacityEditor.valueProperty()); 374 vBox.getChildren().add(opacityEditor); 375 376 props_vbox.getChildren().add(vBox); 377 } 378 379 private void makeBloomUI(Effect effect) { 380 assert effect instanceof Bloom; 381 final Bloom bloom = (Bloom) effect; 382 VBox vBox = new VBox(8.0); 383 384 final SliderControl thresholdEditor = new SliderControl( 385 this, "threshold", 0, 1.0, bloom.getThreshold(), 0.1, false); //NOI18N 386 bloom.thresholdProperty().bind(thresholdEditor.valueProperty()); 387 vBox.getChildren().add(thresholdEditor); 388 389 props_vbox.getChildren().add(vBox); 390 } 391 392 private void makeBoxBlurUI(Effect effect) { 393 assert effect instanceof BoxBlur; 394 final BoxBlur boxBlur = (BoxBlur) effect; 395 VBox vBox = new VBox(8.0); 396 397 final SliderControl widthEditor = new SliderControl( 398 this, "width", 0, 255.0, boxBlur.getWidth(), 1.0, false); //NOI18N 399 boxBlur.widthProperty().bind(widthEditor.valueProperty()); 400 vBox.getChildren().add(widthEditor); 401 402 final SliderControl heightEditor = new SliderControl( 403 this, "height", 0, 255.0, boxBlur.getHeight(), 1.0, false); //NOI18N 404 boxBlur.heightProperty().bind(heightEditor.valueProperty()); 405 vBox.getChildren().add(heightEditor); 406 407 final SliderControl iterationsEditor = new SliderControl( 408 this, "iterations", 0, 3.0, boxBlur.getIterations(), 1.0, true); //NOI18N 409 final Slider slider = iterationsEditor.getSlider(); 410 slider.setBlockIncrement(1.0); 411 slider.setMajorTickUnit(1.0); 412 slider.setMinorTickCount(0); 413 slider.setSnapToTicks(true); 414 slider.setShowTickMarks(true); 415 boxBlur.iterationsProperty().bind(iterationsEditor.valueProperty()); 416 vBox.getChildren().add(iterationsEditor); 417 418 props_vbox.getChildren().add(vBox); 419 } 420 421 private void makeColorAdjustUI(Effect effect) { 422 assert effect instanceof ColorAdjust; 423 final ColorAdjust colorAdjust = (ColorAdjust) effect; 424 VBox vBox = new VBox(8.0); 425 426 final SliderControl brightnessEditor = new SliderControl( 427 this, "brightness", -1.0, 1.0, colorAdjust.getBrightness(), 0.1, false); //NOI18N 428 colorAdjust.brightnessProperty().bind(brightnessEditor.valueProperty()); 429 vBox.getChildren().add(brightnessEditor); 430 431 final SliderControl contrastEditor = new SliderControl( 432 this, "contrast", -1.0, 1.0, colorAdjust.getContrast(), 0.1, false); //NOI18N 433 colorAdjust.contrastProperty().bind(contrastEditor.valueProperty()); 434 vBox.getChildren().add(contrastEditor); 435 436 final SliderControl hueEditor = new SliderControl( 437 this, "hue", -1.0, 1.0, colorAdjust.getHue(), 0.1, false); //NOI18N 438 colorAdjust.hueProperty().bind(hueEditor.valueProperty()); 439 vBox.getChildren().add(hueEditor); 440 441 final SliderControl saturationEditor = new SliderControl( 442 this, "saturation", -1.0, 1.0, colorAdjust.getSaturation(), 0.1, false); //NOI18N 443 colorAdjust.saturationProperty().bind(saturationEditor.valueProperty()); 444 vBox.getChildren().add(saturationEditor); 445 446 props_vbox.getChildren().add(vBox); 447 } 448 449 private void makeColorInputUI(Effect effect) { 450 assert effect instanceof ColorInput; 451 final ColorInput colorInput = (ColorInput) effect; 452 VBox vBox = new VBox(8.0); 453 454 final SliderControl widthEditor = new SliderControl( 455 this, "width", 0, 255.0, colorInput.getWidth(), 1.0, false); //NOI18N 456 colorInput.widthProperty().bind(widthEditor.valueProperty()); 457 vBox.getChildren().add(widthEditor); 458 459 final SliderControl heightEditor = new SliderControl( 460 this, "height", 0, 255.0, colorInput.getHeight(), 1.0, false); //NOI18N 461 colorInput.heightProperty().bind(heightEditor.valueProperty()); 462 vBox.getChildren().add(heightEditor); 463 464 final DoubleTextFieldControl xEditor = new DoubleTextFieldControl( 465 this, "x", -10.0, 10.0, colorInput.getX(), 1.0); //NOI18N 466 colorInput.xProperty().bind(xEditor.valueProperty()); 467 vBox.getChildren().add(xEditor); 468 469 final DoubleTextFieldControl yEditor = new DoubleTextFieldControl( 470 this, "y", -10.0, 10.0, colorInput.getY(), 1.0); //NOI18N 471 colorInput.yProperty().bind(yEditor.valueProperty()); 472 vBox.getChildren().add(yEditor); 473 474 final PaintPicker colorPicker = new PaintPicker(paintPickerDelegate); 475 colorPicker.setPaintProperty(colorInput.getPaint()); 476 colorPicker.paintProperty().addListener(new PaintChangeListener(this, colorInput)); 477 colorPicker.liveUpdateProperty().addListener(new PaintPickerLiveUpdateListener(colorPicker, this)); 478 vBox.getChildren().add(colorPicker); 479 480 props_vbox.getChildren().add(vBox); 481 } 482 483 private void makeDisplacementMapUI(Effect effect) { 484 assert effect instanceof DisplacementMap; 485 final DisplacementMap displacementMap = (DisplacementMap) effect; 486 VBox vBox = new VBox(8.0); 487 488 final DoubleTextFieldControl offsetXEditor = new DoubleTextFieldControl( 489 this, "offsetX", -10.0, 10.0, displacementMap.getOffsetX(), 1.0); //NOI18N 490 displacementMap.offsetXProperty().bind(offsetXEditor.valueProperty()); 491 vBox.getChildren().add(offsetXEditor); 492 493 final DoubleTextFieldControl offsetYEditor = new DoubleTextFieldControl( 494 this, "offsetY", -10.0, 10.0, displacementMap.getOffsetY(), 1.0); //NOI18N 495 displacementMap.offsetYProperty().bind(offsetYEditor.valueProperty()); 496 vBox.getChildren().add(offsetYEditor); 497 498 final DoubleTextFieldControl scaleXEditor = new DoubleTextFieldControl( 499 this, "scaleX", -10.0, 10.0, displacementMap.getScaleX(), 1.0); //NOI18N 500 displacementMap.scaleXProperty().bind(scaleXEditor.valueProperty()); 501 vBox.getChildren().add(scaleXEditor); 502 503 final DoubleTextFieldControl scaleYEditor = new DoubleTextFieldControl( 504 this, "scaleY", -10.0, 10.0, displacementMap.getScaleY(), 1.0); //NOI18N 505 displacementMap.scaleYProperty().bind(scaleYEditor.valueProperty()); 506 vBox.getChildren().add(scaleYEditor); 507 508 final CheckBoxControl wrapEditor = new CheckBoxControl( 509 this, "wrap", displacementMap.isWrap()); //NOI18N 510 displacementMap.wrapProperty().bind(wrapEditor.valueProperty()); 511 vBox.getChildren().add(wrapEditor); 512 513 props_vbox.getChildren().add(vBox); 514 } 515 516 private void makeDropShadowUI(Effect effect) { 517 assert effect instanceof DropShadow; 518 final DropShadow dropShadow = (DropShadow) effect; 519 VBox vBox = new VBox(8.0); 520 521 final EnumControl<BlurType> blurTypeEditor = new EnumControl<>( 522 this, "blurType", BlurType.values(), dropShadow.getBlurType()); //NOI18N 523 dropShadow.blurTypeProperty().bind(blurTypeEditor.valueProperty()); 524 vBox.getChildren().add(blurTypeEditor); 525 526 final SliderControl widthEditor = new SliderControl( 527 this, "width", 0, 255.0, dropShadow.getWidth(), 1.0, false); //NOI18N 528 dropShadow.widthProperty().bind(widthEditor.valueProperty()); 529 vBox.getChildren().add(widthEditor); 530 531 final SliderControl heightEditor = new SliderControl( 532 this, "height", 0, 255.0, dropShadow.getHeight(), 1.0, false); //NOI18N 533 dropShadow.heightProperty().bind(heightEditor.valueProperty()); 534 vBox.getChildren().add(heightEditor); 535 536 // setting radius equivalent to setting both width and height attributes to value of (2 * radius + 1) 537 final SliderControl radiusEditor = new SliderControl( 538 this, "radius", 0, 127.0, dropShadow.getRadius(), 1.0, false); //NOI18N 539 dropShadow.radiusProperty().bind(radiusEditor.valueProperty()); 540 vBox.getChildren().add(radiusEditor); 541 542 final DoubleTextFieldControl offsetXEditor = new DoubleTextFieldControl( 543 this, "offsetX", -10.0, 10.0, dropShadow.getOffsetX(), 1.0); //NOI18N 544 dropShadow.offsetXProperty().bind(offsetXEditor.valueProperty()); 545 vBox.getChildren().add(offsetXEditor); 546 547 final DoubleTextFieldControl offsetYEditor = new DoubleTextFieldControl( 548 this, "offsetY", -10.0, 10.0, dropShadow.getOffsetY(), 1.0); //NOI18N 549 dropShadow.offsetYProperty().bind(offsetYEditor.valueProperty()); 550 vBox.getChildren().add(offsetYEditor); 551 552 final SliderControl spreadEditor = new SliderControl( 553 this, "spread", 0, 1.0, dropShadow.getSpread(), 0.1, false); //NOI18N 554 dropShadow.spreadProperty().bind(spreadEditor.valueProperty()); 555 vBox.getChildren().add(spreadEditor); 556 557 final PaintPicker colorPicker = new PaintPicker(paintPickerDelegate, Mode.COLOR); 558 colorPicker.setPaintProperty(dropShadow.getColor()); 559 colorPicker.paintProperty().addListener(new ColorChangeListener(this, dropShadow)); 560 colorPicker.liveUpdateProperty().addListener(new PaintPickerLiveUpdateListener(colorPicker, this)); 561 vBox.getChildren().add(colorPicker); 562 563 props_vbox.getChildren().add(vBox); 564 } 565 566 private void makeGaussianBlurUI(Effect effect) { 567 assert effect instanceof GaussianBlur; 568 final GaussianBlur gaussianBlur = (GaussianBlur) effect; 569 VBox vBox = new VBox(8.0); 570 571 final SliderControl radiusEditor = new SliderControl( 572 this, "radius", 0, 63.0, gaussianBlur.getRadius(), 0.1, false); //NOI18N 573 gaussianBlur.radiusProperty().bind(radiusEditor.valueProperty()); 574 vBox.getChildren().add(radiusEditor); 575 576 props_vbox.getChildren().add(vBox); 577 } 578 579 private void makeGlowUI(Effect effect) { 580 assert effect instanceof Glow; 581 final Glow glow = (Glow) effect; 582 VBox vBox = new VBox(8.0); 583 584 final SliderControl levelEditor = new SliderControl( 585 this, "level", 0, 1.0, glow.getLevel(), 0.1, false); //NOI18N 586 glow.levelProperty().bind(levelEditor.valueProperty()); 587 vBox.getChildren().add(levelEditor); 588 589 props_vbox.getChildren().add(vBox); 590 } 591 592 private void makeImageInputUI(Effect effect) { 593 assert effect instanceof ImageInput; 594 final ImageInput imageInput = (ImageInput) effect; 595 VBox vBox = new VBox(8.0); 596 597 final DoubleTextFieldControl xEditor = new DoubleTextFieldControl( 598 this, "x", -10.0, 10.0, imageInput.getX(), 1.0); //NOI18N 599 imageInput.xProperty().bind(xEditor.valueProperty()); 600 vBox.getChildren().add(xEditor); 601 602 final DoubleTextFieldControl yEditor = new DoubleTextFieldControl( 603 this, "y", -10.0, 10.0, imageInput.getY(), 1.0); //NOI18N 604 imageInput.yProperty().bind(yEditor.valueProperty()); 605 vBox.getChildren().add(yEditor); 606 607 final ImageControl imageEditor = new ImageControl( 608 this, "source", imageInput.getSource()); //NOI18N 609 imageInput.sourceProperty().bind(imageEditor.valueProperty()); 610 vBox.getChildren().add(imageEditor); 611 612 props_vbox.getChildren().add(vBox); 613 } 614 615 private void makeInnerShadowUI(Effect effect) { 616 assert effect instanceof InnerShadow; 617 final InnerShadow innerShadow = (InnerShadow) effect; 618 VBox vBox = new VBox(8.0); 619 620 final EnumControl<BlurType> blurTypeEditor = new EnumControl<>( 621 this, "blurType", BlurType.values(), innerShadow.getBlurType()); //NOI18N 622 innerShadow.blurTypeProperty().bind(blurTypeEditor.valueProperty()); 623 vBox.getChildren().add(blurTypeEditor); 624 625 final SliderControl chokeEditor = new SliderControl( 626 this, "choke", 0, 1.0, innerShadow.getChoke(), 0.1, false); //NOI18N 627 innerShadow.chokeProperty().bind(chokeEditor.valueProperty()); 628 vBox.getChildren().add(chokeEditor); 629 630 final SliderControl widthEditor = new SliderControl( 631 this, "width", 0, 255.0, innerShadow.getWidth(), 1.0, false); //NOI18N 632 innerShadow.widthProperty().bind(widthEditor.valueProperty()); 633 vBox.getChildren().add(widthEditor); 634 635 final SliderControl heightEditor = new SliderControl( 636 this, "height", 0, 255.0, innerShadow.getHeight(), 1.0, false); //NOI18N 637 innerShadow.heightProperty().bind(heightEditor.valueProperty()); 638 vBox.getChildren().add(heightEditor); 639 640 // setting radius equivalent to setting both width and height attributes to value of (2 * radius + 1) 641 final SliderControl radiusEditor = new SliderControl( 642 this, "radius", 0, 127.0, innerShadow.getRadius(), 1.0, false); //NOI18N 643 innerShadow.radiusProperty().bind(radiusEditor.valueProperty()); 644 vBox.getChildren().add(radiusEditor); 645 646 final DoubleTextFieldControl offsetXEditor = new DoubleTextFieldControl( 647 this, "offsetX", -10.0, 10.0, innerShadow.getOffsetX(), 1.0); //NOI18N 648 innerShadow.offsetXProperty().bind(offsetXEditor.valueProperty()); 649 vBox.getChildren().add(offsetXEditor); 650 651 final DoubleTextFieldControl offsetYEditor = new DoubleTextFieldControl( 652 this, "offsetY", -10.0, 10.0, innerShadow.getOffsetY(), 1.0); //NOI18N 653 innerShadow.offsetYProperty().bind(offsetYEditor.valueProperty()); 654 vBox.getChildren().add(offsetYEditor); 655 656 final PaintPicker colorPicker = new PaintPicker(paintPickerDelegate, Mode.COLOR); 657 colorPicker.setPaintProperty(innerShadow.getColor()); 658 colorPicker.paintProperty().addListener(new ColorChangeListener(this, innerShadow)); 659 colorPicker.liveUpdateProperty().addListener(new PaintPickerLiveUpdateListener(colorPicker, this)); 660 vBox.getChildren().add(colorPicker); 661 662 props_vbox.getChildren().add(vBox); 663 } 664 665 private void makeLightingUI(Effect effect) { 666 assert effect instanceof Lighting; 667 final Lighting lighting = (Lighting) effect; 668 VBox vBox = new VBox(8.0); 669 670 final SliderControl diffuseConstantEditor = new SliderControl( 671 this, "diffuseConstant", 0, 2.0, lighting.getDiffuseConstant(), 1.0, false); //NOI18N 672 lighting.diffuseConstantProperty().bind(diffuseConstantEditor.valueProperty()); 673 vBox.getChildren().add(diffuseConstantEditor); 674 675 final SliderControl specularConstantEditor = new SliderControl( 676 this, "specularConstant", 0, 2.0, lighting.getSpecularConstant(), 1.0, false); //NOI18N 677 lighting.specularConstantProperty().bind(specularConstantEditor.valueProperty()); 678 vBox.getChildren().add(specularConstantEditor); 679 680 final SliderControl specularExponentEditor = new SliderControl( 681 this, "specularExponent", 0, 40.0, lighting.getSpecularExponent(), 1.0, false); //NOI18N 682 lighting.specularExponentProperty().bind(specularExponentEditor.valueProperty()); 683 vBox.getChildren().add(specularExponentEditor); 684 685 final SliderControl surfaceScaleEditor = new SliderControl( 686 this, "surfaceScale", 0, 10.0, lighting.getSurfaceScale(), 1.0, false); //NOI18N 687 lighting.surfaceScaleProperty().bind(surfaceScaleEditor.valueProperty()); 688 vBox.getChildren().add(surfaceScaleEditor); 689 690 final LightControl lightControl = new LightControl( 691 this, "light", lighting.getLight()); //NOI18N 692 lighting.lightProperty().bind(lightControl.valueProperty()); 693 lightControl.liveUpdateProperty().addListener(new LightControlLiveUpdateListener(lightControl, this)); 694 vBox.getChildren().add(lightControl); 695 696 props_vbox.getChildren().add(vBox); 697 } 698 699 private void makeMotionBlurUI(Effect effect) { 700 assert effect instanceof MotionBlur; 701 final MotionBlur motionBlur = (MotionBlur) effect; 702 VBox vBox = new VBox(8.0); 703 704 final SliderControl angleEditor = new SliderControl( 705 this, "angle", 0, 360.0, motionBlur.getAngle(), 1.0, false); //NOI18N 706 motionBlur.angleProperty().bind(angleEditor.valueProperty()); 707 vBox.getChildren().add(angleEditor); 708 709 final SliderControl radiusEditor = new SliderControl( 710 this, "radius", 0, 63.0, motionBlur.getRadius(), 1.0, false); //NOI18N 711 motionBlur.radiusProperty().bind(radiusEditor.valueProperty()); 712 vBox.getChildren().add(radiusEditor); 713 714 props_vbox.getChildren().add(vBox); 715 } 716 717 private void makePerspectiveTransformUI(Effect effect) { 718 assert effect instanceof PerspectiveTransform; 719 final PerspectiveTransform perspectiveTransform = (PerspectiveTransform) effect; 720 VBox vBox = new VBox(8.0); 721 722 final DoubleTextFieldControl llxEditor = new DoubleTextFieldControl( 723 this, "llx", -10.0, 10.0, perspectiveTransform.getLlx(), 1.0); //NOI18N 724 perspectiveTransform.llxProperty().bind(llxEditor.valueProperty()); 725 vBox.getChildren().add(llxEditor); 726 727 final DoubleTextFieldControl llyEditor = new DoubleTextFieldControl( 728 this, "lly", -10.0, 10.0, perspectiveTransform.getLly(), 1.0); //NOI18N 729 perspectiveTransform.llyProperty().bind(llyEditor.valueProperty()); 730 vBox.getChildren().add(llyEditor); 731 732 final DoubleTextFieldControl lrxEditor = new DoubleTextFieldControl( 733 this, "lrx", -10.0, 10.0, perspectiveTransform.getLrx(), 1.0); //NOI18N 734 perspectiveTransform.lrxProperty().bind(lrxEditor.valueProperty()); 735 vBox.getChildren().add(lrxEditor); 736 737 final DoubleTextFieldControl lryEditor = new DoubleTextFieldControl( 738 this, "lry", -10.0, 10.0, perspectiveTransform.getLry(), 1.0); //NOI18N 739 perspectiveTransform.lryProperty().bind(lryEditor.valueProperty()); 740 vBox.getChildren().add(lryEditor); 741 742 final DoubleTextFieldControl ulxEditor = new DoubleTextFieldControl( 743 this, "ulx", -10.0, 10.0, perspectiveTransform.getUlx(), 1.0); //NOI18N 744 perspectiveTransform.ulxProperty().bind(ulxEditor.valueProperty()); 745 vBox.getChildren().add(ulxEditor); 746 747 final DoubleTextFieldControl ulyEditor = new DoubleTextFieldControl( 748 this, "uly", -10.0, 10.0, perspectiveTransform.getUly(), 1.0); //NOI18N 749 perspectiveTransform.ulyProperty().bind(ulyEditor.valueProperty()); 750 vBox.getChildren().add(ulyEditor); 751 752 final DoubleTextFieldControl urxEditor = new DoubleTextFieldControl( 753 this, "urx", -10.0, 10.0, perspectiveTransform.getUrx(), 1.0); //NOI18N 754 perspectiveTransform.urxProperty().bind(urxEditor.valueProperty()); 755 vBox.getChildren().add(urxEditor); 756 757 final DoubleTextFieldControl uryEditor = new DoubleTextFieldControl( 758 this, "ury", -10.0, 10.0, perspectiveTransform.getUry(), 1.0); //NOI18N 759 perspectiveTransform.uryProperty().bind(uryEditor.valueProperty()); 760 vBox.getChildren().add(uryEditor); 761 762 props_vbox.getChildren().add(vBox); 763 } 764 765 private void makeReflectionUI(Effect effect) { 766 assert effect instanceof Reflection; 767 final Reflection reflection = (Reflection) effect; 768 VBox vBox = new VBox(8.0); 769 770 final SliderControl bottomOpacityEditor = new SliderControl( 771 this, "bottomOpacity", 0, 1.0, reflection.getBottomOpacity(), 0.1, false); //NOI18N 772 reflection.bottomOpacityProperty().bind(bottomOpacityEditor.valueProperty()); 773 vBox.getChildren().add(bottomOpacityEditor); 774 775 final SliderControl topOpacityEditor = new SliderControl( 776 this, "topOpacity", 0, 1.0, reflection.getTopOpacity(), 0.1, false); //NOI18N 777 reflection.topOpacityProperty().bind(topOpacityEditor.valueProperty()); 778 vBox.getChildren().add(topOpacityEditor); 779 780 final DoubleTextFieldControl topOffsetEditor = new DoubleTextFieldControl( 781 this, "topOffset", -10.0, 10.0, reflection.getTopOffset(), 1.0); //NOI18N 782 reflection.topOffsetProperty().bind(topOffsetEditor.valueProperty()); 783 vBox.getChildren().add(topOffsetEditor); 784 785 final SliderControl fractionEditor = new SliderControl( 786 this, "fraction", 0, 1.0, reflection.getFraction(), 0.1, false); //NOI18N 787 reflection.fractionProperty().bind(fractionEditor.valueProperty()); 788 vBox.getChildren().add(fractionEditor); 789 790 props_vbox.getChildren().add(vBox); 791 } 792 793 private void makeSepiaToneUI(Effect effect) { 794 assert effect instanceof SepiaTone; 795 final SepiaTone sepiaTone = (SepiaTone) effect; 796 VBox vBox = new VBox(8.0); 797 798 final SliderControl levelEditor = new SliderControl( 799 this, "level", 0, 1.0, sepiaTone.getLevel(), 0.1, false); //NOI18N 800 sepiaTone.levelProperty().bind(levelEditor.valueProperty()); 801 vBox.getChildren().add(levelEditor); 802 803 props_vbox.getChildren().add(vBox); 804 } 805 806 private void makeShadowUI(Effect effect) { 807 assert effect instanceof Shadow; 808 final Shadow shadow = (Shadow) effect; 809 VBox vBox = new VBox(8.0); 810 811 final EnumControl<BlurType> blurTypeEditor = new EnumControl<>( 812 this, "blurType", BlurType.values(), shadow.getBlurType()); //NOI18N 813 shadow.blurTypeProperty().bind(blurTypeEditor.valueProperty()); 814 vBox.getChildren().add(blurTypeEditor); 815 816 final SliderControl widthEditor = new SliderControl( 817 this, "width", 0, 255.0, shadow.getWidth(), 1.0, false); //NOI18N 818 shadow.widthProperty().bind(widthEditor.valueProperty()); 819 vBox.getChildren().add(widthEditor); 820 821 final SliderControl heightEditor = new SliderControl( 822 this, "height", 0, 255.0, shadow.getHeight(), 1.0, false); //NOI18N 823 shadow.heightProperty().bind(heightEditor.valueProperty()); 824 vBox.getChildren().add(heightEditor); 825 826 // setting radius equivalent to setting both width and height attributes to value of (2 * radius + 1) 827 final SliderControl radiusEditor = new SliderControl( 828 this, "radius", 0, 127.0, shadow.getRadius(), 1.0, false); //NOI18N 829 shadow.radiusProperty().bind(radiusEditor.valueProperty()); 830 vBox.getChildren().add(radiusEditor); 831 832 final PaintPicker colorPicker = new PaintPicker(paintPickerDelegate, Mode.COLOR); 833 colorPicker.setPaintProperty(shadow.getColor()); 834 colorPicker.paintProperty().addListener(new ColorChangeListener(this, shadow)); 835 colorPicker.liveUpdateProperty().addListener(new PaintPickerLiveUpdateListener(colorPicker, this)); 836 vBox.getChildren().add(colorPicker); 837 838 props_vbox.getChildren().add(vBox); 839 } 840 841 /** 842 * ************************************************************************* 843 * Static inner class 844 * ************************************************************************* 845 */ 846 private static class PaintPickerLiveUpdateListener implements ChangeListener<Boolean> { 847 848 private final PaintPicker paintPicker; 849 private final EffectPickerController effectPickerController; 850 851 public PaintPickerLiveUpdateListener( 852 PaintPicker paintPicker, 853 EffectPickerController effectPickerController) { 854 this.paintPicker = paintPicker; 855 this.effectPickerController = effectPickerController; 856 } 857 858 @Override 859 public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) { 860 effectPickerController.setLiveUpdate(paintPicker.isLiveUpdate()); 861 } 862 } 863 864 private static class LightControlLiveUpdateListener implements ChangeListener<Boolean> { 865 866 private final LightControl lightControl; 867 private final EffectPickerController effectPickerController; 868 869 public LightControlLiveUpdateListener( 870 LightControl lightControl, 871 EffectPickerController effectPickerController) { 872 this.lightControl = lightControl; 873 this.effectPickerController = effectPickerController; 874 } 875 876 @Override 877 public void changed(ObservableValue<? extends Boolean> ov, Boolean oldValue, Boolean newValue) { 878 effectPickerController.setLiveUpdate(lightControl.isLiveUpdate()); 879 } 880 } 881 882 private static class ColorChangeListener implements ChangeListener<Paint> { 883 884 private final EffectPickerController effectPickerController; 885 private final Effect effect; 886 887 public ColorChangeListener(EffectPickerController effectPickerController, Effect effect) { 888 assert effect instanceof DropShadow 889 || effect instanceof InnerShadow 890 || effect instanceof Shadow; 891 this.effectPickerController = effectPickerController; 892 this.effect = effect; 893 } 894 895 @Override 896 public void changed(ObservableValue<? extends Paint> ov, Paint oldValue, Paint newValue) { 897 assert newValue instanceof Color; 898 final Color color = (Color) newValue; 899 if (effect instanceof DropShadow) { 900 ((DropShadow) effect).setColor(color); 901 } else if (effect instanceof InnerShadow) { 902 ((InnerShadow) effect).setColor(color); 903 } else { 904 assert effect instanceof Shadow; 905 ((Shadow) effect).setColor(color); 906 } 907 // Then notify the controller a change occured 908 effectPickerController.incrementRevision(); 909 } 910 } 911 912 private static class PaintChangeListener implements ChangeListener<Paint> { 913 914 private final EffectPickerController effectPickerController; 915 private final ColorInput colorInput; 916 917 public PaintChangeListener(EffectPickerController effectPickerController, ColorInput colorInput) { 918 this.effectPickerController = effectPickerController; 919 this.colorInput = colorInput; 920 } 921 922 @Override 923 public void changed(ObservableValue<? extends Paint> ov, Paint oldValue, Paint newValue) { 924 colorInput.setPaint(newValue); 925 // Then notify the controller a change occured 926 effectPickerController.incrementRevision(); 927 } 928 } 929 }