|
What this is
Other links
The source code
/*
* Gutter.java
* Copyright (C) 1999, 2000 mike dillon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.gjt.sp.jedit.textarea;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import org.jext.JextTextArea;
public class Gutter extends JComponent implements SwingConstants
{
public Gutter(JEditTextArea textArea, TextAreaDefaults defaults)
{
this.textArea = textArea;
setBackground(defaults.gutterBgColor);
setForeground(defaults.gutterFgColor);
setHighlightedForeground(defaults.gutterHighlightColor);
setCaretMark(defaults.caretMarkColor);
setAnchorMark(defaults.anchorMarkColor);
setSelectionMark(defaults.selectionMarkColor);
setFont(defaults.gutterFont);
setBorder(defaults.gutterBorderWidth, defaults.gutterBorderColor);
setLineNumberAlignment(defaults.gutterNumberAlignment);
setGutterWidth(defaults.gutterWidth);
setCollapsed(defaults.gutterCollapsed);
GutterMouseListener ml = new GutterMouseListener();
addMouseListener(ml);
addMouseMotionListener(ml);
}
///////////////////////////////////////////////////////////////////////////////
// ANTI ALIASING
///////////////////////////////////////////////////////////////////////////////
private boolean antiAliasing = false;
private boolean wasAntiAliasing = false;
public void setAntiAliasingEnabled(boolean on)
{
wasAntiAliasing = antiAliasing;
antiAliasing = on;
}
private void setAntiAliasing(Graphics g)
{
if (antiAliasing)
((Graphics2D) g).setRenderingHints(TextAreaPainter.ANTI_ALIASED_RENDERING);
else if (wasAntiAliasing != antiAliasing)
((Graphics2D) g).setRenderingHints(TextAreaPainter.DEFAULT_RENDERING);
}
public void paintComponent(Graphics gfx)
{
if (!collapsed)
{
setAntiAliasing(gfx);
// fill the background
Rectangle r = gfx.getClipBounds();
gfx.setColor(getBackground());
gfx.fillRect(r.x, r.y, r.width, r.height);
// paint custom highlights, if there are any
if (highlights != null)
paintCustomHighlights(gfx);
// paint line numbers, if they are enabled
if (lineNumberingEnabled)
paintLineNumbers(gfx);
}
}
protected void paintLineNumbers(Graphics gfx)
{
FontMetrics pfm = textArea.getPainter().getFontMetrics();
int lineHeight = pfm.getHeight();
int baseline = (int) Math.round((this.baseline + lineHeight - pfm.getMaxDescent()) / 2.0);
int firstLine = textArea.getFirstLine() + 1;
int lastLine = firstLine + (getHeight() / lineHeight);
int firstValidLine = (int) Math.max(1, firstLine);
int lastValidLine = (int) Math.min(textArea.getLineCount(), lastLine);
gfx.setFont(getFont());
gfx.setColor(getForeground());
String number;
for (int line = firstLine; line <= lastLine; line++, baseline += lineHeight)
{
// only print numbers for valid lines
if (line < firstValidLine || line > lastValidLine)
continue;
number = Integer.toString(line);
int offset;
switch (alignment)
{
case RIGHT:
offset = gutterSize.width - collapsedSize.width - (fm.stringWidth(number) + 1);
break;
case CENTER:
offset = ((gutterSize.width - collapsedSize.width) - fm.stringWidth(number)) / 2;
break;
case LEFT: default:
offset = 1;
}
if (interval > 1 && line % interval == 0)
{
gfx.setColor(getHighlightedForeground());
gfx.drawString(number, ileft + offset, baseline);
gfx.setColor(getForeground());
} else {
gfx.drawString(number, ileft + offset, baseline);
}
if (line == textArea.getCaretLine() + 1)
{
gfx.setColor(caretMark);
gfx.drawRect(ileft + offset - 8, baseline - 6, 4, 4);
}
int anchor = ((JextTextArea) textArea).getAnchorOffset();
if (anchor != -1 && line == textArea.getLineOfOffset(anchor) + 1)
{
gfx.setColor(anchorMark);
gfx.drawRect(ileft + offset - 8, baseline - 6, 4, 4);
}
if ( textArea.getSelectionStart() == textArea.getSelectionEnd())
{
gfx.setColor(getForeground());
continue;
}
if (line >= textArea.getSelectionStartLine() + 1 && line <= textArea.getSelectionEndLine() + 1)
{
gfx.setColor(selectionMark);
gfx.fillRect(ileft + offset - 7, baseline - 5, 3, 3);
}
gfx.setColor(getForeground());
}
}
protected void paintCustomHighlights(Graphics gfx)
{
int lineHeight = textArea.getPainter().getFontMetrics() .getHeight();
int firstLine = textArea.getFirstLine();
int lastLine = firstLine + (getHeight() / lineHeight);
int y = 0;
for (int line = firstLine; line < lastLine; line++, y += lineHeight)
{
highlights.paintHighlight(gfx, line, y);
}
}
/**
* Adds a custom highlight painter.
* @param highlight The highlight
*/
public void addCustomHighlight(TextAreaHighlight highlight)
{
highlight.init(textArea, highlights);
highlights = highlight;
}
/**
* Convenience method for setting a default matte border on the right
* with the specified border width and color
* @param width The border width (in pixels)
* @param color The border color
*/
public void setBorder(int width, Color color)
{
setBorder(BorderFactory.createMatteBorder(0,0,0,width,color));
}
/*
* JComponent.setBorder(Border) is overridden here to cache the left
* inset of the border (if any) to avoid having to fetch it during every
* repaint.
*/
public void setBorder(Border border)
{
super.setBorder(border);
if (border == null)
{
ileft = 0;
collapsedSize.width = 0;
collapsedSize.height = 0;
}
else
{
Insets insets = border.getBorderInsets(this);
ileft = insets.left;
collapsedSize.width = insets.left + insets.right;
collapsedSize.height = insets.top + insets.bottom;
}
}
/*
* JComponent.setFont(Font) is overridden here to cache the baseline for
* the font. This avoids having to get the font metrics during every
* repaint.
*/
public void setFont(Font font)
{
super.setFont(font);
fm = getFontMetrics(font);
baseline = fm.getHeight() - fm.getMaxDescent();
}
/**
* Set the foreground color for highlighted line numbers
* @param highlight The highlight color
*/
public void setHighlightedForeground(Color highlight)
{
intervalHighlight = highlight;
}
/**
* Get the foreground color for highlighted line numbers
* @return The highlight color
*/
public Color getHighlightedForeground()
{
return intervalHighlight;
}
public void setCaretMark(Color mark)
{
caretMark = mark;
}
public void setAnchorMark(Color mark)
{
anchorMark = mark;
}
public void setSelectionMark(Color mark)
{
selectionMark = mark;
}
/**
* Set the width of the expanded gutter
* @param width The gutter width
*/
public void setGutterWidth(int width)
{
if (width < collapsedSize.width) width = collapsedSize.width;
gutterSize.width = width;
// if the gutter is expanded, ask the text area to revalidate
// the layout to resize the gutter
if (!collapsed) textArea.revalidate();
}
/**
* Get the width of the expanded gutter
* @return The gutter width
*/
public int getGutterWidth()
{
return gutterSize.width;
}
/*
* Component.getPreferredSize() is overridden here to support the
* collapsing behavior.
*/
public Dimension getPreferredSize()
{
if (collapsed)
{
return collapsedSize;
} else {
return gutterSize;
}
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
public String getToolTipText(MouseEvent evt)
{
return (highlights == null) ? null :
highlights.getToolTipText(evt);
}
/**
* Identifies whether or not the line numbers are drawn in the gutter
* @return true if the line numbers are drawn, false otherwise
*/
public boolean isLineNumberingEnabled()
{
return lineNumberingEnabled;
}
/**
* Turns the line numbering on or off and causes the gutter to be
* repainted.
* @param enabled true if line numbers are drawn, false otherwise
*/
public void setLineNumberingEnabled(boolean enabled)
{
if (lineNumberingEnabled == enabled) return;
lineNumberingEnabled = enabled;
repaint();
}
/**
* Identifies whether the horizontal alignment of the line numbers.
* @return Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
*/
public int getLineNumberAlignment()
{
return alignment;
}
/**
* Sets the horizontal alignment of the line numbers.
* @param alignment Gutter.RIGHT, Gutter.CENTER, Gutter.LEFT
*/
public void setLineNumberAlignment(int alignment)
{
if (this.alignment == alignment) return;
this.alignment = alignment;
repaint();
}
/**
* Identifies whether the gutter is collapsed or expanded.
* @return true if the gutter is collapsed, false if it is expanded
*/
public boolean isCollapsed()
{
return collapsed;
}
/**
* Sets whether the gutter is collapsed or expanded and force the text
* area to update its layout if there is a change.
* @param collapsed true if the gutter is collapsed,
* false if it is expanded
*/
public void setCollapsed(boolean collapsed)
{
if (this.collapsed == collapsed) return;
this.collapsed = collapsed;
textArea.revalidate();
}
/**
* Toggles whether the gutter is collapsed or expanded.
*/
public void toggleCollapsed()
{
setCollapsed(!collapsed);
}
/**
* Sets the number of lines between highlighted line numbers.
* @return The number of lines between highlighted line numbers or
* zero if highlighting is disabled
*/
public int getHighlightInterval()
{
return interval;
}
/**
* Sets the number of lines between highlighted line numbers. Any value
* less than or equal to one will result in highlighting being disabled.
* @param interval The number of lines between highlighted line numbers
*/
public void setHighlightInterval(int interval)
{
if (interval <= 1) interval = 0;
this.interval = interval;
repaint();
}
public JPopupMenu getContextMenu()
{
return context;
}
public void setContextMenu(JPopupMenu context)
{
this.context = context;
}
// private members
// the JEditTextArea this gutter is attached to
private JEditTextArea textArea;
private JPopupMenu context;
private TextAreaHighlight highlights;
private int baseline = 0;
private int ileft = 0;
private Dimension gutterSize = new Dimension(0,0);
private Dimension collapsedSize = new Dimension(0,0);
private Color intervalHighlight;
private Color caretMark;
private Color anchorMark;
private Color selectionMark;
private FontMetrics fm;
private int alignment;
private int interval = 0;
private boolean lineNumberingEnabled = true;
private boolean collapsed = false;
class GutterMouseListener extends MouseAdapter implements MouseMotionListener
{
public void mouseClicked(MouseEvent e)
{
int count = e.getClickCount();
if (count == 1)
{
if (context == null || context.isVisible())
return;
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
{
//XXX this is a hack to make sure the
//XXX actions get the right text area
textArea.requestFocus();
context.show(Gutter.this, e.getX(), e.getY());
}
} else if (count >= 2) {
toggleCollapsed();
}
}
public void mousePressed(MouseEvent e)
{
dragStart = e.getPoint();
startWidth = gutterSize.width;
}
public void mouseDragged(MouseEvent e)
{
if (dragStart == null) return;
if (isCollapsed()) setCollapsed(false);
Point p = e.getPoint();
gutterSize.width = startWidth + p.x - dragStart.x;
if (gutterSize.width < collapsedSize.width)
{
gutterSize.width = startWidth;
setCollapsed(true);
}
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
textArea.revalidate();
}
});
}
public void mouseExited(MouseEvent e)
{
if (dragStart != null && dragStart.x > e.getPoint().x)
{
setCollapsed(true);
gutterSize.width = startWidth;
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
textArea.revalidate();
}
});
}
//dragStart = null;
}
public void mouseMoved(MouseEvent e) {}
public void mouseReleased(MouseEvent e)
{
dragStart = null;
}
private Point dragStart = null;
private int startWidth = 0;
}
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.