Files
Brainstorm/Foundation SWT/src/com/foundation/view/swt/StyledText.java
2014-05-30 10:31:51 -07:00

499 lines
19 KiB
Java

/*
* Copyright (c) 2006,2009 Declarative Engineering LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Declarative Engineering LLC
* verson 1 which accompanies this distribution, and is available at
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
*/
package com.foundation.view.swt;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.LineStyleListener;
import org.eclipse.swt.custom.StyledTextContent;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Point;
import com.foundation.event.EventSupport;
import com.foundation.event.IEventEmitter;
import com.foundation.event.IEventHandler;
import com.foundation.view.JefColor;
import com.foundation.view.LinkData;
import com.foundation.view.SingleAssociationContainer;
import com.foundation.view.SingleResourceAssociation;
public class StyledText extends Container implements SelectionListener, KeyListener, MouseListener {
public static final int STYLE_FULL_SELECTION = SWT.FULL_SELECTION;
public static final int STYLE_MULTI_LINE = SWT.MULTI;
public static final int STYLE_SINGLE_LINE = SWT.SINGLE;
public static final int STYLE_READ_ONLY = SWT.READ_ONLY;
public static final int STYLE_WRAP = SWT.WRAP;
public static final int LINK_TARGET_BOLD_TEXT = Container.LAST_LINK_TARGET + 1;
public static final int LINK_TARGET_ITALIC_TEXT = Container.LAST_LINK_TARGET + 2;
public static final int LINK_TARGET_UNDERLINE_TEXT = Container.LAST_LINK_TARGET + 3;
public static final int LINK_TARGET_STRIKEOUT_TEXT = Container.LAST_LINK_TARGET + 4;
public static final int LINK_TARGET_TEXT_FONT_NAME = Container.LAST_LINK_TARGET + 5;
public static final int LINK_TARGET_TEXT_FONT_SIZE = Container.LAST_LINK_TARGET + 6;
public static final int LINK_TARGET_TEXT_FOREGROUND_COLOR = Container.LAST_LINK_TARGET + 7;
public static final int LINK_TARGET_TEXT_BACKGROUND_COLOR = Container.LAST_LINK_TARGET + 8;
public static final int LINK_TARGET_TEXT_RISE = Container.LAST_LINK_TARGET + 9;
public static final int LINK_TARGET_TEXT_GLYPH_ASCENT = Container.LAST_LINK_TARGET + 10;
public static final int LINK_TARGET_TEXT_GLYPH_DESCENT = Container.LAST_LINK_TARGET + 11;
public static final int LINK_TARGET_TEXT_GLYPH_WIDTH = Container.LAST_LINK_TARGET + 12;
public static final int LINK_TARGET_LINE_ALIGNMENT = Container.LAST_LINK_TARGET + 13;
public static final int LINK_TARGET_LINE_INDENT = Container.LAST_LINK_TARGET + 14;
public static final int LINK_TARGET_LINE_JUSTIFY = Container.LAST_LINK_TARGET + 15;
public static final int LAST_LINK_TARGET = Container.LAST_LINK_TARGET + 15;
/** The text displayed in the styled text editor. */
private SingleResourceAssociation text = new SingleResourceAssociation(this, this, getViewContext(), SingleResourceAssociation.TYPE_TEXT, true, null);
/** Whether the text is non-editable. */
private final boolean isReadOnly;
/** The document manager. */
private IStyledTextManager manager = new StyledTextManager();
/** The event support used to listen to the StyledLineInfo update event. */
private EventSupport eventSupport = new EventSupport(null);
/** The character offset of the first character in the range selected, or if length is zero then it is the cursor location. */
private int currentRangeOffset = -1;
/** The number of selected characters in the current range. */
private int currentRangeLength = 0;
/** Whether the linkage updates should be ignored. This should only be true if the control is in the process of updating the links and doesn't want feedback. */
private boolean suspendLinkInvocations = false;
/** The linkage for the text selection. */
private Linkage boldTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage italicTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage underlineTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage strikeoutTextLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textFontNameLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textFontSizeLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textBackgroundColorLinkage = new Linkage();
/** The linkage for the text selection. */
private Linkage textForegroundColorLinkage = new Linkage();
public interface IStyledTextManager extends StyledTextContent, LineStyleListener {
//TODO: Add methods to allow the selection or the cursor to change styles.
//TODO: Add methods to allow cut and paste of text using the clipboard.
/**
* Gets the style data for the current range.
* @return The style data for the range set.
* @see #setCurrentRange(int, int)
*/
public StyleLineInfo getCurrentRangeStyle();
/**
* Changes the range of characters the range style model represents.
* @param offset The offset in the text to begin the range.
* @param length The number of characters in the range, or zero if the styles at the cursor are desired.
*/
public void setCurrentRange(int offset, int length);
}//IStyledTextManager//
/**
* StyledText constructor.
* @param parent A composite control which will be the parent of the new instance (cannot be null).
* @param name The unique component name.
* @param style The style of control to construct.
* @see #FULL_SELECTION, MULTI, READ_ONLY, SINGLE, WRAP
*/
public StyledText(Container parent, String name, int style) {
super(parent, name, style);
isReadOnly = (style & STYLE_READ_ONLY) > 0;
}//StyledText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#initializeControl(int)
*/
protected void initializeControl(int style, Object data) {
setSwtWidget(new org.eclipse.swt.custom.StyledText(((Container) getContainer()).getSwtParent(), style));
getSwtWidget().setData(this);
}//initializeControl()//
/**
* Gets the SWT styled text that represents this styled text.
* @return The SWT styled text providing visualization for this styled text.
*/
public org.eclipse.swt.custom.StyledText getSwtStyledText() {
return (org.eclipse.swt.custom.StyledText) getSwtControl();
}//getSwtStyledText()//
/**
* Sets the text.
* @param text The text that will appear in the component.
*/
public void setText(String text) {
verifyThread();
this.text.setDefaultValue(text);
}//setText()//
/**
* Sets the association container used to access the text.
* @param container The text association metadata.
*/
public void setTextAssociation(SingleAssociationContainer container) {
verifyThread();
this.text.setAssociations(container);
}//setTextAssociation()//
/**
* Adds a bold text link associated with the selected text.
* @param link The local linkage.
*/
public void addBoldTextLink(LinkData link) {
boldTextLinkage.add(link);
}//addBoldTextLink()//
/**
* Adds an italic text link associated with the selected text.
* @param link The local linkage.
*/
public void addItalicTextLink(LinkData link) {
italicTextLinkage.add(link);
}//addItalicTextLink()//
/**
* Adds an underline text link associated with the selected text.
* @param link The local linkage.
*/
public void addUnderlineTextLink(LinkData link) {
underlineTextLinkage.add(link);
}//addUnderlineTextLink()//
/**
* Adds a strikeout text link associated with the selected text.
* @param link The local linkage.
*/
public void addStrikeoutTextLink(LinkData link) {
strikeoutTextLinkage.add(link);
}//addStrikeoutTextLink()//
/**
* Adds a font name link associated with the selected text.
* @param link The local linkage.
*/
public void addTextFontNameLink(LinkData link) {
textFontNameLinkage.add(link);
}//addTextFontNameLink()//
/**
* Adds a font size link associated with the selected text.
* @param link The local linkage.
*/
public void addTextFontSizeLink(LinkData link) {
textFontSizeLinkage.add(link);
}//addTextFontSizeLink()//
/**
* Adds a foreground color link associated with the selected text.
* @param link The local linkage.
*/
public void addTextForegroundColorLink(LinkData link) {
textForegroundColorLinkage.add(link);
}//addTextForegroundColorLink()//
/**
* Adds a background color link associated with the selected text.
* @param link The local linkage.
*/
public void addTextBackgroundColorLink(LinkData link) {
textBackgroundColorLinkage.add(link);
}//addTextBackgroundColorLink()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewInitialize()
*/
protected void internalViewInitialize() {
getSwtStyledText().addSelectionListener(this);
getSwtStyledText().addKeyListener(this);
getSwtStyledText().addMouseListener(this);
getSwtStyledText().addLineStyleListener(manager);
getSwtStyledText().setContent(manager);
text.initialize();
eventSupport.register(manager.getCurrentRangeStyle(), StyleLineInfo.EVENT_UPDATED, new IEventHandler() {
public void evaluate(int eventNumber, Object[] eventParameters, int flags) {
//Never called.//
}//evaluate()//
public void evaluate(IEventEmitter eventEmitter, int eventNumber, Object[] eventParameters, int flags) {
updateLinks((StyleLineInfo) eventEmitter);
}//evaluate()//
}, true);
super.internalViewInitialize();
}//internalViewInitialize()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRelease()
*/
protected void internalViewRelease() {
if(!getSwtStyledText().isDisposed()) {
getSwtStyledText().removeSelectionListener(this);
getSwtStyledText().removeKeyListener(this);
getSwtStyledText().removeMouseListener(this);
getSwtStyledText().removeLineStyleListener(manager);
}//if//
super.internalViewRelease();
text.release();
eventSupport.unregisterAll();
}//internalViewRelease()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalViewRefresh()
*/
protected void internalViewRefresh() {
super.internalViewRefresh();
internalViewRefreshText();
}//internalViewRefresh()//
/**
* Refreshes the styled text.
*/
protected void internalViewRefreshText() {
if(text.refresh()) {
convertText((String) text.getValue());
resize();
}//if//
}//internalViewRefreshText()//
/* (non-Javadoc)
* @see com.foundation.view.swt.AbstractComponent#internalOnLinkInvoked(int, java.lang.Object)
*/
protected void internalOnLinkInvoked(int linkTarget, Object data) {
if(!suspendLinkInvocations) {
switch(linkTarget) {
case LINK_TARGET_BOLD_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getBold() == null || !info.getBold().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setBold(value);
break;
}//case//
case LINK_TARGET_ITALIC_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getItalic() == null || !info.getItalic().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setItalic(value);
break;
}//case//
case LINK_TARGET_UNDERLINE_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getBold() == null || !info.getBold().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setUnderline(value);
break;
}//case//
case LINK_TARGET_STRIKEOUT_TEXT: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Boolean value = data instanceof Boolean ? (Boolean) data : info.getItalic() == null || !info.getItalic().booleanValue() ? Boolean.TRUE : Boolean.FALSE;
info.setStrikeout(value);
break;
}//case//
case LINK_TARGET_TEXT_FONT_NAME: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
String value = data instanceof String ? (String) data : info.getFontName() != null ? info.getFontName() : null;
info.setFontName(value);
break;
}//case//
case LINK_TARGET_TEXT_FONT_SIZE: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
Integer value = data instanceof Integer ? (Integer) data : info.getFontHeight() != null ? info.getFontHeight() : null;
info.setFontHeight(value);
break;
}//case//
case LINK_TARGET_TEXT_FOREGROUND_COLOR: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
JefColor value = data instanceof JefColor ? (JefColor) data : info.getForegroundColor() != null ? info.getForegroundColor() : null;
info.setForegroundColor(value);
break;
}//case//
case LINK_TARGET_TEXT_BACKGROUND_COLOR: {
StyleTextInfo info = manager.getCurrentRangeStyle().getStyle();
JefColor value = data instanceof JefColor ? (JefColor) data : info.getBackgroundColor() != null ? info.getBackgroundColor() : null;
info.setBackgroundColor(value);
break;
}//case//
}//switch//
//Force the selection to be restored in the swt styled text control.//
getSwtStyledText().setSelection(currentRangeOffset, currentRangeOffset + currentRangeLength);
}//if//
}//internalOnLinkInvoked()//
/* (non-Javadoc)
* @see com.foundation.view.swt.Component#internalOnValueChanged(com.foundation.view.SingleResourceAssociation)
*/
protected void internalOnValueChanged(SingleResourceAssociation resourceAssociation, int flags) {
if(resourceAssociation == text) {
internalViewRefreshText();
}//if//
else {
super.internalOnValueChanged(resourceAssociation, flags);
}//else//
}//internalOnValueChanged()//
/**
* Updates the linkages related to the selection or cursor style info.
* @param line The line info for the selected text's stylings.
*/
private void updateLinks(StyleLineInfo line) {
suspendLinkInvocations = true;
boldTextLinkage.invoke(line.getStyle().getBold());
italicTextLinkage.invoke(line.getStyle().getItalic());
underlineTextLinkage.invoke(line.getStyle().getUnderline());
strikeoutTextLinkage.invoke(line.getStyle().getStrikeout());
textFontNameLinkage.invoke(line.getStyle().getFontName());
textFontSizeLinkage.invoke(line.getStyle().getFontHeight());
textForegroundColorLinkage.invoke(line.getStyle().getForegroundColor());
textBackgroundColorLinkage.invoke(line.getStyle().getBackgroundColor());
suspendLinkInvocations = false;
}//updateLinks()//
/**
* Converts the text from the external formatting to the styled text control formatting.
* @param text The text to be converted.
*/
protected void convertText(String text) {
//TODO: Convert.
getSwtStyledText().setText(text);
}//convertText()//
/**
* Sets the currently selected range for the styled text control.
* <p>This is used to restore the selected range after applying styling changes to the range.</p>
* @param offset The character offset of the first character in the range selected, or if length is zero then it is the cursor location.
* @param length The number of selected characters.
*/
public void setCurrentRange(int offset, int length) {
if((currentRangeOffset != offset) || (currentRangeLength != length)) {
currentRangeOffset = offset;
currentRangeLength = length;
manager.setCurrentRange(offset, length);
}//if//
}//setCurrentRange()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}//widgetDefaultSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent event) {
//Point selection = getSwtStyledText().getSelectionRange();
//Give the manager the current range for the selection or the cursor position.//
//manager.setCurrentRange(selection.x, selection.y);
}//widgetSelected()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public void keyPressed(KeyEvent eevent) {
}//keyPressed()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
public void keyReleased(KeyEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//keyReleased()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDoubleClick(MouseEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//mouseDoubleClick()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDown(MouseEvent event) {
}//mouseDown()//
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
*/
public void mouseUp(MouseEvent event) {
if(getSwtStyledText().getSelectionCount() > 0) {
Point selection = getSwtStyledText().getSelectionRange();
setCurrentRange(selection.x, selection.y);
}//if//
else {
setCurrentRange(getSwtStyledText().getCaretOffset(), 0);
}//else//
}//mouseUp()//
}//StyledText//
/*
/*
* Converts the text from an XHTML Basic formatting (a subset of XHTML Basic is supported) to the styled text control formatting.
* @param text The text to be converted.
*
protected void convertTextFromXHtmlBasic(String text) {
StringBuffer rawText = new StringBuffer(text);
try {
IDocument xmlDocument = new DocumentBuilder().readDocument(text);
IIterator iterator = xmlDocument.getElements().iterator();
while(iterator.hasNext()) {
IElement next = (IElement) iterator.next();
if(next.isNode()) {
if(((INode) next).getName().equalsIgnoreCase("html")) {
iterator = ((INode) next).getElements().iterator();
}//if//
else if(((INode) next).getName().equalsIgnoreCase("body")) {
convertTextFromXHtmlBasic((INode) next, rawText);
}//else if//
}//if//
}//while//
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
}//convertTextFromHtml()//
/*
* An internal method for converting text to XHtml Basic.
* @param node
* @param buffer
*
private void convertTextFromXHtmlBasic(INode node, StringBuffer buffer) {
for(int index = 0; index < node.getElements().getSize(); index++) {
IElement next = (IElement) node.getElements().get(index);
if(next.isText()) {
int startIndex = buffer.length();
int endIndex;
buffer.append(((IText) next).getText());
endIndex = buffer.length();
}//if//
else if(next.isNode()) {
String nodeName = ((INode) next).getName();
if(nodeName.equals("b")) {
}//if//
}//else if//
}//for//
}//convertTextFromXHtmlBasic()//
/*
* Converts the text from the styled text control to XHTML Basic formatting.
* @return The converted text.
*
protected String convertXHtmlBasicFromText() {
StringBuffer output = new StringBuffer(1000);
try {
IDocument xmlDocument = new DocumentBuilder().createDocument();
xmlDocument.setDocType(new DocType("HTML", "PUBLIC", "-//W3C//DTD XHTML Basic 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"));
}//try//
catch(Throwable e) {
Debug.log(e);
}//catch//
return output.toString();
}//convertXHtmlBasicFromText()//
*/