/*
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a 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, version 3 of the License.
C.a.R. 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, see .
*/
package rene.lister;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import eric.JEricPanel;
import rene.gui.Global;
import rene.util.MyVector;
public class ListerPanel extends JEricPanel {
/**
*
*/
private static final long serialVersionUID=1L;
private final MyVector V; // Vector of listed Elements
int Top; // Top Element
Image I; // Buffer Image
int W, H; // width and height of current image
int panelHeight;
Graphics IG; // Graphics for the image
Font F; // current font
FontMetrics FM; // current font metrics
int Leading, Height, Ascent, Descent; // font stuff
int PageSize; // numbers of lines per page
int HOffset; // horizontal offset of display
boolean ShowLast; // Show last on next redraw
Lister LD;
String Name;
public Color ListingBackground=null;
public boolean MultipleSelection=true; // Allow multiple selection
public boolean EasyMultipleSelection=false; // Multiple select without
// right mouse
public boolean ReportSingleClick=false; // Report single clicks also
public boolean RightMouseClick=false; // Report right mouse clicks also
public ListerPanel(final Lister ld, final String name) {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
LD=ld;
Name=name;
V=new MyVector();
Top=0;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
clicked(e);
}
});
init();
}
public ListerPanel(final Lister ld) {
this(ld, "");
}
/**
* Paint routine. Simply sets up the buffer image, calls dopaint and paints
* the image to the screen.
*/
// @Override
@Override
public void paintComponent(final Graphics g) {
W=getSize().width;
H=getHeight();
I=createImage(W, H);
if (I==null) {
return;
}
IG=I.getGraphics();
init();
dopaint(IG);
g.drawImage(I, 0, 0, W, H, this);
double vp, vs, hp, hs;
if (V.size()>1) {
vp=(double) Top/V.size();
} else {
vp=0;
}
if (V.size()>2*PageSize) {
vs=(double) PageSize/V.size();
} else {
vs=0.5;
}
if (HOffset<10*W) {
hp=(double) HOffset/(10*W);
} else {
hp=0.9;
}
hs=0.1;
}
/**
* Initialize the font stuff and set the background of the panel.
*/
void init() {
F=new Font("Monospaced", 1, 14);
setFont(F);
FM=getFontMetrics(F);
Leading=FM.getLeading()
+Global.getParameter("fixedfont.spacing", -1);
Height=FM.getHeight()+3;
Ascent=FM.getAscent();
Descent=FM.getDescent();
// if (Global.Background!=null) setBackground(Global.Background);
if (Height+Leading>0) {
PageSize=H/(Height+Leading);
} else {
PageSize=10;
}
Top=0;
}
/**
* Paint the current text lines on the image.
*
* @param g
*/
public synchronized void dopaint(final Graphics g) {
Graphics2D g2=(Graphics2D) g;
g2.setColor(Color.white);
g2.fillRect(0, 0, W, H);
g2.setFont(F);
g2.setColor(Color.black);
int h=Leading+Ascent;
int line=Top;
if (line<0) {
return;
}
while (line-Top=V.size()) {
Top=V.size()-1;
}
if (Top<0) {
Top=0;
}
repaint();
}
public synchronized void down(final int n) {
Top-=n;
if (Top<0) {
Top=0;
}
repaint();
}
public synchronized void pageUp() {
up(PageSize-1);
repaint();
}
public synchronized void pageDown() {
down(PageSize-1);
repaint();
}
/**
* Set the vertical position. Used by the scrollbars in the Lister.
*
* @param x
* percentage of text
*/
public synchronized void setVerticalPos(final double x) {
Top=(int) (x*V.size());
if (Top>=V.size()) {
Top=V.size()-1;
}
repaint();
}
/**
* Set the horizontal offset.
*
* @param x
* ofset in percent of 10 times the screen width
*/
public synchronized void setHorizontalPos(final double x) {
HOffset=(int) (x*10*W);
repaint();
}
/**
* Delete all items from the panel.
*/
public synchronized void clear() {
Selected.removeAllElements();
V.removeAllElements();
Top=0;
}
/**
* Make sure, the last element displays.
*/
public synchronized void showLast() {
ShowLast=true;
LD.getVerticalScrollBar().setValue(LD.getVerticalScrollBar().getMaximum());
}
// Mouse routines:
Vector VAL=new Vector(); // Vector of action listener
MyVector Selected=new MyVector(); // currently selected items
/**
* Determine if line sel is selected
*
* @param sel
* @return selected or not
*/
public synchronized boolean isSelected(final int sel) {
final Enumeration e=Selected.elements();
while (e.hasMoreElements()) {
final int n=((Integer) e.nextElement()).intValue();
if (n==sel) {
return true;
}
}
return false;
}
/**
* Toggle the line sel to be selected or not.
*
* @param sel
*/
public synchronized void toggleSelect(final int sel) {
final Enumeration e=Selected.elements();
while (e.hasMoreElements()) {
final Integer i=(Integer) e.nextElement();
if (i.intValue()==sel) {
Selected.removeElement(i);
return;
}
}
Selected.addElement(new Integer(sel));
}
/**
* Expand the selection to include sel and all elements in between.
*
* @param sel
*/
public synchronized void expandSelect(final int sel) { // compute maximal
// selected index
// below sel.
int max=-1;
Enumeration e=Selected.elements();
while (e.hasMoreElements()) {
final int i=((Integer) e.nextElement()).intValue();
if (i>max&&i=0) {
for (int i=max+1; i<=sel; i++) {
select(i);
}
return;
}
int min=V.size();
e=Selected.elements();
while (e.hasMoreElements()) {
final int i=((Integer) e.nextElement()).intValue();
if (isel) {
min=i;
}
}
if (min=V.size()) {
return;
}
final int sel=n+Top;
if (e.getClickCount()>=2) {
if (!MultipleSelection) {
Selected.removeAllElements();
}
select(sel);
} else if (MultipleSelection
&&(e.isControlDown()||EasyMultipleSelection||e.isShiftDown())) {
if (e.isControlDown()||EasyMultipleSelection) {
toggleSelect(sel);
} else if (e.isShiftDown()) {
expandSelect(sel);
}
} else {
Selected.removeAllElements();
Selected.addElement(new Integer(sel));
}
final Graphics g=getGraphics();
paint(g);
g.dispose();
if (e.getClickCount()>=2||ReportSingleClick) {
final Enumeration en=VAL.elements();
while (en.hasMoreElements()) {
((ActionListener) (en.nextElement())).actionPerformed(new ListerMouseEvent(LD, Name, e));
}
}
}
}
// @Override
// public Dimension getPreferredSize() {
// return new Dimension(200, 300);
// }
public synchronized Element getElementAt(final int n) {
return (Element) V.elementAt(n);
}
public synchronized void save(final PrintWriter o) {
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
final Element el=(Element) e.nextElement();
o.println(el.getElementString());
}
}
public void setListingBackground(final Color c) {
ListingBackground=c;
}
}