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 import java.awt.Color;
25 import java.awt.Font;
26 import java.awt.Dimension;
27 import javax.swing.JTextArea;
28 import javax.swing.JScrollPane;
29 import java.util.Vector;
30 
31 import com.sun.star.accessibility.XAccessible;
32 import com.sun.star.accessibility.XAccessibleContext;
33 import com.sun.star.accessibility.XAccessibleComponent;
34 import com.sun.star.accessibility.XAccessibleStateSet;
35 
36 import com.sun.star.uno.AnyConverter;
37 import com.sun.star.uno.UnoRuntime;
38 
39 import com.sun.star.awt.Point;
40 import com.sun.star.awt.Size;
41 
42 /** Display textual information for a given accessible object.  This
43     includes the names of that object of its ancestors as well as some
44     information retrieved from the XAccessibleContext and
45     XAccessibleComponent interfaces.
46 */
47 class TextualDisplay
48     extends JScrollPane
49     implements IAccessibleObjectDisplay
50 {
51     /** Create a new scroll pane that contains a text widget which display
52         information about given accessible objects.
53     */
54     public TextualDisplay ()
55     {
56         // Create a text widget for displaying the text information...
57         maText = new JTextArea (80,10);
58         maText.setBackground (new Color (250,240,230));
59         maText.setFont (new Font ("Courier", Font.PLAIN, 11));
60 
61         // ...and set-up the scroll pane to show this widget.
62         setViewportView (maText);
63         setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
64         setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
65     }
66 
67 
68 
69 
70     /** Set the accessible object to display.  Call this method e.g. when a
71         new object has been focused.
72     */
73     public synchronized void setAccessibleObject (XAccessibleContext xContext)
74     {
75         // First clear the display area.
76         msTextContent = new String ();
77 
78         if (xContext != null)
79         {
80             String sIndentation = showParents (xContext);
81             showContextInfo (xContext, sIndentation);
82             showComponentInfo (xContext, sIndentation);
83         }
84 
85         maText.setText (msTextContent);
86     }
87 
88 
89 
90 
91     public synchronized void updateAccessibleObject (XAccessibleContext xContext)
92     {
93         setAccessibleObject (xContext);
94     }
95 
96 
97 
98     /** Show some of the information available over the given object's
99         XAccessibleContext interface.
100     */
101     private void showContextInfo (XAccessibleContext xContext, String sIndentation)
102     {
103         // Show the description.
104         msTextContent += sIndentation + "Description: "
105             + xContext.getAccessibleDescription() + "\n";
106 
107         showStates (xContext, sIndentation);
108     }
109 
110 
111 
112 
113     /** Show a list of all of the the given object's states.  Use the
114         NameConverter class to transform the numerical state ids into human
115         readable names.
116         @param xContext
117             The accessible context for which to show the state names.
118     */
119     private void showStates (XAccessibleContext xContext, String sIndentation)
120     {
121         // Get the state set object...
122         XAccessibleStateSet xStateSet = xContext.getAccessibleStateSet();
123         // ...and retrieve an array of numerical ids.
124         short aStates[] = xStateSet.getStates();
125 
126         // Iterate over the array and print the names of the states.
127         msTextContent += sIndentation + "States     : ";
128         for (int i=0; i<aStates.length; i++)
129         {
130             if (i > 0)
131                 msTextContent += ", ";
132             msTextContent += NameProvider.getStateName(aStates[i]);
133         }
134         msTextContent += "\n";
135     }
136 
137 
138 
139 
140     /** When the given object supports the XAccessibleComponent interface then
141         show its size and location on the screen.
142     */
143     private void showComponentInfo (XAccessibleContext xContext, String sIndentation)
144     {
145         // Try to cast the given accessible context to the
146         // XAccessibleComponent interface.
147         XAccessibleComponent xComponent =
148             (XAccessibleComponent)UnoRuntime.queryInterface(
149                 XAccessibleComponent.class, xContext);
150         if (xComponent != null)
151         {
152             Point aLocation = xComponent.getLocationOnScreen();
153             msTextContent += sIndentation + "Position   : "
154                 + aLocation.X + ", " + aLocation.Y + "\n";
155 
156             Size aSize = xComponent.getSize();
157             msTextContent += sIndentation + "Size       : "
158                 + aSize.Width + ", " + aSize.Height + "\n";
159         }
160     }
161 
162 
163 
164 
165 
166     /** Print the names of the given object and its parents and return an
167         indentation string that can be used to print further information
168         about the object.
169     */
170     private String showParents (XAccessibleContext xContext)
171     {
172         // Create the path from the given object to its tree's root.
173         Vector aPathToRoot = new Vector();
174         while (xContext != null)
175         {
176             aPathToRoot.add (xContext);
177             // Go up the hierarchy one level to the object's parent.
178             try
179             {
180                 XAccessible xParent = xContext.getAccessibleParent();
181                 if (xParent != null)
182                     xContext = xParent.getAccessibleContext();
183                 else
184                     xContext = null;
185             }
186             catch (Exception e)
187             {
188                 System.err.println ("caught exception " + e + " while getting path to root");
189             }
190         }
191 
192         // Print the path in the accessibility tree from the given context to
193         // the root.
194         String sIndentation = new String ();
195         for (int i=aPathToRoot.size()-1; i>=0; i--)
196         {
197             XAccessibleContext xParentContext = (XAccessibleContext)aPathToRoot.get(i);
198             String sParentName = xParentContext.getAccessibleName();
199             if (sParentName.length() == 0)
200                 sParentName = "<unnamed> / Role "
201                     + NameProvider.getRoleName(xParentContext.getAccessibleRole());
202             msTextContent += sIndentation + sParentName + "\n";
203             sIndentation += msIndentation;
204         }
205 
206         return sIndentation;
207     }
208 
209 
210 
211     /// The text widget that is used for the actual text display.
212     private JTextArea maText;
213 
214     /// The indentation with which an object's child is indented.
215     private final String msIndentation = new String("  ");
216 
217     /// The text content displayed by this object.
218     private String msTextContent = new String ();
219 }
220