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