001: package org.enhydra.jawe.base.panel.panels;
002:
003: import java.awt.Color;
004: import java.awt.Component;
005: import java.awt.Dimension;
006: import java.awt.Point;
007: import java.awt.Rectangle;
008: import java.awt.event.ActionEvent;
009: import java.awt.event.KeyEvent;
010: import java.awt.event.MouseAdapter;
011: import java.awt.event.MouseEvent;
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015: import java.util.Vector;
016:
017: import javax.swing.AbstractAction;
018: import javax.swing.Action;
019: import javax.swing.Box;
020: import javax.swing.BoxLayout;
021: import javax.swing.JButton;
022: import javax.swing.JComponent;
023: import javax.swing.JOptionPane;
024: import javax.swing.JPanel;
025: import javax.swing.JScrollPane;
026: import javax.swing.JTable;
027: import javax.swing.JViewport;
028: import javax.swing.KeyStroke;
029: import javax.swing.ListSelectionModel;
030: import javax.swing.event.ListSelectionEvent;
031: import javax.swing.event.ListSelectionListener;
032: import javax.swing.table.DefaultTableModel;
033: import javax.swing.table.TableCellRenderer;
034: import javax.swing.table.TableColumn;
035:
036: import org.enhydra.jawe.ButtonPropertyChangedListener;
037: import org.enhydra.jawe.JaWEManager;
038: import org.enhydra.jawe.ResourceManager;
039: import org.enhydra.jawe.base.controller.JaWEActions;
040: import org.enhydra.jawe.base.controller.JaWEController;
041: import org.enhydra.jawe.base.editor.StandardXPDLElementEditor;
042: import org.enhydra.jawe.base.panel.InlinePanel;
043: import org.enhydra.jawe.base.panel.PanelSettings;
044: import org.enhydra.jawe.base.panel.panels.tablesorting.BasicSortingTable;
045: import org.enhydra.shark.xpdl.XMLCollection;
046: import org.enhydra.shark.xpdl.XMLCollectionElement;
047: import org.enhydra.shark.xpdl.XMLComplexElement;
048: import org.enhydra.shark.xpdl.XMLElement;
049: import org.enhydra.shark.xpdl.XMLElementChangeInfo;
050: import org.enhydra.shark.xpdl.XMLElementChangeListener;
051: import org.enhydra.shark.xpdl.XMLUtil;
052:
053: /**
054: * Creates a table panel.
055: * @author Sasa Bojanic
056: * @author Zoran Milakovic
057: * @author Miroslav Popov
058: */
059: public class XMLBasicTablePanel extends XMLBasicPanel implements
060: XMLElementChangeListener {
061:
062: public static Color FOREIGN_EL_COLOR_BKG = Color.lightGray;
063: public static Color SPEC_EL_COLOR_BKG = Color.orange;
064:
065: protected static Dimension miniTableDimension = new Dimension(450,
066: 125);
067: protected static Dimension smallTableDimension = new Dimension(450,
068: 200);
069: protected static Dimension mediumTableDimension = new Dimension(
070: 550, 200);
071: protected static Dimension largeTableDimension = new Dimension(650,
072: 200);
073:
074: /**
075: * Object which we are replacing from one place to another within
076: * the list by dragging it.
077: */
078: protected XMLElement movingElement;
079:
080: /**
081: * Index of the object which we are replacing from one place to another
082: * within the list by dragging it.
083: */
084: protected int movingElementPosition;
085:
086: /**
087: * The new index of the object which we are replacing from one place
088: * to another within the list by dragging it.
089: */
090: protected int newMovingElementPosition;
091:
092: /** Indicates if object is being dragged. */
093: protected boolean dragging = false;
094:
095: /**
096: * Indicates if the code for changing object position within the list
097: * is executed.
098: */
099: protected boolean changing = false;
100:
101: protected JTable allItems;
102: protected JPanel toolbox;
103:
104: protected Vector columnNames;
105: protected List columnsToShow;
106:
107: protected InlinePanel ipc;
108:
109: public XMLBasicTablePanel(InlinePanel ipc, XMLCollection myOwner,
110: List columnsToShow, List elementsToShow, String title,
111: boolean hasBorder, boolean hasEmptyBorder,
112: boolean automaticWidth, boolean miniDimension,
113: final boolean colors, final boolean showArrows) {
114:
115: super (ipc, myOwner, title, true, hasBorder, hasEmptyBorder);
116:
117: this .ipc = ipc;
118:
119: myOwner.addListener(this );
120: myOwner.setNotifyListeners(true);
121:
122: columnNames = getColumnNames(columnsToShow);
123: this .columnsToShow = columnsToShow;
124: allItems = createTable(colors);
125: setupTable(miniDimension, automaticWidth, showArrows);
126: fillTableContent(elementsToShow);
127:
128: toolbox = createToolbar();
129: JPanel paneAndArrows = new JPanel();
130: paneAndArrows.setLayout(new BoxLayout(paneAndArrows,
131: BoxLayout.X_AXIS));
132: paneAndArrows.add(createScrollPane());
133:
134: // if (showArrows) {
135: // JPanel p = createArrowPanel();
136: // paneAndArrows.add(Box.createRigidArea(new Dimension(5, 0)));
137: // paneAndArrows.add(p);
138: // }
139:
140: add(toolbox);
141: add(Box.createVerticalStrut(3));
142: add(paneAndArrows);
143:
144: adjustActions();
145: }
146:
147: public JTable getTable() {
148: return allItems;
149: }
150:
151: public XMLElement getSelectedElement() {
152: int row = allItems.getSelectedRow();
153: if (row >= 0) {
154: return (XMLElement) allItems.getValueAt(row, 0);
155: }
156: return null;
157:
158: }
159:
160: public boolean setSelectedElement(Object el) {
161: try {
162: int rc = allItems.getRowCount();
163: if (rc > 0) {
164: for (int i = 0; i < rc; i++) {
165: if (el == allItems.getValueAt(i, 0)) {
166: allItems.setRowSelectionInterval(i, i);
167:
168: // focus the row
169:
170: JViewport viewport = (JViewport) allItems
171: .getParent();
172: // This rectangle is relative to the table where the
173: // northwest corner of cell (0,0) is always (0,0).
174: Rectangle rect = allItems.getCellRect(i, 0,
175: true);
176: // The location of the viewport relative to the table
177: Point pt = viewport.getViewPosition();
178: // Translate the cell location so that it is relative
179: // to the view, assuming the northwest corner of the
180: // view is (0,0)
181: rect.setLocation(rect.x - pt.x, rect.y - pt.y);
182: // Scroll the area into view
183: viewport.scrollRectToVisible(rect);
184:
185: return true;
186: }
187: }
188: }
189: } catch (Exception ex) {
190: }
191: return false;
192: }
193:
194: public void setSelectedRow(int row) {
195: try {
196: allItems.setRowSelectionInterval(row, row);
197:
198: adjustActions();
199: } catch (Exception e) {
200: }
201: }
202:
203: public void addRow(XMLElement e) {
204: int rowpos = allItems.getRowCount();
205: DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
206: Vector v = getRow(e);
207: dtm.insertRow(rowpos, v);
208: }
209:
210: public void removeRow(int row) {
211: DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
212: dtm.removeRow(row);
213: }
214:
215: protected void moveItem(int upOrDown) {
216: newMovingElementPosition = movingElementPosition;
217: if (newMovingElementPosition == -1) {
218: return;
219: }
220: if (upOrDown == 0) {
221: newMovingElementPosition--;
222: } else {
223: newMovingElementPosition++;
224: }
225: moveItem();
226: }
227:
228: protected void moveItem() {
229: changing = true;
230: XMLCollection owncol = (XMLCollection) getOwner();
231: int rowCnt = allItems.getRowCount();
232: if (movingElement == null || movingElementPosition == -1
233: || newMovingElementPosition == -1
234: || newMovingElementPosition == movingElementPosition
235: || (rowCnt - 1) < movingElementPosition
236: || (rowCnt - 1) < newMovingElementPosition
237: || !owncol.contains(movingElement)) {
238: changing = false;
239: return;
240: }
241:
242: if (JaWEManager.getInstance().getJaWEController()
243: .canRepositionElement(owncol, movingElement)) {
244: XMLElement currentElementAtPosition = (XMLElement) allItems
245: .getValueAt(newMovingElementPosition, 0);
246: int newpos = owncol.indexOf(currentElementAtPosition);
247:
248: DefaultTableModel dtm = (DefaultTableModel) allItems
249: .getModel();
250: Vector v = getRow(movingElement);
251: dtm.removeRow(movingElementPosition);
252: dtm.insertRow(newMovingElementPosition, v);
253:
254: JaWEController jc = JaWEManager.getInstance()
255: .getJaWEController();
256: jc.startUndouableChange();
257: owncol.reposition(movingElement, newpos);
258: List toSelect = new ArrayList();
259: toSelect.add(movingElement);
260: jc.endUndouableChange(toSelect);
261:
262: setSelectedRow(newMovingElementPosition);
263:
264: movingElementPosition = newMovingElementPosition;
265: }
266: changing = false;
267: }
268:
269: protected Action newElementAction = new AbstractAction(
270: JaWEActions.NEW_ACTION) {
271: public void actionPerformed(ActionEvent ae) {
272: JaWEController jc = JaWEManager.getInstance()
273: .getJaWEController();
274:
275: XMLCollection col = (XMLCollection) getOwner();
276: XMLElement newEl = JaWEManager.getInstance()
277: .getXPDLObjectFactory().createXPDLObject(col, null,
278: false);
279:
280: boolean isForModal = PanelUtilities.isForModalDialog(newEl);
281: if (!isForModal && ipc.isModified()) {
282: int sw = ipc.showModifiedWarning();
283: if (sw == JOptionPane.CANCEL_OPTION
284: || (sw == JOptionPane.YES_OPTION && ipc
285: .isModified())) {
286: return;
287: }
288: }
289:
290: boolean updInProg = false;
291: if (isForModal) {
292:
293: StandardXPDLElementEditor ed = new StandardXPDLElementEditor();
294: ed.editXPDLElement(newEl);
295: boolean statOK = (ed.getStatus() == StandardXPDLElementEditor.STATUS_OK);
296: boolean canIns = true;
297: if (statOK) {
298: canIns = jc.canInsertElement(col, newEl);
299: }
300: if (!statOK || !canIns) {
301: if (!canIns) {
302: jc
303: .getJaWEFrame()
304: .message(
305: ed
306: .getLanguageDependentString("WarningCannotInsertElement"),
307: JOptionPane.WARNING_MESSAGE);
308: }
309: return;
310: }
311: updInProg = true;
312: }
313: jc.startUndouableChange();
314: col.add(newEl);
315: List temp = new ArrayList();
316: temp.add(newEl);
317: jc.endUndouableChange(temp);
318: if (updInProg) {
319: setSelectedElement(newEl);
320: }
321: adjustActions();
322: }
323: };
324:
325: protected Action editElementAction = new AbstractAction(
326: JaWEActions.EDIT_PROPERTIES_ACTION) {
327: public void actionPerformed(ActionEvent ae) {
328: XMLElement editElement = getSelectedElement();
329: if (editElement != null) {
330: if (ipc.isModified()) {
331: int sw = ipc.showModifiedWarning();
332: if (sw == JOptionPane.CANCEL_OPTION
333: || (sw == JOptionPane.YES_OPTION && ipc
334: .isModified())) {
335: return;
336: }
337: }
338: JaWEManager.getInstance().getXPDLElementEditor()
339: .editXPDLElement(editElement);
340: }
341: }
342: };
343:
344: protected Action deleteElementAction = new AbstractAction(
345: JaWEActions.DELETE_ACTION) {
346: public void actionPerformed(ActionEvent ae) {
347: XMLElement deleteElement = getSelectedElement();
348: if (deleteElement != null) {
349: JaWEController jc = JaWEManager.getInstance()
350: .getJaWEController();
351: List sel = new ArrayList();
352: sel.add(deleteElement.getParent());
353: if (jc.confirmDelete(sel, deleteElement)) {
354: XMLCollection parent = (XMLCollection) getOwner();
355: jc.startUndouableChange();
356: parent.remove(deleteElement);
357: jc.endUndouableChange(sel);
358: ipc.getPanelSettings().adjustActions();
359: adjustActions();
360: }
361: }
362: }
363: };
364:
365: protected Action moveUpAction = new AbstractAction("MoveUp") {
366: public void actionPerformed(ActionEvent ae) {
367: moveItem(0);
368: adjustActions();
369: }
370: };
371:
372: protected Action moveDownAction = new AbstractAction("MoveDown") {
373: public void actionPerformed(ActionEvent ae) {
374: moveItem(1);
375: adjustActions();
376: }
377: };
378:
379: protected Vector getColumnNames(List columnsToShow) {
380: // creating a table which do not allow cell editing
381: Vector cnames = new Vector();
382: cnames.add("Object");
383: XMLElement cel = ((XMLCollection) getOwner())
384: .generateNewElement();
385: if (cel instanceof XMLComplexElement) {
386: Iterator it = columnsToShow.iterator();
387: while (it.hasNext()) {
388: String elemName = (String) it.next();
389: XMLElement el = ((XMLComplexElement) cel).get(elemName);
390: if (el != null) {
391: cnames.add(JaWEManager.getInstance()
392: .getLabelGenerator().getLabel(el));
393: } else {
394: it.remove();
395: }
396: }
397: } else {
398: cnames.add(JaWEManager.getInstance().getLabelGenerator()
399: .getLabel(cel));
400: }
401: return cnames;
402: }
403:
404: protected JTable createTable(final boolean colors) {
405: JTable t = new BasicSortingTable(this , new Vector(),
406: columnNames) {
407:
408: public boolean isCellEditable(int row, int col) {
409: return false;
410: }
411:
412: // This table colors elements depending on their owner
413: public Component prepareRenderer(
414: TableCellRenderer renderer, int rowIndex,
415: int vColIndex) {
416: Component c = super .prepareRenderer(renderer, rowIndex,
417: vColIndex);
418: if (!isCellSelected(rowIndex, vColIndex) && colors) {
419: XMLElement el = (XMLElement) getValueAt(rowIndex, 0);
420: if (el instanceof XMLCollectionElement) {
421: XMLCollectionElement cel = (XMLCollectionElement) el;
422: XMLCollection celOwner = (XMLCollection) cel
423: .getParent();
424: if (celOwner == null) {
425: c.setBackground(SPEC_EL_COLOR_BKG);
426: } else if (celOwner != getOwner()) {
427: c.setBackground(FOREIGN_EL_COLOR_BKG);
428: } else {
429: c.setBackground(getBackground());
430: }
431: } else {
432: c.setBackground(getBackground());
433: }
434: }
435:
436: return c;
437: }
438: };
439:
440: Color bkgCol = new Color(245, 245, 245);
441: if (ipc.getSettings() instanceof PanelSettings) {
442: bkgCol = ((PanelSettings) ipc.getSettings())
443: .getBackgroundColor();
444: }
445: t.setBackground(bkgCol);
446:
447: return t;
448: }
449:
450: protected void setupTable(boolean miniDimension,
451: boolean automaticWidth, final boolean showArrows) {
452: TableColumn column;
453: // setting the first column (object column) to be invisible
454: column = allItems.getColumnModel().getColumn(0);
455: column.setMinWidth(0);
456: column.setMaxWidth(0);
457: column.setPreferredWidth(0);
458: column.setResizable(false);
459: // setting fields that will not be displayed within the table
460:
461: // setting some table properties
462: allItems.setColumnSelectionAllowed(false);
463: allItems.setRowSelectionAllowed(true);
464: allItems.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
465: allItems.getTableHeader().setReorderingAllowed(false);
466:
467: Dimension tDim;
468: int noOfVisibleColumns = columnNames.size() - 1;
469: if (miniDimension) {
470: tDim = new Dimension(miniTableDimension);
471: } else if (noOfVisibleColumns <= 3) {
472: tDim = new Dimension(smallTableDimension);
473: } else if (noOfVisibleColumns <= 5) {
474: tDim = new Dimension(mediumTableDimension);
475: } else {
476: tDim = new Dimension(largeTableDimension);
477: }
478:
479: if (automaticWidth) {
480: tDim.width = allItems.getPreferredScrollableViewportSize().width;
481: }
482: allItems
483: .setPreferredScrollableViewportSize(new Dimension(tDim));
484:
485: allItems.getInputMap(JComponent.WHEN_FOCUSED).put(
486: KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false),
487: "edit");
488: allItems.getActionMap().put("edit", editElementAction);
489:
490: allItems.getInputMap(JComponent.WHEN_FOCUSED).put(
491: KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, false),
492: "delete");
493: allItems.getActionMap().put("delete", deleteElementAction);
494:
495: final XMLCollection col = (XMLCollection) getOwner();
496: final boolean canRepos = JaWEManager.getInstance()
497: .getJaWEController().canRepositionElement(col, null);
498:
499: if (!getOwner().isReadOnly())
500: allItems
501: .setToolTipText(ResourceManager
502: .getLanguageDependentString("MessageDragItemToChangeItsPosition"));
503:
504: // mouse listener for editing on double-click
505: allItems.addMouseListener(new MouseAdapter() {
506: public void mouseClicked(MouseEvent me) {
507: if (me.getClickCount() > 1) {
508: editElementAction.actionPerformed(null);
509: }
510: }
511:
512: /** Marks the object which place within the table will be changed.*/
513: public void mousePressed(MouseEvent me) {
514: movingElement = null;
515: movingElementPosition = -1;
516: if (showArrows && !getOwner().isReadOnly() && canRepos) {
517: dragging = true;
518: }
519: try {
520: movingElementPosition = allItems.getSelectedRow();
521: if (movingElementPosition >= 0) {
522: movingElement = (XMLElement) allItems
523: .getValueAt(movingElementPosition, 0);
524: adjustActions();
525: }
526: } catch (Exception ex) {
527: }
528: }
529:
530: /** Just indicates that dragging is over.*/
531: public void mouseReleased(MouseEvent me) {
532: dragging = false;
533: }
534: });
535:
536: /** Changes position of object within the list.*/
537: if (showArrows && !myOwner.isReadOnly() && canRepos) {// && ((XMLCollection)getOwner()).getParent().isReadOnly()))) {
538: ListSelectionModel rowSM = allItems.getSelectionModel();
539: rowSM.addListSelectionListener(new ListSelectionListener() {
540: public void valueChanged(ListSelectionEvent lse) {
541: if (dragging && !changing) {
542: newMovingElementPosition = -1;
543: try {
544: newMovingElementPosition = allItems
545: .getSelectedRow();
546: } catch (Exception ex) {
547: }
548:
549: moveItem();
550: }
551: adjustActions();
552: }
553: });
554: }
555:
556: }
557:
558: protected void fillTableContent(List elementsToShow) {
559: DefaultTableModel dtm = (DefaultTableModel) allItems.getModel();
560: Iterator it = elementsToShow.iterator();
561:
562: while (it.hasNext()) {
563: XMLElement elem = (XMLElement) it.next();
564: Vector v = getRow(elem);
565: dtm.addRow(v);
566: }
567: }
568:
569: protected Vector getRow(XMLElement elem) {
570: Vector v = new Vector();
571: if (elem instanceof XMLComplexElement) {
572: Iterator itAllElems = columnsToShow.iterator();
573: v = new Vector();
574: XMLComplexElement cmel = (XMLComplexElement) elem;
575: while (itAllElems.hasNext()) {
576: String elName = (String) itAllElems.next();
577: XMLElement el = cmel.get(elName);
578: if (el != null) {
579: v.add(new XMLElementView(ipc, el,
580: XMLElementView.TOVALUE));
581: }
582: }
583: } else {
584: v
585: .add(new XMLElementView(ipc, elem,
586: XMLElementView.TOVALUE));
587: }
588: v.add(0, elem);
589: return v;
590: }
591:
592: protected JScrollPane createScrollPane() {
593: // creates panel
594: JScrollPane allItemsPane = new JScrollPane();
595: allItemsPane.setViewportView(allItems);
596: return allItemsPane;
597: }
598:
599: protected JPanel createToolbar() {
600: JPanel panel = new JPanel();
601: panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
602:
603: JButton buttonNew = PanelUtilities.createToolbarButton(ipc
604: .getSettings(), newElementAction);
605: buttonNew.setRolloverEnabled(true);
606: JButton buttonEdit = PanelUtilities.createToolbarButton(ipc
607: .getSettings(), editElementAction);
608: buttonEdit.setRolloverEnabled(true);
609: JButton buttonDelete = PanelUtilities.createToolbarButton(ipc
610: .getSettings(), deleteElementAction);
611: buttonDelete.setRolloverEnabled(true);
612:
613: panel.add(buttonNew);
614: panel.add(Box.createRigidArea(new Dimension(3, 3)));
615: panel.add(buttonEdit);
616: panel.add(Box.createRigidArea(new Dimension(3, 3)));
617: panel.add(buttonDelete);
618: panel.add(Box.createHorizontalGlue());
619: return panel;
620: }
621:
622: protected JPanel createArrowPanel() {
623: JPanel p = new JPanel();
624: p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
625:
626: JButton buttonUp = new JButton();
627: buttonUp.setIcon(ipc.getPanelSettings().getArrowUpImageIcon());
628: buttonUp.setPreferredSize(new Dimension(16, 16));
629: buttonUp.setEnabled(false);
630: buttonUp.addActionListener(moveUpAction);
631: moveUpAction
632: .addPropertyChangeListener(new ButtonPropertyChangedListener(
633: buttonUp));
634:
635: JButton buttonDown = new JButton();
636: buttonDown.setIcon(ipc.getPanelSettings()
637: .getArrowDownImageIcon());
638: buttonDown.setPreferredSize(new Dimension(16, 16));
639: buttonDown.setEnabled(false);
640: buttonDown.addActionListener(moveDownAction);
641: moveDownAction
642: .addPropertyChangeListener(new ButtonPropertyChangedListener(
643: buttonDown));
644:
645: p.add(buttonUp);
646: p.add(Box.createVerticalGlue());
647: p.add(buttonDown);
648: return p;
649: }
650:
651: public void xmlElementChanged(XMLElementChangeInfo info) {
652: if (info.getAction() == XMLElementChangeInfo.REMOVED) {
653: Iterator it = info.getChangedSubElements().iterator();
654: while (it.hasNext()) {
655: XMLElement el = (XMLElement) it.next();
656: int row = getElementRow(el);
657: // System.out.println("Removing row " + row + " for element " + el);
658: if (row != -1) {
659: removeRow(row);
660: }
661: }
662: } else if (info.getAction() == XMLElementChangeInfo.INSERTED) {
663: Iterator it = info.getChangedSubElements().iterator();
664: while (it.hasNext()) {
665: XMLElement el = (XMLElement) it.next();
666: addRow(el);
667: }
668: }
669: }
670:
671: protected int getElementRow(XMLElement el) {
672: int row = -1;
673: for (int i = 0; i < allItems.getRowCount(); i++) {
674: XMLElement toCompare = (XMLElement) allItems.getValueAt(i,
675: 0);
676: if (el == toCompare) {
677: row = i;
678: break;
679: }
680: }
681: return row;
682: }
683:
684: protected void adjustActions() {
685: JaWEController jc = JaWEManager.getInstance()
686: .getJaWEController();
687:
688: XMLElement selEl = getSelectedElement();
689: newElementAction.setEnabled(jc
690: .canCreateElement((XMLCollection) getOwner()));
691: editElementAction.setEnabled((selEl != null && XMLUtil
692: .getPackage(selEl) != null));
693: deleteElementAction.setEnabled((selEl != null && jc
694: .canRemoveElement((XMLCollection) getOwner(), selEl)));
695:
696: boolean canRepos = JaWEManager.getInstance()
697: .getJaWEController().canRepositionElement(
698: (XMLCollection) getOwner(), null);
699: moveUpAction.setEnabled(selEl != null
700: && allItems.getSelectedRow() > 0 && canRepos);
701: moveDownAction.setEnabled(selEl != null
702: && allItems.getSelectedRow() < allItems.getModel()
703: .getRowCount() - 1 && canRepos);
704: }
705:
706: public void cleanup() {
707: myOwner.removeListener(this);
708: }
709: }
|