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 }