Summary:
The mouse position monitor (MousePositionLS ) calculates in real time whether or not the mouse hits any of shape
objects, whenever the mouse was moved. Here "the mouse hits"
means that the mouse is located on a shape or very close to a shape boundary.
More precisely, the mouse position monitor calculates the hits with a shape
element, a text area or an associated shape objects (i.e. a selection box,
resize handles, start and end points of a curve, segment junction points of polyline,
tangent line of a cubic curve etc.). The mouse position monitor is used
in the various functions such as selecting shape, moving/resizing shape, modifyng shape and so on. |
Class on this page:MousePositionInfo,
MousePositionLS |
=>
DrawTest: Mouse hit test for a closed shape,
Mouse hit test for an unclosed shape
1. Overview
1.1 Mouse position code
The mouse position is classified as Table1.
Table 1. Mouse position code
Code |
int |
Mouse position |
NO_HIT |
0 |
Empty space, i.e. the mouse hits no shape. |
INSIDE_DRAWAREA |
1 |
Inside the drawing area of a shape
(Figure 1.2) |
SELECTION_BOX |
2 |
Selection box |
NW_RESIZE |
3 |
North West Resize Handle |
NE_RESIZE |
4 |
North East Resize Handle |
SE_RESIZE |
5 |
South East Resize Handle |
SW_RESIZE |
6 |
South West Resize Handle |
N_RESIZE |
7 |
North Resize Handle |
E_RESIZE |
8 |
East Resize Handle |
S_RESIZE |
9 |
South Resize Handle |
W_RESIZE |
10 |
West Resize Handle |
BOUNDINGBOX_BOUNDARY |
11 |
Bounding box boundary of a shape |
INSIDE_BOUNDINGBOX |
12 |
Inside the bounding box boundary of a shape |
SHAPE_BOUNDARY |
13 |
Boundary of a shape |
END_POINT |
14 |
Endpoints of a line/polyline/cubic curve (Figure 1.3) |
CONTROL_POINT |
15 |
Control point (Figure 1.3) |
INSIDE_SHAPE |
16 |
Inside a shape |
TEXTBOX_BOUNDARY |
17 |
Boundary of a text box |
INSIDE_TEXTBOX |
18 |
inside a text box |
INSIDE_TEXT |
19 |
Inside the rectangle area in which texts are really displayed. |
Figure 1.1 Selection box, resize handles
Figure 1.2 DRAWAREA (Light green area)
The DRAWAREA is a maximum area which covers a shape itself and its relativefigures
such as its selection box, resize handles and tangent lines.
Figure 1.3Control points, endpoints (start/end point)
The segment junction points (segment junction points) of a polyline or a piecewise cubic curve
and the endpoints of tangent lines are classified as "control points".
1.2 Mouse hit testing
return=>page top
The rough test whether or not the mouse position is inside the DRAWAREA
is executed at the beginning of the test. More precise tests are as follows:
Shape to be tested |
Description |
closed shape |
Judgement of the SHAPE_BOUNDARY, INSIDE_SHAPE
The hit testing for a closed shape can be performed easily by using
the contains method defined in java.awt.Shape interface. For example, we
define four test points around the mouse pointer and tests as follows:
∙ If all the four test points are contained in the shape, then the mouse pointer is located
inside the shape.
∙ If all the four test points aren't contained in the shape, then the mouse
pointer is located outside the shape.
∙ Otherwise, the mouse pointer is on the boundary of the shape.
Mouse position and test points
|
|
|
Inside the shape |
On the shape boundary |
Outside the shape |
:
• Relative methods=>MousePositionLS.createMousePositionOfShape,
MousePositionLS.ptOnShape
• Unit test=>Mouse hit test for a closed shape
|
Line, open polyline, open cubic curve |
Judgement of the SHAPE_BOUNDARY
The "open" means that a shape boundary is not closed. In this
case, the contains method doesn't work.
To test whether or not the mouse pointer is on a line or a curve, the getShortestLine method of the Curve2DUtil is used. The getShortestLine method calculates the nearest point on a line or a curve from the mouse
pointer. This method is performed based on the bisection and Newton-Raphson
method, so it achieves unnecessary accuracy for the hit testing. However
it is very fast and there is no problem for the real time operation.
• User's guide test
• Relative methods=>MousePositionLS.createMousePositionOfShape, MousePositionLS.ptOnShape
• Unit test=>Mouse hit test for an unclosed shape |
Text area |
Judgement of the INSIDE_TEXT
The rectangles covering all the text lines in a text box
can be got by the LineBreaker.getBounds method.
Returns the maximum rectangle which covers all the rectangles by the TextBox.getTextLayoutArea method.
:
• Relative method=> MousePositionLS.ptOnBox |
Rectangle(box) |
Judgement of the SELECTION_BOX, BOUNDINGBOX_BOUNDARY,INSIDE_BOUNDINGBOX
etc
This judgement method is easy.
:
• Relative method=> MousePositionLS.ptOnBox |
Point, small rectangle |
Judgement of the NW_RESIZE - W_RESIZE, END_POINT, CONTROL_POINT etc.
The hit testing for a point or a small rectangle is used for checking whether
the mouse pointer is located on a resize handle or control point. The method
is easy.
:
• Relative method=> MousePositionLS.onResizeMark,
MousePositionLS.onPoint |
2. Class MousePositionInfo
return=>page top
public class MousePositionInfo implements Serializable
A MousePositionInfo object is an output from the mouse position monitor
(MousePositionLS). It contains the information about the hit shape, text
box, mouse position code , hit position and so on.
Method |
Description |
Constructor |
public MousePositionInfo()
Calls the setPositionString method. |
setContainer |
public void setContainer(ShapeContainer container)
Sets the parameter to the corresponding field. |
setShapeContainerInGroup |
public void setShapeContainerInGroup(ShapeContainer shapeContainerInGroup)
Sets the parameter to the corresponding field. |
setTextBox |
public void setTextBox(TextBox textBox)
Sets the parameter to the corresponding field. |
setMouseStatus |
public void setMouseStatus(String mouseStatus)
Sets the parameter to the corresponding field. |
setRightButtonPressed |
public void setRightButtonPressed(boolean pressed)
Sets the parameter to the corresponding field. |
setPosition |
public void setPosition(int position)
Sets the parameter to the corresponding field. |
setPoint |
public void setPoint(Point2D point)
Sets the parameter to the corresponding field. |
setInformation |
public void setInformation(String inf)
Sets the parameter to the corresponding field. |
getContainer |
public ShapeContainer getContainer()
Returns the container field.
|
getShapeContainer
InGroup |
public ShapeContainer getShapeContainerInGroup()
Returns the shapeContainerInGroup field. |
getTextBox |
public TextBox getTextBox()
Returns the textBox field. |
getMouseStatus |
public String getMouseStatus()
Returns the mouseStatus field. |
isRightButtonPressed |
public boolean isRightButtonPressed()
Returns the rightButtonPressed field. |
getPosition |
public int getPosition()
Returns the position field. |
getPoint |
public Point2D getPoint()
Returns the point field. |
getInformation |
public String getInformation()
Returns the information field. |
onResizeMark |
public boolean onResizeMark()
Returns true if the mouse position code equals NW_RESIZE,...... or W_RESIZE. |
onEndPoint |
public boolean onEndPoint()
Returns true if the mouse position code equals END_POINT. |
onControlPoint |
public boolean onControlPoint()
Returns true if the mouse position code equals CONTROL_POINT |
clone |
public Object clone()
Returns a clone object. |
toString |
public String toString()
Returns the string representing this object. |
setPositionString |
private void setPositionString()
Sets the strings representing the mouse position codes
to the positionString field. |
getPositionString
(static) |
public static String getPositionString(int position)
Returns the string of the mouse position code. |
getPositionString
InDetail
(static) |
public static String getPositionStringInDetail(int position)
Returns the detailed string of the mouse position code. |
3. Class MousePositionLS
return=>page top
public class MousePositionLS implements MouseListener, MouseMotionListener
3.1 Getting the mouse position
The MousePositionLS calculates in real time whether or not the mouse hits
any of shape objects whenever the mouse is moved. If the mouse hits the
shape, the MousePositionLS creates a new MousePositionInfo object
and stores it the infos array field.
The mouseMoved and mouseDragged methods receive the mouse movement,
so the both methods call the createMousePositionInfo method
to output the results of the mouse hit testing.
=>Mouse position code
3.2 The related functions
The MousePositionLS class also performs the following functions.
(1) Triggers popup menu
The mouseClicked method of this class or the
mouseClicked method of the
SelectionLS triggers the popup menu and calls the
ExecPopupMenu.show method.
(2) Displaying a MousePositionInfo
The mouseDragged
and mouseMoved methods of this class calls the
displayMousePosition method.
It displays MousePositionInfo objects
on the message panel at the bottom of the window.
If the mouse hits multiple shapes, then it displays multiple MousePositionInfo objects.
Figure 3.1 Message panel
(3) Changing the mouse cursor mark
The mouseMoved method performs the operation.
3.3 Special issues
It seems uneconomical that this class creates new
MousePositionInfo objects whenever the mouse hits a shape.
To avoid this, the MousePositionLS constructor reserves
an array of MousePositionInfo objects.
If the mouse hits a hape, then the setMousePosition method
sets the hit information to a reserved MousePositionInfo object.
For this reason, the processing of outputting MousePositionInfo objects
is a little bit complex. The fields and the methods related to this are as follows:
3.4 MousePositionLS API
return=>page top
public class MousePositionLS implements MouseListener, MouseMotionListener
Method |
Description |
Constructor |
public MousePositionLS()
Calls the activateListener method to register this object to the ListenerPanel as a MouseListener and MouseMotionListener.
|
activateListener |
private void activateListener(boolean activate)
If the activate is true, then this method registers this object to ListenerPanel as a MouseListener and MouseMotionListener.
If the activate is false, then this method removes this object from ListenerPanel. |
isMouseListener |
private boolean isMouseListener()
Inquires whether this object is registered to ListenerPanel or not. |
isMouseMotionListener |
private boolean isMouseMotionListener()
Inquires whether this object is registered to ListenerPanel or not. |
mousePressed |
public void mousePressed(MouseEvent e)
∙ Stores the return value of the isPopupTrigger method of the e (MouseEvent)
to the popupTrigger field.
=>SelectionLS Getting PopupTrigger, Popup Menu
Triggers popup menu
∙ If the mouse right button was pressed, then this method calls the
setRightButtonPressed methods
for all the current MousePositionInfo objects
which were created in the mouseMoved method.
∙ Calls the displayMousePosition method to display the current
MousePositionInfo objects to the message panel.
=>
The related functions (2)
|
mouseDragged |
public void mouseDragged(MouseEvent e)
∙ Creates the MousePositionInfo objects by calling the createMousePositionInfo method of this class.
∙ Calls the displayMousePosition method to display the current MousePositionInfo objects to the message panel. |
mouseReleased |
public void mouseReleased(MouseEvent e)
∙ Stores the return value of the isPopupTrigger method of the e (MouseEvent
) to the static field popupTrigger.
=>SelectionLS Getting PopupTrigger, Popup Menu Triggers popup menu
∙ Calls the displayMousePosition method to display the current mouse position on the message panel. |
mouseClicked |
public void mouseClicked(MouseEvent e)
∙ Calls the displayMousePosition method to display the current mouse position on the message panel.
∙ If the return value of the allMouseEventsCompleted method is true and the value of the statement -
(SelectionLS.popupTrigger||popupTrigger) - is true, then this
method calls the ExecPopupMenu.show method to show the popup menu. The same logic is implemented in the mouseClicked method of the SelectionLS.
=>
Popup Menu Triggers popup menu
|
mouseMoved |
public void mouseMoved(MouseEvent e)
∙ Creates the MousePositionInfo objects by calling the
createMousePositionInfo method of this class and calls the
displayMousePosition method to display them on the message panel.
∙ Changes the cursor mark according to the mouse position code of the
MousePositionInfo given by the
getMousePositionInfoForSelection method.
|
mouseEntered |
public void mouseEntered(MouseEvent e)
Sets the default cursor mark. |
mouseExited |
public void mouseExited(MouseEvent e)
Sets the default cursor mark. |
displayMousePosition |
private void displayMousePosition(String mouseAction, double X, double
Y)
Displays the MousePositionInfo objects on the message panel.
=>
The related functions (2)
|
getMousePositionInfo
ForSelection |
public MousePositionInfo[] getMousePositionInfoForSelection()BR>
Returns the MousePositionInfo objects used for selecting shapes.
If multiple MousePositionInfo objects exists in the infos,
this method sorts them according to their ranks and returns them in descendant order.
The ranks are as follow in descending order(mouse position code):
∙ MousePositionInfo.NW_RESIZE - W_RESIZE, END_POINT, CONTROL_POINT
∙ MousePositionInfo.SELECTION_BOX.
∙ MousePositionInfo.INSIDE_TEXT. ∙ MousePositionInfo.SHAPE_BOUNDARY
∙ MousePositionInfo.TEXTBOX_BOUNDARY.
∙ MousePositionInfo.SELECTION_BOX
∙ MousePositionInfo.INSIDE_TEXTBOX
∙ MousePositionInfo.INSIDE_SHAPE
∙ MousePositionInfo.BOUNDINGBOX_BOUNDARY, INSIDE_BOUNDINGBOX
:
If the same rank is set to mulyiple mouse position informations, for example,
MousePositionInfo.INSIDE_SHAPE, then the higher rank is set
to the mouse position information with the forward shape in
z- order(User's guide).
|
getMousePositionInfo
ForMoveResize |
public MousePositionInfo getMousePositionInfoForMoveResize()
Returns the MousePositionInfo objects used for moving or resizing shapes.
If multiple MousePositionInfo objects exists in the infos,
this method returns the single MousePositionInfo object of the highest rank.
The ranks are as follow in descending order(mouse position code):
∙ MousePositionInfo.NW_RESIZE - W_RESIZE, END_POINT
∙ MousePositionInfo.TEXTBOX_BOUNDARY.
∙ MousePositionInfo.SHAPE_BOUNDARY
∙ MousePositionInfo.SELECTION_BOX
∙ MousePositionInfo.INSIDE_SHAPE
:
If the same rank is set to mulyiple mouse position informations, for
example, MousePositionInfo.INSIDE_SHAPE, then the higher rank is set to
the mouse position information with the forward shape in
z- order(User's guide). |
getAllMousePositionInfo |
public MousePositionInfo[] getAllMousePositionInfo()
Returns all the MousePositionInfo objects which hits shapes.
|
mouseEventCompleted |
public boolean mouseEventCompleted()
Inquires whether or not the methods of this class - mousePressed, mouseDragged,
mouseReleased and mouseClicked - have finished. This method is called from
this class and the SelectionLS class.
|
allMouseEventCompleted |
public boolean allEventsCompleted()
Returns true if the mouseEventCompleted method of this class and the same method
of the SelectionLS both returns true.
=>Popup Menu
Triggers popup menu
|
createMousePositionInfo |
private void createMousePositionInfo(double X, double Y)
Parameters:
(X, Y) - The current mouse position.
Processing:
This method is the main method for the mouse hit testing.
If the shape to be tested is a group of shapes, then this method calls
the createMousePositionOfGroup method, else this method calls the createMousePositionOfShape method. These two methods output MousePositionInfo objects if the mouse hits any of the existing shapes.
|
createMousePosition
OfShape |
private void createMousePositionOfShape(double X, double Y, ShapeContainer
shapeContainer)
Parameters:
(X, Y) - The current mouse position.
shapeContainer - Represents a shape, not a group of shapes.
Processing:
The mouse hit testing for a single shape. The shapeContainer can't be a
group of shapes. |
createMousePosition
OfGroup |
private void createMousePositionOfGroup(double X, double Y, ShapeContainer
shapeContainer)
Parameters:
(X, Y) - The current mouse position.
shapeContainer - Represents a shape, not a group of shapes.
Processing:
The mouse hit testing for a group of shapes.
The hit testing is performed for each shape and the hit types such as
MousePositionInfo.BOUNDINGBOX_BOUNDARY, MousePositionInfo.SELECTION_BOX
and "on resize marks" are tested. Other detailed types will be
tested by createMousePositionOfShapeInGroup.
|
createMousePosition
OfShapeInGroup |
private void createMousePositionOfShapeInGroup(double X, double Y, ShapeContainer
groupContainer, ShapeContainer shapeContainer)
Parameters:
(X, Y) - The current mouse position.
groupContainer - Represents a group of shapes.
shapeContainer - Represents a shape contained in groupContainer.
Processing:
This method tests MousePositionInfo.TEXTBOX_BOUNDARY and MousePositionInfo.INSIDE_TEXT
for each shapeContainer in a group.
|
ptOnShape |
private int ptOnShape(double X, double Y, ShapeContainer shapeContainer)
Parameters:
(X, Y) - The current mouse position.
shapeContainer - Represents a shape, not a group of shapes.
Returns:
0 - Outside the shape.
SHAPE_BOUNDARY - On the shape boundary.
INSIDE_SHAPE - Inside the shape.
Processing:
This method tests whether the point (X,Y) is on a shape boundary or inside a shape. The shapeContainer can't be a group of shapes.
∙ For an open shape
Calculates the nearest point on the shape's boundary from (X,Y) by the getShortestLine of the Curve2DUtil. If the distance between (X,Y) and the nearest point is less than a given tolerance, this
method returns SHAPE_BOUNDARY.
Here the tolerance is given by 0.5*(DrawParameters.Mark_NormalSize/scale) and
the scale means zoom factor.
∙ For a closed shape
This method creates four points around (X,Y) and tests whether the mouse is outside the shape, on the shape boundary
or inside the shape as follows.
∙ If all the four points are contained in the shape, then the mouse
pointer is located inside the shape.
∙ If all the four points aren't contained in the shape, then the
mouse pointer is located outside the shape.
∙ Otherwise, the mouse pointer is on the boundary of the shape.
=>
Mouse hit testing
|
ptOnBox |
private int ptOnBox(double X, double Y, Rectangle2D box)
Parameters:
(X, Y) - The current mouse position.
box - The Rectangle2D object.
Returns:
0 - Outside the shape.
BOUNDINGBOX_BOUNDARY - On the box boundary.
INSIDE_BOUNDINGBOX - Inside the box.
Processing:
The processing is similar to the ptOnShape method. |
ptInfOnBox
|
private String ptInfOnBox(double X, double Y, Rectangle2D box)
This method is called from the createMousePositionOfShape
and createMousePositionOfShapeInGroup methods.
Currently this method is used to add the supplemental information
to the TEXTBOX_BOUNDARY and referred in the TextBox.mouseDragged method.
Parameters:
(X, Y) - The current mouse position.
box - The Rectangle2D object.
Returns:
Returs "outside"/"inside"/"top"/"bottom"/"left"/"right".
Processing:
The processing is similar to the ptOnBox method.
|
onPoint |
private int onPoint(double X, double Y, Point2D[] points)
Parameters:
(X, Y) - The current mouse position.
points - The Point2D objects.
Returns:
If (X,Y) equals any of the points, then returns its array index. Otherwise returns -1.
Processing:
Tests whether the point (X,Y) equals any of the points within a given tolerance. The tolerance is given by 0.5*DrawParameters.Mark_NormalSize/scale. |
onResizeMark |
private int onResizeMark(double X, double Y, Rectangle2D rectangle)
Parameters:
(X, Y) - The current mouse position.
rectangle - The rectangle representing a resize handle.
Returns:
If the mouse is on a resize handle, then returns NW_RESIZE, NE_RESIZE,
SE_RESIZE, SW_RESIZE, N_RESIZE, E_RESIZE, S_RESIZE or W_RESIZE, otherwise
returns 0.
Processing:
Tests whether the point (X,Y) is on a resize handle of a shape or not.
|
boxContains |
private boolean boxContains(double X, double Y, double delta, double boxX,
double boxY)
Parameters:
(X, Y) - The current mouse position.
delta - Half of the edge length.
(boxX, boxY): The center point of the rectangle.
Returns:
Returns true if (X,Y) is inside the box.
Processing:
Tests whether (X,Y) is inside the box whose center point (boxX, boxY) and whose edge length is 2*delta.
|
setMousePosition |
private void setMousePosition(ShapeContainer container, ShapeContainer shapeContainerInGroup,TextBox textBox, int position, Point2D point, String
inf)
Sets the information of mouse hit testing to a MousePositionInfo object
reserved in the infos array.
=>
Special issues
|
|