📄 ruler.java
字号:
* @param g the graphics
* @param canvasPos the position of the item in the canvas
* @param pos the position of the item
* @param index the kind of representation for this item
* @param availableSize the available size until the next item of the same index
*/
protected void paintRawItem(Graphics g, int canvasPos, int pos, int index, double availableSize){
switch (index){
case 0 :
if(isHorizontal){
//drawing the string
String str=canvasPos+"";
Rectangle2D rect=font.getStringBounds(str, new FontRenderContext(new AffineTransform(), true, false));
if(rect.getWidth()<availableSize){
Graphics2D g2=(Graphics2D)g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2.setFont(font);
g2.drawString(str, pos+2, font.getSize()-2);
g2.dispose();
}
g.drawLine(pos, getHeight()-8, pos, getHeight());
}else{
Graphics2D g2=(Graphics2D)g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2.setFont(font);
//drawing the strings
char[] tab=new String(canvasPos+"").toCharArray();
if(tab.length*font.getSize()<=availableSize){
int vpos=font.getSize()-1;
for(char c : tab){
g2.drawString(c+"", 0, pos+vpos);
vpos+=font.getSize()-1;
}
g2.dispose();
}
g.drawLine(getWidth()-8, pos, getWidth(), pos);
}
break;
case 1 :
if(isHorizontal){
g.drawLine(pos, getHeight()-6, pos, getHeight());
}else{
g.drawLine(getWidth()-6, pos, getWidth(), pos);
}
break;
case 2 :
if(isHorizontal){
g.drawLine(pos, getHeight()-4, pos, getHeight());
}else{
g.drawLine(getWidth()-4, pos, getWidth(), pos);
}
break;
}
}
/**
* disposes this ruler
*/
public void dispose() {
rulerRefreshManager.dispose();
rulerRefreshManager=null;
}
/**
* the class of the range of the ruler
* @author Jordi SUC
*/
protected class Range{
/**
* the constant for large
*/
public static final int LARGE=0;
/**
* the constant for medium
*/
public static final int MEDIUM=1;
/**
* the constant for small
*/
public static final int SMALL=2;
/**
* the list of the computed ranges
*/
private LinkedList<Double> ranges=new LinkedList<Double>();
/**
* the constructor of the class
* @param distance the available scaled distance
* @param scale the scale
*/
protected Range(double distance, double scale){
//the geometry distance
double geometryDistance=distance/scale;
//the maximal range
double maxRange=Math.floor(Math.log10(geometryDistance));
//computing the list of all the ranges
double crange=maxRange, availableSpace=0, scaledSpace=0;
while(true){
//checking if the available space can be a part of the ranges
availableSpace=Math.pow(10, crange);
scaledSpace=availableSpace*scale;
if(scaledSpace<=3){
break;
}
ranges.add(availableSpace);
//checking if the middle of the available space can be a part of the ranges
availableSpace=availableSpace/2;
scaledSpace=availableSpace*scale;
if(scaledSpace<=3){
break;
}
ranges.add(availableSpace);
crange--;
}
//handling the list of the ranges so that only the last three ranges remain in it
if(ranges.size()>3){
ranges=new LinkedList<Double>(ranges.subList(ranges.size()-3, ranges.size()));
}
}
/**
* @return the list of the ranges
*/
protected LinkedList<Double> getRanges(){
return ranges;
}
/**
* computes and returns the closest number from the given number that belongs to a range
* @param pos a number
* @return the closest number from the given number that belongs to a range
*/
protected double getRound(double pos){
double res=0;
//getting the smallest integer range
double smallestRange=ranges.getLast();
double pos1=Math.floor(pos/smallestRange)*smallestRange;
double pos2=(Math.floor(pos/smallestRange)+1)*smallestRange;
if(Math.abs(pos1-pos)<Math.abs(pos2-pos)){
res=pos1;
}else{
res=pos2;
}
return res;
}
}
/**
* the class used to refresh
* @author Jordi SUC
*/
protected class RulerRefreshManager extends Thread{
/**
* the listener to the mouse motion actions on the canvas
*/
private MouseMotionListener canvasListener=null;
/**
* whether this thread is disposed
*/
protected boolean isDisposed=false;
/**
* whether the point has changed
*/
private boolean hasChanged=false;
/**
* the position of the mouse
*/
private int pos=0;
/**
* the base scaled position of the mouse
*/
private Point2D.Double displayedPoint=null;
/**
* the constructor of the class
*/
protected RulerRefreshManager() {
canvasListener=new MouseMotionListener(){
public void mouseDragged(MouseEvent evt) {
handleEvent(evt.getPoint());
}
public void mouseMoved(MouseEvent evt) {
handleEvent(evt.getPoint());
}
/**
* handles the event
* @param point the mouse point for the event
*/
protected void handleEvent(Point point) {
//computing the position of the mouse
int tmpPos=pos=(isHorizontal?point.x:point.y);
Point2D.Double dPoint=null;
if(isHorizontal) {
Point2D.Double point2D=new Point2D.Double(point.x, point.y);
dPoint=scrollpane.getSVGFrame().getScaledPoint(point2D, true);
}
synchronized(this) {
pos=tmpPos;
if(isHorizontal) {
displayedPoint=dPoint;
}
hasChanged=true;
}
}
};
//adding a listener to the mouse move actions on the canvas
scrollpane.getSVGCanvas().addMouseMotionListener(canvasListener);
}
/**
* reinitializes this manager
*/
public void reinitialize() {
synchronized(this) {
hasChanged=false;
pos=0;
displayedPoint=null;
}
}
@Override
public void run() {
while(! isDisposed) {
if(hasChanged) {
synchronized(this) {
hasChanged=false;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//repainting all the rulers
currentPosition=pos;
repaint();
if(isHorizontal && displayedPoint!=null) {
scrollpane.getSVGFrame().getStateBar().setSVGX(
SVGEditor.getDisplayFormat().format(displayedPoint.getX()));
scrollpane.getSVGFrame().getStateBar().setSVGY(
SVGEditor.getDisplayFormat().format(displayedPoint.getY()));
}
}
});
}
try {sleep(100);}catch (Exception ex) {}
}
}
/**
* disposes this manager
*/
public void dispose() {
synchronized (this) {
isDisposed=true;
}
scrollpane.getSVGCanvas().removeMouseMotionListener(canvasListener);
canvasListener=null;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -