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 javax.swing.*;
36 import java.awt.Dimension;
37 import java.awt.*;
38 import java.awt.geom.*;
39 
40 import com.sun.star.accessibility.XAccessible;
41 import com.sun.star.accessibility.XAccessibleContext;
42 import com.sun.star.accessibility.XAccessibleComponent;
43 
44 import com.sun.star.awt.Point;
45 import com.sun.star.awt.Size;
46 import com.sun.star.uno.UnoRuntime;
47 
48 
49 /** Display the currently focused accessible object graphically.
50 */
51 public class GraphicalDisplay
52     extends JPanel
53     implements IAccessibleObjectDisplay
54 {
55     /** Create a new graphical widget the displays some of the geometrical
56         information availbable from accessible objects.
57     */
58     public GraphicalDisplay ()
59     {
60         setPreferredSize (new Dimension (300,200));
61     }
62 
63 
64     /** Paint some or all of the area of this widget with the outlines of
65         the currently focues object and its ancestors.
66      */
67     public synchronized void paintComponent (Graphics g)
68     {
69         super.paintComponent (g);
70 
71         setupTransformation ();
72 
73         // Draw the screen representation to give a hint of the location of the
74         // accessible object on the screen.
75         Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
76         // Fill the screen rectangle.
77         g.setColor (new Color (250,240,230));
78         g.fillRect (
79             (int)(mnHOffset+0.5),
80             (int)(mnVOffset+0.5),
81             (int)(mnScale*aScreenSize.getWidth()),
82             (int)(mnScale*aScreenSize.getHeight()));
83         // Draw a frame arround the screen rectangle to increase its visibility.
84         g.setColor (Color.BLACK);
85         g.drawRect (
86             (int)(mnHOffset+0.5),
87             (int)(mnVOffset+0.5),
88             (int)(mnScale*aScreenSize.getWidth()),
89             (int)(mnScale*aScreenSize.getHeight()));
90 
91         // Now do the actual display of the accessible object.
92         drawAccessibleObject (g, mxContext, Color.GREEN);
93     }
94     public synchronized void paintChildren (Graphics g)
95     {
96     }
97     public synchronized void paintBorder (Graphics g)
98     {
99     }
100 
101 
102 
103 
104     /** Draw a simple representation of the given accessible object in the
105         specified color.
106     */
107     public void drawAccessibleObject (Graphics g, XAccessibleContext xContext, Color aColor)
108     {
109         if (xContext != null)
110         {
111             // First draw our parent.
112             XAccessible xParent = xContext.getAccessibleParent();
113             if (xParent != null)
114                 drawAccessibleObject (g, xParent.getAccessibleContext(), Color.GRAY);
115 
116             // When the context supports the XAccessibleComponent interface
117             // then draw its outline.
118             XAccessibleComponent xComponent =
119                 (XAccessibleComponent)UnoRuntime.queryInterface(
120                     XAccessibleComponent.class, xContext);
121             if (xComponent != null)
122             {
123                 // Get size and location on screen and transform them to fit
124                 // everything inside this widget.
125                 Point aLocation = xComponent.getLocationOnScreen();
126                 Size aSize = xComponent.getSize();
127                 g.setColor (aColor);
128                 g.drawRect (
129                     (int)(mnHOffset + mnScale*aLocation.X+0.5),
130                     (int)(mnVOffset + mnScale*aLocation.Y+0.5),
131                     (int)(mnScale*aSize.Width),
132                     (int)(mnScale*aSize.Height));
133             }
134         }
135     }
136 
137 
138     public synchronized void setAccessibleObject (XAccessibleContext xContext)
139     {
140         mxContext = xContext;
141         repaint ();
142     }
143 
144     public synchronized void updateAccessibleObject (XAccessibleContext xContext)
145     {
146         repaint ();
147     }
148 
149 
150     /** Set up the transformation so that the graphical display can show a
151         centered representation of the whole screen.
152     */
153     private void setupTransformation ()
154     {
155         Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
156         Dimension aWidgetSize = getSize();
157         if ((aScreenSize.getWidth() > 0) && (aScreenSize.getHeight() > 0))
158         {
159             // Calculate the scales that would map the screen onto the
160             // widget in both of the coordinate axes and select the smaller
161             // of the two: it maps the screen onto the widget in both axes
162             // at the same time.
163             double nHScale = (aWidgetSize.getWidth() - 10) / aScreenSize.getWidth();
164             double nVScale = (aWidgetSize.getHeight() - 10) / aScreenSize.getHeight();
165             if (nHScale < nVScale)
166                 mnScale = nHScale;
167             else
168                 mnScale = nVScale;
169 
170             // Calculate offsets that center the scaled screen inside the widget.
171             mnHOffset = (aWidgetSize.getWidth() - mnScale*aScreenSize.getWidth()) / 2.0;
172             mnVOffset = (aWidgetSize.getHeight() - mnScale*aScreenSize.getHeight()) / 2.0;
173         }
174         else
175         {
176             // In case of a degenerate (not yet initialized?) screen size
177             // use some meaningless default values.
178             mnScale = 1;
179             mnHOffset = 0;
180             mnVOffset = 0;
181         }
182     }
183 
184 
185     private XAccessibleContext mxContext;
186     private double mnScale;
187     private double mnHOffset;
188     private double mnVOffset;
189 }
190