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