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 }