📄 graphlayout.java
字号:
*/ public synchronized void removeNode (RenderedNode node) { graph.removeNode (node); changedGraph (); } /** * Remove an edge. */ public synchronized void removeEdge (RenderedEdge edge) { graph.removeEdge (edge); changedGraph (); } /** * Handle a loaded image. */ public synchronized boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { if ((infoflags & (ImageObserver.WIDTH | ImageObserver.HEIGHT)) != 0) { for (int i=0; i<graph.sizeNodes; ++i) { RenderedNode n = (RenderedNode)graph.nodes[i]; if (n.icon == img) { n.width = width; n.height = height; changedGraph (); } } } return super.imageUpdate (img, infoflags, x, y, width, height); } /* * Background thread * */ Thread iterator; /** * Start automatic graph layout (in the background). */ public synchronized void start () { if (!running) { running = true; iterator = new Thread (this, "GraphListener"); iterator.setDaemon (true); iterator.setPriority (Thread.MIN_PRIORITY); iterator.start (); } } /** * Stop automatic graph layout. */ public synchronized void stop () { if (running) { running = false; notify (); iterator = null; } } /** * The body of the background thread. Clients should not call this * method. */ final static int MULTIPLIER = 2; public synchronized void run () { quiescent = false; while (running) { long start = System.currentTimeMillis (); if (automaticLayout && !quiescent) { for (int i=0; i < iterations; ++i) { double improvement = algorithm.improveGraph (graph); dirty = true; if (improvement <= threshold * graph.sizeNodes) { quiescent = true; break; } } } if (dirty) super.repaint (); /*int r = (int) (System.currentTimeMillis() - start); int w = Math.max (interval, r * MULTIPLIER); System.out.println ("ran " + r + " msec, now waiting " + w + " msec"); */ try { wait (interval); } catch (InterruptedException e) { } } quiescent = true; } /** * Notify background thread that the graph has changed. */ public synchronized void changedGraph () { if (automaticLayout) quiescent = false; repaint (); } /** * Notify background thread that the view has changed. */ public synchronized void repaint () { if (!running) super.repaint (); else dirty = true; } /** * Show control panel for changing graph layout parameters. */ public void showControlPanel () { if (controlPanel == null) controlPanel = new GraphLayoutControlPanel (this); controlPanel.show (); } protected void finalize () throws Throwable { super.finalize (); if (controlPanel != null) { controlPanel.dispose(); controlPanel = null; } } /* * Scale coordinates from graph to screen. */ double originX = 0.0, originY = 0.0; double scaleX = 1.0, scaleY = 1.0; private void scaleGraph () { Dimension d = size (); double halfScreenWidth = d.width/2.0; double halfScreenHeight = d.height/2.0; double sX = 1.0, sY = 1.0; for (int i=0; i < graph.sizeNodes; ++i) { RenderedNode n = (RenderedNode)graph.nodes[i]; sX = Math.min(sX, (halfScreenWidth - n.width/2.0)/(Math.abs(n.x)+1)); sY = Math.min(sY, (halfScreenHeight - n.height/2.0)/(Math.abs(n.y)+1)); } double oX = halfScreenWidth; double oY = halfScreenHeight; for (int i=0; i < graph.sizeNodes; ++i) { RenderedNode n = (RenderedNode)graph.nodes[i]; n.screenX = (int)(n.x*sX + oX); n.screenY = (int)(n.y*sY + oY); } // save the translation for use in placeNodeOnScreen originX = oX; originY = oY; scaleX = sX; scaleY = sY; } public synchronized void placeNodeOnScreen (RenderedNode n, int x, int y) { graph.placeNode (n, (x - originX)/scaleX, (y - originY)/scaleY); n.screenX = x; n.screenY = y; } public synchronized void placeNodeOnGraph (RenderedNode n, double x, double y) { graph.placeNode (n, x, y); n.screenX = (int)(x*scaleX + originX); n.screenY = (int)(y*scaleY + originY); } /* * Painting methods * */ Image offscreen; // offscreen drawing area Dimension offSize; // size of offscreen buffer Graphics offg; // drawonable associated with offscreen buffer FontMetrics fm; // font metrics for offscreen buffer public void update (Graphics g) { // don't clear window with background color first //long before = System.currentTimeMillis (); paint (g); //long after = System.currentTimeMillis (); //System.out.println ("repaint: " + (after - before) + " msec"); } void createOffscreenArea (Dimension d) { offSize = new Dimension (d.width > 0 ? d.width : 1, d.height > 0 ? d.height : 1); offscreen = createImage (offSize.width, offSize.height); offg = offscreen.getGraphics (); offg.setFont (getFont ()); fm = offg.getFontMetrics (); } public synchronized void paint (Graphics g) { Dimension d = size (); if (offscreen == null || d.width != offSize.width || d.height != offSize.height) createOffscreenArea (d); offg.setColor (getBackground ()); offg.fillRect (0, 0, d.width, d.height); scaleGraph (); // paint the edges first for (int i=0; i<graph.sizeEdges; ++i) { RenderedEdge e = (RenderedEdge)graph.edges[i]; if (e == null) continue; RenderedNode from = (RenderedNode)e.from; RenderedNode to = (RenderedNode)e.to; if (from == null || to == null) continue; Color c = e.color; if (c == null) c = edgeColor; offg.setColor (c); drawArrowToBox (offg, (int)from.screenX, (int)from.screenY, (int)to.screenX, (int)to.screenY, (int)(to.width/2), (int)(to.height/2), 6, 3, e.thick); } // paint the nodes on top for (int i=0; i < graph.sizeNodes; ++i) { RenderedNode n = (RenderedNode)graph.nodes[i]; if (n == null) continue; int width = (int)n.width; int height = (int)n.height; int x = (int)n.screenX - width/2; int y = (int)n.screenY - height/2; Color c = n.color; if (n.icon == null) { if (c == null) c = nodeColor; offg.setColor (c); offg.fillRect (x, y, width, height); offg.setColor (getForeground ()); offg.drawRect (x, y, width-1, height-1); offg.drawString (n.name, x+5, y+2 + fm.getAscent ()); } else { // NIY: scaling if (c == null) offg.drawImage (n.icon, x, y, this); else offg.drawImage (n.icon, x, y, c, this); } } // paint the tip on top if (tip != null) { offg.setColor (tipColor); offg.fillRect (tipX, tipY, tipWidth, tipHeight); offg.setColor (Color.black); offg.drawRect (tipX, tipY, tipWidth-1, tipHeight-1); tip.draw (offg, tipX + 5, tipY + 2, Label.LEFT); } // draw border offg.setColor (quiescent ? getForeground () : Color.red); offg.drawRect (0, 0, d.width-1, d.height-1); // copy to screen g.drawImage (offscreen, 0, 0, null); dirty = false; } void drawArrowToBox (Graphics g, int x1, int y1, int x2, int y2, int wHalfBox, int hHalfBox, int head_length, int head_width, boolean thick) { if (thick) { drawArrowToBox (g, x1, y1, x2, y2, wHalfBox, hHalfBox, head_length, head_width, false); drawArrowToBox (g, x1-1, y1, x2-1, y2, wHalfBox, hHalfBox, head_length, head_width, false); drawArrowToBox (g, x1, y1-1, x2, y2-1, wHalfBox, hHalfBox, head_length, head_width, false); drawArrowToBox (g, x1-1, y1-1, x2-1, y2-1, wHalfBox, hHalfBox, head_length, head_width, false); } else { double dx = x2 - x1; double dy = y2 - y1; double d = Math.sqrt (dx * dx + dy * dy); if (d < 1.0) { d = 1.0; dx = 1; } dx /= d; dy /= d; double lx = head_length * dx; double ly = head_length * dy; double wx = head_width * dx; double wy = head_width * dy; double cp1 = dx*hHalfBox - dy*wHalfBox; double cp2 = dx*hHalfBox + dy*wHalfBox; if (cp1 < 0) { if (cp2 < 0) { // region I x2 += wHalfBox; y2 += wHalfBox*dy/dx; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -