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.canvas; 25 26 import java.awt.Color; 27 import java.awt.Dimension; 28 import java.awt.Graphics; 29 import java.awt.Graphics2D; 30 import java.awt.Rectangle; 31 import java.awt.RenderingHints; 32 import java.awt.Toolkit; 33 import java.awt.geom.Rectangle2D; 34 import java.util.Iterator; 35 import javax.swing.JPanel; 36 import javax.swing.JScrollPane; 37 import javax.swing.JViewport; 38 import javax.swing.event.TreeSelectionEvent; 39 import javax.swing.tree.TreePath; 40 41 import com.sun.star.accessibility.XAccessible; 42 import com.sun.star.accessibility.XAccessibleContext; 43 import com.sun.star.accessibility.XAccessibleComponent; 44 45 import org.openoffice.accessibility.misc.Options; 46 47 /** This canvas displays accessible objects graphically. Each accessible 48 object with graphical representation is represented by an 49 CanvasShape object and has to be added by the 50 <member>addAccessible</member> member function. 51 52 <p>The canvas listens to selection events of the associated JTree and 53 highlights the first selected node of that tree.</p> 54 */ 55 public class Canvas 56 extends JPanel 57 { 58 // This constant can be passed to SetZoomMode to always show the whole screen. 59 public static final int WHOLE_SCREEN = -1; 60 Canvas()61 public Canvas () 62 { 63 super (true); 64 maShapeList = new ShapeContainer (this); 65 maMouseObserver = new MouseObserver (this); 66 maTree = null; 67 mnHOffset = 0; 68 mnVOffset = 0; 69 mnScale = 1; 70 maLastWidgetSize = new Dimension (0,0); 71 } 72 73 74 75 /** Tell the canvas which tree to use to highlight accessible 76 objects and to observe for changes in the tree structure. 77 */ SetTree(javax.swing.JTree aTree)78 public void SetTree (javax.swing.JTree aTree) 79 { 80 if (aTree != maTree) 81 { 82 maTree = aTree; 83 maShapeList.SetTree (maTree); 84 maMouseObserver.SetTree (maTree); 85 } 86 } 87 88 89 90 Clear()91 private void Clear () 92 { 93 maShapeList.Clear(); 94 } 95 96 97 98 GetShapeIterator()99 public Iterator GetShapeIterator () 100 { 101 return maShapeList.GetIterator(); 102 } 103 104 105 106 paintComponent(Graphics g)107 public void paintComponent (Graphics g) 108 { 109 synchronized (g) 110 { 111 super.paintComponent (g); 112 113 Graphics2D g2 = (Graphics2D)g; 114 if (Options.GetBoolean("Antialiasing")) 115 g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, 116 RenderingHints.VALUE_ANTIALIAS_ON); 117 else 118 g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, 119 RenderingHints.VALUE_ANTIALIAS_OFF); 120 121 setupTransformation (); 122 g2.translate (mnHOffset, mnVOffset); 123 g2.scale (mnScale, mnScale); 124 125 // Draw the screen representation to give a hint of the location of the 126 // accessible object on the screen. 127 Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize(); 128 Rectangle2D.Double aScreen = new Rectangle2D.Double ( 129 0, 130 0, 131 aScreenSize.getWidth(), 132 aScreenSize.getHeight()); 133 // Fill the screen rectangle and draw a frame arround it to increase its visibility. 134 g2.setColor (new Color (250,240,230)); 135 g2.fill (aScreen); 136 g2.setColor (Color.BLACK); 137 g2.draw (aScreen); 138 139 synchronized (maShapeList) 140 { 141 Iterator aShapeIterator = maShapeList.GetIterator(); 142 boolean bShowDescriptions = Options.GetBoolean ("ShowDescriptions"); 143 boolean bShowNames = Options.GetBoolean ("ShowNames"); 144 boolean bShowText = Options.GetBoolean ("ShowText"); 145 while (aShapeIterator.hasNext()) 146 { 147 CanvasShape aCanvasShape = 148 (CanvasShape)aShapeIterator.next(); 149 try 150 { 151 aCanvasShape.paint ( 152 g2, 153 bShowDescriptions, bShowNames, bShowText); 154 } 155 catch (Exception aException) 156 { 157 System.err.println ("caught exception while painting a shape:" 158 + aException); 159 aException.printStackTrace (System.err); 160 } 161 } 162 } 163 164 // Paint highlighted frame around active object as the last thing. 165 if (maActiveObject != null) 166 maActiveObject.paint_highlight (g2); 167 } 168 } 169 170 171 172 173 /** Set up the transformation so that the graphical display can show a 174 centered representation of the whole screen. 175 */ setupTransformation()176 private void setupTransformation () 177 { 178 // Turn off scrollbars when showing the whole screen. Otherwise show them when needed. 179 JViewport aViewport = (JViewport)getParent(); 180 JScrollPane aScrollPane = (JScrollPane)aViewport.getParent(); 181 int nZoomMode = Options.GetInteger ("ZoomMode", WHOLE_SCREEN); 182 if (nZoomMode == WHOLE_SCREEN) 183 { 184 if (aScrollPane.getHorizontalScrollBarPolicy() 185 != JScrollPane.HORIZONTAL_SCROLLBAR_NEVER) 186 aScrollPane.setHorizontalScrollBarPolicy ( 187 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 188 if (aScrollPane.getVerticalScrollBarPolicy() 189 != JScrollPane.VERTICAL_SCROLLBAR_NEVER) 190 aScrollPane.setVerticalScrollBarPolicy ( 191 JScrollPane.VERTICAL_SCROLLBAR_NEVER); 192 } 193 else 194 { 195 if (aScrollPane.getHorizontalScrollBarPolicy() 196 != JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) 197 aScrollPane.setHorizontalScrollBarPolicy ( 198 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 199 if (aScrollPane.getVerticalScrollBarPolicy() 200 != JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 201 aScrollPane.setVerticalScrollBarPolicy ( 202 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 203 } 204 205 Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize(); 206 Dimension aWidgetSize = aViewport.getSize(); 207 { 208 if ((aScreenSize.getWidth() > 0) && (aScreenSize.getHeight() > 0)) 209 { 210 if (nZoomMode == WHOLE_SCREEN) 211 { 212 // Calculate the scales that would map the screen onto the 213 // widget in both of the coordinate axes and select the 214 // smaller 215 // of the two: it maps the screen onto the widget in both 216 // axes at the same time. 217 double nHScale = (aWidgetSize.getWidth() - 10) 218 / aScreenSize.getWidth(); 219 double nVScale = (aWidgetSize.getHeight() - 10) 220 / aScreenSize.getHeight(); 221 if (nHScale < nVScale) 222 mnScale = nHScale; 223 else 224 mnScale = nVScale; 225 } 226 else 227 { 228 mnScale = nZoomMode / 100.0; 229 } 230 231 // Calculate offsets that center the scaled screen inside 232 // the widget. 233 mnHOffset = (aWidgetSize.getWidth() 234 - mnScale*aScreenSize.getWidth()) / 2.0; 235 mnVOffset = (aWidgetSize.getHeight() 236 - mnScale*aScreenSize.getHeight()) / 2.0; 237 if (mnHOffset < 0) 238 mnHOffset = 0; 239 if (mnVOffset < 0) 240 mnVOffset = 0; 241 242 setPreferredSize (new Dimension ( 243 (int)(2*mnHOffset + mnScale * aScreenSize.getWidth()), 244 (int)(2*mnVOffset + mnScale * aScreenSize.getHeight()))); 245 revalidate (); 246 } 247 else 248 { 249 // In case of a degenerate (not yet initialized?) screen size 250 // use some meaningless default values. 251 mnScale = 1; 252 mnHOffset = 0; 253 mnVOffset = 0; 254 } 255 } 256 maLastWidgetSize = aWidgetSize; 257 } 258 259 260 HighlightObject(CanvasShape aNewActiveObject)261 protected boolean HighlightObject (CanvasShape aNewActiveObject) 262 { 263 if (aNewActiveObject != maActiveObject) 264 { 265 if (maActiveObject != null) 266 maActiveObject.Highlight (false); 267 268 maActiveObject = aNewActiveObject; 269 if (maActiveObject != null) 270 { 271 /* if (maTree != null) 272 { 273 TreePath aPath = new TreePath ( 274 maActiveObject.GetNode().GetPath()); 275 maTree.scrollPathToVisible (aPath); 276 maTree.setSelectionPath (aPath); 277 maTree.repaint (); 278 } 279 */ 280 maActiveObject.Highlight (true); 281 } 282 repaint (); 283 return true; 284 } 285 else 286 return false; 287 } 288 289 290 291 292 /** Called when the selection of the tree changes. Highlight the 293 corresponding graphical representation of the object. 294 */ SelectObject(javax.swing.tree.TreeNode aNode)295 public void SelectObject (javax.swing.tree.TreeNode aNode) 296 { 297 CanvasShape aCanvasShape = maShapeList.Get (aNode); 298 HighlightObject (aCanvasShape); 299 } 300 301 302 303 304 private int 305 mnXAnchor, 306 mnYAnchor, 307 maResizeFlag; 308 private double 309 mnHOffset, 310 mnVOffset, 311 mnScale; 312 private CanvasShape maActiveObject; 313 private javax.swing.JTree maTree; 314 // The size of the widget at the last call of setupTransformation() 315 private Dimension maLastWidgetSize; 316 private ShapeContainer maShapeList; 317 private MouseObserver maMouseObserver; 318 } 319