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.dialog.assignment;
051:
052: import java.awt.event.ActionEvent;
053: import java.util.ArrayList;
054: import java.util.Iterator;
055: import java.util.List;
056:
057: import javax.swing.AbstractAction;
058: import javax.swing.JButton;
059: import javax.swing.JComponent;
060: import javax.swing.JLabel;
061: import javax.swing.JPanel;
062:
063: import com.jgoodies.forms.builder.DefaultFormBuilder;
064: import com.jgoodies.forms.layout.CellConstraints;
065: import com.jgoodies.forms.layout.FormLayout;
066: import com.projity.configuration.Settings;
067: import com.projity.dialog.AbstractDialog;
068: import com.projity.dialog.ButtonPanel;
069: import com.projity.document.ObjectEvent;
070: import com.projity.grouping.core.NodeList;
071: import com.projity.grouping.core.transform.filtering.NodeFilter;
072: import com.projity.grouping.core.transform.filtering.NotAssignmentFilter;
073: import com.projity.help.HelpUtil;
074: import com.projity.pm.assignment.Assignment;
075: import com.projity.pm.assignment.AssignmentService;
076: import com.projity.pm.graphic.IconManager;
077: import com.projity.pm.graphic.frames.DocumentFrame;
078: import com.projity.pm.graphic.frames.DocumentSelectedEvent;
079: import com.projity.pm.graphic.frames.GraphicManager;
080: import com.projity.pm.graphic.spreadsheet.SpreadSheet;
081: import com.projity.pm.graphic.spreadsheet.selection.event.SelectionNodeEvent;
082: import com.projity.pm.graphic.spreadsheet.selection.event.SelectionNodeListener;
083: import com.projity.pm.graphic.views.GanttView;
084: import com.projity.pm.resource.Resource;
085: import com.projity.pm.task.NormalTask;
086: import com.projity.pm.task.Project;
087: import com.projity.pm.task.Task;
088: import com.projity.preference.GlobalPreferences;
089: import com.projity.strings.Messages;
090: import com.projity.util.Alert;
091: import com.projity.util.DataUtils;
092: import com.projity.util.Environment;
093:
094: public final class AssignmentDialog extends AbstractDialog implements
095: DocumentSelectedEvent.Listener, SelectionNodeListener,
096: ResourceAssigner, ObjectEvent.Listener, CommonAssignmentDialog {
097: private static final long serialVersionUID = 1L;
098: DocumentFrame documentFrame;
099: AssignmentEntryPane spreadSheetPane;
100: JLabel taskNames;
101: // JLabel projectName;
102: JButton assignButton;
103: JButton removeButton;
104: JButton replaceButton;
105: JButton stopEditorButton;
106: JButton cancelEditorButton;
107: JPanel editorsButtons = null;
108: JLabel showingTeamAll = null;
109: List selectedTasks = null;
110:
111: public AssignmentDialog(DocumentFrame documentFrame) {
112: super (documentFrame.getGraphicManager().getFrame(), Messages
113: .getString("Text.AssignResources"), false); //$NON-NLS-1$
114: setDocumentFrame(documentFrame);
115: DocumentSelectedEvent.addListener(this );
116: addDocHelp("Assign_Resources");
117: //createContentPanel();
118: }
119:
120: /**
121: * Creates, intializes and configures the UI components. Real applications
122: * may further bind the components to underlying models.
123: */
124: protected void initControls() {
125: GraphicManager mf = documentFrame.getGraphicManager();
126: spreadSheetPane = new AssignmentEntryPane(this , documentFrame
127: .getProject(), this , false, mf
128: .setAssignmentDialogTransformerInitializationClosure());
129: // projectName = new JLabel();
130: taskNames = new JLabel();
131: Project project = documentFrame.getProject();
132: spreadSheetPane.setProject(project); //init content of spreadsheet
133: setSelectedTasks(mf.getCurrentFrame().getTopSpreadSheet()
134: .getSelectedNodes()); //update
135:
136: // projectName.setAlignmentX(JLabel.LEFT_ALIGNMENT);
137: // projectName.setText(project == null ? "" : "Resources from: " + project.getName());
138: AbstractAction assignAction = new AbstractAction(Messages
139: .getString("Text.Assign")) { //$NON-NLS-1$
140: private static final long serialVersionUID = 1L;
141:
142: public void actionPerformed(ActionEvent e) {
143: AssignmentDialog.this .assign();
144: }
145: };
146: assignButton = new JButton(assignAction);
147:
148: AbstractAction removeAction = new AbstractAction(Messages
149: .getString("Text.Remove")) { //$NON-NLS-1$
150: private static final long serialVersionUID = 1L;
151:
152: public void actionPerformed(ActionEvent e) {
153: AssignmentDialog.this .remove();
154: }
155: };
156: removeButton = new JButton(removeAction);
157:
158: AbstractAction replaceAction = new AbstractAction(Messages
159: .getString("Text.Replace") + Settings.ELLIPSIS) { //$NON-NLS-1$
160: private static final long serialVersionUID = 1L;
161:
162: public void actionPerformed(ActionEvent e) {
163: AssignmentDialog.this .replace();
164: }
165: };
166: replaceButton = new JButton(replaceAction);
167:
168: stopEditorButton = new JButton(new AbstractAction(null,
169: IconManager.getIcon("dialog.ok")) { //$NON-NLS-1$
170: private static final long serialVersionUID = 1L;
171:
172: public void actionPerformed(ActionEvent e) {
173: if (spreadSheetPane.getSpreadSheet()
174: .getCellEditor() != null)
175: spreadSheetPane.getSpreadSheet()
176: .getCellEditor().stopCellEditing();
177: }
178: });
179: cancelEditorButton = new JButton(new AbstractAction(null,
180: IconManager.getIcon("dialog.cancel")) { //$NON-NLS-1$
181: private static final long serialVersionUID = 1L;
182:
183: public void actionPerformed(ActionEvent e) {
184: SpreadSheet sp = spreadSheetPane
185: .getSpreadSheet();
186: if (sp.getCellEditor() != null)
187: sp.getCellEditor().cancelCellEditing();
188: sp.clearSelection();
189: }
190: });
191: setEditorButtonsVisible(false);
192:
193: documentFrame.getProject().addObjectListener(this );
194: documentFrame.getGraphicManager().getPreferences()
195: .addObjectListener(this );
196:
197: }
198:
199: public void setEditorButtonsVisible(boolean visible) {
200: stopEditorButton.setEnabled(visible);
201: cancelEditorButton.setEnabled(visible);
202: }
203:
204: void assign() {
205: SpreadSheet sp = spreadSheetPane.getSpreadSheet();
206: if (sp.isEditing())
207: sp.getCellEditor().stopCellEditing();
208: assign(getSelectedResources(), 1.0D);
209: spreadSheetPane.updateTable();
210: }
211:
212: void assign(List resourceList, double units) {
213: if (selectedTasks == null) // if no selection, do nothing
214: return;
215: NormalTask task;
216: Iterator t = selectedTasks.iterator();
217: Object current = null;
218: List taskList = new ArrayList();
219: while (t.hasNext()) { // go thru all selected tasks
220: current = t.next();
221: if (!(current instanceof NormalTask))
222: continue;
223: task = (NormalTask) current;
224: if (!task.isAssignable())
225: continue;
226: taskList.add(task);
227: }
228: AssignmentService.getInstance().newAssignments(taskList,
229: resourceList, units, 0, this , true);
230: spreadSheetPane.updateTable();
231: }
232:
233: public void assign(Resource resource, double units) {
234: ArrayList list = new ArrayList();
235: list.add(resource);
236: assign(list, units);
237: }
238:
239: /**
240: * Removes given the current task and resource selection
241: *
242: */
243: void remove() {
244: remove(getSelectedResources());
245: }
246:
247: /**
248: * Removes given the current task selection for the given resource lsit
249: * @param resourceList
250: */
251: void remove(List resourceList) {
252: Resource resource;
253: Iterator r = getSelectedResources().iterator();
254: while (r.hasNext()) {
255: remove((Resource) r.next());
256: }
257: spreadSheetPane.updateTable();
258: }
259:
260: /**
261: * Removes given resource from current task selection
262: * @param resource
263: * @param selectedTasks
264: */
265: void remove(Resource resource) {
266: Iterator t = selectedTasks.iterator();
267: NormalTask task;
268: Assignment assignment;
269: while (t.hasNext()) {
270: task = (NormalTask) t.next();
271: assignment = task.findAssignment(resource);
272: if (assignment != null)
273: AssignmentService.getInstance().remove(assignment,
274: this , true);
275: }
276: }
277:
278: void replace() {
279: List list = spreadSheetPane.getSelectedResources(true);
280: if (list.size() > 1) {
281: Alert
282: .warn(
283: Messages
284: .getString("Message.onlyReplaceOneResourceAtATime"), this ); //$NON-NLS-1$
285: return;
286: } else if (list.size() == 0) {
287: return;
288: }
289: Resource resource = (Resource) list.get(0);
290: List replacementList = ReplaceAssignmentDialog
291: .getReplacementFromDialog(documentFrame, resource);
292: if (replacementList == null || replacementList.isEmpty()) // cancelled or nothing chosen
293: return;
294: if (!replacementList.contains(resource)) // if resource was replaced, remove it
295: remove(resource);
296: else
297: // resource is in new list too, so don't touch it
298: replacementList.remove(resource);
299: assign(replacementList, 1.0); //TODO assign what the old one was assigned
300: }
301:
302: // Building *************************************************************
303:
304: /**
305: * Builds the panel. Initializes and configures components first, then
306: * creates a FormLayout, configures the layout, creates a builder, sets a
307: * border, and finally adds the components.
308: *
309: * @return the built panel
310: */
311:
312: private JLabel getTeamOrAllLabel() {
313: if (showingTeamAll == null)
314: showingTeamAll = new JLabel(
315: Messages
316: .getString("AssignmentDialog.ShowingAllResources"), IconManager.getIcon("menu24.showAllResources"), JLabel.LEFT); //$NON-NLS-1$ //$NON-NLS-2$
317:
318: if (documentFrame.getGraphicManager().getPreferences()
319: .isShowProjectResourcesOnly()) {
320: showingTeamAll.setIcon(IconManager
321: .getIcon("menu24.showTeamResources")); //$NON-NLS-1$
322: showingTeamAll
323: .setText(Messages
324: .getString("AssignmentDialog.ShowingOnlyResourcesOnTheProjectTeam")); //$NON-NLS-1$
325: } else {
326: showingTeamAll.setIcon(IconManager
327: .getIcon("menu24.showAllResources")); //$NON-NLS-1$
328: showingTeamAll.setText(Messages
329: .getString("AssignmentDialog.ShowingAllResources")); //$NON-NLS-1$
330: }
331: HelpUtil.addDocHelp(showingTeamAll, "Project_Team");
332: return showingTeamAll;
333: }
334:
335: public JComponent createContentPanel() {
336:
337: // Separating the component initialization and configuration
338: // from the layout code makes both parts easier to read.
339: initControls();
340: FormLayout layout = new FormLayout(
341: "p, 1dlu, default ,3dlu, default", // cols //$NON-NLS-1$
342: "p, 3dlu," + (Environment.getStandAlone() ? "" : "p, 3dlu,") + "fill:200dlu:grow"); // rows //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
343:
344: // Create a builder that assists in adding components to the container.
345: // Wrap the panel with a standardized border.
346: DefaultFormBuilder builder = new DefaultFormBuilder(layout);
347: builder.setDefaultDialogBorder();
348: CellConstraints cc = new CellConstraints();
349: // task names span whole dialog
350: builder.add(taskNames, cc.xyw(builder.getColumn(), builder
351: .getRow(), builder.getColumnCount()));
352: builder.nextLine(2);
353:
354: if (!Environment.getStandAlone()) {
355: builder.add(getTeamOrAllLabel(), cc.xyw(
356: builder.getColumn(), builder.getRow(), builder
357: .getColumnCount()));
358: builder.nextLine(2);
359: }
360:
361: // builder.append(projectName);
362: // builder.nextLine(2);
363:
364: builder.append(spreadSheetPane, createEditorsButtons(),
365: createButtons());
366: return builder.getPanel();
367: }
368:
369: public JComponent createEditorsButtons() {
370: FormLayout layout = new FormLayout("20px", // cols //$NON-NLS-1$
371: "20dlu,20px, 3dlu, 20px"); // rows //$NON-NLS-1$
372: DefaultFormBuilder builder = new DefaultFormBuilder(layout);
373: builder.nextLine(1);
374: builder.append(stopEditorButton);
375: builder.nextLine(2);
376: builder.append(cancelEditorButton);
377: editorsButtons = builder.getPanel();
378: return editorsButtons;
379: }
380:
381: public JComponent createButtons() {
382: FormLayout layout = new FormLayout("default", // cols //$NON-NLS-1$
383: "50dlu,p, 3dlu, p, 3dlu, p"); // rows //$NON-NLS-1$
384: DefaultFormBuilder builder = new DefaultFormBuilder(layout);
385: builder.nextLine(1);
386: builder.append(assignButton);
387: builder.nextLine(2);
388: builder.append(removeButton);
389: builder.nextLine(2);
390: builder.append(replaceButton);
391: return builder.getPanel();
392: }
393:
394: public ButtonPanel createButtonPanel() {
395: return null;
396: }
397:
398: /**
399: * @return Returns the project.
400: */
401: public DocumentFrame getDocumentFrame() {
402: return documentFrame;
403: }
404:
405: /**
406: * @param project The project to set.
407: */
408: public void setDocumentFrame(DocumentFrame documentFrame) {
409: if (documentFrame != null)
410: documentFrame.getProject().removeObjectListener(this );
411: this .documentFrame = documentFrame;
412: Project project = documentFrame.getProject();
413: project.getResourcePool().addObjectListener(this );
414: // if (projectName != null)
415: // projectName.setText(project == null ? "" : "Resources from: " + project.getName());
416: }
417:
418: private static ArrayList emptyList = new ArrayList();
419:
420: public void documentSelected(DocumentSelectedEvent evt) {
421: setDocumentFrame(evt.getCurrent());
422: spreadSheetPane.setProject(getDocumentFrame().getProject());
423: setSelectedTasks(emptyList);
424: }
425:
426: /* (non-Javadoc)
427: * @see com.projity.pm.graphic.spreadsheet.selection.SelectionNodeListener#selectionChanged(com.projity.pm.graphic.spreadsheet.selection.SelectionNodeEvent)
428: */
429: public void selectionChanged(SelectionNodeEvent e) {
430: if (e.getCategory() != GanttView.spreadsheetCategory) //TODO this is kinda ugly.
431: return;
432: List selectedNodes = e.getNodes();
433: setSelectedTasks(selectedNodes);
434: }
435:
436: private static final NodeFilter filter = NotAssignmentFilter
437: .getWritableInstance();
438:
439: private void setSelectedTasks(List selectedNodes) {
440: selectedTasks = NodeList.nodeListToImplList(selectedNodes,
441: filter); // set member
442: String names;
443: if (selectedTasks.size() == 0
444: || !(selectedTasks.get(0) instanceof Task))
445: names = Messages.getString("AssignmentDialog.none"); //$NON-NLS-1$
446: else
447: names = DataUtils
448: .stringListWithMaxAndMessage(
449: selectedTasks,
450: Settings.STRING_LIST_LIMIT,
451: Messages
452: .getString("Message.tooManyTasksSelectedToList")); //$NON-NLS-1$
453:
454: taskNames
455: .setText(Messages.getString("Text.Tasks") + ": " + names); //$NON-NLS-1$ //$NON-NLS-2$
456: spreadSheetPane.setSelectedTasks(selectedTasks);
457: // setEnabled(!selectedTasks.isEmpty());
458: }
459:
460: public List getSelectedResources() {
461: return spreadSheetPane.getSelectedResources(false);
462: }
463:
464: /* (non-Javadoc)
465: * @see com.projity.field.ObjectEvent.Listener#objectChanged(com.projity.field.ObjectEvent)
466: */
467: public void objectChanged(ObjectEvent objectEvent) {
468: if (objectEvent.getObject() instanceof Resource)
469: spreadSheetPane.setProject(documentFrame.getProject());
470: else if (objectEvent.getObject() instanceof Assignment)
471: spreadSheetPane.updateTable(); //TODO one more objectEvent catch. Need something to react to undo and spreadsheet modifications
472: else if (objectEvent.getObject() instanceof GlobalPreferences)
473: getTeamOrAllLabel();
474:
475: }
476: }
|