View | Details | Raw Unified | Return to bug 42741
Collapse All | Expand All

(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/dom/svg/SVGContext.java (+5 lines)
Lines 94-97 Link Here
94
     * Returns the font-size on the associated element.
94
     * Returns the font-size on the associated element.
95
     */
95
     */
96
    float getFontSize();
96
    float getFontSize();
97
    
98
    /**
99
     * whether parsing should be strict (throw exception on error) or not
100
     */
101
    boolean strictParsing = false;
97
}
102
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java (-2 / +8 lines)
Lines 22-27 Link Here
22
import java.awt.Component;
22
import java.awt.Component;
23
import javax.swing.JDialog;
23
import javax.swing.JDialog;
24
import javax.swing.JOptionPane;
24
import javax.swing.JOptionPane;
25
26
import org.apache.batik.swing.JSVGCanvas;
27
import org.apache.batik.util.gui.ErrorConsole;
25
import org.apache.batik.util.gui.JErrorPane;
28
import org.apache.batik.util.gui.JErrorPane;
26
29
27
/**
30
/**
Lines 53-60 Link Here
53
     * Displays an error resulting from the specified Exception.
56
     * Displays an error resulting from the specified Exception.
54
     */
57
     */
55
    public void displayError(Exception ex) {
58
    public void displayError(Exception ex) {
56
        JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
59
//        JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
57
        JDialog dialog = pane.createDialog(parentComponent, "ERROR");
60
    	ErrorConsole console = ErrorConsole.getInstance();
61
    	// <!FIX ME> Document is null for now, how to get access to it??
62
    	console.add(ex, null, JOptionPane.ERROR_MESSAGE);
63
        JDialog dialog = ErrorConsole.createDialog(parentComponent, "ERROR");
58
        dialog.setModal(false);
64
        dialog.setModal(false);
59
        dialog.setVisible(true);
65
        dialog.setVisible(true);
60
    }
66
    }
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java (-3 / +6 lines)
Lines 57-62 Link Here
57
import org.apache.batik.swing.svg.SVGUserAgent;
57
import org.apache.batik.swing.svg.SVGUserAgent;
58
import org.apache.batik.util.SVGConstants;
58
import org.apache.batik.util.SVGConstants;
59
import org.apache.batik.util.XMLConstants;
59
import org.apache.batik.util.XMLConstants;
60
import org.apache.batik.util.gui.ErrorConsole;
60
import org.apache.batik.util.gui.JErrorPane;
61
import org.apache.batik.util.gui.JErrorPane;
61
62
62
import org.w3c.dom.Element;
63
import org.w3c.dom.Element;
Lines 1070-1078 Link Here
1070
            if (svgUserAgent != null) {
1071
            if (svgUserAgent != null) {
1071
                super.displayError(ex);
1072
                super.displayError(ex);
1072
            } else {
1073
            } else {
1073
                JErrorPane pane =
1074
//                JErrorPane pane =
1074
                    new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
1075
//                    new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
1075
                JDialog dialog = pane.createDialog(JSVGCanvas.this, "ERROR");
1076
            	ErrorConsole console = ErrorConsole.getInstance();
1077
            	console.add(ex, getURI(), JOptionPane.ERROR_MESSAGE);
1078
                JDialog dialog = ErrorConsole.createDialog(JSVGCanvas.this, "ERROR");
1076
                dialog.setModal(false);
1079
                dialog.setModal(false);
1077
                dialog.setVisible(true); // Safe to be called from any thread
1080
                dialog.setVisible(true); // Safe to be called from any thread
1078
            }
1081
            }
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java (+10 lines)
Lines 20-31 Link Here
20
20
21
import java.io.InputStream;
21
import java.io.InputStream;
22
import java.io.IOException;
22
import java.io.IOException;
23
import java.lang.reflect.Proxy;
23
import java.util.HashMap;
24
import java.util.HashMap;
24
25
25
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
26
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
26
import org.apache.batik.dom.svg.SVGDocumentFactory;
27
import org.apache.batik.dom.svg.SVGDocumentFactory;
27
import org.apache.batik.dom.util.DocumentDescriptor;
28
import org.apache.batik.dom.util.DocumentDescriptor;
29
import org.apache.batik.swing.svg.SVGDocumentLoader;
28
import org.apache.batik.util.CleanerThread;
30
import org.apache.batik.util.CleanerThread;
31
import org.apache.batik.util.gui.ErrorHandlerProxy;
29
32
30
import org.w3c.dom.Document;
33
import org.w3c.dom.Document;
31
import org.w3c.dom.Element;
34
import org.w3c.dom.Element;
Lines 104-109 Link Here
104
            return ret;
107
            return ret;
105
108
106
        SVGDocument document = documentFactory.createSVGDocument(uri);
109
        SVGDocument document = documentFactory.createSVGDocument(uri);
110
//		System.out.println("Installing proxy");
111
//		SVGDocumentFactory documentFactoryProxy = (SVGDocumentFactory) Proxy
112
//				.newProxyInstance(SVGDocumentFactory.class
113
//						.getClassLoader(),
114
//						new Class[] { SVGDocumentFactory.class },
115
//						new ErrorHandlerProxy(documentFactory, uri));
116
//        SVGDocument document = documentFactoryProxy.createSVGDocument(uri);
107
117
108
        DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
118
        DocumentDescriptor desc = documentFactory.getDocumentDescriptor();
109
        DocumentState state = new DocumentState(uri, document, desc);
119
        DocumentState state = new DocumentState(uri, document, desc);
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/SVGRectElementBridge.java (-1 / +9 lines)
Lines 22-33 Link Here
22
import java.awt.geom.Rectangle2D;
22
import java.awt.geom.Rectangle2D;
23
import java.awt.geom.RoundRectangle2D;
23
import java.awt.geom.RoundRectangle2D;
24
24
25
import javax.swing.JOptionPane;
26
25
import org.apache.batik.dom.svg.AbstractSVGAnimatedLength;
27
import org.apache.batik.dom.svg.AbstractSVGAnimatedLength;
26
import org.apache.batik.dom.svg.AnimatedLiveAttributeValue;
28
import org.apache.batik.dom.svg.AnimatedLiveAttributeValue;
27
import org.apache.batik.dom.svg.LiveAttributeException;
29
import org.apache.batik.dom.svg.LiveAttributeException;
28
import org.apache.batik.dom.svg.SVGOMRectElement;
30
import org.apache.batik.dom.svg.SVGOMRectElement;
29
import org.apache.batik.gvt.ShapeNode;
31
import org.apache.batik.gvt.ShapeNode;
30
import org.apache.batik.gvt.ShapePainter;
32
import org.apache.batik.gvt.ShapePainter;
33
import org.apache.batik.util.gui.ErrorConsole;
31
34
32
import org.w3c.dom.Element;
35
import org.w3c.dom.Element;
33
36
Lines 116-122 Link Here
116
            }
119
            }
117
            shapeNode.setShape(shape);
120
            shapeNode.setShape(shape);
118
        } catch (LiveAttributeException ex) {
121
        } catch (LiveAttributeException ex) {
119
            throw new BridgeException(ctx, ex);
122
        	if (strictParsing) {
123
	            throw new BridgeException(ctx, ex);
124
        	} else {
125
        		ctx.userAgent.displayError(ex);
126
        		shapeNode.setShape(new Rectangle2D.Float(0, 0, 0, 0));
127
        	}
120
        }
128
        }
121
    }
129
    }
122
130
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaPainter.java (+693 lines)
Line 0 Link Here
1
/*
2
 * TextAreaPainter.java - Paints the text area
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.ToolTipManager;
12
import javax.swing.text.*;
13
import javax.swing.JComponent;
14
import java.awt.event.MouseEvent;
15
import java.awt.*;
16
17
/**
18
 * The text area repaint manager. It performs double buffering and paints
19
 * lines of text.
20
 * @author Slava Pestov
21
 * @version $Id: TextAreaPainter.java,v 1.24 1999/12/13 03:40:30 sp Exp $
22
 */
23
public class TextAreaPainter extends JComponent implements TabExpander
24
{
25
	/**
26
	 * Creates a new repaint manager. This should be not be called
27
	 * directly.
28
	 */
29
	public TextAreaPainter(JEditTextArea textArea, TextAreaDefaults defaults)
30
	{
31
		this.textArea = textArea;
32
33
		setAutoscrolls(true);
34
		setDoubleBuffered(true);
35
		setOpaque(true);
36
37
		ToolTipManager.sharedInstance().registerComponent(this);
38
39
		currentLine = new Segment();
40
		currentLineIndex = -1;
41
42
		setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
43
44
		setFont(new Font("Monospaced",Font.PLAIN,14));
45
		setForeground(Color.black);
46
		setBackground(Color.white);
47
48
		blockCaret = defaults.blockCaret;
49
		styles = defaults.styles;
50
		cols = defaults.cols;
51
		rows = defaults.rows;
52
		caretColor = defaults.caretColor;
53
		selectionColor = defaults.selectionColor;
54
		lineHighlightColor = defaults.lineHighlightColor;
55
		lineHighlight = defaults.lineHighlight;
56
		bracketHighlightColor = defaults.bracketHighlightColor;
57
		bracketHighlight = defaults.bracketHighlight;
58
		paintInvalid = defaults.paintInvalid;
59
		eolMarkerColor = defaults.eolMarkerColor;
60
		eolMarkers = defaults.eolMarkers;
61
	}
62
63
	/**
64
	 * Returns if this component can be traversed by pressing the
65
	 * Tab key. This returns false.
66
	 */
67
	public final boolean isManagingFocus()
68
	{
69
		return false;
70
	}
71
72
	/**
73
	 * Returns the syntax styles used to paint colorized text. Entry <i>n</i>
74
	 * will be used to paint tokens with id = <i>n</i>.
75
	 * @see org.gjt.sp.jedit.syntax.Token
76
	 */
77
	public final SyntaxStyle[] getStyles()
78
	{
79
		return styles;
80
	}
81
82
	/**
83
	 * Sets the syntax styles used to paint colorized text. Entry <i>n</i>
84
	 * will be used to paint tokens with id = <i>n</i>.
85
	 * @param styles The syntax styles
86
	 * @see org.gjt.sp.jedit.syntax.Token
87
	 */
88
	public final void setStyles(SyntaxStyle[] styles)
89
	{
90
		this.styles = styles;
91
		repaint();
92
	}
93
94
	/**
95
	 * Returns the caret color.
96
	 */
97
	public final Color getCaretColor()
98
	{
99
		return caretColor;
100
	}
101
102
	/**
103
	 * Sets the caret color.
104
	 * @param caretColor The caret color
105
	 */
106
	public final void setCaretColor(Color caretColor)
107
	{
108
		this.caretColor = caretColor;
109
		invalidateSelectedLines();
110
	}
111
112
	/**
113
	 * Returns the selection color.
114
	 */
115
	public final Color getSelectionColor()
116
	{
117
		return selectionColor;
118
	}
119
120
	/**
121
	 * Sets the selection color.
122
	 * @param selectionColor The selection color
123
	 */
124
	public final void setSelectionColor(Color selectionColor)
125
	{
126
		this.selectionColor = selectionColor;
127
		invalidateSelectedLines();
128
	}
129
130
	/**
131
	 * Returns the line highlight color.
132
	 */
133
	public final Color getLineHighlightColor()
134
	{
135
		return lineHighlightColor;
136
	}
137
138
	/**
139
	 * Sets the line highlight color.
140
	 * @param lineHighlightColor The line highlight color
141
	 */
142
	public final void setLineHighlightColor(Color lineHighlightColor)
143
	{
144
		this.lineHighlightColor = lineHighlightColor;
145
		invalidateSelectedLines();
146
	}
147
148
	/**
149
	 * Returns true if line highlight is enabled, false otherwise.
150
	 */
151
	public final boolean isLineHighlightEnabled()
152
	{
153
		return lineHighlight;
154
	}
155
156
	/**
157
	 * Enables or disables current line highlighting.
158
	 * @param lineHighlight True if current line highlight should be enabled,
159
	 * false otherwise
160
	 */
161
	public final void setLineHighlightEnabled(boolean lineHighlight)
162
	{
163
		this.lineHighlight = lineHighlight;
164
		invalidateSelectedLines();
165
	}
166
167
	/**
168
	 * Returns the bracket highlight color.
169
	 */
170
	public final Color getBracketHighlightColor()
171
	{
172
		return bracketHighlightColor;
173
	}
174
175
	/**
176
	 * Sets the bracket highlight color.
177
	 * @param bracketHighlightColor The bracket highlight color
178
	 */
179
	public final void setBracketHighlightColor(Color bracketHighlightColor)
180
	{
181
		this.bracketHighlightColor = bracketHighlightColor;
182
		invalidateLine(textArea.getBracketLine());
183
	}
184
185
	/**
186
	 * Returns true if bracket highlighting is enabled, false otherwise.
187
	 * When bracket highlighting is enabled, the bracket matching the
188
	 * one before the caret (if any) is highlighted.
189
	 */
190
	public final boolean isBracketHighlightEnabled()
191
	{
192
		return bracketHighlight;
193
	}
194
195
	/**
196
	 * Enables or disables bracket highlighting.
197
	 * When bracket highlighting is enabled, the bracket matching the
198
	 * one before the caret (if any) is highlighted.
199
	 * @param bracketHighlight True if bracket highlighting should be
200
	 * enabled, false otherwise
201
	 */
202
	public final void setBracketHighlightEnabled(boolean bracketHighlight)
203
	{
204
		this.bracketHighlight = bracketHighlight;
205
		invalidateLine(textArea.getBracketLine());
206
	}
207
208
	/**
209
	 * Returns true if the caret should be drawn as a block, false otherwise.
210
	 */
211
	public final boolean isBlockCaretEnabled()
212
	{
213
		return blockCaret;
214
	}
215
216
	/**
217
	 * Sets if the caret should be drawn as a block, false otherwise.
218
	 * @param blockCaret True if the caret should be drawn as a block,
219
	 * false otherwise.
220
	 */
221
	public final void setBlockCaretEnabled(boolean blockCaret)
222
	{
223
		this.blockCaret = blockCaret;
224
		invalidateSelectedLines();
225
	}
226
227
	/**
228
	 * Returns the EOL marker color.
229
	 */
230
	public final Color getEOLMarkerColor()
231
	{
232
		return eolMarkerColor;
233
	}
234
235
	/**
236
	 * Sets the EOL marker color.
237
	 * @param eolMarkerColor The EOL marker color
238
	 */
239
	public final void setEOLMarkerColor(Color eolMarkerColor)
240
	{
241
		this.eolMarkerColor = eolMarkerColor;
242
		repaint();
243
	}
244
245
	/**
246
	 * Returns true if EOL markers are drawn, false otherwise.
247
	 */
248
	public final boolean getEOLMarkersPainted()
249
	{
250
		return eolMarkers;
251
	}
252
253
	/**
254
	 * Sets if EOL markers are to be drawn.
255
	 * @param eolMarkers True if EOL markers should be drawn, false otherwise
256
	 */
257
	public final void setEOLMarkersPainted(boolean eolMarkers)
258
	{
259
		this.eolMarkers = eolMarkers;
260
		repaint();
261
	}
262
263
	/**
264
	 * Returns true if invalid lines are painted as red tildes (~),
265
	 * false otherwise.
266
	 */
267
	public boolean getInvalidLinesPainted()
268
	{
269
		return paintInvalid;
270
	}
271
272
	/**
273
	 * Sets if invalid lines are to be painted as red tildes.
274
	 * @param paintInvalid True if invalid lines should be drawn, false otherwise
275
	 */
276
	public void setInvalidLinesPainted(boolean paintInvalid)
277
	{
278
		this.paintInvalid = paintInvalid;
279
	}
280
281
	/**
282
	 * Adds a custom highlight painter.
283
	 * @param highlight The highlight
284
	 */
285
	public void addCustomHighlight(Highlight highlight)
286
	{
287
		highlight.init(textArea,highlights);
288
		highlights = highlight;
289
	}
290
291
	/**
292
	 * Highlight interface.
293
	 */
294
	public interface Highlight
295
	{
296
		/**
297
		 * Called after the highlight painter has been added.
298
		 * @param textArea The text area
299
		 * @param next The painter this one should delegate to
300
		 */
301
		void init(JEditTextArea textArea, Highlight next);
302
303
		/**
304
		 * This should paint the highlight and delgate to the
305
		 * next highlight painter.
306
		 * @param gfx The graphics context
307
		 * @param line The line number
308
		 * @param y The y co-ordinate of the line
309
		 */
310
		void paintHighlight(Graphics gfx, int line, int y);
311
312
		/**
313
		 * Returns the tool tip to display at the specified
314
		 * location. If this highlighter doesn't know what to
315
		 * display, it should delegate to the next highlight
316
		 * painter.
317
		 * @param evt The mouse event
318
		 */
319
		String getToolTipText(MouseEvent evt);
320
	}
321
322
	/**
323
	 * Returns the tool tip to display at the specified location.
324
	 * @param evt The mouse event
325
	 */
326
	public String getToolTipText(MouseEvent evt)
327
	{
328
		if(highlights != null)
329
			return highlights.getToolTipText(evt);
330
		else
331
			return null;
332
	}
333
334
	/**
335
	 * Returns the font metrics used by this component.
336
	 */
337
	public FontMetrics getFontMetrics()
338
	{
339
		return fm;
340
	}
341
342
	/**
343
	 * Sets the font for this component. This is overridden to update the
344
	 * cached font metrics and to recalculate which lines are visible.
345
	 * @param font The font
346
	 */
347
	public void setFont(Font font)
348
	{
349
		super.setFont(font);
350
		fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
351
		textArea.recalculateVisibleLines();
352
	}
353
354
	/**
355
	 * Repaints the text.
356
	 * @param g The graphics context
357
	 */
358
	public void paint(Graphics gfx)
359
	{
360
		tabSize = fm.charWidth(' ') * ((Integer)textArea
361
			.getDocument().getProperty(
362
			PlainDocument.tabSizeAttribute)).intValue();
363
364
		Rectangle clipRect = gfx.getClipBounds();
365
366
		gfx.setColor(getBackground());
367
		gfx.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height);
368
369
		// We don't use yToLine() here because that method doesn't
370
		// return lines past the end of the document
371
		int height = fm.getHeight();
372
		int firstLine = textArea.getFirstLine();
373
		int firstInvalid = firstLine + clipRect.y / height;
374
		// Because the clipRect's height is usually an even multiple
375
		// of the font height, we subtract 1 from it, otherwise one
376
		// too many lines will always be painted.
377
		int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height;
378
379
		try
380
		{
381
			TokenMarker tokenMarker = textArea.getDocument()
382
				.getTokenMarker();
383
			int x = textArea.getHorizontalOffset();
384
385
			for(int line = firstInvalid; line <= lastInvalid; line++)
386
			{
387
				paintLine(gfx,tokenMarker,line,x);
388
			}
389
390
			if(tokenMarker != null && tokenMarker.isNextLineRequested())
391
			{
392
				int h = clipRect.y + clipRect.height;
393
				repaint(0,h,getWidth(),getHeight() - h);
394
			}
395
		}
396
		catch(Exception e)
397
		{
398
			System.err.println("Error repainting line"
399
				+ " range {" + firstInvalid + ","
400
				+ lastInvalid + "}:");
401
			e.printStackTrace();
402
		}
403
	}
404
405
	/**
406
	 * Marks a line as needing a repaint.
407
	 * @param line The line to invalidate
408
	 */
409
	public final void invalidateLine(int line)
410
	{
411
		repaint(0,textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(),
412
			getWidth(),fm.getHeight());
413
	}
414
415
	/**
416
	 * Marks a range of lines as needing a repaint.
417
	 * @param firstLine The first line to invalidate
418
	 * @param lastLine The last line to invalidate
419
	 */
420
	public final void invalidateLineRange(int firstLine, int lastLine)
421
	{
422
		repaint(0,textArea.lineToY(firstLine) + fm.getMaxDescent() + fm.getLeading(),
423
			getWidth(),(lastLine - firstLine + 1) * fm.getHeight());
424
	}
425
426
	/**
427
	 * Repaints the lines containing the selection.
428
	 */
429
	public final void invalidateSelectedLines()
430
	{
431
		invalidateLineRange(textArea.getSelectionStartLine(),
432
			textArea.getSelectionEndLine());
433
	}
434
435
	/**
436
	 * Implementation of TabExpander interface. Returns next tab stop after
437
	 * a specified point.
438
	 * @param x The x co-ordinate
439
	 * @param tabOffset Ignored
440
	 * @return The next tab stop after <i>x</i>
441
	 */
442
	public float nextTabStop(float x, int tabOffset)
443
	{
444
		int offset = textArea.getHorizontalOffset();
445
		int ntabs = ((int)x - offset) / tabSize;
446
		return (ntabs + 1) * tabSize + offset;
447
	}
448
449
	/**
450
	 * Returns the painter's preferred size.
451
	 */
452
	public Dimension getPreferredSize()
453
	{
454
		Dimension dim = new Dimension();
455
		dim.width = fm.charWidth('w') * cols;
456
		dim.height = fm.getHeight() * rows;
457
		return dim;
458
	}
459
460
461
	/**
462
	 * Returns the painter's minimum size.
463
	 */
464
	public Dimension getMinimumSize()
465
	{
466
		return getPreferredSize();
467
	}
468
469
	// package-private members
470
	int currentLineIndex;
471
	Token currentLineTokens;
472
	Segment currentLine;
473
474
	// protected members
475
	protected JEditTextArea textArea;
476
	
477
	protected SyntaxStyle[] styles;
478
	protected Color caretColor;
479
	protected Color selectionColor;
480
	protected Color lineHighlightColor;
481
	protected Color bracketHighlightColor;
482
	protected Color eolMarkerColor;
483
484
	protected boolean blockCaret;
485
	protected boolean lineHighlight;
486
	protected boolean bracketHighlight;
487
	protected boolean paintInvalid;
488
	protected boolean eolMarkers;
489
	protected int cols;
490
	protected int rows;
491
	
492
	protected int tabSize;
493
	protected FontMetrics fm;
494
495
	protected Highlight highlights;
496
497
	protected void paintLine(Graphics gfx, TokenMarker tokenMarker,
498
		int line, int x)
499
	{
500
		Font defaultFont = getFont();
501
		Color defaultColor = getForeground();
502
503
		currentLineIndex = line;
504
		int y = textArea.lineToY(line);
505
506
		if(line < 0 || line >= textArea.getLineCount())
507
		{
508
			if(paintInvalid)
509
			{
510
				paintHighlight(gfx,line,y);
511
				styles[Token.INVALID].setGraphicsFlags(gfx,defaultFont);
512
				gfx.drawString("~",0,y + fm.getHeight());
513
			}
514
		}
515
		else if(tokenMarker == null)
516
		{
517
			paintPlainLine(gfx,line,defaultFont,defaultColor,x,y);
518
		}
519
		else
520
		{
521
			paintSyntaxLine(gfx,tokenMarker,line,defaultFont,
522
				defaultColor,x,y);
523
		}
524
	}
525
526
	protected void paintPlainLine(Graphics gfx, int line, Font defaultFont,
527
		Color defaultColor, int x, int y)
528
	{
529
		paintHighlight(gfx,line,y);
530
		textArea.getLineText(line,currentLine);
531
532
		gfx.setFont(defaultFont);
533
		gfx.setColor(defaultColor);
534
535
		y += fm.getHeight();
536
		x = Utilities.drawTabbedText(currentLine,x,y,gfx,this,0);
537
538
		if(eolMarkers)
539
		{
540
			gfx.setColor(eolMarkerColor);
541
			gfx.drawString(".",x,y);
542
		}
543
	}
544
545
	protected void paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker,
546
		int line, Font defaultFont, Color defaultColor, int x, int y)
547
	{
548
		textArea.getLineText(currentLineIndex,currentLine);
549
		currentLineTokens = tokenMarker.markTokens(currentLine,
550
			currentLineIndex);
551
552
		paintHighlight(gfx,line,y);
553
554
		gfx.setFont(defaultFont);
555
		gfx.setColor(defaultColor);
556
		y += fm.getHeight();
557
		x = SyntaxUtilities.paintSyntaxLine(currentLine,
558
			currentLineTokens,styles,this,gfx,x,y);
559
560
		if(eolMarkers)
561
		{
562
			gfx.setColor(eolMarkerColor);
563
			gfx.drawString(".",x,y);
564
		}
565
	}
566
567
	protected void paintHighlight(Graphics gfx, int line, int y)
568
	{
569
		if(line >= textArea.getSelectionStartLine()
570
			&& line <= textArea.getSelectionEndLine())
571
			paintLineHighlight(gfx,line,y);
572
573
		if(highlights != null)
574
			highlights.paintHighlight(gfx,line,y);
575
576
		if(bracketHighlight && line == textArea.getBracketLine())
577
			paintBracketHighlight(gfx,line,y);
578
579
		if(line == textArea.getCaretLine())
580
			paintCaret(gfx,line,y);
581
	}
582
583
	protected void paintLineHighlight(Graphics gfx, int line, int y)
584
	{
585
		int height = fm.getHeight();
586
		y += fm.getLeading() + fm.getMaxDescent();
587
588
		int selectionStart = textArea.getSelectionStart();
589
		int selectionEnd = textArea.getSelectionEnd();
590
591
		if(selectionStart == selectionEnd)
592
		{
593
			if(lineHighlight)
594
			{
595
				gfx.setColor(lineHighlightColor);
596
				gfx.fillRect(0,y,getWidth(),height);
597
			}
598
		}
599
		else
600
		{
601
			gfx.setColor(selectionColor);
602
603
			int selectionStartLine = textArea.getSelectionStartLine();
604
			int selectionEndLine = textArea.getSelectionEndLine();
605
			int lineStart = textArea.getLineStartOffset(line);
606
607
			int x1, x2;
608
			if(textArea.isSelectionRectangular())
609
			{
610
				int lineLen = textArea.getLineLength(line);
611
				x1 = textArea._offsetToX(line,Math.min(lineLen,
612
					selectionStart - textArea.getLineStartOffset(
613
					selectionStartLine)));
614
				x2 = textArea._offsetToX(line,Math.min(lineLen,
615
					selectionEnd - textArea.getLineStartOffset(
616
					selectionEndLine)));
617
				if(x1 == x2)
618
					x2++;
619
			}
620
			else if(selectionStartLine == selectionEndLine)
621
			{
622
				x1 = textArea._offsetToX(line,
623
					selectionStart - lineStart);
624
				x2 = textArea._offsetToX(line,
625
					selectionEnd - lineStart);
626
			}
627
			else if(line == selectionStartLine)
628
			{
629
				x1 = textArea._offsetToX(line,
630
					selectionStart - lineStart);
631
				x2 = getWidth();
632
			}
633
			else if(line == selectionEndLine)
634
			{
635
				x1 = 0;
636
				x2 = textArea._offsetToX(line,
637
					selectionEnd - lineStart);
638
			}
639
			else
640
			{
641
				x1 = 0;
642
				x2 = getWidth();
643
			}
644
645
			// "inlined" min/max()
646
			gfx.fillRect(x1 > x2 ? x2 : x1,y,x1 > x2 ?
647
				(x1 - x2) : (x2 - x1),height);
648
		}
649
650
	}
651
652
	protected void paintBracketHighlight(Graphics gfx, int line, int y)
653
	{
654
		int position = textArea.getBracketPosition();
655
		if(position == -1)
656
			return;
657
		y += fm.getLeading() + fm.getMaxDescent();
658
		int x = textArea._offsetToX(line,position);
659
		gfx.setColor(bracketHighlightColor);
660
		// Hack!!! Since there is no fast way to get the character
661
		// from the bracket matching routine, we use ( since all
662
		// brackets probably have the same width anyway
663
		gfx.drawRect(x,y,fm.charWidth('(') - 1,
664
			fm.getHeight() - 1);
665
	}
666
667
	protected void paintCaret(Graphics gfx, int line, int y)
668
	{
669
		if(textArea.isCaretVisible())
670
		{
671
			int offset = textArea.getCaretPosition() 
672
				- textArea.getLineStartOffset(line);
673
			int caretX = textArea._offsetToX(line,offset);
674
			int caretWidth = ((blockCaret ||
675
				textArea.isOverwriteEnabled()) ?
676
				fm.charWidth('w') : 1);
677
			y += fm.getLeading() + fm.getMaxDescent();
678
			int height = fm.getHeight();
679
			
680
			gfx.setColor(caretColor);
681
682
			if(textArea.isOverwriteEnabled())
683
			{
684
				gfx.fillRect(caretX,y + height - 1,
685
					caretWidth,1);
686
			}
687
			else
688
			{
689
				gfx.drawRect(caretX,y,caretWidth - 1,height - 1);
690
			}
691
		}
692
	}
693
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/DefaultInputHandler.java (+347 lines)
Line 0 Link Here
1
/*
2
 * DefaultInputHandler.java - Default implementation of an input handler
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.KeyStroke;
12
import java.awt.event.*;
13
import java.awt.Toolkit;
14
import java.util.Hashtable;
15
import java.util.StringTokenizer;
16
17
/**
18
 * The default input handler. It maps sequences of keystrokes into actions
19
 * and inserts key typed events into the text area.
20
 * @author Slava Pestov
21
 * @version $Id: DefaultInputHandler.java,v 1.18 1999/12/13 03:40:30 sp Exp $
22
 */
23
public class DefaultInputHandler extends InputHandler
24
{
25
	/**
26
	 * Creates a new input handler with no key bindings defined.
27
	 */
28
	public DefaultInputHandler()
29
	{
30
		bindings = currentBindings = new Hashtable();
31
	}
32
33
	/**
34
	 * Sets up the default key bindings.
35
	 */
36
	public void addDefaultKeyBindings()
37
	{
38
		addKeyBinding("BACK_SPACE",BACKSPACE);
39
		addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD);
40
		addKeyBinding("DELETE",DELETE);
41
		addKeyBinding("C+DELETE",DELETE_WORD);
42
43
		addKeyBinding("ENTER",INSERT_BREAK);
44
		addKeyBinding("TAB",INSERT_TAB);
45
46
		addKeyBinding("INSERT",OVERWRITE);
47
		addKeyBinding("C+\\",TOGGLE_RECT);
48
49
		addKeyBinding("HOME",HOME);
50
		addKeyBinding("END",END);
51
		addKeyBinding("S+HOME",SELECT_HOME);
52
		addKeyBinding("S+END",SELECT_END);
53
		addKeyBinding("C+HOME",DOCUMENT_HOME);
54
		addKeyBinding("C+END",DOCUMENT_END);
55
		addKeyBinding("CS+HOME",SELECT_DOC_HOME);
56
		addKeyBinding("CS+END",SELECT_DOC_END);
57
58
		addKeyBinding("PAGE_UP",PREV_PAGE);
59
		addKeyBinding("PAGE_DOWN",NEXT_PAGE);
60
		addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE);
61
		addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE);
62
63
		addKeyBinding("LEFT",PREV_CHAR);
64
		addKeyBinding("S+LEFT",SELECT_PREV_CHAR);
65
		addKeyBinding("C+LEFT",PREV_WORD);
66
		addKeyBinding("CS+LEFT",SELECT_PREV_WORD);
67
		addKeyBinding("RIGHT",NEXT_CHAR);
68
		addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR);
69
		addKeyBinding("C+RIGHT",NEXT_WORD);
70
		addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD);
71
		addKeyBinding("UP",PREV_LINE);
72
		addKeyBinding("S+UP",SELECT_PREV_LINE);
73
		addKeyBinding("DOWN",NEXT_LINE);
74
		addKeyBinding("S+DOWN",SELECT_NEXT_LINE);
75
76
		addKeyBinding("C+ENTER",REPEAT);
77
	}
78
79
	/**
80
	 * Adds a key binding to this input handler. The key binding is
81
	 * a list of white space separated key strokes of the form
82
	 * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt,
83
	 * or S for Shift, and key is either a character (a-z) or a field
84
	 * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE)
85
	 * @param keyBinding The key binding
86
	 * @param action The action
87
	 */
88
	public void addKeyBinding(String keyBinding, ActionListener action)
89
	{
90
	        Hashtable current = bindings;
91
92
		StringTokenizer st = new StringTokenizer(keyBinding);
93
		while(st.hasMoreTokens())
94
		{
95
			KeyStroke keyStroke = parseKeyStroke(st.nextToken());
96
			if(keyStroke == null)
97
				return;
98
99
			if(st.hasMoreTokens())
100
			{
101
				Object o = current.get(keyStroke);
102
				if(o instanceof Hashtable)
103
					current = (Hashtable)o;
104
				else
105
				{
106
					o = new Hashtable();
107
					current.put(keyStroke,o);
108
					current = (Hashtable)o;
109
				}
110
			}
111
			else
112
				current.put(keyStroke,action);
113
		}
114
	}
115
116
	/**
117
	 * Removes a key binding from this input handler. This is not yet
118
	 * implemented.
119
	 * @param keyBinding The key binding
120
	 */
121
	public void removeKeyBinding(String keyBinding)
122
	{
123
		throw new InternalError("Not yet implemented");
124
	}
125
126
	/**
127
	 * Removes all key bindings from this input handler.
128
	 */
129
	public void removeAllKeyBindings()
130
	{
131
		bindings.clear();
132
	}
133
134
	/**
135
	 * Returns a copy of this input handler that shares the same
136
	 * key bindings. Setting key bindings in the copy will also
137
	 * set them in the original.
138
	 */
139
	public InputHandler copy()
140
	{
141
		return new DefaultInputHandler(this);
142
	}
143
144
	/**
145
	 * Handle a key pressed event. This will look up the binding for
146
	 * the key stroke and execute it.
147
	 */
148
	public void keyPressed(KeyEvent evt)
149
	{
150
		int keyCode = evt.getKeyCode();
151
		int modifiers = evt.getModifiers();
152
153
		if(keyCode == KeyEvent.VK_CONTROL ||
154
			keyCode == KeyEvent.VK_SHIFT ||
155
			keyCode == KeyEvent.VK_ALT ||
156
			keyCode == KeyEvent.VK_META)
157
			return;
158
159
		if((modifiers & ~KeyEvent.SHIFT_MASK) != 0
160
			|| evt.isActionKey()
161
			|| keyCode == KeyEvent.VK_BACK_SPACE
162
			|| keyCode == KeyEvent.VK_DELETE
163
			|| keyCode == KeyEvent.VK_ENTER
164
			|| keyCode == KeyEvent.VK_TAB
165
			|| keyCode == KeyEvent.VK_ESCAPE)
166
		{
167
			if(grabAction != null)
168
			{
169
				handleGrabAction(evt);
170
				return;
171
			}
172
173
			KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode,
174
				modifiers);
175
			Object o = currentBindings.get(keyStroke);
176
			if(o == null)
177
			{
178
				// Don't beep if the user presses some
179
				// key we don't know about unless a
180
				// prefix is active. Otherwise it will
181
				// beep when caps lock is pressed, etc.
182
				if(currentBindings != bindings)
183
				{
184
					Toolkit.getDefaultToolkit().beep();
185
					// F10 should be passed on, but C+e F10
186
					// shouldn't
187
					repeatCount = 0;
188
					repeat = false;
189
					evt.consume();
190
				}
191
				currentBindings = bindings;
192
				return;
193
			}
194
			else if(o instanceof ActionListener)
195
			{
196
				currentBindings = bindings;
197
198
				executeAction(((ActionListener)o),
199
					evt.getSource(),null);
200
201
				evt.consume();
202
				return;
203
			}
204
			else if(o instanceof Hashtable)
205
			{
206
				currentBindings = (Hashtable)o;
207
				evt.consume();
208
				return;
209
			}
210
		}
211
	}
212
213
	/**
214
	 * Handle a key typed event. This inserts the key into the text area.
215
	 */
216
	public void keyTyped(KeyEvent evt)
217
	{
218
		int modifiers = evt.getModifiers();
219
		char c = evt.getKeyChar();
220
		if(c != KeyEvent.CHAR_UNDEFINED &&
221
			(modifiers & KeyEvent.ALT_MASK) == 0)
222
		{
223
			if(c >= 0x20 && c != 0x7f)
224
			{
225
				KeyStroke keyStroke = KeyStroke.getKeyStroke(
226
					Character.toUpperCase(c));
227
				Object o = currentBindings.get(keyStroke);
228
229
				if(o instanceof Hashtable)
230
				{
231
					currentBindings = (Hashtable)o;
232
					return;
233
				}
234
				else if(o instanceof ActionListener)
235
				{
236
					currentBindings = bindings;
237
					executeAction((ActionListener)o,
238
						evt.getSource(),
239
						String.valueOf(c));
240
					return;
241
				}
242
243
				currentBindings = bindings;
244
245
				if(grabAction != null)
246
				{
247
					handleGrabAction(evt);
248
					return;
249
				}
250
251
				// 0-9 adds another 'digit' to the repeat number
252
				if(repeat && Character.isDigit(c))
253
				{
254
					repeatCount *= 10;
255
					repeatCount += (c - '0');
256
					return;
257
				}
258
259
				executeAction(INSERT_CHAR,evt.getSource(),
260
					String.valueOf(evt.getKeyChar()));
261
262
				repeatCount = 0;
263
				repeat = false;
264
			}
265
		}
266
	}
267
268
	/**
269
	 * Converts a string to a keystroke. The string should be of the
270
	 * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i>
271
	 * is any combination of A for Alt, C for Control, S for Shift
272
	 * or M for Meta, and <i>shortcut</i> is either a single character,
273
	 * or a keycode name from the <code>KeyEvent</code> class, without
274
	 * the <code>VK_</code> prefix.
275
	 * @param keyStroke A string description of the key stroke
276
	 */
277
	public static KeyStroke parseKeyStroke(String keyStroke)
278
	{
279
		if(keyStroke == null)
280
			return null;
281
		int modifiers = 0;
282
		int index = keyStroke.indexOf('+');
283
		if(index != -1)
284
		{
285
			for(int i = 0; i < index; i++)
286
			{
287
				switch(Character.toUpperCase(keyStroke
288
					.charAt(i)))
289
				{
290
				case 'A':
291
					modifiers |= InputEvent.ALT_MASK;
292
					break;
293
				case 'C':
294
					modifiers |= InputEvent.CTRL_MASK;
295
					break;
296
				case 'M':
297
					modifiers |= InputEvent.META_MASK;
298
					break;
299
				case 'S':
300
					modifiers |= InputEvent.SHIFT_MASK;
301
					break;
302
				}
303
			}
304
		}
305
		String key = keyStroke.substring(index + 1);
306
		if(key.length() == 1)
307
		{
308
			char ch = Character.toUpperCase(key.charAt(0));
309
			if(modifiers == 0)
310
				return KeyStroke.getKeyStroke(ch);
311
			else
312
				return KeyStroke.getKeyStroke(ch,modifiers);
313
		}
314
		else if(key.length() == 0)
315
		{
316
			System.err.println("Invalid key stroke: " + keyStroke);
317
			return null;
318
		}
319
		else
320
		{
321
			int ch;
322
323
			try
324
			{
325
				ch = KeyEvent.class.getField("VK_".concat(key))
326
					.getInt(null);
327
			}
328
			catch(Exception e)
329
			{
330
				System.err.println("Invalid key stroke: "
331
					+ keyStroke);
332
				return null;
333
			}
334
335
			return KeyStroke.getKeyStroke(ch,modifiers);
336
		}
337
	}
338
339
	// private members
340
	private Hashtable bindings;
341
	private Hashtable currentBindings;
342
343
	private DefaultInputHandler(DefaultInputHandler copy)
344
	{
345
		bindings = currentBindings = copy.bindings;
346
	}
347
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/XMLTokenMarker.java (+190 lines)
Line 0 Link Here
1
/*
2
 * XMLTokenMarker.java - XML token marker
3
 * Copyright (C) 1998, 1999 Slava Pestov
4
 * Copyright (C) 2001 Tom Bradford
5
 *
6
 * You may use and modify this package for any purpose. Redistribution is
7
 * permitted, in both source and binary form, provided that this notice
8
 * remains intact in all source distributions of this package.
9
 */
10
package org.apache.batik.apps.svgbrowser.srcview;
11
12
import javax.swing.text.Segment;
13
14
/**
15
 * XML Token Marker Rewrite
16
 *
17
 * @author Tom Bradford
18
 * @version $Id: XMLTokenMarker.java,v 1.5 2001/07/29 20:45:43 tom Exp $
19
 */
20
public class XMLTokenMarker extends TokenMarker {
21
   public XMLTokenMarker() {
22
   }
23
   
24
   public byte markTokensImpl(byte token, Segment line, int lineIndex) {
25
      char[] array = line.array;
26
      int offset = line.offset;
27
      int lastOffset = offset;
28
      int length = line.count + offset;
29
      
30
      // Ugly hack to handle multi-line tags
31
      boolean sk1 = token == Token.KEYWORD1;
32
      
33
      for ( int i = offset; i < length; i++ ) {
34
         int ip1 = i+1;
35
         char c = array[i];
36
         switch ( token ) {
37
            case Token.NULL: // text
38
               switch ( c ) {
39
                  case '<':
40
                     addToken(i-lastOffset, token);
41
                     lastOffset = i;
42
                     if ( SyntaxUtilities.regionMatches(false, line, ip1, "!--") ) {
43
                        i += 3;
44
                        token = Token.COMMENT1;
45
                     }
46
                     else if ( array[ip1] == '!' ) {
47
                        i += 1;
48
                        token = Token.COMMENT2;
49
                     }
50
                     else if ( array[ip1] == '?' ) {
51
                        i += 1;
52
                        token = Token.KEYWORD3;
53
                     }
54
                     else
55
                        token = Token.KEYWORD1;
56
                     break;
57
                     
58
                  case '&':
59
                     addToken(i - lastOffset, token);
60
                     lastOffset = i;
61
                     token = Token.LABEL;
62
                     break;
63
               }
64
               break;
65
               
66
            case Token.KEYWORD1: // tag
67
               switch ( c ) {
68
                  case '>':
69
                     addToken(ip1-lastOffset, token);
70
                     lastOffset = ip1;
71
                     token = Token.NULL;
72
                     sk1 = false;
73
                     break;
74
                     
75
                  case ' ':
76
                  case '\t':
77
                     addToken(i-lastOffset, token);
78
                     lastOffset = i;
79
                     token = Token.KEYWORD2;
80
                     sk1 = false;
81
                     break;
82
                     
83
                  default:
84
                     if ( sk1 ) {
85
                        token = Token.KEYWORD2;
86
                        sk1 = false;
87
                     }
88
                     break;
89
               }
90
               break;
91
92
            case Token.KEYWORD2: // attribute
93
               switch ( c ) {
94
                   case '>':
95
                     addToken(ip1-lastOffset, token);
96
                     lastOffset = ip1;
97
                     token = Token.NULL;
98
                     break;
99
                    
100
                  case '/':
101
                     addToken(i-lastOffset, token);
102
                     lastOffset = i;
103
                     token = Token.KEYWORD1;
104
                     break;
105
                     
106
                  case '=':
107
                     addToken(i-lastOffset, token);
108
                     lastOffset = i;
109
                     token = Token.OPERATOR;
110
               }
111
               break;
112
               
113
            case Token.OPERATOR: // equal for attribute
114
               switch ( c ) {
115
                  case '\"':
116
                  case '\'':
117
                     addToken(i-lastOffset, token);
118
                     lastOffset = i;
119
                     if ( c == '\"' )
120
                        token = Token.LITERAL1;
121
                     else
122
                        token = Token.LITERAL2;
123
                     break;
124
               }
125
               break;
126
               
127
            case Token.LITERAL1:
128
            case Token.LITERAL2: // strings
129
               if ( ( token == Token.LITERAL1 && c == '\"' )
130
                 || ( token == Token.LITERAL2 && c == '\'' ) ) {
131
                  addToken(ip1-lastOffset, token);
132
                  lastOffset = ip1;
133
                  token = Token.KEYWORD1;
134
               }
135
               break;
136
            
137
            case Token.LABEL: // entity
138
               if ( c == ';' ) {
139
                  addToken(ip1-lastOffset, token);
140
                  lastOffset = ip1;
141
                  token = Token.NULL;
142
                  break;
143
               }
144
               break;
145
               
146
            case Token.COMMENT1: // Inside a comment
147
               if ( SyntaxUtilities.regionMatches(false, line, i, "-->") ) {
148
                  addToken((i+3)-lastOffset, token);
149
                  lastOffset = i+3;
150
                  token = Token.NULL;
151
               }
152
               break;
153
154
            case Token.COMMENT2: // Inside a declaration
155
               if ( SyntaxUtilities.regionMatches(false, line, i, ">") ) {
156
                  addToken(ip1-lastOffset, token);
157
                  lastOffset = ip1;
158
                  token = Token.NULL;
159
               }
160
               break;
161
162
            case Token.KEYWORD3: // Inside a processor instruction
163
               if ( SyntaxUtilities.regionMatches(false, line, i, "?>") ) {
164
                  addToken((i+2)-lastOffset, token);
165
                  lastOffset = i+2;
166
                  token = Token.NULL;
167
               }
168
               break;
169
               
170
            default:
171
               throw new InternalError("Invalid state: " + token);
172
         }
173
      }
174
      
175
      switch ( token ) {
176
         case Token.LABEL:
177
            addToken(length-lastOffset, Token.INVALID);
178
            token = Token.NULL;
179
            break;
180
            
181
         default:
182
            addToken(length-lastOffset, token);
183
            break;
184
      }
185
      
186
      return token;
187
   }
188
}
189
190
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaDefaults.java (+83 lines)
Line 0 Link Here
1
/*
2
 * TextAreaDefaults.java - Encapsulates default values for various settings
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.JPopupMenu;
12
import java.awt.Color;
13
14
/**
15
 * Encapsulates default settings for a text area. This can be passed
16
 * to the constructor once the necessary fields have been filled out.
17
 * The advantage of doing this over calling lots of set() methods after
18
 * creating the text area is that this method is faster.
19
 */
20
public class TextAreaDefaults
21
{
22
	private static TextAreaDefaults DEFAULTS;
23
24
	public InputHandler inputHandler;
25
	public SyntaxDocument document;
26
	public boolean editable;
27
28
	public boolean caretVisible;
29
	public boolean caretBlinks;
30
	public boolean blockCaret;
31
	public int electricScroll;
32
33
	public int cols;
34
	public int rows;
35
	public SyntaxStyle[] styles;
36
	public Color caretColor;
37
	public Color selectionColor;
38
	public Color lineHighlightColor;
39
	public boolean lineHighlight;
40
	public Color bracketHighlightColor;
41
	public boolean bracketHighlight;
42
	public Color eolMarkerColor;
43
	public boolean eolMarkers;
44
	public boolean paintInvalid;
45
46
	public JPopupMenu popup;
47
48
	/**
49
	 * Returns a new TextAreaDefaults object with the default values filled
50
	 * in.
51
	 */
52
	public static TextAreaDefaults getDefaults()
53
	{
54
		if(DEFAULTS == null)
55
		{
56
			DEFAULTS = new TextAreaDefaults();
57
58
			DEFAULTS.inputHandler = new DefaultInputHandler();
59
			DEFAULTS.inputHandler.addDefaultKeyBindings();
60
			DEFAULTS.document = new SyntaxDocument();
61
			DEFAULTS.editable = true;
62
63
			DEFAULTS.caretVisible = true;
64
			DEFAULTS.caretBlinks = true;
65
			DEFAULTS.electricScroll = 3;
66
67
			DEFAULTS.cols = 80;
68
			DEFAULTS.rows = 25;
69
			DEFAULTS.styles = SyntaxUtilities.getDefaultSyntaxStyles();
70
			DEFAULTS.caretColor = Color.red;
71
			DEFAULTS.selectionColor = new Color(0xccccff);
72
			DEFAULTS.lineHighlightColor = new Color(0xe0e0e0);
73
			DEFAULTS.lineHighlight = true;
74
			DEFAULTS.bracketHighlightColor = Color.black;
75
			DEFAULTS.bracketHighlight = true;
76
			DEFAULTS.eolMarkerColor = new Color(0x009999);
77
			DEFAULTS.eolMarkers = true;
78
			DEFAULTS.paintInvalid = true;
79
		}
80
81
		return DEFAULTS;
82
	}
83
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SourceViewFrame.java (+810 lines)
Line 0 Link Here
1
package org.apache.batik.apps.svgbrowser.srcview;
2
3
import java.awt.BorderLayout;
4
import java.awt.Color;
5
import java.awt.Dimension;
6
import java.awt.Font;
7
import java.awt.event.ActionEvent;
8
import java.awt.event.ActionListener;
9
import java.io.BufferedOutputStream;
10
import java.io.File;
11
import java.io.FileOutputStream;
12
import java.io.OutputStream;
13
import java.io.OutputStreamWriter;
14
import java.util.HashMap;
15
import java.util.Locale;
16
import java.util.Map;
17
import java.util.MissingResourceException;
18
import java.util.ResourceBundle;
19
20
import javax.swing.AbstractAction;
21
import javax.swing.Action;
22
import javax.swing.BorderFactory;
23
import javax.swing.Box;
24
import javax.swing.BoxLayout;
25
import javax.swing.ImageIcon;
26
import javax.swing.JButton;
27
import javax.swing.JCheckBox;
28
import javax.swing.JDialog;
29
import javax.swing.JFileChooser;
30
import javax.swing.JFrame;
31
import javax.swing.JLabel;
32
import javax.swing.JMenuBar;
33
import javax.swing.JPanel;
34
import javax.swing.JTextField;
35
import javax.swing.JToggleButton;
36
import javax.swing.JToolBar;
37
import javax.swing.SwingUtilities;
38
import javax.swing.UIManager;
39
import javax.swing.event.CaretEvent;
40
import javax.swing.event.CaretListener;
41
import javax.swing.event.DocumentEvent;
42
import javax.swing.event.DocumentListener;
43
import javax.swing.filechooser.FileFilter;
44
45
import org.apache.batik.apps.svgbrowser.AboutDialog;
46
import org.apache.batik.apps.svgbrowser.Application;
47
import org.apache.batik.swing.svg.SVGUserAgent;
48
import org.apache.batik.util.gui.resource.ActionMap;
49
import org.apache.batik.util.gui.resource.ButtonFactory;
50
import org.apache.batik.util.gui.resource.MenuFactory;
51
import org.apache.batik.util.gui.resource.MissingListenerException;
52
import org.apache.batik.util.gui.resource.ResourceManager;
53
54
public class SourceViewFrame extends JFrame implements ActionMap {
55
56
	public static final String RESOURCES = "org.apache.batik.apps.svgbrowser.srcview.resources.SourceViewFrame";
57
58
	// The action names
59
	public static final String SAVE_AS_ACTION = "SaveAsAction";
60
61
	public static final String CLOSE_ACTION = "CloseAction";
62
63
	public static final String UNDO_ACTION = "UndoAction";
64
65
	public static final String REDO_ACTION = "RedoAction";
66
67
	public static final String CUT_ACTION = "CutAction";
68
69
	public static final String COPY_ACTION = "CopyAction";
70
71
	public static final String PASTE_ACTION = "PasteAction";
72
73
	public static final String DELETE_ACTION = "DeleteAction";
74
75
	public static final String SELECT_ALL_ACTION = "SelectAllAction";
76
77
	public static final String FIND_ACTION = "FindAction";
78
79
	public static final String FIND_CLOSE_ACTION = "FindCloseAction";
80
81
	public static final String FIND_AGAIN_ACTION = "FindAgainAction";
82
83
	public static final String FIND_PREVIOUS_ACTION = "FindPreviousAction";
84
85
	public static final String HIGHLIGHT_ALL_ACTION = "HighlightAllAction";
86
87
	public static final String GOTO_LINE_ACTION = "GotoLineAction";
88
89
	public static final String TEXT_SIZE_INCREASE_ACTION = "TextSizeIncreaseAction";
90
91
	public static final String TEXT_SIZE_DECREASE_ACTION = "TextSizeDecreaseAction";
92
93
	public static final String TEXT_SIZE_NORMAL_ACTION = "TextSizeNormalAction";
94
95
	public static final String SYNTAX_HIGHLIGHTING_ACTION = "SyntaxHighlightingAction";
96
97
	public static final String ABOUT_ACTION = "AboutAction";
98
99
	protected static final float[] FONT_SIZES = { 6, 8, 10, 11, 12, 14, 18, 28,
100
			36, 72 };
101
102
	/**
103
	 * The resource bundle
104
	 */
105
	protected static ResourceBundle bundle;
106
107
	/**
108
	 * The resource manager
109
	 */
110
	protected static ResourceManager resources;
111
	static {
112
		bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
113
		resources = new ResourceManager(bundle);
114
	}
115
116
	/**
117
	 * The SVG user agent.
118
	 */
119
	protected SVGUserAgent userAgent;
120
121
	/**
122
	 * The current application.
123
	 */
124
	protected Application application;
125
126
	/**
127
	 * The text to be displayed in the source viewer
128
	 */
129
	protected String sourceText;
130
131
	/**
132
	 * The syntax highlighted text area
133
	 */
134
	protected JEditTextArea textArea;
135
136
	/**
137
	 * TokenMarker used by syntax highlighted text area to tokenize text
138
	 */
139
	protected TokenMarker tokenMarker;
140
141
	/**
142
	 * The current save path.
143
	 */
144
	protected File currentSavePath = new File("");
145
146
	/**
147
	 * The find bar.
148
	 */
149
	protected JToolBar findbar;
150
151
	/**
152
	 * Label to display status messages in the find bar
153
	 */
154
	protected FindBarMessage findbarMessage;
155
	
156
	/**
157
	 * The status bar.
158
	 */
159
	protected StatusBar statusBar;
160
161
	/**
162
	 * The current font size index (into the array FONT_SIZES)
163
	 */
164
	protected int fontSizeIndex;
165
166
	/**
167
	 * The default font size index (into the array FONT_SIZES)
168
	 */
169
	protected final int defaultFontSizeIndex = 4;
170
171
	/**
172
	 * Creates a new source viewer frame.
173
	 */
174
	public SourceViewFrame(Application app, String text, SVGUserAgent agt)
175
			throws MissingResourceException {
176
		application = app;
177
		sourceText = text;
178
		userAgent = agt;
179
180
		listeners.put(SAVE_AS_ACTION, new SaveAsAction());
181
		listeners.put(CLOSE_ACTION, new CloseAction());
182
		listeners.put(UNDO_ACTION, new UndoAction());
183
		listeners.put(REDO_ACTION, new RedoAction());
184
		listeners.put(CUT_ACTION, new CutAction());
185
		listeners.put(COPY_ACTION, new CopyAction());
186
		listeners.put(PASTE_ACTION, new PasteAction());
187
		listeners.put(DELETE_ACTION, new DeleteAction());
188
		listeners.put(SELECT_ALL_ACTION, new SelectAllAction());
189
		listeners.put(FIND_ACTION, new FindAction());
190
		listeners.put(FIND_CLOSE_ACTION, new FindCloseAction());
191
		listeners.put(FIND_AGAIN_ACTION, new FindAgainAction());
192
		listeners.put(FIND_PREVIOUS_ACTION, new FindPreviousAction());
193
		listeners.put(HIGHLIGHT_ALL_ACTION, new HighlightAllAction());
194
		listeners.put(GOTO_LINE_ACTION, new GotoLineAction());
195
		listeners.put(TEXT_SIZE_INCREASE_ACTION, new TextSizeIncreaseAction());
196
		listeners.put(TEXT_SIZE_DECREASE_ACTION, new TextSizeDecreaseAction());
197
		listeners.put(TEXT_SIZE_NORMAL_ACTION, new TextSizeNormalAction());
198
		listeners.put(SYNTAX_HIGHLIGHTING_ACTION,
199
				new SyntaxHighlightingAction());
200
		listeners.put(ABOUT_ACTION, new AboutAction());
201
202
		// Create the menu
203
		MenuFactory mf = new MenuFactory(bundle, this);
204
205
		// TODO:Remove this and use specialized version (commented out below)
206
		JMenuBar mb = mf.createJMenuBar("MenuBar");
207
		// JMenuBar mb = mf.createJMenuBar("MenuBar", application
208
		// .getUISpecialization());
209
		setJMenuBar(mb);
210
211
		// Create the central panel
212
		JPanel center = new JPanel(new BorderLayout());
213
		getContentPane().add(center, BorderLayout.CENTER);
214
215
		// Create syntax-highlighted text area
216
		textArea = new JEditTextArea();
217
		textArea.setText(sourceText);
218
		tokenMarker = new XMLTokenMarker();
219
		textArea.setTokenMarker(tokenMarker);
220
		fontSizeIndex = defaultFontSizeIndex;
221
		TextAreaPainter painter = textArea.getPainter();
222
		painter.setFont(new Font("Monospaced", Font.PLAIN,
223
				(int) (FONT_SIZES[fontSizeIndex])));
224
		textArea.addCaretListener(new CaretListener() {
225
			public void caretUpdate(CaretEvent e) {
226
				JEditTextArea a = (JEditTextArea) e.getSource();
227
				int row = a.getCaretLine() + 1;
228
				int col = a.getCaretPosition() - a.getLineStartOffset(row - 1)
229
						+ 1;
230
				statusBar.setPosition(row, col);
231
			}
232
		});
233
		center.add(textArea);
234
235
		// Create find bar (initially invisible)
236
		ButtonFactory bf = new ButtonFactory(bundle, this);
237
		findbar = new JToolBar();
238
		findbar.setVisible(false);
239
		findbar.setFloatable(false);
240
		findbar.add(bf.createJToolbarButton("FindBarClose"));
241
		findbar
242
				.add(new JLabel(resources.getString("FindBar.label.find")
243
						+ ": "));
244
		final JTextField findText = new JTextField(20);
245
		JPanel p = new JPanel();
246
		p.setOpaque(false);
247
		p.add(findText);
248
		p.setMinimumSize(p.getPreferredSize());
249
		p.setMaximumSize(p.getPreferredSize());
250
		findbar.add(p);
251
		final JButton next = bf.createJToolbarButton("FindBarNext");
252
		next.setEnabled(false);
253
		findbar.add(next);
254
		final JButton previous = bf.createJToolbarButton("FindBarPrevious");
255
		previous.setEnabled(false);
256
		findbar.add(previous);
257
		final JToggleButton highlightAll = bf
258
				.createJToolbarToggleButton("FindBarHighlightAll");
259
		highlightAll.setEnabled(false);
260
		findbar.add(highlightAll);
261
		JCheckBox matchCase = bf.createJCheckBox("FindBarMatchCase");
262
		matchCase.setOpaque(false);
263
		findbar.add(matchCase);
264
		findbarMessage = new FindBarMessage();
265
		findbar.add(findbarMessage);
266
		findText.getDocument().addDocumentListener(new DocumentListener() {
267
			public void changedUpdate(DocumentEvent e) {
268
				update();
269
			}
270
271
			public void insertUpdate(DocumentEvent e) {
272
				update();
273
			}
274
275
			public void removeUpdate(DocumentEvent e) {
276
				update();
277
			}
278
279
			private void update() {
280
				String str = findText.getText().trim();
281
				boolean enabled = !str.equals("");
282
				next.setEnabled(enabled);
283
				previous.setEnabled(enabled);
284
				highlightAll.setEnabled(enabled);
285
				if (enabled) {
286
					if (!find(str, DIRECTION_DOWN)) {
287
						findText.setBackground(new Color(255, 128, 128));
288
					}
289
				} else {
290
					findbarMessage.setMessage(FindBarMessage.NONE);
291
					findText.setBackground(UIManager
292
							.getColor("TextField.background"));
293
				}
294
			}
295
		});
296
		center.add(findbar, BorderLayout.SOUTH);
297
298
		// Create status bar
299
		statusBar = new StatusBar();
300
		getContentPane().add(statusBar, BorderLayout.SOUTH);
301
	}
302
303
	protected static ImageIcon notFoundIcon, continueFromTopIcon;
304
305
	protected static String notFoundStr, continueFromTopStr;
306
	
307
	static {
308
		notFoundStr = resources.getString("FindBarNotFound.text");
309
		notFoundIcon = new ImageIcon(SourceViewFrame.class
310
				.getResource(resources.getString("FindBarNotFound.icon")));
311
		continueFromTopStr = resources.getString("FindBarContinueFromTop.text");
312
		continueFromTopIcon = new ImageIcon(SourceViewFrame.class
313
				.getResource(resources.getString("FindBarContinueFromTop.icon")));
314
	}
315
316
	protected class FindBarMessage extends JLabel {
317
		public static final int NONE = 0, NOT_FOUND = 1, CONTINUE_FROM_TOP = 2;
318
319
		public void setMessage(int type) {
320
			switch (type) {
321
			case NOT_FOUND:
322
				setIcon(notFoundIcon);
323
				setText(notFoundStr);
324
				break;
325
			case CONTINUE_FROM_TOP:
326
				setIcon(continueFromTopIcon);
327
				setText(continueFromTopStr);
328
				break;
329
			case NONE:
330
			default:
331
				setIcon(null);
332
				setText("");
333
				break;
334
			}
335
		}
336
	}
337
338
	/**
339
	 * Save the document as a different file
340
	 */
341
	public class SaveAsAction extends AbstractAction {
342
		public void actionPerformed(ActionEvent e) {
343
			JFileChooser fileChooser;
344
			fileChooser = new JFileChooser(
345
					currentSavePath.isAbsolute() ? currentSavePath
346
							: currentSavePath.getAbsoluteFile());
347
			fileChooser.setDialogTitle(resources.getString("SaveAs.title"));
348
			fileChooser.setFileHidingEnabled(false);
349
			fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
350
			fileChooser.addChoosableFileFilter(new FileFilter() {
351
				public boolean accept(File f) {
352
					if (f == null) {
353
						return false;
354
					}
355
					if (f.isDirectory()) {
356
						return true;
357
					}
358
					String fileName = f.getName().toLowerCase();
359
					return fileName.endsWith(".svg");
360
				}
361
362
				public String getDescription() {
363
					return "SVG Document";
364
				}
365
			});
366
367
			int choice = fileChooser.showSaveDialog(SourceViewFrame.this);
368
			if (choice != JFileChooser.APPROVE_OPTION)
369
				return;
370
371
			final File f = fileChooser.getSelectedFile();
372
373
			statusBar.setMessage(resources.getString("Message.saveAs"));
374
			currentSavePath = f;
375
			OutputStreamWriter w = null;
376
			try {
377
				OutputStream tos = null;
378
				tos = new FileOutputStream(f);
379
				tos = new BufferedOutputStream(tos);
380
				w = new OutputStreamWriter(tos, "utf-8");
381
			} catch (Exception ex) {
382
				userAgent.displayError(ex);
383
				return;
384
			}
385
386
			final OutputStreamWriter writer = w;
387
388
			final Runnable doneRun = new Runnable() {
389
				public void run() {
390
					String doneStr = resources.getString("Message.done");
391
					statusBar.setMessage(doneStr);
392
				}
393
			};
394
395
			try {
396
				writer.write(textArea.getText());
397
				writer.close();
398
399
				SwingUtilities.invokeLater(doneRun);
400
			} catch (Exception ex) {
401
				userAgent.displayError(ex);
402
			}
403
		}
404
	}
405
406
	/**
407
	 * Closes the source viewer
408
	 */
409
	public class CloseAction extends AbstractAction {
410
		public void actionPerformed(ActionEvent e) {
411
			dispose();
412
		}
413
	}
414
415
	/**
416
	 * Undo last action
417
	 */
418
	public class UndoAction extends AbstractAction {
419
		public void actionPerformed(ActionEvent e) {
420
421
		}
422
	}
423
424
	/**
425
	 * Redo last undone action
426
	 */
427
	public class RedoAction extends AbstractAction {
428
		public void actionPerformed(ActionEvent e) {
429
430
		}
431
	}
432
433
	/**
434
	 * Cut selected text
435
	 */
436
	public class CutAction extends AbstractAction {
437
		public void actionPerformed(ActionEvent e) {
438
			textArea.cut();
439
		}
440
	}
441
442
	/**
443
	 * Copy selected text
444
	 */
445
	public class CopyAction extends AbstractAction {
446
		public void actionPerformed(ActionEvent e) {
447
			textArea.copy();
448
		}
449
	}
450
451
	/**
452
	 * Paste copied text
453
	 */
454
	public class PasteAction extends AbstractAction {
455
		public void actionPerformed(ActionEvent e) {
456
			textArea.paste();
457
		}
458
	}
459
460
	/**
461
	 * Delete selected text
462
	 */
463
	public class DeleteAction extends AbstractAction {
464
		public void actionPerformed(ActionEvent e) {
465
		}
466
	}
467
468
	/**
469
	 * Select all text
470
	 */
471
	public class SelectAllAction extends AbstractAction {
472
		public void actionPerformed(ActionEvent e) {
473
			textArea.selectAll();
474
		}
475
	}
476
477
	/**
478
	 * Displays the find bar if not already visible
479
	 */
480
	public class FindAction extends AbstractAction {
481
		public void actionPerformed(ActionEvent e) {
482
			if (!findbar.isVisible()) {
483
				findbar.setVisible(true);
484
			}
485
		}
486
	}
487
488
	/**
489
	 * Closes the find bar if visible
490
	 */
491
	public class FindCloseAction extends AbstractAction {
492
		public void actionPerformed(ActionEvent e) {
493
			if (findbar.isVisible()) {
494
				findbar.setVisible(false);
495
			}
496
		}
497
	}
498
499
	/**
500
	 * Find the string in the text specified using the Find action
501
	 */
502
	public class FindAgainAction extends AbstractAction {
503
		public void actionPerformed(ActionEvent e) {
504
			if (!findbar.isVisible()) {
505
				findbar.setVisible(true);
506
			} else {
507
				find(lastFindStr, DIRECTION_DOWN);
508
			}
509
		}
510
	}
511
512
	/**
513
	 * Find the string in the text specified using the Find action
514
	 */
515
	public class FindPreviousAction extends AbstractAction {
516
		public void actionPerformed(ActionEvent e) {
517
			if (!findbar.isVisible()) {
518
				findbar.setVisible(true);
519
			} else {
520
				find(lastFindStr, DIRECTION_UP);
521
			}
522
		}
523
	}
524
525
	/**
526
	 * Highlight all occurrences of the search phrase in the text
527
	 */
528
	public class HighlightAllAction extends AbstractAction {
529
		public void actionPerformed(ActionEvent e) {
530
		}
531
	}
532
533
	private String lastFindStr;
534
	
535
	private int lastOffset = -1;
536
537
	private static final int DIRECTION_UP = -1, DIRECTION_DOWN = 1;
538
539
	/**
540
	 * Help function to search for a phrase in the text
541
	 * 
542
	 * @param phrase
543
	 *            search string
544
	 * @param direction
545
	 *            whether to search downward or upward
546
	 * @return true is search string found, false otherwise
547
	 */
548
	private boolean find(String phrase, int direction) {
549
		boolean found = false;
550
		boolean wrap = false;
551
		
552
		String text = textArea.getText();
553
		int offset = text.indexOf(phrase, lastOffset + 1);
554
		if (offset < 0 && lastOffset >= 0) {
555
			lastOffset = -1;
556
			wrap = true;
557
			offset = text.indexOf(phrase, 0);
558
		}
559
		lastOffset = offset;
560
		found = lastOffset >= 0;
561
		
562
		if (found) {
563
			textArea.setSelectionStart(lastOffset);
564
			textArea.setSelectionEnd(lastOffset + phrase.length());
565
		}
566
		
567
		if (!found) {
568
			findbarMessage.setMessage(FindBarMessage.NOT_FOUND);
569
		} else if (wrap) {
570
			findbarMessage.setMessage(FindBarMessage.CONTINUE_FROM_TOP);
571
		} else {
572
			findbarMessage.setMessage(FindBarMessage.NONE);
573
		}
574
		return found;
575
	}
576
577
	/**
578
	 * Goto a particular line
579
	 */
580
	public class GotoLineAction extends AbstractAction {
581
		public void actionPerformed(ActionEvent e) {
582
			SwingUtilities.invokeLater(new Runnable() {
583
				public void run() {
584
					GotoLineDialog gld = new GotoLineDialog(
585
							SourceViewFrame.this, textArea.getLineCount());
586
					gld.setVisible(true);
587
					int n = gld.getLineNumber();
588
					if (n > 0) {
589
						gotoLine(n);
590
					}
591
				}
592
			});
593
		}
594
	}
595
596
	/**
597
	 * Helper function to adjust caret position and scroll viewport
598
	 * 
599
	 * @param n
600
	 *            line number of the new caret position
601
	 */
602
	private void gotoLine(int n) {
603
		textArea.setCaretPosition(textArea.getLineStartOffset(n - 1));
604
		textArea.scrollToCaret();
605
	}
606
607
	/**
608
	 * Increase text size
609
	 */
610
	public class TextSizeIncreaseAction extends AbstractAction {
611
		public void actionPerformed(ActionEvent e) {
612
			if (fontSizeIndex < FONT_SIZES.length - 1) {
613
				TextAreaPainter painter = textArea.getPainter();
614
				painter.setFont(painter.getFont().deriveFont(
615
						FONT_SIZES[++fontSizeIndex]));
616
			}
617
		}
618
	}
619
620
	/**
621
	 * Decrease text size
622
	 */
623
	public class TextSizeDecreaseAction extends AbstractAction {
624
		public void actionPerformed(ActionEvent e) {
625
			if (fontSizeIndex > 0) {
626
				TextAreaPainter painter = textArea.getPainter();
627
				painter.setFont(painter.getFont().deriveFont(
628
						FONT_SIZES[--fontSizeIndex]));
629
			}
630
		}
631
	}
632
633
	/**
634
	 * Set text size to default value
635
	 */
636
	public class TextSizeNormalAction extends AbstractAction {
637
		public void actionPerformed(ActionEvent e) {
638
			TextAreaPainter painter = textArea.getPainter();
639
			painter.setFont(painter.getFont().deriveFont(
640
					FONT_SIZES[fontSizeIndex = defaultFontSizeIndex]));
641
		}
642
	}
643
644
	/**
645
	 * Toggle syntax highlighting
646
	 */
647
	public class SyntaxHighlightingAction extends AbstractAction {
648
		public void actionPerformed(ActionEvent e) {
649
			textArea
650
					.setTokenMarker(textArea.getTokenMarker() == null ? tokenMarker
651
							: null);
652
			textArea.repaint();
653
		}
654
	}
655
656
	/**
657
	 * To show the about dialog
658
	 */
659
	public class AboutAction extends AbstractAction {
660
		public void actionPerformed(ActionEvent e) {
661
			AboutDialog dlg = new AboutDialog(SourceViewFrame.this);
662
			// Work around pack() bug on some platforms
663
			dlg.setSize(dlg.getPreferredSize());
664
			dlg.setLocationRelativeTo(SourceViewFrame.this);
665
			dlg.setVisible(true);
666
			dlg.toFront();
667
		}
668
	}
669
670
	/**
671
	 * The map that contains the action listeners
672
	 */
673
	protected Map listeners = new HashMap();
674
675
	/**
676
	 * Returns the action associated with the given string or null on error
677
	 * 
678
	 * @param key
679
	 *            the key mapped with the action to get
680
	 * @throws MissingListenerException
681
	 *             if the action is not found
682
	 */
683
	public Action getAction(String key) throws MissingListenerException {
684
		Action result = (Action) listeners.get(key);
685
		if (result == null) {
686
			throw new MissingListenerException("Can't find action.", RESOURCES,
687
					key);
688
		}
689
		return result;
690
	}
691
692
	private class GotoLineDialog extends JDialog implements ActionListener,
693
			DocumentListener {
694
695
		private JTextField textField;
696
697
		private JButton okButton, cancelButton;
698
699
		private JLabel errorMessage;
700
701
		private int totalLines;
702
703
		private int lineNumber = -1;
704
705
		public GotoLineDialog(JFrame owner, int totalLines) {
706
			super(owner, resources.getString("GotoLine.title"), true);
707
			this.totalLines = totalLines;
708
709
			JPanel content = new JPanel(new BorderLayout());
710
			content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
711
			content.setPreferredSize(new Dimension(300, 120));
712
			getContentPane().add(content);
713
714
			Box input = new Box(BoxLayout.Y_AXIS);
715
			content.add(input, BorderLayout.NORTH);
716
717
			String str = resources.getString("GotoLine.label.enterLineNumber");
718
			str = str.replace("{0}", "" + totalLines);
719
			JLabel label = new JLabel(str);
720
			input.add(label);
721
722
			textField = new JTextField(120);
723
			textField.getDocument().addDocumentListener(this);
724
			input.add(textField);
725
726
			errorMessage = new JLabel();
727
			input.add(errorMessage);
728
729
			Box buttons = new Box(BoxLayout.X_AXIS);
730
			content.add(buttons, BorderLayout.SOUTH);
731
732
			buttons.add(Box.createHorizontalGlue());
733
734
			okButton = new JButton(resources.getString("GotoLine.button.ok"));
735
			okButton.setEnabled(false);
736
			okButton.addActionListener(this);
737
			buttons.add(okButton);
738
739
			buttons.add(Box.createHorizontalStrut(5));
740
741
			cancelButton = new JButton(resources
742
					.getString("GotoLine.button.cancel"));
743
			cancelButton.addActionListener(this);
744
			buttons.add(cancelButton);
745
746
			pack();
747
			setLocationRelativeTo(getParent());
748
		}
749
750
		public int getLineNumber() {
751
			return lineNumber;
752
		}
753
754
		public void actionPerformed(ActionEvent e) {
755
			if (e.getSource() == okButton) {
756
				lineNumber = Integer.parseInt(textField.getText());
757
				dispose();
758
			} else if (e.getSource() == cancelButton) {
759
				dispose();
760
			}
761
		}
762
763
		public void changedUpdate(DocumentEvent e) {
764
			check();
765
		}
766
767
		public void insertUpdate(DocumentEvent e) {
768
			check();
769
		}
770
771
		public void removeUpdate(DocumentEvent e) {
772
			check();
773
		}
774
775
		private void check() {
776
			boolean disabled = false;
777
			String error = "";
778
			try {
779
				String text = textField.getText();
780
				if (text == null || text.trim().equals("")) {
781
					disabled = true;
782
				} else {
783
					int n = Integer.parseInt(text);
784
					if (n < 1 || n > totalLines) {
785
						disabled = true;
786
						error = "Number out of range";
787
					}
788
				}
789
			} catch (NumberFormatException e) {
790
				disabled = true;
791
				error = "Not a number";
792
			}
793
			okButton.setEnabled(!disabled);
794
			errorMessage.setText(error);
795
		}
796
	}
797
798
	public static void main(String[] args) {
799
		// try {
800
		// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
801
		// } catch (Exception e) {
802
		// e.printStackTrace();
803
		// }
804
805
		SourceViewFrame svf = new SourceViewFrame(null, "abcdef", null);
806
		svf.setSize(700, 500);
807
		svf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
808
		svf.setVisible(true);
809
	}
810
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxStyle.java (+136 lines)
Line 0 Link Here
1
/*
2
 * SyntaxStyle.java - A simple text style class
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import java.awt.*;
12
import java.util.StringTokenizer;
13
14
/**
15
 * A simple text style class. It can specify the color, italic flag,
16
 * and bold flag of a run of text.
17
 * @author Slava Pestov
18
 * @version $Id: SyntaxStyle.java,v 1.6 1999/12/13 03:40:30 sp Exp $
19
 */
20
public class SyntaxStyle
21
{
22
	/**
23
	 * Creates a new SyntaxStyle.
24
	 * @param color The text color
25
	 * @param italic True if the text should be italics
26
	 * @param bold True if the text should be bold
27
	 */
28
	public SyntaxStyle(Color color, boolean italic, boolean bold)
29
	{
30
		this.color = color;
31
		this.italic = italic;
32
		this.bold = bold;
33
	}
34
35
	/**
36
	 * Returns the color specified in this style.
37
	 */
38
	public Color getColor()
39
	{
40
		return color;
41
	}
42
43
	/**
44
	 * Returns true if no font styles are enabled.
45
	 */
46
	public boolean isPlain()
47
	{
48
		return !(bold || italic);
49
	}
50
51
	/**
52
	 * Returns true if italics is enabled for this style.
53
	 */
54
	public boolean isItalic()
55
	{
56
		return italic;
57
	}
58
59
	/**
60
	 * Returns true if boldface is enabled for this style.
61
	 */
62
	public boolean isBold()
63
	{
64
		return bold;
65
	}
66
67
	/**
68
	 * Returns the specified font, but with the style's bold and
69
	 * italic flags applied.
70
	 */
71
	public Font getStyledFont(Font font)
72
	{
73
		if(font == null)
74
			throw new NullPointerException("font param must not"
75
				+ " be null");
76
		if(font.equals(lastFont))
77
			return lastStyledFont;
78
		lastFont = font;
79
		lastStyledFont = new Font(font.getFamily(),
80
			(bold ? Font.BOLD : 0)
81
			| (italic ? Font.ITALIC : 0),
82
			font.getSize());
83
		return lastStyledFont;
84
	}
85
86
	/**
87
	 * Returns the font metrics for the styled font.
88
	 */
89
	public FontMetrics getFontMetrics(Font font)
90
	{
91
		if(font == null)
92
			throw new NullPointerException("font param must not"
93
				+ " be null");
94
		if(font.equals(lastFont) && fontMetrics != null)
95
			return fontMetrics;
96
		lastFont = font;
97
		lastStyledFont = new Font(font.getFamily(),
98
			(bold ? Font.BOLD : 0)
99
			| (italic ? Font.ITALIC : 0),
100
			font.getSize());
101
		fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(
102
			lastStyledFont);
103
		return fontMetrics;
104
	}
105
106
	/**
107
	 * Sets the foreground color and font of the specified graphics
108
	 * context to that specified in this style.
109
	 * @param gfx The graphics context
110
	 * @param font The font to add the styles to
111
	 */
112
	public void setGraphicsFlags(Graphics gfx, Font font)
113
	{
114
		Font _font = getStyledFont(font);
115
		gfx.setFont(_font);
116
		gfx.setColor(color);
117
	}
118
119
	/**
120
	 * Returns a string representation of this object.
121
	 */
122
	public String toString()
123
	{
124
		return getClass().getName() + "[color=" + color +
125
			(italic ? ",italic" : "") +
126
			(bold ? ",bold" : "") + "]";
127
	}
128
129
	// private members
130
	private Color color;
131
	private boolean italic;
132
	private boolean bold;
133
	private Font lastFont;
134
	private Font lastStyledFont;
135
	private FontMetrics fontMetrics;
136
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/StatusBar.java (+147 lines)
Line 0 Link Here
1
/*
2
3
   Licensed to the Apache Software Foundation (ASF) under one or more
4
   contributor license agreements.  See the NOTICE file distributed with
5
   this work for additional information regarding copyright ownership.
6
   The ASF licenses this file to You under the Apache License, Version 2.0
7
   (the "License"); you may not use this file except in compliance with
8
   the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
   Unless required by applicable law or agreed to in writing, software
13
   distributed under the License is distributed on an "AS IS" BASIS,
14
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
   See the License for the specific language governing permissions and
16
   limitations under the License.
17
18
 */
19
package org.apache.batik.apps.svgbrowser.srcview;
20
21
import java.awt.Dimension;
22
import java.util.Locale;
23
import java.util.MissingResourceException;
24
import java.util.ResourceBundle;
25
26
import javax.swing.BorderFactory;
27
import javax.swing.Box;
28
import javax.swing.BoxLayout;
29
import javax.swing.JLabel;
30
import javax.swing.JPanel;
31
import javax.swing.border.BevelBorder;
32
33
import org.apache.batik.util.gui.resource.ResourceManager;
34
35
/**
36
 * This class represents a viewer status bar.
37
 *
38
 */
39
public class StatusBar extends JPanel {
40
41
    /**
42
     * The gui resources file name
43
     */
44
    protected static final String RESOURCES =
45
        "org.apache.batik.apps.svgbrowser.srcview.resources.StatusBarMessages";
46
47
    /**
48
     * The resource bundle
49
     */
50
    protected static ResourceBundle bundle;
51
52
    /**
53
     * The resource manager
54
     */
55
    protected static ResourceManager rManager;
56
57
    /**
58
     * The string to be used for "Row"
59
     */
60
    private static String rowStr;
61
    
62
    /**
63
     * The string to be used for "Column"
64
     */
65
    private static String colStr;
66
    
67
    static {
68
        bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
69
        rManager = new ResourceManager(bundle);
70
    	rowStr = rManager.getString("Position.row");
71
    	colStr = rManager.getString("Position.column");
72
    }
73
74
    /**
75
     * The row value
76
     */
77
    protected int row;
78
    
79
    /**
80
     * The column value
81
     */
82
    protected int column;
83
    
84
    /**
85
     * The position label.
86
     */
87
    protected JLabel position;
88
89
    /**
90
     * The message label
91
     */
92
    protected JLabel message;
93
94
    /**
95
     * Creates a new status bar.
96
     */
97
    public StatusBar() throws MissingResourceException {
98
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
99
        setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
100
101
    	position = new JLabel();
102
        position.setPreferredSize(new Dimension(110, 16));
103
        add(position);
104
105
        message = new JLabel();
106
        add(message);
107
        
108
        add(Box.createHorizontalGlue());
109
    }
110
111
    /**
112
     * Sets the row.
113
     */
114
    public void setRow(int row) {
115
    	this.row = row;
116
    	updatePosition();
117
    }
118
119
    /**
120
     * Sets the column.
121
     */
122
    public void setColumn(int column) {
123
    	this.column = column;
124
    	updatePosition();
125
    }
126
    
127
    /**
128
     * Sets the row and column together
129
     */
130
    public void setPosition(int row, int column) {
131
    	this.row = row;
132
    	this.column = column;
133
    	updatePosition();
134
    }
135
    
136
    private void updatePosition() {
137
    	position.setText(rowStr + " " + row + ", " + colStr + " " + column);
138
    }
139
140
    /**
141
     * Sets the message
142
     * @param s the message
143
     */
144
    public void setMessage(String s) {
145
        message.setText(s);
146
    }
147
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/Token.java (+149 lines)
Line 0 Link Here
1
/*
2
 * Token.java - Generic token
3
 * Copyright (C) 1998, 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
10
package org.apache.batik.apps.svgbrowser.srcview;
11
12
/**
13
 * A linked list of tokens. Each token has three fields - a token
14
 * identifier, which is a byte value that can be looked up in the
15
 * array returned by <code>SyntaxDocument.getColors()</code>
16
 * to get a color value, a length value which is the length of the
17
 * token in the text, and a pointer to the next token in the list.
18
 *
19
 * @author Slava Pestov
20
 * @version $Id: Token.java,v 1.12 1999/12/13 03:40:30 sp Exp $
21
 */
22
public class Token
23
{
24
	/**
25
	 * Normal text token id. This should be used to mark
26
	 * normal text.
27
	 */
28
	public static final byte NULL = 0;
29
30
	/**
31
	 * Comment 1 token id. This can be used to mark a comment.
32
	 */
33
	public static final byte COMMENT1 = 1;
34
35
	/**
36
	 * Comment 2 token id. This can be used to mark a comment.
37
	 */
38
	public static final byte COMMENT2 = 2;
39
40
	
41
	/**
42
	 * Literal 1 token id. This can be used to mark a string
43
	 * literal (eg, C mode uses this to mark "..." literals)
44
	 */
45
	public static final byte LITERAL1 = 3;
46
47
	/**
48
	 * Literal 2 token id. This can be used to mark an object
49
	 * literal (eg, Java mode uses this to mark true, false, etc)
50
	 */
51
	public static final byte LITERAL2 = 4;
52
53
	/**
54
	 * Label token id. This can be used to mark labels
55
	 * (eg, C mode uses this to mark ...: sequences)
56
	 */
57
	public static final byte LABEL = 5;
58
59
	/**
60
	 * Keyword 1 token id. This can be used to mark a
61
	 * keyword. This should be used for general language
62
	 * constructs.
63
	 */
64
	public static final byte KEYWORD1 = 6;
65
66
	/**
67
	 * Keyword 2 token id. This can be used to mark a
68
	 * keyword. This should be used for preprocessor
69
	 * commands, or variables.
70
	 */
71
	public static final byte KEYWORD2 = 7;
72
73
	/**
74
	 * Keyword 3 token id. This can be used to mark a
75
	 * keyword. This should be used for data types.
76
	 */
77
	public static final byte KEYWORD3 = 8;
78
79
	/**
80
	 * Operator token id. This can be used to mark an
81
	 * operator. (eg, SQL mode marks +, -, etc with this
82
	 * token type)
83
	 */
84
	public static final byte OPERATOR = 9;
85
86
	/**
87
	 * Invalid token id. This can be used to mark invalid
88
	 * or incomplete tokens, so the user can easily spot
89
	 * syntax errors.
90
	 */
91
	public static final byte INVALID = 10;
92
93
	/**
94
	 * The total number of defined token ids.
95
	 */
96
	public static final byte ID_COUNT = 11;
97
98
	/**
99
	 * The first id that can be used for internal state
100
	 * in a token marker.
101
	 */
102
	public static final byte INTERNAL_FIRST = 100;
103
104
	/**
105
	 * The last id that can be used for internal state
106
	 * in a token marker.
107
	 */
108
	public static final byte INTERNAL_LAST = 126;
109
110
	/**
111
	 * The token type, that along with a length of 0
112
	 * marks the end of the token list.
113
	 */
114
	public static final byte END = 127;
115
116
	/**
117
	 * The length of this token.
118
	 */
119
	public int length;
120
121
	/**
122
	 * The id of this token.
123
	 */
124
	public byte id;
125
126
	/**
127
	 * The next token in the linked list.
128
	 */
129
	public Token next;
130
131
	/**
132
	 * Creates a new token.
133
	 * @param length The length of the token
134
	 * @param id The id of the token
135
	 */
136
	public Token(int length, byte id)
137
	{
138
		this.length = length;
139
		this.id = id;
140
	}
141
142
	/**
143
	 * Returns a string representation of this token.
144
	 */
145
	public String toString()
146
	{
147
		return "[id=" + id + ",length=" + length + "]";
148
	}
149
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextUtilities.java (+183 lines)
Line 0 Link Here
1
/*
2
 * TextUtilities.java - Utility functions used by the text area classes
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.text.*;
12
13
/**
14
 * Class with several utility functions used by the text area component.
15
 * @author Slava Pestov
16
 * @version $Id: TextUtilities.java,v 1.4 1999/12/13 03:40:30 sp Exp $
17
 */
18
public class TextUtilities
19
{
20
	/**
21
	 * Returns the offset of the bracket matching the one at the
22
	 * specified offset of the document, or -1 if the bracket is
23
	 * unmatched (or if the character is not a bracket).
24
	 * @param doc The document
25
	 * @param offset The offset
26
	 * @exception BadLocationException If an out-of-bounds access
27
	 * was attempted on the document text
28
	 */
29
	public static int findMatchingBracket(Document doc, int offset)
30
		throws BadLocationException
31
	{
32
		if(doc.getLength() == 0)
33
			return -1;
34
		char c = doc.getText(offset,1).charAt(0);
35
		char cprime; // c` - corresponding character
36
		boolean direction; // true = back, false = forward
37
38
		switch(c)
39
		{
40
		case '(': cprime = ')'; direction = false; break;
41
		case ')': cprime = '('; direction = true; break;
42
		case '[': cprime = ']'; direction = false; break;
43
		case ']': cprime = '['; direction = true; break;
44
		case '{': cprime = '}'; direction = false; break;
45
		case '}': cprime = '{'; direction = true; break;
46
		default: return -1;
47
		}
48
49
		int count;
50
51
		// How to merge these two cases is left as an exercise
52
		// for the reader.
53
54
		// Go back or forward
55
		if(direction)
56
		{
57
			// Count is 1 initially because we have already
58
			// `found' one closing bracket
59
			count = 1;
60
61
			// Get text[0,offset-1];
62
			String text = doc.getText(0,offset);
63
64
			// Scan backwards
65
			for(int i = offset - 1; i >= 0; i--)
66
			{
67
				// If text[i] == c, we have found another
68
				// closing bracket, therefore we will need
69
				// two opening brackets to complete the
70
				// match.
71
				char x = text.charAt(i);
72
				if(x == c)
73
					count++;
74
75
				// If text[i] == cprime, we have found a
76
				// opening bracket, so we return i if
77
				// --count == 0
78
				else if(x == cprime)
79
				{
80
					if(--count == 0)
81
						return i;
82
				}
83
			}
84
		}
85
		else
86
		{
87
			// Count is 1 initially because we have already
88
			// `found' one opening bracket
89
			count = 1;
90
91
			// So we don't have to + 1 in every loop
92
			offset++;
93
94
			// Number of characters to check
95
			int len = doc.getLength() - offset;
96
97
			// Get text[offset+1,len];
98
			String text = doc.getText(offset,len);
99
100
			// Scan forwards
101
			for(int i = 0; i < len; i++)
102
			{
103
				// If text[i] == c, we have found another
104
				// opening bracket, therefore we will need
105
				// two closing brackets to complete the
106
				// match.
107
				char x = text.charAt(i);
108
109
				if(x == c)
110
					count++;
111
112
				// If text[i] == cprime, we have found an
113
				// closing bracket, so we return i if
114
				// --count == 0
115
				else if(x == cprime)
116
				{
117
					if(--count == 0)
118
						return i + offset;
119
				}
120
			}
121
		}
122
123
		// Nothing found
124
		return -1;
125
	}
126
127
	/**
128
	 * Locates the start of the word at the specified position.
129
	 * @param line The text
130
	 * @param pos The position
131
	 */
132
	public static int findWordStart(String line, int pos, String noWordSep)
133
	{
134
		char ch = line.charAt(pos - 1);
135
136
		if(noWordSep == null)
137
			noWordSep = "";
138
		boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
139
			&& noWordSep.indexOf(ch) == -1);
140
141
		int wordStart = 0;
142
		for(int i = pos - 1; i >= 0; i--)
143
		{
144
			ch = line.charAt(i);
145
			if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
146
				noWordSep.indexOf(ch) == -1))
147
			{
148
				wordStart = i + 1;
149
				break;
150
			}
151
		}
152
153
		return wordStart;
154
	}
155
156
	/**
157
	 * Locates the end of the word at the specified position.
158
	 * @param line The text
159
	 * @param pos The position
160
	 */
161
	public static int findWordEnd(String line, int pos, String noWordSep)
162
	{
163
		char ch = line.charAt(pos);
164
165
		if(noWordSep == null)
166
			noWordSep = "";
167
		boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
168
			&& noWordSep.indexOf(ch) == -1);
169
170
		int wordEnd = line.length();
171
		for(int i = pos; i < line.length(); i++)
172
		{
173
			ch = line.charAt(i);
174
			if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
175
				noWordSep.indexOf(ch) == -1))
176
			{
177
				wordEnd = i;
178
				break;
179
			}
180
		}
181
		return wordEnd;
182
	}
183
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxUtilities.java (+157 lines)
Line 0 Link Here
1
/*
2
 * SyntaxUtilities.java - Utility functions used by syntax colorizing
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.text.*;
12
import java.awt.*;
13
14
/**
15
 * Class with several utility functions used by jEdit's syntax colorizing
16
 * subsystem.
17
 *
18
 * @author Slava Pestov
19
 * @version $Id: SyntaxUtilities.java,v 1.9 1999/12/13 03:40:30 sp Exp $
20
 */
21
public class SyntaxUtilities
22
{
23
	/**
24
	 * Checks if a subregion of a <code>Segment</code> is equal to a
25
	 * string.
26
	 * @param ignoreCase True if case should be ignored, false otherwise
27
	 * @param text The segment
28
	 * @param offset The offset into the segment
29
	 * @param match The string to match
30
	 */
31
	public static boolean regionMatches(boolean ignoreCase, Segment text,
32
					    int offset, String match)
33
	{
34
		int length = offset + match.length();
35
		char[] textArray = text.array;
36
		if(length > text.offset + text.count)
37
			return false;
38
		for(int i = offset, j = 0; i < length; i++, j++)
39
		{
40
			char c1 = textArray[i];
41
			char c2 = match.charAt(j);
42
			if(ignoreCase)
43
			{
44
				c1 = Character.toUpperCase(c1);
45
				c2 = Character.toUpperCase(c2);
46
			}
47
			if(c1 != c2)
48
				return false;
49
		}
50
		return true;
51
	}
52
	
53
	/**
54
	 * Checks if a subregion of a <code>Segment</code> is equal to a
55
	 * character array.
56
	 * @param ignoreCase True if case should be ignored, false otherwise
57
	 * @param text The segment
58
	 * @param offset The offset into the segment
59
	 * @param match The character array to match
60
	 */
61
	public static boolean regionMatches(boolean ignoreCase, Segment text,
62
					    int offset, char[] match)
63
	{
64
		int length = offset + match.length;
65
		char[] textArray = text.array;
66
		if(length > text.offset + text.count)
67
			return false;
68
		for(int i = offset, j = 0; i < length; i++, j++)
69
		{
70
			char c1 = textArray[i];
71
			char c2 = match[j];
72
			if(ignoreCase)
73
			{
74
				c1 = Character.toUpperCase(c1);
75
				c2 = Character.toUpperCase(c2);
76
			}
77
			if(c1 != c2)
78
				return false;
79
		}
80
		return true;
81
	}
82
83
	/**
84
	 * Returns the default style table. This can be passed to the
85
	 * <code>setStyles()</code> method of <code>SyntaxDocument</code>
86
	 * to use the default syntax styles.
87
	 */
88
	public static SyntaxStyle[] getDefaultSyntaxStyles()
89
	{
90
		SyntaxStyle[] styles = new SyntaxStyle[Token.ID_COUNT];
91
92
		styles[Token.COMMENT1] = new SyntaxStyle(Color.black,true,true);
93
		styles[Token.COMMENT2] = new SyntaxStyle(new Color(0x990033),true,true);
94
		styles[Token.KEYWORD1] = new SyntaxStyle(Color.black,false,true);
95
		styles[Token.KEYWORD2] = new SyntaxStyle(Color.magenta,false,true);
96
		styles[Token.KEYWORD3] = new SyntaxStyle(new Color(0x009600),false,false);
97
		styles[Token.LITERAL1] = new SyntaxStyle(new Color(0x650099),false,false);
98
		styles[Token.LITERAL2] = new SyntaxStyle(new Color(0x650099),false,true);
99
		styles[Token.LABEL] = new SyntaxStyle(new Color(0x990033),false,true);
100
		styles[Token.OPERATOR] = new SyntaxStyle(Color.black,false,true);
101
		styles[Token.INVALID] = new SyntaxStyle(Color.red,false,true);
102
103
		return styles;
104
	}
105
106
	/**
107
	 * Paints the specified line onto the graphics context. Note that this
108
	 * method munges the offset and count values of the segment.
109
	 * @param line The line segment
110
	 * @param tokens The token list for the line
111
	 * @param styles The syntax style list
112
	 * @param expander The tab expander used to determine tab stops. May
113
	 * be null
114
	 * @param gfx The graphics context
115
	 * @param x The x co-ordinate
116
	 * @param y The y co-ordinate
117
	 * @return The x co-ordinate, plus the width of the painted string
118
	 */
119
	public static int paintSyntaxLine(Segment line, Token tokens,
120
		SyntaxStyle[] styles, TabExpander expander, Graphics gfx,
121
		int x, int y)
122
	{
123
		Font defaultFont = gfx.getFont();
124
		Color defaultColor = gfx.getColor();
125
126
		int offset = 0;
127
		for(;;)
128
		{
129
			byte id = tokens.id;
130
			if(id == Token.END)
131
				break;
132
133
			int length = tokens.length;
134
			if(id == Token.NULL)
135
			{
136
				if(!defaultColor.equals(gfx.getColor()))
137
					gfx.setColor(defaultColor);
138
				if(!defaultFont.equals(gfx.getFont()))
139
					gfx.setFont(defaultFont);
140
			}
141
			else
142
				styles[id].setGraphicsFlags(gfx,defaultFont);
143
144
			line.count = length;
145
			x = Utilities.drawTabbedText(line,x,y,gfx,expander,0);
146
			line.offset += length;
147
			offset += length;
148
149
			tokens = tokens.next;
150
		}
151
152
		return x;
153
	}
154
155
	// private members
156
	private SyntaxUtilities() {}
157
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TokenMarker.java (+344 lines)
Line 0 Link Here
1
/*
2
 * TokenMarker.java - Generic token marker
3
 * Copyright (C) 1998, 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.text.Segment;
12
import java.util.*;
13
14
/**
15
 * A token marker that splits lines of text into tokens. Each token carries
16
 * a length field and an indentification tag that can be mapped to a color
17
 * for painting that token.<p>
18
 *
19
 * For performance reasons, the linked list of tokens is reused after each
20
 * line is tokenized. Therefore, the return value of <code>markTokens</code>
21
 * should only be used for immediate painting. Notably, it cannot be
22
 * cached.
23
 *
24
 * @author Slava Pestov
25
 * @version $Id: TokenMarker.java,v 1.32 1999/12/13 03:40:30 sp Exp $
26
 *
27
 * @see org.gjt.sp.jedit.syntax.Token
28
 */
29
public abstract class TokenMarker
30
{
31
	/**
32
	 * A wrapper for the lower-level <code>markTokensImpl</code> method
33
	 * that is called to split a line up into tokens.
34
	 * @param line The line
35
	 * @param lineIndex The line number
36
	 */
37
	public Token markTokens(Segment line, int lineIndex)
38
	{
39
		if(lineIndex >= length)
40
		{
41
			throw new IllegalArgumentException("Tokenizing invalid line: "
42
				+ lineIndex);
43
		}
44
45
		lastToken = null;
46
47
		LineInfo info = lineInfo[lineIndex];
48
		LineInfo prev;
49
		if(lineIndex == 0)
50
			prev = null;
51
		else
52
			prev = lineInfo[lineIndex - 1];
53
54
		byte oldToken = info.token;
55
		byte token = markTokensImpl(prev == null ?
56
			Token.NULL : prev.token,line,lineIndex);
57
58
		info.token = token;
59
60
		/*
61
		 * This is a foul hack. It stops nextLineRequested
62
		 * from being cleared if the same line is marked twice.
63
		 *
64
		 * Why is this necessary? It's all JEditTextArea's fault.
65
		 * When something is inserted into the text, firing a
66
		 * document event, the insertUpdate() method shifts the
67
		 * caret (if necessary) by the amount inserted.
68
		 *
69
		 * All caret movement is handled by the select() method,
70
		 * which eventually pipes the new position to scrollTo()
71
		 * and calls repaint().
72
		 *
73
		 * Note that at this point in time, the new line hasn't
74
		 * yet been painted; the caret is moved first.
75
		 *
76
		 * scrollTo() calls offsetToX(), which tokenizes the line
77
		 * unless it is being called on the last line painted
78
		 * (in which case it uses the text area's painter cached
79
		 * token list). What scrollTo() does next is irrelevant.
80
		 *
81
		 * After scrollTo() has done it's job, repaint() is
82
		 * called, and eventually we end up in paintLine(), whose
83
		 * job is to paint the changed line. It, too, calls
84
		 * markTokens().
85
		 *
86
		 * The problem was that if the line started a multiline
87
		 * token, the first markTokens() (done in offsetToX())
88
		 * would set nextLineRequested (because the line end
89
		 * token had changed) but the second would clear it
90
		 * (because the line was the same that time) and therefore
91
		 * paintLine() would never know that it needed to repaint
92
		 * subsequent lines.
93
		 *
94
		 * This bug took me ages to track down, that's why I wrote
95
		 * all the relevant info down so that others wouldn't
96
		 * duplicate it.
97
		 */
98
		 if(!(lastLine == lineIndex && nextLineRequested))
99
			nextLineRequested = (oldToken != token);
100
101
		lastLine = lineIndex;
102
103
		addToken(0,Token.END);
104
105
		return firstToken;
106
	}
107
108
	/**
109
	 * An abstract method that splits a line up into tokens. It
110
	 * should parse the line, and call <code>addToken()</code> to
111
	 * add syntax tokens to the token list. Then, it should return
112
	 * the initial token type for the next line.<p>
113
	 *
114
	 * For example if the current line contains the start of a 
115
	 * multiline comment that doesn't end on that line, this method
116
	 * should return the comment token type so that it continues on
117
	 * the next line.
118
	 *
119
	 * @param token The initial token type for this line
120
	 * @param line The line to be tokenized
121
	 * @param lineIndex The index of the line in the document,
122
	 * starting at 0
123
	 * @return The initial token type for the next line
124
	 */
125
	protected abstract byte markTokensImpl(byte token, Segment line,
126
		int lineIndex);
127
128
	/**
129
	 * Returns if the token marker supports tokens that span multiple
130
	 * lines. If this is true, the object using this token marker is
131
	 * required to pass all lines in the document to the
132
	 * <code>markTokens()</code> method (in turn).<p>
133
	 *
134
	 * The default implementation returns true; it should be overridden
135
	 * to return false on simpler token markers for increased speed.
136
	 */
137
	public boolean supportsMultilineTokens()
138
	{
139
		return true;
140
	}
141
142
	/**
143
	 * Informs the token marker that lines have been inserted into
144
	 * the document. This inserts a gap in the <code>lineInfo</code>
145
	 * array.
146
	 * @param index The first line number
147
	 * @param lines The number of lines 
148
	 */
149
	public void insertLines(int index, int lines)
150
	{
151
		if(lines <= 0)
152
			return;
153
		length += lines;
154
		ensureCapacity(length);
155
		int len = index + lines;
156
		System.arraycopy(lineInfo,index,lineInfo,len,
157
			lineInfo.length - len);
158
159
		for(int i = index + lines - 1; i >= index; i--)
160
		{
161
			lineInfo[i] = new LineInfo();
162
		}
163
	}
164
	
165
	/**
166
	 * Informs the token marker that line have been deleted from
167
	 * the document. This removes the lines in question from the
168
	 * <code>lineInfo</code> array.
169
	 * @param index The first line number
170
	 * @param lines The number of lines
171
	 */
172
	public void deleteLines(int index, int lines)
173
	{
174
		if (lines <= 0)
175
			return;
176
		int len = index + lines;
177
		length -= lines;
178
		System.arraycopy(lineInfo,len,lineInfo,
179
			index,lineInfo.length - len);
180
	}
181
182
	/**
183
	 * Returns the number of lines in this token marker.
184
	 */
185
	public int getLineCount()
186
	{
187
		return length;
188
	}
189
190
	/**
191
	 * Returns true if the next line should be repainted. This
192
	 * will return true after a line has been tokenized that starts
193
	 * a multiline token that continues onto the next line.
194
	 */
195
	public boolean isNextLineRequested()
196
	{
197
		return nextLineRequested;
198
	}
199
200
	// protected members
201
202
	/**
203
	 * The first token in the list. This should be used as the return
204
	 * value from <code>markTokens()</code>.
205
	 */
206
	protected Token firstToken;
207
208
	/**
209
	 * The last token in the list. New tokens are added here.
210
	 * This should be set to null before a new line is to be tokenized.
211
	 */
212
	protected Token lastToken;
213
214
	/**
215
	 * An array for storing information about lines. It is enlarged and
216
	 * shrunk automatically by the <code>insertLines()</code> and
217
	 * <code>deleteLines()</code> methods.
218
	 */
219
	protected LineInfo[] lineInfo;
220
221
	/**
222
	 * The number of lines in the model being tokenized. This can be
223
	 * less than the length of the <code>lineInfo</code> array.
224
	 */
225
	protected int length;
226
227
	/**
228
	 * The last tokenized line.
229
	 */
230
	protected int lastLine;
231
232
	/**
233
	 * True if the next line should be painted.
234
	 */
235
	protected boolean nextLineRequested;
236
237
	/**
238
	 * Creates a new <code>TokenMarker</code>. This DOES NOT create
239
	 * a lineInfo array; an initial call to <code>insertLines()</code>
240
	 * does that.
241
	 */
242
	protected TokenMarker()
243
	{
244
		lastLine = -1;
245
	}
246
247
	/**
248
	 * Ensures that the <code>lineInfo</code> array can contain the
249
	 * specified index. This enlarges it if necessary. No action is
250
	 * taken if the array is large enough already.<p>
251
	 *
252
	 * It should be unnecessary to call this under normal
253
	 * circumstances; <code>insertLine()</code> should take care of
254
	 * enlarging the line info array automatically.
255
	 *
256
	 * @param index The array index
257
	 */
258
	protected void ensureCapacity(int index)
259
	{
260
		if(lineInfo == null)
261
			lineInfo = new LineInfo[index + 1];
262
		else if(lineInfo.length <= index)
263
		{
264
			LineInfo[] lineInfoN = new LineInfo[(index + 1) * 2];
265
			System.arraycopy(lineInfo,0,lineInfoN,0,
266
					 lineInfo.length);
267
			lineInfo = lineInfoN;
268
		}
269
	}
270
271
	/**
272
	 * Adds a token to the token list.
273
	 * @param length The length of the token
274
	 * @param id The id of the token
275
	 */
276
	protected void addToken(int length, byte id)
277
	{
278
		if(id >= Token.INTERNAL_FIRST && id <= Token.INTERNAL_LAST)
279
			throw new InternalError("Invalid id: " + id);
280
281
		if(length == 0 && id != Token.END)
282
			return;
283
284
		if(firstToken == null)
285
		{
286
			firstToken = new Token(length,id);
287
			lastToken = firstToken;
288
		}
289
		else if(lastToken == null)
290
		{
291
			lastToken = firstToken;
292
			firstToken.length = length;
293
			firstToken.id = id;
294
		}
295
		else if(lastToken.next == null)
296
		{
297
			lastToken.next = new Token(length,id);
298
			lastToken = lastToken.next;
299
		}
300
		else
301
		{
302
			lastToken = lastToken.next;
303
			lastToken.length = length;
304
			lastToken.id = id;
305
		}
306
	}
307
308
	/**
309
	 * Inner class for storing information about tokenized lines.
310
	 */
311
	public class LineInfo
312
	{
313
		/**
314
		 * Creates a new LineInfo object with token = Token.NULL
315
		 * and obj = null.
316
		 */
317
		public LineInfo()
318
		{
319
		}
320
321
		/**
322
		 * Creates a new LineInfo object with the specified
323
		 * parameters.
324
		 */
325
		public LineInfo(byte token, Object obj)
326
		{
327
			this.token = token;
328
			this.obj = obj;
329
		}
330
331
		/**
332
		 * The id of the last token of the line.
333
		 */
334
		public byte token;
335
336
		/**
337
		 * This is for use by the token marker implementations
338
		 * themselves. It can be used to store anything that
339
		 * is an object and that needs to exist on a per-line
340
		 * basis.
341
		 */
342
		public Object obj;
343
	}
344
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/KeywordMap.java (+139 lines)
Line 0 Link Here
1
/*
2
 * KeywordMap.java - Fast keyword->id map
3
 * Copyright (C) 1998, 1999 Slava Pestov
4
 * Copyright (C) 1999 Mike Dillon
5
 *
6
 * You may use and modify this package for any purpose. Redistribution is
7
 * permitted, in both source and binary form, provided that this notice
8
 * remains intact in all source distributions of this package.
9
 */
10
package org.apache.batik.apps.svgbrowser.srcview;
11
12
import javax.swing.text.Segment;
13
14
/**
15
 * A <code>KeywordMap</code> is similar to a hashtable in that it maps keys
16
 * to values. However, the `keys' are Swing segments. This allows lookups of
17
 * text substrings without the overhead of creating a new string object.
18
 * <p>
19
 * This class is used by <code>CTokenMarker</code> to map keywords to ids.
20
 *
21
 * @author Slava Pestov, Mike Dillon
22
 * @version $Id: KeywordMap.java,v 1.16 1999/12/13 03:40:30 sp Exp $
23
 */
24
public class KeywordMap
25
{
26
	/**
27
	 * Creates a new <code>KeywordMap</code>.
28
	 * @param ignoreCase True if keys are case insensitive
29
	 */
30
	public KeywordMap(boolean ignoreCase)
31
	{
32
		this(ignoreCase, 52);
33
		this.ignoreCase = ignoreCase;
34
	}
35
36
	/**
37
	 * Creates a new <code>KeywordMap</code>.
38
	 * @param ignoreCase True if the keys are case insensitive
39
	 * @param mapLength The number of `buckets' to create.
40
	 * A value of 52 will give good performance for most maps.
41
	 */
42
	public KeywordMap(boolean ignoreCase, int mapLength)
43
	{
44
		this.mapLength = mapLength;
45
		this.ignoreCase = ignoreCase;
46
		map = new Keyword[mapLength];
47
	}
48
49
	/**
50
	 * Looks up a key.
51
	 * @param text The text segment
52
	 * @param offset The offset of the substring within the text segment
53
	 * @param length The length of the substring
54
	 */
55
	public byte lookup(Segment text, int offset, int length)
56
	{
57
		if(length == 0)
58
			return Token.NULL;
59
		Keyword k = map[getSegmentMapKey(text, offset, length)];
60
		while(k != null)
61
		{
62
			if(length != k.keyword.length)
63
			{
64
				k = k.next;
65
				continue;
66
			}
67
			if(SyntaxUtilities.regionMatches(ignoreCase,text,offset,
68
				k.keyword))
69
				return k.id;
70
			k = k.next;
71
		}
72
		return Token.NULL;
73
	}
74
75
	/**
76
	 * Adds a key-value mapping.
77
	 * @param keyword The key
78
	 * @Param id The value
79
	 */
80
	public void add(String keyword, byte id)
81
	{
82
		int key = getStringMapKey(keyword);
83
		map[key] = new Keyword(keyword.toCharArray(),id,map[key]);
84
	}
85
86
	/**
87
	 * Returns true if the keyword map is set to be case insensitive,
88
	 * false otherwise.
89
	 */
90
	public boolean getIgnoreCase()
91
	{
92
		return ignoreCase;
93
	}
94
95
	/**
96
	 * Sets if the keyword map should be case insensitive.
97
	 * @param ignoreCase True if the keyword map should be case
98
	 * insensitive, false otherwise
99
	 */
100
	public void setIgnoreCase(boolean ignoreCase)
101
	{
102
		this.ignoreCase = ignoreCase;
103
	}
104
105
	// protected members
106
	protected int mapLength;
107
108
	protected int getStringMapKey(String s)
109
	{
110
		return (Character.toUpperCase(s.charAt(0)) +
111
				Character.toUpperCase(s.charAt(s.length()-1)))
112
				% mapLength;
113
	}
114
115
	protected int getSegmentMapKey(Segment s, int off, int len)
116
	{
117
		return (Character.toUpperCase(s.array[off]) +
118
				Character.toUpperCase(s.array[off + len - 1]))
119
				% mapLength;
120
	}
121
122
	// private members
123
	class Keyword
124
	{
125
		public Keyword(char[] keyword, byte id, Keyword next)
126
		{
127
			this.keyword = keyword;
128
			this.id = id;
129
			this.next = next;
130
		}
131
132
		public char[] keyword;
133
		public byte id;
134
		public Keyword next;
135
	}
136
137
	private Keyword[] map;
138
	private boolean ignoreCase;
139
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxDocument.java (+165 lines)
Line 0 Link Here
1
/*
2
 * SyntaxDocument.java - Document that can be tokenized
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.event.*;
12
import javax.swing.text.*;
13
import javax.swing.undo.UndoableEdit;
14
15
/**
16
 * A document implementation that can be tokenized by the syntax highlighting
17
 * system.
18
 *
19
 * @author Slava Pestov
20
 * @version $Id: SyntaxDocument.java,v 1.14 1999/12/13 03:40:30 sp Exp $
21
 */
22
public class SyntaxDocument extends PlainDocument
23
{
24
	/**
25
	 * Returns the token marker that is to be used to split lines
26
	 * of this document up into tokens. May return null if this
27
	 * document is not to be colorized.
28
	 */
29
	public TokenMarker getTokenMarker()
30
	{
31
		return tokenMarker;
32
	}
33
34
	/**
35
	 * Sets the token marker that is to be used to split lines of
36
	 * this document up into tokens. May throw an exception if
37
	 * this is not supported for this type of document.
38
	 * @param tm The new token marker
39
	 */
40
	public void setTokenMarker(TokenMarker tm)
41
	{
42
		tokenMarker = tm;
43
		if(tm == null)
44
			return;
45
		tokenMarker.insertLines(0,getDefaultRootElement()
46
			.getElementCount());
47
		tokenizeLines();
48
	}
49
50
	/**
51
	 * Reparses the document, by passing all lines to the token
52
	 * marker. This should be called after the document is first
53
	 * loaded.
54
	 */
55
	public void tokenizeLines()
56
	{
57
		tokenizeLines(0,getDefaultRootElement().getElementCount());
58
	}
59
60
	/**
61
	 * Reparses the document, by passing the specified lines to the
62
	 * token marker. This should be called after a large quantity of
63
	 * text is first inserted.
64
	 * @param start The first line to parse
65
	 * @param len The number of lines, after the first one to parse
66
	 */
67
	public void tokenizeLines(int start, int len)
68
	{
69
		if(tokenMarker == null || !tokenMarker.supportsMultilineTokens())
70
			return;
71
72
		Segment lineSegment = new Segment();
73
		Element map = getDefaultRootElement();
74
75
		len += start;
76
77
		try
78
		{
79
			for(int i = start; i < len; i++)
80
			{
81
				Element lineElement = map.getElement(i);
82
				int lineStart = lineElement.getStartOffset();
83
				getText(lineStart,lineElement.getEndOffset()
84
					- lineStart - 1,lineSegment);
85
				tokenMarker.markTokens(lineSegment,i);
86
			}
87
		}
88
		catch(BadLocationException bl)
89
		{
90
			bl.printStackTrace();
91
		}
92
	}
93
94
	/**
95
	 * Starts a compound edit that can be undone in one operation.
96
	 * Subclasses that implement undo should override this method;
97
	 * this class has no undo functionality so this method is
98
	 * empty.
99
	 */
100
	public void beginCompoundEdit() {}
101
102
	/**
103
	 * Ends a compound edit that can be undone in one operation.
104
	 * Subclasses that implement undo should override this method;
105
	 * this class has no undo functionality so this method is
106
	 * empty.
107
	 */
108
	public void endCompoundEdit() {}
109
110
	/**
111
	 * Adds an undoable edit to this document's undo list. The edit
112
	 * should be ignored if something is currently being undone.
113
	 * @param edit The undoable edit
114
	 *
115
	 * @since jEdit 2.2pre1
116
	 */
117
	public void addUndoableEdit(UndoableEdit edit) {}
118
119
	// protected members
120
	protected TokenMarker tokenMarker;
121
122
	/**
123
	 * We overwrite this method to update the token marker
124
	 * state immediately so that any event listeners get a
125
	 * consistent token marker.
126
	 */
127
	protected void fireInsertUpdate(DocumentEvent evt)
128
	{
129
		if(tokenMarker != null)
130
		{
131
			DocumentEvent.ElementChange ch = evt.getChange(
132
				getDefaultRootElement());
133
			if(ch != null)
134
			{
135
				tokenMarker.insertLines(ch.getIndex() + 1,
136
					ch.getChildrenAdded().length -
137
					ch.getChildrenRemoved().length);
138
			}
139
		}
140
141
		super.fireInsertUpdate(evt);
142
	}
143
	
144
	/**
145
	 * We overwrite this method to update the token marker
146
	 * state immediately so that any event listeners get a
147
	 * consistent token marker.
148
	 */
149
	protected void fireRemoveUpdate(DocumentEvent evt)
150
	{
151
		if(tokenMarker != null)
152
		{
153
			DocumentEvent.ElementChange ch = evt.getChange(
154
				getDefaultRootElement());
155
			if(ch != null)
156
			{
157
				tokenMarker.deleteLines(ch.getIndex() + 1,
158
					ch.getChildrenRemoved().length -
159
					ch.getChildrenAdded().length);
160
			}
161
		}
162
163
		super.fireRemoveUpdate(evt);
164
	}
165
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/JEditTextArea.java (+2128 lines)
Line 0 Link Here
1
/*
2
 * JEditTextArea.java - jEdit's text component
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.event.*;
12
import javax.swing.text.*;
13
import javax.swing.undo.*;
14
import javax.swing.*;
15
import java.awt.datatransfer.*;
16
import java.awt.event.*;
17
import java.awt.*;
18
import java.util.Enumeration;
19
import java.util.Vector;
20
21
/**
22
 * jEdit's text area component. It is more suited for editing program
23
 * source code than JEditorPane, because it drops the unnecessary features
24
 * (images, variable-width lines, and so on) and adds a whole bunch of
25
 * useful goodies such as:
26
 * <ul>
27
 * <li>More flexible key binding scheme
28
 * <li>Supports macro recorders
29
 * <li>Rectangular selection
30
 * <li>Bracket highlighting
31
 * <li>Syntax highlighting
32
 * <li>Command repetition
33
 * <li>Block caret can be enabled
34
 * </ul>
35
 * It is also faster and doesn't have as many problems. It can be used
36
 * in other applications; the only other part of jEdit it depends on is
37
 * the syntax package.<p>
38
 *
39
 * To use it in your app, treat it like any other component, for example:
40
 * <pre>JEditTextArea ta = new JEditTextArea();
41
 * ta.setTokenMarker(new JavaTokenMarker());
42
 * ta.setText("public class Test {\n"
43
 *     + "    public static void main(String[] args) {\n"
44
 *     + "        System.out.println(\"Hello World\");\n"
45
 *     + "    }\n"
46
 *     + "}");</pre>
47
 *
48
 * @author Slava Pestov
49
 * @version $Id: JEditTextArea.java,v 1.36 1999/12/13 03:40:30 sp Exp $
50
 */
51
public class JEditTextArea extends JComponent
52
{
53
	/**
54
	 * Adding components with this name to the text area will place
55
	 * them left of the horizontal scroll bar. In jEdit, the status
56
	 * bar is added this way.
57
	 */
58
	public static String LEFT_OF_SCROLLBAR = "los";
59
60
	/**
61
	 * Creates a new JEditTextArea with the default settings.
62
	 */
63
	public JEditTextArea()
64
	{
65
		this(TextAreaDefaults.getDefaults());
66
	}
67
68
	/**
69
	 * Creates a new JEditTextArea with the specified settings.
70
	 * @param defaults The default settings
71
	 */
72
	public JEditTextArea(TextAreaDefaults defaults)
73
	{
74
		// Enable the necessary events
75
		enableEvents(AWTEvent.KEY_EVENT_MASK);
76
77
		// Initialize some misc. stuff
78
		painter = new TextAreaPainter(this,defaults);
79
		documentHandler = new DocumentHandler();
80
		listenerList = new EventListenerList();
81
		caretEvent = new MutableCaretEvent();
82
		lineSegment = new Segment();
83
		bracketLine = bracketPosition = -1;
84
		blink = true;
85
86
		// Initialize the GUI
87
		setLayout(new ScrollLayout());
88
		add(CENTER,painter);
89
		add(RIGHT,vertical = new JScrollBar(JScrollBar.VERTICAL));
90
		add(BOTTOM,horizontal = new JScrollBar(JScrollBar.HORIZONTAL));
91
92
		// Add some event listeners
93
		vertical.addAdjustmentListener(new AdjustHandler());
94
		horizontal.addAdjustmentListener(new AdjustHandler());
95
		painter.addComponentListener(new ComponentHandler());
96
		painter.addMouseListener(new MouseHandler());
97
		painter.addMouseMotionListener(new DragHandler());
98
		addFocusListener(new FocusHandler());
99
100
		// Load the defaults
101
		setInputHandler(defaults.inputHandler);
102
		setDocument(defaults.document);
103
		editable = defaults.editable;
104
		caretVisible = defaults.caretVisible;
105
		caretBlinks = defaults.caretBlinks;
106
		electricScroll = defaults.electricScroll;
107
108
		popup = defaults.popup;
109
110
		// We don't seem to get the initial focus event?
111
		focusedComponent = this;
112
	}
113
114
	/**
115
	 * Returns if this component can be traversed by pressing
116
	 * the Tab key. This returns false.
117
	 */
118
	public final boolean isManagingFocus()
119
	{
120
		return true;
121
	}
122
123
	/**
124
	 * Returns the object responsible for painting this text area.
125
	 */
126
	public final TextAreaPainter getPainter()
127
	{
128
		return painter;
129
	}
130
131
	/**
132
	 * Returns the input handler.
133
	 */
134
	public final InputHandler getInputHandler()
135
	{
136
		return inputHandler;
137
	}
138
139
	/**
140
	 * Sets the input handler.
141
	 * @param inputHandler The new input handler
142
	 */
143
	public void setInputHandler(InputHandler inputHandler)
144
	{
145
		this.inputHandler = inputHandler;
146
	}
147
148
	/**
149
	 * Returns true if the caret is blinking, false otherwise.
150
	 */
151
	public final boolean isCaretBlinkEnabled()
152
	{
153
		return caretBlinks;
154
	}
155
156
	/**
157
	 * Toggles caret blinking.
158
	 * @param caretBlinks True if the caret should blink, false otherwise
159
	 */
160
	public void setCaretBlinkEnabled(boolean caretBlinks)
161
	{
162
		this.caretBlinks = caretBlinks;
163
		if(!caretBlinks)
164
			blink = false;
165
166
		painter.invalidateSelectedLines();
167
	}
168
169
	/**
170
	 * Returns true if the caret is visible, false otherwise.
171
	 */
172
	public final boolean isCaretVisible()
173
	{
174
		return (!caretBlinks || blink) && caretVisible;
175
	}
176
177
	/**
178
	 * Sets if the caret should be visible.
179
	 * @param caretVisible True if the caret should be visible, false
180
	 * otherwise
181
	 */
182
	public void setCaretVisible(boolean caretVisible)
183
	{
184
		this.caretVisible = caretVisible;
185
		blink = true;
186
187
		painter.invalidateSelectedLines();
188
	}
189
190
	/**
191
	 * Blinks the caret.
192
	 */
193
	public final void blinkCaret()
194
	{
195
		if(caretBlinks)
196
		{
197
			blink = !blink;
198
			painter.invalidateSelectedLines();
199
		}
200
		else
201
			blink = true;
202
	}
203
204
	/**
205
	 * Returns the number of lines from the top and button of the
206
	 * text area that are always visible.
207
	 */
208
	public final int getElectricScroll()
209
	{
210
		return electricScroll;
211
	}
212
213
	/**
214
	 * Sets the number of lines from the top and bottom of the text
215
	 * area that are always visible
216
	 * @param electricScroll The number of lines always visible from
217
	 * the top or bottom
218
	 */
219
	public final void setElectricScroll(int electricScroll)
220
	{
221
		this.electricScroll = electricScroll;
222
	}
223
224
	/**
225
	 * Updates the state of the scroll bars. This should be called
226
	 * if the number of lines in the document changes, or when the
227
	 * size of the text are changes.
228
	 */
229
	public void updateScrollBars()
230
	{
231
		if(vertical != null && visibleLines != 0)
232
		{
233
			vertical.setValues(firstLine,visibleLines,0,getLineCount());
234
			vertical.setUnitIncrement(2);
235
			vertical.setBlockIncrement(visibleLines);
236
		}
237
238
		int width = painter.getWidth();
239
		if(horizontal != null && width != 0)
240
		{
241
			horizontal.setValues(-horizontalOffset,width,0,width * 5);
242
			horizontal.setUnitIncrement(painter.getFontMetrics()
243
				.charWidth('w'));
244
			horizontal.setBlockIncrement(width / 2);
245
		}
246
	}
247
248
	/**
249
	 * Returns the line displayed at the text area's origin.
250
	 */
251
	public final int getFirstLine()
252
	{
253
		return firstLine;
254
	}
255
256
	/**
257
	 * Sets the line displayed at the text area's origin without
258
	 * updating the scroll bars.
259
	 */
260
	public void setFirstLine(int firstLine)
261
	{
262
		if(firstLine == this.firstLine)
263
			return;
264
		int oldFirstLine = this.firstLine;
265
		this.firstLine = firstLine;
266
		if(firstLine != vertical.getValue())
267
			updateScrollBars();
268
		painter.repaint();
269
	}
270
271
	/**
272
	 * Returns the number of lines visible in this text area.
273
	 */
274
	public final int getVisibleLines()
275
	{
276
		return visibleLines;
277
	}
278
279
	/**
280
	 * Recalculates the number of visible lines. This should not
281
	 * be called directly.
282
	 */
283
	public final void recalculateVisibleLines()
284
	{
285
		if(painter == null)
286
			return;
287
		int height = painter.getHeight();
288
		int lineHeight = painter.getFontMetrics().getHeight();
289
		int oldVisibleLines = visibleLines;
290
		visibleLines = height / lineHeight;
291
		updateScrollBars();
292
	}
293
294
	/**
295
	 * Returns the horizontal offset of drawn lines.
296
	 */
297
	public final int getHorizontalOffset()
298
	{
299
		return horizontalOffset;
300
	}
301
302
	/**
303
	 * Sets the horizontal offset of drawn lines. This can be used to
304
	 * implement horizontal scrolling.
305
	 * @param horizontalOffset offset The new horizontal offset
306
	 */
307
	public void setHorizontalOffset(int horizontalOffset)
308
	{
309
		if(horizontalOffset == this.horizontalOffset)
310
			return;
311
		this.horizontalOffset = horizontalOffset;
312
		if(horizontalOffset != horizontal.getValue())
313
			updateScrollBars();
314
		painter.repaint();
315
	}
316
317
	/**
318
	 * A fast way of changing both the first line and horizontal
319
	 * offset.
320
	 * @param firstLine The new first line
321
	 * @param horizontalOffset The new horizontal offset
322
	 * @return True if any of the values were changed, false otherwise
323
	 */
324
	public boolean setOrigin(int firstLine, int horizontalOffset)
325
	{
326
		boolean changed = false;
327
		int oldFirstLine = this.firstLine;
328
329
		if(horizontalOffset != this.horizontalOffset)
330
		{
331
			this.horizontalOffset = horizontalOffset;
332
			changed = true;
333
		}
334
335
		if(firstLine != this.firstLine)
336
		{
337
			this.firstLine = firstLine;
338
			changed = true;
339
		}
340
341
		if(changed)
342
		{
343
			updateScrollBars();
344
			painter.repaint();
345
		}
346
347
		return changed;
348
	}
349
350
	/**
351
	 * Ensures that the caret is visible by scrolling the text area if
352
	 * necessary.
353
	 * @return True if scrolling was actually performed, false if the
354
	 * caret was already visible
355
	 */
356
	public boolean scrollToCaret()
357
	{
358
		int line = getCaretLine();
359
		int lineStart = getLineStartOffset(line);
360
		int offset = Math.max(0,Math.min(getLineLength(line) - 1,
361
			getCaretPosition() - lineStart));
362
363
		return scrollTo(line,offset);
364
	}
365
366
	/**
367
	 * Ensures that the specified line and offset is visible by scrolling
368
	 * the text area if necessary.
369
	 * @param line The line to scroll to
370
	 * @param offset The offset in the line to scroll to
371
	 * @return True if scrolling was actually performed, false if the
372
	 * line and offset was already visible
373
	 */
374
	public boolean scrollTo(int line, int offset)
375
	{
376
		// visibleLines == 0 before the component is realized
377
		// we can't do any proper scrolling then, so we have
378
		// this hack...
379
		if(visibleLines == 0)
380
		{
381
			setFirstLine(Math.max(0,line - electricScroll));
382
			return true;
383
		}
384
385
		int newFirstLine = firstLine;
386
		int newHorizontalOffset = horizontalOffset;
387
388
		if(line < firstLine + electricScroll)
389
		{
390
			newFirstLine = Math.max(0,line - electricScroll);
391
		}
392
		else if(line + electricScroll >= firstLine + visibleLines)
393
		{
394
			newFirstLine = (line - visibleLines) + electricScroll + 1;
395
			if(newFirstLine + visibleLines >= getLineCount())
396
				newFirstLine = getLineCount() - visibleLines;
397
			if(newFirstLine < 0)
398
				newFirstLine = 0;
399
		}
400
401
		int x = _offsetToX(line,offset);
402
		int width = painter.getFontMetrics().charWidth('w');
403
404
		if(x < 0)
405
		{
406
			newHorizontalOffset = Math.min(0,horizontalOffset
407
				- x + width + 5);
408
		}
409
		else if(x + width >= painter.getWidth())
410
		{
411
			newHorizontalOffset = horizontalOffset +
412
				(painter.getWidth() - x) - width - 5;
413
		}
414
415
		return setOrigin(newFirstLine,newHorizontalOffset);
416
	}
417
418
	/**
419
	 * Converts a line index to a y co-ordinate.
420
	 * @param line The line
421
	 */
422
	public int lineToY(int line)
423
	{
424
		FontMetrics fm = painter.getFontMetrics();
425
		return (line - firstLine) * fm.getHeight()
426
			- (fm.getLeading() + fm.getMaxDescent());
427
	}
428
429
	/**
430
	 * Converts a y co-ordinate to a line index.
431
	 * @param y The y co-ordinate
432
	 */
433
	public int yToLine(int y)
434
	{
435
		FontMetrics fm = painter.getFontMetrics();
436
		int height = fm.getHeight();
437
		return Math.max(0,Math.min(getLineCount() - 1,
438
			y / height + firstLine));
439
	}
440
441
	/**
442
	 * Converts an offset in a line into an x co-ordinate. This is a
443
	 * slow version that can be used any time.
444
	 * @param line The line
445
	 * @param offset The offset, from the start of the line
446
	 */
447
	public final int offsetToX(int line, int offset)
448
	{
449
		// don't use cached tokens
450
		painter.currentLineTokens = null;
451
		return _offsetToX(line,offset);
452
	}
453
454
	/**
455
	 * Converts an offset in a line into an x co-ordinate. This is a
456
	 * fast version that should only be used if no changes were made
457
	 * to the text since the last repaint.
458
	 * @param line The line
459
	 * @param offset The offset, from the start of the line
460
	 */
461
	public int _offsetToX(int line, int offset)
462
	{
463
		TokenMarker tokenMarker = getTokenMarker();
464
465
		/* Use painter's cached info for speed */
466
		FontMetrics fm = painter.getFontMetrics();
467
468
		getLineText(line,lineSegment);
469
470
		int segmentOffset = lineSegment.offset;
471
		int x = horizontalOffset;
472
473
		/* If syntax coloring is disabled, do simple translation */
474
		if(tokenMarker == null)
475
		{
476
			lineSegment.count = offset;
477
			return x + Utilities.getTabbedTextWidth(lineSegment,
478
				fm,x,painter,0);
479
		}
480
		/* If syntax coloring is enabled, we have to do this because
481
		 * tokens can vary in width */
482
		else
483
		{
484
			Token tokens;
485
			if(painter.currentLineIndex == line
486
				&& painter.currentLineTokens != null)
487
				tokens = painter.currentLineTokens;
488
			else
489
			{
490
				painter.currentLineIndex = line;
491
				tokens = painter.currentLineTokens
492
					= tokenMarker.markTokens(lineSegment,line);
493
			}
494
495
			Toolkit toolkit = painter.getToolkit();
496
			Font defaultFont = painter.getFont();
497
			SyntaxStyle[] styles = painter.getStyles();
498
499
			for(;;)
500
			{
501
				byte id = tokens.id;
502
				if(id == Token.END)
503
				{
504
					return x;
505
				}
506
507
				if(id == Token.NULL)
508
					fm = painter.getFontMetrics();
509
				else
510
					fm = styles[id].getFontMetrics(defaultFont);
511
512
				int length = tokens.length;
513
514
				if(offset + segmentOffset < lineSegment.offset + length)
515
				{
516
					lineSegment.count = offset - (lineSegment.offset - segmentOffset);
517
					return x + Utilities.getTabbedTextWidth(
518
						lineSegment,fm,x,painter,0);
519
				}
520
				else
521
				{
522
					lineSegment.count = length;
523
					x += Utilities.getTabbedTextWidth(
524
						lineSegment,fm,x,painter,0);
525
					lineSegment.offset += length;
526
				}
527
				tokens = tokens.next;
528
			}
529
		}
530
	}
531
532
	/**
533
	 * Converts an x co-ordinate to an offset within a line.
534
	 * @param line The line
535
	 * @param x The x co-ordinate
536
	 */
537
	public int xToOffset(int line, int x)
538
	{
539
		TokenMarker tokenMarker = getTokenMarker();
540
541
		/* Use painter's cached info for speed */
542
		FontMetrics fm = painter.getFontMetrics();
543
544
		getLineText(line,lineSegment);
545
546
		char[] segmentArray = lineSegment.array;
547
		int segmentOffset = lineSegment.offset;
548
		int segmentCount = lineSegment.count;
549
550
		int width = horizontalOffset;
551
552
		if(tokenMarker == null)
553
		{
554
			for(int i = 0; i < segmentCount; i++)
555
			{
556
				char c = segmentArray[i + segmentOffset];
557
				int charWidth;
558
				if(c == '\t')
559
					charWidth = (int)painter.nextTabStop(width,i)
560
						- width;
561
				else
562
					charWidth = fm.charWidth(c);
563
564
				if(painter.isBlockCaretEnabled())
565
				{
566
					if(x - charWidth <= width)
567
						return i;
568
				}
569
				else
570
				{
571
					if(x - charWidth / 2 <= width)
572
						return i;
573
				}
574
575
				width += charWidth;
576
			}
577
578
			return segmentCount;
579
		}
580
		else
581
		{
582
			Token tokens;
583
			if(painter.currentLineIndex == line && painter
584
				.currentLineTokens != null)
585
				tokens = painter.currentLineTokens;
586
			else
587
			{
588
				painter.currentLineIndex = line;
589
				tokens = painter.currentLineTokens
590
					= tokenMarker.markTokens(lineSegment,line);
591
			}
592
593
			int offset = 0;
594
			Toolkit toolkit = painter.getToolkit();
595
			Font defaultFont = painter.getFont();
596
			SyntaxStyle[] styles = painter.getStyles();
597
598
			for(;;)
599
			{
600
				byte id = tokens.id;
601
				if(id == Token.END)
602
					return offset;
603
604
				if(id == Token.NULL)
605
					fm = painter.getFontMetrics();
606
				else
607
					fm = styles[id].getFontMetrics(defaultFont);
608
609
				int length = tokens.length;
610
611
				for(int i = 0; i < length; i++)
612
				{
613
					char c = segmentArray[segmentOffset + offset + i];
614
					int charWidth;
615
					if(c == '\t')
616
						charWidth = (int)painter.nextTabStop(width,offset + i)
617
							- width;
618
					else
619
						charWidth = fm.charWidth(c);
620
621
					if(painter.isBlockCaretEnabled())
622
					{
623
						if(x - charWidth <= width)
624
							return offset + i;
625
					}
626
					else
627
					{
628
						if(x - charWidth / 2 <= width)
629
							return offset + i;
630
					}
631
632
					width += charWidth;
633
				}
634
635
				offset += length;
636
				tokens = tokens.next;
637
			}
638
		}
639
	}
640
641
	/**
642
	 * Converts a point to an offset, from the start of the text.
643
	 * @param x The x co-ordinate of the point
644
	 * @param y The y co-ordinate of the point
645
	 */
646
	public int xyToOffset(int x, int y)
647
	{
648
		int line = yToLine(y);
649
		int start = getLineStartOffset(line);
650
		return start + xToOffset(line,x);
651
	}
652
653
	/**
654
	 * Returns the document this text area is editing.
655
	 */
656
	public final SyntaxDocument getDocument()
657
	{
658
		return document;
659
	}
660
661
	/**
662
	 * Sets the document this text area is editing.
663
	 * @param document The document
664
	 */
665
	public void setDocument(SyntaxDocument document)
666
	{
667
		if(this.document == document)
668
			return;
669
		if(this.document != null)
670
			this.document.removeDocumentListener(documentHandler);
671
		this.document = document;
672
673
		document.addDocumentListener(documentHandler);
674
675
		select(0,0);
676
		updateScrollBars();
677
		painter.repaint();
678
	}
679
680
	/**
681
	 * Returns the document's token marker. Equivalent to calling
682
	 * <code>getDocument().getTokenMarker()</code>.
683
	 */
684
	public final TokenMarker getTokenMarker()
685
	{
686
		return document.getTokenMarker();
687
	}
688
689
	/**
690
	 * Sets the document's token marker. Equivalent to caling
691
	 * <code>getDocument().setTokenMarker()</code>.
692
	 * @param tokenMarker The token marker
693
	 */
694
	public final void setTokenMarker(TokenMarker tokenMarker)
695
	{
696
		document.setTokenMarker(tokenMarker);
697
	}
698
699
	/**
700
	 * Returns the length of the document. Equivalent to calling
701
	 * <code>getDocument().getLength()</code>.
702
	 */
703
	public final int getDocumentLength()
704
	{
705
		return document.getLength();
706
	}
707
708
	/**
709
	 * Returns the number of lines in the document.
710
	 */
711
	public final int getLineCount()
712
	{
713
		return document.getDefaultRootElement().getElementCount();
714
	}
715
716
	/**
717
	 * Returns the line containing the specified offset.
718
	 * @param offset The offset
719
	 */
720
	public final int getLineOfOffset(int offset)
721
	{
722
		return document.getDefaultRootElement().getElementIndex(offset);
723
	}
724
725
	/**
726
	 * Returns the start offset of the specified line.
727
	 * @param line The line
728
	 * @return The start offset of the specified line, or -1 if the line is
729
	 * invalid
730
	 */
731
	public int getLineStartOffset(int line)
732
	{
733
		Element lineElement = document.getDefaultRootElement()
734
			.getElement(line);
735
		if(lineElement == null)
736
			return -1;
737
		else
738
			return lineElement.getStartOffset();
739
	}
740
741
	/**
742
	 * Returns the end offset of the specified line.
743
	 * @param line The line
744
	 * @return The end offset of the specified line, or -1 if the line is
745
	 * invalid.
746
	 */
747
	public int getLineEndOffset(int line)
748
	{
749
		Element lineElement = document.getDefaultRootElement()
750
			.getElement(line);
751
		if(lineElement == null)
752
			return -1;
753
		else
754
			return lineElement.getEndOffset();
755
	}
756
757
	/**
758
	 * Returns the length of the specified line.
759
	 * @param line The line
760
	 */
761
	public int getLineLength(int line)
762
	{
763
		Element lineElement = document.getDefaultRootElement()
764
			.getElement(line);
765
		if(lineElement == null)
766
			return -1;
767
		else
768
			return lineElement.getEndOffset()
769
				- lineElement.getStartOffset() - 1;
770
	}
771
772
	/**
773
	 * Returns the entire text of this text area.
774
	 */
775
	public String getText()
776
	{
777
		try
778
		{
779
			return document.getText(0,document.getLength());
780
		}
781
		catch(BadLocationException bl)
782
		{
783
			bl.printStackTrace();
784
			return null;
785
		}
786
	}
787
788
	/**
789
	 * Sets the entire text of this text area.
790
	 */
791
	public void setText(String text)
792
	{
793
		try
794
		{
795
			document.beginCompoundEdit();
796
			document.remove(0,document.getLength());
797
			document.insertString(0,text,null);
798
		}
799
		catch(BadLocationException bl)
800
		{
801
			bl.printStackTrace();
802
		}
803
		finally
804
		{
805
			document.endCompoundEdit();
806
		}
807
	}
808
809
	/**
810
	 * Returns the specified substring of the document.
811
	 * @param start The start offset
812
	 * @param len The length of the substring
813
	 * @return The substring, or null if the offsets are invalid
814
	 */
815
	public final String getText(int start, int len)
816
	{
817
		try
818
		{
819
			return document.getText(start,len);
820
		}
821
		catch(BadLocationException bl)
822
		{
823
			bl.printStackTrace();
824
			return null;
825
		}
826
	}
827
828
	/**
829
	 * Copies the specified substring of the document into a segment.
830
	 * If the offsets are invalid, the segment will contain a null string.
831
	 * @param start The start offset
832
	 * @param len The length of the substring
833
	 * @param segment The segment
834
	 */
835
	public final void getText(int start, int len, Segment segment)
836
	{
837
		try
838
		{
839
			document.getText(start,len,segment);
840
		}
841
		catch(BadLocationException bl)
842
		{
843
			bl.printStackTrace();
844
			segment.offset = segment.count = 0;
845
		}
846
	}
847
848
	/**
849
	 * Returns the text on the specified line.
850
	 * @param lineIndex The line
851
	 * @return The text, or null if the line is invalid
852
	 */
853
	public final String getLineText(int lineIndex)
854
	{
855
		int start = getLineStartOffset(lineIndex);
856
		return getText(start,getLineEndOffset(lineIndex) - start - 1);
857
	}
858
859
	/**
860
	 * Copies the text on the specified line into a segment. If the line
861
	 * is invalid, the segment will contain a null string.
862
	 * @param lineIndex The line
863
	 */
864
	public final void getLineText(int lineIndex, Segment segment)
865
	{
866
		int start = getLineStartOffset(lineIndex);
867
		getText(start,getLineEndOffset(lineIndex) - start - 1,segment);
868
	}
869
870
	/**
871
	 * Returns the selection start offset.
872
	 */
873
	public final int getSelectionStart()
874
	{
875
		return selectionStart;
876
	}
877
878
	/**
879
	 * Returns the offset where the selection starts on the specified
880
	 * line.
881
	 */
882
	public int getSelectionStart(int line)
883
	{
884
		if(line == selectionStartLine)
885
			return selectionStart;
886
		else if(rectSelect)
887
		{
888
			Element map = document.getDefaultRootElement();
889
			int start = selectionStart - map.getElement(selectionStartLine)
890
				.getStartOffset();
891
892
			Element lineElement = map.getElement(line);
893
			int lineStart = lineElement.getStartOffset();
894
			int lineEnd = lineElement.getEndOffset() - 1;
895
			return Math.min(lineEnd,lineStart + start);
896
		}
897
		else
898
			return getLineStartOffset(line);
899
	}
900
901
	/**
902
	 * Returns the selection start line.
903
	 */
904
	public final int getSelectionStartLine()
905
	{
906
		return selectionStartLine;
907
	}
908
909
	/**
910
	 * Sets the selection start. The new selection will be the new
911
	 * selection start and the old selection end.
912
	 * @param selectionStart The selection start
913
	 * @see #select(int,int)
914
	 */
915
	public final void setSelectionStart(int selectionStart)
916
	{
917
		select(selectionStart,selectionEnd);
918
	}
919
920
	/**
921
	 * Returns the selection end offset.
922
	 */
923
	public final int getSelectionEnd()
924
	{
925
		return selectionEnd;
926
	}
927
928
	/**
929
	 * Returns the offset where the selection ends on the specified
930
	 * line.
931
	 */
932
	public int getSelectionEnd(int line)
933
	{
934
		if(line == selectionEndLine)
935
			return selectionEnd;
936
		else if(rectSelect)
937
		{
938
			Element map = document.getDefaultRootElement();
939
			int end = selectionEnd - map.getElement(selectionEndLine)
940
				.getStartOffset();
941
942
			Element lineElement = map.getElement(line);
943
			int lineStart = lineElement.getStartOffset();
944
			int lineEnd = lineElement.getEndOffset() - 1;
945
			return Math.min(lineEnd,lineStart + end);
946
		}
947
		else
948
			return getLineEndOffset(line) - 1;
949
	}
950
951
	/**
952
	 * Returns the selection end line.
953
	 */
954
	public final int getSelectionEndLine()
955
	{
956
		return selectionEndLine;
957
	}
958
959
	/**
960
	 * Sets the selection end. The new selection will be the old
961
	 * selection start and the bew selection end.
962
	 * @param selectionEnd The selection end
963
	 * @see #select(int,int)
964
	 */
965
	public final void setSelectionEnd(int selectionEnd)
966
	{
967
		select(selectionStart,selectionEnd);
968
	}
969
970
	/**
971
	 * Returns the caret position. This will either be the selection
972
	 * start or the selection end, depending on which direction the
973
	 * selection was made in.
974
	 */
975
	public final int getCaretPosition()
976
	{
977
		return (biasLeft ? selectionStart : selectionEnd);
978
	}
979
980
	/**
981
	 * Returns the caret line.
982
	 */
983
	public final int getCaretLine()
984
	{
985
		return (biasLeft ? selectionStartLine : selectionEndLine);
986
	}
987
988
	/**
989
	 * Returns the mark position. This will be the opposite selection
990
	 * bound to the caret position.
991
	 * @see #getCaretPosition()
992
	 */
993
	public final int getMarkPosition()
994
	{
995
		return (biasLeft ? selectionEnd : selectionStart);
996
	}
997
998
	/**
999
	 * Returns the mark line.
1000
	 */
1001
	public final int getMarkLine()
1002
	{
1003
		return (biasLeft ? selectionEndLine : selectionStartLine);
1004
	}
1005
1006
	/**
1007
	 * Sets the caret position. The new selection will consist of the
1008
	 * caret position only (hence no text will be selected)
1009
	 * @param caret The caret position
1010
	 * @see #select(int,int)
1011
	 */
1012
	public final void setCaretPosition(int caret)
1013
	{
1014
		select(caret,caret);
1015
	}
1016
1017
	/**
1018
	 * Selects all text in the document.
1019
	 */
1020
	public final void selectAll()
1021
	{
1022
		select(0,getDocumentLength());
1023
	}
1024
1025
	/**
1026
	 * Moves the mark to the caret position.
1027
	 */
1028
	public final void selectNone()
1029
	{
1030
		select(getCaretPosition(),getCaretPosition());
1031
	}
1032
1033
	/**
1034
	 * Selects from the start offset to the end offset. This is the
1035
	 * general selection method used by all other selecting methods.
1036
	 * The caret position will be start if start &lt; end, and end
1037
	 * if end &gt; start.
1038
	 * @param start The start offset
1039
	 * @param end The end offset
1040
	 */
1041
	public void select(int start, int end)
1042
	{
1043
		int newStart, newEnd;
1044
		boolean newBias;
1045
		if(start <= end)
1046
		{
1047
			newStart = start;
1048
			newEnd = end;
1049
			newBias = false;
1050
		}
1051
		else
1052
		{
1053
			newStart = end;
1054
			newEnd = start;
1055
			newBias = true;
1056
		}
1057
1058
		if(newStart < 0 || newEnd > getDocumentLength())
1059
		{
1060
			throw new IllegalArgumentException("Bounds out of"
1061
				+ " range: " + newStart + "," +
1062
				newEnd);
1063
		}
1064
1065
		// If the new position is the same as the old, we don't
1066
		// do all this crap, however we still do the stuff at
1067
		// the end (clearing magic position, scrolling)
1068
		if(newStart != selectionStart || newEnd != selectionEnd
1069
			|| newBias != biasLeft)
1070
		{
1071
			int newStartLine = getLineOfOffset(newStart);
1072
			int newEndLine = getLineOfOffset(newEnd);
1073
1074
			if(painter.isBracketHighlightEnabled())
1075
			{
1076
				if(bracketLine != -1)
1077
					painter.invalidateLine(bracketLine);
1078
				updateBracketHighlight(end);
1079
				if(bracketLine != -1)
1080
					painter.invalidateLine(bracketLine);
1081
			}
1082
1083
			painter.invalidateLineRange(selectionStartLine,selectionEndLine);
1084
			painter.invalidateLineRange(newStartLine,newEndLine);
1085
1086
			document.addUndoableEdit(new CaretUndo(
1087
				selectionStart,selectionEnd));
1088
1089
			selectionStart = newStart;
1090
			selectionEnd = newEnd;
1091
			selectionStartLine = newStartLine;
1092
			selectionEndLine = newEndLine;
1093
			biasLeft = newBias;
1094
1095
			fireCaretEvent();
1096
		}
1097
1098
		// When the user is typing, etc, we don't want the caret
1099
		// to blink
1100
		blink = true;
1101
		caretTimer.restart();
1102
1103
		// Disable rectangle select if selection start = selection end
1104
		if(selectionStart == selectionEnd)
1105
			rectSelect = false;
1106
1107
		// Clear the `magic' caret position used by up/down
1108
		magicCaret = -1;
1109
1110
		scrollToCaret();
1111
	}
1112
1113
	/**
1114
	 * Returns the selected text, or null if no selection is active.
1115
	 */
1116
	public final String getSelectedText()
1117
	{
1118
		if(selectionStart == selectionEnd)
1119
			return null;
1120
1121
		if(rectSelect)
1122
		{
1123
			// Return each row of the selection on a new line
1124
1125
			Element map = document.getDefaultRootElement();
1126
1127
			int start = selectionStart - map.getElement(selectionStartLine)
1128
				.getStartOffset();
1129
			int end = selectionEnd - map.getElement(selectionEndLine)
1130
				.getStartOffset();
1131
1132
			// Certain rectangles satisfy this condition...
1133
			if(end < start)
1134
			{
1135
				int tmp = end;
1136
				end = start;
1137
				start = tmp;
1138
			}
1139
1140
			StringBuffer buf = new StringBuffer();
1141
			Segment seg = new Segment();
1142
1143
			for(int i = selectionStartLine; i <= selectionEndLine; i++)
1144
			{
1145
				Element lineElement = map.getElement(i);
1146
				int lineStart = lineElement.getStartOffset();
1147
				int lineEnd = lineElement.getEndOffset() - 1;
1148
				int lineLen = lineEnd - lineStart;
1149
1150
				lineStart = Math.min(lineStart + start,lineEnd);
1151
				lineLen = Math.min(end - start,lineEnd - lineStart);
1152
1153
				getText(lineStart,lineLen,seg);
1154
				buf.append(seg.array,seg.offset,seg.count);
1155
1156
				if(i != selectionEndLine)
1157
					buf.append('\n');
1158
			}
1159
1160
			return buf.toString();
1161
		}
1162
		else
1163
		{
1164
			return getText(selectionStart,
1165
				selectionEnd - selectionStart);
1166
		}
1167
	}
1168
1169
	/**
1170
	 * Replaces the selection with the specified text.
1171
	 * @param selectedText The replacement text for the selection
1172
	 */
1173
	public void setSelectedText(String selectedText)
1174
	{
1175
		if(!editable)
1176
		{
1177
			throw new InternalError("Text component"
1178
				+ " read only");
1179
		}
1180
1181
		document.beginCompoundEdit();
1182
1183
		try
1184
		{
1185
			if(rectSelect)
1186
			{
1187
				Element map = document.getDefaultRootElement();
1188
1189
				int start = selectionStart - map.getElement(selectionStartLine)
1190
					.getStartOffset();
1191
				int end = selectionEnd - map.getElement(selectionEndLine)
1192
					.getStartOffset();
1193
1194
				// Certain rectangles satisfy this condition...
1195
				if(end < start)
1196
				{
1197
					int tmp = end;
1198
					end = start;
1199
					start = tmp;
1200
				}
1201
1202
				int lastNewline = 0;
1203
				int currNewline = 0;
1204
1205
				for(int i = selectionStartLine; i <= selectionEndLine; i++)
1206
				{
1207
					Element lineElement = map.getElement(i);
1208
					int lineStart = lineElement.getStartOffset();
1209
					int lineEnd = lineElement.getEndOffset() - 1;
1210
					int rectStart = Math.min(lineEnd,lineStart + start);
1211
1212
					document.remove(rectStart,Math.min(lineEnd - rectStart,
1213
						end - start));
1214
1215
					if(selectedText == null)
1216
						continue;
1217
1218
					currNewline = selectedText.indexOf('\n',lastNewline);
1219
					if(currNewline == -1)
1220
						currNewline = selectedText.length();
1221
1222
					document.insertString(rectStart,selectedText
1223
						.substring(lastNewline,currNewline),null);
1224
1225
					lastNewline = Math.min(selectedText.length(),
1226
						currNewline + 1);
1227
				}
1228
1229
				if(selectedText != null &&
1230
					currNewline != selectedText.length())
1231
				{
1232
					int offset = map.getElement(selectionEndLine)
1233
						.getEndOffset() - 1;
1234
					document.insertString(offset,"\n",null);
1235
					document.insertString(offset + 1,selectedText
1236
						.substring(currNewline + 1),null);
1237
				}
1238
			}
1239
			else
1240
			{
1241
				document.remove(selectionStart,
1242
					selectionEnd - selectionStart);
1243
				if(selectedText != null)
1244
				{
1245
					document.insertString(selectionStart,
1246
						selectedText,null);
1247
				}
1248
			}
1249
		}
1250
		catch(BadLocationException bl)
1251
		{
1252
			bl.printStackTrace();
1253
			throw new InternalError("Cannot replace"
1254
				+ " selection");
1255
		}
1256
		// No matter what happends... stops us from leaving document
1257
		// in a bad state
1258
		finally
1259
		{
1260
			document.endCompoundEdit();
1261
		}
1262
1263
		setCaretPosition(selectionEnd);
1264
	}
1265
1266
	/**
1267
	 * Returns true if this text area is editable, false otherwise.
1268
	 */
1269
	public final boolean isEditable()
1270
	{
1271
		return editable;
1272
	}
1273
1274
	/**
1275
	 * Sets if this component is editable.
1276
	 * @param editable True if this text area should be editable,
1277
	 * false otherwise
1278
	 */
1279
	public final void setEditable(boolean editable)
1280
	{
1281
		this.editable = editable;
1282
	}
1283
1284
	/**
1285
	 * Returns the right click popup menu.
1286
	 */
1287
	public final JPopupMenu getRightClickPopup()
1288
	{
1289
		return popup;
1290
	}
1291
1292
	/**
1293
	 * Sets the right click popup menu.
1294
	 * @param popup The popup
1295
	 */
1296
	public final void setRightClickPopup(JPopupMenu popup)
1297
	{
1298
		this.popup = popup;
1299
	}
1300
1301
	/**
1302
	 * Returns the `magic' caret position. This can be used to preserve
1303
	 * the column position when moving up and down lines.
1304
	 */
1305
	public final int getMagicCaretPosition()
1306
	{
1307
		return magicCaret;
1308
	}
1309
1310
	/**
1311
	 * Sets the `magic' caret position. This can be used to preserve
1312
	 * the column position when moving up and down lines.
1313
	 * @param magicCaret The magic caret position
1314
	 */
1315
	public final void setMagicCaretPosition(int magicCaret)
1316
	{
1317
		this.magicCaret = magicCaret;
1318
	}
1319
1320
	/**
1321
	 * Similar to <code>setSelectedText()</code>, but overstrikes the
1322
	 * appropriate number of characters if overwrite mode is enabled.
1323
	 * @param str The string
1324
	 * @see #setSelectedText(String)
1325
	 * @see #isOverwriteEnabled()
1326
	 */
1327
	public void overwriteSetSelectedText(String str)
1328
	{
1329
		// Don't overstrike if there is a selection
1330
		if(!overwrite || selectionStart != selectionEnd)
1331
		{
1332
			setSelectedText(str);
1333
			return;
1334
		}
1335
1336
		// Don't overstrike if we're on the end of
1337
		// the line
1338
		int caret = getCaretPosition();
1339
		int caretLineEnd = getLineEndOffset(getCaretLine());
1340
		if(caretLineEnd - caret <= str.length())
1341
		{
1342
			setSelectedText(str);
1343
			return;
1344
		}
1345
1346
		document.beginCompoundEdit();
1347
1348
		try
1349
		{
1350
			document.remove(caret,str.length());
1351
			document.insertString(caret,str,null);
1352
		}
1353
		catch(BadLocationException bl)
1354
		{
1355
			bl.printStackTrace();
1356
		}
1357
		finally
1358
		{
1359
			document.endCompoundEdit();
1360
		}
1361
	}
1362
1363
	/**
1364
	 * Returns true if overwrite mode is enabled, false otherwise.
1365
	 */
1366
	public final boolean isOverwriteEnabled()
1367
	{
1368
		return overwrite;
1369
	}
1370
1371
	/**
1372
	 * Sets if overwrite mode should be enabled.
1373
	 * @param overwrite True if overwrite mode should be enabled,
1374
	 * false otherwise.
1375
	 */
1376
	public final void setOverwriteEnabled(boolean overwrite)
1377
	{
1378
		this.overwrite = overwrite;
1379
		painter.invalidateSelectedLines();
1380
	}
1381
1382
	/**
1383
	 * Returns true if the selection is rectangular, false otherwise.
1384
	 */
1385
	public final boolean isSelectionRectangular()
1386
	{
1387
		return rectSelect;
1388
	}
1389
1390
	/**
1391
	 * Sets if the selection should be rectangular.
1392
	 * @param overwrite True if the selection should be rectangular,
1393
	 * false otherwise.
1394
	 */
1395
	public final void setSelectionRectangular(boolean rectSelect)
1396
	{
1397
		this.rectSelect = rectSelect;
1398
		painter.invalidateSelectedLines();
1399
	}
1400
1401
	/**
1402
	 * Returns the position of the highlighted bracket (the bracket
1403
	 * matching the one before the caret)
1404
	 */
1405
	public final int getBracketPosition()
1406
	{
1407
		return bracketPosition;
1408
	}
1409
1410
	/**
1411
	 * Returns the line of the highlighted bracket (the bracket
1412
	 * matching the one before the caret)
1413
	 */
1414
	public final int getBracketLine()
1415
	{
1416
		return bracketLine;
1417
	}
1418
1419
	/**
1420
	 * Adds a caret change listener to this text area.
1421
	 * @param listener The listener
1422
	 */
1423
	public final void addCaretListener(CaretListener listener)
1424
	{
1425
		listenerList.add(CaretListener.class,listener);
1426
	}
1427
1428
	/**
1429
	 * Removes a caret change listener from this text area.
1430
	 * @param listener The listener
1431
	 */
1432
	public final void removeCaretListener(CaretListener listener)
1433
	{
1434
		listenerList.remove(CaretListener.class,listener);
1435
	}
1436
1437
	/**
1438
	 * Deletes the selected text from the text area and places it
1439
	 * into the clipboard.
1440
	 */
1441
	public void cut()
1442
	{
1443
		if(editable)
1444
		{
1445
			copy();
1446
			setSelectedText("");
1447
		}
1448
	}
1449
1450
	/**
1451
	 * Places the selected text into the clipboard.
1452
	 */
1453
	public void copy()
1454
	{
1455
		if(selectionStart != selectionEnd)
1456
		{
1457
			Clipboard clipboard = getToolkit().getSystemClipboard();
1458
1459
			String selection = getSelectedText();
1460
1461
			int repeatCount = inputHandler.getRepeatCount();
1462
			StringBuffer buf = new StringBuffer();
1463
			for(int i = 0; i < repeatCount; i++)
1464
				buf.append(selection);
1465
1466
			clipboard.setContents(new StringSelection(buf.toString()),null);
1467
		}
1468
	}
1469
1470
	/**
1471
	 * Inserts the clipboard contents into the text.
1472
	 */
1473
	public void paste()
1474
	{
1475
		if(editable)
1476
		{
1477
			Clipboard clipboard = getToolkit().getSystemClipboard();
1478
			try
1479
			{
1480
				// The MacOS MRJ doesn't convert \r to \n,
1481
				// so do it here
1482
				String selection = ((String)clipboard
1483
					.getContents(this).getTransferData(
1484
					DataFlavor.stringFlavor))
1485
					.replace('\r','\n');
1486
1487
				int repeatCount = inputHandler.getRepeatCount();
1488
				StringBuffer buf = new StringBuffer();
1489
				for(int i = 0; i < repeatCount; i++)
1490
					buf.append(selection);
1491
				selection = buf.toString();
1492
				setSelectedText(selection);
1493
			}
1494
			catch(Exception e)
1495
			{
1496
				getToolkit().beep();
1497
				System.err.println("Clipboard does not"
1498
					+ " contain a string");
1499
			}
1500
		}
1501
	}
1502
1503
	/**
1504
	 * Called by the AWT when this component is removed from it's parent.
1505
	 * This stops clears the currently focused component.
1506
	 */
1507
	public void removeNotify()
1508
	{
1509
		super.removeNotify();
1510
		if(focusedComponent == this)
1511
			focusedComponent = null;
1512
	}
1513
1514
	/**
1515
	 * Forwards key events directly to the input handler.
1516
	 * This is slightly faster than using a KeyListener
1517
	 * because some Swing overhead is avoided.
1518
	 */
1519
	public void processKeyEvent(KeyEvent evt)
1520
	{
1521
		if(inputHandler == null)
1522
			return;
1523
		switch(evt.getID())
1524
		{
1525
		case KeyEvent.KEY_TYPED:
1526
			inputHandler.keyTyped(evt);
1527
			break;
1528
		case KeyEvent.KEY_PRESSED:
1529
			inputHandler.keyPressed(evt);
1530
			break;
1531
		case KeyEvent.KEY_RELEASED:
1532
			inputHandler.keyReleased(evt);
1533
			break;
1534
		}
1535
	}
1536
1537
	// protected members
1538
	protected static String CENTER = "center";
1539
	protected static String RIGHT = "right";
1540
	protected static String BOTTOM = "bottom";
1541
1542
	protected static JEditTextArea focusedComponent;
1543
	protected static Timer caretTimer;
1544
	
1545
	protected TextAreaPainter painter;
1546
1547
	protected JPopupMenu popup;
1548
1549
	protected EventListenerList listenerList;
1550
	protected MutableCaretEvent caretEvent;
1551
1552
	protected boolean caretBlinks;
1553
	protected boolean caretVisible;
1554
	protected boolean blink;
1555
1556
	protected boolean editable;
1557
1558
	protected int firstLine;
1559
	protected int visibleLines;
1560
	protected int electricScroll;
1561
1562
	protected int horizontalOffset;
1563
	
1564
	protected JScrollBar vertical;
1565
	protected JScrollBar horizontal;
1566
	protected boolean scrollBarsInitialized;
1567
1568
	protected InputHandler inputHandler;
1569
	protected SyntaxDocument document;
1570
	protected DocumentHandler documentHandler;
1571
1572
	protected Segment lineSegment;
1573
1574
	protected int selectionStart;
1575
	protected int selectionStartLine;
1576
	protected int selectionEnd;
1577
	protected int selectionEndLine;
1578
	protected boolean biasLeft;
1579
1580
	protected int bracketPosition;
1581
	protected int bracketLine;
1582
1583
	protected int magicCaret;
1584
	protected boolean overwrite;
1585
	protected boolean rectSelect;
1586
1587
	protected void fireCaretEvent()
1588
	{
1589
		Object[] listeners = listenerList.getListenerList();
1590
		for(int i = listeners.length - 2; i >= 0; i--)
1591
		{
1592
			if(listeners[i] == CaretListener.class)
1593
			{
1594
				((CaretListener)listeners[i+1]).caretUpdate(caretEvent);
1595
			}
1596
		}
1597
	}
1598
1599
	protected void updateBracketHighlight(int newCaretPosition)
1600
	{
1601
		if(newCaretPosition == 0)
1602
		{
1603
			bracketPosition = bracketLine = -1;
1604
			return;
1605
		}
1606
1607
		try
1608
		{
1609
			int offset = TextUtilities.findMatchingBracket(
1610
				document,newCaretPosition - 1);
1611
			if(offset != -1)
1612
			{
1613
				bracketLine = getLineOfOffset(offset);
1614
				bracketPosition = offset - getLineStartOffset(bracketLine);
1615
				return;
1616
			}
1617
		}
1618
		catch(BadLocationException bl)
1619
		{
1620
			bl.printStackTrace();
1621
		}
1622
1623
		bracketLine = bracketPosition = -1;
1624
	}
1625
1626
	protected void documentChanged(DocumentEvent evt)
1627
	{
1628
		DocumentEvent.ElementChange ch = evt.getChange(
1629
			document.getDefaultRootElement());
1630
1631
		int count;
1632
		if(ch == null)
1633
			count = 0;
1634
		else
1635
			count = ch.getChildrenAdded().length -
1636
				ch.getChildrenRemoved().length;
1637
1638
		int line = getLineOfOffset(evt.getOffset());
1639
		if(count == 0)
1640
		{
1641
			painter.invalidateLine(line);
1642
		}
1643
		// do magic stuff
1644
		else if(line < firstLine)
1645
		{
1646
			setFirstLine(firstLine + count);
1647
		}
1648
		// end of magic stuff
1649
		else
1650
		{
1651
			painter.invalidateLineRange(line,firstLine + visibleLines);
1652
			updateScrollBars();
1653
		}
1654
	}
1655
1656
	class ScrollLayout implements LayoutManager
1657
	{
1658
		public void addLayoutComponent(String name, Component comp)
1659
		{
1660
			if(name.equals(CENTER))
1661
				center = comp;
1662
			else if(name.equals(RIGHT))
1663
				right = comp;
1664
			else if(name.equals(BOTTOM))
1665
				bottom = comp;
1666
			else if(name.equals(LEFT_OF_SCROLLBAR))
1667
				leftOfScrollBar.addElement(comp);
1668
		}
1669
1670
		public void removeLayoutComponent(Component comp)
1671
		{
1672
			if(center == comp)
1673
				center = null;
1674
			if(right == comp)
1675
				right = null;
1676
			if(bottom == comp)
1677
				bottom = null;
1678
			else
1679
				leftOfScrollBar.removeElement(comp);
1680
		}
1681
1682
		public Dimension preferredLayoutSize(Container parent)
1683
		{
1684
			Dimension dim = new Dimension();
1685
			Insets insets = getInsets();
1686
			dim.width = insets.left + insets.right;
1687
			dim.height = insets.top + insets.bottom;
1688
1689
			Dimension centerPref = center.getPreferredSize();
1690
			dim.width += centerPref.width;
1691
			dim.height += centerPref.height;
1692
			Dimension rightPref = right.getPreferredSize();
1693
			dim.width += rightPref.width;
1694
			Dimension bottomPref = bottom.getPreferredSize();
1695
			dim.height += bottomPref.height;
1696
1697
			return dim;
1698
		}
1699
1700
		public Dimension minimumLayoutSize(Container parent)
1701
		{
1702
			Dimension dim = new Dimension();
1703
			Insets insets = getInsets();
1704
			dim.width = insets.left + insets.right;
1705
			dim.height = insets.top + insets.bottom;
1706
1707
			Dimension centerPref = center.getMinimumSize();
1708
			dim.width += centerPref.width; 
1709
			dim.height += centerPref.height;
1710
			Dimension rightPref = right.getMinimumSize();
1711
			dim.width += rightPref.width;
1712
			Dimension bottomPref = bottom.getMinimumSize();
1713
			dim.height += bottomPref.height;
1714
1715
			return dim;
1716
		}
1717
1718
		public void layoutContainer(Container parent)
1719
		{
1720
			Dimension size = parent.getSize();
1721
			Insets insets = parent.getInsets();
1722
			int itop = insets.top;
1723
			int ileft = insets.left;
1724
			int ibottom = insets.bottom;
1725
			int iright = insets.right;
1726
1727
			int rightWidth = right.getPreferredSize().width;
1728
			int bottomHeight = bottom.getPreferredSize().height;
1729
			int centerWidth = size.width - rightWidth - ileft - iright;
1730
			int centerHeight = size.height - bottomHeight - itop - ibottom;
1731
1732
			center.setBounds(
1733
				ileft,
1734
				itop,
1735
				centerWidth,
1736
				centerHeight);
1737
1738
			right.setBounds(
1739
				ileft + centerWidth,
1740
				itop,
1741
				rightWidth,
1742
				centerHeight);
1743
1744
			// Lay out all status components, in order
1745
			Enumeration status = leftOfScrollBar.elements();
1746
			while(status.hasMoreElements())
1747
			{
1748
				Component comp = (Component)status.nextElement();
1749
				Dimension dim = comp.getPreferredSize();
1750
				comp.setBounds(ileft,
1751
					itop + centerHeight,
1752
					dim.width,
1753
					bottomHeight);
1754
				ileft += dim.width;
1755
			}
1756
1757
			bottom.setBounds(
1758
				ileft,
1759
				itop + centerHeight,
1760
				size.width - rightWidth - ileft - iright,
1761
				bottomHeight);
1762
		}
1763
1764
		// private members
1765
		private Component center;
1766
		private Component right;
1767
		private Component bottom;
1768
		private Vector leftOfScrollBar = new Vector();
1769
	}
1770
1771
	static class CaretBlinker implements ActionListener
1772
	{
1773
		public void actionPerformed(ActionEvent evt)
1774
		{
1775
			if(focusedComponent != null
1776
				&& focusedComponent.hasFocus())
1777
				focusedComponent.blinkCaret();
1778
		}
1779
	}
1780
1781
	class MutableCaretEvent extends CaretEvent
1782
	{
1783
		MutableCaretEvent()
1784
		{
1785
			super(JEditTextArea.this);
1786
		}
1787
1788
		public int getDot()
1789
		{
1790
			return getCaretPosition();
1791
		}
1792
1793
		public int getMark()
1794
		{
1795
			return getMarkPosition();
1796
		}
1797
	}
1798
1799
	class AdjustHandler implements AdjustmentListener
1800
	{
1801
		public void adjustmentValueChanged(final AdjustmentEvent evt)
1802
		{
1803
			if(!scrollBarsInitialized)
1804
				return;
1805
1806
			// If this is not done, mousePressed events accumilate
1807
			// and the result is that scrolling doesn't stop after
1808
			// the mouse is released
1809
			SwingUtilities.invokeLater(new Runnable() {
1810
				public void run()
1811
				{
1812
					if(evt.getAdjustable() == vertical)
1813
						setFirstLine(vertical.getValue());
1814
					else
1815
						setHorizontalOffset(-horizontal.getValue());
1816
				}
1817
			});
1818
		}
1819
	}
1820
1821
	class ComponentHandler extends ComponentAdapter
1822
	{
1823
		public void componentResized(ComponentEvent evt)
1824
		{
1825
			recalculateVisibleLines();
1826
			scrollBarsInitialized = true;
1827
		}
1828
	}
1829
1830
	class DocumentHandler implements DocumentListener
1831
	{
1832
		public void insertUpdate(DocumentEvent evt)
1833
		{
1834
			documentChanged(evt);
1835
1836
			int offset = evt.getOffset();
1837
			int length = evt.getLength();
1838
1839
			int newStart;
1840
			int newEnd;
1841
1842
			if(selectionStart > offset || (selectionStart 
1843
				== selectionEnd && selectionStart == offset))
1844
				newStart = selectionStart + length;
1845
			else
1846
				newStart = selectionStart;
1847
1848
			if(selectionEnd >= offset)
1849
				newEnd = selectionEnd + length;
1850
			else
1851
				newEnd = selectionEnd;
1852
1853
			select(newStart,newEnd);
1854
		}
1855
	
1856
		public void removeUpdate(DocumentEvent evt)
1857
		{
1858
			documentChanged(evt);
1859
1860
			int offset = evt.getOffset();
1861
			int length = evt.getLength();
1862
1863
			int newStart;
1864
			int newEnd;
1865
1866
			if(selectionStart > offset)
1867
			{
1868
				if(selectionStart > offset + length)
1869
					newStart = selectionStart - length;
1870
				else
1871
					newStart = offset;
1872
			}
1873
			else
1874
				newStart = selectionStart;
1875
1876
			if(selectionEnd > offset)
1877
			{
1878
				if(selectionEnd > offset + length)
1879
					newEnd = selectionEnd - length;
1880
				else
1881
					newEnd = offset;
1882
			}
1883
			else
1884
				newEnd = selectionEnd;
1885
1886
			select(newStart,newEnd);
1887
		}
1888
1889
		public void changedUpdate(DocumentEvent evt)
1890
		{
1891
		}
1892
	}
1893
1894
	class DragHandler implements MouseMotionListener
1895
	{
1896
		public void mouseDragged(MouseEvent evt)
1897
		{
1898
			if(popup != null && popup.isVisible())
1899
				return;
1900
1901
			setSelectionRectangular((evt.getModifiers()
1902
				& InputEvent.CTRL_MASK) != 0);
1903
			select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY()));
1904
		}
1905
1906
		public void mouseMoved(MouseEvent evt) {}
1907
	}
1908
1909
	class FocusHandler implements FocusListener
1910
	{
1911
		public void focusGained(FocusEvent evt)
1912
		{
1913
			setCaretVisible(true);
1914
			focusedComponent = JEditTextArea.this;
1915
		}
1916
1917
		public void focusLost(FocusEvent evt)
1918
		{
1919
			setCaretVisible(false);
1920
			focusedComponent = null;
1921
		}
1922
	}
1923
1924
	class MouseHandler extends MouseAdapter
1925
	{
1926
		public void mousePressed(MouseEvent evt)
1927
		{
1928
			requestFocus();
1929
1930
			// Focus events not fired sometimes?
1931
			setCaretVisible(true);
1932
			focusedComponent = JEditTextArea.this;
1933
1934
			if((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0
1935
				&& popup != null)
1936
			{
1937
				popup.show(painter,evt.getX(),evt.getY());
1938
				return;
1939
			}
1940
1941
			int line = yToLine(evt.getY());
1942
			int offset = xToOffset(line,evt.getX());
1943
			int dot = getLineStartOffset(line) + offset;
1944
1945
			switch(evt.getClickCount())
1946
			{
1947
			case 1:
1948
				doSingleClick(evt,line,offset,dot);
1949
				break;
1950
			case 2:
1951
				// It uses the bracket matching stuff, so
1952
				// it can throw a BLE
1953
				try
1954
				{
1955
					doDoubleClick(evt,line,offset,dot);
1956
				}
1957
				catch(BadLocationException bl)
1958
				{
1959
					bl.printStackTrace();
1960
				}
1961
				break;
1962
			case 3:
1963
				doTripleClick(evt,line,offset,dot);
1964
				break;
1965
			}
1966
		}
1967
1968
		private void doSingleClick(MouseEvent evt, int line, 
1969
			int offset, int dot)
1970
		{
1971
			if((evt.getModifiers() & InputEvent.SHIFT_MASK) != 0)
1972
			{
1973
				rectSelect = (evt.getModifiers() & InputEvent.CTRL_MASK) != 0;
1974
				select(getMarkPosition(),dot);
1975
			}
1976
			else
1977
				setCaretPosition(dot);
1978
		}
1979
1980
		private void doDoubleClick(MouseEvent evt, int line,
1981
			int offset, int dot) throws BadLocationException
1982
		{
1983
			// Ignore empty lines
1984
			if(getLineLength(line) == 0)
1985
				return;
1986
1987
			try
1988
			{
1989
				int bracket = TextUtilities.findMatchingBracket(
1990
					document,Math.max(0,dot - 1));
1991
				if(bracket != -1)
1992
				{
1993
					int mark = getMarkPosition();
1994
					// Hack
1995
					if(bracket > mark)
1996
					{
1997
						bracket++;
1998
						mark--;
1999
					}
2000
					select(mark,bracket);
2001
					return;
2002
				}
2003
			}
2004
			catch(BadLocationException bl)
2005
			{
2006
				bl.printStackTrace();
2007
			}
2008
2009
			// Ok, it's not a bracket... select the word
2010
			String lineText = getLineText(line);
2011
			char ch = lineText.charAt(Math.max(0,offset - 1));
2012
2013
			String noWordSep = (String)document.getProperty("noWordSep");
2014
			if(noWordSep == null)
2015
				noWordSep = "";
2016
2017
			// If the user clicked on a non-letter char,
2018
			// we select the surrounding non-letters
2019
			boolean selectNoLetter = (!Character
2020
				.isLetterOrDigit(ch)
2021
				&& noWordSep.indexOf(ch) == -1);
2022
2023
			int wordStart = 0;
2024
2025
			for(int i = offset - 1; i >= 0; i--)
2026
			{
2027
				ch = lineText.charAt(i);
2028
				if(selectNoLetter ^ (!Character
2029
					.isLetterOrDigit(ch) &&
2030
					noWordSep.indexOf(ch) == -1))
2031
				{
2032
					wordStart = i + 1;
2033
					break;
2034
				}
2035
			}
2036
2037
			int wordEnd = lineText.length();
2038
			for(int i = offset; i < lineText.length(); i++)
2039
			{
2040
				ch = lineText.charAt(i);
2041
				if(selectNoLetter ^ (!Character
2042
					.isLetterOrDigit(ch) &&
2043
					noWordSep.indexOf(ch) == -1))
2044
				{
2045
					wordEnd = i;
2046
					break;
2047
				}
2048
			}
2049
2050
			int lineStart = getLineStartOffset(line);
2051
			select(lineStart + wordStart,lineStart + wordEnd);
2052
2053
			/*
2054
			String lineText = getLineText(line);
2055
			String noWordSep = (String)document.getProperty("noWordSep");
2056
			int wordStart = TextUtilities.findWordStart(lineText,offset,noWordSep);
2057
			int wordEnd = TextUtilities.findWordEnd(lineText,offset,noWordSep);
2058
2059
			int lineStart = getLineStartOffset(line);
2060
			select(lineStart + wordStart,lineStart + wordEnd);
2061
			*/
2062
		}
2063
2064
		private void doTripleClick(MouseEvent evt, int line,
2065
			int offset, int dot)
2066
		{
2067
			select(getLineStartOffset(line),getLineEndOffset(line)-1);
2068
		}
2069
	}
2070
2071
	class CaretUndo extends AbstractUndoableEdit
2072
	{
2073
		private int start;
2074
		private int end;
2075
2076
		CaretUndo(int start, int end)
2077
		{
2078
			this.start = start;
2079
			this.end = end;
2080
		}
2081
2082
		public boolean isSignificant()
2083
		{
2084
			return false;
2085
		}
2086
2087
		public String getPresentationName()
2088
		{
2089
			return "caret move";
2090
		}
2091
2092
		public void undo() throws CannotUndoException
2093
		{
2094
			super.undo();
2095
2096
			select(start,end);
2097
		}
2098
2099
		public void redo() throws CannotRedoException
2100
		{
2101
			super.redo();
2102
2103
			select(start,end);
2104
		}
2105
2106
		public boolean addEdit(UndoableEdit edit)
2107
		{
2108
			if(edit instanceof CaretUndo)
2109
			{
2110
				CaretUndo cedit = (CaretUndo)edit;
2111
				start = cedit.start;
2112
				end = cedit.end;
2113
				cedit.die();
2114
2115
				return true;
2116
			}
2117
			else
2118
				return false;
2119
		}
2120
	}
2121
2122
	static
2123
	{
2124
		caretTimer = new Timer(500,new CaretBlinker());
2125
		caretTimer.setInitialDelay(500);
2126
		caretTimer.start();
2127
	}
2128
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/InputHandler.java (+1070 lines)
Line 0 Link Here
1
/*
2
 * InputHandler.java - Manages key bindings and executes actions
3
 * Copyright (C) 1999 Slava Pestov
4
 *
5
 * You may use and modify this package for any purpose. Redistribution is
6
 * permitted, in both source and binary form, provided that this notice
7
 * remains intact in all source distributions of this package.
8
 */
9
package org.apache.batik.apps.svgbrowser.srcview;
10
11
import javax.swing.text.*;
12
import javax.swing.JPopupMenu;
13
import java.awt.event.*;
14
import java.awt.Component;
15
import java.util.*;
16
17
/**
18
 * An input handler converts the user's key strokes into concrete actions.
19
 * It also takes care of macro recording and action repetition.<p>
20
 *
21
 * This class provides all the necessary support code for an input
22
 * handler, but doesn't actually do any key binding logic. It is up
23
 * to the implementations of this class to do so.
24
 *
25
 * @author Slava Pestov
26
 * @version $Id: InputHandler.java,v 1.14 1999/12/13 03:40:30 sp Exp $
27
 * @see org.gjt.sp.jedit.textarea.DefaultInputHandler
28
 */
29
public abstract class InputHandler extends KeyAdapter
30
{
31
	/**
32
	 * If this client property is set to Boolean.TRUE on the text area,
33
	 * the home/end keys will support 'smart' BRIEF-like behaviour
34
	 * (one press = start/end of line, two presses = start/end of
35
	 * viewscreen, three presses = start/end of document). By default,
36
	 * this property is not set.
37
	 */
38
	public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd";
39
40
	public static final ActionListener BACKSPACE = new backspace();
41
	public static final ActionListener BACKSPACE_WORD = new backspace_word();
42
	public static final ActionListener DELETE = new delete();
43
	public static final ActionListener DELETE_WORD = new delete_word();
44
	public static final ActionListener END = new end(false);
45
	public static final ActionListener DOCUMENT_END = new document_end(false);
46
	public static final ActionListener SELECT_END = new end(true);
47
	public static final ActionListener SELECT_DOC_END = new document_end(true);
48
	public static final ActionListener INSERT_BREAK = new insert_break();
49
	public static final ActionListener INSERT_TAB = new insert_tab();
50
	public static final ActionListener HOME = new home(false);
51
	public static final ActionListener DOCUMENT_HOME = new document_home(false);
52
	public static final ActionListener SELECT_HOME = new home(true);
53
	public static final ActionListener SELECT_DOC_HOME = new document_home(true);
54
	public static final ActionListener NEXT_CHAR = new next_char(false);
55
	public static final ActionListener NEXT_LINE = new next_line(false);
56
	public static final ActionListener NEXT_PAGE = new next_page(false);
57
	public static final ActionListener NEXT_WORD = new next_word(false);
58
	public static final ActionListener SELECT_NEXT_CHAR = new next_char(true);
59
	public static final ActionListener SELECT_NEXT_LINE = new next_line(true);
60
	public static final ActionListener SELECT_NEXT_PAGE = new next_page(true);
61
	public static final ActionListener SELECT_NEXT_WORD = new next_word(true);
62
	public static final ActionListener OVERWRITE = new overwrite();
63
	public static final ActionListener PREV_CHAR = new prev_char(false);
64
	public static final ActionListener PREV_LINE = new prev_line(false);
65
	public static final ActionListener PREV_PAGE = new prev_page(false);
66
	public static final ActionListener PREV_WORD = new prev_word(false);
67
	public static final ActionListener SELECT_PREV_CHAR = new prev_char(true);
68
	public static final ActionListener SELECT_PREV_LINE = new prev_line(true);
69
	public static final ActionListener SELECT_PREV_PAGE = new prev_page(true);
70
	public static final ActionListener SELECT_PREV_WORD = new prev_word(true);
71
	public static final ActionListener REPEAT = new repeat();
72
	public static final ActionListener TOGGLE_RECT = new toggle_rect();
73
74
	// Default action
75
	public static final ActionListener INSERT_CHAR = new insert_char();
76
77
	private static Hashtable actions;
78
79
	static
80
	{
81
		actions = new Hashtable();
82
		actions.put("backspace",BACKSPACE);
83
		actions.put("backspace-word",BACKSPACE_WORD);
84
		actions.put("delete",DELETE);
85
		actions.put("delete-word",DELETE_WORD);
86
		actions.put("end",END);
87
		actions.put("select-end",SELECT_END);
88
		actions.put("document-end",DOCUMENT_END);
89
		actions.put("select-doc-end",SELECT_DOC_END);
90
		actions.put("insert-break",INSERT_BREAK);
91
		actions.put("insert-tab",INSERT_TAB);
92
		actions.put("home",HOME);
93
		actions.put("select-home",SELECT_HOME);
94
		actions.put("document-home",DOCUMENT_HOME);
95
		actions.put("select-doc-home",SELECT_DOC_HOME);
96
		actions.put("next-char",NEXT_CHAR);
97
		actions.put("next-line",NEXT_LINE);
98
		actions.put("next-page",NEXT_PAGE);
99
		actions.put("next-word",NEXT_WORD);
100
		actions.put("select-next-char",SELECT_NEXT_CHAR);
101
		actions.put("select-next-line",SELECT_NEXT_LINE);
102
		actions.put("select-next-page",SELECT_NEXT_PAGE);
103
		actions.put("select-next-word",SELECT_NEXT_WORD);
104
		actions.put("overwrite",OVERWRITE);
105
		actions.put("prev-char",PREV_CHAR);
106
		actions.put("prev-line",PREV_LINE);
107
		actions.put("prev-page",PREV_PAGE);
108
		actions.put("prev-word",PREV_WORD);
109
		actions.put("select-prev-char",SELECT_PREV_CHAR);
110
		actions.put("select-prev-line",SELECT_PREV_LINE);
111
		actions.put("select-prev-page",SELECT_PREV_PAGE);
112
		actions.put("select-prev-word",SELECT_PREV_WORD);
113
		actions.put("repeat",REPEAT);
114
		actions.put("toggle-rect",TOGGLE_RECT);
115
		actions.put("insert-char",INSERT_CHAR);
116
	}
117
118
	/**
119
	 * Returns a named text area action.
120
	 * @param name The action name
121
	 */
122
	public static ActionListener getAction(String name)
123
	{
124
		return (ActionListener)actions.get(name);
125
	}
126
127
	/**
128
	 * Returns the name of the specified text area action.
129
	 * @param listener The action
130
	 */
131
	public static String getActionName(ActionListener listener)
132
	{
133
		Enumeration e = getActions();
134
		while(e.hasMoreElements())
135
		{
136
			String name = (String)e.nextElement();
137
			ActionListener _listener = getAction(name);
138
			if(_listener == listener)
139
				return name;
140
		}
141
		return null;
142
	}
143
144
	/**
145
	 * Returns an enumeration of all available actions.
146
	 */
147
	public static Enumeration getActions()
148
	{
149
		return actions.keys();
150
	}
151
152
	/**
153
	 * Adds the default key bindings to this input handler.
154
	 * This should not be called in the constructor of this
155
	 * input handler, because applications might load the
156
	 * key bindings from a file, etc.
157
	 */
158
	public abstract void addDefaultKeyBindings();
159
160
	/**
161
	 * Adds a key binding to this input handler.
162
	 * @param keyBinding The key binding (the format of this is
163
	 * input-handler specific)
164
	 * @param action The action
165
	 */
166
	public abstract void addKeyBinding(String keyBinding, ActionListener action);
167
168
	/**
169
	 * Removes a key binding from this input handler.
170
	 * @param keyBinding The key binding
171
	 */
172
	public abstract void removeKeyBinding(String keyBinding);
173
174
	/**
175
	 * Removes all key bindings from this input handler.
176
	 */
177
	public abstract void removeAllKeyBindings();
178
179
	/**
180
	 * Grabs the next key typed event and invokes the specified
181
	 * action with the key as a the action command.
182
	 * @param action The action
183
	 */
184
	public void grabNextKeyStroke(ActionListener listener)
185
	{
186
		grabAction = listener;
187
	}
188
189
	/**
190
	 * Returns if repeating is enabled. When repeating is enabled,
191
	 * actions will be executed multiple times. This is usually
192
	 * invoked with a special key stroke in the input handler.
193
	 */
194
	public boolean isRepeatEnabled()
195
	{
196
		return repeat;
197
	}
198
199
	/**
200
	 * Enables repeating. When repeating is enabled, actions will be
201
	 * executed multiple times. Once repeating is enabled, the input
202
	 * handler should read a number from the keyboard.
203
	 */
204
	public void setRepeatEnabled(boolean repeat)
205
	{
206
		this.repeat = repeat;
207
	}
208
209
	/**
210
	 * Returns the number of times the next action will be repeated.
211
	 */
212
	public int getRepeatCount()
213
	{
214
		return (repeat ? Math.max(1,repeatCount) : 1);
215
	}
216
217
	/**
218
	 * Sets the number of times the next action will be repeated.
219
	 * @param repeatCount The repeat count
220
	 */
221
	public void setRepeatCount(int repeatCount)
222
	{
223
		this.repeatCount = repeatCount;
224
	}
225
226
	/**
227
	 * Returns the macro recorder. If this is non-null, all executed
228
	 * actions should be forwarded to the recorder.
229
	 */
230
	public InputHandler.MacroRecorder getMacroRecorder()
231
	{
232
		return recorder;
233
	}
234
235
	/**
236
	 * Sets the macro recorder. If this is non-null, all executed
237
	 * actions should be forwarded to the recorder.
238
	 * @param recorder The macro recorder
239
	 */
240
	public void setMacroRecorder(InputHandler.MacroRecorder recorder)
241
	{
242
		this.recorder = recorder;
243
	}
244
245
	/**
246
	 * Returns a copy of this input handler that shares the same
247
	 * key bindings. Setting key bindings in the copy will also
248
	 * set them in the original.
249
	 */
250
	public abstract InputHandler copy();
251
252
	/**
253
	 * Executes the specified action, repeating and recording it as
254
	 * necessary.
255
	 * @param listener The action listener
256
	 * @param source The event source
257
	 * @param actionCommand The action command
258
	 */
259
	public void executeAction(ActionListener listener, Object source,
260
		String actionCommand)
261
	{
262
		// create event
263
		ActionEvent evt = new ActionEvent(source,
264
			ActionEvent.ACTION_PERFORMED,
265
			actionCommand);
266
267
		// don't do anything if the action is a wrapper
268
		// (like EditAction.Wrapper)
269
		if(listener instanceof Wrapper)
270
		{
271
			listener.actionPerformed(evt);
272
			return;
273
		}
274
275
		// remember old values, in case action changes them
276
		boolean _repeat = repeat;
277
		int _repeatCount = getRepeatCount();
278
279
		// execute the action
280
		if(listener instanceof InputHandler.NonRepeatable)
281
			listener.actionPerformed(evt);
282
		else
283
		{
284
			for(int i = 0; i < Math.max(1,repeatCount); i++)
285
				listener.actionPerformed(evt);
286
		}
287
288
		// do recording. Notice that we do no recording whatsoever
289
		// for actions that grab keys
290
		if(grabAction == null)
291
		{
292
			if(recorder != null)
293
			{
294
				if(!(listener instanceof InputHandler.NonRecordable))
295
				{
296
					if(_repeatCount != 1)
297
						recorder.actionPerformed(REPEAT,String.valueOf(_repeatCount));
298
299
					recorder.actionPerformed(listener,actionCommand);
300
				}
301
			}
302
303
			// If repeat was true originally, clear it
304
			// Otherwise it might have been set by the action, etc
305
			if(_repeat)
306
			{
307
				repeat = false;
308
				repeatCount = 0;
309
			}
310
		}
311
	}
312
313
	/**
314
	 * Returns the text area that fired the specified event.
315
	 * @param evt The event
316
	 */
317
	public static JEditTextArea getTextArea(EventObject evt)
318
	{
319
		if(evt != null)
320
		{
321
			Object o = evt.getSource();
322
			if(o instanceof Component)
323
			{
324
				// find the parent text area
325
				Component c = (Component)o;
326
				for(;;)
327
				{
328
					if(c instanceof JEditTextArea)
329
						return (JEditTextArea)c;
330
					else if(c == null)
331
						break;
332
					if(c instanceof JPopupMenu)
333
						c = ((JPopupMenu)c)
334
							.getInvoker();
335
					else
336
						c = c.getParent();
337
				}
338
			}
339
		}
340
341
		// this shouldn't happen
342
		System.err.println("BUG: getTextArea() returning null");
343
		System.err.println("Report this to Slava Pestov <sp@gjt.org>");
344
		return null;
345
	}
346
347
	// protected members
348
349
	/**
350
	 * If a key is being grabbed, this method should be called with
351
	 * the appropriate key event. It executes the grab action with
352
	 * the typed character as the parameter.
353
	 */
354
	protected void handleGrabAction(KeyEvent evt)
355
	{
356
		// Clear it *before* it is executed so that executeAction()
357
		// resets the repeat count
358
		ActionListener _grabAction = grabAction;
359
		grabAction = null;
360
		executeAction(_grabAction,evt.getSource(),
361
			String.valueOf(evt.getKeyChar()));
362
	}
363
364
	// protected members
365
	protected ActionListener grabAction;
366
	protected boolean repeat;
367
	protected int repeatCount;
368
	protected InputHandler.MacroRecorder recorder;
369
370
	/**
371
	 * If an action implements this interface, it should not be repeated.
372
	 * Instead, it will handle the repetition itself.
373
	 */
374
	public interface NonRepeatable {}
375
376
	/**
377
	 * If an action implements this interface, it should not be recorded
378
	 * by the macro recorder. Instead, it will do its own recording.
379
	 */
380
	public interface NonRecordable {}
381
382
	/**
383
	 * For use by EditAction.Wrapper only.
384
	 * @since jEdit 2.2final
385
	 */
386
	public interface Wrapper {}
387
388
	/**
389
	 * Macro recorder.
390
	 */
391
	public interface MacroRecorder
392
	{
393
		void actionPerformed(ActionListener listener,
394
			String actionCommand);
395
	}
396
397
	public static class backspace implements ActionListener
398
	{
399
		public void actionPerformed(ActionEvent evt)
400
		{
401
			JEditTextArea textArea = getTextArea(evt);
402
403
			if(!textArea.isEditable())
404
			{
405
				textArea.getToolkit().beep();
406
				return;
407
			}
408
409
			if(textArea.getSelectionStart()
410
			   != textArea.getSelectionEnd())
411
			{
412
				textArea.setSelectedText("");
413
			}
414
			else
415
			{
416
				int caret = textArea.getCaretPosition();
417
				if(caret == 0)
418
				{
419
					textArea.getToolkit().beep();
420
					return;
421
				}
422
				try
423
				{
424
					textArea.getDocument().remove(caret - 1,1);
425
				}
426
				catch(BadLocationException bl)
427
				{
428
					bl.printStackTrace();
429
				}
430
			}
431
		}
432
	}
433
434
	public static class backspace_word implements ActionListener
435
	{
436
		public void actionPerformed(ActionEvent evt)
437
		{
438
			JEditTextArea textArea = getTextArea(evt);
439
			int start = textArea.getSelectionStart();
440
			if(start != textArea.getSelectionEnd())
441
			{
442
				textArea.setSelectedText("");
443
			}
444
445
			int line = textArea.getCaretLine();
446
			int lineStart = textArea.getLineStartOffset(line);
447
			int caret = start - lineStart;
448
449
			String lineText = textArea.getLineText(textArea
450
				.getCaretLine());
451
452
			if(caret == 0)
453
			{
454
				if(lineStart == 0)
455
				{
456
					textArea.getToolkit().beep();
457
					return;
458
				}
459
				caret--;
460
			}
461
			else
462
			{
463
				String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
464
				caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
465
			}
466
467
			try
468
			{
469
				textArea.getDocument().remove(
470
						caret + lineStart,
471
						start - (caret + lineStart));
472
			}
473
			catch(BadLocationException bl)
474
			{
475
				bl.printStackTrace();
476
			}
477
		}
478
	}
479
480
	public static class delete implements ActionListener
481
	{
482
		public void actionPerformed(ActionEvent evt)
483
		{
484
			JEditTextArea textArea = getTextArea(evt);
485
486
			if(!textArea.isEditable())
487
			{
488
				textArea.getToolkit().beep();
489
				return;
490
			}
491
492
			if(textArea.getSelectionStart()
493
			   != textArea.getSelectionEnd())
494
			{
495
				textArea.setSelectedText("");
496
			}
497
			else
498
			{
499
				int caret = textArea.getCaretPosition();
500
				if(caret == textArea.getDocumentLength())
501
				{
502
					textArea.getToolkit().beep();
503
					return;
504
				}
505
				try
506
				{
507
					textArea.getDocument().remove(caret,1);
508
				}
509
				catch(BadLocationException bl)
510
				{
511
					bl.printStackTrace();
512
				}
513
			}
514
		}
515
	}
516
517
	public static class delete_word implements ActionListener
518
	{
519
		public void actionPerformed(ActionEvent evt)
520
		{
521
			JEditTextArea textArea = getTextArea(evt);
522
			int start = textArea.getSelectionStart();
523
			if(start != textArea.getSelectionEnd())
524
			{
525
				textArea.setSelectedText("");
526
			}
527
528
			int line = textArea.getCaretLine();
529
			int lineStart = textArea.getLineStartOffset(line);
530
			int caret = start - lineStart;
531
532
			String lineText = textArea.getLineText(textArea
533
				.getCaretLine());
534
535
			if(caret == lineText.length())
536
			{
537
				if(lineStart + caret == textArea.getDocumentLength())
538
				{
539
					textArea.getToolkit().beep();
540
					return;
541
				}
542
				caret++;
543
			}
544
			else
545
			{
546
				String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
547
				caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
548
			}
549
550
			try
551
			{
552
				textArea.getDocument().remove(start,
553
					(caret + lineStart) - start);
554
			}
555
			catch(BadLocationException bl)
556
			{
557
				bl.printStackTrace();
558
			}
559
		}
560
	}
561
562
	public static class end implements ActionListener
563
	{
564
		private boolean select;
565
566
		public end(boolean select)
567
		{
568
			this.select = select;
569
		}
570
571
		public void actionPerformed(ActionEvent evt)
572
		{
573
			JEditTextArea textArea = getTextArea(evt);
574
575
			int caret = textArea.getCaretPosition();
576
577
			int lastOfLine = textArea.getLineEndOffset(
578
				textArea.getCaretLine()) - 1;
579
			int lastVisibleLine = textArea.getFirstLine()
580
				+ textArea.getVisibleLines();
581
			if(lastVisibleLine >= textArea.getLineCount())
582
			{
583
				lastVisibleLine = Math.min(textArea.getLineCount() - 1,
584
					lastVisibleLine);
585
			}
586
			else
587
				lastVisibleLine -= (textArea.getElectricScroll() + 1);
588
589
			int lastVisible = textArea.getLineEndOffset(lastVisibleLine) - 1;
590
			int lastDocument = textArea.getDocumentLength();
591
592
			if(caret == lastDocument)
593
			{
594
				textArea.getToolkit().beep();
595
				return;
596
			}
597
			else if(!Boolean.TRUE.equals(textArea.getClientProperty(
598
				SMART_HOME_END_PROPERTY)))
599
				caret = lastOfLine;
600
			else if(caret == lastVisible)
601
				caret = lastDocument;
602
			else if(caret == lastOfLine)
603
				caret = lastVisible;
604
			else
605
				caret = lastOfLine;
606
607
			if(select)
608
				textArea.select(textArea.getMarkPosition(),caret);
609
			else
610
				textArea.setCaretPosition(caret);
611
		}
612
	}
613
614
	public static class document_end implements ActionListener
615
	{
616
		private boolean select;
617
618
		public document_end(boolean select)
619
		{
620
			this.select = select;
621
		}
622
623
		public void actionPerformed(ActionEvent evt)
624
		{
625
			JEditTextArea textArea = getTextArea(evt);
626
			if(select)
627
				textArea.select(textArea.getMarkPosition(),
628
					textArea.getDocumentLength());
629
			else
630
				textArea.setCaretPosition(textArea
631
					.getDocumentLength());
632
		}
633
	}
634
635
	public static class home implements ActionListener
636
	{
637
		private boolean select;
638
639
		public home(boolean select)
640
		{
641
			this.select = select;
642
		}
643
644
		public void actionPerformed(ActionEvent evt)
645
		{
646
			JEditTextArea textArea = getTextArea(evt);
647
648
			int caret = textArea.getCaretPosition();
649
650
			int firstLine = textArea.getFirstLine();
651
652
			int firstOfLine = textArea.getLineStartOffset(
653
				textArea.getCaretLine());
654
			int firstVisibleLine = (firstLine == 0 ? 0 :
655
				firstLine + textArea.getElectricScroll());
656
			int firstVisible = textArea.getLineStartOffset(
657
				firstVisibleLine);
658
659
			if(caret == 0)
660
			{
661
				textArea.getToolkit().beep();
662
				return;
663
			}
664
			else if(!Boolean.TRUE.equals(textArea.getClientProperty(
665
				SMART_HOME_END_PROPERTY)))
666
				caret = firstOfLine;
667
			else if(caret == firstVisible)
668
				caret = 0;
669
			else if(caret == firstOfLine)
670
				caret = firstVisible;
671
			else
672
				caret = firstOfLine;
673
674
			if(select)
675
				textArea.select(textArea.getMarkPosition(),caret);
676
			else
677
				textArea.setCaretPosition(caret);
678
		}
679
	}
680
681
	public static class document_home implements ActionListener
682
	{
683
		private boolean select;
684
685
		public document_home(boolean select)
686
		{
687
			this.select = select;
688
		}
689
690
		public void actionPerformed(ActionEvent evt)
691
		{
692
			JEditTextArea textArea = getTextArea(evt);
693
			if(select)
694
				textArea.select(textArea.getMarkPosition(),0);
695
			else
696
				textArea.setCaretPosition(0);
697
		}
698
	}
699
700
	public static class insert_break implements ActionListener
701
	{
702
		public void actionPerformed(ActionEvent evt)
703
		{
704
			JEditTextArea textArea = getTextArea(evt);
705
706
			if(!textArea.isEditable())
707
			{
708
				textArea.getToolkit().beep();
709
				return;
710
			}
711
712
			textArea.setSelectedText("\n");
713
		}
714
	}
715
716
	public static class insert_tab implements ActionListener
717
	{
718
		public void actionPerformed(ActionEvent evt)
719
		{
720
			JEditTextArea textArea = getTextArea(evt);
721
722
			if(!textArea.isEditable())
723
			{
724
				textArea.getToolkit().beep();
725
				return;
726
			}
727
728
			textArea.overwriteSetSelectedText("\t");
729
		}
730
	}
731
732
	public static class next_char implements ActionListener
733
	{
734
		private boolean select;
735
736
		public next_char(boolean select)
737
		{
738
			this.select = select;
739
		}
740
741
		public void actionPerformed(ActionEvent evt)
742
		{
743
			JEditTextArea textArea = getTextArea(evt);
744
			int caret = textArea.getCaretPosition();
745
			if(caret == textArea.getDocumentLength())
746
			{
747
				textArea.getToolkit().beep();
748
				return;
749
			}
750
751
			if(select)
752
				textArea.select(textArea.getMarkPosition(),
753
					caret + 1);
754
			else
755
				textArea.setCaretPosition(caret + 1);
756
		}
757
	}
758
759
	public static class next_line implements ActionListener
760
	{
761
		private boolean select;
762
763
		public next_line(boolean select)
764
		{
765
			this.select = select;
766
		}
767
768
		public void actionPerformed(ActionEvent evt)
769
		{
770
			JEditTextArea textArea = getTextArea(evt);
771
			int caret = textArea.getCaretPosition();
772
			int line = textArea.getCaretLine();
773
774
			if(line == textArea.getLineCount() - 1)
775
			{
776
				textArea.getToolkit().beep();
777
				return;
778
			}
779
780
			int magic = textArea.getMagicCaretPosition();
781
			if(magic == -1)
782
			{
783
				magic = textArea.offsetToX(line,
784
					caret - textArea.getLineStartOffset(line));
785
			}
786
787
			caret = textArea.getLineStartOffset(line + 1)
788
				+ textArea.xToOffset(line + 1,magic);
789
			if(select)
790
				textArea.select(textArea.getMarkPosition(),caret);
791
			else
792
				textArea.setCaretPosition(caret);
793
			textArea.setMagicCaretPosition(magic);
794
		}
795
	}
796
797
	public static class next_page implements ActionListener
798
	{
799
		private boolean select;
800
801
		public next_page(boolean select)
802
		{
803
			this.select = select;
804
		}
805
806
		public void actionPerformed(ActionEvent evt)
807
		{
808
			JEditTextArea textArea = getTextArea(evt);
809
			int lineCount = textArea.getLineCount();
810
			int firstLine = textArea.getFirstLine();
811
			int visibleLines = textArea.getVisibleLines();
812
			int line = textArea.getCaretLine();
813
814
			firstLine += visibleLines;
815
816
			if(firstLine + visibleLines >= lineCount - 1)
817
				firstLine = lineCount - visibleLines;
818
819
			textArea.setFirstLine(firstLine);
820
821
			int caret = textArea.getLineStartOffset(
822
				Math.min(textArea.getLineCount() - 1,
823
				line + visibleLines));
824
			if(select)
825
				textArea.select(textArea.getMarkPosition(),caret);
826
			else
827
				textArea.setCaretPosition(caret);
828
		}
829
	}
830
831
	public static class next_word implements ActionListener
832
	{
833
		private boolean select;
834
835
		public next_word(boolean select)
836
		{
837
			this.select = select;
838
		}
839
840
		public void actionPerformed(ActionEvent evt)
841
		{
842
			JEditTextArea textArea = getTextArea(evt);
843
			int caret = textArea.getCaretPosition();
844
			int line = textArea.getCaretLine();
845
			int lineStart = textArea.getLineStartOffset(line);
846
			caret -= lineStart;
847
848
			String lineText = textArea.getLineText(textArea
849
				.getCaretLine());
850
851
			if(caret == lineText.length())
852
			{
853
				if(lineStart + caret == textArea.getDocumentLength())
854
				{
855
					textArea.getToolkit().beep();
856
					return;
857
				}
858
				caret++;
859
			}
860
			else
861
			{
862
				String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
863
				caret = TextUtilities.findWordEnd(lineText,caret,noWordSep);
864
			}
865
866
			if(select)
867
				textArea.select(textArea.getMarkPosition(),
868
					lineStart + caret);
869
			else
870
				textArea.setCaretPosition(lineStart + caret);
871
		}
872
	}
873
874
	public static class overwrite implements ActionListener
875
	{
876
		public void actionPerformed(ActionEvent evt)
877
		{
878
			JEditTextArea textArea = getTextArea(evt);
879
			textArea.setOverwriteEnabled(
880
				!textArea.isOverwriteEnabled());
881
		}
882
	}
883
884
	public static class prev_char implements ActionListener
885
	{
886
		private boolean select;
887
888
		public prev_char(boolean select)
889
		{
890
			this.select = select;
891
		}
892
893
		public void actionPerformed(ActionEvent evt)
894
		{
895
			JEditTextArea textArea = getTextArea(evt);
896
			int caret = textArea.getCaretPosition();
897
			if(caret == 0)
898
			{
899
				textArea.getToolkit().beep();
900
				return;
901
			}
902
903
			if(select)
904
				textArea.select(textArea.getMarkPosition(),
905
					caret - 1);
906
			else
907
				textArea.setCaretPosition(caret - 1);
908
		}
909
	}
910
911
	public static class prev_line implements ActionListener
912
	{
913
		private boolean select;
914
915
		public prev_line(boolean select)
916
		{
917
			this.select = select;
918
		}
919
920
		public void actionPerformed(ActionEvent evt)
921
		{
922
			JEditTextArea textArea = getTextArea(evt);
923
			int caret = textArea.getCaretPosition();
924
			int line = textArea.getCaretLine();
925
926
			if(line == 0)
927
			{
928
				textArea.getToolkit().beep();
929
				return;
930
			}
931
932
			int magic = textArea.getMagicCaretPosition();
933
			if(magic == -1)
934
			{
935
				magic = textArea.offsetToX(line,
936
					caret - textArea.getLineStartOffset(line));
937
			}
938
939
			caret = textArea.getLineStartOffset(line - 1)
940
				+ textArea.xToOffset(line - 1,magic);
941
			if(select)
942
				textArea.select(textArea.getMarkPosition(),caret);
943
			else
944
				textArea.setCaretPosition(caret);
945
			textArea.setMagicCaretPosition(magic);
946
		}
947
	}
948
949
	public static class prev_page implements ActionListener
950
	{
951
		private boolean select;
952
953
		public prev_page(boolean select)
954
		{
955
			this.select = select;
956
		}
957
958
		public void actionPerformed(ActionEvent evt)
959
		{
960
			JEditTextArea textArea = getTextArea(evt);
961
			int firstLine = textArea.getFirstLine();
962
			int visibleLines = textArea.getVisibleLines();
963
			int line = textArea.getCaretLine();
964
965
			if(firstLine < visibleLines)
966
				firstLine = visibleLines;
967
968
			textArea.setFirstLine(firstLine - visibleLines);
969
970
			int caret = textArea.getLineStartOffset(
971
				Math.max(0,line - visibleLines));
972
			if(select)
973
				textArea.select(textArea.getMarkPosition(),caret);
974
			else
975
				textArea.setCaretPosition(caret);
976
		}
977
	}
978
979
	public static class prev_word implements ActionListener
980
	{
981
		private boolean select;
982
983
		public prev_word(boolean select)
984
		{
985
			this.select = select;
986
		}
987
988
		public void actionPerformed(ActionEvent evt)
989
		{
990
			JEditTextArea textArea = getTextArea(evt);
991
			int caret = textArea.getCaretPosition();
992
			int line = textArea.getCaretLine();
993
			int lineStart = textArea.getLineStartOffset(line);
994
			caret -= lineStart;
995
996
			String lineText = textArea.getLineText(textArea
997
				.getCaretLine());
998
999
			if(caret == 0)
1000
			{
1001
				if(lineStart == 0)
1002
				{
1003
					textArea.getToolkit().beep();
1004
					return;
1005
				}
1006
				caret--;
1007
			}
1008
			else
1009
			{
1010
				String noWordSep = (String)textArea.getDocument().getProperty("noWordSep");
1011
				caret = TextUtilities.findWordStart(lineText,caret,noWordSep);
1012
			}
1013
1014
			if(select)
1015
				textArea.select(textArea.getMarkPosition(),
1016
					lineStart + caret);
1017
			else
1018
				textArea.setCaretPosition(lineStart + caret);
1019
		}
1020
	}
1021
1022
	public static class repeat implements ActionListener,
1023
		InputHandler.NonRecordable
1024
	{
1025
		public void actionPerformed(ActionEvent evt)
1026
		{
1027
			JEditTextArea textArea = getTextArea(evt);
1028
			textArea.getInputHandler().setRepeatEnabled(true);
1029
			String actionCommand = evt.getActionCommand();
1030
			if(actionCommand != null)
1031
			{
1032
				textArea.getInputHandler().setRepeatCount(
1033
					Integer.parseInt(actionCommand));
1034
			}
1035
		}
1036
	}
1037
1038
	public static class toggle_rect implements ActionListener
1039
	{
1040
		public void actionPerformed(ActionEvent evt)
1041
		{
1042
			JEditTextArea textArea = getTextArea(evt);
1043
			textArea.setSelectionRectangular(
1044
				!textArea.isSelectionRectangular());
1045
		}
1046
	}
1047
1048
	public static class insert_char implements ActionListener,
1049
		InputHandler.NonRepeatable
1050
	{
1051
		public void actionPerformed(ActionEvent evt)
1052
		{
1053
			JEditTextArea textArea = getTextArea(evt);
1054
			String str = evt.getActionCommand();
1055
			int repeatCount = textArea.getInputHandler().getRepeatCount();
1056
1057
			if(textArea.isEditable())
1058
			{
1059
				StringBuffer buf = new StringBuffer();
1060
				for(int i = 0; i < repeatCount; i++)
1061
					buf.append(str);
1062
				textArea.overwriteSetSelectedText(buf.toString());
1063
			}
1064
			else
1065
			{
1066
				textArea.getToolkit().beep();
1067
			}
1068
		}
1069
	}
1070
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (-23 / +27 lines)
Lines 56-61 Link Here
56
import java.lang.reflect.InvocationTargetException;
56
import java.lang.reflect.InvocationTargetException;
57
import java.lang.reflect.Method;
57
import java.lang.reflect.Method;
58
import java.net.MalformedURLException;
58
import java.net.MalformedURLException;
59
import java.net.URI;
59
import java.util.HashMap;
60
import java.util.HashMap;
60
import java.util.Iterator;
61
import java.util.Iterator;
61
import java.util.LinkedList;
62
import java.util.LinkedList;
Lines 70-75 Link Here
70
import javax.swing.Action;
71
import javax.swing.Action;
71
import javax.swing.BorderFactory;
72
import javax.swing.BorderFactory;
72
import javax.swing.ButtonGroup;
73
import javax.swing.ButtonGroup;
74
import javax.swing.ImageIcon;
73
import javax.swing.JComponent;
75
import javax.swing.JComponent;
74
import javax.swing.JDialog;
76
import javax.swing.JDialog;
75
import javax.swing.JFileChooser;
77
import javax.swing.JFileChooser;
Lines 88-93 Link Here
88
import javax.swing.text.Document;
90
import javax.swing.text.Document;
89
import javax.swing.text.PlainDocument;
91
import javax.swing.text.PlainDocument;
90
92
93
import org.apache.batik.apps.svgbrowser.srcview.JEditTextArea;
94
import org.apache.batik.apps.svgbrowser.srcview.SourceViewFrame;
95
import org.apache.batik.apps.svgbrowser.srcview.XMLTokenMarker;
91
import org.apache.batik.bridge.DefaultExternalResourceSecurity;
96
import org.apache.batik.bridge.DefaultExternalResourceSecurity;
92
import org.apache.batik.bridge.DefaultScriptSecurity;
97
import org.apache.batik.bridge.DefaultScriptSecurity;
93
import org.apache.batik.bridge.EmbededExternalResourceSecurity;
98
import org.apache.batik.bridge.EmbededExternalResourceSecurity;
Lines 102-107 Link Here
102
import org.apache.batik.bridge.UpdateManagerEvent;
107
import org.apache.batik.bridge.UpdateManagerEvent;
103
import org.apache.batik.bridge.UpdateManagerListener;
108
import org.apache.batik.bridge.UpdateManagerListener;
104
import org.apache.batik.dom.StyleSheetProcessingInstruction;
109
import org.apache.batik.dom.StyleSheetProcessingInstruction;
110
import org.apache.batik.dom.svg.LiveAttributeException;
105
import org.apache.batik.dom.svg.SVGOMDocument;
111
import org.apache.batik.dom.svg.SVGOMDocument;
106
import org.apache.batik.dom.util.HashTable;
112
import org.apache.batik.dom.util.HashTable;
107
import org.apache.batik.dom.util.DOMUtilities;
113
import org.apache.batik.dom.util.DOMUtilities;
Lines 133-138 Link Here
133
import org.apache.batik.util.SVGConstants;
139
import org.apache.batik.util.SVGConstants;
134
import org.apache.batik.util.XMLConstants;
140
import org.apache.batik.util.XMLConstants;
135
import org.apache.batik.util.gui.DOMViewer;
141
import org.apache.batik.util.gui.DOMViewer;
142
import org.apache.batik.util.gui.ErrorConsole;
136
import org.apache.batik.util.gui.JErrorPane;
143
import org.apache.batik.util.gui.JErrorPane;
137
import org.apache.batik.util.gui.LocationBar;
144
import org.apache.batik.util.gui.LocationBar;
138
import org.apache.batik.util.gui.MemoryMonitor;
145
import org.apache.batik.util.gui.MemoryMonitor;
Lines 1841-1866 Link Here
1841
1848
1842
            final ParsedURL u = new ParsedURL(svgDocument.getURL());
1849
            final ParsedURL u = new ParsedURL(svgDocument.getURL());
1843
1850
1844
            final JFrame fr = new JFrame(u.toString());
1845
            fr.setSize(resources.getInteger("ViewSource.width"),
1846
                       resources.getInteger("ViewSource.height"));
1847
            final JTextArea ta  = new JTextArea();
1848
            ta.setLineWrap(true);
1849
            ta.setFont(new Font("monospaced", Font.PLAIN, 12));
1850
1851
            JScrollPane scroll = new JScrollPane();
1852
            scroll.getViewport().add(ta);
1853
            scroll.setVerticalScrollBarPolicy
1854
                (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
1855
            fr.getContentPane().add(scroll, BorderLayout.CENTER);
1856
1857
            new Thread() {
1851
            new Thread() {
1858
                public void run() {
1852
                public void run() {
1859
                    char [] buffer = new char[4096];
1853
                    char [] buffer = new char[4096];
1860
1854
1861
                    try {
1855
                    try {
1862
                        Document  doc = new PlainDocument();
1856
                    	StringBuilder sb = new StringBuilder();
1863
1857
                    	
1864
                        ParsedURL purl = new ParsedURL(svgDocument.getURL());
1858
                        ParsedURL purl = new ParsedURL(svgDocument.getURL());
1865
                        InputStream is
1859
                        InputStream is
1866
                            = u.openStream(getInputHandler(purl).
1860
                            = u.openStream(getInputHandler(purl).
Lines 1870-1882 Link Here
1870
                        Reader in = XMLUtilities.createXMLDocumentReader(is);
1864
                        Reader in = XMLUtilities.createXMLDocumentReader(is);
1871
                        int len;
1865
                        int len;
1872
                        while ((len=in.read(buffer, 0, buffer.length)) != -1) {
1866
                        while ((len=in.read(buffer, 0, buffer.length)) != -1) {
1873
                            doc.insertString(doc.getLength(),
1867
                            sb.append(new String(buffer, 0, len));
1874
                                             new String(buffer, 0, len), null);
1875
                        }
1868
                        }
1876
1869
1877
                        ta.setDocument(doc);
1870
                        final JFrame fr = new SourceViewFrame(application, sb.toString(), userAgent);
1878
                        ta.setEditable(false);
1871
                        fr.setTitle(u.toString());
1879
                        ta.setBackground(Color.white);
1872
                        ImageIcon icon = new ImageIcon
1873
                        (getClass().getResource(resources.getString("ViewSource.frameicon")));
1874
                        fr.setIconImage(icon.getImage());
1875
                        fr.setSize(resources.getInteger("ViewSource.width"),
1876
                                   resources.getInteger("ViewSource.height"));
1880
                        fr.setVisible(true);
1877
                        fr.setVisible(true);
1881
                    } catch (Exception ex) {
1878
                    } catch (Exception ex) {
1882
                        userAgent.displayError(ex);
1879
                        userAgent.displayError(ex);
Lines 2734-2742 Link Here
2734
            if (debug) {
2731
            if (debug) {
2735
                ex.printStackTrace();
2732
                ex.printStackTrace();
2736
            }
2733
            }
2737
            JErrorPane pane =
2734
//            JErrorPane pane =
2738
                new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
2735
//                new JErrorPane(ex, JOptionPane.ERROR_MESSAGE);
2739
            JDialog dialog = pane.createDialog(JSVGViewerFrame.this, "ERROR");
2736
        	ErrorConsole console = ErrorConsole.getInstance();
2737
            if (ex instanceof LiveAttributeException) {
2738
            	LiveAttributeException lex = (LiveAttributeException)ex;
2739
        		console.add(lex.getElement().getNodeName(), svgDocument.getDocumentURI(), JOptionPane.ERROR_MESSAGE);
2740
            } else {
2741
	        	console.add(ex, svgDocument.getDocumentURI(), JOptionPane.ERROR_MESSAGE);
2742
            }
2743
            JDialog dialog = ErrorConsole.createDialog(JSVGViewerFrame.this, "ERROR");
2740
            dialog.setModal(false);
2744
            dialog.setModal(false);
2741
            dialog.setVisible(true);
2745
            dialog.setVisible(true);
2742
        }
2746
        }
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JFramesView.java (+380 lines)
Line 0 Link Here
1
/*
2
3
 Licensed to the Apache Software Foundation (ASF) under one or more
4
 contributor license agreements.  See the NOTICE file distributed with
5
 this work for additional information regarding copyright ownership.
6
 The ASF licenses this file to You under the Apache License, Version 2.0
7
 (the "License"); you may not use this file except in compliance with
8
 the License.  You may obtain a copy of the License at
9
10
 http://www.apache.org/licenses/LICENSE-2.0
11
12
 Unless required by applicable law or agreed to in writing, software
13
 distributed under the License is distributed on an "AS IS" BASIS,
14
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 See the License for the specific language governing permissions and
16
 limitations under the License.
17
18
 */
19
package org.apache.batik.util.gui.resource;
20
21
import java.awt.BasicStroke;
22
import java.awt.BorderLayout;
23
import java.awt.Color;
24
import java.awt.Component;
25
import java.awt.Dimension;
26
import java.awt.FontMetrics;
27
import java.awt.Graphics;
28
import java.awt.Graphics2D;
29
import java.awt.Polygon;
30
import java.awt.Rectangle;
31
import java.awt.Stroke;
32
import java.awt.event.ActionEvent;
33
import java.awt.event.AdjustmentEvent;
34
import java.awt.event.AdjustmentListener;
35
import java.awt.event.MouseAdapter;
36
import java.awt.event.MouseEvent;
37
import java.awt.event.MouseListener;
38
import java.awt.event.MouseMotionAdapter;
39
import java.awt.event.MouseMotionListener;
40
import java.util.HashMap;
41
import java.util.Locale;
42
import java.util.Map;
43
import java.util.ResourceBundle;
44
45
import javax.swing.AbstractAction;
46
import javax.swing.Action;
47
import javax.swing.BorderFactory;
48
import javax.swing.Box;
49
import javax.swing.BoxLayout;
50
import javax.swing.JButton;
51
import javax.swing.JComponent;
52
import javax.swing.JLabel;
53
import javax.swing.JPanel;
54
import javax.swing.JPopupMenu;
55
import javax.swing.JScrollBar;
56
import javax.swing.JScrollPane;
57
import javax.swing.border.BevelBorder;
58
59
public class JFramesView extends JPanel implements ActionMap {
60
61
	/**
62
	 * The resource file name
63
	 */
64
	protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.JTimeline";
65
66
	/**
67
	 * The resource bundle
68
	 */
69
	protected static ResourceBundle bundle;
70
71
	/**
72
	 * The resource manager
73
	 */
74
	protected static ResourceManager resources;
75
76
	static {
77
		bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
78
		resources = new ResourceManager(bundle);
79
	}
80
81
	/**
82
	 * The button factory.
83
	 */
84
	protected ButtonFactory bf = new ButtonFactory(bundle, this);
85
86
	/**
87
	 * The menu factory.
88
	 */
89
	protected MenuFactory mf = new MenuFactory(bundle, this);
90
91
	private JTimelineSlider sliderPanel;
92
93
	private JPopupMenu cornerPopup;
94
95
	private JLabel timerLabel;
96
97
	private int precisionMillis = 100;
98
99
	private int pixelsPerUnit = 50;
100
101
	private float value = 1;
102
103
	private int knobPosition;
104
105
	private JScrollPane framesScrollPane;
106
	
107
	private JScrollBar verticalScrollBar;
108
	
109
	public JFramesView() {
110
		super(new BorderLayout());
111
112
		actions.put("CornerButtonAction", new CornerButtonAction());
113
		actions.put("IncreaseUnitSizeMenuItemAction",
114
				new IncreaseUnitSizeMenuItemAction());
115
		actions.put("DecreaseUnitSizeMenuItemAction",
116
				new DecreaseUnitSizeMenuItemAction());
117
118
		sliderPanel = new JTimelineSlider();
119
120
		framesScrollPane = new JScrollPane(
121
				new JTimelineFramesPanel());
122
		framesScrollPane.setBorder(null);
123
		framesScrollPane
124
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
125
		framesScrollPane
126
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
127
		framesScrollPane.setColumnHeaderView(sliderPanel);
128
129
		JButton cornerButton = bf.createJButton("CornerButton");
130
		cornerButton.setFocusable(false);
131
		cornerPopup = new JPopupMenu();
132
		cornerPopup.add(mf.createJMenuItem("IncreaseUnitSizeMenuItem"));
133
		cornerPopup.add(mf.createJMenuItem("DecreaseUnitSizeMenuItem"));
134
		framesScrollPane
135
				.setCorner(JScrollPane.UPPER_RIGHT_CORNER, cornerButton);
136
		add(framesScrollPane);
137
138
		Box footerPanel = new Box(BoxLayout.X_AXIS);
139
		add(footerPanel, BorderLayout.SOUTH);
140
		timerLabel = new JLabel("-- : -- : --");
141
		timerLabel.setBorder(BorderFactory
142
				.createBevelBorder(BevelBorder.LOWERED));
143
		footerPanel.add(timerLabel);
144
		JScrollBar horizScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);
145
		int prefHeight = horizScrollBar.getPreferredSize().height;
146
		footerPanel
147
				.setMaximumSize(new Dimension(Integer.MAX_VALUE, prefHeight));
148
		footerPanel.setMinimumSize(new Dimension(0, prefHeight));
149
		footerPanel.setPreferredSize(footerPanel.getMinimumSize());
150
		footerPanel.add(horizScrollBar);
151
		footerPanel.add(Box.createHorizontalStrut(framesScrollPane
152
				.getVerticalScrollBar().getPreferredSize().width));
153
	}
154
155
	public JScrollBar getVerticalScrollBar() {
156
		return verticalScrollBar;
157
	}
158
159
	public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
160
		this.verticalScrollBar = verticalScrollBar;
161
		add(verticalScrollBar, BorderLayout.EAST);
162
		verticalScrollBar.addAdjustmentListener(new AdjustmentListener() {
163
			public void adjustmentValueChanged(AdjustmentEvent e) {
164
				
165
			}
166
		});
167
	}
168
169
	/**
170
	 * The map that contains the actions
171
	 */
172
	protected Map actions = new HashMap();
173
174
	/**
175
	 * Returns the action associated with the given string or null on error
176
	 * 
177
	 * @param key
178
	 *            the key mapped with the action to get
179
	 * @throws MissingListenerException
180
	 *             if the action is not found
181
	 */
182
	public Action getAction(String key) throws MissingListenerException {
183
		return (Action) actions.get(key);
184
	}
185
186
	protected class CornerButtonAction extends AbstractAction {
187
188
		public void actionPerformed(ActionEvent evt) {
189
			Component invoker = (Component) evt.getSource();
190
			cornerPopup.show(invoker, 0, invoker.getHeight());
191
		}
192
	}
193
194
	protected class IncreaseUnitSizeMenuItemAction extends AbstractAction {
195
196
		public void actionPerformed(ActionEvent evt) {
197
			// TODO:
198
			// Increase unit size in timeline slider
199
		}
200
	}
201
202
	protected class DecreaseUnitSizeMenuItemAction extends AbstractAction {
203
204
		public void actionPerformed(ActionEvent evt) {
205
			// TODO:
206
			// Decrease unit size in timeline slider
207
		}
208
	}
209
210
	public void paint(Graphics g) {
211
		knobPosition = (int) (value * pixelsPerUnit) + SLIDER_X_OFFSET;
212
213
		super.paint(g);
214
	}
215
216
	public static final int SLIDER_X_OFFSET = 10;
217
218
	private static final Color SLIDER_KNOB_FILL_COLOR = new Color(0x77FF7777,
219
			true);
220
221
	private static final Color SLIDER_KNOB_STROKE_COLOR = new Color(0x00FF0000);
222
223
	private static final Stroke SLIDER_KNOB_STROKE = new BasicStroke(1,
224
			BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 5.0f,
225
			new float[] { 5.0f }, 0.0f);
226
227
	private class JTimelineSlider extends JComponent {
228
229
		private boolean paintTrack = false;
230
231
		private Polygon knob;
232
233
		private Rectangle knobBounds;
234
235
		private boolean over;
236
237
		private MouseMotionListener mml = new MouseMotionAdapter() {
238
			public void mouseMoved(MouseEvent e) {
239
				int x = e.getX(), y = e.getY();
240
				boolean b = knobBounds.contains(x, y);
241
				if (b != b) {
242
					repaint();
243
				}
244
				over = b;
245
			}
246
247
			public void mouseDragged(MouseEvent e) {
248
				if (over) {
249
					int x = e.getX();
250
					if (x >= SLIDER_X_OFFSET) {
251
						value = (float) (x - SLIDER_X_OFFSET) / pixelsPerUnit;
252
						JFramesView.this.repaint();
253
					}
254
				}
255
			}
256
		};
257
258
		public JTimelineSlider() {
259
			int height = 30;
260
261
			setMaximumSize(new Dimension(Integer.MAX_VALUE, height));
262
			setMinimumSize(new Dimension(0, height));
263
			setPreferredSize(getMinimumSize());
264
			setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
265
			addMouseMotionListener(mml);
266
267
			int pos = height / 2 - 3;
268
			knob = new Polygon();
269
			knob.addPoint(-4, -pos);
270
			knob.addPoint(4, -pos);
271
			knob.addPoint(4, pos);
272
			knob.addPoint(-4, pos);
273
			knob.addPoint(-4, -pos);
274
275
			knobBounds = new Rectangle(6, height);
276
		}
277
278
		protected void paintComponent(Graphics g) {
279
			super.paintComponent(g);
280
281
			Dimension size = getSize();
282
			if (paintTrack) {
283
				int pos = size.height / 2;
284
				g.setColor(Color.gray);
285
				g.fillRect(0, pos - 1, size.width, 2);
286
				g.setColor(Color.white);
287
				g.drawLine(0, pos + 1, size.width, pos + 1);
288
			}
289
290
			int dx = pixelsPerUnit * precisionMillis / 1000;
291
			FontMetrics fm = g.getFontMetrics();
292
			int timeUnit = 0;
293
			for (int i = SLIDER_X_OFFSET; i < size.width; i += pixelsPerUnit) {
294
				String str = timeUnit++ + "";
295
				int strWidth = fm.stringWidth(str), strHeight = fm.getHeight()
296
						- fm.getDescent();
297
				g.setColor(getBackground());
298
				g.fillRect(i - strWidth / 2, (size.height - strHeight) / 2,
299
						strWidth, strHeight);
300
				g.setColor(Color.black);
301
				g.drawString(str, i - strWidth / 2,
302
						(size.height + strHeight) / 2);
303
				g.setColor(Color.gray);
304
				g.drawLine(i, size.height - 2, i, size.height - 7);
305
				g.drawLine(i, 2, i, 7);
306
				g.setColor(Color.lightGray);
307
				for (int j = i + dx; j < i + pixelsPerUnit; j += dx) {
308
					g.drawLine(j, size.height - 2, j, size.height - 5);
309
					g.drawLine(j, 2, j, 5);
310
				}
311
			}
312
313
			// Paint knob
314
			int x = knobPosition;
315
			int y = size.height / 2;
316
			knobBounds.x = x - knobBounds.width / 2;
317
			knobBounds.y = y - knobBounds.height / 2;
318
319
			g.translate(x, y);
320
			g.setColor(SLIDER_KNOB_FILL_COLOR);
321
			g.fillPolygon(knob);
322
			g.setColor(SLIDER_KNOB_STROKE_COLOR);
323
			g.drawPolygon(knob);
324
			g.translate(-x, -y);
325
		}
326
	}
327
328
	private class JTimelineFramesPanel extends JPanel {
329
330
		private boolean inside;
331
332
		private int hoverPosition;
333
		
334
		private MouseListener ml = new MouseAdapter() {
335
			public void mouseEntered(MouseEvent e) {
336
				inside = true;
337
				JFramesView.this.repaint();
338
			}
339
340
			public void mouseExited(MouseEvent e) {
341
				inside = false;
342
				JFramesView.this.repaint();
343
			}
344
		};
345
346
		private MouseMotionListener mml = new MouseMotionAdapter() {
347
			public void mouseMoved(MouseEvent e) {
348
				int x = e.getX() - SLIDER_X_OFFSET;
349
				int dx = pixelsPerUnit * precisionMillis / 1000;
350
				hoverPosition = SLIDER_X_OFFSET + x - x % dx;
351
				JFramesView.this.repaint();
352
			}
353
		};
354
355
		public JTimelineFramesPanel() {
356
			addMouseListener(ml);
357
			addMouseMotionListener(mml);
358
		}
359
360
		protected void paintComponent(Graphics g) {
361
			Dimension size = getSize();
362
			
363
			int dx = pixelsPerUnit * precisionMillis / 1000;
364
			g.setColor(Color.lightGray);
365
			for (int i = SLIDER_X_OFFSET; i < size.width; i += dx) {
366
				g.drawLine(i, 0, i, size.height);
367
			}
368
369
			g.setColor(SLIDER_KNOB_STROKE_COLOR);
370
			g.drawLine(knobPosition, 0, knobPosition, size.height);
371
			
372
			if (inside) {
373
				Graphics2D g2 = (Graphics2D)g;
374
				g2.setStroke(SLIDER_KNOB_STROKE);
375
				
376
				g2.drawLine(hoverPosition, 0, hoverPosition, size.height);
377
			}
378
		}
379
	}
380
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/ButtonFactory.java (+26 lines)
Lines 28-33 Link Here
28
import javax.swing.JButton;
28
import javax.swing.JButton;
29
import javax.swing.JCheckBox;
29
import javax.swing.JCheckBox;
30
import javax.swing.JRadioButton;
30
import javax.swing.JRadioButton;
31
import javax.swing.JToggleButton;
31
32
32
/**
33
/**
33
 * This class represents a button factory which builds
34
 * This class represents a button factory which builds
Lines 123-128 Link Here
123
    }
124
    }
124
125
125
    /**
126
    /**
127
     * Creates and returns a new swing button initialised
128
     * to be used as a toolbar toggle button
129
     * @param name the name of the button in the resource bundle
130
     * @throws MissingResourceException if key is not the name of a button.
131
     *         It is not thrown if the mnemonic and the action keys are missing
132
     * @throws ResourceFormatException if the mnemonic is not a single
133
     *         character
134
     * @throws MissingListenerException if the button action is not found in
135
     *         the action map
136
     */
137
    public JToggleButton createJToolbarToggleButton(String name)
138
        throws MissingResourceException,
139
               ResourceFormatException,
140
               MissingListenerException {
141
        JToggleButton result;
142
        try {
143
            result = new JToolbarToggleButton(getString(name+TEXT_SUFFIX));
144
        } catch (MissingResourceException e) {
145
            result = new JToolbarToggleButton();
146
        }
147
        initializeButton(result, name);
148
        return result;
149
    }
150
151
    /**
126
     * Creates and returns a new swing radio button
152
     * Creates and returns a new swing radio button
127
     * @param name the name of the button in the resource bundle
153
     * @param name the name of the button in the resource bundle
128
     * @throws MissingResourceException if key is not the name of a button.
154
     * @throws MissingResourceException if key is not the name of a button.
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/Hyperlink.java (+72 lines)
Line 0 Link Here
1
package org.apache.batik.util.gui.resource;
2
3
import java.awt.Cursor;
4
import java.awt.event.MouseAdapter;
5
import java.awt.event.MouseEvent;
6
import java.awt.event.MouseListener;
7
8
import javax.swing.JLabel;
9
10
public class Hyperlink extends JLabel {
11
	private MouseListener ml = new MouseAdapter() {
12
		public void mouseClicked(MouseEvent e) {
13
			if (callback != null) {
14
				callback.linkClicked(new HyperlinkEvent(Hyperlink.this.getCommand()));
15
			}
16
		}
17
	};
18
	
19
	private HyperlinkCallback callback;
20
	
21
	private String command;
22
	
23
	private static final String HTML_TEXT = "<html><font color=\"blue\"><u>__HTML_TEXT__</u></font></html>";
24
	
25
	private String text;
26
	
27
	public Hyperlink(String text, HyperlinkCallback callback) {
28
		this.callback = callback;
29
		setLinkText(text);
30
		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
31
		addMouseListener(ml);
32
	}
33
34
	public String getLinkText() {
35
		return text;
36
	}
37
	
38
	public void setLinkText(String text) {
39
		this.text = text;
40
		super.setText(HTML_TEXT.replace("__HTML_TEXT__", text));
41
	}
42
43
	public String getCommand() {
44
		return command;
45
	}
46
47
	public void setCommand(String command) {
48
		this.command = command;
49
	}
50
51
	public static class HyperlinkEvent {
52
		
53
		private String command;
54
		
55
		public HyperlinkEvent(String command) {
56
			this.command = command;
57
		}
58
59
		public String getCommand() {
60
			return command;
61
		}
62
63
		public void setCommand(String command) {
64
			this.command = command;
65
		}
66
	}
67
	
68
	public static interface HyperlinkCallback {
69
		public void linkClicked(HyperlinkEvent e);
70
	}
71
}
72
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarButton.java (-1 / +9 lines)
Lines 23-28 Link Here
23
import java.awt.event.MouseEvent;
23
import java.awt.event.MouseEvent;
24
24
25
import javax.swing.JButton;
25
import javax.swing.JButton;
26
import javax.swing.UIManager;
26
27
27
/**
28
/**
28
 * This class represents the buttons used in toolbars.
29
 * This class represents the buttons used in toolbars.
Lines 57-63 Link Here
57
        }
58
        }
58
        setBorderPainted(false);
59
        setBorderPainted(false);
59
        setMargin(new Insets(2, 2, 2, 2));
60
        setMargin(new Insets(2, 2, 2, 2));
60
        addMouseListener(new MouseListener());
61
62
        // Windows XP look and feel seems to have a bug due to which the
63
        // size of the parent container changes when the border painted
64
        // property is set. Temporary fix: disable mouseover behavior if
65
        // installed lnf is Windows XP
66
        if (!UIManager.getLookAndFeel().getName().equals("Windows")) {
67
	        addMouseListener(new MouseListener());
68
        }
61
    }
69
    }
62
70
63
    /**
71
    /**
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JDocumentTree.java (+279 lines)
Line 0 Link Here
1
package org.apache.batik.util.gui.resource;
2
3
import java.awt.BorderLayout;
4
import java.awt.Color;
5
import java.awt.Component;
6
import java.awt.Dimension;
7
import java.awt.GradientPaint;
8
import java.awt.Graphics;
9
import java.awt.Graphics2D;
10
import java.awt.Paint;
11
import java.awt.event.MouseAdapter;
12
import java.awt.event.MouseEvent;
13
import java.util.ArrayList;
14
import java.util.Locale;
15
import java.util.ResourceBundle;
16
17
import javax.swing.BorderFactory;
18
import javax.swing.DefaultListModel;
19
import javax.swing.ImageIcon;
20
import javax.swing.JComponent;
21
import javax.swing.JLabel;
22
import javax.swing.JList;
23
import javax.swing.JPanel;
24
import javax.swing.JScrollBar;
25
import javax.swing.JScrollPane;
26
import javax.swing.JTree;
27
import javax.swing.ListCellRenderer;
28
import javax.swing.tree.TreeNode;
29
30
public class JDocumentTree extends JPanel {
31
32
	/**
33
	 * The resource file name
34
	 */
35
	protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.JDocumentTree";
36
37
	/**
38
	 * The resource bundle
39
	 */
40
	protected static ResourceBundle bundle;
41
42
	/**
43
	 * The resource manager
44
	 */
45
	protected static ResourceManager resources;
46
47
	static {
48
		bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
49
		resources = new ResourceManager(bundle);
50
	}
51
52
	private JList nodeList;
53
54
	private JScrollPane nodeListScrollPane;
55
56
	private Node rootNode;
57
58
	public JDocumentTree() {
59
		this(null);
60
	}
61
62
	public JDocumentTree(JTree tree) {
63
		super(new BorderLayout());
64
65
		nodeList = new JList(new DefaultListModel());
66
		nodeList.setFixedCellHeight(25);
67
		nodeList.setCellRenderer(new DocTreeCellRenderer());
68
		nodeListScrollPane = new JScrollPane(nodeList);
69
		nodeListScrollPane
70
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
71
		nodeListScrollPane.setBorder(null);
72
		add(nodeListScrollPane);
73
74
		TreeNode treeNode = (TreeNode) tree.getModel().getRoot();
75
		rootNode = parse(treeNode, null);
76
		rebuildNodeList(nodeList, rootNode);
77
78
		nodeList.addMouseListener(new MouseAdapter() {
79
			public void mouseClicked(MouseEvent e) {
80
				if (e.getClickCount() == 2) {
81
					Node selectedNode = (Node) nodeList.getSelectedValue();
82
					selectedNode.setExpanded(!selectedNode.isExpanded());
83
					rebuildNodeList(nodeList, rootNode);
84
				}
85
			}
86
		});
87
	}
88
89
	public JScrollBar getVerticalScrollBar() {
90
		return nodeListScrollPane.getVerticalScrollBar();
91
	}
92
93
	public void setVerticalScrollBar(JScrollBar verticalScrollBar) {
94
		nodeListScrollPane.setVerticalScrollBar(verticalScrollBar);
95
	}
96
97
	private void rebuildNodeList(JList nodeList, Node node) {
98
		DefaultListModel listModel = (DefaultListModel) nodeList.getModel();
99
		listModel.clear();
100
		addNode(listModel, node);
101
	}
102
103
	private void addNode(DefaultListModel listModel, Node node) {
104
		Node parent = node.getParent();
105
		if (parent == null || parent.isExpanded()) {
106
			listModel.addElement(node);
107
			Node[] children = node.getChildren();
108
			if (children != null) {
109
				for (int i = 0; i < children.length; i++) {
110
					addNode(listModel, children[i]);
111
				}
112
			}
113
		}
114
	}
115
116
	private Node parse(TreeNode treeNode, Node parent) {
117
		if (treeNode == null) {
118
			return null;
119
		}
120
121
		Node docNode = new Node(parent, treeNode.toString());
122
		int childCount = treeNode.getChildCount();
123
		if (childCount > 0) {
124
			ArrayList childDocNodes = new ArrayList();
125
			for (int i = 0; i < childCount; i++) {
126
				Node childDocNode = parse((TreeNode) treeNode.getChildAt(i),
127
						docNode);
128
				if (childDocNode != null) {
129
					childDocNodes.add(childDocNode);
130
				}
131
			}
132
			docNode.setChildren((Node[]) childDocNodes.toArray(new Node[0]));
133
		}
134
135
		return docNode;
136
	}
137
138
	private class Node extends JComponent {
139
140
		private String text;
141
142
		private Node parent;
143
144
		private int depth;
145
146
		private Node[] children;
147
148
		private boolean expanded = true;
149
150
		private boolean locked = false;
151
152
		public Node(Node parent, String text) {
153
			this.parent = parent;
154
			this.depth = parent == null ? 0 : parent.depth + 1;
155
			setText(text);
156
		}
157
158
		public Node getParent() {
159
			return parent;
160
		}
161
162
		public int getDepth() {
163
			return depth;
164
		}
165
166
		public Node[] getChildren() {
167
			return children;
168
		}
169
170
		public int getChildCount() {
171
			return children == null ? 0 : children.length;
172
		}
173
174
		public void setChildren(Node[] children) {
175
			this.children = children;
176
			if (children != null) {
177
				for (int i = 0; i < children.length; i++) {
178
					children[i].parent = this;
179
				}
180
			}
181
		}
182
183
		public boolean isExpanded() {
184
			if (parent == null) {
185
				return true;
186
			}
187
			if (!expanded) {
188
				return false;
189
			}
190
			return parent.isExpanded();
191
		}
192
193
		public void setExpanded(boolean expanded) {
194
			this.expanded = expanded;
195
		}
196
197
		public String getText() {
198
			return text;
199
		}
200
201
		public void setText(String text) {
202
			this.text = text;
203
		}
204
	}
205
206
	private class DocTreeCellRenderer extends JLabel implements
207
			ListCellRenderer {
208
209
		private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon");
210
211
		private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon");
212
213
		private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon");
214
215
		private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon");
216
217
		private final ImageIcon LOCK_ICON = getIcon("TreeNodeLocked.icon");
218
219
		private Paint normalPaint, selectedPaint;
220
221
		private boolean selected;
222
223
		private boolean locked = true;
224
225
		public DocTreeCellRenderer() {
226
			setIcon(SPACER_ICON);
227
228
			Dimension dim = getPreferredSize();
229
			normalPaint = new Color(234, 234, 234);
230
			selectedPaint = new GradientPaint(0, 0, Color.white, 0,
231
					2 * dim.height, Color.gray);
232
		}
233
234
		private ImageIcon getIcon(String name) {
235
			return new ImageIcon(JDocumentTree.this.getClass().getResource(
236
					resources.getString(name)));
237
		}
238
239
		protected void paintComponent(Graphics g) {
240
			Dimension size = getSize();
241
			Graphics2D g2 = (Graphics2D) g;
242
			g2.setPaint(selected ? selectedPaint : normalPaint);
243
			g2.fillRect(0, 0, size.width, size.height);
244
245
			g2.setColor(Color.lightGray);
246
			g2.drawLine(0, size.height - 2, size.width, size.height - 2);
247
			g2.setColor(Color.white);
248
			g2.drawLine(0, size.height - 1, size.width, size.height - 1);
249
250
			super.paintComponent(g);
251
252
			g.setColor(Color.white);
253
			int x, y;
254
			x = size.width - 18;
255
			y = (size.height - 16) / 2;
256
			g.draw3DRect(x, y, 16, 16, false);
257
			if (locked) {
258
				LOCK_ICON.paintIcon(this, g, x, y);
259
			}
260
		}
261
262
		public Component getListCellRendererComponent(JList list, Object value,
263
				int index, boolean isSelected, boolean cellHasFocus) {
264
			Node node = (Node) value;
265
			selected = isSelected;
266
			setText(node.getText());
267
			setBorder(BorderFactory.createEmptyBorder(0, node.depth * 10, 0, 0));
268
			if (node.getChildren() == null || node.getChildCount() == 0) {// leaf
269
				setIcon(LEAF_ICON);
270
			} else if (node.isExpanded()) {
271
				setIcon(OPENED_ICON);
272
			} else {
273
				setIcon(CLOSED_ICON);
274
			}
275
276
			return this;
277
		}
278
	}
279
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java (+84 lines)
Line 0 Link Here
1
/*
2
3
   Licensed to the Apache Software Foundation (ASF) under one or more
4
   contributor license agreements.  See the NOTICE file distributed with
5
   this work for additional information regarding copyright ownership.
6
   The ASF licenses this file to You under the Apache License, Version 2.0
7
   (the "License"); you may not use this file except in compliance with
8
   the License.  You may obtain a copy of the License at
9
10
       http://www.apache.org/licenses/LICENSE-2.0
11
12
   Unless required by applicable law or agreed to in writing, software
13
   distributed under the License is distributed on an "AS IS" BASIS,
14
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
   See the License for the specific language governing permissions and
16
   limitations under the License.
17
18
 */
19
package org.apache.batik.util.gui.resource;
20
21
import java.awt.Insets;
22
import java.awt.event.MouseAdapter;
23
import java.awt.event.MouseEvent;
24
25
import javax.swing.JToggleButton;
26
import javax.swing.UIManager;
27
28
import org.apache.batik.util.gui.resource.JToolbarButton.MouseListener;
29
30
/**
31
 * This class represents the buttons used in toolbars.
32
 *
33
 * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
34
 * @version $Id: JToolbarButton.java 498555 2007-01-22 08:09:33Z cam $
35
 */
36
public class JToolbarToggleButton extends JToggleButton {
37
    /**
38
     * Creates a new toolbar button.
39
     */
40
    public JToolbarToggleButton() {
41
        initialize();
42
    }
43
44
    /**
45
     * Creates a new toolbar button.
46
     * @param txt The button text.
47
     */
48
    public JToolbarToggleButton(String txt) {
49
        super(txt);
50
        initialize();
51
    }
52
53
    /**
54
     * Initializes the button.
55
     */
56
    protected void initialize() {
57
        if (!System.getProperty("java.version").startsWith("1.3")) {
58
            setOpaque(false);
59
            setBackground(new java.awt.Color(0, 0, 0, 0));
60
        }
61
        setBorderPainted(false);
62
        setMargin(new Insets(2, 2, 2, 2));
63
64
        // Windows XP look and feel seems to have a bug due to which the
65
        // size of the parent container changes when the border painted
66
        // property is set. Temporary fix: disable mouseover behavior if
67
        // installed lnf is Windows XP
68
        if (!UIManager.getLookAndFeel().getName().equals("Windows")) {
69
	        addMouseListener(new MouseListener());
70
        }
71
    }
72
73
    /**
74
     * To manage the mouse interactions.
75
     */
76
    protected class MouseListener extends MouseAdapter {
77
        public void mouseEntered(MouseEvent ev) {
78
            setBorderPainted(true);
79
        }
80
        public void mouseExited(MouseEvent ev) {
81
            setBorderPainted(false);
82
        }
83
    }
84
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/TimelineViewer.java (+214 lines)
Line 0 Link Here
1
package org.apache.batik.util.gui;
2
3
import java.awt.BorderLayout;
4
import java.awt.Color;
5
import java.awt.Component;
6
import java.awt.Dimension;
7
import java.awt.GradientPaint;
8
import java.awt.Graphics;
9
import java.awt.Graphics2D;
10
import java.awt.Paint;
11
import java.awt.event.ActionEvent;
12
import java.util.HashMap;
13
import java.util.Locale;
14
import java.util.Map;
15
import java.util.ResourceBundle;
16
17
import javax.swing.AbstractAction;
18
import javax.swing.Action;
19
import javax.swing.Box;
20
import javax.swing.BoxLayout;
21
import javax.swing.ImageIcon;
22
import javax.swing.JDialog;
23
import javax.swing.JLabel;
24
import javax.swing.JOptionPane;
25
import javax.swing.JPanel;
26
import javax.swing.JScrollBar;
27
import javax.swing.JScrollPane;
28
import javax.swing.JSeparator;
29
import javax.swing.JSplitPane;
30
import javax.swing.JToolBar;
31
import javax.swing.JTree;
32
import javax.swing.tree.TreeCellRenderer;
33
34
import org.apache.batik.util.gui.resource.ActionMap;
35
import org.apache.batik.util.gui.resource.JDocumentTree;
36
import org.apache.batik.util.gui.resource.JFramesView;
37
import org.apache.batik.util.gui.resource.MissingListenerException;
38
import org.apache.batik.util.gui.resource.ResourceManager;
39
import org.apache.batik.util.gui.resource.ToolBarFactory;
40
41
public class TimelineViewer extends JPanel implements ActionMap {
42
43
	/**
44
	 * The resource file name
45
	 */
46
	protected static final String RESOURCES = "org.apache.batik.util.gui.resources.TimelineViewer";
47
48
	/**
49
	 * The resource bundle
50
	 */
51
	protected static ResourceBundle bundle;
52
53
	/**
54
	 * The resource manager
55
	 */
56
	protected static ResourceManager resources;
57
58
	static {
59
		bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
60
		resources = new ResourceManager(bundle);
61
	}
62
63
	/**
64
	 * The toolbar factory.
65
	 */
66
	protected ToolBarFactory tf = new ToolBarFactory(bundle, this);
67
68
	private JTree docTree;
69
70
	public TimelineViewer() {
71
		super(new BorderLayout());
72
		setPreferredSize(new Dimension(800, 300));
73
74
		JSplitPane splitPane = new JSplitPane();
75
		splitPane.setResizeWeight(0.0);
76
		JPanel leftPane = new JPanel();
77
		splitPane.setLeftComponent(leftPane);
78
79
		leftPane.setLayout(new BorderLayout());
80
		leftPane.setMinimumSize(new Dimension(300, 0));
81
		leftPane.setPreferredSize(getMinimumSize());
82
		leftPane.add(createToolBar(), BorderLayout.NORTH);
83
84
		JScrollBar scrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 100);
85
		JDocumentTree docTree = new JDocumentTree(new JTree());
86
		docTree.setVerticalScrollBar(scrollBar);
87
		leftPane.add(docTree);
88
89
		JFramesView framesView = new JFramesView();
90
		framesView.setVerticalScrollBar(scrollBar);
91
		splitPane.setRightComponent(framesView);
92
		add(splitPane);
93
	}
94
95
	private JPanel createToolBar() {
96
		JPanel toolbarPanel = new JPanel(new BorderLayout());
97
		JToolBar toolbar = tf.createJToolBar("ToolBar");
98
		toolbar.setFloatable(false);
99
100
		toolbarPanel.add(toolbar);
101
		toolbarPanel.add(new JSeparator(), BorderLayout.SOUTH);
102
103
		return toolbarPanel;
104
	}
105
106
	public JDialog createDialog(Component owner, String title) {
107
		JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(owner),
108
				title);
109
		dialog.getContentPane().add(this, BorderLayout.CENTER);
110
		dialog.pack();
111
		return dialog;
112
	}
113
114
	/**
115
	 * The map that contains the actions
116
	 */
117
	protected Map actions = new HashMap();
118
119
	/**
120
	 * Returns the action associated with the given string or null on error
121
	 * 
122
	 * @param key
123
	 *            the key mapped with the action to get
124
	 * @throws MissingListenerException
125
	 *             if the action is not found
126
	 */
127
	public Action getAction(String key) throws MissingListenerException {
128
		return (Action) actions.get(key);
129
	}
130
131
	/**
132
	 * The action associated with the 'All' button.
133
	 */
134
	protected class DisplayAllButtonAction extends AbstractAction {
135
136
		public void actionPerformed(ActionEvent evt) {
137
		}
138
	}
139
140
	public static void main(String[] args) {
141
		JDialog d = new TimelineViewer().createDialog(null,
142
				"Timeline Viewer 0.1");
143
		d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
144
		d.setVisible(true);
145
	}
146
147
//	private class DocTreeCellRenderer extends Box implements
148
//			TreeCellRenderer {
149
//
150
//		private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon");
151
//
152
//		private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon");
153
//
154
//		private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon");
155
//
156
//		private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon");
157
//
158
//		private Paint gradient;
159
//
160
//		private JLabel label;
161
//
162
//		private JLabel icon;
163
//
164
//		public DocTreeCellRenderer() {
165
//			super(BoxLayout.X_AXIS);
166
//			setOpaque(false);
167
//
168
//			icon = new JLabel(SPACER_ICON);
169
//			add(icon);
170
//
171
//			label = new JLabel();
172
//			add(label);
173
//			
174
//			Dimension dim = getPreferredSize();
175
//			gradient = new GradientPaint(0, 0, Color.white, 0,
176
//					2 * dim.height, Color.gray);
177
//		}
178
//
179
//		public void setBounds(int x, int y, int width, int height) {
180
//			super.setBounds(x, y, docTree.getWidth(), height);
181
//			System.out.println(getBounds());
182
//		}
183
//		
184
//		private ImageIcon getIcon(String name) {
185
//			String uri = resources.getString(name);
186
//			System.out.println(uri);
187
//			return new ImageIcon(TimelineViewer.this.getClass().getResource(
188
//					uri));
189
//		}
190
//
191
//		protected void paintComponent(Graphics g) {
192
//			Graphics2D g2 = (Graphics2D) g;
193
//			g2.setPaint(gradient);
194
//			g2.fillRect(0, 0, getWidth(), getHeight());
195
//
196
//			super.paintComponent(g);
197
//		}
198
//
199
//		public Component getTreeCellRendererComponent(JTree tree, Object value,
200
//				boolean selected, boolean expanded, boolean leaf, int row,
201
//				boolean hasFocus) {
202
//			label.setText(value.toString());
203
//
204
//			if (leaf) {
205
//				icon.setIcon(LEAF_ICON);
206
//			} else if (expanded) {
207
//				icon.setIcon(OPENED_ICON);
208
//			} else {
209
//				icon.setIcon(CLOSED_ICON);
210
//			}
211
//			return this;
212
//		}
213
//	}
214
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorHandlerProxy.java (+38 lines)
Line 0 Link Here
1
package org.apache.batik.util.gui;
2
3
import java.lang.reflect.InvocationHandler;
4
import java.lang.reflect.InvocationTargetException;
5
import java.lang.reflect.Method;
6
7
import javax.swing.JDialog;
8
import javax.swing.JOptionPane;
9
10
public class ErrorHandlerProxy implements InvocationHandler {
11
	
12
	private Object delegate;
13
	
14
	private String uri;
15
	
16
	public ErrorHandlerProxy(Object delegate, String uri) {
17
		this.delegate = delegate;
18
		this.uri = uri;
19
	}
20
21
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
22
		try {
23
			System.out.println("proxy invoked");
24
			return method.invoke(delegate, args);
25
		} catch (InvocationTargetException ite) {
26
			System.out.println("Exception occurred");
27
			ite.printStackTrace();
28
		} catch (Exception e) {
29
			System.out.println("Exception occurred");
30
        	ErrorConsole console = ErrorConsole.getInstance();
31
        	console.add(e, uri, JOptionPane.ERROR_MESSAGE);
32
            JDialog dialog = ErrorConsole.createDialog(null, "ERROR");
33
			dialog.setVisible(true);
34
		}
35
		return null;
36
	}
37
38
}
(-)C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorConsole.java (+645 lines)
Line 0 Link Here
1
package org.apache.batik.util.gui;
2
3
import java.awt.BorderLayout;
4
import java.awt.Color;
5
import java.awt.Component;
6
import java.awt.Container;
7
import java.awt.Dimension;
8
import java.awt.FlowLayout;
9
import java.awt.Font;
10
import java.awt.GradientPaint;
11
import java.awt.Graphics;
12
import java.awt.Graphics2D;
13
import java.awt.SystemColor;
14
import java.awt.event.ActionEvent;
15
import java.awt.event.ActionListener;
16
import java.awt.event.ItemEvent;
17
import java.awt.event.ItemListener;
18
import java.awt.event.MouseAdapter;
19
import java.awt.event.MouseEvent;
20
import java.awt.event.MouseListener;
21
import java.io.BufferedReader;
22
import java.io.File;
23
import java.io.FileReader;
24
import java.io.PrintWriter;
25
import java.io.StringWriter;
26
import java.net.URI;
27
import java.util.ArrayList;
28
import java.util.Enumeration;
29
import java.util.HashMap;
30
import java.util.Iterator;
31
import java.util.List;
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.AbstractButton;
38
import javax.swing.Action;
39
import javax.swing.BorderFactory;
40
import javax.swing.Box;
41
import javax.swing.BoxLayout;
42
import javax.swing.ButtonGroup;
43
import javax.swing.ButtonModel;
44
import javax.swing.ImageIcon;
45
import javax.swing.JButton;
46
import javax.swing.JDialog;
47
import javax.swing.JLabel;
48
import javax.swing.JOptionPane;
49
import javax.swing.JPanel;
50
import javax.swing.JPopupMenu;
51
import javax.swing.JScrollPane;
52
import javax.swing.JTextArea;
53
import javax.swing.JTextPane;
54
import javax.swing.JToggleButton;
55
import javax.swing.JToolBar;
56
import javax.swing.text.BadLocationException;
57
import javax.swing.text.DefaultHighlighter;
58
import javax.swing.text.Highlighter;
59
import javax.swing.text.JTextComponent;
60
import javax.swing.text.Highlighter.HighlightPainter;
61
62
import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
63
import org.apache.batik.util.ParsedURL;
64
import org.apache.batik.util.gui.resource.ActionMap;
65
import org.apache.batik.util.gui.resource.ButtonFactory;
66
import org.apache.batik.util.gui.resource.Hyperlink;
67
import org.apache.batik.util.gui.resource.JToolbarSeparator;
68
import org.apache.batik.util.gui.resource.MenuFactory;
69
import org.apache.batik.util.gui.resource.MissingListenerException;
70
import org.apache.batik.util.gui.resource.ResourceManager;
71
import org.apache.batik.util.gui.resource.Hyperlink.HyperlinkEvent;
72
import org.w3c.dom.Document;
73
import org.xml.sax.Attributes;
74
import org.xml.sax.Locator;
75
import org.xml.sax.SAXException;
76
import org.xml.sax.helpers.LocatorImpl;
77
78
public class ErrorConsole extends JPanel implements ActionMap {
79
80
	/**
81
	 * The resource file name
82
	 */
83
	protected static final String RESOURCES = "org.apache.batik.util.gui.resources.ErrorConsole";
84
85
	/**
86
	 * The resource bundle
87
	 */
88
	protected static ResourceBundle bundle;
89
90
	/**
91
	 * The resource manager
92
	 */
93
	protected static ResourceManager resources;
94
95
	static {
96
		bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
97
		resources = new ResourceManager(bundle);
98
	}
99
100
	/**
101
	 * The button factory.
102
	 */
103
	protected ButtonFactory bf = new ButtonFactory(bundle, this);
104
105
	/**
106
	 * The menu factory.
107
	 */
108
	protected MenuFactory mf = new MenuFactory(bundle, this);
109
110
	private Box consoleList;
111
112
	private ButtonGroup errorGroup;
113
114
	private int displayType;
115
116
	private boolean sortOrderAscending = true;
117
118
	private JPopupMenu popupMenu;
119
120
	public ErrorConsole() {
121
		super(new BorderLayout());
122
123
		actions.put("DisplayAllButtonAction", new DisplayAllButtonAction());
124
		actions.put("DisplayErrorsButtonAction",
125
				new DisplayErrorsButtonAction());
126
		actions.put("DisplayWarningsButtonAction",
127
				new DisplayWarningsButtonAction());
128
		actions.put("DisplayMessagesButtonAction",
129
				new DisplayMessagesButtonAction());
130
		actions.put("ClearButtonAction", new ClearButtonAction());
131
132
		actions.put("FirstLastSortMenuAction", new FirstLastSortMenuAction());
133
		actions.put("LastFirstSortMenuAction", new LastFirstSortMenuAction());
134
		actions.put("CopyMenuAction", new CopyMenuAction());
135
136
		JPanel errorPanel = new JPanel(new BorderLayout());
137
		errorPanel.setBackground(Color.white);
138
139
		JScrollPane errorScrollPane = new JScrollPane(errorPanel);
140
		errorScrollPane
141
				.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
142
		add(errorScrollPane);
143
144
		errorGroup = new ButtonGroup();
145
146
		consoleList = new Box(BoxLayout.Y_AXIS);
147
		errorPanel.add(consoleList, BorderLayout.NORTH);
148
149
		popupMenu = createPopupMenu();
150
151
		add(createToolBar(), BorderLayout.NORTH);
152
		setPreferredSize(new Dimension(550, 400));
153
	}
154
155
	private JToolBar createToolBar() {
156
		JToolBar toolbar = new JToolBar();
157
		toolbar.setFloatable(false);
158
159
		BooleanButtonGroup displayGroup = new BooleanButtonGroup();
160
161
		JToggleButton displayAll = bf
162
				.createJToolbarToggleButton("DisplayAllButton");
163
		displayGroup.add(displayAll);
164
		displayAll.setSelected(true);
165
		displayType(-1, true);
166
		toolbar.add(displayAll);
167
168
		JToggleButton displayErrors = bf
169
				.createJToolbarToggleButton("DisplayErrorsButton");
170
		displayGroup.addOr(displayErrors);
171
		toolbar.add(displayErrors);
172
173
		JToggleButton displayWarnings = bf
174
				.createJToolbarToggleButton("DisplayWarningsButton");
175
		displayGroup.addOr(displayWarnings);
176
		toolbar.add(displayWarnings);
177
178
		JToggleButton displayMessages = bf
179
				.createJToolbarToggleButton("DisplayMessagesButton");
180
		displayGroup.addOr(displayMessages);
181
		toolbar.add(displayMessages);
182
183
		toolbar.add(new JToolbarSeparator());
184
185
		JButton clear = bf.createJToolbarButton("ClearButton");
186
		displayGroup.add(clear);
187
		toolbar.add(clear);
188
189
		return toolbar;
190
	}
191
192
	private class BooleanButtonGroup extends ButtonGroup implements
193
			ItemListener {
194
195
		private List orElements = new ArrayList();
196
197
		private AbstractButton orButton = new JToggleButton();
198
199
		public BooleanButtonGroup() {
200
			orButton.addItemListener(this);
201
			add(orButton);
202
		}
203
204
		public void itemStateChanged(ItemEvent e) {
205
			if (e.getSource() == orButton
206
					&& e.getStateChange() == ItemEvent.DESELECTED) {
207
				for (Iterator i = orElements.iterator(); i.hasNext();) {
208
					AbstractButton button = (AbstractButton) i.next();
209
					button.setSelected(false);
210
				}
211
			} else if (e.getStateChange() == ItemEvent.SELECTED) {
212
				setSelected(((AbstractButton) e.getSource()).getModel(), true);
213
			}
214
		}
215
216
		public void addOr(AbstractButton button) {
217
			orElements.add(button);
218
			button.addItemListener(this);
219
		}
220
221
		public void setSelected(ButtonModel model, boolean selected) {
222
			for (Iterator i = orElements.iterator(); i.hasNext();) {
223
				AbstractButton button = (AbstractButton) i.next();
224
				if (button.getModel() == model) {
225
					orButton.setSelected(selected);
226
					return;
227
				}
228
			}
229
			super.setSelected(model, selected);
230
		}
231
	}
232
233
	private JPopupMenu createPopupMenu() {
234
		JPopupMenu popupMenu = mf.createJMenu("PopupMenu").getPopupMenu();
235
		return popupMenu;
236
	}
237
238
	protected static ErrorConsole instance;
239
240
	public static ErrorConsole getInstance() {
241
		if (instance == null) {
242
			instance = new ErrorConsole();
243
		}
244
		return instance;
245
	}
246
247
	public static JDialog createDialog(Component owner, String title) {
248
		JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(owner),
249
				title);
250
		dialog.getContentPane().add(getInstance(), BorderLayout.CENTER);
251
		dialog.pack();
252
		return dialog;
253
	}
254
255
	public void add(Throwable th, String uri, int type) {
256
		ErrorButton errorButton = new ErrorButton(th, uri, type);
257
		errorButton.setPopupMenu(popupMenu);
258
		consoleList.add(errorButton);
259
		errorGroup.add(errorButton);
260
	}
261
262
	public void add(String elementName, String uri, int type) {
263
		ErrorButton errorButton = new ErrorButton(elementName, uri, type);
264
		errorButton.setPopupMenu(popupMenu);
265
		consoleList.add(errorButton);
266
		errorGroup.add(errorButton);
267
	}
268
269
	/**
270
	 * The map that contains the actions
271
	 */
272
	protected Map actions = new HashMap();
273
274
	/**
275
	 * Returns the action associated with the given string or null on error
276
	 * 
277
	 * @param key
278
	 *            the key mapped with the action to get
279
	 * @throws MissingListenerException
280
	 *             if the action is not found
281
	 */
282
	public Action getAction(String key) throws MissingListenerException {
283
		return (Action) actions.get(key);
284
	}
285
286
	/**
287
	 * The action associated with the 'All' button.
288
	 */
289
	protected class DisplayAllButtonAction extends AbstractAction {
290
291
		public void actionPerformed(ActionEvent evt) {
292
			displayType(-1, true);
293
		}
294
	}
295
296
	/**
297
	 * The action associated with the 'Errors' button.
298
	 */
299
	protected class DisplayErrorsButtonAction extends AbstractAction {
300
301
		public void actionPerformed(ActionEvent evt) {
302
			boolean selected = ((AbstractButton) evt.getSource()).isSelected();
303
			displayType(JOptionPane.ERROR_MESSAGE, selected);
304
		}
305
	}
306
307
	/**
308
	 * The action associated with the 'Warnings' button.
309
	 */
310
	protected class DisplayWarningsButtonAction extends AbstractAction {
311
312
		public void actionPerformed(ActionEvent evt) {
313
			boolean selected = ((AbstractButton) evt.getSource()).isSelected();
314
			displayType(JOptionPane.WARNING_MESSAGE, selected);
315
		}
316
	}
317
318
	/**
319
	 * The action associated with the 'Messages' button.
320
	 */
321
	protected class DisplayMessagesButtonAction extends AbstractAction {
322
323
		public void actionPerformed(ActionEvent evt) {
324
			boolean selected = ((AbstractButton) evt.getSource()).isSelected();
325
			displayType(JOptionPane.INFORMATION_MESSAGE, selected);
326
		}
327
	}
328
329
	/**
330
	 * The action associated with the 'Clear' button.
331
	 */
332
	protected class ClearButtonAction extends AbstractAction {
333
334
		public void actionPerformed(ActionEvent evt) {
335
			clearType(displayType);
336
			Enumeration<AbstractButton> buttons = errorGroup.getElements();
337
			while (buttons.hasMoreElements()) {
338
				errorGroup.remove(buttons.nextElement());
339
			}
340
		}
341
	}
342
343
	/**
344
	 * The action associated with the 'First to Last Sort' menu item.
345
	 */
346
	protected class FirstLastSortMenuAction extends AbstractAction {
347
348
		public void actionPerformed(ActionEvent evt) {
349
			if (sortOrderAscending) {
350
				return;
351
			}
352
			reverseComponentOrder(consoleList);
353
			sortOrderAscending = true;
354
		}
355
	}
356
357
	/**
358
	 * The action associated with the 'Last to First Sort' menu item.
359
	 */
360
	protected class LastFirstSortMenuAction extends AbstractAction {
361
362
		public void actionPerformed(ActionEvent evt) {
363
			if (!sortOrderAscending) {
364
				return;
365
			}
366
			reverseComponentOrder(consoleList);
367
			sortOrderAscending = false;
368
		}
369
	}
370
371
	private void reverseComponentOrder(Container container) {
372
		Component[] components = container.getComponents();
373
		consoleList.removeAll();
374
		for (int i = components.length - 1; i >= 0; i--) {
375
			consoleList.add(components[i]);
376
		}
377
	}
378
379
	/**
380
	 * The action associated with the 'Copy' menu item.
381
	 */
382
	protected class CopyMenuAction extends AbstractAction {
383
384
		public void actionPerformed(ActionEvent evt) {
385
386
		}
387
	}
388
389
	private void clearType(int type) {
390
		Component[] components = consoleList.getComponents();
391
		for (int i = 0; i < components.length; i++) {
392
			ErrorButton eb = (ErrorButton) components[i];
393
			if (type < 0 || eb.getType() == type) {
394
				consoleList.remove(eb);
395
			}
396
		}
397
	}
398
399
	private void displayType(int type, boolean visible) {
400
		displayType = type;
401
		Component[] components = consoleList.getComponents();
402
		for (Component c : components) {
403
			ErrorButton eb = (ErrorButton) c;
404
			if (type < 0 || (eb.getType() == type)) {
405
				eb.setVisible(visible);
406
			}
407
		}
408
	}
409
410
	private class ErrorButton extends JToggleButton {
411
412
		private int type;
413
414
		private JTextPane messageText;
415
416
		private Hyperlink link;
417
418
		private ImageIcon icon;
419
420
		private GradientPaint gradient;
421
422
		private JPanel details;
423
424
		private JPopupMenu popupMenu;
425
426
		private JTextArea detailText;
427
428
		private ItemListener il = new ItemListener() {
429
			public void itemStateChanged(ItemEvent e) {
430
				if (e.getStateChange() == ItemEvent.SELECTED) {
431
					details.setVisible(true);
432
				} else if (e.getStateChange() == ItemEvent.DESELECTED) {
433
					details.setVisible(false);
434
				} else {
435
					return;
436
				}
437
				repaint();
438
			}
439
		};
440
441
		private MouseListener ml = new MouseAdapter() {
442
			public void mouseClicked(MouseEvent e) {
443
				if (e.getButton() == MouseEvent.BUTTON3) {
444
					popupMenu.show(ErrorButton.this, e.getX(), e.getY());
445
				}
446
			}
447
		};
448
449
		public ErrorButton(int type) {
450
			this.type = type;
451
452
			setLayout(new BorderLayout(10, 10));
453
			setContentAreaFilled(false);
454
			setBorderPainted(false);
455
			setOpaque(false);
456
			setFocusPainted(false);
457
			setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
458
			addItemListener(il);
459
			addMouseListener(ml);
460
461
			String s;
462
			switch (type) {
463
			case JOptionPane.WARNING_MESSAGE:
464
				s = resources.getString("ErrorButton.warning_icon");
465
				break;
466
			case JOptionPane.INFORMATION_MESSAGE:
467
				s = resources.getString("ErrorButton.message_icon");
468
				break;
469
			case JOptionPane.ERROR_MESSAGE:
470
			default:
471
				s = resources.getString("ErrorButton.error_icon");
472
				break;
473
			}
474
			icon = new ImageIcon(getClass().getResource(s));
475
			add(new JLabel(icon), BorderLayout.WEST);
476
477
			Box centerPane = new Box(BoxLayout.Y_AXIS);
478
			add(centerPane);
479
480
			messageText = new JTextPane();
481
			messageText.setEditable(false);
482
			messageText.setOpaque(false);
483
			messageText.addMouseListener(new MouseAdapter() {
484
				public void mouseClicked(MouseEvent e) {
485
					ErrorButton.this.setSelected(true);
486
				}
487
			});
488
			centerPane.add(messageText, BorderLayout.NORTH);
489
490
			link = new Hyperlink("", new Hyperlink.HyperlinkCallback() {
491
				public void linkClicked(HyperlinkEvent e) {
492
					// new DocumentViewer(doc).setVisible(true);
493
				}
494
			});
495
			centerPane.add(link, BorderLayout.SOUTH);
496
497
			details = new JPanel(new BorderLayout());
498
			details.setOpaque(false);
499
			details.setVisible(false);
500
			add(details, BorderLayout.SOUTH);
501
502
			detailText = new JTextArea();
503
			detailText.setFont(new Font("Monospaced", Font.PLAIN, 12));
504
			detailText.setEditable(false);
505
			detailText.setLineWrap(true);
506
			final JScrollPane stackTraceScrollPane = new JScrollPane(detailText);
507
			stackTraceScrollPane.getViewport().setPreferredSize(
508
					new Dimension(300, 100));
509
			stackTraceScrollPane.setVisible(false);
510
			final JButton btnShowDetails = new JButton("Show Details >>");
511
			btnShowDetails.addActionListener(new ActionListener() {
512
				public void actionPerformed(ActionEvent e) {
513
					boolean visible = stackTraceScrollPane.isVisible();
514
					stackTraceScrollPane.setVisible(!visible);
515
					btnShowDetails.setText(visible ? "Show Details >>"
516
							: "<< Hide Details");
517
				}
518
			});
519
			JPanel button = new JPanel(new FlowLayout(FlowLayout.LEADING));
520
			button.setOpaque(false);
521
			button.add(btnShowDetails);
522
			details.add(button, BorderLayout.NORTH);
523
			details.add(stackTraceScrollPane);
524
525
			Dimension dim = getPreferredSize();
526
			gradient = new GradientPaint(0, 0, new Color(217, 226, 234), 0,
527
					2 * dim.height, new Color(193, 207, 221));
528
529
		}
530
531
		public ErrorButton(Throwable th, String uri, int type) {
532
			this(type);
533
534
			messageText.setText(th.getMessage());
535
536
			StringWriter sw = new StringWriter();
537
			th.printStackTrace(new PrintWriter(sw));
538
			sw.flush();
539
			detailText.setText(sw.toString());
540
		}
541
542
		public ErrorButton(String elementName, String uri, int type) {
543
			this(type);
544
545
			messageText.setText("Document uri: " + uri);
546
			String text;
547
			try {
548
				BufferedReader reader = new BufferedReader(new FileReader(ParsedURL.parseURL(uri).path));
549
				String line;
550
				StringBuilder sb = new StringBuilder();
551
				while ((line = reader.readLine()) != null) {
552
					sb.append(line + "\n");
553
				}
554
				text = sb.toString();
555
			} catch (Exception e) {
556
				e.printStackTrace();
557
				text = "Error reading file: " + uri;
558
			}
559
			detailText.setText(text);
560
561
			highlightElement(
562
					elementName,
563
					uri,
564
					detailText,
565
					new DefaultHighlighter.DefaultHighlightPainter(Color.yellow));
566
		}
567
568
		private void highlightElement(String name, String uri,
569
				JTextComponent textComponent, HighlightPainter hlPainter) {
570
			Highlighter highlighter = textComponent.getHighlighter();
571
			highlighter.removeAllHighlights();
572
			
573
			String text = textComponent.getText();
574
			for (int index = 0; (index = text.indexOf(name, index)) >= 0; index += name.length()) {
575
				try {
576
					highlighter.addHighlight(index, index + name.length(), hlPainter);
577
				} catch (BadLocationException e) {
578
					break;
579
				}
580
			}
581
		}
582
583
		public void paintComponent(Graphics g) {
584
			Graphics2D g2 = (Graphics2D) g;
585
			int width = getWidth(), height = getHeight();
586
			g2.setPaint(isSelected() ? gradient : Color.white);
587
			g2.fillRect(0, 0, width, height);
588
			g2.setColor(SystemColor.controlShadow);
589
			g2.drawLine(0, height - 1, width, height - 1);
590
			super.paintComponent(g);
591
		}
592
593
		public int getType() {
594
			return type;
595
		}
596
597
		public void setType(int type) {
598
			this.type = type;
599
			repaint();
600
		}
601
602
		public JPopupMenu getPopupMenu() {
603
			return popupMenu;
604
		}
605
606
		public void setPopupMenu(JPopupMenu popupMenu) {
607
			this.popupMenu = popupMenu;
608
		}
609
	}
610
611
	private static Locator searchLoc;
612
613
	public static void main(String[] args) throws Exception {
614
		ErrorConsole ec = ErrorConsole.getInstance();
615
		String uri = new File(System.getProperty("user.home")
616
				+ "/Desktop/batikws/xml-batik/rect.svg").toURI().toString();
617
		final Locator locator = new LocatorImpl();
618
		SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(null) {
619
		    public void startElement(String     uri,
620
                    String     localName,
621
                    String     rawName,
622
                    Attributes attributes) throws SAXException {
623
		    	super.startElement(uri, localName, rawName, attributes);
624
		    	
625
		    	System.out.println(localName);
626
		    	if (currentNode.getNodeName().equals("desc")) {
627
		    		searchLoc = new LocatorImpl(locator);
628
		    	}
629
		    }
630
		};
631
		f.setDocumentLocator(locator);
632
		Document doc = f.createDocument(uri);
633
		if (searchLoc != null) {
634
			System.out.println(searchLoc.getLineNumber() + ", " + searchLoc.getColumnNumber());
635
		}
636
		//ec.add(doc.getChildNodes(), uri, JOptionPane.ERROR_MESSAGE);
637
		ec.add(new Exception("Test Exception"), null,
638
				JOptionPane.WARNING_MESSAGE);
639
		ec.add(new Exception("Test Exception"), null,
640
				JOptionPane.INFORMATION_MESSAGE);
641
		JDialog d = ErrorConsole.createDialog(null, "Error Console 0.1");
642
		d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
643
		d.setVisible(true);
644
	}
645
}

Return to bug 42741