/***************************************************************************** * Copyright (c) 2015, 2016 CEA LIST. * * 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: * Dirk Fauth <dirk.fauth@googlemail.com> - Initial API and implementation * Vincent Lorenzo <vincent.lorenzo@cea.fr> - bug 492571 *****************************************************************************/ package org.eclipse.nebula.widgets.nattable.extension.nebula.richtext; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.nebula.widgets.nattable.edit.editor.AbstractCellEditor; import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor; import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum; import org.eclipse.nebula.widgets.richtext.RichTextEditor; import org.eclipse.nebula.widgets.richtext.RichTextEditorConfiguration; import org.eclipse.nebula.widgets.richtext.toolbar.JavaCallbackListener; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * NatTable {@link ICellEditor} implementation that makes use of the Nebula * {@link RichTextEditor}. */ public class RichTextCellEditor extends AbstractCellEditor { private static final Log LOG = LogFactory.getLog(RichTextCellEditor.class); /** * The rich text editor control, initially <code>null</code>. */ protected RichTextEditor editor = null; /** * The {@link RichTextEditorConfiguration} that should be used for creating * the inline rich text editor control. If <code>null</code> the default * {@link RichTextEditorConfiguration} will be used. * * @since 1.1 */ protected RichTextEditorConfiguration editorConfiguration; /** * @deprecated Only exists for backwards compatibility to avoid API * breakage. The {@link RichTextEditorConfiguration} should be * used instead! */ @Deprecated protected org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration toolbarConfiguration; /** * The style bits that are used to create the rich text editor control. */ protected int style; /** * Create a new resizable {@link RichTextCellEditor} with a default * configuration. */ public RichTextCellEditor() { this((RichTextEditorConfiguration) null, SWT.RESIZE); } /** * Create a new resizable {@link RichTextCellEditor} with the given * configuration. * * @param toolbarConfiguration * The * {@link org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration} * that should be used for creating the {@link RichTextEditor}. * @deprecated Use a constructor with {@link RichTextEditorConfiguration} * parameter */ @Deprecated public RichTextCellEditor(org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration toolbarConfiguration) { this(toolbarConfiguration, SWT.RESIZE); } /** * Create a new resizable {@link RichTextCellEditor} with the given * configuration. * * @param editorConfiguration * The {@link RichTextEditorConfiguration} that should be used * for creating the {@link RichTextEditor} * * @since 1.1 */ public RichTextCellEditor(RichTextEditorConfiguration editorConfiguration) { this(editorConfiguration, SWT.RESIZE); } /** * Create a new {@link RichTextCellEditor} with a default configuration and * the given style bits. * * @param style * The style bits that should be used to create the rich text * editor control. */ public RichTextCellEditor(int style) { this((RichTextEditorConfiguration) null, style); } /** * Create a new {@link RichTextCellEditor} with the given configuration and * the given style bits. * * @param toolbarConfiguration * The * {@link org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration} * that should be used for creating the {@link RichTextEditor}. * @param style * The style bits that should be used to create the rich text * editor control. * @deprecated Use a constructor with {@link RichTextEditorConfiguration} * parameter */ @Deprecated public RichTextCellEditor(org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration toolbarConfiguration, int style) { this((RichTextEditorConfiguration) null, style); this.toolbarConfiguration = toolbarConfiguration; try { Constructor<RichTextEditorConfiguration> declaredConstructor = RichTextEditorConfiguration.class.getDeclaredConstructor(org.eclipse.nebula.widgets.richtext.toolbar.ToolbarConfiguration.class); declaredConstructor.setAccessible(true); this.editorConfiguration = declaredConstructor.newInstance(toolbarConfiguration); } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { LOG.error("Error on creating RichTextCellEditor with ToolbarConfiguration", e); } } /** * Create a new {@link RichTextCellEditor} with the given configuration and * the given style bits. * * @param editorConfiguration * The {@link RichTextEditorConfiguration} that should be used * for creating the {@link RichTextEditor} * @param style * The style bits that should be used to create the rich text * editor control. * @since 1.1 */ public RichTextCellEditor(RichTextEditorConfiguration editorConfiguration, int style) { if (editorConfiguration == null) { editorConfiguration = new RichTextEditorConfiguration(); editorConfiguration.setToolbarCollapsible(true); editorConfiguration.setToolbarInitialExpanded(true); } this.editorConfiguration = editorConfiguration; this.style = style | SWT.EMBEDDED; } @Override public Object getEditorValue() { return this.editor.getText(); } @Override public void setEditorValue(Object value) { this.editor.setText(value != null ? (String) value : ""); } /** * @since 1.1 */ @Override public RichTextEditor getEditorControl() { return this.editor; } @Override protected Control activateCell(Composite parent, Object originalCanonicalValue) { this.editor = createEditorControl(parent); setCanonicalValue(originalCanonicalValue); this.editor.forceFocus(); return this.editor; } @Override public RichTextEditor createEditorControl(Composite parent) { this.editor = createRichTextEditor(parent); this.editor.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.ESC) { close(); } // apply the value on key combination CTRL + RETURN // because RETURN will add a new line to the editor if (e.keyCode == SWT.CR && e.stateMask == SWT.MOD1) { commit(MoveDirectionEnum.NONE); } } }); this.editor.addJavaCallbackListener(new JavaCallbackListener() { @Override public void javaExecutionStarted() { if (RichTextCellEditor.this.focusListener instanceof InlineFocusListener) { ((InlineFocusListener) RichTextCellEditor.this.focusListener).handleFocusChanges = false; } } @Override public void javaExecutionFinished() { if (RichTextCellEditor.this.focusListener instanceof InlineFocusListener) { ((InlineFocusListener) RichTextCellEditor.this.focusListener).handleFocusChanges = true; } } }); return this.editor; } /** * * @param parent * the parent used to create the RichTextEditor wrapped by this * RichtextCellEditor. * @return the created RichTextEditor */ protected RichTextEditor createRichTextEditor(Composite parent) { return new RichTextEditor(parent, this.editorConfiguration, this.style) { @Override protected int getMinimumHeight() { return getMinimumDimension().y; } @Override protected int getMinimumWidth() { return getMinimumDimension().x; } }; } /** * @return The minimum dimension used for the rich text editor control. */ protected Point getMinimumDimension() { return new Point(370, 200); } }