import org.mdi.app.AbstractApplication; public class BasicTutorialMDI extends AbstractMDIApplication { public BasicTutorialMDI() { super("BasicTutorialMDI"); } public static void main(String[] args) { SimpleMDI mdi = new SimpleMDI(); mdi.setVisible(true); } }For the moment, we will only see an empty panel like that:
public BasicTutorialMDI() { super("BasicTutorialMDI"); this.setSize(500, 500); }
import org.mdi.app.AbstractMDIApplication; public class SimpleMenuFactory extends AbstractMDIMenuFactory { private JMenu filemenu = new JMenu("File"); public SimpleMenuFactory() { super(); } protected void initMenus() { JMenuItem exitItem = new JMenuItem(getDefaultExitAction("Exit")); filemenu.add(exitItem); Mbar.add(filemenu); }We don't need to create an Exit action ourselves. We can use the default built-in AbstractMDIMenuFactory.getDefaultExitAction(String) method in the AbstractMDIMenuFactory class. And now whe will have an exit menu. We need to reference the menu factory in the Application:
public BasicTutorialMDI() { super("BasicTutorialMDI"); this.initConfiguration(); // initialize the Application without storing Preferences mfactory = new SimpleMenuFactory(); // create the Application Panels with // preparePanels(int messageAreaSize, boolean hasStatusbar, boolean hasToolBar, MDIMenuFactory mfactory) // - a Message Area of 4 rows height // - a status bar // - no tool bar // - our Menu Factory super.preparePanels(4, true, false, mfactory); this.setSize(500, 500); }
public BasicTutorialMDI() { super("BasicTutorialMDI"); // set the plugins directory. Note that the plugins directory should be initialized before initializing the // configuration to be able to manage Plugins File useDir = System.getProperty("user.dir"); pluginsDir = new File(useDir, "plugins"); this.initConfiguration(); // register plugins in the plugins directory this.registerPlugins(); mfactory = new SimpleMenuFactory(); super.preparePanels(4, true, false, mfactory); this.setSize(500, 500); }For now, we don't have any Plugin to reference, we will do it in the next chapter. We can now do two other useful things about Plugins in the main Application:
public class SimpleMenuFactory extends AbstractMenuFactory { private JMenu filemenu = new JMenu("File"); private JMenu openmenu = new JMenu("Open"); private JMenu helpmenu = new JMenu("Help"); public SimpleMenuFactory() { super(); } protected void initMenus() { JMenuItem exitItem = new JMenuItem(getDefaultExitAction("Exit")); filemenu.add(exitItem); filemenu.add(openmenu); // register key maps staticMenuKeyMap.put(PluginElementTypes.OPEN_ACTIONS, openmenu); registerMenus(); // create the about Plugins menu, it should be done AFTER registering the menus, because the AboutPluginsAction // will be created when registering the menus JMenuItem aboutPluginsItem = new JMenuItem(getPluginsMenuFactory().getAboutPluginsAction()); helpmenu.add(aboutPluginsItem); Mbar.add(filemenu); Mbar.add(helpmenu); } }As you see, the About Plugins is also built-in[1]
package org.mdi.examples.simple.plugins; import org.mdi.plugins.AbstractPlugin; public class OpenImagePlugin extends AbstractPlugin { public static final String OPEN_IMAGES = "OpenImages"; public static final String OPEN_IMAGES_DESC = "Open Images Plugin"; public OpenImagePlugin() { } public String getPluginName() { return OPEN_IMAGES; } public Object getPluginProperty(String prop) { if (prop.equals(PluginElementTypes.PROPERTY_DATE)) return "undef"; else if (prop.equals(PluginElementTypes.PROPERTY_DESC)) return OPEN_IMAGES_DESC; else if (prop.equals(PluginElementTypes.PROPERTY_VERSION)) return "0.1"; else return null; } }Three properties are required to be able to correctly resister this Plugin. They should be returned in the Plugin.getPluginProperty(String)[2]
MDIPluginClass: org.samples.plugins.OpenImagePlugin
This Plugin does nothing but will now be loaded by the Application. So now have something to show in the Help menu.MDIAction
which is also a Swing AbstractAction
, so that it can be used directly in Swing components.package org.mdi.examples.simple.plugins; public class ImportImageAction extends AbstractMDIAction { public ImportImageAction(String name) { super(app, name); this.setDescription("Open Image", "Open Image"); } public void run() throws Exception { } }And now we can call this action in tour Plugin:
package org.mdi.examples.simple.plugins; public class OpenImagePlugin extends AbstractMDIPlugin { public static final String OPEN_IMAGES = "OpenImages"; public static final String OPEN_IMAGES_DESC = "Open Images Plugin"; private List importMenuActions; public OpenImagePlugin() { } public String getPluginName() { return OPEN_IMAGES; } public void register(Application app) { super.register(app); importMenuActions = new Vector(1); importMenuActions.add(new ImportImageAction((GUIApplication) app, "Image")); } public Object getStaticMenuElements(String menu) { if (menu.equals(PluginElementTypes.OPEN_ACTIONS)) return importMenuActions; else return null; } }
AbstractMDIAction
without using a List (using a List is useful if you want to register more than one MDIAction
at onceAbstractMDIAction
and registering itAbstractMDIAction
but creating a new MDIAction
, and calling it in the actionPerformed(ActionEvent)
method of a plain Java AbstractAction
run()
method of the Action is specific of what we do and not related to the framework, lets look at it however to see something functional:public void run() throws Exception { JFileChooser chooser = new JFileChooser("Open Image"); chooser.setDialogTitle("Open Image"); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); if (chooser.showOpenDialog(app.getApplicationWindow()) == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); BufferedImage image = ImageIO.read(file); if (image == null) throw new Exception("Bad File type"); JScrollPane pane = new JScrollPane(new ImagePanel(image)); app.addTab(pane, image, file.getName()); } }We don't have to bother about the Exception, it will be catched by the main Application, and a specific Exception panel will appear if there is any Exception encountered. The important part here is the TabbedApplication.addTab(JComponent, Object, String) after the creation of the image:
MetaData
(MetaData are useful when we want to handle more than one type of File / tabs, which is not the case here, every tab will contain a BufferedImage).public class SimpleMenuFactory extends AbstractMDIMenuFactory { protected void createPopupMenu(JPopupMenu menu) { JMenuItem close = this.getDefaultCloseItem("Close"); menu.add(close); } }
run()
method, an error panel will appearpublic class AnalyseImageAction extends AbstractMDIAction { public AnalyseImageAction(String name) { super(app, name); this.setDescription("Analyse", "Analyze Image"); } public void run() throws Exception { } }And call this class from our menu factory:
public class SimpleMenuFactory extends AbstractMDIMenuFactory { protected void initMenus() { JMenuItem exitItem = new JMenuItem(getDefaultExitAction("Exit")); filemenu.add(exitItem); openmenu = new JMenu("Open"); filemenu.add(openmenu); // new analyseImage Item JMenuItem analyseImageItem = new JMenuItem(new AnalyseImageAction(appli, , "Analyze")); filemenu.add(analyseImageItem); JMenuItem aboutPluginsItem = new JMenuItem(getPluginsMenuFactory().getAboutPluginsAction()); helpmenu.add(aboutPluginsItem); staticMenuKeyMap.put(PluginElementTypes.OPEN_ACTIONS, openmenu); getPluginsMenuFactory().registerMenus(staticMenuKeyMap, null); Mbar.add(filemenu); Mbar.add(helpmenu); } }And now we can write the code that perform the Analysis in the
AnalyseImageAction
class:public void run() throws Exception { // will only analyse the image if there is one available property // for our case, we could also have used app.getTabCount() != 0 if (app.getSelectedProperties() != null) { // specific code, could have been in an Action BufferedImage image = (BufferedImage)app.getSelectedProperties().getObject(); // The application window is the mother component of the dialog // the name of the selected property is the name of the tab JDialog dialog = new JDialog(app.getApplicationWindow(), app.getSelectedProperties().getName(), false); // specific code Container pane = dialog.getContentPane(); pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); pane.add(new JLabel("Width: " + image.getWidth())); pane.add(new JLabel("Height: " + image.getHeight())); pane.add(new JLabel("Type: " + image.getType())); dialog.setSize(200, 100); dialog.setVisible(true); } }
(BufferedImage)app.getSelectedProperties().getObject()
gets the BufferedImage
which is associated with the selected tab.
public BasicTutorialMDI() { super("BasicTutorialMDI"); ImageIcon splash = new ImageIcon(this.getClass().getResource("splash.png")); SplashScreen splashdialog = new SplashScreen(splash, "0.1", "Build xxxx", true); ... splashdialog.dispose(); splashdialog = null; }To change the state of the SplashScreen, we only have to call its SplashScreen.setProgress(int, String) method, for example:
public BasicTutorialMDI() { super("BasicTutorialMDI"); ImageIcon splash = new ImageIcon(this.getClass().getResource("splash.png")); SplashScreen splashdialog = new SplashScreen(splash, "0.1", "Build xxxx", true); ... // initialize configuration without Preferences this.initConfiguration(); splashdialog.setProgress(splashdialog.getProgress() + 20, "Register Plugins"); // register plugins in the plugins directory (same as main application jar directory) this.registerPlugins(); ... }If we want to use it in the menu factory, we need to set the Splash to it after initialization:
public BasicTutorialMDI() { super("BasicTutorialMDI"); ImageIcon splash = new ImageIcon(this.getClass().getResource("splash.png")); SplashScreen splashdialog = new SplashScreen(splash, "0.1", "Build xxxx", true); ... mfactory = new SimpleMenuFactory(); mfactory.setProgressInterface(splashdialog); super.preparePanels(4, true, true, mfactory);
Copyright 2006-2023 Herve Girod. All Rights Reserved. Documentation and source under the LGPL v2 and Apache 2.0 licences