Coverage Report - org.argouml.ui.TabResults
 
Classes in this File Line Coverage Branch Coverage Complexity
TabResults
0%
0/138
0%
0/50
2.318
 
 1  
 /* $Id: TabResults.java 18640 2010-08-12 22:21:43Z tfmorris $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    tfmorris
 11  
  *****************************************************************************
 12  
  *
 13  
  * Some portions of this file was previously release using the BSD License:
 14  
  */
 15  
 
 16  
 // Copyright (c) 1996-2008 The Regents of the University of California. All
 17  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 18  
 // software and its documentation without fee, and without a written
 19  
 // agreement is hereby granted, provided that the above copyright notice
 20  
 // and this paragraph appear in all copies. This software program and
 21  
 // documentation are copyrighted by The Regents of the University of
 22  
 // California. The software program and documentation are supplied "AS
 23  
 // IS", without any accompanying services from The Regents. The Regents
 24  
 // does not warrant that the operation of the program will be
 25  
 // uninterrupted or error-free. The end-user understands that the program
 26  
 // was developed for research purposes and is advised not to rely
 27  
 // exclusively on the program for any reason. IN NO EVENT SHALL THE
 28  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 29  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 30  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 31  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 32  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 33  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 34  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 35  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 36  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 37  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 38  
 
 39  
 package org.argouml.ui;
 40  
 
 41  
 import java.awt.BorderLayout;
 42  
 import java.awt.Dimension;
 43  
 import java.awt.event.ActionEvent;
 44  
 import java.awt.event.ActionListener;
 45  
 import java.awt.event.KeyEvent;
 46  
 import java.awt.event.KeyListener;
 47  
 import java.awt.event.MouseEvent;
 48  
 import java.awt.event.MouseListener;
 49  
 import java.util.ArrayList;
 50  
 import java.util.Enumeration;
 51  
 import java.util.HashSet;
 52  
 import java.util.Iterator;
 53  
 import java.util.List;
 54  
 import java.util.Set;
 55  
 
 56  
 import javax.swing.BorderFactory;
 57  
 import javax.swing.JLabel;
 58  
 import javax.swing.JPanel;
 59  
 import javax.swing.JScrollPane;
 60  
 import javax.swing.JSplitPane;
 61  
 import javax.swing.JTable;
 62  
 import javax.swing.ListSelectionModel;
 63  
 import javax.swing.event.ListSelectionEvent;
 64  
 import javax.swing.event.ListSelectionListener;
 65  
 
 66  
 import org.apache.log4j.Logger;
 67  
 import org.argouml.application.api.AbstractArgoJPanel;
 68  
 import org.argouml.i18n.Translator;
 69  
 import org.argouml.model.Model;
 70  
 import org.argouml.ui.targetmanager.TargetManager;
 71  
 import org.argouml.uml.ChildGenRelated;
 72  
 import org.argouml.uml.PredicateSearch;
 73  
 import org.argouml.uml.TMResults;
 74  
 import org.argouml.uml.diagram.ArgoDiagram;
 75  
 import org.argouml.util.ChildGenerator;
 76  
 
 77  
 
 78  
 /**
 79  
  * The results tab for the find dialog.
 80  
  * <p>
 81  
  * NOTE: An incompatible change was made to the public API for this class
 82  
  * before the release of ArgoUML 0.26 to remove exposed internal implementation
 83  
  * details (GEF).
 84  
  */
 85  
 public class TabResults
 86  
         extends AbstractArgoJPanel
 87  
         implements
 88  
                 Runnable,
 89  
                 MouseListener,
 90  
                 ActionListener,
 91  
                 ListSelectionListener,
 92  
                 KeyListener {
 93  
     /**
 94  
      * Logger.
 95  
      */
 96  0
     private static final Logger LOG = Logger.getLogger(TabResults.class);
 97  
 
 98  
     private static int numJumpToRelated;
 99  
 
 100  
     /**
 101  
      * Insets in pixels.
 102  
      */
 103  
     private static final int INSET_PX = 3;
 104  
 
 105  
     private PredicateSearch pred;
 106  
     private ChildGenerator cg;
 107  
     private Object root;
 108  
     private JSplitPane mainPane;
 109  0
     private List results = new ArrayList();
 110  0
     private Set diagramResults = new HashSet();
 111  0
     private List related = new ArrayList();
 112  0
     private List<ArgoDiagram> diagrams = new ArrayList<ArgoDiagram>();
 113  
     private boolean relatedShown;
 114  
 
 115  0
     private JLabel resultsLabel = new JLabel();
 116  
     private JTable resultsTable;
 117  
     private TMResults resultsModel;
 118  
 
 119  0
     private JLabel relatedLabel = new JLabel();
 120  0
     private JTable relatedTable = new JTable(4, 4);
 121  0
     private TMResults relatedModel = new TMResults();
 122  
 
 123  
     /**
 124  
      * The constructor.
 125  
      *
 126  
      */
 127  
     public TabResults() {
 128  0
         this(true);
 129  0
     }
 130  
 
 131  
     /**
 132  
      * The constructor.
 133  
      *
 134  
      * @param showRelated true if related results should be shown
 135  
      */
 136  
     public TabResults(boolean showRelated) {
 137  0
         super("Results", true);
 138  0
         relatedShown = showRelated;
 139  0
         setLayout(new BorderLayout());
 140  0
         resultsTable = new JTable(10, showRelated ? 4 : 3);
 141  0
         resultsModel = new TMResults(showRelated);
 142  
 
 143  0
         JPanel resultsW = new JPanel();
 144  0
         JScrollPane resultsSP = new JScrollPane(resultsTable);
 145  0
         resultsW.setLayout(new BorderLayout());
 146  0
         resultsLabel.setBorder(BorderFactory.createEmptyBorder(
 147  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 148  0
         resultsW.add(resultsLabel, BorderLayout.NORTH);
 149  0
         resultsW.add(resultsSP, BorderLayout.CENTER);
 150  0
         resultsTable.setModel(resultsModel);
 151  0
         resultsTable.addMouseListener(this);
 152  0
         resultsTable.addKeyListener(this);
 153  0
         resultsTable.getSelectionModel().addListSelectionListener(
 154  
                                                                    this);
 155  0
         resultsTable.setSelectionMode(
 156  
                                        ListSelectionModel.SINGLE_SELECTION);
 157  0
         resultsW.setMinimumSize(new Dimension(100, 100));
 158  
 
 159  0
         JPanel relatedW = new JPanel();
 160  0
         if (relatedShown) {
 161  0
             JScrollPane relatedSP = new JScrollPane(relatedTable);
 162  0
             relatedW.setLayout(new BorderLayout());
 163  0
             relatedLabel.setBorder(BorderFactory.createEmptyBorder(
 164  
                     INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 165  0
             relatedW.add(relatedLabel, BorderLayout.NORTH);
 166  0
             relatedW.add(relatedSP, BorderLayout.CENTER);
 167  0
             relatedTable.setModel(relatedModel);
 168  0
             relatedTable.addMouseListener(this);
 169  0
             relatedTable.addKeyListener(this);
 170  0
             relatedW.setMinimumSize(new Dimension(100, 100));
 171  
         }
 172  
 
 173  0
         if (relatedShown) {
 174  0
             mainPane =
 175  
                 new JSplitPane(JSplitPane.VERTICAL_SPLIT,
 176  
                                resultsW,
 177  
                                relatedW);
 178  0
             add(mainPane, BorderLayout.CENTER);
 179  
         } else {
 180  0
             add(resultsW, BorderLayout.CENTER);
 181  
         }
 182  
 
 183  0
     }
 184  
 
 185  
     /**
 186  
      * @param p the predicate for the search
 187  
      *            <p>
 188  
      *            NOTE: The type of this parameter was changed incompatibly
 189  
      *            before 0.26 from org.argouml.uml.PredicateFind to
 190  
      *            org.argouml.uml.PredicateSearch.
 191  
      */
 192  
     public void setPredicate(PredicateSearch p) {
 193  0
         pred = p;
 194  0
     }
 195  
 
 196  
     /**
 197  
      * @param r the root object for the search
 198  
      */
 199  
     public void setRoot(Object r) {
 200  0
         root = r;
 201  0
     }
 202  
 
 203  
     /**
 204  
      * @param gen the generator.
 205  
      *            <p>
 206  
      *            NOTE: The type of this parameter was changed incompatibly
 207  
      *            before 0.26 from org.tigris.gef.util.ChildGenerator to
 208  
      *            org.argouml.util.ChildGenerator.
 209  
      */
 210  
     public void setGenerator(ChildGenerator gen) {
 211  0
         cg = gen;
 212  0
     }
 213  
 
 214  
     /**
 215  
      * @param res the results
 216  
      * @param dia the diagrams
 217  
      */
 218  
     public void setResults(List res, List dia) {
 219  0
         results = res;
 220  0
         diagrams = dia;
 221  0
         Object[] msgArgs = {Integer.valueOf(results.size()) };
 222  0
         resultsLabel.setText(Translator.messageFormat(
 223  
             "dialog.tabresults.results-items", msgArgs));
 224  0
         resultsModel.setTarget(results, diagrams);
 225  0
         relatedModel.setTarget((List) null, (List) null);
 226  0
         relatedLabel.setText(
 227  
             Translator.localize("dialog.tabresults.related-items"));
 228  0
     }
 229  
     
 230  
     /*
 231  
      * @see org.argouml.ui.AbstractArgoJPanel#spawn()
 232  
      */
 233  
     public AbstractArgoJPanel spawn() {
 234  0
         TabResults newPanel = (TabResults) super.spawn();
 235  0
         if (newPanel != null) {
 236  0
             newPanel.setResults(results, diagrams);
 237  
         }
 238  0
         return newPanel;
 239  
     }
 240  
 
 241  
     /**
 242  
      * Handle a doubleclick on the results tab.
 243  
      */
 244  
     public void doDoubleClick() {
 245  0
         myDoubleClick(resultsTable);
 246  0
     }
 247  
 
 248  
     /**
 249  
      * Select the result at the given index.
 250  
      *
 251  
      * @param index the given index
 252  
      */
 253  
     public void selectResult(int index) {
 254  0
         if (index < resultsTable.getRowCount()) {
 255  0
             resultsTable.getSelectionModel().setSelectionInterval(index,
 256  
                                                                    index);
 257  
         }
 258  0
     }
 259  
 
 260  
     ////////////////////////////////////////////////////////////////
 261  
     // ActionListener implementation
 262  
 
 263  
     /*
 264  
      * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 265  
      */
 266  
     public void actionPerformed(ActionEvent ae) {
 267  
         // ignored
 268  0
     }
 269  
 
 270  
     ////////////////////////////////////////////////////////////////
 271  
     // MouseListener implementation
 272  
 
 273  
     /*
 274  
      * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
 275  
      */
 276  
     public void mousePressed(MouseEvent me) {
 277  
         // ignored
 278  0
     }
 279  
 
 280  
     /*
 281  
      * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
 282  
      */
 283  
     public void mouseReleased(MouseEvent me) {
 284  
         // ignored
 285  0
     }
 286  
 
 287  
     /*
 288  
      * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
 289  
      */
 290  
     public void mouseClicked(MouseEvent me) {
 291  0
         if (me.getClickCount() >= 2) {
 292  0
             myDoubleClick(me.getSource());
 293  
         }
 294  0
     }
 295  
 
 296  
     /*
 297  
      * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
 298  
      */
 299  
     public void mouseEntered(MouseEvent me) {
 300  
         // ignored
 301  0
     }
 302  
 
 303  
     /*
 304  
      * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
 305  
      */
 306  
     public void mouseExited(MouseEvent me) {
 307  
         // ignored
 308  0
     }
 309  
 
 310  
     private void myDoubleClick(Object src) {
 311  0
         Object sel = null;
 312  0
         ArgoDiagram d = null;
 313  0
         if (src == resultsTable) {
 314  0
             int row = resultsTable.getSelectionModel().getMinSelectionIndex();
 315  0
             if (row < 0) {
 316  0
                 return;
 317  
             }
 318  0
             sel = results.get(row);
 319  0
             d = diagrams.get(row);
 320  0
         } else if (src == relatedTable) {
 321  0
             int row = relatedTable.getSelectionModel().getMinSelectionIndex();
 322  0
             if (row < 0) {
 323  0
                 return;
 324  
             }
 325  0
             numJumpToRelated++;
 326  0
             sel = related.get(row);
 327  
         }
 328  
 
 329  0
         if (d != null) {
 330  0
             LOG.debug("go " + sel + " in " + d.getName());
 331  0
             TargetManager.getInstance().setTarget(d);
 332  
         }
 333  0
         if (Model.getFacade().isATaggedValue(sel)) {
 334  
             // For tagged values, use their containing ModelElement since they
 335  
             // don't have property panels of their own
 336  
             // TODO: May want to do this for other types too?
 337  0
             sel = Model.getFacade().getModelElementContainer(sel);
 338  
         }
 339  0
         TargetManager.getInstance().setTarget(sel);
 340  0
     }
 341  
 
 342  
     ////////////////////////////////////////////////////////////////
 343  
     // KeyListener implementation
 344  
 
 345  
     /*
 346  
      * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
 347  
      */
 348  
     public void keyPressed(KeyEvent e) {
 349  0
         if (!e.isConsumed() && e.getKeyChar() == KeyEvent.VK_ENTER) {
 350  0
             e.consume();
 351  0
             myDoubleClick(e.getSource());
 352  
         }
 353  0
     }
 354  
 
 355  
     /*
 356  
      * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
 357  
      */
 358  
     public void keyReleased(KeyEvent e) {
 359  
         // ignored
 360  0
     }
 361  
 
 362  
     /*
 363  
      * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
 364  
      */
 365  
     public void keyTyped(KeyEvent e) {
 366  
         // ignored
 367  0
     }
 368  
 
 369  
     ////////////////////////////////////////////////////////////////
 370  
     // ListSelectionListener implementation
 371  
 
 372  
     /*
 373  
      * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
 374  
      */
 375  
     public void valueChanged(ListSelectionEvent lse) {
 376  0
         if (lse.getValueIsAdjusting()) {
 377  0
             return;
 378  
         }
 379  0
         if (relatedShown) {
 380  0
             int row = lse.getFirstIndex();
 381  0
             Object sel = results.get(row);
 382  0
             LOG.debug("selected " + sel);
 383  0
             related.clear();
 384  0
             Enumeration elems =
 385  
                 ChildGenRelated.getSingleton().gen(sel);
 386  0
             if (elems != null) {
 387  0
                 while (elems.hasMoreElements()) {
 388  0
                     related.add(elems.nextElement());
 389  
                 }
 390  
             }
 391  0
             relatedModel.setTarget(related, null);
 392  0
             Object[] msgArgs = {Integer.valueOf(related.size()) };
 393  0
             relatedLabel.setText(Translator.messageFormat(
 394  
                 "dialog.find.related-elements", msgArgs));
 395  
         }
 396  0
     }
 397  
 
 398  
     /*
 399  
      * @see java.lang.Runnable#run()
 400  
      */
 401  
     public void run() {
 402  0
         resultsLabel.setText(Translator.localize("dialog.find.searching"));
 403  0
         results.clear();
 404  0
         depthFirst(root, null);
 405  0
         setResults(results, diagrams);
 406  0
     }
 407  
 
 408  
     /**
 409  
      * Do a recursive depth first search of the project. The children of the
 410  
      * root are all user models and all the diagrams. Searches of the diagrams
 411  
      * will terminate immediately if they fail to match, but the models are
 412  
      * searched to their leaves, even if the diagram predicate doesn't match an
 413  
      * empty diagram name.  This is inefficient, but shouldn't be a common
 414  
      * case.<p>
 415  
      *
 416  
      * Another effect of the current algorithm is that model elements will
 417  
      * appear once for each diagram that they are included in PLUS an additional
 418  
      * time with no diagram name given.  It would be slightly more friendly
 419  
      * have the non-diagram list only includes those elements which didn't
 420  
      * appear in any other diagram, but we're not going to do the bookkeeping
 421  
      * for now.  - tfm 20060214
 422  
      */
 423  
     private void depthFirst(Object node, ArgoDiagram lastDiagram) {
 424  0
         if (node instanceof ArgoDiagram) {
 425  0
             lastDiagram = (ArgoDiagram) node;
 426  0
             diagramResults.clear();
 427  0
             if (!pred.matchDiagram(lastDiagram)) {
 428  0
                 return;
 429  
             }
 430  
             // diagrams are not placed in search results
 431  
         }
 432  0
         Iterator iterator = cg.childIterator(node);
 433  0
         while (iterator.hasNext()) {
 434  0
             Object child = iterator.next();
 435  0
             if (pred.evaluate(child)
 436  
                     && (lastDiagram != null || pred.matchDiagram(""))) {
 437  
                 // Only return once per diagram so we don't, for example, find
 438  
                 // a class as a diagram element and also as a child of a package
 439  
                 // which is on the diagram
 440  0
                 if (!diagramResults.contains(child)) {
 441  0
                     diagramResults.add(child);
 442  0
                     results.add(child);
 443  0
                     diagrams.add(lastDiagram);
 444  
                 }
 445  
             }
 446  0
             depthFirst(child, lastDiagram);
 447  0
         }
 448  0
     }
 449  
 
 450  
     /**
 451  
      * The UID.
 452  
      */
 453  
     private static final long serialVersionUID = 4980167466628873068L;
 454  
 }