blob: 13f9d67639125b43f599495352d8c00903c5c860 [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 IBM Corporation and others.
// 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.richtext;
import java.net.URL;
import java.util.Iterator;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.epf.common.serviceability.Logger;
import org.eclipse.epf.richtext.actions.CopyAction;
import org.eclipse.epf.richtext.actions.CutAction;
import org.eclipse.epf.richtext.actions.FindReplaceAction;
import org.eclipse.epf.richtext.actions.PasteAction;
import org.eclipse.epf.richtext.actions.PastePlainTextAction;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.HTMLTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.keys.IBindingService;
/**
* The default rich text editor implementation.
* <p>
* The default rich text editor uses XHTML as the underlying markup language for
* the rich text content. It is implemented using a <code>ViewForm</code>
* control with a tool bar at the top, a tab folder that contains a
* <code>RichText</code> control for entering the rich text content, and a tab
* foler that contains a <code>StyleText</code> control for viewing and
* modifying the XHTML representation of the rich text content.
*
* @author Kelvin Low
* @author Jeff Hardy
* @since 1.0
*/
public class RichTextEditor implements IRichTextEditor {
// The HTML tab name.
protected static final String HTML_TAB_NAME = RichTextResources.htmlTab_text;
// If true, log debugging info.
protected boolean debug;
// The plug-in logger.
protected Logger logger;
// The base path used for resolving links (<href>, <img>, etc.).
protected String basePath;
// The editor form.
protected ViewForm form;
// The editor tool bar.
protected IRichTextToolBar toolBar;
// The editor content.
protected Composite content;
// The editor tab folder.
protected CTabFolder tabFolder;
// The rich text tab
protected CTabItem richTextTab;
// The HTML source tab
protected CTabItem htmlTab;
// The embedded rich text control.
protected IRichText richText;
// The underlying HTML text editor.
protected StyledText sourceEdit;
// Drop support
DropTarget sourceEditDropTarget;
// HTML editor's context menu
protected Menu contextMenu;
// Has the HTML source been modified?
protected boolean sourceModified = false;
// The editor's editable flag.
protected boolean editable = true;
// The modify listener for the sourceEdit control.
protected ModifyListener sourceEditModifyListener = new ModifyListener() {
public void modifyText(ModifyEvent e) {
sourceModified = true;
if (richText != null && richText instanceof RichText) {
((RichText) richText).notifyModifyListeners();
}
}
};
// The deactivate listener for the sourceEdit control.
protected Listener sourceEditDeactivateListener = new Listener() {
public void handleEvent(Event event) {
if (sourceModified) {
updateRichText(sourceEdit.getText());
setModified(true);
sourceModified = false;
}
}
};
// The key listener for the sourceEdit control.
protected KeyListener sourceEditKeyListener = new KeyListener() {
public void keyPressed(KeyEvent e) {
Object adapter = PlatformUI.getWorkbench().getAdapter(
IBindingService.class);
if (adapter != null && adapter instanceof IBindingService) {
int accel = SWTKeySupport
.convertEventToUnmodifiedAccelerator(e);
KeyStroke stroke = SWTKeySupport
.convertAcceleratorToKeyStroke(accel);
KeySequence seq = KeySequence.getInstance(stroke);
Binding bind = ((IBindingService) adapter).getPerfectMatch(seq);
if (bind != null) {
ParameterizedCommand command = bind
.getParameterizedCommand();
if (command != null) {
String cmdId = command.getId();
if (cmdId != null
&& cmdId
.equals("org.eclipse.ui.edit.findReplace")) { //$NON-NLS-1$
richText.getFindReplaceAction().execute(RichTextEditor.this);
}
}
}
}
}
public void keyReleased(KeyEvent e) {
}
};
/**
* Creates a new instance.
*
* @param parent
* the parent composite
* @param style
* the editor style
*/
public RichTextEditor(Composite parent, int style) {
this(parent, style, null);
}
/**
* Creates a new instance.
*
* @param parent
* the parent composite
* @param style
* the editor style
* @param basePath
* the base path used for resolving links
*/
public RichTextEditor(Composite parent, int style, String basePath) {
this.basePath = basePath;
debug = RichTextPlugin.getDefault().isDebugging();
logger = RichTextPlugin.getDefault().getLogger();
init(parent, style);
}
/**
* Initializes this editor.
*
* @param parent
* the parent composite
* @param style
* the editor style
*/
protected void init(Composite parent, int style) {
try {
form = new ViewForm(parent, style);
form.marginHeight = 0;
form.marginWidth = 0;
toolBar = new RichTextToolBar(form, SWT.FLAT, this);
content = new Composite(form, SWT.FLAT);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
content.setLayout(layout);
tabFolder = createEditorTabFolder(content, style);
form.setTopLeft((Control) toolBar);
form.setContent(content);
} catch (Exception e) {
logger.logError(e);
}
}
/**
* Returns the form control.
*
* @return the form control
*/
public Control getControl() {
return form;
}
/**
* Returns the rich text control embedded within this editor.
*/
public IRichText getRichTextControl() {
return richText;
}
/**
* Sets the layout data.
*
* @param layoutData
* the layout data to set
*/
public void setLayoutData(Object layoutData) {
if (form != null) {
form.setLayoutData(layoutData);
}
}
/**
* Returns the layout data.
*
* @return the editor's layout data
*/
public Object getLayoutData() {
if (form != null) {
return form.getLayoutData();
}
return null;
}
/**
* Sets focus to this editor.
*/
public void setFocus() {
if (richText != null) {
richText.setFocus();
}
setSelection(0);
}
/**
* Tells the control it does not have focus.
*/
public void setBlur() {
if (richText != null) {
richText.setBlur();
}
}
/**
* Checks whether this editor has focus.
*
* @return <code>true</code> if this editor has the user-interface focus
*/
public boolean hasFocus() {
if (richText != null) {
return richText.hasFocus();
}
return false;
}
/**
* Selects the Rich Text or HTML tab.
*
* @param index
* <code>0</code> for the Rich Text tab, <code>1</code> for
* the HTML tab.
*/
public void setSelection(int index) {
if (tabFolder != null) {
tabFolder.setSelection(index);
}
}
/**
* Returns the base path used for resolving text and image links.
*
* @return the base path used for resolving links specified with <href>,
* <img>, etc.
*/
public String getBasePath() {
return basePath;
}
/**
* Returns the base URL of the rich text control whose content was last
* copied to the clipboard.
*
* @return the base URL of a rich text control
*/
public URL getCopyURL() {
if (richText != null) {
return richText.getCopyURL();
}
return null;
}
/**
* Sets the base URL of the rich text control whose content was last copied
* to the clipboard.
*/
public void setCopyURL() {
if (richText != null) {
richText.setCopyURL();
}
}
/**
* Returns the editable state.
*
* @return <code>true</code> if the content can be edited
*/
public boolean getEditable() {
return editable;
}
/**
* Sets the editable state.
*
* @param editable
* the editable state
*/
public void setEditable(boolean editable) {
this.editable = editable;
if (toolBar != null && tabFolder != null) {
if (tabFolder.getSelection() == richTextTab) {
toolBar.updateToolBar(editable);
}
}
if (richText != null) {
richText.setEditable(editable);
}
if (sourceEdit != null) {
sourceEdit.setEditable(editable);
sourceEdit.getEditable();
}
}
/**
* Checks whether the content has been modified.
*
* @return <code>true</code> if the content has been modified
*/
public boolean getModified() {
if (richText != null) {
return richText.getModified();
}
return false;
}
/**
* Sets the modified state.
*
* @param modified
* the modified state
*/
public void setModified(boolean modified) {
if (richText != null) {
richText.setModified(modified);
}
}
/**
* Returns the rich text content.
*
* @return the rich text content formatted in XHTML
*/
public String getText() {
if (sourceModified) {
setText(sourceEdit.getText());
setModified(true);
sourceModified = false;
}
if (richText != null) {
return richText.getText();
}
return ""; //$NON-NLS-1$
}
/**
* Sets the rich text content.
*
* @param text
* the rich text content in XHTML format
*/
public void setText(String text) {
if (richText != null) {
richText.setText(text);
}
sourceModified = false;
if (tabFolder != null) {
if (toolBar != null) {
toolBar.updateToolBar(editable);
}
if (sourceEdit != null) {
sourceEdit.removeModifyListener(sourceEditModifyListener);
sourceEdit.setText(getText());
sourceEdit.addModifyListener(sourceEditModifyListener);
}
}
}
/*
* (non-Javadoc)
* @see org.eclipse.epf.richtext.IRichText#checkModify()
*/
public void checkModify() {
richText.checkModify();
if (sourceModified) {
notifyModifyListeners();
}
if (debug) {
printDebugMessage("checkModify", "modified=" + sourceModified); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Restores the rich text content back to the initial value.
*/
public void restoreText() {
if (richText != null) {
richText.restoreText();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.epf.richtext.IRichText#getSelected()
*/
public RichTextSelection getSelected() {
if (tabFolder.getSelection() == htmlTab) {
String HTMLsource = sourceEdit.getText();
Point sel = sourceEdit.getSelectionRange();
int selStartIndex = sel.x;
int selEndIndex = sel.x + sel.y - 1;
richText.getSelected().clear();
richText.getSelected().setText(HTMLsource.substring(selStartIndex, selEndIndex + 1));
}
return richText.getSelected();
}
/**
* Returns an application specific property value.
*
* @param key
* the name of the property
* @return the value of the property or <code>null</code> if it has not
* been set
*/
public Object getData(String key) {
if (richText != null) {
richText.getData(key);
}
return null;
}
/**
* Sets an application specific property name and value.
*
* @param key
* the name of the property
* @param value
* the new value for the property
*/
public void setData(String key, Object value) {
if (richText != null) {
richText.setData(key, value);
}
}
/**
* Executes the given rich text command. The supported command strings are
* defined in <code>RichTextCommand<code>.
*
* @param command a rich text command string
* @return a status code returned by the executed command
*/
public int executeCommand(String command) {
if (richText != null) {
return richText.executeCommand(command);
}
return 0;
}
/**
* Executes the given rich text command with a single parameter. The
* supported command strings are defined in <code>RichTextCommand<code>.
*
* @param command a rich text command string
* @param param a parameter for the command or <code>null</code>
* @return a status code returned by the executed command
*/
public int executeCommand(String command, String param) {
if (richText != null) {
return richText.executeCommand(command, param);
}
return 0;
}
/**
* Executes the given rich text command with an array of parameters. The
* supported command strings are defined in <code>RichTextCommand<code>.
*
* @param command a rich text command string
* @param params an array of parameters for the command or <code>null</code>
* @return a status code returned by the executed command
*/
public int executeCommand(String command, String[] params) {
if (richText != null) {
return richText.executeCommand(command, params);
}
return 0;
}
/**
* Disposes the operating system resources allocated by this editor.
*/
public void dispose() {
if (contextMenu != null && !contextMenu.isDisposed()) {
contextMenu.dispose();
contextMenu = null;
}
if (sourceEditDropTarget != null) {
sourceEditDropTarget.dispose();
sourceEditDropTarget = null;
}
if (sourceEdit != null) {
sourceEdit.removeModifyListener(sourceEditModifyListener);
sourceEdit.removeListener(SWT.Deactivate,
sourceEditDeactivateListener);
sourceEdit.removeKeyListener(sourceEditKeyListener);
sourceEditModifyListener = null;
sourceEditDeactivateListener = null;
sourceEditKeyListener = null;
}
if (richText != null) {
richText.dispose();
richText = null;
}
}
/**
* Checks whether this control has been disposed.
*
* @return <code>true</code> if this control is disposed successfully
*/
public boolean isDisposed() {
if (richText != null) {
return richText.isDisposed();
}
return true;
}
/**
* Returns the modify listeners attached to this editor.
*
* @return an iterator for retrieving the modify listeners
*/
public Iterator getModifyListeners() {
if (richText != null) {
richText.getModifyListeners();
}
return null;
}
/**
* Adds a listener to the collection of listeners who will be notified when
* keys are pressed and released within this editor.
*
* @param listener
* the listener which should be notified
*/
public void addKeyListener(KeyListener listener) {
if (richText != null) {
richText.addKeyListener(listener);
}
}
/**
* Removes a listener from the collection of listeners who will be notified
* when keys are pressed and released within this editor.
*
* @param listener
* the listener which should no longer be notified
*/
public void removeKeyListener(KeyListener listener) {
if (richText != null) {
richText.removeKeyListener(listener);
}
}
/**
* Adds a listener to the collection of listeners who will be notified when
* the content of this editor is modified.
*
* @param listener
* the listener which should be notified
*/
public void addModifyListener(ModifyListener listener) {
if (richText != null) {
richText.addModifyListener(listener);
}
}
/**
* Removes a listener from the collection of listeners who will be notified
* when the content of this editor is modified.
*
* @param listener
* the listener which should no longer be notified
*/
public void removeModifyListener(ModifyListener listener) {
if (richText != null) {
richText.removeModifyListener(listener);
}
}
/**
* Adds the listener to the collection of listeners who will be notifed when
* this editor is disposed.
*
* @param listener
* the listener which should be notified
*/
public void addDisposeListener(DisposeListener listener) {
if (richText != null) {
richText.addDisposeListener(listener);
}
}
/**
* Removes a listener from the collection of listeners who will be notified
* when this editor is disposed.
*
* @param listener
* the listener which should no longer be notified
*/
public void removeDisposeListener(DisposeListener listener) {
if (richText != null) {
richText.removeDisposeListener(listener);
}
}
/**
* Adds a listener to the collection of listeners who will be notified when
* help events are generated for this editor.
*
* @param listener
* the listener which should be notified
*/
public void addHelpListener(HelpListener listener) {
if (richText != null) {
richText.addHelpListener(listener);
}
}
/**
* Removes a listener from the collection of listeners who will be notified
* when help events are generated for this editor.
*
* @param listener
* the listener which should no longer be notified
*/
public void removeHelpListener(HelpListener listener) {
if (richText != null) {
richText.removeHelpListener(listener);
}
}
/**
* Adds the listener to the collection of listeners who will be notifed when
* an event of the given type occurs within this editor.
*
* @param eventType
* the type of event to listen for
* @param listener
* the listener which should be notified when the event occurs
*/
public void addListener(int eventType, Listener listener) {
if (richText != null) {
richText.addListener(eventType, listener);
}
}
/**
* Removes the listener from the collection of listeners who will be notifed
* when an event of the given type occurs within this editor.
*
* @param eventType
* the type of event to listen for
* @param listener
* the listener which should no longer be notified when the event
* occurs
*/
public void removeListener(int eventType, Listener listener) {
if (richText != null) {
richText.removeListener(eventType, listener);
}
}
/**
* Returns the event listeners attached to this editor.
*
* @return an iterator for retrieving the event listeners attached to this
* editor
*/
public Iterator getListeners() {
if (richText != null) {
return richText.getListeners();
}
return null;
}
/**
* Notifies the modify listeners that the rich text editor content has
* changed.
*/
protected void notifyModifyListeners() {
if (richText != null) {
Event event = new Event();
event.display = Display.getCurrent();
event.widget = richText.getControl();
for (Iterator i = getModifyListeners(); i != null && i.hasNext();) {
ModifyListener listener = (ModifyListener) i.next();
listener.modifyText(new ModifyEvent(event));
}
}
}
/**
* Fills the tool bar with action items.
*
* @param toolBar
* a tool bar contain rich text actions
*/
public void fillToolBar(IRichTextToolBar toolBar) {
}
/**
* Creates the underlying rich text control.
*
* @param parent
* the parent composite
* @param style
* the style for the control
* @param basePath
* the path used for resolving links
*/
protected IRichText createRichTextControl(Composite parent, int style,
String basePath) {
return new RichText(parent, style, basePath);
}
/**
* Creates the editor tab folder.
*
* @param parent
* the parent control
* @param style
* the style for the control
* @return a new editor toolbar
*/
protected CTabFolder createEditorTabFolder(Composite parent, int style) {
CTabFolder folder = new CTabFolder(parent, SWT.FLAT | SWT.BOTTOM);
folder.setLayout(new GridLayout(1, true));
folder.setLayoutData(new GridData(GridData.FILL_BOTH));
Composite richTextComposite = new Composite(folder, SWT.FLAT);
GridLayout richTextCompositeLayout = new GridLayout(1, false);
richTextCompositeLayout.marginHeight = 0;
richTextCompositeLayout.marginWidth = 0;
richTextComposite.setLayout(richTextCompositeLayout);
richTextComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
richText = createRichTextControl(richTextComposite, style, basePath);
richText.setData(PROPERTY_NAME, this);
richText.getFindReplaceAction().setRichText(this);
richTextTab = new CTabItem(folder, SWT.FLAT);
richTextTab.setText(RichTextResources.richTextTab_text);
richTextTab.setToolTipText(RichTextResources.richTextTab_toolTipText);
richTextTab.setControl(richTextComposite);
Composite htmlComposite = new Composite(folder, SWT.FLAT);
htmlComposite.setLayout(new FillLayout());
sourceEdit = new StyledText(htmlComposite, SWT.FLAT | SWT.MULTI
| SWT.WRAP | SWT.V_SCROLL);
sourceEdit.addModifyListener(sourceEditModifyListener);
sourceEdit.addListener(SWT.Deactivate, sourceEditDeactivateListener);
sourceEdit.addKeyListener(sourceEditKeyListener);
contextMenu = new Menu(parent.getShell(), SWT.POP_UP);
sourceEdit.setMenu(contextMenu);
addDropSupportToStyledText();
fillContextMenu(contextMenu);
htmlTab = new CTabItem(folder, SWT.NONE);
htmlTab.setText(HTML_TAB_NAME);
htmlTab.setToolTipText(RichTextResources.htmlTab_toolTipText);
htmlTab.setControl(htmlComposite);
folder.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
CTabItem item = (CTabItem) event.item;
if (item.getText().equals(HTML_TAB_NAME)) {
sourceEdit.removeModifyListener(sourceEditModifyListener);
sourceEdit.setText(getText());
sourceModified = false;
sourceEdit.addModifyListener(sourceEditModifyListener);
if (toolBar != null) {
toolBar.updateToolBar(editable);
}
sourceEdit.setCaretOffset(richText.getSelected().getOffsetStart());
} else {
updateRichText(sourceEdit.getText());
setModified(true);
if (toolBar != null) {
toolBar.updateToolBar(editable);
}
}
}
});
fillToolBar(toolBar);
folder.setSelection(0);
return folder;
}
/**
* Returns the HTML source edit control.
*
* @return a <code>StyleText</code> object.
*/
public StyledText getSourceEdit() {
return sourceEdit;
}
/**
* Inserts text at the selection (overwriting the selection).
*/
public void addHTML(String text) {
if (text == null || text.length() == 0)
return;
if (tabFolder.getSelection() == richTextTab) {
executeCommand(RichTextCommand.ADD_HTML, text);
} else if (tabFolder.getSelection() == htmlTab) {
String oldHTML = sourceEdit.getText();
Point sel = sourceEdit.getSelectionRange();
int selStartIndex = sel.x;
int selEndIndex = sel.x + sel.y - 1;
String newHTML = oldHTML.substring(0, selStartIndex) + text
+ oldHTML.substring(selEndIndex + 1);
sourceEdit.removeModifyListener(sourceEditModifyListener);
sourceEdit.setText(newHTML);
sourceEdit.addModifyListener(sourceEditModifyListener);
updateRichText(newHTML);
}
}
/**
* Inserts an image at the selection (overwriting the selection).
*/
public void addImage(String imageURL, String height, String width, String altTag) {
if (tabFolder.getSelection() == richTextTab) {
executeCommand(
RichTextCommand.ADD_IMAGE,
new String[] {
imageURL,
height, width, altTag });
} else if (tabFolder.getSelection() == htmlTab) {
StringBuffer imageLink = new StringBuffer();
// order of these attributes is the same as JTidy'ed HTML
imageLink.append("<img"); //$NON-NLS-1$
if (height.length() > 0) {
imageLink.append(" height=\"" + height + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
if (altTag.length() > 0) {
imageLink.append(" alt=\"" + altTag + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
imageLink.append(" src=\"" + imageURL + "\""); //$NON-NLS-1$ //$NON-NLS-2$
if (width.length() > 0) {
imageLink.append(" width=\"" + width + "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
imageLink.append(" />"); //$NON-NLS-1$
String oldHTML = sourceEdit.getText();
Point sel = sourceEdit.getSelectionRange();
int selStartIndex = sel.x;
int selEndIndex = sel.x + sel.y - 1;
String newHTML = oldHTML.substring(0, selStartIndex) + imageLink.toString()
+ oldHTML.substring(selEndIndex + 1);
sourceEdit.removeModifyListener(sourceEditModifyListener);
sourceEdit.setText(newHTML);
sourceEdit.addModifyListener(sourceEditModifyListener);
updateRichText(newHTML);
}
}
/**
* Checks whether the HTML tab is selected.
*
* @return <code>true</code> if the HTML tab is selected.
*/
public boolean isHTMLTabSelected() {
return (tabFolder.getSelection() == htmlTab);
}
/**
* Fills the context menu with menu items.
*
* @param contextMenu
* a context menu containing rich text actions
*/
protected void fillContextMenu(Menu contextMenu) {
final MenuItem cutItem = new MenuItem(contextMenu, SWT.PUSH);
cutItem.setText(RichTextResources.cutAction_text);
cutItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
CutAction action = new CutAction();
action.execute(RichTextEditor.this);
}
});
final MenuItem copyItem = new MenuItem(contextMenu, SWT.PUSH);
copyItem.setText(RichTextResources.copyAction_text);
copyItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
CopyAction action = new CopyAction();
action.execute(RichTextEditor.this);
}
});
final MenuItem pasteItem = new MenuItem(contextMenu, SWT.PUSH);
pasteItem.setText(RichTextResources.pasteAction_text);
pasteItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
PasteAction action = new PasteAction();
action.execute(RichTextEditor.this);
}
});
final MenuItem pastePlainTextItem = new MenuItem(contextMenu, SWT.PUSH);
pastePlainTextItem.setText(RichTextResources.pastePlainTextAction_text);
pastePlainTextItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
PastePlainTextAction action = new PastePlainTextAction();
action.execute(RichTextEditor.this);
}
});
contextMenu.addMenuListener(new MenuListener() {
public void menuHidden(MenuEvent e) {
}
public void menuShown(MenuEvent e) {
String selectedText = getSelected().getText();
boolean selection = selectedText.length() > 0;
cutItem.setEnabled(editable && selection);
copyItem.setEnabled(selection);
pasteItem.setEnabled(editable);
pastePlainTextItem.setEnabled(editable);
}
});
}
/**
* Updates the content of the rich text control without updating the HTML
* source editor.
* <p>
* This method should be called by the HTML source editor to sync up its
* content with the rich text control.
*
* @param text
* the rich text content in XHTML format
*/
private void updateRichText(String text) {
if (richText != null) {
richText.setText(text);
richText.checkModify();
}
sourceModified = false;
if (tabFolder != null) {
if (toolBar != null) {
toolBar.updateToolBar(editable);
}
}
}
private void addDropSupportToStyledText() {
// this function based heavily on the example at:
// http://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
// Allow data to be copied to the drop target
int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
sourceEditDropTarget = new DropTarget(sourceEdit, operations);
// Receive data in Text or HTML format
final TextTransfer textTransfer = TextTransfer.getInstance();
final HTMLTransfer htmlTransfer = HTMLTransfer.getInstance();
Transfer[] types = new Transfer[] {htmlTransfer, textTransfer};
sourceEditDropTarget.setTransfer(types);
sourceEditDropTarget.addDropListener(new DropTargetListener() {
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
// will accept text but prefer to have HTML dropped
for (int i = 0; i < event.dataTypes.length; i++) {
if (htmlTransfer.isSupportedType(event.dataTypes[i])){
event.currentDataType = event.dataTypes[i];
break;
}
}
}
public void dragOver(DropTargetEvent event) {
event.feedback = DND.FEEDBACK_SELECT | DND.FEEDBACK_INSERT_AFTER | DND.FEEDBACK_SCROLL;
}
public void dragOperationChanged(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
} else {
event.detail = DND.DROP_NONE;
}
}
}
public void dragLeave(DropTargetEvent event) {
}
public void dropAccept(DropTargetEvent event) {
}
public void drop(DropTargetEvent event) {
if (textTransfer.isSupportedType(event.currentDataType) ||
htmlTransfer.isSupportedType(event.currentDataType)) {
String text = (String)event.data;
addHTML(text);
}
}
});
}
/**
* Displays the given debug message to the console.
*/
private void printDebugMessage(String method, String msg, String text) {
StringBuffer strBuf = new StringBuffer();
strBuf.append("RichTextEditor[").append(richText.getControl().handle).append(']') //$NON-NLS-1$
.append('.').append(method);
if (msg != null && msg.length() > 0) {
strBuf.append(": ").append(msg); //$NON-NLS-1$
}
if (text != null && text.length() > 0) {
strBuf.append('\n').append(text);
}
System.out.println(strBuf);
}
/**
* Displays the given debug message to the console.
*/
private void printDebugMessage(String method, String msg) {
printDebugMessage(method, msg, null);
}
/**
* Displays the given debug message to the console.
*/
private void printDebugMessage(String method) {
printDebugMessage(method, null);
}
public FindReplaceAction getFindReplaceAction() {
return richText.getFindReplaceAction();
}
public void setFindReplaceAction(FindReplaceAction findReplaceAction) {
richText.setFindReplaceAction(findReplaceAction);
richText.getFindReplaceAction().setRichText(this);
}
}