Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormvelten2011-05-09 15:03:27 +0000
committermvelten2011-05-09 15:03:27 +0000
commited10493ae2225b1580549aabc1a6d0c8f057b312 (patch)
treed721f614086f0b902e0bc5bbef38bcb40a80e467 /extraplugins
parente1c2aba85a4483bfdb5dea4587bd0eb7dd957739 (diff)
downloadorg.eclipse.papyrus-ed10493ae2225b1580549aabc1a6d0c8f057b312.tar.gz
org.eclipse.papyrus-ed10493ae2225b1580549aabc1a6d0c8f057b312.tar.xz
org.eclipse.papyrus-ed10493ae2225b1580549aabc1a6d0c8f057b312.zip
Add EPF Richtext code.
Modified from upstream to handle win32 64bits.
Diffstat (limited to 'extraplugins')
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/.classpath8
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/.project17
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/META-INF/MANIFEST.MF15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/build.properties8
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/lib/Tidy.jarbin0 -> 177868 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.properties16
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.xml15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/CommonHTMLPlugin.java56
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLFormatter.java286
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLParser.java212
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/.classpath7
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/.project28
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF16
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/build.properties6
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/plugin.properties15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java529
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java71
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/ContextProvider.java37
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java532
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PropertyChangeEventWrapper.java65
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/actions/CComboContributionItem.java164
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java122
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java60
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java598
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java47
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java123
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java626
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java127
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java173
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java208
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.classpath7
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.project28
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/META-INF/MANIFEST.MF10
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/build.properties6
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/plugin.properties15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java218
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.classpath7
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.project28
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/META-INF/MANIFEST.MF10
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/build.properties6
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/plugin.properties15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java218
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/.classpath7
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/.project28
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/META-INF/MANIFEST.MF20
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/build.properties8
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/plugin.properties15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/plugin.xml8
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlFormatter.exsd105
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlParser.exsd105
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/schema/markerAttributeContributer.exsd111
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/schema/objectFactory.exsd102
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/AbstractActivator.java518
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/CommonPlugin.java82
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IActivator.java23
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IContextProvider.java15
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLFormatter.java39
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLParser.java25
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IMessageCallback.java26
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPreferenceStoreWrapper.java440
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeEventWrapper.java50
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeListenerWrapper.java23
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/DebugTrace.java104
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/Logger.java134
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ExtensionHelper.java216
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/FileUtil.java1285
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/I18nUtil.java219
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IMarkerAttributeContributer.java25
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IObjectFactory.java23
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ImageUtil.java179
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/MathUtil.java25
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/NetUtil.java400
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ProfilingUtil.java60
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/RestartableJob.java123
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StrUtil.java676
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StringMatcher.java458
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ThreadUtil.java41
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/Timer.java49
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/WarUtil.java57
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/XMLUtil.java666
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ZipUtil.java106
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/AbstractSAXParser.java216
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/XSLTProcessor.java449
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/.project17
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/build.properties4
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/epl-v10.html304
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.properties141
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.xml82
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/license.html79
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/.classpath16
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/.project28
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/META-INF/MANIFEST.MF21
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/about.html22
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/about.ini18
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/about.mappings7
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/about.properties49
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/application_32.gifbin0 -> 1706 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/build.properties23
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddCode.gifbin0 -> 349 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddImage.gifbin0 -> 576 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddLink.gifbin0 -> 225 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddOrderedList.gifbin0 -> 106 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddTable.gifbin0 -> 348 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddUnorderedList.gifbin0 -> 103 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Bold.gifbin0 -> 104 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/ClearContent.gifbin0 -> 328 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Copy.gifbin0 -> 364 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Cut.gifbin0 -> 138 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/FindReplace.gifbin0 -> 332 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Indent.gifbin0 -> 135 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Italic.gifbin0 -> 79 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Outdent.gifbin0 -> 137 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Paste.gifbin0 -> 361 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/PastePlainText.gifbin0 -> 560 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Subscript.gifbin0 -> 85 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Superscript.gifbin0 -> 83 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/TidyHTML.gifbin0 -> 352 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Underline.gifbin0 -> 88 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddCode.gifbin0 -> 349 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddImage.gifbin0 -> 1024 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLine.gifbin0 -> 73 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLink.gifbin0 -> 942 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddOrderedList.gifbin0 -> 152 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddTable.gifbin0 -> 982 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddUnorderedList.gifbin0 -> 139 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Bold.gifbin0 -> 132 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/ClearContent.gifbin0 -> 162 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Copy.gifbin0 -> 994 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Cut.gifbin0 -> 913 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/FindReplace.gifbin0 -> 947 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Indent.gifbin0 -> 905 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Italic.gifbin0 -> 123 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyCenter.gifbin0 -> 67 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyFull.gifbin0 -> 67 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyLeft.gifbin0 -> 67 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyRight.gifbin0 -> 67 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Outdent.gifbin0 -> 905 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Paste.gifbin0 -> 1005 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/PastePlainText.gifbin0 -> 588 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/StrikeThrough.gifbin0 -> 76 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Subscript.gifbin0 -> 130 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Superscript.gifbin0 -> 133 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/TidyHTML.gifbin0 -> 971 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Underline.gifbin0 -> 138 bytes
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/plugin.properties34
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/blank.htm9
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.css457
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.html20
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.js1490
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.xsl32
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichText.java355
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextEditor.java50
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextToolBar.java72
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/Resources.properties160
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichText.java1657
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextCommand.java267
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditor.java1555
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditorForm.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextFormToolkit.java91
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextImages.java475
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextListener.java66
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextPlugin.java80
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextResources.java146
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextSelection.java150
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextToolBar.java191
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddCodeAction.java42
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddImageAction.java76
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLineAction.java58
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLinkAction.java74
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddOrderedListAction.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddTableAction.java81
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddUnorderedListAction.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BaseRichTextAction.java83
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BlockTagAction.java81
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BoldAction.java67
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ClearContentAction.java64
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CopyAction.java84
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CutAction.java76
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FindReplaceAction.java388
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontNameAction.java121
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontSizeAction.java106
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontStyleAction.java94
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IBaseRichTextAction.java62
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextAction.java97
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextComboAction.java76
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IndentAction.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ItalicAction.java67
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyCenterAction.java58
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyFullAction.java58
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyLeftAction.java58
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyRightAction.java58
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/OutdentAction.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PasteAction.java247
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PastePlainTextAction.java62
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextAction.java158
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextComboAction.java148
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SubscriptAction.java68
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SuperscriptAction.java69
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyAction.java95
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyActionGroup.java82
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/UnderlineAction.java68
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddCodeDialog.java79
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddImageDialog.java143
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddLinkDialog.java126
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddTableDialog.java220
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/BaseDialog.java91
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/FindReplaceDialog.java337
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/BlockTag.java195
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontName.java150
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontStyle.java197
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Image.java59
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Link.java89
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Table.java196
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/package.html5
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencePage.java183
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferences.java51
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencesInitializer.java45
-rw-r--r--extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/package.html5
234 files changed, 25894 insertions, 0 deletions
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.common.html/.classpath
new file mode 100644
index 00000000000..8db29a6be58
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="lib/Tidy.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/.project b/extraplugins/epf-richtext/org.eclipse.epf.common.html/.project
new file mode 100644
index 00000000000..4fa523f8557
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.common.html</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.common.html/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..4ba88bc3c10
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/META-INF/MANIFEST.MF
@@ -0,0 +1,15 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.common.html;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: org.eclipse.epf.common.html.CommonHTMLPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.epf.common
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.epf.common.html
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ClassPath: lib/Tidy.jar,
+ .
+
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/about.html b/extraplugins/epf-richtext/org.eclipse.epf.common.html/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.html/build.properties
new file mode 100644
index 00000000000..aca5337e3c1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/build.properties
@@ -0,0 +1,8 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.properties,\
+ .,\
+ META-INF/,\
+ about.html,\
+ plugin.xml,\
+ lib/
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/lib/Tidy.jar b/extraplugins/epf-richtext/org.eclipse.epf.common.html/lib/Tidy.jar
new file mode 100644
index 00000000000..af4eed0506b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/lib/Tidy.jar
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.properties
new file mode 100644
index 00000000000..6372abf9e60
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.properties
@@ -0,0 +1,16 @@
+# NLS_ENCODING=UNICODE
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Common HTML
+providerName=Eclipse.org
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.xml b/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.xml
new file mode 100644
index 00000000000..f6af5e2d3ca
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/plugin.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.epf.common.htmlFormatter">
+ <htmlFormatter
+ class="org.eclipse.epf.common.html.DefaultHTMLFormatter"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.epf.common.htmlParser">
+ <htmlParser
+ class="org.eclipse.epf.common.html.DefaultHTMLParser"/>
+ </extension>
+</plugin>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/CommonHTMLPlugin.java b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/CommonHTMLPlugin.java
new file mode 100644
index 00000000000..ae5a9f9c28f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/CommonHTMLPlugin.java
@@ -0,0 +1,56 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.html;
+
+import org.eclipse.epf.common.AbstractActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The Common plug-in activator.
+ */
+public final class CommonHTMLPlugin extends AbstractActivator {
+
+ // The shared plug-in instance.
+ private static CommonHTMLPlugin plugin;
+
+ /**
+ * Creates a new instance.
+ */
+ public CommonHTMLPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Gets the shared instance.
+ *
+ * @return the shared plug-in instance
+ */
+ public static CommonHTMLPlugin getDefault() {
+ return plugin;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLFormatter.java b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLFormatter.java
new file mode 100644
index 00000000000..eca7bf5a198
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLFormatter.java
@@ -0,0 +1,286 @@
+//------------------------------------------------------------------------------
+// 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.common.html;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.epf.common.IHTMLFormatter;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.epf.common.utils.StrUtil;
+import org.w3c.tidy.Tidy;
+
+/**
+ * Pretty-formats HTML source and makes it XHTML compliant.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class DefaultHTMLFormatter implements IHTMLFormatter{
+
+ protected static final String HTML_BODY_START_TAG = "<body"; //$NON-NLS-1$
+
+ protected static final String HTML_BODY_END_TAG = "</body>"; //$NON-NLS-1$
+
+// private static final int HTML_BODY_START_TAG_LENGTH = HTML_BODY_START_TAG
+// .length();
+
+ protected int lineWidth;
+
+ protected boolean indent;
+
+ protected int indentSize;
+
+ protected String lastErrorStr;
+
+
+
+
+
+ /**
+ * Creates a new instance.
+ */
+ public DefaultHTMLFormatter() {
+ this(132, true, 4);
+ }
+
+ /**
+ * Creates a new instance.
+ */
+ public DefaultHTMLFormatter(int lineWidth, boolean indent, int indentSize) {
+ this.lineWidth = lineWidth;
+ this.indent = indent;
+ this.indentSize = indentSize;
+ }
+
+ /**
+ * Sets the maximum character width of a line.
+ *
+ * @param lineWidth
+ * The line width (in number of characters).
+ */
+ public void setLineWidth(int lineWidth) {
+ this.lineWidth = lineWidth;
+ }
+
+ /**
+ * Enables or disables tags indent.
+ *
+ * @param indent
+ * If true, ident the tags.
+ */
+ public void setIndent(boolean indent) {
+ this.indent = indent;
+ }
+
+ /**
+ * Sets the indent size.
+ *
+ * @param indentSize
+ * The indent size (in number of characters).
+ */
+ public void setIndentSize(int indentSize) {
+ this.indentSize = indentSize;
+ }
+
+ /**
+ * Formats the given HTML source.
+ *
+ * @param html
+ * The HTML source.
+ * @return The pretty-formatted HTML source.
+ */
+ public String formatHTML(String html) throws UnsupportedEncodingException {
+ return formatHTML(html, false, false, false, false);
+ }
+
+ /**
+ * Formats the given HTML source.
+ *
+ * @param html The HTML source.
+ * @param returnBodyOnly if false, return full HTML document or body content based on what is passed in. if true, always return body content only
+ * @param forceOutput if true, return cleaned HTML even if errors. if false, will clean minor problems and return clean HTML, but on a major error, will set getLastErrorStr() and return passed-in html
+ * @param makeBare set to true for cleaning MS HTML
+ * @param word2000 set to true for cleaning MS Word 2000 HTML
+ * @return
+ * @throws UnsupportedEncodingException
+ */
+ public String formatHTML(String html, boolean returnBodyOnly, boolean forceOutput, boolean makeBare, boolean word2000) throws UnsupportedEncodingException {
+ lastErrorStr = null;
+ if (html == null || html.length() == 0) {
+ return html;
+ }
+
+ html = removeLeadingWhitespace(html);
+
+ Tidy tidy = new Tidy();
+ tidy.setXHTML(true);
+ tidy.setDropEmptyParas(false);
+ tidy.setDropFontTags(false);
+ tidy.setQuiet(true);
+ tidy.setShowWarnings(false);
+ tidy.setSmartIndent(false);
+ tidy.setTidyMark(false);
+ tidy.setWraplen(lineWidth);
+ tidy.setIndentAttributes(false);
+ tidy.setIndentContent(indent);
+ tidy.setSpaces(indentSize);
+ tidy.setCharEncoding(org.w3c.tidy.Configuration.UTF8);
+// tidy.setInputEncoding("UTF-16"); //$NON-NLS-1$
+// tidy.setOutputEncoding("UTF-16");//$NON-NLS-1$
+ tidy.setFixBackslash(false);
+ // this will add <p> around each text block (?that isn't in a block already?)
+// tidy.setEncloseBlockText(true);
+ // setting this seemed to prevent JTidy from indenting the source
+// tidy.setPrintBodyOnly(true);
+
+ if (forceOutput) {
+ // output document even if errors are present
+// tidy.setForceOutput(true);
+ }
+ if (makeBare) {
+ // remove MS clutter
+// tidy.setMakeBare(true);
+ tidy.setMakeClean(true);
+ }
+ if (word2000) {
+ // draconian Word2000 cleaning
+ tidy.setWord2000(true);
+ }
+
+
+// Reader input = new StringReader(html);
+// Writer output = new StringWriter();
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ tidy.setErrout(pw);
+ InputStream input= new ByteArrayInputStream(html.getBytes("UTF-8"));
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ tidy.parse(input, output);
+ String error = sw.getBuffer().toString();
+ if (error != null && error.length() > 0
+ && error.startsWith("line") && error.indexOf("column") > 0) { //$NON-NLS-1$ //$NON-NLS-2$
+ lastErrorStr = error;
+ if (!forceOutput) {
+ // if forceOutput is true, JTidy will return clean HTML so don't return here
+ return html;
+ }
+ }
+
+ String formattedHTML = new String(output.toByteArray(), "UTF-8"); //$NON-NLS-1$
+ formattedHTML = StrUtil.getEscapedHTML(formattedHTML);
+
+ String htmlStartUpper = html.substring(0, Math.min(10, html.length())).toUpperCase();
+
+ if (returnBodyOnly || (!htmlStartUpper.startsWith("<!DOCTYPE") && !htmlStartUpper.startsWith("<HTML"))) { //$NON-NLS-1$ //$NON-NLS-2$
+ int startBodyTag = formattedHTML.indexOf(HTML_BODY_START_TAG);
+ int start = -1;
+ if (startBodyTag != -1) {
+ start = formattedHTML.indexOf(">",startBodyTag); //$NON-NLS-1$
+ }
+ int end = formattedHTML.indexOf(HTML_BODY_END_TAG);
+ if (start == -1 || end == -1) {
+ return ""; //$NON-NLS-1$
+ }
+ start += 1;
+ if (start >= end) {
+ return ""; //$NON-NLS-1$
+ }
+ start += FileUtil.LINE_SEP_LENGTH;
+ end -= FileUtil.LINE_SEP_LENGTH;
+ if (indent && indentSize > 0) {
+ end -= indentSize;
+ }
+ if (start >= end) {
+ return ""; //$NON-NLS-1$
+ }
+ String result = formattedHTML.substring(start, end);
+ if (indent && indentSize > 0) {
+ String indentStr = getIndentStr(indentSize * 2);
+ result = fixIndentation(result, indentStr);
+ return result;
+ }
+ }
+ return formattedHTML;
+ }
+
+ /**
+ * Returns the indent string.
+ */
+ protected static String getIndentStr(int indentLength) {
+ if (indentLength == 0) {
+ return ""; //$NON-NLS-1$
+ }
+ StringBuffer indentStr = new StringBuffer();
+ for (int i = 0; i < indentLength; i++) {
+ indentStr.append(' ');
+ }
+ return indentStr.toString();
+ }
+
+ public static final String PRE_TAG_START = "<pre>"; //$NON-NLS-1$
+
+ public static final String PRE_TAG_END = "</pre>"; //$NON-NLS-1$
+
+ public static final int PRE_TAG_END_LENGTH = PRE_TAG_END.length();
+
+ /**
+ * Undo the JTidy indent, but ignore &lt;pre&gt; tags
+ *
+ * @param html
+ * @param indentStr
+ * @return
+ */
+ protected static String fixIndentation(String html, String indentStr) {
+ if (html.startsWith(indentStr)) {
+ html = html.substring(indentStr.length());
+ }
+ StringBuffer strBuf = new StringBuffer();
+ int pre_index = -1;
+ int last_pre_end_index = -1;
+ while ((pre_index = html.indexOf(PRE_TAG_START, last_pre_end_index)) != -1) {
+ strBuf.append(html.substring(
+ last_pre_end_index < 0 ? 0 : last_pre_end_index
+ + PRE_TAG_END_LENGTH, pre_index).replaceAll(
+ "\r\n" + indentStr, "\r\n")); //$NON-NLS-1$ //$NON-NLS-2$
+ last_pre_end_index = html.indexOf(PRE_TAG_END, pre_index);
+ if (last_pre_end_index != -1) {
+ strBuf.append(html.substring(pre_index, last_pre_end_index
+ + PRE_TAG_END_LENGTH));
+ } else {
+ // found <pre>, but no ending </pre> - shouldn't ever get here
+ // append rest of string and return it
+ strBuf.append(html.substring(pre_index));
+ return strBuf.toString();
+ }
+ }
+ strBuf.append(html.substring(
+ last_pre_end_index < 0 ? 0 : last_pre_end_index
+ + PRE_TAG_END_LENGTH).replaceAll("\r\n" + indentStr, //$NON-NLS-1$
+ "\r\n")); //$NON-NLS-1$
+ return strBuf.toString();
+ }
+
+ public String getLastErrorStr() {
+ return lastErrorStr;
+ }
+
+
+ public String removeLeadingWhitespace(String input) {
+ return p_whitespace.matcher(input).replaceAll(""); //$NON-NLS-1$
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLParser.java b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLParser.java
new file mode 100644
index 00000000000..9e99d55b3ed
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.html/src/org/eclipse/epf/common/html/DefaultHTMLParser.java
@@ -0,0 +1,212 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.html;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Properties;
+
+import org.eclipse.epf.common.IHTMLParser;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.tidy.Configuration;
+import org.w3c.tidy.Tidy;
+
+/**
+ * Extracts the title, meta tags and text from a HTML file or source.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class DefaultHTMLParser implements IHTMLParser{
+
+ private static final int BUFFER_SIZE = 4096;
+
+ private static final String HTML_SCRIPT_TAG = "script"; //$NON-NLS-1$
+
+ private static final String HTML_TITLE_TAG = "title"; //$NON-NLS-1$
+
+ private static final String HTML_META_TAG = "meta"; //$NON-NLS-1$
+
+ protected Tidy tidy;
+
+ private String title;
+
+ private String summary;
+
+ private String text;
+
+ private Properties metaTags;
+
+ private StringBuffer htmlText;
+
+ /**
+ * Creates a new instance.
+ */
+ public DefaultHTMLParser() {
+ try {
+ tidy = new Tidy();
+ tidy.setXHTML(true);
+ tidy.setDropEmptyParas(true);
+ tidy.setDropFontTags(true);
+ tidy.setQuiet(true);
+ tidy.setShowWarnings(false);
+ tidy.setSmartIndent(false);
+ tidy.setTidyMark(false);
+ tidy.setWraplen(132);
+ tidy.setIndentAttributes(false);
+ tidy.setIndentContent(false);
+ tidy.setSpaces(2);
+ tidy.setCharEncoding(Configuration.ISO2022);
+// tidy.setInputEncoding("UTF-8"); //$NON-NLS-1$
+// tidy.setOutputEncoding("UTF-8"); //$NON-NLS-1$
+ } catch (Exception e) {
+ tidy = null;
+ }
+ }
+
+ /**
+ * Parses the given HTML file.
+ */
+ public void parse(File file) throws Exception {
+ if (tidy == null || !file.exists() || !file.canRead()) {
+ return;
+ }
+
+ FileInputStream fis = new FileInputStream(file);
+ InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); //$NON-NLS-1$
+ BufferedReader br = new BufferedReader(isr);
+
+ StringBuffer textBuffer = new StringBuffer(BUFFER_SIZE);
+ char[] buffer = new char[BUFFER_SIZE];
+ int charsRead;
+ while ((charsRead = br.read(buffer, 0, BUFFER_SIZE)) > 0) {
+ textBuffer.append(buffer, 0, charsRead);
+ }
+
+ parse(textBuffer.toString());
+
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ /**
+ * Parses the given HTML source.
+ */
+ protected void parse(String htmlSource) throws Exception {
+ title = ""; //$NON-NLS-1$
+ summary = ""; //$NON-NLS-1$
+ text = ""; //$NON-NLS-1$
+ metaTags = new Properties();
+
+ Document doc = getDocument(htmlSource);
+ if (doc != null) {
+ htmlText = new StringBuffer(1024);
+ extract(doc.getChildNodes());
+ text = htmlText.toString();
+ }
+ }
+
+ /**
+ * Returns the title text.
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Returns the HTML meta tags.
+ */
+ public Properties getMetaTags() {
+ return metaTags;
+ }
+
+ /**
+ * Returns the summary.
+ */
+ public String getSummary() {
+ return summary;
+ }
+
+ /**
+ * Returns the body text.
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Returns the DOM document for the given HTML source.
+ */
+ protected Document getDocument(String html) throws Exception {
+ if (html == null || html.length() == 0) {
+ return null;
+ }
+
+ ByteArrayInputStream input = new ByteArrayInputStream(html
+ .getBytes("UTF-8")); //$NON-NLS-1$
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ tidy.setErrout(pw);
+
+ return tidy.parseDOM(input, output);
+ }
+
+ /**
+ * Extracts the title, meta tags and body text from the given nodes.
+ */
+ protected void extract(NodeList nodes) {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ String nodeName = node.getNodeName();
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ if (!nodeName.equals(HTML_SCRIPT_TAG)) {
+ NamedNodeMap attrs = node.getAttributes();
+ for (int j = 0; j < attrs.getLength(); j++) {
+ Node attrNode = attrs.item(j);
+ String attrNodeName = attrNode.getNodeName();
+ String attrNodeValue = attrNode.getNodeValue();
+ if (attrNodeName.equals(HTML_TITLE_TAG)) {
+ title = attrNodeValue;
+ } else if (attrNodeName.equals(HTML_META_TAG)) {
+ metaTags.put(attrNodeName, attrNodeValue);
+ }
+ }
+ NodeList childNodes = node.getChildNodes();
+ if (childNodes != null && childNodes.getLength() > 0) {
+ extract(childNodes);
+ }
+ }
+ break;
+ case Node.TEXT_NODE:
+ htmlText.append(node.getNodeValue()).append(' ');
+ break;
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.classpath
new file mode 100644
index 00000000000..02159672985
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.project b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.project
new file mode 100644
index 00000000000..eacf917d8f1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.common.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 00000000000..0efa3f0b61e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Fri Jan 04 15:09:09 PST 2008
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..0225d64680a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.common.ui
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: org.eclipse.epf.common.ui.CommonUIPlugin
+Import-Package: org.osgi.framework;version="1.3.0"
+Bundle-ActivationPolicy: lazy
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui;visibility:=reexport,
+ org.eclipse.epf.common;visibility:=reexport
+Export-Package: org.eclipse.epf.common.ui,
+ org.eclipse.epf.common.ui.actions,
+ org.eclipse.epf.common.ui.util
+Bundle-Vendor: %providerName
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/about.html b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/build.properties
new file mode 100644
index 00000000000..ebe02751cbb
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ about.html
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/plugin.properties
new file mode 100644
index 00000000000..b50cbf887d1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/plugin.properties
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Common UI plug-in
+providerName=Eclipse.org
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java
new file mode 100644
index 00000000000..fa3ca270068
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java
@@ -0,0 +1,529 @@
+//------------------------------------------------------------------------------
+// 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.common.ui;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.internal.runtime.InternalPlatform;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.IActivator;
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.ui.util.MsgDialog;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.epf.common.utils.I18nUtil;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The abstract base class for all EPF plug-ins.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @author Phong Nguyen Le
+ * @since 1.0
+ */
+public abstract class AbstractPlugin extends AbstractUIPlugin implements IActivator {
+
+
+ // The relative path to the icons.
+ private static final String ICON_PATH = "icons/"; //$NON-NLS-1$;
+
+ // The logger hash map.
+ private static Map<String, Logger> loggers = new HashMap<String, Logger>();
+
+ // The message dialog hash map.
+ private static Map<String, MsgDialog> msgDialogs = new HashMap<String, MsgDialog>();
+
+ // The shared image hash map.
+ private static Map<String, Image> sharedImages = new HashMap<String, Image>();
+
+ // The resource bundle for this plug-in.
+ private ResourceBundle resourceBundle;
+
+ // This plug-in ID.
+ private String pluginId;
+
+ // The plug-in install URL.
+ private URL installURL;
+
+ // The plug-in install path.
+ private String installPath;
+
+ // The plug-in icon URL.
+ private URL iconURL;
+
+ // The profiling flag.
+ private boolean profiling;
+
+ /**
+ * Default constructor.
+ */
+ public AbstractPlugin() {
+ super();
+ }
+
+ /**
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+ init(context);
+
+ // set the
+ if (isDebugging()) {
+ getLogger().logInfo("Started " + pluginId); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ // Free the shared images.
+ for (Iterator images = sharedImages.values().iterator(); images
+ .hasNext();) {
+ Image image = (Image) images.next();
+ if (image != null && !image.isDisposed()) {
+ image.dispose();
+ }
+ }
+
+ super.stop(context);
+
+ if (isDebugging()) {
+ getLogger().logInfo("Stopped " + pluginId); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Initializes this plug-in.
+ *
+ * @param context
+ * The bundle context.
+ */
+ protected void init(BundleContext context) throws Exception {
+ // Get the bundle for this plug-in.
+ Bundle bundle = getBundle();
+
+ // Get the resouce bundle for this plug-in.
+ resourceBundle = Platform.getResourceBundle(bundle);
+
+ // Get the ID for this plug-in.
+ pluginId = bundle.getSymbolicName();
+
+ if (isDebugging()) {
+ getLogger().logInfo("Initializing " + pluginId); //$NON-NLS-1$
+ }
+
+ // Get the install path of this plug-in.
+ installURL = bundle.getEntry("/"); //$NON-NLS-1$
+
+ try {
+ installPath = FileLocator.resolve(installURL).getPath();
+ } catch (IOException e) {
+ installPath = Platform.getInstallLocation().getURL().getPath();
+ }
+
+ try {
+ iconURL = new URL(installURL, ICON_PATH);
+ } catch (IOException e) {
+ }
+
+ String symbolicName = bundle.getSymbolicName();
+ if (symbolicName != null) {
+ String key = symbolicName + "/profiling"; //$NON-NLS-1$
+ String value = InternalPlatform.getDefault().getOption(key);
+ profiling = value == null ? false : value.equalsIgnoreCase("true"); //$NON-NLS-1$
+ }
+
+ if (isDebugging()) {
+ getLogger().logInfo(
+ "Initialized " + pluginId + ", installPath=" + installPath); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ * Returns the ID of this plug-in.
+ *
+ * @return The ID of this plug-in.
+ */
+ public String getId() {
+ return pluginId;
+ }
+
+ /**
+ * Returns the install URL of this plug-in.
+ *
+ * @param The
+ * install URL of this plug-in.
+ */
+ public URL getInstallURL() {
+ return installURL;
+ }
+
+ /**
+ * Returns the install path of this plug-in.
+ *
+ * @param The
+ * install path of this plug-in.
+ */
+ public String getInstallPath() {
+ return installPath;
+ }
+
+ /**
+ * Loads and returns the localized properties of a Java properties file.
+ * <p>
+ *
+ * @param path
+ * The properties file path relative to the plug-in root.
+ * @return A <code>Properties</code> object.
+ */
+ public Properties getProperties(String path) throws IOException {
+ Properties props = new Properties();
+ if (path == null) {
+ return props;
+ }
+
+ String filePath = getLocalizedFile(path, true);
+ if (filePath != null) {
+ props.load(new FileInputStream(filePath));
+ }
+
+ return props;
+ }
+
+ /**
+ * get the locale specific absolute file path name of the given file in the
+ * plugin.
+ *
+ * @param path
+ * The properties file path relative to the plug-in root.
+ * @return String the locale specific absolute file path name of the given
+ * file.
+ * @throws IOException
+ */
+ public String getLocalizedFile(String path, boolean useDefault)
+ throws IOException {
+ String filePath = null;
+ String fileName = FileUtil.getFileName(path);
+ int index = path.lastIndexOf(fileName);
+ String pathName = path.substring(0, index);
+
+ Locale locale = Locale.getDefault();
+
+ Bundle bundle = getBundle();
+ Bundle[] bundles = Platform.getFragments(bundle);
+ if (bundles != null) {
+ for (int i = 0; i < bundles.length; i++) {
+ URL entry = bundles[i].getEntry(pathName);
+ if (entry != null) {
+ URL url = FileLocator.resolve(entry);
+ filePath = I18nUtil.getLocalizedFile(url.getPath()
+ + fileName, locale);
+ if (filePath != null) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (filePath == null) {
+ URL entry = bundle.getEntry(path);
+ if (entry != null) {
+ URL url = FileLocator.resolve(entry);
+ filePath = I18nUtil.getLocalizedFile(url.getPath(), locale);
+ if (filePath == null && useDefault) {
+ filePath = url.getPath();
+ }
+ }
+ }
+
+ return filePath;
+ }
+
+ /**
+ * for the given path in the plugin, find the localized files form the nl
+ * fragemenets and copy the localized files to the destination folder
+ *
+ * @param path
+ * String a relative path to the plugin root. The files in this
+ * folder will be iterated and their localized files will be
+ * copied over
+ * @param toDir
+ * FIle the destination folder
+ * @param recursive
+ * boolean recurively looking for files int the specified folder
+ * @param useLocaleFileName
+ * boolean if true the locale specific file names will be used in
+ * the copied destination, otherwise, the locale specific file
+ * name will be renamed to the default one in the destination
+ * folder
+ * @throws IOException
+ */
+ public void copyLocalizedFiles(String path, File toDir, boolean recursive,
+ boolean useLocaleFileName) throws IOException {
+ String pluginPath = getInstallPath();
+ URI pluginUri = new File(pluginPath).toURI();
+ URI pathUri = new File(pluginPath, path).toURI();
+
+ List<File> files = new ArrayList<File>();
+ File f = new File(pluginPath, path);
+ FileUtil.getAllFiles(f, files, recursive);
+
+ // for each file found in the specified folder, get the localized file
+ for (Iterator it = files.iterator(); it.hasNext();) {
+ URI srcUri = ((File) it.next()).toURI();
+
+ // get the relative path of the file to the plugin root, then find
+ // the localized file
+ String relPath = pluginUri.relativize(srcUri).getPath();
+
+ // only get the locale specific file, don't include the default one
+ String localizedFile = getLocalizedFile(relPath, false);
+ if (localizedFile == null) {
+ continue;
+ }
+
+ // need to change the target file path to relative to the path
+ // instead of the plugin root
+ relPath = pathUri.relativize(srcUri).getPath();
+ File srcFile = new File(localizedFile);
+ File targetFile = new File(toDir, relPath);
+ File targetParent = targetFile.getParentFile();
+
+ // copy the file to the desitination
+ // if useLocaleFileName is true, the destination file name should
+ // also use the locale specific file name
+ if (useLocaleFileName) {
+ String fileName = srcFile.getName();
+ targetFile = new File(targetParent, fileName);
+ }
+
+ if (isDebugging()) {
+ System.out.println("Copying localized file: "); //$NON-NLS-1$
+ System.out.println("Source: " + srcFile); //$NON-NLS-1$
+ System.out.println("Target: " + targetFile); //$NON-NLS-1$
+ System.out.println(""); //$NON-NLS-1$
+ }
+
+ try {
+ if (!targetParent.exists()) {
+ targetParent.mkdirs();
+ }
+
+ if (!targetFile.exists()) {
+ targetFile.createNewFile();
+ }
+
+ FileUtil.copyFile(srcFile, targetFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * Returns the localized resource.
+ *
+ * @param key
+ * The resource key.
+ * @return The localized resource.
+ */
+ public String getString(String key) {
+ if (resourceBundle != null) {
+ try {
+ return resourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the formatted localized message given the resource key and the
+ * message argument.
+ *
+ * @param key
+ * The resource key.
+ * @param argument
+ * The message argument.
+ * @return The formatted localized message.
+ */
+ public String formatMessage(String key, Object argument) {
+ if (resourceBundle != null) {
+ try {
+ String msg = resourceBundle.getString(key);
+ Object[] arguments = { argument };
+ return MessageFormat.format(msg, arguments);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the image URL given the relative path.
+ *
+ * @param relativePath
+ * The image's path relative to the plug-in's root.
+ * @return The image URL.
+ */
+ public URL getImageURL(String relativePath) {
+ try {
+ URL url = new URL(iconURL, relativePath);
+ return FileLocator.resolve(url);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the image descriptor given the relative path.
+ *
+ * @param relativePath
+ * The image's path relative to the plug-in's root.
+ * @return The image descriptor.
+ */
+ public ImageDescriptor getImageDescriptor(String relativePath) {
+ try {
+ URL url = new URL(iconURL, relativePath);
+ return ImageDescriptor.createFromURL(url);
+ } catch (MalformedURLException e) {
+ return ImageDescriptor.getMissingImageDescriptor();
+ }
+ }
+
+ /**
+ * Returns the image given the relative path.
+ * <p>
+ * Note: The returned image need to be freed by the caller.
+ *
+ * @param relativePath
+ * The image's path relative to the plug-in's root.
+ * @return The image.
+ */
+ public Image getImage(String relativePath) {
+ Image image = null;
+
+ ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
+ if (imageDescriptor != null) {
+ image = imageDescriptor.createImage(false);
+ }
+
+ return image;
+ }
+
+ /**
+ * Returns the shared image given the relative path.
+ * <p>
+ * Note: The returned image will be automatically freed when the plug-in
+ * shuts down.
+ *
+ * @param relativePath
+ * The image's path relative to the plug-in's root.
+ * @return The image.
+ */
+ public Image getSharedImage(String relativePath) {
+ Image image = (Image) sharedImages.get(relativePath);
+ if (image != null) {
+ return image;
+ }
+
+ ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
+ if (imageDescriptor != null) {
+ image = imageDescriptor.createImage(false);
+ if (image != null) {
+ sharedImages.put(relativePath, image);
+ }
+ }
+
+ return image;
+ }
+
+ /**
+ * Returns the profiling flag.
+ *
+ * @return <code>true</code> if profiling is enabled for this plu-in
+ */
+ public boolean isProfiling() {
+ return profiling;
+ }
+
+ /**
+ * Returns the logger given the plug-in ID.
+ *
+ * @return The new or cached logger.
+ */
+ public Logger getLogger() {
+ Logger logger = (Logger) loggers.get(pluginId);
+ if (logger == null) {
+ logger = new Logger(this);
+ loggers.put(pluginId, logger);
+ }
+ return logger;
+ }
+
+ /**
+ * Returns the message dialog given the plug-in ID.
+ *
+ * @return The new or cached message dialog.
+ */
+ public static MsgDialog getMsgDialog(IActivator plugin) {
+ MsgDialog msgDialog = (MsgDialog) msgDialogs.get(plugin.getId());
+ if (msgDialog == null) {
+ msgDialog = new MsgDialog(plugin);
+ msgDialogs.put(plugin.getId(), msgDialog);
+ }
+ return msgDialog;
+ }
+
+
+ public MsgDialog getMsgDialog() {
+ return getMsgDialog(this);
+ }
+
+ /**
+ * Returns the standard display to be used. The method first checks, if the
+ * thread calling this method has an associated disaply. If so, this display
+ * is returned. Otherwise the method returns the default display.
+ */
+ public static Display getStandardDisplay() {
+ Display display;
+ display = Display.getCurrent();
+ if (display == null)
+ display = Display.getDefault();
+ return display;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java
new file mode 100644
index 00000000000..3681e7d3c58
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui;
+
+import org.eclipse.epf.common.CommonPlugin;
+import org.eclipse.epf.common.IMessageCallback;
+import org.eclipse.epf.common.ui.util.MsgBox;
+import org.osgi.framework.BundleContext;
+
+public class CommonUIPlugin extends AbstractPlugin {
+
+ // The shared plug-in instance.
+ private static CommonUIPlugin plugin;
+
+ /**
+ * Creates a new instance.
+ */
+ public CommonUIPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+// // set the preference store for the common plugin
+ PreferenceStoreWrapper storeWrapper = new PreferenceStoreWrapper(getPreferenceStore());
+ CommonPlugin.getDefault().setCommonPreferenceStore(storeWrapper);
+
+ // create the message callback context for the non-ui plugins
+ // this is the context for message callback
+ // for eclipse client, this is the Shell object
+ // shell object can't be shared acrooss thread, use a context provider instead
+ //CommonPlugin.getDefault().setContext(MsgBox.getDefaultShell());
+
+ CommonPlugin.getDefault().setContextProvider(new ContextProvider());
+
+ // create the MessageCallback to be accessible to the non-ui plugin
+ IMessageCallback msgCallback = new MessageCallback();
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Gets the shared instance.
+ *
+ * @return the shared plug-in instance
+ */
+ public static CommonUIPlugin getDefault() {
+ return plugin;
+ }
+
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/ContextProvider.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/ContextProvider.java
new file mode 100644
index 00000000000..7530e31cf0d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/ContextProvider.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui;
+
+import org.eclipse.epf.common.IContextProvider;
+import org.eclipse.epf.common.ui.util.MsgBox;
+
+/**
+ * content provider for non-ui plugins
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public class ContextProvider implements IContextProvider {
+
+ public Object getContext() {
+ //TODO: revisit
+ Object ctx = null;
+ try {
+ ctx = CommonUIPlugin.getDefault().getWorkbench().getDisplay().getActiveShell();
+ }
+ catch(Exception e) {
+ //
+ }
+ return ctx != null ? ctx : MsgBox.getDefaultShell();
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java
new file mode 100644
index 00000000000..dfef39b6621
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui;
+
+import org.eclipse.epf.common.AbstractActivator;
+import org.eclipse.epf.common.IMessageCallback;
+import org.eclipse.epf.common.ui.util.MsgDialog;
+
+/**
+ * message callback implementation
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public class MessageCallback implements IMessageCallback {
+
+ public void displayWarning(AbstractActivator plugin, String title, String msg, String reason) {
+ displayWarning(plugin, title, msg, reason, null, null);
+ }
+
+ public void displayWarning(AbstractActivator plugin, String msg, String reason, Throwable ex) {
+ displayWarning(plugin, msg, reason, null, ex);
+ }
+
+ public void displayWarning(AbstractActivator plugin, String msg, String reason,
+ String details, Throwable ex) {
+ String title = CommonUIPlugin.getDefault().getWorkbench().getDisplay().getActiveShell().getText();
+ displayWarning(plugin, title, msg, reason, details, ex);
+ }
+
+ public void displayWarning(AbstractActivator plugin, String title, String msg, String reason,
+ String details, Throwable ex) {
+ MsgDialog dlg = CommonUIPlugin.getDefault().getMsgDialog(plugin);
+ dlg.displayWarning(title, msg, reason, details, ex);
+ }
+
+ public void displayError(AbstractActivator plugin, String title, String msg) {
+ displayError(plugin, title, msg, null, null, null);
+ }
+
+ public void displayError(AbstractActivator plugin, String title, String msg, Throwable ex) {
+ displayError(plugin, title, msg, null, null, ex);
+ }
+ public void displayError(AbstractActivator plugin, String title, String msg, String reason, String details, Throwable ex) {
+ MsgDialog dlg = CommonUIPlugin.getDefault().getMsgDialog(plugin);
+ dlg.displayError(title, msg, reason, details, ex);
+
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java
new file mode 100644
index 00000000000..534f8af084b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java
@@ -0,0 +1,532 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.epf.common.preferences.IPreferenceStoreWrapper;
+import org.eclipse.epf.common.preferences.IPropertyChangeListenerWrapper;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * wrapper class for preference store
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public class PreferenceStoreWrapper implements IPreferenceStoreWrapper {
+ private IPreferenceStore store;
+ public PreferenceStoreWrapper(IPreferenceStore store) {
+ this.store = store;
+ }
+
+ Map<IPropertyChangeListenerWrapper, IPropertyChangeListener> listenerMap = new HashMap<IPropertyChangeListenerWrapper, IPropertyChangeListener>();
+
+ public IPreferenceStore getStore() {
+ return store;
+ }
+
+ public void addPropertyChangeListener(final IPropertyChangeListenerWrapper listener) {
+ // create a PropertyChangeListener and add to the store
+ IPropertyChangeListener pcl = new IPropertyChangeListener(){
+
+ public void propertyChange(PropertyChangeEvent event) {
+ PropertyChangeEventWrapper wrapper = new PropertyChangeEventWrapper(event);
+ listener.propertyChange(wrapper);
+
+ }};
+
+ listenerMap.put(listener, pcl);
+ store.addPropertyChangeListener(pcl);
+ }
+
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ store.firePropertyChangeEvent(name, oldValue, newValue);
+ }
+
+ public void removePropertyChangeListener(IPropertyChangeListenerWrapper listener) {
+ IPropertyChangeListener pcl = listenerMap.remove(listener);
+ if ( pcl != null ) {
+ store.removePropertyChangeListener(pcl);
+ }
+ }
+
+ /**
+ * Returns the current value of the boolean-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>false</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a boolean.
+ *
+ * @param name the name of the preference
+ * @return the boolean-valued preference
+ */
+ public boolean getBoolean(String name) {
+ return store.getBoolean(name);
+ }
+
+ /**
+ * Returns the default value for the boolean-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>false</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a boolean.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public boolean getDefaultBoolean(String name) {
+ return store.getDefaultBoolean(name);
+ }
+
+ /**
+ * Returns the default value for the double-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0.0</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a double.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public double getDefaultDouble(String name) {
+ return store.getDefaultDouble(name);
+ }
+
+ /**
+ * Returns the default value for the float-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0.0f</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a float.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public float getDefaultFloat(String name) {
+ return store.getDefaultFloat(name);
+ }
+
+ /**
+ * Returns the default value for the integer-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as an integer.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public int getDefaultInt(String name) {
+ return store.getDefaultInt(name);
+ }
+
+ /**
+ * Returns the default value for the long-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0L</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a long.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public long getDefaultLong(String name) {
+ return store.getDefaultLong(name);
+ }
+
+ /**
+ * Returns the default value for the string-valued preference
+ * with the given name.
+ * Returns the default-default value (the empty string <code>""</code>)
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a string.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public String getDefaultString(String name) {
+ return store.getDefaultString(name);
+ }
+
+ /**
+ * Returns the current value of the double-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0.0</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a double.
+ *
+ * @param name the name of the preference
+ * @return the double-valued preference
+ */
+ public double getDouble(String name) {
+ return store.getDouble(name);
+ }
+
+ /**
+ * Returns the current value of the float-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0.0f</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a float.
+ *
+ * @param name the name of the preference
+ * @return the float-valued preference
+ */
+ public float getFloat(String name) {
+ return store.getFloat(name);
+ }
+
+ /**
+ * Returns the current value of the integer-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as an integter.
+ *
+ * @param name the name of the preference
+ * @return the int-valued preference
+ */
+ public int getInt(String name) {
+ return store.getInt(name);
+ }
+
+ /**
+ * Returns the current value of the long-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0L</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a long.
+ *
+ * @param name the name of the preference
+ * @return the long-valued preference
+ */
+ public long getLong(String name) {
+ return store.getLong(name);
+ }
+
+ /**
+ * Returns the current value of the string-valued preference with the
+ * given name.
+ * Returns the default-default value (the empty string <code>""</code>)
+ * if there is no preference with the given name, or if the current value
+ * cannot be treated as a string.
+ *
+ * @param name the name of the preference
+ * @return the string-valued preference
+ */
+ public String getString(String name) {
+ return store.getString(name);
+ }
+
+ /**
+ * Returns whether the current value of the preference with the given name
+ * has the default value.
+ *
+ * @param name the name of the preference
+ * @return <code>true</code> if the preference has a known default value
+ * and its current value is the same, and <code>false</code> otherwise
+ * (including the case where the preference is unknown to this store)
+ */
+ public boolean isDefault(String name) {
+ return store.isDefault(name);
+ }
+
+ /**
+ * Returns whether the current values in this property store
+ * require saving.
+ *
+ * @return <code>true</code> if at least one of values of
+ * the preferences known to this store has changed and
+ * requires saving, and <code>false</code> otherwise.
+ */
+ public boolean needsSaving() {
+ return store.needsSaving();
+ }
+
+ /**
+ * Sets the current value of the preference with the given name to
+ * the given string value without sending a property change.
+ * <p>
+ * This method does not fire a property change event and
+ * should only be used for setting internal preferences
+ * that are not meant to be processed by listeners.
+ * Normal clients should instead call #setValue.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void putValue(String name, String value) {
+ store.putValue(name, value);
+ }
+
+ /**
+ * Sets the default value for the double-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, double value) {
+ store.setDefault(name, value);
+ }
+
+ /**
+ * Sets the default value for the float-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, float value) {
+ store.setDefault(name, value);
+ }
+
+ /**
+ * Sets the default value for the integer-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, int value) {
+ store.setDefault(name, value);
+ }
+
+ /**
+ * Sets the default value for the long-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, long value) {
+ store.setDefault(name, value);
+ }
+
+ /**
+ * Sets the default value for the string-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param defaultObject the new default value for the preference
+ */
+ public void setDefault(String name, String defaultObject) {
+ store.setDefault(name, defaultObject);
+ }
+
+ /**
+ * Sets the default value for the boolean-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, boolean value) {
+ store.setDefault(name, value);
+ }
+
+ /**
+ * Sets the current value of the preference with the given name back
+ * to its default value.
+ * <p>
+ * Note that the preferred way of re-initializing a preference to the
+ * appropriate default value is to call <code>setToDefault</code>.
+ * This is implemented by removing the named value from the store,
+ * thereby exposing the default value.
+ * </p>
+ *
+ * @param name the name of the preference
+ */
+ public void setToDefault(String name) {
+ store.setToDefault(name);
+ }
+
+ /**
+ * Sets the current value of the double-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, double value) {
+ store.setValue(name, value);
+ }
+
+ /**
+ * Sets the current value of the float-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, float value) {
+ store.setValue(name, value);
+ }
+
+ /**
+ * Sets the current value of the integer-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, int value) {
+ store.setValue(name, value);
+ }
+
+ /**
+ * Sets the current value of the long-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, long value) {
+ store.setValue(name, value);
+ }
+
+ /**
+ * Sets the current value of the string-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, String value) {
+ store.setValue(name, value);
+ }
+
+ /**
+ * Sets the current value of the boolean-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, boolean value) {
+ store.setValue(name, value);
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PropertyChangeEventWrapper.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PropertyChangeEventWrapper.java
new file mode 100644
index 00000000000..2d3a7717757
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PropertyChangeEventWrapper.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui;
+
+import org.eclipse.epf.common.preferences.IPropertyChangeEventWrapper;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * wrapper class for property change event
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public class PropertyChangeEventWrapper implements IPropertyChangeEventWrapper {
+
+ private PropertyChangeEvent event;
+ public PropertyChangeEventWrapper(PropertyChangeEvent event) {
+ this.event = event;
+ }
+
+ /**
+ * Returns the new value of the property.
+ *
+ * @return the new value, or <code>null</code> if not known
+ * or not relevant (for instance if the property was removed).
+ */
+ public Object getNewValue() {
+ return this.event.getNewValue();
+ }
+
+ /**
+ * Returns the old value of the property.
+ *
+ * @return the old value, or <code>null</code> if not known
+ * or not relevant (for instance if the property was just
+ * added and there was no old value).
+ */
+ public Object getOldValue() {
+ return this.event.getOldValue();
+ }
+
+ /**
+ * Returns the name of the property that changed.
+ * <p>
+ * Warning: there is no guarantee that the property name returned
+ * is a constant string. Callers must compare property names using
+ * equals, not ==.
+ * </p>
+ *
+ * @return the name of the property that changed
+ */
+ public String getProperty() {
+ return this.event.getProperty();
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/actions/CComboContributionItem.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/actions/CComboContributionItem.java
new file mode 100644
index 00000000000..1858e7f8bb6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/actions/CComboContributionItem.java
@@ -0,0 +1,164 @@
+//------------------------------------------------------------------------------
+// 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.common.ui.actions;
+
+import java.util.Collection;
+
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.CoolBar;
+import org.eclipse.swt.widgets.CoolItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * Wraps a CCombo in a ContributionItem for use in a toolbar
+ *
+ * Does not use a ComboViewer because of tabbing issues - see bug 78885
+ * @author Jeff Hardy
+ *
+ */
+public class CComboContributionItem extends ContributionItem {
+
+ protected CCombo CCombo;
+
+ protected ToolItem toolItem;
+
+ protected CoolItem coolItem;
+
+ protected int style;
+
+ protected Collection<String> input;
+
+ /**
+ * Creates a new instance.
+ */
+ public CComboContributionItem(int style) {
+ super();
+ this.style = style;
+ }
+
+ /*
+ * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.ToolBar,
+ * int)
+ */
+ public void fill(ToolBar parent, int index) {
+ toolItem = new ToolItem(parent, SWT.SEPARATOR);
+ Control box = createControl(parent);
+ toolItem.setControl(box);
+ Point preferredSize = CCombo.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+ toolItem.setWidth(preferredSize.x);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.CoolBar,
+ * int)
+ */
+ public void fill(CoolBar coolBar, int index) {
+ Control box = createControl(coolBar);
+
+ if (index >= 0) {
+ coolItem = new CoolItem(coolBar, SWT.DROP_DOWN, index);
+ } else {
+ coolItem = new CoolItem(coolBar, SWT.DROP_DOWN);
+ }
+
+ // Set the back reference.
+ coolItem.setData(this);
+
+ // Add the toolbar to the CoolItem widget.
+ coolItem.setControl(box);
+
+ // If the toolbar item exists then adjust the size of the cool item.
+ Point toolBarSize = box.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+
+ // Set the preferred size to the size of the toolbar plus trim.
+ coolItem.setMinimumSize(toolBarSize);
+ coolItem.setPreferredSize(toolBarSize);
+ coolItem.setSize(toolBarSize);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.Composite)
+ */
+ public void fill(Composite parent) {
+ createControl(parent);
+ }
+
+ /**
+ * Creates the control.
+ */
+ protected Control createControl(final Composite parent) {
+ CCombo = new CCombo(parent, style);
+ CCombo.setVisibleItemCount(10);
+ CCombo.setEnabled(true);
+ CCombo.setItems(input.toArray(new String[0]));
+ CCombo.addDisposeListener(
+ new DisposeListener() {
+ public void widgetDisposed(DisposeEvent event) {
+ dispose();
+ }
+ });
+
+ CCombo.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ performSelectionChanged();
+ }
+ });
+
+ return CCombo;
+ }
+
+ /**
+ * Returns the currently selected method configuration
+ */
+ protected int getSelectionIndex() {
+ return CCombo.getSelectionIndex();
+ }
+
+ protected void setInput(Collection<String> input) {
+ this.input = input;
+ }
+
+
+ protected void performSelectionChanged() {
+ }
+
+ /*
+ * @see org.eclipse.jface.action.ContributionItem#dispose()
+ */
+ public void dispose() {
+ super.dispose();
+ }
+
+ public CCombo getCCombo() {
+ return CCombo;
+ }
+
+ public ToolItem getToolItem() {
+ return toolItem;
+ }
+
+ public CoolItem getCoolItem() {
+ return coolItem;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java
new file mode 100644
index 00000000000..6fc767b6db4
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java
@@ -0,0 +1,122 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.HTMLTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.osgi.framework.Bundle;
+
+/**
+ * Utility class for retrieving data from the clipboard.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class ClipboardUtil {
+
+ /**
+ * The current clipboard.
+ */
+ private static Clipboard clipboard;
+
+ private static final String SOURCE_URL = "SourceURL:"; //$NON-NLS-1$
+
+ private static Transfer htmlTransfer = null;
+
+ static {
+ if (SWT.getPlatform().equals("win32")) { //$NON-NLS-1$
+ try {
+ boolean is64bit = (System.getProperty("os.arch").indexOf("64") != -1);
+ Bundle bundle = null;
+ if (is64bit) {
+ bundle = Platform
+ .getBundle("org.eclipse.epf.common.win32.win32.x86_64"); //$NON-NLS-1$
+ } else {
+ bundle = Platform
+ .getBundle("org.eclipse.epf.common.win32.win32.x86"); //$NON-NLS-1$
+ }
+ if (bundle != null) {
+ Class<?> c = bundle
+ .loadClass("org.eclipse.epf.common.win32.Win32HTMLTransfer"); //$NON-NLS-1$
+ if (c != null) {
+ htmlTransfer = (Transfer) c.newInstance();
+ }
+ }
+ } catch (Exception e) {
+ htmlTransfer = null;
+ }
+ }
+ }
+
+ /**
+ * Gets the HTML source URL from the current clipboard.
+ *
+ * @return the HTML source URL or <code>null</code>
+ */
+ public static String getHTMLSourceURL() {
+ if (htmlTransfer == null) {
+ return null;
+ }
+
+ Clipboard clipboard = new Clipboard(Display.getCurrent());
+ String sourceURL = null;
+ try {
+ String htmlContent = (String) clipboard.getContents(htmlTransfer);
+ if (htmlContent != null && htmlContent.length() > 0) {
+ int index = htmlContent.indexOf(SOURCE_URL);
+ if (index > 0) {
+ sourceURL = htmlContent.substring(index
+ + SOURCE_URL.length());
+ sourceURL = sourceURL.substring(0, sourceURL
+ .indexOf(FileUtil.LINE_SEP));
+ }
+ }
+ if (sourceURL != null && sourceURL.indexOf("\\") != -1) { //$NON-NLS-1$
+ // IE provides sourceURL in form "file://C:\foo\bar.htm"
+ // but when the hrefs are resolved, files look like "file:///C:/foo/bar.htm"
+ URL url = new URL(sourceURL);
+ sourceURL = url.toExternalForm();
+ if (sourceURL.startsWith("file://") && !sourceURL.startsWith("file:///")) { //$NON-NLS-1$ //$NON-NLS-2$
+ // need to add a third / so rte.js can match the sourceURL to hrefs
+ sourceURL = "file:///" + sourceURL.substring(7); //$NON-NLS-1$
+ }
+ }
+ return sourceURL;
+ } catch (MalformedURLException urlEx) {
+ return sourceURL;
+ } finally {
+ clipboard.dispose();
+ }
+ }
+
+ /**
+ * Copy the string to the clipboard.
+ */
+ public static void copyTextHTMLToClipboard(String string) {
+ if (clipboard != null)
+ clipboard.dispose();
+ clipboard = new Clipboard(null);
+ clipboard.setContents(new Object[] { string, string },
+ new Transfer[] { TextTransfer.getInstance(), HTMLTransfer.getInstance() });
+ if (clipboard != null)
+ clipboard.dispose();
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java
new file mode 100644
index 00000000000..d20685d3365
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.ui.util;
+
+import org.eclipse.epf.common.ui.CommonUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Manages the common preferences.
+ *
+ * @author Kelvin Low
+ * @since 1.2
+ */
+public class CommonPreferences {
+
+ /**
+ * Preference key for storing the preference history size.
+ */
+ private static final String PREFERENCE_HISTORY_SIZE = "preferenceHistorySize"; //$NON-NLS-1$
+
+ // The plug-in specific preference store.
+ private static IPreferenceStore prefStore = CommonUIPlugin.getDefault()
+ .getPreferenceStore();
+
+ static {
+ // Initialize the default preference values.
+ prefStore.setDefault(PREFERENCE_HISTORY_SIZE,
+ getDefaultPreferenceHistorySize());
+ }
+
+ /**
+ * Gets the default preference history size.
+ */
+ public static int getDefaultPreferenceHistorySize() {
+ return 10;
+ }
+
+ /**
+ * Gets the preference history size.
+ */
+ public static int getPreferenceHistorySize() {
+ return prefStore.getInt(PREFERENCE_HISTORY_SIZE);
+ }
+
+ /**
+ * Saves the preference history size.
+ */
+ public static void setPreferenceHistorySize(int value) {
+ prefStore.setValue(PREFERENCE_HISTORY_SIZE, value);
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java
new file mode 100644
index 00000000000..6793260c080
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java
@@ -0,0 +1,598 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IconAndMessageDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Displays an error dialog without the Details button.
+ *
+ * @author Bingxue Xu
+ * @since 1.0
+ */
+public class ErrorDialogNoReason extends IconAndMessageDialog {
+
+ /**
+ * Static to prevent opening of error dialogs for automated testing.
+ */
+ public static final boolean AUTOMATED_MODE = false;
+
+ /**
+ * Reserve room for this many list items.
+ */
+ private static final int LIST_ITEM_COUNT = 7;
+
+ /**
+ * The nesting indent.
+ */
+ private static final String NESTING_INDENT = " "; //$NON-NLS-1$
+
+ /**
+ * The Details button.
+ */
+ protected Button detailsButton;
+
+ /**
+ * The title of the dialog.
+ */
+ private String title;
+
+ /**
+ * The SWT list control that displays the error details.
+ */
+ private List list;
+
+ /**
+ * Indicates whether the error details viewer is currently created.
+ */
+ private boolean listCreated = false;
+
+ /**
+ * Filter mask for determining which status items to display.
+ */
+ private int displayMask = 0xFFFF;
+
+ /**
+ * The main status object.
+ */
+ private IStatus status;
+
+ /**
+ * The current clipboard. To be disposed when closing the dialog.
+ */
+ private Clipboard clipboard;
+
+ private boolean shouldIncludeTopLevelErrorInDetails = false;
+
+ /**
+ * Creates an error dialog. Note that the dialog will have no visual
+ * representation (no widgets) until it is told to open.
+ * <p>
+ * Normally one should use <code>openError</code> to create and open one
+ * of these. This constructor is useful only if the error object being
+ * displayed contains child items <it>and </it> you need to specify a mask
+ * which will be used to filter the displaying of these children.
+ * </p>
+ *
+ * @param parentShell
+ * the shell under which to create this dialog
+ * @param dialogTitle
+ * the title to use for this dialog, or <code>null</code> to
+ * indicate that the default title should be used
+ * @param message
+ * the message to show in this dialog, or <code>null</code> to
+ * indicate that the error's message should be shown as the
+ * primary message
+ * @param status
+ * the error to show to the user
+ * @param displayMask
+ * the mask to use to filter the displaying of child items, as
+ * per <code>IStatus.matches</code>
+ * @see org.eclipse.core.runtime.IStatus#matches(int)
+ */
+ public ErrorDialogNoReason(Shell parentShell, String dialogTitle,
+ String message, IStatus status, int displayMask) {
+ super(parentShell);
+ this.title = dialogTitle == null ? JFaceResources
+ .getString("Problem_Occurred") : //$NON-NLS-1$
+ dialogTitle;
+ this.message = message == null ? status.getMessage() : message;
+ this.status = status;
+ this.displayMask = displayMask;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog. Handles the pressing of the Ok
+ * or Details button in this dialog. If the Ok button was pressed then close
+ * this dialog. If the Details button was pressed then toggle the displaying
+ * of the error details area. Note that the Details button will only be
+ * visible if the error being displayed specifies child details.
+ */
+ protected void buttonPressed(int id) {
+ if (id == IDialogConstants.DETAILS_ID) {
+ // was the details button pressed?
+ toggleDetailsArea();
+ } else {
+ super.buttonPressed(id);
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared in Window.
+ */
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(title);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog.
+ */
+ protected void createButtonsForButtonBar(Composite parent) {
+ // create OK and Details buttons
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+ true);
+ createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+ if (shouldShowDetailsButton()) {
+ detailsButton = createButton(parent, IDialogConstants.DETAILS_ID,
+ IDialogConstants.SHOW_DETAILS_LABEL, false);
+ }
+ }
+
+ /**
+ * This implementation of the <code>Dialog</code> framework method creates
+ * and lays out a composite and calls <code>createMessageArea</code> and
+ * <code>createCustomArea</code> to populate it. Subclasses should
+ * override <code>createCustomArea</code> to add contents below the
+ * message.
+ */
+ protected Control createDialogArea(Composite parent) {
+ createMessageArea(parent);
+ // create a composite with standard margins and spacing
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+ GridData childData = new GridData(GridData.FILL_BOTH);
+ childData.horizontalSpan = 2;
+ composite.setLayoutData(childData);
+ composite.setFont(parent.getFont());
+ return composite;
+ }
+
+ /*
+ * @see IconAndMessageDialog#createDialogAndButtonArea(Composite)
+ */
+ protected void createDialogAndButtonArea(Composite parent) {
+ super.createDialogAndButtonArea(parent);
+ if (this.dialogArea instanceof Composite) {
+ // Create a label if there are no children to force a smaller layout
+ Composite dialogComposite = (Composite) dialogArea;
+ if (dialogComposite.getChildren().length == 0)
+ new Label(dialogComposite, SWT.NULL);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.dialogs.IconAndMessageDialog#getImage()
+ */
+ protected Image getImage() {
+ if (status != null) {
+ if (status.getSeverity() == IStatus.WARNING)
+ return getWarningImage();
+ if (status.getSeverity() == IStatus.INFO)
+ return getInfoImage();
+ }
+ // If it was not a warning or an error then return the error image
+ return getErrorImage();
+ }
+
+ /**
+ * Create this dialog's drop-down list component.
+ *
+ * @param parent
+ * the parent composite
+ * @return the drop-down list component
+ */
+ protected List createDropDownList(Composite parent) {
+ // create the list
+ list = new List(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
+ | SWT.MULTI);
+ // fill the list
+ populateList(list);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+ | GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL
+ | GridData.GRAB_VERTICAL);
+ data.heightHint = list.getItemHeight() * LIST_ITEM_COUNT;
+ data.horizontalSpan = 2;
+ list.setLayoutData(data);
+ list.setFont(parent.getFont());
+ Menu copyMenu = new Menu(list);
+ MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE);
+ copyItem.addSelectionListener(new SelectionListener() {
+ /*
+ * @see SelectionListener.widgetSelected (SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ copyToClipboard();
+ }
+
+ /*
+ * @see SelectionListener.widgetDefaultSelected(SelectionEvent)
+ */
+ public void widgetDefaultSelected(SelectionEvent e) {
+ copyToClipboard();
+ }
+ });
+ copyItem.setText(JFaceResources.getString("copy")); //$NON-NLS-1$
+ list.setMenu(copyMenu);
+ listCreated = true;
+ return list;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Window.
+ */
+ /**
+ * Extends <code>Window.open()</code>. Opens an error dialog to display
+ * the error. If you specified a mask to filter the displaying of these
+ * children, the error dialog will only be displayed if there is at least
+ * one child status matching the mask.
+ */
+ public int open() {
+ if (!AUTOMATED_MODE && shouldDisplay(status, displayMask)) {
+ return super.open();
+ }
+ setReturnCode(OK);
+ return OK;
+ }
+
+ /**
+ * Opens an error dialog to display the given error. Use this method if the
+ * error object being displayed does not contain child items, or if you wish
+ * to display all such items without filtering.
+ *
+ * @param parent
+ * the parent shell of the dialog, or <code>null</code> if none
+ * @param dialogTitle
+ * the title to use for this dialog, or <code>null</code> to
+ * indicate that the default title should be used
+ * @param message
+ * the message to show in this dialog, or <code>null</code> to
+ * indicate that the error's message should be shown as the
+ * primary message
+ * @param status
+ * the error to show to the user
+ * @return the code of the button that was pressed that resulted in this
+ * dialog closing. This will be <code>Dialog.OK</code> if the OK
+ * button was pressed, or <code>Dialog.CANCEL</code> if this
+ * dialog's close window decoration or the ESC key was used.
+ */
+ public static int openError(Shell parent, String dialogTitle,
+ String message, IStatus status) {
+ return openError(parent, dialogTitle, message, status, IStatus.OK
+ | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
+ }
+
+ /**
+ * Opens an error dialog to display the given error. Use this method if the
+ * error object being displayed contains child items <it>and </it> you wish
+ * to specify a mask which will be used to filter the displaying of these
+ * children. The error dialog will only be displayed if there is at least
+ * one child status matching the mask.
+ *
+ * @param parentShell
+ * the parent shell of the dialog, or <code>null</code> if none
+ * @param title
+ * the title to use for this dialog, or <code>null</code> to
+ * indicate that the default title should be used
+ * @param message
+ * the message to show in this dialog, or <code>null</code> to
+ * indicate that the error's message should be shown as the
+ * primary message
+ * @param status
+ * the error to show to the user
+ * @param displayMask
+ * the mask to use to filter the displaying of child items, as
+ * per <code>IStatus.matches</code>
+ * @return the code of the button that was pressed that resulted in this
+ * dialog closing. This will be <code>Dialog.OK</code> if the OK
+ * button was pressed, or <code>Dialog.CANCEL</code> if this
+ * dialog's close window decoration or the ESC key was used.
+ * @see org.eclipse.core.runtime.IStatus#matches(int)
+ */
+ public static int openError(Shell parentShell, String title,
+ String message, IStatus status, int displayMask) {
+ ErrorDialogNoReason dialog = new ErrorDialogNoReason(parentShell,
+ title, message, status, displayMask);
+ return dialog.open();
+ }
+
+ /**
+ * Populates the list using this error dialog's status object. This walks
+ * the child static of the status object and displays them in a list. The
+ * format for each entry is status_path : status_message If the status's
+ * path was null then it (and the colon) are omitted.
+ *
+ * @param listToPopulate
+ * The list to fill.
+ */
+ private void populateList(List listToPopulate) {
+ populateList(listToPopulate, status, 0,
+ shouldIncludeTopLevelErrorInDetails);
+ }
+
+ /**
+ * Populate the list with the messages from the given status. Traverse the
+ * children of the status deeply and also traverse CoreExceptions that
+ * appear in the status.
+ *
+ * @param listToPopulate
+ * the list to populate
+ * @param buildingStatus
+ * the status being displayed
+ * @param nesting
+ * the nesting level (increases one level for each level of
+ * children)
+ * @param includeStatus
+ * whether to include the buildingStatus in the display or just
+ * its children
+ */
+ private void populateList(List listToPopulate, IStatus buildingStatus,
+ int nesting, boolean includeStatus) {
+
+ if (!buildingStatus.matches(displayMask)) {
+ return;
+ }
+
+ Throwable t = buildingStatus.getException();
+ boolean isCoreException = t instanceof CoreException;
+ boolean incrementNesting = false;
+
+ if (includeStatus) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < nesting; i++) {
+ sb.append(NESTING_INDENT);
+ }
+ String message = buildingStatus.getMessage();
+ sb.append(message);
+ listToPopulate.add(sb.toString());
+ incrementNesting = true;
+ }
+
+ if (!isCoreException && t != null) {
+ // Include low-level exception message
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < nesting; i++) {
+ sb.append(NESTING_INDENT);
+ }
+ String message = t.getLocalizedMessage();
+ if (message == null)
+ message = t.toString();
+
+ sb.append(message);
+ listToPopulate.add(sb.toString());
+ incrementNesting = true;
+ }
+
+ if (incrementNesting)
+ nesting++;
+
+ // Look for a nested core exception
+ if (isCoreException) {
+ CoreException ce = (CoreException) t;
+ IStatus eStatus = ce.getStatus();
+ // Only print the exception message if it is not contained in the
+ // parent message
+ if (message == null || message.indexOf(eStatus.getMessage()) == -1) {
+ populateList(listToPopulate, eStatus, nesting, true);
+ }
+ }
+
+ // Look for child status
+ IStatus[] children = buildingStatus.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ populateList(listToPopulate, children[i], nesting, true);
+ }
+ }
+
+ /**
+ * Returns whether the given status object should be displayed.
+ *
+ * @param status
+ * a status object
+ * @param mask
+ * a mask as per <code>IStatus.matches</code>
+ * @return <code>true</code> if the given status should be displayed, and
+ * <code>false</code> otherwise
+ * @see org.eclipse.core.runtime.IStatus#matches(int)
+ */
+ protected static boolean shouldDisplay(IStatus status, int mask) {
+ IStatus[] children = status.getChildren();
+ if (children == null || children.length == 0) {
+ return status.matches(mask);
+ }
+ for (int i = 0; i < children.length; i++) {
+ if (children[i].matches(mask))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Toggles the unfolding of the details area. This is triggered by the user
+ * pressing the details button.
+ */
+ private void toggleDetailsArea() {
+ Point windowSize = getShell().getSize();
+ Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ if (listCreated) {
+ list.dispose();
+ listCreated = false;
+ detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
+ } else {
+ list = createDropDownList((Composite) getContents());
+ detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
+ }
+ Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ getShell()
+ .setSize(
+ new Point(windowSize.x, windowSize.y
+ + (newSize.y - oldSize.y)));
+ }
+
+ /**
+ * Put the details of the status of the error onto the stream.
+ *
+ * @param buildingStatus
+ * @param buffer
+ * @param nesting
+ */
+ private void populateCopyBuffer(IStatus buildingStatus,
+ StringBuffer buffer, int nesting) {
+ if (!buildingStatus.matches(displayMask)) {
+ return;
+ }
+ for (int i = 0; i < nesting; i++) {
+ buffer.append(NESTING_INDENT);
+ }
+ buffer.append(buildingStatus.getMessage());
+ buffer.append("\n"); //$NON-NLS-1$
+
+ // Look for a nested core exception
+ Throwable t = buildingStatus.getException();
+ if (t instanceof CoreException) {
+ CoreException ce = (CoreException) t;
+ populateCopyBuffer(ce.getStatus(), buffer, nesting + 1);
+ }
+
+ IStatus[] children = buildingStatus.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ populateCopyBuffer(children[i], buffer, nesting + 1);
+ }
+ }
+
+ /**
+ * Copy the contents of the statuses to the clipboard.
+ */
+ private void copyToClipboard() {
+ if (clipboard != null)
+ clipboard.dispose();
+ StringBuffer statusBuffer = new StringBuffer();
+ populateCopyBuffer(status, statusBuffer, 0);
+ clipboard = new Clipboard(list.getDisplay());
+ clipboard.setContents(new Object[] { statusBuffer.toString() },
+ new Transfer[] { TextTransfer.getInstance() });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.window.Window#close()
+ */
+ public boolean close() {
+ if (clipboard != null)
+ clipboard.dispose();
+ return super.close();
+ }
+
+ /**
+ * Show the details portion of the dialog if it is not already visible. This
+ * method will only work when it is invoked after the control of the dialog
+ * has been set. In other words, after the <code>createContents</code>
+ * method has been invoked and has returned the control for the content area
+ * of the dialog. Invoking the method before the content area has been set
+ * or after the dialog has been disposed will have no effect.
+ *
+ * @since 3.1
+ */
+ protected final void showDetailsArea() {
+ if (!listCreated) {
+ Control control = getContents();
+ if (control != null && !control.isDisposed())
+ toggleDetailsArea();
+ }
+ }
+
+ /**
+ * Return whether the Details button should be included. This method is
+ * invoked once when the dialog is built. By default, the Details button is
+ * only included if the status used when creating the dialog was a
+ * multi-status or if the status contains an exception. Subclasses may
+ * override.
+ *
+ * @return whether the Details button should be included
+ * @since 3.1
+ */
+ protected boolean shouldShowDetailsButton() {
+ return status.isMultiStatus() || status.getException() != null;
+ }
+
+ /**
+ * Set the status displayed by this error dialog to the given status. This
+ * only affects the status displayed by the Details list. The message, image
+ * and title should be updated by the subclass, if desired.
+ *
+ * @param status
+ * the status to be displayed in the details list
+ * @since 3.1
+ */
+ protected final void setStatus(IStatus status) {
+ if (this.status != status) {
+ this.status = status;
+ }
+ shouldIncludeTopLevelErrorInDetails = true;
+ if (listCreated) {
+ repopulateList();
+ }
+ }
+
+ /**
+ * Repopulate the supplied list widget.
+ */
+ private void repopulateList() {
+ if (list != null && !list.isDisposed()) {
+ list.removeAll();
+ populateList(list);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java
new file mode 100644
index 00000000000..52a828d1e80
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * A helper class for retrieving Eclipse menus.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class MenuUtil {
+
+ /**
+ * Searches an array of menu items and returns the menu item that matches
+ * the given menu text.
+ *
+ * @param menuItems
+ * An array of menu items.
+ * @param text
+ * The text to look for.
+ * @return The menu item if found, <code>null</code> otherwise.
+ */
+ public static MenuItem getMenuItem(MenuItem[] menuItems, String text) {
+ if (menuItems == null || text == null || text.length() == 0) {
+ return null;
+ }
+
+ for (int i = 0; i < menuItems.length; i++) {
+ if (menuItems[i].getText().startsWith(text)) {
+ return menuItems[i];
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java
new file mode 100644
index 00000000000..1d97b41167a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java
@@ -0,0 +1,123 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Helper class to display a message box.
+ *
+ * @author Phong Nguyen Le
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public final class MsgBox {
+ /**
+ * Use this method to show error message if you don't want long path to be
+ * cut off.
+ *
+ * @param msg
+ */
+ public static final void nativeShowError(Shell shell, String msg) {
+ if (shell == null) {
+ shell = getDefaultShell();
+ if (shell == null) {
+ return;
+ }
+ }
+ MessageBox msgBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+ msgBox.setMessage(msg);
+ msgBox.setText(shell.getText());
+ msgBox.open();
+ }
+
+ public static final void showError(String msg) {
+ showError(getDefaultShell(), msg);
+ }
+
+ public static final void showError(Shell shell, String msg) {
+ WrappedMessageDialog.openError(shell, shell == null ? null : shell
+ .getText(), msg);
+ }
+
+ public static final void showWarning(String msg) {
+ showWarning(getDefaultShell(), msg);
+ }
+
+ public static final void showWarning(Shell shell, String msg) {
+ WrappedMessageDialog.openWarning(shell, shell == null ? null : shell
+ .getText(), msg);
+ }
+
+ public static final Shell getDefaultShell() {
+ try {
+ Display d = Display.getCurrent();
+ if (d == null) {
+ d = Display.getDefault();
+ }
+
+ Shell s = null;
+ if (d != null) {
+ s = d.getActiveShell();
+ }
+
+ return s;
+ } catch (RuntimeException e) {
+ return null;
+ }
+ }
+
+ public static final Display getDisplay() {
+ try {
+ Display d = Display.getCurrent();
+ if (d == null) {
+ d = Display.getDefault();
+ }
+
+ return d;
+ } catch (RuntimeException e) {
+ return null;
+ }
+ }
+
+ public static final int prompt(String msg) {
+ return prompt(getDefaultShell(), msg);
+ }
+
+ public static final int prompt(Shell shell, String msg) {
+ return prompt(shell, null, msg, SWT.YES | SWT.NO | SWT.CANCEL);
+ }
+
+ public static final int prompt(String msg, int buttons) {
+ return prompt(getDefaultShell(), null, msg, buttons);
+ }
+
+ public static final int prompt(String title, String msg, int buttons) {
+ return prompt(getDefaultShell(), title, msg, buttons);
+ }
+
+ public static final int prompt(Shell shell, String msg, int buttons) {
+ return prompt(shell, null, msg, buttons);
+ }
+
+ public static final int prompt(Shell shell, String title, String msg,
+ int buttons) {
+ MessageBox msgBox = new MessageBox(shell, buttons | SWT.ICON_QUESTION);
+ msgBox.setText(title != null && title.length() > 0 ? title : shell
+ .getText());
+ msgBox.setMessage(msg);
+ return msgBox.open();
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java
new file mode 100644
index 00000000000..e681d33a19d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java
@@ -0,0 +1,626 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.epf.common.IActivator;
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A message dialog used for displaying error, warning, confirmation or
+ * informational messages.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @author Phong Nguyen Le
+ * @since 1.0
+ */
+public class MsgDialog {
+
+ // The plug-in ID.
+ private String pluginId;
+
+ // The plug-in logger.
+ private Logger logger;
+
+ /**
+ * Create a new instance given the plug-in instance.
+ *
+ * @param plugin
+ * The plugin instance.
+ */
+ public MsgDialog(IActivator plugin) {
+ this.pluginId = plugin.getId();
+ this.logger = plugin.getLogger();
+ }
+
+ protected Shell getShell() {
+ return PlatformUI.getWorkbench().getDisplay().getActiveShell();
+ }
+
+ /**
+ * Displays the given error message in an error dialog without the error
+ * reason and Details button.
+ * <p>
+ * Note: The error message will be written to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ */
+ public void displayError(String title, String msg) {
+ display(IStatus.ERROR, title, msg, null, null, null);
+ }
+
+ /**
+ * Displays the given error message in an error dialog without the error
+ * reason and Details button.
+ * <p>
+ * Note: The error message and the exception stack trace will be written to
+ * the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param ex
+ * The exception associated with the error.
+ */
+ public void displayError(String title, String msg, Throwable ex) {
+ display(IStatus.ERROR, title, msg, null, null, ex);
+ }
+
+ /**
+ * Displays the given error message in an error dialog without the Details
+ * button.
+ * <p>
+ * Note: The error message will be written to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param reason
+ * The reason for the error.
+ */
+ public void displayError(String title, String msg, String reason) {
+ display(IStatus.ERROR, title, msg, reason, null, null);
+ }
+
+ /**
+ * Displays the given error message in an error dialog without the Details
+ * button.
+ * <p>
+ * Note: The error message and the exception stack trace will be written to
+ * the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param reason
+ * The reason for the error.
+ * @param ex
+ * The exception associated with the error.
+ */
+ public void displayError(String title, String msg, String reason,
+ Throwable ex) {
+ display(IStatus.ERROR, title, msg, reason, null, ex);
+ }
+
+ /**
+ * Displays the given error message in an error dialog. The Details button
+ * will be displayed if the <code>details</code> parameter it not null or
+ * empty.
+ * <p>
+ * Note: The error message will be written to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param reason
+ * The reason for the error.
+ * @param details
+ * The error details.
+ */
+ public void displayError(String title, String msg, String reason,
+ String details) {
+ display(IStatus.ERROR, title, msg, reason, details, null);
+ }
+
+ /**
+ * Displays the given error message in an error dialog. The Details button
+ * will be displayed if the <code>details</code> parameter it not null or
+ * empty.
+ * <p>
+ * Note: The error message and the exception stack trace will be written to
+ * the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param reason
+ * The reason for the error.
+ * @param details
+ * The error details.
+ * @param ex
+ * The exception associated with the error.
+ */
+ public void displayError(String title, String msg, String reason,
+ String details, Throwable ex) {
+ display(IStatus.ERROR, title, msg, reason, details, ex);
+ }
+
+ /**
+ * Displays the given error status in an error dialog.
+ * <p>
+ * Note: The error message and the exception stack trace will be written to
+ * the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param status
+ * The error status.
+ */
+ public int displayError(String title, IStatus status) {
+ return display(title, null, status);
+ }
+
+ /**
+ * Displays the given error status in an error dialog.
+ * <p>
+ * Note: The error message and the exception stack trace will be written to
+ * the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param status
+ * The error status.
+ */
+ public int displayError(String title, String msg, IStatus status) {
+ return display(title, msg, status);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog without the
+ * warning reason and Details button.
+ * <p>
+ * Note: The waning message will be written to the log file.
+ *
+ * @param title
+ * The title for the warning dialog.
+ * @param msg
+ * The warning message.
+ */
+ public void displayWarning(String title, String msg) {
+ display(IStatus.WARNING, title, msg, null, null, null);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog without the
+ * warning reason and Details button.
+ * <p>
+ * Note: The warning message and the exception stack trace will be written
+ * to the log file.
+ *
+ * @param title
+ * The title for the warning dialog.
+ * @param msg
+ * The warning message.
+ * @param ex
+ * The exception associated with the warning.
+ */
+ public void displayWarning(String title, String msg, Throwable ex) {
+ display(IStatus.WARNING, title, msg, null, null, ex);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog without the
+ * warning reason and Details button.
+ * <p>
+ * Note: The waning message will be written to the log file.
+ *
+ * @param title
+ * The title for the warning dialog.
+ * @param msg
+ * The warning message.
+ * @param reason
+ * The reason for the warning.
+ */
+ public void displayWarning(String title, String msg, String reason) {
+ display(IStatus.WARNING, title, msg, reason, null, null);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog without the
+ * warning reason and Details button.
+ * <p>
+ * Note: The warning message and the exception stack trace will be written
+ * to the log file.
+ *
+ * @param title
+ * The title for the warning dialog.
+ * @param msg
+ * The warning message.
+ * @param reason
+ * The reason for the warning.
+ * @param ex
+ * The exception associated with the warning.
+ */
+ public void displayWarning(String title, String msg, String reason,
+ Throwable ex) {
+ display(IStatus.WARNING, title, msg, reason, null, ex);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog. The Details
+ * button will be displayed if the <code>details</code> parameter it not
+ * null or empty.
+ * <p>
+ * Note: The waning message will be written to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The warning message.
+ * @param reason
+ * The reason for the warning.
+ * @param details
+ * The warning details.
+ */
+ public void displayWarning(String title, String msg, String reason,
+ String details) {
+ display(IStatus.WARNING, title, msg, reason, details, null);
+ }
+
+ /**
+ * Displays the given warning message in a warning dialog. The Details
+ * button will be displayed if the <code>details</code> parameter it not
+ * null or empty.
+ * <p>
+ * Note: The warning message and the exception stack trace will be written
+ * to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The warning message.
+ * @param reason
+ * The reason for the warning.
+ * @param details
+ * The warning details.
+ * @param ex
+ * The exception associated with the warning.
+ */
+ public void displayWarning(String title, String msg, String reason,
+ String details, Throwable ex) {
+ display(IStatus.WARNING, title, msg, reason, details, ex);
+ }
+
+ /**
+ * Displays the given warning status in an error dialog.
+ * <p>
+ * Note: The warning message and the exception stack trace will be written
+ * to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param status
+ * The error status.
+ */
+ public void displayWarning(String title, IStatus status) {
+ display(title, null, status);
+ }
+
+ /**
+ * Displays the given warning status in an error dialog.
+ * <p>
+ * Note: The warning message and the exception stack trace will be written
+ * to the log file.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param status
+ * The error status.
+ */
+ public void displayWarning(String title, String msg, IStatus status) {
+ display(title, msg, status);
+ }
+
+ /**
+ * Displays the given error or warning message in an error or warning
+ * dialog. The Details button will be displayed if the <code>details</code>
+ * parameter it not null or empty.
+ *
+ * @param severity
+ * The severity, either IStatus.ERROR or IStatus.WARNING.
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param reason
+ * The reason for the error.
+ * @param details
+ * The error details.
+ * @param ex
+ * The exception associated with the error.
+ */
+ public synchronized void display(int severity, String title, String msg,
+ String reason, String details, Throwable ex) {
+ if (msg == null && ex != null) {
+ msg = ex.getMessage();
+ }
+
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
+ logger.logMsg(severity, msg, ex);
+ } else {
+ throw new IllegalArgumentException(
+ "severity argument must be IStatus.ERROR or IStatus.WARNING"); //$NON-NLS-1$
+ }
+
+ Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
+ .getDefaultImage();
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ ErrorDialog.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+
+ if (details != null && details.length() > 0) {
+ MultiStatus mStatus = new MultiStatus(pluginId, IStatus.OK, reason,
+ ex);
+ Status status = new Status(severity, pluginId, IStatus.OK, details,
+ ex);
+ mStatus.add(status);
+ org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
+ mStatus);
+ } else if (reason != null && reason.length() > 0) {
+ Status status = new Status(severity, pluginId, IStatus.OK, reason,
+ ex);
+ org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
+ status);
+ } else {
+ if (severity == IStatus.ERROR) {
+ WrappedMessageDialog.openError(shell, title, msg);
+ } else if (severity == IStatus.WARNING) {
+ WrappedMessageDialog.openWarning(shell, title, msg);
+ }
+ }
+
+ if (shellImage != null) {
+ ErrorDialog.setDefaultImage(oldImage);
+ }
+ }
+
+ /**
+ * Displays the given error or warning message in an error or warning
+ * dialog. The Details button will be displayed if the <code>details</code>
+ * parameter it not null or empty.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param status
+ * The error status.
+ */
+ public synchronized int display(String title, IStatus status) {
+ return display(title, null, status);
+ }
+
+ /**
+ * Displays the given error or warning message in an error or warning
+ * dialog. The Details button will be displayed if the <code>details</code>
+ * parameter it not null or empty.
+ *
+ * @param title
+ * The title for the error dialog.
+ * @param msg
+ * The error message.
+ * @param status
+ * The error status.
+ */
+ public synchronized int display(String title, String msg, IStatus status) {
+ if (status == null) {
+ throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
+ }
+
+ if (msg == null) {
+ msg = status.getMessage();
+ }
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ int severity = status.getSeverity();
+ if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
+ logger.logMsg(severity, msg, status.getException());
+ }
+
+ Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
+ .getDefaultImage();
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ ErrorDialog.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+
+ int rc = org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title,
+ msg, status);
+
+ if (shellImage != null) {
+ ErrorDialog.setDefaultImage(oldImage);
+ }
+
+ return rc;
+ }
+
+ /**
+ * Displays the given message in a informational dialog with an "OK" button.
+ *
+ * @param title
+ * The title for the information dialog.
+ * @param msg
+ * The message to display.
+ */
+ public void displayInfo(String title, String msg) {
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ Image oldImage = WrappedMessageDialog.getDefaultImage();
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+ WrappedMessageDialog.openInformation(shell, title, msg);
+
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(oldImage);
+ }
+ }
+
+ /**
+ * Displays the given message in a question dialog with a "Yes" and "No"
+ * button.
+ *
+ * @param title
+ * The title for the information dialog.
+ * @param msg
+ * The message to display.
+ */
+ public boolean displayPrompt(String title, String msg) {
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ Image oldImage = WrappedMessageDialog.getDefaultImage();
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+ boolean result = WrappedMessageDialog.openQuestion(shell, title, msg);
+
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(oldImage);
+ }
+
+ return result;
+ }
+
+ /**
+ * Displays the given message in a confirmation dialog with a "Yes" and
+ * "Cancel" button.
+ *
+ * @param title
+ * The title for the information dialog.
+ * @param msg
+ * The message to display.
+ */
+ public boolean displayConfirmation(String title, String msg) {
+ return displayConfirmationWithCheckBox(title, msg, null) > 0;
+ }
+
+ //return: 0 = cancel, 1 = ok with check-box checked, 2 = ok with check box unchecked
+ public int displayConfirmationWithCheckBox(String title, String msg, String checkBoxLabel) {
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ Image oldImage = WrappedMessageDialog.getDefaultImage();
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+
+ if (shellImage != null) {
+ WrappedMessageDialog.setDefaultImage(oldImage);
+ }
+
+ if (checkBoxLabel == null) {
+ boolean b = WrappedMessageDialog.openConfirm(shell, title, msg);
+ return b ? 1 : 0;
+ }
+
+ return WrappedMessageDialog.openConfirmWithCheckBox(shell, title, msg, checkBoxLabel);
+ }
+
+ public int displayConfirmation(String title, String msg, IStatus status) {
+ if (status == null) {
+ throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
+ }
+
+ if (msg == null) {
+ msg = status.getMessage();
+ }
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ Image shellImage = getShellImage();
+ if (shellImage != null) {
+ ErrorDialogNoReason.setDefaultImage(shellImage);
+ }
+
+ Shell shell = getShell();
+
+ int rc = ErrorDialogNoReason.openError(shell, title, msg, status);
+
+ return rc;
+
+ }
+
+ /**
+ * Returns the image for the current shell.
+ *
+ * @return The current shell image.
+ */
+ private Image getShellImage() {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ if (workbench != null) {
+ IWorkbenchWindow workbenchWindow = workbench
+ .getActiveWorkbenchWindow();
+ if (workbenchWindow != null) {
+ Shell shell = workbenchWindow.getShell();
+ if (shell != null) {
+ return shell.getImage();
+ }
+ }
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java
new file mode 100644
index 00000000000..a928ec798c8
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java
@@ -0,0 +1,127 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+
+/**
+ * Utility class for accessing perspectives.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class PerspectiveUtil {
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private PerspectiveUtil() {
+ }
+
+ /**
+ * Returns the ID of the active perspective.
+ *
+ * @return The active perspective ID.
+ */
+ public static String getActivePerspectiveId() {
+ if (PlatformUI.getWorkbench() == null || PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow() == null) {
+ return null;
+ }
+
+ IWorkbenchPage activePage = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ if (activePage != null) {
+ IPerspectiveDescriptor activePerspective = activePage
+ .getPerspective();
+ return activePerspective.getId();
+ }
+ return null;
+ }
+
+ /**
+ * Opens a perspective.
+ *
+ * @param perspectiveId
+ * The perspective ID.
+ * @return The previously active perspective.
+ */
+ public static IPerspectiveDescriptor openPerspective(String perspectiveId) {
+ IWorkbenchPage activePage = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ if (activePage != null) {
+ IPerspectiveRegistry registry = PlatformUI.getWorkbench()
+ .getPerspectiveRegistry();
+ IPerspectiveDescriptor oldPerspective = activePage.getPerspective();
+ if (!oldPerspective.getId().equals(perspectiveId)) {
+ IPerspectiveDescriptor perspective = registry
+ .findPerspectiveWithId(perspectiveId);
+ activePage.setPerspective(perspective);
+ }
+ return oldPerspective;
+ } else {
+ IWorkbenchWindow activeWindow = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow();
+ try {
+ PlatformUI.getWorkbench().showPerspective(
+ perspectiveId, activeWindow);
+ } catch (WorkbenchException e) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the given perspective is already active.
+ *
+ * @param perspectiveId
+ * The perspective ID.
+ * @return
+ */
+ public static boolean isActivePerspective(String perspectiveId) {
+ String activePerspectiveId = PerspectiveUtil.getActivePerspectiveId();
+ if (perspectiveId == null || activePerspectiveId == null) {
+ return false;
+ }
+ return activePerspectiveId.equalsIgnoreCase(perspectiveId);
+ }
+
+ /**
+ * Returns the view part with the given view ID.
+ *
+ * @param viewId
+ * The view ID.
+ * @return The view part.
+ */
+ public static IViewPart getView(String viewId) {
+ try {
+ IWorkbenchPage activePage = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ if (activePage != null) {
+ IViewPart view = activePage.findView(viewId);
+ if (view == null) {
+ view = activePage.showView(viewId);
+ }
+ return view;
+ }
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java
new file mode 100644
index 00000000000..158d7d882ec
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java
@@ -0,0 +1,173 @@
+//------------------------------------------------------------------------------
+// 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.common.ui.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Utility class for accessing preferences.
+ *
+ * @author Kelvin Low
+ * @since 1.2
+ */
+public class PreferenceUtil {
+
+ // The multi-string preference delimiter.
+ private static final String PREFERENCE_DELIMITER = ";"; //$NON-NLS-1$
+
+ /**
+ * Gets a list containing string values associated with a named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @return a list of string values
+ */
+ public static List<String> getList(IPreferenceStore prefStore, String name) {
+ List<String> values = new ArrayList<String>();
+ if (prefStore != null && name != null) {
+ String value = prefStore.getString(name);
+ StringTokenizer tokenizer = new StringTokenizer(value,
+ PREFERENCE_DELIMITER);
+ int tokenCount = tokenizer.countTokens();
+ for (int i = 0; i < tokenCount; i++) {
+ values.add(tokenizer.nextToken());
+ }
+ }
+ return values;
+ }
+
+ /**
+ * Gets the string values associated with a named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @return a list of string preference values
+ */
+ public static String[] getStringValues(IPreferenceStore prefStore,
+ String name) {
+ List<String> list = getList(prefStore, name);
+ String[] values = new String[list.size()];
+ list.toArray(values);
+ return values;
+ }
+
+ /**
+ * Saves a list containing string values associated with a named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @param values
+ * a list of string values
+ */
+ public static void setList(IPreferenceStore prefStore, String name,
+ List values) {
+ if (prefStore != null && name != null && values != null) {
+ StringBuffer buffer = new StringBuffer();
+ for (Iterator it = values.iterator(); it.hasNext();) {
+ String value = (String) it.next();
+ buffer.append(value);
+ buffer.append(PREFERENCE_DELIMITER);
+ }
+ prefStore.setValue(name, buffer.toString());
+ }
+ }
+
+ /**
+ * Adds a string value to a list containing string values associated with a
+ * named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @param value
+ * a string value
+ * @param defaultValue
+ * a default string value that will be added to the end of the
+ * list
+ */
+ public static void addToList(IPreferenceStore prefStore, String name,
+ String value, String defaultValue) {
+ if (prefStore != null && name != null && value != null) {
+ List<String> list = getList(prefStore, name);
+ list.remove(value);
+ list.add(0, value);
+
+ //adjust the list according to the history size
+ int preferenceHistorySize = CommonPreferences.getPreferenceHistorySize();
+ if (list.size() > preferenceHistorySize) {
+ list = list.subList(0, preferenceHistorySize - 1);
+ }
+ if (defaultValue != null && defaultValue.length() > 0) {
+ if (!list.contains(defaultValue)) {
+ if (list.size() == preferenceHistorySize) {
+ list.add(list.size() - 1, defaultValue);
+ } else {
+ list.add(defaultValue);
+ }
+ }
+ }
+
+ setList(prefStore, name, list);
+ }
+ }
+
+ /**
+ * Adds a string value to a list containing string values associated with a
+ * named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @param value
+ * a string value
+ */
+ public static void addToList(IPreferenceStore prefStore, String name,
+ String value) {
+ addToList(prefStore, name, value, null);
+ }
+
+ /**
+ * Saves an array of string values associated with a named preference.
+ *
+ * @param prefStore
+ * a preference store
+ * @param name
+ * the preference name
+ * @param values
+ * an array of string values
+ */
+ public static void setStringValues(IPreferenceStore prefStore, String name,
+ String[] values) {
+ if (prefStore != null && name != null && values != null) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < values.length; i++) {
+ buffer.append(values[i]);
+ buffer.append(PREFERENCE_DELIMITER);
+ }
+ prefStore.setValue(name, buffer.toString());
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java
new file mode 100644
index 00000000000..926cc5ad791
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java
@@ -0,0 +1,208 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.ui.util;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Displays a message dialog that displays wrapped text.
+ *
+ * @author Bingxue Xu
+ * @since 1.0
+ */
+public class WrappedMessageDialog extends MessageDialog {
+
+ public WrappedMessageDialog(Shell parentShell, String dialogTitle,
+ Image dialogTitleImage, String dialogMessage, int dialogImageType,
+ String[] dialogButtonLabels, int defaultIndex) {
+ super(parentShell, dialogTitle, dialogTitleImage, dialogMessage,
+ dialogImageType, dialogButtonLabels, defaultIndex);
+ }
+
+ protected Control createMessageArea(Composite composite) {
+
+ Control rComposite = super.createMessageArea(composite);
+
+ int minWidth = IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH;// + 300;
+ // TO-DO: need to revist the # of dialog display units and margin
+ // when in other languages
+ int charsPerLine = minWidth / 4 - 15;
+ GridData gd = (GridData) messageLabel.getLayoutData();
+ gd.minimumWidth = minWidth;
+ messageLabel.setText(addLineBreaks(message, charsPerLine));
+
+ return rComposite;
+ }
+
+ String addLineBreaks(String msg, int maxChars) {
+ // System.out.println("$$$ DEBUG: original message = " + msg);
+
+ if (msg == null)
+ return null;
+
+ StringBuffer strBuf = new StringBuffer();
+ int count = 0;
+ for (int i = 0; i < msg.length(); i++) {
+ strBuf.append(msg.charAt(i));
+ if (Character.isWhitespace(msg.charAt(i)))
+ count = 0;
+ else
+ count++;
+
+ if (count >= maxChars) {
+ if (!Character.isWhitespace(msg.charAt(i))) {
+ strBuf.append("\n"); //$NON-NLS-1$
+ }
+ count = 0;
+ }
+ }
+
+ // System.out.println("$$$ DEBUG: broken message = " +
+ // strBuf.toString());
+ return strBuf.toString();
+ }
+
+ public static boolean openConfirm(Shell parent, String title, String message) {
+ WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, QUESTION, new String[] { IDialogConstants.OK_LABEL,
+ IDialogConstants.CANCEL_LABEL }, 0); // OK is the
+ // default
+ return dialog.open() == 0;
+ }
+
+ static class ConfirmWithCheckBoxDialog extends WrappedMessageDialog {
+ private String checkBoxLabel;
+ private Button checkBox;
+ private boolean checkBoxChecked = false;
+
+ public ConfirmWithCheckBoxDialog(Shell parentShell, String dialogTitle,
+ Image dialogTitleImage, String dialogMessage, int dialogImageType,
+ String[] dialogButtonLabels, int defaultIndex, String checkBoxLabel) {
+ super(parentShell, dialogTitle, dialogTitleImage, dialogMessage,
+ dialogImageType, dialogButtonLabels, defaultIndex);
+ this.checkBoxLabel = checkBoxLabel;
+ }
+
+ @Override
+ protected Control createMessageArea(Composite composite) {
+ Control rComposite = super.createMessageArea(composite);
+
+ checkBox = new Button(composite, SWT.CHECK);
+ checkBox.setText(checkBoxLabel);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 3;
+ checkBox.setLayoutData(gd);
+
+ return rComposite;
+ }
+
+ protected void buttonPressed(int buttonId) {
+ checkBoxChecked = checkBox.getSelection();
+ super.buttonPressed(buttonId);
+ }
+
+ public boolean isCheckBoxChecked() {
+ return checkBoxChecked;
+ }
+
+ }
+
+ //return: 0 = cancel, 1 = ok with check-box checked, 2 = ok with check box unchecked
+ public static int openConfirmWithCheckBox(Shell parent, String title, String message, String checkBoxLabel) {
+ ConfirmWithCheckBoxDialog dialog = new ConfirmWithCheckBoxDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, QUESTION, new String[] { IDialogConstants.OK_LABEL,
+ IDialogConstants.CANCEL_LABEL }, 0, checkBoxLabel); // OK is the default
+
+ int ix = dialog.open() ;
+ if (ix != 0) {
+ return 0;
+ }
+
+ return dialog.isCheckBoxChecked() ? 1 : 2;
+ }
+
+ public static void openError(Shell parent, String title, String message) {
+ WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, ERROR, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+ // is
+ // the
+ // default
+ dialog.open();
+ return;
+ }
+
+ public static void openInformation(Shell parent, String title,
+ String message) {
+ WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, INFORMATION,
+ new String[] { IDialogConstants.OK_LABEL }, 0);
+ // ok is the default
+ dialog.open();
+ return;
+ }
+
+ public static boolean openQuestion(Shell parent, String title,
+ String message) {
+ WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, QUESTION, new String[] { IDialogConstants.YES_LABEL,
+ IDialogConstants.NO_LABEL }, 0); // yes is the
+ // default
+ return dialog.open() == 0;
+ }
+
+ public static void openWarning(Shell parent, String title, String message) {
+ WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+ null, // accept
+ // the
+ // default
+ // window
+ // icon
+ message, WARNING, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+ // is
+ // the
+ // default
+ dialog.open();
+ return;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.classpath
new file mode 100644
index 00000000000..02159672985
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.project b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.project
new file mode 100644
index 00000000000..e57f6e3d952
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.common.win32.win32.x86</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..4c8e398d5f9
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.common.win32.win32.x86
+Bundle-Version: 1.5.0.qualifier
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.swt
+Bundle-Vendor: %providerName
+Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86))
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/about.html b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/build.properties
new file mode 100644
index 00000000000..ebe02751cbb
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ about.html
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/plugin.properties
new file mode 100644
index 00000000000..ff010d4c880
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/plugin.properties
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Win32 Common x86
+providerName=Eclipse.org
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java
new file mode 100644
index 00000000000..1a58b1dd316
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.win32;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.FORMATETC;
+import org.eclipse.swt.internal.ole.win32.IDataObject;
+import org.eclipse.swt.internal.ole.win32.STGMEDIUM;
+import org.eclipse.swt.internal.win32.OS;
+
+/**
+ * The class <code>HTMLTransfer</code> provides a platform specific mechanism
+ * for converting text in HTML format represented as a java <code>String</code>
+ * to a platform specific representation of the data and vice versa. See
+ * <code>Transfer</code> for additional information.
+ *
+ * <p>
+ * An example of a java <code>String</code> containing HTML text is shown
+ * below:
+ * </p>
+ *
+ * <code><pre>
+ * String htmlData = &quot;
+ * <p>
+ * This is a paragraph of text.
+ * </p>
+ * &quot;;
+ * </code></pre>
+ */
+public class Win32HTMLTransfer extends ByteArrayTransfer {
+
+ static Win32HTMLTransfer _instance = new Win32HTMLTransfer();
+
+ static final String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+
+ static final int HTML_FORMATID = registerType(HTML_FORMAT);
+
+ static final String NUMBER = "00000000"; //$NON-NLS-1$
+
+ static final String HEADER = "Version:0.9\r\nStartHTML:" + NUMBER //$NON-NLS-1$
+ + "\r\nEndHTML:" + NUMBER + "\r\nStartFragment:" + NUMBER //$NON-NLS-1$ //$NON-NLS-2$
+ + "\r\nEndFragment:" + NUMBER + "\r\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ static final String PREFIX = "<html><body><!--StartFragment-->"; //$NON-NLS-1$
+
+ static final String SUFFIX = "<!--EndFragment--></body></html>"; //$NON-NLS-1$
+
+ static final String StartFragment = "StartFragment:"; //$NON-NLS-1$
+
+ static final String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+ public Win32HTMLTransfer() {
+ }
+
+ /**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+ public static Win32HTMLTransfer getInstance() {
+ return _instance;
+ }
+
+ /**
+ * This implementation of <code>javaToNative</code> converts
+ * HTML-formatted text represented by a java <code>String</code> to a
+ * platform specific representation. For additional information see
+ * <code>Transfer#javaToNative</code>.
+ *
+ * @param object
+ * a java <code>String</code> containing HTML text
+ * @param transferData
+ * an empty <code>TransferData</code> object; this object will
+ * be filled in on return with the platform specific format of
+ * the data
+ */
+ public void javaToNative(Object object, TransferData transferData) {
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String string = (String) object;
+ int count = string.length();
+ char[] chars = new char[count + 1];
+ string.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null,
+ 0, null, null);
+ if (cchMultiByte == 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int startHTML = HEADER.length();
+ int startFragment = startHTML + PREFIX.length();
+ int endFragment = startFragment + cchMultiByte - 1;
+ int endHTML = endFragment + SUFFIX.length();
+
+ StringBuffer buffer = new StringBuffer(HEADER);
+ int maxLength = NUMBER.length();
+ // startHTML
+ int start = buffer.toString().indexOf(NUMBER);
+ String temp = Integer.toString(startHTML);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // endHTML
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endHTML);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // startFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(startFragment);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // endFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endFragment);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+
+ buffer.append(PREFIX);
+ buffer.append(string);
+ buffer.append(SUFFIX);
+
+ count = buffer.length();
+ chars = new char[count + 1];
+ buffer.getChars(0, count, chars, 0);
+ cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0,
+ null, null);
+ int lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT,
+ cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr,
+ cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ return;
+ }
+
+ /**
+ * This implementation of <code>nativeToJava</code> converts a platform
+ * specific representation of HTML text to a java <code>String</code>.
+ * For additional information see <code>Transfer#nativeToJava</code>.
+ *
+ * @param transferData
+ * the platform specific representation of the data to be been
+ * converted
+ * @return a java <code>String</code> containing HTML text if the
+ * conversion was successful; otherwise null
+ */
+ public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject == 0)
+ return null;
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ FORMATETC formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result != COM.S_OK)
+ return null;
+ int hMem = stgmedium.unionField;
+
+ try {
+ int lpMultiByteStr = OS.GlobalLock(hMem);
+ if (lpMultiByteStr == 0)
+ return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar(codePage,
+ OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar == 0)
+ return null;
+ char[] lpWideCharStr = new char[cchWideChar - 1];
+ OS
+ .MultiByteToWideChar(codePage, OS.MB_PRECOMPOSED,
+ lpMultiByteStr, -1, lpWideCharStr,
+ lpWideCharStr.length);
+ return new String(lpWideCharStr);
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+ }
+
+ protected int[] getTypeIds() {
+ return new int[] { HTML_FORMATID };
+ }
+
+ protected String[] getTypeNames() {
+ return new String[] { HTML_FORMAT };
+ }
+
+ boolean checkHTML(Object object) {
+ return (object != null && object instanceof String && ((String) object)
+ .length() > 0);
+ }
+
+ protected boolean validate(Object object) {
+ return checkHTML(object);
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/package.html
new file mode 100644
index 00000000000..2d697e1a095
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86/src/org/eclipse/epf/common/win32/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides windows-specific clipboard transfer services.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.classpath
new file mode 100644
index 00000000000..02159672985
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.project b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.project
new file mode 100644
index 00000000000..0801e35e8a0
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.common.win32.win32.x86_64</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..830ab37eddc
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.common.win32.win32.x86_64
+Bundle-Version: 1.5.0.qualifier
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.swt
+Bundle-Vendor: %providerName
+Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64))
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/about.html b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/build.properties
new file mode 100644
index 00000000000..ebe02751cbb
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ about.html
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/plugin.properties
new file mode 100644
index 00000000000..0992ed99e31
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/plugin.properties
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Win32 Common x86_64
+providerName=Eclipse.org
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java
new file mode 100644
index 00000000000..a5d8162ba96
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/Win32HTMLTransfer.java
@@ -0,0 +1,218 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.win32;
+
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.internal.ole.win32.COM;
+import org.eclipse.swt.internal.ole.win32.FORMATETC;
+import org.eclipse.swt.internal.ole.win32.IDataObject;
+import org.eclipse.swt.internal.ole.win32.STGMEDIUM;
+import org.eclipse.swt.internal.win32.OS;
+
+/**
+ * The class <code>HTMLTransfer</code> provides a platform specific mechanism
+ * for converting text in HTML format represented as a java <code>String</code>
+ * to a platform specific representation of the data and vice versa. See
+ * <code>Transfer</code> for additional information.
+ *
+ * <p>
+ * An example of a java <code>String</code> containing HTML text is shown
+ * below:
+ * </p>
+ *
+ * <code><pre>
+ * String htmlData = &quot;
+ * <p>
+ * This is a paragraph of text.
+ * </p>
+ * &quot;;
+ * </code></pre>
+ */
+public class Win32HTMLTransfer extends ByteArrayTransfer {
+
+ static Win32HTMLTransfer _instance = new Win32HTMLTransfer();
+
+ static final String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+
+ static final int HTML_FORMATID = registerType(HTML_FORMAT);
+
+ static final String NUMBER = "00000000"; //$NON-NLS-1$
+
+ static final String HEADER = "Version:0.9\r\nStartHTML:" + NUMBER //$NON-NLS-1$
+ + "\r\nEndHTML:" + NUMBER + "\r\nStartFragment:" + NUMBER //$NON-NLS-1$ //$NON-NLS-2$
+ + "\r\nEndFragment:" + NUMBER + "\r\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ static final String PREFIX = "<html><body><!--StartFragment-->"; //$NON-NLS-1$
+
+ static final String SUFFIX = "<!--EndFragment--></body></html>"; //$NON-NLS-1$
+
+ static final String StartFragment = "StartFragment:"; //$NON-NLS-1$
+
+ static final String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+ public Win32HTMLTransfer() {
+ }
+
+ /**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+ public static Win32HTMLTransfer getInstance() {
+ return _instance;
+ }
+
+ /**
+ * This implementation of <code>javaToNative</code> converts
+ * HTML-formatted text represented by a java <code>String</code> to a
+ * platform specific representation. For additional information see
+ * <code>Transfer#javaToNative</code>.
+ *
+ * @param object
+ * a java <code>String</code> containing HTML text
+ * @param transferData
+ * an empty <code>TransferData</code> object; this object will
+ * be filled in on return with the platform specific format of
+ * the data
+ */
+ public void javaToNative(Object object, TransferData transferData) {
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String string = (String) object;
+ int count = string.length();
+ char[] chars = new char[count + 1];
+ string.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null,
+ 0, null, null);
+ if (cchMultiByte == 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int startHTML = HEADER.length();
+ int startFragment = startHTML + PREFIX.length();
+ int endFragment = startFragment + cchMultiByte - 1;
+ int endHTML = endFragment + SUFFIX.length();
+
+ StringBuffer buffer = new StringBuffer(HEADER);
+ int maxLength = NUMBER.length();
+ // startHTML
+ int start = buffer.toString().indexOf(NUMBER);
+ String temp = Integer.toString(startHTML);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // endHTML
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endHTML);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // startFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(startFragment);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+ // endFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endFragment);
+ buffer.replace(start + maxLength - temp.length(), start + maxLength,
+ temp);
+
+ buffer.append(PREFIX);
+ buffer.append(string);
+ buffer.append(SUFFIX);
+
+ count = buffer.length();
+ chars = new char[count + 1];
+ buffer.getChars(0, count, chars, 0);
+ cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0,
+ null, null);
+ long lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT,
+ cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr,
+ cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ return;
+ }
+
+ /**
+ * This implementation of <code>nativeToJava</code> converts a platform
+ * specific representation of HTML text to a java <code>String</code>.
+ * For additional information see <code>Transfer#nativeToJava</code>.
+ *
+ * @param transferData
+ * the platform specific representation of the data to be been
+ * converted
+ * @return a java <code>String</code> containing HTML text if the
+ * conversion was successful; otherwise null
+ */
+ public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject == 0)
+ return null;
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ FORMATETC formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result != COM.S_OK)
+ return null;
+ long hMem = stgmedium.unionField;
+
+ try {
+ long lpMultiByteStr = OS.GlobalLock(hMem);
+ if (lpMultiByteStr == 0)
+ return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar(codePage,
+ OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar == 0)
+ return null;
+ char[] lpWideCharStr = new char[cchWideChar - 1];
+ OS
+ .MultiByteToWideChar(codePage, OS.MB_PRECOMPOSED,
+ lpMultiByteStr, -1, lpWideCharStr,
+ lpWideCharStr.length);
+ return new String(lpWideCharStr);
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+ }
+
+ protected int[] getTypeIds() {
+ return new int[] { HTML_FORMATID };
+ }
+
+ protected String[] getTypeNames() {
+ return new String[] { HTML_FORMAT };
+ }
+
+ boolean checkHTML(Object object) {
+ return (object != null && object instanceof String && ((String) object)
+ .length() > 0);
+ }
+
+ protected boolean validate(Object object) {
+ return checkHTML(object);
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/package.html
new file mode 100644
index 00000000000..2d697e1a095
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common.win32.win32.x86_64/src/org/eclipse/epf/common/win32/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides windows-specific clipboard transfer services.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.common/.classpath
new file mode 100644
index 00000000000..4848249846f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/.project b/extraplugins/epf-richtext/org.eclipse.epf.common/.project
new file mode 100644
index 00000000000..9164759b2ef
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.common</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.common/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..ba111075119
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.common;singleton:=true
+Bundle-Version: 1.5.0.qualifier
+Bundle-Activator: org.eclipse.epf.common.CommonPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: com.ibm.icu;visibility:=reexport,
+ org.eclipse.core.resources;visibility:=reexport,
+ org.eclipse.core.runtime;visibility:=reexport,
+ org.apache.ant;visibility:=reexport
+Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.epf.common,
+ org.eclipse.epf.common.preferences,
+ org.eclipse.epf.common.serviceability,
+ org.eclipse.epf.common.utils,
+ org.eclipse.epf.common.xml
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/about.html b/extraplugins/epf-richtext/org.eclipse.epf.common/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.common/build.properties
new file mode 100644
index 00000000000..e2d90b8679a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/build.properties
@@ -0,0 +1,8 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.properties,\
+ .,\
+ META-INF/,\
+ about.html,\
+ plugin.xml,\
+ schema/
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.properties
new file mode 100644
index 00000000000..08c7275f893
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.properties
@@ -0,0 +1,15 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Common
+providerName=Eclipse.org
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.xml b/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.xml
new file mode 100644
index 00000000000..aff271b9081
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/plugin.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension-point id="markerAttributeContributer" name="MarkerAttributeContributer" schema="schema/markerAttributeContributer.exsd"/>
+ <extension-point id="objectFactory" name="ObjectFactory" schema="schema/objectFactory.exsd"/>
+ <extension-point id="htmlFormatter" name="HTMLFormatter" schema="schema/htmlFormatter.exsd"/>
+ <extension-point id="htmlParser" name="HTMLParser" schema="schema/htmlParser.exsd"/>
+</plugin>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlFormatter.exsd b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlFormatter.exsd
new file mode 100644
index 00000000000..a06c38b4166
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlFormatter.exsd
@@ -0,0 +1,105 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.epf.common">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.epf.common" id="htmlFormatter" name="HTML Formatter"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <choice>
+ <element ref="htmlFormatter"/>
+ </choice>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="htmlFormatter">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.epf.common.IHTMLFormatter"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlParser.exsd b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlParser.exsd
new file mode 100644
index 00000000000..38a8881f97e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/htmlParser.exsd
@@ -0,0 +1,105 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.epf.common">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.epf.common" id="htmlParser" name="HTML Parser"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <choice>
+ <element ref="htmlParser"/>
+ </choice>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="htmlParser">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.epf.common.html.IHTMLParser"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/schema/markerAttributeContributer.exsd b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/markerAttributeContributer.exsd
new file mode 100644
index 00000000000..f2a081cf2e3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/markerAttributeContributer.exsd
@@ -0,0 +1,111 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.epf.common">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.epf.common" id="markerAttributeContributer" name="MarkerAttributeContributer"/>
+ </appInfo>
+ <documentation>
+ Allow adding addtional attributes to markers generated from EPF
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="markerAttributeContributer"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="markerAttributeContributer">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ 1.5
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ org.eclipse.epf.common.utils.IMarkerAttributeContributer
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ //------------------------------------------------------------------------------
+// Copyright (c) 2005, 2008 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
+//------------------------------------------------------------------------------
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/schema/objectFactory.exsd b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/objectFactory.exsd
new file mode 100644
index 00000000000..ffa9a99bd00
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/schema/objectFactory.exsd
@@ -0,0 +1,102 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.epf.common">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.epf.common" id="objectFactory" name="ObjectFactory"/>
+ </appInfo>
+ <documentation>
+ Allow to create object through the extension
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="objectFactory"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="objectFactory">
+ <complexType>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ 1.5
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ package org.eclipse.epf.common.utils.IObjectFactory
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/AbstractActivator.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/AbstractActivator.java
new file mode 100644
index 00000000000..b7593501458
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/AbstractActivator.java
@@ -0,0 +1,518 @@
+//------------------------------------------------------------------------------
+// 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.common;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.internal.runtime.InternalPlatform;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.epf.common.preferences.IPreferenceStoreWrapper;
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.epf.common.utils.I18nUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The abstract base class for all EPF plug-ins.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @author Phong Nguyen Le
+ * @since 1.0
+ */
+public abstract class AbstractActivator extends Plugin implements IActivator {
+
+ // The relative path to the icons.
+ private static final String ICON_PATH = "icons/"; //$NON-NLS-1$;
+
+ // The logger hash map.
+ private static Map<String, Logger> loggers = new HashMap<String, Logger>();
+
+ // The message dialog hash map.
+ //private static Map<String, MsgDialog> msgDialogs = new HashMap<String, MsgDialog>();
+
+ // The shared image hash map.
+ //private static Map<String, Image> sharedImages = new HashMap<String, Image>();
+
+ // The resource bundle for this plug-in.
+ private ResourceBundle resourceBundle;
+
+ // This plug-in ID.
+ private String pluginId;
+
+ // The plug-in install URL.
+ private URL installURL;
+
+ // The plug-in install path.
+ private String installPath;
+
+ // The plug-in icon URL.
+ protected URL iconURL;
+
+ // The profiling flag.
+ private boolean profiling;
+
+ /**
+ * Default constructor.
+ */
+ public AbstractActivator() {
+ super();
+ }
+
+ /**
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+ init(context);
+
+ // set the
+ if (isDebugging()) {
+ getLogger().logInfo("Started " + pluginId); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ // Free the shared images.
+// for (Iterator images = sharedImages.values().iterator(); images
+// .hasNext();) {
+// Image image = (Image) images.next();
+// if (image != null && !image.isDisposed()) {
+// image.dispose();
+// }
+// }
+
+ super.stop(context);
+
+ if (isDebugging()) {
+ getLogger().logInfo("Stopped " + pluginId); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Initializes this plug-in.
+ *
+ * @param context
+ * The bundle context.
+ */
+ protected void init(BundleContext context) throws Exception {
+ // Get the bundle for this plug-in.
+ Bundle bundle = getBundle();
+
+ // Get the resouce bundle for this plug-in.
+ resourceBundle = Platform.getResourceBundle(bundle);
+
+ // Get the ID for this plug-in.
+ pluginId = bundle.getSymbolicName();
+
+ if (isDebugging()) {
+ getLogger().logInfo("Initializing " + pluginId); //$NON-NLS-1$
+ }
+
+ // Get the install path of this plug-in.
+ installURL = bundle.getEntry("/"); //$NON-NLS-1$
+
+ try {
+ installPath = FileLocator.resolve(installURL).getPath();
+ } catch (IOException e) {
+ installPath = Platform.getInstallLocation().getURL().getPath();
+ }
+
+ try {
+ iconURL = new URL(installURL, ICON_PATH);
+ } catch (IOException e) {
+ }
+
+ String symbolicName = bundle.getSymbolicName();
+ if (symbolicName != null) {
+ String key = symbolicName + "/profiling"; //$NON-NLS-1$
+ String value = InternalPlatform.getDefault().getOption(key);
+ profiling = value == null ? false : value.equalsIgnoreCase("true"); //$NON-NLS-1$
+ }
+
+ if (isDebugging()) {
+ getLogger().logInfo(
+ "Initialized " + pluginId + ", installPath=" + installPath); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ * Returns the ID of this plug-in.
+ *
+ * @return The ID of this plug-in.
+ */
+ public String getId() {
+ return pluginId;
+ }
+
+ /**
+ * Returns the install URL of this plug-in.
+ *
+ * @param The
+ * install URL of this plug-in.
+ */
+ public URL getInstallURL() {
+ return installURL;
+ }
+
+ /**
+ * Returns the install path of this plug-in.
+ *
+ * @param The
+ * install path of this plug-in.
+ */
+ public String getInstallPath() {
+ return installPath;
+ }
+
+ /**
+ * Loads and returns the localized properties of a Java properties file.
+ * <p>
+ *
+ * @param path
+ * The properties file path relative to the plug-in root.
+ * @return A <code>Properties</code> object.
+ */
+ public Properties getProperties(String path) throws IOException {
+ Properties props = new Properties();
+ if (path == null) {
+ return props;
+ }
+
+ String filePath = getLocalizedFile(path, true);
+ if (filePath != null) {
+ props.load(new FileInputStream(filePath));
+ }
+
+ return props;
+ }
+
+ /**
+ * get the locale specific absolute file path name of the given file in the
+ * plugin.
+ *
+ * @param path
+ * The properties file path relative to the plug-in root.
+ * @return String the locale specific absolute file path name of the given
+ * file.
+ * @throws IOException
+ */
+ public String getLocalizedFile(String path, boolean useDefault)
+ throws IOException {
+ String filePath = null;
+ String fileName = FileUtil.getFileName(path);
+ int index = path.lastIndexOf(fileName);
+ String pathName = path.substring(0, index);
+
+ Locale locale = Locale.getDefault();
+
+ Bundle bundle = getBundle();
+ Bundle[] bundles = Platform.getFragments(bundle);
+ if (bundles != null) {
+ for (int i = 0; i < bundles.length; i++) {
+ URL entry = bundles[i].getEntry(pathName);
+ if (entry != null) {
+ URL url = FileLocator.resolve(entry);
+ filePath = I18nUtil.getLocalizedFile(url.getPath()
+ + fileName, locale);
+ if (filePath != null) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (filePath == null) {
+ URL entry = bundle.getEntry(path);
+ if (entry != null) {
+ URL url = FileLocator.resolve(entry);
+ filePath = I18nUtil.getLocalizedFile(url.getPath(), locale);
+ if (filePath == null && useDefault) {
+ filePath = url.getPath();
+ }
+ }
+ }
+
+ return filePath;
+ }
+
+ /**
+ * for the given path in the plugin, find the localized files form the nl
+ * fragemenets and copy the localized files to the destination folder
+ *
+ * @param path
+ * String a relative path to the plugin root. The files in this
+ * folder will be iterated and their localized files will be
+ * copied over
+ * @param toDir
+ * FIle the destination folder
+ * @param recursive
+ * boolean recurively looking for files int the specified folder
+ * @param useLocaleFileName
+ * boolean if true the locale specific file names will be used in
+ * the copied destination, otherwise, the locale specific file
+ * name will be renamed to the default one in the destination
+ * folder
+ * @throws IOException
+ */
+ public void copyLocalizedFiles(String path, File toDir, boolean recursive,
+ boolean useLocaleFileName) throws IOException {
+ String pluginPath = getInstallPath();
+ URI pluginUri = new File(pluginPath).toURI();
+ URI pathUri = new File(pluginPath, path).toURI();
+
+ List<File> files = new ArrayList<File>();
+ File f = new File(pluginPath, path);
+ FileUtil.getAllFiles(f, files, recursive);
+
+ // for each file found in the specified folder, get the localized file
+ for (Iterator it = files.iterator(); it.hasNext();) {
+ URI srcUri = ((File) it.next()).toURI();
+
+ // get the relative path of the file to the plugin root, then find
+ // the localized file
+ String relPath = pluginUri.relativize(srcUri).getPath();
+
+ // only get the locale specific file, don't include the default one
+ String localizedFile = getLocalizedFile(relPath, false);
+ if (localizedFile == null) {
+ continue;
+ }
+
+ // need to change the target file path to relative to the path
+ // instead of the plugin root
+ relPath = pathUri.relativize(srcUri).getPath();
+ File srcFile = new File(localizedFile);
+ File targetFile = new File(toDir, relPath);
+ File targetParent = targetFile.getParentFile();
+
+ // copy the file to the desitination
+ // if useLocaleFileName is true, the destination file name should
+ // also use the locale specific file name
+ if (useLocaleFileName) {
+ String fileName = srcFile.getName();
+ targetFile = new File(targetParent, fileName);
+ }
+
+ if (isDebugging()) {
+ System.out.println("Copying localized file: "); //$NON-NLS-1$
+ System.out.println("Source: " + srcFile); //$NON-NLS-1$
+ System.out.println("Target: " + targetFile); //$NON-NLS-1$
+ System.out.println(""); //$NON-NLS-1$
+ }
+
+ try {
+ if (!targetParent.exists()) {
+ targetParent.mkdirs();
+ }
+
+ if (!targetFile.exists()) {
+ targetFile.createNewFile();
+ }
+
+ FileUtil.copyFile(srcFile, targetFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * Returns the localized resource.
+ *
+ * @param key
+ * The resource key.
+ * @return The localized resource.
+ */
+ public String getString(String key) {
+ if (resourceBundle != null) {
+ try {
+ return resourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the formatted localized message given the resource key and the
+ * message argument.
+ *
+ * @param key
+ * The resource key.
+ * @param argument
+ * The message argument.
+ * @return The formatted localized message.
+ */
+ public String formatMessage(String key, Object argument) {
+ if (resourceBundle != null) {
+ try {
+ String msg = resourceBundle.getString(key);
+ Object[] arguments = { argument };
+ return MessageFormat.format(msg, arguments);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the image URL given the relative path.
+ *
+ * @param relativePath
+ * The image's path relative to the plug-in's root.
+ * @return The image URL.
+ */
+ public URL getImageURL(String relativePath) {
+ try {
+ URL url = new URL(iconURL, relativePath);
+ return FileLocator.resolve(url);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+// /**
+// * Returns the image descriptor given the relative path.
+// *
+// * @param relativePath
+// * The image's path relative to the plug-in's root.
+// * @return The image descriptor.
+// */
+// public ImageDescriptor getImageDescriptor(String relativePath) {
+// try {
+// URL url = new URL(iconURL, relativePath);
+// return ImageDescriptor.createFromURL(url);
+// } catch (MalformedURLException e) {
+// return ImageDescriptor.getMissingImageDescriptor();
+// }
+// }
+//
+// /**
+// * Returns the image given the relative path.
+// * <p>
+// * Note: The returned image need to be freed by the caller.
+// *
+// * @param relativePath
+// * The image's path relative to the plug-in's root.
+// * @return The image.
+// */
+// public Image getImage(String relativePath) {
+// Image image = null;
+//
+// ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
+// if (imageDescriptor != null) {
+// image = imageDescriptor.createImage(false);
+// }
+//
+// return image;
+// }
+//
+// /**
+// * Returns the shared image given the relative path.
+// * <p>
+// * Note: The returned image will be automatically freed when the plug-in
+// * shuts down.
+// *
+// * @param relativePath
+// * The image's path relative to the plug-in's root.
+// * @return The image.
+// */
+// public Image getSharedImage(String relativePath) {
+// Image image = (Image) sharedImages.get(relativePath);
+// if (image != null) {
+// return image;
+// }
+//
+// ImageDescriptor imageDescriptor = getImageDescriptor(relativePath);
+// if (imageDescriptor != null) {
+// image = imageDescriptor.createImage(false);
+// if (image != null) {
+// sharedImages.put(relativePath, image);
+// }
+// }
+//
+// return image;
+// }
+
+ /**
+ * Returns the profiling flag.
+ *
+ * @return <code>true</code> if profiling is enabled for this plu-in
+ */
+ public boolean isProfiling() {
+ return profiling;
+ }
+
+ /**
+ * Returns the logger given the plug-in ID.
+ *
+ * @return The new or cached logger.
+ */
+ public Logger getLogger() {
+ Logger logger = (Logger) loggers.get(pluginId);
+ if (logger == null) {
+ logger = new Logger(this);
+ loggers.put(pluginId, logger);
+ }
+ return logger;
+ }
+
+ /**
+ * Logs the given object or message.
+ */
+ public void log(Object logEntry) {
+ if (logEntry instanceof Throwable) {
+ ((Throwable) logEntry).printStackTrace(System.err);
+ } else {
+ System.err.println(logEntry);
+ }
+ }
+
+ public IPreferenceStoreWrapper getPreferenceStore() {
+ return CommonPlugin.getDefault().getCommonPreferenceStore();
+ }
+
+
+ public Object getContext() {
+ if ( CommonPlugin.getDefault().contextProvider != null ) {
+ return CommonPlugin.getDefault().contextProvider.getContext();
+ }
+
+ return null;
+ }
+
+ public IMessageCallback getMsgCallback() {
+ return CommonPlugin.getDefault().msgCallback;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/CommonPlugin.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/CommonPlugin.java
new file mode 100644
index 00000000000..aa7c0c0d6ce
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/CommonPlugin.java
@@ -0,0 +1,82 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common;
+
+import org.eclipse.epf.common.preferences.IPreferenceStoreWrapper;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The Common plug-in activator.
+ */
+public final class CommonPlugin extends AbstractActivator {
+
+ // The shared plug-in instance.
+ private static CommonPlugin plugin;
+
+ /**
+ * Creates a new instance.
+ */
+ public CommonPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * @see org.eclipse.epf.common.ui.AbstractPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Gets the shared instance.
+ *
+ * @return the shared plug-in instance
+ */
+ public static CommonPlugin getDefault() {
+ return plugin;
+ }
+
+// /**
+// * set the store wrapper before it's being used.
+// * @param storeWrapper
+// */
+ private IPreferenceStoreWrapper storeWrapper = null;
+
+ public void setCommonPreferenceStore(IPreferenceStoreWrapper storeWrapper) {
+ this.storeWrapper = storeWrapper;
+ }
+
+ public IPreferenceStoreWrapper getCommonPreferenceStore() {
+ return storeWrapper;
+ }
+
+ // this is the context for message callback
+ // for eclipse client, this is the Shell object
+ IContextProvider contextProvider = null;
+
+ public void setContextProvider(IContextProvider contextProvider) {
+ this.contextProvider = contextProvider;
+ }
+
+ IMessageCallback msgCallback = null;
+ public void setMsgCallback(IMessageCallback msgCallback) {
+ this.msgCallback = msgCallback;
+ }
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IActivator.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IActivator.java
new file mode 100644
index 00000000000..4ddeed449fb
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IActivator.java
@@ -0,0 +1,23 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2008 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.common;
+
+import org.eclipse.epf.common.serviceability.Logger;
+
+/**
+ * @author Phong Nguyen Le
+ * @since 1.5
+ *
+ */
+public interface IActivator {
+ String getId();
+ Logger getLogger();
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IContextProvider.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IContextProvider.java
new file mode 100644
index 00000000000..b361fcb8f17
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IContextProvider.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common;
+
+public interface IContextProvider {
+ public Object getContext();
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLFormatter.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLFormatter.java
new file mode 100644
index 00000000000..b9db6ff70d8
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLFormatter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common;
+
+import java.io.UnsupportedEncodingException;
+import java.util.regex.Pattern;
+
+public interface IHTMLFormatter {
+
+ /*
+ * String location = m.group(1);
+ * String lineStr = m.group(2);
+ * String columnStr = m.group(3);
+ * String errorMsg = m.group(4);
+ */
+ public static final Pattern jTidyErrorParser = Pattern
+ .compile(
+ "(line\\s+(\\d+)\\s+column\\s+(\\d+))\\s+-\\s+(.+)", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+
+ public static final String DIAGNOSTIC_SOURCE = "org.eclipse.epf.common.IHTMLFormatter"; //$NON-NLS-1$
+
+ public static final Pattern p_whitespace = Pattern.compile("^\\s+", Pattern.MULTILINE); //$NON-NLS-1$
+
+ public String formatHTML(String html, boolean returnBodyOnly, boolean forceOutput, boolean makeBare, boolean word2000) throws UnsupportedEncodingException;
+
+ public String formatHTML(String text) throws UnsupportedEncodingException;
+
+ public String getLastErrorStr();
+
+ public String removeLeadingWhitespace(String input);
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLParser.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLParser.java
new file mode 100644
index 00000000000..dac8b72e6c3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IHTMLParser.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common;
+
+import java.io.File;
+import java.util.Properties;
+
+public interface IHTMLParser {
+
+ public String getText();
+
+ public String getSummary();
+
+ public Properties getMetaTags();
+
+ public void parse(File file) throws Exception;
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IMessageCallback.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IMessageCallback.java
new file mode 100644
index 00000000000..362f33b983e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/IMessageCallback.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common;
+
+
+public interface IMessageCallback {
+
+ public void displayWarning(AbstractActivator plugin, String title, String msg, String reason);
+ public void displayWarning(AbstractActivator plugin, String msg, String reason, Throwable ex);
+ public void displayWarning(AbstractActivator plugin, String msg, String reason, String details, Throwable ex);
+ public void displayWarning(AbstractActivator plugin, String title, String msg, String reason, String details, Throwable ex);
+
+ public void displayError(AbstractActivator plugin, String title, String msg);
+ public void displayError(AbstractActivator plugin, String title, String msg, Throwable ex);
+ public void displayError(AbstractActivator plugin, String title, String msg, String reason, String details, Throwable ex);
+
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/package.html
new file mode 100644
index 00000000000..dba34bd4a8f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides the activator for managing the Common plug-in's life cycle.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPreferenceStoreWrapper.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPreferenceStoreWrapper.java
new file mode 100644
index 00000000000..938f1fc7820
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPreferenceStoreWrapper.java
@@ -0,0 +1,440 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.preferences;
+
+
+/**
+ * wrapper interface for preference store
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public interface IPreferenceStoreWrapper {
+
+ //public Object getStore();
+
+ public void addPropertyChangeListener(IPropertyChangeListenerWrapper listener);
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue);
+ public void removePropertyChangeListener(IPropertyChangeListenerWrapper listener);
+
+ /**
+ * Returns the current value of the boolean-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>false</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a boolean.
+ *
+ * @param name the name of the preference
+ * @return the boolean-valued preference
+ */
+ public boolean getBoolean(String name);
+
+ /**
+ * Returns the default value for the boolean-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>false</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a boolean.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public boolean getDefaultBoolean(String name);
+
+ /**
+ * Returns the default value for the double-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0.0</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a double.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public double getDefaultDouble(String name);
+
+ /**
+ * Returns the default value for the float-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0.0f</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a float.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public float getDefaultFloat(String name);
+
+ /**
+ * Returns the default value for the integer-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as an integer.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public int getDefaultInt(String name);
+
+ /**
+ * Returns the default value for the long-valued preference
+ * with the given name.
+ * Returns the default-default value (<code>0L</code>) if there
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a long.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public long getDefaultLong(String name);
+
+ /**
+ * Returns the default value for the string-valued preference
+ * with the given name.
+ * Returns the default-default value (the empty string <code>""</code>)
+ * is no default preference with the given name, or if the default
+ * value cannot be treated as a string.
+ *
+ * @param name the name of the preference
+ * @return the default value of the named preference
+ */
+ public String getDefaultString(String name);
+
+ /**
+ * Returns the current value of the double-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0.0</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a double.
+ *
+ * @param name the name of the preference
+ * @return the double-valued preference
+ */
+ public double getDouble(String name);
+
+ /**
+ * Returns the current value of the float-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0.0f</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a float.
+ *
+ * @param name the name of the preference
+ * @return the float-valued preference
+ */
+ public float getFloat(String name);
+
+ /**
+ * Returns the current value of the integer-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as an integter.
+ *
+ * @param name the name of the preference
+ * @return the int-valued preference
+ */
+ public int getInt(String name);
+
+ /**
+ * Returns the current value of the long-valued preference with the
+ * given name.
+ * Returns the default-default value (<code>0L</code>) if there
+ * is no preference with the given name, or if the current value
+ * cannot be treated as a long.
+ *
+ * @param name the name of the preference
+ * @return the long-valued preference
+ */
+ public long getLong(String name);
+
+ /**
+ * Returns the current value of the string-valued preference with the
+ * given name.
+ * Returns the default-default value (the empty string <code>""</code>)
+ * if there is no preference with the given name, or if the current value
+ * cannot be treated as a string.
+ *
+ * @param name the name of the preference
+ * @return the string-valued preference
+ */
+ public String getString(String name);
+
+ /**
+ * Returns whether the current value of the preference with the given name
+ * has the default value.
+ *
+ * @param name the name of the preference
+ * @return <code>true</code> if the preference has a known default value
+ * and its current value is the same, and <code>false</code> otherwise
+ * (including the case where the preference is unknown to this store)
+ */
+ public boolean isDefault(String name);
+
+ /**
+ * Returns whether the current values in this property store
+ * require saving.
+ *
+ * @return <code>true</code> if at least one of values of
+ * the preferences known to this store has changed and
+ * requires saving, and <code>false</code> otherwise.
+ */
+ public boolean needsSaving();
+
+ /**
+ * Sets the current value of the preference with the given name to
+ * the given string value without sending a property change.
+ * <p>
+ * This method does not fire a property change event and
+ * should only be used for setting internal preferences
+ * that are not meant to be processed by listeners.
+ * Normal clients should instead call #setValue.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void putValue(String name, String value);
+
+ /**
+ * Sets the default value for the double-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, double value);
+
+ /**
+ * Sets the default value for the float-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, float value);
+
+ /**
+ * Sets the default value for the integer-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, int value);
+
+ /**
+ * Sets the default value for the long-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, long value);
+
+ /**
+ * Sets the default value for the string-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param defaultObject the new default value for the preference
+ */
+ public void setDefault(String name, String defaultObject);
+
+ /**
+ * Sets the default value for the boolean-valued preference with the
+ * given name.
+ * <p>
+ * Note that the current value of the preference is affected if
+ * the preference's current value was its old default value, in which
+ * case it changes to the new default value. If the preference's current
+ * is different from its old default value, its current value is
+ * unaffected. No property change events are reported by changing default
+ * values.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new default value for the preference
+ */
+ public void setDefault(String name, boolean value);
+
+ /**
+ * Sets the current value of the preference with the given name back
+ * to its default value.
+ * <p>
+ * Note that the preferred way of re-initializing a preference to the
+ * appropriate default value is to call <code>setToDefault</code>.
+ * This is implemented by removing the named value from the store,
+ * thereby exposing the default value.
+ * </p>
+ *
+ * @param name the name of the preference
+ */
+ public void setToDefault(String name);
+
+ /**
+ * Sets the current value of the double-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, double value);
+
+ /**
+ * Sets the current value of the float-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, float value);
+
+ /**
+ * Sets the current value of the integer-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, int value);
+
+ /**
+ * Sets the current value of the long-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, long value);
+
+ /**
+ * Sets the current value of the string-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, String value);
+
+ /**
+ * Sets the current value of the boolean-valued preference with the
+ * given name.
+ * <p>
+ * A property change event is reported if the current value of the
+ * preference actually changes from its previous value. In the event
+ * object, the property name is the name of the preference, and the
+ * old and new values are wrapped as objects.
+ * </p>
+ * <p>
+ * Note that the preferred way of re-initializing a preference to its
+ * default value is to call <code>setToDefault</code>.
+ * </p>
+ *
+ * @param name the name of the preference
+ * @param value the new current value of the preference
+ */
+ public void setValue(String name, boolean value);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeEventWrapper.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeEventWrapper.java
new file mode 100644
index 00000000000..e1b305c88a5
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeEventWrapper.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.preferences;
+
+/**
+ * wrapper interface for property change event
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public interface IPropertyChangeEventWrapper {
+
+ /**
+ * Returns the new value of the property.
+ *
+ * @return the new value, or <code>null</code> if not known
+ * or not relevant (for instance if the property was removed).
+ */
+ public Object getNewValue();
+
+ /**
+ * Returns the old value of the property.
+ *
+ * @return the old value, or <code>null</code> if not known
+ * or not relevant (for instance if the property was just
+ * added and there was no old value).
+ */
+ public Object getOldValue();
+
+ /**
+ * Returns the name of the property that changed.
+ * <p>
+ * Warning: there is no guarantee that the property name returned
+ * is a constant string. Callers must compare property names using
+ * equals, not ==.
+ * </p>
+ *
+ * @return the name of the property that changed
+ */
+ public String getProperty();
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeListenerWrapper.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeListenerWrapper.java
new file mode 100644
index 00000000000..9e4f195a868
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/preferences/IPropertyChangeListenerWrapper.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2009 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.common.preferences;
+
+/**
+ * wrapper interface for property change listener
+ *
+ * @author Jinhua Xi
+ * @since 1.5
+ *
+ */
+public interface IPropertyChangeListenerWrapper {
+
+ public void propertyChange(IPropertyChangeEventWrapper event);
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/DebugTrace.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/DebugTrace.java
new file mode 100644
index 00000000000..0e004d48034
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/DebugTrace.java
@@ -0,0 +1,104 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.serviceability;
+
+/**
+ * Helper utility for printing debug traces to the console.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class DebugTrace {
+
+ /**
+ * Prints a debug trace to the console.
+ *
+ * @param instance
+ * a class instance
+ * @param method
+ * a method name
+ * @param msg
+ * a debug message
+ * @param th
+ * a <code>Throwable</code> object
+ */
+ public static void print(Object instance, String method, String msg,
+ Throwable th) {
+ StringBuffer debugMsg = new StringBuffer();
+ if (instance != null) {
+ debugMsg.append(instance.getClass().getName());
+ if (method != null) {
+ debugMsg.append('.').append(method);
+ }
+ debugMsg.append(": "); //$NON-NLS-1$
+ }
+ if (msg != null && msg.length() > 0) {
+ debugMsg.append(msg);
+ }
+ System.out.println(debugMsg);
+ if (th != null) {
+ th.printStackTrace();
+ }
+ }
+
+ /**
+ * Prints a debug trace to the console.
+ *
+ * @param instance
+ * a class instance
+ * @param method
+ * a method name
+ * @param th
+ * a <code>Throwable</code> object
+ */
+ public static void print(Object instance, String method, Throwable th) {
+ print(instance, method, null, th);
+ }
+
+ /**
+ * Prints a debug trace to the console.
+ *
+ * @param instance
+ * a class instance
+ * @param method
+ * a method name
+ * @param msg
+ * a debug message
+ */
+ public static void print(Object instance, String method, String msg) {
+ print(instance, method, msg, null);
+ }
+
+ /**
+ * Prints a debug trace to the console.
+ *
+ * @param instance
+ * a class instance
+ * @param method
+ * a method name
+ */
+ public static void print(Object instance, String method) {
+ print(instance, method, null, null);
+ }
+
+ /**
+ * Prints a debug trace to the console.
+ *
+ * @param th
+ * a <code>Throwable</code> object
+ */
+ public static void print(Throwable th) {
+ if (th != null) {
+ th.printStackTrace();
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/Logger.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/Logger.java
new file mode 100644
index 00000000000..d8e12460230
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/Logger.java
@@ -0,0 +1,134 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.serviceability;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Generic logger used for logging status messages, warning messages, error
+ * messages, and exception stack traces.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class Logger {
+
+ public static String SeeLogFileForMoreDetails;
+
+ // The plug-in instance.
+ private Plugin plugin;
+
+ // The plug-in ID.
+ private String pluginId;
+
+ /**
+ * Create a new <code>Logger</code> given the plug-in instance.
+ *
+ * @param plugin
+ * The plugin instance.
+ */
+ public Logger(Plugin plugin) {
+ this.plugin = plugin;
+ this.pluginId = plugin.getBundle().getSymbolicName(); //plugin.getId();
+ }
+
+ /**
+ * Logs the given error message.
+ *
+ * @param msg
+ * The error message.
+ */
+ public void logError(String msg) {
+ logMsg(IStatus.ERROR, msg, null);
+ }
+
+ /**
+ * Logs the given exception.
+ *
+ * @param ex
+ * The exception.
+ */
+ public void logError(Throwable ex) {
+ logMsg(IStatus.ERROR, null, ex);
+ }
+
+ /**
+ * Logs the given error message and exception.
+ *
+ * @param msg
+ * The error message.
+ * @param ex
+ * The exception.
+ */
+ public void logError(String msg, Throwable ex) {
+ logMsg(IStatus.ERROR, msg, ex);
+ }
+
+ /**
+ * Logs the given warning message.
+ *
+ * @param msg
+ * The warning message.
+ */
+ public void logWarning(String msg) {
+ logMsg(IStatus.WARNING, msg, null);
+ }
+
+ /**
+ * Logs the given warning message and exception.
+ *
+ * @param msg
+ * The warning message.
+ * @param ex
+ * The exception.
+ */
+ public void logWarning(String msg, Throwable ex) {
+ logMsg(IStatus.WARNING, msg, ex);
+ }
+
+ /**
+ * Logs the given status message and exception.
+ *
+ * @param msg
+ * The status message.
+ */
+ public void logInfo(String msg) {
+ logMsg(IStatus.INFO, msg, null);
+ }
+
+ /**
+ * Logs the given message and exception.
+ *
+ * @param severity
+ * The severity.
+ * @param msg
+ * The message.
+ * @param ex
+ * The exception.
+ */
+ public synchronized void logMsg(int severity, String msg, Throwable ex) {
+ if (msg == null && ex != null) {
+ msg = ex.getMessage();
+ }
+
+ if (msg == null) {
+ msg = ""; //$NON-NLS-1$
+ }
+
+ Status status = new Status(severity, pluginId, IStatus.OK, msg, ex);
+
+ // Call the Eclipse Logger.
+ plugin.getLog().log(status);
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/package.html
new file mode 100644
index 00000000000..7aed6dede63
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/serviceability/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides common error handling, logging and versioning services.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ExtensionHelper.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ExtensionHelper.java
new file mode 100644
index 00000000000..2745046f8c6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ExtensionHelper.java
@@ -0,0 +1,216 @@
+//------------------------------------------------------------------------------
+//Copyright (c) 2005, 2008 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.common.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.CommonPlugin;
+import org.eclipse.epf.common.IHTMLFormatter;
+import org.eclipse.epf.common.IHTMLParser;
+import org.osgi.framework.Bundle;
+
+/**
+* Helper class with methods to retrieve extensions
+* Moved part of org.eclipse.epf.library.edit.util.ExtensionManager, to allow
+* access by classes that have no dependency on org.eclipse.epf.library.edit
+*
+* @author Phong Nguyen Le
+* @author Weiping Lu
+* @since 1.5
+*/
+public class ExtensionHelper {
+ private static Map IDToExtensionMap = new HashMap();
+
+ public static Object createExtension(String namespace, String extensionPointName) {
+ // Process the contributors.
+ //
+ IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(namespace, extensionPointName);
+ if (extensionPoint != null) {
+ IExtension[] extensions = extensionPoint.getExtensions();
+ Object ext = null;
+ ext_walk:
+ for (int i = 0; i < extensions.length; i++) {
+ IExtension extension = extensions[i];
+ String pluginId = extension.getNamespaceIdentifier();
+ Bundle bundle = Platform.getBundle(pluginId);
+ IConfigurationElement[] configElements = extension
+ .getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ IConfigurationElement configElement = configElements[j];
+ try {
+ String className = configElement.getAttribute("class"); //$NON-NLS-1$
+ if(className != null) {
+ ext = bundle.loadClass(className).newInstance();
+ break ext_walk;
+ }
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ }
+ return ext;
+ }
+ return null;
+ }
+
+ public static Object getExtension(String namespace, String extensionPointName) {
+ String ID = namespace + '.' + extensionPointName;
+ Object ext = IDToExtensionMap.get(ID);
+ if(ext == null) {
+ synchronized (IDToExtensionMap) {
+ ext = IDToExtensionMap.get(ID);
+ if(ext == null) {
+ ext = createExtension(namespace, extensionPointName);
+ if(ext != null) {
+ IDToExtensionMap.put(ID, ext);
+ }
+ }
+ }
+
+ }
+ return ext;
+ }
+
+ /**
+ * This is a special method to handle JTidy extensions
+ *
+ */
+ public static Object createExtensionForJTidy(String namespace, String extensionPointName) {
+ List<IHTMLFormatter> formaters = new ArrayList<IHTMLFormatter>();
+ List<IHTMLParser> parsers = new ArrayList<IHTMLParser>();
+
+ IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(namespace, extensionPointName);
+ if (extensionPoint != null) {
+ IExtension[] extensions = extensionPoint.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IExtension extension = extensions[i];
+ String pluginId = extension.getNamespaceIdentifier();
+ Bundle bundle = Platform.getBundle(pluginId);
+ IConfigurationElement[] configElements = extension.getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ IConfigurationElement configElement = configElements[j];
+ try {
+ String className = configElement.getAttribute("class"); //$NON-NLS-1$
+ if(className != null) {
+ Object obj = bundle.loadClass(className).newInstance();
+ if (extensionPointName.equals("htmlFormatter")) { //$NON-NLS-1$
+ formaters.add((IHTMLFormatter)obj);
+ } else if (extensionPointName.equals("htmlParser")) { //$NON-NLS-1$
+ parsers.add((IHTMLParser)obj);
+ }
+ }
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ }
+
+ if (formaters.size() > 0) {
+ if (formaters.size() == 1) {
+ return formaters.get(0);
+ }
+ return selectExtension(formaters);
+ } else if (parsers.size() > 0) {
+ if (parsers.size() == 1) {
+ return parsers.get(0);
+ }
+ return selectExtension(parsers);
+ }
+ }
+
+ return null;
+ }
+
+ private static Object selectExtension(List objs) {
+ for (Object obj : objs) {
+ String name = obj.getClass().getName();
+ if (!(name.equals("org.eclipse.epf.common.html.DefaultHTMLFormatter") //$NON-NLS-1$
+ || name.equals("org.eclipse.epf.common.html.DefaultHTMLParser"))) { //$NON-NLS-1$
+ return obj;
+ }
+ }
+
+ return null;
+ }
+
+ public static IMarkerAttributeContributer getMarkerAttributeContributer() {
+ IMarkerAttributeContributer ret = (IMarkerAttributeContributer) getExtension(
+ CommonPlugin.getDefault().getId(), "markerAttributeContributer");//$NON-NLS-1$
+ return ret;
+ }
+
+ /**
+ * Create object based on type and context through extension
+ * @param type
+ * @param context
+ * @return created object or null if no extension is found
+ */
+ public static Object create(Class type, Object context) {
+ IObjectFactory ret = (IObjectFactory) getExtension(
+ CommonPlugin.getDefault().getId(), "objectFactory");//$NON-NLS-1$
+ if (ret == null) {
+ return null;
+ }
+ return ret.create(type, context);
+ }
+
+ public static <T>List<T> getExtensions(String namespace, String extensionPointName, Class<T> type) {
+ List<T> list = new ArrayList<T>();
+ try {
+ IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(namespace, extensionPointName);
+ if (extensionPoint != null) {
+ IExtension[] extensions = extensionPoint.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IExtension extension = extensions[i];
+ String pluginId = extension.getNamespaceIdentifier();
+ Bundle bundle = Platform.getBundle(pluginId);
+ IConfigurationElement[] configElements = extension
+ .getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ IConfigurationElement configElement = configElements[j];
+ try {
+ String className = configElement.getAttribute("class"); //$NON-NLS-1$
+ if(className != null) {
+ Object ext = bundle.loadClass(className).newInstance();
+ if(type.isInstance(ext)) {
+ list.add((T)ext);
+ }
+ }
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ }
+ }
+ }
+ catch(Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ if(list.isEmpty()) {
+ return Collections.<T>emptyList();
+ }
+ return list;
+ }
+
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/FileUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/FileUtil.java
new file mode 100644
index 00000000000..bf8c51b2e74
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/FileUtil.java
@@ -0,0 +1,1285 @@
+//------------------------------------------------------------------------------
+// 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.common.utils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.nio.CharBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.epf.common.CommonPlugin;
+import org.osgi.framework.Bundle;
+
+/**
+ * Utility class for managing directories and files.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @since 1.0
+ */
+public class FileUtil {
+
+ /**
+ * Platform-specific line separator.
+ */
+ public static final String LINE_SEP = System.getProperty("line.separator"); //$NON-NLS-1$
+
+ /**
+ * Platform-specific file separator.
+ */
+ public static final String FILE_SEP = System.getProperty("file.separator"); //$NON-NLS-1$
+
+ /**
+ * Platform-specific line separator length.
+ */
+ public static final int LINE_SEP_LENGTH = LINE_SEP.length();
+
+ /**
+ * UNC path prefix.
+ */
+ public static final String UNC_PATH_PREFIX = "\\\\"; //$NON-NLS-1$
+
+ /**
+ * UNC path prefix length.
+ */
+ public static final int UNC_PATH_PREFIX_LENGTH = UNC_PATH_PREFIX.length();
+
+ /**
+ * ISO-8859-1 encoding.
+ */
+ public static final String ENCODING_ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$
+
+ /**
+ * UTF-8 encoding.
+ */
+ public static final String ENCODING_UTF_8 = "UTF-8";//$NON-NLS-1$
+
+ private static Map<File, File> copiedFileMap;
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private FileUtil() {
+ }
+
+ /**
+ * Returns the absolute path for a file or directory.
+ *
+ * @param file
+ * a file or directory
+ * @return the absolute path to the file or directory
+ */
+ public static String getAbsolutePath(File file) {
+ return file.getAbsolutePath().replace('\\', '/');
+ }
+
+ /**
+ * Returns the absolute path for a file or directory.
+ *
+ * @param path
+ * a path to a file or directory
+ * @return an absolute path to the file or directory
+ */
+ public static String getAbsolutePath(String path) {
+ return getAbsolutePath(new File(path));
+ }
+
+ /**
+ * Returns the absolute path for a URL.
+ *
+ * @param url
+ * a URL
+ * @return the absolute path of the URL
+ */
+ public static String getAbsolutePath(URL url) {
+ String pathName = url.getFile().substring(1);
+ String result = NetUtil.decodeUrl(pathName, null);
+ return result;
+ }
+
+ /**
+ * Returns the parent directory of a path.
+ *
+ * @param path
+ * a path name
+ * @return the name of the parent directory
+ */
+ public static String getParentDirectory(String path) {
+ return (new File(path)).getParent();
+ }
+
+ /**
+ * Returns the file name and extension from a path.
+ *
+ * @param path
+ * a path name
+ * @return the file name including the file extension
+ */
+ public static String getFileName(String path) {
+ return getFileName(path, true);
+ }
+
+ /**
+ * Returns the file name from a path, with or without the file extension.
+ *
+ * @param path
+ * a path name
+ * @param withExtension
+ * if <code>true</code>, include the file extension in the
+ * result
+ * @return the file name with or without the file extension
+ */
+ public static String getFileName(String path, boolean withExtension) {
+ String normalizedPath = path.replace('\\', '/');
+
+ int prefixLength = 0;
+ if (normalizedPath.startsWith(NetUtil.FILE_URI_PREFIX)) {
+ prefixLength = NetUtil.FILE_URI_PREFIX_LENGTH;
+ } else if (normalizedPath.startsWith(NetUtil.HTTP_URI_PREFIX)) {
+ prefixLength = NetUtil.HTTP_URI_PREFIX_LENGTH;
+ }
+
+ String fileName;
+ int index = normalizedPath.lastIndexOf("/"); //$NON-NLS-1$
+ if (index < prefixLength) {
+ fileName = normalizedPath.substring(prefixLength);
+ } else {
+ fileName = path.substring(index + 1);
+ }
+
+ if (withExtension) {
+ return fileName;
+ }
+
+ index = fileName.indexOf("."); //$NON-NLS-1$
+ return (index > 0) ? fileName.substring(0, index) : fileName;
+ }
+
+ /**
+ * Returns the relative path of a path from a base path.
+ *
+ * @param path
+ * a path
+ * @param basePath
+ * the base path
+ * @return a relative path
+ */
+ public static String getRelativePathToBase(File path, File basePath) {
+ try {
+ String dir = path.toURL().toExternalForm();
+ String baseDir = basePath.toURL().toExternalForm();
+ StringBuffer result = new StringBuffer();
+ if (dir.indexOf(baseDir) == 0) {
+ String delta = dir.substring(baseDir.length());
+ for (int i = 0; i < delta.length(); i++) {
+ if (delta.charAt(i) == '/') {
+ result.append("../"); //$NON-NLS-1$
+ }
+ }
+ }
+ return result.toString();
+ } catch (Exception e) {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ public static String getRelativePath(File path, File basePath) {
+ try {
+ String dir = path.toURL().toExternalForm();
+ String baseDir = appendSeparator(basePath.toURL().toExternalForm(),
+ "/"); //$NON-NLS-1$
+ StringBuffer result = new StringBuffer();
+ while (dir.indexOf(baseDir) == -1) {
+ basePath = basePath.getParentFile();
+ baseDir = appendSeparator(basePath.toURL().toExternalForm(),
+ "/"); //$NON-NLS-1$
+ result.append("../"); //$NON-NLS-1$
+ }
+ if (dir.indexOf(baseDir) == 0) {
+ String delta = dir.substring(baseDir.length());
+ result.append(delta);
+ }
+ return result.toString();
+ } catch (Exception e) {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Appends the platform specific path separator to the end of a path.
+ *
+ * @param path
+ * a path name
+ * @return the path name appended with the platform specific path separator
+ */
+ public static String appendSeparator(String path) {
+ return appendSeparator(path, File.separator);
+ }
+
+ /**
+ * Appends the given path separator to the end of a path
+ *
+ * @param path
+ * a path name
+ * @param separator
+ * a path separator
+ * @return the path name appended with the given separator
+ */
+ public static String appendSeparator(String path, String separator) {
+ return path.endsWith(separator) ? path : path + separator;
+ }
+
+ /**
+ * Removes the ending path separator from a path.
+ *
+ * @param path
+ * a path name
+ * @return the path name minus the platform specific path separator
+ */
+ public static String removeSeparator(String path) {
+ return path.endsWith(File.separator) ? path.substring(0,
+ path.length() - 1) : path;
+ }
+
+ /**
+ * Removes the ending path separator from a path.
+ *
+ * @param path
+ * a path name
+ * @return the path name minus the path separator "\\" or "/"
+ */
+ public static String removeAllSeparator(String path) {
+ return path.endsWith("/") || path.endsWith("\\") ? path.substring(0, path.length() - 1) : path; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Removes the ending path separator from a path.
+ *
+ * @param path
+ * a path name
+ * @param separator
+ * a path separator
+ * @return the path name minus the separator
+ */
+ public static String removeSeparator(String path, String separator) {
+ return path.endsWith(separator) ? path.substring(0, path.length() - 1)
+ : path;
+ }
+
+ /**
+ * Replaces the file name with another in a path.
+ *
+ * @param path
+ * a path name
+ * @param oldFileName
+ * the old file name
+ * @param newFileName
+ * the new file name
+ * @return the new path name with the new file name
+ */
+ public static String replaceFileName(String path, String oldFileName,
+ String newFileName) {
+ int index = path.lastIndexOf(oldFileName);
+ return path.substring(0, index) + newFileName;
+ }
+
+ /**
+ * Replaces the file extension with another in a path.
+ *
+ * @param path
+ * a path name
+ * @param oldFileExt
+ * rhe old file extension
+ * @param newFileExt
+ * the new file extension
+ * @return the new path with the new file extension
+ */
+ public static String replaceExtension(String path, String oldExt,
+ String newExt) {
+ int index = path.lastIndexOf(oldExt);
+ return path.substring(0, index) + newExt;
+ }
+
+ /**
+ * Returns the locale-specific path of a base path.
+ *
+ * @param path
+ * a base path name
+ * @param localeStr
+ * a locale string
+ * @return the locale-specific path
+ */
+ public static String getLocalePath(String path, String localeStr) {
+ if (StrUtil.isBlank(localeStr)) {
+ return path;
+ }
+ String fileName = getFileName(path);
+ return replaceFileName(path, fileName, localeStr + "/" + fileName); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the locale-specific path of a base path.
+ *
+ * @param path
+ * a base path name
+ * @param locale
+ * a locale object
+ * @return the locale-specific path
+ */
+ public static String getLocalePath(String path, Locale locale) {
+ return locale == null ? path : getLocalePath(path, locale.toString());
+ }
+
+ /**
+ * Writes the given text to a text file.
+ *
+ * @param fileName
+ * the target file name
+ * @param text
+ * the text to write
+ * @return <code>true</code> if the given text is written successfully to
+ * file
+ */
+ public static boolean writeFile(String filename, String text) {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(filename);
+ writer.write(text);
+ writer.flush();
+ } catch (IOException e) {
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ return true;
+ } catch (Exception e) {
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Write the given text to a file with UTF-8 encoding.
+ *
+ * @param fileName
+ * the target file name
+ * @param text
+ * the text to write
+ * @param append
+ * if <code>true</code>, append the text to the end of the
+ * file, if <code>false</code>, override the file
+ * @return <code>true</code> if the given text is written successfully to
+ * file
+ */
+ public static boolean writeUTF8File(String filename, String text) {
+ return writeUTF8File(filename, text, false);
+ }
+
+ /**
+ * Write the given text to a file with UTF-8 encoding.
+ *
+ * @param fileName
+ * the target file name
+ * @param text
+ * the text to write
+ * @param append
+ * if <code>true</code>, append the text to the end of the
+ * file, if <code>false</code>, override the file
+ * @return <code>true</code> if the given text is written successfully to
+ * file
+ */
+ public static boolean writeUTF8File(String filename, String text,
+ boolean append) {
+ OutputStreamWriter writer = null;
+ FileOutputStream fileOut = null;
+ try {
+ fileOut = new FileOutputStream(filename, append);
+ writer = new OutputStreamWriter(fileOut, ENCODING_UTF_8);
+ writer.write(text);
+ writer.flush();
+ fileOut.flush();
+ } catch (IOException e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ return true;
+ } catch (Exception e) {
+ }
+ }
+ if (fileOut != null) {
+ try {
+ fileOut.close();
+ return true;
+ } catch (Exception e) {
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Write the content of the given URI to an output stream.
+ *
+ * @param uri
+ * the source URI
+ * @param output
+ * the output stream
+ */
+ public static void writeFile(String uri, OutputStream output)
+ throws IOException {
+ if (uri == null) {
+ return;
+ }
+
+ InputStream input = null;
+ try {
+ input = NetUtil.getInputStream(uri);
+ int bytesRead;
+ byte[] buf = new byte[4096];
+ while ((bytesRead = input.read(buf, 0, 4096)) > 0) {
+ output.write(buf, 0, bytesRead);
+ }
+ output.flush();
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Write the content of the given URI to a <code>PrintWriter</code>.
+ *
+ * @param uri
+ * the source URI
+ * @param writer
+ * the <code>PrintWriter</code> object
+ */
+ public static void writeFile(String uri, PrintWriter pw) throws IOException {
+ if (uri == null) {
+ return;
+ }
+
+ InputStreamReader input = null;
+ try {
+ input = new InputStreamReader(NetUtil.getInputStream(uri));
+ int charsRead;
+ char[] buf = new char[4096];
+ while ((charsRead = input.read(buf, 0, 4096)) > 0) {
+ pw.write(buf, 0, charsRead);
+ }
+ pw.flush();
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Recursively delete all sub-directories and files in a directory except
+ * for the directory itself.
+ *
+ * @param dir
+ * the directory containing the sub-directories and files
+ * @return <code>true</code> if the delete operation is successful
+ */
+ public static boolean deleteAllFiles(String dir) {
+ boolean ret = true;
+ File targetDir = new File(dir);
+ File[] files = targetDir.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ ret = ret && deleteAllFiles(files[i].getAbsolutePath());
+ }
+ ret = ret && files[i].delete();
+ }
+ }
+
+ return ret;
+ }
+
+ public static boolean deleteTree(File file) {
+ boolean ret = true;
+
+ if (file.isDirectory()) {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (File f : files) {
+ if (!deleteTree(f)) {
+ ret = false;
+ }
+ }
+ }
+ }
+
+ if (!file.delete()) {
+ ret = false;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Recursively delete all sub-directories and files in a directory except
+ * for the directory itself and the specified file.
+ *
+ * @param dir
+ * the directory containing the sub-directories and files
+ * @param filesNotToDelete
+ * a list of files and/or directories that should not be deleted
+ * @return <code>true</code> if delete operation is successful
+ */
+ public static boolean deleteAllFiles(String dir, List<File> filesNotToDelete) {
+ boolean ret = true;
+ File targetDir = new File(dir);
+ File[] files = targetDir.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (!filesNotToDelete.contains(files[i])) {
+ if (files[i].isDirectory()) {
+ ret = ret
+ && deleteAllFiles(files[i].getAbsolutePath(),
+ filesNotToDelete);
+ }
+ ret = ret && files[i].delete();
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Copies the content of the source file to the target file. Will overwrite
+ * an existing file if it has write permission
+ *
+ * @param srcFile
+ * the source file or path
+ * @param tgtFile
+ * the target file or path
+ */
+ public static boolean copyFile(File srcFile, File tgtFile) {
+ Map<File, File> map = getCopiedFileMap();
+ File keyFile = null;
+ File valFile = null;
+ if (map != null) {
+ try {
+ keyFile = tgtFile.getCanonicalFile();
+ valFile = srcFile.getCanonicalFile();
+ if (valFile.equals(map.get(keyFile))) {
+ return true;
+ }
+ } catch (Exception e) {
+ keyFile = valFile = null;
+ }
+ }
+
+ try {
+ boolean ret = copyfile(srcFile, tgtFile);
+ if (map != null && keyFile != null && valFile != null) {
+ map.put(keyFile, valFile);
+ }
+ return ret;
+ } catch (IOException ex) {
+ CommonPlugin.getDefault().getLogger().logError(ex);
+ return false;
+ }
+ }
+
+ /**
+ * Copies the content of the source file to the target file.
+ *
+ * @param srcFileName
+ * the source file name
+ * @param tgtFileName
+ * the target file name
+ */
+ public static boolean copyFile(String srcFileName, String tgtFileName) {
+ return copyFile(new File(srcFileName), new File(tgtFileName));
+ }
+
+ /**
+ * Copies one file to another.
+ * <p>
+ * If both source and destination are directories, delegates to
+ * copydirectory().
+ * <p>
+ * source must exist and be readable
+ * <p>
+ * cannot copy a directory to a file
+ * <p>
+ * will not copy if timestamps and filesize match, will overwrite otherwise
+ *
+ * @param source
+ * the source file
+ * @param dest
+ * the destination file
+ * @throws IOException
+ * if an error occurs during the copy operation
+ */
+ private static boolean copyfile(File source, File dest) throws IOException {
+ if (source.equals(dest))
+ // do not copy equal files
+ return false;
+
+ if (!source.exists() || !source.canRead()) {
+ // source does not exist or can't read
+ return false;
+ }
+
+ if (dest.exists() && !dest.canWrite()) {
+ // dest exists and cannot be written
+ return false;
+ }
+
+ if (source.isDirectory()) {
+ if (dest.isFile()) {
+ // can't copy a directory to a file
+ return false;
+ } else {
+ // delegate to copydirectory
+ return copydirectory(source, dest);
+ }
+ } else {
+ // source is a file
+ if (dest.isDirectory()) {
+ String sourceFileName = source.getName();
+ return copyfile(source, new File(dest, sourceFileName));
+ }
+ // both source and dest are files
+ boolean needCopy = true;
+ if (dest.exists()) {
+ needCopy = (dest.lastModified() != source.lastModified())
+ || (dest.length() != source.length());
+ }
+
+ if (needCopy) {
+ FileInputStream input = null;
+ FileOutputStream output = null;
+
+ try {
+ input = new FileInputStream(source);
+ FileChannel in = input.getChannel();
+ if (!dest.exists()) {
+ dest.getParentFile().mkdirs();
+ }
+ output = new FileOutputStream(dest);
+ FileChannel out = output.getChannel();
+ out.transferFrom(in, 0, source.length());
+ dest.setLastModified(source.lastModified());
+ return true;
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ }
+ }
+ if (output != null) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ } else {
+ // did not copy
+ // return true because dest file is same as source
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Copies the content of a directory to another directory.
+ *
+ * @param srcDirName
+ * the source directory name
+ * @param tgtDirName
+ * the target directory name
+ */
+ public static boolean copyDir(File srcDir, File tgtDir) {
+ try {
+ return copydirectory(srcDir, tgtDir);
+ } catch (IOException ex) {
+ CommonPlugin.getDefault().getLogger().logError(ex);
+ return false;
+ }
+ }
+
+ /**
+ * Copies the content of a directory to another directory.
+ *
+ * @param srcDirName
+ * the source directory name
+ * @param tgtDirName
+ * the target directory name
+ */
+ public static boolean copyDir(String srcDirName, String tgtDirName) {
+ return copyDir(new File(srcDirName), new File(tgtDirName));
+ }
+
+ /**
+ * Copies one directory to another - operates ONLY on directories.
+ * <p>
+ * Both source and dest must exist.
+ */
+ private static boolean copydirectory(File sourceDir, File destDir)
+ throws IOException {
+ if (!sourceDir.exists() || !destDir.exists()) {
+ return false;
+ }
+
+ if (!sourceDir.isDirectory() || !destDir.isDirectory()) {
+ return false;
+ }
+
+ File[] files = sourceDir.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ // calc destination name
+ String destName = destDir
+ + File.separator
+ + files[i].getAbsolutePath().substring(
+ sourceDir.getAbsolutePath().length() + 1);
+ if (files[i].isFile()) {
+ // copy the file
+ copyfile(files[i], new File(destName));
+ } else if (files[i].isDirectory()) {
+ // copy directory recursively
+ File destFile = new File(destName);
+ destFile.mkdirs();
+ copydirectory(files[i], destFile);
+ }
+ }
+ }
+ return true;
+ }
+
+ // for some reason, this guy locks the file, if you try to update the file,
+ // got the following exception
+ // java.io.FileNotFoundException:
+ // (The requested operation cannot be performed on a file with a user-mapped
+ // section open)
+ // need to handle later
+ public static CharBuffer readFile(File file) throws IOException {
+ FileInputStream input = null;
+ CharBuffer charBuffer = null;
+ try {
+ input = new FileInputStream(file);
+ FileChannel inChannel = input.getChannel();
+ int length = (int) inChannel.size();
+ MappedByteBuffer byteBuffer = inChannel.map(
+ FileChannel.MapMode.READ_ONLY, 0, length);
+ Charset charset = Charset.forName(ENCODING_ISO_8859_1);
+ CharsetDecoder decoder = charset.newDecoder();
+ charBuffer = decoder.decode(byteBuffer);
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return charBuffer;
+ }
+
+ public static String readInputStream(InputStream input) throws IOException {
+ String result = ""; //$NON-NLS-1$
+ byte[] readData = new byte[8 * 1024];
+ try {
+ int bytesRead = 0;
+ while ( (bytesRead = input.read(readData)) > 0) {
+ result += new String(readData, 0, bytesRead);
+ }
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return result;
+ }
+
+ public static StringBuffer readFile(File file, String encoding)
+ throws IOException {
+
+ StringBuffer result = new StringBuffer();
+ FileInputStream fis = null;
+ InputStreamReader reader = null;
+ int size;
+ try {
+ Charset cs = Charset.forName(encoding);
+ CharsetDecoder csd = cs.newDecoder();
+ csd.onMalformedInput(CodingErrorAction.REPLACE);
+ char[] buffer = new char[1024];
+ fis = new FileInputStream(file);
+ reader = new InputStreamReader(fis, csd);
+ while ((size = reader.read(buffer, 0, 1024)) > 0) {
+ result.append(buffer, 0, size);
+ }
+ } catch (Exception e) {
+ // System.out.println(encoding);
+ e.printStackTrace();
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+
+ if (reader != null) {
+ reader.close();
+ }
+ }
+
+ return result;
+ }
+
+ public static long getSize(File file) {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ return fis.getChannel().size();
+ }
+ catch (IOException e) {
+ //
+ }
+ finally {
+ try {
+ fis.close();
+ }
+ catch(Exception e) {
+ //
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Uses Java 1.4's FileLock class to test for a file lock
+ *
+ * @param file
+ * @return
+ */
+ public static boolean isFileLocked(File file) {
+ boolean isLocked = false;
+ FileOutputStream input = null;
+ FileLock lock = null;
+
+ if (!file.exists()) {
+ return false;
+ }
+ try {
+ input = new FileOutputStream(file);
+ FileChannel fileChannel = input.getChannel();
+
+ lock = fileChannel.tryLock();
+
+ if (lock == null)
+ isLocked = true;
+ else
+ lock.release();
+ } catch (Exception e) {
+ if (e instanceof SecurityException)
+ // Can't write to file.
+ isLocked = true;
+ else if (e instanceof FileNotFoundException)
+ isLocked = false;
+ else if (e instanceof IOException)
+ isLocked = true;
+ // OverlappingFileLockException means that this JVM has it locked
+ // therefore it is not locked to us
+ else if (e instanceof OverlappingFileLockException)
+ isLocked = false;
+ // Could not get a lock for some other reason.
+ else
+ isLocked = true;
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (Exception ex) {
+ }
+ }
+ }
+ return isLocked;
+ }
+
+ /**
+ * Locks a file for the current JVM. Will create the file if it does not
+ * exist
+ *
+ * @param file
+ * @return a FileLock object, or null if file could not be locked
+ */
+ public static FileLock lockFile(File file) {
+ FileOutputStream input = null;
+ FileLock lock = null;
+ try {
+ input = new FileOutputStream(file);
+ FileChannel fileChannel = input.getChannel();
+ lock = fileChannel.tryLock();
+
+ if (lock.isValid())
+ return lock;
+ } catch (Exception e) {
+ // Could not get a lock for some reason.
+ return null;
+ } finally {
+ try {
+ if (input != null && (lock == null || !lock.isValid())) {
+ input.close();
+ }
+ } catch (Exception ex) {
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets all files in a specified path.
+ *
+ * @param path
+ * absolute path of a folder
+ * @param fileList
+ * a list to collect the files
+ * @param recursive
+ * if <code>true</code>, find the files in sub folders as well
+ */
+ public static void getAllFiles(File path, List<File> fileList,
+ boolean recursive) {
+ if (path.isDirectory()) {
+ File[] files = path.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isFile()) {
+ fileList.add(files[i]);
+ } else if (recursive) {
+ getAllFiles(files[i], fileList, recursive);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Given a directory and extension, returns all files (recursively) whose
+ * extension starts with a given extension.
+ *
+ * @param file
+ * a directory
+ * @param extension
+ * a file extension
+ * @return a colleciton of <code>File</code> with the given extension
+ */
+ public static List<File> fileList(File f, String extension) {
+ extension = extension.toUpperCase();
+ List<File> returnList = new ArrayList<File>();
+ try {
+ if (f.isDirectory()) {
+ String[] flist = f.list();
+ for (int i = 0; i < flist.length; ++i) {
+ File fc = new File(f.getPath(), flist[i]);
+ returnList.addAll(fileList(fc, extension));
+ }
+ } else {
+ if (extension != null) {
+ String name = f.getName().toUpperCase();
+ if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
+ if (name
+ .substring(name.lastIndexOf(".") + 1).startsWith(extension)) { //$NON-NLS-1$
+ returnList.add(f);
+ }
+ } else
+ returnList.add(f);
+ }
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ return returnList;
+ }
+
+ /**
+ * Given a directory and extension, returns all files (recursively) whose
+ * extension does not starts with a given extension.
+ *
+ * @param file
+ * a directory
+ * @param extension
+ * a file extension
+ * @return a colleciton of <code>File</code> without the given extension
+ */
+ public static List<File> fileListExcludeExt(File f, String extension) {
+ List<File> returnList = new ArrayList<File>();
+ try {
+ if (f.isDirectory()) {
+ String[] flist = f.list();
+ for (int i = 0; i < flist.length; ++i) {
+ File fc = new File(f.getPath(), flist[i]);
+ returnList.addAll(fileListExcludeExt(fc, extension));
+ }
+ } else {
+ if (extension != null) {
+ String name = f.getName();
+ if (name.lastIndexOf(".") != -1) //$NON-NLS-1$
+ if (!(name.substring(name.lastIndexOf(".") + 1).startsWith(extension))) { //$NON-NLS-1$
+ returnList.add(f);
+ }
+ } else
+ returnList.add(f);
+ }
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ return returnList;
+ }
+
+ /**
+ * Gets all file paths in the specified path.
+ *
+ * @param path,
+ * absolute path of a folder
+ * @param recursive
+ * if <code>true</code>, find the files in sub folders as well
+ */
+ public static ArrayList<String> getAllFileAbsolutePaths(File path,
+ boolean recursive) {
+ ArrayList<File> files = new ArrayList<File>();
+ getAllFiles(path, files, recursive);
+ ArrayList<String> paths = new ArrayList<String>();
+ for (int i = 0; i < files.size(); i++) {
+ String absPath = ((File) files.get(i)).getAbsolutePath();
+ paths.add(absPath);
+ }
+ return paths;
+ }
+
+ /**
+ * Moves a file from a directory to another.
+ * <p>
+ * Attempts to rename the file first. If that fails, will copy the
+ * sourceFile to destFile and delete the sourceFile.
+ *
+ * @param sourceFile
+ * the source file
+ * @param destFile
+ * the destination file
+ * @return
+ */
+ public static boolean moveFile(File sourceFile, File destFile) {
+ try {
+ doMoveFile(sourceFile, destFile);
+ return true;
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ return false;
+ }
+ }
+
+ public static void doMoveFile(File sourceFile, File destFile) throws IOException {
+ // Try to rename the source file to the destination file.
+ if (!sourceFile.renameTo(destFile)) {
+ // Try to copy the source file to the destination file and
+ // delete
+ // the source file.
+ copyfile(sourceFile, destFile);
+ sourceFile.delete();
+ }
+ }
+
+ private static Map<File, File> getCopiedFileMap() {
+ return copiedFileMap;
+ }
+
+ public static void setCopiedFileMap(Map<File, File> copiedFileMap) {
+ FileUtil.copiedFileMap = copiedFileMap;
+ }
+
+
+ /**
+ * Unzips the contents of a zip file to a directory
+ *
+ * @param zipfile
+ * source zip file
+ * @param tgtDir
+ * target directory
+ */
+ public static boolean unzip(File srcZipFile, File tgtDir) {
+ if (! srcZipFile.exists() || ! tgtDir.exists()) {
+ return false;
+ }
+
+ if (! tgtDir.isDirectory()) {
+ return false;
+ }
+
+ try {
+ ZipFile zipFile = new ZipFile(srcZipFile);
+ Enumeration entries = zipFile.entries();
+
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry) entries.nextElement();
+
+ File tgtFile = new File(tgtDir, entry.getName());
+
+ if (entry.isDirectory() && ! tgtFile.exists()) {
+ tgtFile.mkdirs();
+
+ } else {
+ File parentFolder = tgtFile.getParentFile();
+ if (! parentFolder.exists()) {
+ parentFolder.mkdirs();
+ }
+
+ copyInputStream(zipFile.getInputStream(entry),
+ new BufferedOutputStream(new FileOutputStream(
+ new File(tgtDir, entry.getName()))));
+ }
+ }
+
+ zipFile.close();
+ } catch (IOException ioe) {
+ return false;
+ }
+ return false;
+ }
+
+ private static final void copyInputStream(InputStream in, OutputStream out)
+ throws IOException {
+ byte[] buffer = new byte[1024];
+ int len;
+
+ while ((len = in.read(buffer)) >= 0)
+ out.write(buffer, 0, len);
+
+ in.close();
+ out.close();
+ }
+
+ public static class FileChecker {
+ public IStatus syncExecCheckModify(List<String> modifiedFiles) {
+ return Status.OK_STATUS;
+ }
+ }
+
+ private static FileChecker fileChecker;
+ private static void loadDeafultFileChecker() {
+ if (fileChecker != null) {
+ return;
+ }
+ Bundle bundle = Platform.getBundle("org.eclipse.epf.import");
+ try {
+ bundle.start();
+ } catch (Exception e) {
+ }
+ }
+ public static void setFileChecker(FileChecker fileChecker) {
+ FileUtil.fileChecker = fileChecker;
+ }
+
+ public static IStatus syncExecCheckModify(List<String> modifiedFiles) {
+ loadDeafultFileChecker();
+ if (fileChecker != null) {
+ return fileChecker.syncExecCheckModify(modifiedFiles);
+ }
+ return Status.OK_STATUS;
+ }
+
+ public static boolean binaryEqual(File f1, File f2) {
+ BufferedInputStream is1 = null;
+ BufferedInputStream is2 = null;
+
+ int bufSz = 1024;
+ byte buff1[] = new byte[bufSz];
+ byte buff2[] = new byte[bufSz];
+
+ try {
+ is1 = new BufferedInputStream(new FileInputStream(f1));
+ is2 = new BufferedInputStream(new FileInputStream(f2));
+
+ int read1 = -1;
+ int read2 = -1;
+
+ do {
+ int offset1 = 0;
+ while (offset1 < bufSz
+ && (read1 = is1.read(buff1, offset1, bufSz - offset1)) >= 0) {
+ offset1 += read1;
+ }
+
+ int offset2 = 0;
+ while (offset2 < bufSz
+ && (read2 = is2.read(buff2, offset2, bufSz - offset2)) >= 0) {
+ offset2 += read2;
+ }
+ if (offset1 != offset2)
+ return false;
+ if (offset1 != bufSz) {
+ Arrays.fill(buff1, offset1, bufSz, (byte) 0);
+ Arrays.fill(buff2, offset2, bufSz, (byte) 0);
+ }
+ if (!Arrays.equals(buff1, buff2))
+ return false;
+ } while (read1 >= 0 && read2 >= 0);
+ if (read1 < 0 && read2 < 0)
+ return true;
+ return false;
+
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ return false;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/I18nUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/I18nUtil.java
new file mode 100644
index 00000000000..9758975d8e3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/I18nUtil.java
@@ -0,0 +1,219 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Helper utiltiies for handling internationalization.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class I18nUtil {
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private I18nUtil() {
+ }
+
+ /**
+ * Returns the localized string associated with a resource key.
+ *
+ * @param resourceBundle
+ * A resource bundle.
+ * @param key
+ * A resource key.
+ * @return A localized string.
+ */
+ public static String getString(ResourceBundle resourceBundle, String key) {
+ if (resourceBundle != null) {
+ try {
+ return resourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the localized string associated with a resource key and formatted
+ * with a given string.
+ *
+ * @param resourceBundle
+ * A resource bundle.
+ * @param key
+ * A resource key.
+ * @param data
+ * An object.
+ * @return A formatted localized string.
+ */
+ public static String formatString(ResourceBundle resourceBundle,
+ String key, Object data) {
+ if (resourceBundle != null) {
+ try {
+ String localizedStr = resourceBundle.getString(key);
+ return MessageFormat
+ .format(localizedStr, new Object[] { data });
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the localized string associated with a resource key and formatted
+ * with two given string.
+ *
+ * @param resourceBundle
+ * A resource bundle.
+ * @param key
+ * A resource key.
+ * @param data1
+ * An object.
+ * @param data2
+ * An object.
+ * @return A formatted localized string.
+ */
+ public static String formatString(ResourceBundle resourceBundle,
+ String key, Object data1, Object data2) {
+ if (resourceBundle != null) {
+ try {
+ String localizedStr = resourceBundle.getString(key);
+ return MessageFormat.format(localizedStr, new Object[] { data1,
+ data2 });
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the localized string associated with a resource key and formatted
+ * with a given string.
+ *
+ * @param resourceBundle
+ * A resource bundle.
+ * @param key
+ * A resource key.
+ * @param data
+ * An array of objects.
+ * @return A formatted localized string.
+ */
+ public static String formatString(ResourceBundle resourceBundle,
+ String key, Object[] data) {
+ if (resourceBundle != null) {
+ try {
+ String localizedStr = resourceBundle.getString(key);
+ return MessageFormat.format(localizedStr, data);
+ } catch (MissingResourceException e) {
+ }
+ }
+ return '[' + key + ']';
+ }
+
+ /**
+ * Returns the localized integer value associated with a resource key.
+ *
+ * @param resourceBundle
+ * A resource bundle.
+ * @param key
+ * A resource key.
+ * @param defaultValue
+ * The default value to return if the resource key cannot be
+ * located.
+ * @return A localized interger value.
+ */
+ public static int getInt(String intString,
+ int defaultValue) {
+ try {
+ if (intString != null) {
+ return Integer.parseInt(intString);
+ }
+ } catch (Exception e) {
+ }
+ return defaultValue;
+ }
+
+ /**
+ * Returns the localized version of a US English resource file.
+ *
+ * @param path
+ * The absolute path to a resource file.
+ * @param locale
+ * A locale.
+ * @return The localized resource file. If none exists, return null.
+ */
+ public static String getLocalizedFile(String path, Locale locale) {
+ if (locale.equals(Locale.US) || path == null) {
+ return null;
+ }
+
+ // Build the locale string array. This is used to construct the
+ // localized file names.
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+
+ String[] localeStrs = new String[3];
+ if (variant != null && variant.length() > 0) {
+ localeStrs[0] = locale.toString();
+ }
+ if (country != null && country.length() > 0) {
+ localeStrs[1] = language + "_" + country; //$NON-NLS-1$
+ }
+ if (language != null) {
+ localeStrs[2] = language;
+ }
+
+ String dir = path.replace('\\', '/');
+ String fileName;
+
+ int pathIndex = dir.lastIndexOf("/"); //$NON-NLS-1$
+ if (pathIndex > 0) {
+ dir = path.substring(0, pathIndex + 1);
+ fileName = path.substring(pathIndex + 1);
+ } else {
+ fileName = dir;
+ dir = ""; //$NON-NLS-1$
+ }
+
+ String fileExt = ""; //$NON-NLS-1$
+ int extIndex = fileName.lastIndexOf("."); //$NON-NLS-1$
+ if (extIndex > 0) {
+ fileExt = fileName.substring(extIndex);
+ fileName = fileName.substring(0, extIndex);
+ }
+
+ fileName = dir + fileName + "_"; //$NON-NLS-1$
+
+ // Look for the localized file.
+ for (int i = 0; i < 3; i++) {
+ if (localeStrs[i] != null) {
+ // Gets the localized path name.
+ String fname = fileName + localeStrs[i] + fileExt;
+ File file = new File(fname);
+ if (file.exists()) {
+ return fname;
+ }
+ }
+ }
+
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IMarkerAttributeContributer.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IMarkerAttributeContributer.java
new file mode 100644
index 00000000000..ceba9ebd156
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IMarkerAttributeContributer.java
@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+//Copyright (c) 2005, 2008 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.common.utils;
+
+import org.eclipse.core.resources.IMarker;
+
+/**
+* Interface for adding additional attributes to markers
+*
+* @author Weiping Lu
+* @since 1.5
+*/
+public interface IMarkerAttributeContributer {
+
+ void addAddtionalAttributes(IMarker marker, Object context);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IObjectFactory.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IObjectFactory.java
new file mode 100644
index 00000000000..21d93d3e722
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/IObjectFactory.java
@@ -0,0 +1,23 @@
+//------------------------------------------------------------------------------
+//Copyright (c) 2005, 2008 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.common.utils;
+
+/**
+* Interface to create object based on type and context
+*
+* @author Weiping Lu
+* @since 1.5
+*/
+public interface IObjectFactory {
+
+ Object create(Class type, Object context);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ImageUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ImageUtil.java
new file mode 100644
index 00000000000..9af9c4fb740
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ImageUtil.java
@@ -0,0 +1,179 @@
+//------------------------------------------------------------------------------
+// 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.common.utils;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.font.FontRenderContext;
+import java.awt.font.LineBreakMeasurer;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for creating image files.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class ImageUtil {
+
+ // The BufferedImage cache.
+ private static HashMap<String, BufferedImage> imageCache = new HashMap<String, BufferedImage>();
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private ImageUtil() {
+ }
+
+ /**
+ * Creates a <code>BufferedImage</code> from the given image file.
+ *
+ * @param imageFile
+ * an image file
+ * @param c
+ * an AWT component
+ */
+ public static BufferedImage getBufferedImage(String imageFile, Component c) {
+ if (imageFile == null || c == null) {
+ return null;
+ }
+
+ BufferedImage bufferedImage = (BufferedImage) imageCache.get(imageFile);
+ if (bufferedImage != null) {
+ return bufferedImage;
+ }
+
+ Image image = c.getToolkit().getImage(imageFile);
+ MediaTracker tracker = new MediaTracker(c);
+ tracker.addImage(image, 0);
+ try {
+ tracker.waitForAll();
+ } catch (InterruptedException e) {
+ }
+
+ bufferedImage = new BufferedImage(image.getWidth(c),
+ image.getHeight(c), BufferedImage.TYPE_INT_ARGB);
+
+ Graphics2D g2d = bufferedImage.createGraphics();
+ g2d.drawImage(image, 0, 0, c);
+ imageCache.put(imageFile, bufferedImage);
+
+ return bufferedImage;
+ }
+
+ /**
+ * Returns <code>true</code> if the given image is loaded successfully.
+ *
+ * @param image
+ * an AWT image
+ * @param c
+ * an AWT component
+ */
+ public static boolean waitForImage(Image image, Component c) {
+ MediaTracker tracker = new MediaTracker(c);
+ tracker.addImage(image, 0);
+ try {
+ tracker.waitForAll();
+ } catch (InterruptedException ie) {
+ }
+ return (!tracker.isErrorAny());
+ }
+
+ /**
+ * Draws the given text.
+ *
+ * @param g2d
+ * the <code>Graphics2D</code> context
+ * @param text
+ * the text to be rendered
+ * @param font
+ * the font used for rendering the text
+ * @param color
+ * the color used for rendering the text
+ * @param x
+ * the horizontal coordinate used for rendering the text
+ * @param y
+ * the verticalcoordinate used for rendering the text
+ */
+ public static void drawText(Graphics2D g2d, String text, Font font,
+ Color color, int x, int y) {
+ if (text == null || text.length() == 0) {
+ return;
+ }
+ g2d.setColor(color);
+ FontRenderContext frc = g2d.getFontRenderContext();
+ TextLayout textlayout = new TextLayout(text, font, frc);
+ textlayout.draw(g2d, x, y);
+ }
+
+ /**
+ * Draws the given text and wraps it based on the given width.
+ *
+ * @param g2d
+ * the <code>Graphics2D</code> context
+ * @param text
+ * the text to be rendered
+ * @param font
+ * the font used for rendering the text
+ * @param color
+ * the color used for rendering the text
+ * @param x
+ * the horizontal coordinate used for rendering the text
+ * @param y
+ * the verticalcoordinate used for rendering the text
+ * @param width
+ * the maximum width used for wrapping the text
+ * @param maxLine
+ * the maximum number of line of wrapped text
+ */
+ public static void drawText(Graphics2D g2d, String text, Font font,
+ Color color, int x, int y, float width, int maxLine) {
+ if (text == null || text.length() == 0) {
+ return;
+ }
+ float maxWrapWidth = width - 10;
+ g2d.setColor(color);
+ Point2D.Float pen = new Point2D.Float(x, y);
+ Map<TextAttribute, Font> attributes = new HashMap<TextAttribute, Font>();
+ attributes.put(TextAttribute.FONT, font);
+ AttributedCharacterIterator textIterator = new AttributedString(text,
+ attributes).getIterator();
+ FontRenderContext frc = g2d.getFontRenderContext();
+ LineBreakMeasurer measurer = new LineBreakMeasurer(textIterator, frc);
+ int line = 1;
+ while (line <= maxLine) {
+ TextLayout layout = measurer.nextLayout(maxWrapWidth);
+ if (layout == null)
+ break;
+ pen.y += layout.getAscent();
+ float dx = 0;
+ if (layout.isLeftToRight()) {
+ dx = (width - layout.getAdvance());
+ }
+ layout.draw(g2d, pen.x + dx / 2, pen.y);
+ pen.y += layout.getDescent() + layout.getLeading() - 1;
+ line++;
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/MathUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/MathUtil.java
new file mode 100644
index 00000000000..0ad88f943e2
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/MathUtil.java
@@ -0,0 +1,25 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+/**
+ * Utility class for performing math operations.
+ *
+ * @author Phong Nguyen Le
+ * @since 1.0
+ */
+public class MathUtil {
+
+ public static final long ceil1000(long l) {
+ return (l - (l & 7));
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/NetUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/NetUtil.java
new file mode 100644
index 00000000000..b12f20edf37
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/NetUtil.java
@@ -0,0 +1,400 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+
+/**
+ * Implements a utility class for managing URLs and URIs.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class NetUtil {
+
+ /**
+ * FILE scheme.
+ */
+ public final static String FILE_SCHEME = "file"; //$NON-NLS-1$
+
+ /**
+ * File URI prefix.
+ */
+ public final static String FILE_URI_PREFIX = FILE_SCHEME + ":/"; //$NON-NLS-1$
+
+ /**
+ * File URI prefix size.
+ */
+ public final static int FILE_URI_PREFIX_LENGTH = FILE_URI_PREFIX.length();
+
+ /**
+ * HTTP scheme.
+ */
+ public final static String HTTP_SCHEME = "http"; //$NON-NLS-1$
+
+ /**
+ * HTTP URI prefix.
+ */
+ public final static String HTTP_URI_PREFIX = HTTP_SCHEME + "://"; //$NON-NLS-1$
+
+ /**
+ * HTTP URI prefix size.
+ */
+ public final static int HTTP_URI_PREFIX_LENGTH = HTTP_URI_PREFIX.length();
+
+ public static final String FILE_PREFIX_2 = "file://"; //$NON-NLS-1$
+
+ public static final String FILE_PREFIX_3 = "file:///"; //$NON-NLS-1$
+
+ /**
+ * A table of hex values.
+ */
+ private final static String[] HEX_VALUES = {
+ "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%38", "%39", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%48", "%49", "%4A", "%4B", "%4C", "%4D", "%4E", "%4F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%58", "%59", "%5A", "%5B", "%5C", "%5D", "%5E", "%5F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%68", "%69", "%6A", "%6B", "%6C", "%6D", "%6E", "%6F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%78", "%79", "%7A", "%7B", "%7C", "%7D", "%7E", "%7F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ "%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
+ };
+
+ public static final String RAW_URL_RAW = "raw_URL_raw"; //$NON-NLS-1$
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private NetUtil() {
+ }
+
+ /**
+ * Returns the URI for the given file.
+ *
+ * @param file
+ * The input file.
+ * @return The URI for the given file.
+ * @throws MalformedURLException
+ * if an error occur while constructing the URI for the given
+ * file.
+ */
+ public static String getUri(File file) throws MalformedURLException {
+ String url = file.toURL().toExternalForm();
+ StringBuffer strBuf = new StringBuffer();
+ int urlLength = url.length();
+ for (int i = 0; i < urlLength; i++) {
+ char ch = url.charAt(i);
+ switch (ch) {
+ case ' ':
+ strBuf.append("%20"); //$NON-NLS-1$
+ break;
+ default:
+ strBuf.append(ch);
+ break;
+ }
+ }
+ return strBuf.toString();
+ }
+
+ /**
+ * Resolves the given URI using the given the base URI.
+ *
+ * @param uri
+ * The URI to resolve.
+ * @param baseUri
+ * The base URI.
+ * @return A fully formed URI.
+ */
+ public static String resolveUri(String uri, String baseUri) {
+ if (uri == null) {
+ return null;
+ }
+
+ if (uri.startsWith("../")) { //$NON-NLS-1$
+ if (baseUri.endsWith("/")) { //$NON-NLS-1$
+ baseUri = baseUri.substring(0, baseUri.length() - 1);
+ }
+ while (uri.startsWith("../")) { //$NON-NLS-1$
+ uri = uri.substring(3);
+ int index = baseUri.lastIndexOf('/');
+ if (index > 0) {
+ baseUri = baseUri.substring(0, index);
+ }
+ }
+ uri = "/" + uri; //$NON-NLS-1$
+ }
+
+ if (uri.startsWith("/")) { //$NON-NLS-1$
+ return baseUri.endsWith("/") //$NON-NLS-1$
+ ? baseUri + uri.substring(1) : baseUri + uri;
+ }
+
+ if (uri.startsWith(FILE_URI_PREFIX) || uri.startsWith(HTTP_URI_PREFIX)) {
+ return uri;
+ }
+
+ return baseUri.endsWith("/") ? baseUri + uri : baseUri + '/' + uri; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the input stream for the given URI.
+ *
+ * @param uri
+ * The source URI.
+ * @return The input stream for the given URI.
+ * @throw MalformedURLException if a given XML document URI is invalid.
+ * @throw IOException if an I/O error occur while accessing the URI.
+ */
+ public static InputStream getInputStream(String uri)
+ throws MalformedURLException, IOException {
+ if (uri == null) {
+ return null;
+ }
+
+ if (uri.startsWith(HTTP_URI_PREFIX)) {
+ URL url = new URL(uri);
+ return url.openStream();
+ } else if (uri.startsWith(FILE_URI_PREFIX)) {
+ uri = uri.substring(FILE_URI_PREFIX_LENGTH);
+ }
+
+ return new FileInputStream(NetUtil.decodeUrl(uri, null));
+ }
+
+ /**
+ * Returns the Java string represention (encoded in UTF-16) of the given URL
+ * (encoded in the given encoding and ASCII-escaped).
+ *
+ * @param url
+ * The URL to decode.
+ * @param encoding
+ * The encoding of the URL.
+ * @return The Java UTF-16 string respresentation.
+ * @throws IllegalArgumentException
+ * if the given URL contain improperly escaped characters.
+ */
+ public static String decodeUrl(String url, String encoding) {
+ if (url == null) {
+ return url;
+ }
+
+ int len = url.length();
+ if (len == 0) {
+ return url;
+ }
+
+ // Unescape the url.
+ StringBuffer strBuf = new StringBuffer();
+ for (int i = 0; i < len; i++) {
+ char ch = url.charAt(i);
+ switch (ch) {
+ case '+':
+ strBuf.append(' ');
+ break;
+ case '%':
+ try {
+ strBuf.append((char) Integer.parseInt(url.substring(i + 1,
+ i + 3), 16));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException();
+ }
+ i += 2;
+ break;
+ default:
+ strBuf.append(ch);
+ break;
+ }
+ }
+
+ // Convert the un-escaped byte values to Java UTF-16 string.
+ String result = strBuf.toString();
+ if (encoding != null) {
+ try {
+ byte[] bytes = result.getBytes("8859_1"); //$NON-NLS-1$
+ result = new String(bytes, encoding);
+ } catch (UnsupportedEncodingException e) {
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns the ASCII-escaped representation (encoded in the specified
+ * encoding) of the given URL (encoded in UTF-16).
+ *
+ * @param url
+ * The URL to encode.
+ * @param encoding
+ * The encoding of the URL.
+ * @return the ASCII-escaped respresentation.
+ * @throws IllegalArgumentException
+ * if the given URL contain improperly escaped characters.
+ * @throws UnsupportedEncodingException
+ * if the given coding is unsupport.
+ */
+ public static String encodeUrl(String url, String encoding)
+ throws UnsupportedEncodingException {
+ if (url == null) {
+ return url;
+ }
+ int len = url.length();
+ if (len == 0) {
+ return url;
+ }
+
+ StringBuffer result = new StringBuffer();
+
+ byte[] bytes = url.getBytes(encoding);
+ for (int i = 0; i < bytes.length; i++) {
+ char ch = (char) bytes[i];
+
+ if (ch >= 'a' && ch <= 'z') {
+ result.append(ch);
+ } else if (ch >= 'A' && ch <= 'Z') {
+ result.append(ch);
+ } else if (ch >= '0' && ch <= '9') {
+ result.append(ch);
+ } else {
+ switch (ch) {
+ case '-':
+ case '_':
+ case '.':
+ case '!':
+ case '~':
+ case '*':
+ case '\'':
+ case '(':
+ case ')':
+ result.append(ch);
+ break;
+ default:
+ result.append(HEX_VALUES[ch & 0xFF]);
+ break;
+ }
+ }
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Returns the ASCII-escaped representation of the given file URL.
+ *
+ * @param fileURL
+ * The file URL to encode.
+ * @return the ASCII-escaped respresentation.
+ */
+ public static String encodeFileURL(String fileURL) {
+ String url = fileURL;
+ StringBuffer strBuf = new StringBuffer();
+ int urlLength = url.length();
+ for (int i = 0; i < urlLength; i++) {
+ char ch = url.charAt(i);
+ switch (ch) {
+ case ' ':
+ strBuf.append("+"); //$NON-NLS-1$
+ break;
+ default:
+ strBuf.append(ch);
+ break;
+ }
+ }
+ return strBuf.toString();
+ }
+
+ /**
+ * Returns the ASCII-escaped representation of the given file URL.
+ *
+ * @param fileURL
+ * The file URL to encode.
+ * @return the ASCII-escaped respresentation.
+ */
+ public static String decodedFileUrl(String fileURL) {
+ if (isRawUrl(fileURL)) {
+ return fileURL;
+ }
+
+ String url = fileURL;
+ StringBuffer strBuf = new StringBuffer();
+ int urlLength = url.length();
+ for (int i = 0; i < urlLength; i++) {
+ char ch = url.charAt(i);
+ switch (ch) {
+ case '+':
+ strBuf.append(' ');
+ break;
+ case '%':
+ try {
+ strBuf.append((char) Integer.parseInt(url.substring(i + 1,
+ i + 3), 16));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException();
+ }
+ i += 2;
+ break;
+ default:
+ strBuf.append(ch);
+ break;
+ }
+ }
+ return strBuf.toString();
+ }
+
+ public static String decodeURL (String url) throws UnsupportedEncodingException {
+// url = url.replaceAll("\\+", "%2B"); //$NON-NLS-1$
+ url = URLDecoder.decode(url, "UTF-8"); //$NON-NLS-1$
+ return url;
+ }
+
+ public static boolean isRawUrl(String url) {
+ boolean result = false;
+
+ if (url.endsWith(RAW_URL_RAW)) {
+ result = true;
+ }
+
+ return result;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ProfilingUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ProfilingUtil.java
new file mode 100644
index 00000000000..db94b48b4b1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ProfilingUtil.java
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+import java.io.PrintStream;
+
+
+/**
+ * Utility class for profiling
+ *
+ * @author Weiping Lu
+ * @since 1.0
+ */
+
+public class ProfilingUtil {
+
+ public static boolean traceFootprint = false;
+
+ private static PrintStream output = System.out;
+
+ public static void setOutput(PrintStream ps) {
+ output = ps;
+ }
+
+ public static void fullGC() {
+ Runtime rt = Runtime.getRuntime();
+ long isFree = rt.freeMemory();
+ long wasFree;
+ do {
+ wasFree = isFree;
+ rt.runFinalization();
+ rt.gc();
+ isFree = rt.freeMemory();
+ } while (isFree > wasFree);
+ }
+
+ public static long traceUsedMemory(String location) {
+ Runtime rt = Runtime.getRuntime();
+ long usedMem = rt.totalMemory() - rt.freeMemory();
+ output.println("Footprint> " + location + ": " + usedMem/1000 + " K"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ return usedMem;
+ }
+
+ public static long traceUsedMemoryDiff(String locationInfo, long currUsed, long PrevUsed) {
+ long diff = currUsed - PrevUsed;
+ output.println("Footprint> Diff, " + locationInfo + ": " + diff/1000 + " K\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ return diff;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/RestartableJob.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/RestartableJob.java
new file mode 100644
index 00000000000..c60e94cc1c6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/RestartableJob.java
@@ -0,0 +1,123 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2008 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.common.utils;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * Job class that is re-startable
+ *
+ * @author Weiping Lu
+ * @since 1.5
+ */
+
+public abstract class RestartableJob extends Job {
+
+ protected static boolean localDebug = false;
+
+ private boolean toRestart = true;
+ private boolean schedulingLocked = false;
+ private boolean enabled = true;
+
+ public RestartableJob(String name) {
+ super(name);
+ }
+
+ public final void guardedSchedule(long delay) {
+ guardedSchedule(delay, false);
+ }
+
+ private void guardedSchedule(long delay, boolean inRunCall) {
+ if ( ! isEnabled()) {
+ return;
+ }
+ if (!inRunCall && getState() != Job.NONE) {
+ return;
+ }
+ if (isSchedulingLocked()) {
+ return;
+ }
+ if (localDebug) {
+ System.out.println("LD> guardedSchedule completed"); //$NON-NLS-1$
+ }
+ setSchedulingLocked(true);
+ schedule(delay);
+ }
+
+ protected final IStatus run(IProgressMonitor monitor) {
+ if (localDebug) {
+ System.out.println("LD> RestartableJob.run"); //$NON-NLS-1$
+ }
+ setSchedulingLocked(false);
+ setToRestart(false);
+ IStatus status = Status.OK_STATUS;
+ try {
+ status = restartableRun(monitor);
+ } catch (RestartInterruptException e) {
+ guardedSchedule(e.getDelay(), true);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ protected abstract IStatus restartableRun(IProgressMonitor monitor) throws RestartInterruptException;
+ protected abstract void resetToRestart();
+
+ private synchronized boolean isSchedulingLocked() {
+ return schedulingLocked;
+ }
+
+ private synchronized void setSchedulingLocked(boolean schedulingLocked) {
+ this.schedulingLocked = schedulingLocked;
+ }
+
+ private synchronized boolean isToRestart() {
+ return toRestart;
+ }
+
+ private synchronized void setToRestart(boolean toRestart) {
+ this.toRestart = toRestart;
+ }
+
+ public void enableToRestart() {
+ setToRestart(true);
+ }
+
+ public void checkRestartInterruptException(long delay) throws RestartInterruptException {
+ if (isToRestart()) {
+ resetToRestart();
+ throw new RestartInterruptException(delay);
+ }
+ }
+
+ public static class RestartInterruptException extends Exception {
+ private long delay = 0;
+ public RestartInterruptException(long delay) {
+ this.delay = delay;
+ }
+
+ public long getDelay() {
+ return delay;
+ }
+ }
+
+ public synchronized boolean isEnabled() {
+ return enabled;
+ }
+
+ public synchronized void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StrUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StrUtil.java
new file mode 100644
index 00000000000..b4fd0c17f65
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StrUtil.java
@@ -0,0 +1,676 @@
+//------------------------------------------------------------------------------
+// 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.common.utils;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.CommonPlugin;
+
+import com.ibm.icu.lang.UCharacter;
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * A helper class for manuipulating strings.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @since 1.0
+ */
+public class StrUtil {
+ public static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ public static final String TAB = "\t"; //$NON-NLS-1$
+
+ private static final String REGEXP_ANY_SPECIAL_CHARS = "(`|~|!|@|#|\\$|%|\\^|&|\\*|\\(|\\)|\\+|=|\\[|\\]|\\||\\:|\"|<|>|\\?|/|'|\\s|\\\\)+"; //$NON-NLS-1$
+
+ private static final String REGEXP_INVALID_PUBLISHED_PATH_CHARS = "(\\[|#|\\*|\\?|\"|<|>|\\||!|%|/|\\])+"; //$NON-NLS-1$
+
+ private static final String REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX = "(\\[|#|\\*|\\?|\"|<|>|\\||!|%|\\])+"; //$NON-NLS-1$
+
+ private static final String REGEXP_INVALID_FILENAME_CHARS = "(\\[|#|/|\\\\|\\:|\\*|\\?|\"|<|>|\\||\\]|\\s)+"; //$NON-NLS-1$
+
+ private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ public static final String LINE_FEED = System.getProperty("line.separator"); //$NON-NLS-1$
+
+ public static final String ESCAPED_LF = "&#xA;"; //$NON-NLS-1$
+
+ public static final String ESCAPED_CR = "&#xD;"; //$NON-NLS-1$
+
+ public static final String ESCAPED_LINE_FEED = LINE_FEED.replace(
+ "\n", ESCAPED_LF).replace("\r", ESCAPED_CR); //$NON-NLS-1$ //$NON-NLS-2$
+
+ public static final String LINE_FEED_REGEX = LINE_FEED.replaceAll(
+ "\\\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ public static final String ESCAPED_LINE_FEED_REGEX = ESCAPED_LINE_FEED;
+
+ public static final String HTML_BREAK = "<br/>";//$NON-NLS-1$
+
+ public static final String HTML_COPY = "&copy;";//$NON-NLS-1$
+
+ public static final String HTML_EURO = "&euro;";//$NON-NLS-1$
+
+ public static final String HTML_REG = "&reg;";//$NON-NLS-1$
+
+ public static final String HTML_TRADEMARK = "&trade;";//$NON-NLS-1$
+
+ public static boolean during_migration = false;
+
+ private static StrUtilOptions options;
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private StrUtil() {
+ }
+
+ /**
+ * Tests for null string.
+ * <p>
+ * A null string is defined as one that has an empty reference or has zero
+ * length.
+ *
+ * @param str
+ * a string
+ * @return <code>true</code> if the given string is a null string
+ */
+ public static boolean isNull(String str) {
+ return str == null || str.length() == 0;
+ }
+
+ /**
+ * Tests for blank string.
+ * <p>
+ * A blank string is defined as one that has an empty reference or has zero
+ * length after the leading and trailing space characters are trimmed.
+ *
+ * @param str
+ * a string
+ * @return <code>true</code> if the given string is a blank string
+ */
+ public static boolean isBlank(String str) {
+ return str == null || str.trim().length() == 0;
+ }
+
+ /**
+ * Removes the leading and trailing space characters from a string.
+ *
+ * @param str
+ * a string
+ * @return a string with no leading and trailing space characters
+ */
+ public static String trim(String str) {
+ return str == null ? null : str.trim();
+ }
+
+ /**
+ * Removes whitespace characters (TAB, CR, LF and SPACE) from a string.
+ *
+ * @param str
+ * a string
+ * @return a string with whitespace characters removed
+ */
+ public static String removeWhiteSpaceChars(String str) {
+ int len = (str == null) ? 0 : str.length();
+ for (int i = 0; i < len; i++) {
+ switch (str.charAt(i)) {
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ break;
+ default:
+ return str;
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Removes CR, LF from a string.
+ *
+ * @param str
+ * a string
+ * @return a string with CR, LF removed
+ */
+ public static String removeNewlines(String str) {
+ StringBuffer sb = new StringBuffer();
+ int len = (str == null) ? 0 : str.length();
+ for (int i = 0; i < len; i++) {
+ char c = str.charAt(i);
+ switch (c) {
+ case '\r':
+ case '\n':
+ break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Splits a string into an array of string tokens.
+ *
+ * @param str
+ * a string
+ * @param sep
+ * a string containing the string separators
+ * @param count
+ * the desired number of string tokens
+ * @return an array of string tokens
+ */
+ public static String[] split(String str, String sep, int count) {
+ if (str == null || count == 0 || count < -1) {
+ return null;
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(str, sep,
+ count == -1 ? false : true);
+
+ if (count == -1) {
+ count = tokenizer.countTokens();
+ }
+
+ String[] result = new String[count];
+ int i = 0;
+ while (tokenizer.hasMoreTokens()) {
+ String t = tokenizer.nextToken();
+ if (i < count) {
+ if ((t.length() == 1) && (sep.indexOf(t) != -1)) {
+ continue;
+ }
+ result[i++] = t;
+ } else {
+ result[count - 1] += t;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Splits a string into an array of string tokens.
+ *
+ * @param str
+ * a string
+ * @param sep
+ * a string containing the string separators
+ * @return an array of string tokens
+ */
+ public static String[] split(String str, String sep) {
+ return split(str, sep, -1);
+ }
+
+ /**
+ * Replaces a substring within a string with another substring.
+ * <p>
+ * Note: Only the first occurrence of the substring will be replaced.
+ *
+ * @param str
+ * a string
+ * @param src
+ * the substring to replace
+ * @param tgt
+ * the substring to use for the replacement
+ * @return a string with the first substring replaced
+ *
+ * TODO: Review implementation. Call String.replaceFirst() instead?
+ */
+ public static String replace(String str, String src, String tgt) {
+ if ((str == null || str.length() == 0)
+ || (src == null || src.length() == 0)) {
+ return str;
+ }
+
+ String tmpStr = str;
+ int index;
+ while ((index = tmpStr.indexOf(src)) != -1) {
+ tmpStr = tmpStr.substring(0, index) + tgt
+ + tmpStr.substring(index + src.length());
+ }
+ return tmpStr;
+ }
+
+ /**
+ * Returns the integer value of a string.
+ *
+ * @param str
+ * a string
+ * @param defaultValue
+ * a default integer value for the string
+ * @return the integer value of the given string
+ */
+ public static int getIntValue(String str, int defaultValue) {
+ if (StrUtil.isBlank(str)) {
+ return defaultValue;
+ }
+
+ try {
+ return Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns an array of bytes representing the UTF-8 encoding of a string.
+ *
+ * @param str
+ * a string
+ * @return a byte array containing the UTF-8 encoding of the given string
+ */
+ public static byte[] getUTF8Bytes(String str) {
+ char[] c = str.toCharArray();
+ int len = c.length;
+ int count = 0;
+ for (int i = 0; i < len; i++) {
+ int ch = c[i];
+ if (ch <= 0x7f) {
+ count++;
+ } else if (ch <= 0x7ff) {
+ count += 2;
+ } else {
+ count += 3;
+ }
+ }
+
+ byte[] b = new byte[count];
+ int off = 0;
+ for (int i = 0; i < len; i++) {
+ int ch = c[i];
+ if (ch <= 0x7f) {
+ b[off++] = (byte) ch;
+ } else if (ch <= 0x7ff) {
+ b[off++] = (byte) ((ch >> 6) | 0xc0);
+ b[off++] = (byte) ((ch & 0x3f) | 0x80);
+ } else {
+ b[off++] = (byte) ((ch >> 12) | 0xe0);
+ b[off++] = (byte) (((ch >> 6) & 0x3f) | 0x80);
+ b[off++] = (byte) ((ch & 0x3f) | 0x80);
+ }
+ }
+ return b;
+ }
+
+ /**
+ * Returns the hexidecimal character representation for an integer.
+ *
+ * @param value
+ * an integer
+ * @return the hexidecimal representation
+ */
+ private static char toHex(int value) {
+ return HEX_DIGITS[(value & 0xF)];
+ }
+
+ /**
+ * Returns the escaped Unicode representation of a string.
+ *
+ * @param str
+ * a string
+ * @param skipASCII
+ * if <code>true</code>, avoid escaping the ASCII characters
+ * @return the escaped Unicode representation of the given string
+ */
+ public static String toEscapedUnicode(String str, boolean skipASCII) {
+ int len = str.length();
+ StringBuffer result = new StringBuffer(len * 2);
+
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+
+ if (skipASCII && ch < 0x007E) {
+ result.append(ch);
+ } else {
+ result.append("\\u"); //$NON-NLS-1$
+ result.append(toHex((ch >> 12) & 0xF));
+ result.append(toHex((ch >> 8) & 0xF));
+ result.append(toHex((ch >> 4) & 0xF));
+ result.append(toHex(ch & 0xF));
+ }
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Returns the escaped HTML representation of a string.
+ *
+ * @param html
+ * a HTML string
+ * @return the escaped Unicode representation of the given HTML string
+ */
+ public static String getEscapedHTML(String html) {
+ if (html == null || html.length() == 0) {
+ return ""; //$NON-NLS-1$
+ }
+
+ StrUtilOptions options = getOptions();
+ StringBuffer result = new StringBuffer();
+ int length = html.length();
+ for (int i = 0; i < length; i++) {
+ char ch = html.charAt(i);
+ switch (ch) {
+ case '%':
+ if (i + 4 < length) {
+ String hexStr = html.substring(i + 1, i + 5);
+ boolean validHextStr = true;
+
+ for (int j = 0; j < hexStr.length(); j++) {
+ char c = hexStr.charAt(j);
+ if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) {
+ validHextStr = false;
+ break;
+ }
+ }
+
+ if (options == null) {
+ //code below will treat "%20de" as " de"
+ //this may lose some double bytes character(e.g. Chinese), which start with %20, but keep all url links
+ //so far open this convertion not only during library migration to support file like "my design.gif"
+ if (/*during_migration && */validHextStr) {
+ if (hexStr.startsWith("20")) { //$NON-NLS-1$
+ result.append("%20"); //$NON-NLS-1$
+ i += 2;
+ break;
+ }
+ }
+ } else {
+ int ix = options.getRteUrlDecodingOption();
+ if (ix == 1) {
+ validHextStr = false;
+ } else if (ix == 2) {
+ String key = getHexStr("%" + hexStr);
+ if (key != null && options.getRteUrlDecodingHexMap().containsKey(key)) {
+ validHextStr = false;
+ }
+ }
+ }
+
+ if (validHextStr) {
+ try {
+ int codePoint = Integer.parseInt(hexStr, 16);
+ char[] c = UCharacter.toChars(codePoint);
+ result.append(c);
+ i += 4;
+ break;
+ } catch (NumberFormatException e) {
+ // wasn't a valid hex string..
+ // fall through to the result.append(ch)
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ }
+ result.append(ch);
+ break;
+ case '\u00a9':
+ result.append(HTML_COPY);
+ break;
+ case '\u00ae':
+ result.append(HTML_REG);
+ break;
+ case '\u20ac':
+ result.append(HTML_EURO);
+ break;
+ case '\u2122':
+ result.append(HTML_TRADEMARK);
+ break;
+ default:
+ result.append(ch);
+ break;
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns the plain text from HTML text.
+ * <p>
+ * Note: All HTML tags will be stripped.
+ *
+ * @param html
+ * the HTML text.
+ * @return the plain text representation of the given HTML text
+ */
+ public static String getPlainText(String html) {
+ if (html == null) {
+ return ""; //$NON-NLS-1$
+ }
+
+ final Pattern p_plaintext_filter = Pattern.compile(
+ "<[^>]*?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+ final Pattern p_plaintext_filter2 = Pattern.compile(
+ "&.{1,5}[^;];", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+ final Pattern p_plaintext_filter3 = Pattern.compile(
+ "\\s+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+
+ String result = html.replaceAll(p_plaintext_filter.pattern(), " ") //$NON-NLS-1$
+ .replaceAll(p_plaintext_filter2.pattern(), " ") //$NON-NLS-1$
+ .replaceAll(p_plaintext_filter3.pattern(), " "); //$NON-NLS-1$
+ return result;
+ }
+
+ /**
+ * Converts a string into a valid file name.
+ *
+ * @param str
+ * a string
+ * @return a valid file name derived from the given string
+ */
+ public static String makeValidFileName(String str) {
+ if (str == null) {
+ return ""; //$NON-NLS-1$
+ }
+ return getPlainText(str)
+ .replaceAll(REGEXP_INVALID_FILENAME_CHARS, " ").trim(); //$NON-NLS-1$
+ }
+
+ public static String removeSpecialCharacters(String str) {
+ if (str == null) {
+ return ""; //$NON-NLS-1$
+ }
+ return getPlainText(str)
+ .replaceAll(REGEXP_ANY_SPECIAL_CHARS, " ").trim(); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns true if the path does not contain any invalid filename
+ * characters.
+ *
+ * @param path
+ * the file path
+ * @return <code>true</code> if the given path contains only valid
+ * filename characters
+ */
+ public static boolean isValidPublishPath(String path) {
+ // return path.replaceAll(invalidPublishPathCharsRegExp,
+ // "").equals(path);
+
+ if (Platform.getOS().equals(Platform.WS_WIN32)) {
+ return path
+ .replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS, "").equals(path); //$NON-NLS-1$
+ }
+
+ // else default to Linux
+ return path
+ .replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX, "").equals(path); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the lower-case of str unless the current locale is German
+ *
+ * @param str
+ * @return
+ */
+ public static String toLower(String str) {
+ if (Platform.getNL().startsWith("de")) { //$NON-NLS-1$
+ return str;
+ }
+ return str.toLowerCase();
+ }
+
+ /**
+ * escape the " and '
+ *
+ * @param str
+ * @return
+ */
+ public static String escape(String str) {
+ return str.replaceAll("'", "\\\\\'").replaceAll("\"", "\\\\\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+
+ /**
+ * Converts a <code>List</code> to an String array.
+ *
+ * @param list
+ * a <code>List</code>
+ * @return a String array
+ */
+ public static String[] convertListToStrArray(List list) {
+ if (list != null) {
+ int cnt = list.size();
+ String[] strArray = new String[cnt];
+
+ for (int i = 0; i < cnt; i++) {
+ String str = (String) list.get(i);
+ strArray[i] = new String(str);
+ }
+ return strArray;
+ } else {
+ return null;
+ }
+ }
+
+ public static boolean isValidName(String name) {
+ return name.replaceAll(REGEXP_ANY_SPECIAL_CHARS, "").equals(name); //$NON-NLS-1$
+ }
+
+ /**
+ * added some test code
+ *
+ * @param args
+ */
+ public static void main(String[] args) {
+
+ String text = "A&% `&# $~!@#$%^&*()_-+={}[\"]:|\\:;\"'<,>.?/ \t\r\nZ"; //$NON-NLS-1$
+
+ System.out.println("[" + text + "] <== text"); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println("[" + text.replaceAll(REGEXP_ANY_SPECIAL_CHARS, " ") //$NON-NLS-1$ //$NON-NLS-2$
+ + "] <== All"); //$NON-NLS-1$
+ System.out.println("[" //$NON-NLS-1$
+ + text.replaceAll(REGEXP_INVALID_FILENAME_CHARS, " ") //$NON-NLS-1$
+ + "] <== File Name"); //$NON-NLS-1$
+ System.out.println("[" //$NON-NLS-1$
+ + text.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS, " ") //$NON-NLS-1$
+ + "] <== path"); //$NON-NLS-1$
+ System.out.println("[" //$NON-NLS-1$
+ + text.replaceAll(REGEXP_INVALID_PUBLISHED_PATH_CHARS_LINUX,
+ " ") + "] <== path, Linux"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ System.out.println(""); //$NON-NLS-1$
+ }
+
+ /**
+ * Converts the platform line-separator (\n or \n\r or \r) to &lt;br/&gt;
+ *
+ * @param text
+ * @return
+ */
+ public static String convertNewlinesToHTML(String text) {
+ if (text != null) {
+ text = text.replaceAll(LINE_FEED_REGEX, HTML_BREAK + LINE_FEED);
+ text = text.replaceAll(ESCAPED_LINE_FEED_REGEX, HTML_BREAK
+ + ESCAPED_LINE_FEED);
+ }
+ return text;
+ }
+
+ public static URI toURI(String pathStr) {
+ if (pathStr != null && pathStr.length() > 0) {
+ IPath path = Path.fromOSString(pathStr);
+ try {
+ return path.toFile().toURI();
+ } catch (Exception e) {
+ CommonPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ return null;
+ }
+
+ public static String escapeChar(String text, char c) {
+ int i=text.indexOf(c);
+ if ( i < 0 ) {
+ return text;
+ }
+
+ int start = 0;
+ StringBuffer buffer = new StringBuffer();
+ while ( i > start ) {
+ buffer.append(text.substring(start, i)).append("\\"); //$NON-NLS-1$
+ start = i;
+ i=text.indexOf(c, start+1);
+ }
+
+ buffer.append(text.substring(start));
+
+ return buffer.toString();
+ }
+
+ public static String getHexStr(String str) {
+ if (str.length() < 3) {
+ return null;
+ }
+ if (str.charAt(0) != '%') {
+ return null;
+ }
+ StringBuffer b = new StringBuffer();
+ b.append('%');
+ for (int i = 1 ; i <= 2; i++) {
+ char c = str.charAt(i);
+ if (c >= 'a' && c <= 'z') {
+ c -= 'a';
+ c += 'A';
+ }
+ boolean valid = (c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'F');
+ if (!valid) {
+ return null;
+ }
+ b.append(c);
+ }
+
+ return b.toString();
+ }
+
+ public interface StrUtilOptions {
+ int getRteUrlDecodingOption();
+ Map<String, String> getRteUrlDecodingHexMap();
+ }
+
+ public static StrUtilOptions getOptions() {
+ return options;
+ }
+
+ public static void setOptions(StrUtilOptions options) {
+ StrUtil.options = options;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StringMatcher.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StringMatcher.java
new file mode 100644
index 00000000000..4a0b4b443aa
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/StringMatcher.java
@@ -0,0 +1,458 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 API and implementation
+ *******************************************************************************/
+package org.eclipse.epf.common.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * A string pattern matcher. Supports '*' and '?' wildcards.
+ */
+public class StringMatcher {
+ protected String fPattern;
+ protected int fLength; // pattern length
+ protected boolean fIgnoreWildCards;
+ protected boolean fIgnoreCase;
+ protected boolean fHasLeadingStar;
+ protected boolean fHasTrailingStar;
+ protected String fSegments[]; //the given pattern is split into * separated segments
+
+ /* boundary value beyond which we don't need to search in the text */
+ protected int fBound= 0;
+
+
+ protected static final char fSingleWildCard= '\u0000';
+
+ public static class Position {
+ int start; //inclusive
+ int end; //exclusive
+ public Position(int start, int end) {
+ this.start= start;
+ this.end= end;
+ }
+ public int getStart() {
+ return start;
+ }
+ public int getEnd() {
+ return end;
+ }
+ }
+ /**
+ * StringMatcher constructor takes in a String object that is a simple
+ * pattern. The pattern may contain '*' for 0 and many characters and
+ * '?' for exactly one character.
+ *
+ * Literal '*' and '?' characters must be escaped in the pattern
+ * e.g., "\*" means literal "*", etc.
+ *
+ * Escaping any other character (including the escape character itself),
+ * just results in that character in the pattern.
+ * e.g., "\a" means "a" and "\\" means "\"
+ *
+ * If invoking the StringMatcher with string literals in Java, don't forget
+ * escape characters are represented by "\\".
+ *
+ * @param pattern the pattern to match text against
+ * @param ignoreCase if true, case is ignored
+ * @param ignoreWildCards if true, wild cards and their escape sequences are ignored
+ * (everything is taken literally).
+ */
+ public StringMatcher(String pattern, boolean ignoreCase, boolean ignoreWildCards) {
+ if (pattern == null)
+ throw new IllegalArgumentException();
+ fIgnoreCase= ignoreCase;
+ fIgnoreWildCards= ignoreWildCards;
+ fPattern= pattern;
+ fLength= pattern.length();
+
+ if (fIgnoreWildCards) {
+ parseNoWildCards();
+ } else {
+ parseWildCards();
+ }
+ }
+ /**
+ * Find the first occurrence of the pattern between <code>start</code)(inclusive)
+ * and <code>end</code>(exclusive).
+ * @param text the String object to search in
+ * @param start the starting index of the search range, inclusive
+ * @param end the ending index of the search range, exclusive
+ * @return an <code>StringMatcher.Position</code> object that keeps the starting
+ * (inclusive) and ending positions (exclusive) of the first occurrence of the
+ * pattern in the specified range of the text; return null if not found or subtext
+ * is empty (start==end). A pair of zeros is returned if pattern is empty string
+ * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
+ * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
+ */
+ public StringMatcher.Position find(String text, int start, int end) {
+ if (text == null)
+ throw new IllegalArgumentException();
+
+ int tlen= text.length();
+ if (start < 0)
+ start= 0;
+ if (end > tlen)
+ end= tlen;
+ if (end < 0 ||start >= end )
+ return null;
+ if (fLength == 0)
+ return new Position(start, start);
+ if (fIgnoreWildCards) {
+ int x= posIn(text, start, end);
+ if (x < 0)
+ return null;
+ return new Position(x, x+fLength);
+ }
+
+ int segCount= fSegments.length;
+ if (segCount == 0)//pattern contains only '*'(s)
+ return new Position (start, end);
+
+ int curPos= start;
+ int matchStart= -1;
+ int i;
+ for (i= 0; i < segCount && curPos < end; ++i) {
+ String current= fSegments[i];
+ int nextMatch= regExpPosIn(text, curPos, end, current);
+ if (nextMatch < 0 )
+ return null;
+ if(i == 0)
+ matchStart= nextMatch;
+ curPos= nextMatch + current.length();
+ }
+ if (i < segCount)
+ return null;
+ return new Position(matchStart, curPos);
+ }
+ /**
+ * match the given <code>text</code> with the pattern
+ * @return true if matched eitherwise false
+ * @param text a String object
+ */
+ public boolean match(String text) {
+ return match(text, 0, text.length());
+ }
+ /**
+ * Given the starting (inclusive) and the ending (exclusive) positions in the
+ * <code>text</code>, determine if the given substring matches with aPattern
+ * @return true if the specified portion of the text matches the pattern
+ * @param text a String object that contains the substring to match
+ * @param start marks the starting position (inclusive) of the substring
+ * @param end marks the ending index (exclusive) of the substring
+ */
+ public boolean match(String text, int start, int end) {
+ if (null == text)
+ throw new IllegalArgumentException();
+
+ if (start > end)
+ return false;
+
+ if (fIgnoreWildCards)
+ return (end - start == fLength) && fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength);
+ int segCount= fSegments.length;
+ if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) // pattern contains only '*'(s)
+ return true;
+ if (start == end)
+ return fLength == 0;
+ if (fLength == 0)
+ return start == end;
+
+ int tlen= text.length();
+ if (start < 0)
+ start= 0;
+ if (end > tlen)
+ end= tlen;
+
+ int tCurPos= start;
+ int bound= end - fBound;
+ if ( bound < 0)
+ return false;
+ int i=0;
+ String current= fSegments[i];
+ int segLength= current.length();
+
+ /* process first segment */
+ if (!fHasLeadingStar){
+ if(!regExpRegionMatches(text, start, current, 0, segLength)) {
+ return false;
+ } else {
+ ++i;
+ tCurPos= tCurPos + segLength;
+ }
+ }
+ if ((fSegments.length == 1) && (!fHasLeadingStar) && (!fHasTrailingStar)) {
+ // only one segment to match, no wildcards specified
+ return tCurPos == end;
+ }
+ /* process middle segments */
+ while (i < segCount) {
+ current= fSegments[i];
+ int currentMatch;
+ int k= current.indexOf(fSingleWildCard);
+ if (k < 0) {
+ currentMatch= textPosIn(text, tCurPos, end, current);
+ if (currentMatch < 0)
+ return false;
+ } else {
+ currentMatch= regExpPosIn(text, tCurPos, end, current);
+ if (currentMatch < 0)
+ return false;
+ }
+ tCurPos= currentMatch + current.length();
+ i++;
+ }
+
+ /* process final segment */
+ if (!fHasTrailingStar && tCurPos != end) {
+ int clen= current.length();
+ return regExpRegionMatches(text, end - clen, current, 0, clen);
+ }
+ return i == segCount ;
+ }
+
+ /**
+ * This method parses the given pattern into segments seperated by wildcard '*' characters.
+ * Since wildcards are not being used in this case, the pattern consists of a single segment.
+ */
+ private void parseNoWildCards() {
+ fSegments= new String[1];
+ fSegments[0]= fPattern;
+ fBound= fLength;
+ }
+ /**
+ * Parses the given pattern into segments seperated by wildcard '*' characters.
+ */
+ private void parseWildCards() {
+ if(fPattern.startsWith("*"))//$NON-NLS-1$
+ fHasLeadingStar= true;
+ if(fPattern.endsWith("*")) {//$NON-NLS-1$
+ /* make sure it's not an escaped wildcard */
+ if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
+ fHasTrailingStar= true;
+ }
+ }
+
+ Vector<String> temp= new Vector<String>();
+
+ int pos= 0;
+ StringBuffer buf= new StringBuffer();
+ while (pos < fLength) {
+ char c= fPattern.charAt(pos++);
+ switch (c) {
+ case '\\':
+ if (pos >= fLength) {
+ buf.append(c);
+ } else {
+ char next= fPattern.charAt(pos++);
+ /* if it's an escape sequence */
+ if (next == '*' || next == '?' || next == '\\') {
+ buf.append(next);
+ } else {
+ /* not an escape sequence, just insert literally */
+ buf.append(c);
+ buf.append(next);
+ }
+ }
+ break;
+ case '*':
+ if (buf.length() > 0) {
+ /* new segment */
+ temp.addElement(buf.toString());
+ fBound += buf.length();
+ buf.setLength(0);
+ }
+ break;
+ case '?':
+ /* append special character representing single match wildcard */
+ buf.append(fSingleWildCard);
+ break;
+ default:
+ buf.append(c);
+ }
+ }
+
+ /* add last buffer to segment list */
+ if (buf.length() > 0) {
+ temp.addElement(buf.toString());
+ fBound += buf.length();
+ }
+
+ fSegments= new String[temp.size()];
+ temp.copyInto(fSegments);
+ }
+ /**
+ * @param text a string which contains no wildcard
+ * @param start the starting index in the text for search, inclusive
+ * @param end the stopping point of search, exclusive
+ * @return the starting index in the text of the pattern , or -1 if not found
+ */
+ protected int posIn(String text, int start, int end) {//no wild card in pattern
+ int max= end - fLength;
+
+ if (!fIgnoreCase) {
+ int i= text.indexOf(fPattern, start);
+ if (i == -1 || i > max)
+ return -1;
+ return i;
+ }
+
+ for (int i= start; i <= max; ++i) {
+ if (text.regionMatches(true, i, fPattern, 0, fLength))
+ return i;
+ }
+
+ return -1;
+ }
+ /**
+ * @param text a simple regular expression that may only contain '?'(s)
+ * @param start the starting index in the text for search, inclusive
+ * @param end the stopping point of search, exclusive
+ * @param p a simple regular expression that may contains '?'
+ * @return the starting index in the text of the pattern , or -1 if not found
+ */
+ protected int regExpPosIn(String text, int start, int end, String p) {
+ int plen= p.length();
+
+ int max= end - plen;
+ for (int i= start; i <= max; ++i) {
+ if (regExpRegionMatches(text, i, p, 0, plen))
+ return i;
+ }
+ return -1;
+ }
+
+
+ protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) {
+ while (plen-- > 0) {
+ char tchar= text.charAt(tStart++);
+ char pchar= p.charAt(pStart++);
+
+ /* process wild cards */
+ if (!fIgnoreWildCards) {
+ /* skip single wild cards */
+ if (pchar == fSingleWildCard) {
+ continue;
+ }
+ }
+ if (pchar == tchar)
+ continue;
+ if (fIgnoreCase) {
+ if (Character.toUpperCase(tchar) == Character.toUpperCase(pchar))
+ continue;
+ // comparing after converting to upper case doesn't handle all cases;
+ // also compare after converting to lower case
+ if (Character.toLowerCase(tchar) == Character.toLowerCase(pchar))
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+ /**
+ * @param text the string to match
+ * @param start the starting index in the text for search, inclusive
+ * @param end the stopping point of search, exclusive
+ * @param p a string that has no wildcard
+ * @return the starting index in the text of the pattern , or -1 if not found
+ */
+ protected int textPosIn(String text, int start, int end, String p) {
+
+ int plen= p.length();
+ int max= end - plen;
+
+ if (!fIgnoreCase) {
+ int i= text.indexOf(p, start);
+ if (i == -1 || i > max)
+ return -1;
+ return i;
+ }
+
+ for (int i= start; i <= max; ++i) {
+ if (text.regionMatches(true, i, p, 0, plen))
+ return i;
+ }
+
+ return -1;
+ }
+
+ public static String[] convertFromString(String patterns, String separator) {
+ StringTokenizer tokenizer= new StringTokenizer(patterns, separator, true);
+ int tokenCount= tokenizer.countTokens();
+ List<String> result= new ArrayList<String>(tokenCount);
+ boolean escape= false;
+ boolean append= false;
+ while (tokenizer.hasMoreTokens()) {
+ String token= tokenizer.nextToken().trim();
+ if (separator.equals(token)) {
+ if (!escape)
+ escape= true;
+ else {
+ addPattern(result, separator);
+ append= true;
+ }
+ } else {
+ if (!append)
+ result.add(token);
+ else
+ addPattern(result, token);
+ append= false;
+ escape= false;
+ }
+ }
+ return (String[])result.toArray(new String[result.size()]);
+ }
+
+ private static void addPattern(List<String> list, String pattern) {
+ if (list.isEmpty())
+ list.add(pattern);
+ else {
+ int index= list.size() - 1;
+ list.set(index, ((String)list.get(index)) + pattern);
+ }
+ }
+
+ public static String convertToString(String[] patterns, String separator) {
+ int length= patterns.length;
+ StringBuffer strBuf= new StringBuffer();
+ if (length > 0)
+ strBuf.append(escapeSeparator(patterns[0], separator));
+ else
+ return ""; //$NON-NLS-1$
+ int i= 1;
+ while (i < length) {
+ strBuf.append(separator);
+ strBuf.append(" "); //$NON-NLS-1$
+ strBuf.append(escapeSeparator(patterns[i++], separator));
+ }
+ return strBuf.toString();
+ }
+
+ private static String escapeSeparator(String pattern, String separator) {
+ int length= pattern.length();
+ StringBuffer buf= new StringBuffer(length);
+ for (int i= 0; i < length; i++) {
+ char ch= pattern.charAt(i);
+ if (separator.equals(String.valueOf(ch)))
+ buf.append(ch);
+ buf.append(ch);
+ }
+ return buf.toString();
+
+ }
+
+ public static String[] convertFromString(String patterns) {
+ return convertFromString(patterns, SEPARATOR);
+ }
+
+ private static final String SEPARATOR= ","; //$NON-NLS-1$
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ThreadUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ThreadUtil.java
new file mode 100644
index 00000000000..4faf4ee29d7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ThreadUtil.java
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+/**
+ * Utility class for handling threads.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class ThreadUtil {
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private ThreadUtil() {
+ }
+
+ /**
+ * Puts the current thread to sleep for a given duration.
+ *
+ * @param time
+ * The duration in milliseconds.
+ */
+ public static void pause(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/Timer.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/Timer.java
new file mode 100644
index 00000000000..c0dc6361254
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/Timer.java
@@ -0,0 +1,49 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+import com.ibm.icu.util.Calendar;
+
+/**
+ * A simple timer for tracking time.
+ *
+ * @author Jinhua Xi
+ * @since 1.0
+ */
+public class Timer {
+
+ private long initTime;
+
+ private long startTime;
+
+ private long endTime;
+
+ public Timer() {
+ start();
+ initTime = startTime;
+ }
+
+ public void start() {
+ startTime = Calendar.getInstance().getTimeInMillis();
+ }
+
+ public void stop() {
+ endTime = Calendar.getInstance().getTimeInMillis();
+ }
+
+ public int getTime() {
+ return (int) (endTime - startTime);
+ }
+
+ public int getTotalTime() {
+ return (int) (endTime - initTime);
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/WarUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/WarUtil.java
new file mode 100644
index 00000000000..ccd8a0a2c20
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/WarUtil.java
@@ -0,0 +1,57 @@
+//------------------------------------------------------------------------------
+// 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.common.utils;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.War;
+import org.apache.tools.ant.types.FileSet;
+
+
+public class WarUtil {
+
+ /**
+ * Creates a war file.
+ *
+ * @param outputWarFile
+ * an absolute path to the target war file
+ * @param webAppDirectory
+ * an absolute path to a directory containing the files and sub
+ * directories to be wared
+ * @param monitor
+ * a progress monitor
+ * @throws IOException
+ * if an error occurs while creating the zip file
+ */
+ public static void buildWarFile(String outputWarFile, String webAppDirectory,
+ IProgressMonitor monitor) throws IOException {
+
+ try {
+ Project antProject = new Project();
+ antProject.init();
+ War warTask = new War();
+ warTask.setProject(antProject);
+ warTask.setDestFile(new File(outputWarFile));
+ warTask.setWebxml(new File(webAppDirectory + File.separator + "WEB-INF" //$NON-NLS-1$
+ + File.separator + "web.xml")); //$NON-NLS-1$
+ FileSet webFiles = new FileSet();
+ webFiles.setDir(new File(webAppDirectory));
+ warTask.addFileset(webFiles);
+ warTask.execute();
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/XMLUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/XMLUtil.java
new file mode 100644
index 00000000000..100ed59ca33
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/XMLUtil.java
@@ -0,0 +1,666 @@
+//------------------------------------------------------------------------------
+// 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.common.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Utility class for processing XML documents.
+ *
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @author Phong Nguyen Le
+ * @since 1.0
+ */
+public class XMLUtil {
+
+ /**
+ * XML declaration.
+ */
+ public final static String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
+
+ /**
+ * XML Escape characters.
+ */
+ public final static String XML_AMP = "&amp;"; //$NON-NLS-1$
+
+ public final static String XML_BACKSLASH = "&#92;"; //$NON-NLS-1$
+
+ public final static String XML_APOS = "&apos;"; //$NON-NLS-1$
+
+ public final static String XML_CR = "&#13;"; //$NON-NLS-1$
+
+ public final static String XML_GT = "&gt;"; //$NON-NLS-1$
+
+ public final static String XML_LT = "&lt;"; //$NON-NLS-1$
+
+ public final static String XML_LF = "&#10;"; //$NON-NLS-1$
+
+ public final static String XML_QUOT = "&quot;"; //$NON-NLS-1$
+
+ public final static String XML_TAB = "&#9;"; //$NON-NLS-1$
+
+ private static final String CRLF = "\r\n"; //$NON-NLS-1$
+
+ private static final byte[] CRLF_BYTES = CRLF.getBytes();
+
+ /**
+ * Private constructor to prevent this class from being instantiated. All
+ * methods in this class should be static.
+ */
+ private XMLUtil() {
+ }
+
+ /**
+ * Clones the given DOM node into the given DOM document.
+ *
+ * @param node
+ * The DOM node to clone.
+ * @param doc
+ * The target DOM document.
+ * @return The cloned node in the target DOM document.
+ */
+ public static Node cloneNode(Node node, Document doc) {
+ Node clone = null;
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ clone = doc.createElement(node.getNodeName());
+ NamedNodeMap attrs = node.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ Node attrNode = attrs.item(i);
+ Attr attrClone = doc.createAttribute(attrNode.getNodeName());
+ attrClone.setNodeValue(attrNode.getNodeValue());
+ ((Element) clone).setAttributeNode(attrClone);
+ }
+
+ // Iterate through each child nodes.
+ NodeList childNodes = node.getChildNodes();
+ if (childNodes != null) {
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node childNode = childNodes.item(i);
+ Node childClone = cloneNode(childNode, doc);
+ clone.appendChild(childClone);
+ }
+ }
+ break;
+
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ clone = doc.createTextNode(node.getNodeName());
+ clone.setNodeValue(node.getNodeValue());
+ break;
+ }
+ return clone;
+ }
+
+ /**
+ * Escapes a XML attribute to make it XML parser friendly.
+ *
+ * @param str
+ * The XML attribute string.
+ * @return The escaped string.
+ */
+ public static String escapeAttr(String str) {
+ if (str == null || str.length() == 0)
+ return ""; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '<':
+ sb.append(XML_LT);
+ break;
+ case '&':
+ sb.append(XML_AMP);
+ break;
+ case '"':
+ sb.append(XML_QUOT);
+ break;
+ default:
+ sb.append(ch);
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Escapes the given string to make it XML parser friendly.
+ *
+ * @param str
+ * The source string.
+ * @return The escaped string.
+ */
+ public static String escape(String str) {
+ if (str == null || str.length() == 0)
+ return ""; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '<':
+ sb.append(XML_LT);
+ break;
+ case '>':
+ sb.append(XML_GT);
+ break;
+ case '&':
+ sb.append(XML_AMP);
+ break;
+ case '"':
+ sb.append(XML_QUOT);
+ break;
+ case '\'':
+ sb.append(XML_APOS);
+ break;
+ case '\r':
+ sb.append(XML_CR);
+ break;
+ case '\n':
+ sb.append(XML_LF);
+ break;
+ case '\\':
+ sb.append(XML_BACKSLASH);
+ break;
+ default:
+ sb.append(ch);
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Escapes the given string to make it XML parser friendly.
+ *
+ * @param str
+ * The source string.
+ * @param ignoreCRLF
+ * If true, do not escape the CR and LF characters.
+ * @return The escaped string.
+ */
+ public static String escape(String str, boolean ignoreCRLF) {
+ if (str == null || str.length() == 0)
+ return ""; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '<':
+ sb.append(XML_LT);
+ break;
+ case '>':
+ sb.append(XML_GT);
+ break;
+ case '&':
+ // This is to avoid the double escaping (see Bugzilla 179921)
+ if (!str.startsWith(XML_LT+"p/", i) && !str.startsWith(XML_APOS, i) //$NON-NLS-1$
+ && !str.startsWith(XML_AMP, i))
+ sb.append(XML_AMP);
+ else
+ sb.append(ch);
+ break;
+ case '"':
+ sb.append(XML_QUOT);
+ break;
+ case '\'':
+ sb.append(XML_APOS);
+ break;
+ case '\r':
+ if (ignoreCRLF)
+ sb.append(ch);
+ else
+ sb.append(XML_CR);
+ break;
+ case '\n':
+ if (ignoreCRLF)
+ sb.append(ch);
+ else
+ sb.append(XML_LF);
+ break;
+ default:
+ sb.append(ch);
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Unescapes the given XML string.
+ *
+ * @param str
+ * The source string.
+ * @return The escaped string.
+ */
+ public static String unescape(String str) {
+ if (str == null || str.length() == 0)
+ return ""; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '&':
+ if (str.startsWith(XML_LT, i)) {
+ sb.append('<');
+ i += 3;
+ } else if (str.startsWith(XML_GT, i)) {
+ sb.append('>');
+ i += 3;
+ } else if (str.startsWith(XML_AMP, i)) {
+ sb.append('&');
+ i += 4;
+ } else if (str.startsWith(XML_QUOT, i)) {
+ sb.append('"');
+ i += 5;
+ } else if (str.startsWith(XML_APOS, i)) {
+ sb.append("\'"); //$NON-NLS-1$
+ i += 5;
+ } else if (str.startsWith(XML_CR, i)) {
+ sb.append('\r');
+ i += 4;
+ } else if (str.startsWith(XML_LF, i)) {
+ sb.append('\n');
+ i += 4;
+ } else {
+ sb.append(ch);
+ }
+ break;
+ default:
+ sb.append(ch);
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Writes the content of the given DOM document to the output stream.
+ *
+ * @param xmlDoc
+ * The DOM document.
+ * @param output
+ * The output stream.
+ * @throws IOException
+ * if an I/O error occur while accessing the output stream.
+ */
+ public static void writeDocument(Document xmlDoc, OutputStream output)
+ throws IOException {
+ DataOutputStream out = new DataOutputStream(output);
+ writeNode(xmlDoc, "", out); //$NON-NLS-1$
+ out.flush();
+ }
+
+ /**
+ * Writes the content of the given DOM document to the PrintWriter.
+ *
+ * @param xmlDoc
+ * The DOM document.
+ * @param pw
+ * The PrintWriter object.
+ * @throws IOException
+ * if an I/O error occur while accessing the output stream.
+ */
+ public static void writeDocument(Document xmlDoc, PrintWriter pw)
+ throws IOException {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(os);
+ writeNode(xmlDoc, "", out); //$NON-NLS-1$
+ out.flush();
+ // FIXME! Need to specify encoding?
+ String s = os.toString();
+ pw.write(s);
+ pw.flush();
+ }
+
+ /**
+ * Saves the content of the given DOM document to file.
+ *
+ * @param xmlDoc
+ * The DOM document.
+ * @param xmlFile
+ * The XML file.
+ * @throws IOException
+ * if an I/O error occur while accessing the output stream.
+ */
+ public static void saveDocument(Document xmlDoc, String xmlFile)
+ throws IOException {
+ DataOutputStream out = new DataOutputStream(new FileOutputStream(
+ xmlFile));
+ writeNode(xmlDoc, "", out); //$NON-NLS-1$
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Saves the given XML string to the given file.
+ *
+ * @param xmlStr
+ * The XML string.
+ * @param xmlFile
+ * The XML file.
+ * @throws IOException
+ * if an I/O error occur while accessing the output stream.
+ */
+ public static void saveDocument(String xmlStr, String xmlFile)
+ throws IOException {
+ DataOutputStream out = new DataOutputStream(new FileOutputStream(
+ xmlFile));
+ out.write(xmlStr.getBytes());
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Writes the given DOM tree node to the given output stream.
+ *
+ * @param node
+ * The DOM node.
+ * @param indent
+ * The string indentation (containing space characters).
+ * @param out
+ * The output stream.
+ * @throws IOException
+ * if an I/O error occur while accessing the output stream.
+ */
+ private static void writeNode(Node node, String indent, DataOutputStream out)
+ throws IOException {
+ String text;
+
+ switch (node.getNodeType()) {
+ case Node.DOCUMENT_NODE:
+ // Write the XML file signature.
+ out.write(StrUtil.getUTF8Bytes(XML_DECLARATION));
+ out.write(CRLF_BYTES);
+
+ // Iterate through each child nodes.
+ NodeList nodes = node.getChildNodes();
+ if (nodes != null) {
+ for (int i = 0; i < nodes.getLength(); i++) {
+ writeNode(nodes.item(i), "", out); //$NON-NLS-1$
+ }
+ }
+ break;
+
+ case Node.ELEMENT_NODE:
+ String name = node.getNodeName();
+ out.write(StrUtil.getUTF8Bytes(indent + "<" + name)); //$NON-NLS-1$
+ NamedNodeMap attrs = node.getAttributes();
+ for (int i = 0; i < attrs.getLength(); i++) {
+ Node attrNode = attrs.item(i);
+ out.write(StrUtil.getUTF8Bytes(" " + attrNode.getNodeName() //$NON-NLS-1$
+ + "=\"" + escape(attrNode.getNodeValue()) + "\"")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ out.write(StrUtil.getUTF8Bytes(">")); //$NON-NLS-1$
+ out.write(CRLF_BYTES);
+
+ // Iterate through each child nodes.
+ NodeList childNodes = node.getChildNodes();
+ if (childNodes != null) {
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ writeNode(childNodes.item(i), indent, out);
+ }
+ }
+ out.write(StrUtil.getUTF8Bytes(indent + "</" + name + ">")); //$NON-NLS-1$ //$NON-NLS-2$
+ out.write(CRLF_BYTES);
+
+ break;
+
+ case Node.TEXT_NODE:
+ text = StrUtil.removeWhiteSpaceChars(node.getNodeValue());
+ if (text.length() > 0) {
+ out.write(StrUtil.getUTF8Bytes(escape(text)));
+ }
+ break;
+
+ case Node.CDATA_SECTION_NODE:
+ text = StrUtil.removeWhiteSpaceChars(node.getNodeValue());
+ if (text.length() > 0) {
+ out.write(StrUtil.getUTF8Bytes("<![CDATA[")); //$NON-NLS-1$
+ out.write(StrUtil.getUTF8Bytes(text));
+ out.write(StrUtil.getUTF8Bytes("]]>")); //$NON-NLS-1$
+ out.write(CRLF_BYTES);
+ }
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ out.write(StrUtil.getUTF8Bytes("<?" + node.getNodeName() //$NON-NLS-1$
+ + " " + node.getNodeValue() + "?>")); //$NON-NLS-1$ //$NON-NLS-2$
+ out.write(CRLF_BYTES);
+ break;
+
+ case Node.ENTITY_REFERENCE_NODE:
+ out.write(StrUtil.getUTF8Bytes("&" + node.getNodeName() + ";")); //$NON-NLS-1$ //$NON-NLS-2$
+ break;
+ }
+ }
+
+ /**
+ * Returns the file location where the given SAX exception occurred.
+ *
+ * @param e
+ * The SAX parse exception.
+ * @return A string containing the file location where the exception
+ * occurred.
+ */
+ public static String getLocationOfException(SAXParseException e) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("row "); //$NON-NLS-1$
+ sb.append(e.getLineNumber());
+ sb.append(", col "); //$NON-NLS-1$
+ sb.append(e.getColumnNumber());
+
+ String systemId = e.getSystemId();
+ if (systemId != null) {
+ int index = systemId.lastIndexOf('/');
+ if (index != -1) {
+ systemId = systemId.substring(index + 1);
+ }
+ sb.append(" of XML document "); //$NON-NLS-1$
+ sb.append(systemId);
+ }
+
+ return sb.toString();
+ }
+
+ public static Document loadXml(File file) throws Exception {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+
+ return builder.parse(file);
+ }
+
+ public static Document createDocument() throws Exception {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory
+ .newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ return builder.newDocument();
+ }
+
+ /**
+ * text of a leaf node, without child element
+ *
+ * @param tag
+ * @return String
+ */
+ public static String getNodeText(Element tag) {
+ String text = tag.toString();
+ int i = text.indexOf(">"); //$NON-NLS-1$
+ int j = text.lastIndexOf("</"); //$NON-NLS-1$
+ if (i < 0 || j < 0 || j < i) {
+ return ""; //$NON-NLS-1$
+ }
+
+ return text.substring(i + 1, j);
+ }
+
+ public static String getChildText(Element tag, String childTagName) {
+ Element child = getFirstChild(tag, childTagName);
+ if (child != null) {
+ return getNodeText(child);
+ }
+
+ return ""; //$NON-NLS-1$
+ }
+
+ public static Element getFirstChild(Element tag, String childTagName) {
+ NodeList nodes = tag.getElementsByTagName(childTagName);
+ if (nodes == null || nodes.getLength() == 0) {
+ return null;
+ }
+
+ return (Element) nodes.item(0);
+ }
+
+ /**
+ * iterator of all the children of the element
+ *
+ * @param tag
+ * @return Iterator
+ */
+ public static Iterator childIterator(Element tag) {
+ NodeList nodes = tag.getChildNodes();
+
+ // NodeList contains no Element nodes such as text nodes, ignore those
+ List<Node> elements = new ArrayList<Node>();
+ if (nodes != null) {
+ int size = nodes.getLength();
+ for (int i = 0; i < size; i++) {
+ Node node = nodes.item(i);
+ if (node instanceof Element) {
+ elements.add(node);
+ }
+ }
+ }
+
+ return elements.iterator();
+ }
+
+ private static class NodeIterator implements Iterator {
+ int currentIndex = -1;
+
+ int size = 0;
+
+ NodeList nodes = null;
+
+ public NodeIterator(NodeList nodes) {
+ this.nodes = nodes;
+ if (nodes != null)
+ size = nodes.getLength();
+ }
+
+ public void remove() {
+ // Do nothing, this is a readonly iterator.
+ }
+
+ public boolean hasNext() {
+ return currentIndex + 1 < size;
+ }
+
+ public Object next() {
+ if (hasNext()) {
+ return nodes.item(++currentIndex);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * iterator of all the children of the element
+ *
+ * @param tag
+ * @return Iterator
+ */
+ public static Iterator childIterator(Element tag, String childTagName) {
+ NodeList nodes = tag.getElementsByTagName(childTagName);
+ return new NodeIterator(nodes);
+ }
+
+ /**
+ * Gets the list of immediate child elements with the given tag name.
+ *
+ * @param element
+ * @param tagName
+ * @return list of {@link Element} objects
+ */
+ public static List<Element> getChildElementsByTagName(Element element, String tagName) {
+ List<Element> elements = new ArrayList<Element>();
+ NodeList list = element.getChildNodes();
+ int size = list.getLength();
+ if(size > 0) {
+ for (int i = 0; i < size; i++) {
+ Node node = list.item(i);
+ if(node instanceof Element) {
+ Element e = (Element) node;
+ if(e.getTagName().equals(tagName)) {
+ elements.add(e);
+ }
+ }
+ }
+ }
+ return elements;
+ }
+
+ /**
+ * Gets the first element with the given tag name in the immediate child elements.
+ *
+ * @param element
+ * @param tagName
+ * @return
+ */
+ public static Element getFirstChildElementByTagName(Node element, String tagName) {
+ NodeList list = element.getChildNodes();
+ int size = list.getLength();
+ if(size > 0) {
+ for (int i = 0; i < size; i++) {
+ Node node = list.item(i);
+ if(node instanceof Element) {
+ Element e = (Element) node;
+ if(e.getTagName().equals(tagName)) {
+ return e;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public static String removeBOM(String xml) {
+ return xml.trim().replaceFirst("^([\\W]+)<", "<"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ZipUtil.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ZipUtil.java
new file mode 100644
index 00000000000..5396843191e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/ZipUtil.java
@@ -0,0 +1,106 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Utility class for reading and writing zip files.
+ *
+ * @author Kelvin Low
+ * @since 1.2
+ */
+public class ZipUtil {
+
+ /**
+ * Creates a zip file.
+ *
+ * @param zipFilePath
+ * an absolute path to the target zip file
+ * @param contentPath
+ * an absolute path to a directory containing the files and sub
+ * directories to be zipped
+ * @param monitor
+ * a progress monitor
+ * @throws IOException
+ * if an error occurs while creating the zip file
+ */
+ public static void createZipFile(String zipFilePath, String contentPath,
+ IProgressMonitor monitor) throws IOException {
+ ZipOutputStream out = null;
+ try {
+ out = new ZipOutputStream(new FileOutputStream(
+ zipFilePath));
+ File contentDir = new File(contentPath);
+ populateZipFile(out, contentDir.getAbsolutePath(), contentDir,
+ monitor);
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ finally {
+ if (out != null) {
+ try {
+ out.close();
+ }
+ catch (Exception e) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Populates a zip file with directories and files.
+ *
+ * @param out
+ * a zip file output stream
+ * @param rootPath
+ * a root path that is used to compute the relative paths of the
+ * zip content
+ * @param file
+ * a file or directory
+ * @param monitor
+ * a progress monitor
+ */
+ public static void populateZipFile(ZipOutputStream out, String rootPath,
+ File file, IProgressMonitor monitor) throws IOException {
+ File[] files = file.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ populateZipFile(out, rootPath, files[i], monitor);
+ } else {
+ String filePath = files[i].getAbsolutePath();
+ FileInputStream in = new FileInputStream(filePath);
+ String relativePath = filePath
+ .substring(rootPath.length() + 1);
+ out.putNextEntry(new ZipEntry(relativePath));
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = in.read(buffer)) > 0) {
+ out.write(buffer, 0, len);
+ }
+ out.closeEntry();
+ in.close();
+ }
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/package.html
new file mode 100644
index 00000000000..164d717abc6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/utils/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides common clipboard, file, I18N, image, networking, string manipulation and threading services.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/AbstractSAXParser.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/AbstractSAXParser.java
new file mode 100644
index 00000000000..13218b004d5
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/AbstractSAXParser.java
@@ -0,0 +1,216 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.xml;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.utils.NetUtil;
+import org.eclipse.epf.common.utils.StrUtil;
+import org.eclipse.epf.common.utils.XMLUtil;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * An abstract SAX parser that can be used to parse a single XML file or a
+ * directory of XML files.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public abstract class AbstractSAXParser extends DefaultHandler {
+
+ /**
+ * The logger used for logging warnings, errors and exceptions.
+ */
+ protected Logger logger;
+
+ /**
+ * The name of the current XML file being parsed.
+ */
+ protected String xmlFile;
+
+ /**
+ * The String buffer for accumulating text.
+ */
+ protected StringBuffer strBuf;
+
+ /**
+ * The XML validating flag.
+ */
+ private boolean validating;
+
+ /**
+ * Creates a new <code>AbstractSaxParser</code> given the validating flag.
+ *
+ * @param logger
+ * The logger for logging warnings and errors.
+ * @param validating
+ * If true, validate the XML document.
+ */
+ public AbstractSAXParser(Logger logger, boolean validating) {
+ this.logger = logger;
+ this.validating = validating;
+ }
+
+ /**
+ * Parses the given XML directory or file.
+ *
+ * @param xmlPath
+ * The XML directory or file.
+ */
+ public void parse(String xmlPath) {
+ String pathName = StrUtil.replace(xmlPath, "%20", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ File path = new File(pathName);
+ File[] files = path.isFile() ? new File[] { path } : path.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ if (!files[i].isDirectory()) {
+ try {
+ parseFile(files[i].getAbsoluteFile());
+ } catch (Exception e) {
+ if (logger != null) {
+ logger
+ .logError(
+ "Failed to parse \"" + files[i].getAbsolutePath() + '"', e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Parses the given XML file.
+ *
+ * @param xmlFile
+ * The XML file.
+ */
+ protected void parseFile(File xmlFile) throws ParserConfigurationException,
+ IOException, SAXException {
+ // Create the SAX parser factory.
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+
+ // Set the XML validating flag.
+ spf.setValidating(validating);
+
+ // Create the SAX parser.
+ SAXParser saxParser = spf.newSAXParser();
+
+ // Get the SAX XML reader.
+ XMLReader xmlReader = saxParser.getXMLReader();
+
+ // Set the SAX parser handlers to this class.
+ xmlReader.setContentHandler(this);
+ xmlReader.setErrorHandler(this);
+
+ // Instruct the SAX parser to parse the given XML file.
+ this.xmlFile = xmlFile.getAbsolutePath();
+ xmlReader.parse(NetUtil.getUri(xmlFile));
+ }
+
+ /**
+ * Called when the XML parser starts to parse the document.
+ */
+ public void startDocument() {
+ strBuf = new StringBuffer();
+ }
+
+ /**
+ * Called when the the XML parser encounters the chararacter data within a
+ * text element.
+ */
+ public void characters(char[] buffer, int start, int length) {
+ strBuf.append(buffer, start, length);
+ }
+
+ /**
+ * Called when the parser starts to parse each new element.
+ */
+ public abstract void startElement(String namespaceURL, String localName,
+ String qname, Attributes attributes);
+
+ /**
+ * Called when the XML parser reaches the end of the an element.
+ */
+ public abstract void endElement(String namespaceURL, String localName,
+ String qname);
+
+ /**
+ * Called when the XML parser reaches the end of the document.
+ */
+ public void endDocument() {
+ }
+
+ /**
+ * Logs the SAX parsing warning.
+ *
+ * @param e
+ * The SAX parse exception.
+ */
+ public void warning(SAXParseException e) {
+ if (logger != null) {
+ logger
+ .logWarning("SAX parsing warning encountered at " //$NON-NLS-1$
+ + XMLUtil.getLocationOfException(e)
+ + ": " + e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Logs the SAX parsing error.
+ *
+ * @param e
+ * The SAX parse exception.
+ */
+ public void error(SAXParseException e) {
+ if (logger != null) {
+ logger
+ .logError("SAX parsing error encountered at " //$NON-NLS-1$
+ + XMLUtil.getLocationOfException(e)
+ + ": " + e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Logs the SAX non-recoverable error and exits.
+ *
+ * @param e
+ * The SAX parse exception.
+ */
+ public void fatalError(SAXParseException e) throws SAXException {
+ if (logger != null) {
+ logger
+ .logError("SAX parsing fatal error encountered at " //$NON-NLS-1$
+ + XMLUtil.getLocationOfException(e)
+ + ": " + e.getMessage()); //$NON-NLS-1$
+ logger.logError(e);
+ }
+ }
+
+ /**
+ * Returns the current XML file that is being parsed.
+ *
+ * @return The name of the XML file.
+ */
+ public String getXMLFile() {
+ return xmlFile;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/XSLTProcessor.java b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/XSLTProcessor.java
new file mode 100644
index 00000000000..a595850fbec
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/XSLTProcessor.java
@@ -0,0 +1,449 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.common.xml;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.eclipse.epf.common.CommonPlugin;
+
+/**
+ * A wrapper over the XSLT processor bundled with the JRE.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class XSLTProcessor {
+
+ // If true, cache the compiled the XSL transformer with the compiled XSL
+ // templates.
+ private static boolean cacheXSL;
+
+ // Caches the XSL transformers.
+ private static Map<String, CachedTransformer> transformerCache;
+
+ static {
+ String cacheXSLProperty = CommonPlugin.getDefault().getString(
+ "cacheXSL"); //$NON-NLS-1$
+ if (cacheXSLProperty != null && !cacheXSLProperty.startsWith("[")) { //$NON-NLS-1$
+ cacheXSL = Boolean.getBoolean(cacheXSLProperty);
+ } else {
+ cacheXSL = true;
+ }
+ if (cacheXSL) {
+ transformerCache = new HashMap<String, CachedTransformer>();
+ }
+
+ // Increase the entity expansion line limit to handle a larger number of
+ // XML entities.
+ System.setProperty("entityExpansionLimit", "1000000"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Default private constructor to prevent this class from being
+ * instantiated.
+ */
+ private XSLTProcessor() {
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL source, XML source, target
+ * output and encoding.
+ *
+ * @param xslSource
+ * The XSL source.
+ * @param xmlSource
+ * The XML source.
+ * @param output
+ * The output target.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(Source xslSource, Source xmlSource,
+ Writer output, Properties params, String encoding) throws Exception {
+ if (xslSource != null && xmlSource != null) {
+ Transformer transformer = null;
+ String xslFile = xslSource.getSystemId();
+ if (cacheXSL && xslFile != null) {
+ CachedTransformer cachedTransformer = null;
+ synchronized (transformerCache) {
+ cachedTransformer = transformerCache.get(xslFile);
+ if (cachedTransformer == null) {
+ TransformerFactory factory = TransformerFactory
+ .newInstance();
+ transformer = factory.newTransformer(xslSource);
+ transformerCache.put(xslFile, new CachedTransformer(
+ transformer, params));
+ } else {
+ cachedTransformer.setParams(params);
+ transformer = cachedTransformer.getTransformer();
+ }
+ }
+ } else {
+ TransformerFactory factory = TransformerFactory.newInstance();
+ transformer = factory.newTransformer(xslSource);
+
+ if (params != null && params.size() > 0) {
+ for (Iterator<Object> i = params.keySet().iterator(); i
+ .hasNext();) {
+ String paramName = (String) i.next();
+ String paramValue = params.getProperty(paramName);
+ transformer.setParameter(paramName, paramValue);
+ }
+ }
+ }
+
+ if (encoding != null && encoding.length() > 0) {
+ transformer.setOutputProperty("encoding", encoding); //$NON-NLS-1$
+ } else {
+ transformer.setOutputProperty("encoding", "utf-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ transformer.transform(xmlSource, new StreamResult(output));
+ }
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL source, XML source, target
+ * output and encoding.
+ *
+ * @param xslSource
+ * The XSL source.
+ * @param xmlSource
+ * The XML source.
+ * @param output
+ * The output target.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(Source xslSource, Source xmlSource,
+ Writer output, String encoding) throws Exception {
+ transform(xslSource, xmlSource, output, null, encoding);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML source,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML source.
+ * @param output
+ * The output target.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, Source xmlSource,
+ Writer output, Properties params, String encoding) throws Exception {
+ InputStream xslInput = getXslInputStream(xslUri);
+ if (xslInput != null) {
+ StreamSource xslSource = new StreamSource(xslInput);
+ xslSource.setSystemId(new File(xslUri));
+ transform(xslSource, xmlSource, output, params, encoding);
+ try {
+ xslInput.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML source,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML source.
+ * @param output
+ * The output target.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, Source xmlSource,
+ Writer output, String encoding) throws Exception {
+ transform(xslUri, xmlSource, output, null, encoding);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param output
+ * The output target.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, String xmlStr, Writer output,
+ Properties params, String encoding) throws Exception {
+ InputStream xslInput = getXslInputStream(xslUri);
+ if (xslInput != null) {
+ StreamSource xslSource = new StreamSource(xslInput);
+ xslSource.setSystemId(new File(xslUri));
+
+ byte[] xml = xmlStr.getBytes("utf-8"); //$NON-NLS-1$
+ ByteArrayInputStream xmlInput = new ByteArrayInputStream(xml);
+ StreamSource xmlSource = new StreamSource(xmlInput);
+
+ transform(xslSource, xmlSource, output, params, encoding);
+
+ try {
+ xslInput.close();
+ xmlInput.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param output
+ * The output target.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, String xmlStr, Writer output,
+ String encoding) throws Exception {
+ transform(xslUri, xmlStr, output, null, encoding);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param file
+ * The output file.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, String xmlStr, File file,
+ Properties params, String encoding) throws Exception {
+ FileWriter output = new FileWriter(file);
+ if (output != null) {
+ transform(xslUri, xmlStr, output, params, encoding);
+ try {
+ output.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string,
+ * target output and encoding.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param file
+ * The output file.
+ * @param encoding
+ * The target encoding.
+ */
+ public static void transform(String xslUri, String xmlStr, File file,
+ String encoding) throws Exception {
+ transform(xslUri, xmlStr, file, null, encoding);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML source
+ * and target output.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML source.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, Source xmlSource,
+ Properties params, Writer output) throws Exception {
+ transform(xslUri, xmlSource, output, params, null);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML source
+ * and target output.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML source.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, Source xmlSource, Writer output)
+ throws Exception {
+ transform(xslUri, xmlSource, output, null, null);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string
+ * and target output.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, String xmlStr,
+ Properties params, Writer output) throws Exception {
+ transform(xslUri, xmlStr, output, params, null);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string
+ * and target output.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, String xmlStr, Writer output)
+ throws Exception {
+ transform(xslUri, xmlStr, output, null, null);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string
+ * and target output file.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param params
+ * The parameters for the XSL transformation.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, String xmlStr,
+ Properties params, File file) throws Exception {
+ transform(xslUri, xmlStr, file, params, null);
+ }
+
+ /**
+ * Executes the XSL transformation given the XSL stylesheet URI, XML string
+ * and target output file.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ * @param xmlStr
+ * The XML string.
+ * @param output
+ * The output target.
+ */
+ public static void transform(String xslUri, String xmlStr, File file)
+ throws Exception {
+ transform(xslUri, xmlStr, file, null, null);
+ }
+
+ /**
+ * Returns the XSL input stream given the XSL stylesheet URI.
+ *
+ * @param xslURI
+ * The XSL stylesheet URI.
+ */
+ private static InputStream getXslInputStream(String xslUri) {
+ InputStream xslInput = null;
+ try {
+ xslInput = new FileInputStream(xslUri);
+ } catch (Exception e) {
+ if (xslInput == null) {
+ xslInput = XSLTProcessor.class.getClassLoader()
+ .getResourceAsStream(xslUri);
+ }
+ }
+ return xslInput;
+ }
+
+}
+
+/**
+ * A cached XSL Transformer object.
+ */
+class CachedTransformer {
+
+ private Transformer transformer;
+ private Properties params;
+
+ public CachedTransformer(Transformer transformer, Properties params) {
+ this.transformer = transformer;
+ setParams(params);
+ }
+
+ public Transformer getTransformer() {
+ return transformer;
+ }
+
+ public Properties getParams() {
+ return params;
+ }
+
+ public void setParams(Properties params) {
+ if (params != this.params) {
+ transformer.clearParameters();
+ for (Iterator<Object> i = params.keySet().iterator(); i.hasNext();) {
+ String paramName = (String) i.next();
+ String paramValue = params.getProperty(paramName);
+ transformer.setParameter(paramName, paramValue);
+ }
+ this.params = params;
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/package.html b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/package.html
new file mode 100644
index 00000000000..6e3c33ecf8e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.common/src/org/eclipse/epf/common/xml/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides XML and XSLT processing services.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/.project b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/.project
new file mode 100644
index 00000000000..85e7490063c
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.richtext-feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/build.properties
new file mode 100644
index 00000000000..77afc5688a0
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/build.properties
@@ -0,0 +1,4 @@
+bin.includes = feature.xml,\
+ feature.properties,\
+ license.html,\
+ epl-v10.html
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/epl-v10.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/epl-v10.html
new file mode 100644
index 00000000000..cb1073a4bad
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/epl-v10.html
@@ -0,0 +1,304 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<link rel=File-List
+href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
+<title>Eclipse Public License - Version 1.0</title>
+<style>
+<!--
+ /* Font Definitions */
+@font-face
+ {
+ panose-1:2 11 6 4 3 5 4 4 2 4;
+ mso-font-charset:0;
+ mso-font-pitch:variable;
+ mso-font-signature:553679495 -2147483648 8 0 66047 0;}
+ /* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {mso-style-parent:"";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ }
+p
+ {margin-right:0in;
+ mso-margin-top-alt:auto;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ }
+p.BalloonText, li.BalloonText, div.BalloonText
+ {mso-style-name:"Balloon Text";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:8.0pt;
+
+ }
+@page Section1
+ {size:8.5in 11.0in;
+ margin:1.0in 1.25in 1.0in 1.25in;
+ mso-header-margin:.5in;
+ mso-footer-margin:.5in;
+ mso-paper-source:0;}
+div.Section1
+ {page:Section1;}
+-->
+</style>
+</head>
+
+<body lang="EN-US" style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
+</p>
+
+<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Contribution&quot; means:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and<br clear=left>
+b) in the case of each subsequent Contributor:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+changes to the Program, and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+additions to the Program;</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Contributor&quot; means any person or
+entity that distributes the Program.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Licensed Patents &quot; mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Program&quot; means the Contributions
+distributed in accordance with this Agreement.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Recipient&quot; means anyone who
+receives the Program under this Agreement, including all Contributors.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to<span
+style='color:red'> </span>reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. </span></p>
+
+<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:</span>
+</p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it complies with the terms and conditions of this Agreement; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+its license agreement:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
+
+<p><span style='font-size:10.0pt'>When the Program is made available in source
+code form:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it must be made available under this Agreement; and </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
+copy of this Agreement must be included with each copy of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
+copyright notices contained within the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. </span></p>
+
+<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
+
+<p><span style='font-size:10.0pt'>Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor (&quot;Commercial
+Contributor&quot;) hereby agrees to defend and indemnify every other
+Contributor (&quot;Indemnified Contributor&quot;) against any losses, damages and
+costs (collectively &quot;Losses&quot;) arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense.</span> </p>
+
+<p><span style='font-size:10.0pt'>For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. </span></p>
+
+<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
+
+<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</span> </p>
+
+<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </span></p>
+
+<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. </span></p>
+
+<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.</span> </p>
+
+<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.</span> </p>
+
+<p class=MsoNormal></p>
+
+</div>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.properties
new file mode 100644
index 00000000000..6d29802becd
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.properties
@@ -0,0 +1,141 @@
+# NLS_MESSAGEFORMAT_VAR
+
+# "featureName" property - name of the feature
+featureName=EPF Richtext
+
+# "providerName" property - name of the company that provides the feature
+providerName=EPF Project
+
+# "description" property - description of the feature
+description=
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+April 14, 2010\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+ 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+ the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+ extending or updating the functionality of an Eclipse-based product.\n\
+ 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+ Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+ 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+ govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+ Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+ with the Specification. Such Installable Software Agreement must inform the user of the\n\
+ terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+ the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+ indication of agreement by the user, the provisioning Technology will complete installation\n\
+ of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.xml b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.xml
new file mode 100644
index 00000000000..64d9df31657
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/feature.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.epf.richtext"
+ label="%featureName"
+ version="1.6.0.qualifier"
+ provider-name="%providerName">
+
+ <description>
+ %description
+ </description>
+
+ <copyright url="http://www.eclipse.org/legal/epl-v10.html">
+ Copyright (c) 2009 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
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <requires>
+ <import plugin="com.ibm.icu"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.apache.ant"/>
+ <import plugin="org.eclipse.ui"/>
+ <import plugin="org.eclipse.osgi"/>
+ <import plugin="org.eclipse.swt"/>
+ <import plugin="org.eclipse.ui.forms"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.workbench.texteditor"/>
+ </requires>
+
+ <plugin
+ id="org.eclipse.epf.common"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.epf.common.html"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.epf.common.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.epf.common.win32.win32.x86"
+ os="win32"
+ arch="x86"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.epf.common.win32.win32.x86_64"
+ os="win32"
+ arch="x86_64"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.epf.richtext"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"/>
+
+</feature>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/license.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/license.html
new file mode 100644
index 00000000000..a9b560f44cd
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext-feature/license.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<title>Eclipse.org Software User Agreement</title>
+</head>
+
+<body lang="EN-US" link=blue vlink=purple>
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>March 17, 2005</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ (&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse.org CVS repository (&quot;Repository&quot;) in CVS
+ modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Eclipse Update Manager, you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>IBM Public License 1.0 (available at <a href="http://oss.software.ibm.com/developerworks/opensource/license10.html">http://oss.software.ibm.com/developerworks/opensource/license10.html</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<small>Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.</small>
+</body>
+</html>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/.classpath b/extraplugins/epf-richtext/org.eclipse.epf.richtext/.classpath
new file mode 100644
index 00000000000..04683904632
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/.classpath
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src">
+ <attributes>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins">
+ <attributes>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
+ <attributes>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/.project b/extraplugins/epf-richtext/org.eclipse.epf.richtext/.project
new file mode 100644
index 00000000000..92c4c271e3e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.epf.richtext</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/META-INF/MANIFEST.MF b/extraplugins/epf-richtext/org.eclipse.epf.richtext/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..e78c291527b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.epf.richtext;singleton:=true
+Bundle-Version: 1.6.0.qualifier
+Bundle-Activator: org.eclipse.epf.richtext.RichTextPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime;visibility:=reexport,
+ org.eclipse.ui;visibility:=reexport,
+ org.eclipse.ui.forms;visibility:=reexport,
+ org.eclipse.jface.text;visibility:=reexport,
+ org.eclipse.ui.workbench.texteditor;visibility:=reexport,
+ org.eclipse.epf.common.ui;visibility:=reexport
+Bundle-ActivationPolicy: lazy
+Export-Package: org.eclipse.epf.richtext,
+ org.eclipse.epf.richtext.actions,
+ org.eclipse.epf.richtext.dialogs,
+ org.eclipse.epf.richtext.html,
+ org.eclipse.epf.richtext.preferences
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.html
new file mode 100644
index 00000000000..04a6d65fb9f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>February 24, 2005</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.ini b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.ini
new file mode 100644
index 00000000000..46909d4b218
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.ini
@@ -0,0 +1,18 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2004, 2005 IBM Corporation. All Rights Reserved.
+#-------------------------------------------------------------------------------
+
+# about.ini
+# contains information about a feature
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# "%key" are externalized strings defined in about.properties
+# This file does not need to be translated.
+
+# Property "aboutText" contains blurb for "About" dialog (translated)
+aboutText=%featureText
+
+# Property "featureImage" contains path to feature image (32x32)
+featureImage=application_32.gif
+
+# Property "appName" contains name of the application (translated)
+appName=%featureName
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.mappings b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.mappings
new file mode 100644
index 00000000000..2c7deba835c
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.mappings
@@ -0,0 +1,7 @@
+# about.mappings
+# contains fill-ins for about.properties
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file does not need to be translated.
+# Usually generated at build time.
+
+0=1.5.0.4
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.properties
new file mode 100644
index 00000000000..cbb1618b0af
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/about.properties
@@ -0,0 +1,49 @@
+# NLS_ENCODING=UNICODE
+###############################################################################
+# Copyright (c) 2009 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 API and implementation
+###############################################################################
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 2008 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
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# ==============================================================================
+# Do not change the properties between this line and the last line containing:
+# %%% END OF TRANSLATED PROPERTIES %%%
+# Instead, either redefine an existing property, or create a new property,
+# append it to the end of the file, and change the code to use the new name.
+# ==============================================================================
+
+# about.properties
+# contains externalized strings for about.ini
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# fill-ins are supplied by about.mappings
+# This file should be translated.
+
+featureName=EPF Richtext
+
+featureText=EPF Richtext\n\
+\n\
+Version: {0} \n\
+\n\
+(c) Copyright Eclipse contributors and others 2000, 2008. All Rights Reserved.\n\
+\n\
+
+# ==============================================================================
+# %%% END OF TRANSLATED PROPERTIES %%%
+# The above properties have been shipped for translation.
+# ==============================================================================
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/application_32.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/application_32.gif
new file mode 100644
index 00000000000..e6ad7ccd75b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/application_32.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/build.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext/build.properties
new file mode 100644
index 00000000000..8186328815d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/build.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2009 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 API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = icons/,\
+ .,\
+ META-INF/,\
+ rte/,\
+ plugin.properties,\
+ about.html,\
+ about.ini,\
+ about.mappings,\
+ about.properties,\
+ application_32.gif
+
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddCode.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddCode.gif
new file mode 100644
index 00000000000..9ff24e339c2
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddCode.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddImage.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddImage.gif
new file mode 100644
index 00000000000..4308a8a2ec7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddImage.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddLink.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddLink.gif
new file mode 100644
index 00000000000..7b111960867
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddLink.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddOrderedList.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddOrderedList.gif
new file mode 100644
index 00000000000..f9ae4154b12
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddOrderedList.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddTable.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddTable.gif
new file mode 100644
index 00000000000..20884628895
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddTable.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddUnorderedList.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddUnorderedList.gif
new file mode 100644
index 00000000000..9c44ec645ae
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/AddUnorderedList.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Bold.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Bold.gif
new file mode 100644
index 00000000000..2dc59878356
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Bold.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/ClearContent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/ClearContent.gif
new file mode 100644
index 00000000000..9ff6416063d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/ClearContent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Copy.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Copy.gif
new file mode 100644
index 00000000000..e9bc65e32a0
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Copy.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Cut.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Cut.gif
new file mode 100644
index 00000000000..bd43144729a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Cut.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/FindReplace.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/FindReplace.gif
new file mode 100644
index 00000000000..c8f88716c46
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/FindReplace.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Indent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Indent.gif
new file mode 100644
index 00000000000..436e15369b7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Indent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Italic.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Italic.gif
new file mode 100644
index 00000000000..c9b5a4483a7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Italic.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Outdent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Outdent.gif
new file mode 100644
index 00000000000..edcda3eea36
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Outdent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Paste.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Paste.gif
new file mode 100644
index 00000000000..1c7668db98e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Paste.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/PastePlainText.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/PastePlainText.gif
new file mode 100644
index 00000000000..d01a2297af7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/PastePlainText.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Subscript.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Subscript.gif
new file mode 100644
index 00000000000..a7b31aa064e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Subscript.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Superscript.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Superscript.gif
new file mode 100644
index 00000000000..e4b266c5e53
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Superscript.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/TidyHTML.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/TidyHTML.gif
new file mode 100644
index 00000000000..36bc9df8e50
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/TidyHTML.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Underline.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Underline.gif
new file mode 100644
index 00000000000..e2a96469cee
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/dtool16/Underline.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddCode.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddCode.gif
new file mode 100644
index 00000000000..bdb813fc270
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddCode.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddImage.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddImage.gif
new file mode 100644
index 00000000000..0545213fbaa
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddImage.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLine.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLine.gif
new file mode 100644
index 00000000000..7f08dcf651e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLine.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLink.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLink.gif
new file mode 100644
index 00000000000..e99194adefd
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddLink.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddOrderedList.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddOrderedList.gif
new file mode 100644
index 00000000000..b6814c10a08
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddOrderedList.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddTable.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddTable.gif
new file mode 100644
index 00000000000..d368859b9e6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddTable.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddUnorderedList.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddUnorderedList.gif
new file mode 100644
index 00000000000..a4fdfc9e461
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/AddUnorderedList.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Bold.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Bold.gif
new file mode 100644
index 00000000000..00df9e553e5
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Bold.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/ClearContent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/ClearContent.gif
new file mode 100644
index 00000000000..255832653fd
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/ClearContent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Copy.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Copy.gif
new file mode 100644
index 00000000000..f32aceebb3e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Copy.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Cut.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Cut.gif
new file mode 100644
index 00000000000..7e8635c8ab4
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Cut.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/FindReplace.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/FindReplace.gif
new file mode 100644
index 00000000000..11257ecd23b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/FindReplace.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Indent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Indent.gif
new file mode 100644
index 00000000000..78195d0743e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Indent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Italic.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Italic.gif
new file mode 100644
index 00000000000..ad0cd11add5
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Italic.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyCenter.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyCenter.gif
new file mode 100644
index 00000000000..eeabf0513de
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyCenter.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyFull.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyFull.gif
new file mode 100644
index 00000000000..a90a3b8b141
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyFull.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyLeft.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyLeft.gif
new file mode 100644
index 00000000000..e85469b5d7a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyLeft.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyRight.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyRight.gif
new file mode 100644
index 00000000000..0005af11ea1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/JustifyRight.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Outdent.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Outdent.gif
new file mode 100644
index 00000000000..406b94f2840
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Outdent.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Paste.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Paste.gif
new file mode 100644
index 00000000000..94d39a1af5c
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Paste.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/PastePlainText.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/PastePlainText.gif
new file mode 100644
index 00000000000..d8f9895833e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/PastePlainText.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/StrikeThrough.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/StrikeThrough.gif
new file mode 100644
index 00000000000..a1035459470
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/StrikeThrough.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Subscript.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Subscript.gif
new file mode 100644
index 00000000000..1c0f7133c7d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Subscript.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Superscript.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Superscript.gif
new file mode 100644
index 00000000000..32866349b8f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Superscript.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/TidyHTML.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/TidyHTML.gif
new file mode 100644
index 00000000000..adf2410fa60
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/TidyHTML.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Underline.gif b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Underline.gif
new file mode 100644
index 00000000000..e6476d6f45b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/icons/full/etool16/Underline.gif
Binary files differ
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/plugin.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext/plugin.properties
new file mode 100644
index 00000000000..3d5028ae5c0
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/plugin.properties
@@ -0,0 +1,34 @@
+###############################################################################
+# Copyright (c) 2009 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 API and implementation
+###############################################################################
+#-------------------------------------------------------------------------------
+# Copyright (c) 2005, 2006 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+# Plug-in
+pluginName=EPF Rich Text
+providerName=Eclipse.org
+
+################################################################################
+# THE FOLLOWING PROPERTIES SHOULD NOT BE TRANSLATED!!!
+################################################################################
+
+# The HTML file used to render the Rich Text Editor.
+RichText.editorHTML=rte.htm
+
+
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/blank.htm b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/blank.htm
new file mode 100644
index 00000000000..765d74505d5
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/blank.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+<head>
+ <title></title>
+</head>
+<body>
+</body>
+</html>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.css b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.css
new file mode 100644
index 00000000000..4912b2cb390
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.css
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2005, 2006 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
+ */
+
+body {
+ background-image: none;
+ background-color: #ffffff;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ margin: 3px;
+ padding: 0px;
+}
+
+p {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+}
+
+h1 {
+ font-family: arial, helvetica, sans-serif;
+ font-size: large;
+}
+
+h2 {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 150%;
+}
+
+h3 {
+ font-family: arial, helvetica, sans-serif;
+}
+
+h4, h5, h6 {
+ font-family: arial, helvetica, sans-serif;
+}
+
+a:link {
+ color: #003399;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-decoration: none;
+}
+
+a:active {
+ color: #003399;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-decoration: underline;
+}
+
+a:visited {
+ color: #003399;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #ff0000;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-decoration: underline;
+}
+
+ol {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ list-style-type: decimal;
+ margin-left: 30px;
+}
+
+ol li {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-align: left
+}
+
+ul {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ list-style-type: disc;
+ margin-left: 30px;
+ margin-top: 0px;
+}
+
+ul li {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-align: left;
+}
+
+table {
+ background-image: none;
+ background: #ffffff;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+}
+
+tbody {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ valign: baseline;
+}
+
+th {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-align: left;
+}
+
+td {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+}
+
+td ul {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ margin-bottom: 0px;
+ margin-left: 30px;
+}
+
+.pageTitle {
+ background: #9999cc;
+ color: #ffffff;
+ font-size: 12pt;
+ font-weight: bold;
+ padding-bottom: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 5px;
+ text-align: left;
+}
+
+.pageTitleSeparator {
+ background-color: #000000;
+ padding: 0px;
+}
+
+.tab {
+ background-color: #5c81a7;
+ color: #ffffff;
+ font-family: verdana, arial, sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+.activeTab {
+ background-color: #c8d7e3;
+ color: #293d6b;
+ font-family: verdana, arial, sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+a.tab:link, a.tab:active, a.tab:visited {
+ color: #ffffff;
+ font-family: verdana, arial, sans-serif;
+ font-size: 11px;
+ font-weight: bold;
+}
+
+a.tab:hover {
+ text-decoration: underline;
+}
+
+.overview {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ font-weight: normal;
+ padding-bottom: 10px;
+ padding-left: 20px;
+ padding-right: 0px;
+ padding-top: 10px;
+}
+
+.overviewTable {
+ background: #ffffff;
+ width: 100%;
+}
+
+.overviewTable td {
+ padding-bottom: 5px;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+}
+
+.overviewSeparator {
+ background-color: #000000;
+ padding: 0px;
+}
+
+.expandCollapseText {
+ font-family: verdana, arial, sans-serif;
+ font-size: 8pt;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.expandCollapseLink {
+ color: #333333;
+ padding-bottom: 5px;
+ text-decoration: none;
+}
+
+.expandCollapseLink:hover {
+ color: #0000ff;
+ text-decoration: underline;
+}
+
+.expandCollapseLink:visited {
+ color: #333333;
+}
+
+.sectionHeading {
+ background-color: #98b1c4;
+ color: #ffffff;
+ cursor: hand;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ font-weight: bold;
+ padding-bottom: 2px;
+ padding-left: 2px;
+ padding-top: 2px;
+ text-decoration: none;
+}
+
+.sectionContent {
+ padding-bottom: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ text-align: right;
+}
+
+.sectionTable {
+ border-bottom: #ccc solid 0px;
+ border-left: #ccc solid 1px;
+ border-right: #ccc solid 0px;
+ border-top: #ccc solid 1px;
+ padding-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ width: 100%;
+}
+
+.sectionTableHeading {
+ background: #eee;
+ border-bottom: #ccc solid 1px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 1px;
+ border-top: #ccc solid 0px;
+ color: #333333;
+ height: 20;
+ text-align: left;
+ width: 20%;
+}
+
+.sectionTableCell {
+ border-bottom: #ccc solid 1px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 1px;
+ border-top: #ccc solid 0px;
+}
+
+.breakdownTable {
+ border-bottom: #ccc solid 0px;
+ border-left: #ccc solid 1px;
+ border-right: #ccc solid 0px;
+ border-top: #ccc solid 1px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ width: 100%;
+}
+
+.breakdownTable th {
+ background: #eee;
+ border-bottom: #ccc solid 1px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 1px;
+ border-top: #ccc solid 0px;
+ color: #333333;
+ height: 20;
+ text-align: left;
+}
+
+.breakdownTable td {
+ border-bottom: #ccc solid 1px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 1px;
+ border-top: #ccc solid 0px;
+}
+
+.defaultTable {
+ border-bottom: #ccc solid 0px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 0px;
+ border-top: #ccc solid 0px;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ width: 100%;
+}
+
+.defaultTable td {
+ border-bottom: #ccc solid 0px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 0px;
+ border-top: #ccc solid 0px;
+ text-align: left;
+}
+
+.subSectionHeading {
+ color: #333333;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+.subSectionContent {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ text-decoration: none;
+}
+
+.stepHeading {
+ background-color: #ffffff;
+ color: #293d6b;
+ cursor: hand;
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ font-weight: bold;
+ padding-bottom: 2px;
+ padding-left: 2px;
+ padding-top: 2px;
+ text-decoration: none;
+}
+
+.stepContent {
+ border-bottom: #ccc solid 0px;
+ border-left: #ccc solid 0px;
+ border-right: #ccc solid 0px;
+ border-top: #ccc solid 0px;
+ padding-bottom: 5px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ text-align: right;
+}
+
+.stepTable {
+ border-bottom: #999999 solid 1px;
+ border-left: #999999 solid 0px;
+ border-right: #999999 solid 0px;
+ border-top: #999999 solid 0px;
+ padding-bottom: 20px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ width: 100%;
+}
+
+.stepTable td {
+ border: #ccc solid 0px;
+}
+
+.stepSeparator {
+ background-color: #cccccc;
+ padding: 0px;
+}
+
+.backToTopLink {
+ color: #fffff;
+ font-family: verdana, arial, sans-serif;
+ font-size: 8pt;
+ font-weight: normal;
+ margin: 0px;
+ padding-bottom: 10px;
+ text-align: middle;
+ text-decoration: none;
+}
+
+.backToTopLink:hover {
+ color: #969;
+ text-decoration: underline;
+}
+
+.backToTopLink:visited {
+ color: #5c81a7;
+ text-decoration: none;
+}
+
+.copyright {
+ color: #7080b0;
+ font-family: verdana, arial, sans-serif;
+ font-size: 8pt;
+ font-weight: normal;
+ padding-left: 0px;
+ padding-right: 10px;
+ padding-top: 25px;
+ text-align: left;
+ width: 100%;
+}
+
+.versionInfo {
+ color: #7080b0;
+ font-family: verdana, arial, sans-serif;
+ font-size: 8pt;
+ font-weight: normal;
+ padding-left: 10px;
+ padding-right: 0px;
+ padding-top: 25px;
+ text-align: right;
+}
+
+.quote {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ font-style: italic;
+}
+
+.codeSample {
+ font-family: courier;
+ font-size: 10pt;
+}
+
+.elementLink {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ color: #0000ff;
+}
+
+.elementLinkWithType {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ color: #0000ff;
+}
+
+.elementLinkWithUserText {
+ font-family: arial, helvetica, sans-serif;
+ font-size: 10pt;
+ color: #0000ff;
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.html
new file mode 100644
index 00000000000..1c7c52e643e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.html
@@ -0,0 +1,20 @@
+<html>
+<!--
+ Copyright (c) 2005, 2006 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
+-->
+ <head>
+ <script language="JavaScript" type="text/javascript" src="rte.js"></script>
+ </head>
+ <body leftMargin="0" topMargin="0" marginheight="0" marginwidth="0" scroll="no" style="overflow: hidden">
+ <iframe id="rte" name="rte" style="border: none;" frameborder="0" scrolling="auto" width="100%" height="100%"></iframe>
+ <script type="text/javascript">
+ initEditor('rte', 'rte.css', null);
+ </script>
+ </body>
+</html>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.js b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.js
new file mode 100644
index 00000000000..5d6d34da6ee
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.js
@@ -0,0 +1,1490 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+// Note: Mozilla/Firefox does not allow unprivileged scripts to invoke the cut,
+// copy and paste commands. The Javascript must either be signed
+// (see http://www.mozilla.org/projects/security/components/signed-scripts.html),
+// or the users must change their preferences
+// (see http://www.mozilla.org/editor/midasdemo/securityprefs.html).
+// Alternatively, the users can use the ctrl-x, ctrl-c and ctrl-v keys.
+//------------------------------------------------------------------------------
+// Note: The SWT component in eclipse 3.4.X and above has a bug that
+// keyReleased event can't be notified to listener. See (https://bugs.eclipse.org/bugs/show_bug.cgi?id=280146).
+// This issue has blocked EPF upgrade to 1.5.0.5. As a workaround, capture keyReleased event in
+// Javascript. Once this issue is resolved in SWT, we need to resume it
+var STATUS_NOP = 0;
+var STATUS_INITIALIZED = 1;
+var STATUS_MODIFIED = 2;
+var STATUS_GET_TEXT = 3;
+var STATUS_KEY_DOWN = 4;
+var STATUS_KEY_UP = 5;
+var STATUS_SELECT_TEXT = 6;
+var STATUS_SELECT_CONTROL = 7;
+var STATUS_SELECT_NONE = 8;
+var STATUS_EXEC_CMD = 9;
+var STATUS_REFORMAT_LINKS = 10;
+
+var KEY_ARROW_DOWN = 40;
+var KEY_ARROW_LEFT = 37;
+var KEY_ARROW_RIGHT = 39;
+var KEY_ARROW_UP = 38;
+var KEY_BACKSPACE = 8;
+var KEY_END = 35;
+var KEY_HOME = 36;
+var KEY_PAGE_DOWN = 34;
+var KEY_PAGE_UP = 33;
+var KEY_TAB = 9;
+
+var KEY_B = 66;
+var KEY_U = 85;
+var KEY_I = 73;
+var KEY_C = 67;
+var KEY_F = 70;
+var KEY_S = 83;
+var KEY_V = 86;
+var KEY_X = 88;
+var KEY_Z = 90;
+
+var CMD_COPY = "copy";
+var CMD_CUT = "cut";
+var CMD_FIND_TEXT = "findText";
+var CMD_PASTE = "paste";
+var CMD_SAVE = "save";
+var CMD_SAVE_ALL = "saveAll";
+
+var TABLE_HEADERS_NONE = 0;
+var TABLE_HEADERS_COLS = 1;
+var TABLE_HEADERS_ROWS = 2;
+var TABLE_HEADERS_BOTH = 3;
+
+var BOLD = 1;
+var ITALIC = BOLD << 1;
+var UNDERLINE = ITALIC << 1;
+var SUBSCRIPT = UNDERLINE << 1;
+var SUPERSCRIPT = SUBSCRIPT << 1;
+
+
+var editorId;
+var editorCSS;
+var baseHREF;
+var supportRichTextEditing = true;
+var editorDoc;
+var selection;
+var selectionRange;
+var readOnly = false;
+var initialized = false;
+var modified = false;
+var checkResizeElement;
+var selectionInfo = null;
+
+// Initializes the editor.
+function initEditor(id, css, baseURL) {
+ editorId = id;
+ editorCSS = css;
+ baseHREF = baseURL;
+ try {
+ enableRichTextEditing('');
+ initialized = true;
+ setStatus(STATUS_INITIALIZED, null);
+ }
+ catch (e) {
+ supportRichTextEditing = false;
+ }
+}
+
+var excludeModify = new Array(16, KEY_ARROW_DOWN, KEY_ARROW_LEFT,
+ KEY_ARROW_RIGHT, KEY_ARROW_UP, KEY_END, KEY_HOME, KEY_PAGE_DOWN,
+ KEY_PAGE_UP, KEY_TAB);
+
+function keyReleased(event) {
+ var keyCode = event.keyCode;
+ if (keyCode == 0 && !document.all) {
+ keyCode = event.charCode;
+ switch (keyCode) {
+ case 98:
+ keyCode = KEY_B;
+ break;
+ case 99:
+ keyCode = KEY_C;
+ break;
+ case 102:
+ keyCode = KEY_F;
+ break;
+ case 105:
+ keyCode = KEY_I;
+ break;
+ case 115:
+ keyCode = KEY_S;
+ break;
+ case 117:
+ keyCode = KEY_U;
+ break;
+ case 118:
+ keyCode = KEY_V;
+ break;
+ case 120:
+ keyCode = KEY_X;
+ break;
+ case 122:
+ keyCode = KEY_Z;
+ break;
+ }
+ }
+ var ctrlKey = event.ctrlKey;
+ var shiftKey = event.shiftKey;
+ var altKey = event.altKey;
+
+ if ( !ctrlKey && !altKey ) {
+ var modified = true;
+ for (var i = 0; i < excludeModify.length; i++ ) {
+ if ( keyCode == excludeModify[i] ) {
+ modified = false;
+ break;
+ }
+ }
+ if ( modified == true ) {
+ setTimeout("setStatus(STATUS_MODIFIED, null);", 10);
+ }
+ }
+}
+
+// Handles the key events.
+function keyPressed(event) {
+ var keyCode = event.keyCode;
+ if (keyCode == 0 && !document.all) {
+ keyCode = event.charCode;
+ switch (keyCode) {
+ case 98:
+ keyCode = KEY_B;
+ break;
+ case 99:
+ keyCode = KEY_C;
+ break;
+ case 102:
+ keyCode = KEY_F;
+ break;
+ case 105:
+ keyCode = KEY_I;
+ break;
+ case 115:
+ keyCode = KEY_S;
+ break;
+ case 117:
+ keyCode = KEY_U;
+ break;
+ case 118:
+ keyCode = KEY_V;
+ break;
+ case 120:
+ keyCode = KEY_X;
+ break;
+ case 122:
+ keyCode = KEY_Z;
+ break;
+ }
+ }
+ var ctrlKey = event.ctrlKey;
+ var shiftKey = event.shiftKey;
+
+ switch(keyCode) {
+ case KEY_ARROW_DOWN:
+ case KEY_ARROW_LEFT:
+ case KEY_ARROW_RIGHT:
+ case KEY_ARROW_UP:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_PAGE_DOWN:
+ case KEY_PAGE_UP:
+ break;
+ case KEY_TAB:
+ if ( readOnly || !ctrlKey)
+ break;
+
+ var editorWindow = document.getElementById(editorId).contentWindow;
+ var editorDocument = editorWindow.document;
+ var tabText = "&nbsp;&nbsp;&nbsp;&nbsp;";
+
+ if(document.all ){
+ event.keyCode = -1;
+ event.returnValue=false; //IE: cancel the default behavior
+ var rng=editorDocument.selection.createRange();
+ rng.pasteHTML(tabText); //insert 4 spaces for one tab key
+ } else {
+ event.preventDefault();
+ editorDoc.execCommand("insertHTML","",tabText);
+ }
+
+ setTimeout("setStatus(STATUS_MODIFIED, null);", 10);
+ break;
+ case KEY_BACKSPACE:
+ if (!readOnly) {
+ setTimeout("setStatus(STATUS_MODIFIED, null);", 10);
+ }
+ break;
+ case KEY_B:
+ case KEY_U:
+ case KEY_I:
+ if (!readOnly && ctrlKey) {
+ setTimeout("setStatus(STATUS_MODIFIED, null);",10);
+ }
+ break;
+ case KEY_C:
+ if (ctrlKey) {
+ setStatus(STATUS_KEY_DOWN, CMD_COPY);
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ case KEY_F:
+ if (ctrlKey) {
+ if (document.all) {
+ event.keyCode = -1;
+ event.returnValue = false;
+ }
+ else {
+ event.preventDefault();
+ }
+ setStatus(STATUS_KEY_DOWN, CMD_FIND_TEXT);
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ case KEY_S:
+ if (!readOnly && ctrlKey) {
+ if (document.all) {
+ event.keyCode = -1;
+ event.returnValue = false;
+ }
+ else {
+ event.preventDefault();
+ }
+ if (shiftKey) {
+ setStatus(STATUS_KEY_DOWN, CMD_SAVE_ALL);
+ }
+ else {
+ setStatus(STATUS_KEY_DOWN, CMD_SAVE);
+ }
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ case KEY_V:
+ if (ctrlKey) {
+ if (document.all) {
+ event.keyCode = -1;
+ event.returnValue = false;
+ if (!readOnly) {
+ setStatus(STATUS_KEY_DOWN, CMD_PASTE);
+ }
+ }
+ else {
+ if (!readOnly) {
+ // Workaround Mozilla/Firefox paste issues.
+ setTimeout("setStatus(STATUS_KEY_DOWN, CMD_PASTE);", 10);
+ }
+ else {
+ event.preventDefault();
+ }
+ }
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ case KEY_X:
+ if (ctrlKey) {
+ setStatus(STATUS_KEY_DOWN, CMD_CUT);
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ case KEY_Z:
+ if (!readOnly && ctrlKey) {
+ setTimeout("setStatus(STATUS_MODIFIED, null);", 10);
+ }
+ else if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ break;
+ default:
+ if (!document.all && readOnly) {
+ event.preventDefault();
+ }
+ }
+}
+
+function selChanged(event) {
+ updateSelection();
+}
+
+function enableRichTextEditing(html) {
+ var doc = document.getElementById(editorId).contentWindow.document;
+ doc.designMode = "on";
+
+ var htmlSrc = '<html><head><title></title>';
+
+ if (editorCSS != null && editorCSS != '') {
+ htmlSrc += '<link rel="StyleSheet" href="' + editorCSS + '" type="text/css"/>';
+ }
+
+ if (baseHREF != null && baseHREF != '') {
+ htmlSrc += '<base href="' + baseHREF + '"/>';
+ }
+
+ if (!document.all && html == '') {
+ // Mozilla/Firefox will only display the caret if <br/> is added to the HTML body.
+ // Adding <br/> also enables the backspace and delete key by default. Otherwise, the
+ // user need to enter some text before these 2 keys start to function.
+ html = "<br />";
+ }
+
+ htmlSrc += '</head><body>' + html + '</body></html>';
+
+ doc.open();
+ doc.write(htmlSrc);
+ doc.close();
+
+ modified = false;
+
+ if ("attachEvent" in doc) {
+ doc.attachEvent("onkeydown", keyPressed);
+ doc.attachEvent("onkeyup", keyReleased);
+ doc.attachEvent("onselectionchange", selChanged);
+ // for DnD (internal)
+ doc.body.attachEvent("ondrop", checkModified);
+ // for image/table resizing:
+ doc.body.attachEvent("onresizeend", checkModified);
+ }
+ if ("addEventListener" in doc) {
+ doc.addEventListener("keypress", keyPressed, true);
+ doc.addEventListener("keyrelease", keyReleased, true);
+ doc.addEventListener("keypress", selChanged, false);
+ doc.addEventListener("mouseup", selChanged, false);
+ doc.addEventListener("dragdrop", checkModified, false);
+
+ // check mouseup event for image/table resizing
+ doc.addEventListener("mouseup", checkModified, false);
+ }
+
+ setStatus(STATUS_EXEC_CMD, 1);
+}
+
+// this one is for modification check on drag n drop within the RTE
+// checkModified listener
+function checkModified(event) {
+ setTimeout("setStatus(STATUS_MODIFIED, null);", 10);
+}
+
+// Sets the height of the editor.
+function setHeight(height) {
+ if (initialized) {
+ document.getElementById(editorId).height = height + "px";
+ }
+}
+
+// Sets the status.
+// Note: By default, Firefox disables changes to the status bar. For this to work, the user
+// must set the global preference "dom.disable_window_status_change" to false.
+// For Firefox 1.0.x, this setting can be made in /usr/firefox-1.0.7/defaults/pref/firefox.js.
+function setStatus(type, value) {
+ var status = '$$$' + type;
+ if (value != null && value != '') {
+ status += ('$' + value);
+ }
+ window.status = status;
+ window.status = '$$$' + STATUS_NOP;
+}
+
+// Returns the HTML source.
+function getHTML() {
+ var html = document.getElementById(editorId).contentWindow.document.body.innerHTML;
+ if (html == "<P>&nbsp;</P>") {
+ html = "";
+ }
+ if (html != null && html != '') {
+ var regEx = new RegExp("\"file\:([^=]*)(/resources/)([^\"]+)\"", "g");
+ html = html.replace(regEx, "\"./resources/$3\"");
+ regEx = new RegExp("\"file\:([^=]*)/#([^\"]+)\"", "g");
+ html = html.replace(regEx, "\"#$2\"");
+ }
+ return html;
+}
+
+//Returns the HTML source to the Java layer
+function getText() {
+ var html = getHTML();
+ setStatus(STATUS_GET_TEXT, html);
+ return html;
+}
+
+function setInnerHTML(html) {
+ if (document.all) {
+ // IE has problem setting complex HTML set via doc.body.innerHTML.
+ enableRichTextEditing(html);
+ }
+ else {
+ if (html == '') {
+ // Mozilla/Firefox will only display the caret if <br/> is added to the HTML body.
+ html = "<br/>";
+ }
+ var doc = document.getElementById(editorId).contentWindow.document;
+ if (doc.body != null) {
+ doc.body.innerHTML = html;
+ }
+ else {
+ // Mozilla/Firefox can take a while to initialize document.body
+ // after document.write().
+ try {
+ setTimeout("setInnerHTML('" + html + "');", 10);
+ }
+ catch (e) {
+ }
+ }
+ }
+}
+
+// Sets the HTML source.
+function setText(html) {
+ if (supportRichTextEditing) {
+ html = decodeString(html);
+ selectionInfo = getSelectionInfo();
+ setInnerHTML(html);
+ if (selectionInfo != null) {
+ setTimeout("setSelection(selectionInfo);", 10);
+ }
+ modified = false;
+ setStatus(STATUS_EXEC_CMD, 1);
+ }
+}
+
+function setSelection(selectionInfo) {
+ if (!supportRichTextEditing) {
+ return;
+ }
+
+ contentWindow = document.getElementById(editorId).contentWindow;
+ editorDoc = contentWindow.document;
+
+ try {
+ if (document.all) {
+ var startOffset = selectionInfo.start;
+ var len = selectionInfo.len;
+ if (startOffset == 0 && len == 0) {
+ return;
+ }
+ var tempRange = editorDoc.body.createTextRange();
+ tempRange.moveStart('character', startOffset);
+ tempRange.collapse();
+ tempRange.moveEnd('character', len);
+ tempRange.select();
+ tempRange.scrollIntoView();
+ } else {
+ selection = this.window.getSelection();
+ var startContainer = selectionInfo.startContainer;
+ var start = selectionInfo.start;
+ var endContainer = selectionInfo.endContainer;
+ var end = selectionInfo.end;
+ var tempRange = document.createRange();
+ tempRange.setStart(startContainer, start);
+ tempRange.setEnd(endContainer, end);
+ selection.removeAllRanges();
+ selection.addRange(tempRange);
+ contentWindow.focus();
+ }
+ } catch (e) {
+ }
+}
+
+function getSelectionInfo() {
+ if (!supportRichTextEditing) {
+ return null;
+ }
+
+ contentWindow = document.getElementById(editorId).contentWindow;
+ editorDoc = contentWindow.document;
+
+ var tempSelRange;
+ try {
+ if (document.all) {
+ selection = editorDoc.selection;
+ if (selection != null) {
+ tempSelRange = selection.createRange();
+ }
+ // length of selection
+ var tempSelLen = tempSelRange.text.length;
+ // create new range
+ var tempRange = editorDoc.body.createTextRange();
+ // set end of new range to start of selection
+ // this will throw an exception if tempSelRange is not in editor.doc.body (ie, at the start of the RTE).
+ tempRange.setEndPoint("EndToStart", tempSelRange);
+ // length of new range is the start offset
+ var tempText = tempRange.text;
+ // IE counts newlines as 2 characters for length property, but they count as 1 when using moveStart so remove the \r to make the count the same
+ tempText = tempText.replace(/\r/g, "");
+ var startOffset = tempText.length;
+
+ return {start:startOffset, len:tempSelLen};
+ } else {
+ selection = contentWindow.getSelection();
+ if (selection != null) {
+ tempSelRange = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
+ }
+ return {startContainer: tempSelRange.startContainer, start:tempSelRange.startOffset,
+ endContainer: tempSelRange.endContainer, end:tempSelRange.endOffset};
+ }
+ } catch (e) {
+ return null;
+ }
+}
+
+// Decodes the HTML passed from the Java layer.
+function decodeString(str) {
+ if (str != null && str != '') {
+ if (document.all) {
+ str = str.replace(/%sq%/g, "'");
+ str = str.replace(/%EOL%/g, "\n");
+ }
+ else {
+ str = str.replace(/%sq%/g, "&apos;");
+ str = str.replace(/%EOL%/g, "");
+ str = str.replace(/\n/g, "");
+ }
+ }
+ return str;
+}
+
+// updates selection without notifying the Java layer of the selection state
+function internalUpdateSelection() {
+ if (!supportRichTextEditing) {
+ return false;
+ }
+
+ contentWindow = document.getElementById(editorId).contentWindow;
+ editorDoc = contentWindow.document;
+
+ if (document.all) {
+ selection = editorDoc.selection;
+ if (selection != null) {
+ selectionRange = selection.createRange();
+ reformatElementLinks();
+ }
+ }
+ else {
+ selection = contentWindow.getSelection();
+ if (selection != null) {
+ selectionRange = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
+ if (selectionRange.startContainer.nodeName == "HTML" &&
+ selectionRange.endContainer.nodeName == "HTML") {
+ // Mozilla selects the whole document when there's no RTE content, so select just the body
+ selectionRange = editorDoc.createRange();
+ selectionRange.setStart(editorDoc.body, 0);
+ selectionRange.setEnd(editorDoc.body, 0);
+ }
+ }
+ }
+ return true;
+}
+
+// Updates the current selection and selection range.
+function updateSelection() {
+ if (!supportRichTextEditing) {
+ return false;
+ }
+
+ contentWindow = document.getElementById(editorId).contentWindow;
+ editorDoc = contentWindow.document;
+
+ var tempSelRange;
+ var selOffsetStart = 0;
+ var selectedText = "";
+ var fontName = "";
+ var fontSize = "";
+ var blockStyle = "";
+ var textFlags = 0;
+
+
+ if (document.all) {
+ selection = editorDoc.selection;
+ if (selection != null) {
+ selectionRange = selection.createRange();
+ if (selectionRange != null && selection.type != "Control") {
+ tempSelRange = selectionRange.duplicate();
+ }
+ reformatElementLinks();
+ }
+ }
+ else {
+ selection = contentWindow.getSelection();
+ if (selection != null) {
+ selectionRange = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
+ tempSelRange = selectionRange.cloneRange();
+ }
+ }
+ if (tempSelRange != null) {
+ try {
+ if (document.all) {
+ if (selectionRange.text) {
+ selectedText = selectionRange.text;
+ }
+ /* for getting selection offset - commented because we can't select the
+ * proper location in the HTML source tab because JTidy's reformatting of the HTML
+ var html = getHTML();
+ var tempSelLen = tempSelRange.htmlText.length;
+ tempSelRange.moveStart('character', -html.length);
+ selOffsetStart = tempSelRange.htmlText.length - tempSelLen;
+ */
+ var selParent = tempSelRange.parentElement();
+ fontName = tempSelRange.queryCommandValue('fontName');
+ fontSize = tempSelRange.queryCommandValue('fontSize');
+ blockStyle = tempSelRange.queryCommandValue('formatBlock');
+ if (blockStyle == "Normal") {
+ if (selParent.className == "quote") {
+ blockStyle = "<quote>";
+ } else if (selParent.className == "codeSample") {
+ blockStyle = "<code>";
+ } else {
+ blockStyle = "<p>";
+ }
+ } else if (blockStyle == "Heading 3") {
+ blockStyle = "<h3>";
+ } else if (blockStyle == "Heading 4") {
+ blockStyle = "<h4>";
+ } else if (blockStyle == "Heading 5") {
+ blockStyle = "<h5>";
+ } else if (blockStyle == "" || blockStyle == null) {
+ blockStyle = "<p>";
+ }
+ if (tempSelRange.queryCommandValue('bold') == true) {
+ textFlags |= BOLD;
+ }
+ if (tempSelRange.queryCommandValue('italic') == true) {
+ textFlags |= ITALIC;
+ }
+ if (tempSelRange.queryCommandValue('underline') == true) {
+ textFlags |= UNDERLINE;
+ }
+ if (tempSelRange.queryCommandValue('subscript') == true) {
+ textFlags |= SUBSCRIPT;
+ }
+ if (tempSelRange.queryCommandValue('superscript') == true) {
+ textFlags |= SUPERSCRIPT;
+ }
+ setStatus(STATUS_SELECT_TEXT, /* selOffsetStart + "$" + */
+ fontName + "$" + fontSize + "$" + blockStyle + "$" + textFlags + "$" + selectedText);
+ } else {
+ if (selectionRange != null) {
+ selectedText = selectionRange.toString();
+ }
+ var selParent = selection.focusNode;
+ fontName = editorDoc.queryCommandValue('fontName');
+ if (fontName == "") {
+ fontName = "default";
+ }
+ fontSize = editorDoc.queryCommandValue('fontSize');
+ if (fontSize == "") {
+ fontSize = "default";
+ }
+ blockStyle = editorDoc.queryCommandValue('formatBlock');
+ if (blockStyle == "p") {
+ if (selParent.parentNode.className == "quote") {
+ blockStyle = "<quote>";
+ } else if (selParent.parentNode.className == "codeSample") {
+ blockStyle = "<code>";
+ } else {
+ blockStyle = "<p>";
+ }
+ } else if (blockStyle == "h3") {
+ blockStyle = "<h3>";
+ } else if (blockStyle == "h4") {
+ blockStyle = "<h4>";
+ } else if (blockStyle == "h5") {
+ blockStyle = "<h5>";
+ } else if (blockStyle == "") {
+ blockStyle = "<p>";
+ }
+ if (editorDoc.queryCommandState('bold') == true) {
+ textFlags |= BOLD;
+ }
+ if (editorDoc.queryCommandState('italic') == true) {
+ textFlags |= ITALIC;
+ }
+ if (editorDoc.queryCommandState('underline') == true) {
+ textFlags |= UNDERLINE;
+ }
+ if (editorDoc.queryCommandState('subscript') == true) {
+ textFlags |= SUBSCRIPT;
+ }
+ if (editorDoc.queryCommandState('superscript') == true) {
+ textFlags |= SUPERSCRIPT;
+ }
+ setStatus(STATUS_SELECT_TEXT, /* selOffsetStart + "$" + */
+ fontName + "$" + fontSize + "$" + blockStyle + "$" + textFlags + "$" + selectedText);
+ }
+ } catch (e) { }
+ }
+
+ return true;
+}
+
+// Sets focus to this editor.
+function setFocus() {
+ if (!supportRichTextEditing) {
+ return;
+ }
+ if (document.all) {
+ iframe = document.getElementById(editorId);
+ iframe.focus();
+ } else {
+ contentWindow = document.getElementById(editorId).contentWindow;
+ contentWindow.focus();
+ }
+ setStatus(STATUS_EXEC_CMD, 1);
+}
+
+// Reformats element links created via drag & drop.
+function reformatElementLinks() {
+ var linksReformatted = 0;
+ var elements = editorDoc.getElementsByTagName('A');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ if (element.className.toLowerCase() == 'elementlink' ||
+ element.className.toLowerCase() == 'elementlinkwithtype' ||
+ element.className.toLowerCase() == 'elementlinkwithusertext') {
+ if (element.firstChild != null && element.firstChild.firstChild != null &&
+ element.firstChild.firstChild.firstChild != null) {
+ var linkText = element.firstChild.firstChild.firstChild.nodeValue;
+ element.removeChild(element.firstChild);
+ element.appendChild(editorDoc.createTextNode(linkText));
+ linksReformatted++;
+ }
+ }
+ }
+ if (linksReformatted > 0) {
+ setStatus(STATUS_REFORMAT_LINKS, null);
+ }
+}
+
+// Formats the selected text.
+function formatText(command, option) {
+ if (!readOnly && internalUpdateSelection()) {
+ if (editorDoc.execCommand(command, false, option)) {
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ }
+}
+
+// Adds HTML.
+function addHTML(html) {
+ if (!readOnly && html != "") {
+ html = decodeString(html);
+ if (internalUpdateSelection()) {
+ if (document.all) {
+ if (selectionRange.text != null) {
+ selectionRange.pasteHTML(html);
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ }
+ else {
+ selectionRange.deleteContents();
+ var documentFragment = selectionRange.createContextualFragment(html);
+ selectionRange.insertNode(documentFragment);
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ }
+ }
+}
+
+// Adds an image.
+function addImage(url, height, width, alt) {
+ if (internalUpdateSelection()) {
+ if (document.all) {
+ if (url != null && url != '') {
+ formatText('insertimage', url);
+ }
+ if (selection != null && selection.type == 'Control' && selectionRange != null) {
+ if (height != null && height != '') selectionRange.item().height = height;
+ if (width != null && width != '') selectionRange.item().width = width;
+ if (alt != null) selectionRange.item().alt = alt;
+ }
+ } else {
+ var START_MARKER = "A_-_-_";
+ var END_MARKER = ":.:.:";
+ // mark img links with START_MARKER + id + END_MARKER in the id, for later recovery
+ var elements = editorDoc.getElementsByTagName('img');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ element.id = START_MARKER + element.id + END_MARKER;
+ }
+ if (url != null && url != '') {
+ formatText('insertimage', url);
+ }
+ if (internalUpdateSelection()) {
+ var regExID = new RegExp(START_MARKER + "(.*?)" + END_MARKER);
+ var elements = editorDoc.getElementsByTagName('img');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var id = element.id;
+ if (id != null && id != '') {
+ RegExp.lastIndex=0;
+ var matchArray = id.match(regExID);
+ if (matchArray != null && matchArray.length > 0) {
+ var newId = matchArray[1];
+ if (newId.length > 0) {
+ element.id = newId;
+ } else {
+ element.removeAttribute('id');
+ }
+ }
+ } else {
+ // no id, must be the new img
+ if (height != null && height != '') element.height = height;
+ if (width != null && width != '') element.width = width;
+ if (alt != null) element.alt = alt;
+ }
+ }
+ }
+ }
+ setStatus(STATUS_MODIFIED, null);
+ }
+}
+
+// Adds a horizontal line.
+function addLine() {
+ formatText('inserthorizontalrule', null);
+}
+
+// Adds a link.
+function addLink(url) {
+ if (!readOnly && url != null && url != '' && internalUpdateSelection()) {
+ if (document.all) {
+ if (selectionRange.text == null || selectionRange.text == '') {
+ selectionRange.text = url;
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ else if (selectionRange.execCommand('createlink', false, url)) {
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ }
+ else {
+ if (selection == null || selection == "") {
+ var urlTextNode = editorDoc.createTextNode(url);
+ insertNodeAtSelection(document.getElementById(editorFrameId).contentWindow, urlTextNode);
+ }
+ if (editorDoc.execCommand('createlink', false, url)) {
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ }
+ }
+}
+
+// Adds an ordered list.
+function addOrderedList() {
+ formatText('insertorderedlist', null);
+}
+
+// Adds a table.
+function addTable(rows, cols, width, summary, caption, tableheaders) {
+ if (readOnly) return;
+ if (rows == 0) rows = 2;
+ if (cols == 0) cols = 2;
+ if (width == 0) width = "85%";
+ if (internalUpdateSelection()) {
+ var table = editorDoc.createElement("table");
+ table.cellPadding = "2";
+ table.cellSpacing = "0";
+ table.border = "1";
+ table.width = width;
+ table.title = "";
+ if (summary != null && summary != '') {
+ table.summary = summary;
+ }
+ if (caption != null && caption != '') {
+ table.title = caption;
+ table.createCaption();
+ var captionNode = editorDoc.createTextNode(caption);
+ table.caption.appendChild(captionNode);
+ }
+ tbody = editorDoc.createElement("tbody");
+ for (var i = 0; i < rows; i++) {
+ tr = editorDoc.createElement("tr");
+ for (var j = 0; j < cols; j++) {
+ if (i == 0 && (tableheaders == TABLE_HEADERS_COLS || tableheaders == TABLE_HEADERS_BOTH)) {
+ th = editorDoc.createElement("th");
+ th.scope = "col";
+ th.id = "";
+ th.abbr = th.id;
+ var headerNode = editorDoc.createTextNode(th.id);
+ th.appendChild(headerNode);
+ if (!document.all) {
+ br = editorDoc.createElement("br");
+ th.appendChild(br);
+ }
+ tr.appendChild(th);
+ }
+ else if (j == 0 && (tableheaders == TABLE_HEADERS_ROWS || tableheaders == TABLE_HEADERS_BOTH)) {
+ th = editorDoc.createElement("th");
+ th.scope = "row";
+ th.id = "";
+ th.abbr = th.id;
+ var headerNode = editorDoc.createTextNode(th.id);
+ th.appendChild(headerNode);
+ if (!document.all) {
+ br = editorDoc.createElement("br");
+ th.appendChild(br);
+ }
+ tr.appendChild(th);
+ }
+ else {
+ td = editorDoc.createElement("td");
+ if (!document.all) {
+ br = editorDoc.createElement("br");
+ td.appendChild(br);
+ }
+ tr.appendChild(td);
+ }
+ }
+ tbody.appendChild(tr);
+ }
+ table.appendChild(tbody);
+ if (document.all) {
+ selectionRange.parentElement().appendChild(table);
+ }
+ else {
+ selectionRange.insertNode(table);
+ }
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+}
+
+// Adds an unordered list.
+function addUnorderedList() {
+ formatText('insertunorderedlist', null);
+}
+
+// Sets the background color of the selected text.
+function backColor(color) {
+ if (color != null && color != '') {
+ formatText('backcolor', color);
+ }
+}
+
+// Toggles the 'bold' attribute of the selected text.
+function bold() {
+ formatText('bold', null);
+}
+
+// Copies the selected text to the clipboard.
+function copy() {
+ if (internalUpdateSelection()) {
+ if (editorDoc.execCommand('copy', false, null)) {
+ setStatus(STATUS_EXEC_CMD, 1);
+ }
+ }
+}
+
+// Cuts the selected text to the clipboard.
+function cut() {
+ formatText('cut', null);
+}
+
+// Deletes the selected text.
+function deleteText() {
+ formatText('delete', null);
+}
+
+// Finds text.
+function findText(text, dir, options) {
+ if (text == null || text == "") {
+ return;
+ }
+ else {
+ text = decodeString(text);
+ }
+
+ if (internalUpdateSelection()) {
+ if (document.all) {
+ selectionRange.collapse(dir < 0);
+ if (selectionRange.findText(text, dir, options)) {
+ selectionRange.scrollIntoView();
+ selectionRange.select();
+ selectionRange.collapse(dir < 0);
+ setStatus(STATUS_EXEC_CMD, 1);
+ }
+ }
+ else {
+ // find(text, caseSensitive, backwards, wrapAround, wholeWord, searchInFrames, showDialog)
+ var caseSensitive = true;
+ var backwards = false;
+ var wholeWord = true;
+ if ((options & 4) == 0) caseSensitive = false;
+ if (dir == -1) backwards = true;
+ if ((options & 2) == 0) wholeWord = false;
+
+ if ( wholeWord )
+ {
+ while ( contentWindow.find(text, caseSensitive, backwards, false, wholeWord, false, false) )
+ {
+ var ffSelection = contentWindow.getSelection();
+ selectionRange = ffSelection.getRangeAt(0).cloneRange();
+ if (selectionRange.startOffset > 0 )
+ selectionRange.setStart(selectionRange.startContainer, selectionRange.startOffset -1);
+ if (selectionRange.endOffset < selectionRange.endContainer.length )
+ {
+ selectionRange.setEnd(selectionRange.endContainer, selectionRange.endOffset+1);
+ }
+ var newText = selectionRange.toString();
+ var regex = new RegExp("\\b"+text+"\\b");
+
+ if ( newText.match(regex))
+ {
+ setStatus(STATUS_EXEC_CMD, 1);
+ break;
+ }
+ }
+ } else if ( contentWindow.find(text, caseSensitive, backwards, false, wholeWord, false, false) ) {
+ setStatus(STATUS_EXEC_CMD, 1);
+ }
+ }
+ }
+}
+
+// Sets the foreground color of the selected text.
+function foreColor(color) {
+ if (color != null && color != '') {
+ formatText('forecolor', color);
+ }
+}
+
+// Formats the selected text using the given HTML heading tag.
+function formatBlock(tag) {
+ if (tag != null && tag != '') {
+ formatText('formatblock', tag);
+ }
+}
+
+
+var INDENTED_LIST_BAD_HTML_IE = "</li>.*<li style=\"list-style: none\">";
+var INDENTED_LIST_BAD_HTML_MOZ = "</li>.*<li style=\"list-style-type: none; list-style-image: none; list-style-position: outside;\">";
+
+// Indents the selected text.
+function indent() {
+ formatText('indent', null);
+ // fix for sub-lists
+ var html = document.getElementById(editorId).contentWindow.document.body.innerHTML;
+ if (document.all) {
+ html = html.replace(INDENTED_LIST_BAD_HTML_IE, "");
+ } else {
+ // firefox sometimes puts the same as IE, sometimes more junk
+ html = html.replace(INDENTED_LIST_BAD_HTML_IE, "");
+ html = html.replace(INDENTED_LIST_BAD_HTML_MOZ, "");
+ }
+ setText(html);
+}
+
+// Toggles the 'italic' attribute of the selected text.
+function italic() {
+ formatText('italic', null);
+}
+
+// Center justifies the selected text.
+function justifyCenter() {
+ formatText('justifycenter', null);
+}
+
+// Fully justifies the selected text.
+function justifyFull() {
+ formatText('justifyfull', null);
+}
+
+// Left justifies the selected text.
+function justifyLeft() {
+ formatText('justifyleft', null);
+}
+
+// Right justifies the selected text.
+function justifyRight() {
+ formatText('justifyright', null);
+}
+
+// Outdents the selected text.
+function outdent() {
+ formatText('outdent', null);
+}
+
+// Pastes text from the clipboard.
+function paste(sourceURL) {
+ if (sourceURL == null) {
+ sourceURL = "";
+ }
+ else {
+ sourceURL = decodeString(sourceURL);
+ }
+ if (document.all) {
+ var START_MARKER = "A_-_-_";
+ var END_MARKER = ":.:.:";
+ // mark img and <a /> links with START_MARKER + src/href + END_MARKER in the id, for later recovery
+ var elements = editorDoc.getElementsByTagName('img');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var id = element.id;
+ element.id = START_MARKER + element.src + END_MARKER + id;
+ }
+ var elements = editorDoc.getElementsByTagName('a');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var id = element.id;
+ element.id = START_MARKER + element.href + END_MARKER + id;
+ }
+
+ // change the <base> of the document
+ var oldBaseHREF = editorDoc.getElementsByTagName('base')[0].href;
+ editorDoc.getElementsByTagName('base')[0].href = sourceURL;
+
+ formatText('paste', null);
+
+ // restore <base>
+ editorDoc.getElementsByTagName('base')[0].href = oldBaseHREF;
+ }
+ else {
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+ }
+ if (internalUpdateSelection()) {
+ try {
+ var regExRes = new RegExp("file\:([^=]+)(/resources/)(.+)", "g");
+ var regExRef = new RegExp("(.+)(#.+)");
+ var regEx = new RegExp("file\:([^=]+)/([^/]+)", "g");
+ var regExID = new RegExp(START_MARKER + "(.*?)" + END_MARKER + "(.*?)");
+ var elements = editorDoc.getElementsByTagName('img');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var id = element.id;
+ if (id != null && id != '') {
+ RegExp.lastIndex=0;
+ var matchArray = id.match(regExID);
+ if (matchArray != null && matchArray.length > 1) {
+ element.src = matchArray[1];
+ if (matchArray.length > 2 && matchArray[2].length > 0) {
+ element.id = matchArray[2];
+ }
+ else {
+ element.removeAttribute('id');
+ }
+ continue;
+ }
+ }
+ var src = element.src;
+ if (src != null && src != '') {
+ if (src.indexOf('about:./resources') != -1) {
+ // fix for IE 7 when pasting from another RTE
+ // IE7 resolves these as "about:./resources/<file>"
+ // so remove the "about:."
+ src = src.replace("about:", "");
+ }
+ if (src.indexOf('about:resources') != -1) {
+ // fix for IE 7 when pasting from another RTE
+ // IE7 sometimes resolves these as "about:resources/<file>"
+ // so remove the "about:" and put in "./"
+ src = src.replace("about:", "./");
+ }
+ if (src.indexOf('resources') != -1) {
+ element.src = src.replace(regExRes, "./resources/$3");
+ }
+ else {
+ element.src = src.replace(regEx, "./resources/$2");
+ }
+ }
+ }
+ var elements = editorDoc.getElementsByTagName('a');
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ var id = element.id;
+ if (id != null && id != '') {
+ RegExp.lastIndex=0;
+ var matchArray = id.match(regExID);
+ if (matchArray != null && matchArray.length > 1) {
+ element.href = matchArray[1];
+ if (matchArray.length > 2 && matchArray[2].length > 0) {
+ element.id = matchArray[2];
+ }
+ else {
+ element.removeAttribute('id');
+ }
+ continue;
+ }
+ }
+ var href = element.href;
+ if (href != null && href != '') {
+ // fix self-referencing hrefs
+ if (href.indexOf('#') != -1) {
+ RegExp.lastIndex=0;
+ var matchArray = href.match(regExRef);
+ if (matchArray != null && matchArray.length > 2) {
+ var hrefFile = matchArray[1];
+ var ref = matchArray[2];
+ if (hrefFile == sourceURL) {
+ element.href = ref;
+ continue;
+ }
+ }
+ }
+ // fix hrefs already in resources
+ if (href.indexOf('resources') != -1) {
+ element.href = href.replace(regExRes, "./resources/$3");
+ }
+ // fix hrefs not in resources
+ else {
+ element.href = href.replace(regEx, "./resources/$2");
+ }
+ }
+ }
+ }
+ catch (e) {
+ }
+ }
+}
+
+// Redo the previous command.
+function redo() {
+ formatText('redo', null);
+}
+
+// Redo the previous command.
+function removeFormat() {
+ formatText('removeformat', null);
+}
+
+
+
+function _replaceAllText(findText, replaceText, options) {
+ // this is IE only
+ if (document.all) {
+ var tempRange = document.getElementById(editorId).contentWindow.document.body.createTextRange();
+ tempRange.moveStart('character', -10000000000);
+ do {
+ tempRange.collapse();
+ if (tempRange.findText(findText, 10000000000, options)) {
+ tempRange.text = replaceText;
+ tempRange.select();
+ } else {
+ break;
+ }
+ } while (true);
+ }
+}
+
+// Replaces all text.
+function replaceAllText(findText, replaceText, options) {
+ if (readOnly || findText == null || findText == "") {
+ return;
+ }
+ else {
+ findText = decodeString(findText);
+ }
+ if (replaceText == null) {
+ replaceText = "";
+ }
+ else {
+ replaceText = decodeString(replaceText);
+ }
+
+ if (document.all) {
+ // TODO: Move the insertion point to the start of the HTML
+ // and perform a search and replace in the forward direction.
+ _replaceAllText(findText, replaceText, options);
+ }
+ else {
+ // TODO: Emulate the IE implementation.
+ var html = document.getElementById(editorId).contentWindow.document.body.innerHTML;
+ var optionStr = "/g";
+ if ((options & 4) == 0) {
+ optionStr += "i";
+ }
+ var regExp = eval("/" + findText + optionStr);
+ html = html.replace(regExp, replaceText);
+ setText(html);
+ }
+
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+}
+
+// Replaces text.
+function replaceText(replaceText, dir, options) {
+ if (readOnly || !internalUpdateSelection()) {
+ return;
+ }
+ if (replaceText == null) {
+ replaceText = "";
+ }
+ else {
+ replaceText = decodeString(replaceText);
+ }
+ if (document.all) {
+ selectionRange.text = replaceText;
+ if (replaceText != "") {
+ selectionRange.moveStart("word", -1);
+ selectionRange.select();
+ selectionRange.collapse(dir < 0);
+ }
+ }
+ else {
+ selectionRange.deleteContents();
+ selectionRange.insertNode(editorDoc.createTextNode(replaceText));
+ }
+ setStatus(STATUS_EXEC_CMD, 1);
+ setStatus(STATUS_MODIFIED, null);
+}
+
+// Selects all text.
+function selectAll() {
+ if (internalUpdateSelection()) {
+ if (editorDoc.execCommand('selectall', false, null)) {
+ if ( !document.all )
+ {
+ updateSelection();
+ }
+ setStatus(STATUS_EXEC_CMD, 1);
+ }
+ }
+}
+
+// Sets the font name for the selected text.
+function setFontName(name) {
+ if (internalUpdateSelection()) {
+ if (name != null) {
+ if (name == '') {
+ formatText('removeFormat');
+ } else {
+ formatText('fontname', name);
+ }
+ }
+ }
+}
+
+// Sets the font size for the selected text.
+function setFontSize(size) {
+ if (internalUpdateSelection()) {
+ if (size != null) {
+ if (size == '') {
+ formatText('removeFormat');
+ } else {
+ formatText('fontsize', size);
+ }
+ }
+ }
+}
+
+// Sets the font style for the selected text.
+function setFontStyle(style) {
+ if (!readOnly && style != null && style != '' && internalUpdateSelection()) {
+ try {
+ if (document.all) {
+ selectionRange.execCommand("removeformat");
+ selectionRange.parentElement().removeAttribute("className");
+ }
+ }
+ catch (e) {
+ }
+ if (style == "<quote>") {
+ formatText('formatblock', '<p>');
+ if (document.all) {
+ selectionRange.parentElement().className = "quote";
+ }
+ else {
+ selection.focusNode.parentNode.className = "quote";
+ }
+ }
+ else if (style == "<code>") {
+ formatText('formatblock', '<p>');
+ if (document.all) {
+ selectionRange.parentElement().className = "codeSample";
+ }
+ else {
+ selection.focusNode.parentNode.className = "codeSample";
+ }
+ }
+ else {
+ if (!document.all && style == "<p>") {
+ // A hack to get rid of the "className" attribute in Mozilla/Firefox.
+ formatText('formatblock', '<h4>');
+ }
+ formatText('formatblock', style);
+ }
+ }
+}
+
+// Sets whether the content can be edited.
+function setEditable(editable) {
+ var doc = document.getElementById(editorId).contentWindow.document;
+ if (editable != null && editable == 'true') {
+ if (document.all) {
+ doc.body.contentEditable = "true";
+ }
+ else {
+ doc.designMode = "on";
+ }
+ readOnly = false;
+ }
+ else {
+ if (document.all) {
+ doc.body.contentEditable = "false";
+ }
+ else {
+ doc.designMode = "off";
+ }
+ readOnly = true;
+ }
+ setStatus(STATUS_EXEC_CMD, 1);
+}
+
+// Toggles the 'strike-through' attribute of the selected text.
+function strikeThrough() {
+ formatText('strikethrough', size);
+}
+
+// Toggles the 'subscript' attribute of the selected text.
+function subscript() {
+ formatText('subscript', null);
+}
+
+// Toggles the 'superscript' attribute of the selected text.
+function superscript() {
+ formatText('superscript', null);
+}
+
+// Toggles the 'underline' attribute of the selected text.
+function underline() {
+ formatText('underline', null);
+}
+
+// Converts a link to normal text.
+function unlink() {
+ formatText('unlink', null);
+}
+
+function ObjToString(object) {
+ var ret = "Object " + object.name + " is [\n";
+ for (var prop in object) {
+ ret += " " + prop + " is " + object[prop] + ";\n";
+ }
+ return ret + "]";
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.xsl b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.xsl
new file mode 100644
index 00000000000..fc35948be50
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/rte/rte.xsl
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2005, 2006 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
+-->
+
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+<xsl:template match="/rte">
+ <xsl:variable name="rte_id"><xsl:value-of select="@id"/></xsl:variable>
+ <xsl:variable name="rte_js"><xsl:value-of select="@js"/></xsl:variable>
+ <html>
+ <head>
+ <script language="JavaScript" type="text/javascript" src="{$rte_js}"></script>
+ </head>
+ <body leftMargin="0" topMargin="0" marginheight="0" marginwidth="0" scroll="no" style="overflow: hidden">
+ <iframe id="{$rte_id}" name="{$rte_id}" style="border: none;" frameborder="0" scrolling="auto" width="100%" height="100%"></iframe>
+ <script language="JavaScript" type="text/javascript">
+ initEditor('<xsl:value-of select="@id"/>', '<xsl:value-of select="@css"/>', '<xsl:value-of select="@baseURL"/>');
+ </script>
+ </body>
+ </html>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichText.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichText.java
new file mode 100644
index 00000000000..68d20796988
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichText.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+package org.eclipse.epf.richtext;
+
+import java.net.URL;
+import java.util.Iterator;
+
+import org.eclipse.epf.richtext.actions.FindReplaceAction;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * The interface for a rich text control.
+ * <p>
+ * A rich text control is an editable user interface object that displays rich
+ * text and images.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public interface IRichText {
+
+ public static final String PROPERTY_NAME = "richText"; //$NON-NLS-1$
+
+ /**
+ * Returns this rich text control.
+ *
+ * @return this rich text control
+ */
+ public Control getControl();
+
+ /**
+ * Sets the layout data.
+ *
+ * @param layoutData
+ * the layout data to set
+ */
+ public void setLayoutData(Object layoutData);
+
+ /**
+ * Returns the layout data.
+ *
+ * @return this control's layout data
+ */
+ public Object getLayoutData();
+
+ /**
+ * Sets focus to this control.
+ */
+ public void setFocus();
+
+ /**
+ * Tells the control it does not have focus.
+ */
+ public void setBlur();
+
+ /**
+ * Checks whether this control has focus.
+ *
+ * @return <code>true</code> if this control has the user-interface focus
+ */
+ public boolean hasFocus();
+
+ /**
+ * Returns the base path used for resolving text and image links.
+ *
+ * @return the base path used for resolving links in this control
+ */
+ public String getBasePath();
+
+ /**
+ * Returns the editable state.
+ *
+ * @return <code>true</code> if the content is ediatble
+ */
+ public boolean getEditable();
+
+ /**
+ * Sets the editable state.
+ *
+ * @param editable
+ * the editable state
+ */
+ public void setEditable(boolean editable);
+
+ /**
+ * Checks whether the content has been modified.
+ *
+ * @return <code>true</code> if the content has been modified
+ */
+ public boolean getModified();
+
+ /**
+ * Sets the modified state.
+ *
+ * @param modified
+ * the modified state
+ */
+ public void setModified(boolean modified);
+
+ /**
+ * Returns the rich text content.
+ *
+ * @return the rich text content formatted in a markup language
+ */
+ public String getText();
+
+ /**
+ * Sets the rich text content.
+ *
+ * @param text
+ * the rich text content formatted in a markup language
+ */
+ public void setText(String text);
+
+ /**
+ * Restores the rich text content back to the initial value.
+ */
+ public void restoreText();
+
+ /**
+ * Checks whether the editor content has been modified. If it has been
+ * modified, notify the modify listeners.
+ */
+ public void checkModify();
+
+ /**
+ * Returns an object that describes the current selection
+ *
+ * @return a <code>RichTextSelection</code> object
+ */
+ public RichTextSelection 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);
+
+ /**
+ * Sets an application specific property name and value.
+ *
+ * @param key
+ * the name of the property
+ * @param value
+ * the property value
+ */
+ public void setData(String key, Object 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);
+
+ /**
+ * 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);
+
+ /**
+ * 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);
+
+ /**
+ * Returns the modify listeners attached to this control.
+ *
+ * @return an iterator for retrieving the modify listeners
+ */
+ public Iterator<ModifyListener> getModifyListeners();
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * keys are pressed and released within this control.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addKeyListener(KeyListener listener);
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when keys are pressed and released within this control.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeKeyListener(KeyListener listener);
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * the content of this control is modified.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addModifyListener(ModifyListener listener);
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when the content of this control is modified.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeModifyListener(ModifyListener listener);
+
+ /**
+ * Adds the listener to the collection of listeners who will be notifed when
+ * this control is disposed.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addDisposeListener(DisposeListener listener);
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when this control is disposed.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeDisposeListener(DisposeListener listener);
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * help events are generated for this control.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addHelpListener(HelpListener listener);
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when help events are generated for this control.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeHelpListener(HelpListener listener);
+
+ /**
+ * Adds the listener to the collection of listeners who will be notifed when
+ * an event of the given type occurs within this control.
+ *
+ * @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);
+
+ /**
+ * Removes the listener from the collection of listeners who will be notifed
+ * when an event of the given type occurs within this econtrol.
+ *
+ * @param eventType
+ * the type of event to listen to
+ * @param listener
+ * the listener which should no longer be notified when the event
+ * occurs
+ */
+ public void removeListener(int eventType, Listener listener);
+
+ /**
+ * Notifies the modify listeners
+ *
+ */
+ public void notifyModifyListeners();
+
+ /**
+ * Returns the event listeners attached to this control.
+ *
+ * @return an iterator for retrieving the event listeners attached to this
+ * control
+ */
+ public Iterator<RichTextListener> getListeners();
+
+ /**
+ * 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();
+
+ /**
+ * Sets the base URL of the rich text control whose content was last copied
+ * to the clipboard.
+ */
+ public void setCopyURL();
+
+ /**
+ * Disposes the operating system resources allocated by this control.
+ */
+ public void dispose();
+
+ /**
+ * Checks whether this control has been disposed.
+ *
+ * @return <code>true</code> if this control is disposed successfully
+ */
+ public boolean isDisposed();
+
+ /**
+ *
+ * @return the control's FindReplaceAction
+ */
+ public FindReplaceAction getFindReplaceAction();
+
+ /**
+ * Sets the FindReplaceAction to use
+ * @param findReplaceAction
+ */
+ public void setFindReplaceAction(FindReplaceAction findReplaceAction);
+
+ /**
+ * Sets the initialText variable, which stores what is saved on disk
+ * @param text
+ */
+ public void setInitialText(String text);
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextEditor.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextEditor.java
new file mode 100644
index 00000000000..9905e7578f8
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextEditor.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+package org.eclipse.epf.richtext;
+
+import org.eclipse.epf.richtext.actions.FindReplaceAction;
+
+/**
+ * The interface for a rich text editor.
+ * <p>
+ * A rich text editor is a composite user interface object that includes a tool
+ * bar, a tab folder for entering the rich text content, and a tab folder for
+ * viewing and modifying the rich text content in a markup language.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public interface IRichTextEditor extends IRichText {
+
+ /**
+ * Fills the tool bar with rich text action items.
+ *
+ * @param toolBar
+ * a rich text editor tool bar
+ */
+ public void fillToolBar(IRichTextToolBar toolBar);
+
+ /**
+ * Selects the rich text or the markup language tab.
+ *
+ * @param index
+ * <code>0</code> for the rich text tab, <code>1</code> for
+ * the markup language tab
+ */
+ public void setSelection(int index);
+
+ /**
+ * Sets the FindReplaceAction to use
+ * @param findReplaceAction
+ */
+ public void setFindReplaceAction(FindReplaceAction findReplaceAction);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextToolBar.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextToolBar.java
new file mode 100644
index 00000000000..fa8b434f715
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/IRichTextToolBar.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 org.eclipse.epf.richtext.actions.RichTextComboAction;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.ToolBarManager;
+
+/**
+ * The interface for a rich text editor toolbar.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public interface IRichTextToolBar {
+
+
+ /**
+ * Adds a button action to the tool bar.
+ *
+ * @param action
+ * the button action to add
+ */
+ public void addAction(IAction action);
+
+ /**
+ * Adds a combo action to the tool bar.
+ *
+ * @param action
+ * the combo action to add
+ */
+ public void addAction(RichTextComboAction item);
+
+ /**
+ * Adds a separator to the tool bar.
+ */
+ public void addSeparator();
+
+ /**
+ * Updates the toolbar state.
+ * <p>
+ * Enables/disables actions depending on the currently selected
+ * RichTextEditor tab (RichText vs. HTML)
+ *
+ * @param editable specifies whether to enable non-ReadOnly commands
+ */
+ public void updateToolBar(boolean enabled);
+
+ /**
+ *
+ * @return the toolbar manager
+ */
+ public ToolBarManager getToolbarMgr();
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/Resources.properties b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/Resources.properties
new file mode 100644
index 00000000000..1eeeb7bc043
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/Resources.properties
@@ -0,0 +1,160 @@
+###############################################################################
+# Copyright (c) 2009 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 API and implementation
+###############################################################################
+#-------------------------------------------------------------------------------
+# Copyright (c) 2000, 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.
+#-------------------------------------------------------------------------------
+# NLS_MESSAGEFORMAT_VAR
+
+################################################################################
+# BEGIN NO TRANSLATION
+###############################################################################
+# !! DO NOT TRANSLATE THE FOLLOWING LINE !!
+fontNameAction_CSS_Default=arial, helvetica, sans-serif
+# !! DO NOT TRANSLATE THE FOLLOWING LINE !!
+fontNameAction_CSS_Default_Mozilla=arial,helvetica,sans-serif
+################################################################################
+# END NO TRANSLATION
+################################################################################
+
+
+
+# Font Style Names
+fontStyle_normal=Normal
+fontStyle_sectionHeading=Section Heading
+fontStyle_subsectionHeading=Subsection Heading
+fontStyle_subSubsectionHeading=Sub Subsection Heading
+fontStyle_quote=Quote
+fontStyle_codeSample=Code Sample
+
+# HTML Block Tags
+blockTag_paragraph=Paragraph
+blockTag_heading1=Heading 1
+blockTag_heading2=Heading 2
+blockTag_heading3=Heading 3
+blockTag_heading4=Heading 4
+blockTag_heading5=Heading 5
+blockTag_heading6=Heading 6
+blockTag_address=Address
+blockTag_preformattedText=Preformatted Text
+
+# HTML Font Names
+fontName_default=Default
+fontName_arial=Arial
+fontName_courierNew=Courier New
+fontName_timesNewRoman=Times New Roman
+fontName_verdana=Verdana
+
+# Rich Text Editor Tool Buttons
+addHorizontalBarAction_toolTipText=Add Horizontal Bar
+addImageAction_toolTipText=Add Image
+addLineAction_toolTipText=Add Line
+addLinkAction_toolTipText=Add Link
+addOrderedListAction_toolTipText=Add Ordered List
+addTableAction_toolTipText=Add Table
+addUnorderedListAction_toolTipText=Add Unordered List
+boldAction_toolTipText=Bold
+clearContentAction_toolTipText=Clear Content
+copyAction_toolTipText=Copy
+cutAction_toolTipText=Cut
+findReplaceAction_toolTipText=Find/Replace
+indentAction_toolTipText=Indent
+italicAction_toolTipText=Italic
+justifyCenterAction_toolTipText=Justify Center
+justifyFullAction_toolTipText=Justify Full
+justifyLeftAction_toolTipText=Justify Left
+justifyRightAction_toolTipText=Justify Right
+outdentAction_toolTipText=Outdent
+pasteAction_toolTipText=Paste
+pastePlainTextAction_toolTipText=Paste as plain text
+subscriptAction_toolTipText=Subscript
+superscriptAction_toolTipText=Superscript
+underlineAction_toolTipText=Underline
+tidy_clean_text=Default Clean
+tidy_cleaner_text=Clean MS HTML
+tidy_cleanest_text=Clean Word 2000 HTML
+tidy_clean_toolTipText=Clean with JTidy using default options
+tidy_cleaner_toolTipText=Clean HTML of MS HTML
+tidy_cleanest_toolTipText=Clean Word 2000 HTML
+addCodeAction_toolTipText=Insert custom html (javascript or video)
+
+# Rich Text Editor Comboboxes
+fontStyleAction_toolTipText=Set Font Style
+blockTagAction_toolTipText=Set Block Tag
+fontNameAction_toolTipText=Set Font
+fontNameAction_DefaultFontName=Default font
+fontSizeAction_toolTipText=Set Font Size
+
+# Rich Text Editor Context Menu Items
+cutAction_text=&Cut
+copyAction_text=C&opy
+pasteAction_text=&Paste
+pastePlainTextAction_text=Paste &as plain text
+
+# Rich Text Editor Tabs
+richTextTab_text=Rich Text
+richTextTab_toolTipText=Edit content in rich text
+htmlTab_text=HTML
+htmlTab_toolTipText=Edit content in HTML
+
+# Add Dialogs
+addImageDialog_title=Add Image
+addLinkDialog_title=Add Link
+addTableDialog_title=Add Table
+findReplaceDialog_title=Find/Replace
+urlLabel_text=URL:
+summaryLabel_text=Summary:
+captionLabel_text=Caption:
+rowsLabel_text=Rows:
+columnsLabel_text=Columns:
+widthLabel_text=Width:
+tableStyleLabel_text=Style:
+tableHeaderNone_text=Table with no headers
+tableHeaderCols_text=Table with column headers
+tableHeaderRows_text=Table with row headers
+tableHeaderBoth_text=Table with column and row headers
+browseButton_text=Browse...
+addCodeDialog_title=Insert Custom Html
+addCodeDialog_Msg=Input your html for javascript or video:
+
+# Clear Editor Content Dialog
+clearContentDialog_title=Clear Editor Content Confirmation
+clearContentDialog_text=Do you really want to clear the content of this rich text editor?
+
+# Find/Replace Dialog
+findLabel_text=Find:
+replaceLabel_text=Replace with:
+optionsGroup_text=Options
+caseSensitiveCheckbox_text=Case sensitive
+wholeWordCheckbox_text=Whole word
+directionGroup_text=Direction
+forwardRadioButton_text=Forward
+backwardRadioButton_text=Backward
+findButton_text=Find
+replaceButton_text=Replace
+replaceFindButton_text=Replace/Find
+replaceallButton_text=Replace All
+# taken from org.eclipse.ui.workbench.texteditor
+FindReplace_Status_noMatch_label=String Not Found
+
+# Preference Page
+maxCharsPerLineLabel_text=Maximum characters per line:
+indentHTMLCheckbox_text=Indent HTML tags
+indentSizeLabel_text=Indent Size:
+urlDisplayNameLabel_text=URL Display Name:
+
+
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichText.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichText.java
new file mode 100644
index 00000000000..7843a6d70b2
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichText.java
@@ -0,0 +1,1657 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.io.File;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.CommonPlugin;
+import org.eclipse.epf.common.IHTMLFormatter;
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.utils.ExtensionHelper;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.epf.common.utils.XMLUtil;
+import org.eclipse.epf.common.xml.XSLTProcessor;
+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.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.LocationAdapter;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.StatusTextEvent;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.HelpListener;
+import org.eclipse.swt.events.KeyAdapter;
+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.layout.GridData;
+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;
+
+/**
+ * The default rich text control implementation.
+ * <p>
+ * The default rich text editor uses XHTML as the underlying markup language for
+ * the rich text content. It is implemented using a SWT <code>Browser</code>
+ * control and DHTML (HTML, CSS and JavaScript).
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class RichText implements IRichText {
+
+ // Encoded single quote. All single quotes need to be specially encoded to
+ // avoid JavaScript error when calling Browse.executeCommand().
+ private static final String ENCODED_SINGLE_QUOTE = "%sq%"; //$NON-NLS-1$
+
+ private static final String ENCODED_NEWLINE = "%EOL%"; //$NON-NLS-1$
+
+ protected static final String STATUS_PREFIX = "$$$"; //$NON-NLS-1$
+
+ protected static final int STATUS_PREFIX_LENGTH = STATUS_PREFIX.length();
+
+ protected static final int STATUS_NOP = 0;
+
+ protected static final int STATUS_INITIALIZED = 1;
+
+ protected static final int STATUS_MODIFIED = 2;
+
+ protected static final int STATUS_GET_TEXT = 3;
+
+ protected static final int STATUS_KEY_DOWN = 4;
+
+ protected static final int STATUS_KEY_UP = 5;
+
+ protected static final int STATUS_SELECT_TEXT = 6;
+
+ protected static final int STATUS_SELECT_CONTROL = 7;
+
+ protected static final int STATUS_SELECT_NONE = 8;
+
+ protected static final int STATUS_EXEC_CMD = 9;
+
+ protected static final int STATUS_REFORMAT_LINKS = 10;
+
+ // The default base path used for resolving links (<href>, <img>, etc.)
+ private static final String DEFAULT_BASE_PATH = System
+ .getProperty("user.home") //$NON-NLS-1$
+ + System.getProperty("file.separator") + "rte"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ // If true, log debugging info.
+ protected boolean debug;
+
+ // The plug-in logger.
+ protected Logger logger;
+
+ // The underlying SWT Browser used for loading the JavaScript/DHTML editor.
+ protected Browser editor;
+
+ // The underlying OleControlSite for the SWT Browser (Win32 only).
+ protected Control editorControl;
+
+ // The base URL of the rich text control whose content was last
+ // copied to the clipboard.
+ protected static URL copyURL;
+
+ // The context menu associated with this control.
+ protected Menu contextMenu;
+
+ // The folder that contains the supporting CSS and JavaScript files
+ protected String rteFolder;
+
+ // The URL that points to the supporting CSS and JavaScript files.
+ protected String rteURL;
+
+ // The base path used for resolving links (<href>, <img>, etc.)
+ protected String basePath;
+
+ // The DHTML initialization flag.
+ protected boolean initialized;
+
+ // The initial focus.
+ protected boolean initializedWithFocus;
+
+ // The control's initial text. This is used to cache the HTML source passed
+ // in via setText()while the DHTML initialization is happening.
+ protected String initialText;
+
+ // The control's current text.
+ protected String currentText = ""; //$NON-NLS-1$
+
+ // The control's editable flag.
+ protected boolean editable = true;
+
+ // The control's modification flag.
+ protected boolean modified;
+
+ // The control's text and object selection flag.
+ protected boolean hasSelection;
+
+ // The control's text selection
+ protected RichTextSelection richTextSelection = new RichTextSelection();
+
+ // JavaScript command execution status code.
+ protected int status = 0;
+
+ // The HTML source formatter.
+ protected IHTMLFormatter htmlFormatter;
+
+ // The SWT event listeners.
+ protected Map<Listener, RichTextListener> listeners;
+
+ // The modify listeners.
+ protected List<ModifyListener> modifyListeners;
+
+ // The control's edit flag.
+ protected boolean notifyingModifyListeners = false;
+
+ // The controls's focus flag.
+ protected boolean hasFocus = false;
+
+ // The controls's processing JavaScript event flag.
+ protected boolean processingJSEvent = false;
+
+ // The controls's processing MODIFIED JavaScript event flag.
+ protected boolean checkingModifyEvent = false;
+
+ // The control's find/replace text action
+ protected FindReplaceAction findReplaceAction;
+
+ // The control's IE flag
+ protected boolean isIE = false;
+
+ // A event type indicate control has been initialized
+ public static final int RICH_TEXT_INITIALIZED_WIN32 = 98979695;
+ public static final int RICH_TEXT_INITIALIZED_LINUX = 98979694;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent composite
+ * @param style
+ * the style for this control
+ * @param basePath
+ * the path used for resolving links
+ */
+ public RichText(Composite parent, int style, String basePath) {
+ debug = RichTextPlugin.getDefault().isDebugging();
+ logger = RichTextPlugin.getDefault().getLogger();
+ findReplaceAction = new FindReplaceAction(this);
+ rteFolder = RichTextPlugin.getDefault().getInstallPath() + "rte/"; //$NON-NLS-1$
+ rteURL = XMLUtil.escape("file://" + rteFolder); //$NON-NLS-1$
+ setBasePath(basePath);
+
+ try {
+ editor = new Browser(parent, SWT.NONE);
+ if (debug) {
+ printDebugMessage("RichText", "basePath=" + basePath); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ editor.setLayoutData(new GridData(GridData.FILL_BOTH));
+ editor.setData(PROPERTY_NAME, this);
+ init(parent, style);
+ } catch (Exception e) {
+ editor = null;
+ String msg = "Failed to create RichText with basePath=" + basePath; //$NON-NLS-1$
+ logger.logError(msg, e);
+ if (debug) {
+ System.out.println(msg);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent composite
+ * @param style
+ * the style for this control
+ */
+ public RichText(Composite parent, int style) {
+ this(parent, style, null);
+ }
+
+ /**
+ * Sets the base path for resolving links.
+ */
+ protected void setBasePath(String path) {
+ if (path != null && path.length() > 0) {
+ if (path.startsWith(FileUtil.UNC_PATH_PREFIX)) {
+ basePath = FileUtil.UNC_PATH_PREFIX
+ + FileUtil.appendSeparator(path.substring(
+ FileUtil.UNC_PATH_PREFIX_LENGTH).replace('\\',
+ '/'), "/"); //$NON-NLS-1$
+ } else {
+ basePath = FileUtil.appendSeparator(path).replace('\\', '/');
+ }
+ } else {
+ basePath = FileUtil.appendSeparator(DEFAULT_BASE_PATH).replace(
+ '\\', '/');
+ }
+ }
+
+ /**
+ * Initializes this control.
+ *
+ * @param parent
+ * the parent composite
+ * @param style
+ * the style for this control
+ * @throws Exception
+ * when an error has occurred while initialzing this control
+ */
+ protected void init(Composite parent, int style) throws Exception {
+ try {
+ addStatusTextListener();
+ if (debug) {
+ printDebugMessage("init", "added status text listener"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ String editorHTML = generateEditorHTML();
+ if (debug) {
+ printDebugMessage("init", "generated editor HTML"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ editor.setText(editorHTML);
+ if (debug) {
+ printDebugMessage("init", "loaded editor HTML"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ contextMenu = new Menu(parent.getShell(), SWT.POP_UP);
+ editor.setMenu(contextMenu);
+ fillContextMenu(contextMenu);
+ if (debug) {
+ printDebugMessage("init", "added context menu"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ addListeners();
+ if (debug) {
+ printDebugMessage("init", "added listeners"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+// htmlFormatter = new HTMLFormatter();
+ htmlFormatter = (IHTMLFormatter) ExtensionHelper.createExtensionForJTidy(
+ CommonPlugin.getDefault().getId(), "htmlFormatter"); //$NON-NLS-1$
+ if (debug) {
+ printDebugMessage("init", "instantiated HTMLFormatter"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ } catch (Exception e) {
+ editor = null;
+ dispose();
+ throw e;
+ }
+ }
+
+ /**
+ * Returns this rich text control.
+ *
+ * @return this rich text control
+ */
+ public Control getControl() {
+ return editor;
+ }
+
+ /**
+ * Sets the layout data.
+ *
+ * @param layoutData
+ * the layout data to set
+ */
+ public void setLayoutData(Object layoutData) {
+ if (editor != null) {
+ editor.setLayoutData(layoutData);
+ }
+ }
+
+ /**
+ * Returns the layout data.
+ *
+ * @return this control's layout data
+ */
+ public Object getLayoutData() {
+ if (editor != null) {
+ return editor.getLayoutData();
+ }
+ return null;
+ }
+
+ /**
+ * Sets focus to this control.
+ */
+ public void setFocus() {
+ if (debug) {
+ printDebugMessage("setFocus, editable=" + editable); //$NON-NLS-1$
+ }
+ if (editor != null) {
+ if (initialized) {
+ if (!editor.isFocusControl()) {
+ if (!Platform.getOS().equals("win32")) { //$NON-NLS-1$
+ // Workaround for Mozilla and Firefox rich text editor focus
+ // issue.
+ editor.setFocus();
+ }
+ executeCommand(RichTextCommand.SET_FOCUS);
+ }
+ hasFocus = true;
+ } else {
+ initializedWithFocus = true;
+ }
+ }
+ }
+
+ /**
+ * Tells the control it does not have focus.
+ */
+ public void setBlur() {
+ if (debug) {
+ printDebugMessage("setBlur, editable=" + editable); //$NON-NLS-1$
+ }
+ if (editor != null) {
+ if (initialized) {
+ hasFocus = false;
+ } else {
+ initializedWithFocus = false;
+ }
+ }
+ }
+
+ /**
+ * Checks whether this control has focus.
+ *
+ * @return <code>true</code> if this control has the user-interface focus
+ */
+ public boolean hasFocus() {
+ if (editor != null) {
+ return hasFocus;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the base path used for resolving text and image links.
+ *
+ * @return the base path used for resolving links in this control
+ */
+ 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() {
+ return copyURL;
+ }
+
+ /**
+ * Sets the base URL of the rich text control whose content was last copied
+ * to the clipboard.
+ */
+ public void setCopyURL() {
+ try {
+ copyURL = new File(basePath).toURL();
+ } catch (Exception e) {
+ copyURL = null;
+ }
+ }
+
+ /**
+ * Returns the editable state.
+ *
+ * @return <code>true</code> if the content is editable
+ */
+ public boolean getEditable() {
+ return editable;
+ }
+
+ /**
+ * Sets the editable state.
+ *
+ * @param editable
+ * the editable state
+ */
+ public void setEditable(boolean editable) {
+ this.editable = editable;
+ if (initialized) {
+ executeCommand(RichTextCommand.SET_EDITABLE, "" + editable); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Checks whether the content has been modified.
+ *
+ * @return <code>true</code> if the content has been modified
+ */
+ public boolean getModified() {
+ return modified;
+ }
+
+ /**
+ * Sets the modified state.
+ *
+ * @param modified
+ * the modified state
+ */
+ public void setModified(boolean modified) {
+ this.modified = modified;
+ }
+
+ /**
+ * Returns the rich text content.
+ *
+ * @return the rich text content formatted in a markup language
+ */
+ public String getText() {
+ if (editor != null && initialized) {
+ try {
+ executeCommand(RichTextCommand.GET_TEXT);
+ if (currentText != null && currentText.length() > 0) {
+ currentText = currentText.replaceAll(
+ "<P>&nbsp;</P>", "<br/>"); //$NON-NLS-1$ //$NON-NLS-2$
+ currentText = tidyText(currentText);
+ currentText = formatHTML(currentText);
+ } else {
+ currentText = ""; //$NON-NLS-1$
+ }
+ if (debug) {
+ printDebugMessage("getText", "text=", currentText); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return currentText;
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ protected String formatHTML(String text) {
+ String formattedText;
+ try {
+ // Call JTidy to format the source to XHTML.
+ formattedText = htmlFormatter.formatHTML(text);
+ if (htmlFormatter.getLastErrorStr() != null) {
+ logger.logError(htmlFormatter.getLastErrorStr());
+ }
+ return formattedText;
+ } catch (UnsupportedEncodingException e) {
+ logger.logError(e);
+ }
+ return text;
+ }
+
+ /**
+ * Sets the rich text content.
+ *
+ * @param text
+ * the rich text content formatted in a markup language
+ */
+ public void setText(String text) {
+ if (editor != null) {
+ if (debug) {
+ printDebugMessage("setText", "text=", text); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ String newText = text;
+ if (newText != null) {
+ newText = tidyText(newText);
+ // Call JTidy to format the source to XHTML.
+ newText = formatHTML(newText);
+ } else {
+ newText = ""; //$NON-NLS-1$
+ }
+
+ if (initialized) {
+ modified = !newText.equals(currentText);
+ }
+ initialText = newText;
+ if (initialText.equals("") && !isIE) { //$NON-NLS-1$
+ initialText = "<br />"; //$NON-NLS-1$
+ }
+
+ if (debug) {
+ printDebugMessage(
+ "setText", "modified=" + modified + ", newText=", newText); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ if (initialized) {
+ try {
+ executeCommand(RichTextCommand.SET_TEXT, workaroundForObjectParamNode(newText));
+ executeCommand(RichTextCommand.SET_EDITABLE, "" + editable); //$NON-NLS-1$
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+
+ currentText = newText;
+ }
+ }
+
+ /**
+ * Restores the rich text content back to the initial value.
+ */
+ public void restoreText() {
+ setText(initialText);
+ modified = false;
+ }
+
+ /**
+ * Returns the currently selected text.
+ *
+ * @return the selected text or <code>""</code> if there is no
+ * hasSelection
+ */
+ public String getSelectedText() {
+ // executeCommand(RichTextCommand.GET_SELECTED_TEXT);
+ return richTextSelection.getText();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.epf.richtext.IRichText#getSelected()
+ */
+ public RichTextSelection getSelected() {
+ return richTextSelection;
+ }
+
+ /**
+ * 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 (editor != null) {
+ return editor.getData(key);
+ }
+ return null;
+ }
+
+ /**
+ * Sets an application specific property name and value.
+ *
+ * @param key
+ * the name of the property
+ * @param value
+ * the property value
+ */
+ public void setData(String key, Object value) {
+ if (editor != null) {
+ editor.setData(key, value);
+ }
+ }
+
+ /**
+ * Executes the given JavaScript.
+ *
+ * @param script
+ * the JavaScript to execute
+ * @return a status code returned by the executed script
+ */
+ protected int execute(final String script) {
+ status = 0;
+ if (editor != null && script != null && script.length() > 0) {
+ try {
+ if (!isIE && processingJSEvent) {
+ Display.getCurrent().asyncExec(new Runnable() {
+ public void run() {
+ if (!isDisposed()) {
+ editor.execute(script);
+ if (!Platform.getOS().equals(Platform.OS_WIN32)) {
+ if (script.startsWith(RichTextCommand.SET_TEXT)) {
+ notifyListeners(RichText.RICH_TEXT_INITIALIZED_LINUX, new Event());
+ }
+ }
+ }
+ }
+ });
+ } else {
+ editor.execute(script);
+ }
+ if (debug) {
+ printDebugMessage("execute", script); //$NON-NLS-1$
+ }
+ } catch (Exception e) {
+ String msg = "Failed to execute " + script; //$NON-NLS-1$
+ logger.logError(msg, e);
+ if (debug) {
+ printDebugMessage("execute", msg); //$NON-NLS-1$
+ e.printStackTrace();
+ }
+ }
+ }
+ return status;
+ }
+
+ /**
+ * 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) {
+ status = 0;
+ if (command != null && command.equals(RichTextCommand.CLEAR_CONTENT)) {
+ String oldInitialText = initialText;
+ setText(""); //$NON-NLS-1$
+ initialText = oldInitialText;
+ status = 1;
+ modified = true;
+ notifyModifyListeners();
+ } else {
+ status = execute(command + "();"); //$NON-NLS-1$
+ }
+ return status;
+ }
+
+ /**
+ * 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 (param == null) {
+ return executeCommand(command);
+ }
+ return execute(command + "('" + formatText(param) + "');"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * 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 (params == null || params.length == 0) {
+ return executeCommand(command);
+ }
+ StringBuffer sb = new StringBuffer();
+ int paramsLength = params.length;
+ for (int i = 0; i < paramsLength; i++) {
+ sb.append('\'').append(formatText(params[i])).append('\'');
+ if (i < paramsLength - 1) {
+ sb.append(',');
+ }
+ }
+ String param = sb.toString();
+ return execute(command + "(" + param + ");"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Disposes the operating system resources allocated by the control.
+ */
+ public void dispose() {
+ if (contextMenu != null && !contextMenu.isDisposed()) {
+ contextMenu.dispose();
+ contextMenu = null;
+ }
+ if (listeners != null) {
+ listeners.clear();
+ listeners = null;
+ }
+ if (modifyListeners != null) {
+ modifyListeners.clear();
+ modifyListeners = null;
+ }
+ if (htmlFormatter != null) {
+ htmlFormatter = null;
+ }
+ if (this.findReplaceAction != null) {
+ this.findReplaceAction.dispose();
+ this.findReplaceAction = null;
+ }
+ }
+
+ /**
+ * Checks whether this control has been disposed.
+ *
+ * @return <code>true</code> if this control is disposed successfully
+ */
+ public boolean isDisposed() {
+ return editor.isDisposed();
+ }
+
+ /**
+ * Returns the modify listeners attached to this control.
+ *
+ * @return an iterator for retrieving the modify listeners
+ */
+ public Iterator<ModifyListener> getModifyListeners() {
+ return modifyListeners.iterator();
+ }
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * keys are pressed and released within this control.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addKeyListener(KeyListener listener) {
+ if (editor != null) {
+ editor.addKeyListener(listener);
+ }
+ }
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when keys are pressed and released within this control.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeKeyListener(KeyListener listener) {
+ if (editor != null) {
+ editor.removeKeyListener(listener);
+ }
+ }
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * the content of this control is modified.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addModifyListener(ModifyListener listener) {
+ if (editor != null && listener != null
+ && !modifyListeners.contains(listener)) {
+ modifyListeners.add(listener);
+ }
+ }
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when the content of this control is modified.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeModifyListener(ModifyListener listener) {
+ if (editor != null && listener != null
+ && modifyListeners.contains(listener)) {
+ modifyListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notifed when
+ * this control is disposed.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addDisposeListener(DisposeListener listener) {
+ if (editor != null) {
+ editor.addDisposeListener(listener);
+ }
+ }
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when this control is disposed.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeDisposeListener(DisposeListener listener) {
+ if (editor != null) {
+ editor.removeDisposeListener(listener);
+ }
+ }
+
+ /**
+ * Adds a listener to the collection of listeners who will be notified when
+ * help events are generated for this control.
+ *
+ * @param listener
+ * the listener which should be notified
+ */
+ public void addHelpListener(HelpListener listener) {
+ if (editor != null) {
+ editor.addHelpListener(listener);
+ }
+ }
+
+ /**
+ * Removes a listener from the collection of listeners who will be notified
+ * when help events are generated for this control.
+ *
+ * @param listener
+ * the listener which should no longer be notified
+ */
+ public void removeHelpListener(HelpListener listener) {
+ if (editor != null) {
+ editor.removeHelpListener(listener);
+ }
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notifed when
+ * an event of the given type occurs within this control.
+ *
+ * @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 (editor != null && !listeners.containsKey(listener)) {
+ if (eventType != SWT.SELECTED) {
+ if (editorControl == null
+ || (eventType != SWT.Activate
+ && eventType != SWT.Deactivate
+ && eventType != SWT.FocusIn && eventType != SWT.FocusOut)) {
+ editor.addListener(eventType, listener);
+ }
+ }
+ listeners.put(listener, new RichTextListener(eventType, listener));
+ }
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be notifed
+ * when an event of the given type occurs within this control.
+ *
+ * @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 (editor != null && listeners.containsKey(listener)) {
+ if (editorControl == null
+ || (eventType != SWT.Activate
+ && eventType != SWT.Deactivate
+ && eventType != SWT.FocusIn && eventType != SWT.FocusOut)) {
+ editor.removeListener(eventType, listener);
+ }
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Returns the event listeners attached to this control.
+ *
+ * @return an iterator for retrieving the event listeners attached to this
+ * control
+ */
+ public Iterator<RichTextListener> getListeners() {
+ return listeners.values().iterator();
+ }
+
+ /**
+ * Adds the listener to monitor events and status sent by the underlying
+ * DHTML editor.
+ */
+ protected void addStatusTextListener() {
+ editor.addStatusTextListener(new StatusTextListener() {
+ public void changed(StatusTextEvent event) {
+ String eventText = event.text;
+ int eventTextLength = eventText.length();
+ if (eventText.startsWith(STATUS_PREFIX)
+ && eventTextLength > STATUS_PREFIX_LENGTH) {
+ try {
+ processingJSEvent = true;
+ int endStatusIndex = STATUS_PREFIX_LENGTH + 1;
+ if (eventText.length() > STATUS_PREFIX_LENGTH + 1
+ && Character.isDigit(eventText
+ .charAt(endStatusIndex))) {
+ endStatusIndex++;
+ }
+ int statusType = Integer.parseInt(eventText.substring(
+ STATUS_PREFIX_LENGTH, endStatusIndex));
+ switch (statusType) {
+ case STATUS_NOP:
+ break;
+ case STATUS_INITIALIZED:
+ if (!initialized) {
+ initialized = true;
+ if (debug) {
+ printDebugMessage(
+ "statusTextListener", "STATUS_INITIALIZED"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!Platform.getOS().equals("win32")) { //$NON-NLS-1$
+ // Workaround Mozilla'a IFRAME
+ // height issue.
+ executeCommand(RichTextCommand.SET_HEIGHT,
+ "" + editor.getBounds().height); //$NON-NLS-1$
+ }
+ executeCommand(RichTextCommand.SET_TEXT,
+ workaroundForObjectParamNode(currentText));
+ if (initializedWithFocus) {
+ setFocus();
+ }
+ if (!editable) {
+ executeCommand(
+ RichTextCommand.SET_EDITABLE,
+ "" + editable); //$NON-NLS-1$
+ }
+
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ notifyListeners(RichText.RICH_TEXT_INITIALIZED_WIN32, new Event());
+ }
+ }
+ break;
+ case STATUS_MODIFIED:
+ if (debug) {
+ printDebugMessage(
+ "statusTextListener", "STATUS_MODIFIED"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ checkModify();
+ break;
+ case STATUS_GET_TEXT:
+ if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
+ currentText = eventText
+ .substring(STATUS_PREFIX_LENGTH + 2);
+
+ currentText = unWorkaroundForObjectParamNode(currentText);
+ } else {
+ currentText = ""; //$NON-NLS-1$
+ }
+ if (debug) {
+ printDebugMessage(
+ "statusTextListener", //$NON-NLS-1$
+ "STATUS_GET_TEXT, currentText=", currentText); //$NON-NLS-1$
+ }
+ break;
+ case STATUS_KEY_DOWN:
+ if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
+ String cmd = eventText
+ .substring(STATUS_PREFIX_LENGTH + 2);
+ if (debug) {
+ printDebugMessage("statusTextListener", //$NON-NLS-1$
+ "STATUS_KEY_DOWN, cmd=" + cmd); //$NON-NLS-1$
+ }
+ if (cmd.equals(RichTextCommand.COPY)) {
+ setCopyURL();
+ } else if (cmd.equals(RichTextCommand.CUT)) {
+ setCopyURL();
+ CutAction action = new CutAction(
+ RichText.this);
+ action.execute(RichText.this);
+ } else if (cmd
+ .equals(RichTextCommand.FIND_TEXT)) {
+ getFindReplaceAction().execute(
+ RichText.this);
+ } else if (cmd.equals(RichTextCommand.PASTE)) {
+ PasteAction action = new PasteAction(
+ RichText.this);
+ action.execute(RichText.this);
+ } else if (cmd.equals(RichTextCommand.SAVE)) {
+ PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow()
+ .getActivePage().getActiveEditor()
+ .doSave(null);
+ } else if (cmd.equals(RichTextCommand.SAVE_ALL)) {
+ PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow()
+ .getActivePage().saveAllEditors(
+ false);
+ }
+ }
+ break;
+ case STATUS_KEY_UP:
+ if (debug) {
+ printDebugMessage("statusTextListener", //$NON-NLS-1$
+ "STATUS_KEY_UP, modified=" + modified); //$NON-NLS-1$
+ }
+ checkModify();
+ break;
+ case STATUS_SELECT_TEXT:
+ if (eventTextLength >= STATUS_PREFIX_LENGTH + 2) {
+ String[] strings = eventText.substring(
+ STATUS_PREFIX_LENGTH + 2).split(
+ "\\$", 5); //$NON-NLS-1$
+ try {
+ richTextSelection.setFontName(strings[0]);
+ richTextSelection.setFontSize(strings[1]);
+ richTextSelection.setBlockStyle(strings[2]);
+ richTextSelection.setFlags(Integer
+ .parseInt(strings[3]));
+ richTextSelection.setText(strings[4]);
+ } catch (NumberFormatException e) {
+ logger.logError(e);
+ }
+ if (debug) {
+ printDebugMessage(
+ "selectionStatusListener", //$NON-NLS-1$
+ "current selection is=" + richTextSelection); //$NON-NLS-1$
+ }
+
+ hasSelection = true;
+ if (hasFocus())
+ notifyListeners(SWT.SELECTED, new Event());
+ } else {
+ richTextSelection.setText(""); //$NON-NLS-1$
+ hasSelection = false;
+ }
+ if (debug) {
+ printDebugMessage(
+ "statusTextListener", //$NON-NLS-1$
+ "STATUS_SELECT_TEXT, selectedText=", richTextSelection.getText()); //$NON-NLS-1$
+ }
+ break;
+ case STATUS_SELECT_CONTROL:
+ if (debug) {
+ printDebugMessage("statusTextListener", //$NON-NLS-1$
+ "STATUS_SELECT_CONTROL, control selected"); //$NON-NLS-1$
+ }
+ hasSelection = true;
+ break;
+ case STATUS_SELECT_NONE:
+ if (debug) {
+ printDebugMessage("statusTextListener", //$NON-NLS-1$
+ "STATUS_SELECT_NONE, no selection"); //$NON-NLS-1$
+ }
+ hasSelection = false;
+ break;
+ case STATUS_EXEC_CMD:
+ if (eventTextLength >= STATUS_PREFIX_LENGTH + 3) {
+ try {
+ status = Integer.parseInt(eventText
+ .substring(
+ STATUS_PREFIX_LENGTH + 2,
+ STATUS_PREFIX_LENGTH + 3));
+ } catch (Exception e) {
+ status = -1;
+ }
+ }
+ if (debug && status != 1) {
+ printDebugMessage("statusTextListener", //$NON-NLS-1$
+ "STATUS_EXEC_CMD, status=" + status); //$NON-NLS-1$
+ }
+ break;
+ case STATUS_REFORMAT_LINKS:
+ if (debug) {
+ printDebugMessage(
+ "statusTextListener", "STATUS_REFORMAT_LINKS"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (Platform.getOS().equals("win32")) { //$NON-NLS-1$
+ // Workaround the drag and drop issue with DBCS
+ // characters.
+// if (modified) {
+// setText(getText());
+// modified = true;
+// }
+ }
+ checkModify();
+ break;
+ }
+ } catch (Exception e) {
+ } finally {
+ processingJSEvent = false;
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Generates the HTML source for the editor.
+ *
+ * @return the HTML source for the editor
+ */
+ protected String generateEditorHTML() throws Exception {
+ String escapedBasePath = basePath;
+ if (escapedBasePath.startsWith(FileUtil.UNC_PATH_PREFIX))
+ escapedBasePath = escapedBasePath.replaceFirst(
+ "^\\\\\\\\", "\\\\\\\\\\\\\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
+ escapedBasePath = XMLUtil
+ .escape("file://" + escapedBasePath.replaceAll("'", "\\\\'")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ String escapedRteUTL = rteURL.replaceAll("&apos;", "%27"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ StringBuffer rteXML = new StringBuffer();
+ rteXML.append("<rte id=\"").append("rte") //$NON-NLS-1$ //$NON-NLS-2$
+ .append("\" css=\"").append(escapedRteUTL + "rte.css") //$NON-NLS-1$ //$NON-NLS-2$
+ .append("\" js=\"").append(escapedRteUTL + "rte.js") //$NON-NLS-1$ //$NON-NLS-2$
+ .append("\" baseURL=\"").append(escapedBasePath) //$NON-NLS-1$
+ .append("\"/>"); //$NON-NLS-1$
+ StringWriter result = new StringWriter();
+ XSLTProcessor.transform(
+ rteFolder + "rte.xsl", rteXML.toString(), result); //$NON-NLS-1$
+ return result.toString();
+ }
+
+ /**
+ * 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(RichText.this);
+ action.execute(RichText.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(RichText.this);
+ action.execute(RichText.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(RichText.this);
+ action.execute(RichText.this);
+ }
+ });
+
+ final MenuItem pastePlainTextItem = new MenuItem(contextMenu, SWT.PUSH);
+ pastePlainTextItem.setText(RichTextResources.pastePlainTextAction_text);
+ pastePlainTextItem.setImage(RichTextImages.IMG_PASTE_PLAIN_TEXT);
+ pastePlainTextItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ PastePlainTextAction action = new PastePlainTextAction(
+ RichText.this);
+ action.execute(RichText.this);
+ }
+ });
+
+ contextMenu.addMenuListener(new MenuListener() {
+ public void menuHidden(MenuEvent e) {
+ }
+
+ public void menuShown(MenuEvent e) {
+ getSelectedText();
+ cutItem.setEnabled(editable && hasSelection);
+ copyItem.setEnabled(hasSelection);
+ pasteItem.setEnabled(editable);
+ pastePlainTextItem.setEnabled(editable);
+ }
+ });
+ }
+
+ /**
+ * Adds listeners to manage the activation and focus events.
+ */
+ protected void addListeners() {
+ editorControl = getControlSite(editor);
+ if (editorControl != null) {
+ if (debug) {
+ printDebugMessage(
+ "init", "editorControl=" + editorControl.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // only IE (win32) has the editorControl != null
+ isIE = true;
+
+ editorControl.addListener(SWT.Activate, new Listener() {
+ public void handleEvent(Event event) {
+ if (debug) {
+ printDebugMessage("activateListener"); //$NON-NLS-1$
+ }
+ setFocus();
+ notifyListeners(SWT.Activate, event);
+ }
+ });
+
+ editorControl.addListener(SWT.Deactivate, new Listener() {
+ public void handleEvent(Event event) {
+ if (debug) {
+ printDebugMessage("deactivateListener"); //$NON-NLS-1$
+ }
+ setBlur();
+ notifyListeners(SWT.Deactivate, event);
+ }
+ });
+
+ editorControl.addListener(SWT.FocusIn, new Listener() {
+ public void handleEvent(Event event) {
+ if (debug) {
+ printDebugMessage("focusInListener"); //$NON-NLS-1$
+ }
+ executeCommand("updateSelection"); //$NON-NLS-1$
+ notifyListeners(SWT.FocusIn, event);
+ }
+ });
+
+ editorControl.addKeyListener(new KeyAdapter() {
+ public void keyReleased(KeyEvent event) {
+ int keyCode = event.keyCode;
+ int stateMask = event.stateMask;
+ if (debug) {
+ printDebugMessage(
+ "keyUpListener", "keyCode=" + keyCode //$NON-NLS-1$ //$NON-NLS-2$
+ + ", stateMask=" + stateMask + ", editable=" + editable); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if ( stateMask == SWT.CTRL && event.keyCode == 0x11 ) { //0x11 is for all Control key, such as ctrl-b, ctrl-I, ctrl-c, etc..
+ executeCommand("updateSelection");
+ }
+
+ if ((stateMask & SWT.CTRL) > 0
+ || (stateMask & SWT.ALT) > 0
+ || ((stateMask & SWT.SHIFT) > 0 && keyCode == stateMask)) {
+ return;
+ }
+ if (editable) {
+ switch (event.keyCode) {
+ case SWT.ARROW_DOWN:
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_RIGHT:
+ case SWT.ARROW_UP:
+ case SWT.END:
+ case SWT.HOME:
+ case SWT.PAGE_DOWN:
+ case SWT.PAGE_UP:
+ case SWT.TAB:
+ return;
+ default:
+ checkModify();
+ break;
+ }
+ }
+ }
+ });
+
+// editorControl.addListener(SWT.KeyUp, new Listener() {
+// public void handleEvent(Event event) {
+// int keyCode = event.keyCode;
+// int stateMask = event.stateMask;
+// if (debug) {
+// printDebugMessage(
+// "keyUpListener", "keyCode=" + keyCode //$NON-NLS-1$ //$NON-NLS-2$
+// + ", stateMask=" + stateMask + ", editable=" + editable); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+// if ((stateMask & SWT.CTRL) > 0
+// || (stateMask & SWT.ALT) > 0
+// || ((stateMask & SWT.SHIFT) > 0 && keyCode == stateMask)) {
+// return;
+// }
+// if (editable) {
+// switch (event.keyCode) {
+// case SWT.ARROW_DOWN:
+// case SWT.ARROW_LEFT:
+// case SWT.ARROW_RIGHT:
+// case SWT.ARROW_UP:
+// case SWT.END:
+// case SWT.HOME:
+// case SWT.PAGE_DOWN:
+// case SWT.PAGE_UP:
+// case SWT.TAB:
+// return;
+// default:
+// checkModify();
+// break;
+// }
+// }
+// }
+// });
+
+ editor.addLocationListener(new LocationAdapter() {
+ public void changing(LocationEvent event) {
+ // Deactivate the links in the content page in readonly
+ // mode.
+ event.doit = editable;
+ }
+ });
+ } else {
+ editor.addListener(SWT.Activate, new Listener() {
+ public void handleEvent(Event event) {
+ if (debug) {
+ printDebugMessage("activateListener"); //$NON-NLS-1$
+ }
+ setFocus();
+ }
+ });
+
+ editor.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.TAB) {
+ if ((e.stateMask & SWT.SHIFT) != 0) {
+ editor.traverse(SWT.TRAVERSE_TAB_PREVIOUS);
+ } else if ((e.stateMask & SWT.CTRL) == 0 ){
+ editor.traverse(SWT.TRAVERSE_TAB_NEXT);
+ }
+ return;
+ }
+ if (!editable) {
+ e.doit = false;
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ if ((e.stateMask & SWT.CTRL) > 0
+ || (e.stateMask & SWT.ALT) > 0)
+ return;
+ if (editable) {
+ switch (e.keyCode) {
+ case SWT.ARROW_DOWN:
+ case SWT.ARROW_LEFT:
+ case SWT.ARROW_RIGHT:
+ case SWT.ARROW_UP:
+ case SWT.END:
+ case SWT.HOME:
+ case SWT.PAGE_DOWN:
+ case SWT.PAGE_UP:
+ case SWT.SHIFT:
+ case SWT.TAB:
+ break;
+ default:
+ checkModify();
+ break;
+ }
+ }
+ }
+ });
+ }
+
+ editor.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ if (debug) {
+ printDebugMessage("disposeListener"); //$NON-NLS-1$
+ }
+ dispose();
+ }
+ });
+
+ listeners = new Hashtable<Listener, RichTextListener>();
+ modifyListeners = new ArrayList<ModifyListener>();
+ }
+
+ /**
+ * Notifies the rich text event listeners.
+ *
+ * @param eventType
+ * the event type
+ * @param event
+ * the SWT event
+ */
+ protected void notifyListeners(int eventType, Event event) {
+ if (notifyingModifyListeners) {
+ return;
+ }
+
+ if (listeners != null) {
+ event.display = Display.getCurrent();
+ event.widget = editor;
+
+ for (Iterator<RichTextListener> i = listeners.values().iterator(); i
+ .hasNext();) {
+ RichTextListener listener = i.next();
+ if (listener.getEventType() == eventType) {
+ if (debug) {
+ printDebugMessage(
+ "notifyListeners", "notifying listener, " + listener + ", eventType=" + eventType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ listener.getListener().handleEvent(event);
+ if (debug) {
+ printDebugMessage(
+ "notifyListeners", "notified listener, " + listener + ", eventType=" + eventType); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Notifies the modify listeners that the rich text editor content has
+ * changed.
+ */
+ public void notifyModifyListeners() {
+ notifyingModifyListeners = true;
+
+ Event event = new Event();
+ event.display = Display.getCurrent();
+ event.widget = editor;
+
+ for (Iterator<ModifyListener> i = modifyListeners.iterator(); i
+ .hasNext();) {
+ ModifyListener listener = i.next();
+ if (debug) {
+ printDebugMessage(
+ "notifyModifyListeners", "notifying listener, " + listener); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ listener.modifyText(new ModifyEvent(event));
+ if (debug) {
+ printDebugMessage(
+ "notifyModifyListeners", "notified listener, " + listener); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ notifyingModifyListeners = false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.epf.richtext.IRichText#checkModify()
+ */
+ public void checkModify() {
+ try {
+ if (!checkingModifyEvent) {
+ checkingModifyEvent = true;
+ if (modified) {
+ notifyModifyListeners();
+ } else {
+ if (!isIE && processingJSEvent) {
+ Display.getCurrent().asyncExec(new Runnable() {
+ public void run() {
+ if (!getText().equals(initialText)) {
+ modified = true;
+ notifyModifyListeners();
+ }
+ }
+ });
+ } else {
+ if (!getText().equals(initialText)) {
+ modified = true;
+ notifyModifyListeners();
+ }
+ }
+ }
+ if (debug) {
+ printDebugMessage("checkModify", "modified=" + modified); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ } finally {
+ checkingModifyEvent = false;
+ }
+ }
+
+ /**
+ * This provides an opportunity for a sub class to tidy up the rich text.
+ *
+ * @param text
+ * rich text encoded in HTML format
+ */
+ protected String tidyText(String text) {
+ return text;
+ }
+
+ /**
+ * Formats the text for consumption by the JavaScript/DHTML editor.
+ *
+ * @param text
+ * rich text encoded in HTML format
+ */
+ protected String formatText(String text) {
+ if (text == null || text.length() == 0) {
+ return text;
+ }
+ StringBuffer result = new StringBuffer();
+ int textSize = text.length();
+ for (int i = 0; i < textSize; i++) {
+ char ch = text.charAt(i);
+ switch (ch) {
+ case '\r':
+ break;
+ case '\t':
+ result.append(' ');
+ break;
+ case '\n':
+ result.append(ENCODED_NEWLINE);
+ break;
+ case '\'':
+ result.append(ENCODED_SINGLE_QUOTE);
+ break;
+ case '\\':
+ result.append("\\\\"); //$NON-NLS-1$
+ break;
+ default:
+ result.append(ch);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Returns the child <code>OleControlSite</code> contained within the
+ * given <code>Composite</code>.
+ *
+ * @param composite
+ * a <code>Composite</code> object, presumably a
+ * <code>Browser</code>
+ * @return an <code>OleControlSite</code> object
+ */
+ protected Control getControlSite(Composite composite) {
+ if (Platform.getOS().equals("win32")) { //$NON-NLS-1$
+ Control[] controls = composite.getChildren();
+ for (int i = 0; i < controls.length; i++) {
+ String controlClass = controls[i].getClass().getName();
+ if (controlClass.equals("org.eclipse.swt.browser.WebSite")) { //$NON-NLS-1$
+ return controls[i];
+ } else if (controls[i] instanceof Composite) {
+ return getControlSite((Composite) controls[i]);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Displays the given debug message to the console.
+ */
+ protected void printDebugMessage(String method, String msg, String text) {
+ StringBuffer strBuf = new StringBuffer();
+ strBuf.append("RichText[").append(editor.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.
+ */
+ protected void printDebugMessage(String method, String msg) {
+ printDebugMessage(method, msg, null);
+ }
+
+ /**
+ * Displays the given debug message to the console.
+ */
+ protected void printDebugMessage(String method) {
+ printDebugMessage(method, null);
+ }
+
+ public FindReplaceAction getFindReplaceAction() {
+ return findReplaceAction;
+ }
+
+ public void setFindReplaceAction(FindReplaceAction findReplaceAction) {
+ if (findReplaceAction != null) {
+ if (this.findReplaceAction != null
+ && this.findReplaceAction != findReplaceAction) {
+ this.findReplaceAction.dispose();
+ }
+ this.findReplaceAction = findReplaceAction;
+ this.findReplaceAction.setRichText(this);
+ }
+ }
+
+ public void setInitialText(String text) {
+ setText(text);
+ initialText = text == null ? "" : text; //$NON-NLS-1$
+ modified = false;
+ }
+
+ public boolean hasError() {
+ return htmlFormatter.getLastErrorStr() != null;
+ }
+
+ public static String workaroundForObjectParamNode(String html) {
+ String result = html.replaceAll("<param", "<paramTemp"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return result;
+ }
+
+ private String unWorkaroundForObjectParamNode(String html) {
+ String result = html.replaceAll("<paramTemp", "<param"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return result;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextCommand.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextCommand.java
new file mode 100644
index 00000000000..dbf706443ec
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextCommand.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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;
+
+/**
+ * Defines the editing commands supported by the default rich text control and
+ * editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextCommand {
+
+ /**
+ * Adds a HTML fragment.
+ */
+ public static final String ADD_HTML = "addHTML"; //$NON-NLS-1$
+
+ /**
+ * Adds an image.
+ */
+ public static final String ADD_IMAGE = "addImage"; //$NON-NLS-1$
+
+ /**
+ * Adds a horizontal line.
+ */
+ public static final String ADD_LINE = "addLine"; //$NON-NLS-1$
+
+ /**
+ * Adds a link.
+ */
+ public static final String ADD_LINK = "addLink"; //$NON-NLS-1$
+
+ /**
+ * Inserts text over the current selection.
+ */
+ public static final String INSERT_TEXT = "insertText"; //$NON-NLS-1$
+
+ /**
+ * Adds an ordered list.
+ */
+ public static final String ADD_ORDERED_LIST = "addOrderedList"; //$NON-NLS-1$
+
+ /**
+ * Adds a table.
+ */
+ public static final String ADD_TABLE = "addTable"; //$NON-NLS-1$
+
+ /**
+ * Adds an unordered list.
+ */
+ public static final String ADD_UNORDERED_LIST = "addUnorderedList"; //$NON-NLS-1$
+
+ /**
+ * Sets the background color of the selected text.
+ */
+ public static final String BACKGROUND_COLOR = "backColor"; //$NON-NLS-1$
+
+ /**
+ * Toggles the 'bold' attribute of the selected text.
+ */
+ public static final String BOLD = "bold"; //$NON-NLS-1$
+
+ /**
+ * Clears the rich text content.
+ */
+ public static final String CLEAR_CONTENT = "clearContent"; //$NON-NLS-1$
+
+ /**
+ * Copies the selected text to the clipboard.
+ */
+ public static final String COPY = "copy"; //$NON-NLS-1$
+
+ /**
+ * Cuts the selected text to the clipboard.
+ */
+ public static final String CUT = "cut"; //$NON-NLS-1$
+
+ /**
+ * Deletes the selected text.
+ */
+ public static final String DELETE = "deleteText"; //$NON-NLS-1$
+
+ /**
+ * Finds text.
+ */
+ public static final String FIND_TEXT = "findText"; //$NON-NLS-1$
+
+ /**
+ * Gets the HTML source.
+ */
+ public static final String GET_TEXT = "getText"; //$NON-NLS-1$
+
+ /**
+ * Sets the foreground color of the selected text.
+ */
+ public static final String FORGROUND_COLOR = "foreColor"; //$NON-NLS-1$
+
+ /**
+ * Formats the selected text.
+ */
+ public static final String FORMAT_BLOCK = "formatBlock"; //$NON-NLS-1$
+
+ /**
+ * Returns the selected text.
+ */
+ public static final String GET_SELECTED_TEXT = "getSelectedText"; //$NON-NLS-1$
+
+ /**
+ * Indents the selected text.
+ */
+ public static final String INDENT = "indent"; //$NON-NLS-1$
+
+ /**
+ * Toggles the 'italic' attribute of the selected text.
+ */
+ public static final String ITALIC = "italic"; //$NON-NLS-1$
+
+ /**
+ * Center justifies the selected text.
+ */
+ public static final String JUSTIFY_CENTER = "justifyCenter"; //$NON-NLS-1$
+
+ /**
+ * Fully justifies the selected text.
+ */
+ public static final String JUSTIFY_FULL = "justifyFull"; //$NON-NLS-1$
+
+ /**
+ * Left justifies the selected text.
+ */
+ public static final String JUSTIFY_LEFT = "justifyLeft"; //$NON-NLS-1$
+
+ /**
+ * Right justifies the selected text.
+ */
+ public static final String JUSTIFY_RIGHT = "justifyRight"; //$NON-NLS-1$
+
+ /**
+ * Outdents the selected text.
+ */
+ public static final String OUTDENT = "outdent"; //$NON-NLS-1$
+
+ /**
+ * Pastes text from the clipboard.
+ */
+ public static final String PASTE = "paste"; //$NON-NLS-1$
+
+ /**
+ * Replaces all text.
+ */
+ public static final String REPLACE_ALL_TEXT = "replaceAllText"; //$NON-NLS-1$
+
+ /**
+ * Replaces the selected text.
+ */
+ public static final String REPLACE_TEXT = "replaceText"; //$NON-NLS-1$
+
+ /**
+ * Redoes the previous command.
+ */
+ public static final String REDO = "redo"; //$NON-NLS-1$
+
+ /**
+ * Removes the current formatting of the selected text.
+ */
+ public static final String REMOVE_FORMAT = "removeFormat"; //$NON-NLS-1$
+
+ /**
+ * Saves the editor
+ */
+ public static final String SAVE = "save"; //$NON-NLS-1$
+
+ /**
+ * Saves all editors
+ */
+ public static final String SAVE_ALL = "saveAll"; //$NON-NLS-1$
+
+ /**
+ * Selects all text.
+ */
+ public static final String SELECT_ALL = "selectAll"; //$NON-NLS-1$
+
+ /**
+ * Sets the font name for the selected text.
+ */
+ public static final String SET_FONT_NAME = "setFontName"; //$NON-NLS-1$
+
+ /**
+ * Sets the font size for the selected text.
+ */
+ public static final String SET_FONT_SIZE = "setFontSize"; //$NON-NLS-1$
+
+ /**
+ * Sets the font style for the selected text.
+ */
+ public static final String SET_FONT_STYLE = "setFontStyle"; //$NON-NLS-1$
+
+ /**
+ * Sets whether the content can be edited.
+ */
+ public static final String SET_EDITABLE = "setEditable"; //$NON-NLS-1$
+
+ /**
+ * Sets focus to this control.
+ */
+ public static final String SET_FOCUS = "setFocus"; //$NON-NLS-1$
+
+ /**
+ * Sets the height of this control.
+ */
+ public static final String SET_HEIGHT = "setHeight"; //$NON-NLS-1$
+
+ /**
+ * Sets the HTML source.
+ */
+ public static final String SET_TEXT = "setText"; //$NON-NLS-1$
+
+ /**
+ * Toggles the 'strike-through' attribute of the selected text.
+ */
+ public static final String STRIKE_THROUGH = "strikeThrough"; //$NON-NLS-1$
+
+ /**
+ * Toggles the subscript attribute of the selected text.
+ */
+ public static final String SUBSCRIPT = "subscript"; //$NON-NLS-1$
+
+ /**
+ * Toggles the superscript attribute of the selected text.
+ */
+ public static final String SUPERSCRIPT = "superscript"; //$NON-NLS-1$
+
+ /**
+ * Toggles the underline attribute of the selected text.
+ */
+ public static final String UNDERLINE = "underline"; //$NON-NLS-1$
+
+ /**
+ * Undoes the previous command.
+ */
+ public static final String UNDO = "undo"; //$NON-NLS-1$
+
+ /**
+ * Converts a link to normal text.
+ */
+ public static final String UNLINK = "unlink"; //$NON-NLS-1$
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditor.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditor.java
new file mode 100644
index 00000000000..039b2a86c35
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditor.java
@@ -0,0 +1,1555 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.commands.operations.IUndoContext;
+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.action.Action;
+import org.eclipse.jface.action.IAction;
+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.jface.text.Document;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.ITextViewerExtension6;
+import org.eclipse.jface.text.IUndoManager;
+import org.eclipse.jface.text.IUndoManagerExtension;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.TextViewerUndoManager;
+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.VerifyKeyListener;
+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.events.VerifyEvent;
+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.IActionBars;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IKeyBindingService;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.operations.OperationHistoryActionHandler;
+import org.eclipse.ui.operations.RedoActionHandler;
+import org.eclipse.ui.operations.UndoActionHandler;
+import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
+import org.eclipse.ui.texteditor.IReadOnlyDependent;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
+
+/**
+ * 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 TextViewer sourceViewer;
+
+ protected IDocument currentDoc;
+
+ // Drop support
+ protected 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;
+
+ private OperationHistoryActionHandler undoAction;
+
+ private OperationHistoryActionHandler redoAction;
+
+ private IEditorSite editorSite;
+
+ /** The actions registered with the editor. */
+ private Map<String, IAction> fActions= new HashMap<String, IAction>(10);
+
+ /** The verify key listener for activation code triggering. */
+ private ActivationCodeTrigger fActivationCodeTrigger= new ActivationCodeTrigger();
+
+ /** The editor's action activation codes. */
+ private List fActivationCodes= new ArrayList(2);
+
+ final IUndoManager undoManager= new TextViewerUndoManager(10);
+
+ /**
+ * The key binding scopes of this editor.
+ * @since 2.1
+ */
+ private String[] fKeyBindingScopes;
+
+
+ protected IDocumentListener sourceEditDocumentListener= new IDocumentListener() {
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ }
+ public void documentChanged(DocumentEvent event) {
+ sourceModified = true;
+ if (richText != null && richText instanceof RichText) {
+ richText.notifyModifyListeners();
+ }
+ }
+ };
+
+
+ // The deactivate listener for the sourceEdit control.
+ protected Listener sourceEditDeactivateListener = new Listener() {
+ public void handleEvent(Event event) {
+ if (sourceModified) {
+ updateRichText(sourceViewer.getTextWidget().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, IEditorSite editorSite) {
+ this(parent, style, editorSite, 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, IEditorSite editorSite, String basePath) {
+ this.basePath = basePath;
+ this.editorSite = editorSite;
+ 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.setTopCenter(((RichTextToolBar)toolBar).getToolbarMgr().getControl());
+ form.setTopLeft(((RichTextToolBar)toolBar).getToolbarMgrCombo().getControl());
+ 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);
+ if (toolBar != null && tabFolder != null) {
+ toolBar.updateToolBar(editable);
+ }
+
+ }
+
+ /**
+ * 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) {
+ toolBar.updateToolBar(editable);
+ }
+ if (richText != null) {
+ richText.setEditable(editable);
+ }
+ if (sourceViewer != null) {
+ sourceViewer.setEditable(editable);
+ }
+ }
+
+ /**
+ * 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(getSourceEdit().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 (getSourceEdit() != null) {
+ removeModifyListeners();
+ currentDoc.set(text);
+ addModifyListeners();
+ }
+ }
+ }
+
+ protected void addModifyListeners() {
+ if (currentDoc != null) {
+ currentDoc.addDocumentListener(sourceEditDocumentListener);
+ }
+ }
+
+ protected void removeModifyListeners() {
+ if (currentDoc != null) {
+ currentDoc.removeDocumentListener(sourceEditDocumentListener);
+ }
+ }
+
+ /*
+ * (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 = getSourceEdit().getText();
+ Point sel = sourceViewer.getSelectedRange();
+ 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) {
+ return 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 (fActivationCodeTrigger != null) {
+ fActivationCodeTrigger.uninstall();
+ fActivationCodeTrigger= null;
+ }
+ removeModifyListeners();
+ if (getSourceEdit() != null) {
+ getSourceEdit().removeListener(SWT.Deactivate,
+ sourceEditDeactivateListener);
+ getSourceEdit().removeKeyListener(sourceEditKeyListener);
+ sourceEditDeactivateListener = null;
+ sourceEditKeyListener = null;
+ }
+
+ if (sourceViewer != null) {
+ sourceViewer= null;
+ }
+
+ if (fActions != null) {
+ fActions.clear();
+ fActions= null;
+ }
+ if (fActivationCodes != null) {
+ fActivationCodes.clear();
+ fActivationCodes= 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<ModifyListener> 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<RichTextListener> getListeners() {
+ if (richText != null) {
+ return richText.getListeners();
+ }
+ return null;
+ }
+
+ /**
+ * Notifies the modify listeners that the rich text editor content has
+ * changed.
+ */
+ public void notifyModifyListeners() {
+ if (richText != null) {
+ Event event = new Event();
+ event.display = Display.getCurrent();
+ event.widget = richText.getControl();
+
+ for (Iterator<ModifyListener> i = getModifyListeners(); i != null && i.hasNext();) {
+ ModifyListener listener = 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());
+
+ sourceViewer = new TextViewer(htmlComposite, SWT.FLAT | SWT.MULTI
+ | SWT.WRAP | SWT.V_SCROLL);
+ sourceViewer.setUndoManager(undoManager);
+ setDocument(null);
+ addModifyListeners();
+ getSourceEdit().addListener(SWT.Deactivate, sourceEditDeactivateListener);
+ getSourceEdit().addKeyListener(sourceEditKeyListener);
+ contextMenu = new Menu(parent.getShell(), SWT.POP_UP);
+ getSourceEdit().setMenu(contextMenu);
+ // FIXME! This opens up a can of worms, especially with DBCS characters.
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=179432.
+ //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)) {
+ removeModifyListeners();
+ currentDoc.set(getText());
+ sourceModified = false;
+ addModifyListeners();
+ if (toolBar != null) {
+ toolBar.updateToolBar(editable);
+ }
+ } else {
+ updateRichText(getSourceEdit().getText());
+ setModified(true);
+ if (toolBar != null) {
+ toolBar.updateToolBar(editable);
+ }
+ }
+ }
+ });
+ fillToolBar(toolBar);
+
+ initializeActivationCodeTrigger();
+ createActions();
+
+ folder.setSelection(0);
+
+ return folder;
+ }
+
+
+ private void setDocument(IDocument doc) {
+ if (doc == null) {
+ doc = new Document();
+ }
+ // clean up old doc
+ undoManager.disconnect();
+ IDocument oldDoc = sourceViewer.getDocument();
+ if (oldDoc != null) {
+ oldDoc.removeDocumentListener(sourceEditDocumentListener);
+ }
+
+ // hook up new doc
+ currentDoc = doc;
+ sourceViewer.setDocument(currentDoc);
+ currentDoc.addDocumentListener(sourceEditDocumentListener);
+ undoManager.connect(sourceViewer);
+ if (undoAction != null) {
+ undoAction.setContext(getUndoContext());
+ }
+ if (redoAction != null) {
+ redoAction.setContext(getUndoContext());
+ }
+ }
+
+ /**
+ * Returns the HTML source edit control.
+ *
+ * @return a <code>StyleText</code> object.
+ */
+ public StyledText getSourceEdit() {
+ if (sourceViewer != null) {
+ return sourceViewer.getTextWidget();
+ }
+ return null;
+ }
+
+ /**
+ * Inserts text at the selection (overwriting the selection).
+ */
+ public void addHTML(String text) {
+ if (text == null || text.length() == 0)
+ return;
+ if (tabFolder.getSelection() == richTextTab) {
+ //To avoid encoding of javascript
+ text = text.replaceAll("&", "&amp;"); //$NON-NLS-1$//$NON-NLS-2$
+ executeCommand(RichTextCommand.ADD_HTML, text);
+ } else if (tabFolder.getSelection() == htmlTab) {
+ String oldHTML = getSourceEdit().getText();
+ Point sel = sourceViewer.getSelectedRange();
+ int selStartIndex = sel.x;
+ int selEndIndex = sel.x + sel.y - 1;
+ String newHTML = oldHTML.substring(0, selStartIndex) + text
+ + oldHTML.substring(selEndIndex + 1);
+ removeModifyListeners();
+ currentDoc.set(newHTML);
+ addModifyListeners();
+ 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 = getSourceEdit().getText();
+ Point sel = sourceViewer.getSelectedRange();
+ int selStartIndex = sel.x;
+ int selEndIndex = sel.x + sel.y - 1;
+ String newHTML = oldHTML.substring(0, selStartIndex) + imageLink.toString()
+ + oldHTML.substring(selEndIndex + 1);
+ removeModifyListeners();
+ currentDoc.set(newHTML);
+ addModifyListeners();
+ 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(RichTextEditor.this);
+ 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(RichTextEditor.this);
+ 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(RichTextEditor.this);
+ 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(RichTextEditor.this);
+ 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(getSourceEdit(), 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;
+ }
+ }
+ if (!getEditable()) {
+ 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);
+ }
+
+ public FindReplaceAction getFindReplaceAction() {
+ return richText.getFindReplaceAction();
+ }
+
+ public void setFindReplaceAction(FindReplaceAction findReplaceAction) {
+ if (richText != null) {
+ richText.setFindReplaceAction(findReplaceAction);
+ richText.getFindReplaceAction().setRichText(this);
+
+ }
+ }
+
+ public void setInitialText(String text) {
+ if (richText != null) {
+ richText.setInitialText(text);
+ }
+ if (getSourceEdit() != null) {
+ removeModifyListeners();
+ setDocument(new Document(text));
+ addModifyListeners();
+ }
+
+ }
+
+
+ /**
+ * from org.eclipse.ui.texteditor.AbstractTextEditor#getUndoContext()
+ * Returns this editor's viewer's undo manager undo context.
+ *
+ * @return the undo context or <code>null</code> if not available
+ * @since 3.1
+ */
+ private IUndoContext getUndoContext() {
+ if (sourceViewer instanceof ITextViewerExtension6) {
+ IUndoManager undoManager= ((ITextViewerExtension6)sourceViewer).getUndoManager();
+ if (undoManager instanceof IUndoManagerExtension)
+ return ((IUndoManagerExtension)undoManager).getUndoContext();
+ }
+ return null;
+ }
+
+ protected void createActions() {
+ createUndoRedoActions();
+ // select all
+ Action selectAllAction = new Action() {
+ @Override
+ public void run() {
+ getSourceEdit().selectAll();
+ }
+ };
+ selectAllAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL);
+ registerAction(ActionFactory.SELECT_ALL.getId(), selectAllAction);
+ }
+
+ /*
+ * from org.eclipse.ui.texteditor.AbstractTextEditor#createUndoRedoActions()
+ */
+ protected void createUndoRedoActions() {
+ IUndoContext undoContext= getUndoContext();
+ if (undoContext != null) {
+ // Use actions provided by global undo/redo
+
+ // Create the undo action
+ undoAction= new UndoActionHandler(getEditorSite(), undoContext);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION);
+ undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
+ registerAction(ITextEditorActionConstants.UNDO, undoAction);
+
+ // Create the redo action.
+ redoAction= new RedoActionHandler(getEditorSite(), undoContext);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(redoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION);
+ redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
+ registerAction(ITextEditorActionConstants.REDO, redoAction);
+ }
+ }
+
+ private IEditorSite getEditorSite() {
+ return editorSite;
+ }
+
+
+ /**
+ * Registers the given undo/redo action under the given ID and
+ * ensures that previously installed actions get disposed. It
+ * also takes care of re-registering the new action with the
+ * global action handler.
+ *
+ * @param actionId the action id under which to register the action
+ * @param action the action to register
+ * @since 3.1
+ */
+ private void registerAction(String actionId, IAction action) {
+ IAction oldAction= getAction(actionId);
+ if (oldAction instanceof OperationHistoryActionHandler)
+ ((OperationHistoryActionHandler)oldAction).dispose();
+
+ setAction(actionId, action);
+
+ IActionBars actionBars= getEditorSite().getActionBars();
+ if (actionBars != null)
+ actionBars.setGlobalActionHandler(actionId, action);
+ }
+
+
+ /*
+ * @see ITextEditor#getAction(String)
+ */
+ public IAction getAction(String actionID) {
+ assert actionID != null;
+ IAction action= (IAction) fActions.get(actionID);
+
+// if (action == null) {
+// action= findContributedAction(actionID);
+// if (action != null)
+// setAction(actionID, action);
+// }
+
+ return action;
+ }
+
+ /*
+ * @see ITextEditor#setAction(String, IAction)
+ */
+ public void setAction(String actionID, IAction action) {
+ assert actionID != null;
+ if (action == null) {
+ action= (IAction) fActions.remove(actionID);
+ if (action != null)
+ fActivationCodeTrigger.unregisterActionFromKeyActivation(action);
+ } else {
+ fActions.put(actionID, action);
+ fActivationCodeTrigger.registerActionForKeyActivation(action);
+ }
+ }
+
+ /**
+ * Initializes the activation code trigger.
+ *
+ * @since 2.1
+ */
+ private void initializeActivationCodeTrigger() {
+ fActivationCodeTrigger.install();
+ fActivationCodeTrigger.setScopes(fKeyBindingScopes);
+ }
+
+ /**
+ * Internal key verify listener for triggering action activation codes.
+ */
+ class ActivationCodeTrigger implements VerifyKeyListener {
+
+ /** Indicates whether this trigger has been installed. */
+ private boolean fIsInstalled= false;
+ /**
+ * The key binding service to use.
+ * @since 2.0
+ */
+ private IKeyBindingService fKeyBindingService;
+
+ /*
+ * @see VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
+ */
+ public void verifyKey(VerifyEvent event) {
+
+ ActionActivationCode code= null;
+ int size= fActivationCodes.size();
+ for (int i= 0; i < size; i++) {
+ code= (ActionActivationCode) fActivationCodes.get(i);
+ if (code.matches(event)) {
+ IAction action= getAction(code.fActionId);
+ if (action != null) {
+
+ if (action instanceof IUpdate)
+ ((IUpdate) action).update();
+
+ if (!action.isEnabled() && action instanceof IReadOnlyDependent) {
+ IReadOnlyDependent dependent= (IReadOnlyDependent) action;
+ boolean writable= dependent.isEnabled(true);
+ if (writable) {
+ event.doit= false;
+ return;
+ }
+ } else if (action.isEnabled()) {
+ event.doit= false;
+ action.run();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Installs this trigger on the editor's text widget.
+ * @since 2.0
+ */
+ public void install() {
+ if (!fIsInstalled) {
+
+ if (sourceViewer instanceof ITextViewerExtension) {
+ ITextViewerExtension e= (ITextViewerExtension) sourceViewer;
+ e.prependVerifyKeyListener(this);
+ } else {
+ StyledText text= sourceViewer.getTextWidget();
+ text.addVerifyKeyListener(this);
+ }
+
+ fKeyBindingService= getEditorSite().getKeyBindingService();
+ fIsInstalled= true;
+ }
+ }
+
+ /**
+ * Uninstalls this trigger from the editor's text widget.
+ * @since 2.0
+ */
+ public void uninstall() {
+ if (fIsInstalled) {
+
+ if (sourceViewer instanceof ITextViewerExtension) {
+ ITextViewerExtension e= (ITextViewerExtension) sourceViewer;
+ e.removeVerifyKeyListener(this);
+ } else if (sourceViewer != null) {
+ StyledText text= sourceViewer.getTextWidget();
+ if (text != null && !text.isDisposed())
+ text.removeVerifyKeyListener(fActivationCodeTrigger);
+ }
+
+ fIsInstalled= false;
+ fKeyBindingService= null;
+ }
+ }
+
+ /**
+ * Registers the given action for key activation.
+ * @param action the action to be registered
+ * @since 2.0
+ */
+ public void registerActionForKeyActivation(IAction action) {
+ if (action.getActionDefinitionId() != null)
+ fKeyBindingService.registerAction(action);
+ }
+
+ /**
+ * The given action is no longer available for key activation
+ * @param action the action to be unregistered
+ * @since 2.0
+ */
+ public void unregisterActionFromKeyActivation(IAction action) {
+ if (action.getActionDefinitionId() != null)
+ fKeyBindingService.unregisterAction(action);
+ }
+
+ /**
+ * Sets the key binding scopes for this editor.
+ * @param keyBindingScopes the key binding scopes
+ * @since 2.1
+ */
+ public void setScopes(String[] keyBindingScopes) {
+ if (keyBindingScopes != null && keyBindingScopes.length > 0)
+ fKeyBindingService.setScopes(keyBindingScopes);
+ }
+ }
+
+ /**
+ * Representation of action activation codes.
+ */
+ static class ActionActivationCode {
+
+ /** The action id. */
+ public String fActionId;
+ /** The character. */
+ public char fCharacter;
+ /** The key code. */
+ public int fKeyCode= -1;
+ /** The state mask. */
+ public int fStateMask= SWT.DEFAULT;
+
+ /**
+ * Creates a new action activation code for the given action id.
+ * @param actionId the action id
+ */
+ public ActionActivationCode(String actionId) {
+ fActionId= actionId;
+ }
+
+ /**
+ * Returns <code>true</code> if this activation code matches the given verify event.
+ * @param event the event to test for matching
+ * @return whether this activation code matches <code>event</code>
+ */
+ public boolean matches(VerifyEvent event) {
+ return (event.character == fCharacter &&
+ (fKeyCode == -1 || event.keyCode == fKeyCode) &&
+ (fStateMask == SWT.DEFAULT || event.stateMask == fStateMask));
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditorForm.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditorForm.java
new file mode 100644
index 00000000000..aebc146cf72
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextEditorForm.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 org.eclipse.swt.custom.ViewForm;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * A composite for laying out the default rich text editor in an Eclipse form.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextEditorForm extends ViewForm {
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent control
+ * @param style
+ * the style for this control
+ */
+ public RichTextEditorForm(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ /**
+ * @see org.eclipse.swt.widgets#getData(String key)
+ */
+ public Object getData(String key) {
+ if (key != null && key.equals(FormToolkit.KEY_DRAW_BORDER)) {
+ // Return a text border to get the FormToolkit's BorderPainter to
+ // paint a border for the rich text editor.
+ return FormToolkit.TEXT_BORDER;
+ }
+ return super.getData();
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextFormToolkit.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextFormToolkit.java
new file mode 100644
index 00000000000..7809c45f4f3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextFormToolkit.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * A helper toolkit for creating a rich text control and editor that can be
+ * added to an Eclipse form.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextFormToolkit {
+
+ /**
+ * Creates a rich text control and adapts it to be used in a form.
+ *
+ * @param toolkit
+ * the form toolkit
+ * @param parent
+ * the parent control
+ * @param text
+ * the initial text for the viewer
+ * @param style
+ * the initial style for the viewer
+ * @param basePath
+ * the base path used for resolving hrefs
+ * @return a new <code>IRichText</code> instance
+ */
+ public static IRichText createRichText(FormToolkit toolkit,
+ Composite parent, String text, int style) {
+ IRichText richText = new RichText(parent, toolkit.getBorderStyle()
+ | style | toolkit.getOrientation());
+ richText.getControl().setData(FormToolkit.KEY_DRAW_BORDER,
+ FormToolkit.TEXT_BORDER);
+ if (text != null) {
+ richText.setText(text);
+ }
+ return richText;
+ }
+
+ /**
+ * Creates a rich text editor and adapts it to be used in a form.
+ *
+ * @param toolkit
+ * the form toolkit
+ * @param parent
+ * the parent control
+ * @param text
+ * the initial text for the viewer
+ * @param style
+ * the initial style for the viewer
+ * @param basePath
+ * the base path used for resolving hrefs
+ * @return a new <code>IRichText</code> instance
+ */
+ public static IRichTextEditor createRichTextEditor(FormToolkit toolkit,
+ Composite parent, String text, int style, IEditorSite editorSite) {
+ IRichTextEditor richTextEditor = new RichTextEditor(parent, toolkit
+ .getBorderStyle()
+ | style | toolkit.getOrientation(), editorSite);
+ richTextEditor.getControl().setData(FormToolkit.KEY_DRAW_BORDER,
+ FormToolkit.TEXT_BORDER);
+ if (text != null) {
+ richTextEditor.setInitialText(text);
+ }
+ return richTextEditor;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextImages.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextImages.java
new file mode 100644
index 00000000000..db51e92f1f7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextImages.java
@@ -0,0 +1,475 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Shared images used by the default rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextImages {
+
+ private static final String ETOOL16 = "full/etool16/"; //$NON-NLS-1$
+
+ private static final String DTOOL16 = "full/dtool16/"; //$NON-NLS-1$
+
+ private static final RichTextPlugin richTextPlugin = RichTextPlugin
+ .getDefault();
+
+ public static final String IMG_PATH_ADD_IMAGE = ETOOL16 + "AddImage.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_LINE = ETOOL16 + "AddLine.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_LINK = ETOOL16 + "AddLink.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_ORDERED_LIST = ETOOL16
+ + "AddOrderedList.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_TABLE = ETOOL16 + "AddTable.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_UNORDERED_LIST = ETOOL16
+ + "AddUnorderedList.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_BOLD = ETOOL16 + "Bold.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_CLEAR_CONTENT = ETOOL16
+ + "ClearContent.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_COPY = ETOOL16 + "Copy.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_CUT = ETOOL16 + "Cut.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_FIND_REPLACE = ETOOL16
+ + "FindReplace.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_INDENT = ETOOL16 + "Indent.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ITALIC = ETOOL16 + "Italic.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_JUSTIFY_CENTER = ETOOL16
+ + "JustifyCenter.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_JUSTIFY_FULL = ETOOL16
+ + "JustifyFull.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_JUSTIFY_LEFT = ETOOL16
+ + "JustifyLeft.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_JUSTIFY_RIGHT = ETOOL16
+ + "JustifyRight.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_OUTDENT = ETOOL16 + "Outdent.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_PASTE = ETOOL16 + "Paste.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_PASTE_PLAIN_TEXT = ETOOL16 + "PastePlainText.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_STRIKE_THROUGH = ETOOL16
+ + "StrikeThrough.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_SUBSCRIPT = ETOOL16 + "Subscript.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_SUPERSCRIPT = ETOOL16
+ + "Superscript.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_UNDERLINE = ETOOL16 + "Underline.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_TIDY = ETOOL16 + "TidyHTML.gif"; //$NON-NLS-1$
+
+ public static final String IMG_PATH_ADD_CODE = ETOOL16 + "AddCode.gif"; //$NON-NLS-1$
+
+ public static final Image IMG_ADD_IMAGE = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_IMAGE);
+
+ public static final Image IMG_ADD_LINE = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_LINE);
+
+ public static final Image IMG_ADD_LINK = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_LINK);
+
+ public static final Image IMG_ADD_ORDERED_LIST = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_ORDERED_LIST);
+
+ public static final Image IMG_ADD_TABLE = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_TABLE);
+
+ public static final Image IMG_ADD_UNORDERED_LIST = richTextPlugin
+ .getSharedImage(IMG_PATH_ADD_UNORDERED_LIST);
+
+ public static final Image IMG_BOLD = richTextPlugin
+ .getSharedImage(IMG_PATH_BOLD);
+
+ public static final Image IMG_CLEAR_CONTENT = richTextPlugin
+ .getSharedImage(IMG_PATH_CLEAR_CONTENT);
+
+ public static final Image IMG_COPY = richTextPlugin
+ .getSharedImage(IMG_PATH_COPY);
+
+ public static final Image IMG_CUT = richTextPlugin
+ .getSharedImage(IMG_PATH_CUT);
+
+ public static final Image IMG_FIND_REPLACE = richTextPlugin
+ .getSharedImage(IMG_PATH_FIND_REPLACE);
+
+ public static final Image IMG_INDENT = richTextPlugin
+ .getSharedImage(IMG_PATH_INDENT);
+
+ public static final Image IMG_ITALIC = richTextPlugin
+ .getSharedImage(IMG_PATH_ITALIC);
+
+ public static final Image IMG_JUSTIFY_CENTER = richTextPlugin
+ .getSharedImage(IMG_PATH_JUSTIFY_CENTER);
+
+ public static final Image IMG_JUSTIFY_FULL = richTextPlugin
+ .getSharedImage(IMG_PATH_JUSTIFY_FULL);
+
+ public static final Image IMG_JUSTIFY_LEFT = richTextPlugin
+ .getSharedImage(IMG_PATH_JUSTIFY_LEFT);
+
+ public static final Image IMG_JUSTIFY_RIGHT = richTextPlugin
+ .getSharedImage(IMG_PATH_JUSTIFY_RIGHT);
+
+ public static final Image IMG_OUTDENT = richTextPlugin
+ .getSharedImage(IMG_PATH_OUTDENT);
+
+ public static final Image IMG_PASTE = richTextPlugin
+ .getSharedImage(IMG_PATH_PASTE);
+
+ public static final Image IMG_PASTE_PLAIN_TEXT = richTextPlugin
+ .getSharedImage(IMG_PATH_PASTE_PLAIN_TEXT);
+
+ public static final Image IMG_STRIKE_THROUGH = richTextPlugin
+ .getSharedImage(IMG_PATH_STRIKE_THROUGH);
+
+ public static final Image IMG_SUBSCRIPT = richTextPlugin
+ .getSharedImage(IMG_PATH_SUBSCRIPT);
+
+ public static final Image IMG_SUPERSCRIPT = richTextPlugin
+ .getSharedImage(IMG_PATH_SUPERSCRIPT);
+
+ public static final Image IMG_UNDERLINE = richTextPlugin
+ .getSharedImage(IMG_PATH_UNDERLINE);
+ public static final Image IMG_TIDY = richTextPlugin
+ .getSharedImage(IMG_PATH_TIDY);
+
+ public static final ImageDescriptor IMG_DESC_ADD_IMAGE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_IMAGE);
+
+ public static final ImageDescriptor IMG_DESC_ADD_LINE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_LINE);
+
+ public static final ImageDescriptor IMG_DESC_ADD_LINK = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_LINK);
+
+ public static final ImageDescriptor IMG_DESC_ADD_ORDERED_LIST = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_ORDERED_LIST);
+
+ public static final ImageDescriptor IMG_DESC_ADD_TABLE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_TABLE);
+
+ public static final ImageDescriptor IMG_DESC_ADD_UNORDERED_LIST = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_UNORDERED_LIST);
+
+ public static final ImageDescriptor IMG_DESC_BOLD = richTextPlugin
+ .getImageDescriptor(IMG_PATH_BOLD);
+
+ public static final ImageDescriptor IMG_DESC_CLEAR_CONTENT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_CLEAR_CONTENT);
+
+ public static final ImageDescriptor IMG_DESC_COPY = richTextPlugin
+ .getImageDescriptor(IMG_PATH_COPY);
+
+ public static final ImageDescriptor IMG_DESC_CUT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_CUT);
+
+ public static final ImageDescriptor IMG_DESC_FIND_REPLACE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_FIND_REPLACE);
+
+ public static final ImageDescriptor IMG_DESC_INDENT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_INDENT);
+
+ public static final ImageDescriptor IMG_DESC_ITALIC = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ITALIC);
+
+ public static final ImageDescriptor IMG_DESC_JUSTIFY_CENTER = richTextPlugin
+ .getImageDescriptor(IMG_PATH_JUSTIFY_CENTER);
+
+ public static final ImageDescriptor IMG_DESC_JUSTIFY_FULL = richTextPlugin
+ .getImageDescriptor(IMG_PATH_JUSTIFY_FULL);
+
+ public static final ImageDescriptor IMG_DESC_JUSTIFY_LEFT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_JUSTIFY_LEFT);
+
+ public static final ImageDescriptor IMG_DESC_JUSTIFY_RIGHT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_JUSTIFY_RIGHT);
+
+ public static final ImageDescriptor IMG_DESC_OUTDENT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_OUTDENT);
+
+ public static final ImageDescriptor IMG_DESC_PASTE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_PASTE);
+
+ public static final ImageDescriptor IMG_DESC_PASTE_PLAIN_TEXT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_PASTE_PLAIN_TEXT);
+
+ public static final ImageDescriptor IMG_DESC_STRIKE_THROUGH = richTextPlugin
+ .getImageDescriptor(IMG_PATH_STRIKE_THROUGH);
+
+ public static final ImageDescriptor IMG_DESC_SUBSCRIPT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_SUBSCRIPT);
+
+ public static final ImageDescriptor IMG_DESC_SUPERSCRIPT = richTextPlugin
+ .getImageDescriptor(IMG_PATH_SUPERSCRIPT);
+
+ public static final ImageDescriptor IMG_DESC_UNDERLINE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_UNDERLINE);
+
+ public static final ImageDescriptor IMG_DESC_TIDY = richTextPlugin
+ .getImageDescriptor(IMG_PATH_TIDY);
+
+ public static final ImageDescriptor IMG_DESC_ADD_CODE = richTextPlugin
+ .getImageDescriptor(IMG_PATH_ADD_CODE);
+
+
+ public static final String DISABLED_IMG_PATH_ADD_IMAGE = DTOOL16
+ + "AddImage.gif"; //$NON-NLS-1$
+
+// public static final String DISABLED_IMG_PATH_ADD_LINE = DTOOL16
+// + "AddLine.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ADD_LINK = DTOOL16
+ + "AddLink.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ADD_ORDERED_LIST = DTOOL16
+ + "AddOrderedList.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ADD_TABLE = DTOOL16
+ + "AddTable.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ADD_UNORDERED_LIST = DTOOL16
+ + "AddUnorderedList.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_BOLD = DTOOL16 + "Bold.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_CLEAR_CONTENT = DTOOL16
+ + "ClearContent.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_COPY = DTOOL16 + "Copy.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_CUT = DTOOL16 + "Cut.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_FIND_REPLACE = DTOOL16
+ + "FindReplace.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_INDENT = DTOOL16
+ + "Indent.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ITALIC = DTOOL16
+ + "Italic.gif"; //$NON-NLS-1$
+
+// public static final String DISABLED_IMG_PATH_JUSTIFY_CENTER = DTOOL16
+// + "JustifyCenter.gif"; //$NON-NLS-1$
+//
+// public static final String DISABLED_IMG_PATH_JUSTIFY_FULL = DTOOL16
+// + "JustifyFull.gif"; //$NON-NLS-1$
+//
+// public static final String DISABLED_IMG_PATH_JUSTIFY_LEFT = DTOOL16
+// + "JustifyLeft.gif"; //$NON-NLS-1$
+//
+// public static final String DISABLED_IMG_PATH_JUSTIFY_RIGHT = DTOOL16
+// + "JustifyRight.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_OUTDENT = DTOOL16
+ + "Outdent.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_PASTE = DTOOL16 + "Paste.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_PASTE_PLAIN_TEXT = DTOOL16 + "PastePlainText.gif"; //$NON-NLS-1$
+
+// public static final String DISABLED_IMG_PATH_STRIKE_THROUGH = DTOOL16
+// + "StrikeThrough.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_SUBSCRIPT = DTOOL16
+ + "Subscript.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_SUPERSCRIPT = DTOOL16
+ + "Superscript.gif"; //$NON-NLS-1$
+
+ private static String DISABLED_IMG_PATH_TIDY = DTOOL16 + "TidyHTML.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_UNDERLINE = DTOOL16
+ + "Underline.gif"; //$NON-NLS-1$
+
+ public static final String DISABLED_IMG_PATH_ADD_CODE = DTOOL16
+ + "AddCode.gif"; //$NON-NLS-1$
+
+ public static final Image DISABLED_IMG_ADD_IMAGE = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ADD_IMAGE);
+
+// public static final Image DISABLED_IMG_ADD_LINE = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_ADD_LINE);
+
+ public static final Image DISABLED_IMG_ADD_LINK = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ADD_LINK);
+
+ public static final Image DISABLED_IMG_ADD_ORDERED_LIST = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ADD_ORDERED_LIST);
+
+ public static final Image DISABLED_IMG_ADD_TABLE = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ADD_TABLE);
+
+ public static final Image DISABLED_IMG_ADD_UNORDERED_LIST = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ADD_UNORDERED_LIST);
+
+ public static final Image DISABLED_IMG_BOLD = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_BOLD);
+
+ public static final Image DISABLED_IMG_CLEAR_CONTENT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_CLEAR_CONTENT);
+
+ public static final Image DISABLED_IMG_COPY = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_COPY);
+
+ public static final Image DISABLED_IMG_CUT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_CUT);
+
+ public static final Image DISABLED_IMG_FIND_REPLACE = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_FIND_REPLACE);
+
+ public static final Image DISABLED_IMG_INDENT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_INDENT);
+
+ public static final Image DISABLED_IMG_ITALIC = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_ITALIC);
+
+// public static final Image DISABLED_IMG_JUSTIFY_CENTER = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_JUSTIFY_CENTER);
+//
+// public static final Image DISABLED_IMG_JUSTIFY_FULL = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_JUSTIFY_FULL);
+//
+// public static final Image DISABLED_IMG_JUSTIFY_LEFT = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_JUSTIFY_LEFT);
+//
+// public static final Image DISABLED_IMG_JUSTIFY_RIGHT = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_JUSTIFY_RIGHT);
+
+ public static final Image DISABLED_IMG_OUTDENT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_OUTDENT);
+
+ public static final Image DISABLED_IMG_PASTE = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_PASTE);
+
+// public static final Image DISABLED_IMG_STRIKE_THROUGH = richTextPlugin
+// .getSharedImage(DISABLED_IMG_PATH_STRIKE_THROUGH);
+
+ public static final Image DISABLED_IMG_SUBSCRIPT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_SUBSCRIPT);
+
+ public static final Image DISABLED_IMG_SUPERSCRIPT = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_SUPERSCRIPT);
+
+ public static final Image DISABLED_IMG_UNDERLINE = richTextPlugin
+ .getSharedImage(DISABLED_IMG_PATH_UNDERLINE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_IMAGE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_IMAGE);
+
+// public static final ImageDescriptor DISABLED_IMG_DESC_ADD_LINE = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_ADD_LINE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_LINK = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_LINK);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_ORDERED_LIST = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_ORDERED_LIST);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_TABLE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_TABLE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_UNORDERED_LIST = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_UNORDERED_LIST);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_BOLD = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_BOLD);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_CLEAR_CONTENT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_CLEAR_CONTENT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_COPY = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_COPY);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_CUT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_CUT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_FIND_REPLACE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_FIND_REPLACE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_INDENT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_INDENT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ITALIC = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ITALIC);
+
+// public static final ImageDescriptor DISABLED_IMG_DESC_JUSTIFY_CENTER = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_JUSTIFY_CENTER);
+//
+// public static final ImageDescriptor DISABLED_IMG_DESC_JUSTIFY_FULL = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_JUSTIFY_FULL);
+//
+// public static final ImageDescriptor DISABLED_IMG_DESC_JUSTIFY_LEFT = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_JUSTIFY_LEFT);
+//
+// public static final ImageDescriptor DISABLED_IMG_DESC_JUSTIFY_RIGHT = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_JUSTIFY_RIGHT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_OUTDENT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_OUTDENT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_PASTE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_PASTE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_PASTE_PLAIN_TEXT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_PASTE_PLAIN_TEXT);
+
+// public static final ImageDescriptor DISABLED_IMG_DESC_STRIKE_THROUGH = richTextPlugin
+// .getImageDescriptor(DISABLED_IMG_PATH_STRIKE_THROUGH);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_SUBSCRIPT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_SUBSCRIPT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_SUPERSCRIPT = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_SUPERSCRIPT);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_UNDERLINE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_UNDERLINE);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_TIDY = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_TIDY);
+
+ public static final ImageDescriptor DISABLED_IMG_DESC_ADD_CODE = richTextPlugin
+ .getImageDescriptor(DISABLED_IMG_PATH_ADD_CODE);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextListener.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextListener.java
new file mode 100644
index 00000000000..8e6116ab635
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextListener.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 org.eclipse.swt.widgets.Listener;
+
+/**
+ * Listens to a rich text editing event.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextListener {
+
+ private int eventType;
+
+ private Listener listener;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param eventType
+ * the event type
+ * @param listener
+ * the event listener
+ */
+ public RichTextListener(int eventType, Listener listener) {
+ this.eventType = eventType;
+ this.listener = listener;
+ }
+
+ /**
+ * Returns the event type.
+ *
+ * @return the event type
+ */
+ public int getEventType() {
+ return eventType;
+ }
+
+ /**
+ * Returns the event listener.
+ */
+ public Listener getListener() {
+ return listener;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextPlugin.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextPlugin.java
new file mode 100644
index 00000000000..b204b83a44b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextPlugin.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.util.Date;
+
+import org.eclipse.epf.common.ui.AbstractPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The Rich Text plug-in class.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextPlugin extends AbstractPlugin {
+
+ // The shared plug-in instance.
+ private static RichTextPlugin plugin;
+
+ // The date and time when this plug-in was started.
+ private Date startTime;
+
+ /**
+ * Default constructor.
+ */
+ public RichTextPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * @see AbstractPlugin#start(BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ startTime = new Date();
+ }
+
+ /**
+ * @see AbstractPlugin#stop(BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared plug-in instance.
+ */
+ public static RichTextPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the date and time when this plug-in was started.
+ */
+ public Date getStartTime() {
+ return startTime;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextResources.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextResources.java
new file mode 100644
index 00000000000..bf25e27740d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextResources.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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 org.eclipse.osgi.util.NLS;
+
+/**
+ * The RichText resources.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public final class RichTextResources extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.epf.richtext.Resources"; //$NON-NLS-1$
+
+ public static String fontNameAction_CSS_Default;
+ public static String fontNameAction_CSS_Default_Mozilla;
+ public static String fontNameAction_DefaultFontName;
+ public static String fontStyle_normal;
+ public static String fontStyle_sectionHeading;
+ public static String fontStyle_subsectionHeading;
+ public static String fontStyle_subSubsectionHeading;
+ public static String fontStyle_quote;
+ public static String fontStyle_codeSample;
+ public static String blockTag_paragraph;
+ public static String blockTag_heading1;
+ public static String blockTag_heading2;
+ public static String blockTag_heading3;
+ public static String blockTag_heading4;
+ public static String blockTag_heading5;
+ public static String blockTag_heading6;
+ public static String blockTag_address;
+ public static String blockTag_preformattedText;
+ public static String fontName_default;
+ public static String fontName_arial;
+ public static String fontName_courierNew;
+ public static String fontName_timesNewRoman;
+ public static String fontName_verdana;
+ public static String addHorizontalBarAction_toolTipText;
+ public static String addImageAction_toolTipText;
+ public static String addLineAction_toolTipText;
+ public static String addLinkAction_toolTipText;
+ public static String addOrderedListAction_toolTipText;
+ public static String addTableAction_toolTipText;
+ public static String addUnorderedListAction_toolTipText;
+ public static String boldAction_toolTipText;
+ public static String clearContentAction_toolTipText;
+ public static String copyAction_toolTipText;
+ public static String cutAction_toolTipText;
+ public static String findReplaceAction_toolTipText;
+ public static String indentAction_toolTipText;
+ public static String italicAction_toolTipText;
+ public static String justifyCenterAction_toolTipText;
+ public static String justifyFullAction_toolTipText;
+ public static String justifyLeftAction_toolTipText;
+ public static String justifyRightAction_toolTipText;
+ public static String outdentAction_toolTipText;
+ public static String pasteAction_toolTipText;
+ public static String pastePlainTextAction_toolTipText;
+ public static String subscriptAction_toolTipText;
+ public static String superscriptAction_toolTipText;
+ public static String underlineAction_toolTipText;
+ public static String fontStyleAction_toolTipText;
+ public static String blockTagAction_toolTipText;
+ public static String fontNameAction_toolTipText;
+ public static String fontSizeAction_toolTipText;
+ public static String cutAction_text;
+ public static String copyAction_text;
+ public static String pasteAction_text;
+ public static String pastePlainTextAction_text;
+ public static String richTextTab_text;
+ public static String richTextTab_toolTipText;
+ public static String htmlTab_text;
+ public static String htmlTab_toolTipText;
+ public static String addImageDialog_title;
+ public static String addLinkDialog_title;
+ public static String addTableDialog_title;
+ public static String findReplaceDialog_title;
+ public static String urlDisplayNameLabel_text;
+ public static String urlLabel_text;
+ public static String summaryLabel_text;
+ public static String captionLabel_text;
+ public static String rowsLabel_text;
+ public static String columnsLabel_text;
+ public static String widthLabel_text;
+ public static String tableStyleLabel_text;
+ public static String tableHeaderNone_text;
+ public static String tableHeaderCols_text;
+ public static String tableHeaderRows_text;
+ public static String tableHeaderBoth_text;
+ public static String browseButton_text;
+ public static String clearContentDialog_title;
+ public static String clearContentDialog_text;
+ public static String findLabel_text;
+ public static String replaceLabel_text;
+ public static String optionsGroup_text;
+ public static String caseSensitiveCheckbox_text;
+ public static String wholeWordCheckbox_text;
+ public static String directionGroup_text;
+ public static String forwardRadioButton_text;
+ public static String backwardRadioButton_text;
+ public static String findButton_text;
+ public static String replaceButton_text;
+ public static String replaceFindButton_text;
+ public static String replaceallButton_text;
+ public static String FindReplace_Status_noMatch_label;
+ public static String maxCharsPerLineLabel_text;
+ public static String indentHTMLCheckbox_text;
+ public static String indentSizeLabel_text;
+ public static String tidy_clean_text;
+ public static String tidy_cleaner_text;
+ public static String tidy_cleanest_text;
+ public static String tidy_clean_toolTipText;
+ public static String tidy_cleaner_toolTipText;
+ public static String tidy_cleanest_toolTipText;
+ public static String addCodeAction_toolTipText;
+ public static String addCodeDialog_title;
+ public static String addCodeDialog_Msg;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, RichTextResources.class);
+ }
+
+ private RichTextResources() {
+ }
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextSelection.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextSelection.java
new file mode 100644
index 00000000000..ee9c7671704
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextSelection.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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;
+
+/**
+ * Models a text selection in a rich text control and editor.
+ *
+ * @author Jeff Hardy
+ * @since 1.2
+ */
+public class RichTextSelection {
+
+ // The control's text selection.
+ protected String text = ""; //$NON-NLS-1$
+
+ // The control's text selection offset
+ protected int offsetStart = 0;
+
+ // The control's text selection font
+ protected String fontName = ""; //$NON-NLS-1$
+
+ // The control's text selection font size
+ // could be in point size (12pt), or HTML size (1-7)
+ protected String fontSize = ""; //$NON-NLS-1$
+
+ // The control's text current style
+ protected String blockStyle = ""; //$NON-NLS-1$
+
+ // The control's text current flags
+ protected int flags = 0;
+
+ // Text status flags
+ public static final int BOLD = 1;
+
+ public static final int ITALIC = BOLD << 1;
+
+ public static final int UNDERLINE = ITALIC << 1;
+
+ public static final int SUBSCRIPT = UNDERLINE << 1;
+
+ public static final int SUPERSCRIPT = SUBSCRIPT << 1;
+
+ public String getBlockStyle() {
+ return blockStyle;
+ }
+
+ public void setBlockStyle(String blockStyle) {
+ this.blockStyle = blockStyle;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public void setFlags(int flags) {
+ this.flags = flags;
+ }
+
+ public String getFontName() {
+ return fontName;
+ }
+
+ public void setFontName(String fontName) {
+ this.fontName = fontName;
+ }
+
+ public String getFontSize() {
+ return fontSize;
+ }
+
+ public void setFontSize(String fontSize) {
+ this.fontSize = fontSize;
+ }
+
+ public int getOffsetStart() {
+ return offsetStart;
+ }
+
+ public void setOffsetStart(int offsetStart) {
+ this.offsetStart = offsetStart;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public boolean isBold() {
+ return (flags & BOLD) != 0;
+ }
+
+ public boolean isItalic() {
+ return (flags & ITALIC) != 0;
+ }
+
+ public boolean isUnderLine() {
+ return (flags & UNDERLINE) != 0;
+ }
+
+ public boolean isSubscript() {
+ return (flags & SUBSCRIPT) != 0;
+ }
+
+ public boolean isSuperscript() {
+ return (flags & SUPERSCRIPT) != 0;
+ }
+
+ /**
+ * Clears the selection info
+ */
+ public void clear() {
+ text = ""; //$NON-NLS-1$
+ offsetStart = 0;
+ fontName = ""; //$NON-NLS-1$
+ fontSize = ""; //$NON-NLS-1$
+ blockStyle = ""; //$NON-NLS-1$
+ flags = 0;
+ }
+
+ public String toString() {
+ String str = "Text: " + text + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ str += "fontName: " + fontName + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ str += "fontSize: " + fontSize + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ str += "blockStyle: " + blockStyle + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ str += "flags: " + flags + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ return str;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextToolBar.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextToolBar.java
new file mode 100644
index 00000000000..70252607447
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/RichTextToolBar.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.epf.richtext.actions.IRichTextAction;
+import org.eclipse.epf.richtext.actions.RichTextAction;
+import org.eclipse.epf.richtext.actions.RichTextComboAction;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * The default rich text tool bar implementation.
+ *
+ * Split into 2 toolbars (one for CCombos, one for buttons) for tabbing purposes.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class RichTextToolBar implements IRichTextToolBar {
+
+ // The parent rich text control.
+ private IRichText richText;
+
+ // If true, add a new tool bar.
+ private boolean addToolBar = true;
+
+ // The current tool bar manager used to populate the tool actions.
+ private ToolBarManager toolbarMgr;
+
+ // The current tool bar manager used to populate the tool actions.
+ private ToolBarManager toolbarMgrCombo;
+
+ // The action items in the tool bar(s).
+ private List<Object> actionItems = new ArrayList<Object>();
+
+ private static int lastWidth = -1;
+
+ protected Composite parent;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent composite
+ * @param style
+ * the tool bar style
+ * @param richText
+ * the parent rich text control
+ */
+ public RichTextToolBar(Composite parent, int style, IRichText richText) {
+ this.parent = parent;
+ this.richText = richText;
+
+ addToolBar();
+ }
+
+ public void addAction(final IAction action) {
+ if (action != null) {
+ ActionContributionItem item = new ActionContributionItem(action);
+ toolbarMgr.add(item);
+ toolbarMgr.update(true);
+ actionItems.add(item);
+ }
+ }
+
+ /**
+ * Adds a combo action to the tool bar.
+ *
+ * @param action
+ * the action to add
+ */
+ public void addAction(final RichTextComboAction item) {
+ if (item != null) {
+ item.init();
+ toolbarMgrCombo.add(item);
+ toolbarMgrCombo.update(true);
+ actionItems.add(item);
+ }
+ }
+
+ /**
+ * Adds a separator to the tool bar.
+ */
+ public void addSeparator() {
+ toolbarMgr.add(new Separator());
+ }
+
+ /**
+ * Updates the toolbar state.
+ * <p>
+ * Enables/disables actions depending on the currently selected
+ * RichTextEditor tab (RichText vs. HTML)
+ *
+ * @param editable
+ * specifies whether to enable non-ReadOnly commands
+ */
+ public void updateToolBar(boolean editable) {
+ boolean richTextMode = true;
+ if (richText instanceof RichTextEditor
+ && ((RichTextEditor) richText).isHTMLTabSelected()) {
+ richTextMode = false;
+ }
+ for (Iterator i = actionItems.iterator(); i.hasNext();) {
+ Object item = i.next();
+ if (item instanceof ToolItem) {
+ boolean enabledToolItem = true;
+ ToolItem toolItem = (ToolItem) item;
+ IRichTextAction action = (IRichTextAction) toolItem.getData();
+ if (action != null && !editable
+ && action.disableInReadOnlyMode()) {
+ enabledToolItem = false;
+ }
+ if (action != null && !richTextMode
+ && action.disableInSourceMode()) {
+ enabledToolItem = false;
+ }
+ toolItem.setEnabled(enabledToolItem);
+ } else if (item instanceof Combo) {
+ if (richTextMode && editable) {
+ ((Combo) item).setEnabled(true);
+ } else {
+ ((Combo) item).setEnabled(false);
+ }
+ } else if (item instanceof ActionContributionItem) {
+ boolean enabledToolItem = true;
+ RichTextAction action = (RichTextAction) ((ActionContributionItem) item)
+ .getAction();
+ if (action != null && !editable
+ && action.disableInReadOnlyMode()) {
+ enabledToolItem = false;
+ }
+ if (action != null && !richTextMode
+ && action.disableInSourceMode()) {
+ enabledToolItem = false;
+ }
+ action.setEnabled(enabledToolItem);
+ }
+ }
+ }
+
+ /**
+ * Adds a tool bar, if necessary, to contain a button action or separator.
+ */
+ protected void addToolBar() {
+ if (addToolBar) {
+ toolbarMgrCombo = new ToolBarManager(SWT.WRAP | SWT.FLAT | parent.getStyle());
+ toolbarMgrCombo.createControl(parent);
+ toolbarMgr = new ToolBarManager(SWT.WRAP | SWT.FLAT | parent.getStyle());
+ toolbarMgr.createControl(parent);
+ addToolBar = false;
+ }
+ }
+
+ public ToolBarManager getToolbarMgr() {
+ return toolbarMgr;
+ }
+
+ public ToolBarManager getToolbarMgrCombo() {
+ return toolbarMgrCombo;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddCodeAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddCodeAction.java
new file mode 100644
index 00000000000..49a63617e24
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddCodeAction.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+* Licensed Materials - Property of IBM
+* (c) Copyright IBM Corporation 2007,2011. All Rights Reserved.
+*
+* Note to U.S. Government Users Restricted Rights:
+* Use, duplication or disclosure restricted by GSA ADP Schedule
+* Contract with IBM Corp.
+*******************************************************************************/
+
+package org.eclipse.epf.richtext.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.dialogs.AddCodeDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+
+public class AddCodeAction extends RichTextAction {
+
+ public AddCodeAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_CODE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_CODE);
+ setToolTipText(RichTextResources.addCodeAction_toolTipText);
+ }
+
+ public void execute(IRichText richText) {
+ if (richText != null ) {
+ AddCodeDialog dialog = new AddCodeDialog(Display.getCurrent().getActiveShell());
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ String html = RichText.workaroundForObjectParamNode(dialog.getCode());
+ richText.executeCommand(RichTextCommand.ADD_HTML, html);
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddImageAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddImageAction.java
new file mode 100644
index 00000000000..c5b9ece213b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddImageAction.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.dialogs.AddImageDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Adds an image to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddImageAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddImageAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_IMAGE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_IMAGE);
+ setToolTipText(RichTextResources.addImageAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ AddImageDialog dialog = new AddImageDialog(Display.getCurrent()
+ .getActiveShell());
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ String imageURL = dialog.getImage().getURL();
+ if (imageURL.length() > 0) {
+ richText
+ .executeCommand(RichTextCommand.ADD_IMAGE, imageURL);
+ }
+ }
+ }
+ }
+
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLineAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLineAction.java
new file mode 100644
index 00000000000..206e287bc88
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLineAction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Adds a horizontal bar to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddLineAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddLineAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_LINE);
+ setToolTipText(RichTextResources.addLineAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.ADD_LINE);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLinkAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLinkAction.java
new file mode 100644
index 00000000000..91d0ec0fba3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddLinkAction.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.dialogs.AddLinkDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Adds a link to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddLinkAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddLinkAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_LINK);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_LINK);
+ setToolTipText(RichTextResources.addLinkAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ AddLinkDialog dialog = new AddLinkDialog(Display.getCurrent()
+ .getActiveShell(), richText.getBasePath());
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ String linkURL = dialog.getLink().getURL();
+ if (linkURL.length() > 0) {
+ richText.executeCommand(RichTextCommand.ADD_LINK, linkURL);
+ }
+ }
+ }
+ }
+
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddOrderedListAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddOrderedListAction.java
new file mode 100644
index 00000000000..60eca82eb26
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddOrderedListAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Adds an ordered list to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddOrderedListAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddOrderedListAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_ORDERED_LIST);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_ORDERED_LIST);
+ setToolTipText(RichTextResources.addOrderedListAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.ADD_ORDERED_LIST);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddTableAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddTableAction.java
new file mode 100644
index 00000000000..e3d68dab496
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddTableAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.dialogs.AddTableDialog;
+import org.eclipse.epf.richtext.html.Table;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Adds a table to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddTableAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddTableAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_TABLE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_TABLE);
+ setToolTipText(RichTextResources.addTableAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ AddTableDialog dialog = new AddTableDialog(Display.getCurrent()
+ .getActiveShell());
+ dialog.open();
+ if (dialog.getReturnCode() == Window.OK) {
+ Table table = dialog.getTable();
+ int rows = table.getRows();
+ int cols = table.getColumns();
+ String width = table.getWidth();
+ int tableheaders = table.getTableHeaders();
+ String summary = table.getSummary();
+ String caption = table.getCaption();
+ if (rows > 0 && cols > 0) {
+ richText
+ .executeCommand(
+ RichTextCommand.ADD_TABLE,
+ new String[] {
+ "" + rows, "" + cols, "" + width, summary, caption, "" + tableheaders }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddUnorderedListAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddUnorderedListAction.java
new file mode 100644
index 00000000000..fa9c0b8fcef
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/AddUnorderedListAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Adds an unordered list to a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddUnorderedListAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public AddUnorderedListAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_ADD_UNORDERED_LIST);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_ADD_UNORDERED_LIST);
+ setToolTipText(RichTextResources.addUnorderedListAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.ADD_UNORDERED_LIST);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BaseRichTextAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BaseRichTextAction.java
new file mode 100644
index 00000000000..e5024d72520
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BaseRichTextAction.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+/**
+ * The abstract base class for all rich text action.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public abstract class BaseRichTextAction implements IBaseRichTextAction {
+
+ protected String toolTipText;
+
+ protected boolean enabled = true;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public BaseRichTextAction() {
+ }
+
+ /**
+ * Returns the tool tip for the action.
+ *
+ * @return the tool tip text
+ */
+ public String getToolTipText() {
+ return toolTipText;
+ }
+
+ /**
+ * Sets the tool tip for the action.
+ *
+ * @param toolTipText
+ * the tool tip text
+ */
+ public void setToolTipText(String toolTipText) {
+ this.toolTipText = toolTipText;
+ }
+
+ /**
+ * Returns the enabled status of the action.
+ *
+ * @return <code>true</code> if enabled, <code>false</code> if not
+ */
+ public boolean getEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables the action.
+ *
+ * @param enabled
+ * if <code>true</code>, enable the action. if
+ * <code>false</code>, disable it.
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BlockTagAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BlockTagAction.java
new file mode 100644
index 00000000000..92dd320a3a2
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BlockTagAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.html.BlockTag;
+
+/**
+ * Sets the font name for the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class BlockTagAction extends RichTextComboAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public BlockTagAction(final IRichText richText) {
+ super(richText);
+ setToolTipText(RichTextResources.blockTagAction_toolTipText);
+ }
+
+ @Override
+ public Collection<String> getInput() {
+ Collection<String> returnList = new ArrayList<String>();
+
+ returnList.add(BlockTag.PARAGRAPH.getName());
+ returnList.add(BlockTag.HEADING_1.getName());
+ returnList.add(BlockTag.HEADING_2.getName());
+ returnList.add(BlockTag.HEADING_3.getName());
+ returnList.add(BlockTag.HEADING_4.getName());
+ returnList.add(BlockTag.HEADING_5.getName());
+ returnList.add(BlockTag.HEADING_6.getName());
+ returnList.add(BlockTag.ADDRESS.getName());
+ returnList.add(BlockTag.PREFORMATTED_TEXT.getName());
+
+ return returnList;
+ }
+
+
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ String selected = getCComboSelection();
+ richText.executeCommand(RichTextCommand.FORMAT_BLOCK, selected);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BoldAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BoldAction.java
new file mode 100644
index 00000000000..be193e621d1
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/BoldAction.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Toggles the 'bold' attribute of the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class BoldAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public BoldAction(final IRichText richText) {
+ super(richText, IAction.AS_CHECK_BOX);
+ setImageDescriptor(RichTextImages.IMG_DESC_BOLD);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_BOLD);
+ setToolTipText(RichTextResources.boldAction_toolTipText);
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ setChecked(richText.getSelected().isBold());
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.BOLD);
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ClearContentAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ClearContentAction.java
new file mode 100644
index 00000000000..a6a6d0dc676
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ClearContentAction.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Clears the content of a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class ClearContentAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public ClearContentAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_CLEAR_CONTENT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_CLEAR_CONTENT);
+ setToolTipText(RichTextResources.clearContentAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * s rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ if (RichTextPlugin.getDefault().getMsgDialog().displayPrompt(
+ RichTextResources.clearContentDialog_title,
+ RichTextResources.clearContentDialog_text)) {
+ richText.executeCommand(RichTextCommand.CLEAR_CONTENT);
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CopyAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CopyAction.java
new file mode 100644
index 00000000000..e8796f6e854
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CopyAction.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.custom.StyledText;
+
+/**
+ * Copies the selected text in a rich text control to the clipboard.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class CopyAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public CopyAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_COPY);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_COPY);
+ setToolTipText(RichTextResources.copyAction_toolTipText);
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in readonly mode.
+ */
+ public boolean disableInReadOnlyMode() {
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ if (richText instanceof RichTextEditor
+ && ((RichTextEditor) richText).isHTMLTabSelected()) {
+ StyledText styledText = ((RichTextEditor) richText).getSourceEdit();
+ styledText.copy();
+ } else {
+ richText.setCopyURL();
+ richText.executeCommand(RichTextCommand.COPY);
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CutAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CutAction.java
new file mode 100644
index 00000000000..4e03e253654
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/CutAction.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.custom.StyledText;
+
+/**
+ * Cuts the selected text in the rich text control to the clipboard.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class CutAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public CutAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_CUT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_CUT);
+ setToolTipText(RichTextResources.cutAction_toolTipText);
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ if (richText instanceof RichTextEditor
+ && ((RichTextEditor) richText).isHTMLTabSelected()) {
+ StyledText styledText = ((RichTextEditor) richText)
+ .getSourceEdit();
+ styledText.cut();
+ } else {
+ richText.setCopyURL();
+ richText.executeCommand(RichTextCommand.CUT);
+ }
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FindReplaceAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FindReplaceAction.java
new file mode 100644
index 00000000000..267d7b97465
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FindReplaceAction.java
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.common.utils.XMLUtil;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.dialogs.FindReplaceDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Finds and replaces text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class FindReplaceAction extends RichTextAction {
+
+ /**
+ * Finds text sub action.
+ */
+ public static final int FIND_TEXT = 1;
+
+ /**
+ * Replaces text sub action.
+ */
+ public static final int REPLACE_TEXT = 2;
+
+ /**
+ * Replaces and finds text sub action.
+ */
+ public static final int REPLACE_FIND_TEXT = 3;
+
+ /**
+ * Replaces all sub action.
+ */
+ public static final int REPLACE_ALL_TEXT = 4;
+
+ /**
+ * Find match in a forward direction.
+ */
+ public static final int FORWARD_MATCH = 1;
+
+ /**
+ * Find match in a backward direction.
+ */
+ public static final int BACKWARD_MATCH = -1;
+
+ /**
+ * Whole word match.
+ */
+ public static final int WHOLE_WORD_MATCH = 2;
+
+ /**
+ * Case sensitive match.
+ */
+ public static final int CASE_SENSITIVE_MATCH = 4;
+
+ // Encoded single quote.
+ protected static final String ENCODED_SINGLE_QUOTE = "%sq%"; //$NON-NLS-1$
+
+ protected IRichText richText;
+
+ protected StyledText styledText;
+
+ protected boolean foundMatch = false;
+
+ // the dialog instance
+ protected FindReplaceDialog dialog;
+
+ /**
+ * Creates a new instance.
+ */
+ public FindReplaceAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_FIND_REPLACE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_FIND_REPLACE);
+ setToolTipText(RichTextResources.findReplaceAction_toolTipText);
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in readonly mode.
+ */
+ public boolean disableInReadOnlyMode() {
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (this.richText == null)
+ this.richText = richText;
+ if (this.richText != null) {
+ try {
+ if (dialog != null) {
+ dialog.setFindOnly(!this.richText.getEditable());
+ dialog.open();
+ } else {
+ dialog = new FindReplaceDialog(Display
+ .getCurrent().getActiveShell(), this, !this.richText
+ .getEditable());
+ dialog.open();
+ }
+ } catch (Exception e) {
+ RichTextPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>true</code> if a match is found.
+ *
+ * @return <code>true</code> if a match is found.
+ */
+ public boolean getFoundMatch() {
+ return foundMatch;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param subAction
+ * the sub action to execute
+ * @param findText
+ * the find text
+ * @param replaceText
+ * the replace text
+ * @param matchDir
+ * the match direction; the value can either be
+ * <code>FIND_FORWARD</code> or <code>FIND_BACKWARD</code>.
+ * @param matchOptions
+ * the match options
+ */
+ public void run(int subAction, String findText, String replaceText,
+ int matchDir, int matchOptions) {
+ styledText = null;
+ if (richText instanceof RichTextEditor
+ && ((RichTextEditor) richText).isHTMLTabSelected()) {
+ styledText = ((RichTextEditor) richText).getSourceEdit();
+ }
+ if (styledText == null) {
+ if (findText.indexOf("'") != -1) { //$NON-NLS-1$
+ findText = findText.replaceAll("'", ENCODED_SINGLE_QUOTE); //$NON-NLS-1$
+ }
+ if (replaceText.indexOf("'") != -1) { //$NON-NLS-1$
+ replaceText = replaceText.replaceAll("'", ENCODED_SINGLE_QUOTE); //$NON-NLS-1$
+ }
+ }
+ try {
+ foundMatch = false;
+ int status = 0;
+ switch (subAction) {
+ case FIND_TEXT:
+ status = findText(findText, matchDir, matchOptions);
+ break;
+ case REPLACE_TEXT:
+ status = replaceText(replaceText, matchDir, matchOptions);
+ break;
+ case REPLACE_FIND_TEXT:
+ status = replaceFindText(findText, replaceText, matchDir,
+ matchOptions);
+ break;
+ case REPLACE_ALL_TEXT:
+ replaceAll(findText, replaceText, matchOptions);
+ break;
+ }
+ if (status > 0)
+ foundMatch = true;
+ } catch (Exception e) {
+ RichTextPlugin.getDefault().getLogger().logError(e);
+ }
+ }
+
+ /**
+ * Escapes the given text.
+ *
+ * @param text
+ * text to be escaped
+ */
+ protected static String escape(String text) {
+ if (text == null || text.length() == 0)
+ return ""; //$NON-NLS-1$
+ StringBuffer sb = new StringBuffer();
+ int textSize = text.length();
+ for (int i = 0; i < textSize; i++) {
+ char ch = text.charAt(i);
+ switch (ch) {
+ case '<':
+ sb.append(XMLUtil.XML_LT);
+ break;
+ case '>':
+ sb.append(XMLUtil.XML_GT);
+ break;
+ case '&':
+ sb.append(XMLUtil.XML_AMP);
+ break;
+ default:
+ sb.append(ch);
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ protected int findText(String findText, int matchDir, int matchOptions) {
+ int status = 0;
+ if (styledText != null) {
+ status = styledTextFindTextAndSelect(findText, matchDir,
+ matchOptions);
+ } else {
+ status = richText
+ .executeCommand(RichTextCommand.FIND_TEXT, new String[] {
+ findText, "" + matchDir, "" + matchOptions }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return status;
+ }
+
+ protected int replaceText(String replaceText, int matchDir, int matchOptions) {
+ int status = 0;
+ if (styledText != null) {
+ status = styledTextReplaceTextAndSelect(replaceText);
+ } else {
+ status = richText.executeCommand(RichTextCommand.REPLACE_TEXT,
+ new String[] { replaceText,
+ "" + matchDir, "" + matchOptions }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return status;
+ }
+
+ protected int replaceFindText(String findText, String replaceText,
+ int matchDir, int matchOptions) {
+ int status = 0;
+ if (styledText != null) {
+ styledTextReplaceTextAndSelect(replaceText);
+ status = styledTextFindTextAndSelect(findText, matchDir,
+ matchOptions);
+ } else {
+ richText.executeCommand(RichTextCommand.REPLACE_TEXT, new String[] {
+ replaceText, "" + matchDir, "" + matchOptions }); //$NON-NLS-1$ //$NON-NLS-2$
+ status = richText
+ .executeCommand(RichTextCommand.FIND_TEXT, new String[] {
+ findText, "" + matchDir, "" + matchOptions }); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return status;
+ }
+
+ protected void replaceAll(String findText, String replaceText,
+ int matchOptions) {
+ if (styledText != null) {
+ styledTextReplaceAll(findText, replaceText, matchOptions);
+ } else {
+ richText.executeCommand(RichTextCommand.REPLACE_ALL_TEXT,
+ new String[] { escape(findText), escape(replaceText),
+ "" + matchOptions }); //$NON-NLS-1$
+ }
+ }
+
+ protected int styledTextFindTextAndSelect(String findText, int matchDir,
+ int matchOptions) {
+ Point selectionOffset = styledText.getSelectionRange();
+ int firstSelectedOffset = selectionOffset.x;
+ int lastSelectedOffset = selectionOffset.x + selectionOffset.y - 1;
+ String htmlText = styledText.getText();
+ int indexOfMatch = -1;
+ if ((matchOptions & CASE_SENSITIVE_MATCH) == 0) {
+ // TODO: use toUpperCase(Locale) once library has locale attribute
+ htmlText = htmlText.toUpperCase();
+ findText = findText.toUpperCase();
+ }
+ do {
+ if (indexOfMatch != -1) {
+ lastSelectedOffset = indexOfMatch + 1;
+ firstSelectedOffset = indexOfMatch - 1;
+ }
+ if (matchDir == FORWARD_MATCH) {
+ indexOfMatch = htmlText.indexOf(findText,
+ lastSelectedOffset + 1);
+ } else {
+ indexOfMatch = htmlText.lastIndexOf(findText,
+ firstSelectedOffset - 1);
+ }
+ } while (indexOfMatch != -1
+ && ((matchOptions & WHOLE_WORD_MATCH) == WHOLE_WORD_MATCH)
+ && isPartOfWord(htmlText, indexOfMatch, findText.length()));
+ if (indexOfMatch != -1) {
+ styledText.setSelectionRange(indexOfMatch, findText.length());
+ styledText.showSelection();
+ } else {
+ String selectedText = styledText.getSelectionText();
+ if ((matchOptions & CASE_SENSITIVE_MATCH) == 0) {
+ selectedText = selectedText.toUpperCase();
+ }
+ if (selectedText.equals(findText)) {
+ indexOfMatch = styledText.getSelectionRange().x;
+ }
+ }
+ return indexOfMatch;
+
+ }
+
+ protected int styledTextReplaceTextAndSelect(String replaceText) {
+ Point selectionOffset = styledText.getSelectionRange();
+ styledText.replaceTextRange(selectionOffset.x, selectionOffset.y,
+ replaceText);
+ styledText.setSelectionRange(selectionOffset.x, replaceText.length());
+
+ return 1;
+ }
+
+ protected void styledTextReplaceAll(String findText, String replaceText,
+ int matchOptions) {
+ styledText.setSelectionRange(0, 0);
+ while (styledTextFindTextAndSelect(findText, FORWARD_MATCH,
+ matchOptions) != -1) {
+ styledTextReplaceTextAndSelect(replaceText);
+ }
+ }
+
+ protected boolean isWordChar(char c) {
+ if (Character.isLetterOrDigit(c))
+ return true;
+ return false;
+ }
+
+ protected boolean isPartOfWord(String text, int index, int length) {
+ if (index > 0)
+ if (isWordChar(text.charAt(index - 1)))
+ return true;
+ if (text.length() >= index + length)
+ if (isWordChar(text.charAt(index + length)))
+ return true;
+ return false;
+ }
+
+ public IRichText getRichText() {
+ return richText;
+ }
+
+ public void setRichText(IRichText richText) {
+ this.richText = richText;
+ }
+
+ public void dispose() {
+ if (dialog != null) {
+ dialog.close();
+ dialog = null;
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontNameAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontNameAction.java
new file mode 100644
index 00000000000..94de2201f6a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontNameAction.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Sets the font name for the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class FontNameAction extends RichTextComboAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public FontNameAction(final IRichText richText) {
+ super(richText);
+ setToolTipText(RichTextResources.fontNameAction_toolTipText);
+ // get system fonts
+ SortedSet<String> fontSet = new TreeSet<String>();
+ FontData[] fonts = Display.getCurrent().getFontList(null, true);
+ for (int i = 0; i < fonts.length; i++) {
+ fontSet.add(((FontData) fonts[i]).getName());
+ }
+ input = new ArrayList<String>();
+ input.add(RichTextResources.fontNameAction_DefaultFontName);
+ for (Iterator<String> iter = fontSet.iterator(); iter.hasNext();) {
+ String fontName = iter.next();
+ input.add(fontName);
+ }
+
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ String fontName = richText.getSelected().getFontName();
+ if (fontName
+ .equals(RichTextResources.fontNameAction_CSS_Default)
+ || fontName
+ .equals(RichTextResources.fontNameAction_CSS_Default_Mozilla)
+ || fontName.equals("default")) { //$NON-NLS-1$
+ fontName = RichTextResources.fontNameAction_DefaultFontName;
+ }
+ int index = findFontNameInItems(fontName);
+ setNotifyListeners(false);
+ getCCombo().select(index);
+ setNotifyListeners(true);
+ }
+ });
+ }
+
+ private int findFontNameInItems(String fontName) {
+ int index = -1;
+ for (Iterator<String> iter = input.iterator(); iter.hasNext();) {
+ String font = iter.next();
+ index++;
+ if (font.equalsIgnoreCase(fontName)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ String selected = getCComboSelection();
+ if (selected.equals(RichTextResources.fontNameAction_DefaultFontName)) {
+ richText.executeCommand(RichTextCommand.SET_FONT_NAME, ""); //$NON-NLS-1$
+ } else {
+ richText.executeCommand(RichTextCommand.SET_FONT_NAME, selected);
+ }
+ }
+ }
+
+ @Override
+ public Collection<String> getInput() {
+ return input;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontSizeAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontSizeAction.java
new file mode 100644
index 00000000000..f0629c017f4
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontSizeAction.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Sets the font size for the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class FontSizeAction extends RichTextComboAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public FontSizeAction(final IRichText richText) {
+ super(richText);
+ setToolTipText(RichTextResources.fontSizeAction_toolTipText);
+ input = new ArrayList<String>();
+
+ input.add("Default"); //$NON-NLS-1$
+ input.add("1"); //$NON-NLS-1$
+ input.add("2"); //$NON-NLS-1$
+ input.add("3"); //$NON-NLS-1$
+ input.add("4"); //$NON-NLS-1$
+ input.add("5"); //$NON-NLS-1$
+ input.add("6"); //$NON-NLS-1$
+ input.add("7"); //$NON-NLS-1$
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ // mozilla returns "default" if no size is applied
+ // IE returns 2 if no size is applied
+ String fontSize = richText.getSelected().getFontSize();
+ int index = -1;
+ if (fontSize.equals("default")) { //$NON-NLS-1$
+ index = 0;
+ } else {
+ try {
+ index = Integer.parseInt(fontSize);
+ } catch (NumberFormatException e) {
+ // leave index at -1 so nothing is selected
+ }
+ }
+ setNotifyListeners(false);
+ getCCombo().select(index);
+ setNotifyListeners(true);
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ String selected = getCComboSelection();
+ if ("Default".equals(selected)) { //$NON-NLS-1$
+ richText.executeCommand(RichTextCommand.SET_FONT_SIZE, ""); //$NON-NLS-1$
+ } else {
+ richText.executeCommand(RichTextCommand.SET_FONT_SIZE,
+ selected);
+ }
+ }
+ }
+
+ @Override
+ public Collection<String> getInput() {
+ return input;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontStyleAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontStyleAction.java
new file mode 100644
index 00000000000..b0ed90fdc55
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/FontStyleAction.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.html.FontStyle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Sets the font style for the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class FontStyleAction extends RichTextComboAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public FontStyleAction(final IRichText richText) {
+ super(richText);
+ setToolTipText(RichTextResources.fontStyleAction_toolTipText);
+
+ input = new ArrayList<String>();
+ input.add(FontStyle.NORMAL.getName());
+ input.add(FontStyle.SECTION_HEADING.getName());
+ input.add(FontStyle.SUBSECTION_HEADING.getName());
+ input.add(FontStyle.SUB_SUBSECTION_HEADING.getName());
+ input.add(FontStyle.QUOTE.getName());
+ input.add(FontStyle.CODE_SAMPLE.getName());
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ String blockStyle = richText.getSelected().getBlockStyle();
+ String name = FontStyle.getFontStyleName(blockStyle);
+
+ int index = ((List<String>)input).indexOf(name);
+ setNotifyListeners(false);
+ getCCombo().select(index);
+ setNotifyListeners(true);
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ String selected = getCComboSelection();
+ String value = FontStyle.getFontStyleValue(selected);
+ richText.executeCommand(RichTextCommand.SET_FONT_STYLE, value);
+ }
+ }
+
+ @Override
+ public Collection<String> getInput() {
+ return input;
+ }
+
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IBaseRichTextAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IBaseRichTextAction.java
new file mode 100644
index 00000000000..0566ceef0d7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IBaseRichTextAction.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+/**
+ * The base interface for a rich text action.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public interface IBaseRichTextAction {
+
+ /**
+ * Returns the tool tip for the action.
+ *
+ * @return the tool tip text
+ */
+ public String getToolTipText();
+
+ /**
+ * Sets the tool tip for the action.
+ *
+ * @param toolTipText
+ * the tool tip text
+ */
+ public void setToolTipText(String toolTipText);
+
+ /**
+ * Returns the enabled status of the action.
+ *
+ * @return <code>true</code> if enabled, <code>false</code> if not
+ */
+ public boolean getEnabled();
+
+ /**
+ * Enables or disables the action.
+ *
+ * @param enabled
+ * If <code>true</code>, enable the action. if
+ * <code>false</code>, disable it
+ */
+ public void setEnabled(boolean enabled);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextAction.java
new file mode 100644
index 00000000000..572a2b640a0
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextAction.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * The interface for a rich text button action.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public interface IRichTextAction extends IBaseRichTextAction {
+
+ /**
+ * Returns the image for the action.
+ *
+ * @return the image for the action
+ */
+ public Image getImage();
+
+ /**
+ * Sets the image for the action.
+ *
+ * @param image
+ * the image for the action
+ */
+ public void setImage(Image image);
+
+ /**
+ * Returns the disabled image for the action.
+ *
+ * @return the disabled image for the action
+ */
+ public Image getDisabledImage();
+
+ /**
+ * Sets the disabled image for the action.
+ *
+ * @param image
+ * the disabled image for the action
+ */
+ public void setDisabledImage(Image image);
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in readonly mode.
+ */
+ public boolean disableInReadOnlyMode();
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode();
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText);
+
+ /**
+ * Sets the action's ToolItem
+ * @param toolItem
+ */
+ public void setToolItem(ToolItem toolItem);
+
+ /**
+ * Gets the SWT ToolItem Style to be used for this action
+ */
+ public int getStyle();
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextComboAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextComboAction.java
new file mode 100644
index 00000000000..baeaf167cc7
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IRichTextComboAction.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.common.ui.actions.CComboContributionItem;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+
+/**
+ * The interface for a rich text combo action.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ *
+ * @deprecated unused
+ */
+public interface IRichTextComboAction extends IBaseRichTextAction {
+
+// /**
+// * Adds an item.
+// *
+// * @param item
+// * the item to be added
+// */
+// public void addItem(String item);
+//
+// /**
+// * Returns all items.
+// *
+// * @return an array of items
+// */
+// public String[] getItems();
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public void execute(IRichText richText, int index);
+
+ public IStructuredContentProvider getContentProvider();
+
+ public ILabelProvider getLabelProvider();
+
+ public Object getInput();
+
+ /**
+ * Sets the action's ContributionItem
+ *
+ */
+ public void setContributionItem(CComboContributionItem item);
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IndentAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IndentAction.java
new file mode 100644
index 00000000000..7bd985a7b13
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/IndentAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Indents the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class IndentAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public IndentAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_INDENT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_INDENT);
+ setToolTipText(RichTextResources.indentAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.INDENT);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ItalicAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ItalicAction.java
new file mode 100644
index 00000000000..aae6fc1fe6d
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/ItalicAction.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Toggles the 'italic' attribute of the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class ItalicAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public ItalicAction(final IRichText richText) {
+ super(richText, IAction.AS_CHECK_BOX);
+ setImageDescriptor(RichTextImages.IMG_DESC_ITALIC);
+ setToolTipText(RichTextResources.italicAction_toolTipText);
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ setChecked(richText.getSelected().isItalic());
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.ITALIC);
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyCenterAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyCenterAction.java
new file mode 100644
index 00000000000..74b6b86fbe6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyCenterAction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Center justifies the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class JustifyCenterAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public JustifyCenterAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_JUSTIFY_CENTER);
+ setToolTipText(RichTextResources.justifyCenterAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.JUSTIFY_CENTER);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyFullAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyFullAction.java
new file mode 100644
index 00000000000..ca1a4e06d4f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyFullAction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Fully justifies the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class JustifyFullAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public JustifyFullAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_JUSTIFY_FULL);
+ setToolTipText(RichTextResources.justifyFullAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.JUSTIFY_FULL);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyLeftAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyLeftAction.java
new file mode 100644
index 00000000000..7da611fa759
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyLeftAction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Left justifies the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class JustifyLeftAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public JustifyLeftAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_JUSTIFY_LEFT);
+ setToolTipText(RichTextResources.justifyLeftAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.JUSTIFY_LEFT);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyRightAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyRightAction.java
new file mode 100644
index 00000000000..e53aba5e31e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/JustifyRightAction.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Right justifies the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class JustifyRightAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public JustifyRightAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_JUSTIFY_RIGHT);
+ setToolTipText(RichTextResources.justifyRightAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.JUSTIFY_RIGHT);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/OutdentAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/OutdentAction.java
new file mode 100644
index 00000000000..a2c642a06c4
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/OutdentAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Indents the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class OutdentAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public OutdentAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_OUTDENT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_OUTDENT);
+ setToolTipText(RichTextResources.outdentAction_toolTipText);
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.OUTDENT);
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PasteAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PasteAction.java
new file mode 100644
index 00000000000..7affed86025
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PasteAction.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.ui.util.ClipboardUtil;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.epf.common.utils.NetUtil;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.HTMLTransfer;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Pastes text from the clipboard onto a rich text control.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class PasteAction extends RichTextAction {
+
+ private static final String SOURCE_URL = "SourceURL:"; //$NON-NLS-1$
+
+ private static final String HTM_EXT = ".htm"; //$NON-NLS-1$
+
+ private static final String HTML_EXT = ".html"; //$NON-NLS-1$
+
+ private static final Pattern HREF_REFERENCES = Pattern
+ .compile(
+ "href\\s*=\\s*\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+
+ protected static final Pattern p_image_ref = Pattern
+ .compile(
+ "(<(img|iframe).*?src\\s*=\\s*\")(.*?)(\")", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
+
+ protected static String sourceURLStr = ""; //$NON-NLS-1$
+
+ private Logger logger;
+
+ private static String RESOURCES = "resources"; //$NON-NLS-1$
+
+ /**
+ * Creates a new instance.
+ */
+ public PasteAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_PASTE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_PASTE);
+ setToolTipText(RichTextResources.pasteAction_toolTipText);
+ logger = RichTextPlugin.getDefault().getLogger();
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ copyLinkResources(richText);
+ if (richText instanceof RichTextEditor
+ && ((RichTextEditor) richText).isHTMLTabSelected()) {
+ StyledText styledText = ((RichTextEditor) richText)
+ .getSourceEdit();
+ styledText.paste();
+ } else {
+ richText.executeCommand(RichTextCommand.PASTE, sourceURLStr);
+ }
+ }
+ }
+
+ /**
+ * Copies the link resources.
+ *
+ * @param richText
+ * a rich text control
+ */
+ protected void copyLinkResources(IRichText richText) {
+ try {
+ sourceURLStr = ClipboardUtil.getHTMLSourceURL();
+ Clipboard clipboard = new Clipboard(Display.getCurrent());
+ String html = (String) clipboard.getContents(HTMLTransfer
+ .getInstance());
+ if (html != null && html.length() > 0) {
+ String basePath = richText.getBasePath();
+ URL sourceURL = null;
+ if (sourceURLStr == null || sourceURLStr.length() == 0
+ || sourceURLStr.equals("about:blank")) { //$NON-NLS-1$
+ sourceURL = richText.getCopyURL();
+ } else {
+ sourceURL = new URL(sourceURLStr);
+ }
+
+ Matcher matcher = HREF_REFERENCES.matcher(html);
+ while (matcher.find()) {
+ String href = NetUtil.decodeURL(matcher.group(1));
+ try {
+ URL hrefURL = new URL(sourceURL, href);
+ String scheme = hrefURL.getProtocol();
+ if (scheme != null
+ && scheme
+ .equalsIgnoreCase(NetUtil.FILE_SCHEME)) {
+ String url = hrefURL.getPath();
+ File srcFile = new File(NetUtil.decodeURL(url));
+ File tgtFile = null;
+ File tgtDir = null;
+ if (href.startsWith("#") || sourceURL.sameFile(hrefURL)) { //$NON-NLS-1$
+ continue;
+ } else if (href.startsWith(RESOURCES) || href.startsWith("./" + RESOURCES)) { //$NON-NLS-1$
+ tgtFile = new File(basePath, href);
+ tgtDir = tgtFile.getParentFile();
+ } else {
+ String resPath = getSubdirectoryOfResources(href);
+ tgtFile = new File(basePath + RESOURCES, resPath);
+ tgtDir = tgtFile;
+ }
+ tgtDir.mkdirs();
+ FileUtil.copyFile(srcFile, tgtDir);
+ }
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+
+ matcher = p_image_ref.matcher(html);
+ while (matcher.find()) {
+ String src = NetUtil.decodeURL(matcher.group(3));
+ try {
+ URL srcURL = new URL(sourceURL, src);
+ String scheme = srcURL.getProtocol();
+ if (scheme != null
+ && scheme.equalsIgnoreCase(NetUtil.FILE_SCHEME)) {
+ File srcFile = null;
+ String authority = srcURL.getAuthority();
+ if (authority != null) {
+ srcFile = new File(NetUtil.decodeURL(authority + srcURL.getPath()));
+ } else {
+ srcFile = new File(NetUtil.decodeURL(srcURL.getPath()));
+ }
+ File tgtFile = null;
+ File tgtDir = null;
+ if (src.startsWith(RESOURCES) || src.startsWith("./" + RESOURCES)) { //$NON-NLS-1$
+ tgtFile = new File(basePath, src);
+ tgtDir = tgtFile.getParentFile();
+ } else {
+ String resPath = getSubdirectoryOfResources(src);
+ tgtFile = new File(basePath + RESOURCES, resPath);
+ tgtDir = tgtFile;
+ }
+ tgtDir.mkdirs();
+ FileUtil.copyFile(srcFile, tgtDir);
+ }
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+
+ /**
+ * Parses the given HTML content from the clipboard and returns the source
+ * URL.
+ *
+ * @param htmlContent
+ * the HTML content from the clipboard
+ * @return the source URL or <code>null</code>
+ */
+ protected String getSourceURL(String htmlContent) {
+ String sourceURL = null;
+ int sourceURLIndex = htmlContent.indexOf(SOURCE_URL);
+ if (sourceURLIndex > 0) {
+ sourceURL = htmlContent.substring(sourceURLIndex
+ + SOURCE_URL.length());
+ sourceURL = sourceURL.substring(0, sourceURL
+ .indexOf(FileUtil.LINE_SEP));
+ if (sourceURL.toLowerCase().endsWith(HTM_EXT)
+ || sourceURL.toLowerCase().endsWith(HTML_EXT)) {
+ sourceURL = sourceURL.substring(0, sourceURL.indexOf(FileUtil
+ .getFileName(sourceURL)) - 1);
+ sourceURL = sourceURL.replace('\\', '/');
+ }
+ sourceURL = FileUtil.appendSeparator(sourceURL, "/"); //$NON-NLS-1$
+ }
+ return sourceURL;
+ }
+
+ protected String getSubdirectoryOfResources(String path) {
+ String result = ""; //$NON-NLS-1$
+ int res_idx = path.indexOf(RESOURCES);
+ if (res_idx != -1) {
+ Stack<String> stack = new Stack<String>();
+ File relative = new File(path).getParentFile();
+ while (!relative.getName().equals(RESOURCES)) {
+ stack.push(relative.getName());
+ relative = relative.getParentFile();
+ }
+ while (!stack.isEmpty()) {
+ result = result + (String)stack.pop() + File.separator;
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PastePlainTextAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PastePlainTextAction.java
new file mode 100644
index 00000000000..3f797dc66c3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/PastePlainTextAction.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+package org.eclipse.epf.richtext.actions;
+
+import org.eclipse.epf.common.utils.StrUtil;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.widgets.Display;
+
+public class PastePlainTextAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public PastePlainTextAction(IRichText richText) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ setImageDescriptor(RichTextImages.IMG_DESC_PASTE_PLAIN_TEXT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_PASTE_PLAIN_TEXT);
+ setToolTipText(RichTextResources.pastePlainTextAction_toolTipText);
+ setEnabled(true);
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ // get text from clipboard
+ Clipboard clipboard = new Clipboard(Display.getCurrent());
+ String text = (String) clipboard.getContents(TextTransfer
+ .getInstance());
+ if (text != null && text.length() > 0) {
+ text = StrUtil.convertNewlinesToHTML(text);
+ if (richText instanceof RichTextEditor) {
+ ((RichTextEditor)richText).addHTML(text);
+ } else {
+ richText.executeCommand(RichTextCommand.ADD_HTML, text);
+ }
+ }
+ }
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextAction.java
new file mode 100644
index 00000000000..3dfa39996ae
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextAction.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * The abstract implementation of a rich text action.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public abstract class RichTextAction extends Action {
+
+ protected IRichText richText;
+
+ protected ToolItem toolItem;
+
+ protected Collection<IAction> fMenuActions = new LinkedHashSet<IAction>();
+
+ protected IMenuCreator menuCreator = new IMenuCreator() {
+
+ private MenuManager dropDownMenuMgr;
+
+ /**
+ * Creates the menu manager for the drop-down.
+ */
+ private void createDropDownMenuMgr() {
+ if (dropDownMenuMgr == null) {
+ dropDownMenuMgr = new MenuManager();
+ for (Iterator<IAction> iter = getMenuActions().iterator();iter.hasNext();) {
+ IAction item = iter.next();
+ dropDownMenuMgr.add(item);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.action.IMenuCreator#getMenu(org.eclipse.swt.widgets.Control)
+ */
+ public Menu getMenu(Control parent) {
+ createDropDownMenuMgr();
+ return dropDownMenuMgr.createContextMenu(parent);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.action.IMenuCreator#getMenu(org.eclipse.swt.widgets.Menu)
+ */
+ public Menu getMenu(Menu parent) {
+ createDropDownMenuMgr();
+ Menu menu = new Menu(parent);
+ IContributionItem[] items = dropDownMenuMgr.getItems();
+ for (int i = 0; i < items.length; i++) {
+ IContributionItem item = items[i];
+ IContributionItem newItem = item;
+ if (item instanceof ActionContributionItem) {
+ newItem = new ActionContributionItem(
+ ((ActionContributionItem) item).getAction());
+ }
+ newItem.fill(menu, -1);
+ }
+ return menu;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.action.IMenuCreator#dispose()
+ */
+ public void dispose() {
+ if (dropDownMenuMgr != null) {
+ dropDownMenuMgr.dispose();
+ dropDownMenuMgr = null;
+ }
+ }
+ };
+
+ /**
+ * Creates a new instance.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public RichTextAction(IRichText richText, int style) {
+ super(null, style);
+ this.richText = richText;
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in readonly mode.
+ */
+ public boolean disableInReadOnlyMode() {
+ return true;
+ }
+
+ /**
+ * Returns <code>true</code> if this action should be disabled when the
+ * rich text editor is in source edit mode.
+ */
+ public boolean disableInSourceMode() {
+ return true;
+ }
+
+ public void setToolItem(ToolItem toolItem) {
+ this.toolItem = toolItem;
+ }
+
+ @Override
+ public void run() {
+ execute(richText);
+ }
+
+ @Override
+ public String getId() {
+ return getClass().getCanonicalName();
+ }
+
+ public Collection<IAction> getMenuActions() {
+ return fMenuActions;
+ }
+
+ public void addActionToMenu(IAction action) {
+ fMenuActions.add(action);
+ }
+
+ public abstract void execute(IRichText richText);
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextComboAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextComboAction.java
new file mode 100644
index 00000000000..d000ee26a3f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/RichTextComboAction.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import java.util.Collection;
+
+import org.eclipse.epf.common.ui.actions.CComboContributionItem;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.swt.SWT;
+
+/**
+ * The abstract implementation of a rich text combo action.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public abstract class RichTextComboAction extends CComboContributionItem {
+
+ protected IRichText richText;
+
+ protected String toolTipText;
+
+ protected boolean enabled = true;
+
+ protected boolean notifyListeners = false;
+
+
+ /**
+ * Creates a new instance.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public RichTextComboAction(IRichText richText) {
+ super(SWT.READ_ONLY | SWT.FLAT | SWT.BORDER);
+ this.richText = richText;
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public RichTextComboAction(IRichText richText, int style) {
+ super(SWT.READ_ONLY | SWT.FLAT | SWT.BORDER | style);
+ this.richText = richText;
+ }
+
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ * @param index
+ * the index of the selected item
+ */
+ public abstract void execute(IRichText richText);
+
+ public abstract Collection<String> getInput();
+
+ public void init() {
+ setInput(getInput());
+ setNotifyListeners(true);
+ }
+
+ protected String getCComboSelection() {
+ if (getCCombo() != null) {
+ int index = getSelectionIndex();
+ return getCCombo().getItem(index);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the tool tip for the action.
+ *
+ * @return the tool tip text
+ */
+ public String getToolTipText() {
+ return toolTipText;
+ }
+
+ /**
+ * Sets the tool tip for the action.
+ *
+ * @param toolTipText
+ * the tool tip text
+ */
+ public void setToolTipText(String toolTipText) {
+ this.toolTipText = toolTipText;
+ }
+
+ /**
+ * Returns the enabled status of the action.
+ *
+ * @return <code>true</code> if enabled, <code>false</code> if not
+ */
+ public boolean getEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables the action.
+ *
+ * @param enabled
+ * if <code>true</code>, enable the action. if
+ * <code>false</code>, disable it.
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ @Override
+ protected void performSelectionChanged() {
+ if (notifyListeners) {
+ execute(richText);
+ }
+ }
+
+ public boolean isNotifyListeners() {
+ return notifyListeners;
+ }
+
+ public void setNotifyListeners(boolean notifyListeners) {
+ this.notifyListeners = notifyListeners;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SubscriptAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SubscriptAction.java
new file mode 100644
index 00000000000..4dd42bf05c2
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SubscriptAction.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Toggles the subscript attribute of the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class SubscriptAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public SubscriptAction(final IRichText richText) {
+ super(richText, IAction.AS_CHECK_BOX);
+ setImageDescriptor(RichTextImages.IMG_DESC_SUBSCRIPT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_SUBSCRIPT);
+ setToolTipText(RichTextResources.subscriptAction_toolTipText);
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ setChecked(richText.getSelected().isSubscript());
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.SUBSCRIPT);
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SuperscriptAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SuperscriptAction.java
new file mode 100644
index 00000000000..d5a1a294c3a
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/SuperscriptAction.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Toggles the superscript attribute of the selected text in a rich text
+ * control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class SuperscriptAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public SuperscriptAction(final IRichText richText) {
+ super(richText, IAction.AS_CHECK_BOX);
+ setImageDescriptor(RichTextImages.IMG_DESC_SUPERSCRIPT);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_SUPERSCRIPT);
+ setToolTipText(RichTextResources.superscriptAction_toolTipText);
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ setChecked(richText.getSelected().isSuperscript());
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.SUPERSCRIPT);
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyAction.java
new file mode 100644
index 00000000000..7ad78fb9190
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyAction.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.epf.common.CommonPlugin;
+import org.eclipse.epf.common.IHTMLFormatter;
+import org.eclipse.epf.common.utils.ExtensionHelper;
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextEditor;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Runs JTidy on the HTML
+ *
+ * @author Jeff Hardy
+ * @since 1.2
+ */
+public class TidyAction extends RichTextAction {
+
+ boolean forceOutput = false;
+ boolean makeBare = false;
+ boolean word2000 = false;
+
+ // The HTML source formatter.
+ protected IHTMLFormatter htmlFormatter;
+
+
+
+ /**
+ * Creates a new instance.
+ */
+ public TidyAction(IRichText richText, boolean forceOutput, boolean makeBare, boolean word2000) {
+ super(richText, IAction.AS_PUSH_BUTTON);
+ this.forceOutput = forceOutput;
+ this.makeBare = makeBare;
+ this.word2000 = word2000;
+ setImageDescriptor(RichTextImages.IMG_DESC_TIDY);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_TIDY);
+// htmlFormatter = new HTMLFormatter();
+ htmlFormatter = (IHTMLFormatter) ExtensionHelper.createExtensionForJTidy(
+ CommonPlugin.getDefault().getId(), "htmlFormatter"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void execute(IRichText richText) {
+ // get current text
+ String html;
+ if (richText instanceof RichTextEditor) {
+ html = ((RichTextEditor)richText).getText();
+ } else {
+ html = richText.getText();
+ }
+ // call JTidy with the options
+ try {
+ html = htmlFormatter.formatHTML(html, false, forceOutput, makeBare, word2000);
+ } catch (UnsupportedEncodingException e) {
+ RichTextPlugin.getDefault().getLogger().logError(e);
+ }
+ // set text
+ if (richText instanceof RichTextEditor) {
+ ((RichTextEditor)richText).setText(html);
+ } else {
+ richText.setText(html);
+ }
+ richText.checkModify();
+
+ }
+
+ @Override
+ public boolean disableInSourceMode() {
+ return false;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyActionGroup.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyActionGroup.java
new file mode 100644
index 00000000000..0624bbdf76f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/TidyActionGroup.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Runs JTidy on the HTML
+ *
+ * @author Jeff Hardy
+ * @since 1.2
+ */
+public class TidyActionGroup extends RichTextAction {
+
+ TidyAction tidyActionDefault;
+ TidyAction tidyActionCleanMS;
+ TidyAction tidyActionCleanWord2000;
+
+ public TidyActionGroup(IRichText richText) {
+ super(richText, IAction.AS_DROP_DOWN_MENU);
+ // TODO need image
+ setImageDescriptor(RichTextImages.IMG_DESC_TIDY);
+ // TODO need image
+// setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_PASTE);
+ setToolTipText(RichTextResources.tidy_clean_text);
+
+ createActions();
+ setMenuCreator(menuCreator);
+ }
+
+ private void createActions() {
+ tidyActionDefault = new TidyAction(richText, true, false, false);
+ tidyActionDefault.setText(RichTextResources.tidy_clean_text);
+ tidyActionDefault.setToolTipText(RichTextResources.tidy_clean_toolTipText);
+ tidyActionCleanMS = new TidyAction(richText, true, true, false);
+ tidyActionCleanMS.setText(RichTextResources.tidy_cleaner_text);
+ tidyActionCleanMS.setToolTipText(RichTextResources.tidy_cleaner_toolTipText);
+ tidyActionCleanWord2000 = new TidyAction(richText, true, true, true);
+ tidyActionCleanWord2000.setText(RichTextResources.tidy_cleanest_text);
+ tidyActionCleanWord2000.setToolTipText(RichTextResources.tidy_cleanest_toolTipText);
+ addActionToMenu(tidyActionDefault);
+ addActionToMenu(tidyActionCleanMS);
+ addActionToMenu(tidyActionCleanWord2000);
+ }
+
+ @Override
+ public void execute(IRichText richText) {
+ // TODO Auto-generated method stub
+
+ // call normal clean
+ tidyActionDefault.execute(richText);
+
+ }
+
+ @Override
+ public boolean disableInSourceMode() {
+ return false;
+ }
+
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/UnderlineAction.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/UnderlineAction.java
new file mode 100644
index 00000000000..27825aca080
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/UnderlineAction.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.actions;
+
+import org.eclipse.epf.richtext.IRichText;
+import org.eclipse.epf.richtext.RichTextCommand;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Toggles the underline attribute of the selected text in a rich text control.
+ *
+ * @author Kelvin Low
+ * @author Jeff Hardy
+ * @since 1.0
+ */
+public class UnderlineAction extends RichTextAction {
+
+ /**
+ * Creates a new instance.
+ */
+ public UnderlineAction(final IRichText richText) {
+ super(richText, IAction.AS_CHECK_BOX);
+ setImageDescriptor(RichTextImages.IMG_DESC_UNDERLINE);
+ setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_UNDERLINE);
+ setToolTipText(RichTextResources.underlineAction_toolTipText);
+ // add listener
+ richText.addListener(SWT.SELECTED, new Listener() {
+ public void handleEvent(Event event) {
+ setChecked(richText.getSelected().isUnderLine());
+ }
+ });
+ }
+
+ /**
+ * Executes the action.
+ *
+ * @param richText
+ * a rich text control
+ */
+ public void execute(IRichText richText) {
+ if (richText != null) {
+ richText.executeCommand(RichTextCommand.UNDERLINE);
+ }
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/package.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/package.html
new file mode 100644
index 00000000000..8e923674e79
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/actions/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides editing actions for the rich text control and editor.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddCodeDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddCodeDialog.java
new file mode 100644
index 00000000000..982efb716c3
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddCodeDialog.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Licensed Materials - Property of IBM
+* (c) Copyright IBM Corporation 2007,2011. All Rights Reserved.
+*
+* Note to U.S. Government Users Restricted Rights:
+* Use, duplication or disclosure restricted by GSA ADP Schedule
+* Contract with IBM Corp.
+*******************************************************************************/
+
+package org.eclipse.epf.richtext.dialogs;
+
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class AddCodeDialog extends BaseDialog {
+ private Text html;
+ private String htmlStr;
+
+ public AddCodeDialog(Shell parent) {
+ super(parent);
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ Label label = new Label(composite, SWT.NONE);
+ label.setText(RichTextResources.addCodeDialog_Msg);
+ {
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+ }
+
+ html = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ {
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = 2;
+ gd.widthHint = 300;
+ gd.heightHint = 200;
+ html.setLayoutData(gd);
+ }
+ html.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ okButton.setEnabled(html.getText().trim().length() > 0);
+ }
+ });
+
+ super.getShell().setText(RichTextResources.addCodeDialog_title);
+
+ return composite;
+ }
+
+ protected void createButtonsForButtonBar(Composite parent) {
+ super.createButtonsForButtonBar(parent);
+ okButton.setEnabled(false);
+ }
+
+ protected void okPressed() {
+ //add the extra "<br/>" to avoid Jtidy problem
+ String br = "<br/>"; //$NON-NLS-1$
+ String customHtml = html.getText().trim();
+ htmlStr = br + customHtml;
+
+ super.okPressed();
+ }
+
+ public String getCode() {
+ return htmlStr;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddImageDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddImageDialog.java
new file mode 100644
index 00000000000..2d2ec28b782
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddImageDialog.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.dialogs;
+
+import java.io.File;
+
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.html.Image;
+import org.eclipse.swt.SWT;
+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.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Prompts the user to specify the image that will be used to create a HTML
+ * &lt;image&gt; tag in the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddImageDialog extends BaseDialog {
+
+ protected Image image = new Image();
+
+ protected Text urlText;
+
+ protected Button browseButton;
+
+ protected SelectionAdapter browseSelectionAdapter = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ FileDialog dialog = new FileDialog(Display.getCurrent()
+ .getActiveShell(), SWT.OPEN);
+ dialog
+ .setFilterExtensions(new String[] {
+ "*.gif", "*.jpg", "*.bmp" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ String imageFile = dialog.open();
+ if (imageFile != null && imageFile.length() > 0) {
+ File file = new File(imageFile);
+ try {
+ String url = file.toURL().toExternalForm();
+ urlText.setText(url);
+ } catch (Exception e) {
+ logger.logError(e);
+ }
+ }
+ }
+ };
+
+ protected ModifyListener urlTextListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (okButton != null) {
+ okButton.setEnabled(urlText.getText().trim().length() > 0);
+ }
+ }
+ };
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent shell
+ */
+ public AddImageDialog(Shell parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ GridLayout layout = (GridLayout) composite.getLayout();
+ layout.numColumns = 3;
+
+ Label urlLabel = new Label(composite, SWT.NONE);
+ urlLabel.setText(RichTextResources.urlLabel_text);
+ urlText = new Text(composite, SWT.BORDER);
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.widthHint = 300;
+ urlText.setLayoutData(gridData);
+ urlText.addModifyListener(urlTextListener);
+
+ browseButton = new Button(composite, SWT.NONE);
+ browseButton.setText(RichTextResources.browseButton_text);
+ browseButton.addSelectionListener(browseSelectionAdapter);
+
+ super.getShell().setText(RichTextResources.addImageDialog_title);
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ super.createButtonsForButtonBar(parent);
+ okButton.setEnabled(false);
+ }
+
+ @Override
+ protected void okPressed() {
+ String url = urlText.getText();
+ if (url != null && url.length() > 0) {
+ image.setURL(url);
+ }
+ super.okPressed();
+ }
+
+ /**
+ * Gets the user specified image.
+ *
+ * @return an <code>Image</code> object
+ */
+ public Image getImage() {
+ return image;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddLinkDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddLinkDialog.java
new file mode 100644
index 00000000000..5a78077f933
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddLinkDialog.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.dialogs;
+
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.html.Link;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Prompts the user to specify the file that will be used to create a HTML
+ * &lt;a&gt; tag in the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddLinkDialog extends BaseDialog {
+
+ protected Link link = new Link();
+
+ protected Text urlText;
+
+ protected String basePath;
+
+ protected Composite composite;
+
+ protected Label urlLabel;
+
+ protected Text urlDisplayNameText;
+
+ protected Label urlDisplayNameLabel;
+
+ protected ModifyListener urlTextModifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (okButton != null) {
+ okButton.setEnabled(urlText.getText().trim().length() > 0);
+ }
+ }
+ };
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent shell
+ */
+ public AddLinkDialog(Shell parent, String basePath) {
+ super(parent);
+ this.basePath = basePath;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ composite = (Composite) super.createDialogArea(parent);
+
+ urlLabel = new Label(composite, SWT.NONE);
+ urlLabel.setText(RichTextResources.urlLabel_text);
+ urlText = new Text(composite, SWT.BORDER);
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.widthHint = 300;
+ urlText.setLayoutData(gridData);
+ urlText.addModifyListener(urlTextModifyListener);
+
+ urlDisplayNameLabel = new Label(composite, SWT.NONE);
+ urlDisplayNameLabel.setText(RichTextResources.urlDisplayNameLabel_text);
+ urlDisplayNameText = new Text(composite, SWT.BORDER);
+ GridData gridData2 = new GridData(GridData.FILL_HORIZONTAL);
+ gridData2.widthHint = 300;
+ urlDisplayNameText.setLayoutData(gridData2);
+
+ super.getShell().setText(RichTextResources.addLinkDialog_title);
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ super.createButtonsForButtonBar(parent);
+ okButton.setEnabled(false);
+ }
+
+ @Override
+ protected void okPressed() {
+ String url = urlText.getText();
+ if (url != null && url.length() > 0) {
+ link.setURL(url);
+ link.setName(urlDisplayNameText.getText());
+ }
+ super.okPressed();
+ }
+
+ /**
+ * Gets the user specified link.
+ *
+ * @return an <code>Link</code> object
+ */
+ public Link getLink() {
+ return link;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddTableDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddTableDialog.java
new file mode 100644
index 00000000000..27832d5527b
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/AddTableDialog.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.dialogs;
+
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.html.Table;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Prompts the user to specify the attributes that will be used to create a HTML
+ * &lt;table&gt; tag in the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class AddTableDialog extends BaseDialog {
+
+ private static final int DEFAULT_ROWS = 2;
+
+ private static final int DEFAULT_COLUMNS = 2;
+
+ private static final String DEFAULT_WIDTH = "85%"; //$NON-NLS-1$
+
+ private static final String[] TABLE_STYLE_LABELS = {
+ RichTextResources.tableHeaderNone_text,
+ RichTextResources.tableHeaderCols_text,
+ RichTextResources.tableHeaderRows_text,
+ RichTextResources.tableHeaderBoth_text, };
+
+ private Table table = new Table();
+
+ private Text rowsText;
+
+ private Text colsText;
+
+ private Text widthText;
+
+ private Combo tableTypeCombo;
+
+ private Text summaryText;
+
+ private Text captionText;
+
+ private ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(ModifyEvent event) {
+ if (okButton != null) {
+ try {
+ int rows = Integer.parseInt(rowsText.getText().trim());
+ int cols = Integer.parseInt(colsText.getText().trim());
+ String width = widthText.getText().trim();
+ okButton.setEnabled(rows > 0 && cols > 0
+ && width.length() > 0);
+ } catch (Exception e) {
+ okButton.setEnabled(false);
+ }
+ }
+ }
+ };
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent shell
+ */
+ public AddTableDialog(Shell parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ Label rowsLabel = new Label(composite, SWT.NONE);
+ rowsLabel.setText(RichTextResources.rowsLabel_text);
+
+ rowsText = new Text(composite, SWT.BORDER);
+ rowsText.setTextLimit(2);
+ rowsText.setText("" + DEFAULT_ROWS); //$NON-NLS-1$
+ {
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL);
+ rowsText.setLayoutData(gridData);
+ }
+ rowsText.addModifyListener(modifyListener);
+
+ Label colsLabel = new Label(composite, SWT.NONE);
+ colsLabel.setText(RichTextResources.columnsLabel_text);
+
+ colsText = new Text(composite, SWT.BORDER);
+ colsText.setTextLimit(2);
+ colsText.setText("" + DEFAULT_COLUMNS); //$NON-NLS-1$
+ {
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL);
+ colsText.setLayoutData(gridData);
+ }
+ colsText.addModifyListener(modifyListener);
+
+ Label widthLabel = new Label(composite, SWT.NONE);
+ widthLabel.setText(RichTextResources.widthLabel_text);
+
+ widthText = new Text(composite, SWT.BORDER);
+ widthText.setText("" + DEFAULT_WIDTH); //$NON-NLS-1$
+ {
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL);
+ widthText.setLayoutData(gridData);
+ }
+ widthText.addModifyListener(modifyListener);
+
+ Label headerTypeLabel = new Label(composite, SWT.NONE);
+ headerTypeLabel.setText(RichTextResources.tableStyleLabel_text);
+
+ tableTypeCombo = new Combo(composite, SWT.BORDER | SWT.READ_ONLY);
+ tableTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ tableTypeCombo.setItems(TABLE_STYLE_LABELS);
+ tableTypeCombo.setText(TABLE_STYLE_LABELS[0]);
+
+ Label summaryLabel = new Label(composite, SWT.NONE);
+ summaryLabel.setText(RichTextResources.summaryLabel_text);
+ summaryText = new Text(composite, SWT.BORDER);
+ {
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL);
+ summaryText.setLayoutData(gridData);
+ }
+
+ Label captionLabel = new Label(composite, SWT.NONE);
+ captionLabel.setText(RichTextResources.captionLabel_text);
+ captionText = new Text(composite, SWT.BORDER);
+ {
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL
+ | GridData.GRAB_HORIZONTAL);
+ captionText.setLayoutData(gridData);
+ }
+
+ super.getShell().setText(RichTextResources.addTableDialog_title);
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ super.createButtonsForButtonBar(parent);
+ }
+
+ @Override
+ protected void okPressed() {
+ String rowsValue = rowsText.getText();
+ if (rowsValue != null && rowsValue.length() > 0) {
+ try {
+ int rows = Integer.parseInt(rowsValue);
+ table.setRows(rows);
+ } catch (Exception e) {
+ table.setRows(DEFAULT_ROWS);
+ }
+ }
+
+ String colsValue = colsText.getText();
+ if (colsValue != null && colsValue.length() > 0) {
+ try {
+ int cols = Integer.parseInt(colsValue);
+ table.setColumns(cols);
+ } catch (Exception e) {
+ table.setColumns(DEFAULT_COLUMNS);
+ }
+ }
+
+ String widthValue = widthText.getText();
+ if (widthValue != null && widthValue.length() > 0) {
+ table.setWidth(widthValue);
+ } else {
+ table.setWidth(DEFAULT_WIDTH);
+ }
+
+ table.setSummary(summaryText.getText().trim());
+ table.setCaption(captionText.getText().trim());
+ table.setTableHeaders(tableTypeCombo.getSelectionIndex());
+
+ super.okPressed();
+ }
+
+ /**
+ * Gets the user specified table.
+ *
+ * @return an <code>Table</code> object
+ */
+ public Table getTable() {
+ return table;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/BaseDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/BaseDialog.java
new file mode 100644
index 00000000000..ad92d9f2255
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/BaseDialog.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.dialogs;
+
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * The base class for all dialogs used by the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class BaseDialog extends Dialog {
+
+ // A logger for logging runtime warnings and errors.
+ protected Logger logger;
+
+ // The OK button.
+ protected Button okButton;
+
+ // The Cancel button.
+ protected Button cancelButton;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent shell
+ */
+ public BaseDialog(Shell parent) {
+ super(parent);
+ logger = RichTextPlugin.getDefault().getLogger();
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ GridLayout layout = (GridLayout) composite.getLayout();
+ layout.marginWidth = 10;
+ layout.marginHeight = 10;
+ layout.numColumns = 2;
+ GridData gridData = (GridData) composite.getLayoutData();
+ gridData.verticalIndent = 10;
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ // Create the OK button.
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+ true);
+
+ // Create the Cancel button.
+ createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+
+ // Set help context for the OK button.
+ okButton = super.getButton(IDialogConstants.OK_ID);
+
+ // Set help context for the Cancel button.
+ cancelButton = super.getButton(IDialogConstants.CANCEL_ID);
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/FindReplaceDialog.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/FindReplaceDialog.java
new file mode 100644
index 00000000000..c03c6d75e3e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/FindReplaceDialog.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.dialogs;
+
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.epf.richtext.actions.FindReplaceAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Prompts the user to specify the search and replace strings and options.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class FindReplaceDialog extends BaseDialog {
+
+ private FindReplaceAction findReplaceAction;
+
+ private boolean findOnly;
+
+ private Text findText;
+
+ private Text replaceText;
+
+ private Button searchForwardRadioButton;
+
+ private Button searchBackwardRadioButton;
+
+ private Button caseSensitiveCheckbox;
+
+ private Button wholeWordCheckbox;
+
+ private Button findButton;
+
+ private Button replaceButton;
+
+ private Button replaceFindButton;
+
+ private Button replaceAllButton;
+
+ private Label statusLabel;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param parent
+ * the parent shell
+ * @param findReplaceAction
+ * the Find and Replace action
+ * @param findOnly
+ * if <code>true</code>, disable the replace and replace all
+ * functionalities
+ */
+ public FindReplaceDialog(Shell parent, FindReplaceAction findReplaceAction,
+ boolean findOnly) {
+ super(parent);
+ setShellStyle(SWT.DIALOG_TRIM | SWT.MODELESS | getDefaultOrientation());
+ setBlockOnOpen(false);
+ this.findReplaceAction = findReplaceAction;
+ this.findOnly = findOnly;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ GridLayout layout = (GridLayout) composite.getLayout();
+ layout.numColumns = 1;
+
+ Composite textComposite = new Composite(composite, SWT.NONE);
+ textComposite.setLayout(new GridLayout(2, false));
+ textComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Label findLabel = new Label(textComposite, SWT.NONE);
+ findLabel.setText(RichTextResources.findLabel_text);
+ findText = new Text(textComposite, SWT.BORDER);
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.widthHint = 200;
+ findText.setLayoutData(gridData);
+ findText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (findButton != null) {
+ findButton
+ .setEnabled(findText.getText().trim().length() > 0);
+ }
+ if (replaceAllButton != null && !findOnly) {
+ replaceAllButton.setEnabled(findText.getText().trim()
+ .length() > 0);
+ }
+ }
+ });
+
+ Label replaceLabel = new Label(textComposite, SWT.NONE);
+ replaceLabel.setText(RichTextResources.replaceLabel_text);
+ replaceText = new Text(textComposite, SWT.BORDER);
+ replaceText.setLayoutData(gridData);
+ if (findOnly) {
+ replaceText.setEnabled(false);
+ } else {
+ replaceText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if (replaceButton != null) {
+ replaceButton.setEnabled(findReplaceAction
+ .getFoundMatch());
+ }
+ if (replaceFindButton != null) {
+ replaceFindButton.setEnabled(findReplaceAction
+ .getFoundMatch());
+ }
+ }
+ });
+ }
+
+ Composite optionsComposite = new Composite(composite, SWT.NONE);
+ optionsComposite.setLayout(new GridLayout(2, true));
+ optionsComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Group directionGroup = new Group(optionsComposite, SWT.NONE);
+ directionGroup.setText(RichTextResources.directionGroup_text);
+ directionGroup.setLayout(new GridLayout(1, false));
+ directionGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ searchForwardRadioButton = new Button(directionGroup, SWT.RADIO);
+ searchForwardRadioButton
+ .setText(RichTextResources.forwardRadioButton_text);
+ searchForwardRadioButton.setSelection(true);
+ searchBackwardRadioButton = new Button(directionGroup, SWT.RADIO);
+ searchBackwardRadioButton
+ .setText(RichTextResources.backwardRadioButton_text);
+
+ Group optionsGroup = new Group(optionsComposite, SWT.NONE);
+ optionsGroup.setText(RichTextResources.optionsGroup_text);
+ optionsGroup.setLayout(new GridLayout(1, false));
+ optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ caseSensitiveCheckbox = new Button(optionsGroup, SWT.CHECK);
+ caseSensitiveCheckbox
+ .setText(RichTextResources.caseSensitiveCheckbox_text);
+ wholeWordCheckbox = new Button(optionsGroup, SWT.CHECK);
+ wholeWordCheckbox.setText(RichTextResources.wholeWordCheckbox_text);
+
+ statusLabel = new Label(composite, SWT.NONE);
+ statusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ super.getShell().setText(RichTextResources.findReplaceDialog_title);
+
+ return composite;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.CLIENT_ID + 1,
+ RichTextResources.findButton_text, true);
+ findButton = super.getButton(IDialogConstants.CLIENT_ID + 1);
+ findButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent event) {
+ findReplaceAction.run(FindReplaceAction.FIND_TEXT,
+ getFindText(), getReplaceText(), getMatchDirection(),
+ getMatchOptions());
+ if (!findOnly) {
+ replaceButton.setEnabled(findReplaceAction.getFoundMatch());
+ replaceFindButton.setEnabled(findReplaceAction
+ .getFoundMatch());
+ }
+ if (findReplaceAction.getFoundMatch()) {
+ statusLabel.setText(""); //$NON-NLS-1$
+ } else {
+ statusLabel
+ .setText(RichTextResources.FindReplace_Status_noMatch_label);
+ }
+ findButton.setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+
+ createButton(parent, IDialogConstants.CLIENT_ID + 2,
+ RichTextResources.replaceButton_text, false);
+ replaceButton = super.getButton(IDialogConstants.CLIENT_ID + 2);
+ if (!findOnly) {
+ replaceButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent event) {
+ findReplaceAction.run(FindReplaceAction.REPLACE_TEXT,
+ getFindText(), getReplaceText(),
+ getMatchDirection(), getMatchOptions());
+ replaceButton.setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ createButton(parent, IDialogConstants.CLIENT_ID + 3,
+ RichTextResources.replaceFindButton_text, false);
+ replaceFindButton = super.getButton(IDialogConstants.CLIENT_ID + 3);
+ if (!findOnly) {
+ replaceFindButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent event) {
+ findReplaceAction.run(FindReplaceAction.REPLACE_FIND_TEXT,
+ getFindText(), getReplaceText(),
+ getMatchDirection(), getMatchOptions());
+ replaceButton.setEnabled(findReplaceAction.getFoundMatch());
+ replaceFindButton.setEnabled(findReplaceAction
+ .getFoundMatch());
+ replaceFindButton.setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ createButton(parent, IDialogConstants.CLIENT_ID + 4,
+ RichTextResources.replaceallButton_text, false);
+ replaceAllButton = super.getButton(IDialogConstants.CLIENT_ID + 4);
+ if (!findOnly) {
+ replaceAllButton.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent event) {
+ findReplaceAction.run(FindReplaceAction.REPLACE_ALL_TEXT,
+ getFindText(), getReplaceText(),
+ getMatchDirection(), getMatchOptions());
+ replaceButton.setEnabled(false);
+ replaceFindButton.setEnabled(false);
+ replaceAllButton.setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ // Create the Cancel button.
+ createButton(parent, IDialogConstants.CANCEL_ID,
+ IDialogConstants.CANCEL_LABEL, false);
+ cancelButton = super.getButton(IDialogConstants.CANCEL_ID);
+
+ findButton.setEnabled(false);
+ replaceButton.setEnabled(false);
+ replaceFindButton.setEnabled(false);
+ replaceAllButton.setEnabled(false);
+ }
+
+ /**
+ * Gets the user specified find text.
+ *
+ * @return the find text
+ */
+ public String getFindText() {
+ return findText.getText();
+ }
+
+ /**
+ * Gets the user specified replace text.
+ *
+ * @return the replace text
+ */
+ public String getReplaceText() {
+ return replaceText.getText();
+ }
+
+ /**
+ * Gets the text match direction.
+ *
+ * @return <code>FIND_FORWARD</code> or <code>FIND_BACKWARD</code>
+ */
+ public int getMatchDirection() {
+ return searchForwardRadioButton.getSelection() ? FindReplaceAction.FORWARD_MATCH
+ : FindReplaceAction.BACKWARD_MATCH;
+ }
+
+ /**
+ * Gets the text match options.
+ *
+ * @return the text match options
+ */
+ public int getMatchOptions() {
+ int options = 0;
+ if (wholeWordCheckbox.getSelection() == true) {
+ options |= FindReplaceAction.WHOLE_WORD_MATCH;
+ }
+ if (caseSensitiveCheckbox.getSelection() == true) {
+ options |= FindReplaceAction.CASE_SENSITIVE_MATCH;
+ }
+ return options;
+ }
+
+ /**
+ * Checks the find only option.
+ *
+ * @return <code>true</code> if find only option is enabled
+ */
+ public boolean isFindOnly() {
+ return findOnly;
+ }
+
+ /**
+ * Sets the find only option.
+ *
+ * @param findOnly,
+ * if <code>true</code>, enable the find only option
+ */
+ public void setFindOnly(boolean findOnly) {
+ this.findOnly = findOnly;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/package.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/package.html
new file mode 100644
index 00000000000..f2a46edb8e6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/dialogs/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides editing dialogs for the rich text control and editor.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/BlockTag.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/BlockTag.java
new file mode 100644
index 00000000000..57c8433a6a6
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/BlockTag.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.epf.richtext.RichTextResources;
+
+/**
+ * Models a HTML block tag.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class BlockTag {
+
+ // The user friendly names.
+ private static final String NAME_PARAGRAPH = RichTextResources.blockTag_paragraph;
+
+ private static final String NAME_HEADING_1 = RichTextResources.blockTag_heading1;
+
+ private static final String NAME_HEADING_2 = RichTextResources.blockTag_heading2;
+
+ private static final String NAME_HEADING_3 = RichTextResources.blockTag_heading3;
+
+ private static final String NAME_HEADING_4 = RichTextResources.blockTag_heading4;
+
+ private static final String NAME_HEADING_5 = RichTextResources.blockTag_heading5;
+
+ private static final String NAME_HEADING_6 = RichTextResources.blockTag_heading6;
+
+ private static final String NAME_ADDRESS = RichTextResources.blockTag_address;
+
+ private static final String NAME_PREFORMATTED_TEXT = RichTextResources.blockTag_preformattedText;
+
+ // The internal values.
+ private static final String VALUE_PARAGRAPH = "<p>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_1 = "<h1>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_2 = "<h2>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_3 = "<h3>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_4 = "<h4>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_5 = "<h5>"; //$NON-NLS-1$
+
+ private static final String VALUE_HEADING_6 = "<h6>"; //$NON-NLS-1$
+
+ private static final String VALUE_ADDRESS = "<address>"; //$NON-NLS-1$
+
+ private static final String VALUE_PREFORMATTED_TEXT = "<pre>"; //$NON-NLS-1$
+
+ /**
+ * The &lt;p&gt; tag.
+ */
+ static public final BlockTag PARAGRAPH = new BlockTag(NAME_PARAGRAPH,
+ VALUE_PARAGRAPH);
+
+ /**
+ * &lt;h1&gt; tag.
+ */
+ static public final BlockTag HEADING_1 = new BlockTag(NAME_HEADING_1,
+ VALUE_HEADING_1);
+
+ /**
+ * &lt;h2&gt; tag.
+ */
+ static public final BlockTag HEADING_2 = new BlockTag(NAME_HEADING_2,
+ VALUE_HEADING_2);
+
+ /**
+ * &lt;h3&gt; tag.
+ */
+ static public final BlockTag HEADING_3 = new BlockTag(NAME_HEADING_3,
+ VALUE_HEADING_3);
+
+ /**
+ * &lt;h4&gt; tag.
+ */
+ static public final BlockTag HEADING_4 = new BlockTag(NAME_HEADING_4,
+ VALUE_HEADING_4);
+
+ /**
+ * &lt;h5&gt; tag.
+ */
+ static public final BlockTag HEADING_5 = new BlockTag(NAME_HEADING_5,
+ VALUE_HEADING_5);
+
+ /**
+ * &lt;h6&gt; tag.
+ */
+ static public final BlockTag HEADING_6 = new BlockTag(NAME_HEADING_6,
+ VALUE_HEADING_6);
+
+ /**
+ * &lt;address&gt; tag.
+ */
+ static public final BlockTag ADDRESS = new BlockTag(NAME_ADDRESS,
+ VALUE_ADDRESS);
+
+ /**
+ * &lt;pre&gt; tag.
+ */
+ static public final BlockTag PREFORMATTED_TEXT = new BlockTag(
+ NAME_PREFORMATTED_TEXT, VALUE_PREFORMATTED_TEXT);
+
+ // A list of <code>BlockTag</code> objects.
+ static private final List<BlockTag> BLOCK_TAGS = new ArrayList<BlockTag>();
+ static {
+ BLOCK_TAGS.add(PARAGRAPH);
+ BLOCK_TAGS.add(HEADING_1);
+ BLOCK_TAGS.add(HEADING_2);
+ BLOCK_TAGS.add(HEADING_3);
+ BLOCK_TAGS.add(HEADING_4);
+ BLOCK_TAGS.add(HEADING_5);
+ BLOCK_TAGS.add(HEADING_6);
+ BLOCK_TAGS.add(ADDRESS);
+ BLOCK_TAGS.add(PREFORMATTED_TEXT);
+ }
+
+ // The block tag name.
+ private String name;
+
+ // The block tag value.
+ private String value;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param name
+ * the block tag name
+ * @param value
+ * the block tag value
+ */
+ public BlockTag(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Gets the block tag name.
+ *
+ * @return the block tag name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the block tag value.
+ *
+ * @return the block tag value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Gets the <code>BlockTag</code> object that is mapped to the given
+ * index.
+ *
+ * @param index
+ * an index into the <code>BlockTag</code> list
+ * @return a <code>BlockTag</code> object
+ */
+ public static BlockTag getBlockTag(int index) {
+ BlockTag result = (BlockTag) BLOCK_TAGS.get(index);
+ if (result != null) {
+ return result;
+ }
+ return PARAGRAPH;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontName.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontName.java
new file mode 100644
index 00000000000..48714736f1e
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontName.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.epf.richtext.RichTextResources;
+
+/**
+ * Models a HTML font name.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class FontName {
+
+ // The user friendly names.
+ private static final String NAME_DEFAULT = RichTextResources.fontName_default;
+
+ private static final String NAME_ARIAL = RichTextResources.fontName_arial;
+
+ private static final String NAME_COURIER_NEW = RichTextResources.fontName_courierNew;
+
+ private static final String NAME_TIMES_NEW_ROMAN = RichTextResources.fontName_timesNewRoman;
+
+ private static final String NAME_VERDANA = RichTextResources.fontName_verdana;
+
+ // The internal values.
+ private static final String VALUE_DEFAULT = ""; //$NON-NLS-1$
+
+ private static final String VALUE_ARIAL = "Arial, Helvetica, sans-serif"; //$NON-NLS-1$
+
+ private static final String VALUE_COURIER_NEW = "Courier New, Courier, mono"; //$NON-NLS-1$
+
+ private static final String VALUE_TIMES_NEW_ROMAN = "Times New Roman, Times, serif"; //$NON-NLS-1$
+
+ private static final String VALUE_VERDANA = "Verdana, Arial, Helvetica, sans-serif"; //$NON-NLS-1$
+
+ /**
+ * Default font.
+ */
+ static public final FontName DEFAULT = new FontName(NAME_DEFAULT,
+ VALUE_DEFAULT);
+
+ /**
+ * Arial font.
+ */
+ static public final FontName ARIAL = new FontName(NAME_ARIAL, VALUE_ARIAL);
+
+ /**
+ * Courier New font.
+ */
+ static public final FontName COURIER_NEW = new FontName(NAME_COURIER_NEW,
+ VALUE_COURIER_NEW);
+
+ /**
+ * Times New Roman font.
+ */
+ static public final FontName TIMES_NEW_ROMAN = new FontName(
+ NAME_TIMES_NEW_ROMAN, VALUE_TIMES_NEW_ROMAN);
+
+ /**
+ * Verdana font.
+ */
+ static public final FontName VERDANA = new FontName(NAME_VERDANA,
+ VALUE_VERDANA);
+
+ // A list of <code>FontName</code> objects.
+ static private final List<FontName> FONT_NAMES = new ArrayList<FontName>();
+ static {
+ FONT_NAMES.add(DEFAULT);
+ FONT_NAMES.add(ARIAL);
+ FONT_NAMES.add(COURIER_NEW);
+ FONT_NAMES.add(TIMES_NEW_ROMAN);
+ FONT_NAMES.add(VERDANA);
+ }
+
+ // The font name.
+ private String name;
+
+ // The font value.
+ private String value;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param name
+ * the font name
+ * @param value
+ * the font value
+ */
+ public FontName(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Gets the font name.
+ *
+ * @return the font name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the font value.
+ *
+ * @return the font value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Gets the <code>FontName</code> object that is mapped to the given
+ * index.
+ *
+ * @param index
+ * an index into the <code>FontName</code> list
+ * @return a <code>FontName</code> object
+ */
+ public static FontName getFontName(int index) {
+ FontName result = (FontName) FONT_NAMES.get(index);
+ if (result != null) {
+ return result;
+ }
+ return DEFAULT;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontStyle.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontStyle.java
new file mode 100644
index 00000000000..55211d74cbd
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/FontStyle.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.epf.richtext.RichTextResources;
+
+/**
+ * Models a HTML font style.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class FontStyle {
+
+ // The user friendly names.
+ private static final String NAME_NORMAL = RichTextResources.fontStyle_normal;
+
+ private static final String NAME_SECTION_HEADING = RichTextResources.fontStyle_sectionHeading;
+
+ private static final String NAME_SUBSECTION_HEADING = RichTextResources.fontStyle_subsectionHeading;
+
+ private static final String NAME_SUB_SUBSECTION_HEADING = RichTextResources.fontStyle_subSubsectionHeading;
+
+ private static final String NAME_QUOTE = RichTextResources.fontStyle_quote;
+
+ private static final String NAME_CODE_SAMPLE = RichTextResources.fontStyle_codeSample;
+
+ // The internal values.
+ private static final String VALUE_NORMAL = "<p>"; //$NON-NLS-1$
+
+ private static final String VALUE_SECTION_HEADING = "<h3>"; //$NON-NLS-1$
+
+ private static final String VALUE_SUBSECTION_HEADING = "<h4>"; //$NON-NLS-1$
+
+ private static final String VALUE_SUB_SUBSECTION_HEADING = "<h5>"; //$NON-NLS-1$
+
+ private static final String VALUE_QUOTE = "<quote>"; //$NON-NLS-1$
+
+ private static final String VALUE_CODE_SAMPLE = "<code>"; //$NON-NLS-1$
+
+ /**
+ * Font style for normal text.
+ */
+ static public final FontStyle NORMAL = new FontStyle(NAME_NORMAL,
+ VALUE_NORMAL);
+
+ /**
+ * Font style for section heading.
+ */
+ static public final FontStyle SECTION_HEADING = new FontStyle(
+ NAME_SECTION_HEADING, VALUE_SECTION_HEADING);
+
+ /**
+ * Font style for sub section heading.
+ */
+ static public final FontStyle SUBSECTION_HEADING = new FontStyle(
+ NAME_SUBSECTION_HEADING, VALUE_SUBSECTION_HEADING);
+ /**
+ * Font style for sub sub section heading.
+ */
+ static public final FontStyle SUB_SUBSECTION_HEADING = new FontStyle(
+ NAME_SUB_SUBSECTION_HEADING, VALUE_SUB_SUBSECTION_HEADING);
+
+ /**
+ * Font style for quotations.
+ */
+ static public final FontStyle QUOTE = new FontStyle(NAME_QUOTE, VALUE_QUOTE);
+
+ /**
+ * Font style for displaying program codes.
+ */
+ static public final FontStyle CODE_SAMPLE = new FontStyle(NAME_CODE_SAMPLE,
+ VALUE_CODE_SAMPLE);
+
+ // A list of <code>FontStyle</code> objects.
+ static private final List<FontStyle> FONT_STYLES = new ArrayList<FontStyle>();
+ static {
+ FONT_STYLES.add(NORMAL);
+ FONT_STYLES.add(SECTION_HEADING);
+ FONT_STYLES.add(SUBSECTION_HEADING);
+ FONT_STYLES.add(SUB_SUBSECTION_HEADING);
+ FONT_STYLES.add(QUOTE);
+ FONT_STYLES.add(CODE_SAMPLE);
+ }
+
+ // The font style name.
+ private String name;
+
+ // The font style value.
+ private String value;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param name
+ * the font style name
+ * @param value
+ * the font style value
+ */
+ public FontStyle(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Gets the font style name.
+ *
+ * @return the font style name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the font style value.
+ *
+ * @return the font style value
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Gets the <code>FontStyle</code> object that is mapped to the given
+ * index.
+ *
+ * @param index
+ * an index into the <code>FontStyle</code> list
+ * @return a <code>FontStyle</code> object
+ */
+ public static FontStyle getFontStyle(int index) {
+ FontStyle result = (FontStyle) FONT_STYLES.get(index);
+ if (result != null) {
+ return result;
+ }
+ return NORMAL;
+ }
+
+ /**
+ * Gets the display name of the <code>FontStyle</code> object with the
+ * given value.
+ *
+ * @param value
+ * one of the FontStyles
+ * @return a display name of a FontStyle, or null if none found
+ */
+ public static String getFontStyleName(String value) {
+ for (Iterator<FontStyle> iter = FONT_STYLES.iterator(); iter.hasNext();) {
+ FontStyle style = iter.next();
+ if (style.getValue().equals(value)) {
+ return style.getName();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the value of the <code>FontStyle</code> object with the
+ * given display name.
+ *
+ * @param name
+ * one of the FontStyles
+ * @return a value of a FontStyle, or null if none found
+ */
+ public static String getFontStyleValue(String name) {
+ for (Iterator<FontStyle> iter = FONT_STYLES.iterator(); iter.hasNext();) {
+ FontStyle style = iter.next();
+ if (style.getName().equals(name)) {
+ return style.getValue();
+ }
+ }
+ return null;
+ }
+
+} \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Image.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Image.java
new file mode 100644
index 00000000000..8a3a3a85e29
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Image.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+/**
+ * Models a simplified HTML &lt;image&gt; tag.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class Image {
+
+ // The image URL.
+ private String url = ""; //$NON-NLS-1$
+
+ /**
+ * Creates a new instance.
+ */
+ public Image() {
+ }
+
+ /**
+ * Gets the image URL.
+ *
+ * @return the image URL
+ */
+ public String getURL() {
+ return url;
+ }
+
+ /**
+ * Sets the image URL.
+ *
+ * @param url
+ * the image URL
+ */
+ public void setURL(String url) {
+ this.url = url;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Link.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Link.java
new file mode 100644
index 00000000000..6c5573cc515
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Link.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+/**
+ * Models a simplified HTML &lt;link&gt; tag.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class Link {
+
+ // The link name.
+ private String name = ""; //$NON-NLS-1$
+
+ // The link URL.
+ private String url = ""; //$NON-NLS-1$
+
+ /**
+ * Creates a new instance.
+ */
+ public Link() {
+ }
+
+ /**
+ * Gets the link name.
+ *
+ * @return the link name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the link name.
+ *
+ * @param name
+ * the link name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Gets the link URL.
+ *
+ * @return the link URL
+ */
+ public String getURL() {
+ return url;
+ }
+
+ /**
+ * Sets the link URL.
+ *
+ * @param url
+ * the link URL
+ */
+ public void setURL(String url) {
+ this.url = url;
+ }
+
+ /**
+ * @Gets the HTML representation of this link.
+ *
+ * @return the HTML representation of this link
+ */
+ public String toHTML() {
+ return null;
+ }
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Table.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Table.java
new file mode 100644
index 00000000000..a02b28f89b4
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/Table.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// 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.html;
+
+/**
+ * Models a simplified HTML &lt;table&gt; tag.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class Table {
+
+ /**
+ * A table with no headers.
+ */
+ public static final int TABLE_HEADERS_NONE = 0;
+
+ /**
+ * A table with column headers.
+ */
+ public static final int TABLE_HEADERS_COLS = 1;
+
+ /**
+ * A table with row headers.
+ */
+ public static final int TABLE_HEADERS_ROWS = 2;
+
+ /**
+ * A table with both column and row headers.
+ */
+ public static final int TABLE_HEADERS_BOTH = 3;
+
+ // The number of rows.
+ private int rows = 2;
+
+ // The number of columns.
+ private int cols = 2;
+
+ // The table width.
+ private String width = "85%"; //$NON-NLS-1$
+
+ // The type of tableheaders for this table.
+ private int tableHeaders = 0;
+
+ // The table summary.
+ private String summary;
+
+ // The table caption.
+ private String caption;
+
+ /**
+ * Creates a new instance.
+ */
+ public Table() {
+ }
+
+ /**
+ * Gets the number of rows in the table.
+ *
+ * @return the number of rows
+ */
+ public int getRows() {
+ return rows;
+ }
+
+ /**
+ * Sets the number of rows in the table.
+ *
+ * @param rows
+ * the number of rows
+ */
+ public void setRows(int rows) {
+ this.rows = rows;
+ }
+
+ /**
+ * Gets the number of columns in the table.
+ *
+ * @return the number of columns
+ */
+ public int getColumns() {
+ return cols;
+ }
+
+ /**
+ * Sets the number of columns in the table.
+ *
+ * @param cols
+ * the number of columns
+ */
+ public void setColumns(int cols) {
+ this.cols = cols;
+ }
+
+ /**
+ * Gets the table width.
+ *
+ * @return the width of the table
+ */
+ public String getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the table width.
+ *
+ * @param width
+ * the width of the table
+ */
+ public void setWidth(String width) {
+ this.width = width;
+ }
+
+ /**
+ * Gets the table caption.
+ *
+ * @return the table caption
+ */
+ public String getCaption() {
+ return caption;
+ }
+
+ /**
+ * Sets the table caption.
+ *
+ * @para caption the table caption
+ */
+ public void setCaption(String caption) {
+ this.caption = caption;
+ }
+
+ /**
+ * Gets the table summary.
+ *
+ * @return the table summary
+ */
+ public String getSummary() {
+ return summary;
+ }
+
+ /**
+ * Sets the table summary.
+ *
+ * @param summary
+ * the table summary
+ */
+ public void setSummary(String summary) {
+ this.summary = summary;
+ }
+
+ /**
+ * Gets the table headers style.
+ *
+ * @return the integer with value representing
+ * <code>TABLE_HEADERS_NONE</code>,
+ * <code>TABLE_HEADERS_COLS</code>,
+ * <code>TABLE_HEADERS_ROWS</code> or
+ * <code>TABLE_HEADERS_BOTH</code>
+ */
+ public int getTableHeaders() {
+ return tableHeaders;
+ }
+
+ /**
+ * Sets the table headers style.
+ *
+ * @param tableHeaders
+ * an integer with value representing
+ * <code>TABLE_HEADERS_NONE</code>,
+ * <code>TABLE_HEADERS_COLS</code>,
+ * <code>TABLE_HEADERS_ROWS</code> or
+ * <code>TABLE_HEADERS_BOTH</code>
+ */
+ public void setTableHeaders(int tableHeaders) {
+ this.tableHeaders = tableHeaders;
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/package.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/package.html
new file mode 100644
index 00000000000..7e143c8cf34
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/html/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides implementation support for the rich text control and editor.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/package.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/package.html
new file mode 100644
index 00000000000..0238fc370ea
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides the interfaces and implementation for the rich text control and editor.
+</body>
+</html> \ No newline at end of file
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencePage.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencePage.java
new file mode 100644
index 00000000000..6d3379fc763
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencePage.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.preferences;
+
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.epf.richtext.RichTextResources;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ * The Preference page for the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextPreferencePage extends PreferencePage implements
+ IWorkbenchPreferencePage, SelectionListener, ModifyListener {
+
+ private IPreferenceStore store;
+
+ private Text lineWidthText;
+
+ private Button indentCheckbox;
+
+ private Text indentSizeText;
+
+ /**
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ store = RichTextPlugin.getDefault().getPreferenceStore();
+ }
+
+ /**
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(1, false));
+ composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Composite widthComposite = new Composite(composite, SWT.NONE);
+ widthComposite.setLayout(new GridLayout(2, false));
+ widthComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Label lineWidthLabel = new Label(widthComposite, SWT.NONE);
+ lineWidthLabel.setText(RichTextResources.maxCharsPerLineLabel_text);
+
+ lineWidthText = new Text(widthComposite, SWT.BORDER);
+ lineWidthText.setText(store.getString(RichTextPreferences.LINE_WIDTH));
+ lineWidthText.setTextLimit(3);
+ GridData gridData = new GridData();
+ gridData.widthHint = 25;
+ lineWidthText.setLayoutData(gridData);
+ lineWidthText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ }
+ });
+
+ Composite indentComposite = new Composite(composite, SWT.NONE);
+ indentComposite.setLayout(new GridLayout(2, false));
+ indentComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ indentCheckbox = new Button(indentComposite, SWT.CHECK);
+ indentCheckbox.setText(RichTextResources.indentHTMLCheckbox_text);
+ indentCheckbox.setSelection(store
+ .getBoolean(RichTextPreferences.INDENT));
+
+ new Label(indentComposite, SWT.NONE);
+
+ Label indentSizeLabel = new Label(indentComposite, SWT.NONE);
+ gridData = new GridData();
+ gridData.horizontalIndent = 20;
+ indentSizeLabel.setLayoutData(gridData);
+ indentSizeLabel.setText(RichTextResources.indentSizeLabel_text);
+
+ indentSizeText = new Text(indentComposite, SWT.BORDER);
+ indentSizeText
+ .setText(store.getString(RichTextPreferences.INDENT_SIZE));
+ indentSizeText.setTextLimit(1);
+ gridData = new GridData();
+ gridData.widthHint = 10;
+ indentSizeText.setLayoutData(gridData);
+ indentSizeText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ }
+ });
+
+ return composite;
+ }
+
+ /**
+ * @see org.eclipse.jface.preference.PreferencePage.performDefaults
+ */
+ protected void performDefaults() {
+ super.performDefaults();
+ lineWidthText.setText(store
+ .getDefaultString(RichTextPreferences.LINE_WIDTH));
+ indentCheckbox.setSelection(store
+ .getDefaultBoolean(RichTextPreferences.INDENT));
+ indentSizeText.setText(store
+ .getDefaultString(RichTextPreferences.INDENT_SIZE));
+ }
+
+ /**
+ * @see org.eclipse.jface.preference.PreferencePage.performOk
+ */
+ public boolean performOk() {
+ String lineWidthValue = lineWidthText.getText();
+ if (lineWidthValue != null && lineWidthValue.length() > 0) {
+ try {
+ int lineWidth = Integer.parseInt(lineWidthValue);
+ store.setValue(RichTextPreferences.LINE_WIDTH, lineWidth);
+ } catch (Exception e) {
+ }
+ }
+
+ boolean indentValue = indentCheckbox.getSelection();
+ store.setValue(RichTextPreferences.INDENT, indentValue);
+
+ String indentSizeValue = indentSizeText.getText();
+ if (indentSizeValue != null && indentSizeValue.length() > 0) {
+ try {
+ int indentSize = Integer.parseInt(indentSizeValue);
+ store.setValue(RichTextPreferences.INDENT_SIZE, indentSize);
+ } catch (Exception e) {
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetSelected(SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ }
+
+ /**
+ * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(SelectionEvent)
+ */
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+
+ /**
+ * @see org.eclipse.swt.events.ModifyListener#modifyText(ModifyEvent)
+ */
+ public void modifyText(ModifyEvent e) {
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferences.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferences.java
new file mode 100644
index 00000000000..f593198c73f
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferences.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Preferences for the rich text editor.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextPreferences {
+
+ /**
+ * rich text Editor preference keys.
+ */
+ public static final String LINE_WIDTH = "htmlEditor.lineWidth"; //$NON-NLS-1$
+
+ public static final String INDENT = "htmlEditor.indent"; //$NON-NLS-1$
+
+ public static final String INDENT_SIZE = "htmlEditor.indentSize"; //$NON-NLS-1$
+
+ /**
+ * Initializes the default preferences.
+ */
+ public static void initializeDefaultPreferences(IPreferenceStore store) {
+ store.setDefault(LINE_WIDTH, 120);
+ store.setDefault(INDENT, true);
+ store.setDefault(INDENT_SIZE, 4);
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencesInitializer.java b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencesInitializer.java
new file mode 100644
index 00000000000..8bdeb071fed
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/RichTextPreferencesInitializer.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 API and implementation
+ *******************************************************************************/
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.epf.richtext.RichTextPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * The rich text preferences initializer.
+ *
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class RichTextPreferencesInitializer extends
+ AbstractPreferenceInitializer {
+
+ /**
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = RichTextPlugin.getDefault()
+ .getPreferenceStore();
+ RichTextPreferences.initializeDefaultPreferences(store);
+ }
+
+}
diff --git a/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/package.html b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/package.html
new file mode 100644
index 00000000000..292b3aeec02
--- /dev/null
+++ b/extraplugins/epf-richtext/org.eclipse.epf.richtext/src/org/eclipse/epf/richtext/preferences/package.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Provides preference support for the rich text control and editor.
+</body>
+</html> \ No newline at end of file

Back to the top