KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > apps > svgbrowser > FindDialog


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.apps.svgbrowser;
19
20 import java.awt.BorderLayout JavaDoc;
21 import java.awt.Dimension JavaDoc;
22 import java.awt.FlowLayout JavaDoc;
23 import java.awt.Frame JavaDoc;
24 import java.awt.GridBagLayout JavaDoc;
25 import java.awt.Insets JavaDoc;
26 import java.awt.Shape JavaDoc;
27 import java.awt.event.ActionEvent JavaDoc;
28 import java.awt.geom.AffineTransform JavaDoc;
29 import java.awt.geom.Rectangle2D JavaDoc;
30 import java.text.AttributedCharacterIterator JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Locale JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.ResourceBundle JavaDoc;
35
36 import javax.swing.AbstractAction JavaDoc;
37 import javax.swing.Action JavaDoc;
38 import javax.swing.BorderFactory JavaDoc;
39 import javax.swing.ButtonGroup JavaDoc;
40 import javax.swing.JButton JavaDoc;
41 import javax.swing.JCheckBox JavaDoc;
42 import javax.swing.JDialog JavaDoc;
43 import javax.swing.JLabel JavaDoc;
44 import javax.swing.JOptionPane JavaDoc;
45 import javax.swing.JPanel JavaDoc;
46 import javax.swing.JRadioButton JavaDoc;
47 import javax.swing.JTextField JavaDoc;
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 /**
61  * This class represents a Dialog that lets the user searching for text inside
62  * an SVG document.
63  *
64  * @author <a HREF="mailto:tkormann@apache.org">Thierry Kormann</a>
65  * @version $Id: FindDialog.java,v 1.10 2004/08/18 07:12:27 vhardy Exp $
66  */

67 public class FindDialog extends JDialog JavaDoc implements ActionMap {
68
69     /**
70      * The resource file name
71      */

72     protected final static String JavaDoc RESOURCES =
73         "org.apache.batik.apps.svgbrowser.resources.FindDialog";
74
75     // action names
76
public final static String JavaDoc FIND_ACTION = "FindButtonAction";
77
78     public final static String JavaDoc CLEAR_ACTION = "ClearButtonAction";
79
80     public final static String JavaDoc CLOSE_ACTION = "CloseButtonAction";
81
82     /**
83      * The resource bundle
84      */

85     protected static ResourceBundle JavaDoc bundle;
86
87     /**
88      * The resource manager
89      */

90     protected static ResourceManager resources;
91
92     static {
93         bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
94         resources = new ResourceManager(bundle);
95     }
96
97     /** The button factory */
98     protected ButtonFactory buttonFactory;
99
100     /** The GVT root into which text is searched. */
101     protected GraphicsNode gvtRoot;
102
103     /** The GVTTreeWalker used to scan the GVT Tree. */
104     protected GVTTreeWalker walker;
105
106     /** The current index in the TextNode's string. */
107     protected int currentIndex;
108
109     /** The TextField that owns the text to search. */
110     protected JTextField JavaDoc search;
111
112     /** The next button. */
113     protected JButton JavaDoc findButton;
114
115     /** The next button. */
116     protected JButton JavaDoc clearButton;
117
118     /** The cancel button. */
119     protected JButton JavaDoc closeButton;
120
121     /** The case sensitive button. */
122     protected JCheckBox JavaDoc caseSensitive;
123
124     /** The canvas. */
125     protected JSVGCanvas svgCanvas;
126
127     /** The highlight button. */
128     protected JRadioButton JavaDoc highlightButton;
129
130     /** The highlight and center button. */
131     protected JRadioButton JavaDoc highlightCenterButton;
132
133     /** The highlight center and zoom button. */
134     protected JRadioButton JavaDoc highlightCenterZoomButton;
135     /**
136      * Constructs a new <tt>FindDialog</tt>.
137      */

138     public FindDialog(JSVGCanvas svgCanvas) {
139         this(null, svgCanvas);
140     }
141
142     /**
143      * Constructs a new <tt>FindDialog</tt>.
144      */

145     public FindDialog(Frame JavaDoc 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 JavaDoc p = new JPanel JavaDoc(new BorderLayout JavaDoc());
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     /**
170      * Creates the Find panel.
171      */

172     protected JPanel JavaDoc createFindPanel() {
173         JPanel JavaDoc panel = new JPanel JavaDoc(new GridBagLayout JavaDoc());
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 JavaDoc(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 JavaDoc(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 JavaDoc(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 JavaDoc createShowResultPanel() {
204         JPanel JavaDoc panel = new JPanel JavaDoc(new GridBagLayout JavaDoc());
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 JavaDoc(2, 2, 2, 2);
212
213         gbc.anchor = ExtendedGridBagConstraints.WEST;
214         gbc.fill = ExtendedGridBagConstraints.NONE;
215         gbc.setWeight(0, 0);
216
217     ButtonGroup JavaDoc grp = new ButtonGroup JavaDoc();
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     /**
241      * Creates the buttons panel
242      */

243     protected JPanel JavaDoc createButtonsPanel() {
244         JPanel JavaDoc panel = new JPanel JavaDoc(new FlowLayout JavaDoc(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     /**
253      * Sets the graphics node into which text is searched.
254      * @param gvtRoot the GVT root node
255      */

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     /**
266      * Returns the next GraphicsNode that matches the specified string or null
267      * if any.
268      *
269      * @param text the text to match
270      */

271     protected GraphicsNode getNext(String JavaDoc 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     /**
292      * Returns the index inside the specified TextNode of the
293      * specified text, or -1 if not found.
294      *
295      * @param node the graphics node to check
296      * @param text the text use to match
297      * @param index the index from which to start */

298     protected int match(GraphicsNode node, String JavaDoc text, int index) {
299         if (!(node instanceof TextNode)
300             || !node.isVisible()
301             || text == null || text.length() == 0) {
302             return -1;
303         }
304         String JavaDoc 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     /**
313      * Shows the current selected <tt>TextNode</tt>.
314      */

315     protected void showSelectedGraphicsNode() {
316         GraphicsNode gn = walker.getCurrentGraphicsNode();
317         if (!(gn instanceof TextNode)) {
318             return;
319         }
320     TextNode textNode = (TextNode)gn;
321     // mark the selection of the substring found
322
String JavaDoc text = textNode.getText();
323     String JavaDoc 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 JavaDoc 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     // zoom on the TextNode if needed
345
if (highlightButton.isSelected()) {
346         return;
347     }
348
349     // get the highlight shape in GVT root (global) coordinate sytem
350
Shape JavaDoc s = textNode.getHighlightShape();
351     AffineTransform JavaDoc at;
352     if (highlightCenterZoomButton.isSelected()) {
353         at = svgCanvas.getInitialTransform();
354     } else {
355         at = svgCanvas.getRenderingTransform();
356     }
357     // get the bounds of the highlight shape in the canvas coordinate system
358
Rectangle2D JavaDoc gnb = at.createTransformedShape(s).getBounds();
359         
360     Dimension JavaDoc canvasSize = svgCanvas.getSize();
361     // translate the highlight region to (0, 0) in the canvas coordinate
362
// system
363
AffineTransform JavaDoc Tx = AffineTransform.getTranslateInstance
364         (-gnb.getX()-gnb.getWidth()/2,
365          -gnb.getY()-gnb.getHeight()/2);
366     
367     if (highlightCenterZoomButton.isSelected()) {
368         // zoom on the highlight shape such as the shape takes x% of the
369
// canvas size
370
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     // take into account the initial transform
381
AffineTransform JavaDoc newRT = new AffineTransform JavaDoc(at);
382     newRT.preConcatenate(Tx);
383     // change the rendering transform
384
svgCanvas.setRenderingTransform(newRT);
385     }
386
387     // ActionMap implementation
388

389     /**
390      * The map that contains the listeners
391      */

392     protected Map JavaDoc listeners = new HashMap JavaDoc(10);
393
394     /**
395      * Returns the action associated with the given string
396      * or null on error
397      * @param key the key mapped with the action to get
398      * @throws MissingListenerException if the action is not found
399      */

400     public Action JavaDoc getAction(String JavaDoc key) throws MissingListenerException {
401         return (Action JavaDoc)listeners.get(key);
402     }
403
404     //////////////////////////////////////////////////////////////////////////
405
// Action implementation
406
//////////////////////////////////////////////////////////////////////////
407

408     /**
409      * The action associated to the 'find' button.
410      */

411     protected class FindButtonAction extends AbstractAction JavaDoc {
412         public void actionPerformed(ActionEvent JavaDoc e) {
413             String JavaDoc 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         // end of document reached
422
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     /**
432      * The action associated to the 'clear' button.
433      */

434     protected class ClearButtonAction extends AbstractAction JavaDoc {
435         public void actionPerformed(ActionEvent JavaDoc e) {
436         search.setText(null);
437         walker = null;
438         }
439     }
440
441     /**
442      * The action associated to the 'close' button.
443      */

444     protected class CloseButtonAction extends AbstractAction JavaDoc {
445         public void actionPerformed(ActionEvent JavaDoc e) {
446             dispose();
447         }
448     }
449 }
450
451
452
Popular Tags