blob: 3bf45a035aba3b5428aa9e38eb9c191064d1d7a7 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2013, 2021 Dirk Fauth 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.
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# Dirk Fauth <dirk.fauth@gmail.com> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.waltable.edit.editor;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.statet.ecommons.waltable.edit.EditConfigAttributes;
import org.eclipse.statet.ecommons.waltable.style.CellStyleUtil;
/**
* A specialization of {@link TextCellEditor} that uses a multi line text editor as
* editor control. To support multi line editing correctly, the behaviour to commit
* on pressing the enter key is disabled.
* <p>
* A multi line editor usually needs some space. Therefore it might be a good decision
* to set the configuration attribute {@link EditConfigAttributes#OPEN_IN_DIALOG} to
* <code>true</code> for this editor, so the editor always opens in a subdialog.
* </p>
* <p>
* As some table layouts may support enough space for an inline cell editor, this editor
* does not specify {@link ICellEditor#openInline(org.eclipse.statet.ecommons.waltable.config.IConfigRegistry,
* java.util.List)} to always return <code>false</code>.
* </p>
*/
public class MultiLineTextCellEditor extends TextCellEditor {
/**
* Flag to configure whether the text control should enable automatic line wrap behaviour
* or not. By default this editor will support automatic line wrapping.
*/
private boolean lineWrap= true;
/**
* Create a new multi line text editor that ensures to not commit the editor
* value in case enter is typed. The text control will support automatic line wrapping.
*/
public MultiLineTextCellEditor() {
this(true);
}
/**
* Create a new multi line text editor that ensures to not commit the editor
* value in case enter is typed.
* @param lineWrap Flag to configure whether the text control should enable automatic line
* wrap behaviour or not.
*/
public MultiLineTextCellEditor(final boolean lineWrap) {
this.commitOnEnter= false;
this.lineWrap= lineWrap;
}
@Override
public Text createEditorControl(final Composite parent) {
final boolean openInline= openInline(this.configRegistry, this.labelStack.getLabels());
int style= CellStyleUtil.getHorizontalAlignmentSWT(this.cellStyle, SWT.NONE) | SWT.MULTI | SWT.BORDER;
if (!openInline) {
//if the editor control is opened in a dialog, we add scrolling as the size of the
//control is dependent on the dialog size
style= style | SWT.V_SCROLL;
}
if (this.lineWrap) {
style= style | SWT.WRAP;
}
else if (!openInline) {
//if the editor control is opened in a dialog, we add scrolling as the size of the
//control is dependent on the dialog size
style= style | SWT.H_SCROLL;
}
final Text textControl= super.createEditorControl(parent, style);
if (!openInline) {
//add the layout data directly so it will not be layouted by the CellEditDialog
GridDataFactory.fillDefaults().grab(true, true).hint(100, 50).applyTo(textControl);
}
//on inline editing there need to be a different handling of the return key
//as the Text control is performing a new line on return, it is not possible to
//commit a value by pressing enter. So for inline editing we catch enter to
//perform the commit, while pressing Alt/Shift + enter will add a new line
if (openInline) {
this.commitOnEnter= true;
textControl.addKeyListener(new KeyListener() {
@Override
public void keyReleased(final KeyEvent event) {
if (event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR) {
if (event.stateMask == SWT.ALT) {
textControl.insert(textControl.getLineDelimiter());
}
}
}
@Override
public void keyPressed(final KeyEvent e) {
}
});
}
return textControl;
}
@Override
public Rectangle calculateControlBounds(final Rectangle cellBounds) {
final Point size= getEditorControl().computeSize(SWT.DEFAULT, SWT.DEFAULT);
//add a listener that increases/decreases the size of the control if the text is modified
//as the calculateControlBounds method is only called in case of inline editing, this
//listener shouldn't hurt anybody else
getEditorControl().addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
final Point p= getEditorControl().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
final Point loc= getEditorControl().getLocation();
getEditorControl().setBounds(loc.x, loc.y, Math.max(p.x, cellBounds.width), Math.max(p.y, cellBounds.height));
}
});
return new Rectangle(cellBounds.x, cellBounds.y, Math.max(size.x, cellBounds.width), Math.max(size.y, cellBounds.height));
}
/**
* @param lineWrap <code>true</code> if the text control should enable automatic line
* wrap behaviour, <code>false</code> if not
*/
public void setLineWrap(final boolean lineWrap) {
this.lineWrap= lineWrap;
}
}