ASF Bugzilla – Attachment 20443 Details for
Bug 42741
Error Console and Timeline Viewer for Squiggle
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for error console and source viewer for squiggle
patch.txt (text/plain), 245.16 KB, created by
Jasleen Singh
on 2007-07-04 01:29:26 UTC
(
hide
)
Description:
Patch for error console and source viewer for squiggle
Filename:
MIME Type:
Creator:
Jasleen Singh
Created:
2007-07-04 01:29:26 UTC
Size:
245.16 KB
patch
obsolete
>Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/dom/svg/SVGContext.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/dom/svg/SVGContext.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/dom/svg/SVGContext.java (working copy) >@@ -94,4 +94,9 @@ > * Returns the font-size on the associated element. > */ > float getFontSize(); >+ >+ /** >+ * whether parsing should be strict (throw exception on error) or not >+ */ >+ boolean strictParsing = false; > } >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/svg/SVGUserAgentGUIAdapter.java (working copy) >@@ -22,6 +22,9 @@ > import java.awt.Component; > import javax.swing.JDialog; > import javax.swing.JOptionPane; >+ >+import org.apache.batik.swing.JSVGCanvas; >+import org.apache.batik.util.gui.ErrorConsole; > import org.apache.batik.util.gui.JErrorPane; > > /** >@@ -53,8 +56,11 @@ > * Displays an error resulting from the specified Exception. > */ > public void displayError(Exception ex) { >- JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(parentComponent, "ERROR"); >+// JErrorPane pane = new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ // <!FIX ME> Document is null for now, how to get access to it?? >+ console.add(ex, null, JOptionPane.ERROR_MESSAGE); >+ JDialog dialog = ErrorConsole.createDialog(parentComponent, "ERROR"); > dialog.setModal(false); > dialog.setVisible(true); > } >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/swing/JSVGCanvas.java (working copy) >@@ -57,6 +57,7 @@ > import org.apache.batik.swing.svg.SVGUserAgent; > import org.apache.batik.util.SVGConstants; > import org.apache.batik.util.XMLConstants; >+import org.apache.batik.util.gui.ErrorConsole; > import org.apache.batik.util.gui.JErrorPane; > > import org.w3c.dom.Element; >@@ -1070,9 +1071,11 @@ > if (svgUserAgent != null) { > super.displayError(ex); > } else { >- JErrorPane pane = >- new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(JSVGCanvas.this, "ERROR"); >+// JErrorPane pane = >+// new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ console.add(ex, getURI(), JOptionPane.ERROR_MESSAGE); >+ JDialog dialog = ErrorConsole.createDialog(JSVGCanvas.this, "ERROR"); > dialog.setModal(false); > dialog.setVisible(true); // Safe to be called from any thread > } >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java (working copy) >@@ -20,12 +20,15 @@ > > import java.io.InputStream; > import java.io.IOException; >+import java.lang.reflect.Proxy; > import java.util.HashMap; > > import org.apache.batik.dom.svg.SAXSVGDocumentFactory; > import org.apache.batik.dom.svg.SVGDocumentFactory; > import org.apache.batik.dom.util.DocumentDescriptor; >+import org.apache.batik.swing.svg.SVGDocumentLoader; > import org.apache.batik.util.CleanerThread; >+import org.apache.batik.util.gui.ErrorHandlerProxy; > > import org.w3c.dom.Document; > import org.w3c.dom.Element; >@@ -104,6 +107,13 @@ > return ret; > > SVGDocument document = documentFactory.createSVGDocument(uri); >+// System.out.println("Installing proxy"); >+// SVGDocumentFactory documentFactoryProxy = (SVGDocumentFactory) Proxy >+// .newProxyInstance(SVGDocumentFactory.class >+// .getClassLoader(), >+// new Class[] { SVGDocumentFactory.class }, >+// new ErrorHandlerProxy(documentFactory, uri)); >+// SVGDocument document = documentFactoryProxy.createSVGDocument(uri); > > DocumentDescriptor desc = documentFactory.getDocumentDescriptor(); > DocumentState state = new DocumentState(uri, document, desc); >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/SVGRectElementBridge.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/SVGRectElementBridge.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/bridge/SVGRectElementBridge.java (working copy) >@@ -22,12 +22,15 @@ > import java.awt.geom.Rectangle2D; > import java.awt.geom.RoundRectangle2D; > >+import javax.swing.JOptionPane; >+ > import org.apache.batik.dom.svg.AbstractSVGAnimatedLength; > import org.apache.batik.dom.svg.AnimatedLiveAttributeValue; > import org.apache.batik.dom.svg.LiveAttributeException; > import org.apache.batik.dom.svg.SVGOMRectElement; > import org.apache.batik.gvt.ShapeNode; > import org.apache.batik.gvt.ShapePainter; >+import org.apache.batik.util.gui.ErrorConsole; > > import org.w3c.dom.Element; > >@@ -116,7 +119,12 @@ > } > shapeNode.setShape(shape); > } catch (LiveAttributeException ex) { >- throw new BridgeException(ctx, ex); >+ if (strictParsing) { >+ throw new BridgeException(ctx, ex); >+ } else { >+ ctx.userAgent.displayError(ex); >+ shapeNode.setShape(new Rectangle2D.Float(0, 0, 0, 0)); >+ } > } > } > >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaPainter.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaPainter.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaPainter.java (revision 0) >@@ -0,0 +1,693 @@ >+/* >+ * TextAreaPainter.java - Paints the text area >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.ToolTipManager; >+import javax.swing.text.*; >+import javax.swing.JComponent; >+import java.awt.event.MouseEvent; >+import java.awt.*; >+ >+/** >+ * The text area repaint manager. It performs double buffering and paints >+ * lines of text. >+ * @author Slava Pestov >+ * @version $Id: TextAreaPainter.java,v 1.24 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class TextAreaPainter extends JComponent implements TabExpander >+{ >+ /** >+ * Creates a new repaint manager. This should be not be called >+ * directly. >+ */ >+ public TextAreaPainter(JEditTextArea textArea, TextAreaDefaults defaults) >+ { >+ this.textArea = textArea; >+ >+ setAutoscrolls(true); >+ setDoubleBuffered(true); >+ setOpaque(true); >+ >+ ToolTipManager.sharedInstance().registerComponent(this); >+ >+ currentLine = new Segment(); >+ currentLineIndex = -1; >+ >+ setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); >+ >+ setFont(new Font("Monospaced",Font.PLAIN,14)); >+ setForeground(Color.black); >+ setBackground(Color.white); >+ >+ blockCaret = defaults.blockCaret; >+ styles = defaults.styles; >+ cols = defaults.cols; >+ rows = defaults.rows; >+ caretColor = defaults.caretColor; >+ selectionColor = defaults.selectionColor; >+ lineHighlightColor = defaults.lineHighlightColor; >+ lineHighlight = defaults.lineHighlight; >+ bracketHighlightColor = defaults.bracketHighlightColor; >+ bracketHighlight = defaults.bracketHighlight; >+ paintInvalid = defaults.paintInvalid; >+ eolMarkerColor = defaults.eolMarkerColor; >+ eolMarkers = defaults.eolMarkers; >+ } >+ >+ /** >+ * Returns if this component can be traversed by pressing the >+ * Tab key. This returns false. >+ */ >+ public final boolean isManagingFocus() >+ { >+ return false; >+ } >+ >+ /** >+ * Returns the syntax styles used to paint colorized text. Entry <i>n</i> >+ * will be used to paint tokens with id = <i>n</i>. >+ * @see org.gjt.sp.jedit.syntax.Token >+ */ >+ public final SyntaxStyle[] getStyles() >+ { >+ return styles; >+ } >+ >+ /** >+ * Sets the syntax styles used to paint colorized text. Entry <i>n</i> >+ * will be used to paint tokens with id = <i>n</i>. >+ * @param styles The syntax styles >+ * @see org.gjt.sp.jedit.syntax.Token >+ */ >+ public final void setStyles(SyntaxStyle[] styles) >+ { >+ this.styles = styles; >+ repaint(); >+ } >+ >+ /** >+ * Returns the caret color. >+ */ >+ public final Color getCaretColor() >+ { >+ return caretColor; >+ } >+ >+ /** >+ * Sets the caret color. >+ * @param caretColor The caret color >+ */ >+ public final void setCaretColor(Color caretColor) >+ { >+ this.caretColor = caretColor; >+ invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns the selection color. >+ */ >+ public final Color getSelectionColor() >+ { >+ return selectionColor; >+ } >+ >+ /** >+ * Sets the selection color. >+ * @param selectionColor The selection color >+ */ >+ public final void setSelectionColor(Color selectionColor) >+ { >+ this.selectionColor = selectionColor; >+ invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns the line highlight color. >+ */ >+ public final Color getLineHighlightColor() >+ { >+ return lineHighlightColor; >+ } >+ >+ /** >+ * Sets the line highlight color. >+ * @param lineHighlightColor The line highlight color >+ */ >+ public final void setLineHighlightColor(Color lineHighlightColor) >+ { >+ this.lineHighlightColor = lineHighlightColor; >+ invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns true if line highlight is enabled, false otherwise. >+ */ >+ public final boolean isLineHighlightEnabled() >+ { >+ return lineHighlight; >+ } >+ >+ /** >+ * Enables or disables current line highlighting. >+ * @param lineHighlight True if current line highlight should be enabled, >+ * false otherwise >+ */ >+ public final void setLineHighlightEnabled(boolean lineHighlight) >+ { >+ this.lineHighlight = lineHighlight; >+ invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns the bracket highlight color. >+ */ >+ public final Color getBracketHighlightColor() >+ { >+ return bracketHighlightColor; >+ } >+ >+ /** >+ * Sets the bracket highlight color. >+ * @param bracketHighlightColor The bracket highlight color >+ */ >+ public final void setBracketHighlightColor(Color bracketHighlightColor) >+ { >+ this.bracketHighlightColor = bracketHighlightColor; >+ invalidateLine(textArea.getBracketLine()); >+ } >+ >+ /** >+ * Returns true if bracket highlighting is enabled, false otherwise. >+ * When bracket highlighting is enabled, the bracket matching the >+ * one before the caret (if any) is highlighted. >+ */ >+ public final boolean isBracketHighlightEnabled() >+ { >+ return bracketHighlight; >+ } >+ >+ /** >+ * Enables or disables bracket highlighting. >+ * When bracket highlighting is enabled, the bracket matching the >+ * one before the caret (if any) is highlighted. >+ * @param bracketHighlight True if bracket highlighting should be >+ * enabled, false otherwise >+ */ >+ public final void setBracketHighlightEnabled(boolean bracketHighlight) >+ { >+ this.bracketHighlight = bracketHighlight; >+ invalidateLine(textArea.getBracketLine()); >+ } >+ >+ /** >+ * Returns true if the caret should be drawn as a block, false otherwise. >+ */ >+ public final boolean isBlockCaretEnabled() >+ { >+ return blockCaret; >+ } >+ >+ /** >+ * Sets if the caret should be drawn as a block, false otherwise. >+ * @param blockCaret True if the caret should be drawn as a block, >+ * false otherwise. >+ */ >+ public final void setBlockCaretEnabled(boolean blockCaret) >+ { >+ this.blockCaret = blockCaret; >+ invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns the EOL marker color. >+ */ >+ public final Color getEOLMarkerColor() >+ { >+ return eolMarkerColor; >+ } >+ >+ /** >+ * Sets the EOL marker color. >+ * @param eolMarkerColor The EOL marker color >+ */ >+ public final void setEOLMarkerColor(Color eolMarkerColor) >+ { >+ this.eolMarkerColor = eolMarkerColor; >+ repaint(); >+ } >+ >+ /** >+ * Returns true if EOL markers are drawn, false otherwise. >+ */ >+ public final boolean getEOLMarkersPainted() >+ { >+ return eolMarkers; >+ } >+ >+ /** >+ * Sets if EOL markers are to be drawn. >+ * @param eolMarkers True if EOL markers should be drawn, false otherwise >+ */ >+ public final void setEOLMarkersPainted(boolean eolMarkers) >+ { >+ this.eolMarkers = eolMarkers; >+ repaint(); >+ } >+ >+ /** >+ * Returns true if invalid lines are painted as red tildes (~), >+ * false otherwise. >+ */ >+ public boolean getInvalidLinesPainted() >+ { >+ return paintInvalid; >+ } >+ >+ /** >+ * Sets if invalid lines are to be painted as red tildes. >+ * @param paintInvalid True if invalid lines should be drawn, false otherwise >+ */ >+ public void setInvalidLinesPainted(boolean paintInvalid) >+ { >+ this.paintInvalid = paintInvalid; >+ } >+ >+ /** >+ * Adds a custom highlight painter. >+ * @param highlight The highlight >+ */ >+ public void addCustomHighlight(Highlight highlight) >+ { >+ highlight.init(textArea,highlights); >+ highlights = highlight; >+ } >+ >+ /** >+ * Highlight interface. >+ */ >+ public interface Highlight >+ { >+ /** >+ * Called after the highlight painter has been added. >+ * @param textArea The text area >+ * @param next The painter this one should delegate to >+ */ >+ void init(JEditTextArea textArea, Highlight next); >+ >+ /** >+ * This should paint the highlight and delgate to the >+ * next highlight painter. >+ * @param gfx The graphics context >+ * @param line The line number >+ * @param y The y co-ordinate of the line >+ */ >+ void paintHighlight(Graphics gfx, int line, int y); >+ >+ /** >+ * Returns the tool tip to display at the specified >+ * location. If this highlighter doesn't know what to >+ * display, it should delegate to the next highlight >+ * painter. >+ * @param evt The mouse event >+ */ >+ String getToolTipText(MouseEvent evt); >+ } >+ >+ /** >+ * Returns the tool tip to display at the specified location. >+ * @param evt The mouse event >+ */ >+ public String getToolTipText(MouseEvent evt) >+ { >+ if(highlights != null) >+ return highlights.getToolTipText(evt); >+ else >+ return null; >+ } >+ >+ /** >+ * Returns the font metrics used by this component. >+ */ >+ public FontMetrics getFontMetrics() >+ { >+ return fm; >+ } >+ >+ /** >+ * Sets the font for this component. This is overridden to update the >+ * cached font metrics and to recalculate which lines are visible. >+ * @param font The font >+ */ >+ public void setFont(Font font) >+ { >+ super.setFont(font); >+ fm = Toolkit.getDefaultToolkit().getFontMetrics(font); >+ textArea.recalculateVisibleLines(); >+ } >+ >+ /** >+ * Repaints the text. >+ * @param g The graphics context >+ */ >+ public void paint(Graphics gfx) >+ { >+ tabSize = fm.charWidth(' ') * ((Integer)textArea >+ .getDocument().getProperty( >+ PlainDocument.tabSizeAttribute)).intValue(); >+ >+ Rectangle clipRect = gfx.getClipBounds(); >+ >+ gfx.setColor(getBackground()); >+ gfx.fillRect(clipRect.x,clipRect.y,clipRect.width,clipRect.height); >+ >+ // We don't use yToLine() here because that method doesn't >+ // return lines past the end of the document >+ int height = fm.getHeight(); >+ int firstLine = textArea.getFirstLine(); >+ int firstInvalid = firstLine + clipRect.y / height; >+ // Because the clipRect's height is usually an even multiple >+ // of the font height, we subtract 1 from it, otherwise one >+ // too many lines will always be painted. >+ int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height; >+ >+ try >+ { >+ TokenMarker tokenMarker = textArea.getDocument() >+ .getTokenMarker(); >+ int x = textArea.getHorizontalOffset(); >+ >+ for(int line = firstInvalid; line <= lastInvalid; line++) >+ { >+ paintLine(gfx,tokenMarker,line,x); >+ } >+ >+ if(tokenMarker != null && tokenMarker.isNextLineRequested()) >+ { >+ int h = clipRect.y + clipRect.height; >+ repaint(0,h,getWidth(),getHeight() - h); >+ } >+ } >+ catch(Exception e) >+ { >+ System.err.println("Error repainting line" >+ + " range {" + firstInvalid + "," >+ + lastInvalid + "}:"); >+ e.printStackTrace(); >+ } >+ } >+ >+ /** >+ * Marks a line as needing a repaint. >+ * @param line The line to invalidate >+ */ >+ public final void invalidateLine(int line) >+ { >+ repaint(0,textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(), >+ getWidth(),fm.getHeight()); >+ } >+ >+ /** >+ * Marks a range of lines as needing a repaint. >+ * @param firstLine The first line to invalidate >+ * @param lastLine The last line to invalidate >+ */ >+ public final void invalidateLineRange(int firstLine, int lastLine) >+ { >+ repaint(0,textArea.lineToY(firstLine) + fm.getMaxDescent() + fm.getLeading(), >+ getWidth(),(lastLine - firstLine + 1) * fm.getHeight()); >+ } >+ >+ /** >+ * Repaints the lines containing the selection. >+ */ >+ public final void invalidateSelectedLines() >+ { >+ invalidateLineRange(textArea.getSelectionStartLine(), >+ textArea.getSelectionEndLine()); >+ } >+ >+ /** >+ * Implementation of TabExpander interface. Returns next tab stop after >+ * a specified point. >+ * @param x The x co-ordinate >+ * @param tabOffset Ignored >+ * @return The next tab stop after <i>x</i> >+ */ >+ public float nextTabStop(float x, int tabOffset) >+ { >+ int offset = textArea.getHorizontalOffset(); >+ int ntabs = ((int)x - offset) / tabSize; >+ return (ntabs + 1) * tabSize + offset; >+ } >+ >+ /** >+ * Returns the painter's preferred size. >+ */ >+ public Dimension getPreferredSize() >+ { >+ Dimension dim = new Dimension(); >+ dim.width = fm.charWidth('w') * cols; >+ dim.height = fm.getHeight() * rows; >+ return dim; >+ } >+ >+ >+ /** >+ * Returns the painter's minimum size. >+ */ >+ public Dimension getMinimumSize() >+ { >+ return getPreferredSize(); >+ } >+ >+ // package-private members >+ int currentLineIndex; >+ Token currentLineTokens; >+ Segment currentLine; >+ >+ // protected members >+ protected JEditTextArea textArea; >+ >+ protected SyntaxStyle[] styles; >+ protected Color caretColor; >+ protected Color selectionColor; >+ protected Color lineHighlightColor; >+ protected Color bracketHighlightColor; >+ protected Color eolMarkerColor; >+ >+ protected boolean blockCaret; >+ protected boolean lineHighlight; >+ protected boolean bracketHighlight; >+ protected boolean paintInvalid; >+ protected boolean eolMarkers; >+ protected int cols; >+ protected int rows; >+ >+ protected int tabSize; >+ protected FontMetrics fm; >+ >+ protected Highlight highlights; >+ >+ protected void paintLine(Graphics gfx, TokenMarker tokenMarker, >+ int line, int x) >+ { >+ Font defaultFont = getFont(); >+ Color defaultColor = getForeground(); >+ >+ currentLineIndex = line; >+ int y = textArea.lineToY(line); >+ >+ if(line < 0 || line >= textArea.getLineCount()) >+ { >+ if(paintInvalid) >+ { >+ paintHighlight(gfx,line,y); >+ styles[Token.INVALID].setGraphicsFlags(gfx,defaultFont); >+ gfx.drawString("~",0,y + fm.getHeight()); >+ } >+ } >+ else if(tokenMarker == null) >+ { >+ paintPlainLine(gfx,line,defaultFont,defaultColor,x,y); >+ } >+ else >+ { >+ paintSyntaxLine(gfx,tokenMarker,line,defaultFont, >+ defaultColor,x,y); >+ } >+ } >+ >+ protected void paintPlainLine(Graphics gfx, int line, Font defaultFont, >+ Color defaultColor, int x, int y) >+ { >+ paintHighlight(gfx,line,y); >+ textArea.getLineText(line,currentLine); >+ >+ gfx.setFont(defaultFont); >+ gfx.setColor(defaultColor); >+ >+ y += fm.getHeight(); >+ x = Utilities.drawTabbedText(currentLine,x,y,gfx,this,0); >+ >+ if(eolMarkers) >+ { >+ gfx.setColor(eolMarkerColor); >+ gfx.drawString(".",x,y); >+ } >+ } >+ >+ protected void paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker, >+ int line, Font defaultFont, Color defaultColor, int x, int y) >+ { >+ textArea.getLineText(currentLineIndex,currentLine); >+ currentLineTokens = tokenMarker.markTokens(currentLine, >+ currentLineIndex); >+ >+ paintHighlight(gfx,line,y); >+ >+ gfx.setFont(defaultFont); >+ gfx.setColor(defaultColor); >+ y += fm.getHeight(); >+ x = SyntaxUtilities.paintSyntaxLine(currentLine, >+ currentLineTokens,styles,this,gfx,x,y); >+ >+ if(eolMarkers) >+ { >+ gfx.setColor(eolMarkerColor); >+ gfx.drawString(".",x,y); >+ } >+ } >+ >+ protected void paintHighlight(Graphics gfx, int line, int y) >+ { >+ if(line >= textArea.getSelectionStartLine() >+ && line <= textArea.getSelectionEndLine()) >+ paintLineHighlight(gfx,line,y); >+ >+ if(highlights != null) >+ highlights.paintHighlight(gfx,line,y); >+ >+ if(bracketHighlight && line == textArea.getBracketLine()) >+ paintBracketHighlight(gfx,line,y); >+ >+ if(line == textArea.getCaretLine()) >+ paintCaret(gfx,line,y); >+ } >+ >+ protected void paintLineHighlight(Graphics gfx, int line, int y) >+ { >+ int height = fm.getHeight(); >+ y += fm.getLeading() + fm.getMaxDescent(); >+ >+ int selectionStart = textArea.getSelectionStart(); >+ int selectionEnd = textArea.getSelectionEnd(); >+ >+ if(selectionStart == selectionEnd) >+ { >+ if(lineHighlight) >+ { >+ gfx.setColor(lineHighlightColor); >+ gfx.fillRect(0,y,getWidth(),height); >+ } >+ } >+ else >+ { >+ gfx.setColor(selectionColor); >+ >+ int selectionStartLine = textArea.getSelectionStartLine(); >+ int selectionEndLine = textArea.getSelectionEndLine(); >+ int lineStart = textArea.getLineStartOffset(line); >+ >+ int x1, x2; >+ if(textArea.isSelectionRectangular()) >+ { >+ int lineLen = textArea.getLineLength(line); >+ x1 = textArea._offsetToX(line,Math.min(lineLen, >+ selectionStart - textArea.getLineStartOffset( >+ selectionStartLine))); >+ x2 = textArea._offsetToX(line,Math.min(lineLen, >+ selectionEnd - textArea.getLineStartOffset( >+ selectionEndLine))); >+ if(x1 == x2) >+ x2++; >+ } >+ else if(selectionStartLine == selectionEndLine) >+ { >+ x1 = textArea._offsetToX(line, >+ selectionStart - lineStart); >+ x2 = textArea._offsetToX(line, >+ selectionEnd - lineStart); >+ } >+ else if(line == selectionStartLine) >+ { >+ x1 = textArea._offsetToX(line, >+ selectionStart - lineStart); >+ x2 = getWidth(); >+ } >+ else if(line == selectionEndLine) >+ { >+ x1 = 0; >+ x2 = textArea._offsetToX(line, >+ selectionEnd - lineStart); >+ } >+ else >+ { >+ x1 = 0; >+ x2 = getWidth(); >+ } >+ >+ // "inlined" min/max() >+ gfx.fillRect(x1 > x2 ? x2 : x1,y,x1 > x2 ? >+ (x1 - x2) : (x2 - x1),height); >+ } >+ >+ } >+ >+ protected void paintBracketHighlight(Graphics gfx, int line, int y) >+ { >+ int position = textArea.getBracketPosition(); >+ if(position == -1) >+ return; >+ y += fm.getLeading() + fm.getMaxDescent(); >+ int x = textArea._offsetToX(line,position); >+ gfx.setColor(bracketHighlightColor); >+ // Hack!!! Since there is no fast way to get the character >+ // from the bracket matching routine, we use ( since all >+ // brackets probably have the same width anyway >+ gfx.drawRect(x,y,fm.charWidth('(') - 1, >+ fm.getHeight() - 1); >+ } >+ >+ protected void paintCaret(Graphics gfx, int line, int y) >+ { >+ if(textArea.isCaretVisible()) >+ { >+ int offset = textArea.getCaretPosition() >+ - textArea.getLineStartOffset(line); >+ int caretX = textArea._offsetToX(line,offset); >+ int caretWidth = ((blockCaret || >+ textArea.isOverwriteEnabled()) ? >+ fm.charWidth('w') : 1); >+ y += fm.getLeading() + fm.getMaxDescent(); >+ int height = fm.getHeight(); >+ >+ gfx.setColor(caretColor); >+ >+ if(textArea.isOverwriteEnabled()) >+ { >+ gfx.fillRect(caretX,y + height - 1, >+ caretWidth,1); >+ } >+ else >+ { >+ gfx.drawRect(caretX,y,caretWidth - 1,height - 1); >+ } >+ } >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/DefaultInputHandler.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/DefaultInputHandler.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/DefaultInputHandler.java (revision 0) >@@ -0,0 +1,347 @@ >+/* >+ * DefaultInputHandler.java - Default implementation of an input handler >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.KeyStroke; >+import java.awt.event.*; >+import java.awt.Toolkit; >+import java.util.Hashtable; >+import java.util.StringTokenizer; >+ >+/** >+ * The default input handler. It maps sequences of keystrokes into actions >+ * and inserts key typed events into the text area. >+ * @author Slava Pestov >+ * @version $Id: DefaultInputHandler.java,v 1.18 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class DefaultInputHandler extends InputHandler >+{ >+ /** >+ * Creates a new input handler with no key bindings defined. >+ */ >+ public DefaultInputHandler() >+ { >+ bindings = currentBindings = new Hashtable(); >+ } >+ >+ /** >+ * Sets up the default key bindings. >+ */ >+ public void addDefaultKeyBindings() >+ { >+ addKeyBinding("BACK_SPACE",BACKSPACE); >+ addKeyBinding("C+BACK_SPACE",BACKSPACE_WORD); >+ addKeyBinding("DELETE",DELETE); >+ addKeyBinding("C+DELETE",DELETE_WORD); >+ >+ addKeyBinding("ENTER",INSERT_BREAK); >+ addKeyBinding("TAB",INSERT_TAB); >+ >+ addKeyBinding("INSERT",OVERWRITE); >+ addKeyBinding("C+\\",TOGGLE_RECT); >+ >+ addKeyBinding("HOME",HOME); >+ addKeyBinding("END",END); >+ addKeyBinding("S+HOME",SELECT_HOME); >+ addKeyBinding("S+END",SELECT_END); >+ addKeyBinding("C+HOME",DOCUMENT_HOME); >+ addKeyBinding("C+END",DOCUMENT_END); >+ addKeyBinding("CS+HOME",SELECT_DOC_HOME); >+ addKeyBinding("CS+END",SELECT_DOC_END); >+ >+ addKeyBinding("PAGE_UP",PREV_PAGE); >+ addKeyBinding("PAGE_DOWN",NEXT_PAGE); >+ addKeyBinding("S+PAGE_UP",SELECT_PREV_PAGE); >+ addKeyBinding("S+PAGE_DOWN",SELECT_NEXT_PAGE); >+ >+ addKeyBinding("LEFT",PREV_CHAR); >+ addKeyBinding("S+LEFT",SELECT_PREV_CHAR); >+ addKeyBinding("C+LEFT",PREV_WORD); >+ addKeyBinding("CS+LEFT",SELECT_PREV_WORD); >+ addKeyBinding("RIGHT",NEXT_CHAR); >+ addKeyBinding("S+RIGHT",SELECT_NEXT_CHAR); >+ addKeyBinding("C+RIGHT",NEXT_WORD); >+ addKeyBinding("CS+RIGHT",SELECT_NEXT_WORD); >+ addKeyBinding("UP",PREV_LINE); >+ addKeyBinding("S+UP",SELECT_PREV_LINE); >+ addKeyBinding("DOWN",NEXT_LINE); >+ addKeyBinding("S+DOWN",SELECT_NEXT_LINE); >+ >+ addKeyBinding("C+ENTER",REPEAT); >+ } >+ >+ /** >+ * Adds a key binding to this input handler. The key binding is >+ * a list of white space separated key strokes of the form >+ * <i>[modifiers+]key</i> where modifier is C for Control, A for Alt, >+ * or S for Shift, and key is either a character (a-z) or a field >+ * name in the KeyEvent class prefixed with VK_ (e.g., BACK_SPACE) >+ * @param keyBinding The key binding >+ * @param action The action >+ */ >+ public void addKeyBinding(String keyBinding, ActionListener action) >+ { >+ Hashtable current = bindings; >+ >+ StringTokenizer st = new StringTokenizer(keyBinding); >+ while(st.hasMoreTokens()) >+ { >+ KeyStroke keyStroke = parseKeyStroke(st.nextToken()); >+ if(keyStroke == null) >+ return; >+ >+ if(st.hasMoreTokens()) >+ { >+ Object o = current.get(keyStroke); >+ if(o instanceof Hashtable) >+ current = (Hashtable)o; >+ else >+ { >+ o = new Hashtable(); >+ current.put(keyStroke,o); >+ current = (Hashtable)o; >+ } >+ } >+ else >+ current.put(keyStroke,action); >+ } >+ } >+ >+ /** >+ * Removes a key binding from this input handler. This is not yet >+ * implemented. >+ * @param keyBinding The key binding >+ */ >+ public void removeKeyBinding(String keyBinding) >+ { >+ throw new InternalError("Not yet implemented"); >+ } >+ >+ /** >+ * Removes all key bindings from this input handler. >+ */ >+ public void removeAllKeyBindings() >+ { >+ bindings.clear(); >+ } >+ >+ /** >+ * Returns a copy of this input handler that shares the same >+ * key bindings. Setting key bindings in the copy will also >+ * set them in the original. >+ */ >+ public InputHandler copy() >+ { >+ return new DefaultInputHandler(this); >+ } >+ >+ /** >+ * Handle a key pressed event. This will look up the binding for >+ * the key stroke and execute it. >+ */ >+ public void keyPressed(KeyEvent evt) >+ { >+ int keyCode = evt.getKeyCode(); >+ int modifiers = evt.getModifiers(); >+ >+ if(keyCode == KeyEvent.VK_CONTROL || >+ keyCode == KeyEvent.VK_SHIFT || >+ keyCode == KeyEvent.VK_ALT || >+ keyCode == KeyEvent.VK_META) >+ return; >+ >+ if((modifiers & ~KeyEvent.SHIFT_MASK) != 0 >+ || evt.isActionKey() >+ || keyCode == KeyEvent.VK_BACK_SPACE >+ || keyCode == KeyEvent.VK_DELETE >+ || keyCode == KeyEvent.VK_ENTER >+ || keyCode == KeyEvent.VK_TAB >+ || keyCode == KeyEvent.VK_ESCAPE) >+ { >+ if(grabAction != null) >+ { >+ handleGrabAction(evt); >+ return; >+ } >+ >+ KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, >+ modifiers); >+ Object o = currentBindings.get(keyStroke); >+ if(o == null) >+ { >+ // Don't beep if the user presses some >+ // key we don't know about unless a >+ // prefix is active. Otherwise it will >+ // beep when caps lock is pressed, etc. >+ if(currentBindings != bindings) >+ { >+ Toolkit.getDefaultToolkit().beep(); >+ // F10 should be passed on, but C+e F10 >+ // shouldn't >+ repeatCount = 0; >+ repeat = false; >+ evt.consume(); >+ } >+ currentBindings = bindings; >+ return; >+ } >+ else if(o instanceof ActionListener) >+ { >+ currentBindings = bindings; >+ >+ executeAction(((ActionListener)o), >+ evt.getSource(),null); >+ >+ evt.consume(); >+ return; >+ } >+ else if(o instanceof Hashtable) >+ { >+ currentBindings = (Hashtable)o; >+ evt.consume(); >+ return; >+ } >+ } >+ } >+ >+ /** >+ * Handle a key typed event. This inserts the key into the text area. >+ */ >+ public void keyTyped(KeyEvent evt) >+ { >+ int modifiers = evt.getModifiers(); >+ char c = evt.getKeyChar(); >+ if(c != KeyEvent.CHAR_UNDEFINED && >+ (modifiers & KeyEvent.ALT_MASK) == 0) >+ { >+ if(c >= 0x20 && c != 0x7f) >+ { >+ KeyStroke keyStroke = KeyStroke.getKeyStroke( >+ Character.toUpperCase(c)); >+ Object o = currentBindings.get(keyStroke); >+ >+ if(o instanceof Hashtable) >+ { >+ currentBindings = (Hashtable)o; >+ return; >+ } >+ else if(o instanceof ActionListener) >+ { >+ currentBindings = bindings; >+ executeAction((ActionListener)o, >+ evt.getSource(), >+ String.valueOf(c)); >+ return; >+ } >+ >+ currentBindings = bindings; >+ >+ if(grabAction != null) >+ { >+ handleGrabAction(evt); >+ return; >+ } >+ >+ // 0-9 adds another 'digit' to the repeat number >+ if(repeat && Character.isDigit(c)) >+ { >+ repeatCount *= 10; >+ repeatCount += (c - '0'); >+ return; >+ } >+ >+ executeAction(INSERT_CHAR,evt.getSource(), >+ String.valueOf(evt.getKeyChar())); >+ >+ repeatCount = 0; >+ repeat = false; >+ } >+ } >+ } >+ >+ /** >+ * Converts a string to a keystroke. The string should be of the >+ * form <i>modifiers</i>+<i>shortcut</i> where <i>modifiers</i> >+ * is any combination of A for Alt, C for Control, S for Shift >+ * or M for Meta, and <i>shortcut</i> is either a single character, >+ * or a keycode name from the <code>KeyEvent</code> class, without >+ * the <code>VK_</code> prefix. >+ * @param keyStroke A string description of the key stroke >+ */ >+ public static KeyStroke parseKeyStroke(String keyStroke) >+ { >+ if(keyStroke == null) >+ return null; >+ int modifiers = 0; >+ int index = keyStroke.indexOf('+'); >+ if(index != -1) >+ { >+ for(int i = 0; i < index; i++) >+ { >+ switch(Character.toUpperCase(keyStroke >+ .charAt(i))) >+ { >+ case 'A': >+ modifiers |= InputEvent.ALT_MASK; >+ break; >+ case 'C': >+ modifiers |= InputEvent.CTRL_MASK; >+ break; >+ case 'M': >+ modifiers |= InputEvent.META_MASK; >+ break; >+ case 'S': >+ modifiers |= InputEvent.SHIFT_MASK; >+ break; >+ } >+ } >+ } >+ String key = keyStroke.substring(index + 1); >+ if(key.length() == 1) >+ { >+ char ch = Character.toUpperCase(key.charAt(0)); >+ if(modifiers == 0) >+ return KeyStroke.getKeyStroke(ch); >+ else >+ return KeyStroke.getKeyStroke(ch,modifiers); >+ } >+ else if(key.length() == 0) >+ { >+ System.err.println("Invalid key stroke: " + keyStroke); >+ return null; >+ } >+ else >+ { >+ int ch; >+ >+ try >+ { >+ ch = KeyEvent.class.getField("VK_".concat(key)) >+ .getInt(null); >+ } >+ catch(Exception e) >+ { >+ System.err.println("Invalid key stroke: " >+ + keyStroke); >+ return null; >+ } >+ >+ return KeyStroke.getKeyStroke(ch,modifiers); >+ } >+ } >+ >+ // private members >+ private Hashtable bindings; >+ private Hashtable currentBindings; >+ >+ private DefaultInputHandler(DefaultInputHandler copy) >+ { >+ bindings = currentBindings = copy.bindings; >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/XMLTokenMarker.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/XMLTokenMarker.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/XMLTokenMarker.java (revision 0) >@@ -0,0 +1,190 @@ >+/* >+ * XMLTokenMarker.java - XML token marker >+ * Copyright (C) 1998, 1999 Slava Pestov >+ * Copyright (C) 2001 Tom Bradford >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.Segment; >+ >+/** >+ * XML Token Marker Rewrite >+ * >+ * @author Tom Bradford >+ * @version $Id: XMLTokenMarker.java,v 1.5 2001/07/29 20:45:43 tom Exp $ >+ */ >+public class XMLTokenMarker extends TokenMarker { >+ public XMLTokenMarker() { >+ } >+ >+ public byte markTokensImpl(byte token, Segment line, int lineIndex) { >+ char[] array = line.array; >+ int offset = line.offset; >+ int lastOffset = offset; >+ int length = line.count + offset; >+ >+ // Ugly hack to handle multi-line tags >+ boolean sk1 = token == Token.KEYWORD1; >+ >+ for ( int i = offset; i < length; i++ ) { >+ int ip1 = i+1; >+ char c = array[i]; >+ switch ( token ) { >+ case Token.NULL: // text >+ switch ( c ) { >+ case '<': >+ addToken(i-lastOffset, token); >+ lastOffset = i; >+ if ( SyntaxUtilities.regionMatches(false, line, ip1, "!--") ) { >+ i += 3; >+ token = Token.COMMENT1; >+ } >+ else if ( array[ip1] == '!' ) { >+ i += 1; >+ token = Token.COMMENT2; >+ } >+ else if ( array[ip1] == '?' ) { >+ i += 1; >+ token = Token.KEYWORD3; >+ } >+ else >+ token = Token.KEYWORD1; >+ break; >+ >+ case '&': >+ addToken(i - lastOffset, token); >+ lastOffset = i; >+ token = Token.LABEL; >+ break; >+ } >+ break; >+ >+ case Token.KEYWORD1: // tag >+ switch ( c ) { >+ case '>': >+ addToken(ip1-lastOffset, token); >+ lastOffset = ip1; >+ token = Token.NULL; >+ sk1 = false; >+ break; >+ >+ case ' ': >+ case '\t': >+ addToken(i-lastOffset, token); >+ lastOffset = i; >+ token = Token.KEYWORD2; >+ sk1 = false; >+ break; >+ >+ default: >+ if ( sk1 ) { >+ token = Token.KEYWORD2; >+ sk1 = false; >+ } >+ break; >+ } >+ break; >+ >+ case Token.KEYWORD2: // attribute >+ switch ( c ) { >+ case '>': >+ addToken(ip1-lastOffset, token); >+ lastOffset = ip1; >+ token = Token.NULL; >+ break; >+ >+ case '/': >+ addToken(i-lastOffset, token); >+ lastOffset = i; >+ token = Token.KEYWORD1; >+ break; >+ >+ case '=': >+ addToken(i-lastOffset, token); >+ lastOffset = i; >+ token = Token.OPERATOR; >+ } >+ break; >+ >+ case Token.OPERATOR: // equal for attribute >+ switch ( c ) { >+ case '\"': >+ case '\'': >+ addToken(i-lastOffset, token); >+ lastOffset = i; >+ if ( c == '\"' ) >+ token = Token.LITERAL1; >+ else >+ token = Token.LITERAL2; >+ break; >+ } >+ break; >+ >+ case Token.LITERAL1: >+ case Token.LITERAL2: // strings >+ if ( ( token == Token.LITERAL1 && c == '\"' ) >+ || ( token == Token.LITERAL2 && c == '\'' ) ) { >+ addToken(ip1-lastOffset, token); >+ lastOffset = ip1; >+ token = Token.KEYWORD1; >+ } >+ break; >+ >+ case Token.LABEL: // entity >+ if ( c == ';' ) { >+ addToken(ip1-lastOffset, token); >+ lastOffset = ip1; >+ token = Token.NULL; >+ break; >+ } >+ break; >+ >+ case Token.COMMENT1: // Inside a comment >+ if ( SyntaxUtilities.regionMatches(false, line, i, "-->") ) { >+ addToken((i+3)-lastOffset, token); >+ lastOffset = i+3; >+ token = Token.NULL; >+ } >+ break; >+ >+ case Token.COMMENT2: // Inside a declaration >+ if ( SyntaxUtilities.regionMatches(false, line, i, ">") ) { >+ addToken(ip1-lastOffset, token); >+ lastOffset = ip1; >+ token = Token.NULL; >+ } >+ break; >+ >+ case Token.KEYWORD3: // Inside a processor instruction >+ if ( SyntaxUtilities.regionMatches(false, line, i, "?>") ) { >+ addToken((i+2)-lastOffset, token); >+ lastOffset = i+2; >+ token = Token.NULL; >+ } >+ break; >+ >+ default: >+ throw new InternalError("Invalid state: " + token); >+ } >+ } >+ >+ switch ( token ) { >+ case Token.LABEL: >+ addToken(length-lastOffset, Token.INVALID); >+ token = Token.NULL; >+ break; >+ >+ default: >+ addToken(length-lastOffset, token); >+ break; >+ } >+ >+ return token; >+ } >+} >+ >+ >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaDefaults.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaDefaults.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextAreaDefaults.java (revision 0) >@@ -0,0 +1,83 @@ >+/* >+ * TextAreaDefaults.java - Encapsulates default values for various settings >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.JPopupMenu; >+import java.awt.Color; >+ >+/** >+ * Encapsulates default settings for a text area. This can be passed >+ * to the constructor once the necessary fields have been filled out. >+ * The advantage of doing this over calling lots of set() methods after >+ * creating the text area is that this method is faster. >+ */ >+public class TextAreaDefaults >+{ >+ private static TextAreaDefaults DEFAULTS; >+ >+ public InputHandler inputHandler; >+ public SyntaxDocument document; >+ public boolean editable; >+ >+ public boolean caretVisible; >+ public boolean caretBlinks; >+ public boolean blockCaret; >+ public int electricScroll; >+ >+ public int cols; >+ public int rows; >+ public SyntaxStyle[] styles; >+ public Color caretColor; >+ public Color selectionColor; >+ public Color lineHighlightColor; >+ public boolean lineHighlight; >+ public Color bracketHighlightColor; >+ public boolean bracketHighlight; >+ public Color eolMarkerColor; >+ public boolean eolMarkers; >+ public boolean paintInvalid; >+ >+ public JPopupMenu popup; >+ >+ /** >+ * Returns a new TextAreaDefaults object with the default values filled >+ * in. >+ */ >+ public static TextAreaDefaults getDefaults() >+ { >+ if(DEFAULTS == null) >+ { >+ DEFAULTS = new TextAreaDefaults(); >+ >+ DEFAULTS.inputHandler = new DefaultInputHandler(); >+ DEFAULTS.inputHandler.addDefaultKeyBindings(); >+ DEFAULTS.document = new SyntaxDocument(); >+ DEFAULTS.editable = true; >+ >+ DEFAULTS.caretVisible = true; >+ DEFAULTS.caretBlinks = true; >+ DEFAULTS.electricScroll = 3; >+ >+ DEFAULTS.cols = 80; >+ DEFAULTS.rows = 25; >+ DEFAULTS.styles = SyntaxUtilities.getDefaultSyntaxStyles(); >+ DEFAULTS.caretColor = Color.red; >+ DEFAULTS.selectionColor = new Color(0xccccff); >+ DEFAULTS.lineHighlightColor = new Color(0xe0e0e0); >+ DEFAULTS.lineHighlight = true; >+ DEFAULTS.bracketHighlightColor = Color.black; >+ DEFAULTS.bracketHighlight = true; >+ DEFAULTS.eolMarkerColor = new Color(0x009999); >+ DEFAULTS.eolMarkers = true; >+ DEFAULTS.paintInvalid = true; >+ } >+ >+ return DEFAULTS; >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SourceViewFrame.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SourceViewFrame.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SourceViewFrame.java (revision 0) >@@ -0,0 +1,810 @@ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Dimension; >+import java.awt.Font; >+import java.awt.event.ActionEvent; >+import java.awt.event.ActionListener; >+import java.io.BufferedOutputStream; >+import java.io.File; >+import java.io.FileOutputStream; >+import java.io.OutputStream; >+import java.io.OutputStreamWriter; >+import java.util.HashMap; >+import java.util.Locale; >+import java.util.Map; >+import java.util.MissingResourceException; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.ImageIcon; >+import javax.swing.JButton; >+import javax.swing.JCheckBox; >+import javax.swing.JDialog; >+import javax.swing.JFileChooser; >+import javax.swing.JFrame; >+import javax.swing.JLabel; >+import javax.swing.JMenuBar; >+import javax.swing.JPanel; >+import javax.swing.JTextField; >+import javax.swing.JToggleButton; >+import javax.swing.JToolBar; >+import javax.swing.SwingUtilities; >+import javax.swing.UIManager; >+import javax.swing.event.CaretEvent; >+import javax.swing.event.CaretListener; >+import javax.swing.event.DocumentEvent; >+import javax.swing.event.DocumentListener; >+import javax.swing.filechooser.FileFilter; >+ >+import org.apache.batik.apps.svgbrowser.AboutDialog; >+import org.apache.batik.apps.svgbrowser.Application; >+import org.apache.batik.swing.svg.SVGUserAgent; >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.ButtonFactory; >+import org.apache.batik.util.gui.resource.MenuFactory; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+ >+public class SourceViewFrame extends JFrame implements ActionMap { >+ >+ public static final String RESOURCES = "org.apache.batik.apps.svgbrowser.srcview.resources.SourceViewFrame"; >+ >+ // The action names >+ public static final String SAVE_AS_ACTION = "SaveAsAction"; >+ >+ public static final String CLOSE_ACTION = "CloseAction"; >+ >+ public static final String UNDO_ACTION = "UndoAction"; >+ >+ public static final String REDO_ACTION = "RedoAction"; >+ >+ public static final String CUT_ACTION = "CutAction"; >+ >+ public static final String COPY_ACTION = "CopyAction"; >+ >+ public static final String PASTE_ACTION = "PasteAction"; >+ >+ public static final String DELETE_ACTION = "DeleteAction"; >+ >+ public static final String SELECT_ALL_ACTION = "SelectAllAction"; >+ >+ public static final String FIND_ACTION = "FindAction"; >+ >+ public static final String FIND_CLOSE_ACTION = "FindCloseAction"; >+ >+ public static final String FIND_AGAIN_ACTION = "FindAgainAction"; >+ >+ public static final String FIND_PREVIOUS_ACTION = "FindPreviousAction"; >+ >+ public static final String HIGHLIGHT_ALL_ACTION = "HighlightAllAction"; >+ >+ public static final String GOTO_LINE_ACTION = "GotoLineAction"; >+ >+ public static final String TEXT_SIZE_INCREASE_ACTION = "TextSizeIncreaseAction"; >+ >+ public static final String TEXT_SIZE_DECREASE_ACTION = "TextSizeDecreaseAction"; >+ >+ public static final String TEXT_SIZE_NORMAL_ACTION = "TextSizeNormalAction"; >+ >+ public static final String SYNTAX_HIGHLIGHTING_ACTION = "SyntaxHighlightingAction"; >+ >+ public static final String ABOUT_ACTION = "AboutAction"; >+ >+ protected static final float[] FONT_SIZES = { 6, 8, 10, 11, 12, 14, 18, 28, >+ 36, 72 }; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The SVG user agent. >+ */ >+ protected SVGUserAgent userAgent; >+ >+ /** >+ * The current application. >+ */ >+ protected Application application; >+ >+ /** >+ * The text to be displayed in the source viewer >+ */ >+ protected String sourceText; >+ >+ /** >+ * The syntax highlighted text area >+ */ >+ protected JEditTextArea textArea; >+ >+ /** >+ * TokenMarker used by syntax highlighted text area to tokenize text >+ */ >+ protected TokenMarker tokenMarker; >+ >+ /** >+ * The current save path. >+ */ >+ protected File currentSavePath = new File(""); >+ >+ /** >+ * The find bar. >+ */ >+ protected JToolBar findbar; >+ >+ /** >+ * Label to display status messages in the find bar >+ */ >+ protected FindBarMessage findbarMessage; >+ >+ /** >+ * The status bar. >+ */ >+ protected StatusBar statusBar; >+ >+ /** >+ * The current font size index (into the array FONT_SIZES) >+ */ >+ protected int fontSizeIndex; >+ >+ /** >+ * The default font size index (into the array FONT_SIZES) >+ */ >+ protected final int defaultFontSizeIndex = 4; >+ >+ /** >+ * Creates a new source viewer frame. >+ */ >+ public SourceViewFrame(Application app, String text, SVGUserAgent agt) >+ throws MissingResourceException { >+ application = app; >+ sourceText = text; >+ userAgent = agt; >+ >+ listeners.put(SAVE_AS_ACTION, new SaveAsAction()); >+ listeners.put(CLOSE_ACTION, new CloseAction()); >+ listeners.put(UNDO_ACTION, new UndoAction()); >+ listeners.put(REDO_ACTION, new RedoAction()); >+ listeners.put(CUT_ACTION, new CutAction()); >+ listeners.put(COPY_ACTION, new CopyAction()); >+ listeners.put(PASTE_ACTION, new PasteAction()); >+ listeners.put(DELETE_ACTION, new DeleteAction()); >+ listeners.put(SELECT_ALL_ACTION, new SelectAllAction()); >+ listeners.put(FIND_ACTION, new FindAction()); >+ listeners.put(FIND_CLOSE_ACTION, new FindCloseAction()); >+ listeners.put(FIND_AGAIN_ACTION, new FindAgainAction()); >+ listeners.put(FIND_PREVIOUS_ACTION, new FindPreviousAction()); >+ listeners.put(HIGHLIGHT_ALL_ACTION, new HighlightAllAction()); >+ listeners.put(GOTO_LINE_ACTION, new GotoLineAction()); >+ listeners.put(TEXT_SIZE_INCREASE_ACTION, new TextSizeIncreaseAction()); >+ listeners.put(TEXT_SIZE_DECREASE_ACTION, new TextSizeDecreaseAction()); >+ listeners.put(TEXT_SIZE_NORMAL_ACTION, new TextSizeNormalAction()); >+ listeners.put(SYNTAX_HIGHLIGHTING_ACTION, >+ new SyntaxHighlightingAction()); >+ listeners.put(ABOUT_ACTION, new AboutAction()); >+ >+ // Create the menu >+ MenuFactory mf = new MenuFactory(bundle, this); >+ >+ // TODO:Remove this and use specialized version (commented out below) >+ JMenuBar mb = mf.createJMenuBar("MenuBar"); >+ // JMenuBar mb = mf.createJMenuBar("MenuBar", application >+ // .getUISpecialization()); >+ setJMenuBar(mb); >+ >+ // Create the central panel >+ JPanel center = new JPanel(new BorderLayout()); >+ getContentPane().add(center, BorderLayout.CENTER); >+ >+ // Create syntax-highlighted text area >+ textArea = new JEditTextArea(); >+ textArea.setText(sourceText); >+ tokenMarker = new XMLTokenMarker(); >+ textArea.setTokenMarker(tokenMarker); >+ fontSizeIndex = defaultFontSizeIndex; >+ TextAreaPainter painter = textArea.getPainter(); >+ painter.setFont(new Font("Monospaced", Font.PLAIN, >+ (int) (FONT_SIZES[fontSizeIndex]))); >+ textArea.addCaretListener(new CaretListener() { >+ public void caretUpdate(CaretEvent e) { >+ JEditTextArea a = (JEditTextArea) e.getSource(); >+ int row = a.getCaretLine() + 1; >+ int col = a.getCaretPosition() - a.getLineStartOffset(row - 1) >+ + 1; >+ statusBar.setPosition(row, col); >+ } >+ }); >+ center.add(textArea); >+ >+ // Create find bar (initially invisible) >+ ButtonFactory bf = new ButtonFactory(bundle, this); >+ findbar = new JToolBar(); >+ findbar.setVisible(false); >+ findbar.setFloatable(false); >+ findbar.add(bf.createJToolbarButton("FindBarClose")); >+ findbar >+ .add(new JLabel(resources.getString("FindBar.label.find") >+ + ": ")); >+ final JTextField findText = new JTextField(20); >+ JPanel p = new JPanel(); >+ p.setOpaque(false); >+ p.add(findText); >+ p.setMinimumSize(p.getPreferredSize()); >+ p.setMaximumSize(p.getPreferredSize()); >+ findbar.add(p); >+ final JButton next = bf.createJToolbarButton("FindBarNext"); >+ next.setEnabled(false); >+ findbar.add(next); >+ final JButton previous = bf.createJToolbarButton("FindBarPrevious"); >+ previous.setEnabled(false); >+ findbar.add(previous); >+ final JToggleButton highlightAll = bf >+ .createJToolbarToggleButton("FindBarHighlightAll"); >+ highlightAll.setEnabled(false); >+ findbar.add(highlightAll); >+ JCheckBox matchCase = bf.createJCheckBox("FindBarMatchCase"); >+ matchCase.setOpaque(false); >+ findbar.add(matchCase); >+ findbarMessage = new FindBarMessage(); >+ findbar.add(findbarMessage); >+ findText.getDocument().addDocumentListener(new DocumentListener() { >+ public void changedUpdate(DocumentEvent e) { >+ update(); >+ } >+ >+ public void insertUpdate(DocumentEvent e) { >+ update(); >+ } >+ >+ public void removeUpdate(DocumentEvent e) { >+ update(); >+ } >+ >+ private void update() { >+ String str = findText.getText().trim(); >+ boolean enabled = !str.equals(""); >+ next.setEnabled(enabled); >+ previous.setEnabled(enabled); >+ highlightAll.setEnabled(enabled); >+ if (enabled) { >+ if (!find(str, DIRECTION_DOWN)) { >+ findText.setBackground(new Color(255, 128, 128)); >+ } >+ } else { >+ findbarMessage.setMessage(FindBarMessage.NONE); >+ findText.setBackground(UIManager >+ .getColor("TextField.background")); >+ } >+ } >+ }); >+ center.add(findbar, BorderLayout.SOUTH); >+ >+ // Create status bar >+ statusBar = new StatusBar(); >+ getContentPane().add(statusBar, BorderLayout.SOUTH); >+ } >+ >+ protected static ImageIcon notFoundIcon, continueFromTopIcon; >+ >+ protected static String notFoundStr, continueFromTopStr; >+ >+ static { >+ notFoundStr = resources.getString("FindBarNotFound.text"); >+ notFoundIcon = new ImageIcon(SourceViewFrame.class >+ .getResource(resources.getString("FindBarNotFound.icon"))); >+ continueFromTopStr = resources.getString("FindBarContinueFromTop.text"); >+ continueFromTopIcon = new ImageIcon(SourceViewFrame.class >+ .getResource(resources.getString("FindBarContinueFromTop.icon"))); >+ } >+ >+ protected class FindBarMessage extends JLabel { >+ public static final int NONE = 0, NOT_FOUND = 1, CONTINUE_FROM_TOP = 2; >+ >+ public void setMessage(int type) { >+ switch (type) { >+ case NOT_FOUND: >+ setIcon(notFoundIcon); >+ setText(notFoundStr); >+ break; >+ case CONTINUE_FROM_TOP: >+ setIcon(continueFromTopIcon); >+ setText(continueFromTopStr); >+ break; >+ case NONE: >+ default: >+ setIcon(null); >+ setText(""); >+ break; >+ } >+ } >+ } >+ >+ /** >+ * Save the document as a different file >+ */ >+ public class SaveAsAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ JFileChooser fileChooser; >+ fileChooser = new JFileChooser( >+ currentSavePath.isAbsolute() ? currentSavePath >+ : currentSavePath.getAbsoluteFile()); >+ fileChooser.setDialogTitle(resources.getString("SaveAs.title")); >+ fileChooser.setFileHidingEnabled(false); >+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); >+ fileChooser.addChoosableFileFilter(new FileFilter() { >+ public boolean accept(File f) { >+ if (f == null) { >+ return false; >+ } >+ if (f.isDirectory()) { >+ return true; >+ } >+ String fileName = f.getName().toLowerCase(); >+ return fileName.endsWith(".svg"); >+ } >+ >+ public String getDescription() { >+ return "SVG Document"; >+ } >+ }); >+ >+ int choice = fileChooser.showSaveDialog(SourceViewFrame.this); >+ if (choice != JFileChooser.APPROVE_OPTION) >+ return; >+ >+ final File f = fileChooser.getSelectedFile(); >+ >+ statusBar.setMessage(resources.getString("Message.saveAs")); >+ currentSavePath = f; >+ OutputStreamWriter w = null; >+ try { >+ OutputStream tos = null; >+ tos = new FileOutputStream(f); >+ tos = new BufferedOutputStream(tos); >+ w = new OutputStreamWriter(tos, "utf-8"); >+ } catch (Exception ex) { >+ userAgent.displayError(ex); >+ return; >+ } >+ >+ final OutputStreamWriter writer = w; >+ >+ final Runnable doneRun = new Runnable() { >+ public void run() { >+ String doneStr = resources.getString("Message.done"); >+ statusBar.setMessage(doneStr); >+ } >+ }; >+ >+ try { >+ writer.write(textArea.getText()); >+ writer.close(); >+ >+ SwingUtilities.invokeLater(doneRun); >+ } catch (Exception ex) { >+ userAgent.displayError(ex); >+ } >+ } >+ } >+ >+ /** >+ * Closes the source viewer >+ */ >+ public class CloseAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ dispose(); >+ } >+ } >+ >+ /** >+ * Undo last action >+ */ >+ public class UndoAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ >+ } >+ } >+ >+ /** >+ * Redo last undone action >+ */ >+ public class RedoAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ >+ } >+ } >+ >+ /** >+ * Cut selected text >+ */ >+ public class CutAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ textArea.cut(); >+ } >+ } >+ >+ /** >+ * Copy selected text >+ */ >+ public class CopyAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ textArea.copy(); >+ } >+ } >+ >+ /** >+ * Paste copied text >+ */ >+ public class PasteAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ textArea.paste(); >+ } >+ } >+ >+ /** >+ * Delete selected text >+ */ >+ public class DeleteAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ } >+ } >+ >+ /** >+ * Select all text >+ */ >+ public class SelectAllAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ textArea.selectAll(); >+ } >+ } >+ >+ /** >+ * Displays the find bar if not already visible >+ */ >+ public class FindAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (!findbar.isVisible()) { >+ findbar.setVisible(true); >+ } >+ } >+ } >+ >+ /** >+ * Closes the find bar if visible >+ */ >+ public class FindCloseAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (findbar.isVisible()) { >+ findbar.setVisible(false); >+ } >+ } >+ } >+ >+ /** >+ * Find the string in the text specified using the Find action >+ */ >+ public class FindAgainAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (!findbar.isVisible()) { >+ findbar.setVisible(true); >+ } else { >+ find(lastFindStr, DIRECTION_DOWN); >+ } >+ } >+ } >+ >+ /** >+ * Find the string in the text specified using the Find action >+ */ >+ public class FindPreviousAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (!findbar.isVisible()) { >+ findbar.setVisible(true); >+ } else { >+ find(lastFindStr, DIRECTION_UP); >+ } >+ } >+ } >+ >+ /** >+ * Highlight all occurrences of the search phrase in the text >+ */ >+ public class HighlightAllAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ } >+ } >+ >+ private String lastFindStr; >+ >+ private int lastOffset = -1; >+ >+ private static final int DIRECTION_UP = -1, DIRECTION_DOWN = 1; >+ >+ /** >+ * Help function to search for a phrase in the text >+ * >+ * @param phrase >+ * search string >+ * @param direction >+ * whether to search downward or upward >+ * @return true is search string found, false otherwise >+ */ >+ private boolean find(String phrase, int direction) { >+ boolean found = false; >+ boolean wrap = false; >+ >+ String text = textArea.getText(); >+ int offset = text.indexOf(phrase, lastOffset + 1); >+ if (offset < 0 && lastOffset >= 0) { >+ lastOffset = -1; >+ wrap = true; >+ offset = text.indexOf(phrase, 0); >+ } >+ lastOffset = offset; >+ found = lastOffset >= 0; >+ >+ if (found) { >+ textArea.setSelectionStart(lastOffset); >+ textArea.setSelectionEnd(lastOffset + phrase.length()); >+ } >+ >+ if (!found) { >+ findbarMessage.setMessage(FindBarMessage.NOT_FOUND); >+ } else if (wrap) { >+ findbarMessage.setMessage(FindBarMessage.CONTINUE_FROM_TOP); >+ } else { >+ findbarMessage.setMessage(FindBarMessage.NONE); >+ } >+ return found; >+ } >+ >+ /** >+ * Goto a particular line >+ */ >+ public class GotoLineAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ SwingUtilities.invokeLater(new Runnable() { >+ public void run() { >+ GotoLineDialog gld = new GotoLineDialog( >+ SourceViewFrame.this, textArea.getLineCount()); >+ gld.setVisible(true); >+ int n = gld.getLineNumber(); >+ if (n > 0) { >+ gotoLine(n); >+ } >+ } >+ }); >+ } >+ } >+ >+ /** >+ * Helper function to adjust caret position and scroll viewport >+ * >+ * @param n >+ * line number of the new caret position >+ */ >+ private void gotoLine(int n) { >+ textArea.setCaretPosition(textArea.getLineStartOffset(n - 1)); >+ textArea.scrollToCaret(); >+ } >+ >+ /** >+ * Increase text size >+ */ >+ public class TextSizeIncreaseAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (fontSizeIndex < FONT_SIZES.length - 1) { >+ TextAreaPainter painter = textArea.getPainter(); >+ painter.setFont(painter.getFont().deriveFont( >+ FONT_SIZES[++fontSizeIndex])); >+ } >+ } >+ } >+ >+ /** >+ * Decrease text size >+ */ >+ public class TextSizeDecreaseAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ if (fontSizeIndex > 0) { >+ TextAreaPainter painter = textArea.getPainter(); >+ painter.setFont(painter.getFont().deriveFont( >+ FONT_SIZES[--fontSizeIndex])); >+ } >+ } >+ } >+ >+ /** >+ * Set text size to default value >+ */ >+ public class TextSizeNormalAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ TextAreaPainter painter = textArea.getPainter(); >+ painter.setFont(painter.getFont().deriveFont( >+ FONT_SIZES[fontSizeIndex = defaultFontSizeIndex])); >+ } >+ } >+ >+ /** >+ * Toggle syntax highlighting >+ */ >+ public class SyntaxHighlightingAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ textArea >+ .setTokenMarker(textArea.getTokenMarker() == null ? tokenMarker >+ : null); >+ textArea.repaint(); >+ } >+ } >+ >+ /** >+ * To show the about dialog >+ */ >+ public class AboutAction extends AbstractAction { >+ public void actionPerformed(ActionEvent e) { >+ AboutDialog dlg = new AboutDialog(SourceViewFrame.this); >+ // Work around pack() bug on some platforms >+ dlg.setSize(dlg.getPreferredSize()); >+ dlg.setLocationRelativeTo(SourceViewFrame.this); >+ dlg.setVisible(true); >+ dlg.toFront(); >+ } >+ } >+ >+ /** >+ * The map that contains the action listeners >+ */ >+ protected Map listeners = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ Action result = (Action) listeners.get(key); >+ if (result == null) { >+ throw new MissingListenerException("Can't find action.", RESOURCES, >+ key); >+ } >+ return result; >+ } >+ >+ private class GotoLineDialog extends JDialog implements ActionListener, >+ DocumentListener { >+ >+ private JTextField textField; >+ >+ private JButton okButton, cancelButton; >+ >+ private JLabel errorMessage; >+ >+ private int totalLines; >+ >+ private int lineNumber = -1; >+ >+ public GotoLineDialog(JFrame owner, int totalLines) { >+ super(owner, resources.getString("GotoLine.title"), true); >+ this.totalLines = totalLines; >+ >+ JPanel content = new JPanel(new BorderLayout()); >+ content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); >+ content.setPreferredSize(new Dimension(300, 120)); >+ getContentPane().add(content); >+ >+ Box input = new Box(BoxLayout.Y_AXIS); >+ content.add(input, BorderLayout.NORTH); >+ >+ String str = resources.getString("GotoLine.label.enterLineNumber"); >+ str = str.replace("{0}", "" + totalLines); >+ JLabel label = new JLabel(str); >+ input.add(label); >+ >+ textField = new JTextField(120); >+ textField.getDocument().addDocumentListener(this); >+ input.add(textField); >+ >+ errorMessage = new JLabel(); >+ input.add(errorMessage); >+ >+ Box buttons = new Box(BoxLayout.X_AXIS); >+ content.add(buttons, BorderLayout.SOUTH); >+ >+ buttons.add(Box.createHorizontalGlue()); >+ >+ okButton = new JButton(resources.getString("GotoLine.button.ok")); >+ okButton.setEnabled(false); >+ okButton.addActionListener(this); >+ buttons.add(okButton); >+ >+ buttons.add(Box.createHorizontalStrut(5)); >+ >+ cancelButton = new JButton(resources >+ .getString("GotoLine.button.cancel")); >+ cancelButton.addActionListener(this); >+ buttons.add(cancelButton); >+ >+ pack(); >+ setLocationRelativeTo(getParent()); >+ } >+ >+ public int getLineNumber() { >+ return lineNumber; >+ } >+ >+ public void actionPerformed(ActionEvent e) { >+ if (e.getSource() == okButton) { >+ lineNumber = Integer.parseInt(textField.getText()); >+ dispose(); >+ } else if (e.getSource() == cancelButton) { >+ dispose(); >+ } >+ } >+ >+ public void changedUpdate(DocumentEvent e) { >+ check(); >+ } >+ >+ public void insertUpdate(DocumentEvent e) { >+ check(); >+ } >+ >+ public void removeUpdate(DocumentEvent e) { >+ check(); >+ } >+ >+ private void check() { >+ boolean disabled = false; >+ String error = ""; >+ try { >+ String text = textField.getText(); >+ if (text == null || text.trim().equals("")) { >+ disabled = true; >+ } else { >+ int n = Integer.parseInt(text); >+ if (n < 1 || n > totalLines) { >+ disabled = true; >+ error = "Number out of range"; >+ } >+ } >+ } catch (NumberFormatException e) { >+ disabled = true; >+ error = "Not a number"; >+ } >+ okButton.setEnabled(!disabled); >+ errorMessage.setText(error); >+ } >+ } >+ >+ public static void main(String[] args) { >+ // try { >+ // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); >+ // } catch (Exception e) { >+ // e.printStackTrace(); >+ // } >+ >+ SourceViewFrame svf = new SourceViewFrame(null, "abcdef", null); >+ svf.setSize(700, 500); >+ svf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); >+ svf.setVisible(true); >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxStyle.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxStyle.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxStyle.java (revision 0) >@@ -0,0 +1,136 @@ >+/* >+ * SyntaxStyle.java - A simple text style class >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import java.awt.*; >+import java.util.StringTokenizer; >+ >+/** >+ * A simple text style class. It can specify the color, italic flag, >+ * and bold flag of a run of text. >+ * @author Slava Pestov >+ * @version $Id: SyntaxStyle.java,v 1.6 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class SyntaxStyle >+{ >+ /** >+ * Creates a new SyntaxStyle. >+ * @param color The text color >+ * @param italic True if the text should be italics >+ * @param bold True if the text should be bold >+ */ >+ public SyntaxStyle(Color color, boolean italic, boolean bold) >+ { >+ this.color = color; >+ this.italic = italic; >+ this.bold = bold; >+ } >+ >+ /** >+ * Returns the color specified in this style. >+ */ >+ public Color getColor() >+ { >+ return color; >+ } >+ >+ /** >+ * Returns true if no font styles are enabled. >+ */ >+ public boolean isPlain() >+ { >+ return !(bold || italic); >+ } >+ >+ /** >+ * Returns true if italics is enabled for this style. >+ */ >+ public boolean isItalic() >+ { >+ return italic; >+ } >+ >+ /** >+ * Returns true if boldface is enabled for this style. >+ */ >+ public boolean isBold() >+ { >+ return bold; >+ } >+ >+ /** >+ * Returns the specified font, but with the style's bold and >+ * italic flags applied. >+ */ >+ public Font getStyledFont(Font font) >+ { >+ if(font == null) >+ throw new NullPointerException("font param must not" >+ + " be null"); >+ if(font.equals(lastFont)) >+ return lastStyledFont; >+ lastFont = font; >+ lastStyledFont = new Font(font.getFamily(), >+ (bold ? Font.BOLD : 0) >+ | (italic ? Font.ITALIC : 0), >+ font.getSize()); >+ return lastStyledFont; >+ } >+ >+ /** >+ * Returns the font metrics for the styled font. >+ */ >+ public FontMetrics getFontMetrics(Font font) >+ { >+ if(font == null) >+ throw new NullPointerException("font param must not" >+ + " be null"); >+ if(font.equals(lastFont) && fontMetrics != null) >+ return fontMetrics; >+ lastFont = font; >+ lastStyledFont = new Font(font.getFamily(), >+ (bold ? Font.BOLD : 0) >+ | (italic ? Font.ITALIC : 0), >+ font.getSize()); >+ fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics( >+ lastStyledFont); >+ return fontMetrics; >+ } >+ >+ /** >+ * Sets the foreground color and font of the specified graphics >+ * context to that specified in this style. >+ * @param gfx The graphics context >+ * @param font The font to add the styles to >+ */ >+ public void setGraphicsFlags(Graphics gfx, Font font) >+ { >+ Font _font = getStyledFont(font); >+ gfx.setFont(_font); >+ gfx.setColor(color); >+ } >+ >+ /** >+ * Returns a string representation of this object. >+ */ >+ public String toString() >+ { >+ return getClass().getName() + "[color=" + color + >+ (italic ? ",italic" : "") + >+ (bold ? ",bold" : "") + "]"; >+ } >+ >+ // private members >+ private Color color; >+ private boolean italic; >+ private boolean bold; >+ private Font lastFont; >+ private Font lastStyledFont; >+ private FontMetrics fontMetrics; >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/StatusBar.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/StatusBar.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/StatusBar.java (revision 0) >@@ -0,0 +1,147 @@ >+/* >+ >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+ >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import java.awt.Dimension; >+import java.util.Locale; >+import java.util.MissingResourceException; >+import java.util.ResourceBundle; >+ >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.JLabel; >+import javax.swing.JPanel; >+import javax.swing.border.BevelBorder; >+ >+import org.apache.batik.util.gui.resource.ResourceManager; >+ >+/** >+ * This class represents a viewer status bar. >+ * >+ */ >+public class StatusBar extends JPanel { >+ >+ /** >+ * The gui resources file name >+ */ >+ protected static final String RESOURCES = >+ "org.apache.batik.apps.svgbrowser.srcview.resources.StatusBarMessages"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager rManager; >+ >+ /** >+ * The string to be used for "Row" >+ */ >+ private static String rowStr; >+ >+ /** >+ * The string to be used for "Column" >+ */ >+ private static String colStr; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ rManager = new ResourceManager(bundle); >+ rowStr = rManager.getString("Position.row"); >+ colStr = rManager.getString("Position.column"); >+ } >+ >+ /** >+ * The row value >+ */ >+ protected int row; >+ >+ /** >+ * The column value >+ */ >+ protected int column; >+ >+ /** >+ * The position label. >+ */ >+ protected JLabel position; >+ >+ /** >+ * The message label >+ */ >+ protected JLabel message; >+ >+ /** >+ * Creates a new status bar. >+ */ >+ public StatusBar() throws MissingResourceException { >+ setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); >+ setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); >+ >+ position = new JLabel(); >+ position.setPreferredSize(new Dimension(110, 16)); >+ add(position); >+ >+ message = new JLabel(); >+ add(message); >+ >+ add(Box.createHorizontalGlue()); >+ } >+ >+ /** >+ * Sets the row. >+ */ >+ public void setRow(int row) { >+ this.row = row; >+ updatePosition(); >+ } >+ >+ /** >+ * Sets the column. >+ */ >+ public void setColumn(int column) { >+ this.column = column; >+ updatePosition(); >+ } >+ >+ /** >+ * Sets the row and column together >+ */ >+ public void setPosition(int row, int column) { >+ this.row = row; >+ this.column = column; >+ updatePosition(); >+ } >+ >+ private void updatePosition() { >+ position.setText(rowStr + " " + row + ", " + colStr + " " + column); >+ } >+ >+ /** >+ * Sets the message >+ * @param s the message >+ */ >+ public void setMessage(String s) { >+ message.setText(s); >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/Token.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/Token.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/Token.java (revision 0) >@@ -0,0 +1,149 @@ >+/* >+ * Token.java - Generic token >+ * Copyright (C) 1998, 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+/** >+ * A linked list of tokens. Each token has three fields - a token >+ * identifier, which is a byte value that can be looked up in the >+ * array returned by <code>SyntaxDocument.getColors()</code> >+ * to get a color value, a length value which is the length of the >+ * token in the text, and a pointer to the next token in the list. >+ * >+ * @author Slava Pestov >+ * @version $Id: Token.java,v 1.12 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class Token >+{ >+ /** >+ * Normal text token id. This should be used to mark >+ * normal text. >+ */ >+ public static final byte NULL = 0; >+ >+ /** >+ * Comment 1 token id. This can be used to mark a comment. >+ */ >+ public static final byte COMMENT1 = 1; >+ >+ /** >+ * Comment 2 token id. This can be used to mark a comment. >+ */ >+ public static final byte COMMENT2 = 2; >+ >+ >+ /** >+ * Literal 1 token id. This can be used to mark a string >+ * literal (eg, C mode uses this to mark "..." literals) >+ */ >+ public static final byte LITERAL1 = 3; >+ >+ /** >+ * Literal 2 token id. This can be used to mark an object >+ * literal (eg, Java mode uses this to mark true, false, etc) >+ */ >+ public static final byte LITERAL2 = 4; >+ >+ /** >+ * Label token id. This can be used to mark labels >+ * (eg, C mode uses this to mark ...: sequences) >+ */ >+ public static final byte LABEL = 5; >+ >+ /** >+ * Keyword 1 token id. This can be used to mark a >+ * keyword. This should be used for general language >+ * constructs. >+ */ >+ public static final byte KEYWORD1 = 6; >+ >+ /** >+ * Keyword 2 token id. This can be used to mark a >+ * keyword. This should be used for preprocessor >+ * commands, or variables. >+ */ >+ public static final byte KEYWORD2 = 7; >+ >+ /** >+ * Keyword 3 token id. This can be used to mark a >+ * keyword. This should be used for data types. >+ */ >+ public static final byte KEYWORD3 = 8; >+ >+ /** >+ * Operator token id. This can be used to mark an >+ * operator. (eg, SQL mode marks +, -, etc with this >+ * token type) >+ */ >+ public static final byte OPERATOR = 9; >+ >+ /** >+ * Invalid token id. This can be used to mark invalid >+ * or incomplete tokens, so the user can easily spot >+ * syntax errors. >+ */ >+ public static final byte INVALID = 10; >+ >+ /** >+ * The total number of defined token ids. >+ */ >+ public static final byte ID_COUNT = 11; >+ >+ /** >+ * The first id that can be used for internal state >+ * in a token marker. >+ */ >+ public static final byte INTERNAL_FIRST = 100; >+ >+ /** >+ * The last id that can be used for internal state >+ * in a token marker. >+ */ >+ public static final byte INTERNAL_LAST = 126; >+ >+ /** >+ * The token type, that along with a length of 0 >+ * marks the end of the token list. >+ */ >+ public static final byte END = 127; >+ >+ /** >+ * The length of this token. >+ */ >+ public int length; >+ >+ /** >+ * The id of this token. >+ */ >+ public byte id; >+ >+ /** >+ * The next token in the linked list. >+ */ >+ public Token next; >+ >+ /** >+ * Creates a new token. >+ * @param length The length of the token >+ * @param id The id of the token >+ */ >+ public Token(int length, byte id) >+ { >+ this.length = length; >+ this.id = id; >+ } >+ >+ /** >+ * Returns a string representation of this token. >+ */ >+ public String toString() >+ { >+ return "[id=" + id + ",length=" + length + "]"; >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextUtilities.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextUtilities.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TextUtilities.java (revision 0) >@@ -0,0 +1,183 @@ >+/* >+ * TextUtilities.java - Utility functions used by the text area classes >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.*; >+ >+/** >+ * Class with several utility functions used by the text area component. >+ * @author Slava Pestov >+ * @version $Id: TextUtilities.java,v 1.4 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class TextUtilities >+{ >+ /** >+ * Returns the offset of the bracket matching the one at the >+ * specified offset of the document, or -1 if the bracket is >+ * unmatched (or if the character is not a bracket). >+ * @param doc The document >+ * @param offset The offset >+ * @exception BadLocationException If an out-of-bounds access >+ * was attempted on the document text >+ */ >+ public static int findMatchingBracket(Document doc, int offset) >+ throws BadLocationException >+ { >+ if(doc.getLength() == 0) >+ return -1; >+ char c = doc.getText(offset,1).charAt(0); >+ char cprime; // c` - corresponding character >+ boolean direction; // true = back, false = forward >+ >+ switch(c) >+ { >+ case '(': cprime = ')'; direction = false; break; >+ case ')': cprime = '('; direction = true; break; >+ case '[': cprime = ']'; direction = false; break; >+ case ']': cprime = '['; direction = true; break; >+ case '{': cprime = '}'; direction = false; break; >+ case '}': cprime = '{'; direction = true; break; >+ default: return -1; >+ } >+ >+ int count; >+ >+ // How to merge these two cases is left as an exercise >+ // for the reader. >+ >+ // Go back or forward >+ if(direction) >+ { >+ // Count is 1 initially because we have already >+ // `found' one closing bracket >+ count = 1; >+ >+ // Get text[0,offset-1]; >+ String text = doc.getText(0,offset); >+ >+ // Scan backwards >+ for(int i = offset - 1; i >= 0; i--) >+ { >+ // If text[i] == c, we have found another >+ // closing bracket, therefore we will need >+ // two opening brackets to complete the >+ // match. >+ char x = text.charAt(i); >+ if(x == c) >+ count++; >+ >+ // If text[i] == cprime, we have found a >+ // opening bracket, so we return i if >+ // --count == 0 >+ else if(x == cprime) >+ { >+ if(--count == 0) >+ return i; >+ } >+ } >+ } >+ else >+ { >+ // Count is 1 initially because we have already >+ // `found' one opening bracket >+ count = 1; >+ >+ // So we don't have to + 1 in every loop >+ offset++; >+ >+ // Number of characters to check >+ int len = doc.getLength() - offset; >+ >+ // Get text[offset+1,len]; >+ String text = doc.getText(offset,len); >+ >+ // Scan forwards >+ for(int i = 0; i < len; i++) >+ { >+ // If text[i] == c, we have found another >+ // opening bracket, therefore we will need >+ // two closing brackets to complete the >+ // match. >+ char x = text.charAt(i); >+ >+ if(x == c) >+ count++; >+ >+ // If text[i] == cprime, we have found an >+ // closing bracket, so we return i if >+ // --count == 0 >+ else if(x == cprime) >+ { >+ if(--count == 0) >+ return i + offset; >+ } >+ } >+ } >+ >+ // Nothing found >+ return -1; >+ } >+ >+ /** >+ * Locates the start of the word at the specified position. >+ * @param line The text >+ * @param pos The position >+ */ >+ public static int findWordStart(String line, int pos, String noWordSep) >+ { >+ char ch = line.charAt(pos - 1); >+ >+ if(noWordSep == null) >+ noWordSep = ""; >+ boolean selectNoLetter = (!Character.isLetterOrDigit(ch) >+ && noWordSep.indexOf(ch) == -1); >+ >+ int wordStart = 0; >+ for(int i = pos - 1; i >= 0; i--) >+ { >+ ch = line.charAt(i); >+ if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) && >+ noWordSep.indexOf(ch) == -1)) >+ { >+ wordStart = i + 1; >+ break; >+ } >+ } >+ >+ return wordStart; >+ } >+ >+ /** >+ * Locates the end of the word at the specified position. >+ * @param line The text >+ * @param pos The position >+ */ >+ public static int findWordEnd(String line, int pos, String noWordSep) >+ { >+ char ch = line.charAt(pos); >+ >+ if(noWordSep == null) >+ noWordSep = ""; >+ boolean selectNoLetter = (!Character.isLetterOrDigit(ch) >+ && noWordSep.indexOf(ch) == -1); >+ >+ int wordEnd = line.length(); >+ for(int i = pos; i < line.length(); i++) >+ { >+ ch = line.charAt(i); >+ if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) && >+ noWordSep.indexOf(ch) == -1)) >+ { >+ wordEnd = i; >+ break; >+ } >+ } >+ return wordEnd; >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxUtilities.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxUtilities.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxUtilities.java (revision 0) >@@ -0,0 +1,157 @@ >+/* >+ * SyntaxUtilities.java - Utility functions used by syntax colorizing >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.*; >+import java.awt.*; >+ >+/** >+ * Class with several utility functions used by jEdit's syntax colorizing >+ * subsystem. >+ * >+ * @author Slava Pestov >+ * @version $Id: SyntaxUtilities.java,v 1.9 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class SyntaxUtilities >+{ >+ /** >+ * Checks if a subregion of a <code>Segment</code> is equal to a >+ * string. >+ * @param ignoreCase True if case should be ignored, false otherwise >+ * @param text The segment >+ * @param offset The offset into the segment >+ * @param match The string to match >+ */ >+ public static boolean regionMatches(boolean ignoreCase, Segment text, >+ int offset, String match) >+ { >+ int length = offset + match.length(); >+ char[] textArray = text.array; >+ if(length > text.offset + text.count) >+ return false; >+ for(int i = offset, j = 0; i < length; i++, j++) >+ { >+ char c1 = textArray[i]; >+ char c2 = match.charAt(j); >+ if(ignoreCase) >+ { >+ c1 = Character.toUpperCase(c1); >+ c2 = Character.toUpperCase(c2); >+ } >+ if(c1 != c2) >+ return false; >+ } >+ return true; >+ } >+ >+ /** >+ * Checks if a subregion of a <code>Segment</code> is equal to a >+ * character array. >+ * @param ignoreCase True if case should be ignored, false otherwise >+ * @param text The segment >+ * @param offset The offset into the segment >+ * @param match The character array to match >+ */ >+ public static boolean regionMatches(boolean ignoreCase, Segment text, >+ int offset, char[] match) >+ { >+ int length = offset + match.length; >+ char[] textArray = text.array; >+ if(length > text.offset + text.count) >+ return false; >+ for(int i = offset, j = 0; i < length; i++, j++) >+ { >+ char c1 = textArray[i]; >+ char c2 = match[j]; >+ if(ignoreCase) >+ { >+ c1 = Character.toUpperCase(c1); >+ c2 = Character.toUpperCase(c2); >+ } >+ if(c1 != c2) >+ return false; >+ } >+ return true; >+ } >+ >+ /** >+ * Returns the default style table. This can be passed to the >+ * <code>setStyles()</code> method of <code>SyntaxDocument</code> >+ * to use the default syntax styles. >+ */ >+ public static SyntaxStyle[] getDefaultSyntaxStyles() >+ { >+ SyntaxStyle[] styles = new SyntaxStyle[Token.ID_COUNT]; >+ >+ styles[Token.COMMENT1] = new SyntaxStyle(Color.black,true,true); >+ styles[Token.COMMENT2] = new SyntaxStyle(new Color(0x990033),true,true); >+ styles[Token.KEYWORD1] = new SyntaxStyle(Color.black,false,true); >+ styles[Token.KEYWORD2] = new SyntaxStyle(Color.magenta,false,true); >+ styles[Token.KEYWORD3] = new SyntaxStyle(new Color(0x009600),false,false); >+ styles[Token.LITERAL1] = new SyntaxStyle(new Color(0x650099),false,false); >+ styles[Token.LITERAL2] = new SyntaxStyle(new Color(0x650099),false,true); >+ styles[Token.LABEL] = new SyntaxStyle(new Color(0x990033),false,true); >+ styles[Token.OPERATOR] = new SyntaxStyle(Color.black,false,true); >+ styles[Token.INVALID] = new SyntaxStyle(Color.red,false,true); >+ >+ return styles; >+ } >+ >+ /** >+ * Paints the specified line onto the graphics context. Note that this >+ * method munges the offset and count values of the segment. >+ * @param line The line segment >+ * @param tokens The token list for the line >+ * @param styles The syntax style list >+ * @param expander The tab expander used to determine tab stops. May >+ * be null >+ * @param gfx The graphics context >+ * @param x The x co-ordinate >+ * @param y The y co-ordinate >+ * @return The x co-ordinate, plus the width of the painted string >+ */ >+ public static int paintSyntaxLine(Segment line, Token tokens, >+ SyntaxStyle[] styles, TabExpander expander, Graphics gfx, >+ int x, int y) >+ { >+ Font defaultFont = gfx.getFont(); >+ Color defaultColor = gfx.getColor(); >+ >+ int offset = 0; >+ for(;;) >+ { >+ byte id = tokens.id; >+ if(id == Token.END) >+ break; >+ >+ int length = tokens.length; >+ if(id == Token.NULL) >+ { >+ if(!defaultColor.equals(gfx.getColor())) >+ gfx.setColor(defaultColor); >+ if(!defaultFont.equals(gfx.getFont())) >+ gfx.setFont(defaultFont); >+ } >+ else >+ styles[id].setGraphicsFlags(gfx,defaultFont); >+ >+ line.count = length; >+ x = Utilities.drawTabbedText(line,x,y,gfx,expander,0); >+ line.offset += length; >+ offset += length; >+ >+ tokens = tokens.next; >+ } >+ >+ return x; >+ } >+ >+ // private members >+ private SyntaxUtilities() {} >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TokenMarker.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TokenMarker.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/TokenMarker.java (revision 0) >@@ -0,0 +1,344 @@ >+/* >+ * TokenMarker.java - Generic token marker >+ * Copyright (C) 1998, 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.Segment; >+import java.util.*; >+ >+/** >+ * A token marker that splits lines of text into tokens. Each token carries >+ * a length field and an indentification tag that can be mapped to a color >+ * for painting that token.<p> >+ * >+ * For performance reasons, the linked list of tokens is reused after each >+ * line is tokenized. Therefore, the return value of <code>markTokens</code> >+ * should only be used for immediate painting. Notably, it cannot be >+ * cached. >+ * >+ * @author Slava Pestov >+ * @version $Id: TokenMarker.java,v 1.32 1999/12/13 03:40:30 sp Exp $ >+ * >+ * @see org.gjt.sp.jedit.syntax.Token >+ */ >+public abstract class TokenMarker >+{ >+ /** >+ * A wrapper for the lower-level <code>markTokensImpl</code> method >+ * that is called to split a line up into tokens. >+ * @param line The line >+ * @param lineIndex The line number >+ */ >+ public Token markTokens(Segment line, int lineIndex) >+ { >+ if(lineIndex >= length) >+ { >+ throw new IllegalArgumentException("Tokenizing invalid line: " >+ + lineIndex); >+ } >+ >+ lastToken = null; >+ >+ LineInfo info = lineInfo[lineIndex]; >+ LineInfo prev; >+ if(lineIndex == 0) >+ prev = null; >+ else >+ prev = lineInfo[lineIndex - 1]; >+ >+ byte oldToken = info.token; >+ byte token = markTokensImpl(prev == null ? >+ Token.NULL : prev.token,line,lineIndex); >+ >+ info.token = token; >+ >+ /* >+ * This is a foul hack. It stops nextLineRequested >+ * from being cleared if the same line is marked twice. >+ * >+ * Why is this necessary? It's all JEditTextArea's fault. >+ * When something is inserted into the text, firing a >+ * document event, the insertUpdate() method shifts the >+ * caret (if necessary) by the amount inserted. >+ * >+ * All caret movement is handled by the select() method, >+ * which eventually pipes the new position to scrollTo() >+ * and calls repaint(). >+ * >+ * Note that at this point in time, the new line hasn't >+ * yet been painted; the caret is moved first. >+ * >+ * scrollTo() calls offsetToX(), which tokenizes the line >+ * unless it is being called on the last line painted >+ * (in which case it uses the text area's painter cached >+ * token list). What scrollTo() does next is irrelevant. >+ * >+ * After scrollTo() has done it's job, repaint() is >+ * called, and eventually we end up in paintLine(), whose >+ * job is to paint the changed line. It, too, calls >+ * markTokens(). >+ * >+ * The problem was that if the line started a multiline >+ * token, the first markTokens() (done in offsetToX()) >+ * would set nextLineRequested (because the line end >+ * token had changed) but the second would clear it >+ * (because the line was the same that time) and therefore >+ * paintLine() would never know that it needed to repaint >+ * subsequent lines. >+ * >+ * This bug took me ages to track down, that's why I wrote >+ * all the relevant info down so that others wouldn't >+ * duplicate it. >+ */ >+ if(!(lastLine == lineIndex && nextLineRequested)) >+ nextLineRequested = (oldToken != token); >+ >+ lastLine = lineIndex; >+ >+ addToken(0,Token.END); >+ >+ return firstToken; >+ } >+ >+ /** >+ * An abstract method that splits a line up into tokens. It >+ * should parse the line, and call <code>addToken()</code> to >+ * add syntax tokens to the token list. Then, it should return >+ * the initial token type for the next line.<p> >+ * >+ * For example if the current line contains the start of a >+ * multiline comment that doesn't end on that line, this method >+ * should return the comment token type so that it continues on >+ * the next line. >+ * >+ * @param token The initial token type for this line >+ * @param line The line to be tokenized >+ * @param lineIndex The index of the line in the document, >+ * starting at 0 >+ * @return The initial token type for the next line >+ */ >+ protected abstract byte markTokensImpl(byte token, Segment line, >+ int lineIndex); >+ >+ /** >+ * Returns if the token marker supports tokens that span multiple >+ * lines. If this is true, the object using this token marker is >+ * required to pass all lines in the document to the >+ * <code>markTokens()</code> method (in turn).<p> >+ * >+ * The default implementation returns true; it should be overridden >+ * to return false on simpler token markers for increased speed. >+ */ >+ public boolean supportsMultilineTokens() >+ { >+ return true; >+ } >+ >+ /** >+ * Informs the token marker that lines have been inserted into >+ * the document. This inserts a gap in the <code>lineInfo</code> >+ * array. >+ * @param index The first line number >+ * @param lines The number of lines >+ */ >+ public void insertLines(int index, int lines) >+ { >+ if(lines <= 0) >+ return; >+ length += lines; >+ ensureCapacity(length); >+ int len = index + lines; >+ System.arraycopy(lineInfo,index,lineInfo,len, >+ lineInfo.length - len); >+ >+ for(int i = index + lines - 1; i >= index; i--) >+ { >+ lineInfo[i] = new LineInfo(); >+ } >+ } >+ >+ /** >+ * Informs the token marker that line have been deleted from >+ * the document. This removes the lines in question from the >+ * <code>lineInfo</code> array. >+ * @param index The first line number >+ * @param lines The number of lines >+ */ >+ public void deleteLines(int index, int lines) >+ { >+ if (lines <= 0) >+ return; >+ int len = index + lines; >+ length -= lines; >+ System.arraycopy(lineInfo,len,lineInfo, >+ index,lineInfo.length - len); >+ } >+ >+ /** >+ * Returns the number of lines in this token marker. >+ */ >+ public int getLineCount() >+ { >+ return length; >+ } >+ >+ /** >+ * Returns true if the next line should be repainted. This >+ * will return true after a line has been tokenized that starts >+ * a multiline token that continues onto the next line. >+ */ >+ public boolean isNextLineRequested() >+ { >+ return nextLineRequested; >+ } >+ >+ // protected members >+ >+ /** >+ * The first token in the list. This should be used as the return >+ * value from <code>markTokens()</code>. >+ */ >+ protected Token firstToken; >+ >+ /** >+ * The last token in the list. New tokens are added here. >+ * This should be set to null before a new line is to be tokenized. >+ */ >+ protected Token lastToken; >+ >+ /** >+ * An array for storing information about lines. It is enlarged and >+ * shrunk automatically by the <code>insertLines()</code> and >+ * <code>deleteLines()</code> methods. >+ */ >+ protected LineInfo[] lineInfo; >+ >+ /** >+ * The number of lines in the model being tokenized. This can be >+ * less than the length of the <code>lineInfo</code> array. >+ */ >+ protected int length; >+ >+ /** >+ * The last tokenized line. >+ */ >+ protected int lastLine; >+ >+ /** >+ * True if the next line should be painted. >+ */ >+ protected boolean nextLineRequested; >+ >+ /** >+ * Creates a new <code>TokenMarker</code>. This DOES NOT create >+ * a lineInfo array; an initial call to <code>insertLines()</code> >+ * does that. >+ */ >+ protected TokenMarker() >+ { >+ lastLine = -1; >+ } >+ >+ /** >+ * Ensures that the <code>lineInfo</code> array can contain the >+ * specified index. This enlarges it if necessary. No action is >+ * taken if the array is large enough already.<p> >+ * >+ * It should be unnecessary to call this under normal >+ * circumstances; <code>insertLine()</code> should take care of >+ * enlarging the line info array automatically. >+ * >+ * @param index The array index >+ */ >+ protected void ensureCapacity(int index) >+ { >+ if(lineInfo == null) >+ lineInfo = new LineInfo[index + 1]; >+ else if(lineInfo.length <= index) >+ { >+ LineInfo[] lineInfoN = new LineInfo[(index + 1) * 2]; >+ System.arraycopy(lineInfo,0,lineInfoN,0, >+ lineInfo.length); >+ lineInfo = lineInfoN; >+ } >+ } >+ >+ /** >+ * Adds a token to the token list. >+ * @param length The length of the token >+ * @param id The id of the token >+ */ >+ protected void addToken(int length, byte id) >+ { >+ if(id >= Token.INTERNAL_FIRST && id <= Token.INTERNAL_LAST) >+ throw new InternalError("Invalid id: " + id); >+ >+ if(length == 0 && id != Token.END) >+ return; >+ >+ if(firstToken == null) >+ { >+ firstToken = new Token(length,id); >+ lastToken = firstToken; >+ } >+ else if(lastToken == null) >+ { >+ lastToken = firstToken; >+ firstToken.length = length; >+ firstToken.id = id; >+ } >+ else if(lastToken.next == null) >+ { >+ lastToken.next = new Token(length,id); >+ lastToken = lastToken.next; >+ } >+ else >+ { >+ lastToken = lastToken.next; >+ lastToken.length = length; >+ lastToken.id = id; >+ } >+ } >+ >+ /** >+ * Inner class for storing information about tokenized lines. >+ */ >+ public class LineInfo >+ { >+ /** >+ * Creates a new LineInfo object with token = Token.NULL >+ * and obj = null. >+ */ >+ public LineInfo() >+ { >+ } >+ >+ /** >+ * Creates a new LineInfo object with the specified >+ * parameters. >+ */ >+ public LineInfo(byte token, Object obj) >+ { >+ this.token = token; >+ this.obj = obj; >+ } >+ >+ /** >+ * The id of the last token of the line. >+ */ >+ public byte token; >+ >+ /** >+ * This is for use by the token marker implementations >+ * themselves. It can be used to store anything that >+ * is an object and that needs to exist on a per-line >+ * basis. >+ */ >+ public Object obj; >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/KeywordMap.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/KeywordMap.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/KeywordMap.java (revision 0) >@@ -0,0 +1,139 @@ >+/* >+ * KeywordMap.java - Fast keyword->id map >+ * Copyright (C) 1998, 1999 Slava Pestov >+ * Copyright (C) 1999 Mike Dillon >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.Segment; >+ >+/** >+ * A <code>KeywordMap</code> is similar to a hashtable in that it maps keys >+ * to values. However, the `keys' are Swing segments. This allows lookups of >+ * text substrings without the overhead of creating a new string object. >+ * <p> >+ * This class is used by <code>CTokenMarker</code> to map keywords to ids. >+ * >+ * @author Slava Pestov, Mike Dillon >+ * @version $Id: KeywordMap.java,v 1.16 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class KeywordMap >+{ >+ /** >+ * Creates a new <code>KeywordMap</code>. >+ * @param ignoreCase True if keys are case insensitive >+ */ >+ public KeywordMap(boolean ignoreCase) >+ { >+ this(ignoreCase, 52); >+ this.ignoreCase = ignoreCase; >+ } >+ >+ /** >+ * Creates a new <code>KeywordMap</code>. >+ * @param ignoreCase True if the keys are case insensitive >+ * @param mapLength The number of `buckets' to create. >+ * A value of 52 will give good performance for most maps. >+ */ >+ public KeywordMap(boolean ignoreCase, int mapLength) >+ { >+ this.mapLength = mapLength; >+ this.ignoreCase = ignoreCase; >+ map = new Keyword[mapLength]; >+ } >+ >+ /** >+ * Looks up a key. >+ * @param text The text segment >+ * @param offset The offset of the substring within the text segment >+ * @param length The length of the substring >+ */ >+ public byte lookup(Segment text, int offset, int length) >+ { >+ if(length == 0) >+ return Token.NULL; >+ Keyword k = map[getSegmentMapKey(text, offset, length)]; >+ while(k != null) >+ { >+ if(length != k.keyword.length) >+ { >+ k = k.next; >+ continue; >+ } >+ if(SyntaxUtilities.regionMatches(ignoreCase,text,offset, >+ k.keyword)) >+ return k.id; >+ k = k.next; >+ } >+ return Token.NULL; >+ } >+ >+ /** >+ * Adds a key-value mapping. >+ * @param keyword The key >+ * @Param id The value >+ */ >+ public void add(String keyword, byte id) >+ { >+ int key = getStringMapKey(keyword); >+ map[key] = new Keyword(keyword.toCharArray(),id,map[key]); >+ } >+ >+ /** >+ * Returns true if the keyword map is set to be case insensitive, >+ * false otherwise. >+ */ >+ public boolean getIgnoreCase() >+ { >+ return ignoreCase; >+ } >+ >+ /** >+ * Sets if the keyword map should be case insensitive. >+ * @param ignoreCase True if the keyword map should be case >+ * insensitive, false otherwise >+ */ >+ public void setIgnoreCase(boolean ignoreCase) >+ { >+ this.ignoreCase = ignoreCase; >+ } >+ >+ // protected members >+ protected int mapLength; >+ >+ protected int getStringMapKey(String s) >+ { >+ return (Character.toUpperCase(s.charAt(0)) + >+ Character.toUpperCase(s.charAt(s.length()-1))) >+ % mapLength; >+ } >+ >+ protected int getSegmentMapKey(Segment s, int off, int len) >+ { >+ return (Character.toUpperCase(s.array[off]) + >+ Character.toUpperCase(s.array[off + len - 1])) >+ % mapLength; >+ } >+ >+ // private members >+ class Keyword >+ { >+ public Keyword(char[] keyword, byte id, Keyword next) >+ { >+ this.keyword = keyword; >+ this.id = id; >+ this.next = next; >+ } >+ >+ public char[] keyword; >+ public byte id; >+ public Keyword next; >+ } >+ >+ private Keyword[] map; >+ private boolean ignoreCase; >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxDocument.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxDocument.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/SyntaxDocument.java (revision 0) >@@ -0,0 +1,165 @@ >+/* >+ * SyntaxDocument.java - Document that can be tokenized >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.event.*; >+import javax.swing.text.*; >+import javax.swing.undo.UndoableEdit; >+ >+/** >+ * A document implementation that can be tokenized by the syntax highlighting >+ * system. >+ * >+ * @author Slava Pestov >+ * @version $Id: SyntaxDocument.java,v 1.14 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class SyntaxDocument extends PlainDocument >+{ >+ /** >+ * Returns the token marker that is to be used to split lines >+ * of this document up into tokens. May return null if this >+ * document is not to be colorized. >+ */ >+ public TokenMarker getTokenMarker() >+ { >+ return tokenMarker; >+ } >+ >+ /** >+ * Sets the token marker that is to be used to split lines of >+ * this document up into tokens. May throw an exception if >+ * this is not supported for this type of document. >+ * @param tm The new token marker >+ */ >+ public void setTokenMarker(TokenMarker tm) >+ { >+ tokenMarker = tm; >+ if(tm == null) >+ return; >+ tokenMarker.insertLines(0,getDefaultRootElement() >+ .getElementCount()); >+ tokenizeLines(); >+ } >+ >+ /** >+ * Reparses the document, by passing all lines to the token >+ * marker. This should be called after the document is first >+ * loaded. >+ */ >+ public void tokenizeLines() >+ { >+ tokenizeLines(0,getDefaultRootElement().getElementCount()); >+ } >+ >+ /** >+ * Reparses the document, by passing the specified lines to the >+ * token marker. This should be called after a large quantity of >+ * text is first inserted. >+ * @param start The first line to parse >+ * @param len The number of lines, after the first one to parse >+ */ >+ public void tokenizeLines(int start, int len) >+ { >+ if(tokenMarker == null || !tokenMarker.supportsMultilineTokens()) >+ return; >+ >+ Segment lineSegment = new Segment(); >+ Element map = getDefaultRootElement(); >+ >+ len += start; >+ >+ try >+ { >+ for(int i = start; i < len; i++) >+ { >+ Element lineElement = map.getElement(i); >+ int lineStart = lineElement.getStartOffset(); >+ getText(lineStart,lineElement.getEndOffset() >+ - lineStart - 1,lineSegment); >+ tokenMarker.markTokens(lineSegment,i); >+ } >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ } >+ >+ /** >+ * Starts a compound edit that can be undone in one operation. >+ * Subclasses that implement undo should override this method; >+ * this class has no undo functionality so this method is >+ * empty. >+ */ >+ public void beginCompoundEdit() {} >+ >+ /** >+ * Ends a compound edit that can be undone in one operation. >+ * Subclasses that implement undo should override this method; >+ * this class has no undo functionality so this method is >+ * empty. >+ */ >+ public void endCompoundEdit() {} >+ >+ /** >+ * Adds an undoable edit to this document's undo list. The edit >+ * should be ignored if something is currently being undone. >+ * @param edit The undoable edit >+ * >+ * @since jEdit 2.2pre1 >+ */ >+ public void addUndoableEdit(UndoableEdit edit) {} >+ >+ // protected members >+ protected TokenMarker tokenMarker; >+ >+ /** >+ * We overwrite this method to update the token marker >+ * state immediately so that any event listeners get a >+ * consistent token marker. >+ */ >+ protected void fireInsertUpdate(DocumentEvent evt) >+ { >+ if(tokenMarker != null) >+ { >+ DocumentEvent.ElementChange ch = evt.getChange( >+ getDefaultRootElement()); >+ if(ch != null) >+ { >+ tokenMarker.insertLines(ch.getIndex() + 1, >+ ch.getChildrenAdded().length - >+ ch.getChildrenRemoved().length); >+ } >+ } >+ >+ super.fireInsertUpdate(evt); >+ } >+ >+ /** >+ * We overwrite this method to update the token marker >+ * state immediately so that any event listeners get a >+ * consistent token marker. >+ */ >+ protected void fireRemoveUpdate(DocumentEvent evt) >+ { >+ if(tokenMarker != null) >+ { >+ DocumentEvent.ElementChange ch = evt.getChange( >+ getDefaultRootElement()); >+ if(ch != null) >+ { >+ tokenMarker.deleteLines(ch.getIndex() + 1, >+ ch.getChildrenRemoved().length - >+ ch.getChildrenAdded().length); >+ } >+ } >+ >+ super.fireRemoveUpdate(evt); >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/JEditTextArea.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/JEditTextArea.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/JEditTextArea.java (revision 0) >@@ -0,0 +1,2128 @@ >+/* >+ * JEditTextArea.java - jEdit's text component >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.event.*; >+import javax.swing.text.*; >+import javax.swing.undo.*; >+import javax.swing.*; >+import java.awt.datatransfer.*; >+import java.awt.event.*; >+import java.awt.*; >+import java.util.Enumeration; >+import java.util.Vector; >+ >+/** >+ * jEdit's text area component. It is more suited for editing program >+ * source code than JEditorPane, because it drops the unnecessary features >+ * (images, variable-width lines, and so on) and adds a whole bunch of >+ * useful goodies such as: >+ * <ul> >+ * <li>More flexible key binding scheme >+ * <li>Supports macro recorders >+ * <li>Rectangular selection >+ * <li>Bracket highlighting >+ * <li>Syntax highlighting >+ * <li>Command repetition >+ * <li>Block caret can be enabled >+ * </ul> >+ * It is also faster and doesn't have as many problems. It can be used >+ * in other applications; the only other part of jEdit it depends on is >+ * the syntax package.<p> >+ * >+ * To use it in your app, treat it like any other component, for example: >+ * <pre>JEditTextArea ta = new JEditTextArea(); >+ * ta.setTokenMarker(new JavaTokenMarker()); >+ * ta.setText("public class Test {\n" >+ * + " public static void main(String[] args) {\n" >+ * + " System.out.println(\"Hello World\");\n" >+ * + " }\n" >+ * + "}");</pre> >+ * >+ * @author Slava Pestov >+ * @version $Id: JEditTextArea.java,v 1.36 1999/12/13 03:40:30 sp Exp $ >+ */ >+public class JEditTextArea extends JComponent >+{ >+ /** >+ * Adding components with this name to the text area will place >+ * them left of the horizontal scroll bar. In jEdit, the status >+ * bar is added this way. >+ */ >+ public static String LEFT_OF_SCROLLBAR = "los"; >+ >+ /** >+ * Creates a new JEditTextArea with the default settings. >+ */ >+ public JEditTextArea() >+ { >+ this(TextAreaDefaults.getDefaults()); >+ } >+ >+ /** >+ * Creates a new JEditTextArea with the specified settings. >+ * @param defaults The default settings >+ */ >+ public JEditTextArea(TextAreaDefaults defaults) >+ { >+ // Enable the necessary events >+ enableEvents(AWTEvent.KEY_EVENT_MASK); >+ >+ // Initialize some misc. stuff >+ painter = new TextAreaPainter(this,defaults); >+ documentHandler = new DocumentHandler(); >+ listenerList = new EventListenerList(); >+ caretEvent = new MutableCaretEvent(); >+ lineSegment = new Segment(); >+ bracketLine = bracketPosition = -1; >+ blink = true; >+ >+ // Initialize the GUI >+ setLayout(new ScrollLayout()); >+ add(CENTER,painter); >+ add(RIGHT,vertical = new JScrollBar(JScrollBar.VERTICAL)); >+ add(BOTTOM,horizontal = new JScrollBar(JScrollBar.HORIZONTAL)); >+ >+ // Add some event listeners >+ vertical.addAdjustmentListener(new AdjustHandler()); >+ horizontal.addAdjustmentListener(new AdjustHandler()); >+ painter.addComponentListener(new ComponentHandler()); >+ painter.addMouseListener(new MouseHandler()); >+ painter.addMouseMotionListener(new DragHandler()); >+ addFocusListener(new FocusHandler()); >+ >+ // Load the defaults >+ setInputHandler(defaults.inputHandler); >+ setDocument(defaults.document); >+ editable = defaults.editable; >+ caretVisible = defaults.caretVisible; >+ caretBlinks = defaults.caretBlinks; >+ electricScroll = defaults.electricScroll; >+ >+ popup = defaults.popup; >+ >+ // We don't seem to get the initial focus event? >+ focusedComponent = this; >+ } >+ >+ /** >+ * Returns if this component can be traversed by pressing >+ * the Tab key. This returns false. >+ */ >+ public final boolean isManagingFocus() >+ { >+ return true; >+ } >+ >+ /** >+ * Returns the object responsible for painting this text area. >+ */ >+ public final TextAreaPainter getPainter() >+ { >+ return painter; >+ } >+ >+ /** >+ * Returns the input handler. >+ */ >+ public final InputHandler getInputHandler() >+ { >+ return inputHandler; >+ } >+ >+ /** >+ * Sets the input handler. >+ * @param inputHandler The new input handler >+ */ >+ public void setInputHandler(InputHandler inputHandler) >+ { >+ this.inputHandler = inputHandler; >+ } >+ >+ /** >+ * Returns true if the caret is blinking, false otherwise. >+ */ >+ public final boolean isCaretBlinkEnabled() >+ { >+ return caretBlinks; >+ } >+ >+ /** >+ * Toggles caret blinking. >+ * @param caretBlinks True if the caret should blink, false otherwise >+ */ >+ public void setCaretBlinkEnabled(boolean caretBlinks) >+ { >+ this.caretBlinks = caretBlinks; >+ if(!caretBlinks) >+ blink = false; >+ >+ painter.invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns true if the caret is visible, false otherwise. >+ */ >+ public final boolean isCaretVisible() >+ { >+ return (!caretBlinks || blink) && caretVisible; >+ } >+ >+ /** >+ * Sets if the caret should be visible. >+ * @param caretVisible True if the caret should be visible, false >+ * otherwise >+ */ >+ public void setCaretVisible(boolean caretVisible) >+ { >+ this.caretVisible = caretVisible; >+ blink = true; >+ >+ painter.invalidateSelectedLines(); >+ } >+ >+ /** >+ * Blinks the caret. >+ */ >+ public final void blinkCaret() >+ { >+ if(caretBlinks) >+ { >+ blink = !blink; >+ painter.invalidateSelectedLines(); >+ } >+ else >+ blink = true; >+ } >+ >+ /** >+ * Returns the number of lines from the top and button of the >+ * text area that are always visible. >+ */ >+ public final int getElectricScroll() >+ { >+ return electricScroll; >+ } >+ >+ /** >+ * Sets the number of lines from the top and bottom of the text >+ * area that are always visible >+ * @param electricScroll The number of lines always visible from >+ * the top or bottom >+ */ >+ public final void setElectricScroll(int electricScroll) >+ { >+ this.electricScroll = electricScroll; >+ } >+ >+ /** >+ * Updates the state of the scroll bars. This should be called >+ * if the number of lines in the document changes, or when the >+ * size of the text are changes. >+ */ >+ public void updateScrollBars() >+ { >+ if(vertical != null && visibleLines != 0) >+ { >+ vertical.setValues(firstLine,visibleLines,0,getLineCount()); >+ vertical.setUnitIncrement(2); >+ vertical.setBlockIncrement(visibleLines); >+ } >+ >+ int width = painter.getWidth(); >+ if(horizontal != null && width != 0) >+ { >+ horizontal.setValues(-horizontalOffset,width,0,width * 5); >+ horizontal.setUnitIncrement(painter.getFontMetrics() >+ .charWidth('w')); >+ horizontal.setBlockIncrement(width / 2); >+ } >+ } >+ >+ /** >+ * Returns the line displayed at the text area's origin. >+ */ >+ public final int getFirstLine() >+ { >+ return firstLine; >+ } >+ >+ /** >+ * Sets the line displayed at the text area's origin without >+ * updating the scroll bars. >+ */ >+ public void setFirstLine(int firstLine) >+ { >+ if(firstLine == this.firstLine) >+ return; >+ int oldFirstLine = this.firstLine; >+ this.firstLine = firstLine; >+ if(firstLine != vertical.getValue()) >+ updateScrollBars(); >+ painter.repaint(); >+ } >+ >+ /** >+ * Returns the number of lines visible in this text area. >+ */ >+ public final int getVisibleLines() >+ { >+ return visibleLines; >+ } >+ >+ /** >+ * Recalculates the number of visible lines. This should not >+ * be called directly. >+ */ >+ public final void recalculateVisibleLines() >+ { >+ if(painter == null) >+ return; >+ int height = painter.getHeight(); >+ int lineHeight = painter.getFontMetrics().getHeight(); >+ int oldVisibleLines = visibleLines; >+ visibleLines = height / lineHeight; >+ updateScrollBars(); >+ } >+ >+ /** >+ * Returns the horizontal offset of drawn lines. >+ */ >+ public final int getHorizontalOffset() >+ { >+ return horizontalOffset; >+ } >+ >+ /** >+ * Sets the horizontal offset of drawn lines. This can be used to >+ * implement horizontal scrolling. >+ * @param horizontalOffset offset The new horizontal offset >+ */ >+ public void setHorizontalOffset(int horizontalOffset) >+ { >+ if(horizontalOffset == this.horizontalOffset) >+ return; >+ this.horizontalOffset = horizontalOffset; >+ if(horizontalOffset != horizontal.getValue()) >+ updateScrollBars(); >+ painter.repaint(); >+ } >+ >+ /** >+ * A fast way of changing both the first line and horizontal >+ * offset. >+ * @param firstLine The new first line >+ * @param horizontalOffset The new horizontal offset >+ * @return True if any of the values were changed, false otherwise >+ */ >+ public boolean setOrigin(int firstLine, int horizontalOffset) >+ { >+ boolean changed = false; >+ int oldFirstLine = this.firstLine; >+ >+ if(horizontalOffset != this.horizontalOffset) >+ { >+ this.horizontalOffset = horizontalOffset; >+ changed = true; >+ } >+ >+ if(firstLine != this.firstLine) >+ { >+ this.firstLine = firstLine; >+ changed = true; >+ } >+ >+ if(changed) >+ { >+ updateScrollBars(); >+ painter.repaint(); >+ } >+ >+ return changed; >+ } >+ >+ /** >+ * Ensures that the caret is visible by scrolling the text area if >+ * necessary. >+ * @return True if scrolling was actually performed, false if the >+ * caret was already visible >+ */ >+ public boolean scrollToCaret() >+ { >+ int line = getCaretLine(); >+ int lineStart = getLineStartOffset(line); >+ int offset = Math.max(0,Math.min(getLineLength(line) - 1, >+ getCaretPosition() - lineStart)); >+ >+ return scrollTo(line,offset); >+ } >+ >+ /** >+ * Ensures that the specified line and offset is visible by scrolling >+ * the text area if necessary. >+ * @param line The line to scroll to >+ * @param offset The offset in the line to scroll to >+ * @return True if scrolling was actually performed, false if the >+ * line and offset was already visible >+ */ >+ public boolean scrollTo(int line, int offset) >+ { >+ // visibleLines == 0 before the component is realized >+ // we can't do any proper scrolling then, so we have >+ // this hack... >+ if(visibleLines == 0) >+ { >+ setFirstLine(Math.max(0,line - electricScroll)); >+ return true; >+ } >+ >+ int newFirstLine = firstLine; >+ int newHorizontalOffset = horizontalOffset; >+ >+ if(line < firstLine + electricScroll) >+ { >+ newFirstLine = Math.max(0,line - electricScroll); >+ } >+ else if(line + electricScroll >= firstLine + visibleLines) >+ { >+ newFirstLine = (line - visibleLines) + electricScroll + 1; >+ if(newFirstLine + visibleLines >= getLineCount()) >+ newFirstLine = getLineCount() - visibleLines; >+ if(newFirstLine < 0) >+ newFirstLine = 0; >+ } >+ >+ int x = _offsetToX(line,offset); >+ int width = painter.getFontMetrics().charWidth('w'); >+ >+ if(x < 0) >+ { >+ newHorizontalOffset = Math.min(0,horizontalOffset >+ - x + width + 5); >+ } >+ else if(x + width >= painter.getWidth()) >+ { >+ newHorizontalOffset = horizontalOffset + >+ (painter.getWidth() - x) - width - 5; >+ } >+ >+ return setOrigin(newFirstLine,newHorizontalOffset); >+ } >+ >+ /** >+ * Converts a line index to a y co-ordinate. >+ * @param line The line >+ */ >+ public int lineToY(int line) >+ { >+ FontMetrics fm = painter.getFontMetrics(); >+ return (line - firstLine) * fm.getHeight() >+ - (fm.getLeading() + fm.getMaxDescent()); >+ } >+ >+ /** >+ * Converts a y co-ordinate to a line index. >+ * @param y The y co-ordinate >+ */ >+ public int yToLine(int y) >+ { >+ FontMetrics fm = painter.getFontMetrics(); >+ int height = fm.getHeight(); >+ return Math.max(0,Math.min(getLineCount() - 1, >+ y / height + firstLine)); >+ } >+ >+ /** >+ * Converts an offset in a line into an x co-ordinate. This is a >+ * slow version that can be used any time. >+ * @param line The line >+ * @param offset The offset, from the start of the line >+ */ >+ public final int offsetToX(int line, int offset) >+ { >+ // don't use cached tokens >+ painter.currentLineTokens = null; >+ return _offsetToX(line,offset); >+ } >+ >+ /** >+ * Converts an offset in a line into an x co-ordinate. This is a >+ * fast version that should only be used if no changes were made >+ * to the text since the last repaint. >+ * @param line The line >+ * @param offset The offset, from the start of the line >+ */ >+ public int _offsetToX(int line, int offset) >+ { >+ TokenMarker tokenMarker = getTokenMarker(); >+ >+ /* Use painter's cached info for speed */ >+ FontMetrics fm = painter.getFontMetrics(); >+ >+ getLineText(line,lineSegment); >+ >+ int segmentOffset = lineSegment.offset; >+ int x = horizontalOffset; >+ >+ /* If syntax coloring is disabled, do simple translation */ >+ if(tokenMarker == null) >+ { >+ lineSegment.count = offset; >+ return x + Utilities.getTabbedTextWidth(lineSegment, >+ fm,x,painter,0); >+ } >+ /* If syntax coloring is enabled, we have to do this because >+ * tokens can vary in width */ >+ else >+ { >+ Token tokens; >+ if(painter.currentLineIndex == line >+ && painter.currentLineTokens != null) >+ tokens = painter.currentLineTokens; >+ else >+ { >+ painter.currentLineIndex = line; >+ tokens = painter.currentLineTokens >+ = tokenMarker.markTokens(lineSegment,line); >+ } >+ >+ Toolkit toolkit = painter.getToolkit(); >+ Font defaultFont = painter.getFont(); >+ SyntaxStyle[] styles = painter.getStyles(); >+ >+ for(;;) >+ { >+ byte id = tokens.id; >+ if(id == Token.END) >+ { >+ return x; >+ } >+ >+ if(id == Token.NULL) >+ fm = painter.getFontMetrics(); >+ else >+ fm = styles[id].getFontMetrics(defaultFont); >+ >+ int length = tokens.length; >+ >+ if(offset + segmentOffset < lineSegment.offset + length) >+ { >+ lineSegment.count = offset - (lineSegment.offset - segmentOffset); >+ return x + Utilities.getTabbedTextWidth( >+ lineSegment,fm,x,painter,0); >+ } >+ else >+ { >+ lineSegment.count = length; >+ x += Utilities.getTabbedTextWidth( >+ lineSegment,fm,x,painter,0); >+ lineSegment.offset += length; >+ } >+ tokens = tokens.next; >+ } >+ } >+ } >+ >+ /** >+ * Converts an x co-ordinate to an offset within a line. >+ * @param line The line >+ * @param x The x co-ordinate >+ */ >+ public int xToOffset(int line, int x) >+ { >+ TokenMarker tokenMarker = getTokenMarker(); >+ >+ /* Use painter's cached info for speed */ >+ FontMetrics fm = painter.getFontMetrics(); >+ >+ getLineText(line,lineSegment); >+ >+ char[] segmentArray = lineSegment.array; >+ int segmentOffset = lineSegment.offset; >+ int segmentCount = lineSegment.count; >+ >+ int width = horizontalOffset; >+ >+ if(tokenMarker == null) >+ { >+ for(int i = 0; i < segmentCount; i++) >+ { >+ char c = segmentArray[i + segmentOffset]; >+ int charWidth; >+ if(c == '\t') >+ charWidth = (int)painter.nextTabStop(width,i) >+ - width; >+ else >+ charWidth = fm.charWidth(c); >+ >+ if(painter.isBlockCaretEnabled()) >+ { >+ if(x - charWidth <= width) >+ return i; >+ } >+ else >+ { >+ if(x - charWidth / 2 <= width) >+ return i; >+ } >+ >+ width += charWidth; >+ } >+ >+ return segmentCount; >+ } >+ else >+ { >+ Token tokens; >+ if(painter.currentLineIndex == line && painter >+ .currentLineTokens != null) >+ tokens = painter.currentLineTokens; >+ else >+ { >+ painter.currentLineIndex = line; >+ tokens = painter.currentLineTokens >+ = tokenMarker.markTokens(lineSegment,line); >+ } >+ >+ int offset = 0; >+ Toolkit toolkit = painter.getToolkit(); >+ Font defaultFont = painter.getFont(); >+ SyntaxStyle[] styles = painter.getStyles(); >+ >+ for(;;) >+ { >+ byte id = tokens.id; >+ if(id == Token.END) >+ return offset; >+ >+ if(id == Token.NULL) >+ fm = painter.getFontMetrics(); >+ else >+ fm = styles[id].getFontMetrics(defaultFont); >+ >+ int length = tokens.length; >+ >+ for(int i = 0; i < length; i++) >+ { >+ char c = segmentArray[segmentOffset + offset + i]; >+ int charWidth; >+ if(c == '\t') >+ charWidth = (int)painter.nextTabStop(width,offset + i) >+ - width; >+ else >+ charWidth = fm.charWidth(c); >+ >+ if(painter.isBlockCaretEnabled()) >+ { >+ if(x - charWidth <= width) >+ return offset + i; >+ } >+ else >+ { >+ if(x - charWidth / 2 <= width) >+ return offset + i; >+ } >+ >+ width += charWidth; >+ } >+ >+ offset += length; >+ tokens = tokens.next; >+ } >+ } >+ } >+ >+ /** >+ * Converts a point to an offset, from the start of the text. >+ * @param x The x co-ordinate of the point >+ * @param y The y co-ordinate of the point >+ */ >+ public int xyToOffset(int x, int y) >+ { >+ int line = yToLine(y); >+ int start = getLineStartOffset(line); >+ return start + xToOffset(line,x); >+ } >+ >+ /** >+ * Returns the document this text area is editing. >+ */ >+ public final SyntaxDocument getDocument() >+ { >+ return document; >+ } >+ >+ /** >+ * Sets the document this text area is editing. >+ * @param document The document >+ */ >+ public void setDocument(SyntaxDocument document) >+ { >+ if(this.document == document) >+ return; >+ if(this.document != null) >+ this.document.removeDocumentListener(documentHandler); >+ this.document = document; >+ >+ document.addDocumentListener(documentHandler); >+ >+ select(0,0); >+ updateScrollBars(); >+ painter.repaint(); >+ } >+ >+ /** >+ * Returns the document's token marker. Equivalent to calling >+ * <code>getDocument().getTokenMarker()</code>. >+ */ >+ public final TokenMarker getTokenMarker() >+ { >+ return document.getTokenMarker(); >+ } >+ >+ /** >+ * Sets the document's token marker. Equivalent to caling >+ * <code>getDocument().setTokenMarker()</code>. >+ * @param tokenMarker The token marker >+ */ >+ public final void setTokenMarker(TokenMarker tokenMarker) >+ { >+ document.setTokenMarker(tokenMarker); >+ } >+ >+ /** >+ * Returns the length of the document. Equivalent to calling >+ * <code>getDocument().getLength()</code>. >+ */ >+ public final int getDocumentLength() >+ { >+ return document.getLength(); >+ } >+ >+ /** >+ * Returns the number of lines in the document. >+ */ >+ public final int getLineCount() >+ { >+ return document.getDefaultRootElement().getElementCount(); >+ } >+ >+ /** >+ * Returns the line containing the specified offset. >+ * @param offset The offset >+ */ >+ public final int getLineOfOffset(int offset) >+ { >+ return document.getDefaultRootElement().getElementIndex(offset); >+ } >+ >+ /** >+ * Returns the start offset of the specified line. >+ * @param line The line >+ * @return The start offset of the specified line, or -1 if the line is >+ * invalid >+ */ >+ public int getLineStartOffset(int line) >+ { >+ Element lineElement = document.getDefaultRootElement() >+ .getElement(line); >+ if(lineElement == null) >+ return -1; >+ else >+ return lineElement.getStartOffset(); >+ } >+ >+ /** >+ * Returns the end offset of the specified line. >+ * @param line The line >+ * @return The end offset of the specified line, or -1 if the line is >+ * invalid. >+ */ >+ public int getLineEndOffset(int line) >+ { >+ Element lineElement = document.getDefaultRootElement() >+ .getElement(line); >+ if(lineElement == null) >+ return -1; >+ else >+ return lineElement.getEndOffset(); >+ } >+ >+ /** >+ * Returns the length of the specified line. >+ * @param line The line >+ */ >+ public int getLineLength(int line) >+ { >+ Element lineElement = document.getDefaultRootElement() >+ .getElement(line); >+ if(lineElement == null) >+ return -1; >+ else >+ return lineElement.getEndOffset() >+ - lineElement.getStartOffset() - 1; >+ } >+ >+ /** >+ * Returns the entire text of this text area. >+ */ >+ public String getText() >+ { >+ try >+ { >+ return document.getText(0,document.getLength()); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ return null; >+ } >+ } >+ >+ /** >+ * Sets the entire text of this text area. >+ */ >+ public void setText(String text) >+ { >+ try >+ { >+ document.beginCompoundEdit(); >+ document.remove(0,document.getLength()); >+ document.insertString(0,text,null); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ finally >+ { >+ document.endCompoundEdit(); >+ } >+ } >+ >+ /** >+ * Returns the specified substring of the document. >+ * @param start The start offset >+ * @param len The length of the substring >+ * @return The substring, or null if the offsets are invalid >+ */ >+ public final String getText(int start, int len) >+ { >+ try >+ { >+ return document.getText(start,len); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ return null; >+ } >+ } >+ >+ /** >+ * Copies the specified substring of the document into a segment. >+ * If the offsets are invalid, the segment will contain a null string. >+ * @param start The start offset >+ * @param len The length of the substring >+ * @param segment The segment >+ */ >+ public final void getText(int start, int len, Segment segment) >+ { >+ try >+ { >+ document.getText(start,len,segment); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ segment.offset = segment.count = 0; >+ } >+ } >+ >+ /** >+ * Returns the text on the specified line. >+ * @param lineIndex The line >+ * @return The text, or null if the line is invalid >+ */ >+ public final String getLineText(int lineIndex) >+ { >+ int start = getLineStartOffset(lineIndex); >+ return getText(start,getLineEndOffset(lineIndex) - start - 1); >+ } >+ >+ /** >+ * Copies the text on the specified line into a segment. If the line >+ * is invalid, the segment will contain a null string. >+ * @param lineIndex The line >+ */ >+ public final void getLineText(int lineIndex, Segment segment) >+ { >+ int start = getLineStartOffset(lineIndex); >+ getText(start,getLineEndOffset(lineIndex) - start - 1,segment); >+ } >+ >+ /** >+ * Returns the selection start offset. >+ */ >+ public final int getSelectionStart() >+ { >+ return selectionStart; >+ } >+ >+ /** >+ * Returns the offset where the selection starts on the specified >+ * line. >+ */ >+ public int getSelectionStart(int line) >+ { >+ if(line == selectionStartLine) >+ return selectionStart; >+ else if(rectSelect) >+ { >+ Element map = document.getDefaultRootElement(); >+ int start = selectionStart - map.getElement(selectionStartLine) >+ .getStartOffset(); >+ >+ Element lineElement = map.getElement(line); >+ int lineStart = lineElement.getStartOffset(); >+ int lineEnd = lineElement.getEndOffset() - 1; >+ return Math.min(lineEnd,lineStart + start); >+ } >+ else >+ return getLineStartOffset(line); >+ } >+ >+ /** >+ * Returns the selection start line. >+ */ >+ public final int getSelectionStartLine() >+ { >+ return selectionStartLine; >+ } >+ >+ /** >+ * Sets the selection start. The new selection will be the new >+ * selection start and the old selection end. >+ * @param selectionStart The selection start >+ * @see #select(int,int) >+ */ >+ public final void setSelectionStart(int selectionStart) >+ { >+ select(selectionStart,selectionEnd); >+ } >+ >+ /** >+ * Returns the selection end offset. >+ */ >+ public final int getSelectionEnd() >+ { >+ return selectionEnd; >+ } >+ >+ /** >+ * Returns the offset where the selection ends on the specified >+ * line. >+ */ >+ public int getSelectionEnd(int line) >+ { >+ if(line == selectionEndLine) >+ return selectionEnd; >+ else if(rectSelect) >+ { >+ Element map = document.getDefaultRootElement(); >+ int end = selectionEnd - map.getElement(selectionEndLine) >+ .getStartOffset(); >+ >+ Element lineElement = map.getElement(line); >+ int lineStart = lineElement.getStartOffset(); >+ int lineEnd = lineElement.getEndOffset() - 1; >+ return Math.min(lineEnd,lineStart + end); >+ } >+ else >+ return getLineEndOffset(line) - 1; >+ } >+ >+ /** >+ * Returns the selection end line. >+ */ >+ public final int getSelectionEndLine() >+ { >+ return selectionEndLine; >+ } >+ >+ /** >+ * Sets the selection end. The new selection will be the old >+ * selection start and the bew selection end. >+ * @param selectionEnd The selection end >+ * @see #select(int,int) >+ */ >+ public final void setSelectionEnd(int selectionEnd) >+ { >+ select(selectionStart,selectionEnd); >+ } >+ >+ /** >+ * Returns the caret position. This will either be the selection >+ * start or the selection end, depending on which direction the >+ * selection was made in. >+ */ >+ public final int getCaretPosition() >+ { >+ return (biasLeft ? selectionStart : selectionEnd); >+ } >+ >+ /** >+ * Returns the caret line. >+ */ >+ public final int getCaretLine() >+ { >+ return (biasLeft ? selectionStartLine : selectionEndLine); >+ } >+ >+ /** >+ * Returns the mark position. This will be the opposite selection >+ * bound to the caret position. >+ * @see #getCaretPosition() >+ */ >+ public final int getMarkPosition() >+ { >+ return (biasLeft ? selectionEnd : selectionStart); >+ } >+ >+ /** >+ * Returns the mark line. >+ */ >+ public final int getMarkLine() >+ { >+ return (biasLeft ? selectionEndLine : selectionStartLine); >+ } >+ >+ /** >+ * Sets the caret position. The new selection will consist of the >+ * caret position only (hence no text will be selected) >+ * @param caret The caret position >+ * @see #select(int,int) >+ */ >+ public final void setCaretPosition(int caret) >+ { >+ select(caret,caret); >+ } >+ >+ /** >+ * Selects all text in the document. >+ */ >+ public final void selectAll() >+ { >+ select(0,getDocumentLength()); >+ } >+ >+ /** >+ * Moves the mark to the caret position. >+ */ >+ public final void selectNone() >+ { >+ select(getCaretPosition(),getCaretPosition()); >+ } >+ >+ /** >+ * Selects from the start offset to the end offset. This is the >+ * general selection method used by all other selecting methods. >+ * The caret position will be start if start < end, and end >+ * if end > start. >+ * @param start The start offset >+ * @param end The end offset >+ */ >+ public void select(int start, int end) >+ { >+ int newStart, newEnd; >+ boolean newBias; >+ if(start <= end) >+ { >+ newStart = start; >+ newEnd = end; >+ newBias = false; >+ } >+ else >+ { >+ newStart = end; >+ newEnd = start; >+ newBias = true; >+ } >+ >+ if(newStart < 0 || newEnd > getDocumentLength()) >+ { >+ throw new IllegalArgumentException("Bounds out of" >+ + " range: " + newStart + "," + >+ newEnd); >+ } >+ >+ // If the new position is the same as the old, we don't >+ // do all this crap, however we still do the stuff at >+ // the end (clearing magic position, scrolling) >+ if(newStart != selectionStart || newEnd != selectionEnd >+ || newBias != biasLeft) >+ { >+ int newStartLine = getLineOfOffset(newStart); >+ int newEndLine = getLineOfOffset(newEnd); >+ >+ if(painter.isBracketHighlightEnabled()) >+ { >+ if(bracketLine != -1) >+ painter.invalidateLine(bracketLine); >+ updateBracketHighlight(end); >+ if(bracketLine != -1) >+ painter.invalidateLine(bracketLine); >+ } >+ >+ painter.invalidateLineRange(selectionStartLine,selectionEndLine); >+ painter.invalidateLineRange(newStartLine,newEndLine); >+ >+ document.addUndoableEdit(new CaretUndo( >+ selectionStart,selectionEnd)); >+ >+ selectionStart = newStart; >+ selectionEnd = newEnd; >+ selectionStartLine = newStartLine; >+ selectionEndLine = newEndLine; >+ biasLeft = newBias; >+ >+ fireCaretEvent(); >+ } >+ >+ // When the user is typing, etc, we don't want the caret >+ // to blink >+ blink = true; >+ caretTimer.restart(); >+ >+ // Disable rectangle select if selection start = selection end >+ if(selectionStart == selectionEnd) >+ rectSelect = false; >+ >+ // Clear the `magic' caret position used by up/down >+ magicCaret = -1; >+ >+ scrollToCaret(); >+ } >+ >+ /** >+ * Returns the selected text, or null if no selection is active. >+ */ >+ public final String getSelectedText() >+ { >+ if(selectionStart == selectionEnd) >+ return null; >+ >+ if(rectSelect) >+ { >+ // Return each row of the selection on a new line >+ >+ Element map = document.getDefaultRootElement(); >+ >+ int start = selectionStart - map.getElement(selectionStartLine) >+ .getStartOffset(); >+ int end = selectionEnd - map.getElement(selectionEndLine) >+ .getStartOffset(); >+ >+ // Certain rectangles satisfy this condition... >+ if(end < start) >+ { >+ int tmp = end; >+ end = start; >+ start = tmp; >+ } >+ >+ StringBuffer buf = new StringBuffer(); >+ Segment seg = new Segment(); >+ >+ for(int i = selectionStartLine; i <= selectionEndLine; i++) >+ { >+ Element lineElement = map.getElement(i); >+ int lineStart = lineElement.getStartOffset(); >+ int lineEnd = lineElement.getEndOffset() - 1; >+ int lineLen = lineEnd - lineStart; >+ >+ lineStart = Math.min(lineStart + start,lineEnd); >+ lineLen = Math.min(end - start,lineEnd - lineStart); >+ >+ getText(lineStart,lineLen,seg); >+ buf.append(seg.array,seg.offset,seg.count); >+ >+ if(i != selectionEndLine) >+ buf.append('\n'); >+ } >+ >+ return buf.toString(); >+ } >+ else >+ { >+ return getText(selectionStart, >+ selectionEnd - selectionStart); >+ } >+ } >+ >+ /** >+ * Replaces the selection with the specified text. >+ * @param selectedText The replacement text for the selection >+ */ >+ public void setSelectedText(String selectedText) >+ { >+ if(!editable) >+ { >+ throw new InternalError("Text component" >+ + " read only"); >+ } >+ >+ document.beginCompoundEdit(); >+ >+ try >+ { >+ if(rectSelect) >+ { >+ Element map = document.getDefaultRootElement(); >+ >+ int start = selectionStart - map.getElement(selectionStartLine) >+ .getStartOffset(); >+ int end = selectionEnd - map.getElement(selectionEndLine) >+ .getStartOffset(); >+ >+ // Certain rectangles satisfy this condition... >+ if(end < start) >+ { >+ int tmp = end; >+ end = start; >+ start = tmp; >+ } >+ >+ int lastNewline = 0; >+ int currNewline = 0; >+ >+ for(int i = selectionStartLine; i <= selectionEndLine; i++) >+ { >+ Element lineElement = map.getElement(i); >+ int lineStart = lineElement.getStartOffset(); >+ int lineEnd = lineElement.getEndOffset() - 1; >+ int rectStart = Math.min(lineEnd,lineStart + start); >+ >+ document.remove(rectStart,Math.min(lineEnd - rectStart, >+ end - start)); >+ >+ if(selectedText == null) >+ continue; >+ >+ currNewline = selectedText.indexOf('\n',lastNewline); >+ if(currNewline == -1) >+ currNewline = selectedText.length(); >+ >+ document.insertString(rectStart,selectedText >+ .substring(lastNewline,currNewline),null); >+ >+ lastNewline = Math.min(selectedText.length(), >+ currNewline + 1); >+ } >+ >+ if(selectedText != null && >+ currNewline != selectedText.length()) >+ { >+ int offset = map.getElement(selectionEndLine) >+ .getEndOffset() - 1; >+ document.insertString(offset,"\n",null); >+ document.insertString(offset + 1,selectedText >+ .substring(currNewline + 1),null); >+ } >+ } >+ else >+ { >+ document.remove(selectionStart, >+ selectionEnd - selectionStart); >+ if(selectedText != null) >+ { >+ document.insertString(selectionStart, >+ selectedText,null); >+ } >+ } >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ throw new InternalError("Cannot replace" >+ + " selection"); >+ } >+ // No matter what happends... stops us from leaving document >+ // in a bad state >+ finally >+ { >+ document.endCompoundEdit(); >+ } >+ >+ setCaretPosition(selectionEnd); >+ } >+ >+ /** >+ * Returns true if this text area is editable, false otherwise. >+ */ >+ public final boolean isEditable() >+ { >+ return editable; >+ } >+ >+ /** >+ * Sets if this component is editable. >+ * @param editable True if this text area should be editable, >+ * false otherwise >+ */ >+ public final void setEditable(boolean editable) >+ { >+ this.editable = editable; >+ } >+ >+ /** >+ * Returns the right click popup menu. >+ */ >+ public final JPopupMenu getRightClickPopup() >+ { >+ return popup; >+ } >+ >+ /** >+ * Sets the right click popup menu. >+ * @param popup The popup >+ */ >+ public final void setRightClickPopup(JPopupMenu popup) >+ { >+ this.popup = popup; >+ } >+ >+ /** >+ * Returns the `magic' caret position. This can be used to preserve >+ * the column position when moving up and down lines. >+ */ >+ public final int getMagicCaretPosition() >+ { >+ return magicCaret; >+ } >+ >+ /** >+ * Sets the `magic' caret position. This can be used to preserve >+ * the column position when moving up and down lines. >+ * @param magicCaret The magic caret position >+ */ >+ public final void setMagicCaretPosition(int magicCaret) >+ { >+ this.magicCaret = magicCaret; >+ } >+ >+ /** >+ * Similar to <code>setSelectedText()</code>, but overstrikes the >+ * appropriate number of characters if overwrite mode is enabled. >+ * @param str The string >+ * @see #setSelectedText(String) >+ * @see #isOverwriteEnabled() >+ */ >+ public void overwriteSetSelectedText(String str) >+ { >+ // Don't overstrike if there is a selection >+ if(!overwrite || selectionStart != selectionEnd) >+ { >+ setSelectedText(str); >+ return; >+ } >+ >+ // Don't overstrike if we're on the end of >+ // the line >+ int caret = getCaretPosition(); >+ int caretLineEnd = getLineEndOffset(getCaretLine()); >+ if(caretLineEnd - caret <= str.length()) >+ { >+ setSelectedText(str); >+ return; >+ } >+ >+ document.beginCompoundEdit(); >+ >+ try >+ { >+ document.remove(caret,str.length()); >+ document.insertString(caret,str,null); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ finally >+ { >+ document.endCompoundEdit(); >+ } >+ } >+ >+ /** >+ * Returns true if overwrite mode is enabled, false otherwise. >+ */ >+ public final boolean isOverwriteEnabled() >+ { >+ return overwrite; >+ } >+ >+ /** >+ * Sets if overwrite mode should be enabled. >+ * @param overwrite True if overwrite mode should be enabled, >+ * false otherwise. >+ */ >+ public final void setOverwriteEnabled(boolean overwrite) >+ { >+ this.overwrite = overwrite; >+ painter.invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns true if the selection is rectangular, false otherwise. >+ */ >+ public final boolean isSelectionRectangular() >+ { >+ return rectSelect; >+ } >+ >+ /** >+ * Sets if the selection should be rectangular. >+ * @param overwrite True if the selection should be rectangular, >+ * false otherwise. >+ */ >+ public final void setSelectionRectangular(boolean rectSelect) >+ { >+ this.rectSelect = rectSelect; >+ painter.invalidateSelectedLines(); >+ } >+ >+ /** >+ * Returns the position of the highlighted bracket (the bracket >+ * matching the one before the caret) >+ */ >+ public final int getBracketPosition() >+ { >+ return bracketPosition; >+ } >+ >+ /** >+ * Returns the line of the highlighted bracket (the bracket >+ * matching the one before the caret) >+ */ >+ public final int getBracketLine() >+ { >+ return bracketLine; >+ } >+ >+ /** >+ * Adds a caret change listener to this text area. >+ * @param listener The listener >+ */ >+ public final void addCaretListener(CaretListener listener) >+ { >+ listenerList.add(CaretListener.class,listener); >+ } >+ >+ /** >+ * Removes a caret change listener from this text area. >+ * @param listener The listener >+ */ >+ public final void removeCaretListener(CaretListener listener) >+ { >+ listenerList.remove(CaretListener.class,listener); >+ } >+ >+ /** >+ * Deletes the selected text from the text area and places it >+ * into the clipboard. >+ */ >+ public void cut() >+ { >+ if(editable) >+ { >+ copy(); >+ setSelectedText(""); >+ } >+ } >+ >+ /** >+ * Places the selected text into the clipboard. >+ */ >+ public void copy() >+ { >+ if(selectionStart != selectionEnd) >+ { >+ Clipboard clipboard = getToolkit().getSystemClipboard(); >+ >+ String selection = getSelectedText(); >+ >+ int repeatCount = inputHandler.getRepeatCount(); >+ StringBuffer buf = new StringBuffer(); >+ for(int i = 0; i < repeatCount; i++) >+ buf.append(selection); >+ >+ clipboard.setContents(new StringSelection(buf.toString()),null); >+ } >+ } >+ >+ /** >+ * Inserts the clipboard contents into the text. >+ */ >+ public void paste() >+ { >+ if(editable) >+ { >+ Clipboard clipboard = getToolkit().getSystemClipboard(); >+ try >+ { >+ // The MacOS MRJ doesn't convert \r to \n, >+ // so do it here >+ String selection = ((String)clipboard >+ .getContents(this).getTransferData( >+ DataFlavor.stringFlavor)) >+ .replace('\r','\n'); >+ >+ int repeatCount = inputHandler.getRepeatCount(); >+ StringBuffer buf = new StringBuffer(); >+ for(int i = 0; i < repeatCount; i++) >+ buf.append(selection); >+ selection = buf.toString(); >+ setSelectedText(selection); >+ } >+ catch(Exception e) >+ { >+ getToolkit().beep(); >+ System.err.println("Clipboard does not" >+ + " contain a string"); >+ } >+ } >+ } >+ >+ /** >+ * Called by the AWT when this component is removed from it's parent. >+ * This stops clears the currently focused component. >+ */ >+ public void removeNotify() >+ { >+ super.removeNotify(); >+ if(focusedComponent == this) >+ focusedComponent = null; >+ } >+ >+ /** >+ * Forwards key events directly to the input handler. >+ * This is slightly faster than using a KeyListener >+ * because some Swing overhead is avoided. >+ */ >+ public void processKeyEvent(KeyEvent evt) >+ { >+ if(inputHandler == null) >+ return; >+ switch(evt.getID()) >+ { >+ case KeyEvent.KEY_TYPED: >+ inputHandler.keyTyped(evt); >+ break; >+ case KeyEvent.KEY_PRESSED: >+ inputHandler.keyPressed(evt); >+ break; >+ case KeyEvent.KEY_RELEASED: >+ inputHandler.keyReleased(evt); >+ break; >+ } >+ } >+ >+ // protected members >+ protected static String CENTER = "center"; >+ protected static String RIGHT = "right"; >+ protected static String BOTTOM = "bottom"; >+ >+ protected static JEditTextArea focusedComponent; >+ protected static Timer caretTimer; >+ >+ protected TextAreaPainter painter; >+ >+ protected JPopupMenu popup; >+ >+ protected EventListenerList listenerList; >+ protected MutableCaretEvent caretEvent; >+ >+ protected boolean caretBlinks; >+ protected boolean caretVisible; >+ protected boolean blink; >+ >+ protected boolean editable; >+ >+ protected int firstLine; >+ protected int visibleLines; >+ protected int electricScroll; >+ >+ protected int horizontalOffset; >+ >+ protected JScrollBar vertical; >+ protected JScrollBar horizontal; >+ protected boolean scrollBarsInitialized; >+ >+ protected InputHandler inputHandler; >+ protected SyntaxDocument document; >+ protected DocumentHandler documentHandler; >+ >+ protected Segment lineSegment; >+ >+ protected int selectionStart; >+ protected int selectionStartLine; >+ protected int selectionEnd; >+ protected int selectionEndLine; >+ protected boolean biasLeft; >+ >+ protected int bracketPosition; >+ protected int bracketLine; >+ >+ protected int magicCaret; >+ protected boolean overwrite; >+ protected boolean rectSelect; >+ >+ protected void fireCaretEvent() >+ { >+ Object[] listeners = listenerList.getListenerList(); >+ for(int i = listeners.length - 2; i >= 0; i--) >+ { >+ if(listeners[i] == CaretListener.class) >+ { >+ ((CaretListener)listeners[i+1]).caretUpdate(caretEvent); >+ } >+ } >+ } >+ >+ protected void updateBracketHighlight(int newCaretPosition) >+ { >+ if(newCaretPosition == 0) >+ { >+ bracketPosition = bracketLine = -1; >+ return; >+ } >+ >+ try >+ { >+ int offset = TextUtilities.findMatchingBracket( >+ document,newCaretPosition - 1); >+ if(offset != -1) >+ { >+ bracketLine = getLineOfOffset(offset); >+ bracketPosition = offset - getLineStartOffset(bracketLine); >+ return; >+ } >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ >+ bracketLine = bracketPosition = -1; >+ } >+ >+ protected void documentChanged(DocumentEvent evt) >+ { >+ DocumentEvent.ElementChange ch = evt.getChange( >+ document.getDefaultRootElement()); >+ >+ int count; >+ if(ch == null) >+ count = 0; >+ else >+ count = ch.getChildrenAdded().length - >+ ch.getChildrenRemoved().length; >+ >+ int line = getLineOfOffset(evt.getOffset()); >+ if(count == 0) >+ { >+ painter.invalidateLine(line); >+ } >+ // do magic stuff >+ else if(line < firstLine) >+ { >+ setFirstLine(firstLine + count); >+ } >+ // end of magic stuff >+ else >+ { >+ painter.invalidateLineRange(line,firstLine + visibleLines); >+ updateScrollBars(); >+ } >+ } >+ >+ class ScrollLayout implements LayoutManager >+ { >+ public void addLayoutComponent(String name, Component comp) >+ { >+ if(name.equals(CENTER)) >+ center = comp; >+ else if(name.equals(RIGHT)) >+ right = comp; >+ else if(name.equals(BOTTOM)) >+ bottom = comp; >+ else if(name.equals(LEFT_OF_SCROLLBAR)) >+ leftOfScrollBar.addElement(comp); >+ } >+ >+ public void removeLayoutComponent(Component comp) >+ { >+ if(center == comp) >+ center = null; >+ if(right == comp) >+ right = null; >+ if(bottom == comp) >+ bottom = null; >+ else >+ leftOfScrollBar.removeElement(comp); >+ } >+ >+ public Dimension preferredLayoutSize(Container parent) >+ { >+ Dimension dim = new Dimension(); >+ Insets insets = getInsets(); >+ dim.width = insets.left + insets.right; >+ dim.height = insets.top + insets.bottom; >+ >+ Dimension centerPref = center.getPreferredSize(); >+ dim.width += centerPref.width; >+ dim.height += centerPref.height; >+ Dimension rightPref = right.getPreferredSize(); >+ dim.width += rightPref.width; >+ Dimension bottomPref = bottom.getPreferredSize(); >+ dim.height += bottomPref.height; >+ >+ return dim; >+ } >+ >+ public Dimension minimumLayoutSize(Container parent) >+ { >+ Dimension dim = new Dimension(); >+ Insets insets = getInsets(); >+ dim.width = insets.left + insets.right; >+ dim.height = insets.top + insets.bottom; >+ >+ Dimension centerPref = center.getMinimumSize(); >+ dim.width += centerPref.width; >+ dim.height += centerPref.height; >+ Dimension rightPref = right.getMinimumSize(); >+ dim.width += rightPref.width; >+ Dimension bottomPref = bottom.getMinimumSize(); >+ dim.height += bottomPref.height; >+ >+ return dim; >+ } >+ >+ public void layoutContainer(Container parent) >+ { >+ Dimension size = parent.getSize(); >+ Insets insets = parent.getInsets(); >+ int itop = insets.top; >+ int ileft = insets.left; >+ int ibottom = insets.bottom; >+ int iright = insets.right; >+ >+ int rightWidth = right.getPreferredSize().width; >+ int bottomHeight = bottom.getPreferredSize().height; >+ int centerWidth = size.width - rightWidth - ileft - iright; >+ int centerHeight = size.height - bottomHeight - itop - ibottom; >+ >+ center.setBounds( >+ ileft, >+ itop, >+ centerWidth, >+ centerHeight); >+ >+ right.setBounds( >+ ileft + centerWidth, >+ itop, >+ rightWidth, >+ centerHeight); >+ >+ // Lay out all status components, in order >+ Enumeration status = leftOfScrollBar.elements(); >+ while(status.hasMoreElements()) >+ { >+ Component comp = (Component)status.nextElement(); >+ Dimension dim = comp.getPreferredSize(); >+ comp.setBounds(ileft, >+ itop + centerHeight, >+ dim.width, >+ bottomHeight); >+ ileft += dim.width; >+ } >+ >+ bottom.setBounds( >+ ileft, >+ itop + centerHeight, >+ size.width - rightWidth - ileft - iright, >+ bottomHeight); >+ } >+ >+ // private members >+ private Component center; >+ private Component right; >+ private Component bottom; >+ private Vector leftOfScrollBar = new Vector(); >+ } >+ >+ static class CaretBlinker implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ if(focusedComponent != null >+ && focusedComponent.hasFocus()) >+ focusedComponent.blinkCaret(); >+ } >+ } >+ >+ class MutableCaretEvent extends CaretEvent >+ { >+ MutableCaretEvent() >+ { >+ super(JEditTextArea.this); >+ } >+ >+ public int getDot() >+ { >+ return getCaretPosition(); >+ } >+ >+ public int getMark() >+ { >+ return getMarkPosition(); >+ } >+ } >+ >+ class AdjustHandler implements AdjustmentListener >+ { >+ public void adjustmentValueChanged(final AdjustmentEvent evt) >+ { >+ if(!scrollBarsInitialized) >+ return; >+ >+ // If this is not done, mousePressed events accumilate >+ // and the result is that scrolling doesn't stop after >+ // the mouse is released >+ SwingUtilities.invokeLater(new Runnable() { >+ public void run() >+ { >+ if(evt.getAdjustable() == vertical) >+ setFirstLine(vertical.getValue()); >+ else >+ setHorizontalOffset(-horizontal.getValue()); >+ } >+ }); >+ } >+ } >+ >+ class ComponentHandler extends ComponentAdapter >+ { >+ public void componentResized(ComponentEvent evt) >+ { >+ recalculateVisibleLines(); >+ scrollBarsInitialized = true; >+ } >+ } >+ >+ class DocumentHandler implements DocumentListener >+ { >+ public void insertUpdate(DocumentEvent evt) >+ { >+ documentChanged(evt); >+ >+ int offset = evt.getOffset(); >+ int length = evt.getLength(); >+ >+ int newStart; >+ int newEnd; >+ >+ if(selectionStart > offset || (selectionStart >+ == selectionEnd && selectionStart == offset)) >+ newStart = selectionStart + length; >+ else >+ newStart = selectionStart; >+ >+ if(selectionEnd >= offset) >+ newEnd = selectionEnd + length; >+ else >+ newEnd = selectionEnd; >+ >+ select(newStart,newEnd); >+ } >+ >+ public void removeUpdate(DocumentEvent evt) >+ { >+ documentChanged(evt); >+ >+ int offset = evt.getOffset(); >+ int length = evt.getLength(); >+ >+ int newStart; >+ int newEnd; >+ >+ if(selectionStart > offset) >+ { >+ if(selectionStart > offset + length) >+ newStart = selectionStart - length; >+ else >+ newStart = offset; >+ } >+ else >+ newStart = selectionStart; >+ >+ if(selectionEnd > offset) >+ { >+ if(selectionEnd > offset + length) >+ newEnd = selectionEnd - length; >+ else >+ newEnd = offset; >+ } >+ else >+ newEnd = selectionEnd; >+ >+ select(newStart,newEnd); >+ } >+ >+ public void changedUpdate(DocumentEvent evt) >+ { >+ } >+ } >+ >+ class DragHandler implements MouseMotionListener >+ { >+ public void mouseDragged(MouseEvent evt) >+ { >+ if(popup != null && popup.isVisible()) >+ return; >+ >+ setSelectionRectangular((evt.getModifiers() >+ & InputEvent.CTRL_MASK) != 0); >+ select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY())); >+ } >+ >+ public void mouseMoved(MouseEvent evt) {} >+ } >+ >+ class FocusHandler implements FocusListener >+ { >+ public void focusGained(FocusEvent evt) >+ { >+ setCaretVisible(true); >+ focusedComponent = JEditTextArea.this; >+ } >+ >+ public void focusLost(FocusEvent evt) >+ { >+ setCaretVisible(false); >+ focusedComponent = null; >+ } >+ } >+ >+ class MouseHandler extends MouseAdapter >+ { >+ public void mousePressed(MouseEvent evt) >+ { >+ requestFocus(); >+ >+ // Focus events not fired sometimes? >+ setCaretVisible(true); >+ focusedComponent = JEditTextArea.this; >+ >+ if((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0 >+ && popup != null) >+ { >+ popup.show(painter,evt.getX(),evt.getY()); >+ return; >+ } >+ >+ int line = yToLine(evt.getY()); >+ int offset = xToOffset(line,evt.getX()); >+ int dot = getLineStartOffset(line) + offset; >+ >+ switch(evt.getClickCount()) >+ { >+ case 1: >+ doSingleClick(evt,line,offset,dot); >+ break; >+ case 2: >+ // It uses the bracket matching stuff, so >+ // it can throw a BLE >+ try >+ { >+ doDoubleClick(evt,line,offset,dot); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ break; >+ case 3: >+ doTripleClick(evt,line,offset,dot); >+ break; >+ } >+ } >+ >+ private void doSingleClick(MouseEvent evt, int line, >+ int offset, int dot) >+ { >+ if((evt.getModifiers() & InputEvent.SHIFT_MASK) != 0) >+ { >+ rectSelect = (evt.getModifiers() & InputEvent.CTRL_MASK) != 0; >+ select(getMarkPosition(),dot); >+ } >+ else >+ setCaretPosition(dot); >+ } >+ >+ private void doDoubleClick(MouseEvent evt, int line, >+ int offset, int dot) throws BadLocationException >+ { >+ // Ignore empty lines >+ if(getLineLength(line) == 0) >+ return; >+ >+ try >+ { >+ int bracket = TextUtilities.findMatchingBracket( >+ document,Math.max(0,dot - 1)); >+ if(bracket != -1) >+ { >+ int mark = getMarkPosition(); >+ // Hack >+ if(bracket > mark) >+ { >+ bracket++; >+ mark--; >+ } >+ select(mark,bracket); >+ return; >+ } >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ >+ // Ok, it's not a bracket... select the word >+ String lineText = getLineText(line); >+ char ch = lineText.charAt(Math.max(0,offset - 1)); >+ >+ String noWordSep = (String)document.getProperty("noWordSep"); >+ if(noWordSep == null) >+ noWordSep = ""; >+ >+ // If the user clicked on a non-letter char, >+ // we select the surrounding non-letters >+ boolean selectNoLetter = (!Character >+ .isLetterOrDigit(ch) >+ && noWordSep.indexOf(ch) == -1); >+ >+ int wordStart = 0; >+ >+ for(int i = offset - 1; i >= 0; i--) >+ { >+ ch = lineText.charAt(i); >+ if(selectNoLetter ^ (!Character >+ .isLetterOrDigit(ch) && >+ noWordSep.indexOf(ch) == -1)) >+ { >+ wordStart = i + 1; >+ break; >+ } >+ } >+ >+ int wordEnd = lineText.length(); >+ for(int i = offset; i < lineText.length(); i++) >+ { >+ ch = lineText.charAt(i); >+ if(selectNoLetter ^ (!Character >+ .isLetterOrDigit(ch) && >+ noWordSep.indexOf(ch) == -1)) >+ { >+ wordEnd = i; >+ break; >+ } >+ } >+ >+ int lineStart = getLineStartOffset(line); >+ select(lineStart + wordStart,lineStart + wordEnd); >+ >+ /* >+ String lineText = getLineText(line); >+ String noWordSep = (String)document.getProperty("noWordSep"); >+ int wordStart = TextUtilities.findWordStart(lineText,offset,noWordSep); >+ int wordEnd = TextUtilities.findWordEnd(lineText,offset,noWordSep); >+ >+ int lineStart = getLineStartOffset(line); >+ select(lineStart + wordStart,lineStart + wordEnd); >+ */ >+ } >+ >+ private void doTripleClick(MouseEvent evt, int line, >+ int offset, int dot) >+ { >+ select(getLineStartOffset(line),getLineEndOffset(line)-1); >+ } >+ } >+ >+ class CaretUndo extends AbstractUndoableEdit >+ { >+ private int start; >+ private int end; >+ >+ CaretUndo(int start, int end) >+ { >+ this.start = start; >+ this.end = end; >+ } >+ >+ public boolean isSignificant() >+ { >+ return false; >+ } >+ >+ public String getPresentationName() >+ { >+ return "caret move"; >+ } >+ >+ public void undo() throws CannotUndoException >+ { >+ super.undo(); >+ >+ select(start,end); >+ } >+ >+ public void redo() throws CannotRedoException >+ { >+ super.redo(); >+ >+ select(start,end); >+ } >+ >+ public boolean addEdit(UndoableEdit edit) >+ { >+ if(edit instanceof CaretUndo) >+ { >+ CaretUndo cedit = (CaretUndo)edit; >+ start = cedit.start; >+ end = cedit.end; >+ cedit.die(); >+ >+ return true; >+ } >+ else >+ return false; >+ } >+ } >+ >+ static >+ { >+ caretTimer = new Timer(500,new CaretBlinker()); >+ caretTimer.setInitialDelay(500); >+ caretTimer.start(); >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/InputHandler.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/InputHandler.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/srcview/InputHandler.java (revision 0) >@@ -0,0 +1,1070 @@ >+/* >+ * InputHandler.java - Manages key bindings and executes actions >+ * Copyright (C) 1999 Slava Pestov >+ * >+ * You may use and modify this package for any purpose. Redistribution is >+ * permitted, in both source and binary form, provided that this notice >+ * remains intact in all source distributions of this package. >+ */ >+package org.apache.batik.apps.svgbrowser.srcview; >+ >+import javax.swing.text.*; >+import javax.swing.JPopupMenu; >+import java.awt.event.*; >+import java.awt.Component; >+import java.util.*; >+ >+/** >+ * An input handler converts the user's key strokes into concrete actions. >+ * It also takes care of macro recording and action repetition.<p> >+ * >+ * This class provides all the necessary support code for an input >+ * handler, but doesn't actually do any key binding logic. It is up >+ * to the implementations of this class to do so. >+ * >+ * @author Slava Pestov >+ * @version $Id: InputHandler.java,v 1.14 1999/12/13 03:40:30 sp Exp $ >+ * @see org.gjt.sp.jedit.textarea.DefaultInputHandler >+ */ >+public abstract class InputHandler extends KeyAdapter >+{ >+ /** >+ * If this client property is set to Boolean.TRUE on the text area, >+ * the home/end keys will support 'smart' BRIEF-like behaviour >+ * (one press = start/end of line, two presses = start/end of >+ * viewscreen, three presses = start/end of document). By default, >+ * this property is not set. >+ */ >+ public static final String SMART_HOME_END_PROPERTY = "InputHandler.homeEnd"; >+ >+ public static final ActionListener BACKSPACE = new backspace(); >+ public static final ActionListener BACKSPACE_WORD = new backspace_word(); >+ public static final ActionListener DELETE = new delete(); >+ public static final ActionListener DELETE_WORD = new delete_word(); >+ public static final ActionListener END = new end(false); >+ public static final ActionListener DOCUMENT_END = new document_end(false); >+ public static final ActionListener SELECT_END = new end(true); >+ public static final ActionListener SELECT_DOC_END = new document_end(true); >+ public static final ActionListener INSERT_BREAK = new insert_break(); >+ public static final ActionListener INSERT_TAB = new insert_tab(); >+ public static final ActionListener HOME = new home(false); >+ public static final ActionListener DOCUMENT_HOME = new document_home(false); >+ public static final ActionListener SELECT_HOME = new home(true); >+ public static final ActionListener SELECT_DOC_HOME = new document_home(true); >+ public static final ActionListener NEXT_CHAR = new next_char(false); >+ public static final ActionListener NEXT_LINE = new next_line(false); >+ public static final ActionListener NEXT_PAGE = new next_page(false); >+ public static final ActionListener NEXT_WORD = new next_word(false); >+ public static final ActionListener SELECT_NEXT_CHAR = new next_char(true); >+ public static final ActionListener SELECT_NEXT_LINE = new next_line(true); >+ public static final ActionListener SELECT_NEXT_PAGE = new next_page(true); >+ public static final ActionListener SELECT_NEXT_WORD = new next_word(true); >+ public static final ActionListener OVERWRITE = new overwrite(); >+ public static final ActionListener PREV_CHAR = new prev_char(false); >+ public static final ActionListener PREV_LINE = new prev_line(false); >+ public static final ActionListener PREV_PAGE = new prev_page(false); >+ public static final ActionListener PREV_WORD = new prev_word(false); >+ public static final ActionListener SELECT_PREV_CHAR = new prev_char(true); >+ public static final ActionListener SELECT_PREV_LINE = new prev_line(true); >+ public static final ActionListener SELECT_PREV_PAGE = new prev_page(true); >+ public static final ActionListener SELECT_PREV_WORD = new prev_word(true); >+ public static final ActionListener REPEAT = new repeat(); >+ public static final ActionListener TOGGLE_RECT = new toggle_rect(); >+ >+ // Default action >+ public static final ActionListener INSERT_CHAR = new insert_char(); >+ >+ private static Hashtable actions; >+ >+ static >+ { >+ actions = new Hashtable(); >+ actions.put("backspace",BACKSPACE); >+ actions.put("backspace-word",BACKSPACE_WORD); >+ actions.put("delete",DELETE); >+ actions.put("delete-word",DELETE_WORD); >+ actions.put("end",END); >+ actions.put("select-end",SELECT_END); >+ actions.put("document-end",DOCUMENT_END); >+ actions.put("select-doc-end",SELECT_DOC_END); >+ actions.put("insert-break",INSERT_BREAK); >+ actions.put("insert-tab",INSERT_TAB); >+ actions.put("home",HOME); >+ actions.put("select-home",SELECT_HOME); >+ actions.put("document-home",DOCUMENT_HOME); >+ actions.put("select-doc-home",SELECT_DOC_HOME); >+ actions.put("next-char",NEXT_CHAR); >+ actions.put("next-line",NEXT_LINE); >+ actions.put("next-page",NEXT_PAGE); >+ actions.put("next-word",NEXT_WORD); >+ actions.put("select-next-char",SELECT_NEXT_CHAR); >+ actions.put("select-next-line",SELECT_NEXT_LINE); >+ actions.put("select-next-page",SELECT_NEXT_PAGE); >+ actions.put("select-next-word",SELECT_NEXT_WORD); >+ actions.put("overwrite",OVERWRITE); >+ actions.put("prev-char",PREV_CHAR); >+ actions.put("prev-line",PREV_LINE); >+ actions.put("prev-page",PREV_PAGE); >+ actions.put("prev-word",PREV_WORD); >+ actions.put("select-prev-char",SELECT_PREV_CHAR); >+ actions.put("select-prev-line",SELECT_PREV_LINE); >+ actions.put("select-prev-page",SELECT_PREV_PAGE); >+ actions.put("select-prev-word",SELECT_PREV_WORD); >+ actions.put("repeat",REPEAT); >+ actions.put("toggle-rect",TOGGLE_RECT); >+ actions.put("insert-char",INSERT_CHAR); >+ } >+ >+ /** >+ * Returns a named text area action. >+ * @param name The action name >+ */ >+ public static ActionListener getAction(String name) >+ { >+ return (ActionListener)actions.get(name); >+ } >+ >+ /** >+ * Returns the name of the specified text area action. >+ * @param listener The action >+ */ >+ public static String getActionName(ActionListener listener) >+ { >+ Enumeration e = getActions(); >+ while(e.hasMoreElements()) >+ { >+ String name = (String)e.nextElement(); >+ ActionListener _listener = getAction(name); >+ if(_listener == listener) >+ return name; >+ } >+ return null; >+ } >+ >+ /** >+ * Returns an enumeration of all available actions. >+ */ >+ public static Enumeration getActions() >+ { >+ return actions.keys(); >+ } >+ >+ /** >+ * Adds the default key bindings to this input handler. >+ * This should not be called in the constructor of this >+ * input handler, because applications might load the >+ * key bindings from a file, etc. >+ */ >+ public abstract void addDefaultKeyBindings(); >+ >+ /** >+ * Adds a key binding to this input handler. >+ * @param keyBinding The key binding (the format of this is >+ * input-handler specific) >+ * @param action The action >+ */ >+ public abstract void addKeyBinding(String keyBinding, ActionListener action); >+ >+ /** >+ * Removes a key binding from this input handler. >+ * @param keyBinding The key binding >+ */ >+ public abstract void removeKeyBinding(String keyBinding); >+ >+ /** >+ * Removes all key bindings from this input handler. >+ */ >+ public abstract void removeAllKeyBindings(); >+ >+ /** >+ * Grabs the next key typed event and invokes the specified >+ * action with the key as a the action command. >+ * @param action The action >+ */ >+ public void grabNextKeyStroke(ActionListener listener) >+ { >+ grabAction = listener; >+ } >+ >+ /** >+ * Returns if repeating is enabled. When repeating is enabled, >+ * actions will be executed multiple times. This is usually >+ * invoked with a special key stroke in the input handler. >+ */ >+ public boolean isRepeatEnabled() >+ { >+ return repeat; >+ } >+ >+ /** >+ * Enables repeating. When repeating is enabled, actions will be >+ * executed multiple times. Once repeating is enabled, the input >+ * handler should read a number from the keyboard. >+ */ >+ public void setRepeatEnabled(boolean repeat) >+ { >+ this.repeat = repeat; >+ } >+ >+ /** >+ * Returns the number of times the next action will be repeated. >+ */ >+ public int getRepeatCount() >+ { >+ return (repeat ? Math.max(1,repeatCount) : 1); >+ } >+ >+ /** >+ * Sets the number of times the next action will be repeated. >+ * @param repeatCount The repeat count >+ */ >+ public void setRepeatCount(int repeatCount) >+ { >+ this.repeatCount = repeatCount; >+ } >+ >+ /** >+ * Returns the macro recorder. If this is non-null, all executed >+ * actions should be forwarded to the recorder. >+ */ >+ public InputHandler.MacroRecorder getMacroRecorder() >+ { >+ return recorder; >+ } >+ >+ /** >+ * Sets the macro recorder. If this is non-null, all executed >+ * actions should be forwarded to the recorder. >+ * @param recorder The macro recorder >+ */ >+ public void setMacroRecorder(InputHandler.MacroRecorder recorder) >+ { >+ this.recorder = recorder; >+ } >+ >+ /** >+ * Returns a copy of this input handler that shares the same >+ * key bindings. Setting key bindings in the copy will also >+ * set them in the original. >+ */ >+ public abstract InputHandler copy(); >+ >+ /** >+ * Executes the specified action, repeating and recording it as >+ * necessary. >+ * @param listener The action listener >+ * @param source The event source >+ * @param actionCommand The action command >+ */ >+ public void executeAction(ActionListener listener, Object source, >+ String actionCommand) >+ { >+ // create event >+ ActionEvent evt = new ActionEvent(source, >+ ActionEvent.ACTION_PERFORMED, >+ actionCommand); >+ >+ // don't do anything if the action is a wrapper >+ // (like EditAction.Wrapper) >+ if(listener instanceof Wrapper) >+ { >+ listener.actionPerformed(evt); >+ return; >+ } >+ >+ // remember old values, in case action changes them >+ boolean _repeat = repeat; >+ int _repeatCount = getRepeatCount(); >+ >+ // execute the action >+ if(listener instanceof InputHandler.NonRepeatable) >+ listener.actionPerformed(evt); >+ else >+ { >+ for(int i = 0; i < Math.max(1,repeatCount); i++) >+ listener.actionPerformed(evt); >+ } >+ >+ // do recording. Notice that we do no recording whatsoever >+ // for actions that grab keys >+ if(grabAction == null) >+ { >+ if(recorder != null) >+ { >+ if(!(listener instanceof InputHandler.NonRecordable)) >+ { >+ if(_repeatCount != 1) >+ recorder.actionPerformed(REPEAT,String.valueOf(_repeatCount)); >+ >+ recorder.actionPerformed(listener,actionCommand); >+ } >+ } >+ >+ // If repeat was true originally, clear it >+ // Otherwise it might have been set by the action, etc >+ if(_repeat) >+ { >+ repeat = false; >+ repeatCount = 0; >+ } >+ } >+ } >+ >+ /** >+ * Returns the text area that fired the specified event. >+ * @param evt The event >+ */ >+ public static JEditTextArea getTextArea(EventObject evt) >+ { >+ if(evt != null) >+ { >+ Object o = evt.getSource(); >+ if(o instanceof Component) >+ { >+ // find the parent text area >+ Component c = (Component)o; >+ for(;;) >+ { >+ if(c instanceof JEditTextArea) >+ return (JEditTextArea)c; >+ else if(c == null) >+ break; >+ if(c instanceof JPopupMenu) >+ c = ((JPopupMenu)c) >+ .getInvoker(); >+ else >+ c = c.getParent(); >+ } >+ } >+ } >+ >+ // this shouldn't happen >+ System.err.println("BUG: getTextArea() returning null"); >+ System.err.println("Report this to Slava Pestov <sp@gjt.org>"); >+ return null; >+ } >+ >+ // protected members >+ >+ /** >+ * If a key is being grabbed, this method should be called with >+ * the appropriate key event. It executes the grab action with >+ * the typed character as the parameter. >+ */ >+ protected void handleGrabAction(KeyEvent evt) >+ { >+ // Clear it *before* it is executed so that executeAction() >+ // resets the repeat count >+ ActionListener _grabAction = grabAction; >+ grabAction = null; >+ executeAction(_grabAction,evt.getSource(), >+ String.valueOf(evt.getKeyChar())); >+ } >+ >+ // protected members >+ protected ActionListener grabAction; >+ protected boolean repeat; >+ protected int repeatCount; >+ protected InputHandler.MacroRecorder recorder; >+ >+ /** >+ * If an action implements this interface, it should not be repeated. >+ * Instead, it will handle the repetition itself. >+ */ >+ public interface NonRepeatable {} >+ >+ /** >+ * If an action implements this interface, it should not be recorded >+ * by the macro recorder. Instead, it will do its own recording. >+ */ >+ public interface NonRecordable {} >+ >+ /** >+ * For use by EditAction.Wrapper only. >+ * @since jEdit 2.2final >+ */ >+ public interface Wrapper {} >+ >+ /** >+ * Macro recorder. >+ */ >+ public interface MacroRecorder >+ { >+ void actionPerformed(ActionListener listener, >+ String actionCommand); >+ } >+ >+ public static class backspace implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ if(!textArea.isEditable()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ if(textArea.getSelectionStart() >+ != textArea.getSelectionEnd()) >+ { >+ textArea.setSelectedText(""); >+ } >+ else >+ { >+ int caret = textArea.getCaretPosition(); >+ if(caret == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ try >+ { >+ textArea.getDocument().remove(caret - 1,1); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ } >+ } >+ } >+ >+ public static class backspace_word implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int start = textArea.getSelectionStart(); >+ if(start != textArea.getSelectionEnd()) >+ { >+ textArea.setSelectedText(""); >+ } >+ >+ int line = textArea.getCaretLine(); >+ int lineStart = textArea.getLineStartOffset(line); >+ int caret = start - lineStart; >+ >+ String lineText = textArea.getLineText(textArea >+ .getCaretLine()); >+ >+ if(caret == 0) >+ { >+ if(lineStart == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ caret--; >+ } >+ else >+ { >+ String noWordSep = (String)textArea.getDocument().getProperty("noWordSep"); >+ caret = TextUtilities.findWordStart(lineText,caret,noWordSep); >+ } >+ >+ try >+ { >+ textArea.getDocument().remove( >+ caret + lineStart, >+ start - (caret + lineStart)); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ } >+ } >+ >+ public static class delete implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ if(!textArea.isEditable()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ if(textArea.getSelectionStart() >+ != textArea.getSelectionEnd()) >+ { >+ textArea.setSelectedText(""); >+ } >+ else >+ { >+ int caret = textArea.getCaretPosition(); >+ if(caret == textArea.getDocumentLength()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ try >+ { >+ textArea.getDocument().remove(caret,1); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ } >+ } >+ } >+ >+ public static class delete_word implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int start = textArea.getSelectionStart(); >+ if(start != textArea.getSelectionEnd()) >+ { >+ textArea.setSelectedText(""); >+ } >+ >+ int line = textArea.getCaretLine(); >+ int lineStart = textArea.getLineStartOffset(line); >+ int caret = start - lineStart; >+ >+ String lineText = textArea.getLineText(textArea >+ .getCaretLine()); >+ >+ if(caret == lineText.length()) >+ { >+ if(lineStart + caret == textArea.getDocumentLength()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ caret++; >+ } >+ else >+ { >+ String noWordSep = (String)textArea.getDocument().getProperty("noWordSep"); >+ caret = TextUtilities.findWordEnd(lineText,caret,noWordSep); >+ } >+ >+ try >+ { >+ textArea.getDocument().remove(start, >+ (caret + lineStart) - start); >+ } >+ catch(BadLocationException bl) >+ { >+ bl.printStackTrace(); >+ } >+ } >+ } >+ >+ public static class end implements ActionListener >+ { >+ private boolean select; >+ >+ public end(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ int caret = textArea.getCaretPosition(); >+ >+ int lastOfLine = textArea.getLineEndOffset( >+ textArea.getCaretLine()) - 1; >+ int lastVisibleLine = textArea.getFirstLine() >+ + textArea.getVisibleLines(); >+ if(lastVisibleLine >= textArea.getLineCount()) >+ { >+ lastVisibleLine = Math.min(textArea.getLineCount() - 1, >+ lastVisibleLine); >+ } >+ else >+ lastVisibleLine -= (textArea.getElectricScroll() + 1); >+ >+ int lastVisible = textArea.getLineEndOffset(lastVisibleLine) - 1; >+ int lastDocument = textArea.getDocumentLength(); >+ >+ if(caret == lastDocument) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ else if(!Boolean.TRUE.equals(textArea.getClientProperty( >+ SMART_HOME_END_PROPERTY))) >+ caret = lastOfLine; >+ else if(caret == lastVisible) >+ caret = lastDocument; >+ else if(caret == lastOfLine) >+ caret = lastVisible; >+ else >+ caret = lastOfLine; >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ } >+ } >+ >+ public static class document_end implements ActionListener >+ { >+ private boolean select; >+ >+ public document_end(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ if(select) >+ textArea.select(textArea.getMarkPosition(), >+ textArea.getDocumentLength()); >+ else >+ textArea.setCaretPosition(textArea >+ .getDocumentLength()); >+ } >+ } >+ >+ public static class home implements ActionListener >+ { >+ private boolean select; >+ >+ public home(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ int caret = textArea.getCaretPosition(); >+ >+ int firstLine = textArea.getFirstLine(); >+ >+ int firstOfLine = textArea.getLineStartOffset( >+ textArea.getCaretLine()); >+ int firstVisibleLine = (firstLine == 0 ? 0 : >+ firstLine + textArea.getElectricScroll()); >+ int firstVisible = textArea.getLineStartOffset( >+ firstVisibleLine); >+ >+ if(caret == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ else if(!Boolean.TRUE.equals(textArea.getClientProperty( >+ SMART_HOME_END_PROPERTY))) >+ caret = firstOfLine; >+ else if(caret == firstVisible) >+ caret = 0; >+ else if(caret == firstOfLine) >+ caret = firstVisible; >+ else >+ caret = firstOfLine; >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ } >+ } >+ >+ public static class document_home implements ActionListener >+ { >+ private boolean select; >+ >+ public document_home(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ if(select) >+ textArea.select(textArea.getMarkPosition(),0); >+ else >+ textArea.setCaretPosition(0); >+ } >+ } >+ >+ public static class insert_break implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ if(!textArea.isEditable()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ textArea.setSelectedText("\n"); >+ } >+ } >+ >+ public static class insert_tab implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ >+ if(!textArea.isEditable()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ textArea.overwriteSetSelectedText("\t"); >+ } >+ } >+ >+ public static class next_char implements ActionListener >+ { >+ private boolean select; >+ >+ public next_char(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ if(caret == textArea.getDocumentLength()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(), >+ caret + 1); >+ else >+ textArea.setCaretPosition(caret + 1); >+ } >+ } >+ >+ public static class next_line implements ActionListener >+ { >+ private boolean select; >+ >+ public next_line(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ int line = textArea.getCaretLine(); >+ >+ if(line == textArea.getLineCount() - 1) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ int magic = textArea.getMagicCaretPosition(); >+ if(magic == -1) >+ { >+ magic = textArea.offsetToX(line, >+ caret - textArea.getLineStartOffset(line)); >+ } >+ >+ caret = textArea.getLineStartOffset(line + 1) >+ + textArea.xToOffset(line + 1,magic); >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ textArea.setMagicCaretPosition(magic); >+ } >+ } >+ >+ public static class next_page implements ActionListener >+ { >+ private boolean select; >+ >+ public next_page(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int lineCount = textArea.getLineCount(); >+ int firstLine = textArea.getFirstLine(); >+ int visibleLines = textArea.getVisibleLines(); >+ int line = textArea.getCaretLine(); >+ >+ firstLine += visibleLines; >+ >+ if(firstLine + visibleLines >= lineCount - 1) >+ firstLine = lineCount - visibleLines; >+ >+ textArea.setFirstLine(firstLine); >+ >+ int caret = textArea.getLineStartOffset( >+ Math.min(textArea.getLineCount() - 1, >+ line + visibleLines)); >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ } >+ } >+ >+ public static class next_word implements ActionListener >+ { >+ private boolean select; >+ >+ public next_word(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ int line = textArea.getCaretLine(); >+ int lineStart = textArea.getLineStartOffset(line); >+ caret -= lineStart; >+ >+ String lineText = textArea.getLineText(textArea >+ .getCaretLine()); >+ >+ if(caret == lineText.length()) >+ { >+ if(lineStart + caret == textArea.getDocumentLength()) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ caret++; >+ } >+ else >+ { >+ String noWordSep = (String)textArea.getDocument().getProperty("noWordSep"); >+ caret = TextUtilities.findWordEnd(lineText,caret,noWordSep); >+ } >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(), >+ lineStart + caret); >+ else >+ textArea.setCaretPosition(lineStart + caret); >+ } >+ } >+ >+ public static class overwrite implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ textArea.setOverwriteEnabled( >+ !textArea.isOverwriteEnabled()); >+ } >+ } >+ >+ public static class prev_char implements ActionListener >+ { >+ private boolean select; >+ >+ public prev_char(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ if(caret == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(), >+ caret - 1); >+ else >+ textArea.setCaretPosition(caret - 1); >+ } >+ } >+ >+ public static class prev_line implements ActionListener >+ { >+ private boolean select; >+ >+ public prev_line(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ int line = textArea.getCaretLine(); >+ >+ if(line == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ >+ int magic = textArea.getMagicCaretPosition(); >+ if(magic == -1) >+ { >+ magic = textArea.offsetToX(line, >+ caret - textArea.getLineStartOffset(line)); >+ } >+ >+ caret = textArea.getLineStartOffset(line - 1) >+ + textArea.xToOffset(line - 1,magic); >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ textArea.setMagicCaretPosition(magic); >+ } >+ } >+ >+ public static class prev_page implements ActionListener >+ { >+ private boolean select; >+ >+ public prev_page(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int firstLine = textArea.getFirstLine(); >+ int visibleLines = textArea.getVisibleLines(); >+ int line = textArea.getCaretLine(); >+ >+ if(firstLine < visibleLines) >+ firstLine = visibleLines; >+ >+ textArea.setFirstLine(firstLine - visibleLines); >+ >+ int caret = textArea.getLineStartOffset( >+ Math.max(0,line - visibleLines)); >+ if(select) >+ textArea.select(textArea.getMarkPosition(),caret); >+ else >+ textArea.setCaretPosition(caret); >+ } >+ } >+ >+ public static class prev_word implements ActionListener >+ { >+ private boolean select; >+ >+ public prev_word(boolean select) >+ { >+ this.select = select; >+ } >+ >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ int caret = textArea.getCaretPosition(); >+ int line = textArea.getCaretLine(); >+ int lineStart = textArea.getLineStartOffset(line); >+ caret -= lineStart; >+ >+ String lineText = textArea.getLineText(textArea >+ .getCaretLine()); >+ >+ if(caret == 0) >+ { >+ if(lineStart == 0) >+ { >+ textArea.getToolkit().beep(); >+ return; >+ } >+ caret--; >+ } >+ else >+ { >+ String noWordSep = (String)textArea.getDocument().getProperty("noWordSep"); >+ caret = TextUtilities.findWordStart(lineText,caret,noWordSep); >+ } >+ >+ if(select) >+ textArea.select(textArea.getMarkPosition(), >+ lineStart + caret); >+ else >+ textArea.setCaretPosition(lineStart + caret); >+ } >+ } >+ >+ public static class repeat implements ActionListener, >+ InputHandler.NonRecordable >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ textArea.getInputHandler().setRepeatEnabled(true); >+ String actionCommand = evt.getActionCommand(); >+ if(actionCommand != null) >+ { >+ textArea.getInputHandler().setRepeatCount( >+ Integer.parseInt(actionCommand)); >+ } >+ } >+ } >+ >+ public static class toggle_rect implements ActionListener >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ textArea.setSelectionRectangular( >+ !textArea.isSelectionRectangular()); >+ } >+ } >+ >+ public static class insert_char implements ActionListener, >+ InputHandler.NonRepeatable >+ { >+ public void actionPerformed(ActionEvent evt) >+ { >+ JEditTextArea textArea = getTextArea(evt); >+ String str = evt.getActionCommand(); >+ int repeatCount = textArea.getInputHandler().getRepeatCount(); >+ >+ if(textArea.isEditable()) >+ { >+ StringBuffer buf = new StringBuffer(); >+ for(int i = 0; i < repeatCount; i++) >+ buf.append(str); >+ textArea.overwriteSetSelectedText(buf.toString()); >+ } >+ else >+ { >+ textArea.getToolkit().beep(); >+ } >+ } >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java (working copy) >@@ -56,6 +56,7 @@ > import java.lang.reflect.InvocationTargetException; > import java.lang.reflect.Method; > import java.net.MalformedURLException; >+import java.net.URI; > import java.util.HashMap; > import java.util.Iterator; > import java.util.LinkedList; >@@ -70,6 +71,7 @@ > import javax.swing.Action; > import javax.swing.BorderFactory; > import javax.swing.ButtonGroup; >+import javax.swing.ImageIcon; > import javax.swing.JComponent; > import javax.swing.JDialog; > import javax.swing.JFileChooser; >@@ -88,6 +90,9 @@ > import javax.swing.text.Document; > import javax.swing.text.PlainDocument; > >+import org.apache.batik.apps.svgbrowser.srcview.JEditTextArea; >+import org.apache.batik.apps.svgbrowser.srcview.SourceViewFrame; >+import org.apache.batik.apps.svgbrowser.srcview.XMLTokenMarker; > import org.apache.batik.bridge.DefaultExternalResourceSecurity; > import org.apache.batik.bridge.DefaultScriptSecurity; > import org.apache.batik.bridge.EmbededExternalResourceSecurity; >@@ -102,6 +107,7 @@ > import org.apache.batik.bridge.UpdateManagerEvent; > import org.apache.batik.bridge.UpdateManagerListener; > import org.apache.batik.dom.StyleSheetProcessingInstruction; >+import org.apache.batik.dom.svg.LiveAttributeException; > import org.apache.batik.dom.svg.SVGOMDocument; > import org.apache.batik.dom.util.HashTable; > import org.apache.batik.dom.util.DOMUtilities; >@@ -133,6 +139,7 @@ > import org.apache.batik.util.SVGConstants; > import org.apache.batik.util.XMLConstants; > import org.apache.batik.util.gui.DOMViewer; >+import org.apache.batik.util.gui.ErrorConsole; > import org.apache.batik.util.gui.JErrorPane; > import org.apache.batik.util.gui.LocationBar; > import org.apache.batik.util.gui.MemoryMonitor; >@@ -1841,26 +1848,13 @@ > > final ParsedURL u = new ParsedURL(svgDocument.getURL()); > >- final JFrame fr = new JFrame(u.toString()); >- fr.setSize(resources.getInteger("ViewSource.width"), >- resources.getInteger("ViewSource.height")); >- final JTextArea ta = new JTextArea(); >- ta.setLineWrap(true); >- ta.setFont(new Font("monospaced", Font.PLAIN, 12)); >- >- JScrollPane scroll = new JScrollPane(); >- scroll.getViewport().add(ta); >- scroll.setVerticalScrollBarPolicy >- (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); >- fr.getContentPane().add(scroll, BorderLayout.CENTER); >- > new Thread() { > public void run() { > char [] buffer = new char[4096]; > > try { >- Document doc = new PlainDocument(); >- >+ StringBuilder sb = new StringBuilder(); >+ > ParsedURL purl = new ParsedURL(svgDocument.getURL()); > InputStream is > = u.openStream(getInputHandler(purl). >@@ -1870,13 +1864,16 @@ > Reader in = XMLUtilities.createXMLDocumentReader(is); > int len; > while ((len=in.read(buffer, 0, buffer.length)) != -1) { >- doc.insertString(doc.getLength(), >- new String(buffer, 0, len), null); >+ sb.append(new String(buffer, 0, len)); > } > >- ta.setDocument(doc); >- ta.setEditable(false); >- ta.setBackground(Color.white); >+ final JFrame fr = new SourceViewFrame(application, sb.toString(), userAgent); >+ fr.setTitle(u.toString()); >+ ImageIcon icon = new ImageIcon >+ (getClass().getResource(resources.getString("ViewSource.frameicon"))); >+ fr.setIconImage(icon.getImage()); >+ fr.setSize(resources.getInteger("ViewSource.width"), >+ resources.getInteger("ViewSource.height")); > fr.setVisible(true); > } catch (Exception ex) { > userAgent.displayError(ex); >@@ -2734,9 +2731,16 @@ > if (debug) { > ex.printStackTrace(); > } >- JErrorPane pane = >- new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >- JDialog dialog = pane.createDialog(JSVGViewerFrame.this, "ERROR"); >+// JErrorPane pane = >+// new JErrorPane(ex, JOptionPane.ERROR_MESSAGE); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ if (ex instanceof LiveAttributeException) { >+ LiveAttributeException lex = (LiveAttributeException)ex; >+ console.add(lex.getElement().getNodeName(), svgDocument.getDocumentURI(), JOptionPane.ERROR_MESSAGE); >+ } else { >+ console.add(ex, svgDocument.getDocumentURI(), JOptionPane.ERROR_MESSAGE); >+ } >+ JDialog dialog = ErrorConsole.createDialog(JSVGViewerFrame.this, "ERROR"); > dialog.setModal(false); > dialog.setVisible(true); > } >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JFramesView.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JFramesView.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JFramesView.java (revision 0) >@@ -0,0 +1,380 @@ >+/* >+ >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+ >+ */ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.BasicStroke; >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Dimension; >+import java.awt.FontMetrics; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.Polygon; >+import java.awt.Rectangle; >+import java.awt.Stroke; >+import java.awt.event.ActionEvent; >+import java.awt.event.AdjustmentEvent; >+import java.awt.event.AdjustmentListener; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+import java.awt.event.MouseMotionAdapter; >+import java.awt.event.MouseMotionListener; >+import java.util.HashMap; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.JButton; >+import javax.swing.JComponent; >+import javax.swing.JLabel; >+import javax.swing.JPanel; >+import javax.swing.JPopupMenu; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.border.BevelBorder; >+ >+public class JFramesView extends JPanel implements ActionMap { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.JTimeline"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The button factory. >+ */ >+ protected ButtonFactory bf = new ButtonFactory(bundle, this); >+ >+ /** >+ * The menu factory. >+ */ >+ protected MenuFactory mf = new MenuFactory(bundle, this); >+ >+ private JTimelineSlider sliderPanel; >+ >+ private JPopupMenu cornerPopup; >+ >+ private JLabel timerLabel; >+ >+ private int precisionMillis = 100; >+ >+ private int pixelsPerUnit = 50; >+ >+ private float value = 1; >+ >+ private int knobPosition; >+ >+ private JScrollPane framesScrollPane; >+ >+ private JScrollBar verticalScrollBar; >+ >+ public JFramesView() { >+ super(new BorderLayout()); >+ >+ actions.put("CornerButtonAction", new CornerButtonAction()); >+ actions.put("IncreaseUnitSizeMenuItemAction", >+ new IncreaseUnitSizeMenuItemAction()); >+ actions.put("DecreaseUnitSizeMenuItemAction", >+ new DecreaseUnitSizeMenuItemAction()); >+ >+ sliderPanel = new JTimelineSlider(); >+ >+ framesScrollPane = new JScrollPane( >+ new JTimelineFramesPanel()); >+ framesScrollPane.setBorder(null); >+ framesScrollPane >+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); >+ framesScrollPane >+ .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); >+ framesScrollPane.setColumnHeaderView(sliderPanel); >+ >+ JButton cornerButton = bf.createJButton("CornerButton"); >+ cornerButton.setFocusable(false); >+ cornerPopup = new JPopupMenu(); >+ cornerPopup.add(mf.createJMenuItem("IncreaseUnitSizeMenuItem")); >+ cornerPopup.add(mf.createJMenuItem("DecreaseUnitSizeMenuItem")); >+ framesScrollPane >+ .setCorner(JScrollPane.UPPER_RIGHT_CORNER, cornerButton); >+ add(framesScrollPane); >+ >+ Box footerPanel = new Box(BoxLayout.X_AXIS); >+ add(footerPanel, BorderLayout.SOUTH); >+ timerLabel = new JLabel("-- : -- : --"); >+ timerLabel.setBorder(BorderFactory >+ .createBevelBorder(BevelBorder.LOWERED)); >+ footerPanel.add(timerLabel); >+ JScrollBar horizScrollBar = new JScrollBar(JScrollBar.HORIZONTAL); >+ int prefHeight = horizScrollBar.getPreferredSize().height; >+ footerPanel >+ .setMaximumSize(new Dimension(Integer.MAX_VALUE, prefHeight)); >+ footerPanel.setMinimumSize(new Dimension(0, prefHeight)); >+ footerPanel.setPreferredSize(footerPanel.getMinimumSize()); >+ footerPanel.add(horizScrollBar); >+ footerPanel.add(Box.createHorizontalStrut(framesScrollPane >+ .getVerticalScrollBar().getPreferredSize().width)); >+ } >+ >+ public JScrollBar getVerticalScrollBar() { >+ return verticalScrollBar; >+ } >+ >+ public void setVerticalScrollBar(JScrollBar verticalScrollBar) { >+ this.verticalScrollBar = verticalScrollBar; >+ add(verticalScrollBar, BorderLayout.EAST); >+ verticalScrollBar.addAdjustmentListener(new AdjustmentListener() { >+ public void adjustmentValueChanged(AdjustmentEvent e) { >+ >+ } >+ }); >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ protected class CornerButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ Component invoker = (Component) evt.getSource(); >+ cornerPopup.show(invoker, 0, invoker.getHeight()); >+ } >+ } >+ >+ protected class IncreaseUnitSizeMenuItemAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ // TODO: >+ // Increase unit size in timeline slider >+ } >+ } >+ >+ protected class DecreaseUnitSizeMenuItemAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ // TODO: >+ // Decrease unit size in timeline slider >+ } >+ } >+ >+ public void paint(Graphics g) { >+ knobPosition = (int) (value * pixelsPerUnit) + SLIDER_X_OFFSET; >+ >+ super.paint(g); >+ } >+ >+ public static final int SLIDER_X_OFFSET = 10; >+ >+ private static final Color SLIDER_KNOB_FILL_COLOR = new Color(0x77FF7777, >+ true); >+ >+ private static final Color SLIDER_KNOB_STROKE_COLOR = new Color(0x00FF0000); >+ >+ private static final Stroke SLIDER_KNOB_STROKE = new BasicStroke(1, >+ BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 5.0f, >+ new float[] { 5.0f }, 0.0f); >+ >+ private class JTimelineSlider extends JComponent { >+ >+ private boolean paintTrack = false; >+ >+ private Polygon knob; >+ >+ private Rectangle knobBounds; >+ >+ private boolean over; >+ >+ private MouseMotionListener mml = new MouseMotionAdapter() { >+ public void mouseMoved(MouseEvent e) { >+ int x = e.getX(), y = e.getY(); >+ boolean b = knobBounds.contains(x, y); >+ if (b != b) { >+ repaint(); >+ } >+ over = b; >+ } >+ >+ public void mouseDragged(MouseEvent e) { >+ if (over) { >+ int x = e.getX(); >+ if (x >= SLIDER_X_OFFSET) { >+ value = (float) (x - SLIDER_X_OFFSET) / pixelsPerUnit; >+ JFramesView.this.repaint(); >+ } >+ } >+ } >+ }; >+ >+ public JTimelineSlider() { >+ int height = 30; >+ >+ setMaximumSize(new Dimension(Integer.MAX_VALUE, height)); >+ setMinimumSize(new Dimension(0, height)); >+ setPreferredSize(getMinimumSize()); >+ setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); >+ addMouseMotionListener(mml); >+ >+ int pos = height / 2 - 3; >+ knob = new Polygon(); >+ knob.addPoint(-4, -pos); >+ knob.addPoint(4, -pos); >+ knob.addPoint(4, pos); >+ knob.addPoint(-4, pos); >+ knob.addPoint(-4, -pos); >+ >+ knobBounds = new Rectangle(6, height); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ super.paintComponent(g); >+ >+ Dimension size = getSize(); >+ if (paintTrack) { >+ int pos = size.height / 2; >+ g.setColor(Color.gray); >+ g.fillRect(0, pos - 1, size.width, 2); >+ g.setColor(Color.white); >+ g.drawLine(0, pos + 1, size.width, pos + 1); >+ } >+ >+ int dx = pixelsPerUnit * precisionMillis / 1000; >+ FontMetrics fm = g.getFontMetrics(); >+ int timeUnit = 0; >+ for (int i = SLIDER_X_OFFSET; i < size.width; i += pixelsPerUnit) { >+ String str = timeUnit++ + ""; >+ int strWidth = fm.stringWidth(str), strHeight = fm.getHeight() >+ - fm.getDescent(); >+ g.setColor(getBackground()); >+ g.fillRect(i - strWidth / 2, (size.height - strHeight) / 2, >+ strWidth, strHeight); >+ g.setColor(Color.black); >+ g.drawString(str, i - strWidth / 2, >+ (size.height + strHeight) / 2); >+ g.setColor(Color.gray); >+ g.drawLine(i, size.height - 2, i, size.height - 7); >+ g.drawLine(i, 2, i, 7); >+ g.setColor(Color.lightGray); >+ for (int j = i + dx; j < i + pixelsPerUnit; j += dx) { >+ g.drawLine(j, size.height - 2, j, size.height - 5); >+ g.drawLine(j, 2, j, 5); >+ } >+ } >+ >+ // Paint knob >+ int x = knobPosition; >+ int y = size.height / 2; >+ knobBounds.x = x - knobBounds.width / 2; >+ knobBounds.y = y - knobBounds.height / 2; >+ >+ g.translate(x, y); >+ g.setColor(SLIDER_KNOB_FILL_COLOR); >+ g.fillPolygon(knob); >+ g.setColor(SLIDER_KNOB_STROKE_COLOR); >+ g.drawPolygon(knob); >+ g.translate(-x, -y); >+ } >+ } >+ >+ private class JTimelineFramesPanel extends JPanel { >+ >+ private boolean inside; >+ >+ private int hoverPosition; >+ >+ private MouseListener ml = new MouseAdapter() { >+ public void mouseEntered(MouseEvent e) { >+ inside = true; >+ JFramesView.this.repaint(); >+ } >+ >+ public void mouseExited(MouseEvent e) { >+ inside = false; >+ JFramesView.this.repaint(); >+ } >+ }; >+ >+ private MouseMotionListener mml = new MouseMotionAdapter() { >+ public void mouseMoved(MouseEvent e) { >+ int x = e.getX() - SLIDER_X_OFFSET; >+ int dx = pixelsPerUnit * precisionMillis / 1000; >+ hoverPosition = SLIDER_X_OFFSET + x - x % dx; >+ JFramesView.this.repaint(); >+ } >+ }; >+ >+ public JTimelineFramesPanel() { >+ addMouseListener(ml); >+ addMouseMotionListener(mml); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ Dimension size = getSize(); >+ >+ int dx = pixelsPerUnit * precisionMillis / 1000; >+ g.setColor(Color.lightGray); >+ for (int i = SLIDER_X_OFFSET; i < size.width; i += dx) { >+ g.drawLine(i, 0, i, size.height); >+ } >+ >+ g.setColor(SLIDER_KNOB_STROKE_COLOR); >+ g.drawLine(knobPosition, 0, knobPosition, size.height); >+ >+ if (inside) { >+ Graphics2D g2 = (Graphics2D)g; >+ g2.setStroke(SLIDER_KNOB_STROKE); >+ >+ g2.drawLine(hoverPosition, 0, hoverPosition, size.height); >+ } >+ } >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/ButtonFactory.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/ButtonFactory.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/ButtonFactory.java (working copy) >@@ -28,6 +28,7 @@ > import javax.swing.JButton; > import javax.swing.JCheckBox; > import javax.swing.JRadioButton; >+import javax.swing.JToggleButton; > > /** > * This class represents a button factory which builds >@@ -123,6 +124,31 @@ > } > > /** >+ * Creates and returns a new swing button initialised >+ * to be used as a toolbar toggle button >+ * @param name the name of the button in the resource bundle >+ * @throws MissingResourceException if key is not the name of a button. >+ * It is not thrown if the mnemonic and the action keys are missing >+ * @throws ResourceFormatException if the mnemonic is not a single >+ * character >+ * @throws MissingListenerException if the button action is not found in >+ * the action map >+ */ >+ public JToggleButton createJToolbarToggleButton(String name) >+ throws MissingResourceException, >+ ResourceFormatException, >+ MissingListenerException { >+ JToggleButton result; >+ try { >+ result = new JToolbarToggleButton(getString(name+TEXT_SUFFIX)); >+ } catch (MissingResourceException e) { >+ result = new JToolbarToggleButton(); >+ } >+ initializeButton(result, name); >+ return result; >+ } >+ >+ /** > * Creates and returns a new swing radio button > * @param name the name of the button in the resource bundle > * @throws MissingResourceException if key is not the name of a button. >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/Hyperlink.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/Hyperlink.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/Hyperlink.java (revision 0) >@@ -0,0 +1,72 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.Cursor; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+ >+import javax.swing.JLabel; >+ >+public class Hyperlink extends JLabel { >+ private MouseListener ml = new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ if (callback != null) { >+ callback.linkClicked(new HyperlinkEvent(Hyperlink.this.getCommand())); >+ } >+ } >+ }; >+ >+ private HyperlinkCallback callback; >+ >+ private String command; >+ >+ private static final String HTML_TEXT = "<html><font color=\"blue\"><u>__HTML_TEXT__</u></font></html>"; >+ >+ private String text; >+ >+ public Hyperlink(String text, HyperlinkCallback callback) { >+ this.callback = callback; >+ setLinkText(text); >+ setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); >+ addMouseListener(ml); >+ } >+ >+ public String getLinkText() { >+ return text; >+ } >+ >+ public void setLinkText(String text) { >+ this.text = text; >+ super.setText(HTML_TEXT.replace("__HTML_TEXT__", text)); >+ } >+ >+ public String getCommand() { >+ return command; >+ } >+ >+ public void setCommand(String command) { >+ this.command = command; >+ } >+ >+ public static class HyperlinkEvent { >+ >+ private String command; >+ >+ public HyperlinkEvent(String command) { >+ this.command = command; >+ } >+ >+ public String getCommand() { >+ return command; >+ } >+ >+ public void setCommand(String command) { >+ this.command = command; >+ } >+ } >+ >+ public static interface HyperlinkCallback { >+ public void linkClicked(HyperlinkEvent e); >+ } >+} >+ >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarButton.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarButton.java (revision 549415) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarButton.java (working copy) >@@ -23,6 +23,7 @@ > import java.awt.event.MouseEvent; > > import javax.swing.JButton; >+import javax.swing.UIManager; > > /** > * This class represents the buttons used in toolbars. >@@ -57,7 +58,14 @@ > } > setBorderPainted(false); > setMargin(new Insets(2, 2, 2, 2)); >- addMouseListener(new MouseListener()); >+ >+ // Windows XP look and feel seems to have a bug due to which the >+ // size of the parent container changes when the border painted >+ // property is set. Temporary fix: disable mouseover behavior if >+ // installed lnf is Windows XP >+ if (!UIManager.getLookAndFeel().getName().equals("Windows")) { >+ addMouseListener(new MouseListener()); >+ } > } > > /** >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JDocumentTree.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JDocumentTree.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JDocumentTree.java (revision 0) >@@ -0,0 +1,279 @@ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Dimension; >+import java.awt.GradientPaint; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.Paint; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.util.ArrayList; >+import java.util.Locale; >+import java.util.ResourceBundle; >+ >+import javax.swing.BorderFactory; >+import javax.swing.DefaultListModel; >+import javax.swing.ImageIcon; >+import javax.swing.JComponent; >+import javax.swing.JLabel; >+import javax.swing.JList; >+import javax.swing.JPanel; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.JTree; >+import javax.swing.ListCellRenderer; >+import javax.swing.tree.TreeNode; >+ >+public class JDocumentTree extends JPanel { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resource.resources.JDocumentTree"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ private JList nodeList; >+ >+ private JScrollPane nodeListScrollPane; >+ >+ private Node rootNode; >+ >+ public JDocumentTree() { >+ this(null); >+ } >+ >+ public JDocumentTree(JTree tree) { >+ super(new BorderLayout()); >+ >+ nodeList = new JList(new DefaultListModel()); >+ nodeList.setFixedCellHeight(25); >+ nodeList.setCellRenderer(new DocTreeCellRenderer()); >+ nodeListScrollPane = new JScrollPane(nodeList); >+ nodeListScrollPane >+ .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); >+ nodeListScrollPane.setBorder(null); >+ add(nodeListScrollPane); >+ >+ TreeNode treeNode = (TreeNode) tree.getModel().getRoot(); >+ rootNode = parse(treeNode, null); >+ rebuildNodeList(nodeList, rootNode); >+ >+ nodeList.addMouseListener(new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ if (e.getClickCount() == 2) { >+ Node selectedNode = (Node) nodeList.getSelectedValue(); >+ selectedNode.setExpanded(!selectedNode.isExpanded()); >+ rebuildNodeList(nodeList, rootNode); >+ } >+ } >+ }); >+ } >+ >+ public JScrollBar getVerticalScrollBar() { >+ return nodeListScrollPane.getVerticalScrollBar(); >+ } >+ >+ public void setVerticalScrollBar(JScrollBar verticalScrollBar) { >+ nodeListScrollPane.setVerticalScrollBar(verticalScrollBar); >+ } >+ >+ private void rebuildNodeList(JList nodeList, Node node) { >+ DefaultListModel listModel = (DefaultListModel) nodeList.getModel(); >+ listModel.clear(); >+ addNode(listModel, node); >+ } >+ >+ private void addNode(DefaultListModel listModel, Node node) { >+ Node parent = node.getParent(); >+ if (parent == null || parent.isExpanded()) { >+ listModel.addElement(node); >+ Node[] children = node.getChildren(); >+ if (children != null) { >+ for (int i = 0; i < children.length; i++) { >+ addNode(listModel, children[i]); >+ } >+ } >+ } >+ } >+ >+ private Node parse(TreeNode treeNode, Node parent) { >+ if (treeNode == null) { >+ return null; >+ } >+ >+ Node docNode = new Node(parent, treeNode.toString()); >+ int childCount = treeNode.getChildCount(); >+ if (childCount > 0) { >+ ArrayList childDocNodes = new ArrayList(); >+ for (int i = 0; i < childCount; i++) { >+ Node childDocNode = parse((TreeNode) treeNode.getChildAt(i), >+ docNode); >+ if (childDocNode != null) { >+ childDocNodes.add(childDocNode); >+ } >+ } >+ docNode.setChildren((Node[]) childDocNodes.toArray(new Node[0])); >+ } >+ >+ return docNode; >+ } >+ >+ private class Node extends JComponent { >+ >+ private String text; >+ >+ private Node parent; >+ >+ private int depth; >+ >+ private Node[] children; >+ >+ private boolean expanded = true; >+ >+ private boolean locked = false; >+ >+ public Node(Node parent, String text) { >+ this.parent = parent; >+ this.depth = parent == null ? 0 : parent.depth + 1; >+ setText(text); >+ } >+ >+ public Node getParent() { >+ return parent; >+ } >+ >+ public int getDepth() { >+ return depth; >+ } >+ >+ public Node[] getChildren() { >+ return children; >+ } >+ >+ public int getChildCount() { >+ return children == null ? 0 : children.length; >+ } >+ >+ public void setChildren(Node[] children) { >+ this.children = children; >+ if (children != null) { >+ for (int i = 0; i < children.length; i++) { >+ children[i].parent = this; >+ } >+ } >+ } >+ >+ public boolean isExpanded() { >+ if (parent == null) { >+ return true; >+ } >+ if (!expanded) { >+ return false; >+ } >+ return parent.isExpanded(); >+ } >+ >+ public void setExpanded(boolean expanded) { >+ this.expanded = expanded; >+ } >+ >+ public String getText() { >+ return text; >+ } >+ >+ public void setText(String text) { >+ this.text = text; >+ } >+ } >+ >+ private class DocTreeCellRenderer extends JLabel implements >+ ListCellRenderer { >+ >+ private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon"); >+ >+ private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon"); >+ >+ private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon"); >+ >+ private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon"); >+ >+ private final ImageIcon LOCK_ICON = getIcon("TreeNodeLocked.icon"); >+ >+ private Paint normalPaint, selectedPaint; >+ >+ private boolean selected; >+ >+ private boolean locked = true; >+ >+ public DocTreeCellRenderer() { >+ setIcon(SPACER_ICON); >+ >+ Dimension dim = getPreferredSize(); >+ normalPaint = new Color(234, 234, 234); >+ selectedPaint = new GradientPaint(0, 0, Color.white, 0, >+ 2 * dim.height, Color.gray); >+ } >+ >+ private ImageIcon getIcon(String name) { >+ return new ImageIcon(JDocumentTree.this.getClass().getResource( >+ resources.getString(name))); >+ } >+ >+ protected void paintComponent(Graphics g) { >+ Dimension size = getSize(); >+ Graphics2D g2 = (Graphics2D) g; >+ g2.setPaint(selected ? selectedPaint : normalPaint); >+ g2.fillRect(0, 0, size.width, size.height); >+ >+ g2.setColor(Color.lightGray); >+ g2.drawLine(0, size.height - 2, size.width, size.height - 2); >+ g2.setColor(Color.white); >+ g2.drawLine(0, size.height - 1, size.width, size.height - 1); >+ >+ super.paintComponent(g); >+ >+ g.setColor(Color.white); >+ int x, y; >+ x = size.width - 18; >+ y = (size.height - 16) / 2; >+ g.draw3DRect(x, y, 16, 16, false); >+ if (locked) { >+ LOCK_ICON.paintIcon(this, g, x, y); >+ } >+ } >+ >+ public Component getListCellRendererComponent(JList list, Object value, >+ int index, boolean isSelected, boolean cellHasFocus) { >+ Node node = (Node) value; >+ selected = isSelected; >+ setText(node.getText()); >+ setBorder(BorderFactory.createEmptyBorder(0, node.depth * 10, 0, 0)); >+ if (node.getChildren() == null || node.getChildCount() == 0) {// leaf >+ setIcon(LEAF_ICON); >+ } else if (node.isExpanded()) { >+ setIcon(OPENED_ICON); >+ } else { >+ setIcon(CLOSED_ICON); >+ } >+ >+ return this; >+ } >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/resource/JToolbarToggleButton.java (revision 0) >@@ -0,0 +1,84 @@ >+/* >+ >+ Licensed to the Apache Software Foundation (ASF) under one or more >+ contributor license agreements. See the NOTICE file distributed with >+ this work for additional information regarding copyright ownership. >+ The ASF licenses this file to You under the Apache License, Version 2.0 >+ (the "License"); you may not use this file except in compliance with >+ the License. You may obtain a copy of the License at >+ >+ http://www.apache.org/licenses/LICENSE-2.0 >+ >+ Unless required by applicable law or agreed to in writing, software >+ distributed under the License is distributed on an "AS IS" BASIS, >+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ See the License for the specific language governing permissions and >+ limitations under the License. >+ >+ */ >+package org.apache.batik.util.gui.resource; >+ >+import java.awt.Insets; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+ >+import javax.swing.JToggleButton; >+import javax.swing.UIManager; >+ >+import org.apache.batik.util.gui.resource.JToolbarButton.MouseListener; >+ >+/** >+ * This class represents the buttons used in toolbars. >+ * >+ * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a> >+ * @version $Id: JToolbarButton.java 498555 2007-01-22 08:09:33Z cam $ >+ */ >+public class JToolbarToggleButton extends JToggleButton { >+ /** >+ * Creates a new toolbar button. >+ */ >+ public JToolbarToggleButton() { >+ initialize(); >+ } >+ >+ /** >+ * Creates a new toolbar button. >+ * @param txt The button text. >+ */ >+ public JToolbarToggleButton(String txt) { >+ super(txt); >+ initialize(); >+ } >+ >+ /** >+ * Initializes the button. >+ */ >+ protected void initialize() { >+ if (!System.getProperty("java.version").startsWith("1.3")) { >+ setOpaque(false); >+ setBackground(new java.awt.Color(0, 0, 0, 0)); >+ } >+ setBorderPainted(false); >+ setMargin(new Insets(2, 2, 2, 2)); >+ >+ // Windows XP look and feel seems to have a bug due to which the >+ // size of the parent container changes when the border painted >+ // property is set. Temporary fix: disable mouseover behavior if >+ // installed lnf is Windows XP >+ if (!UIManager.getLookAndFeel().getName().equals("Windows")) { >+ addMouseListener(new MouseListener()); >+ } >+ } >+ >+ /** >+ * To manage the mouse interactions. >+ */ >+ protected class MouseListener extends MouseAdapter { >+ public void mouseEntered(MouseEvent ev) { >+ setBorderPainted(true); >+ } >+ public void mouseExited(MouseEvent ev) { >+ setBorderPainted(false); >+ } >+ } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/TimelineViewer.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/TimelineViewer.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/TimelineViewer.java (revision 0) >@@ -0,0 +1,214 @@ >+package org.apache.batik.util.gui; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Dimension; >+import java.awt.GradientPaint; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.Paint; >+import java.awt.event.ActionEvent; >+import java.util.HashMap; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.Action; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.ImageIcon; >+import javax.swing.JDialog; >+import javax.swing.JLabel; >+import javax.swing.JOptionPane; >+import javax.swing.JPanel; >+import javax.swing.JScrollBar; >+import javax.swing.JScrollPane; >+import javax.swing.JSeparator; >+import javax.swing.JSplitPane; >+import javax.swing.JToolBar; >+import javax.swing.JTree; >+import javax.swing.tree.TreeCellRenderer; >+ >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.JDocumentTree; >+import org.apache.batik.util.gui.resource.JFramesView; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+import org.apache.batik.util.gui.resource.ToolBarFactory; >+ >+public class TimelineViewer extends JPanel implements ActionMap { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resources.TimelineViewer"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The toolbar factory. >+ */ >+ protected ToolBarFactory tf = new ToolBarFactory(bundle, this); >+ >+ private JTree docTree; >+ >+ public TimelineViewer() { >+ super(new BorderLayout()); >+ setPreferredSize(new Dimension(800, 300)); >+ >+ JSplitPane splitPane = new JSplitPane(); >+ splitPane.setResizeWeight(0.0); >+ JPanel leftPane = new JPanel(); >+ splitPane.setLeftComponent(leftPane); >+ >+ leftPane.setLayout(new BorderLayout()); >+ leftPane.setMinimumSize(new Dimension(300, 0)); >+ leftPane.setPreferredSize(getMinimumSize()); >+ leftPane.add(createToolBar(), BorderLayout.NORTH); >+ >+ JScrollBar scrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 100); >+ JDocumentTree docTree = new JDocumentTree(new JTree()); >+ docTree.setVerticalScrollBar(scrollBar); >+ leftPane.add(docTree); >+ >+ JFramesView framesView = new JFramesView(); >+ framesView.setVerticalScrollBar(scrollBar); >+ splitPane.setRightComponent(framesView); >+ add(splitPane); >+ } >+ >+ private JPanel createToolBar() { >+ JPanel toolbarPanel = new JPanel(new BorderLayout()); >+ JToolBar toolbar = tf.createJToolBar("ToolBar"); >+ toolbar.setFloatable(false); >+ >+ toolbarPanel.add(toolbar); >+ toolbarPanel.add(new JSeparator(), BorderLayout.SOUTH); >+ >+ return toolbarPanel; >+ } >+ >+ public JDialog createDialog(Component owner, String title) { >+ JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(owner), >+ title); >+ dialog.getContentPane().add(this, BorderLayout.CENTER); >+ dialog.pack(); >+ return dialog; >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ /** >+ * The action associated with the 'All' button. >+ */ >+ protected class DisplayAllButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ } >+ } >+ >+ public static void main(String[] args) { >+ JDialog d = new TimelineViewer().createDialog(null, >+ "Timeline Viewer 0.1"); >+ d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); >+ d.setVisible(true); >+ } >+ >+// private class DocTreeCellRenderer extends Box implements >+// TreeCellRenderer { >+// >+// private final ImageIcon SPACER_ICON = getIcon("TreeNodeSpacer.icon"); >+// >+// private final ImageIcon CLOSED_ICON = getIcon("TreeNodeClosed.icon"); >+// >+// private final ImageIcon OPENED_ICON = getIcon("TreeNodeOpened.icon"); >+// >+// private final ImageIcon LEAF_ICON = getIcon("TreeLeaf.icon"); >+// >+// private Paint gradient; >+// >+// private JLabel label; >+// >+// private JLabel icon; >+// >+// public DocTreeCellRenderer() { >+// super(BoxLayout.X_AXIS); >+// setOpaque(false); >+// >+// icon = new JLabel(SPACER_ICON); >+// add(icon); >+// >+// label = new JLabel(); >+// add(label); >+// >+// Dimension dim = getPreferredSize(); >+// gradient = new GradientPaint(0, 0, Color.white, 0, >+// 2 * dim.height, Color.gray); >+// } >+// >+// public void setBounds(int x, int y, int width, int height) { >+// super.setBounds(x, y, docTree.getWidth(), height); >+// System.out.println(getBounds()); >+// } >+// >+// private ImageIcon getIcon(String name) { >+// String uri = resources.getString(name); >+// System.out.println(uri); >+// return new ImageIcon(TimelineViewer.this.getClass().getResource( >+// uri)); >+// } >+// >+// protected void paintComponent(Graphics g) { >+// Graphics2D g2 = (Graphics2D) g; >+// g2.setPaint(gradient); >+// g2.fillRect(0, 0, getWidth(), getHeight()); >+// >+// super.paintComponent(g); >+// } >+// >+// public Component getTreeCellRendererComponent(JTree tree, Object value, >+// boolean selected, boolean expanded, boolean leaf, int row, >+// boolean hasFocus) { >+// label.setText(value.toString()); >+// >+// if (leaf) { >+// icon.setIcon(LEAF_ICON); >+// } else if (expanded) { >+// icon.setIcon(OPENED_ICON); >+// } else { >+// icon.setIcon(CLOSED_ICON); >+// } >+// return this; >+// } >+// } >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorHandlerProxy.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorHandlerProxy.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorHandlerProxy.java (revision 0) >@@ -0,0 +1,38 @@ >+package org.apache.batik.util.gui; >+ >+import java.lang.reflect.InvocationHandler; >+import java.lang.reflect.InvocationTargetException; >+import java.lang.reflect.Method; >+ >+import javax.swing.JDialog; >+import javax.swing.JOptionPane; >+ >+public class ErrorHandlerProxy implements InvocationHandler { >+ >+ private Object delegate; >+ >+ private String uri; >+ >+ public ErrorHandlerProxy(Object delegate, String uri) { >+ this.delegate = delegate; >+ this.uri = uri; >+ } >+ >+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { >+ try { >+ System.out.println("proxy invoked"); >+ return method.invoke(delegate, args); >+ } catch (InvocationTargetException ite) { >+ System.out.println("Exception occurred"); >+ ite.printStackTrace(); >+ } catch (Exception e) { >+ System.out.println("Exception occurred"); >+ ErrorConsole console = ErrorConsole.getInstance(); >+ console.add(e, uri, JOptionPane.ERROR_MESSAGE); >+ JDialog dialog = ErrorConsole.createDialog(null, "ERROR"); >+ dialog.setVisible(true); >+ } >+ return null; >+ } >+ >+} >Index: C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorConsole.java >=================================================================== >--- C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorConsole.java (revision 0) >+++ C:/Documents and Settings/fyp24ys/Desktop/batikws/xml-batik/sources/org/apache/batik/util/gui/ErrorConsole.java (revision 0) >@@ -0,0 +1,645 @@ >+package org.apache.batik.util.gui; >+ >+import java.awt.BorderLayout; >+import java.awt.Color; >+import java.awt.Component; >+import java.awt.Container; >+import java.awt.Dimension; >+import java.awt.FlowLayout; >+import java.awt.Font; >+import java.awt.GradientPaint; >+import java.awt.Graphics; >+import java.awt.Graphics2D; >+import java.awt.SystemColor; >+import java.awt.event.ActionEvent; >+import java.awt.event.ActionListener; >+import java.awt.event.ItemEvent; >+import java.awt.event.ItemListener; >+import java.awt.event.MouseAdapter; >+import java.awt.event.MouseEvent; >+import java.awt.event.MouseListener; >+import java.io.BufferedReader; >+import java.io.File; >+import java.io.FileReader; >+import java.io.PrintWriter; >+import java.io.StringWriter; >+import java.net.URI; >+import java.util.ArrayList; >+import java.util.Enumeration; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.List; >+import java.util.Locale; >+import java.util.Map; >+import java.util.ResourceBundle; >+ >+import javax.swing.AbstractAction; >+import javax.swing.AbstractButton; >+import javax.swing.Action; >+import javax.swing.BorderFactory; >+import javax.swing.Box; >+import javax.swing.BoxLayout; >+import javax.swing.ButtonGroup; >+import javax.swing.ButtonModel; >+import javax.swing.ImageIcon; >+import javax.swing.JButton; >+import javax.swing.JDialog; >+import javax.swing.JLabel; >+import javax.swing.JOptionPane; >+import javax.swing.JPanel; >+import javax.swing.JPopupMenu; >+import javax.swing.JScrollPane; >+import javax.swing.JTextArea; >+import javax.swing.JTextPane; >+import javax.swing.JToggleButton; >+import javax.swing.JToolBar; >+import javax.swing.text.BadLocationException; >+import javax.swing.text.DefaultHighlighter; >+import javax.swing.text.Highlighter; >+import javax.swing.text.JTextComponent; >+import javax.swing.text.Highlighter.HighlightPainter; >+ >+import org.apache.batik.dom.svg.SAXSVGDocumentFactory; >+import org.apache.batik.util.ParsedURL; >+import org.apache.batik.util.gui.resource.ActionMap; >+import org.apache.batik.util.gui.resource.ButtonFactory; >+import org.apache.batik.util.gui.resource.Hyperlink; >+import org.apache.batik.util.gui.resource.JToolbarSeparator; >+import org.apache.batik.util.gui.resource.MenuFactory; >+import org.apache.batik.util.gui.resource.MissingListenerException; >+import org.apache.batik.util.gui.resource.ResourceManager; >+import org.apache.batik.util.gui.resource.Hyperlink.HyperlinkEvent; >+import org.w3c.dom.Document; >+import org.xml.sax.Attributes; >+import org.xml.sax.Locator; >+import org.xml.sax.SAXException; >+import org.xml.sax.helpers.LocatorImpl; >+ >+public class ErrorConsole extends JPanel implements ActionMap { >+ >+ /** >+ * The resource file name >+ */ >+ protected static final String RESOURCES = "org.apache.batik.util.gui.resources.ErrorConsole"; >+ >+ /** >+ * The resource bundle >+ */ >+ protected static ResourceBundle bundle; >+ >+ /** >+ * The resource manager >+ */ >+ protected static ResourceManager resources; >+ >+ static { >+ bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault()); >+ resources = new ResourceManager(bundle); >+ } >+ >+ /** >+ * The button factory. >+ */ >+ protected ButtonFactory bf = new ButtonFactory(bundle, this); >+ >+ /** >+ * The menu factory. >+ */ >+ protected MenuFactory mf = new MenuFactory(bundle, this); >+ >+ private Box consoleList; >+ >+ private ButtonGroup errorGroup; >+ >+ private int displayType; >+ >+ private boolean sortOrderAscending = true; >+ >+ private JPopupMenu popupMenu; >+ >+ public ErrorConsole() { >+ super(new BorderLayout()); >+ >+ actions.put("DisplayAllButtonAction", new DisplayAllButtonAction()); >+ actions.put("DisplayErrorsButtonAction", >+ new DisplayErrorsButtonAction()); >+ actions.put("DisplayWarningsButtonAction", >+ new DisplayWarningsButtonAction()); >+ actions.put("DisplayMessagesButtonAction", >+ new DisplayMessagesButtonAction()); >+ actions.put("ClearButtonAction", new ClearButtonAction()); >+ >+ actions.put("FirstLastSortMenuAction", new FirstLastSortMenuAction()); >+ actions.put("LastFirstSortMenuAction", new LastFirstSortMenuAction()); >+ actions.put("CopyMenuAction", new CopyMenuAction()); >+ >+ JPanel errorPanel = new JPanel(new BorderLayout()); >+ errorPanel.setBackground(Color.white); >+ >+ JScrollPane errorScrollPane = new JScrollPane(errorPanel); >+ errorScrollPane >+ .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); >+ add(errorScrollPane); >+ >+ errorGroup = new ButtonGroup(); >+ >+ consoleList = new Box(BoxLayout.Y_AXIS); >+ errorPanel.add(consoleList, BorderLayout.NORTH); >+ >+ popupMenu = createPopupMenu(); >+ >+ add(createToolBar(), BorderLayout.NORTH); >+ setPreferredSize(new Dimension(550, 400)); >+ } >+ >+ private JToolBar createToolBar() { >+ JToolBar toolbar = new JToolBar(); >+ toolbar.setFloatable(false); >+ >+ BooleanButtonGroup displayGroup = new BooleanButtonGroup(); >+ >+ JToggleButton displayAll = bf >+ .createJToolbarToggleButton("DisplayAllButton"); >+ displayGroup.add(displayAll); >+ displayAll.setSelected(true); >+ displayType(-1, true); >+ toolbar.add(displayAll); >+ >+ JToggleButton displayErrors = bf >+ .createJToolbarToggleButton("DisplayErrorsButton"); >+ displayGroup.addOr(displayErrors); >+ toolbar.add(displayErrors); >+ >+ JToggleButton displayWarnings = bf >+ .createJToolbarToggleButton("DisplayWarningsButton"); >+ displayGroup.addOr(displayWarnings); >+ toolbar.add(displayWarnings); >+ >+ JToggleButton displayMessages = bf >+ .createJToolbarToggleButton("DisplayMessagesButton"); >+ displayGroup.addOr(displayMessages); >+ toolbar.add(displayMessages); >+ >+ toolbar.add(new JToolbarSeparator()); >+ >+ JButton clear = bf.createJToolbarButton("ClearButton"); >+ displayGroup.add(clear); >+ toolbar.add(clear); >+ >+ return toolbar; >+ } >+ >+ private class BooleanButtonGroup extends ButtonGroup implements >+ ItemListener { >+ >+ private List orElements = new ArrayList(); >+ >+ private AbstractButton orButton = new JToggleButton(); >+ >+ public BooleanButtonGroup() { >+ orButton.addItemListener(this); >+ add(orButton); >+ } >+ >+ public void itemStateChanged(ItemEvent e) { >+ if (e.getSource() == orButton >+ && e.getStateChange() == ItemEvent.DESELECTED) { >+ for (Iterator i = orElements.iterator(); i.hasNext();) { >+ AbstractButton button = (AbstractButton) i.next(); >+ button.setSelected(false); >+ } >+ } else if (e.getStateChange() == ItemEvent.SELECTED) { >+ setSelected(((AbstractButton) e.getSource()).getModel(), true); >+ } >+ } >+ >+ public void addOr(AbstractButton button) { >+ orElements.add(button); >+ button.addItemListener(this); >+ } >+ >+ public void setSelected(ButtonModel model, boolean selected) { >+ for (Iterator i = orElements.iterator(); i.hasNext();) { >+ AbstractButton button = (AbstractButton) i.next(); >+ if (button.getModel() == model) { >+ orButton.setSelected(selected); >+ return; >+ } >+ } >+ super.setSelected(model, selected); >+ } >+ } >+ >+ private JPopupMenu createPopupMenu() { >+ JPopupMenu popupMenu = mf.createJMenu("PopupMenu").getPopupMenu(); >+ return popupMenu; >+ } >+ >+ protected static ErrorConsole instance; >+ >+ public static ErrorConsole getInstance() { >+ if (instance == null) { >+ instance = new ErrorConsole(); >+ } >+ return instance; >+ } >+ >+ public static JDialog createDialog(Component owner, String title) { >+ JDialog dialog = new JDialog(JOptionPane.getFrameForComponent(owner), >+ title); >+ dialog.getContentPane().add(getInstance(), BorderLayout.CENTER); >+ dialog.pack(); >+ return dialog; >+ } >+ >+ public void add(Throwable th, String uri, int type) { >+ ErrorButton errorButton = new ErrorButton(th, uri, type); >+ errorButton.setPopupMenu(popupMenu); >+ consoleList.add(errorButton); >+ errorGroup.add(errorButton); >+ } >+ >+ public void add(String elementName, String uri, int type) { >+ ErrorButton errorButton = new ErrorButton(elementName, uri, type); >+ errorButton.setPopupMenu(popupMenu); >+ consoleList.add(errorButton); >+ errorGroup.add(errorButton); >+ } >+ >+ /** >+ * The map that contains the actions >+ */ >+ protected Map actions = new HashMap(); >+ >+ /** >+ * Returns the action associated with the given string or null on error >+ * >+ * @param key >+ * the key mapped with the action to get >+ * @throws MissingListenerException >+ * if the action is not found >+ */ >+ public Action getAction(String key) throws MissingListenerException { >+ return (Action) actions.get(key); >+ } >+ >+ /** >+ * The action associated with the 'All' button. >+ */ >+ protected class DisplayAllButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ displayType(-1, true); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Errors' button. >+ */ >+ protected class DisplayErrorsButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(JOptionPane.ERROR_MESSAGE, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Warnings' button. >+ */ >+ protected class DisplayWarningsButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(JOptionPane.WARNING_MESSAGE, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Messages' button. >+ */ >+ protected class DisplayMessagesButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ boolean selected = ((AbstractButton) evt.getSource()).isSelected(); >+ displayType(JOptionPane.INFORMATION_MESSAGE, selected); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Clear' button. >+ */ >+ protected class ClearButtonAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ clearType(displayType); >+ Enumeration<AbstractButton> buttons = errorGroup.getElements(); >+ while (buttons.hasMoreElements()) { >+ errorGroup.remove(buttons.nextElement()); >+ } >+ } >+ } >+ >+ /** >+ * The action associated with the 'First to Last Sort' menu item. >+ */ >+ protected class FirstLastSortMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ if (sortOrderAscending) { >+ return; >+ } >+ reverseComponentOrder(consoleList); >+ sortOrderAscending = true; >+ } >+ } >+ >+ /** >+ * The action associated with the 'Last to First Sort' menu item. >+ */ >+ protected class LastFirstSortMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ if (!sortOrderAscending) { >+ return; >+ } >+ reverseComponentOrder(consoleList); >+ sortOrderAscending = false; >+ } >+ } >+ >+ private void reverseComponentOrder(Container container) { >+ Component[] components = container.getComponents(); >+ consoleList.removeAll(); >+ for (int i = components.length - 1; i >= 0; i--) { >+ consoleList.add(components[i]); >+ } >+ } >+ >+ /** >+ * The action associated with the 'Copy' menu item. >+ */ >+ protected class CopyMenuAction extends AbstractAction { >+ >+ public void actionPerformed(ActionEvent evt) { >+ >+ } >+ } >+ >+ private void clearType(int type) { >+ Component[] components = consoleList.getComponents(); >+ for (int i = 0; i < components.length; i++) { >+ ErrorButton eb = (ErrorButton) components[i]; >+ if (type < 0 || eb.getType() == type) { >+ consoleList.remove(eb); >+ } >+ } >+ } >+ >+ private void displayType(int type, boolean visible) { >+ displayType = type; >+ Component[] components = consoleList.getComponents(); >+ for (Component c : components) { >+ ErrorButton eb = (ErrorButton) c; >+ if (type < 0 || (eb.getType() == type)) { >+ eb.setVisible(visible); >+ } >+ } >+ } >+ >+ private class ErrorButton extends JToggleButton { >+ >+ private int type; >+ >+ private JTextPane messageText; >+ >+ private Hyperlink link; >+ >+ private ImageIcon icon; >+ >+ private GradientPaint gradient; >+ >+ private JPanel details; >+ >+ private JPopupMenu popupMenu; >+ >+ private JTextArea detailText; >+ >+ private ItemListener il = new ItemListener() { >+ public void itemStateChanged(ItemEvent e) { >+ if (e.getStateChange() == ItemEvent.SELECTED) { >+ details.setVisible(true); >+ } else if (e.getStateChange() == ItemEvent.DESELECTED) { >+ details.setVisible(false); >+ } else { >+ return; >+ } >+ repaint(); >+ } >+ }; >+ >+ private MouseListener ml = new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ if (e.getButton() == MouseEvent.BUTTON3) { >+ popupMenu.show(ErrorButton.this, e.getX(), e.getY()); >+ } >+ } >+ }; >+ >+ public ErrorButton(int type) { >+ this.type = type; >+ >+ setLayout(new BorderLayout(10, 10)); >+ setContentAreaFilled(false); >+ setBorderPainted(false); >+ setOpaque(false); >+ setFocusPainted(false); >+ setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); >+ addItemListener(il); >+ addMouseListener(ml); >+ >+ String s; >+ switch (type) { >+ case JOptionPane.WARNING_MESSAGE: >+ s = resources.getString("ErrorButton.warning_icon"); >+ break; >+ case JOptionPane.INFORMATION_MESSAGE: >+ s = resources.getString("ErrorButton.message_icon"); >+ break; >+ case JOptionPane.ERROR_MESSAGE: >+ default: >+ s = resources.getString("ErrorButton.error_icon"); >+ break; >+ } >+ icon = new ImageIcon(getClass().getResource(s)); >+ add(new JLabel(icon), BorderLayout.WEST); >+ >+ Box centerPane = new Box(BoxLayout.Y_AXIS); >+ add(centerPane); >+ >+ messageText = new JTextPane(); >+ messageText.setEditable(false); >+ messageText.setOpaque(false); >+ messageText.addMouseListener(new MouseAdapter() { >+ public void mouseClicked(MouseEvent e) { >+ ErrorButton.this.setSelected(true); >+ } >+ }); >+ centerPane.add(messageText, BorderLayout.NORTH); >+ >+ link = new Hyperlink("", new Hyperlink.HyperlinkCallback() { >+ public void linkClicked(HyperlinkEvent e) { >+ // new DocumentViewer(doc).setVisible(true); >+ } >+ }); >+ centerPane.add(link, BorderLayout.SOUTH); >+ >+ details = new JPanel(new BorderLayout()); >+ details.setOpaque(false); >+ details.setVisible(false); >+ add(details, BorderLayout.SOUTH); >+ >+ detailText = new JTextArea(); >+ detailText.setFont(new Font("Monospaced", Font.PLAIN, 12)); >+ detailText.setEditable(false); >+ detailText.setLineWrap(true); >+ final JScrollPane stackTraceScrollPane = new JScrollPane(detailText); >+ stackTraceScrollPane.getViewport().setPreferredSize( >+ new Dimension(300, 100)); >+ stackTraceScrollPane.setVisible(false); >+ final JButton btnShowDetails = new JButton("Show Details >>"); >+ btnShowDetails.addActionListener(new ActionListener() { >+ public void actionPerformed(ActionEvent e) { >+ boolean visible = stackTraceScrollPane.isVisible(); >+ stackTraceScrollPane.setVisible(!visible); >+ btnShowDetails.setText(visible ? "Show Details >>" >+ : "<< Hide Details"); >+ } >+ }); >+ JPanel button = new JPanel(new FlowLayout(FlowLayout.LEADING)); >+ button.setOpaque(false); >+ button.add(btnShowDetails); >+ details.add(button, BorderLayout.NORTH); >+ details.add(stackTraceScrollPane); >+ >+ Dimension dim = getPreferredSize(); >+ gradient = new GradientPaint(0, 0, new Color(217, 226, 234), 0, >+ 2 * dim.height, new Color(193, 207, 221)); >+ >+ } >+ >+ public ErrorButton(Throwable th, String uri, int type) { >+ this(type); >+ >+ messageText.setText(th.getMessage()); >+ >+ StringWriter sw = new StringWriter(); >+ th.printStackTrace(new PrintWriter(sw)); >+ sw.flush(); >+ detailText.setText(sw.toString()); >+ } >+ >+ public ErrorButton(String elementName, String uri, int type) { >+ this(type); >+ >+ messageText.setText("Document uri: " + uri); >+ String text; >+ try { >+ BufferedReader reader = new BufferedReader(new FileReader(ParsedURL.parseURL(uri).path)); >+ String line; >+ StringBuilder sb = new StringBuilder(); >+ while ((line = reader.readLine()) != null) { >+ sb.append(line + "\n"); >+ } >+ text = sb.toString(); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ text = "Error reading file: " + uri; >+ } >+ detailText.setText(text); >+ >+ highlightElement( >+ elementName, >+ uri, >+ detailText, >+ new DefaultHighlighter.DefaultHighlightPainter(Color.yellow)); >+ } >+ >+ private void highlightElement(String name, String uri, >+ JTextComponent textComponent, HighlightPainter hlPainter) { >+ Highlighter highlighter = textComponent.getHighlighter(); >+ highlighter.removeAllHighlights(); >+ >+ String text = textComponent.getText(); >+ for (int index = 0; (index = text.indexOf(name, index)) >= 0; index += name.length()) { >+ try { >+ highlighter.addHighlight(index, index + name.length(), hlPainter); >+ } catch (BadLocationException e) { >+ break; >+ } >+ } >+ } >+ >+ public void paintComponent(Graphics g) { >+ Graphics2D g2 = (Graphics2D) g; >+ int width = getWidth(), height = getHeight(); >+ g2.setPaint(isSelected() ? gradient : Color.white); >+ g2.fillRect(0, 0, width, height); >+ g2.setColor(SystemColor.controlShadow); >+ g2.drawLine(0, height - 1, width, height - 1); >+ super.paintComponent(g); >+ } >+ >+ public int getType() { >+ return type; >+ } >+ >+ public void setType(int type) { >+ this.type = type; >+ repaint(); >+ } >+ >+ public JPopupMenu getPopupMenu() { >+ return popupMenu; >+ } >+ >+ public void setPopupMenu(JPopupMenu popupMenu) { >+ this.popupMenu = popupMenu; >+ } >+ } >+ >+ private static Locator searchLoc; >+ >+ public static void main(String[] args) throws Exception { >+ ErrorConsole ec = ErrorConsole.getInstance(); >+ String uri = new File(System.getProperty("user.home") >+ + "/Desktop/batikws/xml-batik/rect.svg").toURI().toString(); >+ final Locator locator = new LocatorImpl(); >+ SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(null) { >+ public void startElement(String uri, >+ String localName, >+ String rawName, >+ Attributes attributes) throws SAXException { >+ super.startElement(uri, localName, rawName, attributes); >+ >+ System.out.println(localName); >+ if (currentNode.getNodeName().equals("desc")) { >+ searchLoc = new LocatorImpl(locator); >+ } >+ } >+ }; >+ f.setDocumentLocator(locator); >+ Document doc = f.createDocument(uri); >+ if (searchLoc != null) { >+ System.out.println(searchLoc.getLineNumber() + ", " + searchLoc.getColumnNumber()); >+ } >+ //ec.add(doc.getChildNodes(), uri, JOptionPane.ERROR_MESSAGE); >+ ec.add(new Exception("Test Exception"), null, >+ JOptionPane.WARNING_MESSAGE); >+ ec.add(new Exception("Test Exception"), null, >+ JOptionPane.INFORMATION_MESSAGE); >+ JDialog d = ErrorConsole.createDialog(null, "Error Console 0.1"); >+ d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); >+ d.setVisible(true); >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 42741
:
20395
|
20396
|
20443
|
20444
|
20518
|
20519
|
20530
|
20531