001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright � 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.pm.graphic.spreadsheet;
051:
052: import java.awt.Component;
053: import java.awt.Dimension;
054: import java.awt.KeyboardFocusManager;
055: import java.awt.Point;
056: import java.awt.Rectangle;
057: import java.awt.event.ActionEvent;
058: import java.awt.event.KeyAdapter;
059: import java.awt.event.KeyEvent;
060: import java.awt.event.MouseAdapter;
061: import java.awt.event.MouseEvent;
062: import java.io.IOException;
063: import java.util.ArrayList;
064: import java.util.HashMap;
065: import java.util.Iterator;
066: import java.util.LinkedList;
067: import java.util.List;
068: import java.util.Map;
069:
070: import javax.swing.AbstractAction;
071: import javax.swing.DefaultComboBoxModel;
072: import javax.swing.JComponent;
073: import javax.swing.JFrame;
074: import javax.swing.SwingUtilities;
075: import javax.swing.table.JTableHeader;
076: import javax.swing.table.TableCellEditor;
077: import javax.swing.table.TableColumn;
078: import javax.swing.table.TableColumnModel;
079: import javax.swing.table.TableModel;
080:
081: import org.apache.commons.collections.Closure;
082:
083: import com.projity.datatype.Hyperlink;
084: import com.projity.dialog.ResourceAdditionDialog;
085: import com.projity.field.Field;
086: import com.projity.graphic.configuration.ActionList;
087: import com.projity.graphic.configuration.CellStyle;
088: import com.projity.graphic.configuration.GraphicConfiguration;
089: import com.projity.grouping.core.Node;
090: import com.projity.grouping.core.NodeBridge;
091: import com.projity.grouping.core.NodeFactory;
092: import com.projity.help.HelpUtil;
093: import com.projity.job.Job;
094: import com.projity.job.JobRunnable;
095: import com.projity.menu.MenuActionConstants;
096: import com.projity.options.GeneralOption;
097: import com.projity.pm.graphic.frames.GraphicManager;
098: import com.projity.pm.graphic.model.cache.GraphicNode;
099: import com.projity.pm.graphic.model.cache.NodeModelCache;
100: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheet;
101: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheetAction;
102: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheetModel;
103: import com.projity.pm.graphic.spreadsheet.common.transfer.NodeListTransferHandler;
104: import com.projity.pm.graphic.spreadsheet.editor.SimpleComboBoxEditor;
105: import com.projity.pm.graphic.spreadsheet.renderer.NameCellComponent;
106: import com.projity.pm.graphic.spreadsheet.selection.SpreadSheetListSelectionModel;
107: import com.projity.pm.graphic.spreadsheet.selection.SpreadSheetSelectionModel;
108: import com.projity.pm.graphic.spreadsheet.selection.event.HeaderMouseListener;
109: import com.projity.pm.resource.ResourceImpl;
110: import com.projity.pm.resource.ResourcePool;
111: import com.projity.pm.task.Project;
112: import com.projity.server.data.EnterpriseResourceData;
113: import com.projity.server.data.Serializer;
114: import com.projity.session.Session;
115: import com.projity.session.SessionFactory;
116: import com.projity.strings.Messages;
117: import com.projity.util.Alert;
118: import com.projity.util.BrowserControl;
119:
120: /**
121: *
122: */
123: public class SpreadSheet extends CommonSpreadSheet implements Cloneable {
124: private static final long serialVersionUID = 5958334223191182318L;
125: protected SpreadSheetPopupMenu popup = null;
126:
127: public SpreadSheet() {
128: super ();
129: NodeListTransferHandler.registerWith(this );
130:
131: }
132:
133: protected void finalize() {
134: System.out.println("SpreadSheet.finalize()" + this );
135: }
136:
137: public void cleanUp() {
138: ((CommonSpreadSheetModel) getModel()).getCache()
139: .removeNodeModelListener(this );
140: super .cleanUp();
141: }
142:
143: public void setCache(NodeModelCache cache, ArrayList fieldArray,
144: CellStyle cellStyle, ActionList actionList) {
145: // if (getCache()!=null) getCache().close();
146: if (getCache() != null)
147: getCache().getReference().close(); // deepClose
148:
149: SpreadSheetColumnModel colModel;
150: TableColumnModel oldColModel = getColumnModel();
151: if (oldColModel != null
152: && oldColModel instanceof SpreadSheetColumnModel) {
153: if (((SpreadSheetColumnModel) oldColModel).getFieldArray() == fieldArray)
154: colModel = (SpreadSheetColumnModel) oldColModel;
155: else
156: colModel = new SpreadSheetColumnModel(fieldArray);
157: } else
158: colModel = new SpreadSheetColumnModel(fieldArray);
159: setModel(new SpreadSheetModel(cache, colModel, cellStyle,
160: actionList), (colModel == oldColModel) ? null
161: : colModel);
162:
163: }
164:
165: public TableCellEditor getCellEditor(int row, int column) {
166: SpreadSheetModel model = (SpreadSheetModel) getModel();
167: Field field = model.getFieldInColumn(column + 1);
168: GraphicNode node = model.getNode(row);
169: if (field != null
170: && (field.isDynamicOptions() || field.hasFilter())) {
171: return new SimpleComboBoxEditor(new DefaultComboBoxModel(
172: field.getOptions(node.getNode().getImpl())));
173: } else {
174: return super .getCellEditor(row, column);
175: }
176: }
177:
178: public void setFieldArray(ArrayList fieldArray) {
179: ((SpreadSheetColumnModel) getColumnModel())
180: .setFieldArray(fieldArray);
181: createDefaultColumnsFromModel(fieldArray);
182: resizeAndRepaintHeader();
183:
184: }
185:
186: public void resizeAndRepaintHeader() {
187: JTableHeader header = getTableHeader();
188: SpreadSheetColumnModel tm = ((SpreadSheetColumnModel) getColumnModel());
189: int colWidth = tm.getColWidth();// tm.getTotalColumnWidth(); //Hack,
190: // colWidth isn't enough why?
191: header.setPreferredSize(new Dimension(colWidth, header
192: .getPreferredSize().height));
193: header.resizeAndRepaint();
194:
195: }
196:
197: public void createDefaultColumnsFromModel(ArrayList fieldArray) {
198: // Remove any current columns
199: TableColumnModel cm = getColumnModel();
200: while (cm.getColumnCount() > 0) {
201: cm.removeColumn(cm.getColumn(0));
202: }
203:
204: // Create new columns from the data model info
205: int colCount = fieldArray.size();
206: for (int i = 0; i < colCount; i++) {
207: TableColumn newColumn = new TableColumn(i);
208: addColumn(newColumn);
209: }
210:
211: // TableModel m = getModel();
212: // if (m != null) {
213: // // Remove any current columns
214: // TableColumnModel cm = getColumnModel();
215: // while (cm.getColumnCount() > 0) {
216: // cm.removeColumn(cm.getColumn(0));
217: // }
218: //
219: // // Create new columns from the data model info
220: // for (int i = 0; i < m.getColumnCount(); i++) {
221: // TableColumn newColumn = new TableColumn(i);
222: // addColumn(newColumn);
223: // }
224: // }
225: }
226:
227: private void makeCustomTableHeader(TableColumnModel columnModel) {
228: JTableHeader h = new JTableHeader(columnModel) {
229:
230: public String getToolTipText(MouseEvent e) {
231: if (isHasColumnHeaderPopup()) {
232: int col = columnAtPoint(e.getPoint());
233: Field f = ((SpreadSheetModel) getModel())
234: .getFieldInNonTranslatedColumn(col + 1);
235: if (f != null)
236: return "<html>"
237: + f.getName()
238: + "<br>"
239: + Messages
240: .getString("Text.rightClickToInsertRemoveColumns")
241: + "</html>";
242: }
243: return super .getToolTipText(e);
244: }
245:
246: };
247: setTableHeader(h);
248:
249: }
250:
251: public SpreadSheetPopupMenu getPopup() {
252: if (popup == null) {
253: popup = hasRowPopup() ? new SpreadSheetPopupMenu(this )
254: : null;
255: }
256: return popup;
257: }
258:
259: public void setModel(SpreadSheetModel spreadSheetModel,
260: SpreadSheetColumnModel spreadSheetColumnModel) {
261: makeCustomTableHeader(spreadSheetColumnModel);
262: TableModel oldModel = getModel();
263: setModel(spreadSheetModel);
264:
265: if (spreadSheetColumnModel != null) {
266: //System.out.println("creating new ColModel");
267: setColumnModel(spreadSheetColumnModel);
268:
269: selection = new SpreadSheetSelectionModel(this );
270: selection
271: .setRowSelection(new SpreadSheetListSelectionModel(
272: selection, true));
273: selection
274: .setColumnSelection(new SpreadSheetListSelectionModel(
275: selection, false));
276: setSelectionModel(selection.getRowSelection());
277: createDefaultColumnsFromModel(spreadSheetModel
278: .getFieldArray()); //Consume memory
279: getColumnModel().setSelectionModel(
280: selection.getColumnSelection());
281: }
282:
283: registerEditors(); //Consume memory
284: initRowHeader(spreadSheetModel);
285: initModel();
286: initListeners();
287:
288: GraphicConfiguration config = GraphicConfiguration
289: .getInstance();
290: //fix for substance
291: setTableHeader(createDefaultTableHeader());
292: JTableHeader header = getTableHeader();
293: header.setPreferredSize(new Dimension((int) header
294: .getPreferredSize().getWidth(), config
295: .getColumnHeaderHeight()));
296: header.addMouseListener(new HeaderMouseListener(this ));
297:
298: addMouseListener(new MouseAdapter() {
299: // Cursor oldCursor = null;
300: // public void mouseEntered(MouseEvent e) {
301: // Point p = e.getPoint();
302: // int col = columnAtPoint(p);
303: // Field field = ((SpreadSheetModel) getModel()).getFieldInNonTranslatedColumn(col + 1);
304: // System.out.println("mouse entered field " + field);
305: // if (field != null && field.isHyperlink()) {
306: // oldCursor = getCursor();
307: // setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
308: // System.out.println("setting new cursor to " + Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) + " old is " + oldCursor);
309: // } else
310: // super.mouseEntered(e);
311: //
312: // }
313: //
314: // public void mouseExited(MouseEvent e) {
315: // Point p = e.getPoint();
316: // int col = columnAtPoint(p);
317: // Field field = ((SpreadSheetModel) getModel()).getFieldInNonTranslatedColumn(col + 1);
318: // System.out.println("mouse exited field " + field);
319: // if (field != null && field.isHyperlink()) {
320: // setCursor(oldCursor);
321: // System.out.println("setting old cursor to " + oldCursor);
322: // e.consume();
323: // } else
324: // super.mouseEntered(e);
325: // }
326:
327: public void mousePressed(MouseEvent e) { // changed to mousePressed instead of mouseClicked() for snappier handling 17/5/04 hk
328: Point p = e.getPoint();
329: int row = rowAtPoint(p);
330: int col = columnAtPoint(p);
331: SpreadSheetPopupMenu popup = getPopup();
332: if (SwingUtilities.isLeftMouseButton(e)) {
333: SpreadSheetColumnModel columnModel = (SpreadSheetColumnModel) getColumnModel();
334: Field field = ((SpreadSheetModel) getModel())
335: .getFieldInNonTranslatedColumn(col + 1);
336: SpreadSheetModel model = (SpreadSheetModel) getModel();
337: if (field.isNameField()) {
338: // if (col == columnModel.getNameIndex()) {
339: GraphicNode node = model.getNode(row);
340: if (isOnIcon(e)) {
341: if (model.getCellProperties(node)
342: .isCompositeIcon()) {
343: finishCurrentOperations();
344: selection.getRowSelection()
345: .clearSelection();
346: boolean change = true;
347: if (!node.isFetched()) // for subprojects
348: change = node.fetch();
349: if (change)
350: model.changeCollapsedState(row);
351: e.consume(); // prevent dbl click treatment below
352:
353: // because editor may have already been
354: // installed we
355: // have to update its collapsed state
356: // updateNameCellEditor(node);
357:
358: // editCellAt(row,model.findGraphicNodeRow(node));
359: }
360: }
361: } else if (field != null && field.isHyperlink()) {
362: Hyperlink link = (Hyperlink) model.getValueAt(
363: row, col + 1);
364: if (link != null) {
365: BrowserControl
366: .displayURL(link.getAddress());
367: e.consume(); // prevent dbl click treatment below
368: }
369:
370: }
371: if (!e.isConsumed() && e.getClickCount() == 2) { // if above code didn't treat and is dbl click
372: doDoubleClick(row, col);
373: }
374:
375: } else if (popup != null
376: && SwingUtilities.isRightMouseButton(e)) { // e.isPopupTrigger() can be used too
377: // selection.getRowSelection().clearSelection();
378: // selection.getRowSelection().addSelectionInterval(row, row);
379: popup.setRow(row);
380: popup.setCol(col);
381: popup.show(SpreadSheet.this , e.getX(), e.getY());
382: }
383: }
384: });
385:
386: if (oldModel != spreadSheetModel
387: && oldModel instanceof CommonSpreadSheetModel)
388: ((CommonSpreadSheetModel) getModel()).getCache()
389: .removeNodeModelListener(this );
390: spreadSheetModel.getCache().addNodeModelListener(this );
391:
392: // getColumnModel().addColumnModelListener(new TableColumnModelListener(){
393: // public void columnAdded(TableColumnModelEvent e) {
394: // // TODO Auto-generated method stub
395: //
396: // }
397: // public void columnMarginChanged(ChangeEvent e) {
398: // // TODO Auto-generated method stub
399: //
400: // }
401: // public void columnMoved(TableColumnModelEvent e) {
402: // // TODO Auto-generated method stub
403: //
404: // }
405: // public void columnRemoved(TableColumnModelEvent e) {
406: // // TODO Auto-generated method stub
407: //
408: // }
409: // public void columnSelectionChanged(ListSelectionEvent e) {
410: // System.out.println(((e.getValueIsAdjusting())?"lse=":"LSE=")+e.getFirstIndex()+", "+e.getLastIndex());
411: // SpreadSheet.this.revalidate();
412: // //SpreadSheet.this.paintImmediately(0, 0, getWidth(), GraphicConfiguration.getInstance().getColumnHeaderHeight());
413: // }
414: // });
415:
416: }
417:
418: // public void columnSelectionChanged(ListSelectionEvent e) {
419: // System.out.println("JTable: "+((e.getValueIsAdjusting())?"lse=":"LSE=")+e.getFirstIndex()+", "+e.getLastIndex());
420: // super.columnSelectionChanged(e);
421: // }
422:
423: public void doDoubleClick(int row, int col) {
424: GraphicManager.getInstance(this ).doInformationDialog(false);
425: }
426:
427: /*
428: * public SpreadSheetPopupMenu getPopup() { return popup; } public void
429: * setPopup(SpreadSheetPopupMenu popup) { this.popup = popup; }
430: */
431:
432: public boolean isOnIcon(MouseEvent e) {
433: Point p = e.getPoint();
434: int row = rowAtPoint(p);
435: int col = columnAtPoint(p);
436: Rectangle bounds = getCellRect(row, col, false);
437: SpreadSheetModel model = (SpreadSheetModel) getModel();
438: GraphicNode node = model.getNode(row);
439: return NameCellComponent.isOnIcon(new Point(
440: (int) (p.getX() - bounds.getX()),
441: (int) (p.getY() - bounds.getY())), bounds.getSize(),
442: model.getCache().getLevel(node));
443: }
444:
445: public boolean isOnText(MouseEvent e) {
446: Point p = e.getPoint();
447: int row = rowAtPoint(p);
448: int col = columnAtPoint(p);
449: Rectangle bounds = getCellRect(row, col, false);
450: SpreadSheetModel model = (SpreadSheetModel) getModel();
451: GraphicNode node = model.getNode(row);
452: return NameCellComponent.isOnText(new Point(
453: (int) (p.getX() - bounds.getX()),
454: (int) (p.getY() - bounds.getY())), bounds.getSize(),
455: model.getCache().getLevel(node));
456: }
457:
458: public void updateNameCellEditor(GraphicNode node) {
459: SpreadSheetColumnModel columnModel = (SpreadSheetColumnModel) getColumnModel();
460:
461: // if (isEditing() && getEditingColumn() == columnModel.getNameIndex()
462: // && editorComp != null) {
463:
464: if (isEditing()
465: && editorComp != null
466: && ((SpreadSheetModel) getModel()).getFieldInColumn(
467: getEditingColumn() + 1).isNameField()) {
468: NameCellComponent c = (NameCellComponent) editorComp;
469: SpreadSheetModel model = (SpreadSheetModel) getModel();
470: // GraphicNode node = model.getNode(row);
471: if (model.getCellProperties(node).isCompositeIcon())
472: c.setCollapsed(node.isCollapsed());
473: }
474: }
475:
476: protected void initListeners() {
477: addKeyListener(new KeyAdapter() { // TODO need to fix focus problems elsewhere for this to always work
478: public void keyPressed(KeyEvent e) {
479: int row = getSelectedRow();
480: if (row < 0)
481: return;
482: CommonSpreadSheetModel model = (CommonSpreadSheetModel) getModel();
483: if (e.getKeyCode() == KeyEvent.VK_INSERT)
484: executeAction(MenuActionConstants.ACTION_NEW);
485: else if (e.getKeyCode() == KeyEvent.VK_DELETE)
486: executeAction(MenuActionConstants.ACTION_DELETE);
487:
488: }
489: });
490:
491: }
492:
493: // Actions on selected nodes
494: public List getSelectedGraphicNodes() {
495: return rowsToGraphicNodes(getSelectedRows());
496: }
497:
498: public List rowsToGraphicNodes(int[] rows) {
499: if (rows == null || rows.length == 0)
500: return new LinkedList();
501: NodeModelCache cache = ((SpreadSheetModel) getModel())
502: .getCache();
503: return cache.getElementsAt(rows);
504: }
505:
506: // gui actions
507: public void executeAction(String actionId) {
508: CommonSpreadSheetAction action = getAction(actionId);
509: if (action == null) {
510: System.out.println("No action for " + actionId);
511: return;
512: }
513: action.setSpreadSheet(this );
514: action.execute();
515: }
516:
517: // init actions
518: public CommonSpreadSheetAction prepareAction(String actionId) {
519: CommonSpreadSheetAction action = getAction(actionId);
520: action.setSpreadSheet(this );
521: return action;
522: }
523:
524: private String[] actionList = null;
525:
526: public String[] getActionList() {
527: if (actionList == null)
528: actionList = ((SpreadSheetModel) getModel())
529: .getActionList();
530: return actionList;
531: }
532:
533: private Map actionMap = null;
534:
535: public CommonSpreadSheetAction getAction(String actionId) {
536: if (actionMap == null) {
537: actionMap = new HashMap();
538: addActions(getActionList());
539: }
540: return (CommonSpreadSheetAction) actionMap.get(actionId);
541: }
542:
543: private void addAction(String action, String spreadSheetActionId,
544: CommonSpreadSheetAction spreadSheetAction) {
545: if (spreadSheetActionId.equals(action)) {
546: actionMap.put(spreadSheetActionId, spreadSheetAction);
547: }
548: }
549:
550: private void addActions(String[] actions) {
551: // System.out.println("SpreadSheet "+spreadSheetCategory+", "+hashCode()+" addActions("+dumpActions(actions)+")");
552: NodeListTransferHandler handler = null;
553: if (getTransferHandler() instanceof NodeListTransferHandler)
554: handler = (NodeListTransferHandler) getTransferHandler();
555: if (actions != null)
556: for (int i = 0; i < actions.length; i++) {
557: String action = actions[i];
558: addAction(action, MenuActionConstants.ACTION_INDENT,
559: indentAction);
560: addAction(action, MenuActionConstants.ACTION_OUTDENT,
561: outdentAction);
562: addAction(action, MenuActionConstants.ACTION_NEW,
563: newAction);
564: addAction(action, MenuActionConstants.ACTION_DELETE,
565: deleteAction);
566: if (handler != null) {
567: addAction(action, MenuActionConstants.ACTION_COPY,
568: handler.getNodeListCopyAction());
569: addAction(action, MenuActionConstants.ACTION_CUT,
570: handler.getNodeListCutAction());
571: addAction(action, MenuActionConstants.ACTION_PASTE,
572: handler.getNodeListPasteAction());
573: }
574: addAction(action, MenuActionConstants.ACTION_EXPAND,
575: expandAction);
576: addAction(action, MenuActionConstants.ACTION_COLLAPSE,
577: collapseAction);
578:
579: }
580: }
581:
582: public void clearActions() {
583: actionMap = null;
584: actionList = null;
585: popup = null;
586: ((CommonSpreadSheetModel) getModel()).clearActions();
587: }
588:
589: // private static String dumpActions(String[] actions){
590: // if (actions==null) return null;
591: // StringBuffer sb=new StringBuffer();
592: // for (int i=0;i<actions.length;i++){
593: // sb.append(actions[i]).append(',');
594: // }
595: // return sb.toString();
596: // }
597: public void setActions(String[] actions) {
598: //replace default actions
599: actionList = actions;
600: if (actionMap == null)
601: actionMap = new HashMap();
602: else
603: actionMap.clear();
604: addActions(actions);
605: }
606:
607: public void setActions(String actions) {
608: addActions(CommonSpreadSheetModel.convertActions(actions));
609: }
610:
611: // public static final String INDENT = "Action.Indent";
612: // public static final String OUTDENT = "Action.Outdent";
613: // public static final String NEW = "Action.New";
614: // public static final String DELETE = "Action.Delete";
615: // public static final String CUT = "Action.Cut";
616: // public static final String COPY = "Action.Copy";
617: // public static final String PASTE = "Action.Paste";
618:
619: // public static final int INDENT = 0;
620: //
621: // public static final int OUTDENT = 1;
622: //
623: // public static final int NEW = 2;
624: //
625: // public static final int DELETE = 3;
626: //
627: // public static final int CUT = 4;
628: //
629: //
630: // public static final int COPY = 5;
631: //
632: // public static final int PASTE = 6;
633:
634: public static abstract class SpreadSheetAction extends
635: AbstractAction implements Closure, CommonSpreadSheetAction {
636: protected SpreadSheet spreadSheet;
637:
638: protected int[] rows;
639:
640: public SpreadSheetAction(String id, SpreadSheet spreadSheet) {
641: super (Messages.getString(id));
642: this .spreadSheet = spreadSheet;
643: }
644:
645: public void actionPerformed(ActionEvent e) {
646: execute();
647: }
648:
649: public void executeFirst() {
650: rows = spreadSheet.finishCurrentOperations();
651: }
652:
653: public void execute(Object o) {
654: executeFirst();
655: execute();
656: }
657:
658: public abstract void execute();
659:
660: public CommonSpreadSheet getSpreadSheet() {
661: return spreadSheet;
662: }
663:
664: public void setSpreadSheet(CommonSpreadSheet spreadSheet) {
665: this .spreadSheet = (SpreadSheet) spreadSheet;
666: }
667:
668: public NodeModelCache getCache() {
669: return ((SpreadSheetModel) spreadSheet.getModel())
670: .getCache();
671: }
672:
673: public List getSelected() {
674: return spreadSheet
675: .rowsToGraphicNodes((rows == null) ? spreadSheet
676: .getSelectedRows() : rows);
677: }
678: }
679:
680: protected SpreadSheetAction indentAction = new SpreadSheetAction(
681: "Spreadsheet.Action.indent", this ) {
682: public void execute() {
683: finishCurrentOperations();
684: getCache().indentNodes(getSelected());
685: }
686: };
687:
688: protected SpreadSheetAction outdentAction = new SpreadSheetAction(
689: "Spreadsheet.Action.outdent", this ) {
690: public void execute() {
691: finishCurrentOperations();
692: getCache().outdentNodes(getSelected());
693: }
694: };
695:
696: protected SpreadSheetAction newAction = new SpreadSheetAction(
697: "Spreadsheet.Action.new", this ) {
698: public void execute() {
699: List nodes = getSelected();
700: if (nodes == null || nodes.size() == 0) {
701: int row = getCurrentRow();
702: if (row == -1)
703: return;
704: getCache().newNode(
705: (GraphicNode) getCache().getElementAt(row));
706: } else {
707: getCache().newNode(
708: (GraphicNode) nodes.get(nodes.size() - 1));
709: }
710: }
711: };
712:
713: //will be used later
714: protected SpreadSheetAction newResourceAction = new SpreadSheetAction(
715: "Spreadsheet.Action.new", this ) {
716: public void execute() {
717: List nodes = getSelected();
718: final ResourcePool resourcePool = (ResourcePool) getCache()
719: .getModel().getDataFactory();
720: Project project = (Project) resourcePool.getProjects().get(
721: 0);
722: if (nodes == null || nodes.size() == 0)
723: return;
724: final ArrayList descriptors = new ArrayList();
725: Session session = SessionFactory.getInstance().getSession(
726: false);
727: Job job = (Job) SessionFactory.callNoEx(session,
728: "getLoadProjectDescriptorsJob", new Class[] {
729: boolean.class, java.util.List.class,
730: boolean.class }, new Object[] { true,
731: descriptors, true });
732: job.addSwingRunnable(new JobRunnable("Local: addNodes") {
733: public Object run() throws Exception {
734: final Closure setter = new Closure() {
735: public void execute(Object obj) {
736: }
737: };
738: final Closure getter = new Closure() {
739: public void execute(Object obj) {
740: ResourceAdditionDialog.Form form = (ResourceAdditionDialog.Form) obj;
741: List nodes = new ArrayList();
742: for (Iterator i = form
743: .getSelectedResources().iterator(); i
744: .hasNext();) {
745: try {
746: nodes
747: .add(NodeFactory
748: .getInstance()
749: .createNode(
750: Serializer
751: .deserializeResourceAndAddToPool(
752: (EnterpriseResourceData) i
753: .next(),
754: resourcePool,
755: null)));
756: } catch (IOException e) {
757: // TODO Auto-generated catch block
758: e.printStackTrace();
759: } catch (ClassNotFoundException e) {
760: // TODO Auto-generated catch block
761: e.printStackTrace();
762: }
763: }
764: getCache()
765: .addNodes(
766: ((GraphicNode) getSelected()
767: .get(0)).getNode(),
768: nodes);
769: getCache().update();
770: }
771: };
772: ResourceAdditionDialog.Form form = new ResourceAdditionDialog.Form();
773: try {
774: List resources = (List) SessionFactory.call(
775: SessionFactory.getInstance()
776: .getSession(false),
777: "retrieveResourceDescriptors", null,
778: null);
779: HashMap resourceMap = new HashMap();
780: for (Iterator i = resources.iterator(); i
781: .hasNext();) {
782: EnterpriseResourceData data = (EnterpriseResourceData) i
783: .next();
784: resourceMap.put(
785: new Long(data.getUniqueId()), data);
786: }
787: List currentResources = resourcePool
788: .getResourceList();
789: for (Iterator i = currentResources.iterator(); i
790: .hasNext();) {
791: ResourceImpl resource = (ResourceImpl) i
792: .next();
793: Long key = new Long(resource.getUniqueId());
794: if (resourceMap.containsKey(key))
795: resourceMap.remove(key);
796: }
797: form.getSelectedResources().addAll(
798: resourceMap.values());
799: } catch (Exception e) {
800: }
801:
802: ResourceAdditionDialog.getInstance(
803: (JFrame) SwingUtilities
804: .getRoot(SpreadSheet.this ), form)
805: .execute(setter, getter);
806: return null;
807: }
808: });
809: session.schedule(job);
810: }
811: };
812:
813: protected SpreadSheetAction deleteAction = new SpreadSheetAction(
814: "Spreadsheet.Action.delete", this ) {
815: private static final long serialVersionUID = 1561847977122331970L;
816:
817: public void execute() {
818: finishCurrentOperations();
819: List l = getSelectedDeletableRows();
820: if (l.isEmpty())
821: return;
822: if (!GeneralOption.getInstance().isConfirmDeletes()
823: || Alert.okCancel(Messages
824: .getString("Message.confirmDeleteRows"))) {
825: getCache().deleteNodes(l);
826: }
827: }
828: };
829:
830: protected SpreadSheetAction cutAction = new SpreadSheetAction(
831: "Spreadsheet.Action.cut", this ) {
832: private static final long serialVersionUID = -7928292866527615772L;
833:
834: public void execute() {
835: finishCurrentOperations();
836: execute(getSelectedRows());
837: }
838:
839: public void execute(Object object) {
840: if (object != null && object instanceof List) {
841: finishCurrentOperations();
842: List nodes = getSelectedCuttableRows((List) object);
843: if (nodes.isEmpty())
844: return;
845: executeFirst();
846: getCache().cutNodes(nodes);
847: }
848: }
849: };
850:
851: protected SpreadSheetAction copyAction = new SpreadSheetAction(
852: "Spreadsheet.Action.copy", this ) {
853: /**
854: *
855: */
856: private static final long serialVersionUID = -7593036949653490043L;
857:
858: public void execute() {
859: execute(getSelectedNodes());
860: }
861:
862: public void execute(Object object) {
863: if (object != null && object instanceof List) {
864: finishCurrentOperations();
865: List nodes = (List) object;
866: executeFirst();
867: getCache().copyNodes(nodes);
868: }
869: }
870: };
871:
872: protected SpreadSheetAction pasteAction = new SpreadSheetAction(
873: "Spreadsheet.Action.paste", this ) {
874: private static final long serialVersionUID = 5904764895696983803L;
875:
876: public void execute() {
877: execute(getSelectedNodes());
878: }
879:
880: public void execute(Object object) {
881: if (object != null && object instanceof List) {
882: finishCurrentOperations();
883: List selectedNodes = getSelectedNodes();
884: Node parent = null;
885: int position = 0;
886: if (selectedNodes.size() > 0) {
887: Node node = (Node) selectedNodes.get(0);
888: parent = (Node) node.getParent();
889: position = ((NodeBridge) parent).getIndex(node);
890: }
891: List nodes = (List) object;
892: executeFirst();
893: spreadSheet.clearSelection();
894: getCache().pasteNodes(parent, nodes, position);
895: // if (nodes.size() > 0) {
896: // int row = ((SpreadSheetModel) spreadSheet.getModel()).findGraphicNodeRow(spreadSheet.getCache().getGraphicNode(nodes.get(0)));
897: // changeSelection(row, 0, false, false);
898: // if (nodes.size() > 1)
899: // changeSelection(row + nodes.size() - 1, getColumnCount(), false, true);
900: // }
901: }
902: }
903: };
904:
905: protected SpreadSheetAction expandAction = new SpreadSheetAction(
906: "Spreadsheet.Action.expand", this ) {
907: public void execute() {
908: finishCurrentOperations();
909: getCache().expandNodes(getSelected(), true);
910: }
911: };
912: protected SpreadSheetAction collapseAction = new SpreadSheetAction(
913: "Spreadsheet.Action.collapse", this ) {
914: public void execute() {
915: finishCurrentOperations();
916: getCache().expandNodes(getSelected(), false);
917: }
918: };
919:
920: public boolean isReadOnly() {
921: return ((SpreadSheetModel) getModel()).isReadOnly();
922: }
923:
924: public void setReadOnly(boolean readOnly) {
925: ((SpreadSheetModel) getModel()).setReadOnly(readOnly);
926: }
927:
928: // private static final int[] DEFAULT_POPUP_OPTIONS = new int[] {INDENT,OUTDENT,NEW,DELETE,CUT,COPY,PASTE};
929: // private int[] popupActions = DEFAULT_POPUP_OPTIONS;
930: // public final void setPopupActions(int[] popupActions) {
931: // this.popupActions = popupActions;
932: // }
933:
934: // public boolean supportsAction(int option) {
935: // if (popupActions == null)
936: // return false;
937: // for (int i = 0; i<popupActions.length; i++) {
938: // if (popupActions[i] == option)
939: // return true;
940: // }
941: // return false;
942: // }
943: // public boolean hasRowPopup() {
944: // return popupActions != null && popupActions.length > 0;
945: // }
946: public boolean hasRowPopup() {
947: getAction(null);
948: return actionMap != null && actionMap.size() > 0;
949: }
950:
951: public SpreadSheetAction getCopyAction() {
952: return copyAction;
953: }
954:
955: public SpreadSheetAction getCutAction() {
956: return cutAction;
957: }
958:
959: public SpreadSheetAction getPasteAction() {
960: return pasteAction;
961: }
962:
963: }
|