1 import java.awt.*; 2 import javax.swing.*; 3 import javax.swing.tree.*; 4 import java.awt.geom.Rectangle2D; 5 6 import com.sun.star.beans.XPropertyChangeListener; 7 import com.sun.star.beans.PropertyChangeEvent; 8 9 import com.sun.star.accessibility.XAccessible; 10 import com.sun.star.accessibility.XAccessibleContext; 11 import com.sun.star.accessibility.XAccessibleComponent; 12 import com.sun.star.accessibility.XAccessibleExtendedComponent; 13 import com.sun.star.accessibility.XAccessibleText; 14 import com.sun.star.accessibility.XAccessibleStateSet; 15 import com.sun.star.accessibility.AccessibleStateType; 16 17 class CanvasShape 18 { 19 public final Color maHighlightColor = Color.red; 20 public final Color maSelectionColor = Color.green; 21 public final Color maFocusColor = Color.blue; 22 23 // public AccessibleObject (XAccessibleContext xContext, TreePath aPath) 24 public CanvasShape (AccTreeNode aNode) 25 { 26 maNode = aNode; 27 mxContext = aNode.getContext(); 28 msName = "name unknown"; 29 msDescription = "description unknown"; 30 maShape = new Rectangle2D.Double (-10,-10,10,10); 31 maPosition = new Point (-10,-10); 32 maSize = new Dimension (10,10); 33 maFgColor = java.awt.Color.black; 34 maBgColor = Color.blue; 35 mnRole = -1; 36 mbHighlighted = false; 37 mbSelected = false; 38 mbFocused = false; 39 mxComponent = aNode.getComponent(); 40 41 update (); 42 } 43 44 45 46 /** Update the data obtained from the xAccessible. 47 */ 48 public void update () 49 { 50 if (mxContext != null) 51 { 52 msName = mxContext.getAccessibleName(); 53 msDescription = mxContext.getAccessibleDescription(); 54 mnRole = mxContext.getAccessibleRole(); 55 56 // Extract the selected and focused flag. 57 XAccessibleStateSet xStateSet = mxContext.getAccessibleStateSet (); 58 if (xStateSet != null) 59 { 60 mbSelected = xStateSet.contains (AccessibleStateType.SELECTED); 61 mbFocused = xStateSet.contains (AccessibleStateType.FOCUSED); 62 } 63 } 64 65 updateGeometry (); 66 if (mxComponent != null) 67 { 68 // Note: alpha values in office 0..255 have to be mapped to 69 // 255..0 in Java 70 Color aCol = new Color (mxComponent.getForeground(), true); 71 maFgColor = new Color (aCol.getRed (), 72 aCol.getGreen (), 73 aCol.getBlue (), 74 0xff - aCol.getAlpha ()); 75 aCol = new Color (mxComponent.getBackground(), true); 76 maBgColor = new Color (aCol.getRed (), 77 aCol.getGreen (), 78 aCol.getBlue (), 79 0xff - aCol.getAlpha ()); 80 } 81 } 82 83 public void updateGeometry () 84 { 85 if (mxComponent != null) 86 { 87 com.sun.star.awt.Point aLocationOnScreen = mxComponent.getLocationOnScreen(); 88 com.sun.star.awt.Size aSizeOnScreen = mxComponent.getSize(); 89 maPosition = new Point ( 90 aLocationOnScreen.X, 91 aLocationOnScreen.Y); 92 maSize = new Dimension ( 93 aSizeOnScreen.Width, 94 aSizeOnScreen.Height); 95 } 96 } 97 98 99 /** Paint the object into the specified canvas. It is transformed 100 according to the specified offset and scale. 101 */ 102 public void paint (Graphics2D g, 103 double nXOffset, double nYOffset, double nScaleFactor, 104 boolean bShowDescription, boolean bShowName, boolean bShowText) 105 { 106 try{ 107 // Transform the object's position and size according to the 108 // specified offset and scale. 109 Point aLocation = new Point(); 110 maShape = new Rectangle2D.Double ( 111 maPosition.x * nScaleFactor + nXOffset, 112 maPosition.y * nScaleFactor + nYOffset, 113 maSize.width * nScaleFactor, 114 maSize.height * nScaleFactor); 115 116 // Fill the object's bounding box with its background color if it 117 // has no children. 118 if (mxContext.getAccessibleChildCount() == 0) 119 { 120 g.setColor (maBgColor); 121 g.fill (maShape); 122 } 123 124 // Remove alpha channel from color before drawing the frame. 125 Color color = maFgColor; 126 if (maFgColor.getAlpha()<128) 127 color = new Color (maFgColor.getRed(), maFgColor.getGreen(), maFgColor.getBlue()); 128 g.setColor (color); 129 g.draw (maShape); 130 131 if (mbFocused) 132 { 133 g.setColor (maFocusColor); 134 for (int x=0; x<=2; x++) 135 for (int y=0; y<=2; y++) 136 g.fill ( 137 new Rectangle2D.Double ( 138 maShape.x + x/2.0 * maShape.width-3, 139 maShape.y + y/2.0 * maShape.height-3, 140 6, 141 6)); 142 } 143 if (mbSelected) 144 { 145 g.setColor (maSelectionColor); 146 for (int x=0; x<=2; x++) 147 for (int y=0; y<=2; y++) 148 g.draw ( 149 new Rectangle2D.Double ( 150 maShape.x + x/2.0 * maShape.width-2, 151 maShape.y + y/2.0 * maShape.height-2, 152 4, 153 4)); 154 } 155 156 // Write the object's text OR name and description. 157 g.setColor (maFgColor); 158 if (bShowName) 159 paintName (g); 160 if (bShowDescription) 161 paintDescription (g); 162 if (bShowText) 163 paintText (g); 164 } 165 catch (Exception e) 166 { // don't care 167 } 168 } 169 170 public void paint_highlight (Graphics2D g, 171 double nXOffset, double nYOffset, double nScaleFactor) 172 { 173 if (mbHighlighted) 174 g.setColor (maHighlightColor); 175 else 176 g.setColor (maFgColor); 177 g.draw (maShape); 178 } 179 180 181 182 183 private void paintName (Graphics2D g) 184 { 185 g.drawString ("Name: " + msName, 186 (float)maShape.x+5, 187 (float)maShape.y+15); 188 } 189 190 191 192 private void paintDescription (Graphics2D g) 193 { 194 g.drawString ("Description: " + msDescription, 195 (float)maShape.x+5, 196 (float)maShape.y+35); 197 } 198 199 200 201 202 private void paintText (Graphics2D g) 203 { 204 XAccessibleText xText = null; 205 // get XAccessibleText 206 xText = maNode.getText(); 207 208 // Draw every character in the text string. 209 if (xText != null) 210 { 211 String sText = xText.getText(); 212 try 213 { 214 for(int i = 0; i < sText.length(); i++) 215 { 216 com.sun.star.awt.Rectangle aRect = 217 xText.getCharacterBounds(i); 218 219 double x = maShape.x + aRect.X; 220 double y = maShape.y + aRect.Y + aRect.Height; 221 222 g.drawString(sText.substring(i, i+1), (float)x, (float)y); 223 } 224 } 225 catch (com.sun.star.lang.IndexOutOfBoundsException e) 226 {} 227 } 228 } 229 230 231 232 233 /** Callback for disposing events. 234 */ 235 public void disposing (com.sun.star.lang.EventObject e) 236 { 237 System.out.println ("Disposing"); 238 } 239 240 241 242 243 /** Compute whether the specified point lies inside the object's 244 bounding box. 245 */ 246 public boolean contains (int x, int y) 247 { 248 return (maShape.contains (x,y)); 249 } 250 251 public void highlight () 252 { 253 mbHighlighted = true; 254 } 255 256 public void unhighlight () 257 { 258 mbHighlighted = false; 259 } 260 261 public boolean isHighlighted () 262 { 263 return mbHighlighted; 264 } 265 266 public Rectangle getBBox () 267 { 268 return new Rectangle (maPosition, maSize); 269 } 270 271 public Point getOrigin () 272 { 273 return maPosition; 274 } 275 276 public TreePath getPath () 277 { 278 return new TreePath (maNode.createPath()); 279 } 280 281 public int getRole () 282 { 283 return mnRole; 284 } 285 286 public XAccessibleContext getContext () 287 { 288 return mxContext; 289 } 290 291 public XAccessibleComponent getComponent () 292 { 293 return mxComponent; 294 } 295 296 public String toString () 297 { 298 return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y 299 +"x"+maSize.width+"x"+maSize.height+"<"; 300 } 301 302 private AccTreeNode 303 maNode; 304 private XAccessibleContext 305 mxContext; 306 private XAccessibleComponent 307 mxComponent; 308 private String 309 msDescription, 310 msName; 311 private Rectangle2D.Double 312 maShape; 313 private Point 314 maPosition; 315 private Dimension 316 maTransformedSize, 317 maSize; 318 private Color 319 maFgColor, 320 maBgColor; 321 private boolean 322 // Highlighting objects is an internal concept. Corresponds to selection in the tree view. 323 mbHighlighted, 324 // Set when the accessible object is selected. 325 mbSelected, 326 // Set when the accessible object is focused. 327 mbFocused; 328 private int 329 mnRole; 330 } 331