1 29 30 package nextapp.echo2.app; 31 32 import java.beans.PropertyChangeListener ; 33 import java.beans.PropertyChangeSupport ; 34 import java.io.Serializable ; 35 import java.lang.ref.WeakReference ; 36 import java.util.ArrayList ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 import java.util.List ; 40 import java.util.Locale ; 41 import java.util.Map ; 42 43 import nextapp.echo2.app.update.ServerUpdateManager; 44 import nextapp.echo2.app.update.UpdateManager; 45 import nextapp.echo2.app.util.Uid; 46 47 50 public abstract class ApplicationInstance 51 implements Serializable { 52 53 54 public static final String ID_STRING = "NextApp Echo v2.1.0.rc2"; 55 56 public static final String FOCUSED_COMPONENT_CHANGED_PROPERTY = "focusedComponent"; 57 public static final String LOCALE_CHANGED_PROPERTY = "locale"; 58 public static final String MODAL_COMPONENTS_CHANGED_PROPERTY = "modalComponents"; 59 public static final String WINDOWS_CHANGED_PROPERTY = "windows"; 60 61 65 private static final ThreadLocal activeInstance = new InheritableThreadLocal (); 66 67 74 public static final String generateSystemId() { 75 return Uid.generateUidString(); 76 } 77 78 84 public static final ApplicationInstance getActive() { 85 return (ApplicationInstance) activeInstance.get(); 86 } 87 88 98 public static final void setActive(ApplicationInstance applicationInstance) { 99 activeInstance.set(applicationInstance); 100 } 101 102 105 private transient WeakReference focusedComponent; 106 107 111 private Locale locale; 112 113 119 private LayoutDirection layoutDirection; 120 121 125 private Map context; 126 127 131 private Map renderIdToComponentMap; 132 133 138 private HashMap taskQueueMap; 139 140 143 private PropertyChangeSupport propertyChangeSupport; 144 145 148 private UpdateManager updateManager; 149 150 155 private Window defaultWindow; 156 157 160 private StyleSheet styleSheet; 161 162 166 private List modalComponents; 167 168 173 private long nextId; 174 175 178 public ApplicationInstance() { 179 super(); 180 181 locale = Locale.getDefault(); 182 layoutDirection = LayoutDirection.forLocale(locale); 183 184 propertyChangeSupport = new PropertyChangeSupport (this); 185 updateManager = new UpdateManager(this); 186 renderIdToComponentMap = new HashMap (); 187 taskQueueMap = new HashMap (); 188 } 189 190 196 public void addPropertyChangeListener(PropertyChangeListener l) { 197 propertyChangeSupport.addPropertyChangeListener(l); 198 } 199 200 211 public TaskQueueHandle createTaskQueue() { 212 TaskQueueHandle taskQueue = new TaskQueueHandle() { }; 213 synchronized (taskQueueMap) { 214 taskQueueMap.put(taskQueue, null); 215 } 216 return taskQueue; 217 } 218 219 227 public final Window doInit() { 228 if (this != activeInstance.get()) { 229 throw new IllegalStateException ( 230 "Attempt to update state of application user interface outside of user interface thread."); 231 } 232 Window window = init(); 233 setDefaultWindow(window); 234 doValidation(); 235 return window; 236 } 237 238 241 public final void doValidation() { 242 doValidation(defaultWindow); 243 } 244 245 253 private void doValidation(Component c) { 254 c.validate(); 255 int size = c.getComponentCount(); 256 for (int index = 0; index < size; ++index) { 257 doValidation(c.getComponent(index)); 258 } 259 } 260 261 267 public void enqueueCommand(Command command) { 268 updateManager.getServerUpdateManager().enqueueCommand(command); 269 } 270 271 282 public void enqueueTask(TaskQueueHandle taskQueue, Runnable task) { 283 synchronized (taskQueueMap) { 284 List taskList = (List ) taskQueueMap.get(taskQueue); 285 if (taskList == null) { 286 taskList = new ArrayList (); 287 taskQueueMap.put(taskQueue, taskList); 288 } 289 taskList.add(task); 290 } 291 } 292 293 300 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { 301 propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); 302 } 303 304 312 public String generateId() { 313 return Long.toString(nextId++); 314 } 315 316 327 public Object getContextProperty(String propertyName) { 328 return context == null ? null : context.get(propertyName); 329 } 330 331 339 public Component getComponentByRenderId(String renderId) { 340 return (Component) renderIdToComponentMap.get(renderId); 341 } 342 343 348 public Window getDefaultWindow() { 349 return defaultWindow; 350 } 351 352 357 public Component getFocusedComponent() { 358 if (focusedComponent == null) { 359 return null; 360 } else { 361 return (Component) focusedComponent.get(); 362 } 363 } 364 365 371 public LayoutDirection getLayoutDirection() { 372 return layoutDirection; 373 } 374 375 380 public Locale getLocale() { 381 return locale; 382 } 383 384 392 public Component getModalContextRoot() { 393 if (modalComponents == null || modalComponents.size() == 0) { 394 return null; 395 } else { 396 for (int i = modalComponents.size() - 1; i >= 0; --i) { 397 Component component = (Component) modalComponents.get(i); 398 if (component.isRenderVisible()) { 400 return component; 401 } 402 } 403 return null; 404 } 405 } 406 407 416 public Style getStyle(Class componentClass, String styleName) { 417 if (styleSheet == null) { 418 return null; 419 } else { 420 return styleSheet.getStyle(componentClass, styleName); 421 } 422 } 423 424 430 public UpdateManager getUpdateManager() { 431 return updateManager; 432 } 433 434 440 public final boolean hasTaskQueues() { 441 return taskQueueMap.size() > 0; 442 } 443 444 458 public boolean hasQueuedTasks() { 459 if (taskQueueMap.size() == 0) { 460 return false; 461 } 462 Iterator it = taskQueueMap.values().iterator(); 463 while (it.hasNext()) { 464 List taskList = (List ) it.next(); 465 if (taskList != null && taskList.size() > 0) { 466 return true; 467 } 468 } 469 return false; 470 } 471 472 479 private boolean isModal(Component component) { 480 return modalComponents != null && modalComponents.contains(component); 481 } 482 483 489 public abstract Window init(); 490 491 510 void notifyComponentPropertyChange(Component parent, String propertyName, Object oldValue, Object newValue) { 511 if (this != activeInstance.get()) { 513 throw new IllegalStateException ( 514 "Attempt to update state of application user interface outside of user interface thread."); 515 } 516 517 ServerUpdateManager serverUpdateManager = updateManager.getServerUpdateManager(); 518 if (Component.CHILDREN_CHANGED_PROPERTY.equals(propertyName)) { 519 if (newValue == null) { 520 serverUpdateManager.processComponentRemove(parent, (Component) oldValue); 521 } else { 522 serverUpdateManager.processComponentAdd(parent, (Component) newValue); 523 } 524 } else if (Component.PROPERTY_LAYOUT_DATA.equals(propertyName)) { 525 serverUpdateManager.processComponentLayoutDataUpdate(parent); 526 } else if (Component.VISIBLE_CHANGED_PROPERTY.equals(propertyName)) { 527 if (oldValue != null && newValue != null && oldValue.equals(newValue)) { 528 return; 529 } 530 serverUpdateManager.processComponentVisibilityUpdate(parent); 531 } else { 532 if (oldValue != null && newValue != null && oldValue.equals(newValue)) { 533 return; 534 } 535 if (parent instanceof ModalSupport && ModalSupport.MODAL_CHANGED_PROPERTY.equals(propertyName)) { 536 setModal(parent, ((Boolean ) newValue).booleanValue()); 537 } 538 serverUpdateManager.processComponentPropertyUpdate(parent, propertyName, oldValue, newValue); 539 } 540 } 541 542 548 public void processInput(String propertyName, Object propertyValue) { 549 if (FOCUSED_COMPONENT_CHANGED_PROPERTY.equals(propertyName)) { 550 setFocusedComponent((Component) propertyValue); 551 } 552 } 553 554 559 public void processQueuedTasks() { 560 if (taskQueueMap.size() == 0) { 561 return; 562 } 563 564 List currentTasks = new ArrayList (); 565 synchronized (taskQueueMap) { 566 Iterator taskListsIt = taskQueueMap.values().iterator(); 567 while (taskListsIt.hasNext()) { 568 List tasks = (List ) taskListsIt.next(); 569 if (tasks != null) { 570 currentTasks.addAll(tasks); 571 tasks.clear(); 572 } 573 } 574 } 575 Iterator it = currentTasks.iterator(); 576 while (it.hasNext()) { 577 ((Runnable ) it.next()).run(); 578 } 579 } 580 581 591 void registerComponent(Component component) { 592 String renderId = component.getRenderId(); 593 if (renderId == null || renderIdToComponentMap.containsKey(renderId)) { 594 component.assignRenderId(generateId()); 597 } 598 renderIdToComponentMap.put(component.getRenderId(), component); 599 if (component instanceof ModalSupport && ((ModalSupport) component).isModal()) { 600 setModal(component, true); 601 } 602 } 603 604 610 public void removePropertyChangeListener(PropertyChangeListener l) { 611 propertyChangeSupport.removePropertyChangeListener(l); 612 } 613 614 622 public void removeTaskQueue(TaskQueueHandle taskQueueHandle) { 623 synchronized(taskQueueMap) { 624 taskQueueMap.remove(taskQueueHandle); 625 } 626 } 627 628 636 public void setContextProperty(String propertyName, Object propertyValue) { 637 if (context == null) { 638 context = new HashMap (); 639 } 640 if (propertyValue == null) { 641 context.remove(propertyName); 642 } else { 643 context.put(propertyName, propertyValue); 644 } 645 } 646 647 652 private void setDefaultWindow(Window window) { 653 if (defaultWindow != null) { 654 throw new UnsupportedOperationException ("Default window already set."); 655 } 656 657 defaultWindow = window; 658 window.register(this); 659 firePropertyChange(WINDOWS_CHANGED_PROPERTY, null, window); 660 window.doInit(); 661 } 662 663 668 public void setFocusedComponent(Component newValue) { 669 if (newValue instanceof DelegateFocusSupport) { 670 newValue = ((DelegateFocusSupport) newValue).getFocusComponent(); 671 } 672 673 Component oldValue = getFocusedComponent(); 674 if (newValue == null) { 675 focusedComponent = null; 676 } else { 677 focusedComponent = new WeakReference (newValue); 678 } 679 propertyChangeSupport.firePropertyChange(FOCUSED_COMPONENT_CHANGED_PROPERTY, oldValue, newValue); 680 updateManager.getServerUpdateManager().processApplicationPropertyUpdate(FOCUSED_COMPONENT_CHANGED_PROPERTY, 681 oldValue, newValue); 682 } 683 684 689 public void setLocale(Locale newValue) { 690 if (newValue == null) { 691 throw new IllegalArgumentException ("ApplicationInstance Locale may not be null."); 692 } 693 Locale oldValue = locale; 694 locale = newValue; 695 layoutDirection = LayoutDirection.forLocale(locale); 696 propertyChangeSupport.firePropertyChange(LOCALE_CHANGED_PROPERTY, oldValue, newValue); 697 updateManager.getServerUpdateManager().processFullRefresh(); 698 } 699 700 707 private void setModal(Component component, boolean newValue) { 708 boolean oldValue = isModal(component); 709 if (newValue) { 710 if (modalComponents == null) { 711 modalComponents = new ArrayList (); 712 } 713 if (!modalComponents.contains(component)) { 714 modalComponents.add(component); 715 } 716 } else { 717 if (modalComponents != null) { 718 modalComponents.remove(component); 719 } 720 } 721 firePropertyChange(MODAL_COMPONENTS_CHANGED_PROPERTY, new Boolean (oldValue), new Boolean (newValue)); 722 } 723 724 740 public void setStyleSheet(StyleSheet styleSheet) { 741 this.styleSheet = styleSheet; 742 updateManager.getServerUpdateManager().processFullRefresh(); 743 } 744 745 753 void unregisterComponent(Component component) { 754 renderIdToComponentMap.remove(component.getRenderId()); 755 if (component instanceof ModalSupport && ((ModalSupport) component).isModal()) { 756 setModal(component, false); 757 } 758 } 759 760 770 boolean verifyModalContext(Component component) { 771 Component modalContextRoot = getModalContextRoot(); 772 return modalContextRoot == null || modalContextRoot.isAncestorOf(component); 773 } 774 } 775 | Popular Tags |