package org.ovirt.engine.ui.common.widget.panel;
import java.util.ArrayList;
import java.util.List;
import org.gwtbootstrap3.client.shared.event.AlertClosedEvent;
import org.gwtbootstrap3.client.ui.Alert;
import org.gwtbootstrap3.client.ui.Badge;
import org.gwtbootstrap3.client.ui.constants.AlertType;
import org.gwtbootstrap3.client.ui.constants.ColumnSize;
import org.gwtbootstrap3.client.ui.html.Div;
import org.gwtbootstrap3.client.ui.html.Span;
import org.gwtbootstrap3.client.ui.html.Text;
import org.ovirt.engine.ui.common.css.PatternflyConstants;
import org.ovirt.engine.ui.common.utils.ElementTooltipUtils;
import org.ovirt.engine.ui.common.widget.tooltip.WidgetTooltip;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Renders a PatternFly alert panel. @see https://www.patternfly.org/widgets/#alerts
*/
public class AlertPanel extends Composite {
interface ViewUiBinder extends UiBinder<IsWidget, AlertPanel> {
ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
}
public interface Style extends CssResource {
}
@UiField
Span icon;
@UiField
Div messagePanel;
@UiField
Badge badge;
@UiField
Text badgeText;
@UiField(provided = true)
Alert alert;
@UiField
WidgetTooltip alertTooltip;
private Type type;
private ColumnSize widgetColumnSize;
private int count = 1;
private List<SafeHtml> messagesList = new ArrayList<>();
/**
* The types of PatternFly alerts (currently 4).
*
* @see https://www.patternfly.org/widgets/#alerts
*/
public enum Type {
DANGER(AlertType.DANGER, PatternflyConstants.PFICON_ERROR_CIRCLE_O),
WARNING(AlertType.WARNING, PatternflyConstants.PFICON_WARNING_TRIANGLE_O),
SUCCESS(AlertType.SUCCESS, PatternflyConstants.PFICON_OK),
INFO(AlertType.INFO, PatternflyConstants.PFICON_INFO);
private AlertType alertType;
private String iconStyleName;
Type(AlertType alertType, String iconStyleName) {
this.alertType = alertType;
this.iconStyleName = iconStyleName;
}
public static Type from(String name) {
try {
return Type.valueOf(name.toUpperCase());
} catch (IllegalArgumentException e) {
return Type.INFO;
}
}
}
/**
* Create a new alert panel of type 'info'.
*/
public AlertPanel() {
//Need to override onClosed, this is called from JS code when closing the alert panel. The problem is that
//the Alert parent, is the AlertPanel, which doesn't implement HasWidgets. Since AlertPanel is a composite
//it is nearly impossible to have it implement HasWidget, and we also want to clean up the AlertPanel anyway
//So we override onClosed, and detach the AlertPanel from the DOM to clean it up.
alert = new Alert() {
@Override
protected void onClosed(final Event evt) {
ElementTooltipUtils.hideAllTooltips();
RootPanel.detachNow(this);
fireEvent(new AlertClosedEvent(evt));
}
};
initWidget(ViewUiBinder.uiBinder.createAndBindUi(this).asWidget());
setType(Type.INFO);
setWidgetColumnSize(ColumnSize.SM_11);
badge.setVisible(false);
}
/**
* Create a new alert panel with a custom type and message.
*/
public AlertPanel(Type type, SafeHtml message) {
this();
setType(type);
addMessage(message);
}
/**
* Create a new alert panel with a custom type and message, and a CSS class name to apply to the message.
*/
public AlertPanel(Type type, SafeHtml message, String styleName) {
this();
setType(type);
addMessage(message, styleName);
}
public void incCount() {
count++;
updateBadge();
}
private void updateBadge() {
badge.setVisible(count != 1);
badgeText.setText(String.valueOf(count));
if (badge.isVisible()) {
SafeHtmlBuilder builder = new SafeHtmlBuilder();
for (SafeHtml message: messagesList) {
builder.append(message);
}
alertTooltip.setHtml(builder.toSafeHtml());
}
}
/**
* Clear all messages from the panel.
*/
public void clearMessages() {
messagePanel.clear();
}
/**
* Set a List of messages into the alert panel. Apply the same CSS class names to each message.
* Note that this clears any existing messages.
*/
public void setMessages(List<SafeHtml> messages, String... styleNames) {
clearMessages();
for (SafeHtml message: messages) {
HTMLPanel messageLabel = createMessageLabel(message);
for (String s : styleNames) {
messageLabel.addStyleName(s);
}
messagePanel.add(messageLabel);
}
}
/**
* Add a message to the alert panel. Note that this does not clear any messages already in the panel.
*/
public void addMessage(SafeHtml message) {
messagePanel.add(createMessageLabel(message));
}
private HTMLPanel createMessageLabel(SafeHtml message) {
messagesList.add(message);
HTMLPanel messageLabel = new HTMLPanel(message);
return messageLabel;
}
/**
* Add a message to the alert panel. Apply the CSS class name to the message.
* Note that this does not clear any messages already in the panel.
*/
public void addMessage(SafeHtml message, String styleName) {
HTMLPanel messageLabel = createMessageLabel(message);
messageLabel.addStyleName(styleName);
messagePanel.add(messageLabel);
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
getWidget().setType(type.alertType);
// clear all other icon style names
for (Type t : type.getDeclaringClass().getEnumConstants()) {
getWidget().removeStyleName(t.iconStyleName);
}
icon.addStyleName(type.iconStyleName);
}
/**
* Apply the given {@linkplain ColumnSize Bootstrap column size}
* style to the alert widget, replacing one that was set previously.
* <p>
* Pass {@code null} to effectively remove the column size style.
*/
public void setWidgetColumnSize(ColumnSize newColumnSize) {
// clear existing style
if (widgetColumnSize != null) {
getWidget().removeStyleName(widgetColumnSize.getCssName());
}
widgetColumnSize = newColumnSize;
// apply new style
if (widgetColumnSize != null) {
getWidget().addStyleName(widgetColumnSize.getCssName());
}
}
public Alert getWidget() {
return (Alert) super.getWidget();
}
public HTMLPanel getMessageAt(int index) {
return (HTMLPanel) messagePanel.getWidget(index);
}
public WidgetTooltip getAlertTooltip() {
return alertTooltip;
}
}