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