1 18 package org.apache.batik.swing; 19 20 import java.awt.Rectangle ; 21 import java.awt.Dimension ; 22 import java.awt.Component ; 23 import java.awt.BorderLayout ; 24 25 import java.awt.event.ComponentAdapter ; 26 30 31 import java.awt.geom.Rectangle2D ; 32 import java.awt.geom.AffineTransform ; 33 34 import java.awt.event.ComponentEvent ; 35 36 import javax.swing.BoundedRangeModel ; 37 import javax.swing.JScrollBar ; 38 import javax.swing.Box ; 39 import javax.swing.JPanel ; 40 41 import javax.swing.event.ChangeListener ; 42 import javax.swing.event.ChangeEvent ; 43 44 import org.apache.batik.bridge.ViewBox; 45 import org.apache.batik.bridge.UpdateManagerListener; 46 import org.apache.batik.bridge.UpdateManagerEvent; 47 48 import org.apache.batik.gvt.GraphicsNode; 49 50 import org.apache.batik.swing.JSVGCanvas; 51 import org.apache.batik.swing.gvt.JGVTComponentListener; 52 import org.apache.batik.swing.svg.SVGDocumentLoaderAdapter; 53 import org.apache.batik.swing.svg.SVGDocumentLoaderEvent; 54 import org.apache.batik.swing.svg.GVTTreeBuilderListener; 55 import org.apache.batik.swing.svg.GVTTreeBuilderEvent; 56 57 import org.apache.batik.util.SVGConstants; 58 59 import org.w3c.dom.svg.SVGSVGElement; 60 import org.w3c.dom.svg.SVGDocument; 61 62 import org.w3c.dom.events.Event ; 63 import org.w3c.dom.events.EventListener ; 64 65 66 78 public class JSVGScrollPane extends JPanel 79 { 80 protected JSVGCanvas canvas; 81 82 protected JPanel horizontalPanel; 83 protected JScrollBar vertical; 84 protected JScrollBar horizontal; 85 protected Component cornerBox; 86 protected SBListener hsbListener; 87 protected SBListener vsbListener; 88 89 protected Rectangle2D viewBox = null; protected boolean ignoreScrollChange = false; 91 92 93 97 public JSVGScrollPane(JSVGCanvas canvas) 98 { 99 super(); 100 this.canvas = canvas; 101 canvas.setRecenterOnResize(false); 102 103 vertical = new JScrollBar (JScrollBar.VERTICAL, 0, 0, 0, 0); 105 horizontal = new JScrollBar (JScrollBar.HORIZONTAL, 0, 0, 0, 0); 106 107 horizontalPanel = new JPanel (new BorderLayout ()); 109 horizontalPanel.add(horizontal, BorderLayout.CENTER); 110 cornerBox = Box.createRigidArea 111 (new Dimension (vertical.getPreferredSize().width, 112 horizontal.getPreferredSize().height)); 113 horizontalPanel.add(cornerBox, BorderLayout.EAST); 114 115 hsbListener = createScrollBarListener(false); 117 horizontal.getModel().addChangeListener(hsbListener); 118 119 vsbListener = createScrollBarListener(true); 120 vertical.getModel().addChangeListener(vsbListener); 121 122 horizontalPanel.setVisible(false); 124 vertical.setVisible(false); 125 126 128 setLayout(new BorderLayout ()); 130 add(canvas, BorderLayout.CENTER); 131 add(vertical, BorderLayout.EAST); 132 add(horizontalPanel, BorderLayout.SOUTH); 133 134 canvas.addSVGDocumentLoaderListener 136 (new SVGScrollDocumentLoaderListener()); 137 138 ScrollListener xlistener = new ScrollListener(); 140 this.addComponentListener(xlistener); 141 canvas.addJGVTComponentListener(xlistener); 142 canvas.addGVTTreeBuilderListener(xlistener); 143 canvas.addUpdateManagerListener(xlistener); 144 } 146 147 151 protected SBListener createScrollBarListener(boolean isVertical) { 152 return new SBListener(isVertical); 153 } 154 155 public JSVGCanvas getCanvas() { 156 return canvas; 157 } 158 159 160 class SVGScrollDocumentLoaderListener extends SVGDocumentLoaderAdapter { 161 public void documentLoadingCompleted(SVGDocumentLoaderEvent e) { 162 SVGSVGElement root = e.getSVGDocument().getRootElement(); 163 root.addEventListener 164 (SVGConstants.SVG_SVGZOOM_EVENT_TYPE, 165 new EventListener () { 166 public void handleEvent(Event evt) { 167 if (!(evt.getTarget() instanceof SVGSVGElement)) 168 return; 169 SVGSVGElement svg = (SVGSVGElement) evt.getTarget(); 172 scaleChange(svg.getCurrentScale()); 173 } }, false); 175 } }; 177 178 179 184 public void reset() 185 { 186 viewBox = null; 187 horizontalPanel.setVisible(false); 188 vertical.setVisible(false); 189 revalidate(); 190 } 192 193 197 protected void setScrollPosition() { 198 checkAndSetViewBoxRect(); 199 if (viewBox == null) return; 200 201 AffineTransform crt = canvas.getRenderingTransform(); 202 AffineTransform vbt = canvas.getViewBoxTransform(); 203 if (crt == null) crt = new AffineTransform (); 204 if (vbt == null) vbt = new AffineTransform (); 205 206 Rectangle r2d = vbt.createTransformedShape(viewBox).getBounds(); 207 int tx = 0, ty = 0; 209 if (r2d.x < 0) tx -= r2d.x; 210 if (r2d.y < 0) ty -= r2d.y; 211 212 int deltaX = horizontal.getValue()-tx; 213 int deltaY = vertical.getValue() -ty; 214 215 219 crt.preConcatenate 220 (AffineTransform.getTranslateInstance(-deltaX, -deltaY)); 221 canvas.setRenderingTransform(crt); 222 } 224 225 226 236 255 256 257 268 protected class SBListener implements ChangeListener 269 { 270 protected boolean inDrag = false; 272 protected int startValue; 273 274 protected boolean isVertical; 275 276 public SBListener(boolean vertical) 277 { 278 isVertical = vertical; 279 } 281 public synchronized void stateChanged(ChangeEvent e) 282 { 283 if(ignoreScrollChange) return; 286 287 Object src = e.getSource(); 288 if (!(src instanceof BoundedRangeModel )) 289 return; 290 291 int val = ((isVertical)?vertical.getValue(): 292 horizontal.getValue()); 293 294 BoundedRangeModel brm = (BoundedRangeModel )src; 295 if (brm.getValueIsAdjusting()) { 296 if (!inDrag) { 297 inDrag = true; 298 startValue = val; 299 } else { 300 AffineTransform at; 301 if (isVertical) { 302 at = AffineTransform.getTranslateInstance 303 (0, startValue-val); 304 } else { 305 at = AffineTransform.getTranslateInstance 306 (startValue-val, 0); 307 } 308 canvas.setPaintingTransform(at); 309 } 310 } else { 311 if (inDrag) { 312 inDrag = false; 313 if (val == startValue) { 314 canvas.setPaintingTransform(new AffineTransform ()); 315 return; 316 } 317 } 318 setScrollPosition(); 319 } 320 } } 323 324 325 326 protected class ScrollListener extends ComponentAdapter 327 implements JGVTComponentListener, GVTTreeBuilderListener, 328 UpdateManagerListener 329 { 330 protected boolean isReady = false; 331 332 public void componentTransformChanged(ComponentEvent evt) 333 { 334 if(isReady) 335 resizeScrollBars(); 336 } 338 339 public void componentResized(ComponentEvent evt) 340 { 341 if(isReady) 342 resizeScrollBars(); 343 } 345 346 public void gvtBuildPrepare (GVTTreeBuilderEvent e) { 347 isReady = false; 348 vertical .setVisible(false); 350 horizontalPanel.setVisible(false); 351 cornerBox .setVisible(false); 352 } 353 public void gvtBuildCompleted(GVTTreeBuilderEvent e) 354 { 355 isReady = true; 356 viewBox = null; } 359 public void updateCompleted(UpdateManagerEvent e) { 360 if (viewBox == null) { 361 resizeScrollBars(); 362 return; 363 } 364 365 Rectangle2D newview = getViewBoxRect(); 366 if ((newview.getX() != viewBox.getX()) || 367 (newview.getY() != viewBox.getY()) || 368 (newview.getWidth() != viewBox.getWidth()) || 369 (newview.getHeight() != viewBox.getHeight())) { 370 viewBox = newview; 371 resizeScrollBars(); 372 } 373 } 374 375 376 public void gvtBuildCancelled(GVTTreeBuilderEvent e) { } 377 public void gvtBuildFailed (GVTTreeBuilderEvent e) { } 378 public void gvtBuildStarted (GVTTreeBuilderEvent e) { } 379 380 public void managerStarted (UpdateManagerEvent e) { } 381 public void managerSuspended(UpdateManagerEvent e) { } 382 public void managerResumed (UpdateManagerEvent e) { } 383 public void managerStopped (UpdateManagerEvent e) { } 384 public void updateStarted (UpdateManagerEvent e) { } 385 public void updateFailed (UpdateManagerEvent e) { } 386 387 } 389 390 395 protected void resizeScrollBars() 396 { 397 399 ignoreScrollChange = true; 400 401 checkAndSetViewBoxRect(); 402 if (viewBox == null) return; 403 404 AffineTransform vbt = canvas.getViewBoxTransform(); 405 if (vbt == null) vbt = new AffineTransform (); 406 407 Rectangle r2d = vbt.createTransformedShape(viewBox).getBounds(); 408 410 int maxW = r2d.width; 412 int maxH = r2d.height; 413 int tx = 0, ty = 0; 414 if (r2d.x > 0) maxW += r2d.x; 415 else tx -= r2d.x; 416 if (r2d.y > 0) maxH += r2d.y; 417 else ty -= r2d.y; 418 419 vertical.setValue(ty); 422 horizontal.setValue(tx); 423 424 Dimension vpSize = updateScrollbarVisibility 427 (tx, ty, maxW, maxH); 428 429 vertical. setValues(ty, vpSize.height, 0, maxH); 431 horizontal.setValues(tx, vpSize.width, 0, maxW); 432 433 vertical. setBlockIncrement( (int) (0.9f * vpSize.height) ); 437 horizontal.setBlockIncrement( (int) (0.9f * vpSize.width) ); 438 439 vertical. setUnitIncrement( (int) (0.2f * vpSize.height) ); 442 horizontal.setUnitIncrement( (int) (0.2f * vpSize.width) ); 443 444 ignoreScrollChange = false; 445 } 448 protected Dimension updateScrollbarVisibility(int tx, int ty, 449 int maxW, int maxH) { 450 456 Dimension vpSize = canvas.getSize(); 457 int maxVPW = vpSize.width; int minVPW = vpSize.width; 460 int maxVPH = vpSize.height; int minVPH = vpSize.height; 461 if (vertical.isVisible()) { 462 maxVPW += vertical.getPreferredSize().width; 463 } else { 464 minVPW -= vertical.getPreferredSize().width; 465 } 466 if (horizontalPanel.isVisible()) { 467 maxVPH += horizontal.getPreferredSize().height; 468 } else { 469 minVPH -= horizontal.getPreferredSize().height; 470 } 471 472 476 boolean vVis = (maxH > maxVPH) || (vertical.getValue() != 0); 478 boolean hVis = (maxW > maxVPW) || (horizontal.getValue() != 0); 479 Dimension ret = new Dimension (); 480 481 if (vVis) { 487 if (hVis) { 488 horizontalPanel.setVisible(true); 489 vertical.setVisible(true); 490 cornerBox.setVisible(true); 491 492 ret.width = minVPW; 493 ret.height = minVPH; 494 } else { 495 vertical.setVisible(true); 496 ret.width = minVPW; 497 if (maxW > minVPW) { 498 horizontalPanel.setVisible(true); 499 cornerBox.setVisible(true); 500 ret.height = minVPH; 501 } else { 502 horizontalPanel.setVisible(false); 503 cornerBox.setVisible(false); 504 ret.height = maxVPH; 505 } 506 } 507 } else { 508 if (hVis) { 509 horizontalPanel.setVisible(true); 510 ret.height = minVPH; 511 if (maxH > minVPH) { 512 vertical.setVisible(true); 513 cornerBox.setVisible(true); 514 ret.width = minVPW; 515 } else { 516 vertical.setVisible(false); 517 cornerBox.setVisible(false); 518 ret.width = maxVPW; 519 } 520 } else { 521 vertical .setVisible(false); 522 horizontalPanel.setVisible(false); 523 cornerBox .setVisible(false); 524 ret.width = maxVPW; 525 ret.height = maxVPH; 526 } 527 } 528 529 return ret; 531 } 532 533 538 protected void checkAndSetViewBoxRect() { 539 if (viewBox != null) return; 540 541 viewBox = getViewBoxRect(); 542 } 547 548 protected Rectangle2D getViewBoxRect() { 549 SVGDocument doc = canvas.getSVGDocument(); 550 if (doc == null) return null; 551 SVGSVGElement el = doc.getRootElement(); 552 if (el == null) return null; 553 554 String viewBoxStr = el.getAttributeNS 555 (null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE); 556 if (viewBoxStr.length() != 0) { 557 float[] rect = ViewBox.parseViewBoxAttribute(el, viewBoxStr); 558 return new Rectangle2D.Float (rect[0], rect[1], 559 rect[2], rect[3]); 560 } 561 GraphicsNode gn = canvas.getGraphicsNode(); 562 if (gn == null) return null; 563 564 return (Rectangle2D )gn.getBounds().clone(); 565 } 566 567 573 public void scaleChange(float scale) 574 { 575 } 577 } 579 580 | Popular Tags |