001    package view;
002    
003    import controller.IEnvAdapter;
004    import sysModel.ICmdFactory;
005    import sysModel.ISecurityAdapter;
006    import sysModel.env.AEnvFactory;
007    import sysModel.env.AGlobalEnv;
008    
009    import javax.swing.*;
010    import java.awt.*;
011    import java.awt.event.ActionEvent;
012    import java.awt.event.ActionListener;
013    import java.lang.reflect.Constructor;
014    
015    /**
016     * Dialog to create new environment.
017     *
018     * @author Mathias Ricken
019     */
020    public class CreateEnvDialog {
021        /**
022         * Environment factory to be used for creating the environment. This acts both as the factory and as the GUI panel
023         * with the environment settings.
024         */
025        private AEnvFactory _envFactory;
026    
027        /**
028         * Combobox containing the different choices for the environment.
029         */
030        private JComboBox _envChooser;
031    
032        /**
033         * Environment dialog. This component contains everything else.
034         */
035        private JDialog _dialog;
036    
037        /**
038         * Array of buttons on the dialog.
039         */
040        private JButton[] _optButtons;
041    
042        /**
043         * Constant to access the create button in _optButtons.
044         */
045        private static final int CREATE_BUTTON = 0;
046    
047        /**
048         * Constant to access the cancel button in _optButtons.
049         */
050        private static final int CANCEL_BUTTON = 1;
051    
052        /**
053         * Panel for the environment options. Contains the environment factory.
054         */
055        private JPanel _optionsPanel;
056    
057        /**
058         * Adpapter to the model for dealing with environments.
059         */
060        private IEnvAdapter _envAdapter;
061    
062        /**
063         * Creates a new CreateEnvDialog and all its controls.
064         *
065         * @param parent parent frame for the dialog
066         * @param ea     environment adapter
067         */
068        public CreateEnvDialog(JFrame parent, IEnvAdapter ea) {
069            _envAdapter = ea;
070            _dialog = new JDialog(parent, "Create new environment", true);
071            _dialog.setContentPane(makeOptionsPanel());
072            _dialog.pack();
073            _dialog.setResizable(false);
074        }
075    
076    
077        /**
078         * Show the modal dialog that allows the user to create a new environment.  If the dialog is dismissed by clicking
079         * the "OK" button, a new environment is created to the user's specification and returned. If "Cancel" is chosen or
080         * there is an error constructing the environment, <code>null</code> is returned.
081         *
082         * @return the newly created Environment or <code>null</code>
083         */
084        public AEnvFactory showDialog() {
085            _envChooser.setSelectedIndex(0);
086            envChosen();
087    
088            // center dialog in middle of parent frame
089            Component parent = _dialog.getParent();
090            _dialog.setLocation(parent.getX() + parent.getWidth() / 2 - _dialog.getSize().width / 2,
091                parent.getY() + parent.getHeight() / 2 - _dialog.getSize().height / 2);
092            _dialog.setVisible(true); // Modal dialog will block until setVisible(false), see ok/cancel methods
093    
094            return _envFactory;
095        }
096    
097        /**
098         * Remove environment settings from dialog.
099         */
100        private void removeEnvSettings() {
101            if (null != _envFactory) {
102                _optionsPanel.remove(_envFactory);
103                _envFactory = null;
104            }
105        }
106    
107        /**
108         * Add environment factory to dialog.
109         *
110         * @param factory factory to add
111         */
112        private void addEnvSettings(AEnvFactory factory) {
113            _envFactory = factory;
114            _optionsPanel.add(_envFactory);
115        }
116    
117        /**
118         * Callback when user selects new environment class choice from combo box.
119         */
120        private void envChosen() {
121            IEnvChoice envChoice = (IEnvChoice)_envChooser.getSelectedItem();
122            envChoice.select();
123            _dialog.pack();
124            _dialog.getContentPane().validate(); // force immediate validation
125        }
126    
127        /**
128         * Callback when user clicks cancel button.
129         */
130        private void cancelClicked() {
131            _dialog.setVisible(false);
132            removeEnvSettings();
133        }
134    
135        /**
136         * Callback when user clicks ok button.
137         */
138        private void okClicked() {
139            _dialog.setVisible(false);
140        }
141    
142        /**
143         * Build options dialog.
144         *
145         * @return options pane
146         */
147        private JOptionPane makeOptionsPanel() {
148            JPanel myControls = new JPanel();
149            myControls.setLayout(new BoxLayout(myControls, BoxLayout.Y_AXIS));
150    
151            JLabel lab;
152            myControls.add(lab = new JLabel("Choose environment type: "));
153            lab.setAlignmentX(Component.CENTER_ALIGNMENT);
154    
155            _envChooser = new JComboBox();
156    
157            // add environments
158            String[] envClassNames = _envAdapter.getEnvironmentClassNames();
159            Class[] parameterTypes = new Class[]{ICmdFactory.class, ISecurityAdapter.class};
160            Object[] initArgs = new Object[]{_envAdapter.getCmdFactory(), _envAdapter.getSecurityAdapter()};
161            for(int i = 0; i < envClassNames.length; i++) {
162                try {
163                    Class envClass = Class.forName(envClassNames[i]);
164                    Constructor envCtor = envClass.getConstructor(parameterTypes);
165                    AGlobalEnv env = (AGlobalEnv)envCtor.newInstance(initArgs);
166                    AEnvFactory factory = env.makeEnvFactory();
167    
168                    ConcreteEnvChoice choice = new ConcreteEnvChoice(this, factory);
169                    _envChooser.addItem(choice);
170                }
171                catch(Exception e) {
172                    System.err.println(e);
173                }
174            }
175    
176            // add "Add..." choice
177            _envChooser.addItem(new AddEnvChoice(this));
178    
179            _envChooser.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0));
180            _envChooser.addActionListener(new ActionListener() {
181                public void actionPerformed(ActionEvent evt) {
182                    envChosen();
183                }
184            });
185            myControls.add(_envChooser);
186    
187            _optionsPanel = new JPanel();
188            myControls.add(_optionsPanel);
189    
190            JOptionPane optPane = new JOptionPane(myControls, JOptionPane.QUESTION_MESSAGE);
191            _optButtons = new JButton[]{new JButton("Create"), new JButton("Cancel")};
192            optPane.setOptions(_optButtons);
193            optPane.setInitialValue(_optButtons[CREATE_BUTTON]);
194            _optButtons[CREATE_BUTTON].addActionListener(new ActionListener() {
195                public void actionPerformed(ActionEvent e) {
196                    okClicked();
197                }
198            });
199            _optButtons[CANCEL_BUTTON].addActionListener(new ActionListener() {
200                public void actionPerformed(ActionEvent e) {
201                    cancelClicked();
202                }
203            });
204    
205            return optPane;
206        }
207    
208        /**
209         * Nested interface for environment choices.
210         */
211        private interface IEnvChoice {
212            /**
213             * Select this interface.
214             */
215            public void select();
216        }
217    
218        /**
219         * Nested class for choosing an environment.
220         */
221        private static class ConcreteEnvChoice implements IEnvChoice {
222            /**
223             * CreateEnvDialog used.
224             */
225            private CreateEnvDialog _envDialog;
226            /**
227             * Environment settings.
228             */
229            private AEnvFactory _envFactory;
230    
231            /**
232             * Make a new concrete environment choice.
233             *
234             * @param envDialog the create environment dialog
235             * @param factory   environment factory
236             */
237            public ConcreteEnvChoice(CreateEnvDialog envDialog, AEnvFactory factory) {
238                _envDialog = envDialog;
239                _envFactory = factory;
240            }
241    
242            /**
243             * Select this choice.
244             */
245            public void select() {
246                _envDialog._optButtons[CREATE_BUTTON].setEnabled(true);
247                _envDialog.removeEnvSettings();
248                _envDialog.addEnvSettings(_envFactory);
249            }
250    
251            /**
252             * Return string representation.
253             *
254             * @return string representation
255             */
256            public String toString() {
257                return _envFactory.toString();
258            }
259        }
260    
261        /**
262         * Nested class for adding an environment.
263         */
264        private class AddEnvChoice implements IEnvChoice {
265            /**
266             * CreateEnvDialog used.
267             */
268            private CreateEnvDialog _envDialog;
269    
270            /**
271             * Make a new add environment choice.
272             *
273             * @param envDialog the create environment dialog
274             */
275            public AddEnvChoice(CreateEnvDialog envDialog) {
276                _envDialog = envDialog;
277            }
278    
279            public void select() {
280                _envDialog._optButtons[CREATE_BUTTON].setEnabled(false);
281                _envDialog.removeEnvSettings();
282    
283                String className = (new InputStringDialog(_envDialog._dialog, "Add environment class")).showDialog();
284                if (className==null) { return; }
285                try {
286                    Class envClass = Class.forName(className);
287                    Constructor envCtor = envClass.getConstructor(new Class[]{ICmdFactory.class, ISecurityAdapter.class});
288                    AGlobalEnv env = (AGlobalEnv)envCtor.newInstance(
289                        new Object[]{_envAdapter.getCmdFactory(), _envAdapter.getSecurityAdapter()});
290                    AEnvFactory envFactory = env.makeEnvFactory();
291    
292                    ConcreteEnvChoice choice = new ConcreteEnvChoice(_envDialog, envFactory);
293                    _envDialog._envChooser.insertItemAt(choice, _envDialog._envChooser.getItemCount() - 1);
294                    _envDialog._envChooser.setSelectedItem(choice);
295                    choice.select();
296                }
297                catch(Exception e) {
298                    System.err.println(e);
299                    _envDialog._envChooser.setSelectedIndex(0);
300                    ((IEnvChoice)_envDialog._envChooser.getSelectedItem()).select();
301                }
302            }
303    
304            public String toString() {
305                return "Add ...";
306            }
307        }
308    }
309