Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » scout » Colour picker
Colour picker [message #1067517] Tue, 09 July 2013 04:16 Go to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
In our application we want to let the users define certain colours. For this we need a colour picket control. In the back of my head I thought I'd seen a forum post about this, but have been unable to find anything either in the forum or the wiki.

Is there an existing colour picker control that can be used with scout?
Re: Colour picker [message #1070659 is a reply to message #1067517] Thu, 18 July 2013 08:07 Go to previous messageGo to next message
Andreas Hoegger is currently offline Andreas Hoegger
Messages: 173
Registered: February 2010
Senior Member
Hi Urs

So far we did not implement a color picker. To get there implement a custom control and use the
SWT: org.eclipse.swt.widgets.ColorDialog
Swing: javax.swing.JColorChooser

If you are able please create a patch/gerrit change.
Many thanks...

-Andreas
Re: Colour picker [message #1070674 is a reply to message #1070659] Thu, 18 July 2013 08:38 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Thanks Andreas, I'll give it a go.
Re: Colour picker [message #1072724 is a reply to message #1070659] Tue, 23 July 2013 07:34 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Ok, I've managed to put together a custom control with support for SWT, Swing and RAP. It returns a String, containing the chosen colour as a 6-digit hex number. It displays the chosen colour as a rectangular, coloured field (if a colour is defined) or as a white field with black border (if no colour is defined).

It comes with the following properties:
getConfiguredColor() -> the default colour to use
getConfiguredDefaultMenus() -> if set to true, will show pre-defined context menus when right clicking the colour-rectangle with support to clear the chosen colour (all renderers) and the possibility to clear the custom colours (SWT only)

It also comes with a callback method:
execChanged() -> called when a colour is chosen on the UI

index.php/fa/15668/0/

Andreas Hoegger wrote on Thu, 18 July 2013 14:07
If you are able please create a patch/gerrit change.


I'm happy to provide the code to be integrated into Scout by you, but at the moment I'm unable to create a patch/gerrit change. I am posting the code in my next post (and will attach it as a ZIP file).

Here are some previews of a form containing four ColorPickerFields:

index.php/fa/15669/0/
index.php/fa/15670/0/
index.php/fa/15671/0/
Re: Colour picker [message #1072732 is a reply to message #1072724] Tue, 23 July 2013 07:48 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Attached you will find a ZIP file with all the necessary java files:

Client

IColorPickerField
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
import org.eclipse.scout.rt.client.ui.form.fields.IFormField;

public interface IColorPickerField extends IFormField {
  public static final String PROP_COLOR = "Color";
  public static final String PROP_CLEAR_CUSTOM_COLORS = "ClearCustomColors";

  String getColor();

  void setColor(String c);

  boolean hasMenus();

  IMenu[] getMenus();

  IColorPickerUiFacade getUiFacade();
}


IColorPickerUiFacade
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;

public interface IColorPickerUiFacade {
  void setColorFromUI(String color);

  IMenu[] firePopupFromUI();
}


AbstractColorPickerField
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.minicrm.shared.services.process.AbstractColorPickerFieldData;
import org.eclipse.scout.commons.ConfigurationUtility;
import org.eclipse.scout.commons.TypeCastUtility;
import org.eclipse.scout.commons.annotations.ConfigOperation;
import org.eclipse.scout.commons.annotations.ConfigProperty;
import org.eclipse.scout.commons.annotations.ConfigPropertyValue;
import org.eclipse.scout.commons.annotations.FormData;
import org.eclipse.scout.commons.annotations.FormData.DefaultSubtypeSdkCommand;
import org.eclipse.scout.commons.annotations.FormData.SdkCommand;
import org.eclipse.scout.commons.annotations.Order;
import org.eclipse.scout.commons.exception.ProcessingException;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.commons.xmlparser.SimpleXmlElement;
import org.eclipse.scout.rt.client.ui.action.menu.AbstractMenu;
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
import org.eclipse.scout.rt.client.ui.form.fields.customfield.AbstractCustomField;
import org.eclipse.scout.rt.shared.TEXTS;
import org.eclipse.scout.rt.shared.services.common.exceptionhandler.IExceptionHandlerService;
import org.eclipse.scout.rt.shared.ui.UserAgentUtility;
import org.eclipse.scout.service.SERVICES;

@FormData(value = AbstractColorPickerFieldData.class, sdkCommand = SdkCommand.CREATE, defaultSubtypeSdkCommand = DefaultSubtypeSdkCommand.CREATE)
public abstract class AbstractColorPickerField extends AbstractCustomField implements IColorPickerField {
  private static final IScoutLogger LOG = ScoutLogManager.getLogger(AbstractColorPickerField.class);
  private IColorPickerUiFacade m_uiFacade;
  private IMenu[] m_menus;

  private String m_color;

  // ---------------------------------------------------------------------------------
  @Override
  @FormData
  public String getColor() {
    return m_color;
  }

  @Override
  @FormData
  public void setColor(String color) {
    m_color = color;
    propertySupport.setProperty(PROP_COLOR, color);
    execChanged();
  }

  @Override
  public IColorPickerUiFacade getUiFacade() {
    return m_uiFacade;
  }

  @ConfigOperation
  @Order(190)
  // override if needed
  public void execChanged() {
  }

  public void clearCustomColors() {
    String toggle = "Clear";
    if (propertySupport.getProperty(PROP_CLEAR_CUSTOM_COLORS) != null) {
      toggle = null;
    }
    propertySupport.setProperty(PROP_CLEAR_CUSTOM_COLORS, toggle);
  }

  // ---------------------------------------------------------------------------------
  /*
   * Configuration
   */
  // ---------------------------------------------------------------------------------
  @ConfigProperty(ConfigProperty.STRING)
  @Order(500)
  @ConfigPropertyValue("0")
  protected String getConfiguredColor() {
    return null;
  }

  @ConfigProperty(ConfigProperty.BOOLEAN)
  @Order(501)
  @ConfigPropertyValue("FALSE")
  protected boolean getConfiguredDefaultMenus() {
    return false;
  }

  @SuppressWarnings("unchecked")
  private Class<? extends IMenu>[] getConfiguredMenus() {
    Class[] dca = ConfigurationUtility.getDeclaredPublicClasses(getClass());
    Class<IMenu>[] foca = ConfigurationUtility.sortFilteredClassesByOrderAnnotation(dca, IMenu.class);
    if (!getConfiguredDefaultMenus()) {
      List<Class<IMenu>> menus = new ArrayList<Class<IMenu>>();
      for (int i=0; i<foca.length; ++i) {
        boolean local = false;
        for (Class iface : foca[i].getInterfaces()) {
          if (iface.getName().equals(IDefaultColorPickerMenu.class.getName())) {
            local = true;
          }
        }
        if (!local) {
          menus.add(foca[i]);
        }
      }
      foca = menus.toArray(new Class[menus.size()]);
    }
    return ConfigurationUtility.removeReplacedClasses(foca);
  }

  @Override
  protected void initConfig() {
    m_uiFacade = new P_UiFacade();
    super.initConfig();
    setColor(getConfiguredColor());

    // menus
    ArrayList<IMenu> menuList = new ArrayList<IMenu>();
    Class<? extends IMenu>[] menuArray = getConfiguredMenus();
    for (int i = 0; i < menuArray.length; i++) {
      IMenu menu;
      try {
        menu = ConfigurationUtility.newInnerInstance(this, menuArray[i]);
        menuList.add(menu);
      } catch (Throwable t) {
        SERVICES.getService(IExceptionHandlerService.class).handleException(new ProcessingException("menu: " + menuArray[i].getName(), t));
      }
    }
    try {
      injectMenusInternal(menuList);
    } catch (Exception e) {
      LOG.error("error occured while dynamically contributing menus.", e);
    }
    m_menus = menuList.toArray(new IMenu[0]);
  }

  /**
   * Override this internal method only in order to make use of dynamic menus<br>
   * Used to manage menu list and add/remove menus
   * 
   * @param menuList
   *          live and mutable list of configured menus
   */
  protected void injectMenusInternal(List<IMenu> menuList) {
  }

  @Override
  public boolean hasMenus() {
    return m_menus.length > 0;
  }

  @Override
  public IMenu[] getMenus() {
    return m_menus;
  }

  private IMenu[] firePopup() {
    List<IMenu> result = new ArrayList<IMenu>();
    // single observer add our menus
    IMenu[] a = getMenus();
    for (int i = 0; i < a.length; i++) {
      IMenu m = a[i];
      m.prepareAction();
      if (m.isVisible()) {
        result.add(m);
      }
    }
    return result.toArray(new IMenu[result.size()]);
  }

  // ---------------------------------------------------------------------------------
  private class P_UiFacade implements IColorPickerUiFacade {
    @Override
    public void setColorFromUI(String color) {
      setColor(color);
    }

    @Override
    public IMenu[] firePopupFromUI() {
      return firePopup();
    }
  }

  // ---------------------------------------------------------------------------------
  private String m_initColor;

  public AbstractColorPickerField() {
    this(true);
  }

  public AbstractColorPickerField(boolean callInitializer) {
    super(callInitializer);
  }

  // ---------------------------------------------------------------------------------
  /*
   * XML i/o
   */
  @Override
  public void storeXML(SimpleXmlElement x) throws ProcessingException {
    super.storeXML(x);
    try {
      x.setObjectAttribute(IColorPickerField.PROP_COLOR, getColor());
    } catch (IOException e) {
      if (LOG.isInfoEnabled()) {
        LOG.info("not serializable value in field " + getClass().getName() + "/" + getLabel() + ": " + e);
      }
    }
  }

  @Override
  public void loadXML(SimpleXmlElement x) throws ProcessingException {
    super.loadXML(x);
    try {
      String color = TypeCastUtility.castValue(x.getObjectAttribute(IColorPickerField.PROP_COLOR, null), String.class);
      setColor(color);
    } catch (Exception e) {
      // be lenient, maybe the field was changed
      LOG.warn(null, e);
    }
  }

  // ---------------------------------------------------------------------------------
  public void setInitValue(String initColor) {
    m_initColor = initColor;
  }

  public String getInitColor() {
    return m_initColor;
  }

  @Override
  protected boolean execIsSaveNeeded() throws ProcessingException {
    String color = getColor();
    String initColor = getInitColor();

    if (color == null && initColor == null) {
      return false;
    } else if (color == null || initColor == null) {
      return true;
    } else {
      return !color.equals(initColor);
    }
  }

  @Override
  protected void execMarkSaved() throws ProcessingException {
    super.execMarkSaved();
    setInitValue(getColor());
  }

  // ---------------------------------------------------------------------------------
  private interface IDefaultColorPickerMenu extends IMenu {

  }

  @Order(1.0)
  public class ClearColorContextMenu extends AbstractMenu implements IDefaultColorPickerMenu {
    @Override
    protected String getConfiguredText() {
      return TEXTS.get("ClearColor");
    }

    @Override
    protected void execPrepareAction() throws ProcessingException {
      setEnabled(getColor() != null);
    }

    @Override
    protected void execAction() throws ProcessingException {
      setColor(null);
    }

  }

  @Order(2.0)
  public class ClearCustomColorsContextMenu extends AbstractMenu implements IDefaultColorPickerMenu {
    @Override
    protected String getConfiguredText() {
      return TEXTS.get("ClearCustomColors");
    }

    @Override
    protected void execAction() throws ProcessingException {
      clearCustomColors();
    }

    @Override
    protected void execPrepareAction() throws ProcessingException {
      // when "recent color" support has been added to Swing, isSwtUi() can be replaced with isRichClient()
      setVisible(UserAgentUtility.isSwtUi());
      // setVisible(UserAgentUtility.isRichClient());
    }

  }

  @Order(3.0)
  public class DefaultSeparatorContextMenu extends AbstractMenu implements IDefaultColorPickerMenu {

    @Override
    protected boolean getConfiguredSeparator() {
      return true;
    }

  }
}



SWT

SwtScoutColorPickerField
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField;
import org.eclipse.scout.commons.RunnableWithData;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.job.JobEx;
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
import org.eclipse.scout.rt.shared.TEXTS;
import org.eclipse.scout.rt.ui.swt.LogicalGridLayout;
import org.eclipse.scout.rt.ui.swt.SwtMenuUtility;
import org.eclipse.scout.rt.ui.swt.ext.StatusLabelEx;
import org.eclipse.scout.rt.ui.swt.form.fields.SwtScoutFieldComposite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;

public class SwtScoutColorPickerField extends SwtScoutFieldComposite<IColorPickerField> {
  private P_MouseListener m_mouseListener;
  private static RGB[] rgbs;
  private Menu m_contextMenu;

  private final static RGB WHITE = new RGB(255, 255, 255);

  @Override
  protected void initializeSwt(Composite parent) {
    m_mouseListener = new P_MouseListener();

    Composite container = getEnvironment().getFormToolkit().createComposite(parent);
    StatusLabelEx label = getEnvironment().getFormToolkit().createStatusLabel(container, getEnvironment(), getScoutObject());
    Canvas canvas = getEnvironment().getFormToolkit().createCanvas(container);

    canvas.addPaintListener(new P_PaintListener());
    canvas.addMouseListener(m_mouseListener);

    // context menu
    m_contextMenu = new Menu(canvas.getShell(), SWT.POP_UP);
    m_contextMenu.addMenuListener(new P_ContextMenuListener());
    canvas.setMenu(m_contextMenu);

    setSwtContainer(container);
    setSwtLabel(label);
    setSwtField(canvas);

    // layout
    getSwtContainer().setLayout(new LogicalGridLayout(1, 0));
  }

  @Override
  protected void attachScout() {
    super.attachScout();
    updateColorFromScout();
  }

  protected void updateColorFromScout() {
    getSwtField().redraw();
  }

  protected void handleSwtPickColor() {
    Shell shell = new Shell(getEnvironment().getDisplay());

    ColorDialog colorDialog = new ColorDialog(shell);
    colorDialog.setText(TEXTS.get("SelectColor"));
    RGB rgb = getRgb(getScoutObject().getColor());
    if (rgb != null) {
      colorDialog.setRGB(rgb);

      if (rgbs == null) {
        rgbs = colorDialog.getRGBs();
      }
      if (rgbs != null) {
        boolean found = false;
        for(int i=0; i<rgbs.length; ++i) {
          if (rgbs[i] != null && rgbs[i].equals(rgb)) {
            found = true;
            break;
          }
        }
        if (!found) {
          for (int i = 0; i < rgbs.length; ++i) {
            if (WHITE.equals(rgbs[i])) {
              rgbs[i] = rgb;
              found = true;
              break;
            }
          }
        }
        if (!found) {
          rgbs[rgbs.length-1] = rgb;
        }
      } else {
        rgbs = new RGB[] { rgb };
      }
    }
    colorDialog.setRGBs(rgbs);
    RGB selectedColor = colorDialog.open();
    if (selectedColor != null) {
      rgbs = colorDialog.getRGBs();

      final String color = getColorString(selectedColor.red, selectedColor.green, selectedColor.blue).toUpperCase();

      RunnableWithData t = new RunnableWithData() {
        @Override
        public void run() {
          getScoutObject().getUiFacade().setColorFromUI(color);
        }
      };
      getEnvironment().invokeScoutLater(t, 2345);
    }
    shell.dispose();
  }

  public String getColorString(int red, int green, int blue) {
    int iRgb = ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 0);
    String hexString = Integer.toHexString(iRgb);
    while (hexString.length() < 6) {
      hexString = "0" + hexString;
    }
    return hexString;
  }

  public RGB getRgb(String color) {
    if (!StringUtility.isNullOrEmpty(color) && color.length() >= 6) {
      int red = Integer.parseInt(color.substring(0, 2), 16);
      int green = Integer.parseInt(color.substring(2, 4), 16);
      int blue = Integer.parseInt(color.substring(4, 6), 16);
      return new RGB(red, green, blue);
    }
    return null;
  }

  @Override
  protected void handleScoutPropertyChange(String name, Object newValue) {
    if (name.equals(IColorPickerField.PROP_COLOR)) {
      updateColorFromScout();
    } else if (name.equals(IColorPickerField.PROP_CLEAR_CUSTOM_COLORS)) {
      rgbs = new RGB[] { WHITE };
    }
    super.handleScoutPropertyChange(name, newValue);
  }

  private class P_PaintListener implements PaintListener {
    private static final long serialVersionUID = 1L;

    @Override
    public void paintControl(PaintEvent e) {
      if (getScoutObject().getColor() != null) {
        e.gc.setBackground(getEnvironment().getColor(getScoutObject().getColor()));
        e.gc.setForeground(getEnvironment().getColor("000000"));
      } else {
        e.gc.setBackground(getEnvironment().getColor("FFFFFF"));
        e.gc.setForeground(getEnvironment().getColor("000000"));
      }
      Rectangle bounds = getSwtField().getBounds();
      e.gc.fillRectangle(bounds);
      e.gc.drawRectangle(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);
    }
  }

  private class P_MouseListener implements MouseListener, MouseMoveListener {
    @Override
    public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
    }

    @Override
    public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
      if (e != null && e.button == 1) {
        handleSwtPickColor();
      }
    }

    @Override
    public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
    }

    @Override
    public void mouseMove(org.eclipse.swt.events.MouseEvent e) {
    }

  }

  private class P_ContextMenuListener extends MenuAdapter {
    @Override
    public void menuShown(MenuEvent e) {
      for (MenuItem item : m_contextMenu.getItems()) {
        disposeMenuItem(item);
      }
      final AtomicReference<IMenu[]> scoutMenusRef = new AtomicReference<IMenu[]>();
      Runnable t = new Runnable() {
        @Override
        public void run() {
          IMenu[] scoutMenus = getScoutObject().getUiFacade().firePopupFromUI();
          scoutMenusRef.set(scoutMenus);
        }
      };
      JobEx job = getEnvironment().invokeScoutLater(t, 1200);
      try {
        job.join(1200);
      } catch (InterruptedException ex) {
        // nop
      }
      // grab the actions out of the job, when the actions are providden within
      // the scheduled time the popup will be handled.
      if (scoutMenusRef.get() != null) {
        SwtMenuUtility.fillContextMenu(scoutMenusRef.get(), m_contextMenu, getEnvironment());
      }
    }

    private void disposeMenuItem(MenuItem item) {
      Menu menu = item.getMenu();
      if (menu != null) {
        for (MenuItem childItem : menu.getItems()) {
          disposeMenuItem(childItem);
        }
        menu.dispose();
      }
      item.dispose();
    }

  } // end class P_ContextMenuListener
}


plugin.xml
   <extension
         point="org.eclipse.scout.rt.ui.swt.formfields">
     <formField
           active="true"
           modelClass="org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField"
           name="Color Picker Field"
           scope="default">
        <uiClass
              class="org.eclipse.minicrm.ui.swt.form.fields.ext.SwtScoutColorPickerField">
        </uiClass>
     </formField>
   </extension>



Swing

SwingScoutColorPickerField
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JColorChooser;
import javax.swing.JComponent;

import org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField;
import org.eclipse.scout.commons.RunnableWithData;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
import org.eclipse.scout.rt.shared.TEXTS;
import org.eclipse.scout.rt.ui.swing.LogicalGridLayout;
import org.eclipse.scout.rt.ui.swing.SwingPopupWorker;
import org.eclipse.scout.rt.ui.swing.SwingUtility;
import org.eclipse.scout.rt.ui.swing.ext.BorderLayoutEx;
import org.eclipse.scout.rt.ui.swing.ext.JPanelEx;
import org.eclipse.scout.rt.ui.swing.ext.JStatusLabelEx;
import org.eclipse.scout.rt.ui.swing.form.fields.SwingScoutFieldComposite;


public class SwingScoutColorPickerField extends SwingScoutFieldComposite<IColorPickerField> {
  private P_MouseListener m_mouseListener;

  @Override
  protected void initializeSwing() {
    m_mouseListener = new P_MouseListener();
    JPanelEx container = new JPanelEx(new BorderLayoutEx());
    container.setOpaque(false);
    JStatusLabelEx label = new JStatusLabelEx();
    container.add(label, BorderLayoutEx.CENTER);

    MyComponent field = new MyComponent();
    SwingUtility.installDefaultFocusHandling(field);
    container.add(field);

    field.addMouseListener(m_mouseListener);

    setSwingContainer(container);
    setSwingLabel(label);
    setSwingField(field);

    getSwingContainer().setLayout(new LogicalGridLayout(getSwingEnvironment(), 1, 0));
  }

  @Override
  protected void attachScout() {
    super.attachScout();
    updateColorFromScout();
  }

  protected void updateColorFromScout() {
    getSwingField().repaint();
  }

  protected void handleSwtPickColor() {

    Color color = getColor(getScoutObject().getColor());

    // TODO: add recent colour handling : see http://stackoverflow.com/questions/10793916/jcolorchooser-save-restore-recent-colors-in-swatches-panel

    Color selectedColor = JColorChooser.showDialog(getSwingField(), TEXTS.get("SelectColor"), color);
    if (selectedColor != null) {
      final String colorString = getColorString(selectedColor.getRed(), selectedColor.getGreen(), selectedColor.getBlue()).toUpperCase();

      RunnableWithData t = new RunnableWithData() {
        @Override
        public void run() {
          getScoutObject().getUiFacade().setColorFromUI(colorString);
        }
      };
      getSwingEnvironment().invokeScoutLater(t, 2345);
    }
  }

  public String getColorString(int red, int green, int blue) {
    int iRgb = ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 0);
    String hexString = Integer.toHexString(iRgb);
    while (hexString.length() < 6) {
      hexString = "0" + hexString;
    }
    return hexString;
  }

  public Color getColor(String color) {
    if (!StringUtility.isNullOrEmpty(color) && color.length() >= 6) {
      int red = Integer.parseInt(color.substring(0, 2), 16);
      int green = Integer.parseInt(color.substring(2, 4), 16);
      int blue = Integer.parseInt(color.substring(4, 6), 16);
      return new Color(red, green, blue);
    }
    return null;
  }

  @Override
  protected void handleScoutPropertyChange(String name, Object newValue) {
    if (name.equals(IColorPickerField.PROP_COLOR)) {
      updateColorFromScout();
    } else if (name.equals(IColorPickerField.PROP_CLEAR_CUSTOM_COLORS)) {
      // TODO: clear recent
    }
    super.handleScoutPropertyChange(name, newValue);
  }

  private class MyComponent extends JComponent {
    private static final long serialVersionUID = 1L;

    @Override
    public void paint(Graphics g) {
      super.paint(g);
      Rectangle bounds = getSwingField().getBounds();

      if (getScoutObject().getColor() != null) {
        g.setColor(getColor(getScoutObject().getColor()));
      } else {
        g.setColor(getColor("FFFFFF"));
      }
      g.fillRect(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);

      if (getScoutObject().getColor() != null) {
        g.setColor(getColor(getScoutObject().getColor()));
      } else {
        g.setColor(getColor("000000"));
      }
      g.drawRect(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);
    }
  }

  private class P_MouseListener extends MouseAdapter {
    @Override
    public void mousePressed(MouseEvent e) {
      if (e != null) {
        if (e.getButton() == MouseEvent.BUTTON1) {
          handleSwtPickColor();
        }
        if (e.isPopupTrigger() && e.getComponent().isEnabled()) {
          handleSwingPopup(e);
        }
      }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
      if (e != null && e.isPopupTrigger() && e.getComponent().isEnabled()) {
        handleSwingPopup(e);
      }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
    }
  }

  protected void handleSwingPopup(final MouseEvent e) {
    // notify Scout
    Runnable t = new Runnable() {
      @Override
      public void run() {
        IMenu[] a = getScoutObject().getUiFacade().firePopupFromUI();
        // call swing menu
        new SwingPopupWorker(getSwingEnvironment(), e.getComponent(), e.getPoint(), a).enqueue();
      }
    };
    getSwingEnvironment().invokeScoutLater(t, 5678);
    // end notify
  }

}


plugin.xml
  <extension
        point="org.eclipse.scout.rt.ui.swing.formfields">
     <formField
           active="true"
           modelClass="org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField"
           name="Color Picker Field"
           scope="default">
        <uiClass
              class="org.eclipse.minicrm.ui.swing.form.fields.ext.SwingScoutColorPickerField">
        </uiClass>
  </extension>


RAP

RwtScoutColorPickerField
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField;
import org.eclipse.scout.commons.RunnableWithData;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.commons.job.JobEx;
import org.eclipse.scout.rt.client.ui.action.menu.IMenu;
import org.eclipse.scout.rt.shared.TEXTS;
import org.eclipse.scout.rt.ui.rap.LogicalGridLayout;
import org.eclipse.scout.rt.ui.rap.RwtMenuUtility;
import org.eclipse.scout.rt.ui.rap.ext.StatusLabelEx;
import org.eclipse.scout.rt.ui.rap.form.fields.RwtScoutFieldComposite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;

public class RwtScoutColorPickerField extends RwtScoutFieldComposite<IColorPickerField> {
  private P_MouseListener m_mouseListener;
  private Menu m_contextMenu;

  @Override
  protected void initializeUi(Composite parent) {
    m_mouseListener = new P_MouseListener();

    Composite container = getUiEnvironment().getFormToolkit().createComposite(parent);
    StatusLabelEx label = getUiEnvironment().getFormToolkit().createStatusLabel(container, getScoutObject());
    Canvas canvas = getUiEnvironment().getFormToolkit().createCanvas(container);

    canvas.addPaintListener(new P_PaintListener());
    canvas.addMouseListener(m_mouseListener);

    // context menu
    m_contextMenu = new Menu(canvas.getShell(), SWT.POP_UP);
    m_contextMenu.addMenuListener(new P_ContextMenuListener());
    canvas.setMenu(m_contextMenu);

    setUiContainer(container);
    setUiLabel(label);
    setUiField(canvas);

    // layout
    getUiContainer().setLayout(new LogicalGridLayout(1, 0));
  }

  @Override
  protected void attachScout() {
    super.attachScout();
    updateColorFromScout();
  }

  protected void updateColorFromScout() {
    getUiField().redraw();
  }

  protected void handleSwtPickColor() {
    Shell shell = new Shell(getUiEnvironment().getDisplay());

    ColorDialog colorDialog = new ColorDialog(shell);
    colorDialog.setText(TEXTS.get("SelectColor"));
    RGB rgb = getRgb(getScoutObject().getColor());
    if (rgb != null) {
      colorDialog.setRGB(rgb);
    }
    RGB selectedColor = colorDialog.open();
    if (selectedColor != null) {

      final String color = getColorString(selectedColor.red, selectedColor.green, selectedColor.blue).toUpperCase();

      RunnableWithData t = new RunnableWithData() {
        @Override
        public void run() {
          getScoutObject().getUiFacade().setColorFromUI(color);
        }
      };
      getUiEnvironment().invokeScoutLater(t, 2345);
    }
    shell.dispose();
  }

  public String getColorString(int red, int green, int blue) {
    int iRgb = ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 0);
    String hexString = Integer.toHexString(iRgb);
    while (hexString.length() < 6) {
      hexString = "0" + hexString;
    }
    return hexString;
  }

  public RGB getRgb(String color) {
    if (!StringUtility.isNullOrEmpty(color) && color.length() >= 6) {
      int red = Integer.parseInt(color.substring(0, 2), 16);
      int green = Integer.parseInt(color.substring(2, 4), 16);
      int blue = Integer.parseInt(color.substring(4, 6), 16);
      return new RGB(red, green, blue);
    }
    return null;
  }

  @Override
  protected void handleScoutPropertyChange(String name, Object newValue) {
    if (name.equals(IColorPickerField.PROP_COLOR)) {
      updateColorFromScout();
    }
    super.handleScoutPropertyChange(name, newValue);
  }

  private class P_PaintListener implements PaintListener {
    private static final long serialVersionUID = 1L;

    @Override
    public void paintControl(PaintEvent e) {
      if (getScoutObject().getColor() != null) {
        e.gc.setBackground(getUiEnvironment().getColor(getScoutObject().getColor()));
        e.gc.setForeground(getUiEnvironment().getColor("000000"));
      } else {
        e.gc.setBackground(getUiEnvironment().getColor("FFFFFF"));
        e.gc.setForeground(getUiEnvironment().getColor("000000"));
      }
      Rectangle bounds = getUiField().getBounds();
      e.gc.fillRectangle(bounds);
      e.gc.drawRectangle(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);
    }
  }

  private class P_MouseListener implements MouseListener, MouseMoveListener {
    private static final long serialVersionUID = 1L;
    private boolean m_mouseDown = false;

    @Override
    public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent e) {
    }

    @Override
    public void mouseDown(org.eclipse.swt.events.MouseEvent e) {
      if (e != null && e.button == 1) {
        m_mouseDown = true;
        handleSwtPickColor();
      }
    }

    @Override
    public void mouseUp(org.eclipse.swt.events.MouseEvent e) {
    }

    @Override
    public void mouseMove(org.eclipse.swt.events.MouseEvent e) {
    }

  }

  private class P_ContextMenuListener extends MenuAdapter {
    private static final long serialVersionUID = 1L;

    @Override
    public void menuShown(MenuEvent e) {
      for (MenuItem item : m_contextMenu.getItems()) {
        disposeMenuItem(item);
      }
      final AtomicReference<IMenu[]> scoutMenusRef = new AtomicReference<IMenu[]>();
      Runnable t = new Runnable() {
        @Override
        public void run() {
          IMenu[] scoutMenus = getScoutObject().getUiFacade().firePopupFromUI();
          scoutMenusRef.set(scoutMenus);
        }
      };
      JobEx job = getUiEnvironment().invokeScoutLater(t, 1200);
      try {
        job.join(1200);
      } catch (InterruptedException ex) {
        // nop
      }
      // grab the actions out of the job, when the actions are providden within
      // the scheduled time the popup will be handled.
      if (scoutMenusRef.get() != null) {
        RwtMenuUtility.fillContextMenu(scoutMenusRef.get(), getUiEnvironment(), m_contextMenu);
      }
    }

    private void disposeMenuItem(MenuItem item) {
      Menu menu = item.getMenu();
      if (menu != null) {
        for (MenuItem childItem : menu.getItems()) {
          disposeMenuItem(childItem);
        }
        menu.dispose();
      }
      item.dispose();
    }

  } // end class P_ContextMenuListener
}


plugin.xml
   <extension
         point="org.eclipse.scout.rt.ui.rap.formfields">
     <formField
           active="true"
           modelClass="org.eclipse.minicrm.client.ui.form.fields.ext.IColorPickerField"
           name="Color Picker Field"
           scope="default">
        <uiClass
              class="org.eclipse.minicrm.ui.rap.form.fields.ext.RwtScoutColorPickerField">
        </uiClass>
     </formField>
   </extension>


Re: Colour picker [message #1072759 is a reply to message #1072732] Tue, 23 July 2013 08:43 Go to previous messageGo to next message
Andreas Hoegger is currently offline Andreas Hoegger
Messages: 173
Registered: February 2010
Senior Member
Wow - thank you Urs great work.
I opened a Bugzilla413517 to track the contribution. Furthermore I will run through your changes and come up with a gerrit change for review.

-andreas
Re: Colour picker [message #1073116 is a reply to message #1072759] Wed, 24 July 2013 03:06 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
A small correction, it seems there is something funny about the values getBounds() returns in all of the renderers. In order to correctly draw the fields in the currently selected colour, some code must be adjusted:

SWT & RAP

In paintControl() replace
      e.gc.fillRectangle(bounds);
      e.gc.drawRectangle(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);

with
      e.gc.fillRectangle(0, 0, bounds.width - 1, bounds.height - 1);
      e.gc.drawRectangle(0, 0, bounds.width - 1, bounds.height - 1);


Swing

In MyComponent.paint() Replace
      g.fillRect(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);

      if (getScoutObject().getColor() != null) {
        g.setColor(getColor(getScoutObject().getColor()));
      } else {
        g.setColor(getColor("000000"));
      }
      g.drawRect(bounds.x, bounds.y, bounds.width - bounds.x - 1, bounds.height - 1);

with
      g.fillRect(0, 0, bounds.width - 1, bounds.height - 1);

      g.setColor(getColor("000000"));
      g.drawRect(0, 0, bounds.width - 1, bounds.height - 1);

[Updated on: Wed, 24 July 2013 03:06]

Report message to a moderator

Re: Colour picker [message #1073130 is a reply to message #1073116] Wed, 24 July 2013 03:35 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie Bresson
Messages: 654
Registered: October 2011
Senior Member
I really think we should open a Gerrit Change to discuss the code and to push the different version (it is much more easier than in the forum).

A question from my side:
Why isn't the ColorField a ValueField<T> where <T> is a String? I think also in your example, the color is stored in a String (Like in HTML RRGGBB)?
Re: Colour picker [message #1073227 is a reply to message #1073130] Wed, 24 July 2013 06:55 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Jeremie Bresson wrote on Wed, 24 July 2013 09:35
I really think we should open a Gerrit Change to discuss the code and to push the different version (it is much more easier than in the forum).

I just discussed this whole topic offline with Andy this morning. As I understood it, he will open a Gerrit Change and make a proposal for the colour picker based on my code, with some changes that he proposed.

Jeremie Bresson wrote on Wed, 24 July 2013 09:35
A question from my side:
Why isn't the ColorField a ValueField<T> where <T> is a String? I think also in your example, the color is stored in a String (Like in HTML RRGGBB)?

Because that thought only occurred to me after I had posted my code Smile It's a good idea, I think.
Re: Colour picker [message #1074156 is a reply to message #1073227] Fri, 26 July 2013 03:51 Go to previous messageGo to next message
Jeremie Bresson is currently offline Jeremie Bresson
Messages: 654
Registered: October 2011
Senior Member
Urs Beeli wrote on Wed, 24 July 2013 12:55

I just discussed this whole topic offline with Andy this morning. As I understood it, he will open a Gerrit Change and make a proposal for the colour picker based on my code, with some changes that he proposed.


I bet you can do this by yourself. It is not so complicated and you will learn a lot of interesting stuff. (To contribute code on the Eclipse WikiText project, I learned git and gerrit... I had only knowledge of SVN before that. If you are ready you can learn it too).

There is a guide: Contributions for Scout Committers (effort in progress). Everything also apply to contributors too (just the "submit" part is for commiters only).

If you are interested, do not hesitate to ask questions in the forum. I will be happy to guide you. We can also update and improve the guide if it gets challenged.

Re: Colour picker [message #1272685 is a reply to message #1074156] Tue, 18 March 2014 09:53 Go to previous messageGo to next message
Urs Beeli is currently offline Urs Beeli
Messages: 319
Registered: October 2012
Location: Bern, Switzerland
Senior Member
Now contributed to Luna branch

Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=430595
Gerrit Push: https://git.eclipse.org/r/23537
Re: Colour picker [message #1279369 is a reply to message #1272685] Fri, 28 March 2014 12:42 Go to previous messageGo to next message
Andreas Hoegger is currently offline Andreas Hoegger
Messages: 173
Registered: February 2010
Senior Member
Thank you Urs for this great contribution. I was able to apply the patch with few changes.
Will be available with M7.

-andreas
Re: Colour picker [message #1280998 is a reply to message #1067517] Mon, 31 March 2014 03:54 Go to previous message
Matthias Nick is currently offline Matthias Nick
Messages: 149
Registered: August 2013
Senior Member
Hi Urs, Andy,

thank you very much for this contribution. I think this is worth a "new and noteworthy" entry on our wiki.

https://wiki.eclipse.org/Scout/NewAndNoteworthy/4.0

Would you mind to create such an entry?

Thanks,
Matthias
Previous Topic:Table drag & drop
Next Topic:Label Position for AbstractBooleanField
Goto Forum:
  


Current Time: Fri Aug 01 10:15:05 EDT 2014

Powered by FUDForum. Page generated in 0.04543 seconds