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 2004 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.border.*;
32 import javax.swing.event.*;
33 import javax.swing.table.*;
34
35 import java.awt.*;
36 import java.awt.event.*;
37 import java.text.MessageFormat;
38 import java.util.*;
39 import java.beans.PropertyChangeListener;
40 import java.beans.PropertyChangeEvent;
41
42 import com.sun.dhcpmgr.server.*;
43 import com.sun.dhcpmgr.data.*;
44 import com.sun.dhcpmgr.ui.*;
45
46 /**
47 * Dialog to select an option for inclusion in a macro.
48 */
49 public class SelectOptionDialog extends JComponent
50 implements ButtonPanelListener {
51 private JComboBox category;
52 private AutosizingTable optionTable;
53 private ButtonPanel buttonPanel;
54 private OptionTableModel optionTableModel;
55 private TableSorter sortedModel;
56 static final String SELECTED_OPTION = "selected_option";
57 static String value = null;
58 static JDialog dialog;
59 private OptionContext [] categories = {
60 Option.ctxts[Option.STANDARD],
61 Option.ctxts[Option.EXTEND],
62 Option.ctxts[Option.VENDOR],
63 Option.ctxts[Option.SITE]
64 };
65
66 // Model for the table displaying option descriptions
67 class OptionTableModel extends AbstractTableModel {
68 private Option [] data;
69 private ResourceBundle bundle;
70
71 public OptionTableModel() {
72 super();
73 data = new Option[0];
74 // Locate the resource bundle containing the localized descriptions
75 bundle = ResourceBundle.getBundle(
76 "com.sun.dhcpmgr.client.OptionDescriptions",
77 Locale.getDefault());
78 }
79
80 public void setCategory(OptionContext category) {
81 byte code = category.getCode();
82 if (code == Option.ctxts[Option.STANDARD].getCode()) {
83 data = StandardOptions.getAllOptions();
84 } else if (code == Option.ctxts[Option.EXTEND].getCode() ||
85 code == Option.ctxts[Option.SITE].getCode() ||
86 code == Option.ctxts[Option.VENDOR].getCode()) {
87 try {
88 // Get all locally defined options from DataManager
89 Option [] allOptions = DataManager.get().getOptions(false);
90 Vector v = new Vector();
91 // Now filter by the selected type
92 for (int i = 0; i < allOptions.length; ++i) {
93 if (allOptions[i].getContext() == code) {
94 v.addElement(allOptions[i]);
95 }
96 }
97 // Convert to an array
98 data = new Option[v.size()];
99 v.copyInto(data);
100 } catch (Exception e) {
101 data = new Option[0];
102 }
103 }
104 // Tell the sorter things changed
105 sortedModel.reallocateIndexes();
106 fireTableDataChanged();
107 }
108
109 public int getRowCount() {
110 return data.length;
111 }
112
113 public int getColumnCount() {
114 return 2;
115 }
116
117 public Object getValueAt(int row, int column) {
118 if (column == 0) {
119 return data[row].getKey();
120 } else {
121 try {
122 /**
123 * Look up descriptions in the properties file indexed by
124 * option name
125 */
126 return bundle.getString(data[row].getKey());
127 } catch (Exception e) {
128 // Ignore; we just don't have a description for this one
129 return null;
130
131 }
132 }
133 }
134
135 public Class getColumnClass(int column) {
136 return String.class;
137 }
138
139 public String getColumnName(int column) {
140 if (column == 0) {
141 return ResourceStrings.getString("option_column");
142 } else {
143 return ResourceStrings.getString("description_column");
144 }
145 }
146
147 public boolean isCellEditable(int row, int column) {
148 return false;
149 }
150 }
151
152 // Generate the dialog
153 public void createDialog() {
154 dialog = new JDialog((JFrame)null,
155 ResourceStrings.getString("select_option_title"), true);
156
157 dialog.getContentPane().setLayout(new BoxLayout(dialog.getContentPane(),
158 BoxLayout.Y_AXIS));
159
160 // Label and combo box for selecting option category
161 JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
162
163 Mnemonic mnCat =
164 new Mnemonic(ResourceStrings.getString("category_label"));
165 JLabel catLbl =
166 new JLabel(mnCat.getString());
167 panel.add(catLbl);
168 category = new JComboBox(categories);
169
170 catLbl.setLabelFor(category);
171 catLbl.setToolTipText(mnCat.getString());
172 catLbl.setDisplayedMnemonic(mnCat.getMnemonic());
173
174 category.setEditable(false);
175 panel.add(category);
176
177 dialog.getContentPane().add(panel);
178
179 // Table for selecting the options in the given category
180 optionTableModel = new OptionTableModel();
181 // Sort options by name, alphabetically
182 sortedModel = new TableSorter(optionTableModel);
183 sortedModel.sortByColumn(0);
184 // Use an auto-sizing table so descriptions get the space they need
185 optionTable = new AutosizingTable(sortedModel);
186 optionTable.getTableHeader().setReorderingAllowed(false);
187 optionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
188 JScrollPane scrollPane = new JScrollPane(optionTable);
189 panel = new JPanel();
190 panel.add(scrollPane);
191 dialog.getContentPane().add(panel);
192
193 // Put in usual separator and buttons
194 dialog.getContentPane().add(new JSeparator());
195 buttonPanel = new ButtonPanel(false, false);
196 buttonPanel.addButtonPanelListener(this);
197 dialog.getContentPane().add(buttonPanel);
198
199 /*
200 * As user changes category selected, update table to view category
201 * contents
202 */
203 category.addItemListener(new ItemListener() {
204 public void itemStateChanged(ItemEvent e) {
205 updateTable();
206 }
207 });
208
209 // Only enable OK when there is an option selected in the table
210 optionTable.getSelectionModel().addListSelectionListener(
211 new ListSelectionListener() {
212 public void valueChanged(ListSelectionEvent e) {
213 if (optionTable.getSelectedRow() == -1) {
214 buttonPanel.setOkEnabled(false);
215 } else {
216 buttonPanel.setOkEnabled(true);
217 }
218 }
219 });
220
221 // Ensure table displays data for initial selection
222 updateTable();
223 }
224
225 /**
226 * Update the table to the current category selection.
227 */
228 private void updateTable() {
229 optionTableModel.setCategory(categories[category.getSelectedIndex()]);
230 optionTable.clearSelection();
231 }
232
233 public void buttonPressed(int buttonId) {
234 switch (buttonId) {
235 case OK:
236 firePropertyChange(SELECTED_OPTION, null,
237 (String)optionTableModel.getValueAt(
238 sortedModel.mapRowAt(optionTable.getSelectedRow()), 0));
239 break;
240 case CANCEL:
241 firePropertyChange(SELECTED_OPTION, null, null);
242 break;
243 }
244 }
245
246 /**
247 * Here's the way to display this dialog modally and retrieve the value
248 * selected
249 * @param c a component relative to which the dialog should be displayed
250 */
251 public static String showDialog(Component c) {
252 SelectOptionDialog d = new SelectOptionDialog();
253 d.createDialog();
254 /*
255 * When user presses OK or Cancel, retrieve the value and kill the
256 * dialog
257 */
258 d.addPropertyChangeListener(new PropertyChangeListener() {
259 public void propertyChange(PropertyChangeEvent e) {
260 dialog.setVisible(false);
261 dialog.dispose();
262 value = (String)e.getNewValue();
263 }
264 });
265 dialog.setLocationRelativeTo(c);
266 dialog.pack();
267 dialog.setVisible(true);
268 return value;
269 }
270 }