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.common.transfer;
051:
052: import java.awt.datatransfer.Clipboard;
053: import java.awt.datatransfer.DataFlavor;
054: import java.awt.datatransfer.Transferable;
055: import java.awt.datatransfer.UnsupportedFlavorException;
056: import java.io.IOException;
057: import java.text.MessageFormat;
058: import java.util.ArrayList;
059: import java.util.Enumeration;
060: import java.util.Iterator;
061: import java.util.List;
062:
063: import javax.swing.Action;
064: import javax.swing.ActionMap;
065: import javax.swing.InputMap;
066: import javax.swing.JComponent;
067: import javax.swing.KeyStroke;
068: import javax.swing.TransferHandler;
069:
070: import org.apache.commons.collections.Closure;
071: import org.apache.commons.collections.Predicate;
072: import org.apache.commons.collections.Transformer;
073:
074: import com.projity.grouping.core.Node;
075: import com.projity.grouping.core.model.NodeModel;
076: import com.projity.grouping.core.model.NodeModelDataFactory;
077: import com.projity.pm.graphic.spreadsheet.SpreadSheet;
078: import com.projity.pm.graphic.spreadsheet.SpreadSheetModel;
079: import com.projity.pm.graphic.spreadsheet.common.CommonSpreadSheetModel;
080: import com.projity.pm.task.NormalTask;
081: import com.projity.pm.task.Project;
082: import com.projity.pm.task.SubProj;
083: import com.projity.pm.task.Task;
084: import com.projity.strings.Messages;
085: import com.projity.util.Alert;
086:
087: /**
088: *
089: */
090: public class NodeListTransferHandler extends TransferHandler {
091: public NodeListTransferHandler(SpreadSheet spreadSheet) {
092: super ();
093: this .spreadSheet = spreadSheet;
094: }
095:
096: transient protected SpreadSheet spreadSheet;
097:
098: public SpreadSheet getSpreadSheet() {
099: return spreadSheet;
100: }
101:
102: public void setSpreadSheet(SpreadSheet spreadSheet) {
103: this .spreadSheet = spreadSheet;
104: }
105:
106: public void exportToClipboard(JComponent c, Clipboard clip,
107: int action) {
108: boolean exportSuccess = false;
109: Transferable t = null;
110:
111: if (action != NONE) {
112: t = createTransferable(c, action);
113: if (t != null) {
114: clip.setContents(t, null);
115: exportSuccess = true;
116: }
117: }
118:
119: if (exportSuccess) {
120: exportDone(c, t, action);
121: } else {
122: exportDone(c, null, NONE);
123: }
124: }
125:
126: private boolean transformSubprojectBranches(Node parent,
127: NodeModelDataFactory dataFactory, Predicate p) {
128: if (dataFactory instanceof Project
129: && parent.getImpl() instanceof SubProj
130: // &&!((Project)dataFactory).getSubprojectHandler().canInsertProject( ((SubProj)parent.getImpl()).getSubprojectUniqueId() )
131: //TODO disabled, improve paste of subprojects
132: ) {
133: if (!p.evaluate(parent))
134: return false;
135:
136: }
137: for (Enumeration e = parent.children(); e.hasMoreElements();) {
138: Node node = (Node) e.nextElement();
139: if (!transformSubprojectBranches(node, dataFactory, p))
140: return false;
141:
142: }
143: return true;
144: }
145:
146: protected Transferable createTransferable(JComponent c, int action) {
147: SpreadSheet spreadSheet = getSpreadSheet(c);
148: if (spreadSheet == null)
149: return null;
150: ArrayList nodes = (ArrayList) spreadSheet.getSelectedNodes()
151: .clone();
152:
153: ArrayList fields = spreadSheet.getSelectedFields();
154: boolean nodeSelection = (fields == null);
155: if (fields == null)
156: fields = spreadSheet.getSelectableFields();
157: if (action == TransferHandler.COPY) {
158: if (nodeSelection) {
159: SpreadSheet.SpreadSheetAction a = getNodeListCopyAction()
160: .getSpreadSheetAction();
161: a.execute(nodes);
162: }
163: return new NodeListTransferable(nodes, fields, spreadSheet,
164: spreadSheet.getSelectedRows(), spreadSheet
165: .getSelectedColumns(), nodeSelection);
166: } else if (action == TransferHandler.MOVE) {//cut
167: if (nodeSelection) {
168: SpreadSheet.SpreadSheetAction a = ((nodeSelection) ? getNodeListCutAction()
169: : getNodeListCopyAction())
170: .getSpreadSheetAction();
171:
172: for (Iterator i = nodes.iterator(); i.hasNext();) {
173: Node node = (Node) i.next();
174: final boolean[] okForAll = new boolean[] { false };
175: if (!transformSubprojectBranches(node, spreadSheet
176: .getCache().getModel().getDataFactory(),
177: new Predicate() {
178: public boolean evaluate(Object arg0) {
179: if (okForAll[0])
180: return true;
181: Node parent = (Node) arg0;
182: boolean r = Alert
183: .okCancel(Messages
184: .getString("Message.subprojectCut"));
185: if (r)
186: okForAll[0] = true;
187: return r;
188: }
189:
190: }))
191: return null;
192: }
193:
194: a.execute(nodes);
195: }
196: return new NodeListTransferable(nodes, fields, spreadSheet,
197: spreadSheet.getSelectedRows(), spreadSheet
198: .getSelectedColumns(), nodeSelection);
199: } else
200: return null;
201: }
202:
203: protected void exportDone(JComponent source, Transferable data,
204: int action) {
205: }
206:
207: public boolean importData(JComponent c, Transferable t) {
208: SpreadSheet spreadSheet = getSpreadSheet(c);
209: if (spreadSheet == null)
210: return false;
211: DataFlavor flavor = getFlavor(t.getTransferDataFlavors());
212: if (flavor != null) {
213: try {
214: NodeModel model = ((CommonSpreadSheetModel) spreadSheet
215: .getModel()).getCache().getModel();
216: Object data = t.getTransferData(flavor);
217: if (data == null)
218: return false;
219: List nodes = null;
220: if (data instanceof ArrayList) {
221: nodes = (List) data;
222:
223: for (Iterator i = nodes.iterator(); i.hasNext();) {
224: Node node = (Node) i.next();
225: transformSubprojectBranches(node, model
226: .getDataFactory(), new Predicate() {
227: public boolean evaluate(Object arg0) {
228: Node parent = (Node) arg0;
229: //change implementation
230: NormalTask task = new NormalTask();
231: Task source = ((Task) parent.getImpl());
232: source.cloneTo(task);
233: //task.setDuration(source.getActualDuration());
234: parent.setImpl(task);
235: return true;
236: }
237: });
238: }
239:
240: SpreadSheet.SpreadSheetAction a = getNodeListPasteAction()
241: .getSpreadSheetAction();
242: a.execute(nodes);
243: } else if (data instanceof String) {
244: // ArrayList fields=spreadSheet.getSelectedFields();
245: // if (fields==null){
246: // fields=spreadSheet.getSelectableFields(); //The whole line is selected
247: // nodes=NodeListTransferable.stringToNodeList((String)data,spreadSheet,fields,model.getDataFactory());
248: // }else{
249: // NodeListTransferable.pasteString((String)data,spreadSheet);
250: // }
251: NodeListTransferable.pasteString((String) data,
252: spreadSheet);
253: } else
254: return false;
255:
256: return true;
257: } catch (UnsupportedFlavorException ufe) {
258: } catch (IOException ioe) {
259: }
260: }
261: return false;
262: }
263:
264: protected SpreadSheet getSpreadSheet(JComponent c) {
265: if (c instanceof SpreadSheet) {
266: return (SpreadSheet) c;
267: } else
268: return null;
269: }
270:
271: protected DataFlavor getFlavor(DataFlavor[] flavors) {
272: // for (int i=0;i<flavors.length;i++){
273: // System.out.println("flavor #"+i+": "+flavors[i]);
274: // }
275: NodeListTransferable t = new NodeListTransferable(null, null,
276: null, null, null, true);
277: for (int i = 0; i < flavors.length; i++) {
278: if (t.isDataFlavorSupported(flavors[i]))
279: return flavors[i];
280: }
281: return null;
282: }
283:
284: public boolean canImport(JComponent c, DataFlavor[] flavors) {
285: return getFlavor(flavors) != null;
286: }
287:
288: public static void registerWith(SpreadSheet spreadSheet) {
289: NodeListTransferHandler handler = new NodeListTransferHandler(
290: spreadSheet);
291: // if (c instanceof SpreadSheet){
292: // SpreadSheet spreadSheet=(SpreadSheet)c;
293: // handler.setSpreadSheet(spreadSheet);
294: // }
295: spreadSheet.setTransferHandler(handler);
296:
297: InputMap imap = spreadSheet.getInputMap();
298: imap.put(KeyStroke.getKeyStroke("ctrl X"),
299: NodeListTransferHandler.getCutAction().getValue(
300: Action.NAME));
301: imap.put(KeyStroke.getKeyStroke("ctrl C"),
302: NodeListTransferHandler.getCopyAction().getValue(
303: Action.NAME));
304: imap.put(KeyStroke.getKeyStroke("ctrl V"),
305: NodeListTransferHandler.getPasteAction().getValue(
306: Action.NAME));
307: //c.setInputMap(JComponent.WHEN_FOCUSED,imap);
308:
309: ActionMap amap = spreadSheet.getActionMap();
310: amap.put(NodeListTransferHandler.getCutAction().getValue(
311: Action.NAME), NodeListTransferHandler.getCutAction());
312: amap.put(NodeListTransferHandler.getCopyAction().getValue(
313: Action.NAME), NodeListTransferHandler.getCopyAction());
314: amap.put(NodeListTransferHandler.getPasteAction().getValue(
315: Action.NAME), NodeListTransferHandler.getPasteAction());
316:
317: }
318:
319: protected transient NodeListTransfertAction nodeListCutAction,
320: nodeListCopyAction, nodeListPasteAction;
321:
322: protected void initCutAction(SpreadSheet.SpreadSheetAction a) {
323: nodeListCutAction = new NodeListTransfertAction(getCutAction(),
324: a, spreadSheet);
325: nodeListCutAction.putValue("Name", Messages
326: .getString("Spreadsheet.Action.cut"));
327: }
328:
329: protected void initCopyAction(SpreadSheet.SpreadSheetAction a) {
330: nodeListCopyAction = new NodeListTransfertAction(
331: getCopyAction(), a, spreadSheet);
332: nodeListCopyAction.putValue("Name", Messages
333: .getString("Spreadsheet.Action.copy"));
334: }
335:
336: protected void initPasteAction(SpreadSheet.SpreadSheetAction a) {
337: nodeListPasteAction = new NodeListTransfertAction(
338: getPasteAction(), a, spreadSheet);
339: nodeListPasteAction.putValue("Name", Messages
340: .getString("Spreadsheet.Action.paste"));
341: }
342:
343: public NodeListTransfertAction getNodeListCopyAction() {
344: if (nodeListCopyAction == null)
345: initCopyAction(spreadSheet.getCopyAction());
346: return nodeListCopyAction;
347: }
348:
349: public NodeListTransfertAction getNodeListCutAction() {
350: if (nodeListCutAction == null)
351: initCutAction(spreadSheet.getCutAction());
352: return nodeListCutAction;
353: }
354:
355: public NodeListTransfertAction getNodeListPasteAction() {
356: if (nodeListPasteAction == null)
357: initPasteAction(spreadSheet.getPasteAction());
358: return nodeListPasteAction;
359: }
360:
361: }
|