/*******************************************************************************
* Copyright (c) 2006-2007, G. Weirich and Elexis
* 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:
* G. Weirich - initial implementation
* D. Lutz - simplified read-only version
*
* Sponsors:
* Dr. Peter Schönbucher, Luzern
******************************************************************************/
package org.iatrix.widgets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import org.jdom.Document;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import ch.elexis.core.text.model.Samdas;
import ch.elexis.core.ui.util.SWTHelper;
/**
* Ein StyledText mit erweiterten Eigenschaften. Kann XML-Dokumente von SAmDaS-Typ lesen. Aus
* Kompatibiltätsgründen können auch reine Texteinträge gelesen werden, werden beim Speichern aber
* nach XML gewandelt.
*
* @author Gerry
*
*/
public class EnhancedTextFieldRO extends Composite {
StyledText text;
List<Samdas.XRef> links;
List<Samdas.Markup> markups;
List<Samdas.Range> ranges;
Samdas samdas;
Samdas.Record record;
private static Pattern outline = Pattern.compile("^\\S+:", Pattern.MULTILINE);
private static Pattern bold = Pattern.compile("\\*\\S+\\*");
private static Pattern italic = Pattern.compile("\\/\\S+\\/");
private static Pattern underline = Pattern.compile("_\\S+_");
public EnhancedTextFieldRO(Composite parent){
super(parent, SWT.NONE);
setLayout(new TableWrapLayout());
text = new StyledText(this, SWT.WRAP | SWT.READ_ONLY);
text.setLayoutData(SWTHelper.getFillTableWrapData(1, true, 1, true));
text.setWordWrap(true);
}
/**
* Text formatieren (d.h. Style-Ranges erstellen. Es wird unterschieden zwischen dem KG-Eintrag
* alten Stils und dem neuen XML-basierten format.
*/
void doFormat(String tx){
text.setStyleRange(null);
if (tx.startsWith("<")) {
doFormatXML(tx);
tx = text.getText();
} else {
samdas = new Samdas(tx);
record = samdas.getRecord();
text.setText(tx);
}
// Überschriften formatieren
// obsoleted by markups!
Matcher matcher = outline.matcher(tx);
while (matcher.find() == true) {
StyleRange n = new StyleRange();
n.start = matcher.start();
n.length = matcher.end() - n.start;
n.fontStyle = SWT.BOLD;
text.setStyleRange(n);
}
matcher = bold.matcher(tx);
while (matcher.find() == true) {
StyleRange n = new StyleRange();
n.start = matcher.start();
n.length = matcher.end() - n.start;
n.fontStyle = SWT.BOLD;
text.setStyleRange(n);
}
matcher = italic.matcher(tx);
while (matcher.find() == true) {
StyleRange n = new StyleRange();
n.start = matcher.start();
n.length = matcher.end() - n.start;
n.fontStyle = SWT.ITALIC;
text.setStyleRange(n);
}
matcher = underline.matcher(tx);
while (matcher.find() == true) {
StyleRange n = new StyleRange();
n.start = matcher.start();
n.length = matcher.end() - n.start;
n.underline = true;
text.setStyleRange(n);
}
// Obsoleted, do not rely
}
void doFormatXML(String tx){
samdas = new Samdas(tx);
record = samdas.getRecord();
List<Samdas.XRef> xrefs = record.getXrefs();
text.setText(record.getText());
int textlen = text.getCharCount();
markups = record.getMarkups();
links = new ArrayList<>(xrefs.size());
ranges = new ArrayList<>(xrefs.size() + markups.size());
for (Samdas.Markup m : markups) {
String type = m.getType();
StyleRange n = new StyleRange();
n.start = m.getPos();
n.length = m.getLength();
if (type.equalsIgnoreCase("emphasized")) {
n.strikeout = true;
} else if (type.equalsIgnoreCase("bold")) {
n.fontStyle = SWT.BOLD;
} else if (type.equalsIgnoreCase("italic")) {
n.fontStyle = SWT.ITALIC;
} else if (type.equalsIgnoreCase("underlined")) {
n.underline = true;
}
if ((n.start + n.length) > textlen) {
n.length = textlen - n.start;
}
if ((n.length > 0) && (n.start >= 0)) {
text.setStyleRange(n);
ranges.add(m);
} else {
// fehlerhaftes Markup entfernen.
record.remove(m);
}
}
/*
* for(Samdas.XRef xref:xrefs){ IKonsExtension xProvider=hXrefs.get(xref.getProvider());
* if(xProvider==null){ continue; } StyleRange n=new StyleRange(); n.start=xref.getPos();
* n.length=xref.getLength();
* if(xProvider.doLayout(n,xref.getProvider(),xref.getID())==true){ links.add(xref); }
*
* if((n.start+n.length)>text.getCharCount()){ n.length=text.getCharCount()-n.start; }
* if((n.length>0) && (n.start>=0)){ text.setStyleRange(n); ranges.add(xref); }else{
* xref.setPos(0); } }
*/
}
/**
* Liefert den Inhalt des Textfields als jdom-Document zurück
*/
private Document getDocument(){
record.setText(text.getText());
// StyleRange[] rgs=text.getStyleRanges();
return samdas.getDocument();
}
/**
* Liefert den Inhalt des Textfelds als XML-Text zurück
*/
private String getContentsAsXML(){
XMLOutputter xo = new XMLOutputter(Format.getRawFormat());
return xo.outputString(getDocument());
}
/**
* Markup erstellen
*
* @param type
* '*' bold, '/' italic, '_', underline
*/
public void createMarkup(char type, int pos, int len){
String typ = "bold";
switch (type) {
case '/':
typ = "italic";
break;
case '_':
typ = "underline";
break;
}
Samdas.Markup markup = new Samdas.Markup(pos, len, typ);
record.add(markup);
doFormat(getContentsAsXML());
}
/**
* Den Text mit len zeichen ab start durch nt ersetzen
*/
public void replace(int start, int len, String nt){
text.replaceTextRange(start, len, nt);
}
public void setText(String ntext){
doFormat(ntext);
}
/**
* Liefert das zugrundeliegende Text-Control zurueck
*
* @return das zugrundeliegende Text-Control
*/
public Control getControl(){
return text;
}
}