/******************************************************************************* * 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.draw.tools; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import com.cburch.draw.model.AbstractCanvasObject; import com.cburch.draw.model.CanvasObject; import com.cburch.draw.shapes.DrawAttr; import com.cburch.logisim.data.AbstractAttributeSet; import com.cburch.logisim.data.Attribute; import com.cburch.logisim.data.AttributeEvent; import com.cburch.logisim.data.AttributeListener; import com.cburch.logisim.data.AttributeSet; import com.cburch.logisim.util.EventSourceWeakSupport; import com.cburch.logisim.util.UnmodifiableList; public class DrawingAttributeSet implements AttributeSet, Cloneable { private class Restriction extends AbstractAttributeSet implements AttributeListener { private AbstractTool tool; private List<Attribute<?>> selectedAttrs; private List<Attribute<?>> selectedView; Restriction(AbstractTool tool) { this.tool = tool; updateAttributes(); } // // AttributeListener methods // public void attributeListChanged(AttributeEvent e) { fireAttributeListChanged(); } public void attributeValueChanged(AttributeEvent e) { if (selectedAttrs.contains(e.getAttribute())) { @SuppressWarnings("unchecked") Attribute<Object> attr = (Attribute<Object>) e.getAttribute(); fireAttributeValueChanged(attr, e.getValue(),e.getOldValue()); } updateAttributes(); } @Override protected void copyInto(AbstractAttributeSet dest) { DrawingAttributeSet.this.addAttributeListener(this); } @Override public List<Attribute<?>> getAttributes() { return selectedView; } @Override public <V> V getValue(Attribute<V> attr) { return DrawingAttributeSet.this.getValue(attr); } @Override public <V> void setValue(Attribute<V> attr, V value) { DrawingAttributeSet.this.setValue(attr, value); updateAttributes(); } private void updateAttributes() { List<Attribute<?>> toolAttrs; if (tool == null) { toolAttrs = Collections.emptyList(); } else { toolAttrs = tool.getAttributes(); } if (!toolAttrs.equals(selectedAttrs)) { selectedAttrs = new ArrayList<Attribute<?>>(toolAttrs); selectedView = Collections.unmodifiableList(selectedAttrs); DrawingAttributeSet.this.addAttributeListener(this); fireAttributeListChanged(); } } } static final List<Attribute<?>> ATTRS_ALL = UnmodifiableList .create(new Attribute<?>[] { DrawAttr.FONT, DrawAttr.ALIGNMENT, DrawAttr.PAINT_TYPE, DrawAttr.STROKE_WIDTH, DrawAttr.STROKE_COLOR, DrawAttr.FILL_COLOR, DrawAttr.TEXT_DEFAULT_FILL, DrawAttr.CORNER_RADIUS }); static final List<Object> DEFAULTS_ALL = Arrays.asList(new Object[] { DrawAttr.DEFAULT_FONT, DrawAttr.ALIGN_CENTER, DrawAttr.PAINT_STROKE, Integer.valueOf(1), Color.BLACK, Color.WHITE, Color.BLACK, Integer.valueOf(10) }); private EventSourceWeakSupport<AttributeListener> listeners; private List<Attribute<?>> attrs; private List<Object> values; public DrawingAttributeSet() { listeners = new EventSourceWeakSupport<AttributeListener>(); attrs = ATTRS_ALL; values = DEFAULTS_ALL; } public void addAttributeListener(AttributeListener l) { listeners.add(l); } public <E extends CanvasObject> E applyTo(E drawable) { AbstractCanvasObject d = (AbstractCanvasObject) drawable; // use a for(i...) loop since the attribute list may change as we go on for (int i = 0; i < d.getAttributes().size(); i++) { Attribute<?> attr = d.getAttributes().get(i); @SuppressWarnings("unchecked") Attribute<Object> a = (Attribute<Object>) attr; if (attr == DrawAttr.FILL_COLOR && this.containsAttribute(DrawAttr.TEXT_DEFAULT_FILL)) { d.setValue(a, this.getValue(DrawAttr.TEXT_DEFAULT_FILL)); } else if (this.containsAttribute(a)) { Object value = this.getValue(a); d.setValue(a, value); } } return drawable; } @Override public Object clone() { try { DrawingAttributeSet ret = (DrawingAttributeSet) super.clone(); ret.listeners = new EventSourceWeakSupport<AttributeListener>(); ret.values = new ArrayList<Object>(this.values); return ret; } catch (CloneNotSupportedException e) { return null; } } public boolean containsAttribute(Attribute<?> attr) { return attrs.contains(attr); } public AttributeSet createSubset(AbstractTool tool) { return new Restriction(tool); } public Attribute<?> getAttribute(String name) { for (Attribute<?> attr : attrs) { if (attr.getName().equals(name)) return attr; } return null; } public List<Attribute<?>> getAttributes() { return attrs; } @SuppressWarnings("unchecked") public <V> V getValue(Attribute<V> attr) { Iterator<Attribute<?>> ait = attrs.iterator(); Iterator<Object> vit = values.iterator(); while (ait.hasNext()) { Object a = ait.next(); Object v = vit.next(); if (a.equals(attr)) { return (V) v; } } return null; } public boolean isReadOnly(Attribute<?> attr) { return false; } public boolean isToSave(Attribute<?> attr) { return true; } public void removeAttributeListener(AttributeListener l) { listeners.remove(l); } public void setReadOnly(Attribute<?> attr, boolean value) { throw new UnsupportedOperationException("setReadOnly"); } public <V> void setValue(Attribute<V> attr, V value) { Iterator<Attribute<?>> ait = attrs.iterator(); ListIterator<Object> vit = values.listIterator(); while (ait.hasNext()) { Object a = ait.next(); vit.next(); if (a.equals(attr)) { vit.set(value); AttributeEvent e = new AttributeEvent(this, attr, value,null); for (AttributeListener listener : listeners) { listener.attributeValueChanged(e); } if (attr == DrawAttr.PAINT_TYPE) { e = new AttributeEvent(this); for (AttributeListener listener : listeners) { listener.attributeListChanged(e); } } return; } } throw new IllegalArgumentException(attr.toString()); } }