package NET.worlds.scape; import NET.worlds.console.Console; import NET.worlds.console.DialogDisabled; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Panel; import java.awt.Point; import java.util.Vector; public class TabbedPanel extends Panel implements ClickEventHandler, DialogDisabled { private Vector entries = new Vector(); private int rows; private int itemWidth; private int itemHeight; private int itemsPerRow; private int choice; private Font nFont; private FontMetrics nFontMetrics; private Font bFont; private FontMetrics bFontMetrics; private int fontHeight; private TabbedDisplayPanel disp = new TabbedDisplayPanel(); private ClickEventHandler handler; private boolean needRecalc; private boolean isDialogDisabled; public TabbedPanel(ClickEventHandler handler) { this.handler = handler; this.setLayout(new BorderLayout()); this.add("Center", this.disp); } public TabbedPanel() { this(null); this.handler = this; } public void addItem(String name, Component c) { this.entries.addElement(name); this.needRecalc = true; this.repaint(); this.disp.addItem(c); } public void insertItem(int index, String name, Component c) { this.entries.insertElementAt(name, index); this.disp.insertItem(index, c); if (index <= this.choice) { this.choice = Math.min(this.choice + 1, this.entries.size() - 1); } this.needRecalc = true; this.repaint(); } public void removeItem(int index) { this.entries.removeElementAt(index); this.disp.removeItem(index); if (index == this.choice) { int count = this.entries.size(); if (count > 0) { this.choice = Math.min(this.choice, count - 1); this.disp.setChoice(this.choice); } } else if (index < this.choice) { this.choice--; } this.needRecalc = true; this.repaint(); } public void select(int index) { this.choice = index; this.repaint(); this.disp.setChoice(index); } public String getName(int index) { return (String)this.entries.elementAt(index); } public void setName(int index, String name) { this.entries.setElementAt(name, index); this.needRecalc = true; this.repaint(); } @Override public Component getComponent(int index) { return index < this.entries.size() ? this.disp.getComponent(index) : null; } public int selected() { return this.choice; } public int itemAt(Point p) { if (!this.needRecalc) { Point tab = new Point(0, 0); int count = this.entries.size(); for (int i = 0; i < count; i++) { this.getPosition(i, tab); if (p.x >= tab.x && p.y >= tab.y && p.x < tab.x + this.itemWidth && p.y < tab.y + this.itemHeight) { return i; } } } return -1; } @Override public void addNotify() { super.addNotify(); this.nFont = new Font(Console.message("NotifyFont"), 0, 13); this.nFontMetrics = this.getFontMetrics(this.nFont); this.bFont = new Font(Console.message("NotifyFont"), 1, 14); this.bFontMetrics = this.getFontMetrics(this.bFont); this.fontHeight = Math.max(this.nFontMetrics.getHeight(), this.bFontMetrics.getHeight()); this.itemHeight = this.fontHeight + 5; } @Override public Insets insets() { if (this.needRecalc) { this.recalc(); } return new Insets(this.rows * this.itemHeight, 0, 0, 0); } @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); this.needRecalc = true; this.repaint(); } private void recalc() { int row = 0; int itemsOnRow = 0; int x = 0; int count = this.entries.size(); this.itemWidth = 0; for (int i = 0; i < count; i++) { String name = (String)this.entries.elementAt(i); int w = Math.max(this.bFontMetrics.stringWidth(name), this.nFontMetrics.stringWidth(" " + name + " ")); this.itemWidth = Math.max(w, this.itemWidth); } this.itemWidth += 4; this.itemsPerRow = Math.max(1, this.size().width / this.itemWidth); this.rows = (count + this.itemsPerRow - 1) / this.itemsPerRow; this.needRecalc = false; this.invalidate(); this.validate(); } private void getPosition(int entry, Point pos) { int count = this.entries.size(); int firstRow = this.choice / this.itemsPerRow; int entryRow = entry / this.itemsPerRow; int column = entry - entryRow * this.itemsPerRow; pos.x = column * this.itemWidth; pos.y = (this.rows - 1 - entryRow) * this.itemHeight - 2; } private static void vLine(Graphics g, int x1, int y1, int y2) { g.drawLine(x1, y1, x1, y2); } private static void hLine(Graphics g, int x1, int y1, int x2) { g.drawLine(x1, y1, x2, y1); } @Override public void paint(Graphics g) { if (this.needRecalc) { this.recalc(); } g.setColor(this.getBackground()); g.fillRect(0, 0, this.size().width, this.size().height); int count = this.entries.size(); if (count != 0) { Point p = new Point(0, 0); int maxWidth = this.itemWidth - 4; for (int i = 0; i < count; i++) { this.getPosition(i, p); String ent = (String)this.entries.elementAt(i); int x1 = p.x; int y1 = p.y + 4; int y2 = y1 + this.fontHeight; int yFont = y1; Font font = this.nFont; FontMetrics fm = this.nFontMetrics; boolean selected = i == this.choice; if (selected) { y1 = p.y + 2; y2 = y1 + this.fontHeight + 4; yFont = y1 + 1; font = this.bFont; fm = this.bFontMetrics; } int width = fm.stringWidth(ent); int spacing = (maxWidth - width) / 2; int x2 = x1 + maxWidth; g.setFont(font); g.setColor(this.getBackground().brighter()); if (selected) { hLine(g, 0, y2, x1); hLine(g, x2 + 3, y2, this.size().width); } vLine(g, x1, y2, y1 + 2); g.drawLine(x1, y1 + 2, x1 + 2, y1); hLine(g, x1 + 2, y1, x2); g.setColor(this.getBackground().darker()); vLine(g, x2 + 1, y1 + 1, y2); vLine(g, x2 + 2, y1 + 2, y2); g.setColor(this.getForeground()); g.drawString(ent, x1 + 1 + spacing, yFont + fm.getAscent() + fm.getLeading()); } } } @Override public void clickEvent(Component who, Point location, int flags) { } @Override public boolean mouseDown(java.awt.Event event, int x, int y) { Point p = new Point(x, y); int tmp = this.itemAt(p); if (tmp != -1) { this.choice = tmp; this.repaint(); this.disp.setChoice(this.choice); int flags = 1; if (event.metaDown()) { flags |= 4; } this.handler.clickEvent(this, p, flags); return true; } else { return false; } } @Override public boolean handleEvent(java.awt.Event event) { return this.isDialogDisabled ? false : super.handleEvent(event); } @Override public void dialogDisable(boolean disable) { this.isDialogDisabled = disable; Component c = this.getComponent(this.selected()); if (c != null && c instanceof DialogDisabled) { ((DialogDisabled)c).dialogDisable(disable); } } }