blob: 2da846f7c2fd9803b300a13556a3f64d5d6890fe [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2015, 2020 CEA LIST.
*
* 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@googlemail.com> - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.nebula.widgets.nattable.extension.nebula.richtext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.data.convert.ContextualDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.DefaultDisplayConverter;
import org.eclipse.nebula.widgets.nattable.data.convert.IDisplayConverter;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
/**
* {@link IDisplayConverter} that can be used to add HTML markups via String
* replacements. Intended to be used in combination with the
* {@link RichTextCellPainter} to support dynamic text highlighting.
*/
public class MarkupDisplayConverter extends ContextualDisplayConverter {
protected IDisplayConverter wrappedConverter;
protected Map<String, MarkupProcessor> markups = new LinkedHashMap<>();
public MarkupDisplayConverter() {
this(new DefaultDisplayConverter());
}
public MarkupDisplayConverter(IDisplayConverter wrappedConverter) {
this.wrappedConverter = wrappedConverter;
}
@Override
public Object canonicalToDisplayValue(ILayerCell cell, IConfigRegistry configRegistry, Object canonicalValue) {
Object wrappedConverterResult = this.wrappedConverter.canonicalToDisplayValue(cell, configRegistry, canonicalValue);
String result = null;
if (wrappedConverterResult != null) {
result = wrappedConverterResult.toString();
// add markups
for (MarkupProcessor markup : this.markups.values()) {
result = markup.applyMarkup(result);
}
}
return result;
}
@Override
public Object displayToCanonicalValue(ILayerCell cell, IConfigRegistry configRegistry, Object displayValue) {
// remove markups
if (displayValue != null) {
String result = displayValue.toString();
// perform removal in reverse order
List<MarkupProcessor> mc = new ArrayList<>(this.markups.values());
Collections.reverse(mc);
for (MarkupProcessor markup : mc) {
result = markup.removeMarkup(result);
}
return this.wrappedConverter.displayToCanonicalValue(cell, configRegistry, result);
}
return this.wrappedConverter.displayToCanonicalValue(cell, configRegistry, displayValue);
}
/**
* Registers a value and the markup that should be placed around the value
* while rendering.
*
* @param value
* The value that should be replacement with the markup for
* rendering.
* @param markupPrefix
* The String that will be added as prefix to the value.
* @param markupSuffix
* The String that will be added as suffix to the value.
*/
public void registerMarkup(String value, String markupPrefix, String markupSuffix) {
MarkupValue markup = new MarkupValue();
markup.originalValue = value;
markup.markupValue = markupPrefix + value + markupSuffix;
registerMarkup(value, markup);
}
/**
* Registers a regular expression and a markup that should be placed around
* the value that is specified by the regular expression. The regular
* expression needs to contain at least one group.
* <p>
* Example: (IMPORTANT|URGENT) as value will result as either of both words
* will be surrounded by the markup.
* </p>
*
* @param value
* A regular expression that specifies the value that should be
* replacement with the markup for rendering. Needs to contain at
* least one group that will be replaced.
* @param markupPrefix
* The String that will be added as prefix to the value.
* @param markupSuffix
* The String that will be added as suffix to the value.
*
* @since 1.1
*/
public void registerRegexMarkup(String value, String markupPrefix, String markupSuffix) {
RegexMarkupValue markup = new RegexMarkupValue(value, markupPrefix, markupSuffix);
registerMarkup(value, markup);
}
/**
* Registers a custom {@link MarkupProcessor} for a given id.
*
* @param id
* The id under which the {@link MarkupProcessor} should be
* registered.
* @param processor
* The custom {@link MarkupProcessor} that should be registered.
*
* @since 1.1
*/
public void registerMarkup(String id, MarkupProcessor processor) {
this.markups.put(id, processor);
}
/**
* Unregister the markup that was registered for the given value.
*
* @param value
* The value for which a markup was registered. In case of a
* value or regex markup this is the value for which the markup
* was registered. In case of a custom {@link MarkupProcessor} it
* needs to be the id for which it was registered.
*/
public void unregisterMarkup(String value) {
this.markups.remove(value);
}
/**
* Remove all registered markups.
*/
public void clearMarkups() {
this.markups.clear();
}
/**
* Simple value class to store the original value and the markup
* replacement.
*/
protected class MarkupValue implements MarkupProcessor {
String originalValue;
String markupValue;
/**
* @since 1.1
*/
@Override
public String applyMarkup(String input) {
return input.replaceAll(this.originalValue, this.markupValue);
}
/**
* @since 1.1
*/
@Override
public String removeMarkup(String input) {
return input.replaceAll(this.markupValue, this.originalValue);
}
}
}