1 /* 2 * PlanControllerTest.java 31 mai 2006 3 * 4 * Copyright (c) 2006 Emmanuel PUYBARET / eTeks <info@eteks.com>. All Rights 5 * Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify it under 8 * the terms of the GNU General Public License as published by the Free Software 9 * Foundation; either version 2 of the License, or (at your option) any later 10 * version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 15 * details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 19 * Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package com.eteks.sweethome3d.junit; 22 23 import java.awt.EventQueue; 24 import java.lang.reflect.InvocationTargetException; 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.Collection; 28 import java.util.List; 29 import java.util.Locale; 30 31 import javax.swing.undo.UndoManager; 32 import javax.swing.undo.UndoableEditSupport; 33 34 import junit.framework.TestCase; 35 36 import com.eteks.sweethome3d.io.DefaultUserPreferences; 37 import com.eteks.sweethome3d.model.CatalogPieceOfFurniture; 38 import com.eteks.sweethome3d.model.CollectionEvent; 39 import com.eteks.sweethome3d.model.CollectionListener; 40 import com.eteks.sweethome3d.model.FurnitureCategory; 41 import com.eteks.sweethome3d.model.Home; 42 import com.eteks.sweethome3d.model.HomeFurnitureGroup; 43 import com.eteks.sweethome3d.model.HomePieceOfFurniture; 44 import com.eteks.sweethome3d.model.Selectable; 45 import com.eteks.sweethome3d.model.UserPreferences; 46 import com.eteks.sweethome3d.model.Wall; 47 import com.eteks.sweethome3d.swing.SwingViewFactory; 48 import com.eteks.sweethome3d.viewcontroller.PlanController; 49 import com.eteks.sweethome3d.viewcontroller.ViewFactory; 50 51 /** 52 * Tests {@link com.eteks.sweethome3d.viewcontroller.PlanController plan controller}. 53 * @author Emmanuel Puybaret 54 */ 55 public class PlanControllerTest extends TestCase { 56 /** 57 * Performs the same tests as {@link PlanComponentTest#testPlanComponent()} 58 * but with direct calls to controller in memory. 59 */ testPlanContoller()60 public void testPlanContoller() throws InterruptedException, InvocationTargetException { 61 // Run test in Event Dispatch Thread because the default view associated 62 // to plan controller instance performs some actions in EDT even if it's not displayed 63 EventQueue.invokeAndWait(new Runnable() { 64 public void run() { 65 runPlanContollerTest(); 66 } 67 }); 68 } 69 runPlanContollerTest()70 private void runPlanContollerTest() { 71 // 1. Create a frame that displays a PlanComponent at its preferred size, 72 Home home = new Home(); 73 Locale.setDefault(Locale.FRANCE); 74 UserPreferences preferences = new DefaultUserPreferences(); 75 ViewFactory viewFactory = new SwingViewFactory(); 76 UndoableEditSupport undoSupport = new UndoableEditSupport(); 77 UndoManager undoManager = new UndoManager(); 78 undoSupport.addUndoableEditListener(undoManager); 79 PlanController planController = 80 new PlanController(home, preferences, viewFactory, null, undoSupport); 81 82 // Build an ordered list of walls added to home 83 final ArrayList<Wall> orderedWalls = new ArrayList<Wall>(); 84 home.addWallsListener(new CollectionListener<Wall> () { 85 public void collectionChanged(CollectionEvent<Wall> ev) { 86 if (ev.getType() == CollectionEvent.Type.ADD) { 87 orderedWalls.add(ev.getItem()); 88 } 89 } 90 }); 91 92 // 2. Use WALL_CREATION mode 93 planController.setMode(PlanController.Mode.WALL_CREATION); 94 // Click at (20, 20), (500, 22), (498, 300), then double click at (20, 302) in home coordinates space 95 planController.moveMouse(20, 20); 96 planController.pressMouse(20, 20, 1, false, false); 97 planController.toggleMagnetism(false); 98 planController.releaseMouse(20, 20); 99 planController.moveMouse(500, 22); 100 planController.pressMouse(500, 22, 1, false, false); 101 planController.releaseMouse(500, 22); 102 planController.moveMouse(498, 300); 103 planController.pressMouse(498, 300, 1, false, false); 104 planController.releaseMouse(498, 300); 105 planController.moveMouse(20, 302); 106 planController.pressMouse(20, 302, 1, false, false); 107 planController.releaseMouse(20, 302); 108 planController.pressMouse(20, 302, 2, false, false); 109 planController.releaseMouse(20, 302); 110 // Check 3 walls were created at (20, 20), (500, 20), (500, 300) and (20, 300) coordinates 111 Wall wall1 = orderedWalls.get(0); 112 assertCoordinatesEqualWallPoints(20, 20, 500, 20, wall1); 113 Wall wall2 = orderedWalls.get(1); 114 assertCoordinatesEqualWallPoints(500, 20, 500, 300, wall2); 115 Wall wall3 = orderedWalls.get(2); 116 assertCoordinatesEqualWallPoints(500, 300, 20, 300, wall3); 117 // Check they are joined to each other end point 118 assertWallsAreJoined(null, wall1, wall2); 119 assertWallsAreJoined(wall1, wall2, wall3); 120 assertWallsAreJoined(wall2, wall3, null); 121 // Check they are selected 122 assertSelectionContains(home, wall1, wall2, wall3); 123 124 // 3. Click at (20, 300), then double click at (60, 60) with Alt key depressed 125 planController.moveMouse(20, 300); 126 planController.pressMouse(20, 300, 1, false, false); 127 planController.releaseMouse(20, 300); 128 planController.toggleMagnetism(true); 129 planController.moveMouse(60, 60); 130 planController.pressMouse(60, 60, 1, false, false); 131 planController.releaseMouse(60, 60); 132 planController.pressMouse(60, 60, 2, false, false); 133 planController.releaseMouse(60, 60); 134 planController.toggleMagnetism(false); 135 // Check a forth wall was created at (20, 300), (60, 60) coordinates 136 Wall wall4 = orderedWalls.get(orderedWalls.size() - 1); 137 assertCoordinatesEqualWallPoints(20, 300, 60, 60, wall4); 138 assertSelectionContains(home, wall4); 139 assertWallsAreJoined(wall3, wall4, null); 140 141 // 4. Use SELECTION mode 142 planController.setMode(PlanController.Mode.SELECTION); 143 // Check current mode is SELECTION 144 assertEquals("Current mode isn't " + PlanController.Mode.SELECTION, 145 PlanController.Mode.SELECTION, planController.getMode()); 146 // Press the delete key 147 planController.deleteSelection(); 148 // Check plan contains only the first three walls 149 assertHomeContains(home, wall1, wall2, wall3); 150 151 // 5. Use WALL_CREATION mode 152 planController.setMode(PlanController.Mode.WALL_CREATION); 153 // Click at (22, 18), then double click at (20, 300) 154 planController.moveMouse(22, 18); 155 planController.pressMouse(22, 18, 1, false, false); 156 planController.releaseMouse(22, 18); 157 planController.moveMouse(20, 300); 158 planController.pressMouse(20, 300, 1, false, false); 159 planController.releaseMouse(20, 300); 160 planController.pressMouse(20, 300, 2, false, false); 161 planController.releaseMouse(20, 300); 162 // Check a new forth wall was created at (20, 20), (20, 300) coordinates 163 wall4 = orderedWalls.get(orderedWalls.size() - 1); 164 assertCoordinatesEqualWallPoints(20, 20, 20, 300, wall4); 165 // Check its end points are joined to the first and third wall 166 assertWallsAreJoined(wall1, wall4, wall3); 167 168 // 6. Use SELECTION mode 169 planController.setMode(PlanController.Mode.SELECTION); 170 // Drag and drop cursor from (360, 160) to (560, 320) 171 planController.moveMouse(360, 160); 172 planController.pressMouse(360, 160, 1, false, false); 173 planController.moveMouse(560, 320); 174 planController.releaseMouse(560, 320); 175 // Check the selected walls are the second and third ones 176 assertSelectionContains(home, wall2, wall3); 177 178 // 7. Press twice right arrow key 179 planController.moveSelection(2, 0); 180 planController.moveSelection(2, 0); 181 // Check the 4 walls coordinates are (20, 20), (504, 20), (504, 300), (24, 300) 182 assertCoordinatesEqualWallPoints(20, 20, 504, 20, wall1); 183 assertCoordinatesEqualWallPoints(504, 20, 504, 300, wall2); 184 assertCoordinatesEqualWallPoints(504, 300, 24, 300, wall3); 185 assertCoordinatesEqualWallPoints(20, 20, 24, 300, wall4); 186 187 // 8. Click at (504, 40) 188 planController.moveMouse(504, 40); 189 planController.pressMouse(504, 40, 1, true, false); 190 planController.releaseMouse(504, 40); 191 // Check the second wall was removed from selection 192 assertSelectionContains(home, wall3); 193 194 // 9. Drag cursor from (60, 20) to (60, 60) 195 planController.moveMouse(60, 20); 196 planController.pressMouse(60, 20, 1, false, false); 197 planController.moveMouse(60, 60); 198 // Check first wall is selected and that it moved 199 assertSelectionContains(home, wall1); 200 assertCoordinatesEqualWallPoints(20, 60, 504, 60, wall1); 201 // Lose focus 202 planController.escape(); 203 // Check the wall didn't move at end 204 assertCoordinatesEqualWallPoints(20, 20, 504, 20, wall1); 205 206 // 10. Undo 8 times 207 for (int i = 0; i < 6; i++) { 208 undoManager.undo(); 209 } 210 // Check home doesn't contain any wall 211 assertHomeContains(home); 212 213 // 11. Redo 8 times 214 for (int i = 0; i < 6; i++) { 215 undoManager.redo(); 216 } 217 // Check plan contains the four wall 218 assertHomeContains(home, wall1, wall2, wall3, wall4); 219 // Check the second and the third wall are selected 220 assertSelectionContains(home, wall2, wall3); 221 } 222 223 /** 224 * Tests how the children of a group and a subgroup are resized. 225 */ testFurnitureGroupResizing()226 public void testFurnitureGroupResizing() { 227 Home home = new Home(); 228 Locale.setDefault(Locale.ENGLISH); 229 UserPreferences preferences = new DefaultUserPreferences(); 230 ViewFactory viewFactory = new SwingViewFactory(); 231 UndoableEditSupport undoSupport = new UndoableEditSupport(); 232 UndoManager undoManager = new UndoManager(); 233 undoSupport.addUndoableEditListener(undoManager); 234 PlanController planController = 235 new PlanController(home, preferences, viewFactory, null, undoSupport); 236 237 CatalogPieceOfFurniture box = null; 238 for (FurnitureCategory category : preferences.getFurnitureCatalog().getCategories()) { 239 if ("Miscellaneous".equals(category.getName())) { 240 for (CatalogPieceOfFurniture piece : category.getFurniture()) { 241 if ("Box".equals(piece.getName())) { 242 box = piece; 243 break; 244 } 245 } 246 } 247 } 248 assertNotNull("Couldn't find box", box); 249 // 1. Add two boxes to plan 250 HomePieceOfFurniture box1 = new HomePieceOfFurniture(box); 251 home.addPieceOfFurniture(box1); 252 box1.setX(50); 253 box1.setY(50); 254 HomePieceOfFurniture box2 = new HomePieceOfFurniture(box); 255 home.addPieceOfFurniture(box2); 256 box2.setX(200); 257 box2.setY(50); 258 box2.setWidth(200); 259 // Check plan controller updates box size in plan 260 assertEquals("Box width in plan incorrect", 200f, box2.getWidthInPlan()); 261 262 // 2. Group them 263 home.setSelectedItems(Arrays.asList(box1, box2)); 264 planController.groupSelectedFurniture(); 265 List<HomePieceOfFurniture> furniture = home.getFurniture(); 266 assertEquals("Wrong count of pieces", 1, furniture.size()); 267 HomePieceOfFurniture group1 = furniture.get(0); 268 assertTrue("Group not created", group1 instanceof HomeFurnitureGroup); 269 assertEquals("Wrong X", 150f, group1.getX()); 270 271 // 3. Group the subgroup with an other box 272 HomePieceOfFurniture box3 = new HomePieceOfFurniture(box); 273 home.addPieceOfFurniture(box3); 274 box3.setX(150); 275 box3.setWidth(300); 276 box3.setY(250); 277 home.setSelectedItems(Arrays.asList(group1, box3)); 278 planController.groupSelectedFurniture(); 279 furniture = home.getFurniture(); 280 HomePieceOfFurniture mainGroup = furniture.get(0); 281 assertTrue("Group not created", mainGroup instanceof HomeFurnitureGroup); 282 assertEquals("Wrong X", 150f, mainGroup.getX()); 283 assertEquals("Wrong Y", 150f, mainGroup.getY()); 284 285 // 4. Resize group with mouse 286 planController.moveMouse(300, 300); 287 planController.pressMouse(300, 300, 1, false, false); 288 planController.moveMouse(600, 600); 289 planController.releaseMouse(600, 600); 290 assertEquals("Wrong X", 300f, mainGroup.getX()); 291 assertEquals("Wrong Y", 300f, mainGroup.getY()); 292 assertEquals("Wrong width in plan", 600f, group1.getWidthInPlan()); 293 assertEquals("Wrong depth in plan", 200f, group1.getDepthInPlan()); 294 assertEquals("Wrong width", 400f, box2.getWidth()); 295 assertEquals("Wrong width in plan", 400f, box2.getWidthInPlan()); 296 assertEquals("Wrong depth in plan", 200f, box2.getDepthInPlan()); 297 298 // 5. Resize group directly 299 mainGroup.setWidth(150); 300 assertEquals("Wrong width in plan", 150f, mainGroup.getWidthInPlan()); 301 assertEquals("Wrong width", 150f, group1.getWidth()); 302 assertEquals("Wrong width in plan", 150f, group1.getWidthInPlan()); 303 assertEquals("Wrong width", 100f, box2.getWidth()); 304 assertEquals("Wrong width in plan", 100f, box2.getWidthInPlan()); 305 } 306 307 /** 308 * Asserts the start point and the end point of 309 * <code>wall</code> are at (<code>xStart</code>, <code>yStart</code>), (<code>xEnd</code>, <code>yEnd</code>). 310 */ assertCoordinatesEqualWallPoints(float xStart, float yStart, float xEnd, float yEnd, Wall wall)311 private void assertCoordinatesEqualWallPoints(float xStart, float yStart, float xEnd, float yEnd, Wall wall) { 312 assertTrue("Incorrect X start " + xStart + " " + wall.getXStart(), 313 Math.abs(xStart - wall.getXStart()) < 1E-10); 314 assertTrue("Incorrect Y start " + yStart + " " + wall.getYStart(), 315 Math.abs(yStart - wall.getYStart()) < 1E-10); 316 assertTrue("Incorrect X end " + xEnd + " " + wall.getXEnd(), 317 Math.abs(xEnd - wall.getXEnd()) < 1E-10); 318 assertTrue("Incorrect Y end " + yEnd + " " + wall.getYEnd(), 319 Math.abs(yEnd - wall.getYEnd()) < 1E-10); 320 } 321 322 /** 323 * Asserts <code>wall</code> is joined to <code>wallAtStart</code> 324 * and <code>wallAtEnd</code>. 325 */ assertWallsAreJoined(Wall wallAtStart, Wall wall, Wall wallAtEnd)326 private void assertWallsAreJoined(Wall wallAtStart, Wall wall, Wall wallAtEnd) { 327 assertSame("Incorrect wall at start", wallAtStart, wall.getWallAtStart()); 328 assertSame("Incorrect wall at end", wallAtEnd, wall.getWallAtEnd()); 329 } 330 331 /** 332 * Asserts <code>home</code> contains <code>walls</code>. 333 */ assertHomeContains(Home home, Wall ... walls)334 private void assertHomeContains(Home home, Wall ... walls) { 335 Collection<Wall> planWalls = home.getWalls(); 336 assertEquals("Home walls incorrect count", 337 walls.length, planWalls.size()); 338 for (Wall wall : walls) { 339 assertTrue("Wall doesn't belong to plan", planWalls.contains(wall)); 340 } 341 } 342 343 /** 344 * Asserts <code>walls</code> are the current selected ones in <code>home</code>. 345 */ assertSelectionContains(Home home, Wall ... walls)346 private void assertSelectionContains(Home home, 347 Wall ... walls) { 348 List<Selectable> selectedItems = home.getSelectedItems(); 349 assertEquals(walls.length, selectedItems.size()); 350 for (Wall wall : walls) { 351 assertTrue("Wall not selected", selectedItems.contains(wall)); 352 } 353 } 354 } 355