001/*
002 * Copyright (c) 1998-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-08-30 21:33:16 +0000 (Thu, 30 Aug 2012) $' 
007 * '$Revision: 30578 $'
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.gui;
031
032import java.awt.BorderLayout;
033import java.awt.Dimension;
034import java.awt.event.ActionEvent;
035import java.awt.event.ActionListener;
036import java.awt.event.MouseListener;
037
038import javax.swing.JCheckBox;
039import javax.swing.JPanel;
040import javax.swing.JScrollPane;
041import javax.swing.ScrollPaneConstants;
042import javax.swing.SwingUtilities;
043
044import org.apache.commons.logging.Log;
045import org.apache.commons.logging.LogFactory;
046import org.kepler.gui.popups.OutlinePopupListener;
047import org.kepler.util.StaticResources;
048
049import ptolemy.kernel.CompositeEntity;
050import ptolemy.kernel.util.NamedObj;
051import ptolemy.moml.MoMLChangeRequest;
052
053public class WorkflowOutlinePanel extends JPanel {
054        private static final Log log = LogFactory
055                        .getLog(WorkflowOutlinePanel.class.getName());
056        private static final boolean isDebugging = log.isDebugEnabled();
057        
058        private SubsetWorkflowOutlineTreeModel wotm;
059
060        private JCheckBox togglePorts;
061        private JCheckBox toggleRelations;
062        private JCheckBox toggleAttributes;
063        
064        private boolean includeAttributeCheckBox = false;
065        private boolean includePortsCheckBox = false;
066        private boolean includeRelationsCheckBox = false;
067    private MouseListener _mouseListener;
068
069    private AnnotatedPTree _ptree;
070
071    private String _searchTerm;
072    
073        public WorkflowOutlinePanel(CompositeEntity entity, 
074                        boolean includeAttributeCheckBox, boolean includePortsCheckBox, 
075                        boolean includeRelationsCheckBox) {
076                
077                this.includeAttributeCheckBox = includeAttributeCheckBox;
078                this.includePortsCheckBox = includePortsCheckBox;
079                this.includeRelationsCheckBox = includeRelationsCheckBox;
080                
081                initialize(entity);
082        }
083
084        /*
085         * (non-Javadoc)
086         * 
087         * @see org.kepler.gui.TabPane#initializeTab()
088         */
089        public void initialize(CompositeEntity entity) {
090                if (isDebugging) log.debug("initialize()");
091                this.setLayout(new BorderLayout());
092                this.setBackground(TabManager.BGCOLOR);
093                
094                wotm = new SubsetWorkflowOutlineTreeModel(entity);
095
096                refreshOutlineTree();
097        }
098        
099        public void refreshOutlineTree() {
100                if (isDebugging) {
101                        log.debug("refreshOutlineTree()");
102                }
103
104                this.removeAll();
105
106                _ptree = new AnnotatedPTree(wotm, this);
107
108                _mouseListener = new OutlinePopupListener(_ptree);
109                _ptree.setMouseListener(_mouseListener);
110
111                _ptree.setRootVisible(false);
112                _ptree.initAnotatedPTree();
113                JScrollPane jSP = new JScrollPane(_ptree,
114                                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
115                                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
116                jSP.setPreferredSize(new Dimension(200, 200));
117
118                this.add(jSP, BorderLayout.CENTER);
119                
120                setControls();
121
122                this.repaint();
123                this.validate();
124
125                // if panel was showing the results of a search, redo the search
126                if(_searchTerm != null && !_searchTerm.isEmpty()) {
127                    search(_searchTerm);
128                }
129        }
130
131        /** Display the subset of the workflow for entities containing the given term.
132         *  To display everything set the term to the empty string.
133         */
134        public void search(String searchTerm) {
135
136            // reset the display
137        wotm.showAll();
138
139        // do the search if search term is not empty
140            if(!searchTerm.isEmpty()) {
141                Object root = wotm.getRoot();
142                _searchTree(root, searchTerm);
143                // show only the matches
144                wotm.showSubset();
145
146            }
147            
148            // issue an empty change request to repaint the tree
149        MoMLChangeRequest change = 
150                new MoMLChangeRequest(wotm.getRoot(), (NamedObj) wotm.getRoot(), "<group></group>");
151        change.setPersistent(false);
152        ((NamedObj) wotm.getRoot()).requestChange(change);
153
154        // if the search term was not empty, expand the tree to show
155        // the matching nodes
156        if(!searchTerm.isEmpty()) {
157            // do this in the swing thread so that it occurs after the tree is repainted
158            SwingUtilities.invokeLater(new Runnable() {
159                public void run() {
160                    LibrarySearchResultPane.expandAll(_ptree);
161                }
162            });
163        }
164        
165        _searchTerm = searchTerm;
166        
167        }
168        
169        /** Recursively check if a node and its children contain the search term. */
170        private void _searchTree(Object node, String searchTerm) {         
171            
172            NamedObj namedObj = (NamedObj)node;
173            //System.out.println("searching " + namedObj.getFullName());
174            // see if the name contains the search term; ignore case
175            if(namedObj.getName().toLowerCase().contains(searchTerm.toLowerCase())) {           
176                //System.out.println(namedObj);
177                wotm.addToSubset(namedObj);
178            }
179            
180            if(!wotm.isLeaf(node)) {
181                for(int i = 0; i < wotm.getChildCount(node); i++) {
182                    _searchTree(wotm.getChild(node, i), searchTerm);
183                }
184            }
185        }
186        
187        private void setControls() {
188
189                JPanel controlPanel = new JPanel(new BorderLayout());
190                
191                if (includePortsCheckBox) {
192                        togglePorts = new JCheckBox(StaticResources.getDisplayString(
193                                        "outline.showPorts", "Show Ports"));
194                        togglePorts.setSelected(wotm.includePorts);
195                        togglePorts.addActionListener(new ToggleListener());
196                        togglePorts.setBackground(TabManager.BGCOLOR);
197                        controlPanel.add(togglePorts, BorderLayout.NORTH);
198                }
199
200                if (includeAttributeCheckBox) {
201                        toggleAttributes = new JCheckBox(StaticResources.getDisplayString(
202                                        "outline.showAttributes", "Show Attributes"));
203                        toggleAttributes.setSelected(wotm.includeAttributes);
204                        toggleAttributes.addActionListener(new ToggleListener());
205                        toggleAttributes.setBackground(TabManager.BGCOLOR);
206                        controlPanel.add(toggleAttributes, BorderLayout.CENTER);
207
208                }
209
210                if (includeRelationsCheckBox) {
211                        toggleRelations = new JCheckBox(StaticResources.getDisplayString(
212                                        "outline.showRelations", "Show Relations"));
213                        toggleRelations.setSelected(wotm.includeRelations);
214                        toggleRelations.addActionListener(new ToggleListener());
215                        toggleRelations.setBackground(TabManager.BGCOLOR);
216                        controlPanel.add(toggleRelations, BorderLayout.SOUTH);
217                }
218                
219                controlPanel.setBackground(TabManager.BGCOLOR);
220                this.add(controlPanel,BorderLayout.SOUTH);              
221        }
222
223        
224        private class ToggleListener implements ActionListener {
225
226                public void actionPerformed(ActionEvent e) {
227                        if (isDebugging) log.debug("actionPerformed("+e+")");
228                        if (e.getSource() == togglePorts) {
229                                if (isDebugging) log.debug("togglePorts");
230                                if (togglePorts.isSelected()) {
231                                        wotm.includePorts = true;
232                                } else {
233                                        wotm.includePorts = false;
234                                }
235                        } else if (e.getSource() == toggleAttributes) {
236                                if (isDebugging) log.debug("toggleAttributes");
237                                if (toggleAttributes.isSelected()) {
238                                        wotm.includeAttributes = true;
239                                } else {
240                                        wotm.includeAttributes = false;
241                                }
242                        } else if (e.getSource() == toggleRelations) {
243                                if (isDebugging) log.debug("toggleRelations");
244                                if (toggleRelations.isSelected()) {
245                                        wotm.includeRelations = true;
246                                } else {
247                                        wotm.includeRelations = false;
248                                }
249                        }
250                        refreshOutlineTree();
251                }
252        }
253
254}