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