blob: 2448b0814acd5c12ebb96f07834f5544c33740a2 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2013, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.rtm.base.ui.rexpr;
import com.ibm.icu.text.DecimalFormat;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.statet.jcommons.text.core.input.StringParserInput;
import org.eclipse.statet.ecommons.graphics.core.ColorAlphaDef;
import org.eclipse.statet.ecommons.graphics.core.ColorDef;
import org.eclipse.statet.ecommons.graphics.core.HSVColorDef;
import org.eclipse.statet.ecommons.graphics.core.NamedColorDef;
import org.eclipse.statet.ecommons.graphics.core.NumberedRefColorDef;
import org.eclipse.statet.ecommons.ui.components.DoubleText;
import org.eclipse.statet.ecommons.ui.components.ObjValueEvent;
import org.eclipse.statet.ltk.ast.core.AstInfo;
import org.eclipse.statet.r.core.model.RGraphicFunctions;
import org.eclipse.statet.r.core.rsource.ast.RParser;
import org.eclipse.statet.r.ui.graphics.RAlphaChooser;
import org.eclipse.statet.r.ui.graphics.RColorChooser;
import org.eclipse.statet.rtm.base.ui.RtModelUIPlugin;
import org.eclipse.statet.rtm.base.ui.rexpr.RExprWidget.TypeDef;
import org.eclipse.statet.rtm.rtdata.types.RTypedExpr;
public class ColorType extends TypeDef implements PaintListener, Listener {
private Button detail;
private ColorDef currentValue;
private Color currentSWTColor;
private RColorChooser colorChooser;
private final RGraphicFunctions rGraphicFunctions= RGraphicFunctions.DEFAULT;
public ColorType(final RExprTypeUIAdapter type) {
super(type);
}
@Override
public boolean hasDetail() {
return true;
}
@Override
protected Control createDetailControl(final Composite parent) {
this.detail= new Button(parent, SWT.NONE);
this.detail.addPaintListener(this);
this.detail.addListener(SWT.Selection, this);
this.detail.addListener(SWT.Dispose, this);
return this.detail;
}
@Override
public void valueAboutToChange(final ObjValueEvent<RTypedExpr> event) {
final RTypedExpr newExpr= event.newValue;
ColorDef newValue= null;
if (newExpr != null && newExpr.getTypeKey() == RTypedExpr.R) {
try {
final RParser rParser= new RParser(AstInfo.LEVEL_MODEL_DEFAULT);
newValue= this.rGraphicFunctions.parseColorDef(rParser.scanExpr(
new StringParserInput(newExpr.getExpr()).init() ));
}
catch (final Exception e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR, RtModelUIPlugin.BUNDLE_ID,
"An error occurred when parsing the R color value expression.", e ));
}
}
doSetValue(newValue);
this.detail.redraw();
}
@Override
public void paintControl(final PaintEvent e) {
final GC gc= e.gc;
final Point size= this.detail.getSize();
gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_DARK_GRAY));
gc.drawRectangle(4, 4, size.x - 9, size.y - 9);
if (this.currentValue != null) {
if (this.currentValue instanceof ColorAlphaDef) {
if (this.currentSWTColor == null) {
this.currentSWTColor= RAlphaChooser.createPreviewColor(this.detail.getDisplay(), (ColorAlphaDef) this.currentValue);
}
RAlphaChooser.drawPreview(gc, 5, 5, size.x - 10, size.y - 10, this.currentSWTColor);
}
else {
if (this.currentSWTColor == null) {
this.currentSWTColor= RColorChooser.createPreviewColor(this.detail.getDisplay(), this.currentValue);
}
RColorChooser.drawPreview(gc, 5, 5, size.x - 11, size.y - 11, this.currentSWTColor);
}
}
}
@Override
public void handleEvent(final Event event) {
switch (event.type) {
case SWT.Selection:
showColorChooser();
return;
case SWT.Dispose:
if (this.colorChooser != null) {
this.colorChooser.dispose();
}
if (this.currentSWTColor != null) {
this.currentSWTColor.dispose();
this.currentSWTColor= null;
}
return;
default:
break;
}
}
private void showColorChooser() {
if (this.colorChooser == null) {
this.colorChooser= new RColorChooser() {
@Override
protected void onOK() {
ColorType.this.setValue(getValue());
}
};
}
if (this.colorChooser.isActive()) {
this.colorChooser.close();
return;
}
final Rectangle bounds= this.detail.getBounds();
{ final Point location= this.detail.getParent().toDisplay(new Point(bounds.x, bounds.y));
bounds.x= location.x;
bounds.y= location.y;
}
this.colorChooser.open(this.detail.getShell(), bounds, this.currentValue);
}
private void setValue(final ColorDef value) {
if (value == null) {
setExpr(""); //$NON-NLS-1$
return;
}
final StringBuilder sb= new StringBuilder();
ColorAlphaDef alpha= null;
ColorDef color= value;
if (value instanceof ColorAlphaDef) {
alpha= (ColorAlphaDef) value;
color= alpha.getRef();
if (alpha.getAlpha() == 1f) {
alpha= null;
}
}
if (color instanceof NamedColorDef) {
if (alpha != null) {
sb.append(RGraphicFunctions.ADJUST_COLOR_NAME + '(');
}
sb.append('"');
sb.append(((NamedColorDef) color).getName());
sb.append('"');
if (alpha != null) {
final DecimalFormat format= DoubleText.createFormat(3);
sb.append(", "); //$NON-NLS-1$
sb.append(format.format(alpha.getAlpha()));
sb.append(')');
}
}
else if (color instanceof NumberedRefColorDef) {
if (alpha != null) {
sb.append(RGraphicFunctions.ADJUST_COLOR_NAME + '(');
}
sb.append(((NumberedRefColorDef) color).getNumber());
if (alpha != null) {
final DecimalFormat format= DoubleText.createFormat(3);
sb.append(", "); //$NON-NLS-1$
sb.append(format.format(alpha.getAlpha()));
sb.append(')');
}
}
else if (color instanceof HSVColorDef) {
final HSVColorDef hsvColor= (HSVColorDef) color;
sb.append(RGraphicFunctions.HSV_NAME + '(');
final DecimalFormat format= DoubleText.createFormat(3);
sb.append(format.format(hsvColor.getHue()));
sb.append(", "); //$NON-NLS-1$
sb.append(format.format(hsvColor.getSaturation()));
sb.append(", "); //$NON-NLS-1$
sb.append(format.format(hsvColor.getValue()));
if (alpha != null) {
sb.append(", "); //$NON-NLS-1$
sb.append(format.format(alpha.getAlpha()));
}
sb.append(')');
}
else {
sb.append('"');
sb.append('#');
if (alpha != null) {
alpha.printRGBAHex(sb);
}
else {
value.printRGBHex(sb);
}
sb.append('"');
}
doSetValue(value);
this.detail.redraw();
setExpr(sb.toString());
}
private void doSetValue(final ColorDef value) {
if (this.currentSWTColor != null && !this.currentValue.equals(value)) {
this.currentSWTColor.dispose();
this.currentSWTColor= null;
}
this.currentValue= value;
}
}