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 1998-2002 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 package com.sun.dhcpmgr.ui; 29 30 import javax.swing.*; 31 import javax.swing.event.*; 32 import java.awt.*; 33 import java.awt.event.*; 34 import java.util.*; 35 import java.net.URL; 36 37 /** 38 * A main window container for an application which glues together multiple sets 39 * of functionality (called Views) into a whole with a single menu bar, 40 * status bar, and search functionality. 41 * @see View 42 */ 43 public class MainFrame extends JFrame { 44 45 class StatusBar extends JPanel { 46 private JLabel data; 47 private FindPanel finder; 48 49 public StatusBar() { 50 super(new BorderLayout()); 51 setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); 52 data = new JLabel("", SwingConstants.LEFT); 53 Font f = data.getFont(); 54 Font f2 = new Font(f.getName(), Font.PLAIN, f.getSize()); 55 data.setFont(f2); 56 data.setForeground(Color.black); 57 data.setLabelFor(this); 58 add(data, BorderLayout.WEST); 59 finder = new FindPanel(); 60 add(finder, BorderLayout.EAST); 61 } 62 63 public void setText(String s) { 64 data.setText(s); 65 data.setToolTipText(s); 66 // Force a relayout to avoid truncating text if longer 67 invalidate(); 68 validate(); 69 } 70 71 public String getText() { 72 return data.getText(); 73 } 74 } 75 76 /** 77 * The panel with the Find control 78 */ 79 class FindPanel extends JPanel implements ActionListener { 80 private JTextField text; 81 private JButton button; 82 83 public void actionPerformed(ActionEvent e) { 84 activeView.find(text.getText()); 85 } 86 87 public FindPanel() { 88 text = new JTextField("", 20); 89 90 Mnemonic mnNext = 91 new Mnemonic(ResourceStrings.getString("next_button")); 92 button = new JButton(mnNext.getString()); 93 button.setToolTipText(mnNext.getString()); 94 button.setMnemonic(mnNext.getMnemonic()); 95 96 button.addActionListener(this); 97 text.addActionListener(this); 98 99 Mnemonic mnFind = 100 new Mnemonic(ResourceStrings.getString("find_label")); 101 JLabel findLbl = new JLabel(mnFind.getString()); 102 findLbl.setLabelFor(text); 103 findLbl.setToolTipText(mnFind.getString()); 104 findLbl.setDisplayedMnemonic(mnFind.getMnemonic()); 105 add(findLbl); 106 107 add(text); 108 add(button); 109 } 110 } 111 112 // Handler for the File->Exit menu item 113 class ExitAction extends MnemonicAction { 114 public ExitAction() { 115 super(ResourceStrings.getString("exit_item")); 116 } 117 118 public void actionPerformed(ActionEvent e) { 119 setVisible(false); 120 dispose(); 121 } 122 } 123 124 // Handler for Edit->Create menu item 125 class CreateAction extends MnemonicAction { 126 public CreateAction() { 127 super(ResourceStrings.getString("create_item")); 128 } 129 130 public void actionPerformed(ActionEvent e) { 131 activeView.handleCreate(); 132 } 133 } 134 135 // Handler for the Edit->Delete menu item 136 class DeleteAction extends MnemonicAction { 137 public DeleteAction() { 138 super(ResourceStrings.getString("delete_item")); 139 } 140 141 public void actionPerformed(ActionEvent e) { 142 activeView.handleDelete(); 143 } 144 } 145 146 // Handler for the Edit->Duplicate menu item 147 class DuplicateAction extends MnemonicAction { 148 public DuplicateAction() { 149 super(ResourceStrings.getString("duplicate_item")); 150 } 151 152 public void actionPerformed(ActionEvent e) { 153 activeView.handleDuplicate(); 154 } 155 } 156 157 // Handler for the Edit->Properties menu item 158 class PropertiesAction extends MnemonicAction { 159 public PropertiesAction() { 160 super(ResourceStrings.getString("properties_item")); 161 } 162 163 public void actionPerformed(ActionEvent e) { 164 activeView.handleProperties(); 165 } 166 } 167 168 // Handler for the View->Update menu item 169 class UpdateAction extends MnemonicAction { 170 public UpdateAction() { 171 super(ResourceStrings.getString("update_item")); 172 } 173 174 public void actionPerformed(ActionEvent e) { 175 activeView.handleUpdate(); 176 } 177 } 178 179 // Listener for selection events from the views 180 class ViewSelectionListener implements SelectionListener { 181 public void valueChanged() { 182 // Set menu item state on edit menu 183 for (int i = 1; i < menuActions[EDIT_MENU].length; ++i) { 184 if (i == 2) { 185 // Duplicate can only be active for a single selection 186 menuActions[EDIT_MENU][i].setEnabled( 187 !activeView.isSelectionEmpty() 188 && !activeView.isSelectionMultiple()); 189 } else { 190 menuActions[EDIT_MENU][i].setEnabled( 191 !activeView.isSelectionEmpty()); 192 } 193 } 194 } 195 } 196 197 public static final int FILE_MENU = 0; 198 public static final int EDIT_MENU = 1; 199 public static final int VIEW_MENU = 2; 200 public static final int ACTIONS_MENU = 3; 201 public static final int HELP_MENU = 4; 202 public static final int MENU_COUNT = 5; 203 // The set of menus for the application 204 private static String menuKeys[] = { "file_menu", "edit_menu", "view_menu", 205 "actions_menu", "help_menu" }; 206 /* 207 * Table of all the menu actions owned by MainFrame; some end up 208 * delegating to the View. 209 */ 210 private Action [] [] menuActions = { 211 // File Menu 212 { new ExitAction() }, 213 214 // Edit Menu 215 { new CreateAction(), new DeleteAction(), new DuplicateAction(), 216 new PropertiesAction() }, 217 // View Menu 218 { new UpdateAction() }, 219 220 // Actions Menu 221 { }, 222 223 // Help Menu 224 { } 225 }; 226 private JMenuBar menuBar; 227 private JMenu menuList[]; 228 private static StatusBar statusBar; 229 private Component display = null; 230 private JTabbedPane displayPanel; 231 private View activeView, initialView; 232 private Vector views; 233 private int [] separatorIndex = new int[MENU_COUNT]; 234 private ButtonGroup viewButtonGroup = new ButtonGroup(); 235 private ViewSelectionListener viewSelectionListener = 236 new ViewSelectionListener(); 237 private boolean initialized = false; 238 239 public MainFrame() { 240 this(""); 241 } 242 243 public MainFrame(String title) { 244 super(title); 245 views = new Vector(); 246 Container contentPane = getContentPane(); 247 // Create basic menu structure 248 menuBar = new JMenuBar(); 249 menuList = new JMenu[menuKeys.length]; 250 // First the menus 251 for (int i = 0; i < menuList.length; ++i) { 252 Mnemonic m = new Mnemonic(ResourceStrings.getString(menuKeys[i])); 253 menuList[i] = (JMenu)menuBar.add(new JMenu(m.getString())); 254 menuList[i].setMnemonic(m.getMnemonic()); 255 } 256 // Now the items on each menu 257 for (int i = 0; i < menuActions.length; ++i) { 258 for (int j = 0; j < menuActions[i].length; ++j) { 259 menuList[i].add(menuActions[i][j]); 260 } 261 } 262 263 // separatorIndex will remember where we automatically put separators 264 for (int i = 0; i < MENU_COUNT; ++i) { 265 separatorIndex[i] = -1; 266 } 267 268 setJMenuBar(menuBar); 269 contentPane.setLayout(new BorderLayout()); 270 271 // Status bar for messages 272 statusBar = new StatusBar(); 273 contentPane.add(statusBar, BorderLayout.SOUTH); 274 275 // Display panel is the area for the view's main display 276 displayPanel = new JTabbedPane(); 277 displayPanel.addChangeListener(new ChangeListener() { 278 public void stateChanged(ChangeEvent e) { 279 /* 280 * Prevent premature activation of a view which would otherwise 281 * happen as a byproduct of adding views to the tabbed pane. 282 */ 283 if (initialized) { 284 try { 285 setActiveView((View)views.elementAt( 286 displayPanel.getSelectedIndex())); 287 } catch (Throwable t) { 288 t.printStackTrace(); 289 } 290 } 291 } 292 }); 293 contentPane.add(displayPanel, BorderLayout.CENTER); 294 activeView = null; 295 } 296 297 public static String getStatusText() { 298 return statusBar.getText(); 299 } 300 301 public static void setStatusText(String text) { 302 statusBar.setText(text); 303 } 304 305 // Add a global menu 306 public void addMenuAction(int menu, Action action) { 307 menuList[menu].add(action); 308 } 309 310 // Add a view to the system 311 public void addView(View v, boolean isInitial) { 312 views.addElement(v); 313 displayPanel.addTab(v.getName(), v.getDisplay()); 314 if (isInitial) { 315 initialView = v; 316 } 317 318 /* 319 * Listen to selection events from the view, update menu state 320 * accordingly 321 */ 322 v.addSelectionListener(viewSelectionListener); 323 } 324 325 // Delete a view 326 public void deleteView(View v) { 327 views.removeElement(v); 328 /* 329 * If we're deleting the currently active view, need to activate 330 * another one; default to the initial view, unless that is also 331 * the one we're deleting, in which case just pick the first view. 332 */ 333 if (v == activeView) { 334 if (v != initialView) { 335 setActiveView(initialView); 336 } else { 337 setActiveView((View)views.firstElement()); 338 } 339 } 340 displayPanel.remove(v.getDisplay()); 341 v.removeSelectionListener(viewSelectionListener); 342 } 343 344 // Select the view to be shown 345 public void setActiveView(View v) { 346 if (activeView != null) { 347 activeView.setActive(false); 348 } 349 // Remove custom menus from existing active view 350 for (int i = MENU_COUNT + 1; i < menuBar.getMenuCount(); ++i) { 351 menuBar.remove(i); 352 } 353 /* 354 * Remove menu items on standard menus from existing active view, 355 * add those from new view 356 */ 357 for (int i = 0; i < menuList.length; ++i) { 358 JMenu m = menuBar.getMenu(i); 359 if (activeView != null) { 360 Enumeration e = activeView.menuItems(i); 361 if (e != null) { 362 if (separatorIndex[i] != -1) { 363 m.remove(separatorIndex[i]); 364 separatorIndex[i] = -1; 365 } 366 while (e.hasMoreElements()) { 367 JMenuItem mi = (JMenuItem)e.nextElement(); 368 if (mi != null) { 369 m.remove((Component)mi); 370 } 371 } 372 } 373 } 374 Enumeration e = v.menuItems(i); 375 if (e != null) { 376 while (e.hasMoreElements()) { 377 /* 378 * This test here so separator is only added if we 379 * actually get a menu item from the view, protecting 380 * against an empty enumeration causing a stray separator. 381 */ 382 if (separatorIndex[i] == -1) { 383 separatorIndex[i] = m.getItemCount(); 384 m.addSeparator(); 385 } 386 JMenuItem mi = (JMenuItem)e.nextElement(); 387 if (mi != null) { 388 m.add(mi); 389 } 390 } 391 } 392 } 393 394 // Add view's menus 395 Enumeration e = v.menus(); 396 while ((e != null) && e.hasMoreElements()) { 397 JMenu m = (JMenu)e.nextElement(); 398 if (m != null) { 399 menuBar.add(m); 400 } 401 } 402 activeView = v; 403 activeView.setActive(true); 404 viewSelectionListener.valueChanged(); 405 invalidate(); 406 validate(); 407 } 408 409 // Call this to get things started 410 public void initialize() { 411 if (initialView != null) { 412 setActiveView(initialView); 413 initialized = true; 414 } 415 } 416 417 // Set enabled/disabled state for menus 418 public void setMenuEnabled(int menu, boolean state) { 419 menuList[menu].setEnabled(state); 420 } 421 422 // Refresh all views, including those not currently active 423 public void refreshAllViews() { 424 for (Enumeration en = views.elements(); en.hasMoreElements(); ) { 425 View v = (View)en.nextElement(); 426 v.handleUpdate(); 427 } 428 } 429 }