/*
|
* CDDL HEADER START
|
*
|
* The contents of this file are subject to the terms of the
|
* Common Development and Distribution License, Version 1.0 only
|
* (the "License"). You may not use this file except in compliance
|
* with the License.
|
*
|
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
|
* or http://forgerock.org/license/CDDLv1.0.html.
|
* See the License for the specific language governing permissions
|
* and limitations under the License.
|
*
|
* When distributing Covered Code, include this CDDL HEADER in each
|
* file and include the License file at legal-notices/CDDLv1_0.txt.
|
* If applicable, add the following below this CDDL HEADER, with the
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
* information:
|
* Portions Copyright [yyyy] [name of copyright owner]
|
*
|
* CDDL HEADER END
|
*
|
*
|
* Copyright 2008-2010 Sun Microsystems, Inc.
|
* Portions Copyright 2015 ForgeRock AS
|
*/
|
package org.opends.guitools.controlpanel.ui;
|
|
import static org.opends.messages.AdminToolMessages.*;
|
import static org.opends.messages.QuickSetupMessages.INFO_CLOSE_BUTTON_LABEL;
|
|
import java.awt.Component;
|
import java.awt.Dimension;
|
import java.awt.GridBagConstraints;
|
import java.awt.GridBagLayout;
|
import java.awt.Insets;
|
import java.awt.Window;
|
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionListener;
|
|
import javax.swing.BorderFactory;
|
import javax.swing.Box;
|
import javax.swing.JButton;
|
import javax.swing.JCheckBox;
|
import javax.swing.JEditorPane;
|
import javax.swing.JFrame;
|
import javax.swing.JPanel;
|
import javax.swing.JProgressBar;
|
import javax.swing.JScrollPane;
|
import javax.swing.SwingUtilities;
|
import javax.swing.text.html.HTMLDocument;
|
|
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
|
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
|
import org.opends.guitools.controlpanel.event.PrintStreamListener;
|
import org.opends.guitools.controlpanel.ui.components.BasicExpander;
|
import org.opends.guitools.controlpanel.util.ApplicationPrintStream;
|
import org.opends.guitools.controlpanel.util.Utilities;
|
import org.forgerock.i18n.LocalizableMessage;
|
|
/**
|
* The dialog that is used to display progress in a task.
|
*/
|
public class ProgressDialog extends GenericDialog
|
{
|
private static final long serialVersionUID = -6462866257463062629L;
|
private ProgressPanel progressPanel;
|
|
/**
|
* Constructor of the dialog.
|
* @param parentFrame the parent frame.
|
* @param relativeTo the component to use as reference to set the position
|
* of this dialog.
|
* @param title the title of the dialog.
|
* @param info the control panel information.
|
*/
|
public ProgressDialog(JFrame parentFrame, Component relativeTo,
|
LocalizableMessage title, ControlPanelInfo info)
|
{
|
super(parentFrame, getPanel(info));
|
Utilities.centerGoldenMean(this, relativeTo);
|
setTitle(title.toString());
|
progressPanel = (ProgressPanel)panel;
|
getRootPane().setDefaultButton(progressPanel.closeButton);
|
}
|
|
/**
|
* Creates the panel that will be contained in the dialog.
|
* @param info the control panel information.
|
* @return the panel that will be contained in the dialog.
|
*/
|
private static StatusGenericPanel getPanel(ControlPanelInfo info)
|
{
|
ProgressPanel panel = new ProgressPanel();
|
panel.setInfo(info);
|
return panel;
|
}
|
|
/**
|
* Adds two print stream listeners.
|
* @param outPrintStream the output stream listener.
|
* @param errorPrintStream the error stream listener.
|
*/
|
public void addPrintStreamListeners(ApplicationPrintStream outPrintStream,
|
ApplicationPrintStream errorPrintStream)
|
{
|
errorPrintStream.addListener(new PrintStreamListener()
|
{
|
public void newLine(final String msg)
|
{
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
/** {@inheritDoc} */
|
public void run()
|
{
|
progressPanel.appendErrorLine(msg);
|
}
|
});
|
}
|
});
|
outPrintStream.addListener(new PrintStreamListener()
|
{
|
public void newLine(final String msg)
|
{
|
/** {@inheritDoc} */
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
public void run()
|
{
|
progressPanel.appendOutputLine(msg);
|
}
|
});
|
}
|
});
|
}
|
|
/**
|
* Returns the progress bar of the dialog.
|
* @return the progress bar of the dialog.
|
*/
|
public JProgressBar getProgressBar()
|
{
|
return progressPanel.getProgressBar();
|
}
|
|
/**
|
* Appends some text in HTML format to the 'Details' section of the dialog.
|
* @param text the text in HTML format to be appended.
|
*/
|
public void appendProgressHtml(String text)
|
{
|
progressPanel.appendHtml(text);
|
}
|
|
/**
|
* Resets the contents of the 'Details' section of the dialog.
|
*
|
*/
|
public void resetProgressLogs()
|
{
|
progressPanel.resetLogs();
|
}
|
|
/**
|
* Sets the text to be displayed in the summary area of the progress
|
* dialog.
|
* @param text the text to be displayed.
|
*/
|
public void setSummary(LocalizableMessage text)
|
{
|
progressPanel.setSummary(text);
|
}
|
|
/** {@inheritDoc} */
|
public void setEnabledClose(boolean enable)
|
{
|
progressPanel.closeButton.setEnabled(enable);
|
}
|
|
/**
|
* Note: this will make the dialog to be closed asynchronously. So that
|
* sequential calls to setTaskIsOver(true) and setTaskIsOver(false) on the
|
* event thread are guaranteed not to close the dialog.
|
* @param taskIsOver whether the task is finished or not.
|
*/
|
public void setTaskIsOver(boolean taskIsOver)
|
{
|
progressPanel.taskIsOver = taskIsOver;
|
progressPanel.closeWhenOverClicked();
|
}
|
|
/**
|
* The panel contained in the progress dialog.
|
*
|
*/
|
static class ProgressPanel extends StatusGenericPanel
|
{
|
private static final long serialVersionUID = -364496083928260306L;
|
private BasicExpander details;
|
private JEditorPane logs;
|
private JScrollPane scroll;
|
private JCheckBox closeWhenOver;
|
private final String LASTID = "lastid";
|
private final String INIT_TEXT = "<span id=\""+LASTID+
|
"\" style=\"bold\"> </span>";
|
private JProgressBar progressBar;
|
private Component extraStrut;
|
private JButton closeButton;
|
private static final String FAKE_PROGRESS_TEXT =
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+
|
"<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>"+
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
private int heightDiff;
|
private int lastCollapsedHeight = -1;
|
private int lastExpandedHeight = -1;
|
|
private static boolean lastShowDetails;
|
private static boolean lastCloseWhenOver;
|
|
private boolean taskIsOver;
|
|
/**
|
* Default constructor.
|
*
|
*/
|
public ProgressPanel()
|
{
|
super();
|
createLayout();
|
}
|
|
/** {@inheritDoc} */
|
public LocalizableMessage getTitle()
|
{
|
return null;
|
}
|
|
/** {@inheritDoc} */
|
public boolean requiresScroll()
|
{
|
return false;
|
}
|
|
/** {@inheritDoc} */
|
public boolean requiresBorder()
|
{
|
return false;
|
}
|
|
/** {@inheritDoc} */
|
public boolean isDisposeOnClose()
|
{
|
return true;
|
}
|
|
/**
|
* Appends a line to the logs (Details are) section of the panel. The text
|
* will have a new-line char at the end (is similar to println()).
|
* @param msg the HTML formatted text to be appended.
|
*/
|
public void appendErrorLine(String msg)
|
{
|
msg = filterForBugID4988885(msg+"<br>");
|
msg = Utilities.applyFont(msg, ColorAndFontConstants.progressFont);
|
appendHtml(msg);
|
}
|
|
/**
|
* Sets the text to be displayed in the summary area of the progress
|
* dialog.
|
* @param msg the text to be displayed.
|
*/
|
public void setSummary(LocalizableMessage msg)
|
{
|
errorPane.setText(msg.toString());
|
|
if (!details.isSelected() && isVisible())
|
{
|
LocalizableMessage wrappedText = Utilities.wrapHTML(msg, 70);
|
JEditorPane pane = new JEditorPane();
|
pane.setContentType("text/html");
|
pane.setText(wrappedText.toString());
|
ProgressDialog dlg = (ProgressDialog)Utilities.getParentDialog(this);
|
int width = Math.max(pane.getPreferredSize().width + 40,
|
dlg.getWidth());
|
int height = Math.max(pane.getPreferredSize().height + 40 +
|
extraStrut.getHeight() + details.getPreferredSize().height,
|
dlg.getHeight());
|
// We might want to resize things.
|
if (width > dlg.getWidth() || height > dlg.getHeight())
|
{
|
Dimension newDim = new Dimension(width, height);
|
dlg.setSize(newDim);
|
}
|
}
|
}
|
|
/**
|
* Appends a line to the logs (Details are) section of the panel. The text
|
* will be preceded by a new line (is similar to println()).
|
* @param msg the HTML formatted text to be appended.
|
*/
|
public void appendOutputLine(String msg)
|
{
|
appendErrorLine(msg);
|
}
|
|
/**
|
* Appends text to the logs (Details are) section of the panel. The text
|
* will be appended as it is (is similar to print()).
|
* @param msg the HTML formatted text to be appended.
|
*/
|
public void appendHtml(String msg)
|
{
|
HTMLDocument doc = (HTMLDocument)logs.getDocument();
|
|
try
|
{
|
msg = filterForBugID4988885(msg);
|
doc.insertBeforeStart(doc.getElement(LASTID), msg);
|
}
|
catch (Throwable t)
|
{
|
// Bug
|
t.printStackTrace();
|
}
|
}
|
|
/**
|
* Resets the contents of the logs (Details) section.
|
*
|
*/
|
public void resetLogs()
|
{
|
logs.setText(INIT_TEXT);
|
}
|
|
/**
|
* Creates the layout of the panel (but the contents are not populated
|
* here).
|
*
|
*/
|
private void createLayout()
|
{
|
GridBagConstraints gbc = new GridBagConstraints();
|
addErrorPane(gbc);
|
|
errorPane.setVisible(true);
|
errorPane.setText(Utilities.applyFont(
|
INFO_CTRL_PANEL_PLEASE_WAIT_SUMMARY.get(),
|
ColorAndFontConstants.defaultFont));
|
|
gbc.anchor = GridBagConstraints.WEST;
|
gbc.gridwidth = 1;
|
gbc.gridx = 0;
|
gbc.gridy = 1;
|
|
progressBar = new JProgressBar();
|
progressBar.setMaximum(100);
|
gbc.weightx = 1.0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.insets = new Insets(10, 20, 0, 30);
|
add(progressBar, gbc);
|
|
gbc.insets.top = 10;
|
gbc.insets.bottom = 5;
|
details =
|
new BasicExpander(INFO_CTRL_PANEL_PROGRESS_DIALOG_DETAILS_LABEL.get());
|
gbc.gridy ++;
|
add(details, gbc);
|
|
logs = Utilities.makeHtmlPane(FAKE_PROGRESS_TEXT,
|
ColorAndFontConstants.progressFont);
|
gbc.gridy ++;
|
gbc.weighty = 1.0;
|
gbc.fill = GridBagConstraints.BOTH;
|
gbc.insets.top = 5;
|
gbc.insets.right = 20;
|
gbc.insets.bottom = 5;
|
scroll = Utilities.createScrollPane(logs);
|
scroll.setOpaque(false);
|
scroll.getViewport().setOpaque(false);
|
add(scroll, gbc);
|
Dimension scrollDim = scroll.getPreferredSize();
|
|
gbc.weighty = 1.0;
|
extraStrut = Box.createRigidArea(new Dimension(scrollDim.width, 50));
|
add(extraStrut, gbc);
|
gbc.gridy ++;
|
gbc.weighty = 0.0;
|
add(Box.createHorizontalStrut(scrollDim.width), gbc);
|
|
heightDiff = scrollDim.height - extraStrut.getHeight();
|
|
logs.setText(INIT_TEXT);
|
|
scroll.setPreferredSize(scrollDim);
|
|
updateVisibility(lastShowDetails);
|
details.addActionListener(new ActionListener()
|
{
|
/** {@inheritDoc} */
|
public void actionPerformed(ActionEvent ev)
|
{
|
lastShowDetails = details.isSelected();
|
updateVisibility(lastShowDetails);
|
}
|
});
|
|
// The button panel
|
gbc.gridy ++;
|
gbc.weighty = 0.0;
|
gbc.insets = new Insets(0, 0, 0, 0);
|
add(createButtonsPanel(), gbc);
|
}
|
|
private JPanel createButtonsPanel()
|
{
|
JPanel buttonsPanel = new JPanel(new GridBagLayout());
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.gridx = 0;
|
gbc.gridy = 0;
|
gbc.anchor = GridBagConstraints.WEST;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.gridwidth = 1;
|
gbc.gridy = 0;
|
closeWhenOver = Utilities.createCheckBox(
|
INFO_CTRL_PANEL_CLOSE_WINDOW_WHEN_OPERATION_COMPLETES_LABEL.get());
|
closeWhenOver.setOpaque(false);
|
closeWhenOver.addActionListener(new ActionListener()
|
{
|
/** {@inheritDoc} */
|
public void actionPerformed(ActionEvent ev)
|
{
|
closeWhenOverClicked();
|
}
|
});
|
closeWhenOver.setSelected(lastCloseWhenOver);
|
gbc.insets = new Insets(10, 10, 10, 10);
|
buttonsPanel.add(closeWhenOver, gbc);
|
gbc.weightx = 1.0;
|
gbc.gridx ++;
|
buttonsPanel.add(Box.createHorizontalStrut(150));
|
buttonsPanel.add(Box.createHorizontalGlue(), gbc);
|
buttonsPanel.setOpaque(true);
|
buttonsPanel.setBackground(ColorAndFontConstants.greyBackground);
|
gbc.gridx ++;
|
gbc.weightx = 0.0;
|
buttonsPanel.add(Box.createHorizontalStrut(100));
|
gbc.gridx ++;
|
closeButton = Utilities.createButton(INFO_CLOSE_BUTTON_LABEL.get());
|
closeButton.setOpaque(false);
|
gbc.gridx ++;
|
gbc.insets.left = 5;
|
gbc.insets.right = 10;
|
buttonsPanel.add(closeButton, gbc);
|
closeButton.addActionListener(new ActionListener()
|
{
|
/** {@inheritDoc} */
|
public void actionPerformed(ActionEvent ev)
|
{
|
closeClicked();
|
}
|
});
|
|
buttonsPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0,
|
ColorAndFontConstants.defaultBorderColor));
|
|
return buttonsPanel;
|
}
|
|
private void updateVisibility(boolean showDetails)
|
{
|
scroll.setVisible(showDetails);
|
extraStrut.setVisible(!showDetails);
|
details.setSelected(showDetails);
|
|
final Window dialog = Utilities.getParentDialog(this);
|
if (dialog != null)
|
{
|
final Runnable repaint = new Runnable()
|
{
|
public void run()
|
{
|
invalidate();
|
dialog.invalidate();
|
dialog.repaint();
|
}
|
};
|
|
final Dimension dialogSize = dialog.getSize();
|
if (showDetails)
|
{
|
lastCollapsedHeight = dialogSize.height;
|
if (lastExpandedHeight == -1)
|
{
|
dialog.setSize(new Dimension(dialogSize.width, dialogSize.height + heightDiff));
|
}
|
else
|
{
|
dialog.setSize(new Dimension(dialogSize.width, lastExpandedHeight));
|
}
|
SwingUtilities.invokeLater(repaint);
|
}
|
else
|
{
|
lastExpandedHeight = dialogSize.height;
|
if (lastCollapsedHeight == -1)
|
{
|
packParentDialog();
|
}
|
else
|
{
|
dialog.setSize(new Dimension(dialogSize.width, lastCollapsedHeight));
|
SwingUtilities.invokeLater(repaint);
|
}
|
}
|
}
|
}
|
|
/** {@inheritDoc} */
|
public GenericDialog.ButtonType getButtonType()
|
{
|
return GenericDialog.ButtonType.NO_BUTTON;
|
}
|
|
/** {@inheritDoc} */
|
public void configurationChanged(ConfigurationChangeEvent ev)
|
{
|
}
|
|
/** {@inheritDoc} */
|
public Component getPreferredFocusComponent()
|
{
|
return details;
|
}
|
|
/** {@inheritDoc} */
|
public void okClicked()
|
{
|
Utilities.getParentDialog(this).setVisible(false);
|
}
|
|
/**
|
* Returns the progress bar of the dialog.
|
* @return the progress bar of the dialog.
|
*/
|
public JProgressBar getProgressBar()
|
{
|
return progressBar;
|
}
|
|
/**
|
* Checks if the 'Close when over' check box is selected and if it is the
|
* case, closes the dialog after waiting for 2 seconds (so that the user
|
* can see the result, or cancel the automatic closing of the dialog).
|
*
|
*/
|
private void closeWhenOverClicked()
|
{
|
lastCloseWhenOver = closeWhenOver.isSelected();
|
if (lastCloseWhenOver && taskIsOver)
|
{
|
Thread t = new Thread(new Runnable()
|
{
|
/** {@inheritDoc} */
|
public void run()
|
{
|
try
|
{
|
Thread.sleep(2000);
|
SwingUtilities.invokeLater(new Runnable()
|
{
|
public void run()
|
{
|
if (closeWhenOver.isSelected() && taskIsOver)
|
{
|
closeClicked();
|
}
|
}
|
});
|
}
|
catch (Throwable t)
|
{
|
}
|
}
|
});
|
t.start();
|
}
|
}
|
}
|
|
/**
|
* This is necessary because of bug 4988885.
|
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4988885
|
* @param msg the message.
|
* @return the message filtered.
|
*/
|
private static String filterForBugID4988885(String msg)
|
{
|
return msg.replaceAll("<br>", " <br>");
|
}
|
}
|