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