| /*=============================================================================# |
| # 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; |
| } |
| |
| } |