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.Graphics2D; 29 import java.awt.Point; 30 import java.awt.Rectangle; 31 import java.awt.geom.Point2D; 32 import java.awt.geom.Rectangle2D; 33 import java.awt.geom.AffineTransform; 34 import java.awt.geom.NoninvertibleTransformException; 35 36 37 import com.sun.star.accessibility.*; 38 import com.sun.star.lang.EventObject; 39 import com.sun.star.uno.UnoRuntime; 40 41 42 class CanvasShape implements XAccessibleEventListener 43 { 44 public final Color maHighlightColor = Color.red; 45 public final Color maSelectionColor = Color.green; 46 public final Color maFocusColor = Color.blue; 47 CanvasShape(javax.swing.tree.TreeNode aNode, Canvas aCanvas)48 public CanvasShape (javax.swing.tree.TreeNode aNode, Canvas aCanvas) 49 { 50 maNode = aNode; 51 msName = "<no name>"; 52 msDescription = "<no description>"; 53 maShape = new Rectangle2D.Double (-10,-10,10,10); 54 maPosition = new Point (-10,-10); 55 maSize = new Dimension (10,10); 56 maFgColor = java.awt.Color.black; 57 maBgColor = Color.blue; 58 mnRole = -1; 59 mbHighlighted = false; 60 mbSelected = false; 61 mbFocused = false; 62 maCanvas = aCanvas; 63 64 Update (); 65 } 66 67 68 69 getNodePath(javax.swing.tree.TreeNode node)70 public javax.swing.tree.TreePath getNodePath (javax.swing.tree.TreeNode node) 71 { 72 javax.swing.tree.TreeNode parent = node.getParent(); 73 return (parent != null) ? 74 getNodePath(parent).pathByAddingChild(node) : 75 new javax.swing.tree.TreePath(node); 76 } 77 getNodePath()78 public javax.swing.tree.TreePath getNodePath () 79 { 80 return getNodePath(maNode); 81 } 82 83 84 85 /** Update the data obtained from the <type>AccessibilityNode</type> 86 object. 87 */ Update()88 public void Update () 89 { 90 if (maNode instanceof XAccessible) { 91 mxContext = ((XAccessible) maNode).getAccessibleContext(); 92 mxComponent = (XAccessibleComponent)UnoRuntime.queryInterface( 93 XAccessibleComponent.class, mxContext); 94 } 95 96 if (mxContext != null) 97 { 98 msName = mxContext.getAccessibleName(); 99 msDescription = mxContext.getAccessibleDescription(); 100 mnRole = mxContext.getAccessibleRole(); 101 102 // Extract the selected and focused flag. 103 XAccessibleStateSet xStateSet = mxContext.getAccessibleStateSet (); 104 if (xStateSet != null) 105 { 106 mbSelected = xStateSet.contains (AccessibleStateType.SELECTED); 107 mbFocused = xStateSet.contains (AccessibleStateType.FOCUSED); 108 } 109 } 110 111 UpdateGeometry (); 112 113 if (mxComponent != null) 114 { 115 // Note: alpha values in office 0..255 have to be mapped to 116 // 255..0 in Java 117 Color aCol = new Color (mxComponent.getForeground(), true); 118 maFgColor = new Color (aCol.getRed (), 119 aCol.getGreen (), 120 aCol.getBlue (), 121 0xff - aCol.getAlpha ()); 122 aCol = new Color (mxComponent.getBackground(), true); 123 maBgColor = new Color (aCol.getRed (), 124 aCol.getGreen (), 125 aCol.getBlue (), 126 0xff - aCol.getAlpha ()); 127 } 128 } 129 130 131 UpdateGeometry()132 public void UpdateGeometry () 133 { 134 if (mxComponent != null) 135 { 136 com.sun.star.awt.Point aLocationOnScreen = 137 mxComponent.getLocationOnScreen(); 138 com.sun.star.awt.Size aSizeOnScreen = mxComponent.getSize(); 139 maPosition = new Point ( 140 aLocationOnScreen.X, 141 aLocationOnScreen.Y); 142 maSize = new Dimension ( 143 aSizeOnScreen.Width, 144 aSizeOnScreen.Height); 145 } 146 } 147 148 149 150 /** Paint the object into the specified canvas. It is transformed 151 according to the specified offset and scale. 152 */ paint( Graphics2D g, boolean bShowDescription, boolean bShowName, boolean bShowText)153 public void paint ( 154 Graphics2D g, 155 boolean bShowDescription, 156 boolean bShowName, 157 boolean bShowText) 158 { 159 try{ 160 // Transform the object's position and size according to the 161 // specified offset and scale. 162 Point aLocation = new Point(); 163 maShape = new Rectangle2D.Double ( 164 maPosition.x, 165 maPosition.y, 166 maSize.width, 167 maSize.height); 168 maTransformation = g.getTransform(); 169 170 // Fill the object's bounding box with its background color if it 171 // has no children. 172 if (mxContext.getAccessibleChildCount() == 0) 173 { 174 g.setColor (maBgColor); 175 g.fill (maShape); 176 } 177 178 // Remove alpha channel from color before drawing the frame. 179 Color color = maFgColor; 180 if (maFgColor.getAlpha()<128) 181 color = new Color (maFgColor.getRed(), maFgColor.getGreen(), maFgColor.getBlue()); 182 g.setColor (color); 183 g.draw (maShape); 184 185 if (mbFocused) 186 { 187 g.setColor (maFocusColor); 188 for (int x=0; x<=2; x++) 189 for (int y=0; y<=2; y++) 190 g.fill ( 191 new Rectangle2D.Double ( 192 maShape.x + x/2.0 * maShape.width-3, 193 maShape.y + y/2.0 * maShape.height-3, 194 6, 195 6)); 196 } 197 if (mbSelected) 198 { 199 g.setColor (maSelectionColor); 200 for (int x=0; x<=2; x++) 201 for (int y=0; y<=2; y++) 202 g.draw ( 203 new Rectangle2D.Double ( 204 maShape.x + x/2.0 * maShape.width-2, 205 maShape.y + y/2.0 * maShape.height-2, 206 4, 207 4)); 208 } 209 210 // Write the object's text OR name and description. 211 g.setColor (maFgColor); 212 if (bShowName) 213 paintName (g); 214 if (bShowDescription) 215 paintDescription (g); 216 if (bShowText) 217 paintText (g); 218 } 219 catch (Exception e) 220 { // don't care 221 } 222 } 223 224 paint_highlight(Graphics2D g)225 public void paint_highlight (Graphics2D g) 226 { 227 if (mbHighlighted) 228 g.setColor (maHighlightColor); 229 else 230 g.setColor (maFgColor); 231 g.draw (maShape); 232 } 233 234 235 236 paintName(Graphics2D g)237 private void paintName (Graphics2D g) 238 { 239 g.drawString ("Name: " + msName, 240 (float)maShape.x+5, 241 (float)maShape.y+15); 242 } 243 244 245 paintDescription(Graphics2D g)246 private void paintDescription (Graphics2D g) 247 { 248 g.drawString ("Description: " + msDescription, 249 (float)maShape.x+5, 250 (float)maShape.y+35); 251 } 252 253 254 255 paintText(Graphics2D g)256 private void paintText (Graphics2D g) 257 { 258 XAccessibleText xText = null; 259 // get XAccessibleText 260 xText = (XAccessibleText)UnoRuntime.queryInterface( 261 XAccessibleText.class, mxContext); 262 263 // Draw every character in the text string. 264 if (xText != null) 265 { 266 String sText = xText.getText(); 267 try 268 { 269 for(int i = 0; i < sText.length(); i++) 270 { 271 com.sun.star.awt.Rectangle aRect = 272 xText.getCharacterBounds(i); 273 274 double x = maShape.x + aRect.X; 275 double y = maShape.y + aRect.Y + aRect.Height; 276 277 g.drawString (sText.substring(i, i+1), (float)x, (float)y); 278 } 279 } 280 catch (com.sun.star.lang.IndexOutOfBoundsException e) 281 {} 282 } 283 } 284 285 286 /** Compute whether the specified point lies inside the object's 287 bounding box. 288 */ Contains(int x, int y)289 public boolean Contains (int x, int y) 290 { 291 Point2D aPosition = new Point2D.Double (x,y); 292 try 293 { 294 maTransformation.inverseTransform (aPosition, aPosition); 295 // System.out.println ("transformed "+x+","+y+" to "+aPosition); 296 } 297 catch (NoninvertibleTransformException aException) 298 { 299 return false; 300 } 301 return (maShape.contains (aPosition)); 302 } 303 Highlight(boolean bFlag)304 public void Highlight (boolean bFlag) 305 { 306 mbHighlighted = bFlag; 307 } 308 IsHighlighted()309 public boolean IsHighlighted () 310 { 311 return mbHighlighted; 312 } 313 GetBBox()314 public Rectangle GetBBox () 315 { 316 return new Rectangle (maPosition, maSize); 317 } 318 getOrigin()319 public Point getOrigin () 320 { 321 return maPosition; 322 } 323 GetSize()324 public Dimension GetSize () 325 { 326 return maSize; 327 } 328 getRole()329 public int getRole () 330 { 331 return mnRole; 332 } 333 getContext()334 public XAccessibleContext getContext () 335 { 336 return mxContext; 337 } 338 getComponent()339 public XAccessibleComponent getComponent () 340 { 341 return mxComponent; 342 } 343 toString()344 public String toString () 345 { 346 return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y 347 +"x"+maSize.width+"x"+maSize.height+"<"; 348 } 349 350 /** */ notifyEvent(com.sun.star.accessibility.AccessibleEventObject aEvent)351 public void notifyEvent(com.sun.star.accessibility.AccessibleEventObject aEvent) { 352 try { 353 switch (aEvent.EventId) { 354 case AccessibleEventId.BOUNDRECT_CHANGED: 355 case AccessibleEventId.VISIBLE_DATA_CHANGED: 356 UpdateGeometry (); 357 maCanvas.repaint(); 358 break; 359 default: 360 break; 361 } 362 } catch (Exception aException) { 363 System.err.println ("caught exception while updating a shape:" 364 + aException); 365 aException.printStackTrace (System.err); 366 } 367 } 368 369 /** Callback for disposing events. 370 */ disposing(com.sun.star.lang.EventObject e)371 public void disposing (com.sun.star.lang.EventObject e) 372 { 373 System.out.println ("Disposing"); 374 } 375 376 377 378 379 private Canvas 380 maCanvas; 381 private javax.swing.tree.TreeNode 382 maNode; 383 private XAccessibleContext 384 mxContext; 385 private XAccessibleComponent 386 mxComponent; 387 private String 388 msDescription, 389 msName; 390 private Rectangle2D.Double maShape; 391 private AffineTransform maTransformation; 392 private Point maPosition; 393 private Dimension 394 maTransformedSize, 395 maSize; 396 private Color 397 maFgColor, 398 maBgColor; 399 private boolean 400 // Highlighting objects is an internal concept. Corresponds to selection in the tree view. 401 mbHighlighted, 402 // Set when the accessible object is selected. 403 mbSelected, 404 // Set when the accessible object is focused. 405 mbFocused; 406 private int 407 mnRole; 408 } 409