View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.gui;
17  
18  import james.SimSystem;
19  import james.core.data.DBConnectionData;
20  import james.core.experiments.BaseExperiment;
21  import james.core.experiments.taskrunner.parallel.ParallelComputationTaskRunnerFactory;
22  import james.core.experiments.taskrunner.plugintype.TaskRunnerFactory;
23  import james.core.parameters.ParameterBlock;
24  import james.core.parameters.ParameterizedFactory;
25  import james.core.processor.plugintype.ProcessorFactory;
26  import james.gui.application.SplashScreen;
27  import james.gui.application.resource.IconManager;
28  import james.gui.experiment.ExperimentExecutorThreadPool;
29  import james.gui.experiment.execution.ExperimentThread;
30  import james.gui.utils.BasicUtilities;
31  
32  import java.awt.BorderLayout;
33  import java.awt.Dimension;
34  import java.awt.Image;
35  import java.awt.event.ActionEvent;
36  import java.awt.event.ActionListener;
37  import java.awt.event.KeyEvent;
38  import java.awt.event.WindowAdapter;
39  import java.awt.event.WindowEvent;
40  import java.io.File;
41  import java.lang.reflect.InvocationTargetException;
42  import java.net.URI;
43  import java.util.Locale;
44  import java.util.logging.Level;
45  
46  import javax.swing.Icon;
47  import javax.swing.ImageIcon;
48  import javax.swing.JButton;
49  import javax.swing.JDesktopPane;
50  import javax.swing.JFileChooser;
51  import javax.swing.JFrame;
52  import javax.swing.JMenu;
53  import javax.swing.JMenuBar;
54  import javax.swing.JMenuItem;
55  import javax.swing.JPanel;
56  import javax.swing.JSeparator;
57  import javax.swing.JSplitPane;
58  import javax.swing.JTabbedPane;
59  import javax.swing.JToolBar;
60  import javax.swing.KeyStroke;
61  import javax.swing.UIManager;
62  import javax.swing.tree.TreePath;
63  
64  import p3j.database.DatabaseFactory;
65  import p3j.gui.dialogs.CopyGenerationsDialog;
66  import p3j.gui.dialogs.ExecutionPreferencesDialog;
67  import p3j.gui.dialogs.NewProjectionDialog;
68  import p3j.gui.dialogs.PreferencesDialog;
69  import p3j.gui.dialogs.execstatus.ExecProgressInstrFactory;
70  import p3j.gui.misc.NavigationTreeTab;
71  import p3j.gui.misc.P3JConfigFile;
72  import p3j.gui.panels.WelcomePanel;
73  import p3j.gui.panels.dboverview.DatabaseOverviewPanel;
74  import p3j.gui.panels.projections.ProjectionTreePanel;
75  import p3j.gui.panels.results.ResultTreePanel;
76  import p3j.misc.Misc;
77  import p3j.misc.Serializer;
78  import p3j.misc.gui.GUI;
79  import p3j.pppm.ProjectionModel;
80  import p3j.simulation.ExecutionMode;
81  import p3j.simulation.PPPMProcessorFactory;
82  import p3j.simulation.assignments.plugintype.ParamAssignmentGenFactory;
83  
84  import com.jgoodies.looks.HeaderStyle;
85  import com.jgoodies.looks.LookUtils;
86  import com.jgoodies.looks.Options;
87  import com.jgoodies.looks.plastic.PlasticLookAndFeel;
88  
89  /**
90   * Main user interface to P3J (singleton).
91   * 
92   * Created on July 16, 2006
93   * 
94   * @author Christina Bohk
95   * @author Roland Ewald
96   */
97  public final class P3J extends JFrame {
98  
99  	/** Serialization ID. */
100 	private static final long serialVersionUID = -142244898041811667L;
101 
102 	/** Initial window width. */
103 	static final int INITIAL_WIDTH = 1024;
104 
105 	/** Initial window height. */
106 	static final int INITIAL_HEIGHT = 768;
107 
108 	/** Initial width of the projection/result tree tab-pane. */
109 	static final int INITIAL_TREE_WIDTH = 300;
110 
111 	/** Reference to singleton. */
112 	private static P3J instance;
113 
114 	/** The splash screen to be shown at startup. */
115 	private static SplashScreen splashScreen;
116 
117 	/** Current projection to be edited. */
118 	private static ProjectionModel currentProjection;
119 
120 	/** Serialization tool. */
121 	private final Serializer serializer = new Serializer();
122 
123 	// GUI elements
124 
125 	/** Icon for the run button. */
126 	private final Icon runIcon = new ImageIcon(this.getClass().getResource(
127 	    "/p3j/icons/run.gif"));
128 
129 	/** The button to run a calculation. */
130 	private final JButton runButton = new JButton(runIcon);
131 	{
132 		runButton.addActionListener(new ActionListener() {
133 			@Override
134 			public void actionPerformed(ActionEvent e) {
135 				startExperiment();
136 			}
137 		});
138 	}
139 
140 	/** The button in the toolbar shown the replication configurations. */
141 	private JButton execPrefsButton = new JButton();
142 	{
143 		execPrefsButton.addActionListener(new ActionListener() {
144 			@Override
145 			public void actionPerformed(ActionEvent e) {
146 				editExecutionPreferences();
147 			}
148 		});
149 	}
150 
151 	/** Main toolbar. */
152 	private final JToolBar toolBar = new JToolBar();
153 	{
154 		toolBar.add(runButton);
155 		toolBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
156 		toolBar.putClientProperty(PlasticLookAndFeel.IS_3D_KEY, Boolean.FALSE);
157 		toolBar.add(execPrefsButton);
158 	}
159 
160 	/** The desktop. */
161 	private final JDesktopPane desktop = new JDesktopPane();
162 
163 	/** File chooser to save scenario files. */
164 	private final JFileChooser scenarioFileChooser = new JFileChooser();
165 
166 	// File menu
167 
168 	/** Menu to create a new scenario. */
169 	private final JMenuItem newProjectionMenu = new JMenuItem("New projection",
170 	    KeyEvent.VK_N);
171 	{
172 		newProjectionMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
173 		    ActionEvent.CTRL_MASK));
174 		newProjectionMenu.addActionListener(new ActionListener() {
175 			@Override
176 			public void actionPerformed(ActionEvent e) {
177 				newProjection();
178 			}
179 		});
180 	}
181 
182 	/** Menu to load a scenario. */
183 	private final JMenuItem openProjectionMenu = new JMenuItem(
184 	    "Open/import projection...", KeyEvent.VK_O);
185 	{
186 		openProjectionMenu.setVisible(false); // TODO
187 		openProjectionMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
188 		    ActionEvent.CTRL_MASK));
189 		openProjectionMenu.addActionListener(new ActionListener() {
190 			@Override
191 			public void actionPerformed(ActionEvent e) {
192 				loadProjection();
193 			}
194 		});
195 	}
196 
197 	/** Menu to quick-save. */
198 	private final JMenuItem quickSaveProjectionMenu = new JMenuItem(
199 	    "Save projection", KeyEvent.VK_S);
200 	{
201 		quickSaveProjectionMenu.setAccelerator(KeyStroke.getKeyStroke(
202 		    KeyEvent.VK_S, ActionEvent.CTRL_MASK));
203 		quickSaveProjectionMenu.setVisible(false); // TODO
204 		quickSaveProjectionMenu.addActionListener(new ActionListener() {
205 			@Override
206 			public void actionPerformed(ActionEvent e) {
207 				if (currentProjectionFile == null) {
208 					saveProjection();
209 				} else {
210 					quickSaveProjection(currentProjectionFile);
211 				}
212 			}
213 		});
214 	}
215 
216 	/** Menu to save scenario. */
217 	private final JMenuItem saveProjectionMenu = new JMenuItem(
218 	    "Save projection...");
219 	{
220 		saveProjectionMenu.setVisible(false); // TODO
221 		saveProjectionMenu.addActionListener(new ActionListener() {
222 			@Override
223 			public void actionPerformed(ActionEvent e) {
224 				saveProjection();
225 			}
226 		});
227 	}
228 
229 	/** Menu to load results. */
230 	private final JMenuItem loadResultsMenu = new JMenuItem("Load results...");
231 	{
232 		loadResultsMenu.setVisible(false); // TODO
233 	}
234 
235 	/** Menu to save results. */
236 	private final JMenuItem saveResultsMenu = new JMenuItem("Save results...");
237 	{
238 		saveResultsMenu.setVisible(false); // TODO
239 	}
240 
241 	/** Menu to quick-save results. */
242 	private final JMenuItem quickSaveResultsMenu = new JMenuItem("Save results");
243 	{
244 		quickSaveResultsMenu.setVisible(false); // TODO
245 	}
246 
247 	/** Menu to open preferences dialog. */
248 	private final JMenuItem preferencesMenu = new JMenuItem("Preferences...");
249 	{
250 		preferencesMenu.addActionListener(new ActionListener() {
251 			@Override
252 			public void actionPerformed(ActionEvent e) {
253 				editPreferences();
254 			}
255 		});
256 	}
257 
258 	/** Menu to open execution preferences dialog. */
259 	private final JMenuItem execPreferencesMenu = new JMenuItem(
260 	    "Execution Preferences...");
261 	{
262 		execPreferencesMenu.addActionListener(new ActionListener() {
263 			@Override
264 			public void actionPerformed(ActionEvent e) {
265 				execPrefsButton.doClick();
266 			}
267 		});
268 	}
269 
270 	/** Menu to quit. */
271 	private final JMenuItem quitMenu = new JMenuItem("Quit", KeyEvent.VK_Q);
272 	{
273 		quitMenu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
274 		    ActionEvent.CTRL_MASK));
275 		quitMenu.addActionListener(new ActionListener() {
276 			@Override
277 			public void actionPerformed(ActionEvent e) {
278 				quitApplication();
279 			}
280 		});
281 	}
282 
283 	/** File menu. */
284 	private final JMenu fileMenu = new JMenu("File");
285 	{
286 		fileMenu.add(newProjectionMenu);
287 		fileMenu.add(openProjectionMenu);
288 		fileMenu.add(quickSaveProjectionMenu);
289 		fileMenu.add(saveProjectionMenu);
290 		// TODO: Implement binary result storage.
291 		// fileMenu.add(new JSeparator());
292 		fileMenu.add(loadResultsMenu);
293 		fileMenu.add(quickSaveResultsMenu);
294 		fileMenu.add(saveResultsMenu);
295 		fileMenu.add(new JSeparator());
296 		fileMenu.add(preferencesMenu);
297 		fileMenu.add(execPreferencesMenu);
298 		fileMenu.add(new JSeparator());
299 		fileMenu.add(quitMenu);
300 		fileMenu.setMnemonic(KeyEvent.VK_F);
301 	}
302 
303 	// Parameter menu
304 
305 	/** Menu to edit sets. */
306 	private final JMenuItem editSetsMenu = new JMenuItem("Edit Sets...");
307 	{
308 		editSetsMenu.addActionListener(new ActionListener() {
309 			@Override
310 			public void actionPerformed(ActionEvent e) {
311 				editSets();
312 			}
313 		});
314 	}
315 
316 	/** Menu to edit Settypes. */
317 	private final JMenuItem editSetTypesMenu = new JMenuItem("Edit Settypes...");
318 	{
319 		editSetTypesMenu.addActionListener(new ActionListener() {
320 			@Override
321 			public void actionPerformed(ActionEvent e) {
322 				editSetTypes();
323 			}
324 		});
325 
326 	}
327 
328 	/** Menu to input a matrix quickly. */
329 	private final JMenuItem quickMatrixInput = new JMenuItem(
330 	    "Quick Matrix Input...");
331 	{
332 		quickMatrixInput.addActionListener(new ActionListener() {
333 			@Override
334 			public void actionPerformed(ActionEvent e) {
335 				inputMatrixQuickly();
336 			}
337 		});
338 	}
339 
340 	/** Menu to input a matrix quickly. */
341 	private final JMenuItem copyGenerations = new JMenuItem("Copy Generations...");
342 	{
343 		copyGenerations.addActionListener(new ActionListener() {
344 			@Override
345 			public void actionPerformed(ActionEvent e) {
346 				copyGenerations();
347 			}
348 		});
349 	}
350 
351 	/** Parameter menu. */
352 	private final JMenu parameterMenu = new JMenu("Parameters");
353 	{
354 		parameterMenu.add(new JSeparator());
355 		parameterMenu.add(editSetTypesMenu);
356 		parameterMenu.add(editSetsMenu);
357 		parameterMenu.add(new JSeparator());
358 		parameterMenu.add(quickMatrixInput);
359 		parameterMenu.add(copyGenerations);
360 	}
361 
362 	/** Menu to open info panel. */
363 	private final JMenuItem infoMenu = new JMenuItem("Info (Welcome Screen)");
364 	{
365 		infoMenu.addActionListener(new ActionListener() {
366 			@Override
367 			public void actionPerformed(ActionEvent e) {
368 				contentPanel.removeAll();
369 				contentPanel.add(new WelcomePanel(), BorderLayout.CENTER);
370 				pack();
371 				repaint();
372 			}
373 		});
374 	}
375 
376 	/** Help menu. */
377 	private final JMenu helpMenu = new JMenu("Help");
378 	{
379 		helpMenu.add(infoMenu);
380 	}
381 
382 	/** Main menu bar. */
383 	private final JMenuBar menuBar = new JMenuBar();
384 	{
385 		menuBar.add(fileMenu);
386 		// TODO: Redesign and refactor old parameter dialogs
387 		// menuBar.add(parameterMenu);
388 		menuBar.add(helpMenu);
389 		menuBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
390 		menuBar.putClientProperty(PlasticLookAndFeel.IS_3D_KEY, Boolean.FALSE);
391 	}
392 
393 	// Dialogs to be used
394 
395 	/** Stores name of the last saved projection. */
396 	private String currentProjectionFile;
397 
398 	/** Large panel for displaying the content of a selected element. */
399 	private JPanel contentPanel = new JPanel(GUI.getStdBorderLayout());
400 
401 	/**
402 	 * The tabbed pane for viewing the different levels (database overview,
403 	 * structure of a single projection, etc).
404 	 */
405 	private JTabbedPane tabbedPane = new JTabbedPane();
406 
407 	/** Panel that allows navigation through the current projection. */
408 	private ProjectionTreePanel projTreePanel = new ProjectionTreePanel(
409 	    getCurrentProjection(), contentPanel);
410 
411 	/**
412 	 * Panel that allows navigation through the results of the current projection.
413 	 */
414 	private ResultTreePanel resultsPanel = new ResultTreePanel(
415 	    getCurrentProjection(), contentPanel);
416 
417 	/**
418 	 * Panel that allows to navigate through the overall database and load
419 	 * projection models etc.
420 	 */
421 	private DatabaseOverviewPanel dbOverviewPanel;
422 
423 	/** The configuration file. */
424 	private final P3JConfigFile configFile = new P3JConfigFile();
425 
426 	/**
427 	 * Default constructor.
428 	 */
429 	private P3J() {
430 
431 		try {
432 			getConfigFile().readFile("./" + Misc.CONFIG_FILE);
433 		} catch (Exception ex) {
434 			SimSystem.report(ex);
435 			getConfigFile().setFileName("./" + Misc.CONFIG_FILE);
436 			GUI.printErrorMessage(this, "Error while loading configuration file.",
437 			    "An error occurred while attempting to read the file '"
438 			        + Misc.CONFIG_FILE + "' from the working directory:" + ex);
439 		}
440 
441 		updateFromExecConfig();
442 		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
443 		this.initUI();
444 	}
445 
446 	/**
447 	 * Edits the preferences.
448 	 */
449 	protected void editPreferences() {
450 		PreferencesDialog prefsDialog = new PreferencesDialog(this, getConfigFile());
451 		prefsDialog.setVisible(true);
452 		try {
453 			getConfigFile().writeFile();
454 		} catch (Exception ex) {
455 			SimSystem.report(ex);
456 			GUI.printErrorMessage(this, "Error writing configuration file.",
457 			    "An error occurred while attempting to write to file '"
458 			        + getConfigFile().getFileName() + "' in the working directory:"
459 			        + ex);
460 		}
461 		updateFromConfig();
462 	}
463 
464 	/**
465 	 * Edits the execution preferences.
466 	 */
467 	protected void editExecutionPreferences() {
468 		ExecutionPreferencesDialog execPrefsDialog = new ExecutionPreferencesDialog(
469 		    this);
470 		execPrefsDialog.setVisible(true);
471 		try {
472 			getConfigFile().writeFile();
473 		} catch (Exception ex) {
474 			SimSystem.report(Level.SEVERE, "Error writing configuration file.", ex);
475 			GUI.printErrorMessage(this, "Error writing configuration file.",
476 			    "An error occurred while attempting to write to file '"
477 			        + getConfigFile().getFileName() + "' in the working directory:"
478 			        + ex);
479 		}
480 		updateFromExecConfig();
481 	}
482 
483 	/**
484 	 * Displays a dialog to edit sets.
485 	 */
486 	protected void editSets() {
487 		// (new EditSetsDialog(this,
488 		// P3J.getCurrentProjection())).setVisible(true);
489 	}
490 
491 	/**
492 	 * Displays a dialog to edit Settypes.
493 	 */
494 	protected void editSetTypes() {
495 		// (new EditSetTypesDialog(this,
496 		// getCurrentProjection())).setVisible(true);
497 	}
498 
499 	/**
500 	 * Opens dialog to copy generations.
501 	 */
502 	protected void copyGenerations() {
503 		CopyGenerationsDialog cgd = new CopyGenerationsDialog(
504 		    getCurrentProjection(), this);
505 		cgd.setVisible(true);
506 	}
507 
508 	/**
509 	 * Create a new scenario in database.
510 	 */
511 	protected void newProjection() {
512 		NewProjectionDialog newProjectionDialog = new NewProjectionDialog(this,
513 		    DatabaseFactory.getDatabaseSingleton());
514 		newProjectionDialog.setVisible(true);
515 		if (newProjectionDialog.hasCreatedNewProjection()) {
516 			currentProjection = newProjectionDialog.getNewProjection();
517 			projTreePanel.setProjection(currentProjection);
518 			switchNavigationTreeTab(NavigationTreeTab.PROJECTION_OVERVIEW);
519 			dbOverviewPanel.totalRefresh();
520 		}
521 	}
522 
523 	/**
524 	 * Retrieves user interface singleton.
525 	 * 
526 	 * @return instance of P3J
527 	 */
528 	public static P3J getInstance() {
529 		if (instance == null) {
530 			instance = new P3J();
531 		}
532 		return instance;
533 	}
534 
535 	/**
536 	 * Initializes user interface.
537 	 */
538 	private void initUI() {
539 
540 		this.setTitle("P3J : Probabilistic Population Projection");
541 		this.setPreferredSize(new Dimension(INITIAL_WIDTH, INITIAL_HEIGHT));
542 
543 		this.setJMenuBar(menuBar);
544 		this.getContentPane().setLayout(new BorderLayout());
545 		this.getContentPane().add(toolBar, BorderLayout.NORTH);
546 		this.getContentPane().add(desktop, BorderLayout.CENTER);
547 
548 		DatabaseFactory.setDbConnData(getConfigFile().getDBConnectionData());
549 		currentProjection = null;
550 		dbOverviewPanel = new DatabaseOverviewPanel(contentPanel);
551 		projTreePanel = new ProjectionTreePanel(getCurrentProjection(),
552 		    contentPanel);
553 
554 		tabbedPane.removeAll();
555 		tabbedPane.addTab("Database", dbOverviewPanel);
556 		tabbedPane.addTab("Projection", projTreePanel);
557 		tabbedPane.addTab("Results", resultsPanel);
558 		contentPanel.removeAll();
559 		contentPanel.add(new WelcomePanel(), BorderLayout.CENTER);
560 
561 		JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
562 		splitPane.add(tabbedPane);
563 		splitPane.setDividerLocation(INITIAL_TREE_WIDTH);
564 		splitPane.add(contentPanel);
565 
566 		this.getContentPane().add(splitPane);
567 
568 		// Action handler: close window
569 		this.addWindowListener(new WindowAdapter() {
570 			@Override
571 			public void windowClosing(WindowEvent l) {
572 				P3J.this.quitApplication();
573 			}
574 		});
575 
576 		this.pack();
577 		this.repaint();
578 	}
579 
580 	/**
581 	 * Retrieves current PPP model.
582 	 * 
583 	 * @return the PPP model that is currently edited
584 	 */
585 	public static ProjectionModel getCurrentProjection() {
586 		return currentProjection;
587 	}
588 
589 	/**
590 	 * Save current projection.
591 	 */
592 	void saveProjection() {
593 
594 		int userReaction = this.scenarioFileChooser.showDialog(this, "Save");
595 
596 		if (userReaction != JFileChooser.ERROR_OPTION
597 		    && userReaction != JFileChooser.CANCEL_OPTION) {
598 			File projectionFile = this.scenarioFileChooser.getSelectedFile();
599 
600 			String ending = Misc.getFileEnding(projectionFile);
601 
602 			if (ending.compareToIgnoreCase("p3j") != 0) {
603 				projectionFile = new File(projectionFile.getAbsolutePath() + ".p3j");
604 			}
605 
606 			if (projectionFile != null
607 			    && (!projectionFile.exists() || projectionFile.canWrite())) {
608 				quickSaveProjection(projectionFile.getAbsolutePath());
609 			}
610 
611 		}
612 	}
613 
614 	/**
615 	 * Quick-save current scenario.
616 	 * 
617 	 * @param scenarioFile
618 	 *          the file to which the scenario shall be saved
619 	 */
620 	void quickSaveProjection(String scenarioFile) {
621 		try {
622 			serializer.save(getCurrentProjection(), scenarioFile);
623 			this.currentProjectionFile = scenarioFile;
624 		} catch (Exception ex) {
625 			SimSystem.report(Level.SEVERE, "Error while saving scenario file.", ex);
626 			GUI.printErrorMessage(this, "Error while saving scenario file.",
627 			    "An error occurred while attempting to save file to '" + scenarioFile
628 			        + "': " + ex);
629 		}
630 
631 	}
632 
633 	/**
634 	 * Load a scenario.
635 	 */
636 	void loadProjection() {
637 
638 		int userReaction = this.scenarioFileChooser.showDialog(this, "Open");
639 
640 		if (userReaction != JFileChooser.ERROR_OPTION
641 		    && userReaction != JFileChooser.CANCEL_OPTION) {
642 			File scenarioFile = this.scenarioFileChooser.getSelectedFile();
643 
644 			if (scenarioFile != null && scenarioFile.exists()) {
645 				try {
646 					currentProjection = (ProjectionModel) serializer.load(scenarioFile
647 					    .getAbsolutePath());
648 					currentProjectionFile = scenarioFile.getAbsolutePath();
649 					projTreePanel.setProjection(currentProjection);
650 				} catch (Exception ex) {
651 					SimSystem.report(Level.SEVERE, "Error while opening scenario file.",
652 					    ex);
653 					GUI.printErrorMessage(this, "Error while opening scenario file.",
654 					    "An error occurred while attempting to save file to '"
655 					        + scenarioFile.getAbsolutePath() + "': " + ex);
656 				}
657 			}
658 		}
659 	}
660 
661 	// Event Handler
662 
663 	/**
664 	 * Quit application.
665 	 */
666 	public void quitApplication() {
667 		if (GUI.printQuestion(this, "Quit?", "Do you really want to quit?")) {
668 			System.exit(0);
669 		}
670 	}
671 
672 	/**
673 	 * Switches to a new projection model for editing.
674 	 * 
675 	 * @param newProjModel
676 	 *          the new projection model to be edited
677 	 */
678 	public void setCurrentProjection(ProjectionModel newProjModel) {
679 		if (currentProjection != null) {
680 			DatabaseFactory.getDatabaseSingleton().saveProjection(currentProjection);
681 		}
682 		currentProjection = newProjModel;
683 		projTreePanel.setProjection(currentProjection);
684 		resultsPanel.setProjection(currentProjection);
685 		switchNavigationTreeTab(NavigationTreeTab.PROJECTION_OVERVIEW);
686 	}
687 
688 	/**
689 	 * Input a matrix quickly.
690 	 */
691 	protected void inputMatrixQuickly() {
692 		// (new QuickInputDialog(this,
693 		// getCurrentProjection())).setVisible(true);
694 	}
695 
696 	/**
697 	 * Executed to run a calculation.
698 	 */
699 	protected void startExperiment() {
700 		BaseExperiment baseExperiment = new BaseExperiment();
701 		configureModelLocation(baseExperiment);
702 		configureSimulator(baseExperiment);
703 		configureMultiThreading(baseExperiment);
704 		ExperimentExecutorThreadPool.getInstance().getExecutor()
705 		    .execute(new ExperimentThread(baseExperiment));
706 	}
707 
708 	/**
709 	 * Configures the given experiment for multi-threading.
710 	 * 
711 	 * @param baseExperiment
712 	 *          the experiment to be configured
713 	 */
714 	private void configureMultiThreading(BaseExperiment baseExperiment) {
715 		int numOfTrials = (Integer) getConfigFile().get(Misc.PREF_NUM_TRIALS);
716 		int numOfThreads = (Integer) getConfigFile().get(
717 		    Misc.PREF_NUM_PARALLEL_THREADS);
718 		double stopTime = Math.ceil((double) numOfTrials / numOfThreads);
719 
720 		baseExperiment.setDefaultSimStopTime(stopTime);
721 		baseExperiment.setRepeatRuns(numOfThreads);
722 		baseExperiment
723 		    .setComputationInstrumenterFactory(new ExecProgressInstrFactory());
724 		baseExperiment.setComputationInstrumenterParameters(new ParameterBlock(
725 		    numOfTrials, ExecProgressInstrFactory.NUM_OF_TRIALS));
726 
727 		if (numOfThreads > 1) {
728 			baseExperiment
729 			    .setTaskRunnerFactory(new ParameterizedFactory<TaskRunnerFactory>(
730 			        new ParallelComputationTaskRunnerFactory(), new ParameterBlock(
731 			            numOfThreads, ParallelComputationTaskRunnerFactory.NUM_CORES)));
732 		}
733 	}
734 
735 	/**
736 	 * Configures experiment to use PPPM simulator.
737 	 * 
738 	 * @param baseExperiment
739 	 *          the experiment to be configured
740 	 */
741 	private void configureSimulator(BaseExperiment baseExperiment) {
742 		ParameterBlock processorParameters = baseExperiment
743 		    .getParameters()
744 		    .getParameterBlock()
745 		    .addSubBlock(ProcessorFactory.class.getName(),
746 		        PPPMProcessorFactory.class.getName());
747 		processorParameters.addSubBl(ParamAssignmentGenFactory.class.getName(),
748 		    ((ExecutionMode) getConfigFile().get(Misc.PREF_EXECUTION_MODE))
749 		        .getFactoryName());
750 	}
751 
752 	/**
753 	 * Configures experiment regarding model location.
754 	 * 
755 	 * @param baseExperiment
756 	 *          the experiment to be configured
757 	 */
758 	private void configureModelLocation(BaseExperiment baseExperiment) {
759 		try {
760 			DBConnectionData dbData = DatabaseFactory.getDbConnData();
761 			String dbURL = DatabaseFactory.getDbConnData().getUrl();
762 			SimSystem.report(Level.INFO, "Using database URL:" + dbURL);
763 			dbURL = dbURL.substring(dbURL.indexOf('/')).substring(2);
764 			baseExperiment.setModelLocation(new URI("db-p3j://" + dbData.getUser()
765 			    + ":" + dbData.getPassword() + "@" + dbURL + "?"
766 			    + currentProjection.getID()));
767 		} catch (Exception ex) {
768 			SimSystem.report(Level.SEVERE, "Configuration of model location failed.",
769 			    ex);
770 		}
771 	}
772 
773 	/**
774 	 * Main function.
775 	 * 
776 	 * @param argv
777 	 *          command line arguments
778 	 */
779 	public static void main(String[] argv) {
780 
781 		showSplashScreen();
782 		Locale.setDefault(Locale.US);
783 
784 		try {
785 			String lf = LookUtils.IS_OS_WINDOWS ? Options
786 			    .getCrossPlatformLookAndFeelClassName() : Options
787 			    .getSystemLookAndFeelClassName();
788 			UIManager.setLookAndFeel(lf);
789 		} catch (Exception e) {
790 			SimSystem.report(e);
791 		}
792 
793 		P3J p3j = P3J.getInstance();
794 		splashScreen.setVisible(false);
795 		GUI.centerOnScreen(p3j);
796 		p3j.setVisible(true);
797 	}
798 
799 	/**
800 	 * Shows splash screen.
801 	 */
802 	private static void showSplashScreen() {
803 		try {
804 			BasicUtilities.invokeAndWaitOnEDT(new Runnable() {
805 				@Override
806 				public void run() {
807 					Image image = null;
808 					try {
809 						image = IconManager.getImage("image:/p3j/splashscreen.png");
810 					} catch (Exception ex) {
811 						SimSystem.report(ex);
812 					}
813 					splashScreen = new SplashScreen(image, "", "Version 0.9.5", "", true);
814 					splashScreen.setVisible(true);
815 					splashScreen.pack();
816 				}
817 			});
818 		} catch (InterruptedException e1) {
819 			SimSystem.report(e1);
820 		} catch (InvocationTargetException e1) {
821 			SimSystem.report(e1);
822 		}
823 	}
824 
825 	/**
826 	 * Has to be called to refresh GUI after a {@link ProjectionModel} has been
827 	 * deleted.
828 	 * 
829 	 * @param deletedModel
830 	 *          the model that has been deleted from the database
831 	 */
832 	public void projectionDeleted(ProjectionModel deletedModel) {
833 		if (currentProjection.equals(deletedModel)) {
834 			switchNavigationTreeTab(NavigationTreeTab.DB_OVERVIEW);
835 			projTreePanel.setProjection(null);
836 		}
837 		dbOverviewPanel.totalRefresh();
838 	}
839 
840 	/**
841 	 * Switch the navigation tree tab.
842 	 * 
843 	 * @param targetTab
844 	 *          the desired tab of the navigation tree
845 	 */
846 	public void switchNavigationTreeTab(NavigationTreeTab targetTab) {
847 		tabbedPane.setSelectedIndex(targetTab.getTabIndex());
848 	}
849 
850 	/**
851 	 * Update UI in case configuration changed.
852 	 */
853 	private void updateFromConfig() {
854 		this.getContentPane().removeAll();
855 		initUI();
856 	}
857 
858 	/**
859 	 * Updates the summary of the execution preferences displayed on the buttons
860 	 * that opens them.
861 	 */
862 	private void updateFromExecConfig() {
863 		execPrefsButton.setText("#Trials:"
864 		    + getConfigFile().get(Misc.PREF_NUM_TRIALS) + ", #Threads:"
865 		    + getConfigFile().get(Misc.PREF_NUM_PARALLEL_THREADS) + ", Mode:"
866 		    + getConfigFile().get(Misc.PREF_EXECUTION_MODE));
867 	}
868 
869 	/**
870 	 * Get the configuration file.
871 	 * 
872 	 * @return the configFile
873 	 */
874 	public P3JConfigFile getConfigFile() {
875 		return configFile;
876 	}
877 
878 	/**
879 	 * Refreshes the navigation tree and selects the root node in the currently
880 	 * selected tab, so that all relevant GUI elements are refreshed.
881 	 */
882 	public void refreshNavigationTree() {
883 		NavigationTreeTab currentTab = NavigationTreeTab.values()[tabbedPane
884 		    .getSelectedIndex()];
885 		setCurrentProjection(currentProjection);
886 		switchNavigationTreeTab(currentTab);
887 		switch (currentTab) {
888 		case PROJECTION_OVERVIEW:
889 			projTreePanel.getTree().setSelectionPath(
890 			    new TreePath(projTreePanel.getTreeModel().getRoot()));
891 			break;
892 		case RESULTS_OVERVIEW:
893 			resultsPanel.getTree().setSelectionPath(
894 			    new TreePath(resultsPanel.getTreeModel().getRoot()));
895 			break;
896 		}
897 
898 	}
899 }