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 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28 package com.sun.dhcpmgr.client;
29
30 import javax.swing.*;
31 import javax.swing.event.*;
32 import javax.swing.table.*;
33 import java.awt.*;
34 import java.awt.event.*;
35 import java.util.*;
36 import java.text.*;
37 import java.net.*;
38
39 import com.sun.dhcpmgr.ui.*;
40 import com.sun.dhcpmgr.server.*;
41 import com.sun.dhcpmgr.data.*;
42 import com.sun.dhcpmgr.bridge.BridgeException;
43 import com.sun.dhcpmgr.bridge.NoEntryException;
44
45 /**
46 * Address View displays the networks currently under DHCP management, and
47 * as a network is selected from the list its addresses are displayed.
48 */
49 public class AddressView implements View {
50 private JPanel displayPanel;
51 protected static AutosizingTable addressTable;
52 private JScrollPane addressPane;
53 private boolean firstActivation = true;
54 private NetworkListModel networkListModel;
55 private JList networkList;
56 protected static AddressTableModel addressTableModel = null;
57 private TableSorter sortedTableModel;
58 private JCheckBoxMenuItem showGrid;
59 private JCheckBoxMenuItem showAddresses;
60 private JMenuItem addAddrs;
61 private JMenuItem releaseAddrs;
62 private JMenuItem addNet;
63 private JMenuItem deleteNets;
64 private JMenuItem addressHelp;
65 private Vector[] menuItems;
66 private Frame myFrame;
67 private Vector selectionListeners = new Vector();
68 private int sortModelIndex = -1;
69 private static final String NO_NETWORKS =
70 ResourceStrings.getString("no_networks");
71
72 // Model class for the network list
73 class NetworkListModel extends AbstractListModel {
74 private Object currentValue;
75 private Network data[] = null;
76
77 public void load() {
78 try {
79 MainFrame.setStatusText(
80 ResourceStrings.getString("loading_networks"));
81 data = DataManager.get().getNetworks(true);
82 } catch (Throwable e) {
83 e.printStackTrace();
84 } finally {
85 int len = 0;
86 if (data != null) {
87 len = data.length;
88 }
89 MainFrame.setStatusText(
90 MessageFormat.format(
91 ResourceStrings.getString("networks_loaded"), len));
92 }
93 }
94
95 public void reload() {
96 load();
97 fireContentsChanged(this, -1, -1);
98 }
99
100 public int getSize() {
101 if (data == null) {
102 load();
103 }
104 if (data == null) {
105 return 0;
106 } else {
107 return data.length;
108 }
109 }
110
111 public Object getElementAt(int index) {
112 if (data == null) {
113 load();
114 }
115 if (data == null || index >= data.length) {
116 return "";
117 } else {
118 return data[index].toString();
119 }
120 }
121
122 public Network getNetworkAt(int index) {
123 if (data == null || index >= data.length) {
124 return null;
125 } else {
126 return data[index];
127 }
128 }
129 }
130
131 // Container class for the address data
132 class AddressTableModel extends AbstractTableModel {
133 private DhcpClientRecord [] data;
134 private String network;
135 private boolean showAddresses;
136 private boolean firstLoad;
137
138 public AddressTableModel() {
139 data = null;
140 network = "";
141 showAddresses = false;
142 firstLoad = true;
143 }
144
145 public void load(String network) {
146 data = null;
147 fireTableDataChanged();
148 if (network.length() == 0) {
149 // No network number supplied, so can't load
150 return;
151 }
152 this.network = network;
153
154 // Update the status line
155 Object [] objs = {network};
156 String s = MessageFormat.format(
157 ResourceStrings.getString("loading_addresses"), objs);
158 MainFrame.setStatusText(s);
159
160 // Kick off background loading of addresses
161 AddressLoader loader = new AddressLoader();
162
163 }
164
165 // Loading is done, re-sort and tell the view to repaint
166 protected void doneLoading() {
167 sortedTableModel.reallocateIndexes();
168 if (firstLoad) {
169 sortedTableModel.sortByColumn(0);
170 firstLoad = false;
171 }
172 fireTableDataChanged();
173 }
174
175 protected String getNetwork() {
176 return network;
177 }
178
179 protected void setData(DhcpClientRecord [] newdata) {
180 data = newdata;
181 }
182
183 public void setShowAddresses(boolean state) {
184 showAddresses = state;
185 fireTableStructureChanged();
186 sortedTableModel.sortByColumn(sortModelIndex);
187 }
188
189 public int getRowCount() {
190 if (data == null) {
191 return 0;
192 } else {
193 return data.length;
194 }
195 }
196
197 public int getColumnCount() {
198 return 7;
199 }
200
201 public Object getValueAt(int row, int column) {
202 switch (column) {
203 case 0:
204 if (showAddresses) {
205 return data[row].getClientIP();
206 } else {
207 return data[row].getClientName();
208 }
209 case 1:
210 if (data[row].isUnusable()) {
211 return ResourceStrings.getString("unusable");
212 } else if (data[row].isBootp()) {
213 return ResourceStrings.getString("bootp");
214 } else if (data[row].isManual()) {
215 return ResourceStrings.getString("manual");
216 } else if (data[row].isPermanent()) {
217 return ResourceStrings.getString("permanent");
218 } else {
219 return ResourceStrings.getString("dynamic");
220 }
221 case 2:
222 return data[row].getExpiration();
223 case 3:
224 if (showAddresses) {
225 return data[row].getServerIP();
226 } else {
227 return data[row].getServerName();
228 }
229 case 4:
230 return data[row].getMacro();
231 case 5:
232 return data[row].getClientId();
233 case 6:
234 return data[row].getComment();
235 default:
236 return null;
237 }
238 }
239
240 public Class getColumnClass(int column) {
241 switch (column) {
242 case 0:
243 case 3:
244 if (showAddresses) {
245 return IPAddress.class;
246 } else {
247 return String.class;
248 }
249 case 2:
250 return Date.class;
251 case 1:
252 case 4:
253 case 5:
254 case 6:
255 return String.class;
256 default:
257 return super.getColumnClass(column);
258 }
259 }
260
261 public String getColumnName(int column) {
262 switch (column) {
263 case 0:
264 if (showAddresses) {
265 return ResourceStrings.getString("address_column");
266 } else {
267 return ResourceStrings.getString("client_name_column");
268 }
269 case 1:
270 return ResourceStrings.getString("flags_column");
271 case 2:
272 return ResourceStrings.getString("expires_column");
273 case 3:
274 return ResourceStrings.getString("server_column");
275 case 4:
276 return ResourceStrings.getString("macro_column");
277 case 5:
278 return ResourceStrings.getString("client_column");
279 case 6:
280 return ResourceStrings.getString("comment_column");
281 default:
282 return super.getColumnName(column);
283 }
284 }
285
286 protected DhcpClientRecord getClientAt(int row) {
287 return data[row];
288 }
289 }
290
291 // Background loader for addresses.
292 class AddressLoader extends com.sun.dhcpmgr.ui.SwingWorker {
293 public Object construct() {
294 try {
295 String net = addressTableModel.getNetwork();
296 return DataManager.get().getClients(net, true);
297 } catch (final BridgeException e) {
298 // Since we're in a background thread, ask Swing to run ASAP.
299 SwingUtilities.invokeLater(new Runnable() {
300 Object [] args = new Object[] { e.getMessage() };
301 public void run() {
302 MessageFormat form = new MessageFormat(
303 ResourceStrings.getString("error_loading_addrs"));
304 JOptionPane.showMessageDialog(null, form.format(args),
305 ResourceStrings.getString("server_error_title"),
306 JOptionPane.ERROR_MESSAGE);
307 }
308 });
309 }
310 return null;
311 }
312
313 public void finished() {
314 addressTableModel.setData((DhcpClientRecord [])get());
315 addressTableModel.doneLoading();
316 MainFrame.setStatusText(
317 MessageFormat.format(
318 ResourceStrings.getString("address_status_message"),
319 addressTableModel.getRowCount()));
320 addressTable.clearSelection();
321 }
322 }
323
324 // Renderer class used to make unusable addresses bold in the display
325 class AddressTableCellRenderer extends ExtendedCellRenderer {
326 public Component getTableCellRendererComponent(JTable table,
327 Object value, boolean isSelected, boolean hasFocus, int row,
328 int column) {
329 Component c = super.getTableCellRendererComponent(table, value,
330 isSelected, hasFocus, row, column);
331 int modelRow = sortedTableModel.mapRowAt(row);
332 if (modelRow != -1) {
333 if (addressTableModel.getClientAt(modelRow).isUnusable()) {
334 Font f = c.getFont();
335 c.setFont(new Font(f.getName(), Font.BOLD, f.getSize()));
336 }
337 }
338 return c;
339 }
340 }
341
342 // Recipient of update messages sent when the editing dialogs exit
343 class DialogListener implements ActionListener {
344 public void actionPerformed(ActionEvent e) {
345 // Don't reload if cancel happened
346 if (!e.getActionCommand().equals(DialogActions.CANCEL)) {
347 AddressView.this.reload();
348 }
349 }
350 }
351
352 public AddressView() {
353 displayPanel = new JPanel(new BorderLayout());
354
355 // Create network selection list, tie it to table
356 networkListModel = new NetworkListModel();
357 networkList = new JList(networkListModel);
358 networkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
359 networkList.addListSelectionListener(new ListSelectionListener() {
360 public void valueChanged(ListSelectionEvent e) {
361 // Ignore all but the last in a series of these events
362 if (e.getValueIsAdjusting()) {
363 return;
364 }
365 String net = "";
366 int index = networkList.getSelectedIndex();
367 if (index != -1) {
368 net = (String)networkListModel.getElementAt(
369 networkList.getSelectedIndex());
370 }
371 if (net.length() == 0) {
372 // No networks are selected; disable menu items
373 deleteNets.setEnabled(false);
374 addAddrs.setEnabled(false);
375 showAddresses.setEnabled(false);
376 showGrid.setEnabled(false);
377 } else {
378 deleteNets.setEnabled(true);
379 addAddrs.setEnabled(true);
380 showAddresses.setEnabled(true);
381 showGrid.setEnabled(true);
382 }
383 addressTableModel.load(net);
384 }
385 });
386
387 // Use a prototype value as a performance enhancement
388 networkList.setPrototypeCellValue("222.222.222.222");
389 JScrollPane networkPane = new JScrollPane(networkList);
390 JPanel networkPanel = new JPanel(new BorderLayout());
391 networkPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
392
393 Mnemonic mnNetwork = new Mnemonic(ResourceStrings.getString("network"));
394 JLabel nwLbl = new JLabel(mnNetwork.getString());
395 nwLbl.setLabelFor(networkPanel);
396 nwLbl.setToolTipText(mnNetwork.getString());
397 networkPanel.add(nwLbl, BorderLayout.NORTH);
398 nwLbl.setDisplayedMnemonic(mnNetwork.getMnemonic());
399
400 networkPanel.add(networkPane, BorderLayout.CENTER);
401 displayPanel.add(networkPanel, BorderLayout.WEST);
402
403 // Create table to display in data area
404 addressTableModel = new AddressTableModel();
405 sortedTableModel = new TableSorter(addressTableModel);
406 addressTable = new AutosizingTable(sortedTableModel);
407 sortedTableModel.addMouseListenerToHeaderInTable(addressTable);
408 addressTable.getTableHeader().setReorderingAllowed(true);
409 addressTable.getTableHeader().setResizingAllowed(true);
410 addressTable.setSelectionMode(
411 ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
412
413 sortedTableModel.addActionListener(new ActionListener() {
414 private SortedHeaderRenderer sortedRenderer =
415 new SortedHeaderRenderer(addressTable);
416 private TableCellRenderer savedRenderer;
417 public void actionPerformed(ActionEvent e) {
418 // Clear the selection when sorting is changed
419 addressTable.clearSelection();
420 /*
421 * Change the header rendering to show which column is
422 * being used for sorting of the data.
423 */
424 int modelIndex = Integer.parseInt(e.getActionCommand());
425 int viewIndex =
426 addressTable.convertColumnIndexToView(modelIndex);
427 if (sortModelIndex != -1) {
428 int sortViewIndex =
429 addressTable.convertColumnIndexToView(sortModelIndex);
430 addressTable.getColumnModel().getColumn(
431 sortViewIndex).setHeaderRenderer(savedRenderer);
432 }
433 /*
434 * Save the column currently being sorted so we can restore
435 * the renderer later. We save model columns rather than
436 * view columns because model columns are invariant while
437 * view columns can be reordered with confusion resulting.
438 */
439 TableColumn c =
440 addressTable.getColumnModel().getColumn(viewIndex);
441 savedRenderer = c.getHeaderRenderer();
442 c.setHeaderRenderer(sortedRenderer);
443 sortModelIndex = modelIndex;
444 }
445 });
446
447 // Make double-clicks the same as Edit->Properties
448 addressTable.addMouseListener(new MouseAdapter() {
449 public void mouseClicked(MouseEvent e) {
450 if (e.getClickCount() == 2) {
451 handleProperties();
452 }
453 }
454 });
455
456 // Install custom renderer to bold the entries which are unusable
457 TableCellRenderer renderer = new AddressTableCellRenderer();
458 addressTable.setDefaultRenderer(String.class, renderer);
459 addressTable.setDefaultRenderer(IPAddress.class, renderer);
460 addressTable.setDefaultRenderer(Date.class, renderer);
461
462 // Wrap it in a scroll pane
463 addressPane = new JScrollPane(addressTable);
464
465 displayPanel.add(addressPane, BorderLayout.CENTER);
466
467 // Create menu items
468 Mnemonic mnShowAddrs =
469 new Mnemonic(ResourceStrings.getString("show_addresses"));
470 showAddresses = new JCheckBoxMenuItem(mnShowAddrs.getString(),
471 false);
472 showAddresses.setMnemonic(mnShowAddrs.getMnemonic());
473 showAddresses.addActionListener(new ActionListener() {
474 public void actionPerformed(ActionEvent e) {
475 addressTableModel.setShowAddresses(showAddresses.getState());
476 }
477 });
478
479 Mnemonic mnShowGrid =
480 new Mnemonic(ResourceStrings.getString("show_grid"));
481 showGrid = new JCheckBoxMenuItem(mnShowGrid.getString(),
482 true);
483 showGrid.setMnemonic(mnShowGrid.getMnemonic());
484 showGrid.addActionListener(new ActionListener() {
485 public void actionPerformed(ActionEvent e) {
486 addressTable.setShowGrid(showGrid.getState());
487 }
488 });
489
490 Mnemonic mnAddNet =
491 new Mnemonic(ResourceStrings.getString("add_network"));
492 addNet = new JMenuItem(mnAddNet.getString());
493 addNet.setMnemonic(mnAddNet.getMnemonic());
494 addNet.addActionListener(new ActionListener() {
495 public void actionPerformed(ActionEvent e) {
496 ConfigWizard wiz = new ConfigWizard(myFrame,
497 ResourceStrings.getString("net_wiz_title"), false);
498 wiz.addActionListener(new ActionListener() {
499 public void actionPerformed(ActionEvent e) {
500 if (e.getActionCommand().equals("finished")) {
501 reload();
502 }
503 }
504 });
505 wiz.pack();
506 wiz.setVisible(true);
507 }
508 });
509
510
511 Mnemonic mnDelNets =
512 new Mnemonic(ResourceStrings.getString("delete_networks"));
513 deleteNets = new JMenuItem(mnDelNets.getString());
514 deleteNets.setMnemonic(mnDelNets.getMnemonic());
515 deleteNets.addActionListener(new ActionListener() {
516 public void actionPerformed(ActionEvent e) {
517 DeleteNetworksDialog d = new DeleteNetworksDialog(myFrame);
518 d.addActionListener(new ActionListener() {
519 public void actionPerformed(ActionEvent e) {
520 if (e.getActionCommand().equals(DialogActions.OK)) {
521 reload();
522 }
523 }
524 });
525 d.pack();
526 d.setVisible(true);
527 }
528 });
529
530 Mnemonic mnAddAddr =
531 new Mnemonic(ResourceStrings.getString("add_addresses"));
532 addAddrs = new JMenuItem(mnAddAddr.getString());
533 addAddrs.setMnemonic(mnAddAddr.getMnemonic());
534 addAddrs.setEnabled(false); // Start out disabled
535 addAddrs.addActionListener(new ActionListener() {
536 public void actionPerformed(ActionEvent e) {
537 AddressWizard wiz = new AddressWizard(myFrame,
538 networkListModel.getNetworkAt(
539 networkList.getSelectedIndex()));
540 wiz.addActionListener(new DialogListener());
541 wiz.pack();
542 wiz.setVisible(true);
543 }
544 });
545
546 Mnemonic mnRelAddr =
547 new Mnemonic(ResourceStrings.getString("release_addresses"));
548 releaseAddrs = new JMenuItem(mnRelAddr.getString());
549 releaseAddrs.setMnemonic(mnRelAddr.getMnemonic());
550 releaseAddrs.setEnabled(false); // Start out disabled
551 releaseAddrs.addActionListener(new ActionListener() {
552 public void actionPerformed(ActionEvent e) {
553 int [] rows = addressTable.getSelectedRows();
554 if (rows.length == 0) {
555 return;
556 }
557 DhcpClientRecord [] recs = new DhcpClientRecord[rows.length];
558 for (int i = 0; i < rows.length; ++i) {
559 recs[i] = addressTableModel.getClientAt(
560 sortedTableModel.mapRowAt(rows[i]));
561 }
562 ReleaseAddressDialog d = new ReleaseAddressDialog(myFrame, recs,
563 (String)networkListModel.getElementAt(
564 networkList.getSelectedIndex()),
565 showAddresses.isSelected());
566 d.addActionListener(new DialogListener());
567 d.pack();
568 d.setVisible(true);
569 }
570 });
571
572 Mnemonic mnOnAddrs =
573 new Mnemonic(ResourceStrings.getString("on_addresses_item"));
574 addressHelp = new JMenuItem(mnOnAddrs.getString());
575 addressHelp.setMnemonic(mnOnAddrs.getMnemonic());
576 addressHelp.addActionListener(new ActionListener() {
577 public void actionPerformed(ActionEvent e) {
578 DhcpmgrApplet.showHelp("addresses_reference");
579 }
580 });
581
582 /*
583 * Construct the menu lists
584 */
585 menuItems = new Vector[MainFrame.MENU_COUNT];
586 for (int i = 0; i < menuItems.length; ++i) {
587 menuItems[i] = new Vector();
588 }
589 menuItems[MainFrame.VIEW_MENU].addElement(showAddresses);
590 menuItems[MainFrame.VIEW_MENU].addElement(showGrid);
591 menuItems[MainFrame.EDIT_MENU].addElement(addAddrs);
592 menuItems[MainFrame.EDIT_MENU].addElement(releaseAddrs);
593 menuItems[MainFrame.EDIT_MENU].addElement(addNet);
594 menuItems[MainFrame.EDIT_MENU].addElement(deleteNets);
595 menuItems[MainFrame.HELP_MENU].addElement(addressHelp);
596
597 // Listen for selections events, manipulate menu item state as needed
598 addressTable.getSelectionModel().addListSelectionListener(
599 new ListSelectionListener() {
600 public void valueChanged(ListSelectionEvent e) {
601 if (addressTable.getSelectionModel().isSelectionEmpty()) {
602 // Disable menu items
603 releaseAddrs.setEnabled(false);
604 } else {
605 // Enable menu items
606 releaseAddrs.setEnabled(true);
607 }
608 // Notify listeners that our selection state may have changed
609 notifySelectionListeners();
610 }
611 });
612 }
613
614 public String getName() {
615 return ResourceStrings.getString("address_view_name");
616 }
617
618 // Return custom menus for this view, which is nothing at this time
619 public Enumeration menus() {
620 return null;
621 }
622
623 // Return custom menu items for each menu as requested.
624 public Enumeration menuItems(int menu) {
625 return menuItems[menu].elements();
626 }
627
628 public Component getDisplay() {
629 return displayPanel;
630 }
631
632 public void setActive(boolean state) {
633 if (state) {
634 if (firstActivation) {
635 // Find frame we're in for use when creating dialogs
636 myFrame = (Frame)SwingUtilities.getAncestorOfClass(
637 MainFrame.class, addressTable);
638 if (networkListModel.getSize() != 0) {
639 networkList.setSelectedIndex(0);
640 }
641 firstActivation = false;
642 } else {
643 // Clear any messages left from other views
644 MainFrame.setStatusText("");
645 }
646 }
647 }
648
649 // Handle a find
650 public void find(String s) {
651 int startRow = addressTable.getSelectedRow() + 1;
652 for (int i = startRow; i < sortedTableModel.getRowCount(); ++i) {
653 DhcpClientRecord rec =
654 addressTableModel.getClientAt(sortedTableModel.mapRowAt(i));
655 if (rec.getClientName().indexOf(s) != -1 ||
656 rec.toString().indexOf(s) != -1) {
657 addressTable.setRowSelectionInterval(i, i);
658 addressTable.scrollRectToVisible(
659 addressTable.getCellRect(i, 0, false));
660 return;
661 }
662 }
663 // Got to the end, wrap around
664 for (int i = 0; i < startRow; ++i) {
665 DhcpClientRecord rec =
666 addressTableModel.getClientAt(sortedTableModel.mapRowAt(i));
667 if (rec.getClientName().indexOf(s) != -1 ||
668 rec.toString().indexOf(s) != -1) {
669 addressTable.setRowSelectionInterval(i, i);
670 addressTable.scrollRectToVisible(
671 addressTable.getCellRect(i, 0, false));
672 return;
673 }
674 }
675 }
676
677 public void handleCreate() {
678 if (networkList.getSelectedIndex() == -1) {
679 // Tell user to use Network Wizard
680 JOptionPane.showMessageDialog(myFrame,
681 ResourceStrings.getString("run_network_wizard"),
682 ResourceStrings.getString("error_message"),
683 JOptionPane.ERROR_MESSAGE);
684 } else {
685 CreateAddressDialog d = new CreateAddressDialog(myFrame,
686 CreateAddressDialog.CREATE, new DhcpClientRecord(),
687 networkListModel.getNetworkAt(networkList.getSelectedIndex()));
688 d.addActionListener(new DialogListener());
689 d.pack();
690 d.setVisible(true);
691 }
692 }
693
694 public void handleDelete() {
695 int [] rows = addressTable.getSelectedRows();
696 if (rows.length == 0) {
697 return;
698 }
699 DhcpClientRecord [] recs = new DhcpClientRecord[rows.length];
700 for (int i = 0; i < rows.length; ++i) {
701 recs[i] = addressTableModel.getClientAt(
702 sortedTableModel.mapRowAt(rows[i]));
703 }
704 DeleteAddressDialog d = new DeleteAddressDialog(myFrame, recs,
705 (String)networkListModel.getElementAt(
706 networkList.getSelectedIndex()));
707 d.addActionListener(new DialogListener());
708 d.pack();
709 d.setVisible(true);
710 }
711
712 public void handleDuplicate() {
713 int row = addressTable.getSelectedRow();
714 if (row == -1) {
715 return;
716 }
717 DhcpClientRecord rec =
718 addressTableModel.getClientAt(sortedTableModel.mapRowAt(row));
719 if (rec == null) {
720 return;
721 }
722 CreateAddressDialog d = new CreateAddressDialog(myFrame,
723 CreateAddressDialog.DUPLICATE, (DhcpClientRecord)rec.clone(),
724 networkListModel.getNetworkAt(networkList.getSelectedIndex()));
725 d.addActionListener(new DialogListener());
726 d.pack();
727 d.setVisible(true);
728 }
729
730 public void handleProperties() {
731 int [] rows = addressTable.getSelectedRows();
732 if (rows.length == 0) {
733 return;
734 }
735 DhcpClientRecord [] recs = new DhcpClientRecord[rows.length];
736 for (int i = 0; i < rows.length; ++i) {
737 recs[i] =
738 addressTableModel.getClientAt(
739 sortedTableModel.mapRowAt(rows[i]));
740 }
741 if (recs.length == 1) {
742 // Edit a single address
743 CreateAddressDialog d = new CreateAddressDialog(myFrame,
744 CreateAddressDialog.EDIT, (DhcpClientRecord)recs[0].clone(),
745 networkListModel.getNetworkAt(networkList.getSelectedIndex()));
746 d.addActionListener(new DialogListener());
747 d.pack();
748 d.setVisible(true);
749 } else {
750 // Edit a group of addresses
751 ModifyAddressesDialog d = new ModifyAddressesDialog(myFrame, recs,
752 (String)networkListModel.getElementAt(
753 networkList.getSelectedIndex()));
754 d.addActionListener(new DialogListener());
755 d.pack();
756 d.setVisible(true);
757 }
758 }
759
760 public void handleUpdate() {
761 reload();
762 }
763
764 protected void reload() {
765 Object value = networkList.getSelectedValue();
766 networkListModel.reload();
767 networkList.clearSelection();
768 networkList.setSelectedValue(value, true);
769 if (networkListModel.getSize() != 0 &&
770 networkList.getSelectedIndex() == -1) {
771 // Didn't get selected, must be gone. Select first item in list
772 networkList.setSelectedIndex(0);
773 }
774 }
775
776 public void addSelectionListener(SelectionListener listener) {
777 selectionListeners.addElement(listener);
778 }
779
780 public void removeSelectionListener(SelectionListener listener) {
781 selectionListeners.removeElement(listener);
782 }
783
784 private void notifySelectionListeners() {
785 Enumeration en = selectionListeners.elements();
786 while (en.hasMoreElements()) {
787 SelectionListener l = (SelectionListener)en.nextElement();
788 l.valueChanged();
789 }
790 }
791
792 public boolean isSelectionEmpty() {
793 return addressTable.getSelectionModel().isSelectionEmpty();
794 }
795
796 public boolean isSelectionMultiple() {
797 return (addressTable.getSelectedRowCount() > 1);
798 }
799
800 public void startAddressWizard() {
801 addAddrs.doClick();
802 }
803 }