Coverage Report - org.argouml.uml.ui.PropPanel
 
Classes in this File Line Coverage Branch Coverage Complexity
PropPanel
62%
115/183
51%
41/80
2.022
PropPanel$GroupPanel
0%
0/10
0%
0/2
2.022
PropPanel$TargettableButton
0%
0/5
0%
0/2
2.022
 
 1  
 /* $Id: PropPanel.java 19036 2011-02-13 18:17:19Z 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  
  *    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.uml.ui;
 40  
 
 41  
 import java.awt.BorderLayout;
 42  
 import java.awt.Component;
 43  
 import java.awt.Container;
 44  
 import java.awt.Dimension;
 45  
 import java.awt.Font;
 46  
 import java.awt.GridLayout;
 47  
 import java.awt.event.ComponentEvent;
 48  
 import java.awt.event.ComponentListener;
 49  
 import java.util.ArrayList;
 50  
 import java.util.Collection;
 51  
 import java.util.HashSet;
 52  
 import java.util.Iterator;
 53  
 import java.util.List;
 54  
 
 55  
 import javax.swing.Action;
 56  
 import javax.swing.Icon;
 57  
 import javax.swing.ImageIcon;
 58  
 import javax.swing.JButton;
 59  
 import javax.swing.JLabel;
 60  
 import javax.swing.JPanel;
 61  
 import javax.swing.JToolBar;
 62  
 import javax.swing.ListModel;
 63  
 import javax.swing.SwingConstants;
 64  
 import javax.swing.SwingUtilities;
 65  
 import javax.swing.border.TitledBorder;
 66  
 import javax.swing.event.EventListenerList;
 67  
 
 68  
 import org.apache.log4j.Logger;
 69  
 import org.argouml.application.api.AbstractArgoJPanel;
 70  
 import org.argouml.application.helpers.ResourceLoaderWrapper;
 71  
 import org.argouml.i18n.Translator;
 72  
 import org.argouml.kernel.ProfileConfiguration;
 73  
 import org.argouml.kernel.ProjectManager;
 74  
 import org.argouml.model.Model;
 75  
 import org.argouml.ui.ActionCreateContainedModelElement;
 76  
 import org.argouml.ui.LookAndFeelMgr;
 77  
 import org.argouml.ui.targetmanager.TargetEvent;
 78  
 import org.argouml.ui.targetmanager.TargetListener;
 79  
 import org.argouml.ui.targetmanager.TargettableModelView;
 80  
 import org.tigris.gef.presentation.Fig;
 81  
 import org.tigris.swidgets.GridLayout2;
 82  
 import org.tigris.swidgets.Orientation;
 83  
 import org.tigris.toolbar.ToolBarFactory;
 84  
 
 85  
 /**
 86  
  * This abstract class provides the basic layout and event dispatching support
 87  
  * for all Property Panels.<p>
 88  
  *
 89  
  * The property panel is {@link org.argouml.uml.ui.LabelledLayout} layed out as
 90  
  * a number (specified in the constructor) of equally sized panels that split
 91  
  * the available space. Each panel has a column of "captions" and matching
 92  
  * column of "fields" which are laid out independently from the other
 93  
  * panels.<p>
 94  
  *
 95  
  * The Properties panels for UML Model Elements are structured in an inheritance
 96  
  * hierarchy that matches the UML metamodel.
 97  
  */
 98  0
 public abstract class PropPanel extends AbstractArgoJPanel implements
 99  
         UMLUserInterfaceContainer, ComponentListener {
 100  
 
 101  
     /**
 102  
      * Logger.
 103  
      */
 104  900
     private static final Logger LOG = Logger.getLogger(PropPanel.class);
 105  
 
 106  
     private Object target;
 107  
 
 108  
     private Object modelElement;
 109  
 
 110  
     /**
 111  
      * List of event listeners to notify. This is computed one time and frozen
 112  
      * the first time any target change method (e.g. setTarget, targetAdded) is
 113  
      * called.
 114  
      */
 115  
     private EventListenerList listenerList;
 116  
 
 117  4089
     private JPanel buttonPanel = new JPanel(new GridLayout());
 118  
 
 119  
     private JLabel titleLabel;
 120  
 
 121  
     /**
 122  
      * A list with "actions".<p>
 123  
      *
 124  
      * Action in this respect are one of:<ul>
 125  
      * <li> {@link Action}
 126  
      * <li> {@link JButton}
 127  
      * <li> {@link Object}[]
 128  
      * </ul>
 129  
      */
 130  4089
     private List actions = new ArrayList();
 131  
 
 132  900
     private static Font stdFont =
 133  
         LookAndFeelMgr.getInstance().getStandardFont();
 134  
 
 135  
     /**
 136  
      * Construct new PropPanel using LabelledLayout.
 137  
      * <p>
 138  
      * @param icon The icon to display for the panel
 139  
      * @param label The label for the title of the panel (to be localized).
 140  
      */
 141  
     public PropPanel(String label, ImageIcon icon) {
 142  4089
         super(Translator.localize(label));
 143  
 
 144  4089
         LabelledLayout layout = new LabelledLayout();
 145  4089
         layout.setHgap(5);
 146  4089
         setLayout(layout);
 147  
 
 148  4089
         if (icon != null) {
 149  2289
             setTitleLabel(new JLabel(Translator.localize(label), icon,
 150  
                     SwingConstants.LEFT));
 151  
         } else {
 152  1800
             setTitleLabel(new JLabel(Translator.localize(label)));
 153  
         }
 154  4089
         titleLabel.setLabelFor(buttonPanel);
 155  4089
         add(titleLabel);
 156  4089
         add(buttonPanel);
 157  
         
 158  4089
         addComponentListener(this);
 159  4089
     }
 160  
 
 161  
 
 162  
     /*
 163  
      * @see org.tigris.swidgets.Orientable#setOrientation(org.tigris.swidgets.Orientation)
 164  
      */
 165  
     @Override
 166  
     public void setOrientation(Orientation orientation) {
 167  
         // TODO: Do we need to change the layout manager when
 168  
         // changing orientation to match the behavior of the constructor?
 169  
 //        if (getOrientation() != orientation) {
 170  
 //            LabelledLayout layout = new LabelledLayout(orientation == Vertical
 171  
 //                    .getInstance());
 172  
 //            setLayout(layout);
 173  
 //        } 
 174  1800
         super.setOrientation(orientation);
 175  1800
     }
 176  
 
 177  
     /**
 178  
      * Add a button to the toolbar of a property panel using the action to
 179  
      * control the behavior of the action.
 180  
      *
 181  
      * @param action
 182  
      *            the action which will be used in the toolbar button.
 183  
      */
 184  
     protected void addAction(Action action) {
 185  4578
         actions.add(action);
 186  4578
     }
 187  
 
 188  
     /**
 189  
      * Add a button to the toolbar of a property panel using the action to
 190  
      * control the behavior of the action.
 191  
      *
 192  
      * @param action
 193  
      *            the action which will be used in the toolbar button.
 194  
      * @param tooltip
 195  
      *            the tooltip to set, or null to skip setting of a new tooltip.
 196  
      */
 197  
     protected void addAction(Action action, String tooltip) {
 198  0
         JButton button = new TargettableButton(action);
 199  0
         if (tooltip != null) {
 200  0
             button.setToolTipText(tooltip);
 201  
         }
 202  0
         button.setText("");
 203  0
         button.setFocusable(false);
 204  0
         actions.add(button);
 205  0
     }
 206  
 
 207  
     /**
 208  
      * Add multiple buttons at once.
 209  
      *
 210  
      * @param actionArray the Actions.
 211  
      */
 212  
     protected void addAction(Object[] actionArray) {
 213  0
         actions.add(actionArray);
 214  0
     }
 215  
     
 216  
     public void buildToolbar() {
 217  3208
         LOG.debug("Building toolbar");
 218  
 
 219  3208
         ToolBarFactory factory = new ToolBarFactory(getActions());
 220  3208
         factory.setRollover(true);
 221  3208
         factory.setFloatable(false);
 222  3208
         JToolBar toolBar = factory.createToolBar();
 223  3208
         toolBar.setName("misc.toolbar.properties");
 224  
 
 225  3208
         buttonPanel.removeAll();
 226  3208
         buttonPanel.add(BorderLayout.WEST, toolBar);
 227  
         // Set the tooltip of the arrow to open combined tools:
 228  3208
         buttonPanel.putClientProperty("ToolBar.toolTipSelectTool",
 229  
                 Translator.localize("action.select"));
 230  3208
     }
 231  
 
 232  
     /**
 233  
      * Get the actions that will make up the toolbar on this panel.
 234  
      * @return The list of actions to show for this panel.
 235  
      */
 236  
     protected List getActions() {
 237  3208
         return actions;
 238  
     }
 239  
 
 240  
     private static class TargettableButton extends JButton
 241  
         implements TargettableModelView {
 242  
 
 243  
         public TargettableButton(Action action) {
 244  0
             super(action);
 245  0
         }
 246  
 
 247  
         public TargetListener getTargettableModel() {
 248  0
             if (getAction() instanceof TargetListener) {
 249  0
                 return (TargetListener) getAction();
 250  
             }
 251  0
             return null;
 252  
         }
 253  
 
 254  
     }
 255  
 
 256  
     /**
 257  
      * Add a component with the specified label.<p>
 258  
      *
 259  
      * @param label
 260  
      *            the label for the component
 261  
      * @param component
 262  
      *            the component
 263  
      * @return the label added
 264  
      */
 265  
     public JLabel addField(String label, Component component) {
 266  11778
         JLabel jlabel = createLabelFor(label, component);
 267  11778
         component.setFont(stdFont);
 268  11778
         add(jlabel);
 269  11778
         add(component);
 270  11778
         if (component instanceof UMLStereotypeList) {
 271  0
             UMLModelElementListModel2 list =
 272  
                 (UMLModelElementListModel2) ((UMLStereotypeList) component).getModel();
 273  0
             ActionCreateContainedModelElement newAction =
 274  
                 new ActionCreateContainedModelElement(
 275  
                         list.getMetaType(),
 276  
                         list.getTarget(),
 277  
                         "New..."); // TODO: i18n
 278  
         }
 279  11778
         return jlabel;
 280  
     }
 281  
 
 282  
     /** 
 283  
      * @param label The text of the label (the method cares about i18n)
 284  
      * @param comp The component that this label is for
 285  
      * @return a new JLabel
 286  
      */
 287  
     private JLabel createLabelFor(String label, Component comp) {
 288  11778
         JLabel jlabel = new JLabel(Translator.localize(label));
 289  11778
         jlabel.setToolTipText(Translator.localize(label));
 290  11778
         jlabel.setFont(stdFont);
 291  11778
         jlabel.setLabelFor(comp);
 292  11778
         return jlabel;
 293  
     }
 294  
 
 295  
     /**
 296  
      * Add a component with the specified label positioned after another
 297  
      * component.
 298  
      *
 299  
      * @param label
 300  
      *            the label for the component
 301  
      * @param component
 302  
      *            the component
 303  
      * @param afterComponent
 304  
      *            the component before
 305  
      * @return the newly added label
 306  
      */
 307  
     public JLabel addFieldAfter(String label, Component component,
 308  
             Component afterComponent) {
 309  0
         int nComponent = getComponentCount();
 310  0
         for (int i = 0; i < nComponent; ++i) {
 311  0
             if (getComponent(i) == afterComponent) {
 312  0
                 JLabel jlabel = createLabelFor(label, component);
 313  0
                 component.setFont(stdFont);
 314  0
                 add(jlabel, ++i);
 315  0
                 add(component, ++i);
 316  0
                 return jlabel;
 317  
             }
 318  
         }
 319  0
         throw new IllegalArgumentException("Component not found");
 320  
     }
 321  
 
 322  
     /**
 323  
      * Add a component with the specified label positioned before another
 324  
      * component.<p>
 325  
      *
 326  
      * @param label
 327  
      *            the label for the component
 328  
      * @param component
 329  
      *            the to be added component
 330  
      * @param beforeComponent
 331  
      *            the component before its label we add
 332  
      * @return the newly added component
 333  
      */
 334  
     public JLabel addFieldBefore(String label, Component component,
 335  
             Component beforeComponent) {
 336  0
         int nComponent = getComponentCount();
 337  0
         for (int i = 0; i < nComponent; ++i) {
 338  0
             if (getComponent(i) == beforeComponent) {
 339  0
                 JLabel jlabel = createLabelFor(label, component);
 340  0
                 component.setFont(stdFont);
 341  0
                 add(jlabel, i - 1);
 342  0
                 add(component, i++);
 343  0
                 return jlabel;
 344  
             }
 345  
         }
 346  0
         throw new IllegalArgumentException("Component not found");
 347  
     }
 348  
 
 349  
     /**
 350  
      * Add a separator.
 351  
      */
 352  
     protected final void addSeparator() {
 353  0
         add(LabelledLayout.getSeparator());
 354  0
     }
 355  
 
 356  
     /**
 357  
      * Set the target to be associated with a particular property panel.<p>
 358  
      *
 359  
      * This involves resetting the third party listeners.
 360  
      *
 361  
      * @param t
 362  
      *            The object to be set as a target.
 363  
      */
 364  
     public void setTarget(Object t) {
 365  4723
         LOG.debug("setTarget called with " + t + " as parameter (not target!)");
 366  4723
         t = (t instanceof Fig) ? ((Fig) t).getOwner() : t;
 367  
 
 368  
         // If the target has changed notify the third party listener if it
 369  
         // exists and dispatch a new element event listener to
 370  
         // ourself. Otherwise dispatch a target reasserted to ourself.
 371  4723
         Runnable dispatch = null;
 372  4723
         if (t != target) {
 373  
 
 374  
             // Set up the target and its model element variant.
 375  
 
 376  3208
             target = t;
 377  3208
             modelElement = null;
 378  3208
             if (listenerList == null) {
 379  2289
                 listenerList = collectTargetListeners(this);
 380  
             }
 381  
 
 382  3208
             if (Model.getFacade().isAUMLElement(target)) {
 383  0
                 modelElement = target;
 384  
             }
 385  
 
 386  
             // This will add a new ModelElement event listener
 387  
             // after update is complete
 388  
 
 389  3208
             dispatch = new UMLChangeDispatch(this,
 390  
                     UMLChangeDispatch.TARGET_CHANGED_ADD);
 391  
 
 392  3208
             buildToolbar();
 393  
         } else {
 394  1515
             dispatch = new UMLChangeDispatch(this,
 395  
                     UMLChangeDispatch.TARGET_REASSERTED);
 396  
 
 397  
         }
 398  4723
         SwingUtilities.invokeLater(dispatch);
 399  
 
 400  
         // update the titleLabel
 401  
         // MVW: This overrules the icon set initiallly... Why do we need this?
 402  4723
         if (titleLabel != null) {
 403  4723
             Icon icon = null;
 404  4723
             if (t != null) {
 405  4464
                 icon = ResourceLoaderWrapper.getInstance().lookupIcon(t);
 406  
             }
 407  4723
             if (icon != null) {
 408  4464
                 titleLabel.setIcon(icon);
 409  
             }
 410  
         }
 411  4723
     }
 412  
 
 413  
     /**
 414  
      * Builds a eventlistenerlist of all targetlisteners that are part of this
 415  
      * container and its children. Components do not need to register
 416  
      * themselves. They are registered implicitly if they implement the
 417  
      * TargetListener interface.
 418  
      * 
 419  
      * @param container
 420  
      *            the container to search for targetlisteners
 421  
      * @return an EventListenerList with all TargetListeners on this container
 422  
      *         and its children.
 423  
      */
 424  
     private EventListenerList collectTargetListeners(Container container) {
 425  32046
         Component[] components = container.getComponents();
 426  32046
         EventListenerList list = new EventListenerList();
 427  61803
         for (int i = 0; i < components.length; i++) {
 428  29757
             if (components[i] instanceof TargetListener) {
 429  2289
                 list.add(TargetListener.class, (TargetListener) components[i]);
 430  
             }
 431  29757
             if (components[i] instanceof TargettableModelView) {
 432  2289
                 list.add(TargetListener.class,
 433  
                         ((TargettableModelView) components[i])
 434  
                                 .getTargettableModel());
 435  
             }
 436  29757
             if (components[i] instanceof Container) {
 437  29757
                 EventListenerList list2 = collectTargetListeners(
 438  
                                                 (Container) components[i]);
 439  29757
                 Object[] objects = list2.getListenerList();
 440  34335
                 for (int j = 1; j < objects.length; j += 2) {
 441  4578
                     list.add(TargetListener.class, (TargetListener) objects[j]);
 442  
                 }
 443  
             }
 444  
         }
 445  32046
         if (container instanceof PropPanel) {
 446  
             /* We presume that the container equals this PropPanel. */
 447  2289
             for (TargetListener action : collectTargetListenerActions()) {
 448  2289
                 list.add(TargetListener.class, action);
 449  
             }
 450  
         }
 451  32046
         return list;
 452  
     }
 453  
 
 454  
     private Collection<TargetListener> collectTargetListenerActions() {
 455  2289
         Collection<TargetListener> set = new HashSet<TargetListener>();
 456  2289
         for (Object obj : actions) {
 457  4578
             if (obj instanceof TargetListener) {
 458  2289
                 set.add((TargetListener) obj);
 459  
             }
 460  
         }
 461  2289
         return set;
 462  
     }
 463  
 
 464  
     /*
 465  
      * @see org.argouml.ui.TabTarget#getTarget()
 466  
      */
 467  
     public final Object getTarget() {
 468  4723
         return target;
 469  
     }
 470  
 
 471  
     /*
 472  
      * @see org.argouml.ui.TabTarget#refresh()
 473  
      */
 474  
     public void refresh() {
 475  0
         SwingUtilities.invokeLater(new UMLChangeDispatch(this, 0));
 476  0
     }
 477  
 
 478  
     /*
 479  
      * @see org.argouml.ui.TabTarget#shouldBeEnabled(java.lang.Object)
 480  
      */
 481  
     public boolean shouldBeEnabled(Object t) {
 482  0
         t = (t instanceof Fig) ? ((Fig) t).getOwner() : t;
 483  0
         return Model.getFacade().isAUMLElement(t);
 484  
     }
 485  
 
 486  
     /**
 487  
      * This method can be overridden in derived Panels where the appropriate
 488  
      * namespace for display may not be the same as the namespace of the target.
 489  
      *
 490  
      * @return the namespace
 491  
      */
 492  
     protected Object getDisplayNamespace() {
 493  0
         Object ns = null;
 494  0
         Object theTarget = getTarget();
 495  0
         if (Model.getFacade().isAModelElement(theTarget)) {
 496  0
             ns = Model.getFacade().getNamespace(theTarget);
 497  
         }
 498  0
         return ns;
 499  
     }
 500  
 
 501  
     /*
 502  
      * @see org.argouml.uml.ui.UMLUserInterfaceContainer#getProfile()
 503  
      */
 504  
     public ProfileConfiguration getProfile() {
 505  0
         return ProjectManager.getManager().getCurrentProject()
 506  
                 .getProfileConfiguration();
 507  
     }
 508  
 
 509  
     /*
 510  
      * @see org.argouml.uml.ui.UMLUserInterfaceContainer#getModelElement()
 511  
      */
 512  
     public final Object getModelElement() {
 513  0
         return modelElement;
 514  
     }
 515  
 
 516  
     /*
 517  
      * @see org.argouml.uml.ui.UMLUserInterfaceContainer#formatElement(java.lang.Object)
 518  
      */
 519  
     public String formatElement(Object element) {
 520  0
         return getProfile().getFormatingStrategy().formatElement(element,
 521  
                 getDisplayNamespace());
 522  
     }
 523  
 
 524  
     /*
 525  
      * @see org.argouml.uml.ui.UMLUserInterfaceContainer#formatNamespace(java.lang.Object)
 526  
      */
 527  
     public String formatNamespace(Object namespace) {
 528  0
         return getProfile().getFormatingStrategy().formatElement(namespace,
 529  
                 null);
 530  
     }
 531  
 
 532  
     /*
 533  
      * @see org.argouml.uml.ui.UMLUserInterfaceContainer#formatCollection(java.util.Iterator)
 534  
      */
 535  
     public String formatCollection(Iterator iter) {
 536  0
         Object namespace = getDisplayNamespace();
 537  0
         return getProfile().getFormatingStrategy().formatCollection(iter,
 538  
                 namespace);
 539  
     }
 540  
 
 541  
 
 542  
     /**
 543  
      * Get the delete action.
 544  
      *
 545  
      * @return the delete action
 546  
      */
 547  
     protected final Action getDeleteAction() {
 548  0
         return ActionDeleteModelElements.getTargetFollower();
 549  
     }
 550  
 
 551  
     /**
 552  
      * Check whether this element can be deleted. Currently it only checks
 553  
      * whether we delete the main model. ArgoUML does not like that.
 554  
      *
 555  
      * @since 0.13.2
 556  
      * @return whether this element can be deleted
 557  
      */
 558  
     public boolean isRemovableElement() {
 559  0
         return ((getTarget() != null) && (getTarget() != (ProjectManager
 560  
                 .getManager().getCurrentProject().getModel())));
 561  
     }
 562  
 
 563  
     /*
 564  
      * @see TargetListener#targetAdded(TargetEvent)
 565  
      */
 566  
     public void targetAdded(TargetEvent e) {
 567  0
         if (listenerList == null) {
 568  0
             listenerList = collectTargetListeners(this);
 569  
         }
 570  0
         setTarget(e.getNewTarget());
 571  0
         if (isVisible()) {
 572  0
             fireTargetAdded(e);
 573  
         }
 574  0
     }
 575  
 
 576  
     /*
 577  
      * @see TargetListener#targetRemoved(TargetEvent)
 578  
      */
 579  
     public void targetRemoved(TargetEvent e) {
 580  176
         setTarget(e.getNewTarget());
 581  176
         if (isVisible()) {
 582  176
             fireTargetRemoved(e);
 583  
         }
 584  176
     }
 585  
 
 586  
     /*
 587  
      * @see TargetListener#targetSet(TargetEvent)
 588  
      */
 589  
     public void targetSet(TargetEvent e) {
 590  4547
         setTarget(e.getNewTarget());
 591  4547
         if (isVisible()) {
 592  4547
             fireTargetSet(e);
 593  
         }
 594  4547
     }
 595  
 
 596  
     private void fireTargetSet(TargetEvent targetEvent) {
 597  4547
         if (listenerList == null) {
 598  0
             listenerList = collectTargetListeners(this);
 599  
         }
 600  
         // Guaranteed to return a non-null array
 601  4547
         Object[] listeners = listenerList.getListenerList();
 602  18188
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 603  13641
             if (listeners[i] == TargetListener.class) {
 604  13641
                 ((TargetListener) listeners[i + 1]).targetSet(targetEvent);
 605  
             }
 606  
         }
 607  4547
     }
 608  
 
 609  
     private void fireTargetAdded(TargetEvent targetEvent) {
 610  0
         if (listenerList == null) {
 611  0
             listenerList = collectTargetListeners(this);
 612  
         }
 613  
         // Guaranteed to return a non-null array
 614  0
         Object[] listeners = listenerList.getListenerList();
 615  
 
 616  0
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 617  0
             if (listeners[i] == TargetListener.class) {
 618  0
                 ((TargetListener) listeners[i + 1]).targetAdded(targetEvent);
 619  
             }
 620  
         }
 621  0
     }
 622  
 
 623  
     private void fireTargetRemoved(TargetEvent targetEvent) {
 624  176
         if (listenerList == null) {
 625  0
             listenerList = collectTargetListeners(this);
 626  
         }
 627  
         // Guaranteed to return a non-null array
 628  176
         Object[] listeners = listenerList.getListenerList();
 629  704
         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 630  528
             if (listeners[i] == TargetListener.class) {
 631  528
                 ((TargetListener) listeners[i + 1]).targetRemoved(targetEvent);
 632  
             }
 633  
         }
 634  176
     }
 635  
 
 636  
     /**
 637  
      * @param theTitleLabel
 638  
      *            the title of the panel shown at the top
 639  
      */
 640  
     protected void setTitleLabel(JLabel theTitleLabel) {
 641  4089
         titleLabel = theTitleLabel;
 642  4089
         titleLabel.setFont(stdFont);
 643  4089
     }
 644  
 
 645  
     /**
 646  
      * @return the title of the panel shown at the top
 647  
      */
 648  
     protected JLabel getTitleLabel() {
 649  900
         return titleLabel;
 650  
     }
 651  
 
 652  
     protected final JPanel createBorderPanel(String title) {
 653  0
             return new GroupPanel(Translator.localize(title));
 654  
     }
 655  
     
 656  
     private class GroupPanel extends JPanel {
 657  
         
 658  0
         public GroupPanel(String title) {
 659  0
             super(new GridLayout2());
 660  0
             TitledBorder border = new TitledBorder(Translator.localize(title));
 661  0
             border.setTitleFont(stdFont);
 662  0
             setBorder(border);
 663  0
         }
 664  
         
 665  
         public void setEnabled(boolean enabled) {
 666  0
             super.setEnabled(enabled);
 667  0
             for (final Component component : getComponents()) {
 668  0
                 component.setEnabled(enabled);
 669  
             }
 670  0
         }
 671  
     }
 672  
 
 673  
     /**
 674  
      * If there are no buttons to show in the toolbar,
 675  
      * then set the height to e.g. 18, so that the title
 676  
      * is aligned right by the LabelledLayout.
 677  
      *
 678  
      * @param height the height
 679  
      */
 680  
     protected void setButtonPanelSize(int height) {
 681  
         /* Set the minimum and preferred equal,
 682  
          * so that the size is fixed for the labelledlayout.
 683  
          */
 684  900
         buttonPanel.setMinimumSize(new Dimension(0, height));
 685  900
         buttonPanel.setPreferredSize(new Dimension(0, height));
 686  900
     }
 687  
 
 688  
     /**
 689  
      * Look up an icon.
 690  
      *
 691  
      * @param name
 692  
      *            the resource name.
 693  
      * @return an ImageIcon corresponding to the given resource name
 694  
      */
 695  
     protected static ImageIcon lookupIcon(String name) {
 696  2289
         return ResourceLoaderWrapper.lookupIconResource(name);
 697  
     }
 698  
 
 699  
 
 700  
     /*
 701  
      * @see java.awt.event.ComponentListener#componentHidden(java.awt.event.ComponentEvent)
 702  
      */
 703  
     public void componentHidden(ComponentEvent e) {
 704  
         // TODO: do we want to fire targetRemoved here or is it enough to just
 705  
         // stop updating the targets?
 706  1800
     }
 707  
     
 708  
     /*
 709  
      * @see java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent)
 710  
      */
 711  
     public void componentShown(ComponentEvent e) {
 712  
         // Refresh the target for all our children which weren't getting
 713  
         // while not visible
 714  0
         fireTargetSet(new TargetEvent(
 715  
                 this, TargetEvent.TARGET_SET, null, new Object[] {target}));
 716  0
     }
 717  
     
 718  
     /*
 719  
      * @see java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent)
 720  
      */
 721  
     public void componentMoved(ComponentEvent e) {
 722  
         // ignored
 723  1800
     }
 724  
 
 725  
     /*
 726  
      * @see java.awt.event.ComponentListener#componentResized(java.awt.event.ComponentEvent)
 727  
      */
 728  
     public void componentResized(ComponentEvent e) {
 729  
         // ignored        
 730  3000
     }
 731  
 }