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-2016 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/** The generic dialog of the Control Panel. It contains a StatusGenericPanel. */ 059public class GenericDialog extends JDialog 060{ 061 private static final long serialVersionUID = -2643144936460484112L; 062 private static final Color buttonPanelBackground = 063 ColorAndFontConstants.greyBackground; 064 private JButton okButton; 065 066 /** The close button. */ 067 private JButton closeButton; 068 private JButton cancelButton; 069 /** The panel contained in the dialog. */ 070 protected StatusGenericPanel panel; 071 private Component lastComponentWithFocus; 072 073 /** The different combinations of buttons that the dialog can have. */ 074 public enum ButtonType 075 { 076 /** The dialog contains OK and CANCEL buttons. */ 077 OK_CANCEL, 078 /** The dialog contains a OK button. */ 079 OK, 080 /** The dialog contains a CLOSE button. */ 081 CLOSE, 082 /** The dialog has no buttons. */ 083 NO_BUTTON 084 } 085 086 /** 087 * Constructor of the dialog. 088 * @param parentFrame the parent frame of the dialog. 089 * @param panel the panel contained in this dialog. 090 */ 091 public GenericDialog(JFrame parentFrame, StatusGenericPanel panel) 092 { 093 super(parentFrame); 094 this.panel = panel; 095 if (panel.requiresBorder()) 096 { 097 setDefaultBorder(panel); 098 } 099 JMenuBar menu = panel.getMenuBar(); 100 if (menu != null) 101 { 102 parentFrame.setJMenuBar(menu); 103 } 104 setResizable(true); 105 JScrollPane scroll = Utilities.createScrollPane(panel); 106 JPanel inputPanel = new JPanel(new GridBagLayout()); 107 setContentPane(inputPanel); 108 GridBagConstraints gbc = new GridBagConstraints(); 109 gbc.weightx = 1.0; 110 gbc.weighty = 1.0; 111 gbc.gridx = 0; 112 gbc.gridy = 0; 113 gbc.fill = GridBagConstraints.BOTH; 114 if (panel.requiresScroll()) 115 { 116 inputPanel.add(scroll, gbc); 117 } 118 else 119 { 120 inputPanel.add(panel, gbc); 121 } 122 if (panel.getButtonType() != ButtonType.NO_BUTTON) 123 { 124 gbc.gridy ++; 125 gbc.weighty = 0.0; 126 inputPanel.add(createButtonsPanel(panel), gbc); 127 } 128 129 KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); 130 ActionListener actionListener = new ActionListener() 131 { 132 @Override 133 public void actionPerformed(ActionEvent ev) 134 { 135 setVisible(false); 136 } 137 }; 138 getRootPane().registerKeyboardAction(actionListener, stroke, 139 JComponent.WHEN_IN_FOCUSED_WINDOW); 140 141 FocusListener focusListener = new FocusAdapter() 142 { 143 @Override 144 public void focusGained(FocusEvent ev) 145 { 146 lastComponentWithFocus = ev.getComponent(); 147 } 148 }; 149 addFocusListener(focusListener, panel); 150 151 addWindowListener(new WindowAdapter() { 152 @Override 153 public void windowClosing(WindowEvent e) { 154 GenericDialog.this.panel.closeClicked(); 155 } 156 }); 157 158 pack(); 159 if (!SwingUtilities.isEventDispatchThread()) 160 { 161 Thread.dumpStack(); 162 } 163 } 164 165 /** 166 * Method used to add a focus listeners to all the components in the panel. 167 * This is done to recover the focus on an item when the dialog is closed 168 * and then opened again. 169 * @param focusListener the focus listener. 170 * @param container the container where the components are layed out. 171 */ 172 private void addFocusListener(FocusListener focusListener, 173 Container container) 174 { 175 for (int i=0; i < container.getComponentCount(); i++) 176 { 177 Component comp = container.getComponent(i); 178 if (comp instanceof AbstractButton || 179 comp instanceof JTextComponent || 180 comp instanceof JList || 181 comp instanceof JComboBox || 182 comp instanceof JTable) 183 { 184 comp.addFocusListener(focusListener); 185 } 186 else if (comp instanceof JPanel || comp instanceof JScrollPane 187 || comp instanceof JViewport) 188 { 189 addFocusListener(focusListener, (Container)comp); 190 } 191 } 192 } 193 194 @Override 195 public void setVisible(boolean visible) 196 { 197 if (visible && lastComponentWithFocus == null) 198 { 199 lastComponentWithFocus = panel.getPreferredFocusComponent(); 200 } 201 if (visible && lastComponentWithFocus != null && lastComponentWithFocus.isVisible()) 202 { 203 if (lastComponentWithFocus == null) 204 { 205 lastComponentWithFocus = panel.getPreferredFocusComponent(); 206 } 207 lastComponentWithFocus.requestFocusInWindow(); 208 } 209 updateDefaultButton(panel); 210 panel.toBeDisplayed(visible); 211 updateTitle(); 212 super.setVisible(visible); 213 } 214 215 /** 216 * Sets the enable state of the OK button. 217 * @param enable whether the OK button must be enabled or not. 218 */ 219 public void setEnabledOK(boolean enable) 220 { 221 okButton.setEnabled(enable); 222 } 223 224 /** 225 * Sets the enable state of the Cancel button. 226 * @param enable whether the Cancel button must be enabled or not. 227 */ 228 public void setEnabledCancel(boolean enable) 229 { 230 cancelButton.setEnabled(enable); 231 } 232 233 /** 234 * Sets the enable state of the Close button. 235 * @param enable whether the Close button must be enabled or not. 236 */ 237 public void setEnabledClose(boolean enable) 238 { 239 closeButton.setEnabled(enable); 240 } 241 242 /** Updates the title of the dialog using the title of the panel. */ 243 public void updateTitle() 244 { 245 if (panel.getTitle() != null) 246 { 247 setTitle(INFO_CTRL_PANEL_GENERIC_TITLE.get( 248 DynamicConstants.PRODUCT_NAME, panel.getTitle()).toString()); 249 } 250 } 251 252 private void setDefaultBorder(JComponent comp) 253 { 254 Utilities.setBorder(comp, new EmptyBorder(20, 20, 20, 20)); 255 } 256 257 private JPanel createButtonsPanel(final StatusGenericPanel panel) 258 { 259 JPanel buttonsPanel = new JPanel(new GridBagLayout()); 260 GridBagConstraints gbc = new GridBagConstraints(); 261 ButtonType buttonType = panel.getButtonType(); 262 gbc.gridx = 0; 263 gbc.weightx = 1.0; 264 gbc.fill = GridBagConstraints.HORIZONTAL; 265 buttonsPanel.add(Box.createHorizontalGlue(), gbc); 266 buttonsPanel.setOpaque(true); 267 buttonsPanel.setBackground(buttonPanelBackground); 268 gbc.insets = new Insets(10, 0, 10, 0); 269 gbc.insets.left = 5; 270 271 if (buttonType == ButtonType.OK_CANCEL) 272 { 273 gbc.gridx ++; 274 gbc.weightx = 0.0; 275 okButton = Utilities.createButton( 276 INFO_CTRL_PANEL_OK_BUTTON_LABEL.get()); 277 okButton.setOpaque(false); 278 buttonsPanel.add(okButton, gbc); 279 okButton.addActionListener(new ActionListener() 280 { 281 @Override 282 public void actionPerformed(ActionEvent ev) 283 { 284 panel.okClicked(); 285 } 286 }); 287 okButton.setEnabled(panel.isEnableOK()); 288 289 gbc.gridx ++; 290 cancelButton = Utilities.createButton( 291 INFO_CTRL_PANEL_CANCEL_BUTTON_LABEL.get()); 292 cancelButton.setOpaque(false); 293 cancelButton.addActionListener(new ActionListener() 294 { 295 @Override 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 @Override 318 public void actionPerformed(ActionEvent ev) 319 { 320 panel.okClicked(); 321 } 322 }); 323 okButton.setEnabled(panel.isEnableOK()); 324 } 325 326 if (buttonType == ButtonType.CLOSE) 327 { 328 gbc.gridx ++; 329 gbc.weightx = 0.0; 330 closeButton = Utilities.createButton( 331 INFO_CTRL_PANEL_CLOSE_BUTTON_LABEL.get()); 332 closeButton.setOpaque(false); 333 gbc.insets.right = 10; 334 buttonsPanel.add(closeButton, gbc); 335 closeButton.addActionListener(new ActionListener() 336 { 337 @Override 338 public void actionPerformed(ActionEvent ev) 339 { 340 panel.closeClicked(); 341 } 342 }); 343 closeButton.setEnabled(panel.isEnableClose()); 344 } 345 346 347 348 buttonsPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, 349 ColorAndFontConstants.defaultBorderColor)); 350 return buttonsPanel; 351 } 352 353 /** 354 * Updates the default button of the dialog, depending on the type of 355 * generic panel that it contains. 356 * @param panel the generic panel contained in this dialog. 357 */ 358 private void updateDefaultButton(StatusGenericPanel panel) 359 { 360 ButtonType buttonType = panel.getButtonType(); 361 362 if (buttonType == ButtonType.OK_CANCEL) 363 { 364 getRootPane().setDefaultButton(okButton); 365 } 366 else if (buttonType == ButtonType.OK) 367 { 368 getRootPane().setDefaultButton(okButton); 369 } 370 else if (buttonType == ButtonType.CLOSE) 371 { 372 getRootPane().setDefaultButton(closeButton); 373 } 374 } 375}