001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.ui; 028 029import static org.opends.messages.AdminToolMessages.*; 030 031import java.awt.Color; 032import java.awt.Component; 033import java.awt.Container; 034import java.awt.GridBagConstraints; 035import java.awt.GridBagLayout; 036import java.awt.Insets; 037import java.awt.event.ActionEvent; 038import java.awt.event.ActionListener; 039import java.awt.event.FocusAdapter; 040import java.awt.event.FocusEvent; 041import java.awt.event.FocusListener; 042import java.awt.event.KeyEvent; 043import java.awt.event.WindowAdapter; 044import java.awt.event.WindowEvent; 045 046import javax.swing.AbstractButton; 047import javax.swing.BorderFactory; 048import javax.swing.Box; 049import javax.swing.JButton; 050import javax.swing.JComboBox; 051import javax.swing.JComponent; 052import javax.swing.JDialog; 053import javax.swing.JFrame; 054import javax.swing.JList; 055import javax.swing.JMenuBar; 056import javax.swing.JPanel; 057import javax.swing.JScrollPane; 058import javax.swing.JTable; 059import javax.swing.JViewport; 060import javax.swing.KeyStroke; 061import javax.swing.SwingUtilities; 062import javax.swing.border.EmptyBorder; 063import javax.swing.text.JTextComponent; 064 065import org.opends.guitools.controlpanel.util.Utilities; 066import org.opends.server.util.DynamicConstants; 067 068/** 069 * The generic dialog of the Control Panel. It contains a StatusGenericPanel. 070 */ 071public class GenericDialog extends JDialog 072{ 073 private static final long serialVersionUID = -2643144936460484112L; 074 private static final Color buttonPanelBackground = 075 ColorAndFontConstants.greyBackground; 076 private JButton okButton; 077 078 /** The close button. */ 079 protected JButton closeButton; 080 private JButton cancelButton; 081 /** The panel contained in the dialog. */ 082 protected StatusGenericPanel panel; 083 private Component lastComponentWithFocus; 084 085 /** The different combinations of buttons that the dialog can have. */ 086 public enum ButtonType 087 { 088 /** The dialog contains OK and CANCEL buttons. */ 089 OK_CANCEL, 090 /** The dialog contains a OK button. */ 091 OK, 092 /** The dialog contains a CLOSE button. */ 093 CLOSE, 094 /** The dialog has no buttons. */ 095 NO_BUTTON 096 } 097 098 /** 099 * Constructor of the dialog. 100 * @param parentFrame the parent frame of the dialog. 101 * @param panel the panel contained in this dialog. 102 */ 103 public GenericDialog(JFrame parentFrame, StatusGenericPanel panel) 104 { 105 super(parentFrame); 106 this.panel = panel; 107 if (panel.requiresBorder()) 108 { 109 setDefaultBorder(panel); 110 } 111 JMenuBar menu = panel.getMenuBar(); 112 if (menu != null) 113 { 114 parentFrame.setJMenuBar(menu); 115 } 116 setResizable(true); 117 JScrollPane scroll = Utilities.createScrollPane(panel); 118 JPanel inputPanel = new JPanel(new GridBagLayout()); 119 setContentPane(inputPanel); 120 GridBagConstraints gbc = new GridBagConstraints(); 121 gbc.weightx = 1.0; 122 gbc.weighty = 1.0; 123 gbc.gridx = 0; 124 gbc.gridy = 0; 125 gbc.fill = GridBagConstraints.BOTH; 126 if (panel.requiresScroll()) 127 { 128 inputPanel.add(scroll, gbc); 129 } 130 else 131 { 132 inputPanel.add(panel, gbc); 133 } 134 if (panel.getButtonType() != ButtonType.NO_BUTTON) 135 { 136 gbc.gridy ++; 137 gbc.weighty = 0.0; 138 inputPanel.add(createButtonsPanel(panel), gbc); 139 } 140 141 KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); 142 ActionListener actionListener = new ActionListener() 143 { 144 /** {@inheritDoc} */ 145 public void actionPerformed(ActionEvent ev) 146 { 147 setVisible(false); 148 } 149 }; 150 getRootPane().registerKeyboardAction(actionListener, stroke, 151 JComponent.WHEN_IN_FOCUSED_WINDOW); 152 153 FocusListener focusListener = new FocusAdapter() 154 { 155 /** {@inheritDoc} */ 156 public void focusGained(FocusEvent ev) 157 { 158 lastComponentWithFocus = ev.getComponent(); 159 } 160 }; 161 addFocusListener(focusListener, panel); 162 163 addWindowListener(new WindowAdapter() { 164 /** {@inheritDoc} */ 165 public void windowClosing(WindowEvent e) { 166 GenericDialog.this.panel.closeClicked(); 167 } 168 }); 169 170 pack(); 171 if (!SwingUtilities.isEventDispatchThread()) 172 { 173 Thread.dumpStack(); 174 } 175 } 176 177 /** 178 * Method used to add a focus listeners to all the components in the panel. 179 * This is done to recover the focus on an item when the dialog is closed 180 * and then opened again. 181 * @param focusListener the focus listener. 182 * @param container the container where the components are layed out. 183 */ 184 private void addFocusListener(FocusListener focusListener, 185 Container container) 186 { 187 for (int i=0; i < container.getComponentCount(); i++) 188 { 189 Component comp = container.getComponent(i); 190 if (comp instanceof AbstractButton || 191 comp instanceof JTextComponent || 192 comp instanceof JList || 193 comp instanceof JComboBox || 194 comp instanceof JTable) 195 { 196 comp.addFocusListener(focusListener); 197 } 198 else if (comp instanceof JPanel || comp instanceof JScrollPane 199 || comp instanceof JViewport) 200 { 201 addFocusListener(focusListener, (Container)comp); 202 } 203 } 204 } 205 206 /** {@inheritDoc} */ 207 public void setVisible(boolean visible) 208 { 209 if (visible && lastComponentWithFocus == null) 210 { 211 lastComponentWithFocus = panel.getPreferredFocusComponent(); 212 } 213 if (visible && lastComponentWithFocus != null && lastComponentWithFocus.isVisible()) 214 { 215 if (lastComponentWithFocus == null) 216 { 217 lastComponentWithFocus = panel.getPreferredFocusComponent(); 218 } 219 lastComponentWithFocus.requestFocusInWindow(); 220 } 221 updateDefaultButton(panel); 222 panel.toBeDisplayed(visible); 223 updateTitle(); 224 super.setVisible(visible); 225 } 226 227 /** 228 * Sets the enable state of the OK button. 229 * @param enable whether the OK button must be enabled or not. 230 */ 231 public void setEnabledOK(boolean enable) 232 { 233 okButton.setEnabled(enable); 234 } 235 236 /** 237 * Sets the enable state of the Cancel button. 238 * @param enable whether the Cancel button must be enabled or not. 239 */ 240 public void setEnabledCancel(boolean enable) 241 { 242 cancelButton.setEnabled(enable); 243 } 244 245 /** 246 * Sets the enable state of the Close button. 247 * @param enable whether the Close button must be enabled or not. 248 */ 249 public void setEnabledClose(boolean enable) 250 { 251 closeButton.setEnabled(enable); 252 } 253 254 /** Updates the title of the dialog using the title of the panel. */ 255 public void updateTitle() 256 { 257 if (panel.getTitle() != null) 258 { 259 setTitle(INFO_CTRL_PANEL_GENERIC_TITLE.get( 260 DynamicConstants.PRODUCT_NAME, panel.getTitle()).toString()); 261 } 262 } 263 264 private void setDefaultBorder(JComponent comp) 265 { 266 Utilities.setBorder(comp, new EmptyBorder(20, 20, 20, 20)); 267 } 268 269 private JPanel createButtonsPanel(final StatusGenericPanel panel) 270 { 271 JPanel buttonsPanel = new JPanel(new GridBagLayout()); 272 GridBagConstraints gbc = new GridBagConstraints(); 273 ButtonType buttonType = panel.getButtonType(); 274 gbc.gridx = 0; 275 gbc.weightx = 1.0; 276 gbc.fill = GridBagConstraints.HORIZONTAL; 277 buttonsPanel.add(Box.createHorizontalGlue(), gbc); 278 buttonsPanel.setOpaque(true); 279 buttonsPanel.setBackground(buttonPanelBackground); 280 gbc.insets = new Insets(10, 0, 10, 0); 281 gbc.insets.left = 5; 282 283 if (buttonType == ButtonType.OK_CANCEL) 284 { 285 gbc.gridx ++; 286 gbc.weightx = 0.0; 287 okButton = Utilities.createButton( 288 INFO_CTRL_PANEL_OK_BUTTON_LABEL.get()); 289 okButton.setOpaque(false); 290 buttonsPanel.add(okButton, gbc); 291 okButton.addActionListener(new ActionListener() 292 { 293 public void actionPerformed(ActionEvent ev) 294 { 295 panel.okClicked(); 296 } 297 }); 298 okButton.setEnabled(panel.isEnableOK()); 299 300 gbc.gridx ++; 301 cancelButton = Utilities.createButton( 302 INFO_CTRL_PANEL_CANCEL_BUTTON_LABEL.get()); 303 cancelButton.setOpaque(false); 304 cancelButton.addActionListener(new ActionListener() 305 { 306 public void actionPerformed(ActionEvent ev) 307 { 308 panel.cancelClicked(); 309 } 310 }); 311 cancelButton.setEnabled(panel.isEnableCancel()); 312 gbc.insets.right = 10; 313 buttonsPanel.add(cancelButton, gbc); 314 } 315 316 if (buttonType == ButtonType.OK) 317 { 318 gbc.gridx ++; 319 gbc.weightx = 0.0; 320 okButton = Utilities.createButton( 321 INFO_CTRL_PANEL_OK_BUTTON_LABEL.get()); 322 okButton.setOpaque(false); 323 gbc.insets.right = 10; 324 buttonsPanel.add(okButton, gbc); 325 okButton.addActionListener(new ActionListener() 326 { 327 public void actionPerformed(ActionEvent ev) 328 { 329 panel.okClicked(); 330 } 331 }); 332 okButton.setEnabled(panel.isEnableOK()); 333 } 334 335 if (buttonType == ButtonType.CLOSE) 336 { 337 gbc.gridx ++; 338 gbc.weightx = 0.0; 339 closeButton = Utilities.createButton( 340 INFO_CTRL_PANEL_CLOSE_BUTTON_LABEL.get()); 341 closeButton.setOpaque(false); 342 gbc.insets.right = 10; 343 buttonsPanel.add(closeButton, gbc); 344 closeButton.addActionListener(new ActionListener() 345 { 346 public void actionPerformed(ActionEvent ev) 347 { 348 panel.closeClicked(); 349 } 350 }); 351 closeButton.setEnabled(panel.isEnableClose()); 352 } 353 354 355 356 buttonsPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, 357 ColorAndFontConstants.defaultBorderColor)); 358 return buttonsPanel; 359 } 360 361 /** 362 * Updates the default button of the dialog, depending on the type of 363 * generic panel that it contains. 364 * @param panel the generic panel contained in this dialog. 365 */ 366 private void updateDefaultButton(StatusGenericPanel panel) 367 { 368 ButtonType buttonType = panel.getButtonType(); 369 370 if (buttonType == ButtonType.OK_CANCEL) 371 { 372 getRootPane().setDefaultButton(okButton); 373 } 374 else if (buttonType == ButtonType.OK) 375 { 376 getRootPane().setDefaultButton(okButton); 377 } 378 else if (buttonType == ButtonType.CLOSE) 379 { 380 getRootPane().setDefaultButton(closeButton); 381 } 382 } 383}