001/**
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: tao $'
006 * '$Date: 2010-06-03 16:45:10 -0700 (Thu, 03 Jun 2010) $' 
007 * '$Revision: 24730 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.workflowscheduler.gui;
031
032import java.awt.BorderLayout;
033import java.awt.Container;
034import java.awt.Dimension;
035import java.awt.event.ActionEvent;
036import java.awt.event.ActionListener;
037import java.awt.event.WindowAdapter;
038import java.awt.event.WindowEvent;
039import java.util.List;
040
041import javax.swing.Box;
042import javax.swing.BoxLayout;
043import javax.swing.JButton;
044import javax.swing.JDialog;
045import javax.swing.JOptionPane;
046import javax.swing.JPanel;
047import javax.swing.JProgressBar;
048import javax.swing.SwingUtilities;
049
050import org.kepler.gui.ComponentLibraryTab;
051import org.kepler.gui.DualVerticalViewPane;
052import org.kepler.gui.TabPane;
053import org.kepler.gui.ViewPaneLocation;
054import org.kepler.gui.state.StateChangeEvent;
055import org.kepler.gui.state.StateChangeListener;
056import org.kepler.gui.state.StateChangeMonitor;
057import org.kepler.module.workflowschedulergui.Initialize;
058import org.kepler.workflowscheduler.gui.configurationwizard.WorkflowSchedulerConfigEvent;
059
060import ptolemy.actor.gui.TableauFrame;
061//import org.kepler.workflowscheduler.gui.configurationwizard.CompletingConfigurationListenerInterface;
062
063/**
064 * A dialog to display the workflow scheduler. This is a singleton class.
065 * It has two main panels. Left one is the component search. Right one
066 * is the scheduler parent panel. Scheduler parent panel has two options:
067 * shows the real scheduler panel when user click a remote workflow or show
068 * a message to indicate user to choose a remote workflow for scheduling
069 * @author tao
070 *
071 */
072public class WorkflowSchedulerDialog extends JDialog implements ProgressBarControlInterface, StateChangeListener
073{
074  private static final String TITLE = "Workflow Scheduler";
075  private static final String COMPONENTS = "Components";
076  private static final String EAST ="E";
077  private static final int WIDTH = 1150;
078  private static final int HEIGHT = 650;
079  public static final int PROGRESSMIN = 0;
080  public static final int PROGRESSMAX = 100;
081  
082  //private WorkflowSchedulerDialog scheduler = null;
083  private TableauFrame parent = null;
084  //private JButton okButton = null;
085  //private JButton cancelButton =null;
086  private JButton closeButton = null;
087  private JPanel topPanel = null;
088  private JProgressBar progressBar = null;
089  //private boolean showedMessage = true;
090  private ScheduleChangeController scheduleChangeController;
091  private WorkflowSchedulerComponentLibraryTab componentsTab = null;
092  private DualVerticalViewPane componentAndSchedulerPane = null;
093 
094  /**
095   * Constructor
096   */
097  public WorkflowSchedulerDialog(TableauFrame parent)
098  {
099    super(parent);
100    this.parent = parent;
101    initialize();
102    this.pack();
103    this.setVisible(true);
104  }
105  
106  /*
107   * Initialize the dialog
108   */
109  private void initialize()
110  {
111    scheduleChangeController = new ScheduleChangeController();
112    scheduleChangeController.addListener(this);
113    setTitle(TITLE);
114    setPreferredSize(new Dimension(WIDTH, HEIGHT));    
115    if(parent != null)
116    {
117      setLocation(parent.getLocation());
118    }
119    
120    topPanel = new JPanel();
121    topPanel.setLayout(new BorderLayout());
122    componentAndSchedulerPane = new DualVerticalViewPane();
123    try
124    {
125      componentAndSchedulerPane.initializeView();
126    }
127    catch(Exception e)
128    {
129      JOptionPane.showMessageDialog(parent, "Couldn't initialize the scheduler dialog - "+
130          e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
131      return;
132    }
133   
134    componentsTab = new WorkflowSchedulerComponentLibraryTab(parent);
135    componentsTab.initializeTab();
136    //componentsTab.setPreferredSize(new Dimension(200, HEIGHT));
137    componentsTab.setTabName(COMPONENTS);
138    componentsTab.setSkipReposiotryOntology(true);
139    scheduleChangeController.setComponentLibraryTab(componentsTab);
140    //jTree = componentsTab.getJTree();
141    //scheduleChangeController.setResultTree(jTree);
142   
143    try
144    {
145      componentAndSchedulerPane.addTabPane(componentsTab, new ViewPaneLocation("W"));
146      initRightPanel();
147    }
148    catch(Exception e)
149    {
150      JOptionPane.showMessageDialog(this, "Couldn't initialize the scheduler dialog - "+
151          e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
152      return;
153    }      
154    //topPanel.add(schedulerPanel, BorderLayout.EAST);
155    topPanel.add(componentAndSchedulerPane, BorderLayout.CENTER);
156    
157    progressBar = new JProgressBar(PROGRESSMIN, PROGRESSMAX);
158    Dimension barDimension = new Dimension(300, 10);
159    progressBar.setPreferredSize(barDimension);
160    progressBar.setMaximumSize(barDimension);
161    progressBar.setVisible(false);
162    //progressBar.setIndeterminate(true);
163
164    closeButton = new JButton("Close");
165    closeButton.setPreferredSize(new Dimension(100, 50));
166    closeButton.addActionListener(new ActionListener()
167    {
168      public void actionPerformed(ActionEvent e)
169      {
170        setVisible(false);
171      }
172    });   
173    
174    JPanel buttonPanel = new JPanel();
175    buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
176    buttonPanel.add(progressBar);
177    buttonPanel.add(Box.createHorizontalGlue());
178    //buttonPanel.setMaximumSize(new Dimension(350, 40));
179    //buttonPanel.add(okButton);
180    //buttonPanel.add(Box.createHorizontalStrut(10));
181    buttonPanel.add(closeButton);
182    buttonPanel.add(Box.createHorizontalStrut(10));
183    topPanel.add(buttonPanel, BorderLayout.SOUTH);
184    
185    getContentPane().add(topPanel);
186    addWindowListener(new DialogWindowAdapter(this));
187    StateChangeMonitor.getInstance().addStateChangeListener(WorkflowSchedulerConfigEvent.MODIFYCONFIGEVENT, this);
188  }
189  
190  
191  /*
192   * If the workflow scheduler and run engine were configured, it will show a scheduler panel.
193   * Otherwise it will show an installation info panel
194   */
195  private void initRightPanel() throws Exception
196  {
197    if(Initialize.isSchedulerURLConfigured() && Initialize.isWorkflowRunEngineConfigured())
198    {
199      WorkflowSchedulerParentPanel schedulerPanel = 
200          new WorkflowSchedulerParentPanel(parent, scheduleChangeController);
201      ComponentSearchResultTreeSelectionListener listener = 
202          new ComponentSearchResultTreeSelectionListener(schedulerPanel);
203      componentsTab.addTreeSingleSelectionListener(listener);
204      componentAndSchedulerPane.addTabPane(schedulerPanel, new ViewPaneLocation(EAST));
205    }
206    else
207    {
208      WorkflowSchedulerServerInstallationInfoPanel informationPanel = 
209          new WorkflowSchedulerServerInstallationInfoPanel(parent, this);
210      componentAndSchedulerPane.addTabPane(informationPanel, new ViewPaneLocation(EAST));
211    }
212    
213  }
214  
215  
216  /**
217   * Method will be called when configuration is done
218   */
219  public void handleStateChange(StateChangeEvent event)
220  {
221    if(event.getChangedState() != null && event.getChangedState().equals(WorkflowSchedulerConfigEvent.MODIFYCONFIGEVENT))
222    {
223      try
224      {
225        //remove the old server installation info panel since the information may be incorrect after configuring the properties.
226        Container eastContainer = componentAndSchedulerPane.getLocationContainer(EAST);
227        List<TabPane> list = componentAndSchedulerPane.getTabPanes(WorkflowSchedulerParentPanel.SCHEDULER);
228        if(list != null)
229        {
230          for(TabPane pane : list)
231          {
232            if(pane instanceof WorkflowSchedulerServerInstallationInfoPanel)
233            {
234              WorkflowSchedulerServerInstallationInfoPanel infoPane = (WorkflowSchedulerServerInstallationInfoPanel)pane;
235              //System.out.println("removing the old information panel");
236              eastContainer.remove(infoPane);
237            }
238            else if (pane instanceof WorkflowSchedulerParentPanel)
239            {
240              WorkflowSchedulerParentPanel schedulerParentPane = (WorkflowSchedulerParentPanel) pane;
241              //System.out.println("removing the old parent panel");
242              eastContainer.remove(schedulerParentPane);
243            }
244              
245          }
246        }
247      }
248      catch(Exception e)
249      {
250        return;
251      }
252      try
253      {
254        //initialize the new right panel base on the new configuration status (workflow url and run engines are configured or not)
255        initRightPanel();
256      }
257      catch(Exception e)
258      {
259        JOptionPane.showMessageDialog(this, "Couldn't update the scheduler dialog - "+
260            e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
261      } 
262      componentAndSchedulerPane.validate();
263      componentAndSchedulerPane.repaint();
264    }
265    
266  }
267 
268  
269  /**
270   * Get the component search tab
271   * @return
272   */
273  public ComponentLibraryTab getComponentSearchTab()
274  {
275    return componentsTab;
276  }
277  /**
278   * Handle the event that a new schedule is added
279   * @param schedule  the new schedule
280   * @throws Exception
281   */
282  public void addSchedule(Schedule schedule) throws Exception
283  {
284    //do nothing
285  }
286  
287  /**
288   * Handle the event that a schedule is removed
289   * @param schedule the schedule will be removed
290   * @throws Exception
291   */
292  public void removeSchedule(Schedule schedule) throws Exception
293  {
294    //do nothing
295  }
296  
297  /**
298   * Handle the event that a schedule will be enabled
299   * @param schedule the schedule will be enabled
300   * @throws Exception
301   */
302  public void enableSchedule(Schedule schedule) throws Exception
303  {
304    //do nothing
305  }
306  
307  /**
308   * Handle the event that a schedule will be disabled
309   * @param schedule the schedule will be disabled
310   * @throws Exception
311   */
312  public void disableSchedule(Schedule schedule) throws Exception
313  {
314    //do nothing
315  }
316  
317  /**
318   * Handle the event that new schedules will replace the old ones
319   * @param newSchedule new schedules
320   * @throws Exception
321   */
322  public void update(Schedule[] newSchedules) throws Exception
323  {
324    //do nothing
325  }
326  
327  /**
328   * Start the progress bar
329   *
330   */
331  public void start()
332  {
333    if(progressBar != null)
334    {
335      SwingUtilities.invokeLater(new Runnable() 
336      {
337        public void run()
338        {
339          progressBar.setVisible(true);
340          progressBar.setIndeterminate(true);
341        }
342        
343      });
344    }
345  }
346  
347  /**
348   * Stop the progress bar
349   */
350  public void stop()
351  {
352    if(progressBar != null)
353    {
354      SwingUtilities.invokeLater(new Runnable() 
355      {
356        public void run()
357        {
358          progressBar.setIndeterminate(false);
359          progressBar.setValue(PROGRESSMAX);
360          progressBar.setVisible(false);
361        }
362        
363      });
364    }
365  }
366
367  /*
368   * A customized window adapter: the dialog box will be set invisible
369   * when users close the dialog.
370   */
371  private class DialogWindowAdapter extends WindowAdapter
372  {
373    private JDialog dialog = null;
374    
375    /**
376     * Constructor
377     * @param dialog
378     */
379    public DialogWindowAdapter(JDialog dialog)
380    {
381      this.dialog = dialog;
382    }
383    
384    /**
385     * Set the dialog box invisible
386     */
387    public void windowClosing(WindowEvent e) 
388    {
389      if(dialog != null)
390      {
391        dialog.setVisible(false);
392      }
393    }
394  }
395}