intial source from http://www.sf.net/projects/wdte
authorjsurfer <jsurfer>
Thu, 2 Sep 2004 18:29:01 +0000 (18:29 +0000)
committerjsurfer <jsurfer>
Thu, 2 Sep 2004 18:29:01 +0000 (18:29 +0000)
110 files changed:
net.sourceforge.phpeclipse.ui/.classpath [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/.cvsignore [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/.project [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/build.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/icons/full/cview16/preview.gif [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/icons/full/ovr16/error_co.gif [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/icons/full/ovr16/warning_co.gif [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/plugin.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/plugin.xml [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorEditor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorManager.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/WebUI.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/I18NDocumentProvider.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/StructuredTextEditor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/EmptyPreferencePage.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/ITextStylePreferences.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/OverlayPreferenceStore.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/PreferenceDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/preferences/TemplatesPreferencePage.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/BasicCompletionProcessor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/HTMLContextType.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/JSContextType.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/XMLContextType.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/AbstractTextTools.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/IReconcilingParticipant.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/TextDoubleClickStrategy.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/AbstractPartitioner.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/FlatNode.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/IDocumentView.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/InnerDocumentView.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/MultiViewPartitioner.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/OuterDocumentView.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/ViewNode.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/source/DefaultSourceViewerConfiguration.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ModelBasedOutlinePage.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ProblemsLabelDecorator.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/link_editor.gif [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/BrowserPreview.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/IBrowserPreviewPage.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageDescriptorRegistry.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageImageDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/OverlayImageDescriptor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/templates/default-templates.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.ui/templates/default-templates.xml [new file with mode: 0644]
net.sourceforge.phpeclipse.webbrowser/plugin.xml
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/ExtendedBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/ExtendedBrowser.java with 89% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IExternalWebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IExternalWebBrowser.java with 84% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IExternalWebBrowserWorkingCopy.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IExternalWebBrowserWorkingCopy.java with 84% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IInternalWebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IInternalWebBrowser.java with 83% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IInternalWebBrowserWorkingCopy.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IInternalWebBrowserWorkingCopy.java with 81% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IURLMap.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IURLMap.java with 92% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IWebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IWebBrowser.java with 71% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/IWebBrowserEditorInput.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/IWebBrowserEditorInput.java with 91% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/OpenBrowserAction.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/OpenBrowserAction.java with 82% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/OpenBrowserWorkbenchAction.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/OpenBrowserWorkbenchAction.java with 92% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/WebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/WebBrowser.java with 96% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/WebBrowserEditorInput.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/WebBrowserEditorInput.java with 93% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserContentProvider.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserContentProvider.java with 95% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserManager.java [new file with mode: 0644]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserSearcher.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserSearcher.java with 96% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserTableComposite.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserTableComposite.java with 95% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserTableLabelProvider.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserTableLabelProvider.java with 91% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BusyIndicator.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BusyIndicator.java with 98% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/ContextIds.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/ContextIds.java with 95% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/ExternalBrowserDialog.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/ExternalBrowserDialog.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/ExternalWebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/ExternalWebBrowser.java with 87% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/ExternalWebBrowserWorkingCopy.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/ExternalWebBrowserWorkingCopy.java with 64% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/Favorite.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/Favorite.java with 95% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/IWebBrowserListener.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/IWebBrowserListener.java with 86% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/ImageResource.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/ImageResource.java with 99% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/InternalBrowserDialog.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/InternalBrowserDialog.java with 93% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/InternalWebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/InternalWebBrowser.java with 79% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/InternalWebBrowserWorkingCopy.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/InternalWebBrowserWorkingCopy.java with 72% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/InternetPreferencePage.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/InternetPreferencePage.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/OpenWithBrowserActionDelegate.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/OpenWithBrowserActionDelegate.java with 91% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/OrganizeFavoritesDialog.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/OrganizeFavoritesDialog.java with 99% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/SWTUtil.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/SWTUtil.java with 98% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/StandardURLMap.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/StandardURLMap.java with 86% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/SwitchBrowserWorkbenchAction.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/SwitchBrowserWorkbenchAction.java with 96% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/SwitchDefaultBrowserAction.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/SwitchDefaultBrowserAction.java with 86% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/TextAction.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/TextAction.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/Trace.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/Trace.java with 95% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowser.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowser.java with 99% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserEditor.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserEditor.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserEditorActionBarContributor.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserEditorActionBarContributor.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserPreference.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserPreference.java with 98% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserPreferencePage.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserPreferencePage.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserUIPlugin.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserUIPlugin.java with 94% similarity]
net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserUtil.java [moved from net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/WebBrowserUtil.java with 97% similarity]
net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserManager.java [deleted file]
net.sourceforge.phpeclipse.xml.core/.classpath [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/.cvsignore [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/.project [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/build.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/plugin.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/plugin.xml [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/DefaultProblem.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/XMLParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLDocument.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblem.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemCollector.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemReporter.java [new file with mode: 0644]
net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IXMLParser.java [new file with mode: 0644]

diff --git a/net.sourceforge.phpeclipse.ui/.classpath b/net.sourceforge.phpeclipse.ui/.classpath
new file mode 100644 (file)
index 0000000..275b34c
--- /dev/null
@@ -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/net.sourceforge.phpeclipse.ui/.cvsignore b/net.sourceforge.phpeclipse.ui/.cvsignore
new file mode 100644 (file)
index 0000000..977bb37
--- /dev/null
@@ -0,0 +1,5 @@
+bin
+build.xml
+ui.jar
+uisrc.zip
+net.sf.solareclipse.*
diff --git a/net.sourceforge.phpeclipse.ui/.project b/net.sourceforge.phpeclipse.ui/.project
new file mode 100644 (file)
index 0000000..17ea460
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>net.sourceforge.phpeclipse.ui</name>
+       <comment></comment>
+       <projects>
+               <project>net.sf.wdte.core</project>
+       </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.jdt.core.javanature</nature>
+               <nature>org.eclipse.pde.PluginNature</nature>
+       </natures>
+</projectDescription>
diff --git a/net.sourceforge.phpeclipse.ui/build.properties b/net.sourceforge.phpeclipse.ui/build.properties
new file mode 100644 (file)
index 0000000..d1ab63e
--- /dev/null
@@ -0,0 +1,2 @@
+bin.includes = plugin.xml
+source.ui.jar = src/
diff --git a/net.sourceforge.phpeclipse.ui/icons/full/cview16/preview.gif b/net.sourceforge.phpeclipse.ui/icons/full/cview16/preview.gif
new file mode 100644 (file)
index 0000000..1ca9d52
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/icons/full/cview16/preview.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/icons/full/ovr16/error_co.gif b/net.sourceforge.phpeclipse.ui/icons/full/ovr16/error_co.gif
new file mode 100644 (file)
index 0000000..8612eaf
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/icons/full/ovr16/error_co.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/icons/full/ovr16/warning_co.gif b/net.sourceforge.phpeclipse.ui/icons/full/ovr16/warning_co.gif
new file mode 100644 (file)
index 0000000..3af228c
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/icons/full/ovr16/warning_co.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/plugin.properties b/net.sourceforge.phpeclipse.ui/plugin.properties
new file mode 100644 (file)
index 0000000..550ff12
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2004 Christopher Lenz and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     Christopher Lenz - initial english resources
+# 
+# $Id: plugin.properties,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+#
+
+pluginName = Web Development Tools UI
+providerName= WDTE Project
+
+preferencePageName = PHPeclipse Web Development
+
+viewCategoryName = PHPeclipse Web Development
+previewViewName = Browser Preview
+
+templates.contextType.xml=xml
+templates.contextType.html=html
+templates.contextType.javascript=javascript
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/plugin.xml b/net.sourceforge.phpeclipse.ui/plugin.xml
new file mode 100644 (file)
index 0000000..dcf6ae5
--- /dev/null
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+   id="net.sourceforge.phpeclipse.ui"
+   name="%pluginName"
+   version="0.0.1"
+   provider-name="%providerName"
+   class="net.sourceforge.phpeclipse.ui.WebUI">
+
+   <runtime>
+      <library name="wdtui.jar">
+         <export name="*"/>
+      </library>
+   </runtime>
+   <requires>
+      <import plugin="net.sourceforge.phpeclipse.core"/>
+      <import plugin="org.eclipse.core.resources"/>
+      <import plugin="org.eclipse.core.runtime"/>
+      <import plugin="org.eclipse.jface.text"/>
+      <import plugin="org.eclipse.osgi"/>
+      <import plugin="org.eclipse.ui"/>
+      <import plugin="org.eclipse.ui.editors"/>
+      <import plugin="org.eclipse.ui.ide"/>
+      <import plugin="org.eclipse.ui.views"/>
+      <import plugin="org.eclipse.ui.workbench.texteditor"/>
+   </requires>
+
+
+   <extension
+         point="org.eclipse.ui.preferencePages">
+      <page
+            name="%preferencePageName"
+            class="net.sourceforge.phpeclipse.ui.preferences.EmptyPreferencePage"
+            id="net.sourceforge.phpeclipse.ui.preferencePage">
+      </page>
+      <page
+            name="Templates"
+            category="net.sourceforge.phpeclipse.ui.preferencePage"
+            class="net.sourceforge.phpeclipse.ui.templates.preferences.TemplatesPreferencePage"
+            id="net.sourceforge.phpeclipse.ui.templates.preferences.TemplatesPreferencePage">
+      </page>
+   </extension>
+   <extension
+         point="org.eclipse.ui.views">
+      <category
+            name="%viewCategoryName"
+            id="net.sourceforge.phpeclipse.ui.views">
+      </category>
+      <view
+            name="%previewViewName"
+            icon="icons/full/cview16/preview.gif"
+            category="net.sourceforge.phpeclipse.ui.views"
+            fastViewWidthRatio="66"
+            class="net.sourceforge.phpeclipse.ui.views.preview.BrowserPreview"
+            id="net.sourceforge.phpeclipse.ui.views.browserPreview">
+      </view>
+   </extension>
+
+   <extension
+         point="org.eclipse.ui.editors.templates">
+      <contextType
+            name="%templates.contextType.xml"
+            class="net.sourceforge.phpeclipse.ui.templates.template.XMLContextType"
+            id="xml">
+      </contextType>
+      <contextType
+            name="%templates.contextType.html"
+            class="net.sourceforge.phpeclipse.ui.templates.template.HTMLContextType"
+            id="html">
+      </contextType>
+      <contextType
+            name="%templates.contextType.javascript"
+            class="net.sourceforge.phpeclipse.ui.templates.template.JSContextType"
+            id="javascript">
+      </contextType>
+ <!--     <contextType
+            name="%templates.javadoc.contextType.name"
+            class="org.eclipse.jdt.internal.corext.template.java.JavaDocContextType"
+            id="javadoc">
+      </contextType> -->
+      <include
+               file="templates/default-templates.xml"
+               translations="templates/default-templates.properties">
+      </include>
+ <!--     <include
+               file="templates/default-codetemplates.xml"
+               translations="templates/default-templates.properties">
+      </include> -->
+   </extension>
+   <extension
+         point="org.eclipse.team.core.fileTypes">
+      <fileTypes
+            type="text"
+            extension="htm">
+      </fileTypes>
+      <fileTypes
+            type="text"
+            extension="html">
+      </fileTypes>
+   </extension>
+</plugin>
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorEditor.java
new file mode 100644 (file)
index 0000000..214c8ab
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU  and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: ColorEditor.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui;
+
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.ColorDialog;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A "button" of a certain color determined by the color picker.
+ */
+public class ColorEditor {
+
+       private Point extent;
+
+       Button button;
+
+       Image image;
+
+       RGB rgb;
+
+       Color color;
+
+       public ColorEditor(Composite parent) {
+               button = new Button(parent, SWT.PUSH);
+               extent = computeImageSize(parent);
+               image = new Image(parent.getDisplay(), extent.x, extent.y);
+
+               GC gc = new GC(image);
+
+               gc.setBackground(button.getBackground());
+               gc.fillRectangle(0, 0, extent.x, extent.y);
+
+               gc.dispose();
+
+               button.setImage(image);
+
+               button.addSelectionListener(new SelectionAdapter() {
+
+                       public void widgetSelected(SelectionEvent event) {
+                               ColorDialog colorDialog = new ColorDialog(button.getShell());
+                               colorDialog.setRGB(rgb);
+
+                               RGB newColor = colorDialog.open();
+                               if (newColor != null) {
+                                       rgb = newColor;
+                                       updateColorImage();
+                               }
+                       }
+               });
+
+               button.addDisposeListener(new DisposeListener() {
+
+                       public void widgetDisposed(DisposeEvent event) {
+                               if (image != null) {
+                                       image.dispose();
+                                       image = null;
+                               }
+
+                               if (color != null) {
+                                       color.dispose();
+                                       color = null;
+                               }
+                       }
+               });
+       }
+
+       public RGB getColorValue() {
+               return rgb;
+       }
+
+       public void setColorValue(RGB rgb) {
+               this.rgb = rgb;
+
+               updateColorImage();
+       }
+
+       public Button getButton() {
+               return button;
+       }
+
+       protected void updateColorImage() {
+               Display display = button.getDisplay();
+
+               GC gc = new GC(image);
+
+               gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
+               gc.drawRectangle(0, 2, extent.x - 1, extent.y - 4);
+
+               if (color != null) {
+                       color.dispose();
+               }
+
+               color = new Color(display, rgb);
+
+               gc.setBackground(color);
+               gc.fillRectangle(1, 3, extent.x - 2, extent.y - 5);
+
+               gc.dispose();
+
+               button.setImage(image);
+       }
+
+       protected Point computeImageSize(Control control) {
+               Font f = JFaceResources.getFontRegistry().get(
+                               JFaceResources.DEFAULT_FONT);
+
+               GC gc = new GC(control);
+               gc.setFont(f);
+
+               int height = gc.getFontMetrics().getHeight();
+
+               gc.dispose();
+
+               return new Point(height * 3 - 6, height);
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorManager.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/ColorManager.java
new file mode 100644 (file)
index 0000000..469b9c6
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *        Igor Malinin - initial contribution
+ * 
+ * $Id: ColorManager.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Color Manager.
+ * 
+ * @author Igor Malinin
+ */
+public class ColorManager {
+       protected Map colors = new HashMap( 10 );
+
+       public void bindColor( String key, RGB rgb ) {
+               Object value = colors.get( key );
+               if ( value != null ) {
+                       throw new UnsupportedOperationException();
+               }
+
+               Color color = new Color( Display.getCurrent(), rgb );
+
+               colors.put( key, color );
+       }
+
+       public void unbindColor( String key ) {
+               Color color = (Color) colors.remove( key );
+               if ( color != null ) {
+                       color.dispose();
+               }
+       }
+
+       public Color getColor( String key ) {
+               return (Color) colors.get( key );
+       }
+
+       public void dispose() {
+               Iterator i = colors.values().iterator();
+               while ( i.hasNext() ) {
+                       ((Color) i.next()).dispose();
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/WebUI.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/WebUI.java
new file mode 100644 (file)
index 0000000..39a172e
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial implementation
+ * 
+ * $Id: WebUI.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui;
+
+import java.io.IOException;
+import java.net.URL;
+
+import net.sourceforge.phpeclipse.ui.templates.template.HTMLContextType;
+import net.sourceforge.phpeclipse.ui.templates.template.JSContextType;
+import net.sourceforge.phpeclipse.ui.templates.template.XMLContextType;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * The web development tools UI plugin.
+ */
+public class WebUI extends AbstractUIPlugin {
+  private static final String CUSTOM_TEMPLATES_KEY= "net.sourceforge.phpeclipse.ui.templates"; //$NON-NLS-1$
+
+       // Constants ---------------------------------------------------------------
+
+       public static final String ICON_OVERLAY_ERROR =
+               "full/ovr16/error_co.gif"; //$NON-NLS-1$
+       public static final String ICON_OVERLAY_WARNING =
+               "full/ovr16/warning_co.gif"; //$NON-NLS-1$
+
+       // Instance Variables ------------------------------------------------------
+
+       /** The shared instance. */
+       private static WebUI plugin;
+
+       /** The template store. */
+       private TemplateStore fStore;
+       /** The context type registry. */
+       private ContributionContextTypeRegistry fRegistry;
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * The constructor.
+        */
+       public WebUI() {
+               plugin = this;
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Returns the shared instance.
+        */
+       public static WebUI getDefault() {
+               return plugin;
+       }
+
+       // AbstractUIPlugin Implementation -----------------------------------------
+
+       /*
+        * @see AbstractUIPlugin#initializeImageRegistry(ImageRegistry)
+        */
+       protected void initializeImageRegistry(ImageRegistry reg) {
+               reg.put(ICON_OVERLAY_ERROR, getImageDescriptor(ICON_OVERLAY_ERROR));
+               reg.put(ICON_OVERLAY_WARNING, getImageDescriptor(ICON_OVERLAY_WARNING));
+       }
+
+       // Private Methods ---------------------------------------------------------
+
+       /**
+        * Returns an image descriptor for the image corresponding to the specified
+        * key (which is the name of the image file).
+        * 
+        * @param key The key of the image
+        * @return The descriptor for the requested image, or <code>null</code> if 
+        *         the image could not be found
+        */
+       private ImageDescriptor getImageDescriptor(String key) {
+               try {
+                       URL url = getBundle().getEntry("/icons/" + key); //$NON-NLS-1$
+                       return ImageDescriptor.createFromURL(url);
+               } catch (IllegalStateException e) {
+                       return null;
+               }
+       }
+       
+       /**
+        * Returns this plug-in's template store.
+        * 
+        * @return the template store of this plug-in instance
+        */
+       public TemplateStore getTemplateStore() {
+               if (fStore == null) {
+                       fStore= new ContributionTemplateStore(getContextTypeRegistry(), getDefault().getPreferenceStore(), CUSTOM_TEMPLATES_KEY);
+                       try {
+                               fStore.load();
+                       } catch (IOException e) {
+                               WebUI.getDefault().getLog().log(new Status(IStatus.ERROR, "net.sourceforge.phpeclipse.ui", IStatus.OK, "", e)); //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+               }
+               return fStore;
+       }
+
+       /**
+        * Returns this plug-in's context type registry.
+        * 
+        * @return the context type registry for this plug-in instance
+        */
+       public ContextTypeRegistry getContextTypeRegistry() {
+               if (fRegistry == null) {
+                       // create an configure the contexts available in the editor
+                       fRegistry= new ContributionContextTypeRegistry();
+                       fRegistry.addContextType(XMLContextType.XML_CONTEXT_TYPE);
+                       fRegistry.addContextType(HTMLContextType.HTML_CONTEXT_TYPE);
+                       fRegistry.addContextType(JSContextType.JS_CONTEXT_TYPE);
+               }
+               return fRegistry;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.java
new file mode 100644 (file)
index 0000000..28ae4ee
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: EditorMessages.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.editor;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * @author Igor Malinin
+ */
+public class EditorMessages {
+       private static ResourceBundle bundle = ResourceBundle
+               .getBundle("net.sourceforge.phpeclipse.ui.editor.EditorMessages"); //$NON-NLS-1$
+
+       private EditorMessages() {}
+
+       public static String getString( String key ) {
+               try {
+                       return bundle.getString( key );
+               } catch ( MissingResourceException e ) {
+                       return "!" + key + "!"; //$NON-NLS-1$ //$NON-NLS-2$
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/EditorMessages.properties
new file mode 100644 (file)
index 0000000..543c355
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2004 Christopher Lenz and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     Christopher Lenz - initial english resources
+# 
+# $Id: EditorMessages.properties,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+#
+
+I18NDocumentProvider.task.saving=Saving
+I18NDocumentProvider.error.encoding=Declared encoding is not supported!
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/I18NDocumentProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/I18NDocumentProvider.java
new file mode 100644 (file)
index 0000000..7aaf2ed
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: I18NDocumentProvider.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.editor;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ContainerGenerator;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
+
+/**
+ * @author Igor Malinin
+ */
+public class I18NDocumentProvider extends FileDocumentProvider {
+
+       private static final char BOM = 0xFEFF;
+
+       /*
+        * @see org.eclipse.ui.editors.text.StorageDocumentProvider#setDocumentContent(IDocument,
+        *      InputStream, String)
+        */
+       protected void setDocumentContent(IDocument document,
+                       InputStream contentStream, String encoding) throws CoreException {
+               Reader in = null;
+
+               try {
+                       if (encoding == null) {
+                               encoding = getDefaultEncoding();
+                       }
+
+                       in = new InputStreamReader(contentStream, encoding);
+
+                       StringBuffer buffer = new StringBuffer();
+
+                       char[] readBuffer = new char[2048];
+                       int n = in.read(readBuffer);
+                       while (n > 0) {
+                               buffer.append(readBuffer, 0, n);
+                               n = in.read(readBuffer);
+                       }
+
+                       if (buffer.length() > 0 && buffer.charAt(0) == BOM) {
+                               buffer.deleteCharAt(0);
+                       }
+
+                       document.set(buffer.toString());
+               } catch (IOException x) {
+                       String msg = x.getMessage();
+                       if (msg == null) {
+                               msg = ""; //$NON-NLS-1$
+                       }
+
+                       IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
+                                       IStatus.OK, msg, x);
+
+                       throw new CoreException(s);
+               } finally {
+                       if (in != null) try {
+                               in.close();
+                       } catch (IOException x) {
+                       }
+               }
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSaveDocument(IProgressMonitor,
+        *      Object, IDocument, boolean)
+        */
+       protected void doSaveDocument(IProgressMonitor monitor, Object element,
+                       IDocument document, boolean overwrite) throws CoreException {
+               if (!(element instanceof IFileEditorInput)) {
+                       super.doSaveDocument(monitor, element, document, overwrite);
+                       return;
+               }
+
+               IFileEditorInput input = (IFileEditorInput) element;
+
+               try {
+                       String content = document.get();
+
+                       String encoding = getDeclaredEncoding(new ByteArrayInputStream(
+                                       content.getBytes("ISO-8859-1")));
+
+                       if (encoding == null) {
+                               encoding = super.getEncoding(element);
+                               if (encoding == null /* || !encoding.startsWith("UTF-16") */) {
+                                       encoding = getDefaultEncoding();
+                               }
+                       } else {
+                               setEncoding(element, encoding);
+                       }
+
+                       if (encoding.startsWith("UTF-16")) {
+                               content = BOM + content;
+                       }
+
+                       InputStream stream;
+                       try {
+                               stream = new ByteArrayInputStream(content.getBytes(encoding));
+                       } catch (UnsupportedEncodingException e) {
+                               IStatus s = new Status(
+                                               IStatus.ERROR,
+                                               PlatformUI.PLUGIN_ID,
+                                               IStatus.OK,
+                                               EditorMessages
+                                                               .getString("I18NDocumentProvider.error.encoding"),
+                                               e);
+
+                               throw new CoreException(s);
+                       }
+
+                       IFile file = input.getFile();
+                       if (file.exists()) {
+                               FileInfo info = (FileInfo) getElementInfo(element);
+
+                               if (info != null && !overwrite) {
+                                       checkSynchronizationState(info.fModificationStamp, file);
+                               }
+
+                               // inform about the upcoming content change
+                               fireElementStateChanging(element);
+
+                               try {
+                                       file.setContents(stream, overwrite, true, monitor);
+                               } catch (CoreException x) {
+                                       // inform about failure
+                                       fireElementStateChangeFailed(element);
+                                       throw x;
+                               } catch (RuntimeException x) {
+                                       // inform about failure
+                                       fireElementStateChangeFailed(element);
+                                       throw x;
+                               }
+
+                               // If here, the editor state will be flipped to "not dirty".
+                               // Thus, the state changing flag will be reset.
+
+                               if (info != null) {
+                                       ResourceMarkerAnnotationModel model = (ResourceMarkerAnnotationModel) info.fModel;
+
+                                       model.updateMarkers(info.fDocument);
+
+                                       info.fModificationStamp = computeModificationStamp(file);
+                               }
+                       } else {
+                               try {
+                                       monitor.beginTask(EditorMessages
+                                                       .getString("I18NDocumentProvider.task.saving"), //$NON-NLS-1$
+                                                       2000);
+
+                                       ContainerGenerator generator = new ContainerGenerator(file
+                                                       .getParent().getFullPath());
+
+                                       generator.generateContainer(new SubProgressMonitor(monitor,
+                                                       1000));
+
+                                       file.create(stream, false, new SubProgressMonitor(monitor,
+                                                       1000));
+                               } finally {
+                                       monitor.done();
+                               }
+                       }
+               } catch (IOException x) {
+                       IStatus s = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
+                                       IStatus.OK, x.getMessage(), x);
+
+                       throw new CoreException(s);
+               }
+       }
+
+       /*
+        * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#getEncoding(Object)
+        */
+       public String getEncoding(Object element) {
+               String encoding = super.getEncoding(element);
+               if (encoding != null) {
+                       return encoding;
+               }
+
+               if (element instanceof IStorageEditorInput) {
+                       IStorageEditorInput sei = (IStorageEditorInput) element;
+
+                       try {
+                               InputStream in = sei.getStorage().getContents();
+                               try {
+                                       encoding = getDeclaredEncoding(in);
+                               } finally {
+                                       in.close();
+                               }
+                       } catch (CoreException e) {
+                       } catch (IOException e) {
+                       }
+
+                       if (encoding == null) {
+                               encoding = getDefaultEncoding();
+                       }
+
+                       setEncoding(element, encoding);
+               }
+
+               return encoding;
+       }
+
+       /*
+        * @see org.eclipse.ui.editors.text.IStorageDocumentProvider#setEncoding(Object,
+        *      String)
+        */
+       public void setEncoding(Object element, String encoding) {
+               if (encoding == null) {
+                       encoding = getDefaultEncoding();
+               }
+
+               super.setEncoding(element, encoding);
+       }
+
+       /**
+        * Tries to determine encoding from contents of the stream. Returns <code>null</code>
+        * if encoding is unknown.
+        */
+       public String getDeclaredEncoding(InputStream in) throws IOException {
+               return getBOMEncoding(in);
+       }
+
+       /**
+        * Tries to determine encoding from the byte order mark. Returns <code>null</code>
+        * if encoding is unknown.
+        */
+       private String getBOMEncoding(InputStream in) throws IOException {
+               int first = in.read();
+               if (first < 0) {
+                       return null;
+               }
+
+               int second = in.read();
+               if (second < 0) {
+                       return null;
+               }
+
+               // look for the UTF-16 Byte Order Mark (BOM)
+               if (first == 0xFE && second == 0xFF) {
+                       return "UTF-16BE";
+               }
+
+               if (first == 0xFF && second == 0xFE) {
+                       return "UTF-16LE";
+               }
+
+               int third = in.read();
+               if (third < 0) {
+                       return null;
+               }
+
+               // look for the UTF-8 BOM
+               if (first == 0xEF && second == 0xBB && third == 0xBF) {
+                       return "UTF-8";
+               }
+
+               return null;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/StructuredTextEditor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/editor/StructuredTextEditor.java
new file mode 100644 (file)
index 0000000..c09a5be
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API and implementation
+ * 
+ * $Id: StructuredTextEditor.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.editor;
+
+import net.sourceforge.phpeclipse.core.model.ISourceModel;
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.ui.text.IReconcilingParticipant;
+import net.sourceforge.phpeclipse.ui.views.outline.ModelBasedOutlinePage;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * Abstract base class for editors that keep a source model synchronized with
+ * the textual contants being edited.
+ */
+public abstract class StructuredTextEditor extends TextEditor
+       implements IReconcilingParticipant {
+
+       // Inner Classes -----------------------------------------------------------
+
+    /**
+     * Listens to changes to the selection in the outline page, and changes the
+     * selection and highlight range in the editor accordingly.
+     */
+    private class OutlineSelectionChangedListener
+        implements ISelectionChangedListener {
+
+        /*
+         * @see ISelectionChangedListener#selectionChanged(SelectionChangedEvent)
+         */
+        public void selectionChanged(SelectionChangedEvent event) {
+            IStructuredSelection selection =
+                (IStructuredSelection) event.getSelection();
+            if (selection.isEmpty()) {
+                resetHighlightRange();
+            } else {
+                ISourceReference element = (ISourceReference)
+                                       selection.getFirstElement();
+                highlightElement(element, true);
+            }
+        }
+
+    }
+
+       // Instance Variables ------------------------------------------------------
+
+       /**
+        * The associated outline page.
+        */
+       private IContentOutlinePage outlinePage;
+
+       /**
+        * Listens to changes in the outline page's selection to update the editor
+        * selection and highlight range.
+        */
+       private ISelectionChangedListener outlinePageSelectionListener;
+
+       // TextEditor Implementation -----------------------------------------------
+
+       /*
+        * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+        */
+       public Object getAdapter(Class adapter) {
+               if (adapter.equals(IContentOutlinePage.class)) {
+                       if (outlinePage == null) {
+                               outlinePage = createOutlinePage();
+                outlinePageSelectionListener =
+                    new OutlineSelectionChangedListener();
+                outlinePage.addSelectionChangedListener(
+                outlinePageSelectionListener);
+                       }
+                       return outlinePage;
+               }
+               return super.getAdapter(adapter);
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged()
+        */
+       protected void handleCursorPositionChanged() {
+               super.handleCursorPositionChanged();
+               highlightElement(computeHighlightRangeSourceReference(), false);
+               synchronizeOutlinePageSelection();
+       }
+
+       // IReconcilingParticipant Implementation ----------------------------------
+
+       /* 
+        * @see IReconcilingParticipant#reconciled()
+        */
+       public void reconciled() {
+               Shell shell = getSite().getShell();
+               if ((shell != null) && !shell.isDisposed()) {
+                       shell.getDisplay().asyncExec(new Runnable() {
+                               public void run() {
+                                       if (outlinePage instanceof IUpdate) {
+                                               ((IUpdate) outlinePage).update();
+                                       }
+                                       synchronizeOutlinePageSelection();
+                               }
+                       });
+               }
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Computes and returns the source reference that includes the caret and
+        * serves as provider for the outline page selection and the editor range
+        * indication.
+        * 
+        * @return the computed source reference
+        */
+       public ISourceReference computeHighlightRangeSourceReference() {
+               ISourceViewer sourceViewer = getSourceViewer();
+               if (sourceViewer == null) {
+                       return null;
+               }
+               StyledText styledText = sourceViewer.getTextWidget();
+               if ((styledText == null) || styledText.isDisposed()) {
+                       return null;
+               }
+               int offset = sourceViewer.getVisibleRegion().getOffset();
+               int caret = offset + styledText.getCaretOffset();
+
+               return getElementAt(caret);
+       }
+
+       /**
+        * Returns the source model element at the specified offset.
+        * 
+        * @param offset the offset into the document
+        * @return the element at the given offset, or <tt>null</tt> if no model is
+        *         available or there is no element at the offset
+        */
+       public ISourceReference getElementAt(int offset) {
+               ISourceReference retVal = null;
+               ISourceModel model = getSourceModel();
+               if (model != null) {
+                       ISourceReference elements[] = model.getElements();
+                       retVal = getElementAt(model, elements, offset);
+               }
+               return retVal;
+       }
+
+       /**
+        * Returns the structure source model corresponding to the document
+        * currently being edited.
+        * 
+        * Concrete implementations must implement this method to return the model
+        * appropriate to the content being edited.
+        * 
+        * @return the source model
+        */
+       public abstract ISourceModel getSourceModel();
+
+       /**
+        * Informs the editor that its outliner has been closed.
+        * 
+        * TODO There must be a more elegant way to get notified when the outline 
+        *      page was closed. Otherwise move this method into an interface
+        */
+       public void outlinePageClosed() {
+               if (outlinePage != null) {
+                       outlinePage.removeSelectionChangedListener(
+                                       outlinePageSelectionListener);
+                       outlinePage = null;
+                       resetHighlightRange();
+               }
+       }
+
+       /**
+        * Synchronizes the outliner selection with the given element position in 
+        * the editor.
+        * 
+        * @param element the java element to select
+        */
+       public void synchronizeOutlinePage(ISourceReference element) {
+               if (outlinePage != null) {
+                       outlinePage.removeSelectionChangedListener(
+                               outlinePageSelectionListener);
+                       if (outlinePage instanceof ModelBasedOutlinePage) {
+                               ((ModelBasedOutlinePage) outlinePage).select(element);
+                       }
+                       outlinePage.addSelectionChangedListener(
+                               outlinePageSelectionListener);
+               }
+       }
+
+       /**
+        * Synchronizes the outliner selection with the currently highlighted source
+        * reference.
+        */
+       public void synchronizeOutlinePage() {
+               ISourceReference element = computeHighlightRangeSourceReference();
+               synchronizeOutlinePage(element);
+       }
+
+       // Protected Methods -------------------------------------------------------
+
+       protected abstract IContentOutlinePage createOutlinePage();
+
+       /**
+        * Highlights the given element.
+        * 
+        * @param element the element that should be highlighted
+        * @param moveCursor whether the cursor should be moved to the element
+        */
+       protected final void highlightElement(ISourceReference element,
+                       boolean moveCursor) {
+               if (element != null) {
+                       IRegion highlightRegion = element.getSourceRegion();
+                       setHighlightRange(highlightRegion.getOffset(),
+                               highlightRegion.getLength(), moveCursor);
+               } else {
+                       resetHighlightRange();
+               }
+       }
+
+       /**
+        * Returns whether the outline page is currently linked with the editor,
+        * meaning that its selection should automatically be updated to reflect the
+        * current cursor position.
+        * 
+        * @return <tt>true</tt> if the outline page is linked with the editor,
+        *         <tt>false</tt> otherwise
+        */
+       protected abstract boolean isOutlineLinkedWithEditor();
+
+       // Private Methods ---------------------------------------------------------
+
+       /**
+        * Recursively searches the specified list of elements managed by the given
+        * model for the element that covers the specified offfset with minimal 
+        * padding.
+        * 
+        * @param model the source model
+        * @param elements the current list of elements
+        * @param offset the offset into the document
+        * @return the model element at the specified offset, or <tt>null</tt> if
+        *         no element could be found
+        */
+       private static ISourceReference getElementAt(
+                       ISourceModel model, ISourceReference elements[], int offset) {
+               ISourceReference retVal = null;
+               for (int i = 0; i < elements.length; i++) {
+                       ISourceReference element = elements[i];
+                       IRegion region = element.getSourceRegion();
+                       if ((offset > region.getOffset())
+                        && (offset < (region.getOffset() + region.getLength()))) {
+                               ISourceReference[] children = model.getChildren(element);
+                               if (children.length > 0) {
+                                       retVal = getElementAt(model, children, offset);
+                                       if (retVal != null) {
+                                               break;
+                                       }
+                               }
+                               if (retVal == null) {
+                                       retVal = element;
+                               }
+                       }
+               }
+               return retVal;
+       }
+
+       private void synchronizeOutlinePageSelection() {
+               IPreferenceStore store = getPreferenceStore();
+               if (store != null) {
+                       boolean linkWithEditor = isOutlineLinkedWithEditor();
+                       if (linkWithEditor) {
+                               synchronizeOutlinePage(computeHighlightRangeSourceReference());
+                       }
+               }
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.java
new file mode 100644 (file)
index 0000000..885d41b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API and implementation
+ * 
+ * $Id: WebUIMessages.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.internal;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class that provides easy access to externalized strings.
+ */
+public final class WebUIMessages {
+
+       // Constants ---------------------------------------------------------------
+
+       /**
+        * Qualified name of the resource bundle containing the localized messages.
+        */
+       private static final String RESOURCE_BUNDLE =
+               "net.sourceforge.phpeclipse.ui.internal.WebUIMessages"; //$NON-NLS-1$
+
+       // Class Variables ---------------------------------------------------------
+
+       /**
+        * The resource bundle.
+        */
+       private static ResourceBundle resourceBundle =
+               ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Hidden constructor.
+        */
+       private WebUIMessages() {
+               // Hidden
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Returns the resource bundle.
+        * 
+        * @return the resource bundle
+        */
+       public static ResourceBundle getResourceBundle() {
+               return resourceBundle;
+       }
+
+       /**
+        * Returns the message identified by the specified key.
+        * 
+        * @param key the message key
+        * @return the localized message, or the key enclosed by exclamation marks
+        *         if no message was found for the key
+        */
+       public static String getString(String key) {
+               try {
+                       return resourceBundle.getString(key);
+               } catch (MissingResourceException e) {
+                       return "!" + key + "!"; //$NON-NLS-2$ //$NON-NLS-1$
+               }
+       }
+
+       /**
+        * Returns the message identified by the specified key, replacing a single
+        * parameter with the provided value.
+        * 
+        * @param key the message key
+        * @param arg the parameter value
+        * @return the formatted string, or the key enclosed by exclamation marks
+        *         if no message was found for the key
+        */
+       public static String getString(String key, String arg) {
+               return getString(key, new String[] { arg });
+       }
+
+       /**
+        * Returns the message identified by the specified key, replacing all
+        * parameters with the provided values.
+        * 
+        * @param key the message key
+        * @param args the parameter values
+        * @return the formatted string, or the key enclosed by exclamation marks
+        *         if no message was found for the key
+        */
+       public static String getString(String key, String[] args) {
+               return MessageFormat.format(getString(key), args);      
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.properties b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/internal/WebUIMessages.properties
new file mode 100644 (file)
index 0000000..259e7c6
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2004 Christopher Lenz and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     Christopher Lenz - initial english resources
+# 
+# $Id: WebUIMessages.properties,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+#
+
+# Outline Page -----------------------------------------------------------------
+
+OutlinePage.linkWithEditor.image = link_editor.gif
+OutlinePage.linkWithEditor.label = Link with editor
+OutlinePage.linkWithEditor.tooltip = Link with editor
+OutlinePage.linkWithEditor.description = Link with editor
+
+# Preview View -----------------------------------------------------------------
+
+BrowserPreview.notAvailable = A preview is not available.
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/EmptyPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/EmptyPreferencePage.java
new file mode 100644 (file)
index 0000000..9cc1c24
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: EmptyPreferencePage.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.preferences;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ * Empty preference page (could be used as a preferences category).
+ * 
+ * @author Igor Malinin
+ */
+public class EmptyPreferencePage extends PreferencePage implements
+               IWorkbenchPreferencePage {
+
+       /*
+        * @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
+        */
+       protected Control createContents(Composite parent) {
+               return new Composite(parent, SWT.NULL);
+       }
+
+       /*
+        * @see org.eclipse.ui.IWorkbenchPreferencePage#init(IWorkbench)
+        */
+       public void init(IWorkbench workbench) {
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/ITextStylePreferences.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/ITextStylePreferences.java
new file mode 100644 (file)
index 0000000..6235a01
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: ITextStylePreferences.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.preferences;
+
+
+/**
+ * 
+ * 
+ * @author Igor Malinin
+ */
+public interface ITextStylePreferences {
+       public static final String SUFFIX_FOREGROUND = "_foreground"; //$NON-NLS-1$
+       public static final String SUFFIX_BACKGROUND = "_background"; //$NON-NLS-1$
+       public static final String SUFFIX_STYLE      = "_style";      //$NON-NLS-1$
+
+       public static final String STYLE_NORMAL = "normal"; //$NON-NLS-1$
+       public static final String STYLE_BOLD   = "bold";   //$NON-NLS-1$
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/OverlayPreferenceStore.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/OverlayPreferenceStore.java
new file mode 100644 (file)
index 0000000..61951fa
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: OverlayPreferenceStore.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+
+/**
+ * An overlaying preference store.
+ */
+public class OverlayPreferenceStore implements IPreferenceStore {
+       private class PropertyListener implements IPropertyChangeListener {
+               public void propertyChange(PropertyChangeEvent event) {
+                       PreferenceDescriptor key = findOverlayKey(event.getProperty());
+                       if (key != null) {
+                               propagateProperty(parent, key, store);
+                       }
+               }
+       }
+
+       IPreferenceStore parent;
+       IPreferenceStore store;
+
+       private PreferenceDescriptor[] keys;
+
+       private PropertyListener fPropertyListener;
+
+       public OverlayPreferenceStore(
+               IPreferenceStore parent, PreferenceDescriptor[] overlayKeys
+       ) {
+               this.parent = parent;
+               this.keys = overlayKeys;
+
+               store = new PreferenceStore();
+       }
+
+       PreferenceDescriptor findOverlayKey(String key) {
+               for (int i = 0; i < keys.length; i++) {
+                       if (keys[i].key.equals(key)) {
+                               return keys[i];
+                       }
+               }
+
+               return null;
+       }
+
+       private boolean covers(String key) {
+               return (findOverlayKey(key) != null);
+       }
+
+       void propagateProperty(
+               IPreferenceStore orgin, PreferenceDescriptor key,
+               IPreferenceStore target
+       ) {
+               if (orgin.isDefault(key.key)) {
+                       if (!target.isDefault(key.key)) {
+                               target.setToDefault(key.key);
+                       }
+
+                       return;
+               }
+
+               PreferenceDescriptor.Type d = key.type;
+               if (PreferenceDescriptor.BOOLEAN == d) {
+                       boolean originValue = orgin.getBoolean(key.key);
+                       boolean targetValue = target.getBoolean(key.key);
+                       if (targetValue != originValue) {
+                               target.setValue(key.key, originValue);
+                       }
+               } else if (PreferenceDescriptor.DOUBLE == d) {
+                       double originValue = orgin.getDouble(key.key);
+                       double targetValue = target.getDouble(key.key);
+                       if (targetValue != originValue) {
+                               target.setValue(key.key, originValue);
+                       }
+               } else if (PreferenceDescriptor.FLOAT == d) {
+                       float originValue = orgin.getFloat(key.key);
+                       float targetValue = target.getFloat(key.key);
+                       if (targetValue != originValue) {
+                               target.setValue(key.key, originValue);
+                       }
+               } else if (PreferenceDescriptor.INT == d) {
+                       int originValue = orgin.getInt(key.key);
+                       int targetValue = target.getInt(key.key);
+                       if (targetValue != originValue) {
+                               target.setValue(key.key, originValue);
+                       }
+               } else if (PreferenceDescriptor.LONG == d) {
+                       long originValue = orgin.getLong(key.key);
+                       long targetValue = target.getLong(key.key);
+                       if (targetValue != originValue) {
+                               target.setValue(key.key, originValue);
+                       }
+               } else if (PreferenceDescriptor.STRING == d) {
+                       String originValue = orgin.getString(key.key);
+                       String targetValue = target.getString(key.key);
+                       if (targetValue != null && originValue != null
+                                       && !targetValue.equals(originValue)) {
+                               target.setValue(key.key, originValue);
+                       }
+               }
+       }
+
+       public void propagate() {
+               for (int i = 0; i < keys.length; i++) {
+                       propagateProperty(store, keys[i], parent);
+               }
+       }
+
+       private void loadProperty(
+               IPreferenceStore orgin, PreferenceDescriptor key,
+               IPreferenceStore target, boolean forceInitialization
+       ) {
+               PreferenceDescriptor.Type d = key.type;
+               if (PreferenceDescriptor.BOOLEAN == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, true);
+                       }
+                       target.setValue(key.key, orgin.getBoolean(key.key));
+                       target.setDefault(key.key, orgin.getDefaultBoolean(key.key));
+               } else if (PreferenceDescriptor.DOUBLE == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, 1.0D);
+                       }
+                       target.setValue(key.key, orgin.getDouble(key.key));
+                       target.setDefault(key.key, orgin.getDefaultDouble(key.key));
+               } else if (PreferenceDescriptor.FLOAT == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, 1.0F);
+                       }
+                       target.setValue(key.key, orgin.getFloat(key.key));
+                       target.setDefault(key.key, orgin.getDefaultFloat(key.key));
+               } else if (PreferenceDescriptor.INT == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, 1);
+                       }
+                       target.setValue(key.key, orgin.getInt(key.key));
+                       target.setDefault(key.key, orgin.getDefaultInt(key.key));
+               } else if (PreferenceDescriptor.LONG == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, 1L);
+                       }
+                       target.setValue(key.key, orgin.getLong(key.key));
+                       target.setDefault(key.key, orgin.getDefaultLong(key.key));
+               } else if (PreferenceDescriptor.STRING == d) {
+                       if (forceInitialization) {
+                               target.setValue(key.key, "1"); //$NON-NLS-1$
+                       }
+                       target.setValue(key.key, orgin.getString(key.key));
+                       target.setDefault(key.key, orgin.getDefaultString(key.key));
+               }
+       }
+
+       public void load() {
+               for (int i = 0; i < keys.length; i++) {
+                       loadProperty(parent, keys[i], store, true);
+               }
+       }
+
+       public void loadDefaults() {
+               for (int i = 0; i < keys.length; i++) {
+                       setToDefault(keys[i].key);
+               }
+       }
+
+       public void start() {
+               if (fPropertyListener == null) {
+                       fPropertyListener = new PropertyListener();
+                       parent.addPropertyChangeListener(fPropertyListener);
+               }
+       }
+
+       public void stop() {
+               if (fPropertyListener != null) {
+                       parent.removePropertyChangeListener(fPropertyListener);
+                       fPropertyListener = null;
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#addPropertyChangeListener(IPropertyChangeListener)
+        */
+       public void addPropertyChangeListener(IPropertyChangeListener listener) {
+               store.addPropertyChangeListener(listener);
+       }
+
+       /*
+        * @see IPreferenceStore#removePropertyChangeListener(IPropertyChangeListener)
+        */
+       public void removePropertyChangeListener(IPropertyChangeListener listener) {
+               store.removePropertyChangeListener(listener);
+       }
+
+       /*
+        * @see IPreferenceStore#firePropertyChangeEvent(String, Object, Object)
+        */
+       public void firePropertyChangeEvent(
+               String name, Object oldValue, Object newValue
+       ) {
+               store.firePropertyChangeEvent(name, oldValue, newValue);
+       }
+
+       /*
+        * @see IPreferenceStore#contains(String)
+        */
+       public boolean contains(String name) {
+               return store.contains(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getBoolean(String)
+        */
+       public boolean getBoolean(String name) {
+               return store.getBoolean(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultBoolean(String)
+        */
+       public boolean getDefaultBoolean(String name) {
+               return store.getDefaultBoolean(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultDouble(String)
+        */
+       public double getDefaultDouble(String name) {
+               return store.getDefaultDouble(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultFloat(String)
+        */
+       public float getDefaultFloat(String name) {
+               return store.getDefaultFloat(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultInt(String)
+        */
+       public int getDefaultInt(String name) {
+               return store.getDefaultInt(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultLong(String)
+        */
+       public long getDefaultLong(String name) {
+               return store.getDefaultLong(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDefaultString(String)
+        */
+       public String getDefaultString(String name) {
+               return store.getDefaultString(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getDouble(String)
+        */
+       public double getDouble(String name) {
+               return store.getDouble(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getFloat(String)
+        */
+       public float getFloat(String name) {
+               return store.getFloat(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getInt(String)
+        */
+       public int getInt(String name) {
+               return store.getInt(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getLong(String)
+        */
+       public long getLong(String name) {
+               return store.getLong(name);
+       }
+
+       /*
+        * @see IPreferenceStore#getString(String)
+        */
+       public String getString(String name) {
+               return store.getString(name);
+       }
+
+       /*
+        * @see IPreferenceStore#isDefault(String)
+        */
+       public boolean isDefault(String name) {
+               return store.isDefault(name);
+       }
+
+       /*
+        * @see IPreferenceStore#needsSaving()
+        */
+       public boolean needsSaving() {
+               return store.needsSaving();
+       }
+
+       /*
+        * @see IPreferenceStore#putValue(String, String)
+        */
+       public void putValue(String name, String value) {
+               if (covers(name)) {
+                       store.putValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, double)
+        */
+       public void setDefault(String name, double value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, float)
+        */
+       public void setDefault(String name, float value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, int)
+        */
+       public void setDefault(String name, int value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, long)
+        */
+       public void setDefault(String name, long value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, String)
+        */
+       public void setDefault(String name, String value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setDefault(String, boolean)
+        */
+       public void setDefault(String name, boolean value) {
+               if (covers(name)) {
+                       store.setDefault(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setToDefault(String)
+        */
+       public void setToDefault(String name) {
+               store.setToDefault(name);
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, double)
+        */
+       public void setValue(String name, double value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, float)
+        */
+       public void setValue(String name, float value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, int)
+        */
+       public void setValue(String name, int value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, long)
+        */
+       public void setValue(String name, long value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, String)
+        */
+       public void setValue(String name, String value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+
+       /*
+        * @see IPreferenceStore#setValue(String, boolean)
+        */
+       public void setValue(String name, boolean value) {
+               if (covers(name)) {
+                       store.setValue(name, value);
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/PreferenceDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/preferences/PreferenceDescriptor.java
new file mode 100644 (file)
index 0000000..d8b8610
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: PreferenceDescriptor.java,v 1.1 2004-09-02 18:26:30 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.preferences;
+
+/**
+ * Preference descriptor.
+ * 
+ * @author Igor Malinin
+ */
+public final class PreferenceDescriptor {
+       public static final Type BOOLEAN = new Type();
+       public static final Type DOUBLE  = new Type();
+       public static final Type FLOAT   = new Type();
+       public static final Type INT     = new Type();
+       public static final Type LONG    = new Type();
+       public static final Type STRING  = new Type();
+
+       public static final class Type {
+               Type() {}
+       }
+
+       public final Type  type;
+       public final String key;
+
+       public PreferenceDescriptor(Type type, String key) {
+               this.type = type;
+               this.key = key;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/preferences/TemplatesPreferencePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/preferences/TemplatesPreferencePage.java
new file mode 100644 (file)
index 0000000..ecdc770
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.ui.templates.preferences;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.texteditor.templates.TemplatePreferencePage;
+/**
+ * @see org.eclipse.jface.preference.PreferencePage
+ */
+public class TemplatesPreferencePage extends TemplatePreferencePage implements IWorkbenchPreferencePage {
+       
+       public TemplatesPreferencePage() {
+               setPreferenceStore(WebUI.getDefault().getPreferenceStore());
+               setTemplateStore(WebUI.getDefault().getTemplateStore());
+               setContextTypeRegistry(WebUI.getDefault().getContextTypeRegistry());
+       }
+
+       protected boolean isShowFormatterSetting() {
+               return false;
+       }
+       
+       
+       public boolean performOk() {
+               boolean ok= super.performOk();
+               
+               WebUI.getDefault().savePluginPreferences();
+               
+               return ok;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/BasicCompletionProcessor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/BasicCompletionProcessor.java
new file mode 100644 (file)
index 0000000..1e68c52
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.ui.templates.template;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.swt.graphics.Image;
+/**
+ * A completion processor for XML templates.
+ */
+public class BasicCompletionProcessor extends TemplateCompletionProcessor {
+  private static final String DEFAULT_IMAGE = "icons/template.gif"; //$NON-NLS-1$
+
+  /**
+   * We watch for angular brackets since those are often part of XML templates.
+   */
+  protected String extractPrefix(ITextViewer viewer, int offset) {
+    IDocument document = viewer.getDocument();
+    int i = offset;
+    if (i > document.getLength())
+      return ""; //$NON-NLS-1$
+
+    try {
+      while (i > 0) {
+        char ch = document.getChar(i - 1);
+        if (ch != '<' && ch != '&' && ch != '{' && !Character.isJavaIdentifierPart(ch))
+          break;
+        i--;
+      }
+
+      return document.get(i, offset - i);
+    } catch (BadLocationException e) {
+      return ""; //$NON-NLS-1$
+    }
+  }
+
+  /**
+   * Cut out angular brackets for relevance sorting, since the template name does not contain the brackets.
+   */
+  protected int getRelevance(Template template, String prefix) {
+    //         if (prefix.startsWith("<")) //$NON-NLS-1$
+    //                 prefix= prefix.substring(1);
+    if (template.getName().startsWith(prefix))
+      return 90;
+    return 0;
+  }
+
+  /**
+   * Simply return all templates.
+   */
+  protected Template[] getTemplates(String contextTypeId) {
+    return WebUI.getDefault().getTemplateStore().getTemplates();
+  }
+
+  /**
+   * Return the XML context type that is supported by this plugin.
+   */
+  protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+    return WebUI.getDefault().getContextTypeRegistry().getContextType(XMLContextType.XML_CONTEXT_TYPE);
+  }
+
+  /**
+   * Always return the default image.
+   */
+  protected Image getImage(Template template) {
+    ImageRegistry registry = WebUI.getDefault().getImageRegistry();
+    Image image = registry.get(DEFAULT_IMAGE);
+    if (image == null) {
+      ImageDescriptor desc = WebUI.imageDescriptorFromPlugin("org.eclipse.ui.examples.javaeditor", DEFAULT_IMAGE); //$NON-NLS-1$
+      registry.put(DEFAULT_IMAGE, desc);
+      image = registry.get(DEFAULT_IMAGE);
+    }
+    return image;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer,
+   *      int)
+   */
+  public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+    ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
+
+    // adjust offset to end of normalized selection
+    if (selection.getOffset() == offset)
+      offset = selection.getOffset() + selection.getLength();
+
+    String prefix = extractPrefix(viewer, offset);
+    prefix = prefix.toLowerCase();
+    Region region = new Region(offset - prefix.length(), prefix.length());
+    TemplateContext context = createContext(viewer, region);
+    if (context == null)
+      return new ICompletionProposal[0];
+
+    context.setVariable("selection", selection.getText()); // name of the selection variables {line, word}_selection //$NON-NLS-1$
+
+    Template[] templates = getTemplates(context.getContextType().getId());
+
+    List matches = new ArrayList();
+    for (int i = 0; i < templates.length; i++) {
+      Template template = templates[i];
+      try {
+        context.getContextType().validate(template.getPattern());
+      } catch (TemplateException e) {
+        continue;
+      }
+
+      if (template.getName().startsWith(prefix)) { //&& template.matches(prefix, context.getContextType().getId()))
+        matches.add(createProposal(template, context, region, getRelevance(template, prefix)));
+      }
+    }
+
+    return (ICompletionProposal[]) matches.toArray(new ICompletionProposal[matches.size()]);
+
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/HTMLContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/HTMLContextType.java
new file mode 100644 (file)
index 0000000..908b084
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.ui.templates.template;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+
+/**
+ * A very simple context type.
+ */
+public class HTMLContextType extends TemplateContextType {
+
+       /** This context's id */
+       public static final String HTML_CONTEXT_TYPE= "html"; //$NON-NLS-1$
+
+       /**
+        * Creates a new XML context type. 
+        */
+       public HTMLContextType() {
+               addGlobalResolvers();
+       }
+
+       private void addGlobalResolvers() {
+               addResolver(new GlobalTemplateVariables.Cursor());
+               addResolver(new GlobalTemplateVariables.WordSelection());
+               addResolver(new GlobalTemplateVariables.LineSelection());
+               addResolver(new GlobalTemplateVariables.Dollar());
+               addResolver(new GlobalTemplateVariables.Date());
+               addResolver(new GlobalTemplateVariables.Year());
+               addResolver(new GlobalTemplateVariables.Time());
+               addResolver(new GlobalTemplateVariables.User());
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/JSContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/JSContextType.java
new file mode 100644 (file)
index 0000000..63d51da
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.ui.templates.template;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+
+/**
+ * A very simple context type.
+ */
+public class JSContextType extends TemplateContextType {
+
+       /** This context's id */
+       public static final String JS_CONTEXT_TYPE= "javascript"; //$NON-NLS-1$
+
+       /**
+        * Creates a new XML context type. 
+        */
+       public JSContextType() {
+               addGlobalResolvers();
+       }
+
+       private void addGlobalResolvers() {
+               addResolver(new GlobalTemplateVariables.Cursor());
+               addResolver(new GlobalTemplateVariables.WordSelection());
+               addResolver(new GlobalTemplateVariables.LineSelection());
+               addResolver(new GlobalTemplateVariables.Dollar());
+               addResolver(new GlobalTemplateVariables.Date());
+               addResolver(new GlobalTemplateVariables.Year());
+               addResolver(new GlobalTemplateVariables.Time());
+               addResolver(new GlobalTemplateVariables.User());
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/XMLContextType.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/templates/template/XMLContextType.java
new file mode 100644 (file)
index 0000000..9944dfb
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.ui.templates.template;
+
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+
+/**
+ * A very simple context type.
+ */
+public class XMLContextType extends TemplateContextType {
+
+       /** This context's id */
+       public static final String XML_CONTEXT_TYPE= "xml"; //$NON-NLS-1$
+
+       /**
+        * Creates a new XML context type. 
+        */
+       public XMLContextType() {
+               addGlobalResolvers();
+       }
+
+       private void addGlobalResolvers() {
+               addResolver(new GlobalTemplateVariables.Cursor());
+               addResolver(new GlobalTemplateVariables.WordSelection());
+               addResolver(new GlobalTemplateVariables.LineSelection());
+               addResolver(new GlobalTemplateVariables.Dollar());
+               addResolver(new GlobalTemplateVariables.Date());
+               addResolver(new GlobalTemplateVariables.Year());
+               addResolver(new GlobalTemplateVariables.Time());
+               addResolver(new GlobalTemplateVariables.User());
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/AbstractTextTools.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/AbstractTextTools.java
new file mode 100644 (file)
index 0000000..38a4f8b
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: AbstractTextTools.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.ui.ColorManager;
+import net.sourceforge.phpeclipse.ui.preferences.ITextStylePreferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * @author Igor Malinin
+ */
+public class AbstractTextTools {
+
+       /** The preference store */
+       protected IPreferenceStore store;
+
+       /** The color manager */
+       protected ColorManager colorManager;
+
+       private Map tokens;
+
+       private String[] properties;
+
+       private String[] foregroundPropertyNames;
+
+       private String[] backgroundPropertyNames;
+
+       private String[] stylePropertyNames;
+
+       private IPropertyChangeListener listener;
+
+       /**
+        * Creates a new text tools collection.
+        */
+       public AbstractTextTools(IPreferenceStore store, String[] properties) {
+         this(store, properties, new ColorManager());
+       }
+       /**
+        * Creates a new text tools collection.
+        */
+       public AbstractTextTools(IPreferenceStore store, String[] properties, ColorManager manager) {
+               this.store = store;
+               this.properties = properties;
+
+               colorManager = manager;
+
+               tokens = new HashMap();
+
+               int length = properties.length;
+
+               foregroundPropertyNames = new String[length];
+               backgroundPropertyNames = new String[length];
+               stylePropertyNames = new String[length];
+
+               for (int i = 0; i < length; i++) {
+                       String property = properties[i];
+
+                       String foreground = property
+                                       + ITextStylePreferences.SUFFIX_FOREGROUND;
+                       String background = property
+                                       + ITextStylePreferences.SUFFIX_BACKGROUND;
+                       String style = property + ITextStylePreferences.SUFFIX_STYLE;
+
+                       foregroundPropertyNames[i] = foreground;
+                       backgroundPropertyNames[i] = background;
+                       stylePropertyNames[i] = style;
+
+                       RGB rgb;
+
+                       rgb = getColor(store, foreground);
+                       if (rgb != null) {
+                               colorManager.bindColor(foreground, rgb);
+                       }
+
+                       rgb = getColor(store, background);
+                       if (rgb != null) {
+                               colorManager.bindColor(background, rgb);
+                       }
+
+                       tokens.put(property, new Token(new TextAttribute(colorManager
+                                       .getColor(foreground), colorManager.getColor(background),
+                                       getStyle(store, style))));
+               }
+
+               listener = new IPropertyChangeListener() {
+
+                       public void propertyChange(PropertyChangeEvent event) {
+                               adaptToPreferenceChange(event);
+                       }
+               };
+
+               store.addPropertyChangeListener(listener);
+       }
+
+       /**
+        * Disposes all the individual tools of this tools collection.
+        */
+       public void dispose() {
+               if (store != null) {
+                       store.removePropertyChangeListener(listener);
+
+                       store = null;
+                       listener = null;
+               }
+
+               if (colorManager != null) {
+                       colorManager.dispose();
+
+                       colorManager = null;
+               }
+
+               tokens = null;
+
+               properties = null;
+               foregroundPropertyNames = null;
+               backgroundPropertyNames = null;
+               stylePropertyNames = null;
+       }
+
+       /**
+        * Returns the color manager which is used to manage any XML-specific
+        * colors needed for such things like syntax highlighting.
+        * 
+        * @return the color manager to be used for XML text viewers
+        */
+       public ColorManager getColorManager() {
+               return colorManager;
+       }
+
+       public Map getTokens() {
+               return tokens;
+       }
+
+       protected Token getToken(String key) {
+               int index = indexOf(key);
+               if (index < 0) {
+                       return null;
+               }
+
+               return (Token) tokens.get(properties[index]);
+       }
+
+       /**
+        * Determines whether the preference change encoded by the given event
+        * changes the behavior of one its contained components.
+        * 
+        * @param event
+        *            the event to be investigated
+        * @return <code>true</code> if event causes a behavioral change
+        */
+       public boolean affectsBehavior(PropertyChangeEvent event) {
+               return (indexOf(event.getProperty()) >= 0);
+       }
+
+       /**
+        * Adapts the behavior of the contained components to the change encoded in
+        * the given event.
+        * 
+        * @param event
+        *            the event to whch to adapt
+        */
+       protected void adaptToPreferenceChange(PropertyChangeEvent event) {
+               String property = event.getProperty();
+
+               Token token = getToken(property);
+               if (token != null) {
+                       if (property.endsWith(ITextStylePreferences.SUFFIX_FOREGROUND)
+                                       || property
+                                                       .endsWith(ITextStylePreferences.SUFFIX_BACKGROUND)) {
+                               adaptToColorChange(token, event);
+                       } else if (property.endsWith(ITextStylePreferences.SUFFIX_STYLE)) {
+                               adaptToStyleChange(token, event);
+                       }
+               }
+       }
+
+       private void adaptToColorChange(Token token, PropertyChangeEvent event) {
+               RGB rgb = getColor(event.getNewValue());
+
+               String property = event.getProperty();
+
+               colorManager.unbindColor(property);
+               if (rgb != null) {
+                       colorManager.bindColor(property, rgb);
+               }
+
+               Object data = token.getData();
+               if (data instanceof TextAttribute) {
+                       TextAttribute old = (TextAttribute) data;
+
+                       int i = indexOf(property);
+
+                       token.setData(new TextAttribute(colorManager
+                                       .getColor(foregroundPropertyNames[i]), colorManager
+                                       .getColor(backgroundPropertyNames[i]), old.getStyle()));
+               }
+       }
+
+       private void adaptToStyleChange(Token token, PropertyChangeEvent event) {
+               int style = getStyle((String) event.getNewValue());
+
+               Object data = token.getData();
+               if (data instanceof TextAttribute) {
+                       TextAttribute old = (TextAttribute) data;
+                       if (old.getStyle() != style) {
+                               token.setData(new TextAttribute(old.getForeground(), old
+                                               .getBackground(), style));
+                       }
+               }
+       }
+
+       private int indexOf(String property) {
+               if (property != null) {
+                       int length = properties.length;
+
+                       for (int i = 0; i < length; i++) {
+                               if (property.equals(properties[i])
+                                               || property.equals(foregroundPropertyNames[i])
+                                               || property.equals(backgroundPropertyNames[i])
+                                               || property.equals(stylePropertyNames[i])) {
+                                       return i;
+                               }
+                       }
+               }
+
+               return -1;
+       }
+
+       private RGB getColor(IPreferenceStore store, String key) {
+               return getColor(store.getString(key));
+       }
+
+       private RGB getColor(Object value) {
+               if (value instanceof RGB) {
+                       return (RGB) value;
+               }
+
+               String str = (String) value;
+               if (str.length() > 0) {
+                       return StringConverter.asRGB(str);
+               }
+
+               return null;
+       }
+
+       private int getStyle(IPreferenceStore store, String key) {
+               return getStyle(store.getString(key));
+       }
+
+       private int getStyle(String value) {
+               if (value.indexOf(ITextStylePreferences.STYLE_BOLD) >= 0) {
+                       return SWT.BOLD;
+               }
+
+               return SWT.NORMAL;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/IReconcilingParticipant.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/IReconcilingParticipant.java
new file mode 100644 (file)
index 0000000..26f9f62
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IReconcilingParticipant.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text;
+
+/**
+ *  Interface for classes participating in reconciling.
+ */
+public interface IReconcilingParticipant {
+       
+       /**
+        * Called after reconciling has been finished.
+        */
+       void reconciled();
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/TextDoubleClickStrategy.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/TextDoubleClickStrategy.java
new file mode 100644 (file)
index 0000000..c3e70a5
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: TextDoubleClickStrategy.java,v 1.1 2004-09-02 18:26:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+
+/**
+ * @author Igor Malinin
+ */
+public class TextDoubleClickStrategy implements ITextDoubleClickStrategy {
+
+       /*
+        * @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(ITextViewer)
+        */
+       public void doubleClicked(ITextViewer viewer) {
+               int offset = viewer.getSelectedRange().x;
+               if (offset < 0) { return; }
+
+               selectWord(viewer, viewer.getDocument(), offset);
+       }
+
+       protected void selectWord(ITextViewer textViewer, IDocument document,
+                       int offset) {
+               try {
+                       int start = offset;
+                       while (start >= 0) {
+                               char c = document.getChar(start);
+
+                               if (!Character.isUnicodeIdentifierPart(c)) {
+                                       break;
+                               }
+
+                               --start;
+                       }
+
+                       int length = document.getLength();
+
+                       int end = offset;
+                       while (end < length) {
+                               char c = document.getChar(end);
+
+                               if (!Character.isUnicodeIdentifierPart(c)) {
+                                       break;
+                               }
+
+                               ++end;
+                       }
+
+                       if (start == end) {
+                               textViewer.setSelectedRange(start, 0);
+                       } else {
+                               textViewer.setSelectedRange(start + 1, end - start - 1);
+                       }
+               } catch (BadLocationException x) {
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/AbstractPartitioner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/AbstractPartitioner.java
new file mode 100644 (file)
index 0000000..981b803
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: AbstractPartitioner.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IDocumentPartitionerExtension;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TypedRegion;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.IToken;
+
+/**
+ * Advanced partitioner which maintains partitions as views to connected document. Views have own partitioners themselves. This
+ * class is designed as a base for complex partitioners such as for JSP, PHP, ASP, etc. languages.
+ * 
+ * @author Igor Malinin
+ */
+public abstract class AbstractPartitioner implements IDocumentPartitioner, IDocumentPartitionerExtension {
+  public final static boolean DEBUG = true;
+
+  /** Partition scanner */
+  protected IPartitionTokenScanner scanner;
+
+  /** Connected document */
+  protected IDocument document;
+
+  /** Flat structure of the document */
+  protected List nodes = new ArrayList();
+
+  /** The offset at which the first changed partition starts */
+  protected int regionStart;
+
+  /** The offset at which the last changed partition ends */
+  protected int regionEnd;
+
+  public AbstractPartitioner(IPartitionTokenScanner scanner) {
+    this.scanner = scanner;
+  }
+
+  protected FlatNode createNode(String type, int offset, int length) {
+    if (DEBUG) {
+      Assert.isTrue(offset >= 0, Integer.toString(offset));
+    }
+    FlatNode node = new FlatNode(type);
+    node.offset = offset;
+    node.length = length;
+    return node;
+  }
+
+  protected void addInnerRegion(FlatNode position) {
+    nodes.add(computeFlatNodeIndex(position.offset), position);
+  }
+
+  protected void removeInnerRegion(FlatNode position) {
+    nodes.remove(position); // TODO: Indexed remove?
+  }
+
+  protected void deleteInnerRegion(FlatNode position) {
+    nodes.remove(position); // TODO: Indexed remove?
+  }
+
+  protected void resizeInnerRegion(FlatNode position) {
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#connect(IDocument)
+   */
+  public void connect(IDocument document) {
+    this.document = document;
+
+    initialize();
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#disconnect()
+   */
+  public void disconnect() {
+    nodes.clear();
+    document = null;
+  }
+
+  /**
+   * Performs the initial partitioning of the partitioner's document.
+   */
+  protected void initialize() {
+    scanner.setRange(document, 0, document.getLength());
+
+    IToken token = scanner.nextToken();
+    while (!token.isEOF()) {
+      String contentType = getTokenContentType(token);
+
+      if (isSupportedContentType(contentType)) {
+        addInnerRegion(createNode(contentType, scanner.getTokenOffset(), scanner.getTokenLength()));
+      }
+
+      token = scanner.nextToken();
+    }
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+   */
+  public void documentAboutToBeChanged(DocumentEvent event) {
+    regionStart = regionEnd = -1;
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#documentChanged(DocumentEvent)
+   */
+  public boolean documentChanged(DocumentEvent event) {
+    return (documentChanged2(event) != null);
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitionerExtension#documentChanged2(DocumentEvent)
+   */
+  public IRegion documentChanged2(DocumentEvent event) {
+    int first = fixupPartitions(event);
+
+    FlatNode[] category = (FlatNode[]) nodes.toArray(new FlatNode[nodes.size()]);
+
+    // repartition changed region
+
+    String contentType = IDocument.DEFAULT_CONTENT_TYPE;
+
+    int offset;
+
+    if (first == 0) {
+      offset = 0; // Bug #697414: first offset
+    } else {
+      offset = event.getOffset();
+
+      FlatNode partition = category[first - 1];
+      if (partition.includes(offset)) {
+        offset = partition.offset;
+        contentType = partition.type;
+        --first;
+      } else if (offset == partition.offset + partition.length) {
+        offset = partition.offset;
+        contentType = partition.type;
+        --first;
+      } else {
+        offset = partition.offset + partition.length;
+      }
+    }
+
+    // should not be changed since last conversion
+    // category = (FlatNode[]) nodes.toArray(new FlatNode[nodes.size()]);
+    if (DEBUG) {
+      Assert.isTrue(offset >= 0, Integer.toString(offset));
+    }
+    scanner.setPartialRange(document, offset, document.getLength(), contentType, offset);
+
+    int lastScannedPosition = offset;
+    IToken token = scanner.nextToken();
+    while (!token.isEOF()) {
+      contentType = getTokenContentType(token);
+
+      if (!isSupportedContentType(contentType)) {
+        token = scanner.nextToken();
+        continue;
+      }
+
+      offset = scanner.getTokenOffset();
+      if (DEBUG) {
+        Assert.isTrue(offset >= 0, scanner.toString());
+      }
+      int length = scanner.getTokenLength();
+
+      lastScannedPosition = offset + length;
+
+      // remove all affected positions
+      while (first < category.length) {
+        FlatNode p = category[first];
+        if (p.offset + p.length < lastScannedPosition
+            || (p.overlapsWith(offset, length) && (!containsPosition(offset, length) || !contentType.equals(p.type)))) {
+          removeInnerRegion(p);
+          rememberRegion(p.offset, p.length);
+          ++first;
+        } else {
+          break;
+        }
+      }
+
+      // if position already exists we are done
+      if (containsPosition(offset, length)) {
+        if (lastScannedPosition > event.getOffset()) {
+          // TODO: optional repartition till end of doc
+          return createRegion();
+        }
+
+        ++first;
+      } else {
+        // insert the new type position
+        addInnerRegion(createNode(contentType, offset, length));
+        rememberRegion(offset, length);
+      }
+      //            try {
+      token = scanner.nextToken();
+      //            } catch (ArrayIndexOutOfBoundsException e) {
+      //              System.out.println(this.getClass().toString());
+      //              throw e;
+      //            }
+    }
+
+    // remove all positions behind lastScannedPosition
+    // since there aren't any further types
+
+    // Do not need to recalculate (lost remove events)!
+    // first = computeIndexInInnerDocuments(lastScannedPosition);
+    while (first < category.length) {
+      FlatNode p = category[first++];
+      removeInnerRegion(p);
+      rememberRegion(p.offset, p.length);
+    }
+
+    return createRegion();
+  }
+
+  protected int fixupPartitions(DocumentEvent event) {
+    int offset = event.getOffset();
+    int length = event.getLength();
+    int end = offset + length;
+
+    // fixup flat nodes laying on change boundaries
+
+    int first = computeFlatNodeIndex(offset);
+    if (first > 0) {
+      FlatNode p = (FlatNode) nodes.get(first - 1);
+
+      int right = p.offset + p.length;
+      if (offset < right) {
+        // change overlaps with partition
+        if (end < right) {
+          // cahnge completely inside partition
+          String text = event.getText();
+          p.length -= length;
+          if (text != null) {
+            p.length += text.length();
+          }
+        } else {
+          // cut partition at right
+          int cut = p.offset + p.length - offset;
+          p.length -= cut;
+        }
+      }
+    }
+
+    int last = computeFlatNodeIndex(end);
+    if (first < last) {
+      FlatNode p = (FlatNode) nodes.get(last - 1);
+
+      int right = p.offset + p.length;
+      if (end < right) {
+        // cut partition at left
+        int cut = end - p.offset;
+        p.length -= cut;
+        p.offset = offset;
+
+        String text = event.getText();
+        if (text != null) {
+          p.offset += text.length();
+        }
+
+        --last;
+      }
+    }
+
+    // fixup flat nodes laying afrer change
+
+    String text = event.getText();
+    if (text != null) {
+      length -= text.length();
+    }
+
+    for (int i = last, size = nodes.size(); i < size; i++) {
+      ((FlatNode) nodes.get(i)).offset -= length;
+    }
+
+    // delete flat nodes laying completely inside change boundaries
+
+    if (first < last) {
+      do {
+        deleteInnerRegion((FlatNode) nodes.get(--last));
+      } while (first < last);
+
+      rememberRegion(offset, 0);
+    }
+
+    return first;
+  }
+
+  /**
+   * Returns whether the given type is one of the legal content types.
+   * 
+   * @param contentType
+   *          the content type to check
+   * @return <code>true</code> if the content type is a legal content type
+   */
+  protected boolean isSupportedContentType(String contentType) {
+    /* TODO: implementation */
+    //         if (contentType != null) {
+    //                 for (int i= 0; i < fLegalContentTypes.length; i++) {
+    //                         if (fLegalContentTypes[i].equals(contentType)) {
+    //                                 return true;
+    //                         }
+    //                 }
+    //         }
+    //         return false;
+    return (contentType != null);
+  }
+
+  /**
+   * Returns a content type encoded in the given token. If the token's data is not <code>null</code> and a string it is assumed
+   * that it is the encoded content type.
+   * 
+   * @param token
+   *          the token whose content type is to be determined
+   * @return the token's content type
+   */
+  protected String getTokenContentType(IToken token) {
+    Object data = token.getData();
+    if (data instanceof String) {
+      return (String) data;
+    }
+
+    return null;
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#getLegalContentTypes()
+   */
+  public String[] getLegalContentTypes() {
+    // TODO: implementation
+    return null;
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#getContentType(int)
+   */
+  public String getContentType(int offset) {
+    return getPartition(offset).getType();
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
+   */
+  public ITypedRegion getPartition(int offset) {
+    if (nodes.size() == 0) {
+      return new TypedRegion(0, document.getLength(), IDocument.DEFAULT_CONTENT_TYPE);
+    }
+
+    int index = computeFlatNodeIndex(offset);
+    if (index < nodes.size()) {
+      FlatNode next = (FlatNode) nodes.get(index);
+
+      if (offset == next.offset) {
+        return new TypedRegion(next.offset, next.length, next.type);
+      }
+
+      if (index == 0) {
+        return new TypedRegion(0, next.offset, IDocument.DEFAULT_CONTENT_TYPE);
+      }
+
+      FlatNode prev = (FlatNode) nodes.get(index - 1);
+
+      if (prev.includes(offset)) {
+        return new TypedRegion(prev.offset, prev.length, prev.type);
+      }
+
+      int end = prev.offset + prev.length;
+      return new TypedRegion(end, next.offset - end, IDocument.DEFAULT_CONTENT_TYPE);
+    }
+
+    FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
+
+    if (prev.includes(offset)) {
+      return new TypedRegion(prev.offset, prev.length, prev.type);
+    }
+
+    int end = prev.offset + prev.length;
+
+    return new TypedRegion(end, document.getLength() - end, IDocument.DEFAULT_CONTENT_TYPE);
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int, int)
+   */
+  public ITypedRegion[] computePartitioning(int offset, int length) {
+    List list = new ArrayList();
+
+    int end = offset + length;
+
+    int index = computeFlatNodeIndex(offset);
+    while (true) {
+      FlatNode prev = (index > 0) ? (FlatNode) nodes.get(index - 1) : null;
+
+      if (prev != null) {
+        if (prev.overlapsWith(offset, length)) {
+          list.add(new TypedRegion(prev.offset, prev.length, prev.type));
+        }
+
+        if (end <= prev.offset + prev.length) {
+          break;
+        }
+      }
+
+      FlatNode next = (index < nodes.size()) ? (FlatNode) nodes.get(index) : null;
+
+      if (next == null || offset < next.offset) {
+        int off0 = offset;
+        int off1 = offset + length;
+
+        if (prev != null && off0 < prev.offset + prev.length) {
+          off0 = prev.offset + prev.length;
+        }
+
+        if (next != null && next.offset < off1) {
+          off1 = next.offset;
+        }
+
+        if (off0 < off1) {
+          list.add(new TypedRegion(off0, off1 - off0, IDocument.DEFAULT_CONTENT_TYPE));
+        }
+      }
+
+      if (next == null) {
+        break;
+      }
+
+      ++index;
+    }
+
+    return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
+  }
+
+  /**
+   * Computes the index in the list of flat nodes at which an flat node with the given offset would be inserted. The flat node is
+   * supposed to become the first in this list of all flat nodes with the same offset.
+   * 
+   * @param offset
+   *          the offset for which the index is computed
+   * @return the computed index
+   */
+  protected int computeFlatNodeIndex(int offset) {
+    if (nodes.size() == 0) {
+      return 0;
+    }
+
+    int left = 0, mid = 0;
+    int right = nodes.size() - 1;
+
+    FlatNode p = null;
+
+    while (left < right) {
+      mid = (left + right) / 2;
+
+      p = (FlatNode) nodes.get(mid);
+
+      if (offset < p.offset) {
+        right = (left == mid) ? left : mid - 1;
+      } else if (offset > p.offset) {
+        left = (right == mid) ? right : mid + 1;
+      } else if (offset == p.offset) {
+        left = right = mid;
+      }
+    }
+
+    int pos = left;
+    p = (FlatNode) nodes.get(pos);
+    if (offset > p.offset) {
+      // append to the end
+      pos++;
+    } else {
+      // entry will became the first of all entries with the same offset
+      do {
+        --pos;
+        if (pos < 0) {
+          break;
+        }
+        p = (FlatNode) nodes.get(pos);
+      } while (offset == p.offset);
+      ++pos;
+    }
+
+    return pos;
+  }
+
+  public boolean containsPosition(int offset, int length) {
+    int size = nodes.size();
+    if (size == 0) {
+      return false;
+    }
+
+    int index = computeFlatNodeIndex(offset);
+    if (index < size) {
+      FlatNode p = (FlatNode) nodes.get(index);
+
+      while (p.offset == offset) {
+        if (p.length == length) {
+          return true;
+        }
+
+        if (++index < size) {
+          p = (FlatNode) nodes.get(index);
+        } else {
+          break;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Helper method for tracking the minimal region containg all partition changes. If <code>offset</code> is smaller than the
+   * remembered offset, <code>offset</code> will from now on be remembered. If <code>offset + length</code> is greater than the
+   * remembered end offset, it will be remembered from now on.
+   * 
+   * @param offset
+   *          the offset
+   * @param length
+   *          the length
+   */
+  protected final void rememberRegion(int offset, int length) {
+    // remember start offset
+    if (regionStart == -1) {
+      regionStart = offset;
+    } else if (offset < regionStart) {
+      regionStart = offset;
+    }
+
+    // remember end offset
+    int endOffset = offset + length;
+
+    if (regionEnd == -1) {
+      regionEnd = endOffset;
+    } else if (endOffset > regionEnd) {
+      regionEnd = endOffset;
+    }
+  }
+
+  /**
+   * Creates the minimal region containing all partition changes using the remembered offsets.
+   * 
+   * @return the minimal region containing all the partition changes
+   */
+  protected final IRegion createRegion() {
+    if (regionStart == -1 || regionEnd == -1) {
+      return null;
+    }
+
+    return new Region(regionStart, regionEnd - regionStart);
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/FlatNode.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/FlatNode.java
new file mode 100644 (file)
index 0000000..93c6452
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2003-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: FlatNode.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+/**
+ * @author Igor Malinin
+ */
+public class FlatNode {
+
+       /** Content-type of the node */
+       public final String type;
+
+       /** Flat offset of the node */
+       public int offset;
+
+       /** Flat length of the node */
+       public int length;
+
+       public FlatNode(String type) {
+               this.type = type;
+       }
+
+       /**
+        * Checks whether the given offset is inside of this position's text range.
+        * 
+        * @param offset
+        *            the offset to check
+        * @return <code>true</code> if offset is inside of this position
+        */
+       public boolean includes(int offset) {
+               return (this.offset <= offset && offset < this.offset + length);
+       }
+
+       /**
+        * Checks whether the intersection of the given text range and the text
+        * range represented by this position is empty or not.
+        * 
+        * @param offset
+        *            the offset of the range to check
+        * @param length
+        *            the length of the range to check
+        * @return <code>true</code> if intersection is not empty
+        */
+       public boolean overlapsWith(int offset, int length) {
+               int end = offset + length;
+               int thisEnd = this.offset + this.length;
+
+               if (length > 0) {
+                       if (this.length > 0) {
+                               return (this.offset < end && offset < thisEnd);
+                       }
+                       return (offset <= this.offset && this.offset < end);
+               }
+
+               if (this.length > 0) {
+                       return (this.offset <= offset && offset < thisEnd);
+               }
+
+               return (this.offset == offset);
+       }
+
+       /*
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return "FlatNode[" + type + ", " + offset + ", " + length + "]";
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/IDocumentView.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/IDocumentView.java
new file mode 100644 (file)
index 0000000..2ec3410
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: IDocumentView.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * View to part of parent document. Provides methods for translating character
+ * offsets between this view and parent document.
+ * 
+ * @author Igor Malinin
+ */
+public interface IDocumentView extends IDocument {
+
+       IDocument getParentDocument();
+
+       int getParentOffset(int localOffset);
+
+       int getLocalOffset(int parentOffset);
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/InnerDocumentView.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/InnerDocumentView.java
new file mode 100644 (file)
index 0000000..70cb17e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: InnerDocumentView.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+import org.eclipse.jface.text.AbstractDocument;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextStore;
+
+/**
+ * Inner view to parent document.
+ * 
+ * @author Igor Malinin
+ */
+public class InnerDocumentView extends AbstractDocument implements
+               IDocumentView {
+
+       /**
+        * Implements ITextStore based on IDocument.
+        */
+       class TextStore implements ITextStore {
+
+               /*
+                * @see ITextStore#set
+                */
+               public void set(String txt) {
+                       try {
+                               parent.replace(range.offset, range.length, txt);
+                       } catch (BadLocationException x) {
+                       }
+               }
+
+               /*
+                * @see ITextStore#replace
+                */
+               public void replace(int offset, int length, String txt) {
+                       try {
+                               parent.replace(range.offset + offset, length, txt);
+                       } catch (BadLocationException x) {
+                       }
+               }
+
+               /*
+                * @see ITextStore#getLength
+                */
+               public int getLength() {
+                       return range.length;
+               }
+
+               /*
+                * @see ITextStore#get
+                */
+               public String get(int offset, int length) {
+                       try {
+                               return parent.get(range.offset + offset, length);
+                       } catch (BadLocationException x) {
+                       }
+
+                       return null;
+               }
+
+               /*
+                * @see ITextStore#get
+                */
+               public char get(int offset) {
+                       try {
+                               return parent.getChar(range.offset + offset);
+                       } catch (BadLocationException x) {
+                       }
+
+                       return (char) 0;
+               }
+       }
+
+       /** The parent document */
+       IDocument parent;
+
+       /** The section inside the parent document */
+       ViewNode range;
+
+       /**
+        * Constructs inner view to parent document.
+        * 
+        * @param parent
+        *            parent document
+        * @param range
+        */
+       public InnerDocumentView(IDocument parent, ViewNode range) {
+               this.parent = parent;
+               this.range = range;
+
+               setTextStore(new TextStore());
+               setLineTracker(new DefaultLineTracker());
+               getTracker().set(getStore().get(0, getLength()));
+               completeInitialization();
+       }
+
+       /*
+        * @see net.sourceforge.phpeclipse.text.rules.IDocumentView#getParentDocument()
+        */
+       public IDocument getParentDocument() {
+               return parent;
+       }
+
+       /*
+        * @see org.eclipse.jface.text.AbstractDocument#fireDocumentAboutToBeChanged(DocumentEvent)
+        */
+       protected void fireDocumentAboutToBeChanged(DocumentEvent event) {
+               super.fireDocumentAboutToBeChanged(event);
+       }
+
+       /*
+        * @see org.eclipse.jface.text.AbstractDocument#fireDocumentChanged(DocumentEvent)
+        */
+       protected void fireDocumentChanged(DocumentEvent event) {
+               try {
+                       // TODO: move to a better place
+                       getTracker().replace(event.getOffset(), event.getLength(),
+                                       event.getText());
+               } catch (BadLocationException x) {
+               }
+
+               super.fireDocumentChanged(event);
+       }
+
+       /*
+        * @see net.sf.wdte.text.rules.IDocumentView#getParentOffset(int)
+        */
+       public int getParentOffset(int localOffset) {
+               return localOffset + range.offset;
+       }
+
+       /*
+        * @see net.sf.wdte.text.rules.IDocumentView#getLocalOffset(int)
+        */
+       public int getLocalOffset(int parentOffset) {
+               return parentOffset - range.offset;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/MultiViewPartitioner.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/MultiViewPartitioner.java
new file mode 100644 (file)
index 0000000..c5aa8ec
--- /dev/null
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: MultiViewPartitioner.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IDocumentPartitioningListener;
+import org.eclipse.jface.text.IDocumentPartitioningListenerExtension;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.TypedRegion;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+
+/**
+ * Advanced partitioner which maintains partitions as views to connected document. Views have own partitioners themselves. This
+ * class is designed as a base for complex partitioners such as for JSP, PHP, ASP, etc. languages.
+ * 
+ * @author Igor Malinin
+ */
+public abstract class MultiViewPartitioner extends AbstractPartitioner {
+
+  class ViewListener implements IDocumentPartitioningListener, IDocumentPartitioningListenerExtension {
+
+    /*
+     * @see org.eclipse.jface.text.IDocumentPartitioningListener#documentPartitioningChanged(IDocument)
+     */
+    public void documentPartitioningChanged(IDocument document) {
+      IDocumentView view = (IDocumentView) document;
+
+      int start = view.getParentOffset(0);
+      int end = view.getParentOffset(view.getLength());
+
+      rememberRegion(start, end - start);
+    }
+
+    /*
+     * @see org.eclipse.jface.text.IDocumentPartitioningListenerExtension#documentPartitioningChanged(IDocument, IRegion)
+     */
+    public void documentPartitioningChanged(IDocument document, IRegion region) {
+      IDocumentView view = (IDocumentView) document;
+
+      int offset = region.getOffset();
+
+      int start = view.getParentOffset(offset);
+      int end = view.getParentOffset(offset + region.getLength());
+
+      rememberRegion(start, end - start);
+    }
+  }
+
+  private ViewListener viewListener = new ViewListener();
+
+  private OuterDocumentView outerDocument;
+
+  private DocumentEvent outerDocumentEvent;
+
+  public MultiViewPartitioner(IPartitionTokenScanner scanner) {
+    super(scanner);
+  }
+
+  public void setOuterPartitioner(IDocumentPartitioner partitioner) {
+    if (outerDocument == null) {
+      if (partitioner == null) {
+        return;
+      }
+
+      outerDocument = new OuterDocumentView(document, nodes);
+      outerDocument.addDocumentPartitioningListener(viewListener);
+    }
+
+    IDocumentPartitioner old = outerDocument.getDocumentPartitioner();
+    if (old != null) {
+      outerDocument.setDocumentPartitioner(null);
+      old.disconnect();
+    }
+
+    if (partitioner != null) {
+      partitioner.connect(outerDocument);
+    }
+
+    outerDocument.setDocumentPartitioner(partitioner);
+
+    if (partitioner == null) {
+      outerDocument.removeDocumentPartitioningListener(viewListener);
+      outerDocument = null;
+    }
+  }
+
+  /**
+   * Create subpartitioner.
+   * 
+   * @param contentType
+   *          name of inner partition or <code>null</code> for outer partition
+   */
+  protected abstract IDocumentPartitioner createPartitioner(String contentType);
+
+  protected void addInnerRegion(FlatNode position) {
+    if (outerDocument != null) {
+      if (DEBUG) {
+        Assert.isTrue(position.offset >= 0, Integer.toString(position.offset));
+      }
+      DocumentEvent event = new DocumentEvent(outerDocument, outerDocument.getLocalOffset(position.offset), position.length, null);
+
+      outerDocument.fireDocumentAboutToBeChanged(event);
+      super.addInnerRegion(position);
+      outerDocument.fireDocumentChanged(event);
+    } else {
+      super.addInnerRegion(position);
+    }
+
+    if (position instanceof ViewNode) {
+      // TODO: revisit condition
+      IDocumentPartitioner partitioner = createPartitioner(position.type);
+      if (partitioner != null) {
+        InnerDocumentView innerDocument = new InnerDocumentView(document, (ViewNode) position);
+
+        ((ViewNode) position).view = innerDocument;
+
+        partitioner.connect(innerDocument);
+        innerDocument.setDocumentPartitioner(partitioner);
+        innerDocument.addDocumentPartitioningListener(viewListener);
+      }
+    }
+  }
+
+  protected void removeInnerRegion(FlatNode position) {
+    try {
+      if (outerDocument != null) {
+        DocumentEvent event = null;
+        if (position.offset >= 0) {
+          event = new DocumentEvent(outerDocument, outerDocument.getLocalOffset(position.offset), 0, document.get(position.offset,
+              position.length));
+
+          outerDocument.fireDocumentAboutToBeChanged(event);
+        }
+        super.removeInnerRegion(position);
+        if (position.offset >= 0) {
+          outerDocument.fireDocumentChanged(event);
+        }
+      } else {
+        super.removeInnerRegion(position);
+      }
+
+      if (position instanceof ViewNode) {
+        // TODO: revisit condition
+        InnerDocumentView innerDocument = ((ViewNode) position).view;
+        if (innerDocument != null) {
+          IDocumentPartitioner partitioner = innerDocument.getDocumentPartitioner();
+
+          innerDocument.removeDocumentPartitioningListener(viewListener);
+          innerDocument.setDocumentPartitioner(null);
+          partitioner.disconnect();
+        }
+      }
+    } catch (BadLocationException e) {
+    }
+  }
+
+  protected void deleteInnerRegion(FlatNode position) {
+    super.deleteInnerRegion(position);
+
+    if (position instanceof ViewNode) {
+      // TODO: revisit condition
+      InnerDocumentView innerDocument = ((ViewNode) position).view;
+      if (innerDocument != null) {
+        IDocumentPartitioner partitioner = innerDocument.getDocumentPartitioner();
+
+        innerDocument.removeDocumentPartitioningListener(viewListener);
+        innerDocument.setDocumentPartitioner(null);
+        partitioner.disconnect();
+      }
+    }
+  }
+
+  public void connect(IDocument document) {
+    //         outerDocument = new OuterDocumentView(document, innerPositions);
+
+    super.connect(document);
+
+    setOuterPartitioner(createPartitioner(null));
+    //         IDocumentPartitioner partitioner =
+    //                 partitioner.connect(outerDocument);
+    //         outerDocument.setDocumentPartitioner(partitioner);
+    //         outerDocument.addDocumentPartitioningListener(viewListener);
+  }
+
+  public void disconnect() {
+    try {
+      if (outerDocument != null) {
+        outerDocument.removeDocumentPartitioningListener(viewListener);
+
+        IDocumentPartitioner partitioner = outerDocument.getDocumentPartitioner();
+
+        outerDocument.setDocumentPartitioner(null);
+        partitioner.disconnect();
+      }
+    } finally {
+      // TODO: cleanup listeners
+      outerDocument = null;
+    }
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#documentAboutToBeChanged(DocumentEvent)
+   */
+  public void documentAboutToBeChanged(DocumentEvent event) {
+    super.documentAboutToBeChanged(event);
+
+    outerDocumentEvent = null;
+
+    int offset = event.getOffset();
+    int length = event.getLength();
+    int end = offset + length;
+
+    // find left partition
+    int first = computeFlatNodeIndex(offset);
+    if (first > 0) {
+      FlatNode p = (FlatNode) nodes.get(first - 1);
+
+      int right = p.offset + p.length;
+      if (offset < right) {
+        // change overlaps with partition
+        InnerDocumentView innerDocument = null;
+        if (p instanceof ViewNode) {
+          // TODO: revisit condition
+          innerDocument = ((ViewNode) p).view;
+        }
+
+        if (end < right) {
+          if (innerDocument != null) {
+            // cahnge completely inside partition
+            int start = innerDocument.getLocalOffset(offset);
+            innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, start, length, event.getText()));
+          }
+
+          return;
+        }
+
+        if (innerDocument != null) {
+          // cut partition at right
+          int start = innerDocument.getLocalOffset(offset);
+          innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, start, innerDocument.getLength() - start,
+              null));
+        }
+      }
+    }
+
+    // find right partition
+    int last = computeFlatNodeIndex(end);
+    if (last > 0) {
+      FlatNode p = (FlatNode) nodes.get(last - 1);
+
+      if (p instanceof ViewNode) {
+        // TODO: revisit condition
+        InnerDocumentView innerDocument = ((ViewNode) p).view;
+        if (innerDocument != null) {
+          int right = p.offset + p.length;
+          if (end < right) {
+            // cut partition at left
+            int cut = innerDocument.getLocalOffset(end);
+            innerDocument.fireDocumentAboutToBeChanged(new DocumentEvent(innerDocument, 0, cut, null));
+          }
+        }
+      }
+    }
+
+    if (outerDocument != null) {
+      int left = outerDocument.getLocalOffset(offset);
+      int right = outerDocument.getLocalOffset(end);
+
+      String text = event.getText();
+
+      if (left != right || text != null && text.length() > 0) {
+        outerDocumentEvent = new DocumentEvent(outerDocument, left, right - left, text);
+
+        outerDocument.fireDocumentAboutToBeChanged(outerDocumentEvent);
+      }
+    }
+  }
+
+  protected int fixupPartitions(DocumentEvent event) {
+    int offset = event.getOffset();
+    int length = event.getLength();
+    int end = offset + length;
+
+    // fixup/notify inner views laying on change boundaries
+
+    int first = computeFlatNodeIndex(offset);
+    if (first > 0) {
+      FlatNode p = (FlatNode) nodes.get(first - 1);
+
+      int right = p.offset + p.length;
+      if (offset < right) {
+        // change overlaps with partition
+        if (end < right) {
+          // cahnge completely inside partition
+          String text = event.getText();
+          p.length -= length;
+          if (text != null) {
+            p.length += text.length();
+          }
+
+          if (p instanceof ViewNode) {
+            // TODO: revisit condition
+            InnerDocumentView innerDocument = ((ViewNode) p).view;
+            if (innerDocument != null) {
+              int start = innerDocument.getLocalOffset(offset);
+              innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, start, length, text));
+            }
+          }
+        } else {
+          // cut partition at right
+          int cut = p.offset + p.length - offset;
+          p.length -= cut;
+
+          if (p instanceof ViewNode) {
+            // TODO: revisit condition
+            InnerDocumentView innerDocument = ((ViewNode) p).view;
+            if (innerDocument != null) {
+              int start = innerDocument.getLocalOffset(offset);
+              // TODO: ???fireDocumentAboutToBeChanged???
+              innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, start, cut, null));
+            }
+          }
+        }
+      }
+    }
+
+    int last = computeFlatNodeIndex(end);
+    if (last > 0 && first != last) {
+      FlatNode p = (FlatNode) nodes.get(last - 1);
+
+      int right = p.offset + p.length;
+      if (end < right) {
+        // cut partition at left
+        int cut = end - p.offset;
+        p.length -= cut;
+        p.offset = offset;
+
+        String text = event.getText();
+        if (text != null) {
+          p.offset += text.length();
+        }
+
+        if (p instanceof ViewNode) {
+          // TODO: revisit condition
+          InnerDocumentView innerDocument = ((ViewNode) p).view;
+          if (innerDocument != null) {
+            // TODO: ???fireDocumentAboutToBeChanged???
+            innerDocument.fireDocumentChanged(new DocumentEvent(innerDocument, 0, cut, null));
+          }
+        }
+
+        --last;
+      }
+    }
+
+    // fixup inner views laying afrer change
+
+    String text = event.getText();
+    if (text != null) {
+      length -= text.length();
+    }
+
+    for (int i = last, size = nodes.size(); i < size; i++) {
+      ((FlatNode) nodes.get(i)).offset -= length;
+    }
+
+    // delete inner views laying completely inside change boundaries
+
+    if (first < last) {
+      do {
+        deleteInnerRegion((FlatNode) nodes.get(--last));
+      } while (first < last);
+
+      rememberRegion(offset, 0);
+    }
+
+    // notify outer view
+
+    if (outerDocumentEvent != null) {
+      outerDocument.fireDocumentChanged(outerDocumentEvent);
+    }
+
+    return first;
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int, int)
+   */
+  protected String getContentType(String parent, String view) {
+    if (view != null) {
+      return view;
+    }
+
+    if (parent != null) {
+      return parent;
+    }
+
+    return IDocument.DEFAULT_CONTENT_TYPE;
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#computePartitioning(int, int)
+   */
+  public ITypedRegion[] computePartitioning(int offset, int length) {
+    List list = new ArrayList();
+
+    int end = offset + length;
+
+    int index = computeFlatNodeIndex(offset);
+    while (true) {
+      FlatNode prev = (index > 0) ? (FlatNode) nodes.get(index - 1) : null;
+
+      if (prev != null) {
+        if (prev.overlapsWith(offset, length)) {
+          addInnerPartitions(list, offset, length, prev);
+        }
+
+        if (end <= prev.offset + prev.length) {
+          break;
+        }
+      }
+
+      FlatNode next = (index < nodes.size()) ? (FlatNode) nodes.get(index) : null;
+
+      if (next == null || offset < next.offset) {
+        addOuterPartitions(list, offset, length, prev, next);
+      }
+
+      if (next == null) {
+        break;
+      }
+
+      ++index;
+    }
+
+    return (TypedRegion[]) list.toArray(new TypedRegion[list.size()]);
+  }
+
+  private void addOuterPartitions(List list, int offset, int length, FlatNode prev, FlatNode next) {
+    // limit region
+    int start = offset;
+    int end = offset + length;
+
+    if (prev != null && start < prev.offset + prev.length) {
+      start = prev.offset + prev.length;
+    }
+
+    if (next != null && next.offset < end) {
+      end = next.offset;
+    }
+
+    if (start == end) {
+      return;
+    }
+
+    if (outerDocument == null) {
+      list.add(new TypedRegion(start, end - start, getContentType(null, IDocument.DEFAULT_CONTENT_TYPE)));
+      return;
+    }
+
+    try {
+      // convert to outer offsets
+      start = outerDocument.getLocalOffset(start);
+      end = outerDocument.getLocalOffset(end);
+      if (end - start >= 0) {//jsurfer insert line
+        ITypedRegion[] regions = outerDocument.computePartitioning(start, end - start);
+
+        for (int i = 0; i < regions.length; i++) {
+          ITypedRegion region = regions[i];
+
+          // convert back to parent offsets
+          start = outerDocument.getParentOffset(region.getOffset());
+          end = start + region.getLength();
+
+          if (prev != null) {
+            offset = prev.offset + prev.length;
+            if (start < offset) {
+              start = offset;
+            }
+          }
+
+          if (next != null) {
+            offset = next.offset;
+            if (offset < end) {
+              end = offset;
+            }
+          }
+
+          list.add(new TypedRegion(start, end - start, getContentType(null, region.getType())));
+        }
+      }
+    } catch (BadLocationException x) {
+    }
+  }
+
+  private void addInnerPartitions(List list, int offset, int length, FlatNode position) {
+    InnerDocumentView innerDocument = null;
+    if (position instanceof ViewNode) {
+      // TODO: revisit condition
+      innerDocument = ((ViewNode) position).view;
+    }
+
+    if (innerDocument == null) {
+      // simple partition
+      list.add(new TypedRegion(position.offset, position.length, getContentType(position.type, null)));
+      return;
+    }
+
+    // multiplexing to inner view
+    try {
+      // limit region
+      int start = Math.max(offset, position.offset);
+      int end = Math.min(offset + length, position.offset + position.length);
+
+      // convert to document offsets
+      length = end - start;
+      offset = innerDocument.getLocalOffset(start);
+
+      ITypedRegion[] regions = innerDocument.computePartitioning(offset, length);
+
+      for (int i = 0; i < regions.length; i++) {
+        ITypedRegion region = regions[i];
+
+        // convert back to parent offsets
+        offset = innerDocument.getParentOffset(region.getOffset());
+        length = region.getLength();
+
+        list.add(new TypedRegion(offset, length, getContentType(position.type, region.getType())));
+      }
+    } catch (BadLocationException x) {
+    }
+  }
+
+  /*
+   * @see org.eclipse.jface.text.IDocumentPartitioner#getPartition(int)
+   */
+  public ITypedRegion getPartition(int offset) {
+    if (nodes.size() == 0) {
+      return getOuterPartition(offset, null, null);
+    }
+
+    int index = computeFlatNodeIndex(offset);
+    if (index < nodes.size()) {
+      FlatNode next = (FlatNode) nodes.get(index);
+
+      if (offset == next.offset) {
+        return getInnerPartition(offset, next);
+      }
+
+      if (index == 0) {
+        return getOuterPartition(offset, null, next);
+      }
+
+      FlatNode prev = (FlatNode) nodes.get(index - 1);
+
+      if (prev.includes(offset)) {
+        return getInnerPartition(offset, prev);
+      }
+
+      return getOuterPartition(offset, prev, next);
+    }
+
+    FlatNode prev = (FlatNode) nodes.get(nodes.size() - 1);
+
+    if (prev.includes(offset)) {
+      return getInnerPartition(offset, prev);
+    }
+
+    return getOuterPartition(offset, prev, null);
+  }
+
+  protected ITypedRegion getOuterPartition(int offset, FlatNode prev, FlatNode next) {
+    try {
+      int start, end;
+      String type;
+
+      if (outerDocument == null) {
+        start = 0;
+        end = document.getLength();
+        type = getContentType(null, IDocument.DEFAULT_CONTENT_TYPE);
+      } else {
+        ITypedRegion region = outerDocument.getPartition(outerDocument.getLocalOffset(offset));
+
+        start = region.getOffset();
+        end = start + region.getLength();
+
+        // convert to parent offset
+        start = outerDocument.getParentOffset(start);
+        end = outerDocument.getParentOffset(end);
+
+        type = getContentType(null, region.getType());
+      }
+
+      if (prev != null) {
+        offset = prev.offset + prev.length;
+        if (start < offset) {
+          start = offset;
+        }
+      }
+
+      if (next != null) {
+        offset = next.offset;
+        if (offset < end) {
+          end = offset;
+        }
+      }
+
+      return new TypedRegion(start, end - start, type);
+    } catch (BadLocationException x) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  protected ITypedRegion getInnerPartition(int offset, FlatNode position) {
+    if (position instanceof ViewNode) {
+      // TODO: revisit condition
+      InnerDocumentView innerDocument = ((ViewNode) position).view;
+
+      if (innerDocument != null) {
+        // multiplexing to inner view
+        try {
+          // convert to inner offset
+          ITypedRegion region = innerDocument.getPartition(innerDocument.getLocalOffset(offset));
+
+          // convert to parent offset
+          offset = innerDocument.getParentOffset(region.getOffset());
+
+          return new TypedRegion(offset, region.getLength(), getContentType(position.type, region.getType()));
+        } catch (BadLocationException x) {
+        }
+      }
+    }
+
+    // simple partition
+    return new TypedRegion(position.offset, position.length, position.type);
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/OuterDocumentView.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/OuterDocumentView.java
new file mode 100644 (file)
index 0000000..c438031
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: OuterDocumentView.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.AbstractDocument;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextStore;
+
+/**
+ * Outer view to parent document.
+ * 
+ * @author Igor Malinin
+ */
+public class OuterDocumentView extends AbstractDocument implements
+               IDocumentView {
+
+       /**
+        * Implements ITextStore based on IDocument.
+        */
+       class TextStore implements ITextStore {
+
+               /*
+                * @see ITextStore#set
+                */
+               public void set(String txt) {
+                       try {
+                               parent.replace(0, parent.getLength(), txt);
+                       } catch (BadLocationException x) {
+                               // cannot happen
+                       }
+               }
+
+               /*
+                * @see ITextStore#replace
+                */
+               public void replace(int offset, int length, String txt) {
+                       try {
+                               int start = getParentOffset(offset);
+                               int end = getParentOffset(offset + length - 1) + 1;
+
+                               parent.replace(start, end - start, txt);
+                       } catch (BadLocationException x) {
+                               // ignored as surrounding document should have handled this
+                       }
+               }
+
+               /*
+                * @see ITextStore#getLength
+                */
+               public int getLength() {
+                       int length = parent.getLength();
+
+                       Iterator i = ranges.iterator();
+                       while (i.hasNext()) {
+                               length -= ((FlatNode) i.next()).length;
+                       }
+
+                       return length;
+               }
+
+               /*
+                * @see ITextStore#get
+                */
+               public String get(int offset, int length) {
+                       StringBuffer buf = new StringBuffer(length);
+
+                       try {
+                               FlatNode range = null;
+
+                               Iterator i = ranges.iterator();
+                               while (i.hasNext()) {
+                                       range = (FlatNode) i.next();
+
+                                       if (offset < range.offset) {
+                                               break;
+                                       }
+
+                                       offset += range.length;
+
+                                       range = null;
+                               }
+
+                               int remainder = length - buf.length();
+                               while (remainder > 0) {
+                                       if (range == null || offset + remainder < range.offset) {
+                                               buf.append(parent.get(offset, remainder));
+                                               break;
+                                       }
+
+                                       buf.append(parent.get(offset, range.offset - offset));
+                                       offset = range.offset + range.length;
+                                       range = i.hasNext() ? (FlatNode) i.next() : null;
+
+                                       remainder = length - buf.length();
+                               }
+                       } catch (BadLocationException x) {
+                               return null;
+                       }
+
+                       return buf.toString();
+               }
+
+               /*
+                * @see ITextStore#get
+                */
+               public char get(int offset) {
+                       try {
+                               return parent.getChar(getParentOffset(offset));
+                       } catch (BadLocationException x) {
+                       }
+
+                       return (char) 0;
+               }
+       }
+
+       /** The parent document */
+       IDocument parent;
+
+       /** The section inside the parent document */
+       List ranges;
+
+       /**
+        * Constructs outer view to parent document.
+        * 
+        * @param parent
+        *            parent document
+        */
+       public OuterDocumentView(IDocument parent, List ranges) {
+               this.parent = parent;
+               this.ranges = ranges;
+
+               setTextStore(new TextStore());
+               setLineTracker(new DefaultLineTracker());
+               getTracker().set(getStore().get(0, getLength()));
+
+               completeInitialization();
+       }
+
+//     public void addRange(Position range) {
+//             DocumentEvent event = new DocumentEvent(this,
+//                     getLocalOffset(range.offset), range.length, "");
+//             fireDocumentAboutToBeChanged(event);
+//             ranges.add(-getIndex(range) - 1, range);
+//             fireDocumentChanged(event);
+//     }
+//
+//     public void removeRange(Position range) {
+//             String text;
+//             try {
+//                     text = parent.get(range.offset, range.length);
+//             } catch (BadLocationException e) {
+//                     return;
+//             }
+//             DocumentEvent event = new DocumentEvent(this,
+//                     getLocalOffset(range.offset), 0, text);
+//             fireDocumentAboutToBeChanged(event);
+//             deleteRange(range);
+//             fireDocumentChanged(event);
+//     }
+//
+//     public void deleteRange(Position range) {
+//             ranges.remove(getIndex(range));
+//     }
+//
+//     private int getIndex(Position range) {
+//             return Collections.binarySearch(ranges, range, new Comparator() {
+//                     public int compare(Object o1, Object o2) {
+//                             int offset1 = ((Position) o1).offset;
+//                             int offset2 = ((Position) o2).offset;
+//
+//                             if (offset1 < offset2) return -1;
+//                             if (offset1 > offset2) return 1;
+//                             return 0;
+//                     }
+//             });
+//     }
+
+       /*
+        * @see org.eclipse.jface.text.AbstractDocument#fireDocumentAboutToBeChanged(DocumentEvent)
+        */
+       protected void fireDocumentAboutToBeChanged(DocumentEvent event) {
+               super.fireDocumentAboutToBeChanged(event);
+       }
+
+       /*
+        * @see org.eclipse.jface.text.AbstractDocument#fireDocumentChanged(DocumentEvent)
+        */
+       protected void fireDocumentChanged(DocumentEvent event) {
+               try {
+                       // TODO: move to a better place
+                       getTracker().replace(event.getOffset(), event.getLength(),
+                                       event.getText());
+               } catch (BadLocationException x) {
+               }
+
+               super.fireDocumentChanged(event);
+       }
+
+       /*
+        * @see net.sourceforge.phpeclipse.text.rules.IDocumentView#getParentDocument()
+        */
+       public IDocument getParentDocument() {
+               return parent;
+       }
+
+       /*
+        * @see net.sourceforge.phpeclipse.text.rules.IDocumentView#getParentOffset(int)
+        */
+       public int getParentOffset(int localOffset) {
+               int offset = localOffset;
+
+               Iterator i = ranges.iterator();
+               while (i.hasNext()) {
+                       FlatNode range = (FlatNode) i.next();
+
+                       if (offset < range.offset) {
+                               break;
+                       }
+
+                       offset += range.length;
+               }
+
+               return offset;
+       }
+
+       /*
+        * @see net.sf.wdte.text.rules.IDocumentView#getLocalOffset(int)
+        */
+       public int getLocalOffset(int parentOffset) {
+//         Assert.isTrue(parentOffset>=0);
+               int localOffset = parentOffset;
+
+               Iterator i = ranges.iterator();
+               while (i.hasNext()) {
+                       FlatNode range = (FlatNode) i.next();
+
+                       if (parentOffset <= range.offset) {
+                               break;
+                       }
+
+                       if (parentOffset <= range.offset + range.length) {
+                               localOffset -= parentOffset - range.offset;
+                               break;
+                       }
+
+                       localOffset -= range.length;
+               }
+               // TODO jsurfer change start - check this
+//        if (localOffset<0) {
+//          return 0;
+//        }
+        // jsurfer change end
+               return localOffset;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/ViewNode.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/rules/ViewNode.java
new file mode 100644 (file)
index 0000000..ef5ab0e
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: ViewNode.java,v 1.1 2004-09-02 18:26:29 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.rules;
+
+/**
+ * @author Igor Malinin
+ */
+public class ViewNode extends FlatNode {
+
+       /** Inner view of the document */
+       public InnerDocumentView view;
+
+       public ViewNode(String type) {
+               super(type);
+       }
+
+       /*
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               return "ViewNode[" + type + ", " + offset + ", " + length + "]";
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/source/DefaultSourceViewerConfiguration.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/text/source/DefaultSourceViewerConfiguration.java
new file mode 100644 (file)
index 0000000..7e7309b
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2002-2004 Widespace, OU and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://solareclipse.sourceforge.net/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Igor Malinin - initial contribution
+ * 
+ * $Id: DefaultSourceViewerConfiguration.java,v 1.1 2004-09-02 18:26:32 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.text.source;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+/**
+ * @author Igor Malinin
+ */
+public class DefaultSourceViewerConfiguration extends SourceViewerConfiguration {
+
+       /** Preference key used to look up display tab width. */
+       public static final String PREFERENCE_TAB_WIDTH =
+               "net.sourceforge.phpeclipse.ui.editor.tabWidth"; //$NON-NLS-1$
+
+       /** Preference key for inserting spaces rather than tabs. */
+       public static final String PREFERENCE_SPACES_FOR_TABS =
+               "net.sourceforge.phpeclipse.ui.editor.spacesForTabs"; //$NON-NLS-1$
+
+       private IPreferenceStore store;
+
+       public DefaultSourceViewerConfiguration(IPreferenceStore store) {
+               this.store = store;
+       }
+
+       /*
+        * @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String)
+        */
+       public String[] getIndentPrefixes(ISourceViewer sourceViewer,
+                       String contentType) {
+               // prefix[0] is either '\t' or ' ' x tabWidth, depending on useSpaces
+
+               int tabWidth = store.getInt(PREFERENCE_TAB_WIDTH);
+               boolean useSpaces = store.getBoolean(PREFERENCE_SPACES_FOR_TABS);
+
+               String[] prefixes = new String[tabWidth + 1];
+
+               for (int i = 0; i <= tabWidth; i++) {
+                       StringBuffer prefix = new StringBuffer(tabWidth - 1);
+
+                       if (useSpaces) {
+                               for (int j = 0; j + i < tabWidth; j++) {
+                                       prefix.append(' ');
+                               }
+
+                               if (i != 0) {
+                                       prefix.append('\t');
+                               }
+                       } else {
+                               for (int j = 0; j < i; j++) {
+                                       prefix.append(' ');
+                               }
+
+                               if (i != tabWidth) {
+                                       prefix.append('\t');
+                               }
+                       }
+
+                       prefixes[i] = prefix.toString();
+               }
+
+               prefixes[tabWidth] = ""; //$NON-NLS-1$
+
+               return prefixes;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ModelBasedOutlinePage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ModelBasedOutlinePage.java
new file mode 100644 (file)
index 0000000..8f9fda4
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial implementation
+ * 
+ * $Id: ModelBasedOutlinePage.java,v 1.1 2004-09-02 18:26:28 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.outline;
+
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceModel;
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.ui.editor.StructuredTextEditor;
+import net.sourceforge.phpeclipse.ui.internal.WebUIMessages;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.ResourceAction;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * 
+ */
+public class ModelBasedOutlinePage extends ContentOutlinePage
+       implements IUpdate {
+
+       // Inner Classes -----------------------------------------------------------
+
+       public class ContentProvider implements ITreeContentProvider {
+
+               /*
+                * ITreeContentProvider#getChildren(Object)
+                */
+               public Object[] getChildren(Object parentElement) {
+                       if (parentElement instanceof ISourceReference) {
+                               return model.getChildren((ISourceReference) parentElement);
+                       }
+                       return new Object[0];
+               }
+
+               /*
+                * @see ITreeContentProvider#getParent(Object)
+                */
+               public Object getParent(Object element) {
+                       if (element instanceof ISourceReference) {
+                               return model.getParent((ISourceReference) element);
+                       }
+                       return null;
+               }
+
+               /*
+                * @see ITreeContentProvider#hasChildren(Object)
+                */
+               public boolean hasChildren(Object element) {
+                       return getChildren(element).length > 0;
+               }
+
+               /*
+                * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(Object)
+                */
+               public Object[] getElements(Object inputElement) {
+                       return model.getElements();
+               }
+
+               /* 
+                * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+                */
+               public void dispose() {
+               }
+
+               /*
+                * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object)
+                */
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+                       if (oldInput != newInput) {
+                               if (newInput instanceof ISourceModel) {
+                                       model = (ISourceModel) newInput;
+                               }          
+                       }
+               }
+
+       }
+
+       /**
+        * This action toggles whether this outline page links its selection
+        * to the active editor.
+        */
+       private class ToggleLinkingAction extends ResourceAction {
+               
+               /**
+                * Constructs a new action.
+                */
+               public ToggleLinkingAction() {
+                       super(WebUIMessages.getResourceBundle(),
+                               "OutlinePage.linkWithEditor."); //$NON-NLS-1$
+                       if ((preferenceStore != null)
+                        && (linkWithEditorPreferenceKey != null)) {
+                               boolean checked = preferenceStore.getBoolean(
+                                               linkWithEditorPreferenceKey);
+                               valueChanged(checked, false);
+                       } else {
+                               setEnabled(false);
+                       }
+               }
+
+               /*
+                * @see org.eclipse.jface.action.Action#run()
+                */
+               public void run() {
+                       if ((preferenceStore != null)
+                        && (linkWithEditorPreferenceKey != null)) {
+                               valueChanged(isChecked(), true);
+                       }
+               }
+       
+               // Private Methods -----------------------------------------------------
+
+               /**
+                * Updates whether the outline page is linked to the active editor.
+                * 
+                * @param checked Whether linking is enabled
+                * @param store Whether the new state should be written back as a 
+                *        preference
+                */
+               private void valueChanged(final boolean checked, boolean store) {
+                       setChecked(checked);
+                       BusyIndicator.showWhile(getTreeViewer().getControl().getDisplay(),
+                               new Runnable() {
+                                       public void run() {
+                                               editor.synchronizeOutlinePage();
+                                       }
+                               });
+                       if (store) {
+                               preferenceStore.setValue(
+                                       linkWithEditorPreferenceKey, checked);
+                       }
+               }
+
+       }
+
+       // Instance Variables ------------------------------------------------------
+
+       /**
+        * The associated editor.
+        */
+       private StructuredTextEditor editor;
+
+       /**
+        * The structured source model.
+        */
+       private ISourceModel model;
+
+       /**
+        * The preference store.
+        */
+       private IPreferenceStore preferenceStore;
+
+       /**
+        * The preference key which specifies whether the outline page is linked to
+        * the active editor.
+        */
+       private String linkWithEditorPreferenceKey;
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Constructor.
+        * 
+        * @param editor The associated structured text editor
+        */
+       public ModelBasedOutlinePage(StructuredTextEditor editor) {
+               this.editor = editor;
+       }
+
+       // ContentOutlinePage Implementation ---------------------------------------
+
+       /*
+        * @see org.eclipse.ui.part.IPage#createControl(Composite)
+        */
+       public void createControl(Composite parent) {
+               super.createControl(parent);
+               TreeViewer viewer = getTreeViewer();
+               viewer.setContentProvider(new ContentProvider());
+       }
+
+       /*
+        * @see org.eclipse.ui.part.IPage#dispose()
+        */
+       public void dispose() {
+               if (editor != null) {
+                       editor.outlinePageClosed();
+                       editor = null;
+               }
+               super.dispose();
+       }
+
+       /*
+        * @see org.eclipse.ui.part.Page#makeContributions(IMenuManager, IToolBarManager, IStatusLineManager)
+        */
+       public void makeContributions(IMenuManager menuManager,
+               IToolBarManager toolBarManager, IStatusLineManager statusLineManager) {
+               if (toolBarManager != null) {
+                       toolBarManager.add(new ToggleLinkingAction());
+               }
+               super.makeContributions(menuManager, toolBarManager, statusLineManager);
+       }
+
+       // IUpdate Implementation --------------------------------------------------
+
+       /**
+        * @see IUpdate#update()
+        */
+       public void update() {
+               ISourceModel model = editor.getSourceModel();
+               if (model != null) {
+                       TreeViewer viewer = getTreeViewer();
+                       if (viewer != null) {
+                               Control control = viewer.getControl();
+                               if ((control != null) && !control.isDisposed()) {
+                                       control.setRedraw(false);
+                                       viewer.setInput(model);
+                                       viewer.expandAll();
+                                       control.setRedraw(true);
+                               }
+                       }
+               }
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Selects a specific element in the outline page.
+        * 
+        * @param element the element to select
+        */
+       public void select(ISourceReference element) {
+               TreeViewer viewer = getTreeViewer();
+               if (viewer != null) {
+                       ISelection selection = viewer.getSelection();
+                       if (selection instanceof IStructuredSelection) {
+                               IStructuredSelection structuredSelection =
+                                       (IStructuredSelection) selection;
+                               List elements = structuredSelection.toList();
+                               if (!elements.contains(element)) {
+                                       if (element == null) {
+                                               selection = StructuredSelection.EMPTY;
+                                       } else {
+                                               selection = new StructuredSelection(element);
+                                       }
+                                       viewer.setSelection(selection, true);
+                               }
+                       }
+               }
+       }
+
+       // Protected Methods -------------------------------------------------------
+
+       protected final StructuredTextEditor getEditor() {
+               return editor;
+       }
+
+       protected final void setPreferenceStore(IPreferenceStore store) {
+               preferenceStore = store;
+       }
+
+       protected final void setLinkWithEditorPreferenceKey(String key) {
+               linkWithEditorPreferenceKey = key;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ProblemsLabelDecorator.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/ProblemsLabelDecorator.java
new file mode 100644 (file)
index 0000000..72a211b
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial implementation
+ * 
+ * $Id: ProblemsLabelDecorator.java,v 1.1 2004-09-02 18:26:28 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.outline;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.views.util.ImageDescriptorRegistry;
+import net.sourceforge.phpeclipse.ui.views.util.ImageImageDescriptor;
+import net.sourceforge.phpeclipse.ui.views.util.OverlayImageDescriptor;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Label decorator for the outline page that adds error and warning overlay
+ * icons to elements in the outline. The information is retrieved from the 
+ * annotation model corresponding to the input of the associated text editor.
+ */
+public class ProblemsLabelDecorator extends LabelProvider
+       implements ILabelDecorator {
+
+       // Constants ---------------------------------------------------------------
+
+       private static final String ANNOTATION_TYPE_ERROR =
+               "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$
+
+       private static final String ANNOTATION_TYPE_WARNING =
+               "org.eclipse.ui.workbench.texteditor.warning"; //$NON-NLS-1$
+
+       // Instance Variables ------------------------------------------------------
+
+       /** The associated text editor if the decorator is used in the outline. */
+       private ITextEditor editor;
+
+       /** Registry of icons and overlay icons. */
+       private ImageDescriptorRegistry registry = new ImageDescriptorRegistry();
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Constructor.
+        * 
+        * @param editor the associated text editor
+        */
+       public ProblemsLabelDecorator(ITextEditor editor) {
+               this.editor = editor;
+       }
+
+       // ILabelDecorator Implementation ------------------------------------------
+
+       /* 
+        * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+        */
+       public void dispose() {
+               super.dispose();
+               registry.dispose();
+       }
+
+       /* 
+        * @see ILabelDecorator#decorateImage(Image, Object)
+        */
+       public Image decorateImage(Image image, Object element) {
+               Annotation annotations[] =
+                       getAssociatedAnnotations((ISourceReference) element);
+               ImageDescriptor overlay = null;
+               for (int i = 0; i < annotations.length; i++) {
+                       if (isError(annotations[i])) {
+                               overlay = WebUI.getDefault().getImageRegistry().getDescriptor(
+                                               WebUI.ICON_OVERLAY_ERROR);
+                       } else if (isWarning(annotations[i])) {
+                               overlay = WebUI.getDefault().getImageRegistry().getDescriptor(
+                                               WebUI.ICON_OVERLAY_WARNING);
+                       }
+               }
+               if (overlay != null) {
+                       ImageDescriptor base = new ImageImageDescriptor(image);
+                       return registry.get(new OverlayImageDescriptor(base,
+                                       new ImageDescriptor[][] { null, null, { overlay }, null },
+                                       null));
+               } else {
+               }
+               return image;
+       }
+
+       /* 
+        * @see ILabelDecorator#decorateText(String, Object)
+        */
+       public String decorateText(String text, Object element) {
+               return text;
+       }
+
+       // Private Methods ---------------------------------------------------------
+
+       /**
+        * Returns all annotations associated with the given model element.
+        * 
+        * @param element the model element for which annotations should be
+        *        collected
+        * @return an array containing all annotations for the given element, or an
+        *         empty array if no annotations are found
+        */
+       private Annotation[] getAssociatedAnnotations(ISourceReference element) {
+               List retVal = new ArrayList();
+               if (editor != null) {
+                       IEditorInput input = editor.getEditorInput();
+                       IAnnotationModel model =
+                               editor.getDocumentProvider().getAnnotationModel(input);
+                       for (Iterator i = model.getAnnotationIterator(); i.hasNext(); ) {
+                               Annotation annotation = (Annotation) i.next();
+                               Position pos = model.getPosition(annotation);
+                               if (pos!=null && isInside(pos.getOffset(), element)) {
+                                       retVal.add(annotation);
+                               }
+                       }
+               }
+               return (Annotation[]) retVal.toArray(new Annotation[retVal.size()]);
+       }
+
+       /**
+        * Determines whether the given annotation is an error.
+        * 
+        * @param annotation the annotation to check
+        * @return <tt>true</tt> if the annotation is to be displayed as an error,
+        *         <tt>false</tt> otherwise
+        */
+       private boolean isError(Annotation annotation) {
+               return ANNOTATION_TYPE_ERROR.equals(annotation.getType());
+       }
+
+       /**
+        * Determines whether the given annotation is a warning.
+        * 
+        * @param annotation the annotation to check
+        * @return <tt>true</tt> if the annotation is to be displayed as a warning,
+        *         <tt>false</tt> otherwise
+        */
+       private boolean isWarning(Annotation annotation) {
+               return ANNOTATION_TYPE_WARNING.equals(annotation.getType());
+       }
+
+       /**
+        * Tests if the given position is inside the source region of a model
+        * element.
+        * 
+        * @param pos the position to be tested
+        * @param element the source element
+        * @return boolean <tt>true</tt> if position is located inside the
+        *         element, otherwise <tt>false</tt>
+        */
+       private boolean isInside(int pos, ISourceReference element) {
+               IRegion region = element.getSourceRegion();
+               if (region != null) {
+                       int offset = region.getOffset();
+                       return ((offset <= pos) && (offset + region.getLength() > pos));                        
+               }
+               return false;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/link_editor.gif b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/link_editor.gif
new file mode 100644 (file)
index 0000000..f865f3a
Binary files /dev/null and b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/outline/link_editor.gif differ
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/BrowserPreview.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/BrowserPreview.java
new file mode 100644 (file)
index 0000000..f4e0247
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API and implementation
+ * 
+ * $Id: BrowserPreview.java,v 1.1 2004-09-02 18:26:31 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.preview;
+
+import net.sourceforge.phpeclipse.ui.internal.WebUIMessages;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.part.IPage;
+import org.eclipse.ui.part.IPageBookViewPage;
+import org.eclipse.ui.part.MessagePage;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.part.PageBookView;
+
+/**
+ * 
+ */
+public class BrowserPreview extends PageBookView {
+
+       /* 
+        * @see PageBookView#createDefaultPage(org.eclipse.ui.part.PageBook)
+        */
+       protected IPage createDefaultPage(PageBook book) {
+               MessagePage page = new MessagePage();
+               page.createControl(book);
+               page.setMessage(WebUIMessages.getString(
+                               "BrowserPreview.notAvailable")); //$NON-NLS-1$);
+               return page;
+       }
+
+       /* 
+        * @see PageBookView#doCreatePage(org.eclipse.ui.IWorkbenchPart)
+        */
+       protected PageRec doCreatePage(IWorkbenchPart part) {
+               // Try to get an outline page.
+               Object adapter = part.getAdapter(IBrowserPreviewPage.class);
+               if (adapter instanceof IBrowserPreviewPage) {
+                       IBrowserPreviewPage page = (IBrowserPreviewPage) adapter;
+                       if (page instanceof IPageBookViewPage) {
+                               initPage((IPageBookViewPage) page);
+                       }
+                       page.createControl(getPageBook());
+                       return new PageRec(part, page);
+               }
+               // There is no preview
+               return null;
+       }
+
+       /* 
+        * @see PageBookView#doDestroyPage(IWorkbenchPart, PageBookView.PageRec)
+        */
+       protected void doDestroyPage(IWorkbenchPart part, PageRec pageRecord) {
+               IBrowserPreviewPage page = (IBrowserPreviewPage) pageRecord.page;
+               page.dispose();
+               pageRecord.dispose();
+       }
+
+       /* 
+        * @see PageBookView#getBootstrapPart()
+        */
+       protected IWorkbenchPart getBootstrapPart() {
+               IWorkbenchPage page = getSite().getPage();
+               if (page != null) {
+                       return page.getActiveEditor();
+               }
+               return null;
+       }
+
+       /* 
+        * @see PageBookView#isImportant(IWorkbenchPart)
+        */
+       protected boolean isImportant(IWorkbenchPart part) {
+               return (part instanceof IEditorPart);
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/IBrowserPreviewPage.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/preview/IBrowserPreviewPage.java
new file mode 100644 (file)
index 0000000..e076e50
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial implementation
+ * 
+ * $Id: IBrowserPreviewPage.java,v 1.1 2004-09-02 18:26:31 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.preview;
+
+import org.eclipse.ui.part.IPage;
+
+/**
+ * 
+ */
+public interface IBrowserPreviewPage extends IPage {
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageDescriptorRegistry.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageDescriptorRegistry.java
new file mode 100644 (file)
index 0000000..c3b15af
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial implementation based on the internal Eclipse
+ *                        class of the same name, defined in multiple packages
+ * 
+ * $Id: ImageDescriptorRegistry.java,v 1.1 2004-09-02 18:26:28 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Registry that keeps a table of image descriptors and the images created from
+ * those descriptors.
+ */
+public class ImageDescriptorRegistry {
+
+       /**
+        * Stores all registered image descriptors as keys, and the images created
+        * from them as values.
+        */
+       private Map registry = new HashMap(10);
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Creates a new image descriptor registry for the current or default
+        * display, respectively.
+        */
+       public ImageDescriptorRegistry() {
+               this(Display.getCurrent() != null ?
+                               Display.getCurrent() : Display.getDefault());
+       }
+
+       /**
+        * Creates a new image descriptor registry for the given display. All images
+        * managed by this registry will be disposed when the display gets disposed.
+        * 
+        * @param display the display the images managed by this registry are
+        *        allocated for 
+        */
+       public ImageDescriptorRegistry(Display display) {
+               display.disposeExec(new Runnable() {
+                       public void run() {
+                               dispose();
+                       }       
+               });
+       }
+       
+       /**
+        * Returns the image assiciated with the given image descriptor.
+        * 
+        * @param descriptor the image descriptor for which the registry manages an
+        *        image
+        * @return the image associated with the image descriptor or <tt>null</tt>
+        *         if the image descriptor can't create the requested image.
+        */
+       public Image get(ImageDescriptor descriptor) {
+               if (descriptor == null) {
+                       descriptor = ImageDescriptor.getMissingImageDescriptor();
+               }
+               Image result = (Image) registry.get(descriptor);
+               if (result == null) {
+                       result = descriptor.createImage();
+                       if (result != null) {
+                               registry.put(descriptor, result);
+                       }
+               }
+               return result;
+       }
+
+       /**
+        * Disposes all images managed by this registry.
+        */     
+       public void dispose() {
+               for (Iterator i = registry.values().iterator(); i.hasNext(); ) {
+                       ((Image) i.next()).dispose();
+               }
+               registry.clear();
+       }
+       
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageImageDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/ImageImageDescriptor.java
new file mode 100644 (file)
index 0000000..e1af923
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial version based on the Eclipse class of the same
+ *                        name in org.eclipse.jdt.internal.ui.viewsupport
+ * 
+ * $Id: ImageImageDescriptor.java,v 1.1 2004-09-02 18:26:28 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.util;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+
+/**
+ * <tt>ImageDescriptor</tt> implementation that wraps an existing {@link Image}.
+ */
+public class ImageImageDescriptor extends ImageDescriptor {
+
+       // Instance Variables ------------------------------------------------------
+
+       /** The wrapped image. */
+       private Image image;
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Constructor.
+        * 
+        * @param image the image to wrap
+        */
+       public ImageImageDescriptor(Image image) {
+               this.image= image;
+       }
+
+       // ImageDescriptor Implementation ------------------------------------------
+
+       /*
+        * @see ImageDescriptor#getImageData()
+        */
+       public ImageData getImageData() {
+               return image.getImageData();
+       }
+
+       /*
+        * @see Object#equals(Object)
+        */
+       public boolean equals(Object o) {
+               if (o instanceof ImageImageDescriptor) {
+                       ImageImageDescriptor other = (ImageImageDescriptor) o;
+                       if (image.equals(other.image)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /*
+        * @see Object#hashCode()
+        */
+       public int hashCode() {
+               return image.hashCode();
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/OverlayImageDescriptor.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpeclipse/ui/views/util/OverlayImageDescriptor.java
new file mode 100644 (file)
index 0000000..e9e995a
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial version based on the internal Eclipse class
+ *                        org.eclipse.ui.internal.ide.misc.OverlayIcon
+ * 
+ * $Id: OverlayImageDescriptor.java,v 1.1 2004-09-02 18:26:28 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui.views.util;
+
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * An overlay image descriptor can add several overlay icons to a base image.
+ */
+public class OverlayImageDescriptor extends CompositeImageDescriptor {
+
+       // Instance Variables ------------------------------------------------------
+
+       /** Size of the resulting composite image. */
+       private Point size = null;
+
+       /** The base image. */
+       private ImageDescriptor base;
+       
+       /** The overlay images. */
+       private ImageDescriptor overlays[][];
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * Creates the image descriptor. The size of the resulting image will be the
+        * same as the size of the base image.
+        * 
+        * @param base the descriptor of the base image
+        * @param overlays descriptors of the overlay images
+        */
+       public OverlayImageDescriptor(ImageDescriptor base,
+                       ImageDescriptor[][] overlays) {
+               this(base, overlays, null);
+       }
+
+       /**
+        * Creates the image descriptor.
+        * 
+        * @param base the descriptor of the base image
+        * @param overlays descriptors of the overlay images
+        * @param size the size of the composite image, or <tt>null</tt> to use the
+        *        size of the base image
+        */
+       public OverlayImageDescriptor(ImageDescriptor base,
+                       ImageDescriptor[][] overlays, Point size) {
+               this.base = base;
+               this.overlays = overlays;
+               if (size == null) {
+                       ImageData data = base.getImageData();
+                       size = new Point(data.width, data.height); 
+               }
+               this.size = size;
+       }
+
+       // CompositeImageDescriptor Implementation ---------------------------------
+
+       /* 
+        * @see CompositeImageDescriptor#drawCompositeImage(int, int)
+        */
+       protected void drawCompositeImage(int width, int height) {
+               ImageData bg;
+               if ((base == null) || ((bg = base.getImageData()) == null)) {
+                       bg = DEFAULT_IMAGE_DATA;
+               }
+               drawImage(bg, 0, 0);
+               if (overlays != null) {
+                       if (overlays.length > 0) {
+                               drawTopRight(overlays[0]);
+                       }
+                       if (overlays.length > 1) {
+                               drawBottomRight(overlays[1]);
+                       }
+                       if (overlays.length > 2) {
+                               drawBottomLeft(overlays[2]);
+                       }
+                       if (overlays.length > 3) {
+                               drawTopLeft(overlays[3]);
+                       }
+               }
+       }
+
+       /* 
+        * @see CompositeImageDescriptor#getSize()
+        */
+       protected Point getSize() {
+               return size;
+       }
+
+       // Private Methods ---------------------------------------------------------
+
+       private void drawBottomLeft(ImageDescriptor[] descriptors) {
+               if (descriptors == null) {
+                       return;
+               }
+               int length = descriptors.length;
+               int x = 0;
+               for (int i = 0; i < 3; i++) {
+                       if ((i < length) && (descriptors[i] != null)) {
+                               ImageData id = descriptors[i].getImageData();
+                               drawImage(id, x, getSize().y - id.height);
+                               x += id.width;
+                       }
+               }
+       }
+
+       private void drawBottomRight(ImageDescriptor[] descriptors) {
+               if (descriptors == null) {
+                       return;
+               }
+               int length = descriptors.length;
+               int x = getSize().x;
+               for (int i = 2; i >= 0; i--) {
+                       if (i < length && descriptors[i] != null) {
+                               ImageData id = descriptors[i].getImageData();
+                               x -= id.width;
+                               drawImage(id, x, getSize().y - id.height);
+                       }
+               }
+       }
+
+       private void drawTopLeft(ImageDescriptor[] descriptors) {
+               if (descriptors == null) {
+                       return;
+               }
+               int length = descriptors.length;
+               int x = 0;
+               for (int i = 0; i < 3; i++) {
+                       if (i < length && descriptors[i] != null) {
+                               ImageData id = descriptors[i].getImageData();
+                               drawImage(id, x, 0);
+                               x += id.width;
+                       }
+               }
+       }
+
+       private void drawTopRight(ImageDescriptor[] descriptors) {
+               if (descriptors == null) {
+                       return;
+               }
+               int length = descriptors.length;
+               int x = getSize().x;
+               for (int i = 2; i >= 0; i--) {
+                       if (i < length && descriptors[i] != null) {
+                               ImageData id = descriptors[i].getImageData();
+                               x -= id.width;
+                               drawImage(id, x, 0);
+                       }
+               }
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.ui/templates/default-templates.properties b/net.sourceforge.phpeclipse.ui/templates/default-templates.properties
new file mode 100644 (file)
index 0000000..b200f2b
--- /dev/null
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2000, 2004 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
diff --git a/net.sourceforge.phpeclipse.ui/templates/default-templates.xml b/net.sourceforge.phpeclipse.ui/templates/default-templates.xml
new file mode 100644 (file)
index 0000000..43746d5
--- /dev/null
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates>
+<template name="for" description="for array" id="net.sf.wdte.ui.templates.for_array" context="javascript" enabled="true">for (var ${index} = 0; ${index} &lt; ${array}.length; ${index}++) {
+       ${line_selection}${cursor}
+}</template>
+  <template name="xml" description="html page with head,title,body" 
+  id="net.sf.wdte.ui.xml.templates.xml" context="xml" enabled="true">
+&lt;?xml ?&gt;</template> 
+
+  <template name="&lt;html" description="html page with head,title,body" 
+  id="net.sf.wdte.ui.templates.html" context="html" enabled="true">
+&lt;html&gt;
+&lt;head&gt;
+&lt;meta http-equiv="Content-Language" content="en" /&gt;
+&lt;meta name="GENERATOR" content="PHPEclipse 1.0" /&gt;
+&lt;meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /&gt;
+&lt;title&gt;${title}&lt;/title&gt;
+&lt;/head&gt;
+&lt;body bgcolor="#FFFFFF" text="#000000" link="#FF9966" vlink="#FF9966" alink="#FFCC99"&gt;
+${cursor}
+&lt;/body&gt;
+&lt;/html&gt;
+  </template>  
+  <template name="&lt;title" description="title" id="net.sf.wdte.ui.templates.title" context="html" enabled="true">
+  &lt;title&gt;${cursor}&lt;/title&gt;
+  </template> 
+  
+  <template name="&lt;table" description="3x3 table" id="net.sf.wdte.ui.templates.table" context="html" enabled="true">
+  &lt;table&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t00}&lt;/td&gt;&lt;td&gt;${t01}&lt;/td&gt;&lt;td&gt;${t02}&lt;/td&gt;
+    &lt;/tr&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t10}&lt;/td&gt;&lt;td&gt;${t11}&lt;/td&gt;&lt;td&gt;${t12}&lt;/td&gt;
+    &lt;/tr&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t20}&lt;/td&gt;&lt;td&gt;${t21}&lt;/td&gt;&lt;td&gt;${t22}&lt;/td&gt;
+    &lt;/tr&gt;    
+  &lt;/table&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;table" description="3x3 table with header" id="net.sf.wdte.ui.templates.table_header" context="html" enabled="true">
+  &lt;table&gt;
+    &lt;tr&gt;
+      &lt;th&gt;${header0}&lt;/th&gt;&lt;th&gt;${header1}&lt;/th&gt;&lt;th&gt;${header2}&lt;/th&gt;
+    &lt;/tr&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t00}&lt;/td&gt;&lt;td&gt;${t01}&lt;/td&gt;&lt;td&gt;${t02}&lt;/td&gt;
+    &lt;/tr&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t10}&lt;/td&gt;&lt;td&gt;${t11}&lt;/td&gt;&lt;td&gt;${t12}&lt;/td&gt;
+    &lt;/tr&gt;
+    &lt;tr&gt;
+      &lt;td&gt;${t20}&lt;/td&gt;&lt;td&gt;${t21}&lt;/td&gt;&lt;td&gt;${t22}&lt;/td&gt;
+    &lt;/tr&gt;    
+  &lt;/table&gt;
+  ${cursor}
+  </template>
+  
+  <template name="&lt;a" description="hyperlink (href)" id="net.sf.wdte.ui.templates.a" context="html" enabled="true">
+  &lt;a href="${link}"&gt;${description}&lt;/a&gt; ${cursor}
+  </template>  
+  <template name="&lt;a" description="hyperlink image" id="net.sf.wdte.ui.templates.a_image" context="html" enabled="true">
+  &lt;a href="${link}"&gt;&lt;img src="${image}"&gt;&lt;/a&gt; ${cursor}
+  </template> 
+  <template name="&lt;a" description="hyperlink fragment identifier (name)" id="net.sf.wdte.ui.templates.a_anchor" context="html" enabled="true">
+  &lt;a name="${anchor}"&gt;${description}&lt;/a&gt; ${cursor}
+  </template> 
+  <template name="&lt;p" description="paragraph" id="net.sf.wdte.ui.templates.p" context="html" enabled="true">
+  &lt;p&gt;${cursor}&lt;/p&gt;
+  </template>
+  <template name="&lt;h1" description="heading 1" id="net.sf.wdte.ui.templates.h1" context="html" enabled="true">
+  &lt;h1&gt;${cursor}&lt;/h1&gt;
+  </template>
+  <template name="&lt;h2" description="heading 2" id="net.sf.wdte.ui.templates.h2" context="html" enabled="true">
+  &lt;h2&gt;${cursor}&lt;/h2&gt;
+  </template>
+  <template name="&lt;h3" description="heading 3" id="net.sf.wdte.ui.templates.h3" context="html" enabled="true">
+  &lt;h3&gt;${cursor}&lt;/h3&gt;
+  </template>
+  <template name="&lt;h4" description="heading 4" id="net.sf.wdte.ui.templates.h4" context="html" enabled="true">
+  &lt;h4&gt;${cursor}&lt;/h4&gt;
+  </template>
+  <template name="&lt;h5" description="heading 5" id="net.sf.wdte.ui.templates.h5" context="html" enabled="true">
+  &lt;h5&gt;${cursor}&lt;/h5&gt;
+  </template>
+  <template name="&lt;h6" description="heading 6" id="net.sf.wdte.ui.templates.h6" context="html" enabled="true">
+  &lt;h6&gt;${cursor}&lt;/h6&gt;
+  </template>
+  <template name="&lt;address" description="address" id="net.sf.wdte.ui.templates.address" context="html" enabled="true">
+  &lt;address&gt;${cursor}&lt;/address&gt;
+  </template>
+  <template name="&lt;pre" description="preformat" id="net.sf.wdte.ui.templates.pre" context="html" enabled="true">
+  &lt;pre&gt;${cursor}&lt;/pre&gt;
+  </template>
+  <template name="&lt;code" description="code block" id="net.sf.wdte.ui.templates.code" context="html" enabled="true">
+  &lt;code&gt;${cursor}&lt;/code&gt;
+  </template>
+  <template name="&lt;blockquote" description="blockquote" id="net.sf.wdte.ui.templates.blockquote" context="html" enabled="true">
+  &lt;blockquote&gt;${cursor}&lt;br/&gt;
+  &lt;/blockquote&gt;
+  </template>
+  <template name="&lt;hr" description="horizontal line" id="net.sf.wdte.ui.templates.hr" context="html" enabled="true">
+  &lt;hr width="100%" size="2"&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;ul" description="bulleted list" id="net.sf.wdte.ui.templates.ul" context="html" enabled="true">
+  &lt;ul&gt;
+    &lt;li&gt;${item1}&lt;br/&gt;
+    &lt;/li&gt;
+    &lt;li&gt;${item2}&lt;br/&gt;
+    &lt;/li&gt;
+  &lt;/ul&gt;
+  </template>
+  <template name="&lt;ol" description="numbered list" id="net.sf.wdte.ui.templates.ol" context="html" enabled="true">
+  &lt;ol&gt;
+    &lt;li&gt;${item1}&lt;br/&gt;
+    &lt;/li&gt;
+    &lt;li&gt;${item2}&lt;br/&gt;
+    &lt;/li&gt;
+  &lt;/ol&gt;
+  </template>
+  <template name="&lt;dl" description="term list" id="net.sf.wdte.ui.templates.dl_term" context="html" enabled="true">
+  &lt;dl&gt;
+    &lt;dt&gt;${item1}&lt;br/&gt;
+    &lt;/dt&gt;
+    &lt;dt&gt;${item2}&lt;br/&gt;
+    &lt;/dt&gt;
+  &lt;/dl&gt;
+  </template>
+  <template name="&lt;dl" description="definition list" id="net.sf.wdte.ui.templates.dl_list" context="html" enabled="true">
+  &lt;dl&gt;
+    &lt;dd&gt;${item1}&lt;br/&gt;
+    &lt;/dd&gt;
+    &lt;dd&gt;${item2}&lt;br/&gt;
+    &lt;/dd&gt;
+  &lt;/dl&gt;
+  </template>
+  <template name="&lt;form" description="form get" id="net.sf.wdte.ui.templates.form_get" context="html" enabled="true">
+  &lt;form action="${link}" method="${get}"&gt;
+  ${cursor}
+  &lt;/form&gt;
+  </template>
+  <template name="&lt;form" description="form post" id="net.sf.wdte.ui.templates.form_post" context="html" enabled="true">
+  &lt;form action="${link}" method="${post}" enctype="text/plain"&gt;
+  ${cursor}
+  &lt;/form&gt;
+  </template>
+  <template name="&lt;form" description="form upload file" id="net.sf.wdte.ui.templates.form_upload" context="html" enabled="true">
+  &lt;form action="${link}" method="${post}" enctype="multipart/form-data"&gt;
+  &lt;p&gt;${text}&lt;/p&gt;
+  &lt;input type="file" name="${name}" size="50" maxlength="100000" accept="text/*"/&gt;&lt;br/&gt;
+  &lt;input type="submit" value="${value}"/&gt;
+  ${cursor}
+  &lt;/form&gt;
+  </template>
+  <template name="&lt;input" description="input type=text (form)" id="net.sf.wdte.ui.templates.form_input_text" context="html" enabled="true">
+  &lt;input type="text" name="${name}" value="${value}" size="40" maxlength="40"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;input" description="input type=password (form)" id="net.sf.wdte.ui.templates.form_input_password" context="html" enabled="true">
+  &lt;input type="password" name="${name}" size="40" maxlength="40"/&gt;
+  ${cursor}
+  </template>  
+  <template name="&lt;input" description="input type=radio (form)" id="net.sf.wdte.ui.templates.form_input_radio" context="html" enabled="true">
+  &lt;input type="radio" name="${name}" value="${value}"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;input" description="input type=checkbox (form)" id="net.sf.wdte.ui.templates.form_input_checkbox" context="html" enabled="true">
+  &lt;input type="checkbox" name="${name}" value="${value}"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;input" description="input type=button (form button)" id="net.sf.wdte.ui.templates.form_input_button" context="html" enabled="true">
+  &lt;input type="button" name="${name}" value="${value}"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;input" description="input type=submit (form button)" id="net.sf.wdte.ui.templates.form_input_submit" context="html" enabled="true">
+  &lt;input type="submit" name="${name}" value="${value}"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;input" description="input type=reset (form button)" id="net.sf.wdte.ui.templates.form_input_reset" context="html" enabled="true">
+  &lt;input type="reset" name="${name}" value="${value}"/&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;textarea" description="textarea (form)" id="net.sf.wdte.ui.templates.form_input_textarea" context="html" enabled="true">
+  &lt;textarea name="${name}" rows="10" cols="50" wrap="off"&gt;
+  ${text}
+  &lt;/textarea&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;select" description="select option (form)" id="net.sf.wdte.ui.templates.form_input_select" context="html" enabled="true">
+  &lt;select name="${name}" size="3"&gt;
+    &lt;option value="${value1}"&gt;${option1}&lt;/option&gt;
+    &lt;option value="${value2}"&gt;${option2}&lt;/option&gt;
+    &lt;option value="${value3}"&gt;${option3}&lt;/option&gt;
+  &lt;/select&gt;
+  </template>
+  <template name="&lt;xml" description="xml version=1.0" id="net.sf.wdte.ui.templates.xml" context="html" enabled="true">
+  &lt;?xml version="1.0"?&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;xml" description="xml-stylesheet type=text/xsl" id="net.sf.wdte.ui.templates.xml_stylesheet" context="html" enabled="true">
+  &lt;?xml-stylesheet type="text/xsl" href="${url}"&gt;
+  ${cursor}
+  </template>
+  <template name="&lt;script" description="JavaScript inline" id="net.sf.wdte.ui.templates.javascript_inline" context="html" enabled="true">&lt;script language="JavaScript" type="text/javascript"&gt;
+  ${cursor}
+&lt;/script&gt;
+  </template>
+  <template name="&lt;script" description="JavaScript file" id="net.sf.wdte.ui.templates.javascript_file" context="html" enabled="true">&lt;script language="JavaScript" type="text/javascript" src="${jsfile}.js"&gt;&lt;/script&gt;${cursor}
+  </template>
+  <template name="&lt;style" description="style text/css" id="net.sf.wdte.ui.templates.css" context="html" enabled="true">&lt;/style type="text/css"&gt;
+<!--
+  ${cursor}
+-->
+&lt;/style&gt;
+  </template>
+  <template name="&amp;quot" description="quot" id="net.sf.wdte.ui.templates.quot" context="html" enabled="true">&amp;quot;</template>
+  <template name="&amp;amp" description="ampersand" id="net.sf.wdte.ui.templates.ampersand" context="html" enabled="true">&amp;amp;</template>
+  <template name="&amp;lt" description="less than" id="net.sf.wdte.ui.templates.less_than" context="html" enabled="true">&amp;lt;</template>
+  <template name="&amp;gt" description="greater than" id="net.sf.wdte.ui.templates.greater" context="html" enabled="true">&amp;gt;</template>
+  
+  <template name="&amp;nbsp" description="no-break space" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;nbsp;</template>
+  <template name="&amp;iexcl" description="iexcl" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;iexcl;</template>
+  <template name="&amp;cent" description="cent" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;cent;</template>
+  <template name="&amp;pound" description="pound" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;pound;</template>
+  <template name="&amp;curren" description="curren" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;curren;</template>
+  <template name="&amp;yen" description="yen" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;yen;</template>
+  <template name="&amp;brvbar" description="brvbar" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;brvbar;</template>
+  <template name="&amp;brkbar" description="brkbar" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;brkbar;</template>
+  <template name="&amp;sect" description="sect" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;sect;</template>
+  <template name="&amp;uml" description="uml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;uml;</template>
+  <template name="&amp;die" description="die" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;die;</template>
+  <template name="&amp;copy" description="copy" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;copy;</template>
+  <template name="&amp;ordf" description="ordf" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ordf;</template>
+  <template name="&amp;laquo" description="laquo" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;laquo;</template>
+  <template name="&amp;not" description="not" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;not;</template>
+  <template name="&amp;shy" description="shy" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;shy;</template>
+  <template name="&amp;reg" description="reg" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;reg;</template>
+  <template name="&amp;macr" description="macr" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;macr;</template>
+  <template name="&amp;hibar" description="hibar" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;hibar;</template>
+  <template name="&amp;deg" description="deg" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;deg;</template>
+  <template name="&amp;plusmn" description="plusmn" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;plusmn;</template>
+  <template name="&amp;sup2" description="sup2" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;sup2;</template>
+  <template name="&amp;sup3" description="sup3" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;sup3;</template>
+  <template name="&amp;acute" description="acute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;acute;</template>
+  <template name="&amp;micro" description="micro" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;micro;</template>
+  <template name="&amp;para" description="para" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;para;</template>
+  <template name="&amp;middot" description="middot" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;middot;</template>
+  <template name="&amp;cedil" description="cedil" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;cedil;</template>
+  <template name="&amp;sup1" description="sup1" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;sup1;</template>
+  <template name="&amp;ordm" description="ordm" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ordm;</template>
+  <template name="&amp;raquo" description="raquo" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;raquo;</template>
+  <template name="&amp;frac14" description="frac14" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;frac14;</template>
+  <template name="&amp;frac12" description="frac12" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;frac12;</template>
+  <template name="&amp;frac34" description="frac34" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;frac34;</template>
+  <template name="&amp;iquest" description="iquest" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;iquest;</template>
+  <template name="&amp;Agrave" description="Agrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Agrave;</template>
+  <template name="&amp;Aacute" description="Aacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Aacute;</template>
+  <template name="&amp;Acirc" description="Acirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Acirc;</template>
+  <template name="&amp;Atilde" description="Atilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Atilde;</template>
+  <template name="&amp;Auml" description="Auml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Auml;</template>
+  <template name="&amp;Aring" description="Aring" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Aring;</template>
+  <template name="&amp;AElig" description="AElig" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;AElig;</template>
+  <template name="&amp;Ccedil" description="Ccedil" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ccedil;</template>
+  <template name="&amp;Egrave" description="Egrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Egrave;</template>
+  <template name="&amp;Eacute" description="Eacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Eacute;</template>
+  <template name="&amp;Ecirc" description="Ecirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ecirc;</template>
+  <template name="&amp;Euml" description="Euml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Euml;</template>
+  <template name="&amp;lgrave" description="lgrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;lgrave;</template>
+  <template name="&amp;lacute" description="lacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;lacute;</template>
+  <template name="&amp;lcirc" description="lcirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;lcirc;</template>
+  <template name="&amp;luml" description="luml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;luml;</template>
+  <template name="&amp;ETH" description="ETH" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ETH;</template>
+  <template name="&amp;Ntilde" description="Ntilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ntilde;</template>
+  <template name="&amp;Ograve" description="Ograve" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ograve;</template>
+  <template name="&amp;Oacute" description="Oacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Oacute;</template>
+  <template name="&amp;Ocirc" description="Ocirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ocirc;</template>
+  <template name="&amp;Otilde" description="Otilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Otilde;</template>
+  <template name="&amp;Ouml" description="Ouml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ouml;</template>
+  <template name="&amp;times" description="times" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;times;</template>
+  <template name="&amp;Oslash" description="Oslash" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Oslash;</template>
+  <template name="&amp;Ugrave" description="Ugrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ugrave;</template>
+  <template name="&amp;Uacute" description="Uacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Uacute;</template>
+  <template name="&amp;Ucirc" description="Ucirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Ucirc;</template>
+  <template name="&amp;Uuml" description="Uuml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Uuml;</template>
+  <template name="&amp;Yacute" description="Yacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;Yacute;</template>
+  <template name="&amp;THORN" description="THORN" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;THORN;</template>
+  <template name="&amp;szlig" description="szlig" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;szlig;</template>
+  <template name="&amp;agrave" description="agrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;agrave;</template>
+  <template name="&amp;aacute" description="aacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;aacute;</template>
+  <template name="&amp;acirc" description="acirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;acirc;</template>
+  <template name="&amp;atilde" description="atilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;atilde;</template>
+  <template name="&amp;auml" description="auml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;auml;</template>
+  <template name="&amp;aring" description="aring" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;aring;</template>
+  <template name="&amp;aelig" description="aelig" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;aelig;</template>
+  <template name="&amp;ccedil" description="ccedil" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ccedil;</template>
+  <template name="&amp;egrave" description="egrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;egrave;</template>
+  <template name="&amp;eacute" description="eacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;eacute;</template>
+  <template name="&amp;ecirc" description="ecirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ecirc;</template>
+  <template name="&amp;euml" description="euml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;euml;</template>
+  <template name="&amp;igrave" description="igrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;igrave;</template>
+  <template name="&amp;iacute" description="iacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;iacute;</template>
+  <template name="&amp;icirc" description="icirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;icirc;</template>
+  <template name="&amp;iuml" description="iuml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;iuml;</template>
+  <template name="&amp;eth" description="eth" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;eth;</template>
+  <template name="&amp;ntilde" description="ntilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ntilde;</template>
+  <template name="&amp;ograve" description="ograve" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ograve;</template>
+  <template name="&amp;oacute" description="oacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;oacute;</template>
+  <template name="&amp;ocirc" description="ocirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ocirc;</template>
+  <template name="&amp;otilde" description="otilde" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;otilde;</template>
+  <template name="&amp;ouml" description="ouml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ouml;</template>
+  <template name="&amp;divide" description="divide" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;divide;</template>
+  <template name="&amp;oslash" description="oslash" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;oslash;</template>
+  <template name="&amp;ugrave" description="ugrave" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ugrave;</template>
+  <template name="&amp;uacute" description="uacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;uacute;</template>
+  <template name="&amp;ucirc" description="ucirc" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;ucirc;</template>
+  <template name="&amp;uuml" description="uuml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;uuml;</template>
+  <template name="&amp;yacute" description="yacute" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;yacute;</template>
+  <template name="&amp;thorn" description="thorn" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;thorn;</template>
+  <template name="&amp;yuml" description="yuml" id="net.sf.wdte.ui.templates." context="html" enabled="true">&amp;yuml;</template>
+
+  <template name="#00FFFF" description="Aqua (Color Code)" id="net.sf.wdte.ui.templates.aqua" context="html" enabled="true">#00FFFF</template>
+  <template name="#000000" description="Black (Color Code)" id="net.sf.wdte.ui.templates.black" context="html" enabled="true">#000000</template>
+  <template name="#0000FF" description="Blue (Color Code)" id="net.sf.wdte.ui.templates.blue" context="html" enabled="true">#0000FF</template>
+  <template name="#A52A2A" description="Brown (Color Code)" id="net.sf.wdte.ui.templates.brown" context="html" enabled="true">#A52A2A</template>
+  <template name="#00FFFF" description="Cyan (Color Code)" id="net.sf.wdte.ui.templates.cyan" context="html" enabled="true">#00FFFF</template>
+  <template name="#FF00FF" description="Fuchsia (Color Code)" id="net.sf.wdte.ui.templates.fuchsia" context="html" enabled="true">#FF00FF</template>
+  <template name="#FFD700" description="Gold (Color Code)" id="net.sf.wdte.ui.templates.gold" context="html" enabled="true">#FFD700</template>
+  <template name="#808080" description="Gray (Color Code)" id="net.sf.wdte.ui.templates.gray" context="html" enabled="true">#808080</template>
+  <template name="#008000" description="Green (Color Code)" id="net.sf.wdte.ui.templates.green" context="html" enabled="true">#008000</template>
+  <template name="#00FF00" description="Lime (Color Code)" id="net.sf.wdte.ui.templates.lime" context="html" enabled="true">#00FF00</template>
+  <template name="#FF00FF" description="Magenta (Color Code)" id="net.sf.wdte.ui.templates.magenta" context="html" enabled="true">#FF00FF</template>
+  <template name="#800000" description="Maroon (Color Code)" id="net.sf.wdte.ui.templates.maroon" context="html" enabled="true">#800000</template>
+  <template name="#000080" description="Navy (Color Code)" id="net.sf.wdte.ui.templates.navy" context="html" enabled="true">#000080</template>
+  <template name="#808000" description="Olive (Color Code)" id="net.sf.wdte.ui.templates.olive" context="html" enabled="true">#808000</template>
+  <template name="#FFA500" description="Orange (Color Code)" id="net.sf.wdte.ui.templates.orange" context="html" enabled="true">#FFA500</template>
+  <template name="#FFC0CB" description="Pink (Color Code)" id="net.sf.wdte.ui.templates.pink" context="html" enabled="true">#FFC0CB</template>
+  <template name="#800080" description="Purple (Color Code)" id="net.sf.wdte.ui.templates.purple" context="html" enabled="true">#800080</template>
+  <template name="#FF0000" description="Red (Color Code)" id="net.sf.wdte.ui.templates.red" context="html" enabled="true">#FF0000</template>
+  <template name="#C0C0C0" description="Silver (Color Code)" id="net.sf.wdte.ui.templates.silver" context="html" enabled="true">#C0C0C0</template>
+  <template name="#008080" description="Teal (Color Code)" id="net.sf.wdte.ui.templates.teal" context="html" enabled="true">#008080</template>
+  <template name="#FFFFFF" description="White (Color Code)" id="net.sf.wdte.ui.templates.white" context="html" enabled="true">#FFFFFF</template>
+  <template name="#FFFF00" description="Yellow (Color Code)" id="net.sf.wdte.ui.templates.yellow" context="html" enabled="true">#FFFF00</template>
+
+  <template name="Aqua" description="Aqua (Color Code)" id="net.sf.wdte.ui.templates.ccaqua" context="html" enabled="true">#00FFFF</template>
+  <template name="Black" description="Black (Color Code)" id="net.sf.wdte.ui.templates.ccblack" context="html" enabled="true">#000000</template>
+  <template name="Blue" description="Blue (Color Code)" id="net.sf.wdte.ui.templates.ccblue" context="html" enabled="true">#0000FF</template>
+  <template name="Brown" description="Brown (Color Code)" id="net.sf.wdte.ui.templates.ccbrown" context="html" enabled="true">#A52A2A</template>
+  <template name="Cyan" description="Cyan (Color Code)" id="net.sf.wdte.ui.templates.cccyan" context="html" enabled="true">#00FFFF</template>
+  <template name="Fuchsia" description="Fuchsia (Color Code)" id="net.sf.wdte.ui.templates.ccfuchsia" context="html" enabled="true">#FF00FF</template>
+  <template name="Gold" description="Gold (Color Code)" id="net.sf.wdte.ui.templates.ccgold" context="html" enabled="true">#FFD700</template>
+  <template name="Gray" description="Gray (Color Code)" id="net.sf.wdte.ui.templates.ccgray" context="html" enabled="true">#808080</template>
+  <template name="Green" description="Green (Color Code)" id="net.sf.wdte.ui.templates.ccgreen" context="html" enabled="true">#008000</template>
+  <template name="Lime" description="Lime (Color Code)" id="net.sf.wdte.ui.templates.cclime" context="html" enabled="true">#00FF00</template>
+  <template name="Magenta" description="Magenta (Color Code)" id="net.sf.wdte.ui.templates.ccmagenta" context="html" enabled="true">#FF00FF</template>
+  <template name="Maroon" description="Maroon (Color Code)" id="net.sf.wdte.ui.templates.ccmaroon" context="html" enabled="true">#800000</template>
+  <template name="Navy" description="Mavy (Color Code)" id="net.sf.wdte.ui.templates.ccnavy" context="html" enabled="true">#000080</template>
+  <template name="Olive" description="Olive (Color Code)" id="net.sf.wdte.ui.templates.ccolive" context="html" enabled="true">#808000</template>
+  <template name="Orange" description="Orange (Color Code)" id="net.sf.wdte.ui.templates.ccorange" context="html" enabled="true">#FFA500</template>
+  <template name="Pink" description="Pink (Color Code)" id="net.sf.wdte.ui.templates.ccpink" context="html" enabled="true">#FFC0CB</template>
+  <template name="Purple" description="Purple (Color Code)" id="net.sf.wdte.ui.templates.ccpurple" context="html" enabled="true">#800080</template>
+  <template name="Red" description="Red (Color Code)" id="net.sf.wdte.ui.templates.ccred" context="html" enabled="true">#FF0000</template>
+  <template name="Silver" description="Silver (Color Code)" id="net.sf.wdte.ui.templates.ccsilver" context="html" enabled="true">#C0C0C0</template>
+  <template name="Teal" description="Teal (Color Code)" id="net.sf.wdte.ui.templates.ccteal" context="html" enabled="true">#008080</template>
+  <template name="White" description="White (Color Code)" id="net.sf.wdte.ui.templates.ccwhite" context="html" enabled="true">#FFFFFF</template>
+  <template name="Yellow" description="Yellow (Color Code)" id="net.sf.wdte.ui.templates.ccyellow" context="html" enabled="true">#FFFF00</template>
+  <template name="&lt;br&gt;" description="&lt;br&gt;" id="net.sf.wdte.ui.templates.br" context="html" enabled="true">&lt;br/&gt;${cursor}</template>
+  <template name="&lt;div&gt;" description="div block with id" id="net.sf.wdte.ui.templates.div" context="html" enabled="true">&lt;div id=&quot;${id}&quot;&gt;${cursor}&lt;/div&gt;</template>
+  <template name="&lt;strong&gt;" description="&lt;strong&gt;" id="net.sf.wdte.ui.templates.strong" context="html" enabled="true">&lt;strong&gt;${cursor}&lt;/strong&gt;</template>
+  <template name="{" description="{* *} (Smarty comment)" id="net.sf.wdte.ui.templates.smarty_comment" context="html" enabled="true">{* ${cursor} *}</template>
+  <template name="{assign" description="{assign var= value= } (Smarty)" id="net.sf.wdte.ui.templates.smarty_assign" context="html" enabled="true">{assign var=&quot;${name}&quot; values=&quot;${value}&quot;}</template>
+  <template name="{capture" description="{capture }{/capture} (Smarty)" id="net.sf.wdte.ui.templates.smarty_capture" context="html" enabled="true">{capture name=${name}}
+${cursor}
+{/capture}</template>
+<template name="{config_load" description="{config_load} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{config_load file=&quot;${file}&quot;}</template>
+<template name="{config_load" description="{config_load} with section (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{config_load file=&quot;${file}&quot; section=&quot;${section}&quot;}</template>
+<template name="{counter" description="{counter start= skip= print= } (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{counter start=${start} skip=${skip} print=false}</template>
+<template name="{counter" description="{counter} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{counter}</template><template name="{cycle" description="{cycle values= } (Smarty)" id="net.sf.wdte.ui.templates." context="html" enabled="true">{cycle values=&quot;${values}&quot;}</template>
+<template name="{eval" description="{eval var=#conf#} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{eval var=#${conf}#}</template>
+<template name="{eval" description="{eval var=$var} (smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{eval var=$$${var}}</template>
+<template name="{fetch" description="{fetch file=} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{fetch file=&quot;${file}&quot;}</template>
+<template name="{foreach" description="{foreach}{/foreach} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item}}
+${cursor}
+{/foreach}</template>
+<template name="{foreach" description="{foreach}{/foreach} with key (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item} key=${key}}
+${cursor}
+{/foreach}</template>
+<template name="{foreach" description="{foreach}{/foreach} with name (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item} name=${name}}
+${cursor}
+{/foreach}</template>
+<template name="{foreach" description="{foreach}{foreachelse}{/foreach} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item}}
+${cursor}
+{foreachelse}
+${cursor}
+{/foreach}</template>
+<template name="{foreach" description="{foreach}{foreachelse}{/foreach} with key (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item} key=${key}}
+${cursor}
+{foreachelse}
+${cursor}
+{/foreach}</template>
+<template name="{foreach" description="{foreach}{foreachelse}{/foreach} with name (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{foreach from=$$${from} item=${item} name=${name}}
+${cursor}
+{foreachelse}
+${cursor}
+{/foreach}</template>
+<template name="{if" description="{if}{/if} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{if $$${var}}${cursor}{/if}</template><template name="{if" description="{if}{elseif}{/if} (Smarty)" id="net.sf.wdte.ui.templates." context="html" enabled="true">{if $$${var}}
+${cursor}
+{elseif $$${var2}}
+
+{/if}</template><template name="{if" description="{if}{elseif}{else}{/if} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{if $$${var}}
+${cursor}
+{elseif $$${var2}}
+
+{else}
+
+{/if}</template>
+<template name="{if" description="{if}{else}{/if} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{if $$${var}}
+${cursor}
+{else}
+
+{/if}</template><template name="{include" description="{include file=&quot;&quot;} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{include file=&quot;${file}&quot;}</template>
+<template name="{include_php" description="{include_php file=&quot;&quot;} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{include_php file=&quot;${file}&quot;}</template>
+<template name="{ldelim}" description="{ldelim} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{ldelim}</template>
+<template name="{literal" description="{literal}{/literal} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{literal}
+${cursor}
+{/literal}</template>
+<template name="{rdelim}" description="{rdelim} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{rdelim}</template>
+<template name="{section" description="{section }{/section} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{section name=${name} loop=$$${loop}}
+${cursor}
+{/section}</template><template name="{section" description="{section}{sectionelse}{/section} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{section name=${name} loop=$$${loop}}
+${cursor}
+{sectionelse}
+
+{/section}</template><template name="{smarty.cookies.var}" description="{$smarty.cookies.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.cookies.${var}}</template>
+<template name="{smarty.env.var}" description="{$smarty.env.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.env.${var}}</template>
+<template name="{smarty.get.var}" description="{$smarty.get.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.get.${var}}</template>
+<template name="{smarty.now|date_format}" description="{$smarty.now|date_format} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.now|date_format:&quot;%Y-%m-%d %H:%M:%S&quot;}</template>
+<template name="{smarty.now}" description="{$smarty.now} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.now}</template>
+<template name="{smarty.post.var}" description="{$smarty.post.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.post.${var}}</template>
+<template name="{smarty.request.var}" description="{$smarty.request.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.request.${var}}</template>
+<template name="{smarty.server.var}" description="{$smarty.server.var} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$smarty.server.${var}}</template>
+<template name="{strip" description="{strip}{/strip} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{strip}
+${cursor}
+{/strip}</template>
+<template name="{var|capitalize}" description="{$var|capitalize} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|capitalize}</template>
+<template name="{var|count_characters}" description="{$var|count_characters} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|count_characters}</template>
+<template name="{var|count_paragraphs}" description="{$var|count_paragraphs} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|count_paragraphs}</template>
+<template name="{var|count_sentences}" description="{$var|count_sentences} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|count_sentences}</template>
+<template name="{var|count_words}" description="{$var|count_words} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|count_words}</template>
+<template name="{var|date_format}" description="{$var|date_format} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|date_format:&quot;%Y-%m-%d %H:%M:%S&quot;}</template>
+<template name="{var|default}" description="{$var|default} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|default:&quot;${text}&quot;}</template>
+<template name="{var|escape:value}" description="{$var|escape:value} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|escape:&quot;${value}&quot;}</template>
+<template name="{var|escape}" description="{$var|escape} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|escape}</template>
+<template name="{var|indent:nr}" description="{$var|indent:nr} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|indent:${nr}}</template>
+<template name="{var|indent}" description="{$var|indent} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|indent}</template>
+<template name="{var|lower}" description="{$var|lower} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|lower}</template>
+<template name="{var|nl2br}" description="{$var|nl2br} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|nl2br}</template>
+<template name="{var|regex_replace}" description="{$var|regex_replace} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|regex_replace:&quot;${regex}&quot;:&quot;${replace}&quot;}</template>
+<template name="{var|replace}" description="{$var|replace} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|replace:&quot;${find}&quot;:&quot;${replace}&quot;}</template>
+<template name="{var|spacify}" description="{$var|spacify} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|spacify}</template>
+<template name="{var|string_format}" description="{$var|string_format} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|string_format:&quot;%.2f&quot;}</template>
+<template name="{var|strip_tags}" description="{$var|strip_tags} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|strip_tags}</template>
+<template name="{var|strip}" description="{$var|strip} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|strip}</template>
+<template name="{var|truncate}" description="{$var|truncate} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|truncate:${nr}}</template>
+<template name="{var|upper}" description="{$var|upper} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|upper}</template>
+<template name="{var|wordwrap}" description="{$var|wordwrap} (Smarty)" id="net.sf.wdte.ui.templates.smarty_" context="html" enabled="true">{$$${var}|wordwrap:${nr}:&quot;${sign}&quot;}</template>
+</templates>
\ No newline at end of file
index d09433b..2554e9e 100644 (file)
@@ -5,7 +5,7 @@
   name="%pluginName"
   version="3.0.0"
   provider-name="%providerName"
-  class="org.eclipse.webbrowser.internal.WebBrowserUIPlugin">
+  class="net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserUIPlugin">
 
   <requires>
     <import plugin="org.eclipse.core.resources" version="3.0.0" match="equivalent"/>
@@ -18,7 +18,7 @@
   <runtime>
     <library name="webbrowser.jar">
       <export name="*"/>
-      <packages prefixes="org.eclipse.webbrowser"/>
+      <packages prefixes="net.sourceforge.phpeclipse.webbrowser"/>
     </library>
   </runtime>
 
 
   <extension point="org.eclipse.ui.actionSets">
     <actionSet
-      id="org.eclipse.webbrowser.actionSet"
+      id="net.sourceforge.phpeclipse.webbrowser.actionSet"
       label="%actionSetWebBrowserTitle"
       visible="false">
       <action
-        id="org.eclipse.webbrowser.action.open"
+        id="net.sourceforge.phpeclipse.webbrowser.action.open"
         toolbarPath="browser"
         label="%actionSetOpenWebBrowser"
         tooltip="%actionSetOpenWebBrowser"
         icon="icons/obj16/internal_browser.gif"
-        class="org.eclipse.webbrowser.OpenBrowserWorkbenchAction"/>
+        class="net.sourceforge.phpeclipse.webbrowser.OpenBrowserWorkbenchAction"/>
       <action
-        id="org.eclipse.webbrowser.action.switch"
+        id="net.sourceforge.phpeclipse.webbrowser.action.switch"
         menubarPath="window/browser"
         label="%actionSetSwitchBrowser"
         tooltip="%actionSetSwitchBrowser"
         style="pulldown"
-        class="org.eclipse.webbrowser.internal.SwitchBrowserWorkbenchAction"/>
+        class="net.sourceforge.phpeclipse.webbrowser.internal.SwitchBrowserWorkbenchAction"/>
     </actionSet>
   </extension>
 
     <page
       id="org.eclipse.internet"
       name="%preferenceInternetTitle"
-      class="org.eclipse.webbrowser.internal.InternetPreferencePage"/>
+      class="net.sourceforge.phpeclipse.webbrowser.internal.InternetPreferencePage"/>
     <page
-      id="org.eclipse.webbrowser.preferencePage"
+      id="net.sourceforge.phpeclipse.webbrowser.preferencePage"
       name="%preferenceWebBrowserTitle"
       category="org.eclipse.internet"
-      class="org.eclipse.webbrowser.internal.WebBrowserPreferencePage"/>
+      class="net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserPreferencePage"/>
   </extension>
 
   <extension point="net.sourceforge.phpeclipse.webbrowser.urlMap">
     <urlMap
-      id="org.eclipse.webbrowser.standard.urlMap"
-      class="org.eclipse.webbrowser.internal.StandardURLMap"/>
+      id="net.sourceforge.phpeclipse.webbrowser.standard.urlMap"
+      class="net.sourceforge.phpeclipse.webbrowser.internal.StandardURLMap"/>
   </extension>
 
   <extension point="net.sourceforge.phpeclipse.webbrowser.favorites">
     <favorite
-      id="org.eclipse.webbrowser.favorite.eclipse"
+      id="net.sourceforge.phpeclipse.webbrowser.favorite.eclipse"
       name="PHPEclipse"
       url="http://www.phpeclipse.de"
       locked="false"/>
     <favorite
-      id="org.eclipse.webbrowser.favorite.eclipse"
+      id="net.sourceforge.phpeclipse.webbrowser.favorite.eclipse"
       name="Eclipse"
       url="http://www.eclipse.org"
       locked="false"/>
+    <favorite
+      id="net.sourceforge.phpeclipse.webbrowser.favorite.eclipse"
+      name="EclipseProject.de"
+      url="http://www.eclipseproject.de"
+      locked="false"/>
+    <favorite
+      id="net.sourceforge.phpeclipse.webbrowser.favorite.eclipse"
+      name="JSurfer.org"
+      url="http://www.jsurfer.org"
+      locked="false"/>
   </extension>
   
   <extension point="org.eclipse.ui.editors">
-    <editor id="org.eclipse.webbrowser"
+    <editor id="net.sourceforge.phpeclipse.webbrowser"
       name="%viewWebBrowserTitle"
       icon="icons/obj16/internal_browser.gif"
-      class="org.eclipse.webbrowser.internal.WebBrowserEditor"
+      class="net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserEditor"
       extensions="gif,jpg,jpeg,xhtml"
-      contributorClass="org.eclipse.webbrowser.internal.WebBrowserEditorActionBarContributor"/>
+      contributorClass="net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserEditorActionBarContributor"/>
   </extension>
        
   <extension point="org.eclipse.ui.elementFactories">
-    <factory id="org.eclipse.webbrowser.elementFactory"
-       class="org.eclipse.webbrowser.WebBrowserEditorInput"/>
+    <factory id="net.sourceforge.phpeclipse.webbrowser.elementFactory"
+       class="net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput"/>
   </extension>
 
 </plugin>
\ No newline at end of file
@@ -8,11 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
+
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowser;
 
 import org.eclipse.swt.browser.Browser;
 import org.eclipse.swt.widgets.Composite;
-import org.eclipse.webbrowser.internal.WebBrowser;
 /**
  * Web browser widget. Extends the eclipse Browser widget by adding an
  * optional toolbar and statusbar.
@@ -8,7 +8,7 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
 
 import java.net.URL;
 import org.eclipse.ui.IEditorInput;
@@ -26,7 +26,7 @@ public interface IWebBrowserEditorInput extends IEditorInput {
         * given input is being displayed in, or false if it should
         * open up in a new page.
         *
-        * @param input org.eclipse.webbrowser.IWebBrowserEditorInput
+        * @param input net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput
         * @return boolean
         */
        public boolean canReplaceInput(IWebBrowserEditorInput input);
@@ -8,11 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
+
+import net.sourceforge.phpeclipse.webbrowser.WebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
 
 import org.eclipse.jface.action.Action;
-import org.eclipse.webbrowser.WebBrowser;
-import org.eclipse.webbrowser.WebBrowserEditorInput;
 /**
  * Action to open the Web browser.
  */
@@ -8,13 +8,14 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
+
+import net.sourceforge.phpeclipse.webbrowser.WebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
 
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.ui.*;
-import org.eclipse.webbrowser.WebBrowser;
-import org.eclipse.webbrowser.WebBrowserEditorInput;
 /**
  * Action to open the Web broswer.
  */
@@ -8,13 +8,14 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
 
 import java.net.URL;
 import java.util.List;
 
+import net.sourceforge.phpeclipse.webbrowser.internal.*;
+
 import org.eclipse.swt.widgets.Display;
-import org.eclipse.webbrowser.internal.*;
 /**
  * The main interface to the internal Web browser. If allows
  * you to query the file types supported by the Web browser
@@ -8,15 +8,17 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser;
+package net.sourceforge.phpeclipse.webbrowser;
 
 import java.net.URL;
+
+import net.sourceforge.phpeclipse.webbrowser.internal.ImageResource;
+import net.sourceforge.phpeclipse.webbrowser.internal.Trace;
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserPreference;
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserUIPlugin;
+
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.ui.*;
-import org.eclipse.webbrowser.internal.ImageResource;
-import org.eclipse.webbrowser.internal.Trace;
-import org.eclipse.webbrowser.internal.WebBrowserPreference;
-import org.eclipse.webbrowser.internal.WebBrowserUIPlugin;
 import org.eclipse.core.runtime.IAdaptable;
 /**
  * The editor input for the integrated web browser.
@@ -46,7 +48,7 @@ public class WebBrowserEditorInput implements IWebBrowserEditorInput, IPersistab
 
        public static final int SHOW_ALL = SHOW_TOOLBAR | SHOW_STATUSBAR;
 
-       private static final String ELEMENT_FACTORY_ID = "org.eclipse.webbrowser.elementFactory";
+       private static final String ELEMENT_FACTORY_ID = "net.sourceforge.phpeclipse.webbrowser.elementFactory";
        private static final String MEMENTO_URL = "url";
        private static final String MEMENTO_STYLE = "style";
        private static final String MEMENTO_ID = "id";
@@ -100,7 +102,7 @@ public class WebBrowserEditorInput implements IWebBrowserEditorInput, IPersistab
         * given input is being displayed in, or false if it should
         * open up in a new page.
         *
-        * @param input org.eclipse.webbrowser.IWebBrowserEditorInput
+        * @param input net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput
         * @return boolean
         */
        public boolean canReplaceInput(IWebBrowserEditorInput input) {
@@ -8,12 +8,14 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.util.*;
+
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.webbrowser.IWebBrowser;
 
 /**
  * Monitor content provider.
diff --git a/net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserManager.java b/net.sourceforge.phpeclipse.webbrowser/src/net/sourceforge/phpeclipse/webbrowser/internal/BrowserManager.java
new file mode 100644 (file)
index 0000000..30a22f9
--- /dev/null
@@ -0,0 +1,287 @@
+/**********************************************************************
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ Â *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.XMLMemento;
+
+/**
+ *  
+ */
+public class BrowserManager {
+  private static final int ADD = 0;
+
+  private static final int CHANGE = 1;
+
+  private static final int REMOVE = 2;
+
+  protected List browsers;
+
+  protected IWebBrowser currentBrowser;
+
+  protected List browserListeners = new ArrayList();
+
+  private Preferences.IPropertyChangeListener pcl;
+
+  protected boolean ignorePreferenceChanges = false;
+
+  protected static BrowserManager instance;
+
+  public static BrowserManager getInstance() {
+    if (instance == null)
+      instance = new BrowserManager();
+    return instance;
+  }
+
+  private BrowserManager() {
+    pcl = new Preferences.IPropertyChangeListener() {
+      public void propertyChange(Preferences.PropertyChangeEvent event) {
+        if (ignorePreferenceChanges)
+          return;
+        String property = event.getProperty();
+        if (property.equals("browsers")) {
+          loadBrowsers();
+        }
+      }
+    };
+
+    WebBrowserUIPlugin.getInstance().getPluginPreferences().addPropertyChangeListener(pcl);
+  }
+
+  protected void dispose() {
+    WebBrowserUIPlugin.getInstance().getPluginPreferences().removePropertyChangeListener(pcl);
+
+    // clear the cache
+    if (browsers != null) {
+      Iterator iterator = browsers.iterator();
+      while (iterator.hasNext()) {
+        Object obj = iterator.next();
+        if (obj instanceof IInternalWebBrowser) {
+          IInternalWebBrowser wb = (IInternalWebBrowser) obj;
+          if (wb.getClearHistoryOnExit())
+            WebBrowserPreference.setInternalWebBrowserHistory(null);
+        }
+      }
+    }
+  }
+
+  public IExternalWebBrowserWorkingCopy createExternalWebBrowser() {
+    return new ExternalWebBrowserWorkingCopy();
+  }
+
+  public List getWebBrowsers() {
+    if (browsers == null)
+      loadBrowsers();
+    return new ArrayList(browsers);
+  }
+
+  protected void loadBrowsers() {
+    Trace.trace(Trace.FINEST, "Loading web browsers");
+
+    Preferences prefs = WebBrowserUIPlugin.getInstance().getPluginPreferences();
+    String xmlString = prefs.getString("browsers");
+    if (xmlString != null && xmlString.length() > 0) {
+      browsers = new ArrayList();
+
+      try {
+        ByteArrayInputStream in = new ByteArrayInputStream(xmlString.getBytes());
+        Reader reader = new InputStreamReader(in);
+        IMemento memento = XMLMemento.createReadRoot(reader);
+
+        IMemento child = memento.getChild("internal");
+        if (child != null) {
+          InternalWebBrowser browser = new InternalWebBrowser();
+          browser.load(child);
+          browsers.add(browser);
+        }
+
+        IMemento[] children = memento.getChildren("external");
+        int size = children.length;
+        for (int i = 0; i < size; i++) {
+          ExternalWebBrowser browser = new ExternalWebBrowser();
+          browser.load(children[i]);
+          browsers.add(browser);
+        }
+
+        Integer current = memento.getInteger("current");
+        if (current != null) {
+          currentBrowser = (IWebBrowser) browsers.get(current.intValue());
+        }
+      } catch (Exception e) {
+        Trace.trace(Trace.WARNING, "Could not load browsers: " + e.getMessage());
+      }
+      addInternalBrowser(browsers);
+      if (currentBrowser == null && browsers.size() > 0)
+        currentBrowser = (IWebBrowser) browsers.get(0);
+    } else {
+      setupDefaultBrowsers();
+      saveBrowsers();
+      return;
+    }
+  }
+
+  protected void saveBrowsers() {
+    try {
+      ignorePreferenceChanges = true;
+      XMLMemento memento = XMLMemento.createWriteRoot("web-browsers");
+
+      Iterator iterator = browsers.iterator();
+      while (iterator.hasNext()) {
+        Object obj = iterator.next();
+        if (obj instanceof InternalWebBrowser) {
+          InternalWebBrowser browser = (InternalWebBrowser) obj;
+          IMemento child = memento.createChild("internal");
+          browser.save(child);
+        } else if (obj instanceof ExternalWebBrowser) {
+          ExternalWebBrowser browser = (ExternalWebBrowser) obj;
+          IMemento child = memento.createChild("external");
+          browser.save(child);
+        }
+      }
+
+      memento.putInteger("current", browsers.indexOf(currentBrowser));
+
+      StringWriter writer = new StringWriter();
+      memento.save(writer);
+      String xmlString = writer.getBuffer().toString();
+      Preferences prefs = WebBrowserUIPlugin.getInstance().getPluginPreferences();
+      prefs.setValue("browsers", xmlString);
+      WebBrowserUIPlugin.getInstance().savePluginPreferences();
+    } catch (Exception e) {
+      Trace.trace(Trace.SEVERE, "Could not save browsers", e);
+    }
+    ignorePreferenceChanges = false;
+  }
+
+  protected void addInternalBrowser(List browserList) {
+    if (browserList == null)
+      return;
+
+    Iterator iterator = browserList.iterator();
+    while (iterator.hasNext()) {
+      IWebBrowser browser = (IWebBrowser) iterator.next();
+      if (browser instanceof IInternalWebBrowser)
+        return;
+    }
+
+    // add the internal browser if we can
+    WebBrowserUIPlugin.getInstance().getLog().log(
+        new Status(IStatus.INFO, WebBrowserUIPlugin.PLUGIN_ID, 0, WebBrowserUtil.canUseInternalWebBrowser() + "/"
+            + WebBrowserUtil.isInternalBrowserOperational(), null));
+    if (!WebBrowserUtil.canUseInternalWebBrowser() || !WebBrowserUtil.isInternalBrowserOperational())
+      return;
+
+    browserList.add(0, new InternalWebBrowser());
+  }
+
+  private void setupDefaultBrowsers() {
+    browsers = new ArrayList();
+
+    addInternalBrowser(browsers);
+
+    // handle all the EXTERNAL browsers by criteria and add those too at startup
+    WebBrowserUtil.addFoundBrowsers(browsers);
+
+    // by default, if internal is there, that is current, else set the first external one
+    if (!browsers.isEmpty())
+      currentBrowser = (IWebBrowser) browsers.get(0);
+  }
+
+  protected void addBrowser(IExternalWebBrowser browser) {
+    if (browsers == null)
+      loadBrowsers();
+    if (!browsers.contains(browser))
+      browsers.add(browser);
+    fireWebBrowserEvent(browser, ADD);
+    saveBrowsers();
+  }
+
+  protected void removeWebBrowser(IExternalWebBrowser browser) {
+    if (browsers == null)
+      loadBrowsers();
+    browsers.remove(browser);
+    fireWebBrowserEvent(browser, REMOVE);
+  }
+
+  // Internal Web browser CAN be "edited", just not created or removed
+  protected void browserChanged(IWebBrowser browser) {
+    fireWebBrowserEvent(browser, CHANGE);
+    saveBrowsers();
+  }
+
+  /**
+   * Add Web browser listener.
+   * 
+   * @param listener
+   */
+  public void addWebBrowserListener(IWebBrowserListener listener) {
+    browserListeners.add(listener);
+  }
+
+  /**
+   * Remove Web browser listener.
+   * 
+   * @param listener
+   */
+  public void removeWebBrowserListener(IWebBrowserListener listener) {
+    browserListeners.remove(listener);
+  }
+
+  /**
+   * Fire a Web browser event.
+   * 
+   * @param browser
+   * @param type
+   */
+  protected void fireWebBrowserEvent(IWebBrowser browser, int type) {
+    Object[] obj = browserListeners.toArray();
+
+    int size = obj.length;
+    for (int i = 0; i < size; i++) {
+      IWebBrowserListener listener = (IWebBrowserListener) obj[i];
+      if (type == ADD)
+        listener.browserAdded(browser);
+      else if (type == CHANGE)
+        listener.browserChanged(browser);
+      else if (type == REMOVE)
+        listener.browserRemoved(browser);
+    }
+  }
+
+  public IWebBrowser getCurrentWebBrowser() {
+    if (browsers == null)
+      loadBrowsers();
+
+    return currentBrowser;
+  }
+
+  public void setCurrentWebBrowser(IWebBrowser wb) {
+    if (browsers.contains(wb))
+      currentBrowser = wb;
+    saveBrowsers();
+  }
+}
\ No newline at end of file
@@ -1,4 +1,4 @@
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 /**********************************************************************
  * Copyright (c) 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
@@ -15,11 +15,13 @@ import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.List;
+
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+
 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.swt.widgets.DirectoryDialog;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
 import org.eclipse.core.runtime.IProgressMonitor;
 /**
  * 
@@ -8,10 +8,16 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.util.Iterator;
 
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+
 import org.eclipse.jface.viewers.*;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
@@ -21,11 +27,6 @@ import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.ui.help.WorkbenchHelp;
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IInternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.IWebBrowser;
 import org.eclipse.jface.viewers.CheckStateChangedEvent;
 import org.eclipse.jface.viewers.CheckboxTableViewer;
 import org.eclipse.jface.viewers.ICheckStateListener;
@@ -8,14 +8,15 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
 
 import org.eclipse.jface.viewers.ILabelProviderListener;
 
 import org.eclipse.swt.graphics.Image;
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IWebBrowser;
 import org.eclipse.jface.viewers.ITableLabelProvider;
 /**
  * Web browser table label provider.
@@ -8,10 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.io.File;
 
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.swt.SWT;
@@ -29,7 +31,6 @@ import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.help.WorkbenchHelp;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
 /**
  * 
  */
@@ -1,11 +1,12 @@
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.net.URL;
 
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+
 import org.eclipse.swt.program.Program;
 import org.eclipse.ui.IMemento;
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
 /**
  * 
  */
@@ -19,21 +20,21 @@ public class ExternalWebBrowser implements IExternalWebBrowser {
        protected String parameters;
        
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IWebBrowser#getName()
+        * @see net.sourceforge.phpeclipse.webbrowser.IWebBrowser#getName()
         */
        public String getName() {
                return name;
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowser#getLocation()
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser#getLocation()
         */
        public String getLocation() {
                return location;
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowser#getParameters()
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser#getParameters()
         */
        public String getParameters() {
                return parameters;
@@ -58,7 +59,7 @@ public class ExternalWebBrowser implements IExternalWebBrowser {
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IWebBrowser#openURL(java.net.URL)
+        * @see net.sourceforge.phpeclipse.webbrowser.IWebBrowser#openURL(java.net.URL)
         */
        public void openURL(URL url) {
                String urlText = WebBrowserPreference.getHomePageURL();
@@ -1,7 +1,7 @@
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
 /**
  * 
  */
@@ -18,21 +18,21 @@ public class ExternalWebBrowserWorkingCopy extends ExternalWebBrowser implements
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy#setName(java.lang.String)
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy#setName(java.lang.String)
         */
        public void setName(String name) {
                this.name = name;
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy#setLocation(java.lang.String)
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy#setLocation(java.lang.String)
         */
        public void setLocation(String location) {
                this.location = location;
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy#setParameters(java.lang.String)
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy#setParameters(java.lang.String)
         */
        public void setParameters(String params) {
                this.parameters = params;
@@ -47,7 +47,7 @@ public class ExternalWebBrowserWorkingCopy extends ExternalWebBrowser implements
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy#save()
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy#save()
         */
        public IExternalWebBrowser save() {
                if (browser != null) {
@@ -8,9 +8,9 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
-import org.eclipse.webbrowser.IWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
 
 /**
  * 
@@ -8,7 +8,10 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.internal.SWTUtil;
 
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.swt.SWT;
@@ -19,8 +22,6 @@ import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.help.WorkbenchHelp;
-import org.eclipse.webbrowser.IInternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.internal.SWTUtil;
 /**
  * 
  */
@@ -1,11 +1,12 @@
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.net.URL;
 
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
+
 import org.eclipse.ui.IMemento;
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IInternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.WebBrowserEditorInput;
 /**
  * 
  */
@@ -17,7 +18,7 @@ public class InternalWebBrowser implements IInternalWebBrowser {
        protected boolean clearHistory;
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IWebBrowser#getName()
+        * @see net.sourceforge.phpeclipse.webbrowser.IWebBrowser#getName()
         */
        public String getName() {
                return WebBrowserUIPlugin.getResource("%internalWebBrowserName");
@@ -45,7 +46,7 @@ public class InternalWebBrowser implements IInternalWebBrowser {
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IWebBrowser#openURL(java.net.URL)
+        * @see net.sourceforge.phpeclipse.webbrowser.IWebBrowser#openURL(java.net.URL)
         */
        public void openURL(URL url) {
                WebBrowserEditor.open(new WebBrowserEditorInput(url));
@@ -1,7 +1,7 @@
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IInternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowserWorkingCopy;
 /**
  * 
  */
@@ -31,7 +31,7 @@ public class InternalWebBrowserWorkingCopy extends InternalWebBrowser implements
        }
 
        /* (non-Javadoc)
-        * @see org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy#save()
+        * @see net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy#save()
         */
        public IInternalWebBrowser save() {
                if (browser != null) {
@@ -8,18 +8,20 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.net.URL;
 import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.webbrowser.WebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
+import net.sourceforge.phpeclipse.webbrowser.internal.Trace;
+
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.ui.*;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.webbrowser.WebBrowser;
-import org.eclipse.webbrowser.WebBrowserEditorInput;
-import org.eclipse.webbrowser.internal.Trace;
 /**
  * Action to open the Web broswer on a resource.
  */
@@ -8,7 +8,7 @@
  * Contributors:
  *    IBM - Initial API and implementation
  **********************************************************************/
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
@@ -8,9 +8,9 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
-import org.eclipse.webbrowser.IURLMap;
+import net.sourceforge.phpeclipse.webbrowser.IURLMap;
 /**
  * Standard URL mappings.
  */
@@ -8,10 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.util.Iterator;
 
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.action.ActionContributionItem;
 import org.eclipse.jface.action.IAction;
@@ -21,7 +23,6 @@ import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.ui.*;
-import org.eclipse.webbrowser.IWebBrowser;
 /**
  * Action to open the Web broswer.
  */
@@ -8,11 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import net.sourceforge.phpeclipse.webbrowser.IInternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
 
 import org.eclipse.jface.action.Action;
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IWebBrowser;
 /**
  * Action to open the Web browser.
  */
@@ -8,12 +8,13 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowser;
 
 import org.eclipse.swt.SWTError;
 import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.dnd.*;
-import org.eclipse.webbrowser.internal.WebBrowser;
 import org.eclipse.jface.action.Action;
 /**
  * Text actions (cut, copy, paste) for the Web browser.
 //TODO 1. Handle the sizing of a popup running in shelled out secondary window.
 //TODO 2. Support printing: waiting on eclipse bug 47937/44823.
 
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.util.*;
-import org.eclipse.webbrowser.IURLMap;
+
+import net.sourceforge.phpeclipse.webbrowser.IURLMap;
+
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.swt.layout.FillLayout;
@@ -8,9 +8,12 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.net.URL;
+
+import net.sourceforge.phpeclipse.webbrowser.*;
+
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
@@ -22,13 +25,12 @@ import org.eclipse.core.runtime.*;
 import org.eclipse.core.resources.*;
 import org.eclipse.ui.*;
 import org.eclipse.ui.part.*;
-import org.eclipse.webbrowser.*;
 /**
  * An integrated Web browser, defined as an editor to make
  * better use of the desktop.
  */
 public class WebBrowserEditor extends EditorPart {
-       public static final String WEB_BROWSER_EDITOR_ID = "org.eclipse.webbrowser";
+       public static final String WEB_BROWSER_EDITOR_ID = "net.sourceforge.phpeclipse.webbrowser";
        protected WebBrowser webBrowser;
        protected String initialURL;
        protected Image image;
@@ -144,7 +146,7 @@ public class WebBrowserEditor extends EditorPart {
        /**
         * Returns the web editor input, if available.
         *
-        * @return org.eclipse.webbrowser.IWebBrowserEditorInput
+        * @return net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput
         */
        protected IWebBrowserEditorInput getWebBrowserEditorInput() {
                IEditorInput input = getEditorInput();
@@ -8,7 +8,7 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.text.MessageFormat;
 
@@ -36,7 +36,7 @@ public class WebBrowserUIPlugin extends AbstractUIPlugin {
        /**
         * Returns the singleton instance of this plugin.
         *
-        * @return org.eclipse.webbrowser.WebBrowserPlugin
+        * @return net.sourceforge.phpeclipse.webbrowser.WebBrowserPlugin
         */
        public static WebBrowserUIPlugin getInstance() {
                return singleton;
@@ -8,7 +8,7 @@
  * Contributors:
  *    IBM - Initial API and implementation
  */
-package org.eclipse.webbrowser.internal;
+package net.sourceforge.phpeclipse.webbrowser.internal;
 
 import java.io.File;
 import java.io.InputStreamReader;
@@ -18,12 +18,13 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.IExternalWebBrowserWorkingCopy;
+import net.sourceforge.phpeclipse.webbrowser.IURLMap;
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowser;
+
 import org.eclipse.ui.IMemento;
 import org.eclipse.ui.XMLMemento;
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.IURLMap;
-import org.eclipse.webbrowser.IWebBrowser;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.core.runtime.*;
diff --git a/net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserManager.java b/net.sourceforge.phpeclipse.webbrowser/src/org/eclipse/webbrowser/internal/BrowserManager.java
deleted file mode 100644 (file)
index 55b33d9..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- *    IBM - Initial API and implementation
- **********************************************************************/
-package org.eclipse.webbrowser.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Preferences;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.ui.IMemento;
-import org.eclipse.ui.XMLMemento;
-import org.eclipse.webbrowser.IExternalWebBrowser;
-import org.eclipse.webbrowser.IExternalWebBrowserWorkingCopy;
-import org.eclipse.webbrowser.IInternalWebBrowser;
-import org.eclipse.webbrowser.IWebBrowser;
-/**
- * 
- */
-public class BrowserManager {
-       private static final int ADD = 0;
-       private static final int CHANGE = 1;
-       private static final int REMOVE = 2;
-
-       protected List browsers;
-       protected IWebBrowser currentBrowser;
-       protected List browserListeners = new ArrayList();
-       
-       private Preferences.IPropertyChangeListener pcl;
-       protected boolean ignorePreferenceChanges = false;
-
-       protected static BrowserManager instance;
-       
-       public static BrowserManager getInstance() {
-               if (instance == null)
-                       instance = new BrowserManager();
-               return instance;
-       }
-       
-       private BrowserManager() {
-               pcl = new Preferences.IPropertyChangeListener() {
-                       public void propertyChange(Preferences.PropertyChangeEvent event) {
-                               if (ignorePreferenceChanges)
-                                       return;
-                               String property = event.getProperty();
-                               if (property.equals("browsers")) {
-                                       loadBrowsers();
-                               }
-                       }
-               };
-               
-               WebBrowserUIPlugin.getInstance().getPluginPreferences().addPropertyChangeListener(pcl);
-       }
-       
-       protected void dispose() {
-               WebBrowserUIPlugin.getInstance().getPluginPreferences().removePropertyChangeListener(pcl);
-               
-               // clear the cache
-               Iterator iterator = browsers.iterator();
-               while (iterator.hasNext()) {
-                       Object obj = iterator.next();
-                       if (obj instanceof IInternalWebBrowser) {
-                               IInternalWebBrowser wb = (IInternalWebBrowser) obj;
-                               if (wb.getClearHistoryOnExit())
-                                       WebBrowserPreference.setInternalWebBrowserHistory(null);
-                       }
-               }
-       }
-
-       public IExternalWebBrowserWorkingCopy createExternalWebBrowser() {
-               return new ExternalWebBrowserWorkingCopy();
-       }       
-
-       public List getWebBrowsers() {
-               if (browsers == null)
-                       loadBrowsers();
-               return new ArrayList(browsers);
-       }
-       
-       protected void loadBrowsers() {
-               Trace.trace(Trace.FINEST, "Loading web browsers");
-               
-               Preferences prefs = WebBrowserUIPlugin.getInstance().getPluginPreferences();
-               String xmlString = prefs.getString("browsers");
-               if (xmlString != null && xmlString.length() > 0) {
-                       browsers = new ArrayList();
-                       
-                       try {
-                               ByteArrayInputStream in = new ByteArrayInputStream(xmlString.getBytes());
-                               Reader reader = new InputStreamReader(in);
-                               IMemento memento = XMLMemento.createReadRoot(reader);
-               
-                               IMemento child = memento.getChild("internal");
-                               if (child != null) {
-                                       InternalWebBrowser browser = new InternalWebBrowser();
-                                       browser.load(child);
-                                       browsers.add(browser);
-                               }
-                               
-                               IMemento[] children = memento.getChildren("external");
-                               int size = children.length;
-                               for (int i = 0; i < size; i++) {
-                                       ExternalWebBrowser browser = new ExternalWebBrowser();
-                                       browser.load(children[i]);
-                                       browsers.add(browser);
-                               }
-                               
-                               Integer current = memento.getInteger("current");
-                               if (current != null) {
-                                       currentBrowser = (IWebBrowser) browsers.get(current.intValue()); 
-                               }       
-                       } catch (Exception e) {
-                               Trace.trace(Trace.WARNING, "Could not load browsers: " + e.getMessage());
-                       }
-                       addInternalBrowser(browsers);
-                       if (currentBrowser == null && browsers.size() > 0)
-                               currentBrowser = (IWebBrowser) browsers.get(0);
-               } else {
-                       setupDefaultBrowsers();
-                       saveBrowsers();
-                       return;
-               }
-       }
-
-       protected void saveBrowsers() {
-               try {
-                       ignorePreferenceChanges = true;
-                       XMLMemento memento = XMLMemento.createWriteRoot("web-browsers");
-
-                       Iterator iterator = browsers.iterator();
-                       while (iterator.hasNext()) {
-                               Object obj = iterator.next();
-                               if (obj instanceof InternalWebBrowser) {
-                                       InternalWebBrowser browser = (InternalWebBrowser) obj;
-                                       IMemento child = memento.createChild("internal");
-                                       browser.save(child);
-                               } else if (obj instanceof ExternalWebBrowser) {
-                                       ExternalWebBrowser browser = (ExternalWebBrowser) obj;
-                                       IMemento child = memento.createChild("external");
-                                       browser.save(child);
-                               }
-                       }
-                       
-                       memento.putInteger("current", browsers.indexOf(currentBrowser));
-
-                       StringWriter writer = new StringWriter();
-                       memento.save(writer);
-                       String xmlString = writer.getBuffer().toString();
-                       Preferences prefs = WebBrowserUIPlugin.getInstance().getPluginPreferences();
-                       prefs.setValue("browsers", xmlString);
-                       WebBrowserUIPlugin.getInstance().savePluginPreferences();
-               } catch (Exception e) {
-                       Trace.trace(Trace.SEVERE, "Could not save browsers", e);
-               }
-               ignorePreferenceChanges = false;
-       }
-       
-       protected void addInternalBrowser(List browserList) {
-               if (browserList == null)
-                       return;
-
-               Iterator iterator = browserList.iterator();
-               while (iterator.hasNext()) {
-                       IWebBrowser browser = (IWebBrowser) iterator.next();
-                       if (browser instanceof IInternalWebBrowser)
-                               return;
-               }
-
-               // add the internal browser if we can
-               WebBrowserUIPlugin.getInstance().getLog().log(new Status(IStatus.INFO,
-                       WebBrowserUIPlugin.PLUGIN_ID, 0, WebBrowserUtil.canUseInternalWebBrowser() + "/" + WebBrowserUtil.isInternalBrowserOperational(), null));
-               if (!WebBrowserUtil.canUseInternalWebBrowser() || !WebBrowserUtil.isInternalBrowserOperational())
-                       return;
-               
-               browserList.add(0, new InternalWebBrowser());
-       }
-       
-       private void setupDefaultBrowsers() {
-               browsers = new ArrayList();
-               
-               addInternalBrowser(browsers);
-               
-               // handle all the EXTERNAL browsers by criteria and add those too at startup
-               WebBrowserUtil.addFoundBrowsers(browsers);
-               
-               // by default, if internal is there, that is current, else set the first external one
-               if (!browsers.isEmpty())
-                       currentBrowser = (IWebBrowser) browsers.get(0);
-       }
-
-       protected void addBrowser(IExternalWebBrowser browser) {
-               if (browsers == null)
-                       loadBrowsers();
-               if (!browsers.contains(browser))
-                       browsers.add(browser);
-               fireWebBrowserEvent(browser, ADD);
-               saveBrowsers();
-       }
-       
-       protected void removeWebBrowser(IExternalWebBrowser browser) {
-               if (browsers == null)
-                       loadBrowsers();
-               browsers.remove(browser);
-               fireWebBrowserEvent(browser, REMOVE);
-       }
-       
-       // Internal Web browser CAN be "edited", just not created or removed
-       protected void browserChanged(IWebBrowser browser) {
-               fireWebBrowserEvent(browser, CHANGE);
-               saveBrowsers();
-       }
-       
-       /**
-        * Add Web browser listener.
-        * @param listener
-        */
-       public void addWebBrowserListener(IWebBrowserListener listener) {
-               browserListeners.add(listener);
-       }
-
-       /**
-        * Remove Web browser listener.
-        * @param listener
-        */
-       public void removeWebBrowserListener(IWebBrowserListener listener) {
-               browserListeners.remove(listener);
-       }
-       
-       /**
-        * Fire a Web browser event.
-        * @param browser
-        * @param type
-        */
-       protected void fireWebBrowserEvent(IWebBrowser browser, int type) {
-               Object[] obj = browserListeners.toArray();
-               
-               int size = obj.length;
-               for (int i = 0; i < size; i++) {
-                       IWebBrowserListener listener = (IWebBrowserListener) obj[i];
-                       if (type == ADD)
-                               listener.browserAdded(browser);
-                       else if (type == CHANGE)
-                               listener.browserChanged(browser);
-                       else if (type == REMOVE)
-                               listener.browserRemoved(browser);
-               }
-       }
-       
-       public IWebBrowser getCurrentWebBrowser() {
-               if (browsers == null)
-                       loadBrowsers();
-
-               return currentBrowser; 
-       }
-
-       public void setCurrentWebBrowser(IWebBrowser wb) {
-               if (browsers.contains(wb))
-                       currentBrowser = wb;
-               saveBrowsers();
-       }
-}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.xml.core/.classpath b/net.sourceforge.phpeclipse.xml.core/.classpath
new file mode 100644 (file)
index 0000000..275b34c
--- /dev/null
@@ -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/net.sourceforge.phpeclipse.xml.core/.cvsignore b/net.sourceforge.phpeclipse.xml.core/.cvsignore
new file mode 100644 (file)
index 0000000..a238c03
--- /dev/null
@@ -0,0 +1,5 @@
+bin
+build.xml
+xmlcore.jar
+xmlcoresrc.zip
+net.sf.solareclipse.*
diff --git a/net.sourceforge.phpeclipse.xml.core/.project b/net.sourceforge.phpeclipse.xml.core/.project
new file mode 100644 (file)
index 0000000..53683af
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>net.sourceforge.phpeclipse.xml.core</name>
+       <comment></comment>
+       <projects>
+               <project>net.sf.wdte.core</project>
+       </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.jdt.core.javanature</nature>
+               <nature>org.eclipse.pde.PluginNature</nature>
+       </natures>
+</projectDescription>
diff --git a/net.sourceforge.phpeclipse.xml.core/build.properties b/net.sourceforge.phpeclipse.xml.core/build.properties
new file mode 100644 (file)
index 0000000..6ba9e81
--- /dev/null
@@ -0,0 +1,2 @@
+bin.includes = plugin.xml
+source.xmlcore.jar = src/
diff --git a/net.sourceforge.phpeclipse.xml.core/plugin.properties b/net.sourceforge.phpeclipse.xml.core/plugin.properties
new file mode 100644 (file)
index 0000000..4d68bae
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2004 Christopher Lenz and others.
+# All rights reserved. This program and the accompanying materials 
+# are made available under the terms of the Common Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/cpl-v10.html
+# 
+# Contributors:
+#     Christopher Lenz - initial english resources
+# 
+# $Id: plugin.properties,v 1.1 2004-09-02 18:26:54 jsurfer Exp $
+#
+
+pluginName = Web Development Tools XML Core
+providerName= WDTE Project
diff --git a/net.sourceforge.phpeclipse.xml.core/plugin.xml b/net.sourceforge.phpeclipse.xml.core/plugin.xml
new file mode 100644 (file)
index 0000000..0e5b3e3
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+   id="net.sourceforge.phpeclipse.xml.core"
+   name="%pluginName"
+   version="0.0.1"
+   provider-name="%providerName"
+   class="">
+
+   <runtime>
+      <library name="xmlcore.jar">
+         <export name="*"/>
+      </library>
+   </runtime>
+   <requires>
+      <import plugin="net.sourceforge.phpeclipse.core"/>
+      <import plugin="org.eclipse.core.resources"/>
+      <import plugin="org.eclipse.core.runtime"/>
+      <import plugin="org.eclipse.text"/>
+   </requires>
+
+
+</plugin>
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java
new file mode 100644 (file)
index 0000000..7fb5ab3
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: XMLDocument.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.internal.model;
+
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.xml.core.internal.parser.XMLParser;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.xml.core.parser.IXMLParser;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+
+/**
+ *  
+ */
+public class XMLDocument extends SourceReference implements IXMLDocument, IDocumentListener {
+  // Instance Variables ------------------------------------------------------
+
+  private IXMLElement root;
+
+  private String systemId;
+
+  private Object dirtyLock = new Object();
+
+  private boolean dirty = true;
+
+  // Constructors ------------------------------------------------------------
+
+  public XMLDocument(IDocument document, String systemId) {
+    super(document, 0, document.getLength());
+    this.systemId = systemId;
+  }
+
+  // IXMLDocument Implementation ---------------------------------------------
+
+  /*
+   * @see IXMLDocument#getRoot()
+   */
+  public IXMLElement getRoot() {
+    return root;
+  }
+
+  /*
+   * @see net.sourceforge.phpeclipse.xml.core.model.IXMLDocument#getSystemId()
+   */
+  public String getSystemId() {
+    return systemId;
+  }
+
+  /*
+   * @see IStyleSheet#reconcile(IProblemCollector)
+   */
+  public void reconcile(IProblemCollector problemCollector, IFile file) {
+    synchronized (dirtyLock) {
+      if (!dirty) {
+        return;
+      }
+      dirty = false;
+    }
+
+    synchronized (this) {
+      boolean doParse = false;
+      root = null;
+      if (file != null) {
+        String filename = file.getLocation().toString();
+        int len = filename.length();
+        if (len >= 4) {
+          if ((filename.charAt(len - 1) != 'l' && filename.charAt(len - 1) != 'L')
+              || (filename.charAt(len - 2) != 'p' && filename.charAt(len - 2) != 'P')
+              || (filename.charAt(len - 3) != 't' && filename.charAt(len - 3) != 'T') 
+              || (filename.charAt(len - 4) != '.')) {
+            if ((filename.charAt(len - 1) != 'm' && filename.charAt(len - 1) != 'M')
+                || (filename.charAt(len - 2) != 't' && filename.charAt(len - 2) != 'T')
+                || (filename.charAt(len - 3) != 'h' && filename.charAt(len - 3) != 'H') 
+                || (filename.charAt(len - 4) != '.')) {
+              if (len >= 5) {
+                if ((filename.charAt(len - 1) != 'l' && filename.charAt(len - 1) != 'L')
+                    || (filename.charAt(len - 2) != 'm' && filename.charAt(len - 2) != 'M')
+                    || (filename.charAt(len - 3) != 't' && filename.charAt(len - 3) != 'T')
+                    || (filename.charAt(len - 4) != 'h' && filename.charAt(len - 4) != 'H') 
+                    || (filename.charAt(len - 5) != '.')) {
+                  doParse = true;
+                }
+              }
+            }
+          }
+        } else {
+          doParse = true;
+        }
+      }
+      if (doParse) {
+        IXMLParser parser = new XMLParser();
+        parser.setProblemCollector(problemCollector);
+        parser.setSource(getDocument());
+        parser.setSystemId(systemId);
+        IXMLDocument model = parser.parse();
+        if (model != null) {
+          root = model.getRoot();
+        }
+      }
+    }
+  }
+
+  // IDocumentListener Implementation ----------------------------------------
+
+  /*
+   * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+   */
+  public void documentAboutToBeChanged(DocumentEvent event) {
+    // do nothing
+  }
+
+  /*
+   * @see IDocumentListener#documentChanged(DocumentEvent)
+   */
+  public void documentChanged(DocumentEvent event) {
+    synchronized (dirtyLock) {
+      dirty = true;
+    }
+  }
+
+  // Public Methods ----------------------------------------------------------
+
+  /**
+   * Sets the root element.
+   * 
+   * @param root
+   *          the root element to set
+   */
+  public void setRoot(IXMLElement root) {
+    this.root = root;
+  }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLElement.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLElement.java
new file mode 100644 (file)
index 0000000..2200619
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: XMLElement.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * 
+ */
+public class XMLElement extends SourceReference implements IXMLElement {
+
+       // Instance Variables ------------------------------------------------------
+
+       private List children;
+
+       private String localName;
+       private String namespaceURI;
+       private String prefix;
+
+       private IXMLElement parent;
+
+       // Constructors ------------------------------------------------------------
+
+       public XMLElement(IDocument document) {
+               super(document);
+       }
+
+       public XMLElement(IDocument document, int offset) {
+               super(document, offset);
+       }
+
+       public XMLElement(IDocument document, int offset, int length) {
+               super(document, offset, length);
+       }
+
+       // IXMLElement Implementation -------------------------------------------------
+
+       /* 
+        * @see IXMLElement#getChildren()
+        */
+       public IXMLElement[] getChildren() {
+               if (children != null) {
+                       return (IXMLElement[]) children.toArray(
+                                       new IXMLElement[children.size()]);
+               }
+               return new IXMLElement[0];
+       }
+
+       /* 
+        * @see IXMLElement#getLocalName()
+        */
+       public String getLocalName() {
+               return localName;
+       }
+
+       /* 
+        * @see IXMLElement#getNamespaceURI()
+        */
+       public String getNamespaceURI() {
+               return namespaceURI;
+       }
+
+       /* 
+        * @see IXMLElement#getPrefix()
+        */
+       public String getPrefix() {
+               return prefix;
+       }
+
+       /* 
+        * @see IXMLElement#getParent()
+        */
+       public IXMLElement getParent() {
+               return parent;
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       public void addChild(IXMLElement child) {
+               if (children == null) {
+                       children = new ArrayList();
+               }
+               children.add(child);
+       }
+
+       public void setLocalName(String localName) {
+               this.localName = localName;
+       }
+
+       public void setNamespaceURI(String namespaceURI) {
+               this.namespaceURI = namespaceURI;
+       }
+
+       public void setPrefix(String prefix) {
+               this.prefix = prefix;
+       }
+
+       public void setParent(IXMLElement parent) {
+               this.parent = parent;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/DefaultProblem.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/DefaultProblem.java
new file mode 100644 (file)
index 0000000..bb933e1
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2003-2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API and implementation
+ * 
+ * $Id: DefaultProblem.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.internal.parser;
+
+import net.sourceforge.phpeclipse.xml.core.parser.IProblem;
+
+public class DefaultProblem implements IProblem {
+
+       // Instance Variables ------------------------------------------------------
+
+       private String message;
+       private int sourceStart;
+       private int sourceEnd;
+       private int sourceLineNumber;
+       private boolean error;
+
+       // Constructors ------------------------------------------------------------
+
+       public DefaultProblem(String message, int sourceStart, int sourceEnd,
+                       int sourceLineNumber, boolean error) {
+               this.message = message;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+               this.sourceLineNumber = sourceLineNumber;
+               this.error = error;
+       }
+
+       // IProblem Implementation -------------------------------------------------
+
+       /*
+        * @see IProblem#getMessage()
+        */
+       public String getMessage() {
+               return message;
+       }
+
+       /*
+        * @see IProblem#getSourceStart()
+        */
+       public int getSourceStart() {
+               return sourceStart;
+       }
+
+       /*
+        * @see IProblem#getSourceEnd()
+        */
+       public int getSourceEnd() {
+               return sourceEnd;
+       }
+
+       /*
+        * @see IProblem#getSourceLineNumber()
+        */
+       public int getSourceLineNumber() {
+               return sourceLineNumber;
+       }
+
+       /*
+        * @see IProblem#isError()
+        */
+       public boolean isError() {
+               return error;
+       }
+
+       /*
+        * @see IProblem#isWarning()
+        */
+       public boolean isWarning() {
+               return !error;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/XMLParser.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/internal/parser/XMLParser.java
new file mode 100644 (file)
index 0000000..81a0e64
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: XMLParser.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.internal.parser;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import net.sourceforge.phpeclipse.xml.core.internal.model.XMLDocument;
+import net.sourceforge.phpeclipse.xml.core.internal.model.XMLElement;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblem;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.xml.core.parser.IXMLParser;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * SAX-based default implementation of the {@link IXMLParser} interface.
+ * 
+ * TODO This implementation doesn't do error recovery, as SAX doesn't allow it.
+ *      Maybe we partition the document and parse individual fragments so that
+ *      errors can be isolated to their source
+ */
+public class XMLParser implements IXMLParser {
+       /**
+        * SAX content handler that builds a model of the XML document.
+        */
+       class ModelBuilder extends DefaultHandler {
+               /**
+                * The document model being built.
+                */
+               XMLDocument document;
+
+               /**
+                * The current top element. That is the element that has been most 
+                * recently opened by a start tag.
+                */
+               private XMLElement top;
+
+               /**
+                * The SAX locator provided by the parser, used to calculate the source
+                * regions covered by elements.
+                */
+               private Locator locator;
+
+               /**
+                * Limits parsing time.
+                */
+               private long timeout;
+
+               /*
+                * @see org.xml.sax.ContentHandler#startDocument()
+                */
+               public void startDocument() throws SAXException {
+                       timeout = System.currentTimeMillis() + 2000;
+                       document = new XMLDocument(source, systemId);
+               }
+
+               /*
+                * @see org.xml.sax.ContentHandler#startElement(String, String, String, Attributes)
+                */
+               public void startElement(
+                       String namespaceURI, String localName, String qName, Attributes atts
+               ) throws SAXException {
+                       if (System.currentTimeMillis() > timeout) {
+                               throw new SAXException("timeout");
+                       }
+
+                       XMLElement newTop = new XMLElement(source);
+                       newTop.setLocalName(localName);
+                       newTop.setNamespaceURI(namespaceURI);
+
+                       if (qName != null) {
+                               int colonIndex = qName.indexOf(':');
+                               if (colonIndex >= 0) {
+                                       newTop.setPrefix(qName.substring(0, colonIndex));
+                               }
+                       }
+
+                       int offset = computeOffset(newTop,
+                                       locator.getLineNumber(),
+                                       locator.getColumnNumber());
+
+                       if (offset >= 0) {
+                               newTop.setSourceRegion(offset, 0);
+                       }
+                       if (top != null) {
+                               newTop.setParent(top);
+                       }
+                       top = newTop;
+               }
+
+               /*
+                * @see org.xml.sax.ContentHandler#endElement(String, String, String)
+                */
+               public void endElement(
+                       String namespaceURI, String localName, String qName
+               ) throws SAXException {
+                       int length = computeLength(top,
+                                       locator.getLineNumber(),
+                                       locator.getColumnNumber());
+
+                       if (length >= 0) {
+                               top.setSourceRegion(top.getSourceRegion().getOffset(), length);
+                       }
+
+                       XMLElement previousTop = (XMLElement) top.getParent();
+                       if (previousTop != null) {
+                               previousTop.addChild(top);
+                       } else {
+                               // this is the root element
+                               document.setRoot(top);
+                       } 
+                       top = previousTop;
+               }
+
+               /* 
+                * @see org.xml.sax.ErrorHandler#error(SAXParseException)
+                */
+               public void error(SAXParseException e) throws SAXException {
+                       if (problemCollector != null) {
+                               problemCollector.addProblem(createProblem(e, true));
+                       }
+               }
+
+               /* 
+                * @see org.xml.sax.ErrorHandler#fatalError(SAXParseException)
+                */
+               public void fatalError(SAXParseException e) throws SAXException {
+                       if (problemCollector != null) {
+                               problemCollector.addProblem(createProblem(e, true));
+                       }
+               }
+
+               /* 
+                * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
+                */
+               public void warning(SAXParseException e) throws SAXException {
+                       if (problemCollector != null) {
+                               problemCollector.addProblem(createProblem(e, false));
+                       }
+               }
+
+               /*
+                * @see org.xml.sax.ContentHandler#setDocumentLocator(Locator)
+                */
+               public void setDocumentLocator(Locator locator) {
+                       this.locator = locator;
+               }
+
+               /**
+                * Creates a <tt>IProblem</tt> instance based on the information
+                * accessible from the parse exception. This method estimates the exact
+                * location of the error based on the line and column numbers provided
+                * with the exception.
+                * 
+                * TODO Limit the location to the current top element
+                * 
+                * @param e the SAX parse exception
+                * @param error whether the problem is an error or a warning
+                * @return the created problem object
+                */
+               private IProblem createProblem(SAXParseException e, boolean error) {
+                       int line = e.getLineNumber();
+                       int column = e.getColumnNumber();
+                       if (line < 0) {
+                               line = 0;
+                       }
+                       if (column < 1) {
+                               column = 1;
+                       }
+
+                       int offset = 0, length = 1;
+                       try {
+                               offset = getOffset(line, column);
+                               length = getLastCharColumn(line) - column;
+                       } catch (BadLocationException ble) {
+                               ble.printStackTrace();
+                       }
+
+                       return new DefaultProblem(e.getLocalizedMessage(),
+                                                       offset, offset + length, line, error);
+               }
+       }
+
+       // Instance Variables ------------------------------------------------------
+
+       /**
+        * The associated problem collector.
+        */
+       IProblemCollector problemCollector;
+
+       /**
+        * The document containing the source that should be parsed.
+        */
+       IDocument source;
+
+       /**
+        * The system ID of the document to parse, if available. This is necessary
+        * to resolve relative external entities. Can be <tt>null</tt>.
+        */
+       String systemId;
+
+       // IXMLParser Implementation -----------------------------------------------
+
+       /*
+        * @see IXMLParser#parse()
+        */
+       public IXMLDocument parse() {
+               SAXParserFactory factory = SAXParserFactory.newInstance();
+               factory.setNamespaceAware(true);
+               factory.setValidating(false);
+
+               try {
+                       SAXParser parser = factory.newSAXParser();
+
+                       InputSource in = new InputSource(new StringReader(source.get()));
+                       if (systemId != null) {
+                               in.setSystemId(systemId);
+                       }
+
+                       ModelBuilder builder = new ModelBuilder();
+                       parser.parse(in, builder);
+                       return builder.document;
+               } catch (ParserConfigurationException e) {
+                       // TODO Throw CoreException or at least log the error
+               } catch (SAXParseException e) {
+                       // Already handled by the ModelBuilder
+               } catch (SAXException e) {
+                       // SAX exceptions that are not parsing errors
+                       // TODO Throw CoreException or at least log the error
+               } catch (IOException e) {
+                       // TODO Throw CoreException or at least log the error
+               }
+
+               return null;
+       }
+
+       /* 
+        * @see IProblemReporter#setProblemCollector(IProblemCollector)
+        */
+       public void setProblemCollector(IProblemCollector problemCollector) {
+               this.problemCollector = problemCollector;
+       }
+
+       /* 
+        * @see IXMLParser#setSource(IDocument)
+        */
+       public void setSource(IDocument source) {
+               this.source = source;
+       }
+
+       /* 
+        * @see IXMLParser#setSystemId(String)
+        */
+       public void setSystemId(String systemId) {
+               this.systemId = systemId;
+       }
+
+       // Private Methods ---------------------------------------------------------
+
+       /**
+        * Computes the exact length of the given element by searching for the
+        * offset of the last character of the end tag.
+        */
+       int computeLength(XMLElement element, int line, int column) {
+               try {
+                       int offset;
+                       if (column <= 0) {
+                               int lineOffset = source.getLineOffset(line);
+                               String endTag = getEndTag(element);
+
+                               IRegion result = findStringForward(lineOffset, endTag);
+                               if (result != null) {
+                                       offset = result.getOffset() + endTag.length();
+                               } else {
+                                       result = findStringForward(lineOffset, "/>"); //$NON-NLS-1$
+                                       if (result == null) {
+                                               offset = -1;
+                                       } else {
+                                               offset = result.getOffset() + 2;
+                                       }
+                               }
+
+                               if ((offset < 0) || (getLine(offset) != line)) {
+                                       offset = lineOffset;
+                               } else {
+                                       offset++;
+                               }
+                       } else {
+                               offset = getOffset(line, column);
+                       }
+
+                       return offset - element.getSourceRegion().getOffset();
+               } catch (BadLocationException e) {
+                       // ignore as the parser may be out of sync with the document during
+                       // reconciliation
+               }
+
+               return -1;
+       }
+
+       /**
+        * Computes the offset at which the specified elements start tag begins in
+        * the source.
+        */
+       int computeOffset(XMLElement element, int line, int column) {
+               try {
+                       int offset;
+                       String prefix = "<"; //$NON-NLS-1$
+                       if (column <= 0) {
+                               offset = getOffset(line, 0);
+                               int lastCharColumn = getLastCharColumn(line);
+                               String lineText = source
+                                       .get(source.getLineOffset(line - 1), lastCharColumn);
+                               String startTag = getStartTag(element);
+
+                               int lastIndex = lineText.indexOf(startTag);
+                               if (lastIndex > -1) {
+                                       offset += lastIndex + 1;
+                               } else {
+                                       offset = getOffset(line, lastCharColumn);
+                                       IRegion result = findStringBackward(offset - 1, prefix);
+                                       offset = result.getOffset();
+                               }
+                       } else {
+                               offset = getOffset(line, column);
+                               IRegion result = findStringForward(offset - 1, prefix);
+                               offset = result.getOffset();
+                       }
+
+                       return offset;
+               } catch (BadLocationException e) {
+                       // ignore as the parser may be out of sync with the document during
+                       // reconciliation
+               }
+
+               return -1;
+       }
+
+       private IRegion findStringBackward(
+               int startOffset, String string
+       ) throws BadLocationException {
+               int offset = startOffset;
+               int length = string.length();
+
+               String match;
+               while (offset >= 0) {
+                       match = source.get(offset, length);
+                       if (match.equals(string)) {
+                               return new Region(offset, length);
+                       }
+                       offset -= 1;
+               }
+
+               return null;
+       }
+
+       private IRegion findStringForward(
+               int startOffset, String string
+       ) throws BadLocationException {
+               int offset = startOffset;
+               int length = string.length();
+
+               String match;
+               int sourceLength = source.getLength();
+               while (offset + length <= sourceLength) {
+                       match = source.get(offset, length);
+                       if (match.equals(string)) {
+                               return new Region(offset, length);
+                       }
+                       offset += 1;
+               }
+
+               return null;
+       }
+
+       /**
+        * Given an XML element, this method reconstructs the corresponding end tag
+        * of the element, including the namespace prefix if there was one. 
+        * 
+        * @param element the XML element for which the end tag should be contructed
+        * @return the end tag as string
+        */
+       private String getEndTag(IXMLElement element) {
+               StringBuffer buf = new StringBuffer("</"); //$NON-NLS-1$
+               if (element.getPrefix() != null) {
+                       buf.append(element.getPrefix());
+                       buf.append(':');
+               }
+               buf.append(element.getLocalName());
+               buf.append('>');
+
+               return buf.toString();
+       }
+
+       /**
+        * Reconstructs and returns the start tag corresponding to the given XML
+        * element, excluding any attribute specifications or the closing 
+        * <tt>&gt;</tt> character.
+        * 
+        * @param element the XML element for which the start tag should be
+        *        constructed
+        * @return the start tag as string, excluding everything after the tag name
+        *         itself
+        */
+       private String getStartTag(IXMLElement element) {
+               StringBuffer buf = new StringBuffer("<"); //$NON-NLS-1$
+               if (element.getPrefix() != null) {
+                       buf.append(element.getPrefix());
+                       buf.append(':');
+               }
+               buf.append(element.getLocalName());
+
+               return buf.toString();
+       }
+
+       int getOffset(int line, int column) throws BadLocationException {
+               return source.getLineOffset(line - 1) + column - 1;
+       }
+
+       private int getLine(int offset) throws BadLocationException {
+               return source.getLineOfOffset(offset) + 1;
+       }
+
+       int getLastCharColumn(int line) throws BadLocationException {
+               String lineDelimiter = source.getLineDelimiter(line - 1);
+               int lineDelimiterLength = (lineDelimiter != null)
+                               ? lineDelimiter.length() : 0;
+
+               return source.getLineLength(line - 1) - lineDelimiterLength;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLDocument.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLDocument.java
new file mode 100644 (file)
index 0000000..22e09c3
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IXMLDocument.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * 
+ */
+public interface IXMLDocument extends ISourceReference {
+
+       /**
+        * Returns the root element of the document.
+        * 
+        * @return the document element
+        */
+       IXMLElement getRoot();
+
+       /**
+        * Returns the system ID of the document.
+        * 
+        * @return the system ID
+        */
+       String getSystemId();
+
+       void reconcile(IProblemCollector collector, IFile file);
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLElement.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/model/IXMLElement.java
new file mode 100644 (file)
index 0000000..c5fc3cb
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IXMLElement.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+
+/**
+ * Basic model element
+ */
+public interface IXMLElement extends ISourceReference {
+
+       IXMLElement[] getChildren();
+
+       String getLocalName();
+
+       String getNamespaceURI();
+
+       String getPrefix();
+
+       IXMLElement getParent();
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblem.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblem.java
new file mode 100644 (file)
index 0000000..89e0c2b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IProblem.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.parser;
+
+/**
+ * 
+ */
+public interface IProblem {
+
+       /**
+        * Returns a localized, human-readable message string which describes the
+        * problem.
+        * 
+        * @return the problem message
+        */
+       String getMessage();
+
+       /**
+        * Returns the start position of the problem (inclusive).
+        * 
+        * @return the start position of the problem, or -1 if unknown
+        */
+       int getSourceStart();
+
+       /**
+        * Returns the end position of the problem (inclusive).
+        * 
+        * @return the end position of the problem), or -1 if unknown
+        */
+       int getSourceEnd();
+
+       /**
+        * Returns the line number of the source where the problem begins.
+        * 
+        * @return the line number of the source where the problem begins
+        */
+       int getSourceLineNumber();
+
+       /**
+        * Returns whether the problem is an error.
+        * 
+        * @return <code>true</code> if the problem is an error, <code>false</code>
+        *         otherwise
+        */
+       boolean isError();
+
+       /**
+        * Returns whether the problem is a warning.
+        * 
+        * @return <code>true</code> if the problem is a warning, <code>false</code>
+        *         otherwise
+        */
+       boolean isWarning();
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemCollector.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemCollector.java
new file mode 100644 (file)
index 0000000..72b88fa
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IProblemCollector.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.parser;
+
+/**
+ * 
+ */
+public interface IProblemCollector {
+
+       /**
+        * Notification of an error or warning.
+        * 
+        * @param problem the discovered problem
+        */
+       void addProblem(IProblem problem);
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemReporter.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IProblemReporter.java
new file mode 100644 (file)
index 0000000..6d74ec8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IProblemReporter.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.parser;
+
+/**
+ * Basic interface for classes that report errors to a problem collector.
+ */
+public interface IProblemReporter {
+
+       /**
+        * Sets the problem collector that should be used by the reporter.
+        * 
+        * @param problemCollector the problem collector to use
+        */
+       void setProblemCollector(IProblemCollector problemCollector);
+
+}
diff --git a/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IXMLParser.java b/net.sourceforge.phpeclipse.xml.core/src/net/sourceforge/phpeclipse/xml/core/parser/IXMLParser.java
new file mode 100644 (file)
index 0000000..c48a1d3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: IXMLParser.java,v 1.1 2004-09-02 18:26:55 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.parser;
+
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Interface for classes that implement parsing of XML files.
+ */
+public interface IXMLParser extends IProblemReporter {
+
+       IXMLDocument parse();
+
+       void setSource(IDocument source);
+
+       void setSystemId(String systemId);
+}