/*******************************************************************************
* Copyright (c) 2010-2014 SAP AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
*******************************************************************************/
package org.eclipse.skalli.view.component;
import org.apache.commons.lang.StringEscapeUtils;
import org.eclipse.skalli.commons.HtmlUtils;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Embedded;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.NativeButton;
import com.vaadin.ui.Window.Notification;
public class Tray extends CustomComponent {
private static final long serialVersionUID = -5069545260062750691L;
private Embedded trayIcon;
private ThemeResource icon;
private boolean isVisible;
private boolean isEnabled;
private boolean isRequired;
private final Component component;
private Button activator;
private Button opener;
private final ThemeResource ERROR_ICON = new ThemeResource("icons/tray/error.png");
private static final String STYLE_TRAY = "tray";
private static final String STYLE_TRAY_HEADER = "header";
private static final String STYLE_TRAY_HEADER_ICON = "header-icon";
private static final String STYLE_TRAY_HEADER_LABEL = "header-label";
private static final String STYLE_TRAY_DESCRIPTION = "description";
private static final String STYLE_TRAY_OPEN = "open";
private static final String STYLE_TRAY_CLOSED = "closed";
private static final String STYLE_TRAY_ENABLED = "enabled";
private static final String STYLE_TRAY_DISABLED = "disabled";
public Tray(Component component,
String caption, String description, ThemeResource icon,
boolean isVisible, boolean isEnabled, boolean isRequired)
{
this.component = component;
ComponentContainer content = createContent(caption, description, icon, isRequired);
content.addComponent(component);
setContentState(isVisible, isEnabled);
}
private ComponentContainer createContent(String caption, String description, ThemeResource icon, boolean isRequired) {
CssLayout layout = new CssLayout();
layout.setStyleName(STYLE_TRAY);
layout.setMargin(true);
HorizontalLayout header = new HorizontalLayout();
header.setSpacing(true);
header.setStyleName(STYLE_TRAY_HEADER);
header.setWidth("100%");
this.icon = icon;
trayIcon = new Embedded(null, icon);
trayIcon.setStyleName(STYLE_TRAY_HEADER_ICON);
header.addComponent(trayIcon);
header.setComponentAlignment(trayIcon, Alignment.MIDDLE_LEFT);
header.setExpandRatio(trayIcon, 0);
Label captionLabel = new Label(StringEscapeUtils.escapeHtml(caption), Label.CONTENT_XHTML);
captionLabel.setStyleName(STYLE_TRAY_HEADER_LABEL);
header.addComponent(captionLabel);
header.setExpandRatio(captionLabel, 1);
header.setComponentAlignment(captionLabel, Alignment.MIDDLE_LEFT);
this.isRequired = isRequired;
if (!isRequired) {
activator = new NativeButton("", new ToggleEnabledListener());
header.addComponent(activator);
header.setExpandRatio(activator, 0);
header.setComponentAlignment(activator, Alignment.MIDDLE_RIGHT);
}
opener = new NativeButton("", new ToggleVisibleListener());
header.addComponent(opener);
header.setExpandRatio(opener, 0);
header.setComponentAlignment(opener, Alignment.MIDDLE_RIGHT);
layout.addComponent(header);
CssLayout content = new CssLayout();
Label descriptionLabel = new Label(HtmlUtils.clean(description), Label.CONTENT_XHTML);
descriptionLabel.setStyleName(STYLE_TRAY_DESCRIPTION);
content.addComponent(descriptionLabel);
layout.addComponent(content);
setCompositionRoot(layout);
return content;
}
public boolean isContentVisible() {
return isVisible;
}
public void setContentVisible(boolean isContentVisible) {
setContentState(isContentVisible, isEnabled);
requestRepaint();
}
public boolean isContentEnabled() {
return isEnabled;
}
public void setContentEnabled(boolean isContentEnabled) {
setContentState(isContentEnabled, isContentEnabled);
requestRepaint();
}
public void markAsInvalid(boolean isInvalid) {
if (isInvalid) {
trayIcon.setSource(ERROR_ICON);
} else {
trayIcon.setSource(icon);
}
}
protected void setContentState(boolean isVisible, boolean isEnabled) {
this.isVisible = isVisible;
this.isEnabled = isRequired ? true : isEnabled;
if (component != null) {
component.setEnabled(isEnabled);
component.setVisible(isVisible);
}
opener.setDescription(isVisible ? "Hide details" : "Show details");
opener.setStyleName(isVisible ? STYLE_TRAY_OPEN : STYLE_TRAY_CLOSED);
if (!isRequired) {
activator.setDescription(isEnabled ? "Disable this project nature" : "Enable this project nature");
activator.setStyleName(isEnabled ? STYLE_TRAY_ENABLED : STYLE_TRAY_DISABLED);
}
}
private class ToggleVisibleListener implements Button.ClickListener {
private static final long serialVersionUID = 6624509900591216536L;
@Override
public void buttonClick(ClickEvent event) {
setContentVisible(!isVisible);
}
}
private class ToggleEnabledListener implements Button.ClickListener {
private static final long serialVersionUID = 539162056096468214L;
@Override
public void buttonClick(ClickEvent event) {
boolean wasEnabled = isEnabled;
setContentEnabled(!isEnabled);
if (wasEnabled) {
getWindow().showNotification(
"Potential Data Loss",
"Removing a project nature removes also the maintained data!",
Notification.TYPE_WARNING_MESSAGE);
}
}
}
}