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 }