/******************************************************************************* * 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.Component; import java.awt.Window; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import com.bfh.logisim.hdlgenerator.HDLColorRenderer; import com.bfh.logisim.settings.Settings; import com.cburch.logisim.comp.ComponentFactory; import com.cburch.logisim.data.Attribute; import com.cburch.logisim.data.AttributeEvent; import com.cburch.logisim.data.AttributeListener; import com.cburch.logisim.data.AttributeSet; public abstract class AttributeSetTableModel implements AttrTableModel, AttributeListener { private class AttrRow implements AttrTableModelRow { private Attribute<Object> attr; AttrRow(Attribute<?> attr) { @SuppressWarnings("unchecked") Attribute<Object> objAttr = (Attribute<Object>) attr; this.attr = objAttr; } public Component getEditor(Window parent) { Object value = attrs.getValue(attr); return attr.getCellEditor(parent, value); } public String getLabel() { return attr.getDisplayName(); } public String getValue() { Object value = attrs.getValue(attr); if (value == null) { return ""; } else { try { String Str = attr.toDisplayString(value); if (Str.isEmpty()&&attr.getName().equals("label")&&CompInst!=null&&CompInst.RequiresNonZeroLabel()) return HDLColorRenderer.RequiredFieldString; return Str; } catch (Exception e) { return "???"; } } } public boolean isValueEditable() { return !attrs.isReadOnly(attr); } public void setValue(Object value) throws AttrTableSetException { Attribute<Object> attr = this.attr; if (attr == null || value == null) return; try { if (value instanceof String) { value = attr.parse((String) value); } setValueRequested(attr, value); } catch (ClassCastException e) { String msg = Strings.get("attributeChangeInvalidError") + ": " + e; throw new AttrTableSetException(msg); } catch (NumberFormatException e) { String msg = Strings.get("attributeChangeInvalidError"); String emsg = e.getMessage(); if (emsg != null && emsg.length() > 0) msg += ": " + emsg; msg += "."; throw new AttrTableSetException(msg); } } } private class HDLrow extends AttrRow { HDLrow(Attribute<?> attr) { super(attr); } @Override public String getLabel() { if (CompInst == null) return HDLColorRenderer.UnKnownString; if (CompInst.HDLSupportedComponent(Settings.VHDL, attrs)) return HDLColorRenderer.VHDLSupportString; return HDLColorRenderer.NoSupportString; } @Override public String getValue() { if (CompInst == null) return HDLColorRenderer.UnKnownString; if (CompInst.HDLSupportedComponent(Settings.VERILOG, attrs)) return HDLColorRenderer.VHDLSupportString; return HDLColorRenderer.NoSupportString; } @Override public boolean isValueEditable() { return false; } @Override public void setValue(Object value) { // Do Nothing } } private ArrayList<AttrTableModelListener> listeners; private AttributeSet attrs; private HashMap<Attribute<?>, AttrRow> rowMap; private ArrayList<AttrRow> rows; private ComponentFactory CompInst = null; public AttributeSetTableModel(AttributeSet attrs) { this.attrs = attrs; this.listeners = new ArrayList<AttrTableModelListener>(); this.rowMap = new HashMap<Attribute<?>, AttrRow>(); this.rows = new ArrayList<AttrRow>(); if (attrs != null) { /* put the vhdl/verilog row */ HDLrow rowd = new HDLrow(null); rows.add(rowd); for (Attribute<?> attr : attrs.getAttributes()) { if (!attr.isHidden()) { AttrRow row = new AttrRow(attr); rowMap.put(attr, row); rows.add(row); } } } } public void SetInstance(ComponentFactory fact) { CompInst = fact; } public void SetIsTool() { /* We remove the label attribute for a tool */ for (Attribute<?> attr : attrs.getAttributes()) { if (attr.getName().equals("label")) { AttrRow row = rowMap.get(attr); rowMap.remove(attr); rows.remove(row); } } } public void addAttrTableModelListener(AttrTableModelListener listener) { if (listeners.isEmpty() && attrs != null) { attrs.addAttributeListener(this); } listeners.add(listener); } // // AttributeListener methods // public void attributeListChanged(AttributeEvent e) { // if anything has changed, don't do anything int index = 0; boolean match = true; int rowsSize = rows.size(); for (Attribute<?> attr : attrs.getAttributes()) { if (!attr.isHidden()) { if (index >= rowsSize || rows.get(index).attr != attr) { match = false; break; } index++; } } if (match && index == rows.size()) return; // compute the new list of rows, possible adding into hash map ArrayList<AttrRow> newRows = new ArrayList<AttrRow>(); HashSet<Attribute<?>> missing = new HashSet<Attribute<?>>( rowMap.keySet()); /* put the vhdl/verilog row */ HDLrow rowd = new HDLrow(null); newRows.add(rowd); for (Attribute<?> attr : attrs.getAttributes()) { if (!attr.isHidden()) { AttrRow row = rowMap.get(attr); if (row == null) { row = new AttrRow(attr); rowMap.put(attr, row); } else { missing.remove(attr); } newRows.add(row); } } rows = newRows; for (Attribute<?> attr : missing) { rowMap.remove(attr); } fireStructureChanged(); } public void attributeValueChanged(AttributeEvent e) { Attribute<?> attr = e.getAttribute(); AttrTableModelRow row = rowMap.get(attr); if (row != null) { int index = rows.indexOf(row); if (index >= 0) { fireValueChanged(index); } } } protected void fireStructureChanged() { AttrTableModelEvent event = new AttrTableModelEvent(this); for (AttrTableModelListener l : listeners) { l.attrStructureChanged(event); } } protected void fireTitleChanged() { AttrTableModelEvent event = new AttrTableModelEvent(this); for (AttrTableModelListener l : listeners) { l.attrTitleChanged(event); } } protected void fireValueChanged(int index) { AttrTableModelEvent event = new AttrTableModelEvent(this, index); for (AttrTableModelListener l : listeners) { l.attrValueChanged(event); } } public AttributeSet getAttributeSet() { return attrs; } public AttrTableModelRow getRow(int rowIndex) { return rows.get(rowIndex); } public int getRowCount() { return rows.size(); } public abstract String getTitle(); public void removeAttrTableModelListener(AttrTableModelListener listener) { listeners.remove(listener); if (listeners.isEmpty() && attrs != null) { attrs.removeAttributeListener(this); } } public void setAttributeSet(AttributeSet value) { if (attrs != value) { if (!listeners.isEmpty()) { attrs.removeAttributeListener(this); } attrs = value; if (!listeners.isEmpty()) { attrs.addAttributeListener(this); } attributeListChanged(null); } } protected abstract void setValueRequested(Attribute<Object> attr, Object value) throws AttrTableSetException; }