KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > taskblocks > app > ProjectFrame


1 /*
2  * Copyright (C) Jakub Neubauer, 2007
3  *
4  * This file is part of TaskBlocks
5  *
6  * TaskBlocks is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * TaskBlocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */

19
20 package taskblocks.app;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.FileDialog JavaDoc;
25 import java.awt.Font JavaDoc;
26 import java.awt.Toolkit JavaDoc;
27 import java.awt.event.ActionEvent JavaDoc;
28 import java.awt.event.ActionListener JavaDoc;
29 import java.awt.event.KeyEvent JavaDoc;
30 import java.awt.event.MouseEvent JavaDoc;
31 import java.awt.event.WindowEvent JavaDoc;
32 import java.awt.event.WindowListener JavaDoc;
33 import java.io.File JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.List JavaDoc;
36
37 import javax.swing.Action JavaDoc;
38 import javax.swing.Box JavaDoc;
39 import javax.swing.JCheckBoxMenuItem JavaDoc;
40 import javax.swing.JFileChooser JavaDoc;
41 import javax.swing.JFrame JavaDoc;
42 import javax.swing.JLabel JavaDoc;
43 import javax.swing.JMenu JavaDoc;
44 import javax.swing.JMenuBar JavaDoc;
45 import javax.swing.JMenuItem JavaDoc;
46 import javax.swing.JOptionPane JavaDoc;
47 import javax.swing.JPanel JavaDoc;
48 import javax.swing.JSeparator JavaDoc;
49 import javax.swing.KeyStroke JavaDoc;
50 import javax.swing.event.ChangeEvent JavaDoc;
51 import javax.swing.event.ChangeListener JavaDoc;
52 import javax.swing.event.MenuEvent JavaDoc;
53 import javax.swing.event.MenuListener JavaDoc;
54
55 import taskblocks.graph.GraphActionListener;
56 import taskblocks.graph.TaskGraphComponent;
57 import taskblocks.io.BugzillaExportDialog;
58 import taskblocks.io.ProjectSaveLoad;
59 import taskblocks.io.WrongDataException;
60 import taskblocks.modelimpl.TaskImpl;
61 import taskblocks.modelimpl.TaskModelImpl;
62 import taskblocks.modelimpl.TaskPainterImpl;
63
64 public class ProjectFrame extends JFrame JavaDoc implements WindowListener JavaDoc, GraphActionListener {
65     
66     static int _numWindows;
67     static List JavaDoc<JMenuItem JavaDoc> _windowMenuItems = new ArrayList JavaDoc<JMenuItem JavaDoc>();
68
69     TaskModelImpl _taskModel;
70     TaskGraphComponent _graph;
71     
72     File JavaDoc _file;
73     boolean _newCleanProject;
74     JCheckBoxMenuItem JavaDoc _myWindowMenuItem;
75     
76     Action JavaDoc _shrinkAction = new MyAction("Shrink", TaskBlocks.getImage("shrink.png"), "Shrink tasks as near as possible") {
77         public void actionPerformed(ActionEvent JavaDoc e) {
78             _graph.getGraphRepresentation().shrinkTasks();
79             _graph.repaint();
80         }
81     };
82     
83     Action JavaDoc _scaleDownAction = new MyAction("Zoom Out", TaskBlocks.getImage("zoomOut.png")) {
84         public void actionPerformed(ActionEvent JavaDoc arg0) {
85             _graph.scaleDown();
86         }
87     };
88     
89     Action JavaDoc _scaleUpAction = new MyAction("Zoom In", TaskBlocks.getImage("zoomIn.png")) {
90         public void actionPerformed(ActionEvent JavaDoc arg0) {
91             _graph.scaleUp();
92         }
93     };
94     
95     Action JavaDoc _closeFileAction = new MyAction("Close") {
96         public void actionPerformed(ActionEvent JavaDoc arg0) {
97             tryClose();
98         }
99     };
100     
101     Action JavaDoc _loadFileAction = new MyAction("Open...", TaskBlocks.getImage("folder.gif"), "Lets you open an existing project") {
102         public void actionPerformed(ActionEvent JavaDoc e) {
103
104             File JavaDoc f = null;
105             if(TaskBlocks.RUNNING_ON_MAC || TaskBlocks.RUNNING_ON_WINDOWS) {
106                 // MacOS & Windows user feeling
107
FileDialog JavaDoc fd = new FileDialog JavaDoc(ProjectFrame.this, "blabla", FileDialog.LOAD);
108                 fd.setVisible(true);
109                 if(fd.getFile() != null) {
110                     f = new File JavaDoc(fd.getDirectory(), fd.getFile());
111                 }
112             } else {
113                 JFileChooser JavaDoc fc = new JFileChooser JavaDoc();
114                 fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
115                 fc.showOpenDialog(ProjectFrame.this);
116                 f = fc.getSelectedFile();
117             }
118             
119             if(f != null) {
120                 openFile(f);
121             }
122         }
123     };
124     
125     Action JavaDoc _newFileAction = new MyAction("New Project") {
126         public void actionPerformed(ActionEvent JavaDoc e) {
127             new ProjectFrame();
128         }
129     };
130
131     Action JavaDoc _saveAction = new MyAction("Save", TaskBlocks.getImage("save.png")) {
132         public void actionPerformed(ActionEvent JavaDoc e) {
133             save();
134         }
135     };
136     
137     Action JavaDoc _saveAsAction = new MyAction("Save As...") {
138         public void actionPerformed(ActionEvent JavaDoc e) {
139             File JavaDoc oldFile = _file;
140             _file = null;
141             if(!save()) {
142                 _file = oldFile;
143             }
144         }
145     };
146     
147     Action JavaDoc _leftAction = new MyAction("Left", TaskBlocks.getImage("left.gif"), "Scrolls left") {
148         public void actionPerformed(ActionEvent JavaDoc e) {
149             _graph.moveLeft();
150         }
151     };
152
153     Action JavaDoc _focusTodayAction = new MyAction("Focus on today", TaskBlocks.getImage("down.gif"), "Scrolls to current day") {
154         public void actionPerformed(ActionEvent JavaDoc e) {
155             _graph.focusOnToday();
156         }
157     };
158
159     Action JavaDoc _rightAction = new MyAction("Right", TaskBlocks.getImage("right.gif"), "Scrolls right") {
160         public void actionPerformed(ActionEvent JavaDoc e) {
161             _graph.moveRight();
162         }
163     };
164     
165     ChangeListener JavaDoc _graphChangeListener = new ChangeListener JavaDoc(){
166         public void stateChanged(ChangeEvent JavaDoc e) {
167             _newCleanProject = false;
168             updateActionsEnableState();
169         }
170     };
171     
172     Action JavaDoc _minimizeAction = new MyAction("Minimize"){
173         public void actionPerformed(ActionEvent JavaDoc e) {
174             ProjectFrame.this.setExtendedState(JFrame.ICONIFIED);
175         }
176     };
177
178     Action JavaDoc _newTaskAction = new MyAction("New Task...", TaskBlocks.getImage("newtask.png"), "Opens the New Task Wizard"){
179         public void actionPerformed(ActionEvent JavaDoc e) {
180             TaskConfigDialog.openDialog(ProjectFrame.this, null, _taskModel, _graph, true);
181         }
182     };
183
184     Action JavaDoc _newManAction = new MyAction("New Worker...", TaskBlocks.getImage("newman.png"), "Opens the New Worker Wizard"){
185         public void actionPerformed(ActionEvent JavaDoc e) {
186             ManConfigDialog.openDialog(ProjectFrame.this, null, _taskModel, _graph, true);
187         }
188     };
189     Action JavaDoc _aboutAction = new MyAction("About..."){
190         public void actionPerformed(ActionEvent JavaDoc e) {
191             AboutDialog.showAbout(ProjectFrame.this);
192         }
193     };
194
195     Action JavaDoc _bugzillaSubmit = new MyAction("Export to Bugzilla...", TaskBlocks.getImage("bugzilla.png"), "Opens the Bugzilla Export dialog"){
196         public void actionPerformed(ActionEvent JavaDoc e) {
197             BugzillaExportDialog.openDialog(ProjectFrame.this, _taskModel._tasks);
198             
199         }};
200         
201     Action JavaDoc _deleteSel = new MyAction("Delete Selection", TaskBlocks.getImage("delete.gif"), "Deletes selected objects") {
202         public void actionPerformed(ActionEvent JavaDoc e) {
203             _graph.deleteSelection();
204         }
205     };
206
207     /**
208      * creates window with empty project.
209      */

210     public ProjectFrame() {
211         this(TaskModelImpl.createEmptyModel());
212         setTitle("New project");
213         _newCleanProject = true;
214         updateActionsEnableState();
215     }
216     
217     public ProjectFrame(File JavaDoc f) throws WrongDataException {
218         this(new ProjectSaveLoad().loadProject(f));
219         setFile(f);
220         updateActionsEnableState();
221     }
222     
223     private ProjectFrame(TaskModelImpl model) {
224         // there are some issues with transparent icon in frame, so we use icon
225
// with filled background.
226
this.setIconImage(TaskBlocks.getImage("frameicon32.png").getImage());
227         _taskModel = model;
228         buildGui();
229         pack();
230         setSize(800,400);
231         fillMenu();
232         _graph.setGraphChangeListener(_graphChangeListener);
233         this.addWindowListener(this);
234         setLocationRelativeTo(null);
235         setVisible(true);
236         _numWindows++;
237     }
238
239     /**
240      * Opens the specified file. If this frame contains empty project, opens the file in this frame.
241      * If project in this frame is modified, opens new window with it.
242      *
243      * @param f
244      */

245     public void openFile(File JavaDoc f) {
246         try {
247             // check if the project is empty
248
_graph.getGraphRepresentation().updateModel();
249             if(_taskModel._tasks.length == 0) {
250                 _taskModel = new ProjectSaveLoad().loadProject(f);
251                 _graph.setModel(_taskModel);
252                 setFile(f);
253                 updateActionsEnableState();
254             } else {
255                 new ProjectFrame(f);
256             }
257             
258         } catch (WrongDataException e) {
259             JOptionPane.showMessageDialog(null, "<html><b>Couldn't Open File</b><br><br><font size=\"-2\">" + e.getMessage() + "<br><br>");
260         }
261     }
262
263     public void setTitle(String JavaDoc title) {
264         super.setTitle(title + " - Task Blocks");
265         _myWindowMenuItem.setText(title);
266     }
267
268     public void windowActivated(WindowEvent JavaDoc arg0) {
269     }
270     
271     public void windowClosed(WindowEvent JavaDoc arg0) {
272         _numWindows--;
273         _windowMenuItems.remove(_myWindowMenuItem);
274         if(_numWindows <= 0) {
275             System.exit(0);
276         }
277     }
278     
279     public void windowClosing(WindowEvent JavaDoc arg0) {
280         tryClose();
281     }
282     
283     public void windowDeactivated(WindowEvent JavaDoc arg0) {}
284     
285     public void windowDeiconified(WindowEvent JavaDoc arg0) {}
286     
287     public void windowIconified(WindowEvent JavaDoc arg0) {}
288     
289     public void windowOpened(WindowEvent JavaDoc arg0) {}
290
291     private void buildGui() {
292         
293         // create components
294
JPanel JavaDoc mainP = new JPanel JavaDoc(new BorderLayout JavaDoc());
295         MyToolBar toolB = new MyToolBar();
296         _graph = new TaskGraphComponent(_taskModel, new TaskPainterImpl());
297         
298         // setup toolbar actions
299
toolB.add(_loadFileAction);
300         toolB.add(_saveAction);
301         toolB.add(Box.createHorizontalStrut(4));
302         toolB.add(new FixedSeparator(FixedSeparator.VERTICAL));
303         toolB.add(Box.createHorizontalStrut(4));
304         toolB.add(_newTaskAction);
305         toolB.add(_newManAction);
306         toolB.add(_shrinkAction);
307         toolB.add(Box.createHorizontalStrut(4));
308         toolB.add(new FixedSeparator(FixedSeparator.VERTICAL));
309         toolB.add(Box.createHorizontalStrut(4));
310         toolB.add(_scaleUpAction);
311         toolB.add(_scaleDownAction);
312         toolB.add(Box.createHorizontalStrut(8));
313         toolB.add(_leftAction);
314         toolB.add(_rightAction);
315         toolB.add(_focusTodayAction);
316         toolB.add(Box.createHorizontalStrut(4));
317         toolB.add(new FixedSeparator(FixedSeparator.VERTICAL));
318         toolB.add(Box.createHorizontalStrut(4));
319         toolB.add(_deleteSel);
320         // set component's properties
321
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
322         mainP.add(toolB, BorderLayout.NORTH);
323         mainP.add(_graph, BorderLayout.CENTER);
324         getContentPane().setLayout(new BorderLayout JavaDoc());
325         getContentPane().add(mainP);
326         //toolB.setRollover(true);
327
toolB.setFloatable(false);
328         
329         _graph.setGraphActionListener(this);
330     }
331     
332     private void fillMenu() {
333         JMenuBar JavaDoc menu = getJMenuBar();
334         if(menu == null) {
335             menu = new JMenuBar JavaDoc();
336             this.setJMenuBar(menu);
337         }
338         JMenu JavaDoc menuFile = new JMenu JavaDoc("File");
339         menuFile.add(_newFileAction).setAccelerator(getAcceleratorStroke('N'));
340         menuFile.add(_loadFileAction).setAccelerator(getAcceleratorStroke('O'));
341         menuFile.add(new JSeparator JavaDoc());
342         menuFile.add(_saveAction).setAccelerator(getAcceleratorStroke('S'));
343         menuFile.add(_saveAsAction);
344         menuFile.add(new JSeparator JavaDoc());
345         menuFile.add(_closeFileAction).setAccelerator(getAcceleratorStroke('W'));
346         menu.add(menuFile);
347         
348         JMenu JavaDoc menuProject = new JMenu JavaDoc("Project");
349         menuProject.add(_newTaskAction).setAccelerator(getAcceleratorStroke('T'));
350         menuProject.add(_newManAction).setAccelerator(getAcceleratorStroke('U'));
351         menuProject.add(new JSeparator JavaDoc());
352         JMenuItem JavaDoc mi = menuProject.add(_deleteSel);
353         if(TaskBlocks.RUNNING_ON_MAC) {
354             mi.setAccelerator(getAcceleratorStroke(KeyEvent.VK_BACK_SPACE));
355         } else {
356             mi.setAccelerator(getAcceleratorStroke(KeyEvent.VK_DELETE));
357         }
358         menuProject.add(new JSeparator JavaDoc());
359         menuProject.add(_shrinkAction).setAccelerator(getAcceleratorStroke('R'));
360         menuProject.add(_bugzillaSubmit);
361         menu.add(menuProject);
362         
363         
364         final JMenu JavaDoc menuWindow = new JMenu JavaDoc("Window");
365         _myWindowMenuItem = new JCheckBoxMenuItem JavaDoc("???");
366         _myWindowMenuItem.setFont(_myWindowMenuItem.getFont().deriveFont(Font.PLAIN));
367         _myWindowMenuItem.addActionListener(new ActionListener JavaDoc(){
368             public void actionPerformed(ActionEvent JavaDoc e) {
369                 ProjectFrame.this.toFront();
370             }});
371         _windowMenuItems.add(_myWindowMenuItem);
372         menuWindow.addMenuListener(new MenuListener JavaDoc(){
373             public void menuCanceled(MenuEvent JavaDoc e) {
374             }
375
376             public void menuDeselected(MenuEvent JavaDoc e) {
377             }
378
379             public void menuSelected(MenuEvent JavaDoc e) {
380                 menuWindow.removeAll();
381                 JMenuItem JavaDoc minItem = menuWindow.add(new JMenuItem JavaDoc(_minimizeAction));
382                 minItem.setAccelerator(getAcceleratorStroke('M'));
383                 minItem.setFont(minItem.getFont().deriveFont(Font.PLAIN));
384                 menuWindow.add(new JSeparator JavaDoc());
385                 for(JMenuItem JavaDoc winItem: _windowMenuItems) {
386                     menuWindow.add(winItem);
387                     winItem.setSelected(winItem == _myWindowMenuItem);
388                 }
389             }});
390         menu.add(menuWindow);
391         
392         if(!TaskBlocks.RUNNING_ON_MAC) {
393             JMenu JavaDoc menuHelp = new JMenu JavaDoc("Help");
394             menuHelp.add(_aboutAction);
395             menu.add(menuHelp);
396         }
397
398         // not bold menu items and on mac without icons
399
for(int i = 0; i < menu.getMenuCount(); i++) {
400             JMenu JavaDoc subMenu = menu.getMenu(i);
401             subMenu.setFont(subMenu.getFont().deriveFont(Font.PLAIN));
402             for(Component JavaDoc c: subMenu.getMenuComponents()) {
403                 if(c instanceof JMenuItem JavaDoc) {
404                     // MacOS user feeling
405
if(TaskBlocks.RUNNING_ON_MAC) {
406                         // clear icons from all menus. It is convention on Mac
407
((JMenuItem JavaDoc)c).setIcon(null);
408                     }
409                     ((JMenuItem JavaDoc)c).setFont(c.getFont().deriveFont(Font.PLAIN));
410                 }
411             }
412         }
413     }
414     
415     private KeyStroke JavaDoc getAcceleratorStroke(char key) {
416         return KeyStroke.getKeyStroke(key, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
417     }
418     private KeyStroke JavaDoc getAcceleratorStroke(int keyCode) {
419         return KeyStroke.getKeyStroke(keyCode, 0);
420     }
421         
422     private void setFile(File JavaDoc f) {
423         _file = f;
424         setTitle(_file.getName());
425     }
426
427     private void tryClose() {
428         if(_graph.getGraphRepresentation().isSaveDirty()) {
429             // not saved - ask for save
430
String JavaDoc SAVE = "Save";
431             String JavaDoc DONT_SAVE = "Don't Save";
432             String JavaDoc CANCEL = "Cancel";
433             Object JavaDoc[] options;
434             
435             // from unknown reasons the appearing order is reversed on Mac
436
if(TaskBlocks.RUNNING_ON_MAC) {
437                 options = new Object JavaDoc[] {SAVE, CANCEL, DONT_SAVE};
438             } else {
439                 options = new Object JavaDoc[] {DONT_SAVE, SAVE, CANCEL};
440             }
441             JLabel JavaDoc l = new JLabel JavaDoc("<html><b>Do you want to save changes to this document<br>before closing?</b><br><br><font size=\"-2\">If you don't save, your changes will be lost.<br></font><br>");
442             l.setFont(l.getFont().deriveFont(Font.PLAIN));
443             JOptionPane JavaDoc op = new JOptionPane JavaDoc(l, JOptionPane.QUESTION_MESSAGE, 0, null, options);
444             op.createDialog(this, _file == null ? "Unsaved project" : _file.getName()).setVisible(true);
445             op.setInitialSelectionValue(CANCEL);
446             Object JavaDoc choice = op.getValue();
447             if(choice == null) {
448                 return; // cancel;
449
}
450             if(choice.equals(SAVE)) {
451                 // save
452
if(!save()) {
453                     // save didn't success, don't close
454
return;
455                 } else {
456                     this.dispose();
457                 }
458             } else if(choice.equals(DONT_SAVE)) {
459                 this.dispose();
460             }
461         } else {
462             this.dispose();
463         }
464     }
465     
466     private void updateActionsEnableState() {
467         boolean unsaved = _newCleanProject || _graph.getGraphRepresentation().isSaveDirty();
468         _saveAction.setEnabled(unsaved);
469         
470         // MacOS user feeling
471
getRootPane().putClientProperty("windowModified", unsaved?Boolean.TRUE : Boolean.FALSE);
472         _newTaskAction.setEnabled(_graph.getGraphRepresentation().getManCount() > 0);
473     }
474
475     private boolean save() {
476         _graph.getGraphRepresentation().updateModel();
477         File JavaDoc f = _file;
478         if(f == null) {
479             
480             // ask for file
481
if(TaskBlocks.RUNNING_ON_MAC || TaskBlocks.RUNNING_ON_WINDOWS) {
482                 // MacOS user feeling
483
FileDialog JavaDoc fd = new FileDialog JavaDoc(ProjectFrame.this, "blabla", FileDialog.SAVE);
484                 fd.setVisible(true);
485                 if(fd.getFile() != null) {
486                     f = new File JavaDoc(fd.getDirectory(), fd.getFile());
487                 }
488             } else {
489                 JFileChooser JavaDoc fc = new JFileChooser JavaDoc();
490                 fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
491                 fc.showSaveDialog(ProjectFrame.this);
492                 f = fc.getSelectedFile();
493             }
494         }
495         if(f != null) {
496             try {
497                 new ProjectSaveLoad().saveProject(f, _taskModel);
498                 setFile(f);
499                 _graph.getGraphRepresentation().clearSaveDirtyFlag();
500                 return true;
501             } catch (Exception JavaDoc e1) {
502                 JOptionPane.showMessageDialog(null, "<html><b>Couldn't Save</b><br><br><font size=\"-2\">" + e1.getMessage() + "<br><br>");
503                 e1.printStackTrace();
504             }
505         }
506         return false;
507     }
508     
509     private void configureTask(TaskImpl t) {
510         _graph.getGraphRepresentation().updateModel(); // GUI -> model update
511
if(TaskConfigDialog.openDialog(this, t, _taskModel, _graph, false)) {
512             _graph.setModel(_taskModel); // model -> GUI udate
513
_graph.getGraphRepresentation().setDirty(); // the model->GUI resetted the dirty flag
514
_graph.repaint();
515         }
516     }
517
518     public void mouseClicked(Object JavaDoc task, MouseEvent JavaDoc e) {
519         if(task != null && e.getClickCount() >= 2) {
520             configureTask((TaskImpl)task);
521         }
522     }
523 }
524
Popular Tags