/******************************************************************************* * This file is part of logisim-evolution. * * logisim-evolution is 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, either version 3 of the License, or * (at your option) any later version. * * logisim-evolution 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 logisim-evolution. If not, see <http://www.gnu.org/licenses/>. * * Original code by Carl Burch (http://www.cburch.com), 2011. * Subsequent modifications by : * + Haute École Spécialisée Bernoise * http://www.bfh.ch * + Haute École du paysage, d'ingénierie et d'architecture de Genève * http://hepia.hesge.ch/ * + Haute École d'Ingénierie et de Gestion du Canton de Vaud * http://www.heig-vd.ch/ * The project is currently maintained by : * + REDS Institute - HEIG-VD * Yverdon-les-Bains, Switzerland * http://reds.heig-vd.ch *******************************************************************************/ package com.cburch.logisim.tools; import java.awt.Color; import java.awt.Cursor; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import javax.swing.Icon; import com.cburch.logisim.circuit.Circuit; import com.cburch.logisim.circuit.CircuitEvent; import com.cburch.logisim.circuit.CircuitListener; import com.cburch.logisim.circuit.RadixOption; import com.cburch.logisim.circuit.Wire; import com.cburch.logisim.circuit.WireSet; import com.cburch.logisim.comp.Component; import com.cburch.logisim.comp.ComponentDrawContext; import com.cburch.logisim.comp.ComponentUserEvent; import com.cburch.logisim.data.AttributeSet; import com.cburch.logisim.data.Location; import com.cburch.logisim.data.Value; import com.cburch.logisim.gui.main.Canvas; import com.cburch.logisim.prefs.AppPreferences; import com.cburch.logisim.proj.Project; import com.cburch.logisim.util.Icons; public class PokeTool extends Tool { private class Listener implements CircuitListener { public void circuitChanged(CircuitEvent event) { Circuit circ = pokedCircuit; if (event.getCircuit() == circ && circ != null && (event.getAction() == CircuitEvent.ACTION_REMOVE || event .getAction() == CircuitEvent.ACTION_CLEAR) && !circ.contains(pokedComponent)) { removeCaret(false); } } } private static class WireCaret extends AbstractCaret { // Canvas canvas; Wire wire; int x; int y; WireCaret(Canvas c, Wire w, int x, int y, AttributeSet opts) { canvas = c; wire = w; this.x = x; this.y = y; // this.opts = opts; } @Override public void draw(Graphics g) { Value v = canvas.getCircuitState().getValue(wire.getEnd0()); RadixOption radix1 = RadixOption .decode(AppPreferences.POKE_WIRE_RADIX1.get()); RadixOption radix2 = RadixOption .decode(AppPreferences.POKE_WIRE_RADIX2.get()); if (radix1 == null) radix1 = RadixOption.RADIX_2; String vStr = radix1.toString(v); if (radix2 != null && v.getWidth() > 1) { vStr += " / " + radix2.toString(v); } FontMetrics fm = g.getFontMetrics(); g.setColor(caretColor); g.fillRect(x + 2, y + 2, fm.stringWidth(vStr) + 4, fm.getAscent() + fm.getDescent() + 4); g.setColor(Color.BLACK); g.drawRect(x + 2, y + 2, fm.stringWidth(vStr) + 4, fm.getAscent() + fm.getDescent() + 4); g.fillOval(x - 2, y - 2, 5, 5); g.drawString(vStr, x + 4, y + 4 + fm.getAscent()); } } private static final Icon toolIcon = Icons.getIcon("poke.gif"); private static final Color caretColor = new Color(255, 255, 150); private static Cursor cursor = Cursor .getPredefinedCursor(Cursor.HAND_CURSOR); private Listener listener; private Circuit pokedCircuit; private Component pokedComponent; private Caret pokeCaret; public PokeTool() { this.listener = new Listener(); } @Override public void deselect(Canvas canvas) { removeCaret(true); canvas.setHighlightedWires(WireSet.EMPTY); } @Override public void draw(Canvas canvas, ComponentDrawContext context) { if (pokeCaret != null) pokeCaret.draw(context.getGraphics()); } @Override public boolean equals(Object other) { return other instanceof PokeTool; } @Override public Cursor getCursor() { return cursor; } @Override public String getDescription() { return Strings.get("pokeToolDesc"); } @Override public String getDisplayName() { return Strings.get("pokeTool"); } @Override public String getName() { return "Poke Tool"; } @Override public int hashCode() { return PokeTool.class.hashCode(); } @Override public void keyPressed(Canvas canvas, KeyEvent e) { if (pokeCaret != null) { pokeCaret.keyPressed(e); canvas.getProject().repaintCanvas(); } } @Override public void keyReleased(Canvas canvas, KeyEvent e) { if (pokeCaret != null) { pokeCaret.keyReleased(e); canvas.getProject().repaintCanvas(); } } @Override public void keyTyped(Canvas canvas, KeyEvent e) { if (pokeCaret != null) { pokeCaret.keyTyped(e); canvas.getProject().repaintCanvas(); } } @Override public void mouseDragged(Canvas canvas, Graphics g, MouseEvent e) { if (pokeCaret != null) { pokeCaret.mouseDragged(e); canvas.getProject().repaintCanvas(); } } @Override public void mousePressed(Canvas canvas, Graphics g, MouseEvent e) { int x = e.getX(); int y = e.getY(); Location loc = Location.create(x, y); boolean dirty = false; canvas.setHighlightedWires(WireSet.EMPTY); if (pokeCaret != null && !pokeCaret.getBounds(g).contains(loc)) { dirty = true; removeCaret(true); } if (pokeCaret == null) { ComponentUserEvent event = new ComponentUserEvent(canvas, x, y); Circuit circ = canvas.getCircuit(); for (Component c : circ.getAllContaining(loc, g)) { if (pokeCaret != null) break; if (c instanceof Wire) { Caret caret = new WireCaret(canvas, (Wire) c, x, y, canvas .getProject().getOptions().getAttributeSet()); setPokedComponent(circ, c, caret); canvas.setHighlightedWires(circ.getWireSet((Wire) c)); } else { Pokable p = (Pokable) c.getFeature(Pokable.class); if (p != null) { Caret caret = p.getPokeCaret(event); setPokedComponent(circ, c, caret); AttributeSet attrs = c.getAttributeSet(); if (attrs != null && attrs.getAttributes().size() > 0) { Project proj = canvas.getProject(); proj.getFrame().viewComponentAttributes(circ, c); } } } } } if (pokeCaret != null) { dirty = true; pokeCaret.mousePressed(e); } if (dirty) canvas.getProject().repaintCanvas(); } @Override public void mouseReleased(Canvas canvas, Graphics g, MouseEvent e) { if (pokeCaret != null) { pokeCaret.mouseReleased(e); canvas.getProject().repaintCanvas(); } } @Override public void paintIcon(ComponentDrawContext c, int x, int y) { Graphics g = c.getGraphics(); if (toolIcon != null) { toolIcon.paintIcon(c.getDestination(), g, x + 2, y + 2); } else { g.setColor(java.awt.Color.black); g.drawLine(x + 4, y + 2, x + 4, y + 17); g.drawLine(x + 4, y + 17, x + 1, y + 11); g.drawLine(x + 4, y + 17, x + 7, y + 11); g.drawLine(x + 15, y + 2, x + 15, y + 17); g.drawLine(x + 15, y + 2, x + 12, y + 8); g.drawLine(x + 15, y + 2, x + 18, y + 8); } } private void removeCaret(boolean normal) { Circuit circ = pokedCircuit; Caret caret = pokeCaret; if (caret != null) { if (normal) caret.stopEditing(); else caret.cancelEditing(); circ.removeCircuitListener(listener); pokedCircuit = null; pokedComponent = null; pokeCaret = null; } } private void setPokedComponent(Circuit circ, Component comp, Caret caret) { removeCaret(true); pokedCircuit = circ; pokedComponent = comp; pokeCaret = caret; if (caret != null) { circ.addCircuitListener(listener); } } }