Coverage Report - org.argouml.ui.DetailsPane
 
Classes in this File Line Coverage Branch Coverage Complexity
DetailsPane
49%
108/217
38%
49/126
2.944
 
 1  
 /* $Id: DetailsPane.java 18455 2010-06-23 16:30:10Z bobtarling $
 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  
  *    bobtarling
 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.Component;
 43  
 import java.awt.Dimension;
 44  
 import java.awt.Font;
 45  
 import java.awt.Rectangle;
 46  
 import java.awt.event.MouseEvent;
 47  
 import java.awt.event.MouseListener;
 48  
 import java.util.ArrayList;
 49  
 import java.util.Iterator;
 50  
 import java.util.List;
 51  
 
 52  
 import javax.swing.Icon;
 53  
 import javax.swing.JPanel;
 54  
 import javax.swing.JTabbedPane;
 55  
 import javax.swing.event.ChangeEvent;
 56  
 import javax.swing.event.ChangeListener;
 57  
 import javax.swing.event.EventListenerList;
 58  
 
 59  
 import org.apache.log4j.Logger;
 60  
 import org.argouml.application.api.AbstractArgoJPanel;
 61  
 import org.argouml.i18n.Translator;
 62  
 import org.argouml.model.Model;
 63  
 import org.argouml.swingext.LeftArrowIcon;
 64  
 import org.argouml.swingext.UpArrowIcon;
 65  
 import org.argouml.ui.ProjectBrowser.Position;
 66  
 import org.argouml.ui.targetmanager.TargetEvent;
 67  
 import org.argouml.ui.targetmanager.TargetListener;
 68  
 import org.argouml.ui.targetmanager.TargetManager;
 69  
 import org.argouml.uml.ui.PropPanel;
 70  
 import org.argouml.uml.ui.TabProps;
 71  
 import org.tigris.swidgets.Orientable;
 72  
 import org.tigris.swidgets.Orientation;
 73  
 
 74  
 /**
 75  
  * The lower-right pane of the main ArgoUML window, which shows
 76  
  * the details of a selected model element. <p>
 77  
  *
 78  
  * This panel has several tabs that show details of the selected
 79  
  * ToDoItem, or the selected model element in the Explorer (NavigatorPane),
 80  
  * or the MultiEditorPane. <p>
 81  
  *
 82  
  * There are requests to have the cursor automatically
 83  
  * be set to the primary field.
 84  
  */
 85  
 public class DetailsPane
 86  
     extends JPanel
 87  
     implements ChangeListener, MouseListener,
 88  
                Orientable,
 89  
                TargetListener {
 90  
 
 91  
     /**
 92  
      * Logger.
 93  
      */
 94  900
     private static final Logger LOG = Logger.getLogger(DetailsPane.class);
 95  
 
 96  
     /**
 97  
      * The top level pane, which is a tabbed pane.
 98  
      */
 99  5400
     private JTabbedPane topLevelTabbedPane = new JTabbedPane();
 100  
 
 101  
     /**
 102  
      * The current target.
 103  
      */
 104  
     private Object currentTarget;
 105  
 
 106  
     
 107  
     /**
 108  
      * The list of all the tabs, which are JPanels, in the JTabbedPane tabs.
 109  
      */
 110  5400
     private List<JPanel> tabPanelList = new ArrayList<JPanel>();
 111  
 
 112  
     /**
 113  
      * index of the selected tab in the JTabbedPane.
 114  
      */
 115  5400
     private int lastNonNullTab = -1;
 116  
 
 117  
     /**
 118  
      * The list with targetlisteners, this are the property panels
 119  
      * managed by TabProps It should only contain one listener at a
 120  
      * time.
 121  
      */
 122  5400
     private EventListenerList listenerList = new EventListenerList();
 123  
     
 124  
     private Orientation orientation;
 125  
     
 126  5400
     private boolean hasTabs = false;
 127  
 
 128  
     /**
 129  
      * Adds a listener.
 130  
      * @param listener the listener to add
 131  
      */
 132  
     private void addTargetListener(TargetListener listener) {
 133  2528
         listenerList.add(TargetListener.class, listener);
 134  2528
     }
 135  
 
 136  
     /**
 137  
      * Removes a target listener.
 138  
      * @param listener the listener to remove
 139  
      */
 140  
     private void removeTargetListener(TargetListener listener) {
 141  12182
         listenerList.remove(TargetListener.class, listener);
 142  12182
     }
 143  
 
 144  
     /**
 145  
      * Gets all of the tabPanels from the ConfigLoader, then
 146  
      * adds them to the JTabbedPane.<p>
 147  
      *
 148  
      * Sets the target to null.<p>
 149  
      *
 150  
      * Registers listeners.<p>
 151  
      *
 152  
      * @param compassPoint the position for which to build the pane
 153  
      * @param theOrientation is the orientation.
 154  
      */
 155  5400
     public DetailsPane(String compassPoint, Orientation theOrientation) {
 156  5400
         LOG.info("making DetailsPane(" + compassPoint + ")");
 157  
         
 158  5400
         orientation = theOrientation;
 159  
 
 160  5400
         loadTabs(compassPoint, theOrientation);
 161  
         
 162  5400
         setOrientation(orientation);
 163  
         
 164  5400
         setLayout(new BorderLayout());
 165  5400
         setFont(new Font("Dialog", Font.PLAIN, 10));
 166  5400
         add(topLevelTabbedPane, BorderLayout.CENTER);
 167  
 
 168  5400
         setTarget(null, true);
 169  5400
         topLevelTabbedPane.addMouseListener(this);
 170  5400
         topLevelTabbedPane.addChangeListener(this);
 171  5400
     }
 172  
 
 173  
     /* TODO: Some parts of ArgoUML have preliminary support for multiple
 174  
      * details panels, but we currently only support 
 175  
      * the default South (bottom) panel
 176  
      */
 177  
     private void loadTabs(String direction, Orientation theOrientation) {
 178  5400
         if (Position.South.toString().equalsIgnoreCase(direction)
 179  
                 // Special case for backward compatibility
 180  
                 || "detail".equalsIgnoreCase(direction)) {
 181  
             /* The south panel always has tabs - but they are 
 182  
              * added (later) elsewhere.
 183  
              */
 184  900
             hasTabs = true;
 185  
         } 
 186  5400
     }
 187  
     
 188  
     boolean hasTabs() {
 189  5400
         return hasTabs;
 190  
     }
 191  
 
 192  
     /**
 193  
      * Returns the JTabbedPane that contains all details panels.
 194  
      * @return the JTabbedPane.
 195  
      */
 196  
     JTabbedPane getTabs() {
 197  0
         return topLevelTabbedPane;
 198  
     }
 199  
 
 200  
     /**
 201  
      * @param p the panel to be added 
 202  
      * @param atEnd true = add the panel at the end, 
 203  
      *                  false = at the beginning
 204  
      * @deprecated by Bob Tarling in 0.29.3 use addTab(JPanel, boolean)
 205  
      */
 206  
     @Deprecated
 207  
     public void addTab(AbstractArgoJPanel p, boolean atEnd) {
 208  8100
         Icon icon = p.getIcon();
 209  8100
         String title = Translator.localize(p.getTitle());
 210  8100
         if (atEnd) {
 211  7200
             topLevelTabbedPane.addTab(title, icon, p); 
 212  7200
             tabPanelList.add(p);
 213  
         } else { 
 214  900
             topLevelTabbedPane.insertTab(title, icon, p, null, 0);
 215  900
             tabPanelList.add(0, p);
 216  
         }
 217  
 
 218  8100
     }
 219  
 
 220  
     /**
 221  
      * @param p the panel to be added 
 222  
      * @param atEnd true = add the panel at the end, 
 223  
      *                  false = at the beginning
 224  
      */
 225  
     public void addTab(JPanel p, boolean atEnd) {
 226  
         final Icon icon;
 227  
         final String title;
 228  0
         if (p instanceof AbstractArgoJPanel) {
 229  0
             icon = ((AbstractArgoJPanel) p).getIcon();
 230  0
             title =
 231  
                 Translator.localize(((AbstractArgoJPanel) p).getTitle());
 232  
         } else {
 233  0
             icon = null;
 234  0
             title = p.getName();
 235  
         }
 236  0
         if (atEnd) {
 237  0
             topLevelTabbedPane.addTab(title, icon, p); 
 238  0
             tabPanelList.add(p);
 239  
         } else { 
 240  0
             topLevelTabbedPane.insertTab(title, icon, p, null, 0);
 241  0
             tabPanelList.add(0, p);
 242  
         }
 243  0
     }
 244  
 
 245  
     /**
 246  
      * @param p the panel to be removed
 247  
      */
 248  
     public void removeTab(JPanel p) {
 249  0
         topLevelTabbedPane.remove(p); 
 250  0
         tabPanelList.remove(p);
 251  0
     }
 252  
 
 253  
     /**
 254  
      * Selects the to do tab, and sets the target of that tab.
 255  
      * 
 256  
      * @param item the selected todo item
 257  
      * @return true if todo tab is really selected.
 258  
      * @deprecated for 0.25.5 by tfmorris. Send an event that TabToDoTargets
 259  
      *             listen to.
 260  
      */
 261  
     @Deprecated
 262  
     public boolean setToDoItem(Object item) {
 263  0
         enableTabs(item);
 264  0
         for (JPanel t : tabPanelList) {
 265  0
             if (t instanceof TabToDoTarget) {
 266  0
                 ((TabToDoTarget) t).setTarget(item);
 267  0
                 topLevelTabbedPane.setSelectedComponent(t);
 268  0
                 return true;
 269  
             }
 270  
         }
 271  0
         return false;
 272  
     }
 273  
 
 274  
     /**
 275  
      * Selects the prop tab if it is appropriate for the target.
 276  
      *
 277  
      * @param target
 278  
      *            the target object
 279  
      * @return true if props tab is really selected
 280  
      */
 281  
     private boolean selectPropsTab(Object target) {
 282  900
         if (getTabProps().shouldBeEnabled(target)) {
 283  900
             int indexOfPropPanel = topLevelTabbedPane
 284  
                     .indexOfComponent(getTabProps());
 285  900
             topLevelTabbedPane.setSelectedIndex(indexOfPropPanel);
 286  900
             lastNonNullTab = indexOfPropPanel;
 287  900
             return true;
 288  
         }
 289  0
         return false;
 290  
     }
 291  
 
 292  
     /**
 293  
      * Sets the target of the Details pane to either be a
 294  
      * selected model element or
 295  
      * the owner(model element) of a selected fig.<p>
 296  
      *
 297  
      * Decides which panels to enable.
 298  
      *
 299  
      * @param target the target object
 300  
      */
 301  
     private void setTarget(Object target, boolean defaultToProperties) {
 302  6727
         enableTabs(target);
 303  6727
         if (target != null) {
 304  1201
             boolean tabSelected = false;
 305  
 
 306  
             // Always select properties panel if defaultToProperties is true,
 307  
             // and if properties panel is appropriate for selected perspective
 308  1201
             if (defaultToProperties || lastNonNullTab < 0) {
 309  900
                 tabSelected = selectPropsTab(target);
 310  
             } else {
 311  
                 // Select prop panel if current panel is not appropriate
 312  
                 // for selected target
 313  301
                 Component selectedTab = topLevelTabbedPane
 314  
                         .getComponentAt(lastNonNullTab);
 315  301
                 if (selectedTab instanceof TabTarget) {
 316  301
                     if (((TabTarget) selectedTab).shouldBeEnabled(target)) {
 317  301
                         topLevelTabbedPane.setSelectedIndex(lastNonNullTab);
 318  301
                         tabSelected = true;
 319  
                     } else {
 320  0
                         tabSelected = selectPropsTab(target);
 321  
                     }
 322  
                 }
 323  
             }
 324  1201
             if (!tabSelected) {
 325  0
                 for (int i = lastNonNullTab + 1;
 326  0
                      i < topLevelTabbedPane.getTabCount();
 327  0
                      i++) {
 328  0
                     Component tab = topLevelTabbedPane.getComponentAt(i);
 329  0
                     if (tab instanceof TabTarget) {
 330  0
                         if (((TabTarget) tab).shouldBeEnabled(target)) {
 331  0
                             topLevelTabbedPane.setSelectedIndex(i);
 332  0
                             ((TabTarget) tab).setTarget(target);
 333  0
                             lastNonNullTab = i;
 334  0
                             tabSelected = true;
 335  0
                             break;
 336  
                         }
 337  
                     }
 338  
                 }
 339  
             }
 340  
             // default tab todo
 341  1201
             if (!tabSelected) {
 342  0
                 JPanel tab = tabPanelList.get(0);
 343  0
                 if (!(tab instanceof TabToDoTarget)) {
 344  0
                     for (JPanel panel : tabPanelList) {
 345  0
                         if (panel instanceof TabToDoTarget) {
 346  0
                             tab = panel;
 347  0
                             break;
 348  
                         }
 349  
                     }
 350  
                 }
 351  0
                 if (tab instanceof TabToDoTarget) {
 352  0
                     topLevelTabbedPane.setSelectedComponent(tab);
 353  0
                     ((TabToDoTarget) tab).setTarget(target);
 354  0
                     lastNonNullTab = topLevelTabbedPane.getSelectedIndex();
 355  
                 }
 356  
             }
 357  
 
 358  1201
         } else {
 359  
             // default tab todo
 360  5526
             JPanel tab =
 361  
                 tabPanelList.isEmpty() ? null : (JPanel) tabPanelList.get(0);
 362  5526
             if (!(tab instanceof TabToDoTarget)) {
 363  5400
                 Iterator it = tabPanelList.iterator();
 364  5400
                 while (it.hasNext()) {
 365  0
                     Object o = it.next();
 366  0
                     if (o instanceof TabToDoTarget) {
 367  0
                         tab = (JPanel) o;
 368  0
                         break;
 369  
                     }
 370  0
                 }
 371  
             }
 372  5526
             if (tab instanceof TabToDoTarget) {
 373  126
                 topLevelTabbedPane.setSelectedComponent(tab);
 374  126
                 ((TabToDoTarget) tab).setTarget(target);
 375  
 
 376  
             } else {
 377  5400
                 topLevelTabbedPane.setSelectedIndex(-1);
 378  
             }
 379  
         }
 380  6727
         currentTarget = target;
 381  
 
 382  6727
     }
 383  
 
 384  
     /**
 385  
      * Returns the current model target.
 386  
      * @return the current model target
 387  
      */
 388  
     public Object getTarget() {
 389  0
         return currentTarget;
 390  
     }
 391  
 
 392  
     /*
 393  
      * @see java.awt.Component#getMinimumSize()
 394  
      */
 395  
     @Override
 396  
     public Dimension getMinimumSize() {
 397  0
         return new Dimension(100, 100);
 398  
     }
 399  
 
 400  
 
 401  
     /**
 402  
      * Get the index of the tab with the given name.
 403  
      *
 404  
      * @param tabName the name of the required tab
 405  
      * @return index of the tab of the given name
 406  
      */
 407  
     public int getIndexOfNamedTab(String tabName) {
 408  0
         for (int i = 0; i < tabPanelList.size(); i++) {
 409  0
             String title = topLevelTabbedPane.getTitleAt(i);
 410  0
             if (title != null && title.equals(tabName)) {
 411  0
                 return i;
 412  
             }
 413  
         }
 414  0
         return -1;
 415  
     }
 416  
 
 417  
     /**
 418  
      * Get the number of tabs.
 419  
      *
 420  
      * @return the number of tab pages
 421  
      */
 422  
     public int getTabCount() {
 423  0
         return tabPanelList.size();
 424  
     }
 425  
 
 426  
     /**
 427  
      * Selects a tab by given name.
 428  
      * @param tabName the given name
 429  
      * @return true if the named tab has been found
 430  
      */
 431  
     public boolean selectTabNamed(String tabName) {
 432  0
         int index = getIndexOfNamedTab(tabName);
 433  0
         if (index != -1) {
 434  0
             topLevelTabbedPane.setSelectedIndex(index);
 435  0
             return true;
 436  
         }
 437  0
         return false;
 438  
     }
 439  
 
 440  
     /**
 441  
      * Helper method to add a Property panel for a given class.
 442  
      *
 443  
      * @param c the given class
 444  
      * @param p the given property panel
 445  
      */
 446  
     public void addToPropTab(Class c, PropPanel p) {
 447  0
         for (JPanel panel : tabPanelList) {
 448  0
             if (panel instanceof TabProps) {
 449  0
                 ((TabProps) panel).addPanel(c, p);
 450  
             }
 451  
         }
 452  0
     }
 453  
 
 454  
     /**
 455  
      * returns the Property panel in the Details Pane.
 456  
      *
 457  
      * @return the property panel
 458  
      */
 459  
     public TabProps getTabProps() {
 460  1800
         for (JPanel tab : tabPanelList) {
 461  3600
             if (tab instanceof TabProps) {
 462  1800
                 return (TabProps) tab;
 463  
             }
 464  
         }
 465  0
         return null;
 466  
     }
 467  
 
 468  
     /**
 469  
      * Returns the tab instance of the specified class.
 470  
      *
 471  
      * @param tabClass the given class
 472  
      * @return the tab instance for the given class
 473  
      */
 474  
     public AbstractArgoJPanel getTab(
 475  
             Class< ? extends AbstractArgoJPanel> tabClass) {
 476  0
         for (JPanel tab : tabPanelList) {
 477  0
             if (tab.getClass().equals(tabClass)) {
 478  0
                 return (AbstractArgoJPanel) tab;
 479  
             }
 480  
         }
 481  0
         return null;
 482  
     }
 483  
 
 484  
     /**
 485  
      * Reacts to a change in the selected tab by calling
 486  
      * refresh() for TabToDoTarget's
 487  
      * &
 488  
      * setTarget on a  TabModelTarget or TabFigTarget instance. <p>
 489  
      *
 490  
      * Called when the user selects a new tab, by clicking or
 491  
      * otherwise.
 492  
      *
 493  
      * {@inheritDoc}
 494  
      */
 495  
     public void stateChanged(ChangeEvent e) {
 496  2039
         LOG.debug("DetailsPane state changed");
 497  2039
         Component sel = topLevelTabbedPane.getSelectedComponent();
 498  
         
 499  
         // update the previously selected tab
 500  2039
         if (lastNonNullTab >= 0) {
 501  239
             JPanel tab = tabPanelList.get(lastNonNullTab);
 502  239
             if (tab instanceof TargetListener) {
 503  
                 // not visible any more - so remove as listener
 504  239
                 removeTargetListener((TargetListener) tab);
 505  
             }
 506  
         }
 507  2039
         Object target = TargetManager.getInstance().getSingleTarget();
 508  
         
 509  
         // If sel is the ToDo Tab (i.e. is an instance of TabToDoTarget), we 
 510  
         // don't need to do anything, because the ToDo Tab is already dealt 
 511  
         // with by it's own listener. TabProps is also deals with itself.
 512  
         // TODO: Do we really need this for anything?
 513  2039
         if (!(sel instanceof TabToDoTarget) && !(sel instanceof TabProps)) {
 514  
             // The other tabs need to be updated depending on the selection.
 515  0
             if (sel instanceof TabTarget) {
 516  0
                 ((TabTarget) sel).setTarget(target);
 517  
             }
 518  0
             else if (sel instanceof TargetListener) {
 519  0
                 removeTargetListener((TargetListener) sel);
 520  0
                 addTargetListener((TargetListener) sel);
 521  
                 // Newly selected tab may have stale target info, so generate
 522  
                 // a new set target event for it to refresh it
 523  0
                 ((TargetListener) sel).targetSet(new TargetEvent(this,
 524  
                         TargetEvent.TARGET_SET, new Object[] {},
 525  
                         new Object[] { target }));
 526  
             }
 527  
         }
 528  
         
 529  2039
         if (target != null
 530  
             && Model.getFacade().isAUMLElement(target)
 531  
             && topLevelTabbedPane.getSelectedIndex() > 0) {
 532  0
             lastNonNullTab = topLevelTabbedPane.getSelectedIndex();
 533  
         }
 534  
 
 535  2039
     }
 536  
 
 537  
     /**
 538  
      * no action currently executed here.
 539  
      * called when the user clicks once on a tab.
 540  
      *
 541  
      * @param tab the index of the clicked tab
 542  
      */
 543  
     public void mySingleClick(int tab) {
 544  
         //TODO: should fire its own event and ProjectBrowser
 545  
         //should register a listener
 546  0
         LOG.debug("single: "
 547  
                 + topLevelTabbedPane.getComponentAt(tab).toString());
 548  0
     }
 549  
 
 550  
     /**
 551  
      * Spawns a new tab.
 552  
      * called when the user clicks twice on a tab.
 553  
      *
 554  
      * @param tab the index of the clicked tab
 555  
      */
 556  
     public void myDoubleClick(int tab) {
 557  
         //TODO: should fire its own event and ProjectBrowser
 558  
         //should register a listener
 559  0
         LOG.debug("double: "
 560  
                 + topLevelTabbedPane.getComponentAt(tab).toString());
 561  
 //        JPanel t = (JPanel) tabPanelList.elementAt(tab);
 562  
         // Currently this feature is disabled for ArgoUML.
 563  
 //        if (t instanceof AbstractArgoJPanel)
 564  
 //            ((AbstractArgoJPanel) t).spawn();
 565  0
     }
 566  
 
 567  
     /*
 568  
      * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
 569  
      */
 570  
     public void mousePressed(MouseEvent me) {
 571  
         // empty implementation - we only handle mouseClicked
 572  0
     }
 573  
 
 574  
     /*
 575  
      * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
 576  
      */
 577  
     public void mouseReleased(MouseEvent me) {
 578  
         // empty implementation - we only handle mouseClicked
 579  0
     }
 580  
 
 581  
     /*
 582  
      * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
 583  
      */
 584  
     public void mouseEntered(MouseEvent me) {
 585  
         // empty implementation - we only handle mouseClicked
 586  0
     }
 587  
 
 588  
     /*
 589  
      * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
 590  
      */
 591  
     public void mouseExited(MouseEvent me) {
 592  
         // empty implementation - we only handle mouseClicked
 593  0
     }
 594  
 
 595  
     /*
 596  
      * if(the mouse click is not in the bounds of the tabbed panel)
 597  
      *      then call mySingleClick() or myDoubleClick().
 598  
      *
 599  
      * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
 600  
      */
 601  
     public void mouseClicked(MouseEvent me) {
 602  0
         int tab = topLevelTabbedPane.getSelectedIndex();
 603  0
         if (tab != -1) {
 604  0
             Rectangle tabBounds = topLevelTabbedPane.getBoundsAt(tab);
 605  0
             if (!tabBounds.contains(me.getX(), me.getY())) {
 606  0
                 return;
 607  
             }
 608  0
             if (me.getClickCount() == 1) {
 609  0
                 mySingleClick(tab);
 610  0
             } else if (me.getClickCount() >= 2) {
 611  0
                 myDoubleClick(tab);
 612  
             }
 613  
         }
 614  0
     }
 615  
 
 616  
     /**
 617  
      * Graphic that goes on the tab label.
 618  
      */
 619  5400
     private Icon upArrowIcon = new UpArrowIcon();
 620  
 
 621  
     /**
 622  
      * Graphic that goes on the tab label.
 623  
      */
 624  5400
     private Icon leftArrowIcon = new LeftArrowIcon();
 625  
 
 626  
     /*
 627  
      * @see org.tigris.swidgets.Orientable#setOrientation(org.tigris.swidgets.Orientation)
 628  
      */
 629  
     public void setOrientation(Orientation newOrientation) {
 630  6300
         for (JPanel t : tabPanelList) {
 631  0
             if (t instanceof Orientable) {
 632  0
                 Orientable o = (Orientable) t;
 633  0
                 o.setOrientation(newOrientation);
 634  0
             }
 635  
         }
 636  6300
     }
 637  
 
 638  
     /*
 639  
      * @see TargetListener#targetAdded(TargetEvent)
 640  
      */
 641  
     public void targetAdded(TargetEvent e) {
 642  0
         setTarget(e.getNewTarget(), false);
 643  0
         fireTargetAdded(e);
 644  0
     }
 645  
 
 646  
     /*
 647  
      * @see TargetListener#targetRemoved(TargetEvent)
 648  
      */
 649  
     public void targetRemoved(TargetEvent e) {
 650  88
         setTarget(e.getNewTarget(), false);
 651  88
         fireTargetRemoved(e);
 652  88
     }
 653  
 
 654  
     /*
 655  
      * @see TargetListener#targetSet(TargetEvent)
 656  
      */
 657  
     public void targetSet(TargetEvent e) {
 658  1239
         setTarget(e.getNewTarget(), false);
 659  1239
         fireTargetSet(e);
 660  1239
     }
 661  
 
 662  
     /**
 663  
      * Enables/disables the tabs on the tabbed card. Also selects the tab to
 664  
      * show.
 665  
      *
 666  
      * @param target the target object
 667  
      */
 668  
     private void enableTabs(Object target) {
 669  
 
 670  
         // TODO: Quick return here for target == null? - tfm
 671  
         
 672  
         // iterate through the tabbed panels to determine whether they
 673  
         // should be enabled.
 674  18670
         for (int i = 0; i < tabPanelList.size(); i++) {
 675  11943
             JPanel tab = tabPanelList.get(i);
 676  11943
             boolean shouldEnable = false;
 677  11943
             if (tab instanceof TargetListener) {
 678  11943
                 if (tab instanceof TabTarget) {
 679  10616
                     shouldEnable = ((TabTarget) tab).shouldBeEnabled(target);
 680  
                 } else {
 681  1327
                     if (tab instanceof TabToDoTarget) {
 682  1327
                         shouldEnable = true;
 683  
                     }
 684  
                 }
 685  
                 // TODO: Do we want all enabled tabs to listen or only the one
 686  
                 // that is selected/visible? - tfm
 687  11943
                 removeTargetListener((TargetListener) tab);
 688  11943
                 if (shouldEnable) {
 689  2528
                     addTargetListener((TargetListener) tab);
 690  
                 }
 691  
 
 692  11943
                 topLevelTabbedPane.setEnabledAt(i, shouldEnable);
 693  
             }
 694  
         }
 695  6727
     }
 696  
 
 697  
     private void fireTargetSet(TargetEvent targetEvent) {
 698  
         //          Guaranteed to return a non-null array
 699  1239
         Object[] listeners = listenerList.getListenerList();
 700  3566
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 701  2327
             if (listeners[i] == TargetListener.class) {
 702  
                 // Lazily create the event:
 703  2327
                 ((TargetListener) listeners[i + 1]).targetSet(targetEvent);
 704  
             }
 705  
         }
 706  1239
     }
 707  
 
 708  
     private void fireTargetAdded(TargetEvent targetEvent) {
 709  
         // Guaranteed to return a non-null array
 710  0
         Object[] listeners = listenerList.getListenerList();
 711  
 
 712  0
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 713  0
             if (listeners[i] == TargetListener.class) {
 714  
                 // Lazily create the event:
 715  0
                 ((TargetListener) listeners[i + 1]).targetAdded(targetEvent);
 716  
             }
 717  
         }
 718  0
     }
 719  
 
 720  
     private void fireTargetRemoved(TargetEvent targetEvent) {
 721  
         // Guaranteed to return a non-null array
 722  88
         Object[] listeners = listenerList.getListenerList();
 723  176
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 724  88
             if (listeners[i] == TargetListener.class) {
 725  
                 // Lazily create the event:
 726  88
                 ((TargetListener) listeners[i + 1]).targetRemoved(targetEvent);
 727  
             }
 728  
         }
 729  88
     }
 730  
 
 731  
 }