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 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2016 ForgeRock AS.
016 */
017
018package org.opends.quicksetup.ui;
019
020import org.forgerock.i18n.LocalizableMessage;
021import static org.opends.messages.QuickSetupMessages.*;
022
023import java.awt.Dimension;
024import java.awt.GridBagConstraints;
025import java.awt.GridBagLayout;
026import java.awt.event.ActionEvent;
027import java.awt.event.ActionListener;
028
029import javax.swing.Box;
030import javax.swing.JButton;
031import javax.swing.JDialog;
032import javax.swing.JEditorPane;
033import javax.swing.JFrame;
034import javax.swing.JLabel;
035import javax.swing.JPanel;
036import javax.swing.JProgressBar;
037import javax.swing.JScrollPane;
038import javax.swing.event.HyperlinkEvent;
039import javax.swing.event.HyperlinkListener;
040
041import org.opends.quicksetup.event.MinimumSizeComponentListener;
042import org.opends.quicksetup.util.HtmlProgressMessageFormatter;
043import org.opends.quicksetup.util.ProgressMessageFormatter;
044
045/** This panel is used to show the progress of the start/stop/restart operations. */
046public class ProgressDialog extends JDialog
047{
048  private static final long serialVersionUID = 8635080171100378470L;
049
050  private JEditorPane progressBarLabel;
051
052  private JProgressBar progressBar;
053
054  private JEditorPane detailsTextArea;
055
056  private LocalizableMessage lastText;
057
058  private JFrame parent;
059
060  private JButton closeButton;
061
062  private LocalizableMessage panelTitle = INFO_PROGRESS_TITLE.get();
063
064  private ProgressMessageFormatter formatter =
065    new HtmlProgressMessageFormatter();
066
067  /**
068   * ProgressDialog constructor.
069   * @param frame the parent frame for this dialog.
070   */
071  public ProgressDialog(JFrame frame)
072  {
073    super(frame);
074    this.parent = frame;
075    setTitle(INFO_PROGRESS_DIALOG_TITLE.get().toString());
076    createLayout();
077  }
078
079  /** Prepares size for this dialog. */
080  @Override
081  public void pack()
082  {
083    /* TODO: find a way to calculate this dynamically. */
084    setPreferredSize(new Dimension(500, 300));
085    addComponentListener(new MinimumSizeComponentListener(this, 500, 300));
086    super.pack();
087    closeButton.requestFocusInWindow();
088    getRootPane().setDefaultButton(closeButton);
089  }
090
091  /**
092   * Returns the parent for this dialog.
093   * @return the parent for this dialog.
094   */
095  public JFrame getFrame()
096  {
097    return parent;
098  }
099
100  /**
101   * Returns the title of the panel.
102   * @return the title of the panel
103   */
104  public LocalizableMessage getPanelTitle()
105  {
106    return panelTitle;
107  }
108
109  /**
110   * Sets the enable state of the close button.
111   * @param enable whether to enable or disable the button.
112   */
113  public void setCloseButtonEnabled(boolean enable)
114  {
115    closeButton.setEnabled(enable);
116  }
117
118  /**
119   * Sets the text in the summary label.  The text can be in HTML format.
120   * @param text the text to be set.
121   */
122  public void setSummary(LocalizableMessage text)
123  {
124    if (text != null) {
125      progressBarLabel.setText(text.toString());
126    } else {
127      progressBarLabel.setText(null);
128    }
129  }
130
131  /**
132   * Sets the text in the details text pane.  The text can be in HTML format.
133   * @param text the text to be set.
134   */
135  public void setDetails(LocalizableMessage text)
136  {
137    if (text != null) {
138      detailsTextArea.setText(text.toString());
139    } else {
140      detailsTextArea.setText(null);
141    }
142  }
143
144  /**
145   * Returns the formatter that will be used to display the messages in this
146   * panel.
147   * @return the formatter that will be used to display the messages in this
148   * panel.
149   */
150  private ProgressMessageFormatter getFormatter()
151  {
152    if (formatter == null)
153    {
154      formatter = new HtmlProgressMessageFormatter();
155    }
156    return formatter;
157  }
158
159  /** Creates the layout of the dialog panel. */
160  private void createLayout()
161  {
162    /* Create title panel */
163    JPanel titlePanel = new JPanel(new GridBagLayout());
164    titlePanel.setOpaque(false);
165    GridBagConstraints gbc = new GridBagConstraints();
166    gbc.anchor = GridBagConstraints.NORTHWEST;
167    gbc.fill = GridBagConstraints.HORIZONTAL;
168    gbc.weightx = 0.0;
169    gbc.gridwidth = GridBagConstraints.RELATIVE;
170
171    LocalizableMessage title = getPanelTitle();
172
173    JLabel l =
174        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
175            UIFactory.TextStyle.TITLE);
176    l.setOpaque(false);
177    titlePanel.add(l, gbc);
178
179    gbc.weightx = 1.0;
180    gbc.gridwidth = GridBagConstraints.REMAINDER;
181    titlePanel.add(Box.createHorizontalGlue(), gbc);
182
183    /* Create input panel. */
184    JPanel mainPanel = new JPanel(new GridBagLayout());
185    mainPanel.setOpaque(false);
186    gbc.insets = UIFactory.getEmptyInsets();
187    gbc.anchor = GridBagConstraints.NORTHWEST;
188    gbc.gridwidth = GridBagConstraints.REMAINDER;
189    gbc.weightx = 1.0;
190    gbc.fill = GridBagConstraints.HORIZONTAL;
191    mainPanel.add(titlePanel, gbc);
192
193    gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
194    progressBarLabel =
195        UIFactory.makeHtmlPane(INFO_PROGRESSBAR_INITIAL_LABEL.get(),
196            UIFactory.PROGRESS_FONT);
197    progressBarLabel.setOpaque(false);
198    progressBarLabel.setEditable(false);
199    mainPanel.add(progressBarLabel, gbc);
200
201    gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_BAR;
202    gbc.insets.bottom = UIFactory.BOTTOM_INSET_PROGRESS_BAR;
203    mainPanel.add(createProgressBarPanel(), gbc);
204    progressBar.setToolTipText(INFO_PROGRESSBAR_TOOLTIP.get().toString());
205
206    l =
207        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
208            INFO_PROGRESS_DETAILS_LABEL.get(),
209            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
210
211    gbc.insets = UIFactory.getEmptyInsets();
212    mainPanel.add(l, gbc);
213
214    JScrollPane scroll = new JScrollPane();
215    detailsTextArea = UIFactory.makeProgressPane(scroll);
216    detailsTextArea.setBackground(
217        UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
218    detailsTextArea.addHyperlinkListener(new HyperlinkListener()
219    {
220      @Override
221      public void hyperlinkUpdate(HyperlinkEvent e)
222      {
223        if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
224        {
225          String url = e.getURL().toString();
226          lastText = getFormatter().getFormattedAfterUrlClick(url,
227              lastText);
228          setDetails(lastText);
229        }
230      }
231    });
232    detailsTextArea.setAutoscrolls(true);
233    scroll.setViewportView(detailsTextArea);
234
235    scroll.setBorder(UIFactory.TEXT_AREA_BORDER);
236    scroll.setWheelScrollingEnabled(true);
237    l.setLabelFor(detailsTextArea);
238    gbc.insets.top = UIFactory.TOP_INSET_PROGRESS_TEXTAREA;
239    gbc.fill = GridBagConstraints.BOTH;
240    gbc.weighty = 1.0;
241    mainPanel.add(scroll, gbc);
242
243    /* Create buttons panel */
244    JPanel buttonsPanel = new JPanel(new GridBagLayout());
245    buttonsPanel.setBackground(UIFactory.DEFAULT_BACKGROUND);
246    gbc.fill = GridBagConstraints.HORIZONTAL;
247    gbc.weightx = 1.0;
248    gbc.insets = UIFactory.getEmptyInsets();
249    gbc.gridwidth = GridBagConstraints.RELATIVE;
250    buttonsPanel.add(Box.createHorizontalGlue(), gbc);
251    closeButton =
252        UIFactory.makeJButton(INFO_CLOSE_BUTTON_LABEL.get(),
253            INFO_CLOSE_PROGRESS_BUTTON_TOOLTIP.get());
254    gbc.fill = GridBagConstraints.NONE;
255    gbc.weightx = 0.0;
256    gbc.gridwidth = GridBagConstraints.REMAINDER;
257    buttonsPanel.add(closeButton, gbc);
258    closeButton.addActionListener(new ActionListener()
259    {
260      @Override
261      public void actionPerformed(ActionEvent ev)
262      {
263        dispose();
264      }
265    });
266
267    JPanel p = new JPanel(new GridBagLayout());
268    p.setBackground(UIFactory.DEFAULT_BACKGROUND);
269    gbc.insets = UIFactory.getEmptyInsets();
270    gbc.fill = GridBagConstraints.BOTH;
271    gbc.gridwidth = GridBagConstraints.REMAINDER;
272    gbc.weightx = 1.0;
273    gbc.weighty = 1.0;
274    gbc.insets = UIFactory.getEmptyInsets();
275    JPanel p1 = new JPanel(new GridBagLayout());
276    p1.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
277    p1.setBorder(UIFactory.DIALOG_PANEL_BORDER);
278    gbc.insets = UIFactory.getCurrentStepPanelInsets();
279    p1.add(mainPanel, gbc);
280    gbc.insets = UIFactory.getEmptyInsets();
281    p.add(p1, gbc);
282    gbc.weighty = 0.0;
283    gbc.insets = UIFactory.getButtonsPanelInsets();
284    p.add(buttonsPanel, gbc);
285
286    getContentPane().add(p);
287  }
288
289  /**
290   * Creates the progress bar panel.
291   * @return the created panel.
292   */
293  private JPanel createProgressBarPanel()
294  {
295    JPanel panel = new JPanel(new GridBagLayout());
296    panel.setOpaque(false);
297    GridBagConstraints gbc = new GridBagConstraints();
298    gbc.insets = UIFactory.getEmptyInsets();
299    gbc.fill = GridBagConstraints.HORIZONTAL;
300
301    progressBar = new JProgressBar();
302    progressBar.setIndeterminate(true);
303    // The ProgressDescriptor provides the ratio in %
304    progressBar.setMaximum(100);
305
306    gbc.gridwidth = GridBagConstraints.RELATIVE;
307    gbc.weightx = 0.0;
308    panel.add(Box.createHorizontalStrut(UIFactory.PROGRESS_BAR_SIZE), gbc);
309    gbc.gridwidth = GridBagConstraints.REMAINDER;
310    gbc.weightx = 1.0;
311    panel.add(Box.createHorizontalGlue(), gbc);
312
313    gbc.gridwidth = GridBagConstraints.RELATIVE;
314    gbc.weightx = 0.0;
315    //panel.add(progressBar, gbc);
316    gbc.gridwidth = GridBagConstraints.REMAINDER;
317    gbc.weightx = 1.0;
318    panel.add(Box.createHorizontalGlue(), gbc);
319
320    return panel;
321  }
322
323  /**
324   * Method written for testing purposes.
325   * @param args the arguments to be passed to the test program.
326   */
327  public static void main(String[] args)
328  {
329    try
330    {
331      ProgressDialog dlg = new ProgressDialog(new JFrame());
332      dlg.pack();
333      dlg.setVisible(true);
334    } catch (Exception ex)
335    {
336      ex.printStackTrace();
337    }
338  }
339}