1 18 package org.apache.batik.apps.svgbrowser; 19 20 import java.awt.BorderLayout ; 21 import java.awt.Dimension ; 22 import java.awt.FlowLayout ; 23 import java.awt.Frame ; 24 import java.awt.GridBagLayout ; 25 import java.awt.Insets ; 26 import java.awt.Shape ; 27 import java.awt.event.ActionEvent ; 28 import java.awt.geom.AffineTransform ; 29 import java.awt.geom.Rectangle2D ; 30 import java.text.AttributedCharacterIterator ; 31 import java.util.HashMap ; 32 import java.util.Locale ; 33 import java.util.Map ; 34 import java.util.ResourceBundle ; 35 36 import javax.swing.AbstractAction ; 37 import javax.swing.Action ; 38 import javax.swing.BorderFactory ; 39 import javax.swing.ButtonGroup ; 40 import javax.swing.JButton ; 41 import javax.swing.JCheckBox ; 42 import javax.swing.JDialog ; 43 import javax.swing.JLabel ; 44 import javax.swing.JOptionPane ; 45 import javax.swing.JPanel ; 46 import javax.swing.JRadioButton ; 47 import javax.swing.JTextField ; 48 49 import org.apache.batik.gvt.GVTTreeWalker; 50 import org.apache.batik.gvt.GraphicsNode; 51 import org.apache.batik.gvt.TextNode; 52 import org.apache.batik.gvt.text.Mark; 53 import org.apache.batik.swing.JSVGCanvas; 54 import org.apache.batik.util.gui.ExtendedGridBagConstraints; 55 import org.apache.batik.util.gui.resource.ActionMap; 56 import org.apache.batik.util.gui.resource.ButtonFactory; 57 import org.apache.batik.util.gui.resource.MissingListenerException; 58 import org.apache.batik.util.gui.resource.ResourceManager; 59 60 67 public class FindDialog extends JDialog implements ActionMap { 68 69 72 protected final static String RESOURCES = 73 "org.apache.batik.apps.svgbrowser.resources.FindDialog"; 74 75 public final static String FIND_ACTION = "FindButtonAction"; 77 78 public final static String CLEAR_ACTION = "ClearButtonAction"; 79 80 public final static String CLOSE_ACTION = "CloseButtonAction"; 81 82 85 protected static ResourceBundle bundle; 86 87 90 protected static ResourceManager resources; 91 92 static { 93 bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); 94 resources = new ResourceManager(bundle); 95 } 96 97 98 protected ButtonFactory buttonFactory; 99 100 101 protected GraphicsNode gvtRoot; 102 103 104 protected GVTTreeWalker walker; 105 106 107 protected int currentIndex; 108 109 110 protected JTextField search; 111 112 113 protected JButton findButton; 114 115 116 protected JButton clearButton; 117 118 119 protected JButton closeButton; 120 121 122 protected JCheckBox caseSensitive; 123 124 125 protected JSVGCanvas svgCanvas; 126 127 128 protected JRadioButton highlightButton; 129 130 131 protected JRadioButton highlightCenterButton; 132 133 134 protected JRadioButton highlightCenterZoomButton; 135 138 public FindDialog(JSVGCanvas svgCanvas) { 139 this(null, svgCanvas); 140 } 141 142 145 public FindDialog(Frame owner, JSVGCanvas svgCanvas) { 146 super(owner, resources.getString("Dialog.title")); 147 this.svgCanvas = svgCanvas; 148 149 buttonFactory = new ButtonFactory(bundle, this); 150 151 listeners.put(FIND_ACTION, 152 new FindButtonAction()); 153 154 listeners.put(CLEAR_ACTION, 155 new ClearButtonAction()); 156 157 listeners.put(CLOSE_ACTION, 158 new CloseButtonAction()); 159 160 JPanel p = new JPanel (new BorderLayout ()); 161 p.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); 162 p.add(createFindPanel(), BorderLayout.CENTER); 163 p.add(createShowResultPanel(), BorderLayout.SOUTH); 164 165 getContentPane().add(p, BorderLayout.CENTER); 166 getContentPane().add(createButtonsPanel(), BorderLayout.SOUTH); 167 } 168 169 172 protected JPanel createFindPanel() { 173 JPanel panel = new JPanel (new GridBagLayout ()); 174 175 panel.setBorder(BorderFactory.createTitledBorder 176 (BorderFactory.createEtchedBorder(), 177 resources.getString("Panel.title"))); 178 179 ExtendedGridBagConstraints gbc = new ExtendedGridBagConstraints(); 180 gbc.insets = new Insets (2, 2, 2, 2); 181 182 gbc.anchor = ExtendedGridBagConstraints.EAST; 183 gbc.fill = ExtendedGridBagConstraints.NONE; 184 gbc.setWeight(0, 0); 185 gbc.setGridBounds(0, 0, 1, 1); 186 panel.add(new JLabel (resources.getString("FindLabel.text")), gbc); 187 188 gbc.fill = ExtendedGridBagConstraints.HORIZONTAL; 189 gbc.setWeight(1.0, 0); 190 gbc.setGridBounds(1, 0, 2, 1); 191 panel.add(search = new JTextField (20), gbc); 192 193 gbc.fill = ExtendedGridBagConstraints.NONE; 194 gbc.anchor = ExtendedGridBagConstraints.WEST; 195 gbc.setWeight(0, 0); 196 gbc.setGridBounds(1, 1, 1, 1); 197 caseSensitive = buttonFactory.createJCheckBox("CaseSensitiveCheckBox"); 198 panel.add(caseSensitive, gbc); 199 200 return panel; 201 } 202 203 protected JPanel createShowResultPanel() { 204 JPanel panel = new JPanel (new GridBagLayout ()); 205 206 panel.setBorder(BorderFactory.createTitledBorder 207 (BorderFactory.createEtchedBorder(), 208 resources.getString("ShowResultPanel.title"))); 209 210 ExtendedGridBagConstraints gbc = new ExtendedGridBagConstraints(); 211 gbc.insets = new Insets (2, 2, 2, 2); 212 213 gbc.anchor = ExtendedGridBagConstraints.WEST; 214 gbc.fill = ExtendedGridBagConstraints.NONE; 215 gbc.setWeight(0, 0); 216 217 ButtonGroup grp = new ButtonGroup (); 218 219 highlightButton = buttonFactory.createJRadioButton("Highlight"); 220 highlightButton.setSelected(true); 221 grp.add(highlightButton); 222 gbc.setGridBounds(0, 0, 1, 1); 223 panel.add(highlightButton, gbc); 224 225 highlightCenterButton = 226 buttonFactory.createJRadioButton("HighlightAndCenter"); 227 grp.add(highlightCenterButton); 228 gbc.setGridBounds(0, 1, 1, 1); 229 panel.add(highlightCenterButton, gbc); 230 231 highlightCenterZoomButton = 232 buttonFactory.createJRadioButton("HighlightCenterAndZoom"); 233 grp.add(highlightCenterZoomButton); 234 gbc.setGridBounds(0, 2, 1, 1); 235 panel.add(highlightCenterZoomButton, gbc); 236 237 return panel; 238 } 239 240 243 protected JPanel createButtonsPanel() { 244 JPanel panel = new JPanel (new FlowLayout (FlowLayout.RIGHT)); 245 panel.add(findButton = buttonFactory.createJButton("FindButton")); 246 panel.add(clearButton = buttonFactory.createJButton("ClearButton")); 247 panel.add(closeButton = buttonFactory.createJButton("CloseButton")); 248 return panel; 249 } 250 251 252 256 public void setGraphicsNode(GraphicsNode gvtRoot) { 257 this.gvtRoot = gvtRoot; 258 if (gvtRoot != null) { 259 this.walker = new GVTTreeWalker(gvtRoot); 260 } else { 261 this.walker = null; 262 } 263 } 264 265 271 protected GraphicsNode getNext(String text) { 272 if (walker == null && gvtRoot != null) { 273 walker = new GVTTreeWalker(gvtRoot); 274 } 275 GraphicsNode gn = walker.getCurrentGraphicsNode(); 276 int index = match(gn, text, currentIndex+text.length()); 277 if (index >= 0) { 278 currentIndex = index; 279 } else { 280 currentIndex = 0; 281 gn = walker.nextGraphicsNode(); 282 while (gn != null && 283 ((currentIndex = match(gn, text, currentIndex)) < 0)) { 284 currentIndex = 0; 285 gn = walker.nextGraphicsNode(); 286 } 287 } 288 return gn; 289 } 290 291 298 protected int match(GraphicsNode node, String text, int index) { 299 if (!(node instanceof TextNode) 300 || !node.isVisible() 301 || text == null || text.length() == 0) { 302 return -1; 303 } 304 String s = ((TextNode)node).getText(); 305 if (!caseSensitive.isSelected()) { 306 s = s.toLowerCase(); 307 text = text.toLowerCase(); 308 } 309 return s.indexOf(text, index); 310 } 311 312 315 protected void showSelectedGraphicsNode() { 316 GraphicsNode gn = walker.getCurrentGraphicsNode(); 317 if (!(gn instanceof TextNode)) { 318 return; 319 } 320 TextNode textNode = (TextNode)gn; 321 String text = textNode.getText(); 323 String pattern = search.getText(); 324 if (!caseSensitive.isSelected()) { 325 text = text.toLowerCase(); 326 pattern = pattern.toLowerCase(); 327 } 328 int end = text.indexOf(pattern, currentIndex); 329 330 AttributedCharacterIterator aci = 331 textNode.getAttributedCharacterIterator(); 332 aci.first(); 333 for (int i=0; i < end; ++i) { 334 aci.next(); 335 } 336 Mark startMark = textNode.getMarkerForChar(aci.getIndex(), true); 337 338 for (int i = 0; i < pattern.length()-1; ++i) { 339 aci.next(); 340 } 341 Mark endMark = textNode.getMarkerForChar(aci.getIndex(), false); 342 svgCanvas.select(startMark, endMark); 343 344 if (highlightButton.isSelected()) { 346 return; 347 } 348 349 Shape s = textNode.getHighlightShape(); 351 AffineTransform at; 352 if (highlightCenterZoomButton.isSelected()) { 353 at = svgCanvas.getInitialTransform(); 354 } else { 355 at = svgCanvas.getRenderingTransform(); 356 } 357 Rectangle2D gnb = at.createTransformedShape(s).getBounds(); 359 360 Dimension canvasSize = svgCanvas.getSize(); 361 AffineTransform Tx = AffineTransform.getTranslateInstance 364 (-gnb.getX()-gnb.getWidth()/2, 365 -gnb.getY()-gnb.getHeight()/2); 366 367 if (highlightCenterZoomButton.isSelected()) { 368 double sx = canvasSize.width/gnb.getWidth(); 371 double sy = canvasSize.height/gnb.getHeight(); 372 double scale = Math.min(sx, sy) / 8; 373 if (scale > 1) { 374 Tx.preConcatenate 375 (AffineTransform.getScaleInstance(scale, scale)); 376 } 377 } 378 Tx.preConcatenate(AffineTransform.getTranslateInstance 379 (canvasSize.width/2, canvasSize.height/2)); 380 AffineTransform newRT = new AffineTransform (at); 382 newRT.preConcatenate(Tx); 383 svgCanvas.setRenderingTransform(newRT); 385 } 386 387 389 392 protected Map listeners = new HashMap (10); 393 394 400 public Action getAction(String key) throws MissingListenerException { 401 return (Action )listeners.get(key); 402 } 403 404 408 411 protected class FindButtonAction extends AbstractAction { 412 public void actionPerformed(ActionEvent e) { 413 String text = search.getText(); 414 if (text == null || text.length() == 0) { 415 return; 416 } 417 GraphicsNode gn = getNext(text); 418 if (gn != null) { 419 showSelectedGraphicsNode(); 420 } else { 421 walker = null; 423 JOptionPane.showMessageDialog(FindDialog.this, 424 resources.getString("End.text"), 425 resources.getString("End.title"), 426 JOptionPane.INFORMATION_MESSAGE); 427 } 428 } 429 } 430 431 434 protected class ClearButtonAction extends AbstractAction { 435 public void actionPerformed(ActionEvent e) { 436 search.setText(null); 437 walker = null; 438 } 439 } 440 441 444 protected class CloseButtonAction extends AbstractAction { 445 public void actionPerformed(ActionEvent e) { 446 dispose(); 447 } 448 } 449 } 450 451 452 | Popular Tags |