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