Coverage Report - org.argouml.ui.explorer.PerspectiveConfigurator
 
Classes in this File Line Coverage Branch Coverage Complexity
PerspectiveConfigurator
85%
205/241
45%
11/24
2.594
PerspectiveConfigurator$1
100%
2/2
N/A
2.594
PerspectiveConfigurator$2
50%
1/2
N/A
2.594
PerspectiveConfigurator$DuplicatePerspectiveListener
11%
1/9
0%
0/2
2.594
PerspectiveConfigurator$LibraryListSelectionListener
14%
1/7
0%
0/6
2.594
PerspectiveConfigurator$MoveDownListener
10%
1/10
0%
0/2
2.594
PerspectiveConfigurator$MoveUpListener
10%
1/10
0%
0/2
2.594
PerspectiveConfigurator$NewPerspectiveListener
100%
9/9
N/A
2.594
PerspectiveConfigurator$OkListener
100%
7/7
100%
2/2
2.594
PerspectiveConfigurator$PerspectiveListSelectionListener
86%
19/22
50%
11/22
2.594
PerspectiveConfigurator$RemovePerspectiveListener
11%
1/9
0%
0/4
2.594
PerspectiveConfigurator$RenameDocumentListener
71%
10/14
50%
2/4
2.594
PerspectiveConfigurator$RenameListener
11%
1/9
0%
0/4
2.594
PerspectiveConfigurator$ResetListener
100%
8/8
75%
3/4
2.594
PerspectiveConfigurator$RuleListMouseListener
11%
1/9
0%
0/12
2.594
PerspectiveConfigurator$RuleListener
11%
1/9
0%
0/6
2.594
PerspectiveConfigurator$RulesListSelectionListener
9%
1/11
0%
0/10
2.594
 
 1  
 /* $Id: PerspectiveConfigurator.java 17843 2010-01-12 19:23:29Z 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  
  *    tfmorris
 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.explorer;
 40  
 
 41  
 import java.awt.BorderLayout;
 42  
 import java.awt.FlowLayout;
 43  
 import java.awt.GridBagConstraints;
 44  
 import java.awt.GridBagLayout;
 45  
 import java.awt.GridLayout;
 46  
 import java.awt.Insets;
 47  
 import java.awt.event.ActionEvent;
 48  
 import java.awt.event.ActionListener;
 49  
 import java.awt.event.MouseAdapter;
 50  
 import java.awt.event.MouseEvent;
 51  
 import java.util.ArrayList;
 52  
 import java.util.Collection;
 53  
 import java.util.Collections;
 54  
 import java.util.Comparator;
 55  
 import java.util.List;
 56  
 
 57  
 import javax.swing.BorderFactory;
 58  
 import javax.swing.BoxLayout;
 59  
 import javax.swing.DefaultListModel;
 60  
 import javax.swing.JButton;
 61  
 import javax.swing.JLabel;
 62  
 import javax.swing.JList;
 63  
 import javax.swing.JPanel;
 64  
 import javax.swing.JScrollPane;
 65  
 import javax.swing.JSplitPane;
 66  
 import javax.swing.JTextField;
 67  
 import javax.swing.ListSelectionModel;
 68  
 import javax.swing.event.DocumentEvent;
 69  
 import javax.swing.event.DocumentListener;
 70  
 import javax.swing.event.ListSelectionEvent;
 71  
 import javax.swing.event.ListSelectionListener;
 72  
 
 73  
 import org.apache.log4j.Logger;
 74  
 import org.argouml.i18n.Translator;
 75  
 import org.argouml.swingext.SpacerPanel;
 76  
 import org.argouml.ui.explorer.rules.PerspectiveRule;
 77  
 import org.argouml.util.ArgoDialog;
 78  
 
 79  
 /**
 80  
  * The "Configure Perspectives" dialog.<p>
 81  
  *
 82  
  * This class implements the following features:<p>
 83  
  * <ul>
 84  
  * <li>- saving perspectives to the user profile.
 85  
  * <li>- adding new perspectives.
 86  
  * <li>- deleting perspectives.
 87  
  * <li>- renaming perspectives.
 88  
  * <li>- duplicating existing perspectives.
 89  
  * <li>- reordering perspectives.
 90  
  * <li>- selecting any number and combination of rules for a perspective.
 91  
  * </ul><p>
 92  
  *
 93  
  * This dialog behaves almost exactly as described in
 94  
  * http://java.sun.com/products/jlf/at/book/Idioms6.html#57371
 95  
  *
 96  
  * @since 21 December 2003.
 97  
  * @author  alexb
 98  
  */
 99  189
 public class PerspectiveConfigurator extends ArgoDialog {
 100  
     /**
 101  
      * Logger.
 102  
      */
 103  55
     private static final Logger LOG =
 104  
         Logger.getLogger(PerspectiveConfigurator.class);
 105  
 
 106  
     /**
 107  
      * Insets in pixels.
 108  
      */
 109  
     private static final int INSET_PX = 3;
 110  
 
 111  
     ////////////////////////////////////////////////////////////////
 112  
     // instance variables
 113  
 
 114  
     private JPanel  configPanelNorth;
 115  
     private JPanel  configPanelSouth;
 116  
     private JSplitPane splitPane;
 117  
     private JTextField renameTextField;
 118  
     private JButton newPerspectiveButton;
 119  
     private JButton removePerspectiveButton;
 120  
     private JButton duplicatePerspectiveButton;
 121  
     private JButton moveUpButton, moveDownButton;
 122  
     private JButton addRuleButton;
 123  
     private JButton removeRuleButton;
 124  
     private JButton resetToDefaultButton;
 125  
 
 126  
     private JList   perspectiveList;
 127  
     private JList   perspectiveRulesList;
 128  
     private JList   ruleLibraryList;
 129  
     private DefaultListModel perspectiveListModel;       // at the top
 130  
     private DefaultListModel perspectiveRulesListModel;  // right bottom
 131  
     private DefaultListModel ruleLibraryListModel;       // left bottom
 132  
 
 133  
     private JLabel persLabel;
 134  
     private JLabel ruleLibLabel;
 135  
     private JLabel rulesLabel;
 136  
 
 137  
     /**
 138  
      * Creates a new instance of PerspectiveDesignerDialog.
 139  
      */
 140  
     public PerspectiveConfigurator() {
 141  55
         super(Translator.localize("dialog.title.configure-perspectives"),
 142  
               ArgoDialog.OK_CANCEL_OPTION,
 143  
               true); // the dialog is modal
 144  
 
 145  55
         configPanelNorth = new JPanel();
 146  55
         configPanelSouth = new JPanel();
 147  
         
 148  55
         makeLists();
 149  
         
 150  55
         makeButtons();
 151  
         
 152  55
         makeLayout();
 153  55
         updateRuleLabel();
 154  
         
 155  55
         makeListeners();
 156  
         
 157  55
         loadPerspectives();
 158  55
         loadLibrary();
 159  
         //sortJListModel(ruleLibraryList);
 160  
         
 161  55
         splitPane =
 162  
             new JSplitPane(JSplitPane.VERTICAL_SPLIT,
 163  
                     configPanelNorth, configPanelSouth);
 164  55
         splitPane.setContinuousLayout(true);
 165  
         
 166  55
         setContent(splitPane);
 167  55
     }
 168  
 
 169  
     /**
 170  
      * Make the lists on the dialog box and fill them.
 171  
      */
 172  
     private void makeLists() {
 173  55
         renameTextField = new JTextField();
 174  
 
 175  55
         perspectiveListModel = new DefaultListModel();
 176  55
         perspectiveList = new JList(perspectiveListModel);
 177  55
         perspectiveRulesListModel = new DefaultListModel();
 178  55
         perspectiveRulesList = new JList(perspectiveRulesListModel);
 179  55
         ruleLibraryListModel = new DefaultListModel();
 180  55
         ruleLibraryList = new JList(ruleLibraryListModel);
 181  
 
 182  55
         perspectiveList.setBorder(BorderFactory.createEmptyBorder(
 183  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 184  55
         perspectiveRulesList.setBorder(BorderFactory.createEmptyBorder(
 185  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 186  55
         ruleLibraryList.setBorder(BorderFactory.createEmptyBorder(
 187  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 188  
 
 189  55
         perspectiveList.setSelectionMode(
 190  
                 ListSelectionModel.SINGLE_SELECTION);
 191  55
         perspectiveRulesList.setSelectionMode(
 192  
                 ListSelectionModel.SINGLE_SELECTION);
 193  55
         ruleLibraryList.setSelectionMode(
 194  
                 ListSelectionModel.SINGLE_SELECTION);
 195  55
     }
 196  
 
 197  
     /**
 198  
      * Make the buttons on the dialog box with localized strings and mnemonics.
 199  
      */
 200  
     private void makeButtons() {
 201  55
         newPerspectiveButton = new JButton();
 202  55
         nameButton(newPerspectiveButton, "button.new");
 203  55
         newPerspectiveButton.setToolTipText(
 204  
                 Translator.localize("button.new.tooltip"));
 205  
 
 206  55
         removePerspectiveButton = new JButton();
 207  55
         nameButton(removePerspectiveButton, "button.remove");
 208  55
         removePerspectiveButton.setToolTipText(
 209  
                 Translator.localize("button.remove.tooltip"));
 210  
 
 211  55
         duplicatePerspectiveButton = new JButton();
 212  55
         nameButton(duplicatePerspectiveButton, "button.duplicate");
 213  55
         duplicatePerspectiveButton.setToolTipText(
 214  
                 Translator.localize("button.duplicate.tooltip"));
 215  
 
 216  55
         moveUpButton = new JButton();
 217  55
         nameButton(moveUpButton, "button.move-up");
 218  55
         moveUpButton.setToolTipText(
 219  
                 Translator.localize("button.move-up.tooltip"));
 220  
 
 221  55
         moveDownButton = new JButton();
 222  55
         nameButton(moveDownButton, "button.move-down");
 223  55
         moveDownButton.setToolTipText(
 224  
                 Translator.localize("button.move-down.tooltip"));
 225  
 
 226  55
         addRuleButton = new JButton(">>");
 227  55
         addRuleButton.setToolTipText(Translator.localize("button.add-rule"));
 228  55
         removeRuleButton = new JButton("<<");
 229  55
         removeRuleButton.setToolTipText(Translator.localize(
 230  
                 "button.remove-rule"));
 231  
 
 232  55
         resetToDefaultButton = new JButton();
 233  55
         nameButton(resetToDefaultButton, "button.restore-defaults");
 234  55
         resetToDefaultButton.setToolTipText(
 235  
                 Translator.localize("button.restore-defaults.tooltip"));
 236  
 
 237  
         //disable the buttons for now, since no selection has been made yet
 238  55
         removePerspectiveButton.setEnabled(false);
 239  55
         duplicatePerspectiveButton.setEnabled(false);
 240  55
         moveUpButton.setEnabled(false);
 241  55
         moveDownButton.setEnabled(false);
 242  55
         addRuleButton.setEnabled(false);
 243  55
         removeRuleButton.setEnabled(false);
 244  55
         renameTextField.setEnabled(false);
 245  55
     }
 246  
 
 247  
     /**
 248  
      * Make the layout for the dialog box.
 249  
      */
 250  
     private void makeLayout() {
 251  55
         GridBagLayout gb = new GridBagLayout();
 252  55
         configPanelNorth.setLayout(gb);
 253  55
         configPanelSouth.setLayout(gb);
 254  55
         GridBagConstraints c = new GridBagConstraints();
 255  55
         c.ipadx = 3;
 256  55
         c.ipady = 3;
 257  
 
 258  55
         persLabel = new JLabel(); // the text will be set later
 259  55
         persLabel.setBorder(BorderFactory.createEmptyBorder(
 260  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 261  55
         c.fill = GridBagConstraints.BOTH;
 262  55
         c.gridx = 0;
 263  55
         c.gridy = 0;
 264  55
         c.gridwidth = 3;
 265  55
         c.weightx = 1.0;  c.weighty = 0.0;
 266  55
         gb.setConstraints(persLabel, c);
 267  55
         configPanelNorth.add(persLabel);
 268  
 
 269  55
         JPanel persPanel = new JPanel(new BorderLayout());
 270  55
         JScrollPane persScroll =
 271  
             new JScrollPane(perspectiveList,
 272  
                             JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 273  
                             JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 274  55
         persPanel.add(renameTextField, BorderLayout.NORTH);
 275  55
         persPanel.add(persScroll, BorderLayout.CENTER);
 276  55
         c.gridx = 0;
 277  55
         c.gridy = 1;
 278  55
         c.gridwidth = 4;
 279  55
         c.weightx = 1.0;  c.weighty = 1.0;
 280  55
         gb.setConstraints(persPanel, c);
 281  55
         configPanelNorth.add(persPanel);
 282  
 
 283  55
         JPanel persButtons = new JPanel(new GridLayout(6, 1, 0, 5));
 284  55
         persButtons.add(newPerspectiveButton);
 285  55
         persButtons.add(removePerspectiveButton);
 286  55
         persButtons.add(duplicatePerspectiveButton);
 287  55
         persButtons.add(moveUpButton);
 288  55
         persButtons.add(moveDownButton);
 289  55
         persButtons.add(resetToDefaultButton);
 290  55
         JPanel persButtonWrapper =
 291  
             new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
 292  55
         persButtonWrapper.add(persButtons);
 293  55
         c.gridx = 4;
 294  55
         c.gridy = 1;
 295  55
         c.gridwidth = 1;
 296  55
         c.weightx = 0.0;  c.weighty = 0.0;
 297  55
         c.ipadx = 0;      c.ipady = 0;
 298  55
         c.insets = new Insets(0, 5, 0, 0);
 299  55
         gb.setConstraints(persButtonWrapper, c);
 300  55
         configPanelNorth.add(persButtonWrapper);
 301  
 
 302  55
         ruleLibLabel = new JLabel(); // the text will be set later
 303  55
         ruleLibLabel.setBorder(BorderFactory.createEmptyBorder(
 304  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 305  55
         c.gridx = 0;
 306  55
         c.gridy = 3;
 307  55
         c.gridwidth = 1;
 308  55
         c.weightx = 1.0;
 309  55
         c.weighty = 0.0;
 310  55
         c.ipadx = 3;
 311  55
         c.ipady = 3;
 312  55
         c.insets = new Insets(10, 0, 0, 0);
 313  55
         gb.setConstraints(ruleLibLabel, c);
 314  55
         configPanelSouth.add(ruleLibLabel);
 315  
 
 316  55
         addRuleButton.setMargin(new Insets(2, 15, 2, 15));
 317  55
         removeRuleButton.setMargin(new Insets(2, 15, 2, 15));
 318  55
         JPanel xferButtons = new JPanel();
 319  55
         xferButtons.setLayout(new BoxLayout(xferButtons, BoxLayout.Y_AXIS));
 320  55
         xferButtons.add(addRuleButton);
 321  55
         xferButtons.add(new SpacerPanel());
 322  55
         xferButtons.add(removeRuleButton);
 323  55
         c.gridx = 2;
 324  55
         c.gridy = 4;
 325  55
         c.weightx = 0.0;
 326  55
         c.weighty = 0.0;
 327  55
         c.insets = new Insets(0, 3, 0, 5);
 328  55
         gb.setConstraints(xferButtons, c);
 329  55
         configPanelSouth.add(xferButtons);
 330  
 
 331  55
         rulesLabel = new JLabel(); // the text will be set later
 332  55
         rulesLabel.setBorder(BorderFactory.createEmptyBorder(
 333  
                 INSET_PX, INSET_PX, INSET_PX, INSET_PX));
 334  55
         c.gridx = 3;
 335  55
         c.gridy = 3;
 336  55
         c.gridwidth = 1;
 337  55
         c.weightx = 1.0;
 338  55
         c.insets = new Insets(10, 0, 0, 0);
 339  55
         gb.setConstraints(rulesLabel, c);
 340  55
         configPanelSouth.add(rulesLabel);
 341  
 
 342  55
         c.gridx = 0;
 343  55
         c.gridy = 4;
 344  55
         c.weighty = 1.0;
 345  55
         c.gridwidth = 2;
 346  55
         c.gridheight = 2;
 347  55
         c.insets = new Insets(0, 0, 0, 0);
 348  55
         JScrollPane ruleLibScroll =
 349  
             new JScrollPane(ruleLibraryList,
 350  
                             JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 351  
                             JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 352  55
         gb.setConstraints(ruleLibScroll, c);
 353  55
         configPanelSouth.add(ruleLibScroll);
 354  
 
 355  55
         c.gridx = 3;
 356  55
         c.gridy = 4;
 357  55
         c.gridwidth = 2;
 358  55
         c.gridheight = 2;
 359  55
         JScrollPane rulesScroll =
 360  
             new JScrollPane(perspectiveRulesList,
 361  
                             JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
 362  
                             JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
 363  55
         gb.setConstraints(rulesScroll, c);
 364  55
         configPanelSouth.add(rulesScroll);
 365  55
     }
 366  
 
 367  
     /**
 368  
      * Add action listeners to the buttons and lists.
 369  
      */
 370  
     private void makeListeners() {
 371  55
         renameTextField.addActionListener(new RenameListener());
 372  55
         renameTextField.getDocument().addDocumentListener(
 373  
                 new RenameDocumentListener());
 374  
 
 375  
 
 376  55
         newPerspectiveButton.addActionListener(new NewPerspectiveListener());
 377  55
         removePerspectiveButton.addActionListener(
 378  
                 new RemovePerspectiveListener());
 379  55
         duplicatePerspectiveButton.addActionListener(
 380  
                 new DuplicatePerspectiveListener());
 381  55
         moveUpButton.addActionListener(new MoveUpListener());
 382  55
         moveDownButton.addActionListener(new MoveDownListener());
 383  55
         addRuleButton.addActionListener(new RuleListener());
 384  55
         removeRuleButton.addActionListener(new RuleListener());
 385  55
         resetToDefaultButton.addActionListener(new ResetListener());
 386  
 
 387  55
         perspectiveList.addListSelectionListener(
 388  
                 new PerspectiveListSelectionListener());
 389  55
         perspectiveRulesList.addListSelectionListener(
 390  
                 new RulesListSelectionListener());
 391  55
         perspectiveRulesList.addMouseListener(new RuleListMouseListener());
 392  55
         ruleLibraryList.addListSelectionListener(
 393  
                 new LibraryListSelectionListener());
 394  55
         ruleLibraryList.addMouseListener(new RuleListMouseListener());
 395  
 
 396  55
         getOkButton().addActionListener(new OkListener());
 397  55
     }
 398  
 
 399  
     /**
 400  
      * Load all the existing rules from the perspective manager
 401  
      * for presentation. These will be presented as the library of rules
 402  
      * the user may pick from.
 403  
      */
 404  
     private void loadLibrary() {
 405  56
         List<PerspectiveRule> rulesLib = new ArrayList<PerspectiveRule>();
 406  56
         rulesLib.addAll(PerspectiveManager.getInstance().getRules());
 407  19992
         Collections.sort(rulesLib, new Comparator<PerspectiveRule>() {
 408  
             public int compare(PerspectiveRule o1, PerspectiveRule o2) {
 409  19936
                 return o1.toString().compareTo(o2.toString());
 410  
             }
 411  
         });
 412  
         // remove the ones already selected (if a perspective is selected)
 413  56
         ExplorerPerspective selPers =
 414  
             (ExplorerPerspective) perspectiveList.getSelectedValue();
 415  56
         if (selPers != null) {
 416  1
             for (PerspectiveRule persRule : selPers.getList()) {
 417  0
                 for (PerspectiveRule libRule : rulesLib) {
 418  0
                     if (libRule.toString().equals(persRule.toString())) {
 419  0
                         rulesLib.remove(libRule);
 420  0
                         break;
 421  
                     }
 422  
                 }
 423  
             }
 424  
         }
 425  
         // add them
 426  56
         ruleLibraryListModel.clear();
 427  56
         for (PerspectiveRule rule : rulesLib) {
 428  4480
             ruleLibraryListModel.addElement(rule);
 429  
         }
 430  56
         updateLibLabel();
 431  56
     }
 432  
 
 433  
     /**
 434  
      * Load the perspectives from the perspective manager for presentation.
 435  
      */
 436  
     private void loadPerspectives() {
 437  55
         List<ExplorerPerspective> perspectives = 
 438  
             PerspectiveManager.getInstance().getPerspectives();
 439  
 
 440  
         // must add an editable list of new ExplorerPerspective's
 441  
         // to the list model so that the original ones are not changed
 442  
         // in the case of a cancel action by the user.
 443  55
         for (ExplorerPerspective perspective : perspectives) {
 444  495
             List<PerspectiveRule> rules = perspective.getList();
 445  
 
 446  495
             ExplorerPerspective editablePerspective =
 447  
                 new ExplorerPerspective(perspective.toString());
 448  495
             for (PerspectiveRule rule : rules) {
 449  6655
                 editablePerspective.addRule(rule);
 450  
             }
 451  
 
 452  495
             perspectiveListModel.addElement(editablePerspective);
 453  495
         }
 454  
 
 455  55
         updatePersLabel();
 456  55
     }
 457  
 
 458  
     /**
 459  
      * Update the label above the list of perspectives with count.
 460  
      */
 461  
     private void updatePersLabel() {
 462  69
         persLabel.setText(Translator.localize("label.perspectives")
 463  
                 + " (" + perspectiveListModel.size() + ")");
 464  69
     }
 465  
 
 466  
     /**
 467  
      * Update the label above the library of rules list with count.
 468  
      */
 469  
     private void updateLibLabel() {
 470  
         // update the label (which shows the number of rules)
 471  56
         ruleLibLabel.setText(Translator.localize("label.rules-library")
 472  
                 + " (" + ruleLibraryListModel.size() + ")");
 473  56
     }
 474  
 
 475  
     /**
 476  
      * Update the label above the library of rules list with count.
 477  
      */
 478  
     private void updateRuleLabel() {
 479  
         // update the label (which shows the number of rules)
 480  57
         rulesLabel.setText(Translator.localize("label.selected-rules")
 481  
                 + " (" + perspectiveRulesListModel.size() + ")");
 482  57
     }
 483  
 
 484  
     /**
 485  
      * @param list the JList to be sorted
 486  
      */
 487  
     private void sortJListModel(JList list) {
 488  1
         DefaultListModel model = (DefaultListModel) list.getModel();
 489  1
         List all = new ArrayList();
 490  1
         for (int i = 0; i < model.getSize(); i++) {
 491  0
             all.add(model.getElementAt(i));
 492  
         }
 493  1
         model.clear();
 494  1
         Collections.sort(all, new Comparator() {
 495  
             public int compare(Object o1, Object o2) {
 496  0
                 return o1.toString().compareTo(o2.toString());
 497  
             }
 498  
         });
 499  1
         for (Object obj : all) {
 500  0
             model.addElement(obj);
 501  
         }
 502  1
     }
 503  
 
 504  
     /**
 505  
      * Handles pressing the OK button. <p>
 506  
      *
 507  
      * Updates the perspectives in the explorer,
 508  
      * saves the user perspectives and exits.
 509  
      */
 510  55
     class OkListener implements ActionListener {
 511  
         public void actionPerformed(ActionEvent e) {
 512  
 
 513  1
             PerspectiveManager.getInstance().removeAllPerspectives();
 514  
 
 515  10
             for (int i = 0; i < perspectiveListModel.size(); i++) {
 516  9
                 ExplorerPerspective perspective = 
 517  
                     (ExplorerPerspective) perspectiveListModel.get(i);
 518  9
                 PerspectiveManager.getInstance().addPerspective(perspective);
 519  
             }
 520  
 
 521  1
             PerspectiveManager.getInstance().saveUserPerspectives();
 522  1
         }
 523  
     }
 524  
 
 525  
     /**
 526  
      * Handles pressing the Reset-To-Default button. <p>
 527  
      *
 528  
      * Resets all perspectives to the build-in defaults.
 529  
      */
 530  55
     class ResetListener implements ActionListener {
 531  
         public void actionPerformed(ActionEvent e) {
 532  
 
 533  13
             Collection<ExplorerPerspective> c =
 534  
                 PerspectiveManager.getInstance().getDefaultPerspectives();
 535  13
             if (c.size() > 0) {
 536  13
                 perspectiveListModel.removeAllElements();
 537  13
                 for (ExplorerPerspective p : c) {
 538  117
                     perspectiveListModel.addElement(p);
 539  
                 }
 540  13
                 updatePersLabel();
 541  
             }
 542  13
         }
 543  
     }
 544  
 
 545  
     /**
 546  
      * Handles pressing the "New" button.
 547  
      */
 548  55
     class NewPerspectiveListener implements ActionListener {
 549  
         public void actionPerformed(ActionEvent e) {
 550  1
             Object[] msgArgs = {
 551  
                 Integer.valueOf((perspectiveList.getModel().getSize() + 1)),
 552  
             };
 553  1
             ExplorerPerspective newPers =
 554  
                 new ExplorerPerspective(Translator.messageFormat(
 555  
                     "dialog.perspective.explorer-perspective", msgArgs));
 556  1
             perspectiveListModel.insertElementAt(newPers, 0);
 557  1
             perspectiveList.setSelectedValue(newPers, true);
 558  1
             perspectiveRulesListModel.clear();
 559  1
             updatePersLabel();
 560  1
             updateRuleLabel();
 561  1
         }
 562  
     }
 563  
 
 564  
     /**
 565  
      * Handles pressing the "Remove" button.
 566  
      */
 567  55
     class RemovePerspectiveListener implements ActionListener {
 568  
         public void actionPerformed(ActionEvent e) {
 569  0
             Object sel = perspectiveList.getSelectedValue();
 570  0
             if (perspectiveListModel.getSize() > 1) {
 571  0
                 perspectiveListModel.removeElement(sel);
 572  
             }
 573  0
             perspectiveList.setSelectedIndex(0);
 574  0
             if (perspectiveListModel.getSize() == 1) {
 575  0
                 removePerspectiveButton.setEnabled(false);
 576  
             }
 577  0
             updatePersLabel();
 578  0
         }
 579  
     }
 580  
 
 581  
     /**
 582  
      * Handles pressing the Duplicate button.
 583  
      */
 584  55
     class DuplicatePerspectiveListener implements ActionListener {
 585  
         public void actionPerformed(ActionEvent e) {
 586  0
             Object sel = perspectiveList.getSelectedValue();
 587  0
             if (sel != null) {
 588  0
                 Object[] msgArgs = {sel.toString() };
 589  0
                 ExplorerPerspective newPers =
 590  
                     ((ExplorerPerspective) sel).makeNamedClone(Translator
 591  
                         .messageFormat("dialog.perspective.copy-of", msgArgs));
 592  0
                 perspectiveListModel.insertElementAt(newPers, 0);
 593  0
                 perspectiveList.setSelectedValue(newPers, true);
 594  
             }
 595  0
             updatePersLabel();
 596  0
         }
 597  
     }
 598  
 
 599  
     /**
 600  
      * Handles pressing the ">>" or "<<" buttons.
 601  
      */
 602  110
     class RuleListener implements ActionListener {
 603  
         public void actionPerformed(ActionEvent e) {
 604  
 
 605  0
             Object src = e.getSource();
 606  0
             if (perspectiveList.getSelectedValue() == null) {
 607  0
                 return;
 608  
             }
 609  0
             if (src == addRuleButton) {
 610  0
                 doAddRule();
 611  0
             } else if (src == removeRuleButton) {
 612  0
                 doRemoveRule();
 613  
             }
 614  0
         }
 615  
     }
 616  
 
 617  
     /**
 618  
      * Handles double-clicking on the library list or on the ruleslist.
 619  
      * This triggers the same functions as ">>" or "<<".
 620  
      */
 621  110
     class RuleListMouseListener extends MouseAdapter {
 622  
         public void mouseClicked(MouseEvent me) {
 623  0
             Object src = me.getSource();
 624  0
             if (me.getClickCount() != 2
 625  
                 || perspectiveList.getSelectedValue() == null) {
 626  0
                 return;
 627  
             }
 628  
 
 629  0
             if (src == ruleLibraryList && addRuleButton.isEnabled()) {
 630  0
                 doAddRule();
 631  
             }
 632  0
             if (src == perspectiveRulesList && removeRuleButton.isEnabled()) {
 633  0
                 doRemoveRule();
 634  
             }
 635  0
         }
 636  
     }
 637  
 
 638  
     /**
 639  
      * Add the currently selected rule from the library to the rules list
 640  
      * for the current perspective.
 641  
      */
 642  
     private void doAddRule() {
 643  0
         Object sel = ruleLibraryList.getSelectedValue();
 644  0
         int selLibNr = ruleLibraryList.getSelectedIndex();
 645  
         try {
 646  0
             PerspectiveRule newRule = 
 647  
                 (PerspectiveRule) sel.getClass().newInstance();
 648  
 
 649  0
             perspectiveRulesListModel.insertElementAt(newRule, 0);
 650  0
             ((ExplorerPerspective) perspectiveList.getSelectedValue())
 651  
                 .addRule(newRule);
 652  0
             sortJListModel(perspectiveRulesList);
 653  0
             perspectiveRulesList.setSelectedValue(newRule, true);
 654  
             // remove the rule from the library list
 655  0
             loadLibrary();
 656  
             // set the newly selected item in the library list
 657  0
             if (!(ruleLibraryListModel.size() > selLibNr)) {
 658  0
                 selLibNr = ruleLibraryListModel.size() - 1;
 659  
             }
 660  0
             ruleLibraryList.setSelectedIndex(selLibNr);
 661  0
             updateRuleLabel();
 662  0
         } catch (Exception e) {
 663  0
             LOG.error("problem adding rule", e);
 664  0
         }
 665  0
     }
 666  
 
 667  
     /**
 668  
      * Remove the currently selected rule from the rules list
 669  
      * for the current perspective.
 670  
      */
 671  
     private void doRemoveRule() {
 672  0
         int selLibNr = ruleLibraryList.getSelectedIndex();
 673  0
         PerspectiveRule sel =
 674  
             (PerspectiveRule) perspectiveRulesList.getSelectedValue();
 675  0
         int selectedItem = perspectiveRulesList.getSelectedIndex();
 676  0
         Object selPers = perspectiveList.getSelectedValue();
 677  
 
 678  0
         perspectiveRulesListModel.removeElement(sel);
 679  0
         ((ExplorerPerspective) selPers).removeRule(sel);
 680  
 
 681  0
         if (perspectiveRulesListModel.getSize() > selectedItem) {
 682  0
             perspectiveRulesList.setSelectedIndex(selectedItem);
 683  0
         } else if (perspectiveRulesListModel.getSize() > 0) {
 684  0
             perspectiveRulesList.setSelectedIndex(
 685  
                     perspectiveRulesListModel.getSize() - 1);
 686  
         }
 687  0
         loadLibrary();
 688  
         // set the newly selected item in the library list
 689  0
         ruleLibraryList.setSelectedIndex(selLibNr);
 690  0
         updateRuleLabel();
 691  0
     }
 692  
 
 693  
     /**
 694  
      * Handles pressing the move up button.
 695  
      */
 696  55
     class MoveUpListener implements ActionListener {
 697  
         /*
 698  
          * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
 699  
          */
 700  
         public void actionPerformed(ActionEvent e) {
 701  0
             int sel = perspectiveList.getSelectedIndex();
 702  0
             if (sel > 0) {
 703  0
                 Object selObj = perspectiveListModel.get(sel);
 704  0
                 Object prevObj = perspectiveListModel.get(sel - 1);
 705  0
                 perspectiveListModel.set(sel, prevObj);
 706  0
                 perspectiveListModel.set(sel - 1, selObj);
 707  0
                 perspectiveList.setSelectedIndex(sel - 1);
 708  0
                 perspectiveList.ensureIndexIsVisible(sel - 1);
 709  
             }
 710  0
         }
 711  
     }
 712  
 
 713  
     /**
 714  
      * Handles pressing the move down button.
 715  
      */
 716  55
     class MoveDownListener implements ActionListener {
 717  
         public void actionPerformed(ActionEvent e) {
 718  0
             int sel = perspectiveList.getSelectedIndex();
 719  0
             if (sel < (perspectiveListModel.getSize() - 1)) {
 720  0
                 Object selObj = perspectiveListModel.get(sel);
 721  0
                 Object nextObj = perspectiveListModel.get(sel + 1);
 722  0
                 perspectiveListModel.set(sel, nextObj);
 723  0
                 perspectiveListModel.set(sel + 1, selObj);
 724  0
                 perspectiveList.setSelectedIndex(sel + 1);
 725  0
                 perspectiveList.ensureIndexIsVisible(sel + 1);
 726  
             }
 727  0
         }
 728  
     }
 729  
 
 730  
     /**
 731  
      * Handles confirming a changed text in the text-entry field
 732  
      * (e.g. pressing Enter) for the perspective name.
 733  
      */
 734  55
     class RenameListener implements ActionListener {
 735  
         public void actionPerformed(ActionEvent e) {
 736  0
             int sel = perspectiveList.getSelectedIndex();
 737  0
             Object selPers = perspectiveList.getSelectedValue();
 738  0
             String newName = renameTextField.getText();
 739  0
             if (sel >= 0 && newName.length() > 0) {
 740  0
                 ((ExplorerPerspective) selPers).setName(newName);
 741  0
                 perspectiveListModel.set(sel, selPers);
 742  
                 /* TODO: Replace the functioncall in the next line
 743  
                  * by .requestFocusInWindow() once
 744  
                  * we do not support Java 1.3 any more.
 745  
                  */
 746  0
                 perspectiveList.requestFocus();
 747  
             }
 748  0
         }
 749  
     }
 750  
 
 751  
     /**
 752  
      * Handles changes in the text in the text-entry field
 753  
      * for the perspective name.
 754  
      */
 755  55
     class RenameDocumentListener implements DocumentListener {
 756  
         public void insertUpdate(DocumentEvent e) {
 757  1
             update();
 758  1
         }
 759  
         public void removeUpdate(DocumentEvent e) {
 760  0
             update();
 761  0
         }
 762  
         public void changedUpdate(DocumentEvent e) {
 763  0
             update();
 764  0
         }
 765  
         private void update() {
 766  1
             int sel = perspectiveList.getSelectedIndex();
 767  1
             Object selPers = perspectiveList.getSelectedValue();
 768  1
             String newName = renameTextField.getText();
 769  1
             if (sel >= 0 && newName.length() > 0) {
 770  1
                 ((ExplorerPerspective) selPers).setName(newName);
 771  1
                 perspectiveListModel.set(sel, selPers);
 772  
             }
 773  1
         }
 774  
 
 775  
     }
 776  
 
 777  
     /**
 778  
      * Handles selection changes in the perspective list.
 779  
      */
 780  55
     class PerspectiveListSelectionListener implements ListSelectionListener {
 781  
         /*
 782  
          * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
 783  
          */
 784  
         public void valueChanged(ListSelectionEvent lse) {
 785  1
             if (lse.getValueIsAdjusting()) {
 786  0
                 return;
 787  
             }
 788  
 
 789  1
             Object selPers = perspectiveList.getSelectedValue();
 790  1
             loadLibrary();
 791  1
             Object selRule = ruleLibraryList.getSelectedValue();
 792  1
             renameTextField.setEnabled(selPers != null);
 793  1
             removePerspectiveButton.setEnabled(selPers != null);
 794  1
             duplicatePerspectiveButton.setEnabled(selPers != null);
 795  1
             moveUpButton.setEnabled(perspectiveList.getSelectedIndex() > 0);
 796  1
             moveDownButton.setEnabled((selPers != null)
 797  
                     && (perspectiveList.getSelectedIndex()
 798  
                             < (perspectiveList.getModel().getSize() - 1)));
 799  
 
 800  1
             if (selPers == null) {
 801  0
                 return;
 802  
             }
 803  1
             renameTextField.setText(selPers.toString());
 804  
 
 805  1
             ExplorerPerspective pers = (ExplorerPerspective) selPers;
 806  1
             perspectiveRulesListModel.clear();
 807  
 
 808  1
             for (PerspectiveRule rule : pers.getList()) {
 809  0
                 perspectiveRulesListModel.insertElementAt(rule, 0);
 810  
             }
 811  1
             sortJListModel(perspectiveRulesList);
 812  1
             addRuleButton.setEnabled(selPers != null && selRule != null);
 813  1
             updateRuleLabel();
 814  1
         }
 815  
     }
 816  
 
 817  
     /**
 818  
      * Handles selection changes in the rules list.
 819  
      */
 820  55
     class RulesListSelectionListener implements ListSelectionListener {
 821  
         /*
 822  
          * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
 823  
          */
 824  
         public void valueChanged(ListSelectionEvent lse) {
 825  0
             if (lse.getValueIsAdjusting()) {
 826  0
                 return;
 827  
             }
 828  
 
 829  0
             Object selPers = null;
 830  0
             if (perspectiveListModel.size() > 0) {
 831  0
                 selPers = perspectiveList.getSelectedValue();
 832  
             }
 833  
 
 834  0
             Object selRule = null;
 835  0
             if (perspectiveRulesListModel.size() > 0) {
 836  0
                 selRule = perspectiveRulesList.getSelectedValue();
 837  
             }
 838  
 
 839  0
             removeRuleButton.setEnabled(selPers != null && selRule != null);
 840  0
         }
 841  
     }
 842  
 
 843  
     /**
 844  
      * Handles selection changes in the library list.
 845  
      *
 846  
      */
 847  55
     class LibraryListSelectionListener implements ListSelectionListener {
 848  
         /*
 849  
          * @see javax.swing.event.ListSelectionListener#valueChanged(javax.swing.event.ListSelectionEvent)
 850  
          */
 851  
         public void valueChanged(ListSelectionEvent lse) {
 852  0
             if (lse.getValueIsAdjusting()) {
 853  0
                 return;
 854  
             }
 855  
 
 856  0
             Object selPers = perspectiveList.getSelectedValue();
 857  0
             Object selRule = ruleLibraryList.getSelectedValue();
 858  0
             addRuleButton.setEnabled(selPers != null && selRule != null);
 859  0
         }
 860  
     }
 861  
 }