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 }