package shipmaker.render; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.util.List; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import render.FocusableOverlay; import render.MouseEventType; import render.OverlayManager; import render.RenderNode; import render.RenderPreferences; import render.XYTRenderNode; import shipmaker.CatalogPartType; import shipmaker.EditorShip; import shipmaker.catalog.PartCatalog; public class CatalogSelector extends XYTRenderNode implements FocusableOverlay { private List<CatalogPartType> types; private int scrollPoint; private OverlayManager om; private CatalogPartType selectedType; private EditorShip ship; private static final int ROW_HEIGHT = 15; private static final int ROWS = 8; private static final int VPADDING = 10; private static final int WIDTH = 200; private class TypeRow extends XYTRenderNode { private int position; public TypeRow(int position) { super(0, ROW_HEIGHT * position, 0); this.position = position; } private CatalogPartType representedType() { int index = position + scrollPoint; if (index >=0 && index < types.size()) { return types.get(index); } return null; } public void draw(Graphics2D g, RenderPreferences prefs) { boolean selected = selectedType == representedType(); g.setColor(Color.white); g.setFont(new Font("SansSerif", Font.BOLD, 14)); int index = position + scrollPoint; if (index >=0 && index < types.size()) { if (selected) { g.fillRoundRect(0, 0, WIDTH, ROW_HEIGHT, 8, 8); g.setColor(prefs.spaceColor()); } g.drawString(types.get(index).name(), VPADDING, ROW_HEIGHT-2); } } public boolean interacted(AffineTransform root, MouseEvent e, MouseEventType t) { if (t != MouseEventType.MOUSE_PRESS) return false; Point2D.Float src = new Point2D.Float(); src.setLocation(e.getX(), e.getY()); try { root.invert(); } catch (NoninvertibleTransformException e1) { e1.printStackTrace(); } Point2D dest = new Point2D.Float(); root.transform(src, dest); if (dest.getY() >=0 && dest.getY()<=ROW_HEIGHT && dest.getX() > 0 && dest.getX() < WIDTH) { selectedType = representedType(); om.setFocused(CatalogSelector.this); return true; } return false; } } public CatalogSelector(OverlayManager om, EditorShip es) { super(0, -(ROWS * ROW_HEIGHT), 0); this.ship = es; scrollPoint = 0; types = PartCatalog.allTypes(); XYTRenderNode list = new XYTRenderNode(0, 0, 0); for (int i=0; i<ROWS; i++) { list.addChild(new TypeRow(i)); } addChild(list); XYTRenderNode preview = new XYTRenderNode(WIDTH + (ROWS*ROW_HEIGHT-40)/2, (ROWS*ROW_HEIGHT+40)/2, 0) { public void draw(Graphics2D g, RenderPreferences prefs) { if (selectedType!=null) { g.setColor(Color.white); g.setStroke(new BasicStroke(2)); g.setFont(new Font("SansSerif", Font.BOLD, 12)); g.drawString("Add", -10, 35); int w = ROWS*ROW_HEIGHT-40; g.drawRoundRect(-w/2, -w/2, w, w, 8, 8); selectedType.preview(g, prefs); } } public boolean interacted(AffineTransform root, MouseEvent e, MouseEventType t) { if (e.getButton() == MouseEvent.BUTTON1 && t == MouseEventType.MOUSE_PRESS) { Point2D.Float pt = RenderNode.reverse(root, e); int w = ROWS*ROW_HEIGHT-40; if (Math.abs(pt.getX()) < w/2 && Math.abs(pt.getY()) < w/2) { ship.addPart(selectedType); selectedType = null; return true; } } return false; } }; addChild(preview); addChild(new XYTRenderNode(WIDTH+10, 10, 0) { public void draw(Graphics2D g, RenderPreferences prefs) { g.setStroke(new BasicStroke(2)); g.setColor(Color.white); g.drawRoundRect(-10, -10, 20, 20, 8, 8); g.drawLine(-5, 0, 0, -5); g.drawLine(5, 0, 0, -5); } public boolean interacted(AffineTransform root, MouseEvent e, MouseEventType t) { if (e.getButton() == MouseEvent.BUTTON1 && t == MouseEventType.MOUSE_PRESS) { Point2D.Float pt = RenderNode.reverse(root, e); if (Math.abs(pt.getX()) < 10 && Math.abs(pt.getY()) < 10) { scroll(-1); return true; } } return false; } }); addChild(new XYTRenderNode(WIDTH+10, 30, 0) { public void draw(Graphics2D g, RenderPreferences prefs) { g.setStroke(new BasicStroke(2)); g.setColor(Color.white); g.drawRoundRect(-10, -10, 20, 20, 8, 8); g.drawLine(-5, 0, 0, 5); g.drawLine(5, 0, 0, 5); } public boolean interacted(AffineTransform root, MouseEvent e, MouseEventType t) { if (e.getButton() == MouseEvent.BUTTON1 && t == MouseEventType.MOUSE_PRESS) { Point2D.Float pt = RenderNode.reverse(root, e); if (Math.abs(pt.getX()) < 10 && Math.abs(pt.getY()) < 10) { scroll(1); return true; } } return false; } }); this.om = om; } private void scroll(int dist) { scrollPoint += dist; } public void draw(Graphics2D g, RenderPreferences prefs) { g.setColor(Color.white); g.setStroke(new BasicStroke(2)); g.drawRoundRect(0, 0, WIDTH, ROWS*ROW_HEIGHT, 8, 8); g.setFont(new Font("SansSerif", Font.BOLD, 16)); g.drawString("Part Blueprints", 10, -4); } public void lostFocus() { selectedType = null; } }