View Javadoc

1   /*
2   Copyright (C) 2000 - 2007 Grid Systems, S.A.
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2, as
6   published by the Free Software Foundation.
7   
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17  
18  /*
19   * Project: KernelConfigurator
20   * Created on 24-feb-2004
21   *
22   * Copyright (c)2003 Grid Systems
23   */
24  package com.gridsystems.config.app;
25  
26  import java.awt.BorderLayout;
27  import java.awt.Container;
28  import java.awt.Cursor;
29  import java.awt.Frame;
30  import java.awt.event.WindowAdapter;
31  import java.awt.event.WindowEvent;
32  import java.text.MessageFormat;
33  
34  import javax.swing.Action;
35  import javax.swing.JFrame;
36  import javax.swing.JMenu;
37  import javax.swing.JMenuBar;
38  import javax.swing.JMenuItem;
39  import javax.swing.JOptionPane;
40  import javax.swing.JSeparator;
41  import javax.swing.JSplitPane;
42  import javax.swing.JTree;
43  import javax.swing.event.TreeSelectionEvent;
44  import javax.swing.event.TreeSelectionListener;
45  import javax.swing.event.TreeExpansionEvent;
46  import javax.swing.event.TreeExpansionListener;
47  import javax.swing.event.TreeWillExpandListener;
48  import javax.swing.tree.TreePath;
49  import javax.swing.tree.TreeSelectionModel;
50  
51  import org.apache.commons.logging.Log;
52  import org.apache.commons.logging.LogFactory;
53  
54  import com.gridsystems.config.Configurator;
55  import com.gridsystems.config.SwingConfiguratorView;
56  import com.gridsystems.config.modules.jvm.JVMConfigurator;
57  import com.gridsystems.config.tools.swing.ReflectedAction;
58  
59  /**
60   * Swing Mode Main Window.
61   *
62   * @author <a href="mailto:rruiz@gridsystems.com">Rodrigo Ruiz Aguayo</a>
63   * @version 1.0
64   */
65  public class ConfigFrame extends JFrame
66    implements TreeSelectionListener, TreeWillExpandListener, TreeExpansionListener {
67    /**
68     * Class logger.
69     */
70    private static Log log = LogFactory.getLog(ConfigFrame.class);
71  
72    /**
73     * Configurator Tree / Current View separator.
74     */
75    private JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
76  
77    /**
78     * Configurator view browser.
79     */
80    private ConfigPanel panel = new ConfigPanel();
81  
82    /**
83     * Default constructor.
84     */
85    public ConfigFrame() {
86      super();
87  
88      this.setTitle(UI.getString("app.title"));
89  
90      Container c = getContentPane();
91      c.setLayout(new BorderLayout());
92  
93      // MenuBar
94      createMenuBar();
95  
96      // JTree
97      JTree tree = new ConfigTree();
98      tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
99      tree.addTreeSelectionListener(this);
100     tree.addTreeExpansionListener(this);
101     tree.addTreeWillExpandListener(this);
102 
103     // ContentPane
104     splitter.setLeftComponent(tree);
105     splitter.setRightComponent(panel);
106 
107     c.add(splitter, BorderLayout.CENTER);
108 
109     // Close Control
110     setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
111     addWindowListener(new WindowAdapter() {
112       public void windowClosing(WindowEvent event) {
113         closeWindow();
114       }
115     });
116 
117     // Expand
118     int count = tree.getRowCount();
119     for (int i = count; i >= 0; i--) {
120       tree.expandRow(i);
121     }
122 
123     //  PATCH FOR USABILITY
124     Class ixosConfig = null;
125     try {
126       ixosConfig = Class.forName(
127           "com.gridsystems.innergrid.kernel.ixos.configurator.IxosConfigurator");
128       Configurator ixosConf;
129       ixosConf = (Configurator)ixosConfig.getMethod("getInstance").invoke(null);
130       panel.setConfigurator(ixosConf);
131     } catch (Exception e) {
132     }
133     // PATCH END
134   }
135 
136   /**
137    * Gets the config panel.
138    *
139    * @return The panel
140    */
141   public ConfigPanel getConfigPanel() {
142     return panel;
143   }
144 
145   /**
146    * Creates the menu bar of the window. It will contain entries for
147    * accepting and discarding all modified views, and for closing the
148    * application.
149    */
150   private void createMenuBar() {
151     JMenuBar mbar = getJMenuBar();
152     if (mbar == null) {
153       Action action;
154 
155       mbar = new JMenuBar();
156       JMenu mnuFile = new JMenu(new ReflectedAction(this, null, "mnuFile"));
157       mbar.add(mnuFile);
158 
159       action = new ReflectedAction(this, "doApplyAll", "cmdApplyAll");
160       mnuFile.add(new JMenuItem(action));
161 
162       action = new ReflectedAction(this, "doDiscardAll", "cmdDiscardAll");
163       mnuFile.add(new JMenuItem(action));
164 
165       mnuFile.add(new JSeparator());
166 
167       action = new ReflectedAction(this, "closeWindow", "cmdClose");
168       mnuFile.add(new JMenuItem(action));
169 
170       setJMenuBar(mbar);
171     }
172   }
173 
174   /**
175    * {@inheritDoc}
176    */
177   public void valueChanged(TreeSelectionEvent e) {
178     TreePath path = e.getNewLeadSelectionPath();
179     if (path == null) {
180       // The user has collapsed an ancestor of the current configurator.
181       // There is no current path in the event, so we ask the tree
182       JTree tree = (JTree)e.getSource();
183       path = tree.getLeadSelectionPath();
184     }
185     ConfigNode node = (ConfigNode)path.getLastPathComponent();
186     if (node != null) {
187       Configurator cfg = node.getConfigurator();
188       if (cfg != null) {
189         panel.setConfigurator(cfg);
190       }
191     }
192   }
193 
194   /**
195    * Performs an Apply on all modified views. It asks for confirmation on each
196    * modified view if asked to do so.
197    *
198    * @param ask Whether to ask confirmation or not
199    * @return    false if the operation has been cancelled; true otherwise
200    */
201   private boolean doApplyAll(boolean ask) {
202     Configurator[] configs = UI.getConfigurators();
203 
204     // Puts the JVM configurator at the last position, so it is applied after the rest
205     Configurator jvmc = JVMConfigurator.getInstance();
206     int last = configs.length - 1;
207     for (int i = 0; i < last; i++) {
208       if (configs[i] == jvmc) {
209         configs[i] = configs[last];
210         configs[last] = jvmc;
211         break;
212       }
213     }
214 
215     // Flag to know if there were errors applying changes
216     for (int i = 0; i < configs.length; i++) {
217       try {
218         if (configs[i].hasView()) {
219           SwingConfiguratorView view = (SwingConfiguratorView)configs[i].getView();
220 
221           if (view.hasErrors()) {
222             String title = UI.getString("app.title");
223             String pattern = UI.getString("messages.confirmDiscard");
224             String msg = MessageFormat.format(pattern,
225               new Object[] { configs[i].getName() });
226 
227             int answer = JOptionPane.showConfirmDialog(this, msg, title,
228               JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
229 
230             if (answer == JOptionPane.OK_OPTION) {
231               continue;
232             }
233             if (answer == JOptionPane.CANCEL_OPTION) {
234               return false;
235             }
236           }
237           if (ask && view.isModified()) {
238             String title = UI.getString("app.title");
239             String pattern = UI.getString("messages.confirmApply");
240             String msg = MessageFormat.format(pattern,
241               new Object[] { configs[i].getName() });
242             int answer = JOptionPane.showConfirmDialog(this, msg, title,
243               JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
244 
245             if (answer == JOptionPane.NO_OPTION) {
246               continue;
247             }
248             if (answer == JOptionPane.CANCEL_OPTION) {
249               return false;
250             }
251           }
252         }
253         configs[i].apply();
254       } catch (Exception e) {
255         String name = configs[i].getClass().getName();
256         log.error("Error applying configuration for " + name, e);
257         String title = UI.getString("app.title");
258         String pattern = UI.getString("messages.applyErrors.swing");
259         String msg = MessageFormat.format(
260           pattern, new Object[] {configs[i].getName(), e.getMessage()});
261         if (JOptionPane.showConfirmDialog(this, msg, title,
262           JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE)
263           == JOptionPane.NO_OPTION) {
264           return false;
265         }
266       }
267     }
268     return true;
269   }
270 
271   /**
272    * Performs the operation of the "Apply All" menu item.
273    */
274   public void doApplyAll() {
275     try {
276       Cursor cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
277       this.setCursor(cursor);
278       doApplyAll(false);
279     } finally {
280       this.setCursor(null);
281     }
282   }
283 
284   /**
285    * Performs the operation of "Discard All" menu item.
286    */
287   public void doDiscardAll() {
288     Configurator[] configs = UI.getConfigurators();
289 
290     for (int i = 0; i < configs.length; i++) {
291       configs[i].discard();
292     }
293   }
294 
295   /**
296    * Closes the window.
297    *
298    * @return true if and only if the configurator can be closed.
299    */
300   public boolean closeWindow() {
301     Configurator.setClosing(true);
302     if (doApplyAll(true)) {
303       this.setVisible(false);
304       this.dispose();
305 
306       // Needed in case JOptionPane has been used
307       Frame frame = JOptionPane.getRootFrame();
308       if (frame != null) {
309         frame.dispose();
310       }
311       return true;
312     }
313     Configurator.setClosing(false);
314     return false;
315   }
316 
317 
318   /**
319    * Shows a message explaining to the user that the tree is expanding.
320    *
321    * Shows a message explaining to the user that the tree is expanding (this
322    * process can last several seconds).
323    *
324    * @param treeExpansionEvent the information of the event.
325    */
326   public void treeWillExpand(TreeExpansionEvent treeExpansionEvent) {
327     this.panel.showExpansionMessage();
328   }
329 
330   /**
331    * {@inheritDoc}
332    * Not used. Implemented as part of the TreeWillExpandListener interface.
333    */
334   public void treeWillCollapse(TreeExpansionEvent treeExpansionEvent) {
335   }
336 
337   /**
338    * Hides the message explaining to the user that the tree is expanding.
339    *
340    * Hides the message explaining to the user that the tree is expanding. This
341    * message is set by the <code>treeWillExpand(TreeExpansionEvent)</code> when
342    * a tree node starts expanding (the expansion can last several seconds).
343    *
344    * @param treeExpansionEvent the information of the event.
345    */
346   public void treeExpanded(TreeExpansionEvent treeExpansionEvent) {
347     this.panel.hideExpansionMessage();
348   }
349 
350   /**
351    * {@inheritDoc}
352    * Not used. Implemented as part of the TreeExpansionListener interface.
353    */
354   public void treeCollapsed(TreeExpansionEvent treeExpansionEvent) {
355   }
356 }