001    /**
002     * Copyright (C) 2007-2008, Jens Lehmann
003     *
004     * This file is part of DL-Learner.
005     * 
006     * DL-Learner is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published by
008     * the Free Software Foundation; either version 3 of the License, or
009     * (at your option) any later version.
010     *
011     * DL-Learner is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    
021    package org.dllearner.tools.ore;
022    
023    
024    import java.awt.BorderLayout;
025    import java.awt.CardLayout;
026    import java.awt.Component;
027    import java.awt.Dialog;
028    import java.awt.Font;
029    import java.awt.Frame;
030    import java.awt.Insets;
031    import java.awt.event.WindowAdapter;
032    import java.awt.event.WindowEvent;
033    import java.beans.PropertyChangeEvent;
034    import java.beans.PropertyChangeListener;
035    
036    import javax.swing.BorderFactory;
037    import javax.swing.Box;
038    import javax.swing.BoxLayout;
039    import javax.swing.JButton;
040    import javax.swing.JDialog;
041    import javax.swing.JPanel;
042    import javax.swing.JScrollPane;
043    import javax.swing.JSeparator;
044    import javax.swing.JTextArea;
045    import javax.swing.UIManager;
046    import javax.swing.border.EmptyBorder;
047    
048    /**
049     * This class implements a basic wizard dialog, where the programmer can
050     * insert one or more Components to act as panels. These panels can be navigated
051     * through arbitrarily using the 'Next' or 'Back' buttons, or the dialog itself
052     * can be closed using the 'Cancel' button. Note that even though the dialog
053     * uses a CardLayout manager, the order of the panels is not linear. Each panel
054     * determines at runtime what its next and previous panel will be.
055     * @author Lorenz Buehmann
056     */
057    public class Wizard extends WindowAdapter implements PropertyChangeListener {
058    
059        /**
060         * Indicates that the 'Finish' button was pressed to close the dialog.
061         */    
062        public static final int FINISH_RETURN_CODE = 0;
063        /**
064         * Indicates that the 'Cancel' button was pressed to close the dialog, or
065         * the user pressed the close box in the corner of the window.
066         */    
067        public static final int CANCEL_RETURN_CODE = 1;
068        /**
069         * Indicates that the dialog closed due to an internal error.
070         */    
071        public static final int ERROR_RETURN_CODE = 2;
072            
073        /**
074         * The String-based action command for the 'Next' button.
075         */    
076        public static final String NEXT_BUTTON_ACTION_COMMAND = "NextButtonActionCommand";
077        /**
078         * The String-based action command for the 'Back' button.
079         */    
080        public static final String BACK_BUTTON_ACTION_COMMAND = "BackButtonActionCommand";
081        /**
082         * The String-based action command for the 'Cancel' button.
083         */    
084        public static final String CANCEL_BUTTON_ACTION_COMMAND = "CancelButtonActionCommand";
085            
086    
087        // The text used for the buttons    
088        
089        static final String BACK_TEXT ="< Back";
090        static final String NEXT_TEXT ="Next >";
091        static final String FINISH_TEXT = "Finish";
092        static final String CANCEL_TEXT = "Cancel";
093    
094           
095        private WizardModel wizardModel;
096        private WizardController wizardController;
097        private JDialog wizardDialog;
098            
099        private JPanel cardPanel;
100        private CardLayout cardLayout;
101        private LeftPanel leftPanel;
102        private JButton backButton;
103        private JButton nextButton;
104        private JButton cancelButton;
105        private JTextArea informationsField;
106        
107        private int returnCode;
108        
109        private int knowledgeSourceType;
110        
111       
112    
113        
114        
115        /**
116         * Default constructor. This method creates a new WizardModel object and passes it
117         * into the overloaded constructor.
118         */    
119        public Wizard() {
120            this((Frame) null);
121        }
122        
123        /**
124         * This method accepts a java.awt.Dialog object as the javax.swing.JDialog's
125         * parent.
126         * @param owner The java.awt.Dialog object that is the owner of this dialog.
127         */    
128        public Wizard(Dialog owner) {
129            wizardModel = new WizardModel();
130            wizardDialog = new JDialog(owner);         
131            initComponents();
132        }
133     
134        /**
135         * This method accepts a java.awt.Frame object as the javax.swing.JDialog's
136         * parent.
137         * @param owner The java.awt.Frame object that is the owner of the javax.swing.JDialog.
138         */    
139        public Wizard(Frame owner) {
140            wizardModel = new WizardModel();
141            wizardDialog = new JDialog(owner);         
142            initComponents();
143        }
144        
145           
146       
147        /**
148         * Returns an instance of the JDialog that this class created. This is useful in
149         * the event that you want to change any of the JDialog parameters manually.
150         * @return The JDialog instance that this class created.
151         */    
152        public JDialog getDialog() {
153            return wizardDialog;
154        }
155        
156        /**
157         * Returns the owner of the generated javax.swing.JDialog.
158         * @return The owner (java.awt.Frame or java.awt.Dialog) of the javax.swing.JDialog generated
159         * by this class.
160         */    
161        public Component getOwner() {
162            return wizardDialog.getOwner();
163        }
164        
165        /**
166         * Sets the title of the generated javax.swing.JDialog.
167         * @param s The title of the dialog.
168         */    
169        public void setTitle(String s) {
170            wizardDialog.setTitle(s);
171        }
172        
173        /**
174         * Returns the current title of the generated dialog.
175         * @return The String-based title of the generated dialog.
176         */    
177        public String getTitle() {
178            return wizardDialog.getTitle();
179        }
180        
181        /**
182         * Sets the modality of the generated javax.swing.JDialog.
183         * @param b the modality of the dialog
184         */    
185        public void setModal(boolean b) {
186            wizardDialog.setModal(b);
187        }
188        
189        /**
190         * Returns the modality of the dialog.
191         * @return A boolean indicating whether or not the generated javax.swing.JDialog is modal.
192         */    
193        public boolean isModal() {
194            return wizardDialog.isModal();
195        }
196        
197        /**
198         * Convienence method that displays a modal wizard dialog and blocks until the dialog
199         * has completed.
200         * @return Indicates how the dialog was closed. Compare this value against the RETURN_CODE
201         * constants at the beginning of the class.
202         */    
203        public int showModalDialog() {
204            
205            wizardDialog.setModal(true);
206            //wizardDialog.pack();
207           wizardDialog.setVisible(true);
208            
209            
210            return returnCode;
211        }
212        
213        /**
214         * Returns the current model of the wizard dialog.
215         * @return A WizardModel instance, which serves as the model for the wizard dialog.
216         */    
217        public WizardModel getModel() {
218            return wizardModel;
219        }
220        
221        /**
222         * Add a Component as a panel for the wizard dialog by registering its
223         * WizardPanelDescriptor object. Each panel is identified by a unique Object-based
224         * identifier (often a String), which can be used by the setCurrentPanel()
225         * method to display the panel at runtime.
226         * @param id An Object-based identifier used to identify the WizardPanelDescriptor object.
227         * @param panel The WizardPanelDescriptor object which contains helpful information about the panel.
228         */    
229        public void registerWizardPanel(Object id, WizardPanelDescriptor panel) {
230            
231            //  Add the incoming panel to our JPanel display that is managed by
232            //  the CardLayout layout manager.
233            
234            cardPanel.add(panel.getPanelComponent(), id);
235            
236            //  Set a callback to the current wizard.
237            
238            panel.setWizard(this);
239            
240            //  Place a reference to it in the model. 
241            
242            wizardModel.registerPanel(id, panel);
243            
244        }  
245        
246        /**
247         * Displays the panel identified by the object passed in. This is the same Object-based
248         * identified used when registering the panel.
249         * @param id The Object-based identifier of the panel to be displayed.
250         */    
251        public void setCurrentPanel(Object id) {
252    
253            //  Get the hashtable reference to the panel that should
254            //  be displayed. If the identifier passed in is null, then close
255            //  the dialog.
256            
257            if (id == null){
258                close(ERROR_RETURN_CODE);
259            }
260            WizardPanelDescriptor oldPanelDescriptor = wizardModel.getCurrentPanelDescriptor();
261            if (oldPanelDescriptor != null){
262                oldPanelDescriptor.aboutToHidePanel();
263            }
264            wizardModel.setCurrentPanel(id);
265            wizardModel.getCurrentPanelDescriptor().aboutToDisplayPanel();
266            
267            //  Show the panel in the dialog.
268            
269            cardLayout.show(cardPanel, id.toString());
270            wizardModel.getCurrentPanelDescriptor().displayingPanel();        
271            
272            
273        }
274        
275        /**
276         * Method used to listen for property change events from the model and update the
277         * dialog's graphical components as necessary.
278         * @param evt PropertyChangeEvent passed from the model to signal that one of its properties has changed value.
279         */    
280        public void propertyChange(PropertyChangeEvent evt) {
281            
282            if (evt.getPropertyName().equals(WizardModel.CURRENT_PANEL_DESCRIPTOR_PROPERTY)) {
283                wizardController.resetButtonsToPanelRules(); 
284            } else if (evt.getPropertyName().equals(WizardModel.NEXT_FINISH_BUTTON_TEXT_PROPERTY)) {            
285                nextButton.setText(evt.getNewValue().toString());
286            } else if (evt.getPropertyName().equals(WizardModel.BACK_BUTTON_TEXT_PROPERTY)) {            
287                backButton.setText(evt.getNewValue().toString());
288            } else if (evt.getPropertyName().equals(WizardModel.CANCEL_BUTTON_TEXT_PROPERTY)) {            
289                cancelButton.setText(evt.getNewValue().toString());
290            } else if (evt.getPropertyName().equals(WizardModel.NEXT_FINISH_BUTTON_ENABLED_PROPERTY)) {            
291                nextButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
292            } else if (evt.getPropertyName().equals(WizardModel.BACK_BUTTON_ENABLED_PROPERTY)) {            
293                backButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
294            } else if (evt.getPropertyName().equals(WizardModel.CANCEL_BUTTON_ENABLED_PROPERTY)) {            
295                cancelButton.setEnabled(((Boolean) evt.getNewValue()).booleanValue());
296            }
297            
298        }
299        
300        /**
301         * Retrieves the last return code set by the dialog.
302         * @return An integer that identifies how the dialog was closed. See the *_RETURN_CODE
303         * constants of this class for possible values.
304         */    
305        public int getReturnCode() {
306            return returnCode;
307        }
308        
309       /**
310         * Mirrors the WizardModel method of the same name.
311         * @return A boolean indicating if the button is enabled.
312         */  
313        public boolean getBackButtonEnabled() {
314            return wizardModel.getBackButtonEnabled().booleanValue();
315        }
316    
317       /**
318         * Mirrors the WizardModel method of the same name.
319         * @param newValue The new enabled status of the button.
320         */ 
321        public void setBackButtonEnabled(boolean newValue) {
322            wizardModel.setBackButtonEnabled(new Boolean(newValue));
323        }
324    
325       /**
326         * Mirrors the WizardModel method of the same name.
327         * @return A boolean indicating if the button is enabled.
328         */ 
329        public boolean getNextFinishButtonEnabled() {
330            return wizardModel.getNextFinishButtonEnabled().booleanValue();
331        }
332    
333       /**
334         * Mirrors the WizardModel method of the same name.
335         * @param newValue The new enabled status of the button.
336         */ 
337        public void setNextFinishButtonEnabled(boolean newValue) {
338            wizardModel.setNextFinishButtonEnabled(new Boolean(newValue));
339        }
340     
341       /**
342         * Mirrors the WizardModel method of the same name.
343         * @return A boolean indicating if the button is enabled.
344         */ 
345        public boolean getCancelButtonEnabled() {
346            return wizardModel.getCancelButtonEnabled().booleanValue();
347        }
348    
349        /**
350         * Mirrors the WizardModel method of the same name.
351         * @param newValue The new enabled status of the button.
352         */ 
353        public void setCancelButtonEnabled(boolean newValue) {
354            wizardModel.setCancelButtonEnabled(new Boolean(newValue));
355        }
356        
357        /**
358         * Closes the dialog and sets the return code to the integer parameter.
359         * @param code The return code.
360         */    
361        void close(int code) {
362            returnCode = code;
363            wizardDialog.dispose();
364        }
365        
366        /**
367         * This method initializes the components for the wizard dialog: it creates a JDialog
368         * as a CardLayout panel surrounded by a small amount of space on each side, as well
369         * as three buttons at the bottom.
370         */
371        
372        private void initComponents() {
373    
374            wizardModel.addPropertyChangeListener(this);       
375            wizardController = new WizardController(this);       
376    
377            wizardDialog.getContentPane().setLayout(new BorderLayout());
378            wizardDialog.addWindowListener(this);
379                    
380            //  Create the outer wizard panel, which is responsible for three buttons:
381            //  Next, Back, and Cancel. It is also responsible a JPanel above them that
382            //  uses a CardLayout layout manager to display multiple panels in the 
383            //  same spot.
384            
385            JPanel buttonPanel = new JPanel();
386            JSeparator separator = new JSeparator();
387            Box buttonBox = new Box(BoxLayout.X_AXIS);
388    
389            cardPanel = new JPanel();
390            cardPanel.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10)));       
391    
392            cardLayout = new CardLayout(); 
393            cardPanel.setLayout(cardLayout);
394            
395            backButton = new JButton();
396            nextButton = new JButton();
397            cancelButton = new JButton();
398            
399            backButton.setActionCommand(BACK_BUTTON_ACTION_COMMAND);
400            nextButton.setActionCommand(NEXT_BUTTON_ACTION_COMMAND);
401            cancelButton.setActionCommand(CANCEL_BUTTON_ACTION_COMMAND);
402    
403            backButton.addActionListener(wizardController);
404            nextButton.addActionListener(wizardController);
405            cancelButton.addActionListener(wizardController);
406            
407            //  Create the buttons with a separator above them, then place them
408            //  on the east side of the panel with a small amount of space between
409            //  the back and the next button, and a larger amount of space between
410            //  the next button and the cancel button.
411            
412            buttonPanel.setLayout(new BorderLayout());
413            buttonPanel.add(separator, BorderLayout.NORTH);
414    
415            buttonBox.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10)));       
416            buttonBox.add(backButton);
417            buttonBox.add(Box.createHorizontalStrut(10));
418            buttonBox.add(nextButton);
419            buttonBox.add(Box.createHorizontalStrut(30));
420            buttonBox.add(cancelButton);
421            
422            buttonPanel.add(buttonBox, java.awt.BorderLayout.EAST);
423            
424            JPanel informationPanel = new JPanel();
425            JScrollPane infoScrollPane = new JScrollPane();
426            informationsField = new JTextArea();
427            
428            
429            //setLayout(new GridBagLayout());
430            infoScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
431            infoScrollPane.setViewportBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
432            informationsField.setBackground(UIManager.getDefaults().getColor("control"));
433            informationsField.setColumns(80);
434            informationsField.setEditable(false);
435            informationsField.setLineWrap(true);
436            informationsField.setRows(3);
437            informationsField.setFont(new Font("Serif", Font.PLAIN, 14));
438            informationsField.setWrapStyleWord(true);
439            infoScrollPane.setViewportView(informationsField);
440            informationPanel.add(infoScrollPane);
441            
442            JPanel buttonInformationPanel = new JPanel();
443            buttonInformationPanel.setLayout(new BorderLayout());
444            buttonInformationPanel.add(buttonPanel, BorderLayout.SOUTH);
445            buttonInformationPanel.add(informationPanel, BorderLayout.NORTH);
446            
447            wizardDialog.getContentPane().add(buttonInformationPanel, java.awt.BorderLayout.SOUTH);
448            wizardDialog.getContentPane().add(cardPanel, java.awt.BorderLayout.CENTER);
449            
450            leftPanel = new LeftPanel(0);
451            wizardDialog.getContentPane().add(leftPanel, BorderLayout.WEST);
452        }
453        
454        
455       /**
456         * If the user presses the close box on the dialog's window, treat it
457         * as a cancel.
458         * @param e The event passed in from AWT.
459         */ 
460        
461        @Override
462            public void windowClosing(WindowEvent e) {
463            returnCode = CANCEL_RETURN_CODE;
464        }
465        
466        /**
467         * Returns the left navigation panel.
468         * @return LeftPanel, subclassed from JPanel
469         */
470            public LeftPanel getLeftPanel() {
471                    return leftPanel;
472            }
473            
474            /**
475             * Sets the actual panel which has to be printed bold in the left navigation panel.
476             * @param i the number of the panel
477             */
478            public void setLeftPanel(int i) {
479                    ((LeftPanel) (wizardDialog.getContentPane().getComponent(2))).set(i);
480                    
481                    
482            }
483            
484            /**
485             * Returns the information field.
486             * @return JTextArea
487             */
488            public JTextArea getInformationField(){
489                    return informationsField;
490            }
491    
492            /**
493             * Sets the type of knowledge source - SPARQL or OWL.
494             * @param knowledgeSourceType 0 for OWL, 1 for SPARQL
495             */
496            public void setKnowledgeSourceType(int knowledgeSourceType) {
497                    this.knowledgeSourceType = knowledgeSourceType;
498            }
499    
500            /**
501             * Returns the type of knowledge source, represented as number - 0 for OWL, 1 for SPARQL.
502             * @return integer value
503             */
504            public int getKnowledgeSourceType() {
505                    return knowledgeSourceType;
506            }
507    
508    
509    
510       
511    
512    }