/*******************************************************************************
* Copyright (c) 2017 Pivotal Software, Inc.
* 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:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.wizard;
import java.util.function.Supplier;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.springframework.ide.eclipse.boot.wizard.CheckBoxesSection.CheckBoxModel;
import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression;
import org.springsource.ide.eclipse.commons.livexp.core.LiveVariable;
import org.springsource.ide.eclipse.commons.livexp.core.ValidationResult;
import org.springsource.ide.eclipse.commons.livexp.core.Validator;
import org.springsource.ide.eclipse.commons.livexp.core.ValueListener;
import org.springsource.ide.eclipse.commons.livexp.ui.IPageWithSections;
import org.springsource.ide.eclipse.commons.livexp.ui.WizardPageSection;
import org.springsource.ide.eclipse.commons.livexp.util.Filter;
import org.springsource.ide.eclipse.commons.ui.HtmlTooltip;
public class SelectedButtonSection<T> extends WizardPageSection {
private Composite buttonComp;
private ValueListener<Boolean> selectionListener;
protected final CheckBoxModel<T> model;
protected final LiveVariable<Boolean> isVisible = new LiveVariable<>(true);
public SelectedButtonSection(IPageWithSections owner, CheckBoxModel<T> model) {
super(owner);
this.model = model;
}
@Override
public void createContents(Composite page) {
if (page != null && !page.isDisposed()) {
buttonComp = new Composite(page, SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).applyTo(buttonComp);
createButtonArea();
isVisible.addListener(new ValueListener<Boolean>() {
public void gotValue(LiveExpression<Boolean> exp, Boolean reveal) {
if (reveal != null && buttonComp != null && !buttonComp.isDisposed()) {
buttonComp.setVisible(reveal);
GridData data = (GridData) buttonComp.getLayoutData();
data.exclude = !reveal;
}
}
});
}
}
private void createButtonArea() {
GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).spacing(10, 0).applyTo(buttonComp);
Label xButton = new Label(buttonComp, SWT.READ_ONLY);
GridDataFactory.fillDefaults().grab(false, false).align(SWT.BEGINNING, SWT.CENTER).applyTo(xButton);
xButton.setText("X");
xButton.setFont(getBold());
applyDefaultEffects(xButton);
xButton.addMouseListener(new MouseListener() {
@Override
public void mouseUp(MouseEvent event) {
// Do nothing
}
@Override
public void mouseDown(MouseEvent event) {
removeSelection();
}
@Override
public void mouseDoubleClick(MouseEvent event) {
removeSelection();
}
});
xButton.addMouseTrackListener(new MouseTrackListener() {
@Override
public void mouseHover(MouseEvent event) {
// Do nothing. Enter/exit events are faster than hover, so those will
// be fired first before hover
}
@Override
public void mouseExit(MouseEvent event) {
applyDefaultEffects(xButton);
}
@Override
public void mouseEnter(MouseEvent event) {
applyHoverEffects(xButton);
}
});
xButton.setToolTipText("Click to remove the dependency");
Label label = new Label(buttonComp, SWT.NONE);
GridDataFactory.fillDefaults().grab(false, false).align(SWT.BEGINNING, SWT.CENTER).hint(170, SWT.DEFAULT)
.applyTo(label);
label.setText(model.getLabel());
Supplier<String> tooltip = model.getTooltipHtml();
if (tooltip != null) {
// Setup HTML tooltip and its content
HtmlTooltip htmlTooltip = new HtmlTooltip(label);
htmlTooltip.setMaxSize(400, 400);
htmlTooltip.setHtml(tooltip);
}
}
private Font getBold() {
// Note: fonts from the registry do not need to be managed outside for disposal.
return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);
}
protected void applyHoverEffects(Label xButton) {
if (xButton != null && !xButton.isDisposed()) {
xButton.setForeground(getSystemColor(SWT.COLOR_RED));
}
}
protected void applyDefaultEffects(Label xButton) {
if (xButton != null && !xButton.isDisposed()) {
xButton.setForeground(getSystemColor(SWT.COLOR_DARK_GRAY));
}
}
protected Color getSystemColor(int colorCode) {
return Display.getDefault().getSystemColor(colorCode);
}
protected void removeSelection() {
model.getSelection().setValue(false);
}
@Override
public void dispose() {
if (buttonComp != null && !buttonComp.isDisposed()) {
buttonComp.dispose();
buttonComp = null;
}
if (selectionListener != null) {
model.getSelection().removeListener(selectionListener);
}
}
/**
* Apply filter and return whether this widget's visibility has changed as a
* result.
*
* @return Whether visibility of this widget changed.
*/
public boolean applyFilter(Filter<T> filter) {
boolean wasVisible = isVisible.getValue();
isVisible.setValue(filter.accept(model.getValue()));
boolean changed = wasVisible != isVisible.getValue();
return changed;
}
public boolean isVisible() {
return isVisible.getValue();
}
@Override
public String toString() {
return "SelectedButtonSection(" + model.getLabel() + ")";
}
@Override
public LiveExpression<ValidationResult> getValidator() {
return Validator.OK;
}
}