001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032: package com.vividsolutions.jump.workbench;
033:
034: import com.vividsolutions.jump.I18N;
035: import com.vividsolutions.jump.task.TaskMonitor;
036: import com.vividsolutions.jump.util.Blackboard;
037: import com.vividsolutions.jump.util.LangUtil;
038: import com.vividsolutions.jump.util.StringUtil;
039: import com.vividsolutions.jump.util.commandline.CommandLine;
040: import com.vividsolutions.jump.util.commandline.OptionSpec;
041: import com.vividsolutions.jump.util.commandline.ParseException;
042: import com.vividsolutions.jump.workbench.driver.DriverManager;
043: import com.vividsolutions.jump.workbench.plugin.PlugInManager;
044: import com.vividsolutions.jump.workbench.ui.SplashPanel;
045: import com.vividsolutions.jump.workbench.ui.SplashWindow;
046: import com.vividsolutions.jump.workbench.ui.WorkbenchFrame;
047: import com.vividsolutions.jump.workbench.ui.images.IconLoader;
048:
049: import java.awt.*;
050: import java.awt.event.WindowAdapter;
051: import java.awt.event.WindowEvent;
052:
053: import java.io.File;
054:
055: import java.util.ArrayList;
056: import java.util.List;
057:
058: import javax.swing.*;
059: import javax.swing.ImageIcon;
060: import javax.swing.JLabel;
061: import javax.swing.JPanel;
062: import javax.swing.UIManager;
063:
064: /**
065: * This class is responsible for setting up and displaying the main JUMP
066: * workbench window.
067: */
068:
069: public class JUMPWorkbench {
070: private static ImageIcon splashImage;
071:
072: public static ImageIcon splashImage() {
073: // Lazily initialize it, as it may not even be called (e.g. EZiLink),
074: // and we want the splash screen to appear ASAP [Jon Aquino]
075: if (splashImage == null) {
076: splashImage = IconLoader.icon("splash.png");
077: //splashImage = IconLoader.icon(I18N.get("splash.png"));
078: }
079: return splashImage;
080: }
081:
082: private static final ImageIcon APP_ICON = IconLoader
083: .icon("app-icon.gif");
084: public static final String VERSION_TEXT = I18N
085: .get("JUMPWorkbench.version.number");
086: //-- dont change the following strings
087: public final static String PROPERTIES_OPTION = "properties";
088: public final static String PLUG_IN_DIRECTORY_OPTION = "plug-in-directory";
089: public final static String I18N_FILE = "i18n";
090: public static final String INITIAL_PROJECT_FILE = "project";
091:
092: // Added by STanner to allow I18N to have access to this
093: public static String I18N_SETLOCALE = "";
094:
095: private static Class progressMonitorClass = SingleLineProgressMonitor.class;
096:
097: //<<TODO:REFACTORING>> Move images package under
098: // com.vividsolutions.jump.workbench
099: //to avoid naming conflicts with other libraries. [Jon Aquino]
100: private CommandLine commandLine;
101: private WorkbenchContext context = new JUMPWorkbenchContext(this );
102: private WorkbenchFrame frame;
103: private DriverManager driverManager = new DriverManager(frame);
104: private WorkbenchProperties dummyProperties = new WorkbenchProperties() {
105: public List getPlugInClasses() {
106: return new ArrayList();
107: }
108:
109: public List getPlugInClasses(ClassLoader classLoader) {
110: return new ArrayList();
111: }
112:
113: public List getInputDriverClasses() {
114: return new ArrayList();
115: }
116:
117: public List getOutputDriverClasses() {
118: return new ArrayList();
119: }
120:
121: public List getConfigurationClasses() {
122: return new ArrayList();
123: }
124: };
125:
126: private WorkbenchProperties properties = dummyProperties;
127: private PlugInManager plugInManager;
128: private Blackboard blackboard = new Blackboard();
129:
130: /**
131: * @param s
132: * a visible SplashWindow to close when initialization is
133: * complete and the WorkbenchFrame is opened
134: */
135: public JUMPWorkbench(String title, String[] args, ImageIcon icon,
136: final JWindow s, TaskMonitor monitor) throws Exception {
137: parseCommandLine(args);
138: // load i18n specified in command line ( '-i18n translation' )
139: if (commandLine.hasOption(I18N_FILE)) {
140: I18N.loadFile(commandLine.getOption(I18N_FILE).getArg(0));
141: I18N_SETLOCALE = commandLine.getOption(I18N_FILE).getArg(0);
142: }
143: frame = new WorkbenchFrame(title, icon, context);
144: frame.addWindowListener(new WindowAdapter() {
145: public void windowOpened(WindowEvent e) {
146: s.setVisible(false);
147: }
148: });
149:
150: if (commandLine.hasOption(PROPERTIES_OPTION)) {
151: File propertiesFile = new File(commandLine.getOption(
152: PROPERTIES_OPTION).getArg(0));
153: if (propertiesFile.exists()) {
154: properties = new WorkbenchPropertiesFile(
155: propertiesFile, frame);
156: } else {
157: System.out
158: .println("JUMP: Warning: Properties file does not exist: "
159: + propertiesFile);
160: }
161: }
162:
163: File extensionsDirectory = null;
164: if (commandLine.hasOption(PLUG_IN_DIRECTORY_OPTION)) {
165: extensionsDirectory = new File(commandLine.getOption(
166: PLUG_IN_DIRECTORY_OPTION).getArg(0));
167: if (!extensionsDirectory.exists()) {
168: System.out
169: .println("JUMP: Warning: Extensions directory does not exist: "
170: + extensionsDirectory);
171: extensionsDirectory = null;
172: }
173: } else {
174: extensionsDirectory = new File("../lib/ext");
175: if (!extensionsDirectory.exists()) {
176: // Added further information so that debug user will know where
177: // it is actually looking for as the extension directory. [Ed Deen]
178: System.out
179: .println("JUMP: Warning: Extensions directory does not exist: "
180: + extensionsDirectory
181: + " where homedir = ["
182: + System.getProperty("user.dir") + "]");
183: extensionsDirectory = null;
184: }
185: }
186: if (commandLine.hasOption(INITIAL_PROJECT_FILE)) {
187: String task = commandLine.getOption(INITIAL_PROJECT_FILE)
188: .getArg(0);
189: this .getBlackboard().put(INITIAL_PROJECT_FILE, task);
190: }
191:
192: plugInManager = new PlugInManager(context, extensionsDirectory,
193: monitor);
194:
195: //Load drivers before initializing the frame because part of the frame
196: //initialization is the initialization of the driver dialogs. [Jon
197: // Aquino]
198: //The initialization of some plug-ins (e.g. LoadDatasetPlugIn) requires
199: // that
200: //the drivers be loaded. Thus load the drivers here, before the
201: // plug-ins
202: //are initialized.
203: driverManager.loadDrivers(properties);
204: }
205:
206: public static void main(String[] args) {
207: try {
208: //Init the L&F before instantiating the progress monitor [Jon
209: // Aquino]
210: initLookAndFeel();
211: ProgressMonitor progressMonitor = (ProgressMonitor) progressMonitorClass
212: .newInstance();
213: SplashPanel splashPanel = new SplashPanel(splashImage(),
214: I18N.get("JUMPWorkbench.version") + " "
215: + VERSION_TEXT /*+ JUMPVersion.CURRENT_VERSION*/); //[sstein] added but disabled JumpVersion
216: splashPanel.add(progressMonitor, new GridBagConstraints(0,
217: 10, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
218: GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0,
219: 10), 0, 0));
220:
221: main(args, I18N.get("JUMPWorkbench.jump"),
222: new JUMPConfiguration(), splashPanel,
223: progressMonitor);
224: } catch (Throwable t) {
225: WorkbenchFrame.handleThrowable(t, null);
226: }
227: }
228:
229: /**
230: * setupClass is specified as a String to prevent it from being loaded
231: * before we display the splash screen, in case setupClass takes a long time
232: * to load.
233: * @param args main application arguments
234: * @param title application title
235: * @param setup an object implementing the Setup interface
236: * (e.g. JUMPConfiguration)
237: * @param splashComponent
238: * a component to open until the workbench frame is displayed
239: * @param taskMonitor
240: * notified of progress of plug-in loading
241: */
242: public static void main(String[] args, String title, Setup setup,
243: JComponent splashComponent, TaskMonitor taskMonitor) {
244: try {
245: //I don't know if we still need to specify the SAX driver [Jon
246: // Aquino 10/30/2003]
247: System.setProperty("org.xml.sax.driver",
248: "org.apache.xerces.parsers.SAXParser");
249:
250: initLookAndFeel();
251: SplashWindow splashWindow = new SplashWindow(
252: splashComponent);
253: splashWindow.setVisible(true);
254:
255: JUMPWorkbench workbench = new JUMPWorkbench(title, args,
256: APP_ICON, splashWindow, taskMonitor);
257:
258: setup.setup(workbench.context);
259:
260: workbench.context.getWorkbench().getPlugInManager().load();
261: workbench.getFrame().setVisible(true);
262: } catch (Throwable t) {
263: WorkbenchFrame.handleThrowable(t, null);
264: }
265: }
266:
267: private static void initLookAndFeel() throws Exception {
268: if (LangUtil.ifNull(System.getProperty("initLookAndFeel"),
269: "true").toString().equalsIgnoreCase("false")) {
270: return;
271: }
272: //Apple stuff from Raj Singh's startup script [Jon Aquino 10/30/2003]
273: System.setProperty("apple.laf.useScreenMenuBar", "true");
274: System.setProperty("apple.awt.showGrowBox", "true");
275: if (UIManager.getLookAndFeel() != null
276: && UIManager
277: .getLookAndFeel()
278: .getClass()
279: .getName()
280: .equals(
281: UIManager
282: .getSystemLookAndFeelClassName())) {
283: return;
284: }
285: String laf = System.getProperty("swing.defaultlaf");
286: if (laf == null) {
287: laf = UIManager.getSystemLookAndFeelClassName();
288: }
289: UIManager.setLookAndFeel(laf);
290: }
291:
292: public DriverManager getDriverManager() {
293: return driverManager;
294: }
295:
296: /**
297: * The properties file; not to be confused with the WorkbenchContext
298: * properties.
299: */
300: public WorkbenchProperties getProperties() {
301: return properties;
302: }
303:
304: public WorkbenchFrame getFrame() {
305: return frame;
306: }
307:
308: public WorkbenchContext getContext() {
309: return context;
310: }
311:
312: private void parseCommandLine(String[] args)
313: throws WorkbenchException {
314: //<<TODO:QUESTION>> Notify MD: using CommandLine [Jon Aquino]
315: commandLine = new CommandLine('-');
316: commandLine.addOptionSpec(new OptionSpec(PROPERTIES_OPTION, 1));
317: commandLine.addOptionSpec(new OptionSpec(
318: PLUG_IN_DIRECTORY_OPTION, 1));
319: commandLine.addOptionSpec(new OptionSpec(I18N_FILE, 1));
320: //[UT] 17.08.2005
321: commandLine.addOptionSpec(new OptionSpec(INITIAL_PROJECT_FILE,
322: 1));
323:
324: try {
325: commandLine.parse(args);
326: } catch (ParseException e) {
327: throw new WorkbenchException(
328: "A problem occurred parsing the command line: "
329: + e.toString());
330: }
331: }
332:
333: public PlugInManager getPlugInManager() {
334: return plugInManager;
335: }
336:
337: //<<TODO>> Make some properties persistent using a #makePersistent(key)
338: // method. [Jon Aquino]
339: /**
340: * Expensive data structures can be cached on the blackboard so that several
341: * plug-ins can share them.
342: */
343: public Blackboard getBlackboard() {
344: return blackboard;
345: }
346:
347: private static abstract class ProgressMonitor extends JPanel
348: implements TaskMonitor {
349: private Component component;
350:
351: public ProgressMonitor(Component component) {
352: this .component = component;
353: setLayout(new BorderLayout());
354: add(component, BorderLayout.CENTER);
355: setOpaque(false);
356: }
357:
358: protected Component getComponent() {
359: return component;
360: }
361:
362: protected abstract void addText(String s);
363:
364: public void report(String description) {
365: addText(description);
366: }
367:
368: public void report(int itemsDone, int totalItems,
369: String itemDescription) {
370: addText(itemsDone + " / " + totalItems + " "
371: + itemDescription);
372: }
373:
374: public void report(Exception exception) {
375: addText(StringUtil.toFriendlyName(exception.getClass()
376: .getName()));
377: }
378:
379: public void allowCancellationRequests() {
380: }
381:
382: public boolean isCancelRequested() {
383: return false;
384: }
385: }
386:
387: private static class VerticallyScrollingProgressMonitor extends
388: ProgressMonitor {
389: private static int ROWS = 3;
390: private JLabel[] labels;
391:
392: public VerticallyScrollingProgressMonitor() {
393: super (new JPanel(new GridLayout(ROWS, 1)));
394:
395: JPanel panel = (JPanel) getComponent();
396: panel.setOpaque(false);
397: labels = new JLabel[ROWS];
398:
399: for (int i = 0; i < ROWS; i++) {
400: //" " not "", to give the label some height. [Jon Aquino]
401: labels[i] = new JLabel(" ");
402: labels[i].setFont(labels[i].getFont().deriveFont(
403: Font.BOLD));
404: panel.add(labels[i]);
405: }
406: }
407:
408: protected void addText(String s) {
409: for (int i = 0; i < (ROWS - 1); i++) { //-1
410: labels[i].setText(labels[i + 1].getText());
411: }
412:
413: labels[ROWS - 1].setText(s);
414: }
415: }
416:
417: private static class SingleLineProgressMonitor extends
418: ProgressMonitor {
419: public SingleLineProgressMonitor() {
420: super (new JLabel(" "));
421: ((JLabel) getComponent()).setFont(((JLabel) getComponent())
422: .getFont().deriveFont(Font.BOLD));
423: ((JLabel) getComponent())
424: .setHorizontalAlignment(JLabel.LEFT);
425: }
426:
427: protected void addText(String s) {
428: ((JLabel) getComponent()).setText(s);
429: }
430: }
431:
432: private static class HorizontallyScrollingProgressMonitor extends
433: ProgressMonitor {
434: private static final String BUFFER = " ";
435:
436: public HorizontallyScrollingProgressMonitor() {
437: super (new JLabel(" "));
438: ((JLabel) getComponent()).setFont(((JLabel) getComponent())
439: .getFont().deriveFont(Font.BOLD));
440: ((JLabel) getComponent())
441: .setHorizontalAlignment(JLabel.RIGHT);
442: }
443:
444: protected void addText(String s) {
445: ((JLabel) getComponent()).setText(BUFFER + s
446: + ((JLabel) getComponent()).getText());
447: }
448: }
449: }
|