1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.ximtec.igesture.tool.view;
29
30 import java.awt.Cursor;
31 import java.awt.Point;
32 import java.beans.IndexedPropertyChangeEvent;
33 import java.beans.PropertyChangeEvent;
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.FileOutputStream;
37 import java.lang.reflect.Constructor;
38 import java.util.Date;
39 import java.util.Properties;
40 import java.util.logging.Level;
41 import java.util.logging.Logger;
42
43 import javax.swing.JFileChooser;
44 import javax.swing.JOptionPane;
45 import javax.swing.SwingUtilities;
46
47 import org.sigtec.util.Constant;
48 import org.ximtec.igesture.core.DataObject;
49 import org.ximtec.igesture.core.DataObjectWrapper;
50 import org.ximtec.igesture.io.AbstractGestureDevice;
51 import org.ximtec.igesture.io.GestureDevice;
52 import org.ximtec.igesture.storage.StorageEngineConverter;
53 import org.ximtec.igesture.storage.StorageManager;
54 import org.ximtec.igesture.storage.StorageManager.StorageEngineType;
55 import org.ximtec.igesture.tool.GestureConstants;
56 import org.ximtec.igesture.tool.core.Controller;
57 import org.ximtec.igesture.tool.core.DefaultController;
58 import org.ximtec.igesture.tool.core.EdtProxy;
59 import org.ximtec.igesture.tool.core.ExecCmd;
60 import org.ximtec.igesture.tool.core.GenericLocateableAction;
61 import org.ximtec.igesture.tool.core.TabbedView;
62 import org.ximtec.igesture.tool.locator.Locator;
63 import org.ximtec.igesture.tool.locator.Service;
64 import org.ximtec.igesture.tool.service.DeviceManagerService;
65 import org.ximtec.igesture.tool.service.GuiBundleService;
66 import org.ximtec.igesture.tool.service.SwingMouseReaderService;
67 import org.ximtec.igesture.tool.util.ComponentFactory;
68 import org.ximtec.igesture.tool.util.ExtensionFileFilter;
69 import org.ximtec.igesture.tool.util.FileType;
70 import org.ximtec.igesture.tool.view.admin.AdminController;
71 import org.ximtec.igesture.tool.view.batch.BatchController;
72 import org.ximtec.igesture.tool.view.composite.CompositeController;
73 import org.ximtec.igesture.tool.view.devicemanager.DeviceManagerController;
74 import org.ximtec.igesture.tool.view.testbench.TestbenchController;
75 import org.ximtec.igesture.tool.view.testset.TestSetController;
76 import org.ximtec.igesture.tool.view.welcome.WelcomeController;
77
78
79
80
81
82
83
84
85
86 public class MainController extends DefaultController implements Service {
87
88 private static final Logger LOGGER = Logger.getLogger(MainController.class
89 .getName());
90
91
92 public static final String CMD_LOAD = "load";
93 public static final String CMD_EXIT = "close";
94 public static final String CMD_SAVE = "save";
95 public static final String CMD_SAVE_AS = "saveAs";
96 public static final String CMD_START_WAITING = "startWaiting";
97 public static final String CMD_STOP_WAITING = "stopWaiting";
98 public static final String CMD_SHOW_ABOUT_DIALOG = "showAboutDialog";
99 public static final String CMD_CLOSE_WS = "closeWorkspace";
100 public static final String CMD_CHANGE_TAB = "changeTab";
101 public static final String CMD_SHOW_DEVICE_MANAGER = "showDeviceManager";
102
103
104 private static Class< ? >[] activeControllers = new Class< ? >[] {
105 AdminController.class, TestbenchController.class,
106 BatchController.class, TestSetController.class,
107 CompositeController.class };
108
109
110 private static Class< ? >[] passiveControllers = new Class< ? >[] { WelcomeController.class };
111
112 public static final String IDENTIFIER = "mainController";
113
114
115 private MainModel mainModel;
116 private GuiBundleService guiBundle;
117 private SwingMouseReaderService deviceClient;
118 private StorageEngineType storageEngineType;
119 private DeviceManagerService deviceManager;
120
121
122 private IMainView mainView;
123
124
125 private Properties properties;
126
127
128
129
130
131 private boolean modelIsModified;
132
133
134
135
136
137
138
139
140
141
142 public MainController() {
143 super(null);
144 initServices();
145 initMainView();
146 initSubControllersAndViews(passiveControllers);
147 getAction(CMD_CLOSE_WS).setEnabled(false);
148 getAction(CMD_SAVE).setEnabled(false);
149 getAction(CMD_SAVE_AS).setEnabled(false);
150 this.modelIsModified = false;
151 }
152
153
154
155
156
157
158
159
160
161
162
163 private Controller createController(Class< ? > controllerClass)
164 throws Exception {
165
166 boolean instantiated = false;
167
168 Controller controller = null;
169 try {
170 if (!instantiated
171 && (controllerClass.getConstructor(Controller.class) != null)) {
172 Constructor< ? > constructor = controllerClass
173 .getConstructor(Controller.class);
174 controller = (Controller)constructor
175 .newInstance(MainController.this);
176 instantiated = true;
177 }
178 }
179 catch (Exception e) {
180 e.printStackTrace();
181 }
182 if (!instantiated) {
183 try {
184 controller = (Controller)controllerClass.newInstance();
185 }
186 catch (Exception e) {
187 e.printStackTrace();
188 }
189 }
190
191 if (controller == null)
192 throw new Exception();
193 return controller;
194 }
195
196
197
198
199
200 @ExecCmd(name = CMD_CHANGE_TAB)
201 protected void execChangeTab() {
202 LOGGER.info("Change Tab");
203 GestureDevice< ? , ? > gestureDevice = getLocator().getService(
204 SwingMouseReaderService.IDENTIFIER, GestureDevice.class);
205 if (gestureDevice != null) {
206 gestureDevice.clear();
207 }
208
209
210
211
212
213
214 for (AbstractGestureDevice< ? , ? > device : getLocator().getService(
215 DeviceManagerService.IDENTIFIER, DeviceManagerController.class)
216 .getDevices()) {
217 device.removeAllGestureHandler();
218 }
219 }
220
221
222
223
224
225 @ExecCmd(name = CMD_CLOSE_WS)
226 protected void execCloseWsCommand() {
227 LOGGER.info("Command Close Workspace");
228 if (modelIsModified
229 && mainModel.isActive()
230 && JOptionPane.YES_OPTION == showYesNoDialog(GestureConstants.MAIN_CONTROLLER_DIALOG_SAVE)) {
231 mainModel.getStorageManager().commit();
232 }
233 mainView.removeAllTabs();
234 mainModel.stop();
235 mainModel.setStorageEngine(null);
236 initSubControllersAndViews(passiveControllers);
237
238 getAction(CMD_CLOSE_WS).setEnabled(false);
239 getAction(CMD_SAVE).setEnabled(false);
240 getAction(CMD_SAVE_AS).setEnabled(false);
241 getAction(CMD_LOAD).setEnabled(true);
242
243 mainView.setTitlePostfix(null);
244
245 }
246
247
248
249
250
251 @ExecCmd(name = CMD_EXIT)
252 protected void execExitCommand() {
253 LOGGER.info("Command Exit");
254
255 if (modelIsModified) {
256 switch (showYesNoDialog(GestureConstants.MAIN_CONTROLLER_DIALOG_EXIT)) {
257 case JOptionPane.YES_OPTION:
258 mainModel.getStorageManager().commit();
259 shutdownApplication();
260 break;
261
262 case JOptionPane.NO_OPTION:
263 shutdownApplication();
264 break;
265
266 case JOptionPane.CANCEL_OPTION:
267 LOGGER.info("Exit cancelled.");
268 break;
269 }
270 }
271 else {
272 shutdownApplication();
273 }
274 }
275
276
277
278
279
280
281 private void shutdownApplication() {
282 getLocator().stopAll();
283 storeProperties();
284 System.exit(0);
285 }
286
287
288
289
290
291
292 private void storeProperties() {
293 try {
294 mainModel.getProperties().storeToXML(
295 new FileOutputStream(GestureConstants.PROPERTIES),
296 "iGesture: " + new Date());
297 }
298 catch (Exception e) {
299 LOGGER.log(Level.WARNING, "Failed to store properties.", e);
300 }
301 }
302
303
304
305
306
307 @ExecCmd(name = CMD_LOAD)
308 protected void execLoadCommand() {
309 LOGGER.info("Command Load");
310 File dataBase = getDatabase(false);
311
312 if (dataBase != null) {
313 mainView.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
314 mainView.removeAllTabs();
315 mainModel.stop();
316 loadAndInitProject(dataBase);
317 mainView.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
318 }
319
320 }
321
322
323 private void loadAndInitProject(File dataBase) {
324 storageEngineType = StorageManager.getEngineType(dataBase);
325 mainModel.setStorageEngine(StorageManager.createStorageEngine(dataBase));
326 mainModel.start();
327 initSubControllersAndViews(activeControllers);
328
329
330 getAction(CMD_CLOSE_WS).setEnabled(true);
331 getAction(CMD_SAVE).setEnabled(true);
332 getAction(CMD_LOAD).setEnabled(false);
333 getAction(CMD_SAVE_AS).setEnabled(true);
334
335 this.modelIsModified = false;
336 mainModel.setProjectName(dataBase.getName());
337 mainView.setTitlePostfix(dataBase);
338 }
339
340
341
342
343
344 @ExecCmd(name = CMD_SAVE_AS)
345 protected void execSaveAsCommand() {
346 LOGGER.info("Command Save AS");
347 File dataBase = getDatabase(true);
348
349 StorageEngineType targetFileType = StorageManager.getEngineType(dataBase);
350
351 if (dataBase != null) {
352 if (storageEngineType == targetFileType) {
353 mainModel.getStorageManager().copyTo(dataBase);
354 this.modelIsModified = false;
355 mainView.setTitlePostfix(dataBase);
356 }
357 else {
358
359 File workingCopy = new File(dataBase.getParentFile(), Long
360 .toString(System.currentTimeMillis())
361 + Constant.DOT + storageEngineType.name());
362 mainModel.getStorageManager().copyTo(workingCopy);
363 mainView.removeAllTabs();
364 mainModel.stop();
365 mainModel.setStorageEngine(null);
366
367 StorageEngineConverter converter = new StorageEngineConverter();
368 converter.convert(workingCopy, dataBase);
369 loadAndInitProject(dataBase);
370 workingCopy.delete();
371
372 storageEngineType = targetFileType;
373 mainView.setTitlePostfix(dataBase);
374
375 }
376 }
377
378 }
379
380
381
382
383
384 @ExecCmd(name = CMD_SAVE)
385 protected void execSaveCommand() {
386 LOGGER.info("Command Save");
387 mainModel.getStorageManager().commit();
388 this.modelIsModified = false;
389 }
390
391
392
393
394
395 @ExecCmd(name = CMD_SHOW_ABOUT_DIALOG)
396 protected void execShowAboutDialog() {
397 LOGGER.info("Show About Dialog.");
398 AboutDialog dialog = new AboutDialog(GestureConstants.ABOUT, getLocator()
399 .getService(GuiBundleService.IDENTIFIER, GuiBundleService.class));
400 Point point = mainView.getLocation();
401 point.translate(100, 60);
402 dialog.setLocation(point);
403 dialog.setVisible(true);
404 }
405
406
407
408
409
410 @ExecCmd(name = CMD_SHOW_DEVICE_MANAGER)
411 protected void execShowDeviceManager() {
412 LOGGER.info("Show Device Manager.");
413 Point point = mainView.getLocation();
414 point.translate(100, 60);
415 deviceManager.showView(point);
416 }
417
418
419
420
421
422
423
424 private ComponentFactory getComponentFactory() {
425 return getLocator().getService(ComponentFactory.class.getName(),
426 ComponentFactory.class);
427 }
428
429
430
431
432
433
434
435 private File getDatabase(boolean isSaveDialog) {
436 File file = null;
437 JFileChooser chooser = new JFileChooser();
438 chooser.addChoosableFileFilter(FileType.db4oWorkbench.getFilter());
439 chooser.addChoosableFileFilter(FileType.xstreamWorkbench.getFilter());
440 chooser.setFileFilter(FileType.compressedWorkbench.getFilter());
441 chooser.setCurrentDirectory(new File(properties
442 .getProperty(Property.WORKING_DIRECTORY)));
443 int result = 0;
444
445 if (isSaveDialog) {
446 result = chooser.showSaveDialog(null);
447 }
448 else {
449 result = chooser.showOpenDialog(null);
450 }
451
452 if (result == JFileChooser.APPROVE_OPTION) {
453 file = chooser.getSelectedFile();
454
455 if (file != null) {
456 try {
457 ExtensionFileFilter fileFilter = (ExtensionFileFilter)chooser
458 .getFileFilter();
459 if (!fileFilter.accept(file)) {
460 file = new File(file.getAbsolutePath() + Constant.DOT
461 + fileFilter.getExtension());
462 }
463 }
464 catch (Exception e) {
465 e.printStackTrace();
466 }
467
468 properties.setProperty(Property.WORKING_DIRECTORY, file.getParent());
469 }
470
471 }
472
473 return file;
474 }
475
476
477
478
479
480
481
482 @Override
483 public String getIdentifier() {
484 return IDENTIFIER;
485 }
486
487
488 @Override
489 public TabbedView getView() {
490 return null;
491 }
492
493
494
495
496
497
498
499
500 private void initControllers(Class< ? >[] controllers) {
501 if (!SwingUtilities.isEventDispatchThread()) {
502 throw new RuntimeException("Must not be executed in the EDT.");
503 }
504
505 for (Class< ? > clazz : controllers) {
506 try {
507 Controller controller = createController(clazz);
508 addController(controller);
509 mainView.addTab(controller.getView());
510 }
511 catch (Exception e) {
512 LOGGER.log(Level.SEVERE, "Could not initialize view. "
513 + clazz.getName(), e);
514 }
515 }
516 }
517
518
519
520
521
522
523
524
525 private void initMainView() {
526 if (mainView == null) {
527
528 addAction(CMD_LOAD, new GenericLocateableAction(this,
529 GestureConstants.OPEN_PROJECT, CMD_LOAD));
530 addAction(CMD_SAVE, new GenericLocateableAction(this,
531 GestureConstants.SAVE, CMD_SAVE));
532 addAction(CMD_EXIT, new GenericLocateableAction(this,
533 GestureConstants.EXIT, CMD_EXIT));
534 addAction(CMD_SHOW_ABOUT_DIALOG, new GenericLocateableAction(this,
535 GestureConstants.ABOUT, CMD_SHOW_ABOUT_DIALOG));
536 addAction(CMD_CLOSE_WS, new GenericLocateableAction(this,
537 GestureConstants.CLOSE_PROJECT, CMD_CLOSE_WS));
538 addAction(CMD_SAVE_AS, new GenericLocateableAction(this,
539 GestureConstants.SAVE_AS, CMD_SAVE_AS));
540 addAction(CMD_SHOW_DEVICE_MANAGER, new GenericLocateableAction(this,
541 GestureConstants.DEVICE_MANAGER, CMD_SHOW_DEVICE_MANAGER));
542
543 mainView = EdtProxy.newInstance(new MainView(this), IMainView.class);
544 mainView.addWindowListener(new MainWindowAdapter(this));
545 }
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560 private void initServices() {
561 guiBundle = new GuiBundleService(GestureConstants.RESOURCE_BUNDLE);
562
563 properties = new Properties();
564
565 try {
566 properties
567 .loadFromXML(new FileInputStream(GestureConstants.PROPERTIES));
568 }
569 catch (Exception e) {
570
571 properties.setProperty(Property.WORKING_DIRECTORY, System
572 .getProperty(GestureConstants.USER_DIR));
573 LOGGER.log(Level.WARNING, "Failed to load properties.");
574 }
575
576 mainModel = new MainModel(null, this, properties);
577 deviceClient = new SwingMouseReaderService();
578
579
580
581
582
583 setLocator(Locator.getDefault());
584 getLocator().addService(mainModel);
585 getLocator().addService(guiBundle);
586 getLocator().addService(deviceClient);
587
588
589
590 deviceManager = new DeviceManagerService(this,
591 GestureConstants.DEVICE_MANAGER, guiBundle);
592 getLocator().addService(deviceManager);
593
594 getLocator().addService(new ComponentFactory(guiBundle));
595 getLocator().addService(this);
596 getLocator().startAll();
597 }
598
599
600
601
602
603
604
605
606
607 private void initSubControllersAndViews(final Class< ? >[] controllers) {
608
609 if (SwingUtilities.isEventDispatchThread()) {
610 initControllers(controllers);
611 }
612 else {
613 try {
614 SwingUtilities.invokeAndWait(new Runnable() {
615
616 @Override
617 public void run() {
618 initControllers(controllers);
619 }
620 });
621
622 }
623 catch (Exception e) {
624 e.printStackTrace();
625 LOGGER.log(Level.SEVERE, "View Initialization failed. ");
626 }
627 }
628 }
629
630
631
632
633
634
635
636 private void persist(IndexedPropertyChangeEvent event) {
637 LOGGER
638 .info("Store, Delete, Update: indexed property " + event.getSource());
639
640 if (event.getOldValue() == null) {
641 mainModel.getStorageManager().store((DataObject)event.getNewValue());
642 }
643 else if (event.getNewValue() == null
644 && event.getOldValue() instanceof DataObject) {
645 mainModel.getStorageManager().remove((DataObject)event.getOldValue());
646 }
647
648 mainModel.getStorageManager().update((DataObject)event.getSource());
649 }
650
651
652
653
654
655
656
657 private void persist(PropertyChangeEvent event) {
658 LOGGER.info("Update: property " + event.getSource());
659 mainModel.getStorageManager().update((DataObject)event.getSource());
660 }
661
662
663
664
665
666
667
668
669
670 @Override
671 public void propertyChange(PropertyChangeEvent event) {
672 LOGGER.info("PropertyChange");
673 super.propertyChange(event);
674
675 this.modelIsModified = true;
676
677
678 if (event.getSource() instanceof DataObject) {
679
680 if (event instanceof IndexedPropertyChangeEvent) {
681 persist((IndexedPropertyChangeEvent)event);
682 }
683 else {
684 persist(event);
685 }
686
687 }
688 else if (event.getSource() instanceof DataObjectWrapper) {
689 LOGGER.info("DataObjectWrapper: "
690 + event.getSource().getClass().getName());
691
692 if (event.getOldValue() instanceof DataObject
693 && event.getNewValue() == null) {
694 mainModel.getStorageManager()
695 .remove((DataObject)event.getOldValue());
696 }
697 else if (event.getNewValue() instanceof DataObject
698 && event.getOldValue() == null) {
699 mainModel.getStorageManager().store((DataObject)event.getNewValue());
700 }
701 else if (event.getNewValue() instanceof DataObject
702 && event.getOldValue() != null) {
703 mainModel.getStorageManager()
704 .update((DataObject)event.getNewValue());
705 }
706 }
707 }
708
709
710
711
712
713
714
715
716 private int showYesNoDialog(String key) {
717 String title = getComponentFactory().getGuiBundle().getName(
718 GestureConstants.APPLICATION_ROOT);
719 String text = Constant.SINGLE_QUOTE + mainModel.getProjectName()
720 + Constant.SINGLE_QUOTE_BLANK
721 + getComponentFactory().getGuiBundle().getShortDescription(key);
722 return JOptionPane.showConfirmDialog(null, text, title,
723 JOptionPane.YES_NO_CANCEL_OPTION);
724 }
725
726 }