/* * Copyright 2003-2010 Tufts University Licensed under the * Educational Community License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ package tufts.vue; import java.util.List; import java.util.Iterator; import java.util.ArrayList; import java.util.Vector; import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.table.*; import tufts.vue.LWPathway.Entry; /** * PathwayTableModel.java * * Provides a view of the currently active LWPathwayList (from the currently active map). * This view is a list of all the pathways and their contents in a single list, with * the option of a pathway being "closed", in which case it's contents doesn't appear * in the list. * * @see PathwayTable * @see LWPathwayList * @see LWPathway * * @author Scott Fraize * @author Jay Briedis * @version February 2004 */ public class PathwayTableModel extends DefaultTableModel implements ActiveListener, LWComponent.Listener { private LWMap mMap; final static String[] ColumnNames = {"A", "B", "C", "D", "E", "F"}; public static final int COL_VISIBLE = 1; public static final int COL_OPEN = 0; //public static final int COL_MAPVIEW = 6; public static final int COL_LABEL = 2; // Applies to pathway's and pathway members public static final int COL_NOTES = 3; // Applies to pathway's and pathway members public static final int COL_LOCKEDnMAPVIEW = 5; public static final int COL_COLOR = 4; // public static final int COL_REVEALER = 1; public PathwayTableModel() { VUE.addActiveListener(LWMap.class, this); //VUE.addActiveListener(LWPathway.class, this); VUE.addActiveListener(LWPathway.Entry.class, this); setMap(VUE.getActiveMap()); } private void setMap(LWMap map) { if (mMap == map) return; if (mMap != null) mMap.getPathwayList().removeListener(this); mMap = map; if (mMap != null) mMap.getPathwayList().addListener(this); fireTableDataChanged(); } /** LWComponent.Listener */ public void LWCChanged(LWCEvent e) { boolean fireChange = false; if (e.key instanceof LWComponent.Key) { if (e.getKey().type == LWComponent.KeyType.DATA) fireChange = true; } else { // if we can't know the key type, just fire no matter what fireChange = true; } if (fireChange) { //System.out.println("TABLE DATA CHANGED: " + e); fireTableDataChanged(); } /* if (e.getSource() instanceof LWPathway) { // The events mainly of interest to us are either a structural event, or a LWPathway label/note event, // although if anything in the pathway changes, fire a change event just in case. if (DEBUG.PATHWAY) System.out.println(this + " pathway event " + e); fireTableDataChanged(); } else if (e.key == LWKey.Label || e.getName().startsWith("pathway.")) { if (DEBUG.PATHWAY) System.out.println(this + " pathway child event " + e); // This means one of the LWComponents in the pathway has changed. // We only care about label changes as that's all that's displayed // in the PathwayTable, or if pathway.notes has changed so we can update // the note icon. // We only really need the PathwayTable to repaint if a label // has changed, but this will do it. // TODO: a global selection (ActiveChangeSupport / ActiveSelection) of a // single pathway will serve the purposes of the currently selected // pathway -- we should be able to get rid of this pathway.list.active event... if (false && e.getName().equals("pathway.list.active")) ;//setCurrentPathway((LWPathway) e.getComponent()); else fireTableDataChanged(); } */ } public void activeChanged(ActiveEvent e) { if (e.type == LWMap.class) { setMap((LWMap) e.active); } else if (e.type == LWPathway.Entry.class) { final LWPathway.Entry entry = (LWPathway.Entry) e.active; final LWPathway pathway = (entry == null ? null : entry.pathway); setCurrentPathway(pathway); if (getPathwayList() != null) { getPathwayList().setActivePathway(pathway); fireTableDataChanged(); } } // else if (e.type == LWPathway.class) { // if (getPathwayList() != null) { // getPathwayList().setActivePathway((LWPathway) e.active); // fireTableDataChanged(); // } // } } LWPathwayList getPathwayList() { return mMap == null ? null : mMap.getPathwayList(); } Iterator<LWPathway> getPathwayIterator() { return mMap == null ? VueUtil.EmptyIterator : mMap.getPathwayList().iterator(); } public void moveRow(int start,int end, int to, LWPathway pathway) { //System.out.println("MOVE : " + start + " to: " + to); //final LWPathway activePathway = VUE.getActivePathway(); pathway.moveEntry(start, to); fireTableDataChanged(); return; } void fireChanged(Object invoker) { fireTableChanged(new DataEvent(invoker)); } private void setCurrentPathway(LWPathway path) { if (getPathwayList() != null){ getPathwayList().setActivePathway(path); fireTableDataChanged(); //VUE.setActive(LWPathway.class, this, path); } } /* for PathwayPanel int getCurrentPathwayIndex(){ return getList().indexOf(VUE.getActivePathway()); } */ /* * for PathwayTable * Given @param pRow in the displayed table model, * return the pathway that contains it. If element * at that row is a pathway, return that pathway. */ LWPathway getPathwayForElementAt(int pRow) { Iterator i = getPathwayIterator(); int row = 0; while (i.hasNext()) { LWPathway p = (LWPathway) i.next(); if (row++ == pRow) return p; if (p.isOpen()) { for (int index = 0; index < p.length(); index++) { if (row++ == pRow) return p; } } } throw new IllegalArgumentException("Couldn't find any element at row " + pRow); } /* * for PathwayTable * Returns index of element within given pathway. We need * this because an element can appear in the pathway more * than once, and this is how we differentiate them (by index). * If the element at @param pRow is a pathway, return -1.*/ int getPathwayIndexForElementAt(int pRow) { Iterator i = getPathwayIterator(); int row = 0; while (i.hasNext()) { LWPathway p = (LWPathway) i.next(); if (row++ == pRow) return -1; if (p.isOpen()) { for (int index = 0; index < p.length(); index++) if (row++ == pRow) return index; } } throw new IllegalArgumentException("Couldn't find any element at row " + pRow); } // get the model list /* private List getList() { List list = new ArrayList(); Iterator<LWPathway> i = getPathwayIterator(); while (i.hasNext()) { LWPathway p = i.next(); list.add(p); if (p.isOpen()) { for (LWPathway.Entry e : p.getEntries()) list.add(e.node); } } return list; } */ /** * @return the entry currently displayed in the given row. */ LWPathway.Entry getEntry(int pRow) { if (pRow < 0) return null; Iterator<LWPathway> i = getPathwayIterator(); int row = 0; while (i.hasNext()) { LWPathway p = i.next(); if (row++ == pRow) return p.asEntry(); if (p.isOpen()) { for (LWPathway.Entry e : p.getEntries()) { if (row++ == pRow) return e; } } } return null; } /** * @return the entry display at the given row. If the given * entry is not currently displayed (the pathway is closed), * return -1. */ int getRow(LWPathway.Entry findEntry) { Iterator<LWPathway> i = getPathwayIterator(); int row = 0; while (i.hasNext()) { LWPathway p = i.next(); if (findEntry.isPathway() && findEntry.pathway == p) return row; row++; if (p.isOpen()) { for (LWPathway.Entry e : p.getEntries()) { if (e == findEntry) return row; row++; } } } return -1; } /* Object getElement(int pRow) { if (pRow < 0) return null; Iterator<LWPathway> i = getPathwayIterator(); int row = 0; while (i.hasNext()) { LWPathway p = i.next(); if (row++ == pRow) return p; if (p.isOpen()) { for (LWPathway.Entry e : p.getEntries()) { if (row++ == pRow) return e; } } } return null; } */ public synchronized int getRowCount() { int rows = 0; Iterator<LWPathway> i = getPathwayIterator(); while (i.hasNext()) { LWPathway p = i.next(); rows++; if (p.isOpen()) rows += p.length(); } return rows; ///final int rowCount = getList().size(); //if (DEBUG.PATHWAY) System.out.println("getRowCount=" + rowCount); //return rowCount; } public int getColumnCount() { return ColumnNames.length; } public String getColumnName(int col){ return ColumnNames[col]; } public Class getColumnClass(int col){ if (col == COL_COLOR) return Color.class; else if (col == COL_VISIBLE || col == COL_NOTES || col == COL_LOCKEDnMAPVIEW)// || col == COL_MAPVIEW) return ImageIcon.class; else if (col == COL_LABEL || col == COL_OPEN) return Object.class; // else if (col == COL_REVEALER) // return Boolean.class; //return javax.swing.JLabel.class; else return null; } public boolean isCellEditable(int row, int col){ if (getPathwayList() != null) { final LWPathway.Entry entry = getEntry(row); if (entry == null) return false; if (entry.pathway.isLocked()) return false; //if (col == 3) // label always editable //return true; // 2 problems: need to add end-of-action undo // marker, and as single-line edit will blow // away any newlines in the label. if (entry.isPathway()) return col == COL_COLOR || col == COL_LABEL;// || col == COL_REVEALER; } return false; } public boolean containsPathwayNamed(String label) { Iterator i = getPathwayIterator(); while (i.hasNext()){ LWPathway p = (LWPathway) i.next(); if (p.getLabel().equals(label)) return true; } return false; } public synchronized Object getValueAt(int row, int col) { final LWPathway.Entry entry = getEntry(row); if (entry == null) return null; if (entry.isPathway()) { LWPathway p = entry.pathway; try { switch (col) { case COL_VISIBLE: return p.isVisible() ? Boolean.TRUE : Boolean.FALSE; case COL_COLOR: return p.getStrokeColor(); case COL_OPEN: return p.isOpen() ? Boolean.TRUE : Boolean.FALSE; case COL_LABEL: return p.getDisplayLabel(); case COL_NOTES: return p.hasNotes() ? Boolean.TRUE : Boolean.FALSE; case COL_LOCKEDnMAPVIEW: return p.isLocked() ? Boolean.TRUE : Boolean.FALSE; // case COL_REVEALER: return new Boolean(getPathwayList().getRevealer() == p); //case COL_REVEALER: return new Boolean(p.isRevealer()); } } catch (Exception e) { e.printStackTrace(); System.err.println("exception in the table model, setting pathway cell:" + e); } } else { try { if (col == COL_LABEL) return entry.getLabel(); else if (col == COL_LOCKEDnMAPVIEW) return entry.isMapView() ? Boolean.TRUE : Boolean.FALSE; } catch (Exception e) { e.printStackTrace(); System.err.println("exception in the table model, setting pathway element cell:" + e); } } return null; } public void setValueAt(Object aValue, int row, int col){ if (DEBUG.PATHWAY) System.out.println(this + " setValutAt " + row + "," + col + " " + aValue); LWPathway.Entry entry = getEntry(row); if (entry == null) return; if (entry.isPathway()) { LWPathway p = entry.pathway; boolean bool = false; if (aValue instanceof Boolean) bool = ((Boolean)aValue).booleanValue(); if (col == COL_VISIBLE) { p.setVisible(!p.isVisible()); } // not proper (must use aValue to be proper) else if (col == COL_COLOR) { p.setStrokeColor((Color)aValue); } // proper else if (col == COL_OPEN) { p.setOpen(!p.isOpen()); } // not proper else if (col == COL_LABEL) { entry.setLabel((String)aValue); } // proper else if (col == COL_LOCKEDnMAPVIEW) { p.setLocked(!p.isLocked()); } // not proper //else if (col == COL_MAPVIEW) //{entry.setMapView(((Boolean)aValue).booleanValue()); //} /* else if (col == COL_REVEALER) { if (bool) getPathwayList().setRevealer(p); else getPathwayList().setRevealer(null); }*/ } else { if (col == COL_LABEL) entry.setLabel((String)aValue); else if (col == COL_LOCKEDnMAPVIEW) { if (!entry.isOffMapSlide()) { entry.setMapView(!entry.isMapView()); //VUE.getSlideViewer().reload(); } } } VUE.getUndoManager().mark(); // all the above sets will trigger LWCEvents, listeneted to by the // LWPathways they're in, which are listeneted to by their map's // LWPathwayList, which is listented to by us, the PathwayTableModel. // When we get the callback to LWCChanged, we call fireTableDataChanged. } private class DataEvent extends javax.swing.event.TableModelEvent { private Object invoker; DataEvent(Object invoker) { super(PathwayTableModel.this); this.invoker = invoker; } public String toString() { return "TableModelEvent[" + "src=" + getSource() + " rows=" + getFirstRow() + "-" + getLastRow() + " col=" + getColumn() + " type=" + getType() + " invoker=" + invoker.getClass().getName() + "]"; } } /** for PathwayTable */ /* LWPathway getCurrentPathway(){ if (getPathwayList() != null) return getPathwayList().getActivePathway(); else return null; } */ }