001: /*
002: * Project: AMODA - Abstract Modeled Application
003: * Class: de.gulden.framework.amoda.environment.gui.GUIApplicationEnvironment
004: * Version: snapshot-beautyj-1.1
005: *
006: * Date: 2004-09-29
007: *
008: * This is a snapshot version of the AMODA 0.2 development branch,
009: * it is not released as a seperate version.
010: * For AMODA, see http://amoda.berlios.de/.
011: *
012: * This is licensed under the GNU Lesser General Public License (LGPL)
013: * and comes with NO WARRANTY.
014: *
015: * Author: Jens Gulden
016: * Email: amoda@jensgulden.de
017: */
018:
019: package de.gulden.framework.amoda.environment.gui;
020:
021: import de.gulden.framework.amoda.environment.commandline.*;
022: import de.gulden.framework.amoda.environment.gui.component.DefaultButton;
023: import de.gulden.framework.amoda.generic.behaviour.*;
024: import de.gulden.framework.amoda.generic.core.*;
025: import de.gulden.framework.amoda.generic.interaction.*;
026: import de.gulden.framework.amoda.generic.option.*;
027: import de.gulden.framework.amoda.model.behaviour.*;
028: import de.gulden.framework.amoda.model.core.*;
029: import de.gulden.framework.amoda.model.core.WorkspaceProvider;
030: import de.gulden.framework.amoda.model.interaction.*;
031: import de.gulden.framework.amoda.model.interaction.Dialog;
032: import de.gulden.util.Toolbox;
033: import de.gulden.util.xml.XMLToolbox;
034: import java.awt.*;
035: import java.lang.*;
036: import java.util.*;
037: import javax.swing.*;
038:
039: /**
040: * Class GUIApplicationEnvironment.
041: *
042: * @author Jens Gulden
043: * @version snapshot-beautyj-1.1
044: */
045: public class GUIApplicationEnvironment extends
046: CommandLineApplicationEnvironment implements WorkspaceProvider,
047: FontProvider {
048:
049: // ------------------------------------------------------------------------
050: // --- fields ---
051: // ------------------------------------------------------------------------
052:
053: public static String FONT_DEFAULT = "default";
054:
055: public static String FONT_MENU = "menu";
056:
057: public static String FONT_BUTTON = "button";
058:
059: public static String FONT_LABEL = "label";
060:
061: protected JFrame frame;
062:
063: protected Hashtable fontCache = new Hashtable();
064:
065: protected JMenu windowMenu = null;
066:
067: protected JMenu fileMenu = null;
068:
069: protected Command exitCommand;
070:
071: protected Command openMostRecentFileCommand;
072:
073: public static Dimension BUTTON_PREFERRED_SIZE = new Dimension(80,
074: 25);
075:
076: public CommandLineApplicationEnvironment fallbackCommandLineApplicationEnvironment;
077:
078: // ------------------------------------------------------------------------
079: // --- constructor ---
080: // ------------------------------------------------------------------------
081:
082: public GUIApplicationEnvironment() {
083: // your code here
084: }
085:
086: // ------------------------------------------------------------------------
087: // --- methods ---
088: // ------------------------------------------------------------------------
089:
090: public CommandLineApplicationEnvironment getFallbackCommandLineApplicationEnvironment() {
091: return fallbackCommandLineApplicationEnvironment;
092: }
093:
094: public void setFallbackCommandLineApplicationEnvironment(
095: CommandLineApplicationEnvironment commandLineApplicationEnvironment) {
096: this .fallbackCommandLineApplicationEnvironment = commandLineApplicationEnvironment;
097: }
098:
099: public void launch(Application application) {
100: if (!(application instanceof GUIApplication)) { // running a CommandLineApplication inside GUIApplicationEnvirnonment
101: de.gulden.framework.amoda.environment.commandline.CommandLineApplicationEnvironmentFactory f = new de.gulden.framework.amoda.environment.commandline.CommandLineApplicationEnvironmentFactory(
102: getFactory().getArgs());
103: setFallbackCommandLineApplicationEnvironment((CommandLineApplicationEnvironment) f
104: .createApplicationEnvironment());
105: // enable 'gui' option, so user can set
106: ((GenericFeature) options.get("gui")).setSystem(false);
107: // hide main-gui-window related option-groups
108: ((GenericFeature) options.get("environment"))
109: .setSystem(true);
110: ((GenericFeature) options.get("font")).setSystem(true);
111: } else { // normal GUIApplication
112: ((GenericFeature) application.getFeature("default"))
113: .setSystem(true);
114: }
115: super .launch(application);
116: }
117:
118: public void doMessage(Message message) {
119: GenericApplication application = getGenericApplication();
120: if ((application == null) || !application.isQuiet()) {
121: JFrame frame = getFrame();
122: if (frame instanceof de.gulden.framework.amoda.environment.gui.component.CommandLineWrapperFrame) {
123: ((de.gulden.framework.amoda.environment.gui.component.CommandLineWrapperFrame) frame)
124: .doMessage(message);
125: } else {
126: if ((frame != null)
127: && (!((de.gulden.framework.amoda.generic.core.GenericFeature) message)
128: .isSystem())) {
129: if (message.getType() == Message.STATUS_MESSAGE) {
130: String text = message.getText();
131: if (!Toolbox.isEmpty(text)) {
132: ((de.gulden.framework.amoda.environment.gui.component.GUIFrame) frame)
133: .setStatus(text);
134: } else {
135: ((de.gulden.framework.amoda.environment.gui.component.GUIFrame) frame)
136: .resetStatus();
137: }
138: } else {
139: internalDoMessage(message);
140: }
141: } else { // marked as "system": fallback to command-line behaviour
142: getFallbackCommandLineApplicationEnvironment()
143: .doMessage(message);
144: }
145: }
146:
147: }
148: }
149:
150: public void doQuestion(Question question) {
151: GenericQuestion q = (GenericQuestion) question;
152: JOptionPane p = internalCreateJOptionPane(q);
153: JDialog dialog = p.createDialog(getFrame(), q.getMetadata()
154: .get("title", "Question"));
155: dialog.setVisible(true);
156: String answerString = (String) p.getValue();
157: if (answerString == null) {
158: q.setAnswer(Question.CANCEL); // option id "cancel"
159: return;
160: }
161: // find answer in answer options
162: for (Iterator it = q.getAnswerOptions().iterator(); it
163: .hasNext();) {
164: de.gulden.framework.amoda.model.option.Option o = (de.gulden.framework.amoda.model.option.Option) it
165: .next();
166: if (answerString.equals(o.toString())) {
167: q.setAnswer(o.getId());
168: return;
169: }
170: }
171: }
172:
173: public void doErrorMessage(ErrorMessage errorMessage) {
174: // pass to GUIFrame:
175: JFrame frame = getFrame();
176: if (frame instanceof de.gulden.framework.amoda.model.interaction.ErrorMessagePerformer) {
177: ((de.gulden.framework.amoda.model.interaction.ErrorMessagePerformer) frame)
178: .doErrorMessage(errorMessage); // GUIFrame implements ErrorMessagePerformer
179: } else { // fallback as ordinary message, might lead to console output if another fallback
180: doMessage(errorMessage);
181: }
182: if (errorMessage.exitApplication()) {
183: // System.exit(1); // **************** SAUBERER: Application.stop(), frame.destroy() ... ****!!!!
184: }
185: }
186:
187: public void doDialog(Dialog dialog) {
188: GenericDialog d = (GenericDialog) dialog;
189: de.gulden.framework.amoda.generic.option.GenericOptions options = (de.gulden.framework.amoda.generic.option.GenericOptions) d
190: .getOptions();
191: if (!d.isFileDialog()) {
192: JComponent optionsPanel = createOptionsEditor(options);
193: JDialog jdialog = internalCreateJDialog(d, optionsPanel,
194: FlowLayout.CENTER);
195: jdialog.setVisible(true);
196: // ActionListeners on buttons will close dialog and set answer value
197: // now execute all <command>s attached to <dialog>
198: for (Iterator it = d
199: .getAll(
200: de.gulden.framework.amoda.model.behaviour.Command.class,
201: false).values().iterator(); it.hasNext();) {
202: de.gulden.framework.amoda.generic.behaviour.GenericCommand c = (de.gulden.framework.amoda.generic.behaviour.GenericCommand) it
203: .next();
204: c.perform();
205: }
206: } else { // isFileDialog()==true
207: JFileChooser fc = new JFileChooser();
208: /*if (isSave()) {
209: title="Save";
210: } else {
211: title="Load";
212: }*/
213: /*if (d.isDirectories()) {
214: fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
215: } else {
216: fc.setFileSelectionMode(JFileChooser.FILES_ONLY);//FILES_AND_DIRECTORIES);
217: }*/
218: fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
219:
220: // set file filters
221: for (Iterator it = d.getOptions().getEntries().values()
222: .iterator(); it.hasNext();) {
223: de.gulden.framework.amoda.generic.option.GenericOptionEntry o = (de.gulden.framework.amoda.generic.option.GenericOptionEntry) it
224: .next();
225: Class optType = o.getType();
226: if (o.getType() == String.class) {
227: String suffix = o.getValue().getString();
228: if (suffix.startsWith("*.")) {
229: suffix = suffix.substring(2);
230: }
231: String description = o.findTitle();
232: javax.swing.filechooser.FileFilter ff = new de.gulden.util.swing.SuffixFileFilter(
233: suffix, description);
234: fc.addChoosableFileFilter(ff);
235: }
236: }
237:
238: // find first file-typed option among options
239: de.gulden.framework.amoda.generic.option.GenericOptionEntry resultOption = null;
240: for (Iterator it = d.getOptions().getEntries().values()
241: .iterator(); (resultOption == null) && it.hasNext();) {
242: de.gulden.framework.amoda.generic.option.GenericOptionEntry o = (de.gulden.framework.amoda.generic.option.GenericOptionEntry) it
243: .next();
244: Class optType = o.getType();
245: if (optType == java.io.File.class) {
246: resultOption = o;
247: //// clear before new asking:
248: }
249: }
250:
251: if (resultOption == null) { // create if doesn't exist yet
252: resultOption = new de.gulden.framework.amoda.generic.option.GenericOptionEntry();
253: resultOption.setName("file");
254: resultOption.setType(java.io.File.class);
255: ((de.gulden.framework.amoda.generic.option.GenericOptions) d
256: .getOptions()).add(resultOption);
257: }
258:
259: java.io.File file = resultOption
260: .getValue(
261: de.gulden.framework.amoda.model.option.Option.STATE_CURRENT)
262: .getFile();
263: if (file != null) {
264: fc.setSelectedFile(file);
265: }
266:
267: int answer;
268: if (d.isSave()) {
269: answer = fc.showSaveDialog(getFrame());
270: } else {
271: answer = fc.showOpenDialog(getFrame());
272: }
273:
274: if (answer == JFileChooser.APPROVE_OPTION) {
275: if (resultOption != null) {
276: java.io.File f = fc.getSelectedFile();
277: if (!f.isDirectory()) { // if file, make sure the filename has the correct suffix
278: javax.swing.filechooser.FileFilter ff = fc
279: .getFileFilter();
280: if (ff instanceof de.gulden.util.swing.SuffixFileFilter) {
281: de.gulden.util.swing.SuffixFileFilter sff = (de.gulden.util.swing.SuffixFileFilter) ff;
282: String suffix = sff.getSuffix();
283: if (!f.getName().endsWith("." + suffix)) {
284: f = new java.io.File(f
285: .getAbsolutePath()
286: + "." + suffix);
287: }
288: }
289: }
290: ((de.gulden.framework.amoda.generic.data.GenericValue) resultOption
291: .getValue(de.gulden.framework.amoda.model.option.Option.STATE_CURRENT))
292: .set(f);
293: } else {
294: //nop - wouldn't make sence to not give a file option to store the result, but do not throw error
295: }
296: } else {
297: if (resultOption != null) {
298: ((de.gulden.framework.amoda.generic.data.GenericValue) resultOption
299: .getValue(de.gulden.framework.amoda.model.option.Option.STATE_CURRENT))
300: .set(null);
301: } else {
302: //nop - wouldn't make sence to not give a file option to store the result, but do not throw error
303: }
304: }
305: }
306: }
307:
308: public void doWizard(Wizard wizard) {
309: // your code here
310: }
311:
312: public JFrame getFrame() {
313: return frame;
314: }
315:
316: public void setFrame(JFrame _frame) {
317: frame = _frame;
318: }
319:
320: public JComponent createOptionsEditor(GenericOptions options) {
321: if (options.getParentMember() == null)
322: options.setParentMember(getGenericApplication()); // WORKAROUND
323: if (options == getGenericApplication().getOptions()) {
324: ((GenericOptionEntry) options.getOptionEntry("gui"))
325: .setSystem(true); // might have been false for wrapped CommandLineApplication, make invisible here because we are surely running in a GUI here
326: }
327: de.gulden.framework.amoda.generic.behaviour.GenericCondition cond = new de.gulden.framework.amoda.generic.behaviour.GenericCondition() {
328: public boolean test() {
329: de.gulden.framework.amoda.generic.core.GenericFeature f = ((de.gulden.framework.amoda.generic.core.GenericFeature) getObject());
330: return f.isEnabled() && (!f.isSystem());
331: }
332: };
333: int depth = options.countMaxDepth(cond);
334: if (depth == 0) {
335: JLabel label = new JLabel("-empty-", JLabel.CENTER);
336: label.setFont(getDefaultFont());
337: return label;
338: } else if (depth == 1) { // no grouping at all
339: JPanel panel = new JPanel();
340: panel.setLayout(new GridBagLayout());
341: FeatureGroup fg = getGenericApplication().getFeatureGroup(
342: "commandline-wrapper");
343: Feature optionsFeature = fg.getFeature("options");
344: boolean showDescriptionLabels = optionsFeature.getOptions()
345: .getBoolean("show-descriptions");
346: for (Iterator it = options.getEntries().values().iterator(); it
347: .hasNext();) {
348: GenericOptionEntry entry = (GenericOptionEntry) it
349: .next();
350: entry.setParent(options); // WORKAROUND
351: if (cond.test(entry)) {
352: entry.createGUIEditorComponent(panel, this );
353: if (showDescriptionLabels) {
354: String descr = entry.getMetadata().get(
355: "description");
356: JTextArea descrLabel = new JTextArea();
357: descrLabel.setText(descr);
358: descrLabel.setLineWrap(true);
359: descrLabel.setWrapStyleWord(true);
360: descrLabel.setEditable(false);
361: descrLabel.setOpaque(false); // don't paint white background
362: descrLabel.setFont(getFont("menu"));
363: descrLabel.setForeground(new Color(0xff9999cc)); // "Sun dark-blue", TODO: configurable
364: GridBagConstraints gc = new GridBagConstraints();
365: gc.fill = GridBagConstraints.HORIZONTAL;
366: gc.gridwidth = GridBagConstraints.REMAINDER;
367: gc.gridx = 1;
368: panel.add(descrLabel, gc);
369: // vertical space
370: gc = new GridBagConstraints();
371: gc.fill = GridBagConstraints.HORIZONTAL;
372: gc.gridwidth = GridBagConstraints.REMAINDER;
373: panel.add(new JPanel(), gc);
374: }
375: }
376: }
377: return panel;
378: } else if (depth == 2) { // grouping by titledborders
379: JPanel panel = new JPanel();
380: panel.setLayout(new GridBagLayout());
381: GridBagConstraints gbc = new GridBagConstraints();
382: gbc.gridwidth = GridBagConstraints.REMAINDER;
383: gbc.fill = GridBagConstraints.HORIZONTAL;
384: for (Iterator it = options.getGroups().values().iterator(); it
385: .hasNext();) {
386: GenericOptions g = (GenericOptions) it.next();
387: if (cond.test(g) && g.countMaxDepth(cond) > 0) {
388: JComponent gPanel = createOptionsEditor(g); // RECURSION
389: javax.swing.border.TitledBorder border = new javax.swing.border.TitledBorder(
390: g.findTitle());
391: border.setTitleFont(getFont(FONT_MENU));
392: gPanel.setBorder(border);
393: panel.add(gPanel, gbc);
394: }
395: }
396: return panel;
397: } else { // depth>=3: grouping with tabbedpane and titledborders
398: JTabbedPane panel = new JTabbedPane();
399: panel.setFont(getDefaultFont());
400: // flat entries, which are attached to the application directly without group
401: GenericOptions flatEntries = new GenericOptions();
402: flatEntries.setParent(options.getParent());
403: Collection flats = options.getEntries().values();
404: flats = cond.filter(flats); // only enabled and non-system
405: if (flats.size() > 0) {
406: flatEntries.addAll(flats);
407: flatEntries.setParent(null); // !!! make sure that only flat entries are found in next recursion step
408: // but to keep option entries valid, set parent directly on each
409: for (Iterator it = flats.iterator(); it.hasNext();) {
410: GenericOptionEntry entry = (GenericOptionEntry) it
411: .next();
412: entry.setParent(options.getParent());
413: }
414: //flatEntries.setParent(options.getParent()/*getGenericApplication()*/); // now set correct parent
415: JComponent gPanel = createOptionsEditor(flatEntries); // RECURSION
416: //flatEntries.setParent(getGenericApplication()); // now set correct parent
417: panel.addTab("General", gPanel);
418: }
419: // groups
420: for (Iterator it = options.getGroups().values().iterator(); it
421: .hasNext();) {
422: GenericOptions g = (GenericOptions) it.next();
423: if (cond.test(g) && (g.countMaxDepth(cond) > 0)) {
424: g = g.flattenHierarchy(2, cond);
425: JComponent gPanel = createOptionsEditor(g); // RECURSION
426: panel.addTab(g.findTitle(), gPanel);
427: }
428: }
429: return panel;
430: }
431: }
432:
433: public Font getDefaultFont() {
434: return getFont(FONT_DEFAULT);
435: }
436:
437: public Font getFont(String id) {
438: Font f = (Font) fontCache.get(id);
439: if (f == null) {
440: String fontDescription = getGenericApplication()
441: .getOptions().getString("font." + id);
442: StringTokenizer st = new StringTokenizer(fontDescription,
443: ",", false);
444: String fontName = st.nextToken();
445: String fontStyleStr = st.nextToken(); // may also be "bold|italics"
446: String fontSizeStr = st.nextToken();
447: int fontStyle = Font.PLAIN;
448: if (fontStyleStr != null) {
449: fontStyleStr = fontStyleStr.toLowerCase();
450: if (fontStyleStr.indexOf("bold") != -1) {
451: fontStyle |= Font.BOLD;
452: }
453: if (fontStyleStr.indexOf("italic") != -1) {
454: fontStyle |= Font.ITALIC;
455: }
456: }
457: int fontSize = 12;
458: if (fontStyleStr != null) {
459: try {
460: fontSize = Integer.parseInt(fontStyleStr);
461: } catch (NumberFormatException nfe) {
462: //nop
463: }
464: }
465: f = new Font(fontName, fontStyle, fontSize);
466: fontCache.put(id, f);
467: }
468: return f;
469: }
470:
471: public JMenu getWindowMenu() {
472: return windowMenu;
473: }
474:
475: public Command getExitCommand() {
476: return exitCommand;
477: }
478:
479: public void createPopupMenuFromFeatureGroup(
480: FeatureGroup featureGroup, JPopupMenu menu) {
481: if (featureGroup.isEnabled()) {
482: if (menu.getSubElements().length > 0) {
483: menu.addSeparator();
484: }
485: Object previousFeature = null;
486: for (Iterator it = featureGroup.getFeatures().iterator(); it
487: .hasNext();) {
488: Object f = it.next();
489: if (f instanceof FeatureGroup) {
490: createPopupMenuFromFeatureGroup((FeatureGroup) f,
491: menu);
492: } else {
493: if (previousFeature instanceof FeatureGroup) {
494: menu.addSeparator();
495: }
496: menu.add(createMenuItemFromFeature((Feature) f));
497: }
498: previousFeature = f;
499: }
500: }
501: }
502:
503: public JMenu getFileMenu() {
504: return fileMenu;
505: }
506:
507: public Command getOpenMostRecentFileCommand() {
508: return openMostRecentFileCommand;
509: }
510:
511: public void setOpenMostRecentFileCommand(
512: Command _openMostRecentFileCommand) {
513: openMostRecentFileCommand = _openMostRecentFileCommand;
514: }
515:
516: public JButton createButtonFromFeature(Feature feature) {
517: JButton item = new DefaultButton();
518: initFromFeature(item, feature);
519: return item;
520: }
521:
522: public JMenuItem createMenuItemFromFeature(Feature feature) {
523: JMenuItem item = new JMenuItem();
524: item.setFont(getFrame().getJMenuBar().getFont());
525: initFromFeature(item, feature);
526: return item;
527: }
528:
529: public void doAbout() {
530: // this is called only when a non-GUIApp is run inside GUIEnv
531: if (getFrame().isVisible()) { // normal mode
532: GUIApplication a = new GUIApplication() {
533: };
534: a.internalSetGenericApplicationEnvironment(this ); // (set field directly to avoid auto-setting backward-reference)
535: a.setMetadata(getGenericApplication().getMetadata());
536: a.setOptions(getGenericApplication().getOptions());
537: a.about();
538: } else { // during init: fallback to text output
539: super .doAbout();
540: }
541: }
542:
543: public void doHelp() {
544: // this is called only when a non-GUIApp is run inside GUIEnv
545: if (getFrame().isVisible()) { // normal mode
546: GUIApplication a = new GUIApplication() {
547: };
548: a.internalSetGenericApplicationEnvironment(this ); // (set field directly to avoid auto-setting backward-reference)
549: a.setMetadata(getGenericApplication().getMetadata());
550: a.setOptions(getGenericApplication().getOptions());
551: a.help();
552: } else { // during init: fallback to text output
553: super .doHelp();
554: }
555: }
556:
557: public void internalDoMessage(Message message) {
558: JOptionPane.showMessageDialog(frame, message.getText(), message
559: .getMetadata().get("title", "Message"), message
560: .getType());
561: }
562:
563: protected void prepareApplicationWelcome() {
564: super .prepareApplicationWelcome();
565: de.gulden.framework.amoda.generic.core.GenericApplication application = getGenericApplication();
566: // set look and feel if specified by options
567: String lafName = application.getOptions().getString(
568: "swing-look-and-feel");
569: if (!Toolbox.empty(lafName)) {
570: try {
571: javax.swing.UIManager.setLookAndFeel(lafName);
572: } catch (Throwable t) {
573: System.out
574: .println("Warning: Cannot set look-and-feel '"
575: + lafName + "' - ignoring.");
576: }
577: }
578: initDefaultUIFonts();
579:
580: JFrame frame;
581: if (application instanceof GUIApplication) { // no GUIFrame if CommandLineApplication
582: frame = createGUIFrame(); //new de.gulden.framework.amoda.environment.gui.component.GUIFrame(this);
583: } else {
584: frame = createCommandLineWrapperFrame();//new JFrame(); // invisible dummy
585: }
586: java.net.URL url = de.gulden.framework.amoda.generic.metadata.GenericMetadata
587: .findIconResource(getGenericApplication());
588: if (url != null) {
589: java.awt.Image icon = frame.getToolkit().getImage(url);
590: frame.setIconImage(icon);
591: }
592: setFrame(frame);
593: }
594:
595: protected void prepareApplicationStart() {
596: super .prepareApplicationStart();
597: // this is called right before application.start() ist called
598: de.gulden.framework.amoda.generic.core.GenericApplication application = getGenericApplication();
599: if (application.getOptions()
600: .getBoolean("main-window-maximized")) {
601: // doesn't work on Linux with 1.4.1:
602: //f.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH); // Jdk 1.4 required! ***
603: getFrame().setLocation(0, 0);
604: java.awt.Dimension screenSize = getFrame().getToolkit()
605: .getScreenSize();
606: getFrame().setSize(screenSize.width, screenSize.height);
607: } else {
608: getFrame().setLocation(100, 100);
609: getFrame().setSize(
610: getGenericApplication().getOptions().getInt(
611: "main-window-width"),
612: getGenericApplication().getOptions().getInt(
613: "main-window-height"));
614: }
615: getFrame()
616: .setTitle(
617: de.gulden.framework.amoda.generic.metadata.GenericMetadata
618: .findTitle(getGenericApplication()));
619:
620: if (application instanceof GUIApplication) {
621: de.gulden.framework.amoda.environment.gui.component.GUIFrame f = (de.gulden.framework.amoda.environment.gui.component.GUIFrame) getFrame();
622: JMenuBar menubar;
623: JMenu menu;
624: JMenuItem item;
625: Feature feature;
626: menubar = f.getJMenuBar();
627: for (Iterator it = application.getFeatureGroups()
628: .iterator(); it.hasNext();) {
629: Object o = it.next();
630: de.gulden.framework.amoda.generic.core.GenericFeatureGroup g = (de.gulden.framework.amoda.generic.core.GenericFeatureGroup) o;
631: if (g.isEnabled() && (!g.isSystem())) {
632: menu = new JMenu(g.findTitle());
633: menu.setFont(menubar.getFont());
634: createMenuItemsFromFeatureGroup(g, menu);
635: menubar.add(menu);
636: // special:
637: if (g.getId().equals("file-features")) {
638: this .fileMenu = menu;
639: } else if (g.getId().equals("window-features")) {
640: this .windowMenu = menu;
641: }
642: }
643: }
644: f.resetStatus();
645: } else { // e.g. a CommandLineApplication running
646: getFrame().show();
647: }
648: }
649:
650: protected void initDefaultUIFonts() {
651: Font font;
652: font = getDefaultFont();
653: UIDefaults defaults = UIManager.getDefaults();
654: for (Enumeration e = defaults.keys(); e.hasMoreElements();) {
655: Object o = e.nextElement();
656: if (o instanceof String) {
657: String key = (String) o;
658: if (key.endsWith(".font")) {
659: UIManager.put(key,
660: new javax.swing.plaf.FontUIResource(font));
661: }
662: }
663: }
664: }
665:
666: protected JFrame createGUIFrame() {
667: return new de.gulden.framework.amoda.environment.gui.component.GUIFrame(
668: this );
669: }
670:
671: protected JFrame createCommandLineWrapperFrame() {
672: return new de.gulden.framework.amoda.environment.gui.component.CommandLineWrapperFrame(
673: this );
674: }
675:
676: protected void launchAfterInit(GenericApplication genericApplication) {
677: if (!genericApplication.getOptions().getBoolean("gui")) {
678: // perform launch again on fallback environment (CommandLineApplications that run in GUIEnvionrments should be able to be initialized mutliple times without harm)
679: getFallbackCommandLineApplicationEnvironment().launch(
680: genericApplication);
681: } else {
682: super .launchAfterInit(genericApplication); // normal GUI mode, or CommandLineApplication in GUI-wrapper
683: }
684: }
685:
686: protected void initFromFeature(AbstractButton item, Feature feature) {
687: String title = de.gulden.framework.amoda.generic.metadata.GenericMetadata
688: .findTitle(feature);
689: if (item instanceof JMenuItem) {
690: title = title.trim();
691: }
692: item.setText(title);
693: String shortcut = ((de.gulden.framework.amoda.generic.core.GenericFeature) feature)
694: .getShortcut();
695: if (shortcut != null) {
696: StringTokenizer st = new StringTokenizer(shortcut, " +-,",
697: false);
698: shortcut = "ctrl";
699: while (st.hasMoreTokens()) {
700: String tok = st.nextToken();
701: if (st.hasMoreTokens()) { // not last one: force modifiers to lower case
702: tok = tok.toLowerCase();
703: }
704: shortcut += " " + tok;
705: }
706: if (item instanceof JMenuItem) {
707: javax.swing.KeyStroke ks = javax.swing.KeyStroke
708: .getKeyStroke(shortcut); // parses string
709: if (ks != null) {
710: ((JMenuItem) item).setAccelerator(ks);
711: }
712: }
713: }
714: int commandCount = 0;
715: for (Iterator it = feature.getAll(GenericCommand.class, false)
716: .values().iterator(); it.hasNext();) {
717: GenericCommand c = (GenericCommand) it.next();
718: c.setParent(getGenericApplication());
719: item.addActionListener((java.awt.event.ActionListener) c);
720: commandCount++;
721: // special:
722: if (((c instanceof de.gulden.framework.amoda.generic.behaviour.CommandApplicationExit) || ((c instanceof de.gulden.framework.amoda.generic.behaviour.CommandWrapper) && (((de.gulden.framework.amoda.generic.behaviour.CommandWrapper) c)
723: .getWrapped() instanceof de.gulden.framework.amoda.generic.behaviour.CommandApplicationExit)))
724: && (exitCommand == null)) {
725: exitCommand = c; // remember exit command to execute exactly the same when window-closing is activated
726: }
727: }
728: if (commandCount == 0) {
729: item.setEnabled(false);
730: }
731: }
732:
733: protected void createMenuItemsFromFeatureGroup(
734: FeatureGroup featureGroup, JMenu menu) {
735: if (featureGroup.isEnabled()) {
736: java.awt.Component[] components = menu.getMenuComponents();
737: if ((components.length > 0)
738: && (components[components.length - 1] instanceof javax.swing.MenuElement)) { // last one not yet separator
739: menu.addSeparator();
740: }
741: Object previousFeature = null;
742: for (Iterator it = featureGroup.getFeatures().iterator(); it
743: .hasNext();) {
744: Object f = it.next();
745: if (f instanceof FeatureGroup) {
746: createMenuItemsFromFeatureGroup((FeatureGroup) f,
747: menu);
748: } else {
749: if (previousFeature instanceof FeatureGroup) {
750: menu.addSeparator();
751: }
752: menu.add(createMenuItemFromFeature((Feature) f));
753: }
754: previousFeature = f;
755: }
756: }
757: }
758:
759: protected void launchStart(GenericApplication application) {
760: //if (application instanceof GUIApplication) { // if CommandLineApp in CommandLineWrapperFrame, start via Start-Button
761: if ((!(getFrame() instanceof de.gulden.framework.amoda.environment.gui.component.CommandLineWrapperFrame))
762: || (!application.getFeatureGroup("commandline-wrapper")
763: .getFeature("start").isEnabled())) {
764: application.start();
765: }
766: }
767:
768: private JOptionPane internalCreateJOptionPane(GenericQuestion q) {
769: Collection answerOptions = q.getAnswerOptions();
770: // convert each answer option to Strings for button labels
771: String[] answers = new String[answerOptions.size()];
772: int i = 0;
773: for (Iterator it = answerOptions.iterator(); it.hasNext();) {
774: answers[i++] = it.next().toString();
775: }
776: JOptionPane p = new JOptionPane();
777: p.setMessageType(q.getType());
778: p.setMessage(q.getText());
779: p.setOptions(answers);
780: p.setInitialValue(q.getDefaultAnswer());
781: return p;
782: }
783:
784: private JButton internalCreateOptionButton(
785: GenericOptionEntry option, GenericDialog parentDialog) {
786: JButton button = new DefaultButton(option.findTitle());
787: button.setFont(getDefaultFont());
788: if (option.getId().equals(parentDialog.getDefaultAnswer())) {
789: parentDialog.getJDialog().getRootPane().setDefaultButton(
790: button);
791: }
792: for (Iterator it = option
793: .getAll(
794: de.gulden.framework.amoda.generic.behaviour.GenericCommand.class,
795: false).values().iterator(); it.hasNext();) {
796: de.gulden.framework.amoda.generic.behaviour.GenericCommand c = (de.gulden.framework.amoda.generic.behaviour.GenericCommand) it
797: .next();
798: de.gulden.framework.amoda.generic.behaviour.GenericCommand cc = (de.gulden.framework.amoda.generic.behaviour.GenericCommand) c
799: .clone();
800: cc.setParent(parentDialog);
801: button.addActionListener(cc); // let all <command>s specified inside <option> be executed when button is chosen
802: }
803: return button;
804: }
805:
806: private JDialog internalCreateJDialog(GenericDialog d,
807: JComponent mainComponent, int buttonOrientation) {
808: JDialog dialog = new JDialog(getFrame(), true);
809: d.setJDialog(dialog);
810: String title = d.getTitle();
811: if (title == null) {
812: title = d.getMetadata().get("title", "Dialog");
813: }
814: dialog.setTitle(title);
815: dialog.getContentPane().setLayout(new BorderLayout());
816: dialog.getContentPane().add(mainComponent, BorderLayout.CENTER);
817: JPanel buttonsPanel = new JPanel();
818: buttonsPanel.setLayout(new FlowLayout(buttonOrientation));
819: Collection answerOptions = d.getAnswerOptions();
820: for (Iterator it = answerOptions.iterator(); it.hasNext();) {
821: de.gulden.framework.amoda.generic.option.GenericOptionEntry answer = (de.gulden.framework.amoda.generic.option.GenericOptionEntry) it
822: .next();
823: buttonsPanel.add(internalCreateOptionButton(answer, d));
824: }
825: dialog.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
826: dialog.pack();
827: Toolbox.centerComponent(dialog, getFrame());
828: return dialog;
829: }
830:
831: // ------------------------------------------------------------------------
832: // --- static method ---
833: // ------------------------------------------------------------------------
834:
835: public static void invoke(Class applicationClass, String[] args)
836: throws Exception {
837: de.gulden.framework.amoda.generic.core.GenericApplicationEnvironment
838: .invoke(applicationClass, args,
839: GUIApplicationEnvironmentFactory.class);
840: }
841:
842: } // end GUIApplicationEnvironment
|