1 /*************************************************************************
2  *
3  *  The Contents of this file are made available subject to the terms of
4  *  the BSD license.
5  *
6  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *************************************************************************/
34 
35 import java.awt.Color;
36 import java.awt.Font;
37 import java.awt.Dimension;
38 import javax.swing.JTextArea;
39 import javax.swing.JScrollPane;
40 import java.util.Vector;
41 
42 import com.sun.star.accessibility.XAccessible;
43 import com.sun.star.accessibility.XAccessibleContext;
44 import com.sun.star.accessibility.XAccessibleComponent;
45 import com.sun.star.accessibility.XAccessibleStateSet;
46 
47 import com.sun.star.uno.AnyConverter;
48 import com.sun.star.uno.UnoRuntime;
49 
50 import com.sun.star.awt.Point;
51 import com.sun.star.awt.Size;
52 
53 /** Display textual information for a given accessible object.  This
54     includes the names of that object of its ancestors as well as some
55     information retrieved from the XAccessibleContext and
56     XAccessibleComponent interfaces.
57 */
58 class TextualDisplay
59     extends JScrollPane
60     implements IAccessibleObjectDisplay
61 {
62     /** Create a new scroll pane that contains a text widget which display
63         information about given accessible objects.
64     */
65     public TextualDisplay ()
66     {
67         // Create a text widget for displaying the text information...
68         maText = new JTextArea (80,10);
69         maText.setBackground (new Color (250,240,230));
70         maText.setFont (new Font ("Courier", Font.PLAIN, 11));
71 
72         // ...and set-up the scroll pane to show this widget.
73         setViewportView (maText);
74         setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
75         setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
76     }
77 
78 
79 
80 
81     /** Set the accessible object to display.  Call this method e.g. when a
82         new object has been focused.
83     */
84     public synchronized void setAccessibleObject (XAccessibleContext xContext)
85     {
86         // First clear the display area.
87         msTextContent = new String ();
88 
89         if (xContext != null)
90         {
91             String sIndentation = showParents (xContext);
92             showContextInfo (xContext, sIndentation);
93             showComponentInfo (xContext, sIndentation);
94         }
95 
96         maText.setText (msTextContent);
97     }
98 
99 
100 
101 
102     public synchronized void updateAccessibleObject (XAccessibleContext xContext)
103     {
104         setAccessibleObject (xContext);
105     }
106 
107 
108 
109     /** Show some of the information available over the given object's
110         XAccessibleContext interface.
111     */
112     private void showContextInfo (XAccessibleContext xContext, String sIndentation)
113     {
114         // Show the description.
115         msTextContent += sIndentation + "Description: "
116             + xContext.getAccessibleDescription() + "\n";
117 
118         showStates (xContext, sIndentation);
119     }
120 
121 
122 
123 
124     /** Show a list of all of the the given object's states.  Use the
125         NameConverter class to transform the numerical state ids into human
126         readable names.
127         @param xContext
128             The accessible context for which to show the state names.
129     */
130     private void showStates (XAccessibleContext xContext, String sIndentation)
131     {
132         // Get the state set object...
133         XAccessibleStateSet xStateSet = xContext.getAccessibleStateSet();
134         // ...and retrieve an array of numerical ids.
135         short aStates[] = xStateSet.getStates();
136 
137         // Iterate over the array and print the names of the states.
138         msTextContent += sIndentation + "States     : ";
139         for (int i=0; i<aStates.length; i++)
140         {
141             if (i > 0)
142                 msTextContent += ", ";
143             msTextContent += NameProvider.getStateName(aStates[i]);
144         }
145         msTextContent += "\n";
146     }
147 
148 
149 
150 
151     /** When the given object supports the XAccessibleComponent interface then
152         show its size and location on the screen.
153     */
154     private void showComponentInfo (XAccessibleContext xContext, String sIndentation)
155     {
156         // Try to cast the given accessible context to the
157         // XAccessibleComponent interface.
158         XAccessibleComponent xComponent =
159             (XAccessibleComponent)UnoRuntime.queryInterface(
160                 XAccessibleComponent.class, xContext);
161         if (xComponent != null)
162         {
163             Point aLocation = xComponent.getLocationOnScreen();
164             msTextContent += sIndentation + "Position   : "
165                 + aLocation.X + ", " + aLocation.Y + "\n";
166 
167             Size aSize = xComponent.getSize();
168             msTextContent += sIndentation + "Size       : "
169                 + aSize.Width + ", " + aSize.Height + "\n";
170         }
171     }
172 
173 
174 
175 
176 
177     /** Print the names of the given object and its parents and return an
178         indentation string that can be used to print further information
179         about the object.
180     */
181     private String showParents (XAccessibleContext xContext)
182     {
183         // Create the path from the given object to its tree's root.
184         Vector aPathToRoot = new Vector();
185         while (xContext != null)
186         {
187             aPathToRoot.add (xContext);
188             // Go up the hierarchy one level to the object's parent.
189             try
190             {
191                 XAccessible xParent = xContext.getAccessibleParent();
192                 if (xParent != null)
193                     xContext = xParent.getAccessibleContext();
194                 else
195                     xContext = null;
196             }
197             catch (Exception e)
198             {
199                 System.err.println ("caught exception " + e + " while getting path to root");
200             }
201         }
202 
203         // Print the path in the accessibility tree from the given context to
204         // the root.
205         String sIndentation = new String ();
206         for (int i=aPathToRoot.size()-1; i>=0; i--)
207         {
208             XAccessibleContext xParentContext = (XAccessibleContext)aPathToRoot.get(i);
209             String sParentName = xParentContext.getAccessibleName();
210             if (sParentName.length() == 0)
211                 sParentName = "<unnamed> / Role "
212                     + NameProvider.getRoleName(xParentContext.getAccessibleRole());
213             msTextContent += sIndentation + sParentName + "\n";
214             sIndentation += msIndentation;
215         }
216 
217         return sIndentation;
218     }
219 
220 
221 
222     /// The text widget that is used for the actual text display.
223     private JTextArea maText;
224 
225     /// The indentation with which an object's child is indented.
226     private final String msIndentation = new String("  ");
227 
228     /// The text content displayed by this object.
229     private String msTextContent = new String ();
230 }
231