blob: ccefb3244f69b0783b07a14490f8304967bc1a61 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.ui.fields;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.scout.commons.OptimisticLock;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.util.Regex;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
public class StyledTextField extends TextField {
private P_SuffixListener m_suffixListener = null;
private String m_readOnlyPrefix;
private String m_readOnlySuffix;
private OptimisticLock m_revalLock = new OptimisticLock();
/**
* @param parent
* @param style
* of the text field
*/
public StyledTextField(Composite parent) {
this(parent, "");
}
public StyledTextField(Composite parent, String labelName) {
super(parent, labelName);
}
public String getReadOnlySuffix() {
return m_readOnlySuffix;
}
public String getModifiableText() {
String text = getText();
if (m_suffixListener != null && text.length() >= m_suffixListener.getSuffix().length()) {
text = text.substring(0, text.length() - m_suffixListener.getSuffix().length());
}
return text;
}
public void setReadOnlySuffix(String suffix) {
m_readOnlySuffix = suffix;
updateListeners();
}
public void setReadOnlyPrefix(String readOnlyPrefix) {
m_readOnlyPrefix = readOnlyPrefix;
updateListeners();
}
public String getReadOnlyPrefix() {
return m_readOnlyPrefix;
}
private synchronized void updateListeners() {
StyledText textComp = getTextComponent();
if (StringUtility.isNullOrEmpty(getReadOnlyPrefix()) && StringUtility.isNullOrEmpty(getReadOnlySuffix())) {
// uninstall
if (m_suffixListener != null) {
m_suffixListener.setSuffix("");
textComp.removeListener(SWT.Selection, m_suffixListener);
textComp.removeListener(SWT.MouseDown, m_suffixListener);
textComp.removeListener(SWT.Modify, m_suffixListener);
textComp.removeVerifyKeyListener(m_suffixListener);
textComp.removeListener(SWT.KeyDown, m_suffixListener);
textComp.removeListener(SWT.FocusIn, m_suffixListener);
m_suffixListener = null;
}
}
else {
if (m_suffixListener == null) {
m_suffixListener = new P_SuffixListener();
}
m_suffixListener.setPrefix(getReadOnlyPrefix());
m_suffixListener.setSuffix(getReadOnlySuffix());
textComp.addListener(SWT.Selection, m_suffixListener);
textComp.addListener(SWT.MouseDown, m_suffixListener);
textComp.addListener(SWT.Modify, m_suffixListener);
textComp.addVerifyKeyListener(m_suffixListener);
textComp.addListener(SWT.KeyDown, m_suffixListener);
textComp.addListener(SWT.FocusIn, m_suffixListener);
}
}
@Override
public void setText(String text) {
if (text == null) {
text = "";
}
String prefix = "";
if (m_suffixListener != null) {
prefix = m_suffixListener.getPrefix();
}
if (!text.startsWith(prefix)) {
text = prefix + text;
}
String suffix = "";
if (m_suffixListener != null) {
suffix = m_suffixListener.getSuffix();
}
if (!text.endsWith(suffix)) {
text += suffix;
}
super.setText(text);
}
private class P_SuffixListener implements Listener, VerifyKeyListener {
private Pattern m_preSuffixPattern;
private StyleRange m_suffixStyleRange;
private StyleRange m_prefixStyleRange;
private static final String prePostFixRegex = "^(#0#).*(#1#)$";
private String m_suffixString = "";
private String m_prefixString = "";
public P_SuffixListener() {
this("");
}
public P_SuffixListener(String suffix) {
this(suffix, null);
}
public P_SuffixListener(String postfix, StyleRange style) {
if (style == null) {
style = new StyleRange(-1, -1, getDisplay().getSystemColor(SWT.COLOR_BLUE), null);
}
m_suffixStyleRange = new StyleRange(-1, -1, style.foreground, style.background, style.fontStyle);
m_prefixStyleRange = new StyleRange(-1, -1, style.foreground, style.background, style.fontStyle);
m_preSuffixPattern = Pattern.compile(Regex.replace(prePostFixRegex, m_prefixString, m_suffixString));
setSuffix(postfix);
}
@Override
public void verifyKey(VerifyEvent event) {
Event e = new Event();
e.keyCode = event.keyCode;
e.character = event.character;
e.doit = event.doit;
e.widget = event.widget;
e.type = SWT.Verify;
handleEvent(e);
event.doit = e.doit;
}
@Override
public void handleEvent(Event event) {
try {
if (m_revalLock.acquire()) {
Point textSelection = getTextComponent().getSelection();
Matcher suffixMatcher = m_preSuffixPattern.matcher(getTextComponent().getText());
if (suffixMatcher.find()) {
switch (event.type) {
case SWT.Verify: {
if (event.character == SWT.BS) {
event.doit = !(textSelection.x - 1 < suffixMatcher.end(1) && textSelection.x == textSelection.y);
}
if (event.character == SWT.DEL) {
event.doit = !(textSelection.x + 1 > suffixMatcher.start(2) && textSelection.x == textSelection.y);
}
break;
}
case SWT.Modify: {
updateStyleRanges();
break;
}
case SWT.KeyDown:
case SWT.MouseDown:
case SWT.Selection:
Point selection = getTextComponent().getSelection();
if (selection.x < suffixMatcher.end(1)) {
selection.x = suffixMatcher.end(1);
if (selection.x > selection.y) {
selection.y = selection.x;
}
event.doit = false;
}
if (selection.y > suffixMatcher.start(2)) {
selection.y = suffixMatcher.start(2);
if (selection.y < selection.x) {
selection.x = selection.y;
}
event.doit = false;
}
if (!event.doit) {
getTextComponent().setSelection(selection);
}
break;
case SWT.FocusIn:
int x = getTextComponent().getSelection().x;
if (x < suffixMatcher.end(1) || x > suffixMatcher.start(2)) {
getTextComponent().setSelection(suffixMatcher.end(1));
}
break;
}
}
}
}
finally {
m_revalLock.release();
}
}
String getPrefix() {
return m_prefixString;
}
String getSuffix() {
return m_suffixString;
}
void setSuffix(String postfix) {
try {
if (m_revalLock.acquire()) {
if (postfix == null) {
postfix = "";
}
// remove old suffix
StyledText text = getTextComponent();
if (m_suffixString != null) {
Matcher suffixMatcher = m_preSuffixPattern.matcher(text.getText());
if (suffixMatcher.find()) {
String newText = text.getText().substring(0, suffixMatcher.start(2));
text.setText(newText);
}
}
m_suffixString = postfix;
m_preSuffixPattern = Pattern.compile(Regex.replace(prePostFixRegex, m_prefixString, m_suffixString));
if (!text.getText().endsWith(m_suffixString)) {
text.setText(text.getText() + m_suffixString);
}
updateStyleRanges();
}
}
finally {
m_revalLock.release();
}
}
void setPrefix(String prefix) {
try {
if (m_revalLock.acquire()) {
if (prefix == null) {
prefix = "";
}
// remove old suffix
StyledText text = getTextComponent();
if (m_prefixString != null) {
Matcher suffixMatcher = m_preSuffixPattern.matcher(text.getText());
if (suffixMatcher.find()) {
String newText = text.getText().substring(suffixMatcher.end(1));
text.setText(newText);
}
}
m_prefixString = prefix;
m_preSuffixPattern = Pattern.compile(Regex.replace(prePostFixRegex, m_prefixString, m_suffixString));
if (!text.getText().startsWith(m_prefixString)) {
text.setText(m_prefixString + text.getText());
}
updateStyleRanges();
}
}
finally {
m_revalLock.release();
}
}
private void updateStyleRanges() {
Matcher preSuffixMatcher = m_preSuffixPattern.matcher(getTextComponent().getText());
if (preSuffixMatcher.find()) {
m_suffixStyleRange.start = preSuffixMatcher.start(2);
m_suffixStyleRange.length = preSuffixMatcher.end(2) - preSuffixMatcher.start(2);
m_prefixStyleRange.start = preSuffixMatcher.start(1);
m_prefixStyleRange.length = preSuffixMatcher.end(1) - preSuffixMatcher.start(1);
getTextComponent().setStyleRanges(new StyleRange[]{m_prefixStyleRange, m_suffixStyleRange});
}
else {
getTextComponent().setStyleRanges(null);
}
}
} // end class P_SuffixListener
}