package iiuf.awt; import java.net.URL; import java.awt.Frame; import java.awt.Canvas; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.Color; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Button; import java.awt.Cursor; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentListener; import java.awt.event.AdjustmentEvent; import java.awt.ItemSelectable; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseListener; import java.awt.event.MouseEvent; import java.awt.event.AdjustmentListener; import java.awt.event.AdjustmentEvent; import java.awt.Scrollbar; import java.util.Vector; import java.util.Hashtable; import iiuf.db.Proxy; import iiuf.util.Util; import iiuf.util.CacheArray; import iiuf.util.CacheArrayBackEnd; import iiuf.util.EventListenerList; /** Database table view implementation. (c) 1999, 2000, 2001, IIUF, DIUF<p> @author $Author: ohitz $ @version $Name: $ $Revision: 1.1 $ */ public class TableView extends Canvas implements AdjustmentListener, ItemSelectable, FindListener { private final static int MIN_COL_SIZE = 10; private final static int DEF_COL_SIZE = 50; private Proxy req; private int relop; private int txt_height = -1; private int start; private CacheArray cache; private String[] columns; private int[] column_starts; private Vector columns_v; private EventListenerList listeners = new EventListenerList(); private int dragX; private int dragCol; private int oldX; private Hashtable labels = new Hashtable(); private int evt_id; private boolean absNav; private int limit = Integer.MAX_VALUE; public TableView(Proxy req, int relop) { this(req, relop, null); } public TableView(Proxy req, int relop, String[] columns_) { cache = new CacheArray(128, new CacheArrayBackEnd() { public int chunkSize() {return 1;} public int maxChunks() {return 25;} public void read(long start, Object[] data, int idx, int count) { try { Proxy[] resp = TableView.this.req.find((int)start, count, TableView.this.relop); for(int i = 0; i < resp.length; i++) data[idx++] = resp[i]; } catch(Exception e) { e.printStackTrace(); } } public void write(long start, Object[] data, int idx, int count) {} }); setRequest(req, relop); addMouseListener(new MouseListener() { public void mouseClicked(MouseEvent e) { int id = getItemIdx(e.getY()); if(id < 0) return; ItemEvent ev = new ItemEvent(TableView.this, 0, cache.elementAt(id), ItemEvent.SELECTED); ItemListener[] l = (ItemListener[])listeners.getListeners(ItemListener.class); for(int i = 0; i < l.length; i++) l[i].itemStateChanged(ev); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} }); addMouseMotionListener(new MouseMotionListener() { Cursor crsr = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); public void mouseDragged(MouseEvent e) { if(dragCol > 0) { int x = e.getX(); int clipX = column_starts[dragCol]; Cursor ncrsr = Cursor.getPredefinedCursor(x - TableView.this.oldX < 0 ? Cursor.W_RESIZE_CURSOR : Cursor.E_RESIZE_CURSOR); TableView.this.oldX = x; for(int i = dragCol; i < column_starts.length; i++) { column_starts[i] += x - dragX; if(column_starts[i] - column_starts[i - 1] < MIN_COL_SIZE) column_starts[i] = column_starts[i - 1] + MIN_COL_SIZE; } if(ncrsr != crsr) { crsr = ncrsr; setCursor(crsr); } dragX = column_starts[dragCol]; Dimension size = getSize(); if(dragX < clipX) clipX = dragX; repaint(clipX, 0, size.width - x, size.height); } } public void mouseMoved(MouseEvent e) { Cursor ncrsr = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); int x = e.getX(); boolean dir = x - TableView.this.oldX < 0; TableView.this.oldX = x; TableView.this.dragCol = -1; for(int i = 0; i < column_starts.length; i++) if(x > (column_starts[i] - 5) && x < (column_starts[i] + 5)) { ncrsr = Cursor.getPredefinedCursor(dir ? Cursor.W_RESIZE_CURSOR : Cursor.E_RESIZE_CURSOR); TableView.this.dragX = x; TableView.this.dragCol = i; break; } if(ncrsr != crsr) { crsr = ncrsr; setCursor(crsr); } } }); if(columns_ != null) for(int i = 0; i < columns_.length; i++) addColumn(columns_[i]); } public void setAbsNav() { absNav = true; } public void setRelNav() { absNav = false; } public void adjustmentValueChanged(AdjustmentEvent e) { if(absNav) setStart(e.getValue()); else addStart(e.getValue()); } public Dimension getMinimumSize() { return new Dimension(columns_v.size() * MIN_COL_SIZE, 100); } public Dimension getPreferredSize() { if(column_starts.length > 0) return new Dimension(column_starts[column_starts.length - 1] + DEF_COL_SIZE, 200); else return new Dimension(0, 0); } public void addItemListener(ItemListener listener) { listeners.add(ItemListener.class, listener); } public void addItemListener(ItemListener listener, boolean weak) { listeners.add(ItemListener.class, listener, weak); } public void removeItemListener(ItemListener listener) { listeners.remove(ItemListener.class, listener); } public Object[] getSelectedObjects() { return null; } public synchronized void addColumn(String column) { addColumn(column, column); } public synchronized void addColumn(String column, String label) { columns_v.addElement(column); labels.put(column, label); updateColumns(); } public synchronized void removeColumn(String column) { columns_v.removeElement(column); labels.remove(column); updateColumns(); } private void updateColumns() { columns = new String[columns_v.size()]; column_starts = new int[columns.length]; for(int i = 0; i < columns.length; i++) { columns[i] = (String)columns_v.elementAt(i); if(column_starts[i] < MIN_COL_SIZE) column_starts[i] = i == 0 ? 0 : column_starts[i - 1] + DEF_COL_SIZE; } } public void find(Proxy proxy, int relop_) { req = proxy; relop = relop_; cache.flush(); cache.clear(); limit = Integer.MAX_VALUE; setStart(0, true); } public synchronized void setRequest(Proxy req_, int relop_) { req = req_; relop = relop_; cache.flush(); cache.clear(); columns_v = new Vector(); limit = Integer.MAX_VALUE; updateColumns(); setStart(0, true); } public void update(Graphics g) { paint(g); } private int getItemIdx(int y) { return y < txt_height ? -1 : start -1 + y / txt_height; } public synchronized void paint(Graphics g) { txt_height = g.getFontMetrics().getHeight(); int asc = g.getFontMetrics().getAscent(); Rectangle clip = g.getClipBounds(); Object[] range = cache.elementsAt(start, (clip.y + clip.height) / txt_height); // draw rectangles g.setColor(Color.white); g.fillRect(clip.x, 0, clip.width, txt_height); for(int row = 1; row <= range.length; row++) { g.setColor(((start + row ) & 1) == 1 ? Color.lightGray : Color.white); g.fillRect(clip.x, txt_height * row, clip.width, txt_height); } // draw h-line g.setColor(Color.black); g.drawLine(clip.x, txt_height, clip.x + clip.width, txt_height); // draw columns asc += txt_height; for(int col = 0; col < columns.length; col++) { int x = column_starts[col]; g.setClip(clip.x, clip.y, clip.width, clip.height); g.clipRect(x, 0, ((col + 1 < columns.length) ? column_starts[col + 1] : x + clip.width) - x, clip.height); // draw v-line g.drawLine(x, 0, x, clip.y + clip.height); // draw title g.drawString(columns[col], x + 2, asc - txt_height); // draw column for(int row = 0; row < range.length; row++) if(range[row] != null) { try { g.drawString(((Proxy)range[row]).getField(columns[col]).stringValue(0), x + 2, txt_height * row + asc); } catch(Exception e) { e.printStackTrace(); } } else { if(limit == Integer.MAX_VALUE) limit = start + row - 1; break; } } } public synchronized final void addStart(int amount) { setStart(start + amount); } public final void setStart(int start) { setStart(start, false); } private synchronized final void setStart(int start_, boolean repaint) { if(start_ < 0) start_ = 0; if(start_ > limit) start_ = limit; if(start_ != start || repaint) { start = start_; repaint(); } } public synchronized final int getStart() { return start; } static TableView tv; public static void main(String[] argv) { try { Proxy p = (Proxy)Class.forName(argv[1]).getConstructor(new Class[] {iiuf.db.Connection.class}).newInstance(new Object[] {new iiuf.db.fmpro.Connection(new URL(argv[0]))}); tv = new TableView(p, Proxy.AND); for(int i = 2; i < argv.length; i++) tv.addColumn(argv[i]); tv.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { System.out.println(e.getItem()); } }); ActionListener bh = new ActionListener() { public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("UP")) tv.addStart(+1); else if(e.getActionCommand().equals("DOWN")) tv.addStart(-1); } }; Frame f = new Frame(); Scrollbar sb = new Scrollbar(Scrollbar.VERTICAL, 0, 10, 0, 437); sb.addAdjustmentListener(new AdjustmentListener() { public void adjustmentValueChanged(AdjustmentEvent e) { tv.setStart(e.getValue()); } }); f.setLayout(new GridBagLayout()); f.add(tv, Awt.constraints(false, GridBagConstraints.BOTH)); f.add(sb, Awt.constraints(true, GridBagConstraints.VERTICAL)); f.pack(); f.setVisible(true); } catch(Exception e) { e.printStackTrace(); System.exit(1); } } } /* $Log: TableView.java,v $ Revision 1.1 2002/07/11 09:20:36 ohitz Initial checkin Revision 1.7 2001/01/12 08:26:20 schubige TJGUI update and some TreeView bug fixes Revision 1.6 2001/01/04 16:28:29 schubige Header update for 2001 and DIUF Revision 1.5 2001/01/03 15:23:50 schubige graph stuff beta Revision 1.4 2000/01/11 09:36:50 schubige added voter stuff Revision 1.3 1999/11/26 10:00:41 schubige updated for new awt package Revision 1.2 1999/11/26 09:14:29 schubige intermediate commit Revision 1.1 1999/11/26 08:51:16 schubige *** empty log message *** */