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