/* * 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 tufts.Util; import tufts.vue.gui.DeleteSlideDialog; import tufts.vue.gui.GUI; import tufts.vue.gui.WindowDisplayAction; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.dnd.InvalidDnDOperationException; import java.awt.event.*; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import javax.swing.*; import javax.swing.plaf.TableUI; import javax.swing.table.*; import javax.swing.border.*; import javax.swing.event.*; import osid.dr.Asset; /** * A JTable that displays all of the pathways that exists in a given map, * and provides user interaction with the list of pathways. Relies * on PathwayTableModel to produce a view of all the pathways that allows * for "opening" and "closing" the pathway -- displaying or hiding the * pathway elements in the JTable. * * @see PathwayTableModel * @see LWPathwayList * @see LWPathway * * @author Jay Briedis * @author Scott Fraize * @version $Revision: 1.115 $ / $Date: 2010-02-03 19:17:41 $ / $Author: mike $ */ public class PathwayTable extends JTable implements DropTargetListener, DragSourceListener, DragGestureListener, MouseListener, ActionListener { private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(PathwayTable.class); private DropTarget dropTarget = null; private DragSource dragSource = null; private int dropIndex = -1; private int dropRow = -1; private final ImageIcon notesIcon; private final ImageIcon lockIcon; private final ImageIcon lockOpenIcon; private final ImageIcon mapViewIcon; private final ImageIcon slideViewIcon; private final ImageIcon eyeOpen; private final ImageIcon eyeClosed; final static char RightArrowChar = 0x25B8; // unicode final static char DownArrowChar = 0x25BE; // unicode // default of "SansSerif" on mac appears be same as default system font: "Lucida Grande" private final Font PathwayFont = new Font("SansSerif", Font.BOLD, 12); private final Font EntryFont = new Font("SansSerif", Font.PLAIN, 10); private final Font SelectedEntryFont = new Font("SansSerif", Font.BOLD, 10); private final Color BGColor = Color.white;//new Color(241, 243, 246);; //private final Color SelectedBGColor = Color.white; //private final Color CurrentNodeColor = Color.red; private final LineBorder DefaultBorder = null;//new LineBorder(regular, 2); private int lastSelectedRow = -1; // private LWPathway.Entry lastSelectedEntry; private static final boolean showHeaders = true; // sets whether or not table column headers are shown private final int[] colWidths = {30,20,200,30,30,20}; private static Color SelectedColor; private static PathwayTable Singleton; public void setUI(TableUI ui) { super.setUI(ui); } public PathwayTable(PathwayTableModel model) { super(model); initComponents(); SelectedColor = GUI.getTextHighlightColor(); this.notesIcon = VueResources.getImageIcon("notes"); this.lockIcon = VueResources.getImageIcon("lock"); this.lockOpenIcon = VueResources.getImageIcon("lockOpen"); this.eyeOpen = VueResources.getImageIcon("pathwayOn"); this.eyeClosed = VueResources.getImageIcon("pathwayOff"); this.mapViewIcon = VueResources.getImageIcon("mapView"); this.slideViewIcon = VueResources.getImageIcon("slideView"); // this.setDoubleBuffered(true); this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); this.setRowHeight(20); this.setRowSelectionAllowed(true); this.setShowVerticalLines(false); this.setDoubleBuffered(true); this.setShowHorizontalLines(true); this.setGridColor(Color.lightGray); this.setIntercellSpacing(new Dimension(0,1)); this.setBackground(BGColor); // this.setIgnoreRepaint(true); //this.setSelectionBackground(SelectedBGColor); // this.setDragEnabled(true); // ToolTipManager.sharedInstance().registerComponent(this); this.getTableHeader().setReorderingAllowed(false); this.getTableHeader().setResizingAllowed(false); if (showHeaders) { this.getTableHeader().setVisible(false); this.getTableHeader().setPreferredSize(new Dimension(this.getTableHeader().getPreferredSize().width, 1)); this.getTableHeader().setIgnoreRepaint(true); } this.setDefaultRenderer(Color.class, new ColorRenderer()); this.setDefaultRenderer(ImageIcon.class, new ImageRenderer()); this.setDefaultRenderer(Object.class, new LabelRenderer()); this.setDefaultEditor(Color.class, new ColorEditor()); JTextField field = new PathwayNameField(); LabelCellEditor labelEditor = new LabelCellEditor(field); ((PathwayNameField)field).setCellEditor(labelEditor); this.setDefaultEditor(Object.class, labelEditor); this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); CellEditor e = this.getCellEditor(2,0); for (int i = 0; i < colWidths.length; i++){ TableColumn col = getColumn(PathwayTableModel.ColumnNames[i]); if (i == PathwayTableModel.COL_OPEN) col.setMaxWidth(26); else if (i == PathwayTableModel.COL_LABEL) {//col.setMaxWidth(colWidths[i]); col.setMinWidth(160); col.setWidth(160); } else if ( i == PathwayTableModel.COL_COLOR) { col.setMaxWidth(25); } else { col.setMaxWidth(colWidths[i]); } } VUE.addActiveListener(LWPathway.Entry.class, this); addMouseListener(this); /* getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent le) { handleValueChanged(le); } }); */ addKeyListener(PathwayKeyHandler); // addKeyListener(new KeyAdapter() { // public void keyPressed(KeyEvent e) { // if (DEBUG.PATHWAY || DEBUG.KEYS) System.out.println(this + " " + e); // final LWPathway pathway = VUE.getActivePathway(); // if (pathway == null) // return; // switch (e.getKeyCode()) { // case KeyEvent.VK_UP: // case KeyEvent.VK_LEFT: // if (pathway.atFirst()) // pathway.setIndex(-1); // else // pathway.setPrevious(); // e.consume(); // break; // case KeyEvent.VK_DOWN: // case KeyEvent.VK_RIGHT: // pathway.setNext(); // e.consume(); // break; // } // } // }); Singleton = this; renamePresentation.addActionListener(this); playbackPresentation.addActionListener(this); masterSlidePresentation.addActionListener(this); deletePresentation.addActionListener(this); editEntry.addActionListener(this); previewEntry.addActionListener(this); addNoteEntry.addActionListener(this); deleteEntry.addActionListener(this); duplicateEntry.addActionListener(this); // end of PathwayTable constructor } public static final KeyListener PathwayKeyHandler = new KeyAdapter() { public void keyPressed(KeyEvent e) { if (DEBUG.PATHWAY || DEBUG.KEYS) System.out.println(this + " " + e); final LWPathway pathway = VUE.getActivePathway(); if (pathway == null) return; boolean handled = true; switch (e.getKeyCode()) { case KeyEvent.VK_PAGE_UP: // page-up will not go to master-slide: presentation slides only pathway.setPrevious(); break; case KeyEvent.VK_UP: case KeyEvent.VK_LEFT: if (pathway.atFirst()) { // load master slide pathway.setIndex(-1); } else pathway.setPrevious(); break; case KeyEvent.VK_DOWN: case KeyEvent.VK_RIGHT: case KeyEvent.VK_PAGE_DOWN: pathway.setNext(); break; case KeyEvent.VK_HOME: pathway.setFirst(); break; case KeyEvent.VK_END: pathway.setLast(); break; case KeyEvent.VK_ENTER: if (e.getSource() == PathwayTable.Singleton) { if (VUE.getActiveViewer() != null) VUE.getActiveViewer().popFocal(); break; } else handled = false; default: handled = false; } if (handled) e.consume(); } }; public void valueChanged(ListSelectionEvent e) { //System.out.println("JTABLE VALUE CHANGED " + e); super.valueChanged(e); handleValueChanged(e); } // public void columnSelectionChanged(ListSelectionEvent e) { // System.out.println("JTABLE COL SELECTION CHANGED " + e); // super.columnSelectionChanged(e); // } private void handleValueChanged(ListSelectionEvent le) { // this usually happens via mouse click, but also possible via arrow key's moving selected item // Note that dragging the mouse over an image icon sends us continuous value change events, // so ignore events where the model says the value is adjusting, so we only change on the // final event. This does have an odd side effect tho: if you click down over one image // icon, then release over another, only the released over icon get's the change request. ListSelectionModel lsm = (ListSelectionModel) le.getSource(); if (lsm.isSelectionEmpty() || le.getValueIsAdjusting()) return; if (DEBUG.PATHWAY) { System.out.println("PathwayTable: VALUECHANGED: " + le); if (DEBUG.META) new Throwable("PATHWAYVALUECHANGED").printStackTrace(); } PathwayTableModel tableModel = getTableModel(); int row = lsm.getMinSelectionIndex(); lastSelectedRow = row; int col = getSelectedColumn(); if (DEBUG.PATHWAY) System.out.println("PathwayTable: valueChanged: selected row "+row+", col "+col); final LWPathway.Entry entry = tableModel.getEntry(row); if (DEBUG.PATHWAY) System.out.println("PathwayTable: valueChanged: object at row: " + entry); boolean selectedEntry = true; // TODO: this isn't adequate for handling clicks on particular columns for, e.g., toggling values // there, as if the row is already selected, there's no guarantee we get a new selection event // when clicking (apparently if you click in the map-view column in another row, which doesn't // change the selectedion, and then back on the map view icon for the selected row, we // start getting selection events again, tho obviously we can't rely on that as a user action). // We can always catch the actual mouse events, tho JTable editors may also handle this for us (?) // -- SMF 2007-05-10 /* if (entry.isPathway()) { if (col == PathwayTableModel.COL_VISIBLEnMAPVIEW || col == PathwayTableModel.COL_OPEN || col == PathwayTableModel.COL_LOCKED) { // setValue forces a value toggle in these cases setValueAt(entry.pathway, row, col); selectedEntry = false; } //pathway.setCurrentIndex(-1); } else if (col == PathwayTableModel.COL_VISIBLEnMAPVIEW && entry.hasVariableDisplayMode()) { setValueAt(entry.pathway, row,col); selectedEntry = false; } */ if (selectedEntry) { entry.pathway.setCurrentEntry(entry); // The above will generate the below event, but only if it's the current pathway. // If this entry isn't on the current pathway, this will ensure the entry's // pathway becomes the new current pathway (and if the event won't actually fire // again if there's been no change). VUE.setActive(LWPathway.Entry.class, this, entry); } else { // in case the setValueAt's resulted in any permanent changes: VUE.getUndoManager().mark(); } } public void activeChanged(ActiveEvent e, LWPathway.Entry entry) { if (entry != null) { int row = getTableModel().getRow(entry); if (row >= 0) changeSelection(row, -1, false, false); } } private static Color lastAlpha; private static Color lastMixed; private static Color selectedColor(LWPathway p) { //if (true) return SelectedColor; final Color alphaColor = p.getColor(); // todo: LWPathway should cache this as a white / non-alpha color if (alphaColor != lastAlpha) { lastAlpha = alphaColor; lastMixed = Util.alphaMix(alphaColor, Color.white); } return lastMixed; } private static Color selectedColor(LWPathway.Entry e) { return selectedColor(e.pathway); } /* LWPathway.Entry getLastSelectedEntry() { return lastSelectedEntry; } int getLastSelectedRow() { return lastSelectedRow; } */ private void initComponents() { dropTarget = new DropTarget(this, this); dragSource = new DragSource(); dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); } private PathwayTableModel getTableModel() { return (PathwayTableModel) getModel(); } private class LabelEditor extends AbstractCellEditor { public LabelEditor() { } //public LabelEditor(JTextField f){super(f);} public Object getCellEditorValue() { // TODO Auto-generated method stub return null; } } private class ColorEditor extends AbstractCellEditor implements TableCellEditor, MouseListener { Color currentColor; ColorRenderer button; int curRow =0; public ColorEditor() { button = new ColorRenderer(); button.addMouseListener(this); button.setBorder(null); } public Object getCellEditorValue() { return currentColor; } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { curRow=row; currentColor = (Color)value; // button.setBackground(currentColor); // button.setForeground(currentColor); Component c = button.getTableCellRendererComponent(table, value, isSelected,true, row, column); c.addMouseListener(this); return c; } public void mouseClicked(MouseEvent arg0) { } public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub if (VUE.getActivePathway().isLocked()) return; // System.out.println(e.getY()); if (e.getY() > 20) return; Color c = VueUtil.runColorChooser("Pathway Color Selection", currentColor, VUE.getDialogParent()); fireEditingStopped(); if (c != null) { getTableModel().setValueAt(currentColor = c, curRow, 4); } } public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } } private class ColorRenderer extends JPanel implements TableCellRenderer { private final Color TopGradient1 = new Color(179,166,121), BottomGradient1 = new Color(142,129,82); private final Color TopGradient2 = new Color(195,193,186); private final Color BottomGradient2 = new Color(162,161,156); private GradientPaint Gradient = null; private GradientPaint Gradient2 = null; private int curRow =0; public ColorRenderer() { setOpaque(true); //Gradient = new GradientPaint(0, 0, TopGradient1, // 0, 20, BottomGradient1); //Gradient2 = new GradientPaint(0, 0, TopGradient2, // 0, 20, BottomGradient2); setToolTipText("Select Color"); } //final RoundRectangle2D BlobShape = new RoundRectangle2D.Float(); Color paintColor = null; /* protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D)g; paintGradient(g2); g2.setColor(paintColor); g2.fillRoundRect(2, 2, getWidth()-8, 20-4,7,7); g2.setColor(Color.gray); g2.drawRoundRect(2, 2, getWidth()-8, 20-4,7,7); } public void setPaintColor(Color c) { paintColor = c; } private void paintGradient(Graphics2D g) { Paint p = g.getPaint(); final LWPathway.Entry entry = getTableModel().getEntry(curRow); final LWPathway activePathway = VUE.getActivePathway(); // final LWPathway.Entry entryReal = getTableModel().getEntry(PathwayTable.this.getSelectedRow()); //entry. // if (entry.pathway != null && entryReal.equals(entry.pathway)) if (entry != null && entry.pathway != null && entry.node == activePathway) g.setPaint(Gradient); else g.setPaint(Gradient2); g.fillRect(0, 0, getWidth(),20); g.setPaint(p); g.setColor(Color.white); g.fillRect(0,20,getWidth(),40); } boolean useGoldGradient = true; */ public java.awt.Component getTableCellRendererComponent( JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int col) { final LWPathway.Entry entry = getTableModel().getEntry(row); // paintColor = (Color)getTableModel().getValueAt(row, 4); curRow=row; paintColor = (Color)color; GradientLabel gl = new GradientLabel(entry.pathway,paintColor); if (entry == null) { { // setBackground((Color) color); // setForeground((Color) color); return gl; } } else if (entry.isPathway()) { //setBackground((Color) color); //setForeground((Color) color); return gl; } else { JLabel p = new DefaultTableCellRenderer(); p.setOpaque(true); final LWPathway activePathway = VUE.getActivePathway(); if (entry.pathway == activePathway && entry.pathway.getCurrentEntry() == entry) { // useGoldGradient = true; p.setBackground(selectedColor(entry)); p.setForeground(selectedColor(entry)); } else { // useGoldGradient=false; p.setBackground(BGColor); p.setForeground(BGColor); } return p; } // return null; } } private static Font ArrowIconFont = new Font("Lucida Sans Unicode", Font.PLAIN, 20); private class LabelRenderer extends DefaultTableCellRenderer{ public java.awt.Component getTableCellRendererComponent( javax.swing.JTable jTable, Object value, boolean isSelected, boolean hasFocus, int row, int col) { final LWPathway.Entry entry = getTableModel().getEntry(row); String debug = ""; if (Util.isUnixPlatform()) ArrowIconFont = new Font("DejaVu Sans", Font.PLAIN, 20); if (entry == null) return this; if (DEBUG.PATHWAY) debug = "(row"+row+")"; JLabel label = new JLabel(); setMinimumSize(new Dimension(10, 20)); setPreferredSize(new Dimension(500, 20)); if (entry.isPathway()) { String emptyString = null; GradientLabel gl = new GradientLabel(entry.pathway); if (col == PathwayTableModel.COL_OPEN) { boolean bool = false; if (value instanceof Boolean) bool = ((Boolean)value).booleanValue(); setFont(ArrowIconFont); setForeground(Color.white); setText(bool ? " "+DownArrowChar : " "+RightArrowChar); } else { // final LWPathway p = entry.pathway; if (entry.pathway.getEntries().isEmpty()) { if (entry.pathway.getEntries().isEmpty()) emptyString = VueResources.getString("pathways.empty.label"); if (getRowHeight(row) != 40) setRowHeight(row, 40); gl = new GradientLabel(entry.pathway,emptyString); } /*if (p == VUE.getActivePathway()) setBackground(Color.red); else*/ //Background is always going to be gradient now. setBackground(BGColor); setFont(PathwayFont); if (VUE.getActiveEntry() == entry) setForeground(Color.black); else setForeground(Color.white); setText(debug+" " + entry.getLabel()); // this.setAlignmentY(Component.TOP_ALIGNMENT); } this.setOpaque(false); gl.setLayout(new BorderLayout()); gl.add(this,BorderLayout.NORTH); // todo: not very efficient to be now using the GradientLabel this way -- // we're constructing one of these for each pathway for every single paint, // and they create a ton of sub-objects themselves... return gl; } else { //entry is not a pathway if you're in the wrong column go null; //only return the label for the proper column... final LWPathway activePathway = VUE.getActivePathway(); if (col != PathwayTableModel.COL_LABEL) { if (entry.pathway == activePathway && entry.pathway.getCurrentEntry() == entry) { setBackground(selectedColor(entry)); setForeground(selectedColor(entry)); } else { setBackground(BGColor); setForeground(BGColor); } this.setOpaque(false); label.setForeground(this.getForeground()); label.setBackground(this.getBackground()); label.setOpaque(true); label.setLayout(new BorderLayout()); label.add(this,BorderLayout.CENTER); return label; } setFont(SelectedEntryFont); setForeground(Color.black); if (entry.pathway == activePathway && entry.pathway.getCurrentEntry() == entry) { // This is the current item on the current path setBackground(selectedColor(entry)); setText(debug+" "+entry.getLabel()); //setText(debug+" * "+getText()); } else { // setFont(EntryFont); setText(debug+" "+entry.getLabel()); if (entry.node != null && (entry.node.isFiltered() || entry.node.isHidden())) setForeground(Color.lightGray); } this.setOpaque(false); label.setForeground(this.getForeground()); label.setBackground(this.getBackground()); label.setOpaque(true); label.setLayout(new BorderLayout()); label.add(this,BorderLayout.CENTER); return label; } } } private static final RoundRectangle2D BlobShape = new RoundRectangle2D.Float(); private class GradientLabel extends JPanel { //Gradient painting necessities private final Color TopGradient1 = new Color(179,166,121), BottomGradient1 = new Color(142,129,82); private final Color TopGradient2 = new Color(195,193,186); private final Color BottomGradient2 = new Color(162,161,156); private LWPathway path; private GradientPaint Gradient = null; private GradientPaint Gradient2 = null; private String emptyString = null; private Color paintColor = null; public GradientLabel(LWPathway pathway, String emptyString, Color paintColor) { setOpaque(false); path=pathway; Gradient = new GradientPaint(0, 0, TopGradient1, 0, 20, BottomGradient1); Gradient2 = new GradientPaint(0, 0, TopGradient2, 0, 20, BottomGradient2); setLayout(new BorderLayout()); this.paintColor = paintColor; setPreferredSize(new Dimension(getWidth(),40)); this.emptyString = emptyString; } public GradientLabel(LWPathway pathway, String emptyString) { this(pathway,emptyString,null); } public GradientLabel(LWPathway pathway) { this(pathway,null,null); } public GradientLabel(LWPathway pathway, Color paintColor) { this(pathway,null,paintColor); } public void paintComponent(Graphics _g) { final Graphics2D g = (Graphics2D) _g; paintGradient(g); if (paintColor != null) paintColorBlob(g, paintColor); // super.paintComponent(g2); } private void paintColorBlob(final Graphics2D g, final Color color) { BlobShape.setRoundRect(2, 1, getWidth()-8, 20-4, 7, 7); // Draw the pathway color swatch. // We want to show the translucent nature of the pathway // color, so we fill with white first, so when we draw the // translucent pathway color, it will be mixed with pure // white (default map color) g.setColor(Color.white); g.fill(BlobShape); g.setColor(color); g.fill(BlobShape); // Now draw a border on the color swatch: g.setColor(Color.gray); g.draw(BlobShape); // g.setColor(color); // g.fillRoundRect(2, 2, getWidth()-8, 20-4,7,7); // g.setColor(Color.gray); // g.drawRoundRect(2, 2, getWidth()-8, 20-4,7,7); } private void paintGradient(Graphics2D g) { Paint p = g.getPaint(); if (path != null && path == VUE.getActivePathway()) g.setPaint(Gradient); else g.setPaint(Gradient2); g.fillRect(0, 0, getWidth(),20); g.setPaint(p); g.setColor(Color.white); g.fillRect(0,20,getWidth(),40); g.setColor(Color.lightGray); g.setFont(EntryFont); if (emptyString != null) g.drawString(emptyString, 0, 33); } } private final Border iconBorder = new EmptyBorder(3,0,5,5); private final Border NodeIconBorder = new EmptyBorder(1,0,0,0); private class ImageRenderer extends DefaultTableCellRenderer { public java.awt.Component getTableCellRendererComponent( javax.swing.JTable jTable, Object obj, boolean isSelected, boolean hasFocus, int row, int col) { final LWPathway.Entry entry = getTableModel().getEntry(row); if (entry == null) return this; this.setBorder(DefaultBorder); if (entry.isPathway()) { boolean bool = false; if (obj instanceof Boolean) bool = ((Boolean)obj).booleanValue(); if (col == PathwayTableModel.COL_VISIBLE) { setIcon(bool ? eyeOpen : eyeClosed); setBorder(iconBorder); setToolTipText("Show/hide pathway"); } else if (col == PathwayTableModel.COL_NOTES) { if (entry.node == VUE.getActivePathway() && entry.pathway.getCurrentEntry() == entry) setBackground(selectedColor(entry)); else setBackground(BGColor); if (entry.hasNotes()) { setIcon(notesIcon); setToolTipText(entry.getNotes()); } else { setToolTipText(null); setIcon(null); } } else if (col == PathwayTableModel.COL_LOCKEDnMAPVIEW) { setBorder(iconBorder); setIcon(bool ? lockIcon : lockOpenIcon); this.setAlignmentY(JLabel.CENTER_ALIGNMENT); if (entry.node == VUE.getActivePathway() && entry.pathway.getCurrentEntry() == entry) setBackground(selectedColor(entry)); else setBackground(BGColor); setToolTipText("Is locked"); } else { if (entry.node == VUE.getActivePathway() && entry.pathway.getCurrentEntry() == entry) setBackground(selectedColor(entry)); else setBackground(BGColor); } GradientLabel gl = new GradientLabel(entry.pathway); this.setOpaque(false); gl.add(this,BorderLayout.NORTH); return gl; } else { final LWPathway activePathway = VUE.getActivePathway(); //System.out.println("return null"); if (entry.pathway == activePathway && entry.pathway.getCurrentEntry() == entry) { setBackground(selectedColor(entry)); setForeground(selectedColor(entry)); setOpaque(true); setIcon(null); } else { setBackground(BGColor); setOpaque(true); setForeground(BGColor); setIcon(null); } if (col == PathwayTableModel.COL_NOTES) { if (entry.hasNotes()) { setIcon(notesIcon); setToolTipText(entry.getNotes()); } else { setToolTipText(null); setIcon(null); } } else if (col == PathwayTableModel.COL_LOCKEDnMAPVIEW) { if (entry.hasVariableDisplayMode()) { boolean isMapView = false; if (obj instanceof Boolean) isMapView = ((Boolean)obj).booleanValue(); if (isMapView) { setBorder(NodeIconBorder); setIcon(mapViewIcon); } else { setIcon(entry.pathway.mSlideIcon); //setIcon(slideViewIcon); } } else { setIcon(null); } setToolTipText("Toggle map/slide node"); } return this; } } } public String toString() { return "PathwayTable[" + VUE.getActivePathway() + "]"; } public void dragEnter(DropTargetDragEvent arg0) { /* PathwayTableModel model = (PathwayTableModel)this.getModel(); System.out.println(arg0.getLocation()); int index = model.getPathwayIndexForElementAt(rowAtPoint(arg0.getLocation())); if (index < 0) { arg0.rejectDrag(); System.out.println("DRAG REJECTED" +index); } else { arg0.acceptDrag(DnDConstants.ACTION_MOVE); System.out.println("DRAG ACCEPTED" + index); } */ arg0.acceptDrag(DnDConstants.ACTION_MOVE); } public void dragOver(DropTargetDragEvent arg0) { arg0.acceptDrag(DnDConstants.ACTION_MOVE); /*PathwayTableModel model = (PathwayTableModel)this.getModel(); System.out.println(arg0.getLocation()); int index = model.getPathwayIndexForElementAt(rowAtPoint(arg0.getLocation())); if (index < 0) { arg0.rejectDrag(); } else { arg0.acceptDrag(DnDConstants.ACTION_MOVE); } */ } public void drop(DropTargetDropEvent arg0) { Transferable transferable = arg0.getTransferable(); LWPathway.Entry entry =null; try { entry = (LWPathway.Entry)transferable.getTransferData(DataFlavor.plainTextFlavor); } catch (UnsupportedFlavorException e) { e.printStackTrace(); arg0.rejectDrop(); arg0.dropComplete(false); } catch (IOException e) { e.printStackTrace(); arg0.rejectDrop(); arg0.dropComplete(false); } if( entry != null ) { // See where in the list we dropped the element. PathwayTableModel model = (PathwayTableModel)this.getModel(); //System.out.println("START" + model.getPathwayForElementAt(dropRow)); //System.out.println("END" + model.getPathwayForElementAt(rowAtPoint(arg0.getLocation()))); if (!model.getPathwayForElementAt(dropRow).equals(model.getPathwayForElementAt(rowAtPoint(arg0.getLocation())))) { VueUtil.alert(this, VueResources.getString("presentationDialog.dropError.text"), VueResources.getString("presentationDialog.dropError.title"), JOptionPane.ERROR_MESSAGE); arg0.rejectDrop(); arg0.dropComplete(false); } else { if (dropIndex < 0 || model.getPathwayIndexForElementAt(rowAtPoint(arg0.getLocation())) < 0) { arg0.dropComplete(false); arg0.rejectDrop(); } else { model.moveRow(dropIndex, dropIndex, model.getPathwayIndexForElementAt(rowAtPoint(arg0.getLocation())), model.getPathwayForElementAt(dropRow)); VUE.getUndoManager().mark(); arg0.dropComplete(true); arg0.acceptDrop(DnDConstants.ACTION_MOVE); } } } // end if: we got the object // Else there was a problem getting the object else { arg0.dropComplete(false); arg0.rejectDrop(); } // end else: can't get the object return; } public void dropActionChanged(DropTargetDragEvent arg0) { } public void dragGestureRecognized(DragGestureEvent event) { PathwayTableModel model = (PathwayTableModel)this.getModel(); //System.out.println("SELROW : " + this.getSelectedRow()); dropIndex = model.getPathwayIndexForElementAt(this.getSelectedRow()); dropRow = this.getSelectedRow(); try { //TODO: FIGURE OUT WHAT TO TRANSFER LWPathway.Entry entry = model.getEntry(this.getSelectedRow()); if(entry.isPathway()) return; else dragSource.startDrag(event, DragSource.DefaultMoveDrop, entry, this); } catch (InvalidDnDOperationException e) { System.err.println(e.getMessage()); e.printStackTrace(); } } public void dragExit(DropTargetEvent arg0) { // not implemented // System.out.println("dragexittarget"); } public void dragDropEnd(DragSourceDropEvent arg0) { // not implemented //System.out.println("dragendsource"); } public void dragEnter(DragSourceDragEvent arg0) { // not implemented //System.out.println("dragentersource"); } public void dragExit(DragSourceEvent arg0) { // System.out.println("dragexitsource"); //not implemented } public void dragOver(DragSourceDragEvent arg0) { //Not implemented //System.out.println("dragoversource"); } public void dropActionChanged(DragSourceDragEvent arg0) { // not implemented' // System.out.println("dropactionchanged"); } private void displayContextMenu(MouseEvent e) { getPopup(e).show(e.getComponent(), e.getX(), e.getY()); } private JPopupMenu m = null; //presentation menu items private static final String context="contextMenus.pathways."; private static final JMenuItem renamePresentation = new JMenuItem(VueResources.getString(context+"pathway.rename")); private static final JMenuItem playbackPresentation = new JMenuItem(VueResources.getString(context+"pathway.start")); private static final JMenuItem addNoteEntry = new JMenuItem(VueResources.getString(context+"pathway.notes")); private static final JMenuItem masterSlidePresentation = new JMenuItem(VueResources.getString(context+"pathway.masterslide")); private static final JMenuItem deletePresentation = new JMenuItem(VueResources.getString(context+"pathway.delete")); //entry menu items private static final JMenuItem deleteEntry = new JMenuItem(VueResources.getString(context+"entry.delete")); private static final JMenuItem previewEntry = new JMenuItem(VueResources.getString(context+"entry.preview")); private static final JMenuItem editEntry = new JMenuItem(VueResources.getString(context+"entry.edit")); private static final JMenuItem duplicateEntry = new JMenuItem(VueResources.getString(context+"entry.duplicate")); public void actionPerformed(ActionEvent e) { if (DEBUG.EVENTS) Log.debug("actionPerformed: " + e); if (e.getSource().equals(renamePresentation)) { //System.out.println("selectedX : " + selectedX); //the pathway name column is always column 2 boolean a = this.editCellAt(selectedY,2); } else if (e.getSource().equals(playbackPresentation)) { final PresentationTool presTool = PresentationTool.getTool(); GUI.invokeAfterAWT(new Runnable() { public void run() { VUE.toggleFullScreen(true); }}); GUI.invokeAfterAWT(new Runnable() { public void run() { //VueToolbarController.getController().setSelectedTool(presTool); VUE.setActive(VueTool.class, this, presTool); }}); GUI.invokeAfterAWT(new Runnable() { public void run() { presTool.startPresentation(); }}); } else if (e.getSource().equals(masterSlidePresentation)) { Actions.EditMasterSlide.act(selectedEntry.pathway.getMasterSlide()); } else if (e.getSource().equals(deletePresentation)) { final Object[] defaultOrderButtons = {VueResources.getString("optiondialog.deletepathway.cancel"),VueResources.getString("optiondialog.deletepathway.delete")}; final Object[] macOrderButtons = {VueResources.getString("optiondialog.deletepathway.delete"), VueResources.getString("optiondialog.deletepathway.cancel")}; int response = VueUtil.option (VUE.getDialogParent(), VueResources.getString("optiondialog.deletepathway.message") , VueResources.getString("optiondialog.deletepathway.title"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, (Util.isMacPlatform() ? macOrderButtons : defaultOrderButtons), VueResources.getString("optiondialog.deletepathway.cancel") ); if (Util.isMacPlatform() ? response == 0 : response == 1) { //delete the pathway VUE.getPathwayPanel().deletePathway(selectedEntry.pathway); } } else if (e.getSource().equals(addNoteEntry)) { Actions.NotesAction.actionPerformed(e); } else if (e.getSource().equals(editEntry) || e.getSource().equals(previewEntry)) { Actions.EditSlide.act(selectedEntry.getSlide()); } else if (e.getSource().equals(duplicateEntry)) { //Actions.DuplicateSlide.act(selectedEntry.getFocal()); } else if (e.getSource().equals(deleteEntry)) { GUI.invokeAfterAWT(new Runnable() { public void run() { DeleteSlideDialog dsd = PathwayPanel.getDeleteSlideDialog(); java.awt.Point p = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint(); p.x -= dsd.getWidth() / 2; p.y -= dsd.getHeight() / 2; dsd.setLocation(p); if (dsd.showAgain()) { dsd.setVisible(true); } if (dsd.getOkCanel()) VUE.getActivePathway().remove(VUE.getActivePathway().getCurrentIndex()); }}); } repaint(); } LWPathway.Entry selectedEntry = null; int selectedX = 0; int selectedY = 0; private JPopupMenu getPopup(MouseEvent e) { m = new JPopupMenu(VueResources.getString("pathwaytable.menu.pathway")); int row = this.rowAtPoint(e.getPoint()); PathwayTableModel tableModel = getTableModel(); int col = this.getColumnModel().getColumnIndexAtX(e.getX()); final LWPathway.Entry entry = tableModel.getEntry(row); WindowDisplayAction infoAction = new WindowDisplayAction(VUE.getInfoDock()); JCheckBoxMenuItem infoCheckBox = new JCheckBoxMenuItem(infoAction); infoCheckBox.setSelected(VUE.getInfoDock().isShowing()); VUE.setActive(LWPathway.Entry.class, this, entry); if (row >= 0) changeSelection(row, -1, false, false); selectedEntry = VUE.getActiveEntry(); selectedX = col; selectedY = row; if (entry.isPathway()) { infoCheckBox.setText(VueResources.getString("pathwaytable.menu.pathwayinfo")); m.add(infoCheckBox); m.add(playbackPresentation); m.addSeparator(); m.add(addNoteEntry); m.addSeparator(); m.add(renamePresentation); m.add(masterSlidePresentation); m.add(deletePresentation); } else { infoCheckBox.setText(VueResources.getString("pathwaytable.menu.slideinfo")); m.add(infoCheckBox); m.add(previewEntry); m.addSeparator(); m.add(addNoteEntry); m.addSeparator(); m.add(editEntry); m.add(masterSlidePresentation); //m.add(duplicateEntry); m.add(deleteEntry); editEntry.setEnabled(!entry.isPortal()); } return m; } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} private boolean mouseWasConsumed; public void mousePressed(MouseEvent e) { mouseWasConsumed = false; if (DEBUG.MOUSE) Log.debug(e); if (GUI.isMenuPopup(e)) { displayContextMenu(e); mouseWasConsumed = true; return; } if ((e.getModifiers() & MouseEvent.BUTTON3_MASK )!=0) return; int row = getSelectedRow(); PathwayTableModel tableModel = getTableModel(); lastSelectedRow = row; int col = getSelectedColumn(); //this.changeSelection(row,col,false,false); if (DEBUG.PATHWAY) System.out.println("PathwayTable: valueChanged: selected row "+row+", col "+col); final LWPathway.Entry entry = tableModel.getEntry(row); // the below statement appears to be by definition false: // a pathway entry asks it's pathway if it has no members, // which should never be true, unless this is somehow // to detect something that was just deleted? -- SMF 2008-05-28 if (entry.pathway.getEntries().isEmpty()) return; if (entry.isPathway()) { if (col == PathwayTableModel.COL_VISIBLE || col == PathwayTableModel.COL_OPEN || col == PathwayTableModel.COL_LOCKEDnMAPVIEW) { // setValue forces a value toggle in these cases setValueAt(entry.pathway, row, col); mouseWasConsumed = true; } } else if (col == PathwayTableModel.COL_LOCKEDnMAPVIEW && entry.hasVariableDisplayMode()) { setValueAt(entry.pathway, row,col); PathwayPanel.updateMapViewDependentActions(); mouseWasConsumed = true; } } public void mouseClicked(MouseEvent e) { if (DEBUG.MOUSE) Log.debug(e); if (!mouseWasConsumed && isDoubleClickEvent(e)) { Actions.LaunchPresentation.fire(this, e); } } private final boolean isDoubleClickEvent(MouseEvent e) { return (e.getClickCount() > 1 && e.getClickCount() % 2 == 0) // % 2 detects cascading double clicks (reported as a 4 click, 6 click, etc) && (e.getModifiers() & java.awt.event.InputEvent.BUTTON1_MASK) != 0; } class LabelCellEditor extends DefaultCellEditor { public LabelCellEditor(JTextField edit) { super(edit); } } class PathwayNameField extends JTextField implements MouseListener { LabelCellEditor labelEditor; public PathwayNameField() { super(); addMouseListener(this); } public void setCellEditor(LabelCellEditor editor) { labelEditor = editor; } public Rectangle getBounds() { Rectangle r = super.getBounds(); r.height=20; return r; } public boolean isOpaque() { return true; } //public void repaint(){} //public void paintImmediately(){} // public void paint(Graphics g){} public void paintComponent(Graphics g) { g.setColor(Color.white); super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; Rectangle r= g2.getClipRect(); g2.setColor(Color.gray); g2.drawLine(r.x, 20, r.width, 20); g2.setColor(Color.lightGray); g2.setFont(EntryFont); g2.drawString("This pathway is empty", 0, 33); } public void paintBorder(Graphics g) { } // public void paintChildren(Graphics g){} // public void update(){} public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } public void mousePressed(MouseEvent e) { if (e.getY() >20 && labelEditor != null) labelEditor.stopCellEditing(); } public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } } }