/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.properties;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.Request;
import org.xmind.gef.draw2d.IDecoratedFigure;
import org.xmind.gef.draw2d.decoration.IDecoration;
import org.xmind.gef.draw2d.decoration.IShapeDecoration;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
import org.xmind.ui.color.ColorPicker;
import org.xmind.ui.color.IColorSelection;
import org.xmind.ui.color.PaletteContents;
import org.xmind.ui.commands.CommandMessages;
import org.xmind.ui.decorations.IDecorationDescriptor;
import org.xmind.ui.decorations.IDecorationManager;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.properties.DecorationLabelProvider;
import org.xmind.ui.properties.StyledPropertySectionPart;
import org.xmind.ui.style.Styles;
import org.xmind.ui.viewers.MComboViewer;
import org.xmind.ui.viewers.SWTUtils;
import org.xmind.ui.viewers.SliderViewer;
public class BoundaryShapePropertySectionPart extends StyledPropertySectionPart {
private class FillColorOpenListener implements IOpenListener {
public void open(OpenEvent event) {
changeFillColor((IColorSelection) event.getSelection());
}
}
private class ShapeSelectionChangedListener implements
ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
if (isRefreshing())
return;
Object o = ((IStructuredSelection) event.getSelection())
.getFirstElement();
if (o instanceof IDecorationDescriptor) {
changeShape(((IDecorationDescriptor) o).getId());
}
}
}
private class OpacityLabelProvider extends LabelProvider {
public String getText(Object element) {
int value = getOpacityValueFromScaleElement(element);
if (value >= 0) {
return NLS
.bind(PropertyMessages.BoundaryOpacity_pattern, value);
}
return super.getText(element);
}
}
private class OpacitySelectionChangedListener implements
ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
int value = getOpacityValueFromScaleSelection(event.getSelection());
if (value >= 0) {
opacityInput.setText(String.valueOf(value));
previewOpacity(value);
}
}
}
private class OpacityPostSelectionChangedListener implements
ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
int value = getOpacityValueFromScaleSelection(event.getSelection());
if (value >= 0) {
changeOpacity(value);
selectAllOpacityText(true);
}
}
}
private static List<IDecorationDescriptor> BoundaryShapes;
private MComboViewer shapeViewer;
private ColorPicker fillColorPicker;
private Text opacityInput;
private SliderViewer opacityScale;
private Image opacityImage;
protected void createContent(Composite parent) {
Composite line1 = new Composite(parent, SWT.NONE);
line1.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
false));
GridLayout layout1 = new GridLayout(2, false);
layout1.marginWidth = 0;
layout1.marginHeight = 0;
layout1.horizontalSpacing = 3;
layout1.verticalSpacing = 3;
line1.setLayout(layout1);
createLineContent1(line1);
Composite line2 = new Composite(parent, SWT.NONE);
line2.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
false));
GridLayout layout2 = new GridLayout(4, false);
layout2.marginWidth = 0;
layout2.marginHeight = 0;
layout2.horizontalSpacing = 3;
layout2.verticalSpacing = 3;
line2.setLayout(layout2);
createLineContent2(line2);
}
private void createLineContent1(Composite parent) {
shapeViewer = new MComboViewer(parent, MComboViewer.NORMAL);
shapeViewer.getControl().setLayoutData(
new GridData(GridData.FILL, GridData.FILL, true, false));
shapeViewer.getControl().setToolTipText(
PropertyMessages.BoundaryShape_toolTip);
shapeViewer.setContentProvider(new ArrayContentProvider());
shapeViewer.setLabelProvider(new DecorationLabelProvider());
shapeViewer.setInput(getBoundaryShapes());
shapeViewer
.addSelectionChangedListener(new ShapeSelectionChangedListener());
fillColorPicker = new ColorPicker(ColorPicker.AUTO | ColorPicker.CUSTOM
| ColorPicker.NONE, PaletteContents.getDefault());
fillColorPicker.getAction().setToolTipText(
PropertyMessages.BoundaryFillColor_toolTip);
fillColorPicker.addOpenListener(new FillColorOpenListener());
ToolBarManager colorBar = new ToolBarManager(SWT.FLAT);
colorBar.add(fillColorPicker);
ToolBar barControl = colorBar.createControl(parent);
barControl.setLayoutData(new GridData(GridData.END, GridData.CENTER,
false, false));
}
private void createLineContent2(Composite parent) {
Label opacityLabel = new Label(parent, SWT.NONE);
opacityLabel.setImage(getOpacityImage());
opacityLabel.setLayoutData(new GridData(GridData.BEGINNING,
GridData.CENTER, false, false));
opacityLabel.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
releaseImages();
}
});
opacityInput = new Text(parent, SWT.BORDER | SWT.SINGLE | SWT.TRAIL);
SWTUtils.makeNumeralInput(opacityLabel, false, false);
GridData inputData = new GridData(GridData.FILL, GridData.CENTER,
false, false);
inputData.widthHint = 25;
opacityInput.setLayoutData(inputData);
opacityInput.setTextLimit(3);
opacityInput.setToolTipText(PropertyMessages.BoundaryOpacity_toolTip);
Listener inputEventHandler = new Listener() {
public void handleEvent(Event event) {
if (event.type == SWT.DefaultSelection) {
int value = getOpacityValueFromTextWidget();
if (value >= 0) {
changeOpacity(value);
selectAllOpacityText(false);
}
} else if (event.type == SWT.KeyDown) {
if (event.character == SWT.ESC) {
updateOpacityToWidget();
}
} else if (event.type == SWT.FocusIn) {
selectAllOpacityText(false);
}
}
};
opacityInput.addListener(SWT.DefaultSelection, inputEventHandler);
opacityInput.addListener(SWT.KeyDown, inputEventHandler);
opacityInput.addListener(SWT.FocusIn, inputEventHandler);
Label percentageLabel = new Label(parent, SWT.NONE);
percentageLabel.setText("%"); //$NON-NLS-1$
percentageLabel.setLayoutData(new GridData(GridData.FILL,
GridData.CENTER, false, false));
opacityScale = new SliderViewer(parent, SWT.HORIZONTAL);
opacityScale.setLabelProvider(new OpacityLabelProvider());
opacityScale.getControl().setLayoutData(
new GridData(GridData.FILL, GridData.CENTER, true, false));
opacityScale.getControl().setBackground(parent.getBackground());
opacityScale
.addSelectionChangedListener(new OpacitySelectionChangedListener());
opacityScale
.addPostSelectionChangedListener(new OpacityPostSelectionChangedListener());
}
private Image getOpacityImage() {
if (opacityImage == null) {
ImageDescriptor icon = MindMapUI.getImages().get(
IMindMapImages.OPAQUE);
if (icon != null) {
opacityImage = icon.createImage(false);
}
}
return opacityImage;
}
private void releaseImages() {
if (opacityImage != null) {
opacityImage.dispose();
opacityImage = null;
}
}
private void selectAllOpacityText(final boolean takeFocus) {
if (opacityInput != null && !opacityInput.isDisposed()) {
opacityInput.getDisplay().asyncExec(new Runnable() {
public void run() {
if (opacityInput != null && !opacityInput.isDisposed()) {
if (takeFocus)
opacityInput.setFocus();
opacityInput.selectAll();
}
}
});
}
}
private int getOpacityValueFromTextWidget() {
if (opacityInput != null && !opacityInput.isDisposed()) {
try {
return Math.min(100, Integer.parseInt(opacityInput.getText()));
} catch (NumberFormatException e) {
}
}
return -1;
}
private int getOpacityValueFromScaleSelection(ISelection selection) {
Object o = ((IStructuredSelection) selection).getFirstElement();
return getOpacityValueFromScaleElement(o);
}
private int getOpacityValueFromScaleElement(Object o) {
if (o instanceof Double) {
double value = ((Double) o).doubleValue();
return (int) Math.round(value * 100);
}
return -1;
}
public void setFocus() {
if (shapeViewer != null && !shapeViewer.getControl().isDisposed()) {
shapeViewer.getControl().setFocus();
}
}
public void dispose() {
super.dispose();
shapeViewer = null;
fillColorPicker = null;
opacityInput = null;
opacityScale = null;
}
protected void doRefresh() {
String shapeId = null;
if (shapeViewer != null && !shapeViewer.getControl().isDisposed()) {
shapeId = getStyleValue(Styles.ShapeClass, null);
IDecorationDescriptor element = getSelectableShape(shapeId);
if (element == null) {
shapeViewer.setSelection(StructuredSelection.EMPTY);
} else {
shapeViewer.setSelection(new StructuredSelection(element));
}
}
if (fillColorPicker != null) {
if (shapeId == null)
shapeId = getStyleValue(Styles.ShapeClass, null);
updateColorPicker(fillColorPicker, Styles.FillColor, shapeId);
}
updateOpacityToWidget();
}
private void updateOpacityToWidget() {
String value = getStyleValue(Styles.Opacity, null);
double doubleValue = parseOpacityValue(value);
doubleValue = Math.max(0, Math.min(1, doubleValue));
if (opacityInput != null && !opacityInput.isDisposed()) {
opacityInput.setText(String.valueOf((int) Math
.round(doubleValue * 100)));
}
if (opacityScale != null && !opacityScale.getControl().isDisposed()) {
opacityScale.setSelection(new StructuredSelection(Double
.valueOf(doubleValue)));
}
}
private double parseOpacityValue(String value) {
if (value != null) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException e) {
}
}
return 1;
}
private IDecorationDescriptor getSelectableShape(String shapeId) {
if (shapeId == null)
return null;
IDecorationDescriptor descriptor = MindMapUI.getDecorationManager()
.getDecorationDescriptor(shapeId);
if (!getBoundaryShapes().contains(descriptor))
return null;
return descriptor;
}
private void changeShape(String newShape) {
Request request = createStyleRequest(CommandMessages.Command_ModifyBoundaryShape);
addStyle(request, Styles.ShapeClass, newShape);
sendRequest(request);
}
protected void changeFillColor(IColorSelection selection) {
changeColor(selection, Styles.FillColor,
CommandMessages.Command_ModifyFillColor);
}
private void changeOpacity(int opacityValue) {
Request request = createStyleRequest(CommandMessages.Command_ModifyWallpaperOpacity);
String value = String.valueOf((double) opacityValue * 1.0 / 100);
addStyle(request, Styles.Opacity, value);
sendRequest(request);
}
private void previewOpacity(int value) {
IGraphicalViewer viewer = getActiveViewer();
if (viewer != null) {
int alpha = -1;
for (Object o : getSelectedElements()) {
IPart p = viewer.findPart(o);
if (p instanceof IGraphicalPart) {
IFigure figure = ((IGraphicalPart) p).getFigure();
if (figure instanceof IDecoratedFigure) {
IDecoration decoration = ((IDecoratedFigure) figure)
.getDecoration();
if (decoration instanceof IShapeDecoration) {
if (alpha < 0) {
alpha = value * 255 / 100;
}
((IShapeDecoration) decoration).setFillAlpha(
figure, alpha);
}
}
}
}
}
}
private static List<IDecorationDescriptor> getBoundaryShapes() {
if (BoundaryShapes == null) {
BoundaryShapes = MindMapUI.getDecorationManager().getDescriptors(
IDecorationManager.CATEGORY_BOUNDARY_SHAPE);
}
return BoundaryShapes;
}
}