Changeset 28
- Timestamp:
- 05/14/08 09:32:42 (16 years ago)
- Location:
- trunk/src/org/expeditee/items
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/expeditee/items/InteractiveWidget.java
r11 r28 24 24 * 25 25 * @author Brook 26 * 26 * 27 27 */ 28 28 public abstract class InteractiveWidget { 29 29 30 30 protected JComponent _component; 31 31 32 32 /** A widget is comprised of dots and lines that basically form a rectangle */ 33 33 private WidgetCorner _d1, _d2, _d3, _d4; 34 34 35 private WidgetEdge _l1, _l2, _l3, _l4; 36 35 37 /* GUIDE: 36 38 * l1 … … 43 45 */ 44 46 private List<Item> _items; // used for quickly returning item list 45 47 46 48 // Widget size restrictions 47 49 private int _minWidth = 50; 50 48 51 private int _minHeight = 50; 52 49 53 private int _maxWidth = 300; 54 50 55 private int _maxHeight = 300; 51 52 // The Expeditee item that is used for saving widget state in expiditee world 56 57 // The Expeditee item that is used for saving widget state in expiditee 58 // world 53 59 private Text _source; 54 60 61 // A flag for signifying whether the swing components are ready to paint. 62 // If the swing components has not been layed out, if they are painted they 63 // will 64 // not draw in the correct positions. 65 private boolean _isReadyToPaint = false; 66 55 67 /** 56 68 * Creates a InteractiveWidget from a text item. 57 69 * 58 * @param source Must not be null, first line of text used - which the format must 59 * be as follows: "@iw <<widget_class_name>> [<<width>>] [<<height>>] [: [<<arg1>>] [<<arg2>>] [...]]". 60 * 61 * e.g: "@iw org.expeditee.items.SampleWidget1 100 20 : 2" 62 * creates a SampleWidget1 with width = 100 and height = 20 with 1 argument = "2" 63 * 70 * @param source 71 * Must not be null, first line of text used - which the format 72 * must be as follows: "@iw <<widget_class_name>> [<<width>>] [<<height>>] [: [<<arg1>>] [<<arg2>>] 73 * [...]]". 74 * 75 * e.g: "@iw org.expeditee.items.SampleWidget1 100 20 : 2" creates a 76 * SampleWidget1 with width = 100 and height = 20 with 1 argument = "2" 77 * 64 78 * @return An InteractiveWidget instance. Never null. 65 79 * 66 * @throws NullPointerException 67 * 68 * 69 * @throws IllegalArgumentException 70 * if source's text is in the incorrect format71 * or if source'sparent is null72 * 73 * @throws InteractiveWidgetNotAvailableException 74 * If the given widget class name in the source text75 * doesn't exist or not an InteractiveWidget or the widget76 * does notsupply a valid constructor for creation.80 * @throws NullPointerException 81 * if source is null 82 * 83 * @throws IllegalArgumentException 84 * if source's text is in the incorrect format or if source's 85 * parent is null 86 * 87 * @throws InteractiveWidgetNotAvailableException 88 * If the given widget class name in the source text doesn't 89 * exist or not an InteractiveWidget or the widget does not 90 * supply a valid constructor for creation. 77 91 * 78 92 * Note: could throw other exceptions depending on the type of widget being 79 93 * instantainiated. source must have a parent 80 94 * 81 * class names beginning with $, the $ will be replaced with "org.expeditee.items." 82 */ 83 public static InteractiveWidget CreateWidget(Text source) 84 throws InteractiveWidgetNotAvailableException { 85 86 if (source == null) throw new NullPointerException("source"); 87 if (source.getParent() == null) 88 throw new IllegalArgumentException("source's parent is null, InteractiveWidget's must be created from Text items with non-null parents"); 95 * class names beginning with $, the $ will be replaced with 96 * "org.expeditee.items." 97 */ 98 public static InteractiveWidget CreateWidget(Text source) 99 throws InteractiveWidgetNotAvailableException { 100 101 if (source == null) 102 throw new NullPointerException("source"); 103 if (source.getParent() == null) 104 throw new IllegalArgumentException( 105 "source's parent is null, InteractiveWidget's must be created from Text items with non-null parents"); 89 106 90 107 String TAG = ItemUtils.GetTag(ItemUtils.TAG_IWIDGET); 91 92 108 93 109 String text = source.getTextNoList(); 94 if (text == null) throw new IllegalArgumentException("source does not have any text"); 95 96 int index = text.indexOf(':'); // used for signifying start of arguments 97 if (index == 0) throw new IllegalArgumentException("Source text must begin with \"" + TAG + "\""); 98 99 String[] tokens = (index == -1) ? 100 text.split("\\s+") : text.substring(0,index).split(" "); 101 110 if (text == null) 111 throw new IllegalArgumentException("source does not have any text"); 112 113 int index = text.indexOf(':'); // used for signifying start of 114 // arguments 115 if (index == 0) 116 throw new IllegalArgumentException("Source text must begin with \"" 117 + TAG + "\""); 118 119 String[] tokens = (index == -1) ? text.split("\\s+") : text.substring( 120 0, index).split(" "); 121 102 122 // Check starts with the widget tag 103 123 if (tokens.length < 1 || !tokens[0].equals(TAG)) 104 throw new IllegalArgumentException("Source text must begin with \"" + TAG + "\""); 124 throw new IllegalArgumentException("Source text must begin with \"" 125 + TAG + "\""); 105 126 106 127 int width = -1, height = -1; 107 128 108 129 if (tokens.length < 2) 109 throw new IllegalArgumentException("Missing widget class name in source text"); 110 130 throw new IllegalArgumentException( 131 "Missing widget class name in source text"); 132 111 133 try { 112 134 113 135 if (tokens.length >= 3) { // parse optional width 114 136 width = Integer.parseInt(tokens[2]); 115 137 width = (width <= 0) ? width = -1 : width; 116 138 } 117 139 118 140 if (tokens.length >= 4) { // parse optional height 119 141 height = Integer.parseInt(tokens[3]); 120 142 height = (height <= 0) ? height = -1 : height; 121 143 } 122 144 123 145 } catch (NumberFormatException nfe) { 124 throw new IllegalArgumentException("Bad width or height given in source text", nfe); 125 } 126 146 throw new IllegalArgumentException( 147 "Bad width or height given in source text", nfe); 148 } 149 127 150 if (tokens.length > 4) 128 throw new IllegalArgumentException("to many arguments given before \":\" in source text"); 129 151 throw new IllegalArgumentException( 152 "to many arguments given before \":\" in source text"); 153 130 154 String classname = tokens[1]; 131 if (classname.charAt(0) == '$') classname = "org.expeditee.items." + classname.substring(1); 132 // Attempt to locate the class using reflection 133 Class iwclass = findIWidgetClass(classname); 134 155 if (classname.charAt(0) == '$') 156 classname = "org.expeditee.items." + classname.substring(1); 157 // Attempt to locate the class using reflection 158 Class<?> iwclass = findIWidgetClass(classname); 159 135 160 if (iwclass == null) // ensure it exists 136 throw new InteractiveWidgetNotAvailableException(classname + " does not exit or is not an InteractiveWidget"); 137 161 throw new InteractiveWidgetNotAvailableException(classname 162 + " does not exit or is not an InteractiveWidget"); 163 138 164 // Extract out the parameters - if any 139 165 String[] args = null; 140 166 if (index > 0) { // index of the first ":" 141 args = (text.length() == (index + 1)) ? 142 null : parseArgs(text.substring(index + 1));167 args = (text.length() == (index + 1)) ? null : parseArgs(text 168 .substring(index + 1)); 143 169 } 144 170 … … 146 172 try { 147 173 // Instantainiate the widget - passing the params 148 Class parameterTypes[] = new Class[] { Text.class, String[].class};174 Class parameterTypes[] = new Class[] { Text.class, String[].class }; 149 175 Constructor ct = iwclass.getConstructor(parameterTypes); 150 151 Object arglist[] = new Object[] { 152 source, 153 args 154 }; 155 156 inst = (InteractiveWidget)ct.newInstance(arglist); 176 177 Object arglist[] = new Object[] { source, args }; 178 179 inst = (InteractiveWidget) ct.newInstance(arglist); 157 180 } catch (Exception e) { 158 throw new InteractiveWidgetNotAvailableException("Failed to create instance via reflection: " + e.toString(), e); 159 } 160 161 // Use default dimensions if not provided (or provided as negitive values) 162 if (width <= 0) width = inst.getWidth(); 163 if (height <= 0) height = inst.getHeight(); 164 181 throw new InteractiveWidgetNotAvailableException( 182 "Failed to create instance via reflection: " + e.toString(), 183 e); 184 } 185 186 // Use default dimensions if not provided (or provided as negitive 187 // values) 188 if (width <= 0) 189 width = inst.getWidth(); 190 if (height <= 0) 191 height = inst.getHeight(); 192 165 193 inst.setSize(width, height); 166 194 167 195 return inst; 168 196 } 169 197 170 198 /** 171 199 * Locates the class from the classname of an InteractiveWidget class 172 * @param classname The name of the class to search 200 * 201 * @param classname 202 * The name of the class to search 173 203 * @return Null if doesn't exist or not an InteractiveWidget 174 204 */ … … 176 206 try { 177 207 Class c = Class.forName(classname); // attempt to find the class 178 179 // If one is found, ensure that it is a descendant of an InteractiveWidget 180 for (Class superclass = c.getSuperclass(); 181 superclass != null && superclass != Item.class; 182 superclass = superclass.getSuperclass()) { 183 if (superclass == InteractiveWidget.class) return c; 184 } 185 186 } catch (ClassNotFoundException e) {} 187 208 209 // If one is found, ensure that it is a descendant of an 210 // InteractiveWidget 211 for (Class superclass = c.getSuperclass(); superclass != null 212 && superclass != Item.class; superclass = superclass 213 .getSuperclass()) { 214 if (superclass == InteractiveWidget.class) 215 return c; 216 } 217 218 } catch (ClassNotFoundException e) { 219 } 220 188 221 // Doesn't exist or not an InteractiveWidget 189 222 return null; 190 223 } 191 192 /** 193 * Using Microsofts commandline convention: Args seperated with white spaces. 194 * Options with white spaces enclosed with quotes. Args with quotes must be double quoted 195 * args1 args2=sfasas args3="option with spaces" arg""4"" 196 * 197 * @param args Null and empty excepted 224 225 /** 226 * Using Microsofts commandline convention: Args seperated with white 227 * spaces. Options with white spaces enclosed with quotes. Args with quotes 228 * must be double quoted args1 args2=sfasas args3="option with spaces" 229 * arg""4"" 230 * 231 * @param args 232 * Null and empty excepted 198 233 * @return An array of args. null if none provided 199 234 */ 200 235 static String[] parseArgs(String args) { 201 202 if (args == null) return null; 203 236 237 if (args == null) 238 return null; 239 204 240 args = args.trim(); 205 if (args.length() == 0) return null; 206 207 List <String> vargs = new LinkedList<String>(); 241 if (args.length() == 0) 242 return null; 243 244 List<String> vargs = new LinkedList<String>(); 208 245 StringBuilder sb = new StringBuilder(); 209 246 boolean quoteOn = false; 210 247 for (int i = 0; i < args.length(); i++) { 211 248 212 249 char c = args.charAt(i); 213 250 if (c == ' ' && !quoteOn) { 214 251 215 252 // Extract arg 216 253 vargs.add(sb.toString()); 217 254 sb = new StringBuilder(); 218 255 219 256 // Consume white spaces 220 while (args.charAt(++i) == ' ' && i < args.length()) { } 257 while (args.charAt(++i) == ' ' && i < args.length()) { 258 } 221 259 i--; 222 260 223 261 } else if (c == '\"') { 224 262 // If double qouted 225 if (args.length() >= (i + 2) && 226 args.charAt(i + 1) == '\"') { 227 263 if (args.length() >= (i + 2) && args.charAt(i + 1) == '\"') { 264 228 265 sb.append(c); // add escaped 229 i 230 266 i++; 267 231 268 } else { 232 269 quoteOn = !quoteOn; 233 270 } 234 271 235 272 } else { 236 273 sb.append(c); 237 274 } 238 275 } 239 240 if (sb.length() > 0) vargs.add(sb.toString()); 241 242 if (vargs.size() == 0) return null; 243 else return vargs.toArray(new String[vargs.size()]); 244 } 245 276 277 if (sb.length() > 0) 278 vargs.add(sb.toString()); 279 280 if (vargs.size() == 0) 281 return null; 282 else 283 return vargs.toArray(new String[vargs.size()]); 284 } 285 246 286 /** 247 287 * Reverse of parseArgs 288 * 248 289 * @return Null if args is null or empty / all whitespace 249 290 */ 250 291 static String formatArgs(String[] args) { 251 if (args == null) return null; 252 292 if (args == null) 293 return null; 294 253 295 StringBuilder sb = new StringBuilder(); 254 296 255 297 for (String s : args) { 256 if (s == null) continue; 257 298 if (s == null) 299 continue; 300 258 301 // Escape quotes 259 StringBuilder formatted = new StringBuilder(s.replaceAll("\"", "\"\"")); 302 StringBuilder formatted = new StringBuilder(s.replaceAll("\"", 303 "\"\"")); 260 304 261 305 // Encapsulate spaces … … 265 309 formatted.append('\"'); 266 310 } 267 268 if (sb.length() > 0) sb.append(' '); 311 312 if (sb.length() > 0) 313 sb.append(' '); 269 314 sb.append(formatted); 270 315 } 271 316 272 317 return sb.length() > 0 ? sb.toString() : null; 273 318 } 274 275 /** 276 * Arguments represent state. They are used for saving, loading, creating and cloning 277 * Special formatting is done for you. 278 * 279 * @return Can be null for no params. 280 */ 281 protected abstract String[] getArgs(); 282 319 320 /** 321 * Arguments represent state. They are used for saving, loading, creating 322 * and cloning Special formatting is done for you. 323 * 324 * @param isCopy 325 * If true, then the requested arguments returned should 326 * represent a copy of this instance Otherwise the arguments 327 * returned should represent this instance. This gives the widget 328 * the chance to allocate new/duplicate resources if they need 329 * to. 330 * 331 * @return Can be null for no params. 332 */ 333 protected abstract String[] getArgs(boolean isCopy); 334 283 335 /** 284 336 * Constructor 285 * @param source Must not be null. Neither must it's parent 286 * @param component Must not be null 287 */ 288 protected InteractiveWidget(Text source, JComponent component, int minWidth, 289 int maxWidth, int minHeight, int maxHeight) { 290 291 if (component == null) throw new NullPointerException("component"); 292 if (source == null) throw new NullPointerException("source"); 293 if (source.getParent() == null) 294 throw new IllegalArgumentException("source's parent is null, InteractiveWidget's must be created from Text items with non-null parents"); 295 337 * 338 * @param source 339 * Must not be null. Neither must it's parent 340 * @param component 341 * Must not be null 342 */ 343 protected InteractiveWidget(Text source, JComponent component, 344 int minWidth, int maxWidth, int minHeight, int maxHeight) { 345 346 if (component == null) 347 throw new NullPointerException("component"); 348 if (source == null) 349 throw new NullPointerException("source"); 350 if (source.getParent() == null) 351 throw new IllegalArgumentException( 352 "source's parent is null, InteractiveWidget's must be created from Text items with non-null parents"); 353 296 354 _component = component; 297 355 _source = source; 298 356 299 357 _minWidth = minWidth; 300 358 301 if (maxWidth < _minWidth && maxWidth >= 0) 302 throw new IllegalArgumentException("maxWidth smaller than the min Width"); 359 if (maxWidth < _minWidth && maxWidth >= 0) 360 throw new IllegalArgumentException( 361 "maxWidth smaller than the min Width"); 303 362 _maxWidth = maxWidth; 304 363 305 364 _minHeight = minHeight; 306 if (maxHeight < _minHeight && maxHeight >= 0) 307 throw new IllegalArgumentException("maxHeight smaller than the min Height"); 365 if (maxHeight < _minHeight && maxHeight >= 0) 366 throw new IllegalArgumentException( 367 "maxHeight smaller than the min Height"); 308 368 _maxHeight = maxHeight; 309 310 369 311 370 int x = source.getX(); 312 371 int y = source.getY(); 313 372 int width = (_minWidth < 0) ? 10 : _minWidth; 314 373 int height = (_minHeight < 0) ? 10 : _minHeight; 315 374 316 375 Frame idAllocator = _source.getParent(); 317 376 318 377 // create WidgetCorners 319 378 _d1 = new WidgetCorner(x, y, idAllocator.getNextItemID(), this); 320 379 _d2 = new WidgetCorner(x + width, y, idAllocator.getNextItemID(), this); 321 _d3 = new WidgetCorner(x + width, y + height, idAllocator.getNextItemID(), this); 380 _d3 = new WidgetCorner(x + width, y + height, idAllocator 381 .getNextItemID(), this); 322 382 _d4 = new WidgetCorner(x, y + height, idAllocator.getNextItemID(), this); 323 383 … … 336 396 _items.add(_l2); 337 397 _items.add(_l3); 338 _items.add(_l4); 398 _items.add(_l4); 339 399 } 340 400 … … 342 402 * @return A copy of this widget 343 403 */ 344 public abstract InteractiveWidget copy() throws InteractiveWidgetNotAvailableException; 404 public final InteractiveWidget copy() 405 throws InteractiveWidgetNotAvailableException { 406 407 Text t = _source.copy(); 408 String clonedAnnotation = getAnnotationString(true); 409 _source.setText(clonedAnnotation); 410 return InteractiveWidget.CreateWidget(t); 411 } 345 412 346 413 /** … … 348 415 */ 349 416 protected abstract String getTopMostClassName(); 350 417 351 418 /** 352 419 * Note updates the source text with current state info 420 * 353 421 * @return The Text item that this widget was created from. 354 422 */ 355 423 public Text getSource() { 356 424 357 StringBuilder sb = new StringBuilder(ItemUtils.GetTag(ItemUtils.TAG_IWIDGET)); 425 // Build the annotation string such that it represents this widgets 426 // current state 427 String newAnnotation = getAnnotationString(false); 428 429 // Set the new text 430 _source.setText(newAnnotation); 431 432 return _source; 433 } 434 435 /** 436 * @param copiedVersion 437 * True to return a copied representation of this instance. False 438 * to return this instances current state version. 439 * 440 * @return The expeditee anotation string. 441 */ 442 private String getAnnotationString(boolean copiedVersion) { 443 444 // Create tag and append classname 445 StringBuilder sb = new StringBuilder(ItemUtils 446 .GetTag(ItemUtils.TAG_IWIDGET)); 358 447 sb.append(' '); 359 448 sb.append(getTopMostClassName()); 360 sb.append(' '); 449 450 // Append size information if needed (not an attibute of text items) 361 451 if (!isFixedSize()) { 452 sb.append(' '); 362 453 sb.append(getWidth()); 363 454 sb.append(' '); 364 455 sb.append(getHeight()); 365 sb.append(' '); 366 } 367 368 // Append new tags 369 String stateArgs = InteractiveWidget.formatArgs(getArgs()); 456 } 457 458 // Append arguments if any 459 String stateArgs = InteractiveWidget.formatArgs(getArgs(copiedVersion)); 370 460 if (stateArgs != null) { 371 461 sb.append(':'); 372 462 sb.append(stateArgs); 373 463 } 374 375 // Set the new text 376 _source.setText(sb.toString()); 377 378 return _source; 379 } 380 464 465 return sb.toString(); 466 } 467 381 468 /** 382 469 * Clamped to current min/max width/height. 470 * 383 471 * @param width 384 472 * @param height 385 473 */ 386 474 public void setSize(int width, int height) { 387 475 388 476 // Clamp 389 if (width < _minWidth && _minWidth >= 0) width = _minWidth; 390 else if (width > _maxWidth && _maxWidth >= 0) width = _maxWidth; 391 392 if (height < _minHeight && _minHeight >= 0) height = _minHeight; 393 else if (height > _maxHeight && _maxHeight >= 0) height = _maxHeight; 394 395 boolean vfloating[] = new boolean[] { 396 _d1.isFloating(), 397 _d2.isFloating(), 398 _d3.isFloating(), 399 _d4.isFloating() 400 }; 401 402 _d1.setFloating(true); 403 _d2.setFloating(true); 404 _d3.setFloating(true); 405 _d4.setFloating(true); 406 407 int x = _d1.getX() + width; 408 int y = _d1.getY() + height; 409 _d2.setX(x); 410 _d3.setX(x); 411 _d3.setY(y); 412 _d4.setY(y); 413 414 _d1.setFloating(vfloating[0]); 415 _d2.setFloating(vfloating[1]); 416 _d3.setFloating(vfloating[2]); 417 _d4.setFloating(vfloating[3]); 418 419 } 420 421 422 423 public void setPosition(int x, int y) { 424 425 boolean vfloating[] = new boolean[] { 426 _d1.isFloating(), 427 _d2.isFloating(), 428 _d3.isFloating(), 429 _d4.isFloating() 430 }; 431 432 int width = getWidth(); 433 int height = getHeight(); 434 477 if (width < _minWidth && _minWidth >= 0) 478 width = _minWidth; 479 else if (width > _maxWidth && _maxWidth >= 0) 480 width = _maxWidth; 481 482 if (height < _minHeight && _minHeight >= 0) 483 height = _minHeight; 484 else if (height > _maxHeight && _maxHeight >= 0) 485 height = _maxHeight; 486 487 boolean vfloating[] = new boolean[] { _d1.isFloating(), 488 _d2.isFloating(), _d3.isFloating(), _d4.isFloating() }; 489 435 490 _d1.setFloating(true); 436 491 _d2.setFloating(true); 437 492 _d3.setFloating(true); 438 493 _d4.setFloating(true); 439 494 495 int x = _d1.getX() + width; 496 int y = _d1.getY() + height; 497 _d2.setX(x); 498 _d3.setX(x); 499 _d3.setY(y); 500 _d4.setY(y); 501 502 _d1.setFloating(vfloating[0]); 503 _d2.setFloating(vfloating[1]); 504 _d3.setFloating(vfloating[2]); 505 _d4.setFloating(vfloating[3]); 506 507 } 508 509 public void setPosition(int x, int y) { 510 511 boolean vfloating[] = new boolean[] { _d1.isFloating(), 512 _d2.isFloating(), _d3.isFloating(), _d4.isFloating() }; 513 514 int width = getWidth(); 515 int height = getHeight(); 516 517 _d1.setFloating(true); 518 _d2.setFloating(true); 519 _d3.setFloating(true); 520 _d4.setFloating(true); 521 440 522 _d1.setPosition(x, y); 441 523 _d2.setPosition(x + width, y); 442 524 _d3.setPosition(x + width, y + height); 443 525 _d4.setPosition(x, y + height); 444 526 445 527 _d1.setFloating(vfloating[0]); 446 528 _d2.setFloating(vfloating[1]); … … 449 531 450 532 } 451 533 452 534 private boolean _settingPositionFlag = false; // used for recursion 453 535 454 536 /** 455 537 * to be called from corners only 538 * 456 539 * @param src 457 540 * @param x … … 460 543 */ 461 544 boolean setPositions(WidgetCorner src, int x, int y) { 462 463 if (_settingPositionFlag) return false; 545 546 if (_settingPositionFlag) 547 return false; 464 548 _settingPositionFlag = true; 465 549 550 // Check to see if the widget is fully being picked up 551 boolean isAllPickedUp = (_d1.isFloating() && _d2.isFloating() 552 && _d3.isFloating() && _d4.isFloating()); 553 466 554 int newX = x; 467 555 468 556 // X Positions 469 557 if (src == _d1 || src == _d4) { 470 471 // Note: the isFloating test is an indication to whether or not 472 // the widgets rectangle is being fully picked up... if it is then 473 // tere is no need to specially enforce constraints because they will 474 // all be moved togather with same relative positions. 475 if (src == _d1 && _d4.isFloating()) _d1.setX(newX); 476 else if (src == _d4 && _d1.isFloating()) _d4.setX(newX); 558 559 if (src == _d1 && isAllPickedUp) 560 _d1.setX(newX); 561 else if (src == _d4 && isAllPickedUp) 562 _d4.setX(newX); 477 563 else { 478 564 // Check min X constraint 479 565 if (_minWidth >= 0) { 480 566 if ((_d2.getX() - x) < _minWidth) { 481 newX = 567 newX = _d2.getX() - _minWidth; 482 568 } 483 569 } … … 485 571 if (_maxWidth >= 0) { 486 572 if ((_d2.getX() - x) > _maxWidth) { 487 newX = 573 newX = _d2.getX() - _maxWidth; 488 574 } 489 575 } 490 491 _d1.setX(newX); 492 _d4.setX(newX); 493 } 494 576 577 if (!(src == _d4 && _d1.isFloating() && _d4.isFloating())) 578 _d1.setX(newX); 579 if (!(src == _d1 && _d4.isFloating() && _d1.isFloating())) 580 _d4.setX(newX); 581 } 582 495 583 } else if (src == _d2 || src == _d3) { 496 497 if (src == _d2 && _d3.isFloating()) _d2.setX(newX); 498 else if (src == _d3 && _d2.isFloating()) _d3.setX(newX); 584 585 if (src == _d2 && isAllPickedUp) 586 _d2.setX(newX); 587 else if (src == _d3 && isAllPickedUp) 588 _d3.setX(newX); 499 589 else { 500 590 // Check min X constraint … … 507 597 if (_maxWidth >= 0) { 508 598 if ((x - _d1.getX()) > _maxWidth) { 509 newX = 599 newX = _d1.getX() + _maxWidth; 510 600 } 511 601 } 512 513 _d2.setX(newX); 514 _d3.setX(newX); 515 } 516 517 } 518 602 603 if (!(src == _d3 && _d2.isFloating() && _d3.isFloating())) 604 _d2.setX(newX); 605 if (!(src == _d2 && _d3.isFloating() && _d2.isFloating())) 606 _d3.setX(newX); 607 } 608 609 } 610 519 611 int newY = y; 520 612 521 613 // Y Positions 522 614 if (src == _d1 || src == _d2) { 523 524 if (src == _d1 && _d2.isFloating()) _d1.setY(newY); 525 else if (src == _d2 && _d1.isFloating()) _d2.setY(newY); 615 616 if (src == _d1 && isAllPickedUp) 617 _d1.setY(newY); 618 else if (src == _d2 && isAllPickedUp) 619 _d2.setY(newY); 526 620 else { 527 621 // Check min Y constraint 528 622 if (_minHeight >= 0) { 529 623 if ((_d4.getY() - y) < _minHeight) { 530 newY = 624 newY = _d4.getY() - _minHeight; 531 625 } 532 626 } … … 534 628 if (_maxHeight >= 0) { 535 629 if ((_d4.getY() - y) > _maxHeight) { 536 newY = 630 newY = _d4.getY() - _maxHeight; 537 631 } 538 632 } 539 _d1.setY(newY); 540 _d2.setY(newY); 541 } 542 633 634 if (!(src == _d2 && _d1.isFloating() && _d2.isFloating())) 635 _d1.setY(newY); 636 if (!(src == _d1 && _d2.isFloating() && _d1.isFloating())) 637 _d2.setY(newY); 638 639 } 640 543 641 } else if (src == _d3 || src == _d4) { 544 545 if (src == _d3 && _d4.isFloating()) _d3.setY(newY); 546 else if (src == _d4 && _d3.isFloating()) _d4.setY(newY); 642 643 if (src == _d3 && isAllPickedUp) 644 _d3.setY(newY); 645 else if (src == _d4 && isAllPickedUp) 646 _d4.setY(newY); 547 647 else { 548 648 // Check min Y constraint … … 555 655 if (_maxHeight >= 0) { 556 656 if ((y - _d1.getY()) > _maxHeight) { 557 newY = 657 newY = _d1.getY() + _maxHeight; 558 658 } 559 659 } 560 561 _d3.setY(newY); 562 _d4.setY(newY); 563 } 564 } 565 566 // Update source text position so position is remembered from loading 660 661 if (!(src == _d4 && _d3.isFloating() && _d4.isFloating())) 662 _d3.setY(newY); 663 if (!(src == _d3 && _d4.isFloating() && _d3.isFloating())) 664 _d4.setY(newY); 665 } 666 } 667 668 // Update source text position so position is remembered from loading 567 669 int newTextX = getX(); 568 670 int newTextY = getY(); 569 671 if (_source.getX() != newTextX || _source.getY() != newTextY) 570 672 _source.setPosition(newTextX, newTextY); 571 673 572 674 _settingPositionFlag = false; 573 675 return true; 574 676 } 575 677 576 678 public int getX() { 577 679 return Math.min(_d1.getX(), _d2.getX()); 578 680 } 579 681 580 682 public int getY() { 581 683 return Math.min(_d1.getY(), _d4.getY()); 582 684 } 583 685 584 686 public int getWidth() { 585 687 return Math.abs(_d2.getX() - _d1.getX()); 586 688 } 587 689 588 690 public int getHeight() { 589 691 return Math.abs(_d4.getY() - _d1.getY()); 590 692 } 591 592 /** 593 * The order of the items in the list is as specified: 594 _d1 595 _d2 596 _d3 597 _d4 598 _l1 599 _l2 600 _l3 601 _l4 602 * @return All of the Expeditee items that form the bounderies of this widget 603 * in an unmodifiable list 693 694 /** 695 * The order of the items in the list is as specified: _d1 _d2 _d3 _d4 _l1 696 * _l2 _l3 _l4 697 * 698 * @return All of the Expeditee items that form the bounderies of this 699 * widget in an unmodifiable list 604 700 */ 605 701 public List<Item> getItems() { 606 702 return Collections.unmodifiableList(_items); 607 703 } 608 609 704 610 705 public JComponent getComponant() { 611 706 return _component; 612 707 } 613 614 public final void onParentFameHidden() { 615 onRemovedFromFrame(); 616 } 617 618 public final void onParentFameShown() { 619 onAddedToFrame(); 620 } 621 622 public void onRemovedFromFrame() { 623 if (_component.getParent() != null) { 624 _component.getParent().remove(_component); 625 } 626 } 627 628 public void onAddedToFrame() { 629 630 if (_component.getParent() == null) { 631 if (Browser._theBrowser != null) { 632 // Due to precaching - before adding physical swing componant must check 633 // to see that this widget belongs to a frame that is considered current. 634 if (_d1.getParent() == DisplayIO.getCurrentFrame()) { 635 Browser._theBrowser.getContentPane().add(_component); 636 layout(_component); 637 } 638 639 } else { // if widgets exist on startup frame this will occur 640 641 synchronized(_widgetsToAddLater) { 642 _widgetsToAddLater.add(this); 643 } 644 SwingUtilities.invokeLater(new AddToFrameLater()); 645 } 646 } 647 } 648 649 /** 650 * Must be able to add widgets on first loaded frame: these are loaded before 651 * the browser singleton is made available. 652 */ 653 private static List<InteractiveWidget> _widgetsToAddLater = new LinkedList<InteractiveWidget>(); 654 708 709 public final void onParentFameHidden(WidgetCorner notifier) { 710 onRemovedFromFrame(notifier); 711 } 712 713 public final void onParentFameShown(WidgetCorner notifier, 714 boolean isOverlayed, int overlayLevel) { 715 addJComponantToFrame(notifier, isOverlayed, overlayLevel, true); 716 } 717 718 public void onRemovedFromFrame(WidgetCorner notifier) { 719 if (notifier == _d4) { 720 if (_component.getParent() != null) { 721 _component.getParent().remove(_component); 722 } 723 } 724 } 725 726 public void onAddedToFrame(WidgetCorner notifier, boolean isOverlayed, 727 int overlayLevel) { 728 addJComponantToFrame(notifier, isOverlayed, overlayLevel, false); 729 } 730 731 private void addJComponantToFrame(WidgetCorner notifier, 732 boolean isOverlayed, int overlayLevel, boolean isShown) { 733 if (notifier == _d4) { 734 if (isOverlayed && overlayLevel == Item.PERMISSION_NONE) 735 return; // non-active overlays 736 737 if (_component.getParent() == null) { 738 if (Browser._theBrowser != null) { 739 // Due to precaching - before adding physical swing 740 // componant must check 741 // to see that this widget belongs to a frame that is 742 // considered current. 743 // If the widget is shown however this does not apply - 744 // since it has been explicitly 745 // made clear the the widget is shown. 746 if (isShown 747 || _d1.getParent() == DisplayIO.getCurrentFrame()) { 748 Browser._theBrowser.getContentPane().add(_component); 749 layout(_component); 750 } 751 752 } else { // if widgets exist on startup frame this will occur 753 754 synchronized (_widgetsToAddLater) { 755 _widgetsToAddLater.add(new WidgetInfo(notifier, 756 isOverlayed, overlayLevel, this)); 757 } 758 SwingUtilities.invokeLater(new AddToFrameLater()); 759 } 760 } 761 } 762 } 763 764 /** 765 * Used for passing info to the swing thread 766 * 767 * @author Brook Novak 768 */ 769 class WidgetInfo { 770 771 WidgetInfo(WidgetCorner notifier, boolean isOverlayed, 772 int overlayLevel, InteractiveWidget widget) { 773 _widget = widget; 774 _isOverlayed = isOverlayed; 775 _overlayLevel = overlayLevel; 776 _notifier = notifier; 777 } 778 779 InteractiveWidget _widget; 780 781 boolean _isOverlayed; 782 783 int _overlayLevel; 784 785 WidgetCorner _notifier; 786 } 787 788 /** 789 * Must be able to add widgets on first loaded frame: these are loaded 790 * before the browser singleton is made available. 791 */ 792 private static List<WidgetInfo> _widgetsToAddLater = new LinkedList<WidgetInfo>(); 793 655 794 /** 656 795 * Ensures widgets are added correctly to first loaded frame 657 796 */ 658 publicclass AddToFrameLater implements Runnable {797 class AddToFrameLater implements Runnable { 659 798 public void run() { 660 799 if (!_widgetsToAddLater.isEmpty()) { 661 List< InteractiveWidget> tmp = null;662 synchronized (_widgetsToAddLater) {663 tmp = new LinkedList< InteractiveWidget>(_widgetsToAddLater);800 List<WidgetInfo> tmp = null; 801 synchronized (_widgetsToAddLater) { 802 tmp = new LinkedList<WidgetInfo>(_widgetsToAddLater); 664 803 } 665 804 _widgetsToAddLater.clear(); 666 for (InteractiveWidget iw : tmp) { 667 iw.onAddedToFrame(); 668 } 669 } 670 } 671 } 672 805 for (WidgetInfo iwi : tmp) { 806 iwi._widget.onAddedToFrame(iwi._notifier, iwi._isOverlayed, 807 iwi._overlayLevel); 808 } 809 } 810 } 811 } 812 673 813 /** 674 814 * Due to absolute positioning... 815 * 675 816 * @param parent 676 817 */ 677 818 private void layout(Component parent) { 678 819 679 820 parent.doLayout(); 680 821 681 822 if (parent instanceof Container) { 682 for (Component c : ((Container)parent).getComponents()) { 683 684 if (c instanceof Container) layout(c); 685 else c.doLayout(); 686 } 687 } 688 } 689 690 823 for (Component c : ((Container) parent).getComponents()) { 824 825 if (c instanceof Container) 826 layout(c); 827 else 828 c.doLayout(); 829 } 830 } 831 832 _isReadyToPaint = true; 833 } 691 834 692 835 public void onBoundsChanged() { 693 836 694 837 _component.setBounds(getX(), getY(), getWidth(), getHeight()); 695 696 } 697 838 839 } 840 698 841 /** 699 842 * Paints the widget excluding the boundries. That is, the Swing graphics 843 * 700 844 * @param g 701 845 */ 702 846 public void paint(Graphics g) { 847 848 if (!_isReadyToPaint) { 849 layout(_component); 850 } 703 851 704 852 Point loc = _component.getLocation(); … … 706 854 _component.paint(g); 707 855 g.translate(-loc.x, -(loc.y - 1)); 708 709 } 710 711 /** 712 * Called from the widgets corners: Whenever the corners are repainted 713 * and the widget is floating (e.g. currently picked up / rubberbanding) 714 * then a shaded area is drawn instead of the actual widget so the manipulation of 715 * the widget is as smooth as possible. 716 * The shaded area is only draw once so it selects one of the 4 possible 717 * notifiers to be the actual trigger to draw the shaded area 856 857 } 858 859 /** 860 * Called from the widgets corners: Whenever the corners are repainted and 861 * the widget is floating (e.g. currently picked up / rubberbanding) then a 862 * shaded area is drawn instead of the actual widget so the manipulation of 863 * the widget is as smooth as possible. The shaded area is only draw once so 864 * it selects one of the 4 possible notifiers to be the actual trigger to 865 * draw the shaded area 866 * 718 867 * @param g 719 868 * @param notifier … … 724 873 // paint over the widget interface in these cases: must only 725 874 // paint if an object is floating 726 if (notifier == _d4 && 727 (_d1.isFloating() || 728 _d2.isFloating() || 729 _d3.isFloating() || 730 _d4.isFloating() 731 )) { 875 if (notifier == _d4 876 && (_d1.isFloating() || _d2.isFloating() 877 || _d3.isFloating() || _d4.isFloating())) { 732 878 g.setColor(Color.DARK_GRAY); 733 879 g.fillRect(getX(), getY(), getWidth(), getHeight()); 734 880 } 735 } 736 } 737 881 } 882 } 883 738 884 /** 739 885 * @return True if this widget cannot be resized in either directions 740 886 */ 741 887 public boolean isFixedSize() { 742 return this._minHeight == this._maxHeight && 743 this._minWidth == this._maxWidth && 744 this._minHeight >= 0 && 745 this._minWidth >= 0; 746 } 747 888 return this._minHeight == this._maxHeight 889 && this._minWidth == this._maxWidth && this._minHeight >= 0 890 && this._minWidth >= 0; 891 } 892 748 893 private static boolean _isExepiteeHighlightingEnabled = true; 894 749 895 /** 750 896 * Enables/Disables highlighting of all widgets - if the enable value has 751 897 * changed the current frame will repaint. 752 898 * 753 * The purpose of this is so that widgets can have an extra context: 754 * no expeditee highlighting if focus is on a swing componet. 755 * 756 * @param enable Set to true to enable painting, false to disable painting. 899 * The purpose of this is so that widgets can have an extra context: no 900 * expeditee highlighting if focus is on a swing componet. 901 * 902 * @param enable 903 * Set to true to enable painting, false to disable painting. 757 904 */ 758 905 public static void enableExepiteeHighlighting(boolean enable) { … … 762 909 } 763 910 } 764 911 765 912 public static boolean isExepiteeHighlightingEnabled() { 766 913 return _isExepiteeHighlightingEnabled; 767 914 } 768 769 915 770 916 } -
trunk/src/org/expeditee/items/SampleWidget1.java
r11 r28 49 49 50 50 @Override 51 protected String[] getArgs( ) {51 protected String[] getArgs(boolean isCopy) { 52 52 53 53 String[] stateArgs = new String[_combo.getItemCount() + 1]; … … 58 58 59 59 return stateArgs; 60 }61 62 @Override63 public InteractiveWidget copy() throws InteractiveWidgetNotAvailableException {64 Text t = this.getSource().copy();65 return InteractiveWidget.CreateWidget(t);66 60 } 67 61 -
trunk/src/org/expeditee/items/SampleWidget2.java
r11 r28 12 12 13 13 public class SampleWidget2 extends InteractiveWidget { 14 15 14 16 15 private JComboBox _combo; … … 70 69 int div = Integer.parseInt(args[2]); 71 70 ((JSplitPane)super._component).setDividerLocation(div); 72 } catch (NumberFormatException e) { 73 e.printStackTrace(); 74 } 71 } catch (NumberFormatException e) {} 75 72 76 73 } … … 81 78 82 79 @Override 83 protected String[] getArgs( ) {80 protected String[] getArgs(boolean isCopy) { 84 81 return new String[] { 85 82 Integer.toString(_combo.getSelectedIndex()), … … 90 87 91 88 @Override 92 public InteractiveWidget copy() throws InteractiveWidgetNotAvailableException {93 Text t = this.getSource().copy();94 return InteractiveWidget.CreateWidget(t);95 }96 97 @Override98 89 protected String getTopMostClassName() { 99 90 return getClass().getName(); -
trunk/src/org/expeditee/items/WidgetCorner.java
r11 r28 32 32 public void onParentFameHidden() { 33 33 super.onParentFameHidden(); 34 _widgetSource.onParentFameHidden( );34 _widgetSource.onParentFameHidden(this); 35 35 } 36 36 37 37 @Override 38 public void onParentFameShown( ) {39 super.onParentFameShown( );40 _widgetSource.onParentFameShown( );38 public void onParentFameShown(boolean isOverlayed, int overlayLevel) { 39 super.onParentFameShown(isOverlayed, overlayLevel); 40 _widgetSource.onParentFameShown(this, isOverlayed, overlayLevel); 41 41 } 42 42 … … 44 44 public void onRemovedFromFrame() { 45 45 super.onRemovedFromFrame(); 46 _widgetSource.onRemovedFromFrame( );46 _widgetSource.onRemovedFromFrame(this); 47 47 } 48 48 49 49 @Override 50 public void onAddedToFrame( ) {51 super.onAddedToFrame( );52 _widgetSource.onAddedToFrame( );50 public void onAddedToFrame(boolean isOverlayed, int overlayLevel) { 51 super.onAddedToFrame(isOverlayed, overlayLevel); 52 _widgetSource.onAddedToFrame(this, isOverlayed, overlayLevel); 53 53 } 54 54
Note:
See TracChangeset
for help on using the changeset viewer.