001/**
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
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 */
029package org.kepler.workflowscheduler.gui.configurationwizard;
030
031import java.awt.BorderLayout;
032import java.awt.Dimension;
033import java.awt.Point;
034import java.awt.event.ActionEvent;
035import java.awt.event.MouseAdapter;
036import java.awt.event.MouseEvent;
037
038import javax.swing.AbstractAction;
039import javax.swing.BorderFactory;
040import javax.swing.JMenuItem;
041import javax.swing.JPanel;
042import javax.swing.JPopupMenu;
043import javax.swing.JScrollPane;
044import javax.swing.JTable;
045import javax.swing.ListSelectionModel;
046
047import org.kepler.module.workflowschedulergui.Initialize;
048import org.kepler.workflowscheduler.gui.WorkflowRunEngine;
049
050
051public class KnownWorkflowRunEnginePanel extends JPanel implements WorkflowRunEngineConfigurationChangeListener
052{
053  private int BORDERGAP = 20;
054  private WorkflowRunEngine[] engineList = null;
055  private KnownWorkflowRunEngineTableModel engineTableModel = null;
056  private JTable engineTable = null;
057  private WorkflowRunEngine selectedEngine = null;
058  
059  /**
060   * Constructor
061   * @param engineList
062   */
063  public KnownWorkflowRunEnginePanel(WorkflowRunEngine[] engineList)
064  {
065    this.engineList = engineList;
066    initialize();
067  }
068  /*
069   * Initialize the panel
070   */
071  private void initialize()
072  {
073    
074    this.setLayout(new BorderLayout());
075    this.setBorder(BorderFactory.createEmptyBorder(BORDERGAP, BORDERGAP, BORDERGAP, BORDERGAP));
076    //JTableHeader header = scheduleTable.getTableHeader();
077    //header.setBackground(Color.LIGHT_GRAY);
078    engineTableModel = new KnownWorkflowRunEngineTableModel(engineList);   
079    engineTable = new JTable(engineTableModel);
080    engineTable.setAutoCreateColumnsFromModel(false);
081    engineTable.addMouseListener(new PopupListener());
082    engineTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
083    JScrollPane scrollPane = new JScrollPane(engineTable);
084    scrollPane.setPreferredSize(new Dimension(600, 150));
085    //scrollPane.setPreferredSize(new Dimension(800, 180));
086    add(scrollPane, BorderLayout.CENTER);
087    /*if(engineList == null)
088    {
089      this.setVisible(false);
090    }*/
091    
092  }
093  
094  /*
095   * Update the table after the table data model was changed
096   */
097  private void updateTable()
098  {
099    engineTableModel = new KnownWorkflowRunEngineTableModel(engineList);
100    engineTable.setModel(engineTableModel);
101    //scheduleTableModel.fireTableDataChanged();
102    engineTable.repaint();
103    engineTable.validate();
104    /*if(engineList == null)
105    {
106      this.setVisible(false);
107    }
108    else
109    {
110      this.setVisible(true);
111    }*/
112    //System.out.println("After repaint table");
113  }
114  
115  
116  /**
117   * Add a new engine to the configuration
118   * @param engine then engine will be added
119   */
120  public void add(WorkflowRunEngine engine)
121  {
122    if(engine != null)
123    {
124      if(engineList == null )
125      {
126        engineList = new WorkflowRunEngine[1];
127        engineList[0] = engine;
128      }
129      else 
130      {
131        WorkflowRunEngine[] oldArray = engineList;
132        int size = engineList.length;
133        int newSize = size+1;
134        engineList = new WorkflowRunEngine[newSize];
135        engineList[0]= engine;
136        for(int i=0; i<size; i++)
137        {
138          engineList[i+1] = oldArray[i];
139        }
140     }
141     updateTable();
142   }
143  }
144  
145  /*
146   * Delete an engine.
147   */
148  private void delete(WorkflowRunEngine engine)
149  {
150    //first delete the engine from configuration file
151    Initialize.removeWorkflowRunEngineFromConfig(engine);
152    if(engine != null)
153    {
154      if(engineList != null && engineList.length != 0)
155      {
156        boolean foundIt = false;
157        WorkflowRunEngine[] oldArray = engineList;
158        int size = engineList.length;
159        int newSize = size-1;
160        WorkflowRunEngine[] newArray = null;
161        if(newSize > 0)
162        {
163          //Note: only newSize is greater than zero, we initialize the array.
164          newArray = new WorkflowRunEngine[newSize];
165        }
166        //compare size -1 elements in old array
167        for(int i=0; i<newSize; i++)
168        {
169          WorkflowRunEngine existEngine = oldArray[i];
170          if( existEngine != null && existEngine.getName() != null  &&
171              existEngine.getName().equals(engine.getName()) && 
172              existEngine.getURL() != null && existEngine.getURL().equals(engine.getURL()))
173          {
174            foundIt = true;
175            newArray[i] = oldArray[i+1];//skip the the element having index=i in old array.
176          }
177          else
178          {
179            if(!foundIt)
180            {
181              newArray[i]=oldArray[i];
182            }
183            else
184            {
185              newArray[i] = oldArray[i+1];
186            }
187          }
188        }
189        
190       if(!foundIt)
191       {
192         //If we didn't find matched schedule above for loop,
193         //We must compare the last element in the original list
194         WorkflowRunEngine existEngine = oldArray[size-1];
195         if( existEngine != null && existEngine.getName() != null  &&
196             existEngine.getName().equals(engine.getName()) && 
197             existEngine.getURL() != null && existEngine.getURL().equals(engine.getURL()))
198         {
199           // the last element is the schedule we will remove. So 
200           //scheduleList will be the newArray
201           engineList = newArray;
202           updateTable();
203         }
204        
205       }
206       else
207       {
208         engineList = newArray;
209         updateTable();
210       }
211        
212       
213     }  
214   }
215
216  }
217  
218  /*
219   * Class to handle right-click menu
220   */
221  private class PopupListener extends MouseAdapter 
222  {
223    
224    // on the Mac, popups are triggered on mouse pressed, while mouseReleased triggers them
225    // on the PC; use the trigger flag to record a trigger in mac, but do not show popup until the
226    // mouse released event 
227
228    boolean trigger = false;
229    private JPopupMenu popup = null;
230    //private WorkflowRunEngine selectedEngine = null;
231
232    /**
233     * Handle mouse pressed event
234     */
235    public void mousePressed(MouseEvent e)
236    {
237     
238        //select the clicked row first
239        engineTable.clearSelection();
240        int selrow = engineTable.rowAtPoint(new Point(e.getX(), e.getY()));
241        //System.out.println("the selection row number is============= "+selrow);
242        engineTable.setRowSelectionInterval(selrow, selrow);
243        selectedEngine = engineList[selrow];
244        // for mac
245        if (e.isPopupTrigger()) 
246        {
247          trigger = true;
248        }
249      
250    }
251
252    /**
253     * Handle mouse released event
254     */
255    public void mouseReleased(MouseEvent e)
256    {
257      maybeShowPopup(e);     
258    }
259
260    /*
261     *Show right popup menu
262     */
263    private void maybeShowPopup(MouseEvent e)
264    {
265      //trigger = true is for mac. e.isPopupTrigger()  is for pc
266      if(e.isPopupTrigger() || trigger)
267      {
268        if(selectedEngine != null)
269        {
270          popup = new JPopupMenu();
271          JMenuItem delete = new JMenuItem("Delete");
272          DeleteWorkflowRunEngineAction deleteAction = new DeleteWorkflowRunEngineAction(selectedEngine);
273          delete.addActionListener(deleteAction);
274          popup.add(delete);
275          trigger = false;
276          popup.show(e.getComponent(), e.getX(), e.getY());
277        }
278        
279      }
280    }
281
282  }
283  
284  /*
285   * Action to remove the workflow run engine from configuration file and also remove
286   * it from the known workflow run engine table.
287   * @author tao
288   *
289   */
290  private class DeleteWorkflowRunEngineAction extends AbstractAction
291  {
292    private WorkflowRunEngine deletedEngine = null;
293    
294    public DeleteWorkflowRunEngineAction(WorkflowRunEngine deletedEngine)
295    {
296      this.deletedEngine = deletedEngine;
297    }
298    /**
299     * Remove the selected engine
300     */
301    public void actionPerformed(ActionEvent e)
302    {
303      delete(deletedEngine);
304    }
305  }
306
307}