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