/******************************************************************************* * 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.gui.generic; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.AbstractSpinnerModel; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JSpinner; public class ZoomControl extends JPanel { private class GridIcon extends JComponent implements MouseListener, PropertyChangeListener { private static final long serialVersionUID = 1L; boolean state = true; public GridIcon() { addMouseListener(this); setPreferredSize(new Dimension(15, 15)); setToolTipText(""); setFocusable(true); } @Override public String getToolTipText(MouseEvent e) { return Strings.get("zoomShowGrid"); } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { model.setShowGrid(!state); } public void mouseReleased(MouseEvent e) { } @Override protected void paintComponent(Graphics g) { int width = getWidth(); int height = getHeight(); g.setColor(state ? Color.black : getBackground().darker()); int dim = (Math.min(width, height) - 4) / 3 * 3 + 1; int xoff = (width - dim) / 2; int yoff = (height - dim) / 2; for (int x = 0; x < dim; x += 3) { for (int y = 0; y < dim; y += 3) { g.drawLine(x + xoff, y + yoff, x + xoff, y + yoff); } } } public void propertyChange(PropertyChangeEvent evt) { update(); } private void update() { boolean grid = model.getShowGrid(); if (grid != state) { state = grid; repaint(); } } } private class SpinnerModel extends AbstractSpinnerModel implements PropertyChangeListener { private static final long serialVersionUID = 1L; public Object getNextValue() { double zoom = model.getZoomFactor(); double[] choices = model.getZoomOptions(); double factor = zoom * 100.0 * 1.001; for (int i = 0; i < choices.length; i++) { if (choices[i] > factor) return toString(choices[i]); } return null; } public Object getPreviousValue() { double zoom = model.getZoomFactor(); double[] choices = model.getZoomOptions(); double factor = zoom * 100.0 * 0.999; for (int i = choices.length - 1; i >= 0; i--) { if (choices[i] < factor) return toString(choices[i]); } return null; } public Object getValue() { double zoom = model.getZoomFactor(); return toString(zoom * 100.0); } public void propertyChange(PropertyChangeEvent evt) { fireStateChanged(); } public void setValue(Object value) { if (value instanceof String) { String s = (String) value; if (s.endsWith("%")) s = s.substring(0, s.length() - 1); s = s.trim(); try { double zoom = Double.parseDouble(s) / 100.0; model.setZoomFactor(zoom); } catch (NumberFormatException e) { } } } private String toString(double factor) { if (factor > 10) { return (int) (factor + 0.5) + "%"; } else if (factor > 0.1) { return (int) (factor * 100 + 0.5) / 100.0 + "%"; } else { return factor + "%"; } } } private static final long serialVersionUID = 1L; private ZoomModel model; private JSpinner spinner; private SpinnerModel spinnerModel; private GridIcon grid; public ZoomControl(ZoomModel model) { super(new BorderLayout()); this.model = model; spinnerModel = new SpinnerModel(); spinner = new JSpinner(); spinner.setModel(spinnerModel); this.add(spinner, BorderLayout.CENTER); grid = new GridIcon(); this.add(grid, BorderLayout.EAST); grid.update(); model.addPropertyChangeListener(ZoomModel.SHOW_GRID, grid); model.addPropertyChangeListener(ZoomModel.ZOOM, spinnerModel); } public void setZoomModel(ZoomModel value) { ZoomModel oldModel = model; if (oldModel != value) { if (oldModel != null) { oldModel.removePropertyChangeListener(ZoomModel.SHOW_GRID, grid); oldModel.removePropertyChangeListener(ZoomModel.ZOOM, spinnerModel); } model = value; spinnerModel = new SpinnerModel(); spinner.setModel(spinnerModel); grid.update(); if (value != null) { value.addPropertyChangeListener(ZoomModel.SHOW_GRID, grid); value.addPropertyChangeListener(ZoomModel.ZOOM, spinnerModel); } } } }