diff options
| author | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-02-12 22:33:32 -0800 |
| commit | c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch) | |
| tree | df9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/console/TreePanel.java | |
| download | worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip | |
Initial commit
Diffstat (limited to 'NET/worlds/console/TreePanel.java')
| -rw-r--r-- | NET/worlds/console/TreePanel.java | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/NET/worlds/console/TreePanel.java b/NET/worlds/console/TreePanel.java new file mode 100644 index 0000000..3737f20 --- /dev/null +++ b/NET/worlds/console/TreePanel.java @@ -0,0 +1,315 @@ +package NET.worlds.console; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Event; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Scrollbar; +import java.util.Vector; + +public class TreePanel extends ExposedPanel implements DialogDisabled { + private static final long serialVersionUID = -5534860983354876334L; + private Vector<TreeNode> items = new Vector<TreeNode>(); + private boolean delayRepaints; + private boolean needRepaint; + private boolean needRecalc; + private boolean needMakeVisible; + private Scrollbar scrollbar = new WiderScrollbar(); + private int scrollPos = 0; + private int linesVisible; + private int selectedIndex = -1; + private boolean hasFocus = true; + private Font nFont = new Font(Console.message("TreeFont"), 0, 13); + private FontMetrics nFontMetrics = this.getFontMetrics(this.nFont); + private Font bFont = new Font(Console.message("TreeFont"), 1, 11); + private FontMetrics bFontMetrics = this.getFontMetrics(this.bFont); + private int fontHeight = Math.max(this.nFontMetrics.getHeight(), this.bFontMetrics.getHeight()); + private int itemHeight = this.fontHeight; + private boolean isDialogDisabled; + private static final int[] cxs = new int[]{0, 0, 6}; + private static final int[] cys = new int[]{6, -6, 0}; + private MoveablePolygon closedIcon = new MoveablePolygon(cxs, cys); + private static final int[] oxs = new int[]{-5, 6, 0}; + private static final int[] oys = new int[]{0, 0, 6}; + private MoveablePolygon openedIcon = new MoveablePolygon(oxs, oys); + private static final Color normBGColor = new Color(80, 80, 80); + private static final Color normFGColor = new Color(190, 190, 190); + private static final Color selFGColor = new Color(255, 255, 175); + private static final int indentPixels = 14; + + public TreePanel() { + this.setBackground(normBGColor); + this.setLayout(new BorderLayout()); + this.add("East", this.scrollbar); + this.scrollbar.hide(); + } + + public synchronized void delayRepaints(boolean state) { + if (!(this.delayRepaints = state)) { + if (this.needRecalc) { + this.recalc(); + } + + if (this.needMakeVisible) { + this.makeVisible(this.selectedIndex); + } + + if (this.needRepaint) { + this.repaint(); + } + } + } + + private synchronized void needRepaint(boolean needRecalc, boolean needMakeVisible) { + this.needRepaint = true; + this.needRecalc |= needRecalc; + this.needMakeVisible |= needMakeVisible; + this.delayRepaints(this.delayRepaints); + } + + public synchronized int getSelectedIndex() { + return this.selectedIndex; + } + + public synchronized void select(int item) { + this.selectedIndex = item; + this.needRepaint(false, true); + } + + public void setFocus(boolean hasFocus) { + if (this.hasFocus != hasFocus) { + this.hasFocus = hasFocus; + this.needRepaint(false, false); + } + } + + @Override + public boolean hasFocus() { + return this.hasFocus; + } + + @Override + public synchronized void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + this.needRepaint(true, false); + } + + public synchronized TreeNode getSelectedNode() { + return this.selectedIndex != -1 ? this.items.elementAt(this.selectedIndex) : null; + } + + public synchronized void reset(Vector<TreeNode> items) { + this.items = items; + this.needRepaint(true, false); + } + + public synchronized void removeAllElements() { + this.items.removeAllElements(); + this.needRepaint(true, false); + } + + public synchronized void insertElementAt(TreeNode ele, int index) { + this.items.insertElementAt(ele, index); + this.needRepaint(true, false); + } + + public synchronized void removeElementAt(int index) { + this.items.removeElementAt(index); + this.needRepaint(true, false); + } + + public synchronized void addElement(TreeNode ele) { + this.items.addElement(ele); + this.needRepaint(true, false); + } + + public int countElements() { + return this.items.size(); + } + + public TreeNode elementAt(int index) { + return this.items.elementAt(index); + } + + public TreeNode elementAt(Point p) { + int item = this.scrollPos + p.y / this.itemHeight; + return item < this.items.size() ? this.items.elementAt(item) : null; + } + + private void makeVisible(int item) { + int count = this.items.size(); + if (count > this.linesVisible && (item < this.scrollPos || item >= this.scrollPos + this.linesVisible)) { + this.setScrollValue(Math.min(item * this.itemHeight, this.scrollbar.getMaximum())); + } + + this.needMakeVisible = false; + } + + private void add(GridBagLayout gbag, Component comp, GridBagConstraints c) { + gbag.setConstraints(comp, c); + this.add(comp); + } + + public synchronized void recalc() { + int height = this.getSize().height; + this.linesVisible = Math.max(1, height / this.itemHeight); + int count = this.items.size(); + if (count > this.linesVisible) { + if (!this.scrollbar.isVisible()) { + this.scrollbar.setVisible(true); + this.validate(); + } + + this.scrollbar.setValues(this.scrollPos * this.itemHeight, this.linesVisible * this.itemHeight, 0, count * this.itemHeight); + this.scrollbar.setPageIncrement(this.linesVisible * this.itemHeight); + this.scrollbar.setLineIncrement(this.itemHeight); + } else { + if (this.scrollbar.isVisible()) { + this.scrollbar.hide(); + this.validate(); + } + + this.scrollPos = 0; + } + + this.needRecalc = false; + } + + @Override + public synchronized void paint(Graphics g) { + super.paint(g); + int width = this.getSize().width; + int height = this.getSize().height; + int count = this.items.size(); + int y = 0; + + for (int i = this.scrollPos; i < count; i++) { + TreeNode node = this.elementAt(i); + String name = node.toString(); + boolean isTitle = node.displayAsTitle(); + Font font = this.nFont; + FontMetrics metrics = this.nFontMetrics; + if (isTitle) { + font = this.bFont; + metrics = this.bFontMetrics; + } + + g.setFont(font); + int ascent = metrics.getAscent(); + int x = node.getLevel() * 14; + g.setColor(normFGColor); + if (node.isOpen()) { + this.openedIcon.drawFilled(g, x + 5, y + ascent - 5); + } else { + this.closedIcon.drawFilled(g, x + 5, y + ascent - 5); + } + + if (i == this.selectedIndex) { + g.setColor(selFGColor); + } + + g.drawString(name, x + 11 + 5, y + ascent); + if (i == this.selectedIndex && this.hasFocus) { + g.drawRect(x + 11 + 3, y, metrics.stringWidth(name) + 3, this.itemHeight); + } + + y += this.itemHeight; + if (y >= height) { + break; + } + } + + this.needRepaint = false; + } + + @Override + public boolean handleEvent(Event e) { + if (this.isDialogDisabled) { + return false; + } else { + switch (e.id) { + case 601: + return this.scrollLineUp(); + case 602: + return this.scrollLineDown(); + case 603: + return this.scrollPageUp(); + case 604: + return this.scrollPageDown(); + case 605: + return this.scrollAbsolute(); + default: + return super.handleEvent(e); + } + } + } + + @Override + public void dialogDisable(boolean disable) { + this.isDialogDisabled = disable; + } + + @Override + public synchronized boolean mouseDown(Event e, int x, int y) { + this.setFocus(true); + int item = this.scrollPos + y / this.itemHeight; + if (item >= 0 && item < this.items.size()) { + if (e.clickCount == 1) { + this.treeSelect(item); + int yStart = y / this.itemHeight * this.itemHeight; + TreeNode node = this.elementAt(item); + MoveablePolygon widget = node.isOpen() ? this.openedIcon : this.closedIcon; + FontMetrics metrics = node.displayAsTitle() ? this.nFontMetrics : this.bFontMetrics; + widget.moveTo(node.getLevel() * 14 + 5, yStart + metrics.getAscent() - 5); + if (widget.getBoundingBox().inside(x, y)) { + this.treeOpen(item); + } + } else { + this.treeOpen(item); + } + } + + return true; + } + + public void treeSelect(int item) { + } + + public void treeOpen(int item) { + } + + private boolean setScrollValue(int value) { + value = Math.max(this.scrollbar.getMinimum(), value); + value = Math.min(this.scrollbar.getMaximum(), value); + this.scrollPos = value / this.itemHeight; + this.scrollbar.setValue(this.scrollPos * this.itemHeight); + this.needRepaint(false, false); + return true; + } + + private boolean scrollLineUp() { + return this.setScrollValue(this.scrollPos * this.itemHeight - this.scrollbar.getLineIncrement()); + } + + private boolean scrollLineDown() { + return this.setScrollValue(this.scrollPos * this.itemHeight + this.scrollbar.getLineIncrement()); + } + + private boolean scrollPageUp() { + return this.setScrollValue(this.scrollPos * this.itemHeight - this.scrollbar.getPageIncrement()); + } + + private boolean scrollPageDown() { + return this.setScrollValue(this.scrollPos * this.itemHeight + this.scrollbar.getPageIncrement()); + } + + private boolean scrollAbsolute() { + return this.setScrollValue(this.scrollbar.getValue()); + } +} |