1 /* 2 * ImportedFurnitureWizardStepsController.java 4 juil. 07 3 * 4 * Sweet Home 3D, Copyright (c) 2007 Emmanuel PUYBARET / eTeks <info@eteks.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 package com.eteks.sweethome3d.viewcontroller; 21 22 import java.beans.PropertyChangeEvent; 23 import java.beans.PropertyChangeListener; 24 import java.beans.PropertyChangeSupport; 25 import java.net.URL; 26 import java.util.Arrays; 27 import java.util.List; 28 29 import javax.swing.undo.CannotRedoException; 30 import javax.swing.undo.CannotUndoException; 31 import javax.swing.undo.UndoableEdit; 32 import javax.swing.undo.UndoableEditSupport; 33 34 import com.eteks.sweethome3d.model.CatalogDoorOrWindow; 35 import com.eteks.sweethome3d.model.CatalogPieceOfFurniture; 36 import com.eteks.sweethome3d.model.Content; 37 import com.eteks.sweethome3d.model.FurnitureCatalog; 38 import com.eteks.sweethome3d.model.FurnitureCategory; 39 import com.eteks.sweethome3d.model.Home; 40 import com.eteks.sweethome3d.model.HomePieceOfFurniture; 41 import com.eteks.sweethome3d.model.Sash; 42 import com.eteks.sweethome3d.model.Selectable; 43 import com.eteks.sweethome3d.model.UserPreferences; 44 45 /** 46 * Wizard controller to manage furniture importation. 47 * @author Emmanuel Puybaret 48 */ 49 public class ImportedFurnitureWizardController extends WizardController 50 implements Controller { 51 public enum Property {STEP, NAME, CREATOR, MODEL, WIDTH, DEPTH, HEIGHT, ELEVATION, MOVABLE, 52 DOOR_OR_WINDOW, COLOR, CATEGORY, BACK_FACE_SHOWN, MODEL_SIZE, MODEL_ROTATION, STAIRCASE_CUT_OUT_SHAPE, 53 ICON_YAW, PROPORTIONAL} 54 55 public enum Step {MODEL, ROTATION, ATTRIBUTES, ICON}; 56 57 private final Home home; 58 private final CatalogPieceOfFurniture piece; 59 private final String modelName; 60 private final UserPreferences preferences; 61 private final FurnitureController furnitureController; 62 private final ContentManager contentManager; 63 private final UndoableEditSupport undoSupport; 64 private final PropertyChangeSupport propertyChangeSupport; 65 66 private final ImportedFurnitureWizardStepState furnitureModelStepState; 67 private final ImportedFurnitureWizardStepState furnitureOrientationStepState; 68 private final ImportedFurnitureWizardStepState furnitureAttributesStepState; 69 private final ImportedFurnitureWizardStepState furnitureIconStepState; 70 private ImportedFurnitureWizardStepsView stepsView; 71 72 private Step step; 73 private String name; 74 private String creator; 75 private Content model; 76 private float width; 77 private float proportionalWidth; 78 private float depth; 79 private float proportionalDepth; 80 private float height; 81 private float proportionalHeight; 82 private float elevation; 83 private boolean movable; 84 private boolean doorOrWindow; 85 private String staircaseCutOutShape; 86 private Integer color; 87 private FurnitureCategory category; 88 private boolean backFaceShown; 89 private long modelSize; 90 private float [][] modelRotation; 91 private float iconYaw; 92 private boolean proportional; 93 private final ViewFactory viewFactory; 94 95 /** 96 * Creates a controller that edits a new catalog piece of furniture. 97 */ ImportedFurnitureWizardController(UserPreferences preferences, ViewFactory viewFactory, ContentManager contentManager)98 public ImportedFurnitureWizardController(UserPreferences preferences, 99 ViewFactory viewFactory, 100 ContentManager contentManager) { 101 this(null, null, null, preferences, null, viewFactory, contentManager, null); 102 } 103 104 /** 105 * Creates a controller that edits a new catalog piece of furniture with a given 106 * <code>modelName</code>. 107 */ ImportedFurnitureWizardController(String modelName, UserPreferences preferences, ViewFactory viewFactory, ContentManager contentManager)108 public ImportedFurnitureWizardController(String modelName, 109 UserPreferences preferences, 110 ViewFactory viewFactory, 111 ContentManager contentManager) { 112 this(null, null, modelName, preferences, null, viewFactory, contentManager, null); 113 } 114 115 /** 116 * Creates a controller that edits <code>piece</code> values. 117 */ ImportedFurnitureWizardController(CatalogPieceOfFurniture piece, UserPreferences preferences, ViewFactory viewFactory, ContentManager contentManager)118 public ImportedFurnitureWizardController(CatalogPieceOfFurniture piece, 119 UserPreferences preferences, 120 ViewFactory viewFactory, 121 ContentManager contentManager) { 122 this(null, piece, null, preferences, null, viewFactory, contentManager, null); 123 } 124 125 /** 126 * Creates a controller that edits a new imported home piece of furniture. 127 */ ImportedFurnitureWizardController(Home home, UserPreferences preferences, FurnitureController furnitureController, ViewFactory viewFactory, ContentManager contentManager, UndoableEditSupport undoSupport)128 public ImportedFurnitureWizardController(Home home, 129 UserPreferences preferences, 130 FurnitureController furnitureController, 131 ViewFactory viewFactory, 132 ContentManager contentManager, 133 UndoableEditSupport undoSupport) { 134 this(home, null, null, preferences, furnitureController, viewFactory, contentManager, undoSupport); 135 } 136 137 /** 138 * Creates a controller that edits a new imported home piece of furniture 139 * with a given <code>modelName</code>. 140 */ ImportedFurnitureWizardController(Home home, String modelName, UserPreferences preferences, FurnitureController furnitureController, ViewFactory viewFactory, ContentManager contentManager, UndoableEditSupport undoSupport)141 public ImportedFurnitureWizardController(Home home, 142 String modelName, 143 UserPreferences preferences, 144 FurnitureController furnitureController, 145 ViewFactory viewFactory, 146 ContentManager contentManager, 147 UndoableEditSupport undoSupport) { 148 this(home, null, modelName, preferences, furnitureController, viewFactory, contentManager, undoSupport); 149 } 150 151 /** 152 * Creates a controller that edits <code>piece</code> values. 153 */ ImportedFurnitureWizardController(Home home, CatalogPieceOfFurniture piece, String modelName, UserPreferences preferences, FurnitureController furnitureController, ViewFactory viewFactory, ContentManager contentManager, UndoableEditSupport undoSupport)154 private ImportedFurnitureWizardController(Home home, 155 CatalogPieceOfFurniture piece, 156 String modelName, 157 UserPreferences preferences, 158 FurnitureController furnitureController, 159 ViewFactory viewFactory, 160 ContentManager contentManager, 161 UndoableEditSupport undoSupport) { 162 super(preferences, viewFactory); 163 this.home = home; 164 this.piece = piece; 165 this.modelName = modelName; 166 this.preferences = preferences; 167 this.furnitureController = furnitureController; 168 this.viewFactory = viewFactory; 169 this.undoSupport = undoSupport; 170 this.contentManager = contentManager; 171 this.propertyChangeSupport = new PropertyChangeSupport(this); 172 setTitle(this.preferences.getLocalizedString(ImportedFurnitureWizardController.class, 173 piece == null 174 ? "importFurnitureWizard.title" 175 : "modifyFurnitureWizard.title")); 176 // Initialize states 177 this.furnitureModelStepState = new FurnitureModelStepState(); 178 this.furnitureOrientationStepState = new FurnitureOrientationStepState(); 179 this.furnitureAttributesStepState = new FurnitureAttributesStepState(); 180 this.furnitureIconStepState = new FurnitureIconStepState(); 181 setStepState(this.furnitureModelStepState); 182 } 183 184 /** 185 * Imports piece in catalog and/or home and posts an undoable operation. 186 */ 187 @Override finish()188 public void finish() { 189 CatalogPieceOfFurniture newPiece; 190 if (isDoorOrWindow()) { 191 newPiece = new CatalogDoorOrWindow(getName(), getIcon(), getModel(), 192 getWidth(), getDepth(), getHeight(), getElevation(), 193 isMovable(), 1, 0, new Sash [0], getColor(), 194 getModelRotation(), isBackFaceShown(), getModelSize(), getCreator(), 195 getIconYaw(), isProportional()); 196 } else { 197 newPiece = new CatalogPieceOfFurniture(getName(), getIcon(), getModel(), getWidth(), 198 getDepth(), getHeight(), getElevation(), isMovable(), 199 getStaircaseCutOutShape(), getColor(), 200 getModelRotation(), isBackFaceShown(), getModelSize(), getCreator(), 201 getIconYaw(), isProportional()); 202 } 203 204 if (this.home != null) { 205 // Add new piece to home 206 addPieceOfFurniture(this.furnitureController.createHomePieceOfFurniture(newPiece)); 207 } 208 // Remove the edited piece from catalog 209 FurnitureCatalog catalog = this.preferences.getFurnitureCatalog(); 210 if (this.piece != null) { 211 catalog.delete(this.piece); 212 } 213 // If a category exists, add new piece to catalog 214 if (this.category != null) { 215 catalog.add(this.category, newPiece); 216 } 217 } 218 219 /** 220 * Controls new piece added to home. 221 * Once added the furniture will be selected in view 222 * and undo support will receive a new undoable edit. 223 * @param piece the piece of furniture to add. 224 */ addPieceOfFurniture(HomePieceOfFurniture piece)225 public void addPieceOfFurniture(HomePieceOfFurniture piece) { 226 boolean basePlanLocked = this.home.isBasePlanLocked(); 227 boolean allLevelsSelection = this.home.isAllLevelsSelection(); 228 List<Selectable> oldSelection = this.home.getSelectedItems(); 229 // Get index of the piece added to home 230 int pieceIndex = this.home.getFurniture().size(); 231 232 this.home.addPieceOfFurniture(piece, pieceIndex); 233 this.home.setSelectedItems(Arrays.asList(piece)); 234 if (!piece.isMovable() && basePlanLocked) { 235 this.home.setBasePlanLocked(false); 236 } 237 this.home.setAllLevelsSelection(false); 238 if (this.undoSupport != null) { 239 UndoableEdit undoableEdit = new PieceOfFurnitureImportationUndoableEdit( 240 this.home, this.preferences, oldSelection.toArray(new Selectable [oldSelection.size()]), 241 basePlanLocked, allLevelsSelection, piece, pieceIndex); 242 this.undoSupport.postEdit(undoableEdit); 243 } 244 } 245 246 /** 247 * Undoable edit for piece importation. This class isn't anonymous to avoid 248 * being bound to controller and its view. 249 */ 250 private static class PieceOfFurnitureImportationUndoableEdit extends LocalizedUndoableEdit { 251 private final Home home; 252 private final Selectable [] oldSelection; 253 private final boolean oldBasePlanLocked; 254 private final boolean oldAllLevelsSelection; 255 private final HomePieceOfFurniture piece; 256 private final int pieceIndex; 257 PieceOfFurnitureImportationUndoableEdit(Home home, UserPreferences preferences, Selectable [] oldSelection, boolean oldBasePlanLocked, boolean oldAllLevelsSelection, HomePieceOfFurniture piece, int pieceIndex)258 private PieceOfFurnitureImportationUndoableEdit(Home home, 259 UserPreferences preferences, 260 Selectable [] oldSelection, 261 boolean oldBasePlanLocked, 262 boolean oldAllLevelsSelection, 263 HomePieceOfFurniture piece, 264 int pieceIndex) { 265 super(preferences, ImportedFurnitureWizardController.class, "undoImportFurnitureName"); 266 this.home = home; 267 this.oldSelection = oldSelection; 268 this.oldBasePlanLocked = oldBasePlanLocked; 269 this.oldAllLevelsSelection = oldAllLevelsSelection; 270 this.piece = piece; 271 this.pieceIndex = pieceIndex; 272 } 273 274 @Override undo()275 public void undo() throws CannotUndoException { 276 super.undo(); 277 this.home.deletePieceOfFurniture(this.piece); 278 this.home.setSelectedItems(Arrays.asList(this.oldSelection)); 279 this.home.setAllLevelsSelection(this.oldAllLevelsSelection); 280 this.home.setBasePlanLocked(this.oldBasePlanLocked); 281 } 282 283 @Override redo()284 public void redo() throws CannotRedoException { 285 super.redo(); 286 this.home.addPieceOfFurniture(this.piece, this.pieceIndex); 287 this.home.setSelectedItems(Arrays.asList(this.piece)); 288 if (!piece.isMovable() && this.oldBasePlanLocked) { 289 this.home.setBasePlanLocked(false); 290 } 291 this.home.setAllLevelsSelection(false); 292 } 293 } 294 295 /** 296 * Returns the content manager of this controller. 297 */ getContentManager()298 public ContentManager getContentManager() { 299 return this.contentManager; 300 } 301 302 /** 303 * Returns the current step state. 304 */ 305 @Override getStepState()306 protected ImportedFurnitureWizardStepState getStepState() { 307 return (ImportedFurnitureWizardStepState)super.getStepState(); 308 } 309 310 /** 311 * Returns the furniture choice step state. 312 */ getFurnitureModelStepState()313 protected ImportedFurnitureWizardStepState getFurnitureModelStepState() { 314 return this.furnitureModelStepState; 315 } 316 317 /** 318 * Returns the furniture orientation step state. 319 */ getFurnitureOrientationStepState()320 protected ImportedFurnitureWizardStepState getFurnitureOrientationStepState() { 321 return this.furnitureOrientationStepState; 322 } 323 324 /** 325 * Returns the furniture attributes step state. 326 */ getFurnitureAttributesStepState()327 protected ImportedFurnitureWizardStepState getFurnitureAttributesStepState() { 328 return this.furnitureAttributesStepState; 329 } 330 331 /** 332 * Returns the furniture icon step state. 333 */ getFurnitureIconStepState()334 protected ImportedFurnitureWizardStepState getFurnitureIconStepState() { 335 return this.furnitureIconStepState; 336 } 337 338 /** 339 * Returns the unique wizard view used for all steps. 340 */ getStepsView()341 protected ImportedFurnitureWizardStepsView getStepsView() { 342 // Create view lazily only once it's needed 343 if (this.stepsView == null) { 344 this.stepsView = this.viewFactory.createImportedFurnitureWizardStepsView( 345 this.piece, this.modelName, this.home != null, this.preferences, this); 346 } 347 return this.stepsView; 348 } 349 350 /** 351 * Switch in the wizard view to the given <code>step</code>. 352 */ setStep(Step step)353 protected void setStep(Step step) { 354 if (step != this.step) { 355 Step oldStep = this.step; 356 this.step = step; 357 this.propertyChangeSupport.firePropertyChange(Property.STEP.name(), oldStep, step); 358 } 359 } 360 361 /** 362 * Returns the current step in wizard view. 363 */ getStep()364 public Step getStep() { 365 return this.step; 366 } 367 368 /** 369 * Adds the property change <code>listener</code> in parameter to this controller. 370 */ addPropertyChangeListener(Property property, PropertyChangeListener listener)371 public void addPropertyChangeListener(Property property, PropertyChangeListener listener) { 372 this.propertyChangeSupport.addPropertyChangeListener(property.name(), listener); 373 } 374 375 /** 376 * Removes the property change <code>listener</code> in parameter from this controller. 377 */ removePropertyChangeListener(Property property, PropertyChangeListener listener)378 public void removePropertyChangeListener(Property property, PropertyChangeListener listener) { 379 this.propertyChangeSupport.removePropertyChangeListener(property.name(), listener); 380 } 381 382 /** 383 * Returns the model content of the imported piece. 384 */ getModel()385 public Content getModel() { 386 return this.model; 387 } 388 389 /** 390 * Sets the model content of the imported piece. 391 */ setModel(Content model)392 public void setModel(Content model) { 393 if (model != this.model) { 394 Content oldModel = this.model; 395 this.model = model; 396 this.propertyChangeSupport.firePropertyChange(Property.MODEL.name(), oldModel, model); 397 } 398 } 399 400 /** 401 * Returns <code>true</code> if imported piece back face should be shown. 402 */ isBackFaceShown()403 public boolean isBackFaceShown() { 404 return this.backFaceShown; 405 } 406 407 /** 408 * Sets whether imported piece back face should be shown. 409 */ setBackFaceShown(boolean backFaceShown)410 public void setBackFaceShown(boolean backFaceShown) { 411 if (backFaceShown != this.backFaceShown) { 412 this.backFaceShown = backFaceShown; 413 this.propertyChangeSupport.firePropertyChange(Property.BACK_FACE_SHOWN.name(), !backFaceShown, backFaceShown); 414 } 415 } 416 417 /** 418 * Returns the model size of the imported piece. 419 */ getModelSize()420 public long getModelSize() { 421 return this.modelSize; 422 } 423 424 /** 425 * Sets the model size of the content of the imported piece. 426 */ setModelSize(long modelSize)427 public void setModelSize(long modelSize) { 428 if (modelSize != this.modelSize) { 429 long oldModelSize = this.modelSize; 430 this.modelSize = modelSize; 431 this.propertyChangeSupport.firePropertyChange(Property.MODEL_SIZE.name(), oldModelSize, modelSize); 432 } 433 } 434 435 /** 436 * Returns the pitch angle of the imported piece model. 437 */ getModelRotation()438 public float [][] getModelRotation() { 439 return this.modelRotation; 440 } 441 442 /** 443 * Sets the orientation pitch angle of the imported piece model. 444 */ setModelRotation(float [][] modelRotation)445 public void setModelRotation(float [][] modelRotation) { 446 if (modelRotation != this.modelRotation) { 447 float [][] oldModelRotation = this.modelRotation; 448 this.modelRotation = modelRotation; 449 this.propertyChangeSupport.firePropertyChange(Property.MODEL_ROTATION.name(), oldModelRotation, modelRotation); 450 } 451 } 452 453 /** 454 * Returns the name of the imported piece. 455 */ getName()456 public String getName() { 457 return this.name; 458 } 459 460 /** 461 * Sets the name of the imported piece. 462 */ setName(String name)463 public void setName(String name) { 464 if (name != this.name) { 465 String oldName = this.name; 466 this.name = name; 467 if (this.propertyChangeSupport != null) { 468 this.propertyChangeSupport.firePropertyChange(Property.NAME.name(), oldName, name); 469 } 470 } 471 } 472 473 /** 474 * Returns the creator of the imported piece. 475 * @since 5.5 476 */ getCreator()477 public String getCreator() { 478 return this.creator; 479 } 480 481 /** 482 * Sets the creator of the imported piece. 483 * @since 5.5 484 */ setCreator(String creator)485 public void setCreator(String creator) { 486 if (creator != this.creator) { 487 String oldCreator = this.creator; 488 this.creator = creator; 489 if (this.propertyChangeSupport != null) { 490 this.propertyChangeSupport.firePropertyChange(Property.CREATOR.name(), oldCreator, creator); 491 } 492 } 493 } 494 495 /** 496 * Returns the width. 497 */ getWidth()498 public float getWidth() { 499 return this.width; 500 } 501 502 /** 503 * Sets the width of the imported piece. 504 */ setWidth(float width)505 public void setWidth(float width) { 506 setWidth(width, false); 507 } 508 509 /** 510 * Sets the width of the imported piece. 511 */ setWidth(float width, boolean keepProportionalWidthUnchanged)512 private void setWidth(float width, boolean keepProportionalWidthUnchanged) { 513 float adjustedWidth = Math.max(width, 0.001f); 514 if (adjustedWidth == width || !keepProportionalWidthUnchanged) { 515 this.proportionalWidth = width; 516 } 517 if (adjustedWidth != this.width) { 518 float oldWidth = this.width; 519 this.width = adjustedWidth; 520 this.propertyChangeSupport.firePropertyChange(Property.WIDTH.name(), oldWidth, adjustedWidth); 521 } 522 } 523 524 /** 525 * Returns the depth of the imported piece. 526 */ getDepth()527 public float getDepth() { 528 return this.depth; 529 } 530 531 /** 532 * Sets the depth of the imported piece. 533 */ setDepth(float depth)534 public void setDepth(float depth) { 535 setDepth(depth, false); 536 } 537 538 /** 539 * Sets the depth of the imported piece. 540 */ setDepth(float depth, boolean keepProportionalDepthUnchanged)541 private void setDepth(float depth, boolean keepProportionalDepthUnchanged) { 542 float adjustedDepth = Math.max(depth, 0.001f); 543 if (adjustedDepth == depth || !keepProportionalDepthUnchanged) { 544 this.proportionalDepth = depth; 545 } 546 if (adjustedDepth != this.depth) { 547 float oldDepth = this.depth; 548 this.depth = adjustedDepth; 549 this.propertyChangeSupport.firePropertyChange(Property.DEPTH.name(), oldDepth, adjustedDepth); 550 } 551 } 552 553 /** 554 * Returns the height. 555 */ getHeight()556 public float getHeight() { 557 return this.height; 558 } 559 560 /** 561 * Sets the size of the imported piece. 562 */ setHeight(float height)563 public void setHeight(float height) { 564 setHeight(height, false); 565 } 566 567 /** 568 * Sets the size of the imported piece. 569 */ setHeight(float height, boolean keepProportionalHeightUnchanged)570 private void setHeight(float height, boolean keepProportionalHeightUnchanged) { 571 float adjustedHeight = Math.max(height, 0.001f); 572 if (adjustedHeight == height || !keepProportionalHeightUnchanged) { 573 this.proportionalHeight = height; 574 } 575 if (adjustedHeight != this.height) { 576 float oldHeight = this.height; 577 this.height = adjustedHeight; 578 this.propertyChangeSupport.firePropertyChange(Property.HEIGHT.name(), oldHeight, adjustedHeight); 579 } 580 } 581 582 /** 583 * Returns the elevation of the imported piece. 584 */ getElevation()585 public float getElevation() { 586 return this.elevation; 587 } 588 589 /** 590 * Sets the elevation of the imported piece. 591 */ setElevation(float elevation)592 public void setElevation(float elevation) { 593 if (elevation != this.elevation) { 594 float oldElevation = this.elevation; 595 this.elevation = elevation; 596 this.propertyChangeSupport.firePropertyChange(Property.ELEVATION.name(), oldElevation, elevation); 597 } 598 } 599 600 /** 601 * Returns <code>true</code> if imported piece is movable. 602 */ isMovable()603 public boolean isMovable() { 604 return this.movable; 605 } 606 607 /** 608 * Sets whether imported piece is movable. 609 */ setMovable(boolean movable)610 public void setMovable(boolean movable) { 611 if (movable != this.movable) { 612 this.movable = movable; 613 this.propertyChangeSupport.firePropertyChange(Property.MOVABLE.name(), !movable, movable); 614 } 615 } 616 617 /** 618 * Returns <code>true</code> if imported piece is a door or a window. 619 */ isDoorOrWindow()620 public boolean isDoorOrWindow() { 621 return this.doorOrWindow; 622 } 623 624 /** 625 * Sets whether imported piece is a door or a window. 626 */ setDoorOrWindow(boolean doorOrWindow)627 public void setDoorOrWindow(boolean doorOrWindow) { 628 if (doorOrWindow != this.doorOrWindow) { 629 this.doorOrWindow = doorOrWindow; 630 this.propertyChangeSupport.firePropertyChange(Property.DOOR_OR_WINDOW.name(), !doorOrWindow, doorOrWindow); 631 if (doorOrWindow) { 632 setStaircaseCutOutShape(null); 633 setMovable(false); 634 } 635 } 636 } 637 638 /** 639 * Returns the shape used to cut out upper levels at its intersection with a staircase. 640 */ getStaircaseCutOutShape()641 public String getStaircaseCutOutShape() { 642 return this.staircaseCutOutShape; 643 } 644 645 /** 646 * Sets the shape used to cut out upper levels at its intersection with a staircase. 647 */ setStaircaseCutOutShape(String staircaseCutOutShape)648 public void setStaircaseCutOutShape(String staircaseCutOutShape) { 649 if (staircaseCutOutShape != this.staircaseCutOutShape) { 650 String oldStaircaseCutOutShape = this.staircaseCutOutShape; 651 this.staircaseCutOutShape = staircaseCutOutShape; 652 if (this.propertyChangeSupport != null) { 653 this.propertyChangeSupport.firePropertyChange(Property.STAIRCASE_CUT_OUT_SHAPE.name(), oldStaircaseCutOutShape, staircaseCutOutShape); 654 } 655 if (this.staircaseCutOutShape != null) { 656 setDoorOrWindow(false); 657 setMovable(false); 658 } 659 } 660 } 661 662 /** 663 * Returns the color of the imported piece. 664 */ getColor()665 public Integer getColor() { 666 return this.color; 667 } 668 669 /** 670 * Sets the color of the imported piece. 671 */ setColor(Integer color)672 public void setColor(Integer color) { 673 if (color != this.color) { 674 Integer oldColor = this.color; 675 this.color = color; 676 this.propertyChangeSupport.firePropertyChange(Property.COLOR.name(), oldColor, color); 677 } 678 } 679 680 /** 681 * Returns the category of the imported piece. 682 */ getCategory()683 public FurnitureCategory getCategory() { 684 return this.category; 685 } 686 687 /** 688 * Sets the category of the imported piece. 689 */ setCategory(FurnitureCategory category)690 public void setCategory(FurnitureCategory category) { 691 if (category != this.category) { 692 FurnitureCategory oldCategory = this.category; 693 this.category = category; 694 this.propertyChangeSupport.firePropertyChange(Property.CATEGORY.name(), oldCategory, category); 695 } 696 } 697 698 /** 699 * Returns the icon of the imported piece. 700 */ getIcon()701 private Content getIcon() { 702 return getStepsView().getIcon(); 703 } 704 705 /** 706 * Returns the yaw of the piece icon. 707 */ getIconYaw()708 public float getIconYaw() { 709 return this.iconYaw; 710 } 711 712 /** 713 * Sets the yaw angle of the piece icon. 714 */ setIconYaw(float iconYaw)715 public void setIconYaw(float iconYaw) { 716 if (iconYaw != this.iconYaw) { 717 float oldIconYaw = this.iconYaw; 718 this.iconYaw = iconYaw; 719 this.propertyChangeSupport.firePropertyChange(Property.ICON_YAW.name(), oldIconYaw, iconYaw); 720 } 721 } 722 723 /** 724 * Returns <code>true</code> if piece proportions should be kept. 725 */ isProportional()726 public boolean isProportional() { 727 return this.proportional; 728 } 729 730 /** 731 * Sets whether piece proportions should be kept or not. 732 */ setProportional(boolean proportional)733 public void setProportional(boolean proportional) { 734 if (proportional != this.proportional) { 735 this.proportional = proportional; 736 this.propertyChangeSupport.firePropertyChange(Property.PROPORTIONAL.name(), !proportional, proportional); 737 } 738 } 739 740 /** 741 * Returns <code>true</code> if piece name is valid. 742 */ isPieceOfFurnitureNameValid()743 public boolean isPieceOfFurnitureNameValid() { 744 return this.name != null 745 && this.name.length() > 0; 746 } 747 748 /** 749 * Step state superclass. All step state share the same step view, 750 * that will display a different component depending on their class name. 751 */ 752 protected abstract class ImportedFurnitureWizardStepState extends WizardControllerStepState { 753 private URL icon = ImportedFurnitureWizardController.class.getResource("resources/importedFurnitureWizard.png"); 754 getStep()755 public abstract Step getStep(); 756 757 @Override enter()758 public void enter() { 759 setStep(getStep()); 760 } 761 762 @Override getView()763 public View getView() { 764 return getStepsView(); 765 } 766 767 @Override getIcon()768 public URL getIcon() { 769 return this.icon; 770 } 771 } 772 773 /** 774 * Furniture model step state (first step). 775 */ 776 private class FurnitureModelStepState extends ImportedFurnitureWizardStepState { 777 private PropertyChangeListener modelChangeListener = new PropertyChangeListener() { 778 public void propertyChange(PropertyChangeEvent ev) { 779 setNextStepEnabled(getModel() != null); 780 } 781 }; 782 783 @Override enter()784 public void enter() { 785 super.enter(); 786 setFirstStep(true); 787 // First step is valid once a model is available 788 setNextStepEnabled(getModel() != null); 789 addPropertyChangeListener(Property.MODEL, this.modelChangeListener); 790 } 791 792 @Override getStep()793 public Step getStep() { 794 return Step.MODEL; 795 } 796 797 @Override goToNextStep()798 public void goToNextStep() { 799 setStepState(getFurnitureOrientationStepState()); 800 } 801 802 @Override exit()803 public void exit() { 804 removePropertyChangeListener(Property.MODEL, this.modelChangeListener); 805 } 806 } 807 808 /** 809 * Furniture orientation step state (second step). 810 */ 811 private class FurnitureOrientationStepState extends ImportedFurnitureWizardStepState { 812 @Override enter()813 public void enter() { 814 super.enter(); 815 // Step always valid by default 816 setNextStepEnabled(true); 817 } 818 819 @Override getStep()820 public Step getStep() { 821 return Step.ROTATION; 822 } 823 824 @Override goBackToPreviousStep()825 public void goBackToPreviousStep() { 826 setStepState(getFurnitureModelStepState()); 827 } 828 829 @Override goToNextStep()830 public void goToNextStep() { 831 setStepState(getFurnitureAttributesStepState()); 832 } 833 } 834 835 /** 836 * Furniture attributes step state (third step). 837 */ 838 private class FurnitureAttributesStepState extends ImportedFurnitureWizardStepState { 839 PropertyChangeListener widthChangeListener = new PropertyChangeListener() { 840 public void propertyChange(PropertyChangeEvent ev) { 841 if (isProportional()) { 842 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.DEPTH, depthChangeListener); 843 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.HEIGHT, heightChangeListener); 844 845 // If proportions should be kept, update depth and height 846 float ratio = (Float)ev.getNewValue() / (Float)ev.getOldValue(); 847 setDepth(proportionalDepth * ratio, true); 848 setHeight(proportionalHeight * ratio, true); 849 850 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.DEPTH, depthChangeListener); 851 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.HEIGHT, heightChangeListener); 852 } 853 } 854 }; 855 PropertyChangeListener depthChangeListener = new PropertyChangeListener() { 856 public void propertyChange(PropertyChangeEvent ev) { 857 if (isProportional()) { 858 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.WIDTH, widthChangeListener); 859 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.HEIGHT, heightChangeListener); 860 861 // If proportions should be kept, update width and height 862 float ratio = (Float)ev.getNewValue() / (Float)ev.getOldValue(); 863 setWidth(proportionalWidth * ratio, true); 864 setHeight(proportionalHeight * ratio, true); 865 866 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.WIDTH, widthChangeListener); 867 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.HEIGHT, heightChangeListener); 868 } 869 } 870 }; 871 PropertyChangeListener heightChangeListener = new PropertyChangeListener() { 872 public void propertyChange(PropertyChangeEvent ev) { 873 if (isProportional()) { 874 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.WIDTH, widthChangeListener); 875 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.DEPTH, depthChangeListener); 876 877 // If proportions should be kept, update width and depth 878 float ratio = (Float)ev.getNewValue() / (Float)ev.getOldValue(); 879 setWidth(proportionalWidth * ratio, true); 880 setDepth(proportionalDepth * ratio, true); 881 882 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.WIDTH, widthChangeListener); 883 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.DEPTH, depthChangeListener); 884 } 885 } 886 }; 887 PropertyChangeListener nameAndCategoryChangeListener = new PropertyChangeListener() { 888 public void propertyChange(PropertyChangeEvent ev) { 889 checkPieceOfFurnitureNameInCategory(); 890 } 891 }; 892 893 @Override enter()894 public void enter() { 895 super.enter(); 896 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.WIDTH, this.widthChangeListener); 897 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.DEPTH, this.depthChangeListener); 898 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.HEIGHT, this.heightChangeListener); 899 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.NAME, this.nameAndCategoryChangeListener); 900 ImportedFurnitureWizardController.this.addPropertyChangeListener(Property.CATEGORY, this.nameAndCategoryChangeListener); 901 checkPieceOfFurnitureNameInCategory(); 902 } 903 checkPieceOfFurnitureNameInCategory()904 private void checkPieceOfFurnitureNameInCategory() { 905 setNextStepEnabled(isPieceOfFurnitureNameValid()); 906 } 907 908 @Override getStep()909 public Step getStep() { 910 return Step.ATTRIBUTES; 911 } 912 913 @Override goBackToPreviousStep()914 public void goBackToPreviousStep() { 915 setStepState(getFurnitureOrientationStepState()); 916 } 917 918 @Override goToNextStep()919 public void goToNextStep() { 920 setStepState(getFurnitureIconStepState()); 921 } 922 923 @Override exit()924 public void exit() { 925 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.WIDTH, this.widthChangeListener); 926 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.DEPTH, this.depthChangeListener); 927 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.HEIGHT, this.heightChangeListener); 928 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.NAME, this.nameAndCategoryChangeListener); 929 ImportedFurnitureWizardController.this.removePropertyChangeListener(Property.CATEGORY, this.nameAndCategoryChangeListener); 930 } 931 } 932 933 /** 934 * Furniture icon step state (last step). 935 */ 936 private class FurnitureIconStepState extends ImportedFurnitureWizardStepState { 937 @Override enter()938 public void enter() { 939 super.enter(); 940 setLastStep(true); 941 // Step always valid by default 942 setNextStepEnabled(true); 943 } 944 945 @Override getStep()946 public Step getStep() { 947 return Step.ICON; 948 } 949 950 @Override goBackToPreviousStep()951 public void goBackToPreviousStep() { 952 setStepState(getFurnitureAttributesStepState()); 953 } 954 } 955 } 956