1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * ident        "%Z%%M% %I%     %E% SMI"
  24  *
  25  * Copyright 2002 by Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 package com.sun.dhcpmgr.ui;
  29 
  30 import java.awt.*;
  31 import java.awt.event.*;
  32 import javax.swing.*;
  33 import javax.swing.event.*;
  34 import java.util.*;
  35 
  36 import com.sun.dhcpmgr.data.IPAddress;
  37 import com.sun.dhcpmgr.data.ValidationException;
  38 
  39 /**
  40  * A panel which allows the user to edit a list of IP addresses.  Consists of
  41  * a text field for entering new data, paired with a list which allows the
  42  * addresses entered to be ordered or deleted.
  43  */
  44 public class IPAddressList extends JPanel {
  45     IPAddressField address;
  46     JList serverList;
  47     IPAddressListModel serverListModel;
  48     JButton add, delete;
  49     UpButton moveUp;
  50     DownButton moveDown;
  51     
  52     /**
  53      * Construct the address list.
  54      */
  55     public IPAddressList() {
  56         super();
  57         GridBagLayout bag = new GridBagLayout();
  58         setLayout(bag);
  59         
  60         GridBagConstraints c = new GridBagConstraints();
  61         c.gridx = c.gridy = 0;
  62         c.weightx = c.weighty = 1.0;
  63         c.gridheight = 1;
  64         c.gridwidth = 1;
  65         
  66         // Field to type in addresses
  67         address = new IPAddressField();
  68         address.getAccessibleContext().setAccessibleDescription(
  69             ResourceStrings.getString("dhcp_server_address"));
  70 
  71         c.fill = GridBagConstraints.HORIZONTAL;
  72         bag.setConstraints(address, c);
  73         add(address);
  74 
  75         // Button for Add operation
  76         Mnemonic mnAdd = new Mnemonic(ResourceStrings.getString("add"));
  77         add = new JButton(mnAdd.getString());
  78         add.setToolTipText(mnAdd.getString());      
  79         add.setMnemonic(mnAdd.getMnemonic()); 
  80 
  81         c.fill = GridBagConstraints.NONE;
  82         ++c.gridx;
  83         c.weightx = 0.5;
  84         bag.setConstraints(add, c);
  85         add(add);
  86         
  87         // List for addresses
  88         serverListModel = new IPAddressListModel();
  89         serverList = new JList(serverListModel);
  90         // Make sure it's wide enough for our purposes
  91         serverList.setPrototypeCellValue("222.222.222.222");
  92         serverList.setSelectionMode(
  93             ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
  94         JScrollPane scrollPane = new JScrollPane(serverList);
  95         // Don't allow horizontal scrolling here
  96         scrollPane.setHorizontalScrollBarPolicy(
  97             JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  98         c.fill = GridBagConstraints.BOTH;
  99         c.gridx = 0;
 100         ++c.gridy;
 101         c.weightx = 1.0;
 102         bag.setConstraints(scrollPane, c);
 103         add(scrollPane);
 104         
 105         // Buttons to manipulate the list contents
 106         JPanel buttonPanel = new JPanel(new VerticalButtonLayout());
 107         moveUp = new UpButton();
 108         moveUp.setToolTipText(ResourceStrings.getString("move_up"));
 109         buttonPanel.add(moveUp);
 110         moveDown = new DownButton();
 111         moveDown.setToolTipText(ResourceStrings.getString("move_down"));
 112         buttonPanel.add(moveDown);
 113 
 114         Mnemonic mnDelete = new Mnemonic(ResourceStrings.getString("delete"));
 115         delete = new JButton(mnDelete.getString());
 116         delete.setToolTipText(mnDelete.getString());    
 117         delete.setMnemonic(mnDelete.getMnemonic());     
 118 
 119         buttonPanel.add(delete);
 120         ++c.gridx;
 121         c.weightx = 0.5;
 122         bag.setConstraints(buttonPanel, c);
 123         add(buttonPanel);
 124         
 125         // Disable all buttons to start; selection changes adjust button state
 126         add.setEnabled(false);
 127         delete.setEnabled(false);
 128         moveUp.setEnabled(false);
 129         moveDown.setEnabled(false);
 130         
 131         // Create listener for button presses, take action as needed
 132         ActionListener l = new ActionListener() {
 133             public void actionPerformed(ActionEvent e) {
 134                 if (e.getSource() == add || e.getSource() == address) {
 135                     IPAddress a = address.getValue();
 136                     if (a != null) {
 137                         serverListModel.addElement(a);
 138                     }
 139                 } else if (e.getSource() == delete) {
 140                     int [] indices = serverList.getSelectedIndices();
 141                     if (indices.length > 1) {
 142                         /*
 143                          * Need to sort the indices so that the delete's
 144                          * don't interfere with each other
 145                          */
 146                         for (int i = 0; i < indices.length; ++i) {
 147                             for (int j = i; j < indices.length; ++j) {
 148                                 if (indices[i] > indices[j]) {
 149                                     int k = indices[i];
 150                                     indices[i] = indices[j];
 151                                     indices[j] = k;
 152                                 }
 153                             }
 154                         }
 155                     }
 156                     // Now delete from high index to low
 157                     for (int i = indices.length - 1; i >= 0; --i) {
 158                         serverListModel.removeElementAt(indices[i]);
 159                     }
 160                     if (indices.length > 1) {
 161                         // Clear selection if multiple deleted
 162                         serverList.clearSelection();
 163                         /*
 164                          * We don't get a selection event for some reason
 165                          * so make it work for now
 166                          */
 167                         delete.setEnabled(false);
 168                     } else {
 169                         // Make sure to select something in the list
 170                         if (serverListModel.getSize() == 0) {
 171                             /*
 172                              * List is empty, nothing to select so disable
 173                              * delete
 174                              */
 175                             delete.setEnabled(false);
 176                         } else if (indices[0] >= serverListModel.getSize()) {
 177                             // Select last one if we're off the end
 178                             serverList.setSelectedIndex(
 179                                 serverListModel.getSize()-1);
 180                         } else {
 181                             // Select next one in list
 182                             serverList.setSelectedIndex(indices[0]);
 183                         }
 184                     }
 185                 } else if (e.getSource() == moveUp) {
 186                     int i = serverList.getSelectedIndex();
 187                     serverListModel.moveUp(i);
 188                     // Keep item selected so repeated moveUp's affect same item
 189                     serverList.setSelectedIndex(i-1);
 190                 } else if (e.getSource() == moveDown) {
 191                     int i = serverList.getSelectedIndex();
 192                     serverListModel.moveDown(i);
 193                     // Keep item selected so repeated moveDowns affect same item
 194                     serverList.setSelectedIndex(i+1);
 195                 }
 196             }
 197         };
 198         address.addActionListener(l);
 199         add.addActionListener(l);
 200         delete.addActionListener(l);
 201         moveUp.addActionListener(l);
 202         moveDown.addActionListener(l);
 203         
 204         // Put a selection listener on the list to enable buttons appropriately
 205         serverList.addListSelectionListener(new ListSelectionListener() {
 206             public void valueChanged(ListSelectionEvent e) {
 207                 int [] indices = serverList.getSelectedIndices();
 208                 switch (indices.length) {
 209                 case 0:
 210                     // Nothing selected; disable them all
 211                     delete.setEnabled(false);
 212                     moveUp.setEnabled(false);
 213                     moveDown.setEnabled(false);
 214                     break;
 215                 case 1:
 216                     delete.setEnabled(true);
 217                     // Can't move first one up
 218                     if (indices[0] == 0) {
 219                         moveUp.setEnabled(false);
 220                     } else {
 221                         moveUp.setEnabled(true);
 222                     }
 223                     // Can't move last one down
 224                     if (indices[0] == (serverListModel.getSize() - 1)) {
 225                         moveDown.setEnabled(false);
 226                     } else {
 227                         moveDown.setEnabled(true);
 228                     }
 229                     break;
 230                 default:
 231                     // More than one; only delete is allowed
 232                     delete.setEnabled(true);
 233                     moveUp.setEnabled(false);
 234                     moveDown.setEnabled(false);
 235                 }
 236             }
 237         });
 238         // Enable Add when address is not empty.
 239         address.getDocument().addDocumentListener(new DocumentListener() {
 240             public void insertUpdate(DocumentEvent e) {
 241                 add.setEnabled(address.getText().length() != 0);
 242             }
 243             public void changedUpdate(DocumentEvent e) {
 244                 insertUpdate(e);
 245             }
 246             public void removeUpdate(DocumentEvent e) {
 247                 insertUpdate(e);
 248             }
 249         });
 250     }
 251     
 252     /**
 253      * Initialize the data in the list
 254      */
 255     public void setAddressList(IPAddress [] ipAddrs) {
 256         serverListModel.setData(ipAddrs);
 257     }
 258     
 259     /**
 260      * Set the addresses from a comma-delimited string
 261      */
 262     public void setAddressList(String s) {
 263         serverListModel.setData(s);
 264     }
 265     
 266     /** 
 267      * Retrieve the data in the list
 268      */
 269     public Vector getAddressList() {
 270         return serverListModel.getDataVector();
 271     }
 272     
 273     /**
 274      * Retrieve the list converted to a comma-delimited string
 275      */
 276     public String getAddressListString() {
 277         return serverListModel.getDataString();
 278     }
 279     
 280     /**
 281      * Return the size of the list
 282      */
 283     public int getListSize() {
 284         return serverListModel.getDataVector().size();
 285     }
 286 
 287     class IPAddressListModel extends AbstractListModel {
 288         private Vector addrs;
 289         
 290         public IPAddressListModel() {
 291             super();
 292             addrs = new Vector();
 293         }
 294         
 295         public int getSize() {
 296             return addrs.size();
 297         }
 298         
 299         public Object getElementAt(int index) {
 300             return addrs.elementAt(index);
 301         }
 302 
 303         public void setData(IPAddress [] ipAddrs) {
 304             addrs.removeAllElements();
 305             for (int i = 0; i < ipAddrs.length; ++i) {
 306                 addrs.addElement(ipAddrs[i]);
 307             }
 308             fireContentsChanged(this, 0, addrs.size()-1);
 309         }
 310         
 311         public void setData(String s) {
 312             addrs.removeAllElements();
 313             StringTokenizer st = new StringTokenizer(s, ",");
 314             while (st.hasMoreTokens()) {
 315                 try {
 316                     addrs.addElement(new IPAddress(st.nextToken()));
 317                 } catch (ValidationException e) {
 318                     // Ignore it, didn't parse for some reason
 319                 }
 320             }
 321             fireContentsChanged(this, 0, addrs.size()-1);
 322         }
 323         
 324         public void addElement(IPAddress addr) {
 325             addrs.addElement(addr);
 326             fireIntervalAdded(this, addrs.size()-1, addrs.size()-1);
 327         }
 328         
 329         public void removeElementAt(int index) {
 330             addrs.removeElementAt(index);
 331             fireIntervalRemoved(this, index, index);
 332         }
 333         
 334         public void moveUp(int index) {
 335             Object t = addrs.elementAt(index-1);
 336             addrs.setElementAt(addrs.elementAt(index), index-1);
 337             addrs.setElementAt(t, index);
 338             fireContentsChanged(this, index-1, index);
 339         }
 340         
 341         public void moveDown(int index) {
 342             Object t = addrs.elementAt(index+1);
 343             addrs.setElementAt(addrs.elementAt(index), index+1);
 344             addrs.setElementAt(t, index);
 345             fireContentsChanged(this, index, index+1);
 346         }
 347         
 348         public Vector getDataVector() {
 349             return (Vector)addrs.clone();
 350         }
 351         
 352         public String getDataString() {
 353             StringBuffer b = new StringBuffer();
 354             Enumeration en = addrs.elements();
 355             while (en.hasMoreElements()) {
 356                 if (b.length() != 0) {
 357                     b.append(',');
 358                 }
 359                 b.append(((IPAddress)en.nextElement()).getHostAddress());
 360             }
 361             return b.toString();
 362         }
 363     }   
 364 }