Coverage Report - org.argouml.ui.MultiEditorPane
 
Classes in this File Line Coverage Branch Coverage Complexity
MultiEditorPane
44%
42/95
23%
9/38
2.05
 
 1  
 /* $Id: MultiEditorPane.java 17841 2010-01-12 19:17:52Z linus $
 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  
  *    dthompson
 11  
  *****************************************************************************
 12  
  *
 13  
  * Some portions of this file was previously release using the BSD License:
 14  
  */
 15  
 
 16  
 // Copyright (c) 1996-2007 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.Rectangle;
 45  
 import java.awt.event.MouseEvent;
 46  
 import java.awt.event.MouseListener;
 47  
 import java.util.ArrayList;
 48  
 import java.util.Arrays;
 49  
 import java.util.List;
 50  
 
 51  
 import javax.swing.JPanel;
 52  
 import javax.swing.JTabbedPane;
 53  
 import javax.swing.SwingConstants;
 54  
 import javax.swing.event.ChangeEvent;
 55  
 import javax.swing.event.ChangeListener;
 56  
 
 57  
 import org.apache.log4j.Logger;
 58  
 import org.argouml.application.api.AbstractArgoJPanel;
 59  
 import org.argouml.ui.targetmanager.TargetEvent;
 60  
 import org.argouml.ui.targetmanager.TargetListener;
 61  
 import org.argouml.ui.targetmanager.TargetManager;
 62  
 import org.argouml.uml.diagram.ui.ModeLabelDragFactory;
 63  
 import org.argouml.uml.diagram.ui.TabDiagram;
 64  
 import org.tigris.gef.base.Globals;
 65  
 import org.tigris.gef.base.ModeDragScrollFactory;
 66  
 import org.tigris.gef.base.ModeFactory;
 67  
 import org.tigris.gef.base.ModePopupFactory;
 68  
 import org.tigris.gef.base.ModeSelectFactory;
 69  
 
 70  
 /**
 71  
  * The upper right pane in the ArgoUML user interface.  It may have several
 72  
  * tabs with different kinds of "major" editors that allow the user to
 73  
  * edit whatever is selected in the ExplorerPane. <p>
 74  
  * Currently, there is only the Diagram tab.
 75  
  */
 76  
 public class MultiEditorPane
 77  
     extends JPanel
 78  
     implements ChangeListener, MouseListener, TargetListener {
 79  
 
 80  
     {
 81  
         // I hate this so much even before I start writing it.
 82  
         // Re-initialising a global in a place where no-one will see it just
 83  
         // feels wrong.  Oh well, here goes.
 84  900
         ArrayList<ModeFactory> modeFactories = new ArrayList<ModeFactory>();
 85  900
         modeFactories.add(new ModeLabelDragFactory());
 86  900
         modeFactories.add(new ModeSelectFactory());
 87  900
         modeFactories.add(new ModePopupFactory());
 88  900
         modeFactories.add(new ModeDragScrollFactory()); 
 89  900
         Globals.setDefaultModeFactories(modeFactories);
 90  
     }
 91  
     
 92  
     /** logger */
 93  900
     private static final Logger LOG = Logger.getLogger(MultiEditorPane.class);
 94  
         
 95  
     /**
 96  
      * Classes for tabs to be included in the property panel.
 97  
      * (previously stored in org/argouml/argo.ini)
 98  
      */
 99  900
     private final JPanel[] tabInstances = new JPanel[] {
 100  
         new TabDiagram(),
 101  
         // org.argouml.ui.TabTable
 102  
         // TabMetrics
 103  
         // TabJavaSrc | TabSrc
 104  
         // TabUMLDisplay
 105  
         // TabHash
 106  
     };
 107  
 
 108  900
     private JTabbedPane tabs = new JTabbedPane(SwingConstants.BOTTOM);
 109  
 
 110  900
     private List<JPanel> tabPanels = 
 111  
         new ArrayList<JPanel>(Arrays.asList(tabInstances));
 112  
     
 113  
     private Component lastTab;
 114  
 
 115  
     /**
 116  
      * Constructs the MultiEditorPane. This is the pane in which the tabs with
 117  
      * the diagrams are drawn in ArgoUML. The MultiEditorPane is a JTabbedPane
 118  
      * that holds 0-* JPanels that can show several editors but only show one
 119  
      * editor at the moment (argouml version 0.13.3). With this editor diagrams
 120  
      * can be edited.
 121  
      */
 122  900
     public MultiEditorPane() {
 123  900
         LOG.info("making MultiEditorPane");
 124  
 
 125  900
         setLayout(new BorderLayout());
 126  900
         add(tabs, BorderLayout.CENTER);
 127  
 
 128  1800
         for (int i = 0; i < tabPanels.size(); i++) {
 129  900
             String title = "tab";
 130  900
             JPanel t = tabPanels.get(i);
 131  900
             if (t instanceof AbstractArgoJPanel) {
 132  900
                 title = ((AbstractArgoJPanel) t).getTitle();
 133  
             }
 134  
             // TODO: I18N
 135  900
             tabs.addTab("As " + title, t);
 136  900
             tabs.setEnabledAt(i, false);
 137  900
             if (t instanceof TargetListener) {
 138  900
                 TargetManager.getInstance()
 139  
                     .addTargetListener((TargetListener) t);
 140  
             }
 141  
         }
 142  
 
 143  900
         tabs.addChangeListener(this);
 144  900
         tabs.addMouseListener(this);
 145  900
         setTarget(null);
 146  900
     }
 147  
 
 148  
     /*
 149  
      * @see java.awt.Component#getPreferredSize()
 150  
      */
 151  
     @Override
 152  
     public Dimension getPreferredSize() {
 153  900
         return new Dimension(400, 500);
 154  
     }
 155  
 
 156  
     /*
 157  
      * @see java.awt.Component#getMinimumSize()
 158  
      */
 159  
     @Override
 160  
     public Dimension getMinimumSize() {
 161  0
         return new Dimension(100, 100);
 162  
     }
 163  
 
 164  
     /**
 165  
      * Sets the target of the multieditorpane. The multieditorpane can
 166  
      * have several tabs. If a tab is an instance of tabmodeltarget
 167  
      * (that is a tab that displays model elements) that tab should
 168  
      * display the target if the target is an ArgoDiagram.
 169  
      * @param t the target
 170  
      */
 171  
     private void setTarget(Object t) {
 172  900
         enableTabs(t);
 173  900
         for (int i = 0; i < tabs.getTabCount(); i++) {
 174  900
             Component tab = tabs.getComponentAt(i);
 175  900
             if (tab.isEnabled()) {
 176  900
                 tabs.setSelectedComponent(tab);
 177  900
                 break;
 178  
             }
 179  
         }
 180  900
     }
 181  
 
 182  
     /**
 183  
      * Enables the tabs on the MultiEditorPane depending on the result of its
 184  
      * shouldBeEnabled method.
 185  
      * @param t The target for which the shouldBeEnabled test
 186  
      * should hold true.
 187  
      */
 188  
     private void enableTabs(Object t) {
 189  1800
         for (int i = 0; i < tabs.getTabCount(); i++) {
 190  900
             Component tab = tabs.getComponentAt(i);
 191  900
             if (tab instanceof TabTarget) {
 192  900
                 TabTarget targetTab = (TabTarget) tab;
 193  900
                 boolean shouldBeEnabled = targetTab.shouldBeEnabled(t);
 194  900
                 tabs.setEnabledAt(i, shouldBeEnabled);
 195  
             }
 196  
         }
 197  900
     }
 198  
 
 199  
     /**
 200  
      * Returns the index of a tab with a certain name in the JTabbedPane which
 201  
      * is the component shown by the multieditorpane. At the moment (version
 202  
      * 0.13.3 of ArgoUML) there is only 1 tab, the Diagram tab.
 203  
      *
 204  
      * @param tabName the given tab name
 205  
      * @return The index.
 206  
      */
 207  
     public int getIndexOfNamedTab(String tabName) {
 208  0
         for (int i = 0; i < tabPanels.size(); i++) {
 209  0
             String title = tabs.getTitleAt(i);
 210  0
             if (title != null && title.equals(tabName)) {
 211  0
                 return i;
 212  
             }
 213  
         }
 214  0
         return -1;
 215  
     }
 216  
 
 217  
     /**
 218  
      * Selects a certain tab and shows it. At the moment (version
 219  
      * 0.13.3 of ArgoUML) there is only 1 tab, the Diagram tab.
 220  
      * @param tabName the name of the tab
 221  
      */
 222  
     public void selectTabNamed(String tabName) {
 223  0
         int index = getIndexOfNamedTab(tabName);
 224  0
         if (index != -1) {
 225  0
             tabs.setSelectedIndex(index);
 226  
         }
 227  0
     }
 228  
 
 229  
     /**
 230  
      * Selects the next tab in the JTabbedPane. At the moment (version 0.13.3 of
 231  
      * ArgoUML) there is only 1 tab, the Diagram tab.
 232  
      */
 233  
     public void selectNextTab() {
 234  0
         int size = tabPanels.size();
 235  0
         int currentTab = tabs.getSelectedIndex();
 236  0
         for (int i = 1; i < tabPanels.size(); i++) {
 237  0
             int newTab = (currentTab + i) % size;
 238  0
             if (tabs.isEnabledAt(newTab)) {
 239  0
                 tabs.setSelectedIndex(newTab);
 240  0
                 return;
 241  
             }
 242  
         }
 243  0
     }
 244  
 
 245  
 
 246  
     /*
 247  
      * Called when the user selects a tab, by clicking or otherwise.
 248  
      *
 249  
      * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
 250  
      */
 251  
     public void stateChanged(ChangeEvent  e) {
 252  
         //TODO: should fire its own event and ProjectBrowser
 253  
         //should register a listener
 254  0
         if (lastTab != null) {
 255  0
             lastTab.setVisible(false);
 256  
         }
 257  0
         lastTab = tabs.getSelectedComponent();
 258  0
         LOG.debug(
 259  
             "MultiEditorPane state changed:" + lastTab.getClass().getName());
 260  0
         lastTab.setVisible(true);
 261  0
         if (lastTab instanceof TabModelTarget) {
 262  0
             ((TabModelTarget) lastTab).refresh();
 263  
         }
 264  0
     }
 265  
 
 266  
     /*
 267  
      * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
 268  
      */
 269  
     public void mousePressed(MouseEvent me) {
 270  
         // empty implementation - we only handle mouseClicked
 271  0
     }
 272  
 
 273  
     /*
 274  
      * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
 275  
      */
 276  
     public void mouseReleased(MouseEvent me) {
 277  
         // empty implementation - we only handle mouseClicked
 278  0
     }
 279  
 
 280  
     /*
 281  
      * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
 282  
      */
 283  
     public void mouseEntered(MouseEvent me) {
 284  
         // empty implementation - we only handle mouseClicked
 285  0
     }
 286  
 
 287  
     /*
 288  
      * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
 289  
      */
 290  
     public void mouseExited(MouseEvent me) {
 291  
         // empty implementation - we only handle mouseClicked
 292  0
     }
 293  
 
 294  
     /*
 295  
      * Catches a mouseevent and calls mySingleClick and myDoubleClick if a tab
 296  
      * is clicked which is selected.
 297  
      * @see java.awt.event.MouseListener#mouseClicked(MouseEvent)
 298  
      */
 299  
     public void mouseClicked(MouseEvent me) {
 300  0
         int tab = tabs.getSelectedIndex();
 301  0
         if (tab != -1) {
 302  0
             Rectangle tabBounds = tabs.getBoundsAt(tab);
 303  0
             if (!tabBounds.contains(me.getX(), me.getY()))
 304  0
                 return;
 305  0
             if (me.getClickCount() == 1) {
 306  0
                 mySingleClick(tab);
 307  0
                 me.consume();
 308  0
             } else if (me.getClickCount() >= 2) {
 309  0
                 myDoubleClick(tab);
 310  0
                 me.consume();
 311  
             }
 312  
         }
 313  0
     }
 314  
 
 315  
     /**
 316  
      * Called when the user clicks once on a tab.
 317  
      *
 318  
      * @param tab the tab that was clicked on
 319  
      */
 320  
     public void mySingleClick(int tab) {
 321  
         //TODO: should fire its own event and ProjectBrowser
 322  
         //should register a listener
 323  0
         LOG.debug("single: " + tabs.getComponentAt(tab).toString());
 324  0
     }
 325  
 
 326  
     /**
 327  
      * When the user double clicks on a tab, this tab is spawned by this method
 328  
      * if it is selected.
 329  
      *
 330  
      * @param tab The index of the tab.
 331  
      */
 332  
     public void myDoubleClick(int tab) {
 333  
         //TODO: should fire its own event and ProjectBrowser
 334  
         //should register a listener
 335  0
         LOG.debug("double: " + tabs.getComponentAt(tab).toString());
 336  
 //        JPanel t = (JPanel) tabPanels.elementAt(tab);
 337  
         // Currently this feature is disabled for ArgoUML.
 338  
 //        if (t instanceof AbstractArgoJPanel)
 339  
 //             ((AbstractArgoJPanel) t).spawn();
 340  0
     }
 341  
 
 342  
     /*
 343  
      * @see org.argouml.ui.targetmanager.TargetListener#targetAdded(
 344  
      *         org.argouml.ui.targetmanager.TargetEvent)
 345  
      */
 346  
     public void targetAdded(TargetEvent e) {
 347  0
         setTarget(e.getNewTarget());
 348  0
     }
 349  
 
 350  
     /*
 351  
      * @see org.argouml.ui.targetmanager.TargetListener#targetRemoved(
 352  
      *         org.argouml.ui.targetmanager.TargetEvent)
 353  
      */
 354  
     public void targetRemoved(TargetEvent e) {
 355  
         // how to handle empty target lists?  probably the
 356  
         // MultiEditorPane should only show an empty pane in that case
 357  0
         setTarget(e.getNewTarget());
 358  0
     }
 359  
 
 360  
     /*
 361  
      * @see org.argouml.ui.targetmanager.TargetListener#targetSet(
 362  
      *         org.argouml.ui.targetmanager.TargetEvent)
 363  
      */
 364  
     public void targetSet(TargetEvent e) {
 365  0
         setTarget(e.getNewTarget());
 366  0
     }
 367  
 
 368  
     /**
 369  
      * @return returns the upper right panel tabs (the diagram tabs)
 370  
      */
 371  
     protected JTabbedPane getTabs() {
 372  0
         return tabs;
 373  
     }
 374  
 
 375  
 }
 376