Home
Categories
Dictionary
Download
Project Details
Changes Log
Tutorials
FAQ
License

Configuration tutorial



This tutorial explains how to manage the configuration in the application and the plugins.

Overview

For this tutorial, we will reuse what we have done for the basic tutorial.

With this tutorial, we will learn to:
  • Manage configuration settings in a homogenous way for the main Application and its Plugins
  • Serialize the configuration

Create the configuration for the application

We will use a configuration to store the last directory used for opening a File.

Implement the Configuration interface

First we will implement the Configuration interface:
      public class AppliConfiguration implements Configuration {
        private static AppliConfiguration conf = null;
        public File lastDir = new File(System.getProperty("user.dir"));

        private AppliConfiguration() {
        }

        public static AppliConfiguration getInstance() {
          if (conf == null) {
            conf = new AppliConfiguration();
          }
          return conf;
        }

        @Override
        public void putConfiguration(Preferences p, File file) {
        }

        @Override
        public void getConfiguration(Preferences p, File file) {
        }

      }
For the moment the Configuration.getConfiguration(Preferences, File) and Configuration.putConfiguration(Preferences, File) methods do nothing. This will be our next step.
Note that we used a Singleton pattern for our configuration. This is not mandatory, but as we will use it in our Plugin later, it will be easier for us.

Implement the getConfiguration and putConfiguration methods

We will implement the Configuration.getConfiguration(Preferences, File) method to deserialize the configuration at start:
      @Override
      public void getConfiguration(Preferences p, File file) {
        String path = p.get("lastDir", lastDir.getAbsolutePath());
        if (path != null) {
          lastDir = new File(path);
        }
      }
And then we will implement the Configuration.putConfiguration(Preferences, File) method to serialize the configuration when we exit the application:
      @Override
      public void putConfiguration(Preferences p, File file) {
        String path = lastDir.getAbsolutePath();
        p.put("lastDir", path);
      }

Set the configuration in the application

To manage the the configuration in the application, we will add the following lines in the application constructor before registering the plugins:
      Preferences pref = Preferences.userRoot();
      this.initConfiguration(pref);
We replace the usage of the AbstractApplication.initConfiguration() method by AbstractApplication.initConfiguration(Preferences, File)

      public ConfigTutorialMDI() {
        super("ConfigTutorialMDI");
        // set the configuration
        this.setConfiguration(AppliConfiguration.getInstance());

        // 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");
      
           // initialize configuration with Preferences
           pref = Preferences.userRoot();
           this.initConfiguration(pref);
      
        // register plugins in the plugins directory
        this.registerPlugins();

        mfactory = new SimpleMenuFactory();
        super.preparePanels(4, true, false, mfactory);
        this.setSize(500, 500);
      }

Use the configuration in the plugin

Using the configuration in the plugin is very simple. We will just modify the ImportImageAction to use the last directory we created in the configuration:
      protected class ImportImageAction extends AbstractMDIAction {
        public ImportImageAction(String name) {
          super(appli, name);
          this.setDescription("Open Image", "Open Image");
        }

        @Override
        public void run() throws Exception {
      
            // get the application configuration
            AppliConfiguration conf = AppliConfiguration.getInstance();
      
          TabbedApplication gui = (TabbedApplication) app;
          JFileChooser chooser = new JFileChooser("Open Image");
          chooser.setDialogTitle("Open Image");
      
             // use the last parent directory
             chooser.setCurrentDirectory(conf.lastDir);
      
          chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
          if (chooser.showOpenDialog(gui.getApplicationWindow()) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            BufferedImage image = ImageIO.read(file);
            if (image == null) {
              throw new Exception("Bad File type");
            }
      
            // set the last parent directory
            conf.lastDir = file.getParentFile();
      
            JScrollPane pane = new JScrollPane(new ImagePanel(image));
            gui.addTab(pane, image, file.getName());
          }
        }
      }

Create the configuration for the plugin

Now we will create two configuration propeties for the Plugin:
  • The limitWidth property will be a boolean which will specify if the width of images we open in the Plugin must be limited in the panel
  • The maxWidth property will be an int which will specify the value of this property

Create the configuration class for the plugin

The configuration class will be:
      public class OpenImagePluginConfiguration implements Configuration {
        private static OpenImagePluginConfiguration conf = null;
        public int maxWidth = 1000;
        public boolean limitWidth = false;

        private OpenImagePluginConfiguration() {
        }

        public static OpenImagePluginConfiguration getInstance() {
          if (conf == null) {
            conf = new OpenImagePluginConfiguration();
          }
          return conf;
        }

        @Override
        public void putConfiguration(Preferences p, File file) {
          p.putInt("maxWidth", maxWidth);
          p.putBoolean("limitWidth", limitWidth);
        }

        @Override
        public void getConfiguration(Preferences p, File file) {
          maxWidth = p.getInt("maxWidth", maxWidth);
          limitWidth = p.getBoolean("limitWidth", limitWidth);
        }
      }

Create the configuration class for the plugin

We need to implement the Plugin.getPluginConfiguration() method to be able to retrieve the configuration for the Plugin:
      public class OpenImagePlugin extends AbstractMDIPlugin {
        private final OpenImagePluginConfiguration pluginConf = OpenImagePluginConfiguration.getInstance();

        ...
        @Override
        public Configuration getPluginConfiguration() {
          return pluginConf;
        }
      }
Now the configuration of our Plugin will be maintained, that is:
  • It will be deserialized at start
  • It will be serialized when exiting the application
We now need to be able to set the configuration configuration parameters for our Plugin. TO do that, we will create a "Plugins" menu, and a menu item for our Plugin which will allow us to do that.

Create a Plugins menu

We will now create a panel to be able to set the configuration properties. To do that, we will add a new "Plugins" menu which will allow us to set the configuration parameters for our Plugin:
configtutorialmenus
First we modify our Menu factory to include a menu specific for our Plugin:
      public class SimpleMenuFactory extends AbstractMenuFactory {
        private JMenu filemenu = new JMenu("File");
        private JMenu openmenu = new JMenu("Open");
        private final JMenu pluginsmenu = new JMenu("Plugins");
        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);
          staticMenuKeyMap.put(PluginElementTypes.PLUGIN_MENU, pluginsmenu);
          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);
        }
      }

Create a panel to set the configuration properties in the Plugin

We will now create the menu item and the panel for our Plugin. First we create the menu item, and show a dialog when clicking on the item:
      public class OpenImagePlugin extends AbstractMDIPlugin {
        private AbstractAction configAction;

        public Object getStaticMenuElements(String menu) {
          if (menu.equals(PluginElementTypes.OPEN_ACTIONS)) {
            return importImageAction;
          } else if (menu.equals(PluginElementTypes.PLUGIN_MENU)) {
            return configAction;
          } else {
            return null;
          }
        }

        public void register(MDIApplication app) throws Exception {
          super.register(app);
          importImageAction = new ImportImageAction("Image");

          configAction = new AbstractAction("Image Plugin") {
            @Override
            public void actionPerformed(ActionEvent e) {
              showPluginSettings();
            }
          };
        }

        private void showPluginSettings() {
          JDialog d = new JDialog(((GUIApplication) appli).getApplicationWindow(), "Open Image");
          d.setSize(300, 300);
          d.setVisible(true);
        }
      }
For the moment the dialog is empty, but we can create its content with GUI elements which will allow to set the configuration properties:
  • A checkbox for the limitWidth property
  • A spinner for the maxWidth property
      public class OpenImagePlugin extends AbstractMDIPlugin {
        private AbstractAction importImageAction;
        private AbstractAction configAction;

        private final SpinnerNumberModel maxWidthModel = new SpinnerNumberModel(1000, 10, 1000, 10);
           private JSpinner maxWidthSpinner;
           private final JCheckBox limitWidthCb = new JCheckBox("Limit Width");
           private JPanel confPanel = null;
           private final OpenImagePluginConfiguration pluginConf = OpenImagePluginConfiguration.getInstance();

        public void register(MDIApplication app) throws Exception {
          super.register(app);
          importImageAction = new ImportImageAction("Image");

          maxWidthSpinner = new JSpinner(maxWidthModel);
             maxWidthSpinner.setEditor(new JSpinner.NumberEditor(maxWidthSpinner, "####"));
             maxWidthSpinner.setMaximumSize(maxWidthSpinner.getPreferredSize());
             maxWidthSpinner.addChangeListener((ChangeEvent e) -> {
               try {
                 int value = ((Integer) ((JSpinner) e.getSource()).getValue());
                 if (value < 10) {
                    value = 10;
                 } else if (value > 1000) {
                   value = 1000;
                 }
                 pluginConf.maxWidth = value;
               } catch (ArithmeticException ex) {
               }
             });
             limitWidthCb.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                  pluginConf.limitWidth = limitWidthCb.isSelected();
               }
             });

             confPanel = new JPanel();
             confPanel.setLayout(new BoxLayout(confPanel, BoxLayout.Y_AXIS));
             JPanel hpanel = new JPanel();
             hpanel.setLayout(new BoxLayout(hpanel, BoxLayout.X_AXIS));
             hpanel.add(new JLabel("Max Width"));
             hpanel.add(Box.createRigidArea(new Dimension(5, 0)));
             hpanel.add(maxWidthSpinner);
             hpanel.add(Box.createHorizontalGlue());
             confPanel.add(hpanel);
             confPanel.add(Box.createVerticalStrut(5));
             hpanel = new JPanel();
             hpanel.setLayout(new BoxLayout(hpanel, BoxLayout.X_AXIS));
             hpanel.add(limitWidthCb);
             hpanel.add(Box.createHorizontalGlue());
             confPanel.add(hpanel);
             confPanel.add(Box.createVerticalGlue());

          configAction = new AbstractAction("Image Plugin") {
            @Override
            public void actionPerformed(ActionEvent e) {
              showPluginSettings();
            }
          };
        }
      }
Now we can use the panel when we open the settings:
      private void showPluginSettings() {
        JDialog d = new JDialog(((GUIApplication) appli).getApplicationWindow(), "Open Image");
        d.getContentPane().add(confPanel, BorderLayout.CENTER);
        d.setSize(300, 300);
        d.setVisible(true);
      }
We now have the following panel when we click on the menu item for the Plugin:
configtutorialconfigGUI
The last thing we must do is to set the GUI settings for the value of the unserialized configuration when starting the application:
      @Override
      public void resetSettings() {
        maxWidthSpinner.setValue(pluginConf.maxWidth);
        limitWidthCb.setSelected(pluginConf.limitWidth);
      }

Use the configuration properties in the Plugin

We will now use the configuration properties when we open an Image. Basically we want to avoid the image to be larger than maxWidth if the limitWidth property is true:
      public class ImagePanel extends JPanel {
        private final Image image;

        public ImagePanel(Image image) {
          super();
          this.image = image;
        }

        @Override
        public void paint(Graphics g) {
          int width = image.getWidth(this);
          int height = image.getHeight(this);
          OpenImagePluginConfiguration conf = OpenImagePluginConfiguration.getInstance();
          int maxWidth = conf.maxWidth;
          if (conf.limitWidth && width > maxWidth) {
            height = (int) ((float) height / (float) width * (float) maxWidth);
            width = maxWidth;
             }

          g.drawImage(image, 0, 0, width, height, this);
          this.setPreferredSize(new Dimension(width, height));
        }
      }

See also


Categories: swing | tutorials

Copyright 2006-2023 Herve Girod. All Rights Reserved. Documentation and source under the LGPL v2 and Apache 2.0 licences