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.accessibility.awb.view; 25 26 import java.awt.Color; 27 import java.awt.Component; 28 import java.awt.Font; 29 import java.awt.GridBagLayout; 30 import java.awt.GridBagConstraints; 31 import java.awt.Insets; 32 33 import java.util.Vector; 34 35 import java.lang.reflect.Method; 36 import java.lang.NoSuchMethodException; 37 import java.lang.IllegalAccessException; 38 import java.lang.reflect.InvocationTargetException; 39 40 import javax.swing.JPanel; 41 import javax.swing.JTree; 42 import javax.swing.BorderFactory; 43 import javax.swing.border.Border; 44 import javax.swing.border.BevelBorder; 45 import javax.swing.SwingUtilities; 46 47 import com.sun.star.accessibility.AccessibleEventObject; 48 import com.sun.star.accessibility.XAccessibleContext; 49 import com.sun.star.accessibility.XAccessibleComponent; 50 import com.sun.star.accessibility.XAccessibleEventBroadcaster; 51 import com.sun.star.accessibility.XAccessibleEventListener; 52 import com.sun.star.accessibility.XAccessibleSelection; 53 import com.sun.star.lang.EventObject; 54 import com.sun.star.uno.UnoRuntime; 55 56 import org.openoffice.accessibility.awb.view.ObjectView; 57 58 59 60 /** This container of specialized object views displays information about 61 one accessible object. 62 In this it plays several roles: 63 1. Object container. 64 2. Accessibility event dispatcher. 65 3. Object view class registration manager. 66 4. Swing widget. 67 */ 68 public class ObjectViewContainer 69 extends JPanel 70 implements XAccessibleEventListener 71 { ObjectViewContainer()72 public ObjectViewContainer () 73 { 74 maFont = new Font ("Dialog", Font.PLAIN, 11); 75 maViewTemplates = new Vector (); 76 maViewBorder = BorderFactory.createBevelBorder (BevelBorder.RAISED); 77 GridBagLayout aLayout = new GridBagLayout (); 78 setLayout (aLayout); 79 // maLayoutManager = new LayoutManager (this); 80 maLayoutManager = null; 81 82 RegisterView (ContextView.class); 83 RegisterView (ComponentView.class); 84 RegisterView (ParentView.class); 85 RegisterView (StateSetView.class); 86 RegisterView (FocusView.class); 87 RegisterView (TextView.class); 88 RegisterView (EditableTextView.class); 89 RegisterView (TableView.class); 90 RegisterView (SelectionView.class); 91 RegisterView (ServiceInterfaceView.class); 92 RegisterView (EventMonitorView.class); 93 94 mxContext = null; 95 96 // addMouseListener (maLayoutManager); 97 // addMouseMotionListener (maLayoutManager); 98 } 99 100 101 102 /** Remove all existing views and create new ones according to the 103 interfaces supported by the given object. 104 */ SetObject(XAccessibleContext xContext)105 public synchronized void SetObject (XAccessibleContext xContext) 106 { 107 // Call Destroy at all views to give them a chance to release their 108 // resources. 109 int n = getComponentCount(); 110 for (int i=0; i<n; i++) 111 ((ObjectView)getComponent(i)).Destroy(); 112 // Remove existing views. 113 removeAll (); 114 115 mxContext = xContext; 116 117 // Add new views. 118 for (int i=0; i<maViewTemplates.size(); i++) 119 { 120 try 121 { 122 Class aViewClass = (Class)maViewTemplates.elementAt (i); 123 Method aCreateMethod = aViewClass.getDeclaredMethod ( 124 "Create", new Class[] { 125 ObjectViewContainer.class, 126 XAccessibleContext.class}); 127 if (aCreateMethod != null) 128 { 129 ObjectView aView = (ObjectView) 130 aCreateMethod.invoke ( 131 null, new Object[] {this, xContext}); 132 Add (aView); 133 } 134 } 135 catch (NoSuchMethodException e) 136 {System.err.println ("Caught exception while creating view " 137 + i + " : " + e);} 138 catch (IllegalAccessException e) 139 {System.err.println ("Caught exception while creating view " 140 + i + " : " + e);} 141 catch (InvocationTargetException e) 142 {System.err.println ("Caught exception while creating view " 143 + i + " : " + e);} 144 } 145 146 UpdateLayoutManager (); 147 148 // Now set the object at all views. 149 n = getComponentCount(); 150 for (int i=0; i<n; i++) 151 ((ObjectView)getComponent(i)).SetObject (xContext); 152 153 setPreferredSize (getLayout().preferredLayoutSize (this)); 154 ((GridBagLayout) getLayout()).invalidateLayout(this); 155 validate(); 156 } 157 158 159 160 161 /** Add the given class to the list of classes which will be 162 instantiated the next time an accessible object is set. 163 */ RegisterView(Class aObjectViewClass)164 public void RegisterView (Class aObjectViewClass) 165 { 166 maViewTemplates.addElement (aObjectViewClass); 167 } 168 169 170 171 172 /** Replace one view class with another. 173 */ ReplaceView(Class aObjectViewClass, Class aSubstitution)174 public void ReplaceView (Class aObjectViewClass, Class aSubstitution) 175 { 176 int nIndex = maViewTemplates.indexOf (aObjectViewClass); 177 if (nIndex >= 0) 178 maViewTemplates.setElementAt (aSubstitution, nIndex); 179 } 180 181 182 /** Return a font that should be used for widgets in the views. 183 */ GetViewFont()184 public Font GetViewFont () 185 { 186 return maFont; 187 } 188 GetErrorColor()189 public Color GetErrorColor () 190 { 191 return new Color (255,80,50); 192 } 193 194 /** Add an object view and place it below all previously added views. 195 @param aView 196 This argument may be null. In this case nothing happens. 197 */ Add(ObjectView aView)198 private void Add (ObjectView aView) 199 { 200 if (aView != null) 201 { 202 GridBagConstraints constraints = new GridBagConstraints (); 203 constraints.gridx = 0; 204 constraints.gridy = getComponentCount(); 205 constraints.gridwidth = 1; 206 constraints.gridheight = 1; 207 constraints.weightx = 1; 208 constraints.weighty = 0; 209 constraints.ipadx = 2; 210 constraints.ipady = 5; 211 constraints.insets = new Insets (5,5,5,5); 212 constraints.anchor = GridBagConstraints.NORTH; 213 constraints.fill = GridBagConstraints.HORIZONTAL; 214 215 aView.setBorder ( 216 BorderFactory.createTitledBorder ( 217 maViewBorder, aView.GetTitle())); 218 219 add (aView, constraints); 220 } 221 } 222 223 /** Update the layout manager by setting the vertical weight of the 224 bottom entry to 1 and so make it strech to over the available 225 space. 226 227 */ UpdateLayoutManager()228 private void UpdateLayoutManager () 229 { 230 // Adapt the layout manager. 231 if (getComponentCount() > 1000) 232 { 233 Component aComponent = getComponent (getComponentCount()-1); 234 GridBagLayout aLayout = (GridBagLayout)getLayout(); 235 GridBagConstraints aConstraints = aLayout.getConstraints (aComponent); 236 aConstraints.weighty = 1; 237 aLayout.setConstraints (aComponent, aConstraints); 238 } 239 } 240 241 242 243 244 /** Put the event just received into the event queue which will deliver 245 it soon asynchronuously to the DispatchEvent method. 246 */ notifyEvent(final AccessibleEventObject aEvent)247 public void notifyEvent (final AccessibleEventObject aEvent) 248 { 249 SwingUtilities.invokeLater( 250 new Runnable() 251 { 252 public void run() 253 { 254 DispatchEvent (aEvent); 255 } 256 } 257 ); 258 } 259 260 261 262 263 /** Forward accessibility events to all views without them being 264 registered as event listeners each on their own. 265 */ DispatchEvent(AccessibleEventObject aEvent)266 private void DispatchEvent (AccessibleEventObject aEvent) 267 { 268 int n = getComponentCount(); 269 for (int i=0; i<n; i++) 270 ((ObjectView)getComponent(i)).notifyEvent (aEvent); 271 } 272 273 274 275 /** When the object is disposed that is displayed by the views of this 276 container then tell all views about this. 277 */ disposing(EventObject aEvent)278 public void disposing (EventObject aEvent) 279 { 280 mxContext = null; 281 SwingUtilities.invokeLater( 282 new Runnable() 283 { 284 public void run() 285 { 286 SetObject (null); 287 } 288 } 289 ); 290 } 291 292 293 294 295 /// The current accessible context display by the views. 296 private XAccessibleContext mxContext; 297 298 /// Observe this tree for selection changes and notify them to all 299 /// children. 300 private JTree maTree; 301 private Border maViewBorder; 302 /// List of view templates which are instantiated when new object is set. 303 private Vector maViewTemplates; 304 private Font maFont; 305 private LayoutManager maLayoutManager; 306 } 307