1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package org.openoffice.java.accessibility; 25 26 import com.sun.star.uno.*; 27 import com.sun.star.accessibility.*; 28 29 public class Frame extends java.awt.Frame implements javax.accessibility.Accessible, NativeFrame { 30 protected XAccessibleComponent unoAccessibleComponent; 31 32 boolean opened = false; 33 boolean visible = false; 34 boolean active = false; 35 36 java.awt.EventQueue eventQueue = null; 37 Frame(XAccessibleComponent xAccessibleComponent)38 protected Frame(XAccessibleComponent xAccessibleComponent) { 39 initialize(xAccessibleComponent); 40 } 41 Frame(String name, XAccessibleComponent xAccessibleComponent)42 protected Frame(String name, XAccessibleComponent xAccessibleComponent) { 43 super(name); 44 initialize(xAccessibleComponent); 45 } 46 initialize(XAccessibleComponent xAccessibleComponent)47 private void initialize(XAccessibleComponent xAccessibleComponent) { 48 unoAccessibleComponent = xAccessibleComponent; 49 eventQueue = java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue(); 50 XAccessibleEventBroadcaster broadcaster = (XAccessibleEventBroadcaster) 51 UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class, 52 unoAccessibleComponent); 53 if (broadcaster != null) { 54 broadcaster.addEventListener(new AccessibleFrameListener()); 55 } 56 } 57 58 java.awt.Component initialComponent = null; 59 getInitialComponent()60 public java.awt.Component getInitialComponent() { 61 return initialComponent; 62 } 63 setInitialComponent(java.awt.Component c)64 public void setInitialComponent(java.awt.Component c) { 65 initialComponent = c; 66 } 67 getHWND()68 public Integer getHWND() { 69 return null; 70 } 71 72 /** 73 * Determines whether this <code>Component</code> is showing on screen. 74 * This means that the component must be visible, and it must be in a 75 * <code>container</code> that is visible and showing. 76 * @see #addNotify 77 * @see #removeNotify 78 * @since JDK1.0 79 */ isShowing()80 public boolean isShowing() { 81 if (isVisible()) { 82 java.awt.Container parent = getParent(); 83 return (parent == null) || parent.isShowing(); 84 } 85 return false; 86 } 87 88 /** 89 * Makes this <code>Component</code> displayable by connecting it to a 90 * native screen resource. 91 * This method is called internally by the toolkit and should 92 * not be called directly by programs. 93 * @see #isDisplayable 94 * @see #removeNotify 95 * @since JDK1.0 96 */ addNotify()97 public void addNotify() { 98 // createHierarchyEvents(0, null, null, 0, false); 99 } 100 101 /** 102 * Makes this <code>Component</code> undisplayable by destroying it native 103 * screen resource. 104 * This method is called by the toolkit internally and should 105 * not be called directly by programs. 106 * @see #isDisplayable 107 * @see #addNotify 108 * @since JDK1.0 109 */ removeNotify()110 public void removeNotify() { 111 } 112 113 /** 114 * Determines if the object is visible. Note: this means that the 115 * object intends to be visible; however, it may not in fact be 116 * showing on the screen because one of the objects that this object 117 * is contained by is not visible. To determine if an object is 118 * showing on the screen, use <code>isShowing</code>. 119 * 120 * @return true if object is visible; otherwise, false 121 */ isVisible()122 public boolean isVisible(){ 123 return visible; 124 } 125 126 /** 127 * Shows or hides this component depending on the value of parameter 128 * <code>b</code>. 129 * @param b if <code>true</code>, shows this component; 130 * otherwise, hides this component 131 * @see #isVisible 132 * @since JDK1.1 133 */ setVisible(boolean b)134 public void setVisible(boolean b) { 135 if (visible != b){ 136 visible = b; 137 if (b) { 138 // If it is the first show, fire WINDOW_OPENED event 139 if (!opened) { 140 postWindowEvent(java.awt.event.WindowEvent.WINDOW_OPENED); 141 opened = true; 142 } 143 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_SHOWN); 144 } else { 145 postComponentEvent(java.awt.event.ComponentEvent.COMPONENT_HIDDEN); 146 } 147 } 148 } 149 dispose()150 public void dispose() { 151 setVisible(false); 152 postWindowEvent(java.awt.event.WindowEvent.WINDOW_CLOSED); 153 } 154 postWindowEvent(int i)155 protected void postWindowEvent(int i) { 156 eventQueue.postEvent(new java.awt.event.WindowEvent(this, i)); 157 } 158 postComponentEvent(int i)159 protected void postComponentEvent(int i) { 160 eventQueue.postEvent(new java.awt.event.ComponentEvent(this, i)); 161 } 162 163 /** 164 * Update the proxy objects appropriately on property change events 165 */ 166 protected class AccessibleFrameListener implements XAccessibleEventListener { 167 AccessibleFrameListener()168 protected AccessibleFrameListener() { 169 } 170 171 // The only expected state changes are ACTIVE and VISIBLE setComponentState(short state, boolean enable)172 protected void setComponentState(short state, boolean enable) { 173 switch (state) { 174 case AccessibleStateType.ACTIVE: 175 active = enable; 176 if (enable) { 177 AccessibleObjectFactory.postWindowActivated(Frame.this); 178 } else { 179 AccessibleObjectFactory.postWindowLostFocus(Frame.this); 180 } 181 break; 182 case AccessibleStateType.ICONIFIED: 183 if (Build.DEBUG) { 184 System.err.println("[frame]" + getTitle() + (enable ? " is now " : " is no longer ") + "iconified"); 185 } 186 postWindowEvent(enable ? 187 java.awt.event.WindowEvent.WINDOW_ICONIFIED : 188 java.awt.event.WindowEvent.WINDOW_DEICONIFIED); 189 break; 190 case AccessibleStateType.VISIBLE: 191 Frame.this.setVisible(enable); 192 break; 193 default: 194 if (Build.DEBUG) { 195 System.err.println("[frame]: " + getTitle() + "unexpected state change " + state); 196 } 197 break; 198 } 199 } 200 201 /** Updates the accessible name and fires the appropriate PropertyChangedEvent */ handleNameChangedEvent(Object any)202 protected void handleNameChangedEvent(Object any) { 203 try { 204 String title = AnyConverter.toString(any); 205 setTitle(title); 206 // This causes the property change event to be fired in the VCL thread 207 // context. If this causes problems, it has to be deligated to the java 208 // dispatch thread .. 209 javax.accessibility.AccessibleContext ac = accessibleContext; 210 if (ac!= null) { 211 ac.setAccessibleName(title); 212 } 213 } catch (com.sun.star.lang.IllegalArgumentException e) { 214 } 215 } 216 217 /** Updates the accessible description and fires the appropriate PropertyChangedEvent */ handleDescriptionChangedEvent(Object any)218 protected void handleDescriptionChangedEvent(Object any) { 219 try { 220 // This causes the property change event to be fired in the VCL thread 221 // context. If this causes problems, it has to be deligated to the java 222 // dispatch thread .. 223 javax.accessibility.AccessibleContext ac = accessibleContext; 224 if (ac!= null) { 225 ac.setAccessibleDescription(AnyConverter.toString(any)); 226 } 227 } catch (com.sun.star.lang.IllegalArgumentException e) { 228 } 229 } 230 231 /** Updates the internal states and fires the appropriate PropertyChangedEvent */ handleStateChangedEvent(Object any1, Object any2)232 protected void handleStateChangedEvent(Object any1, Object any2) { 233 try { 234 if (AnyConverter.isShort(any1)) { 235 setComponentState(AnyConverter.toShort(any1), false); 236 } 237 238 if (AnyConverter.isShort(any2)) { 239 setComponentState(AnyConverter.toShort(any2), true); 240 } 241 } 242 243 catch (com.sun.star.lang.IllegalArgumentException e) { 244 } 245 } 246 247 /** Fires a visible data property change event */ handleVisibleDataEvent()248 protected void handleVisibleDataEvent() { 249 javax.accessibility.AccessibleContext ac = accessibleContext; 250 if (ac != null) { 251 ac.firePropertyChange(javax.accessibility.AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, null, null); 252 } 253 } 254 255 /** Called by OpenOffice process to notify property changes */ notifyEvent(AccessibleEventObject event)256 public void notifyEvent(AccessibleEventObject event) { 257 switch (event.EventId) { 258 case AccessibleEventId.NAME_CHANGED: 259 // Set the accessible name for the corresponding context, which will fire a property 260 // change event itself 261 handleNameChangedEvent(event.NewValue); 262 break; 263 case AccessibleEventId.DESCRIPTION_CHANGED: 264 // Set the accessible description for the corresponding context, which will fire a property 265 // change event itself - so do not set propertyName ! 266 handleDescriptionChangedEvent(event.NewValue); 267 break; 268 case AccessibleEventId.STATE_CHANGED: 269 // Update the internal state set and fire the appropriate PropertyChangedEvent 270 handleStateChangedEvent(event.OldValue, event.NewValue); 271 break; 272 case AccessibleEventId.CHILD: 273 if (AnyConverter.isObject(event.OldValue)) { 274 AccessibleObjectFactory.removeChild(Frame.this, event.OldValue); 275 } else if (AnyConverter.isObject(event.NewValue)) { 276 AccessibleObjectFactory.addChild(Frame.this, event.NewValue); 277 } 278 break; 279 case AccessibleEventId.VISIBLE_DATA_CHANGED: 280 case AccessibleEventId.BOUNDRECT_CHANGED: 281 handleVisibleDataEvent(); 282 break; 283 default: 284 // Warn about unhandled events 285 if(Build.DEBUG) { 286 System.out.println(this + ": unhandled accessibility event id=" + event.EventId); 287 } 288 } 289 } 290 291 /** Called by OpenOffice process to notify that the UNO component is disposing */ disposing(com.sun.star.lang.EventObject eventObject)292 public void disposing(com.sun.star.lang.EventObject eventObject) { 293 } 294 } 295 296 protected javax.accessibility.AccessibleContext accessibleContext = null; 297 298 /** Returns the AccessibleContext associated with this object */ getAccessibleContext()299 public javax.accessibility.AccessibleContext getAccessibleContext() { 300 if (accessibleContext == null) { 301 accessibleContext = new AccessibleFrame(); 302 accessibleContext.setAccessibleName(getTitle()); 303 } 304 return accessibleContext; 305 } 306 307 protected class AccessibleFrame extends java.awt.Frame.AccessibleAWTFrame { AccessibleFrame()308 protected AccessibleFrame() { 309 super(); 310 } 311 312 protected java.awt.event.ComponentListener accessibleComponentHandler = null; 313 314 /** 315 * Fire PropertyChange listener, if one is registered, 316 * when shown/hidden.. 317 */ 318 protected class AccessibleComponentHandler implements java.awt.event.ComponentListener { componentHidden(java.awt.event.ComponentEvent e)319 public void componentHidden(java.awt.event.ComponentEvent e) { 320 AccessibleFrame.this.firePropertyChange( 321 javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 322 javax.accessibility.AccessibleState.VISIBLE, null); 323 } 324 componentShown(java.awt.event.ComponentEvent e)325 public void componentShown(java.awt.event.ComponentEvent e) { 326 AccessibleFrame.this.firePropertyChange( 327 javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 328 null, javax.accessibility.AccessibleState.VISIBLE); 329 } 330 componentMoved(java.awt.event.ComponentEvent e)331 public void componentMoved(java.awt.event.ComponentEvent e) { 332 } 333 componentResized(java.awt.event.ComponentEvent e)334 public void componentResized(java.awt.event.ComponentEvent e) { 335 } 336 } // inner class AccessibleComponentHandler 337 338 protected java.awt.event.WindowListener accessibleWindowHandler = null; 339 340 /** 341 * Fire PropertyChange listener, if one is registered, 342 * when window events happen 343 */ 344 protected class AccessibleWindowHandler implements java.awt.event.WindowListener { 345 /** Invoked when the Window is set to be the active Window. */ windowActivated(java.awt.event.WindowEvent e)346 public void windowActivated(java.awt.event.WindowEvent e) { 347 AccessibleFrame.this.firePropertyChange( 348 javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 349 null, javax.accessibility.AccessibleState.ACTIVE); 350 if (Build.DEBUG) { 351 System.err.println("[frame] " + getTitle() + " is now active"); 352 } 353 } 354 355 /** Invoked when a window has been closed as the result of calling dispose on the window. */ windowClosed(java.awt.event.WindowEvent e)356 public void windowClosed(java.awt.event.WindowEvent e) { 357 if (Build.DEBUG) { 358 System.err.println("[frame] " + getTitle() + " has been closed"); 359 } 360 } 361 362 /** Invoked when the user attempts to close the window from the window's system menu. */ windowClosing(java.awt.event.WindowEvent e)363 public void windowClosing(java.awt.event.WindowEvent e) { 364 if (Build.DEBUG) { 365 System.err.println("[frame] " + getTitle() + " is closing"); 366 } 367 } 368 369 /** Invoked when a Window is no longer the active Window. */ windowDeactivated(java.awt.event.WindowEvent e)370 public void windowDeactivated(java.awt.event.WindowEvent e) { 371 AccessibleFrame.this.firePropertyChange( 372 javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY, 373 javax.accessibility.AccessibleState.ACTIVE, null); 374 if (Build.DEBUG) { 375 System.err.println("[frame] " + getTitle() + " is no longer active"); 376 } 377 } 378 379 /** Invoked when a window is changed from a minimized to a normal state. */ windowDeiconified(java.awt.event.WindowEvent e)380 public void windowDeiconified(java.awt.event.WindowEvent e) { 381 if (Build.DEBUG) { 382 System.err.println("[frame] " + getTitle() + " is no longer iconified"); 383 } 384 } 385 386 /** Invoked when a window is changed from a normal to a minimized state. */ windowIconified(java.awt.event.WindowEvent e)387 public void windowIconified(java.awt.event.WindowEvent e) { 388 if (Build.DEBUG) { 389 System.err.println("[frame] " + getTitle() + " has been iconified"); 390 } 391 } 392 393 /** Invoked the first time a window is made visible. */ windowOpened(java.awt.event.WindowEvent e)394 public void windowOpened(java.awt.event.WindowEvent e) { 395 if (Build.DEBUG) { 396 System.err.println("[frame] " + getTitle() + " has been opened"); 397 } 398 } 399 400 } // inner class AccessibleWindowHandler 401 402 protected java.awt.event.ContainerListener accessibleContainerHandler = null; 403 404 /** 405 * Fire PropertyChange listener, if one is registered, 406 * when children added/removed. 407 */ 408 409 protected class AccessibleContainerHandler implements java.awt.event.ContainerListener { componentAdded(java.awt.event.ContainerEvent e)410 public void componentAdded(java.awt.event.ContainerEvent e) { 411 java.awt.Component c = e.getChild(); 412 if (c != null && c instanceof javax.accessibility.Accessible) { 413 AccessibleFrame.this.firePropertyChange( 414 javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 415 null, ((javax.accessibility.Accessible) c).getAccessibleContext()); 416 } 417 } componentRemoved(java.awt.event.ContainerEvent e)418 public void componentRemoved(java.awt.event.ContainerEvent e) { 419 java.awt.Component c = e.getChild(); 420 if (c != null && c instanceof javax.accessibility.Accessible) { 421 AccessibleFrame.this.firePropertyChange( 422 javax.accessibility.AccessibleContext.ACCESSIBLE_CHILD_PROPERTY, 423 ((javax.accessibility.Accessible) c).getAccessibleContext(), null); 424 } 425 } 426 } 427 428 protected int propertyChangeListenerCount = 0; 429 430 /** 431 * Add a PropertyChangeListener to the listener list. 432 * 433 * @param listener The PropertyChangeListener to be added 434 */ addPropertyChangeListener(java.beans.PropertyChangeListener listener)435 public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) { 436 if (propertyChangeListenerCount++ == 0) { 437 accessibleWindowHandler = new AccessibleWindowHandler(); 438 Frame.this.addWindowListener(accessibleWindowHandler); 439 440 accessibleContainerHandler = new AccessibleContainerHandler(); 441 Frame.this.addContainerListener(accessibleContainerHandler); 442 443 accessibleComponentHandler = new AccessibleComponentHandler(); 444 Frame.this.addComponentListener(accessibleComponentHandler); 445 } 446 super.addPropertyChangeListener(listener); 447 } 448 449 /** 450 * Remove a PropertyChangeListener from the listener list. 451 * This removes a PropertyChangeListener that was registered 452 * for all properties. 453 * 454 * @param listener The PropertyChangeListener to be removed 455 */ removePropertyChangeListener(java.beans.PropertyChangeListener listener)456 public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) { 457 if (--propertyChangeListenerCount == 0) { 458 Frame.this.removeComponentListener(accessibleComponentHandler); 459 accessibleComponentHandler = null; 460 461 Frame.this.removeContainerListener(accessibleContainerHandler); 462 accessibleContainerHandler = null; 463 464 Frame.this.removeWindowListener(accessibleWindowHandler); 465 accessibleWindowHandler = null; 466 } 467 super.removePropertyChangeListener(listener); 468 } 469 470 /** 471 * Get the state set of this object. 472 * 473 * @return an instance of AccessibleState containing the current state 474 * of the object 475 * @see javax.accessibility.AccessibleState 476 */ getAccessibleStateSet()477 public javax.accessibility.AccessibleStateSet getAccessibleStateSet() { 478 javax.accessibility.AccessibleStateSet states = super.getAccessibleStateSet(); 479 if ((getExtendedState() & java.awt.Frame.ICONIFIED) > 0) { 480 states.add(javax.accessibility.AccessibleState.ICONIFIED); 481 } 482 return states; 483 } 484 485 /* 486 * AccessibleComponent 487 */ 488 489 /** Returns the background color of the object */ getBackground()490 public java.awt.Color getBackground() { 491 try { 492 return new java.awt.Color(unoAccessibleComponent.getBackground()); 493 } catch (com.sun.star.uno.RuntimeException e) { 494 return null; 495 } 496 } 497 setBackground(java.awt.Color c)498 public void setBackground(java.awt.Color c) { 499 // Not supported by UNO accessibility API 500 } 501 502 /** Returns the foreground color of the object */ getForeground()503 public java.awt.Color getForeground() { 504 try { 505 return new java.awt.Color(unoAccessibleComponent.getForeground()); 506 } catch (com.sun.star.uno.RuntimeException e) { 507 return null; 508 } 509 } 510 setForeground(java.awt.Color c)511 public void setForeground(java.awt.Color c) { 512 // Not supported by UNO accessibility API 513 } 514 getCursor()515 public java.awt.Cursor getCursor() { 516 // Not supported by UNO accessibility API 517 return null; 518 } 519 setCursor(java.awt.Cursor cursor)520 public void setCursor(java.awt.Cursor cursor) { 521 // Not supported by UNO accessibility API 522 } 523 getFont()524 public java.awt.Font getFont() { 525 // FIXME 526 return null; 527 } 528 setFont(java.awt.Font f)529 public void setFont(java.awt.Font f) { 530 // Not supported by UNO accessibility API 531 } 532 getFontMetrics(java.awt.Font f)533 public java.awt.FontMetrics getFontMetrics(java.awt.Font f) { 534 // FIXME 535 return null; 536 } 537 isEnabled()538 public boolean isEnabled() { 539 return Frame.this.isEnabled(); 540 } 541 setEnabled(boolean b)542 public void setEnabled(boolean b) { 543 // Not supported by UNO accessibility API 544 } 545 isVisible()546 public boolean isVisible() { 547 return Frame.this.isVisible(); 548 } 549 setVisible(boolean b)550 public void setVisible(boolean b) { 551 // Not supported by UNO accessibility API 552 } 553 isShowing()554 public boolean isShowing() { 555 return Frame.this.isShowing(); 556 } 557 contains(java.awt.Point p)558 public boolean contains(java.awt.Point p) { 559 try { 560 return unoAccessibleComponent.containsPoint(new com.sun.star.awt.Point(p.x, p.y)); 561 } catch (com.sun.star.uno.RuntimeException e) { 562 return false; 563 } 564 } 565 566 /** Returns the location of the object on the screen. */ getLocationOnScreen()567 public java.awt.Point getLocationOnScreen() { 568 try { 569 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocationOnScreen(); 570 return new java.awt.Point(unoPoint.X, unoPoint.Y); 571 } catch (com.sun.star.uno.RuntimeException e) { 572 return null; 573 } 574 } 575 576 /** Gets the location of this component in the form of a point specifying the component's top-left corner */ getLocation()577 public java.awt.Point getLocation() { 578 try { 579 com.sun.star.awt.Point unoPoint = unoAccessibleComponent.getLocation(); 580 return new java.awt.Point( unoPoint.X, unoPoint.Y ); 581 } catch (com.sun.star.uno.RuntimeException e) { 582 return null; 583 } 584 } 585 586 /** Moves this component to a new location */ setLocation(java.awt.Point p)587 public void setLocation(java.awt.Point p) { 588 // Not supported by UNO accessibility API 589 } 590 591 /** Gets the bounds of this component in the form of a Rectangle object */ getBounds()592 public java.awt.Rectangle getBounds() { 593 try { 594 com.sun.star.awt.Rectangle unoRect = unoAccessibleComponent.getBounds(); 595 return new java.awt.Rectangle(unoRect.X, unoRect.Y, unoRect.Width, unoRect.Height); 596 } catch (com.sun.star.uno.RuntimeException e) { 597 return null; 598 } 599 } 600 601 /** Moves and resizes this component to conform to the new bounding rectangle r */ setBounds(java.awt.Rectangle r)602 public void setBounds(java.awt.Rectangle r) { 603 // Not supported by UNO accessibility API 604 } 605 606 /** Returns the size of this component in the form of a Dimension object */ getSize()607 public java.awt.Dimension getSize() { 608 try { 609 com.sun.star.awt.Size unoSize = unoAccessibleComponent.getSize(); 610 return new java.awt.Dimension(unoSize.Width, unoSize.Height); 611 } catch (com.sun.star.uno.RuntimeException e) { 612 return null; 613 } 614 } 615 616 /** Resizes this component so that it has width d.width and height d.height */ setSize(java.awt.Dimension d)617 public void setSize(java.awt.Dimension d) { 618 // Not supported by UNO accessibility API 619 } 620 621 /** Returns the Accessible child, if one exists, contained at the local coordinate Point */ getAccessibleAt(java.awt.Point p)622 public javax.accessibility.Accessible getAccessibleAt(java.awt.Point p) { 623 try { 624 java.awt.Component c = AccessibleObjectFactory.getAccessibleComponent( 625 unoAccessibleComponent.getAccessibleAtPoint(new com.sun.star.awt.Point(p.x, p.y))); 626 627 return (javax.accessibility.Accessible) c; 628 } catch (com.sun.star.uno.RuntimeException e) { 629 return null; 630 } 631 } 632 isFocusTraversable()633 public boolean isFocusTraversable() { 634 return Frame.this.isFocusable(); 635 } 636 requestFocus()637 public void requestFocus() { 638 unoAccessibleComponent.grabFocus(); 639 } 640 } 641 642 /** 643 * Determines whether this component is displayable. A component is 644 * displayable when it is connected to a native screen resource. 645 * <p> 646 * A component is made displayable either when it is added to 647 * a displayable containment hierarchy or when its containment 648 * hierarchy is made displayable. 649 * A containment hierarchy is made displayable when its ancestor 650 * window is either packed or made visible. 651 * <p> 652 * A component is made undisplayable either when it is removed from 653 * a displayable containment hierarchy or when its containment hierarchy 654 * is made undisplayable. A containment hierarchy is made 655 * undisplayable when its ancestor window is disposed. 656 * 657 * @return <code>true</code> if the component is displayable 658 */ 659 @Override isDisplayable()660 public boolean isDisplayable() { 661 return true; 662 } 663 664 } 665 666