office-gobmx/toolkit/test/accessibility/CanvasShape.java
Noel Grandin 8d8e6c84e5 [API CHANGE] Drop css::accessibility::XAccessibleStateSet
which is internal API, unused (as far as I can tell) by external
users.
This state is purely a bitset
  (as implemented by utl::AccessibleStateSetHelper)
so we can just return it as a 64-bit value.

This shaves significant time off the performance profiles
of code that loads very complex shapes, because this state
is frequently used, and we no longer need to allocate a return
value on the heap for every call.

Change-Id: Icf1b3bd367c256646ae9015f9127025f59459c2c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136786
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-07-08 10:10:11 +02:00

286 lines
8.8 KiB
Java

/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
import java.awt.*;
import javax.swing.tree.*;
import java.awt.geom.Rectangle2D;
import com.sun.star.accessibility.XAccessibleContext;
import com.sun.star.accessibility.XAccessibleComponent;
import com.sun.star.accessibility.XAccessibleText;
import com.sun.star.accessibility.AccessibleStateType;
class CanvasShape
{
private final Color maHighlightColor = Color.red;
private final Color maSelectionColor = Color.green;
private final Color maFocusColor = Color.blue;
public CanvasShape (AccTreeNode aNode)
{
maNode = aNode;
mxContext = aNode.getContext();
msName = "name unknown";
msDescription = "description unknown";
maShape = new Rectangle2D.Double (-10,-10,10,10);
maPosition = new Point (-10,-10);
maSize = new Dimension (10,10);
maFgColor = java.awt.Color.black;
maBgColor = Color.blue;
mbHighlighted = false;
mbSelected = false;
mbFocused = false;
mxComponent = aNode.getComponent();
update ();
}
/** Update the data obtained from the xAccessible.
*/
public void update ()
{
if (mxContext != null)
{
msName = mxContext.getAccessibleName();
msDescription = mxContext.getAccessibleDescription();
// Extract the selected and focused flag.
long nStateSet = mxContext.getAccessibleStateSet ();
mbSelected = (nStateSet & AccessibleStateType.SELECTED) != 0;
mbFocused = (nStateSet & AccessibleStateType.FOCUSED) != 0;
}
updateGeometry ();
if (mxComponent != null)
{
// Note: alpha values in office 0..255 have to be mapped to
// 255..0 in Java
Color aCol = new Color (mxComponent.getForeground(), true);
maFgColor = new Color (aCol.getRed (),
aCol.getGreen (),
aCol.getBlue (),
0xff - aCol.getAlpha ());
aCol = new Color (mxComponent.getBackground(), true);
maBgColor = new Color (aCol.getRed (),
aCol.getGreen (),
aCol.getBlue (),
0xff - aCol.getAlpha ());
}
}
public void updateGeometry ()
{
if (mxComponent != null)
{
com.sun.star.awt.Point aLocationOnScreen = mxComponent.getLocationOnScreen();
com.sun.star.awt.Size aSizeOnScreen = mxComponent.getSize();
maPosition = new Point (
aLocationOnScreen.X,
aLocationOnScreen.Y);
maSize = new Dimension (
aSizeOnScreen.Width,
aSizeOnScreen.Height);
}
}
/** Paint the object into the specified canvas. It is transformed
according to the specified offset and scale.
*/
public void paint (Graphics2D g,
double nXOffset, double nYOffset, double nScaleFactor,
boolean bShowDescription, boolean bShowName, boolean bShowText)
{
try{
// Transform the object's position and size according to the
// specified offset and scale.
maShape = new Rectangle2D.Double (
maPosition.x * nScaleFactor + nXOffset,
maPosition.y * nScaleFactor + nYOffset,
maSize.width * nScaleFactor,
maSize.height * nScaleFactor);
// Fill the object's bounding box with its background color if it
// has no children.
if (mxContext.getAccessibleChildCount() == 0)
{
g.setColor (maBgColor);
g.fill (maShape);
}
// Remove alpha channel from color before drawing the frame.
Color color = maFgColor;
if (maFgColor.getAlpha()<128)
color = new Color (maFgColor.getRed(), maFgColor.getGreen(), maFgColor.getBlue());
g.setColor (color);
g.draw (maShape);
if (mbFocused)
{
g.setColor (maFocusColor);
for (int x=0; x<=2; x++)
for (int y=0; y<=2; y++)
g.fill (
new Rectangle2D.Double (
maShape.x + x/2.0 * maShape.width-3,
maShape.y + y/2.0 * maShape.height-3,
6,
6));
}
if (mbSelected)
{
g.setColor (maSelectionColor);
for (int x=0; x<=2; x++)
for (int y=0; y<=2; y++)
g.draw (
new Rectangle2D.Double (
maShape.x + x/2.0 * maShape.width-2,
maShape.y + y/2.0 * maShape.height-2,
4,
4));
}
// Write the object's text OR name and description.
g.setColor (maFgColor);
if (bShowName)
paintName (g);
if (bShowDescription)
paintDescription (g);
if (bShowText)
paintText (g);
}
catch (Exception e)
{ // don't care
}
}
public void paint_highlight (Graphics2D g)
{
if (mbHighlighted)
g.setColor (maHighlightColor);
else
g.setColor (maFgColor);
g.draw (maShape);
}
private void paintName (Graphics2D g)
{
g.drawString ("Name: " + msName,
(float)maShape.x+5,
(float)maShape.y+15);
}
private void paintDescription (Graphics2D g)
{
g.drawString ("Description: " + msDescription,
(float)maShape.x+5,
(float)maShape.y+35);
}
private void paintText (Graphics2D g)
{
XAccessibleText xText = null;
// get XAccessibleText
xText = maNode.getText();
// Draw every character in the text string.
if (xText != null)
{
String sText = xText.getText();
try
{
for(int i = 0; i < sText.length(); i++)
{
com.sun.star.awt.Rectangle aRect =
xText.getCharacterBounds(i);
double x = maShape.x + aRect.X;
double y = maShape.y + aRect.Y + aRect.Height;
g.drawString(sText.substring(i, i+1), (float)x, (float)y);
}
}
catch (com.sun.star.lang.IndexOutOfBoundsException e)
{}
}
}
/** Compute whether the specified point lies inside the object's
bounding box.
*/
public boolean contains (int x, int y)
{
return maShape.contains (x,y);
}
public void highlight ()
{
mbHighlighted = true;
}
public void unhighlight ()
{
mbHighlighted = false;
}
public Rectangle getBBox ()
{
return new Rectangle (maPosition, maSize);
}
public TreePath getPath ()
{
return new TreePath (maNode.createPath());
}
@Override
public String toString ()
{
return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y
+"x"+maSize.width+"x"+maSize.height+"<";
}
private final AccTreeNode maNode;
private final XAccessibleContext mxContext;
private final XAccessibleComponent mxComponent;
private String msDescription, msName;
private Rectangle2D.Double maShape;
private Point maPosition;
private Dimension maSize;
private Color maFgColor, maBgColor;
private boolean
// Highlighting objects is an internal concept. Corresponds to selection in the tree view.
mbHighlighted,
// Set when the accessible object is selected.
mbSelected,
// Set when the accessible object is focused.
mbFocused;
}