--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+bin
+build
+dist
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>net.sourceforge.phpeclipse.css.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.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+source.csscore.jar = src/
+bin.includes = plugin.xml,\
+ *.jar,\
+ csscore.jar,\
+ plugin.properties
+src.includes = .project,\
+ .classpath,\
+ build.properties,\
+ plugin.properties,\
+ plugin.xml,\
+ schema/,\
+ src/
--- /dev/null
+#
+# 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 english resources
+#
+# $Id: plugin.properties,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+#
+
+pluginName = Web Development Tools CSS Core
+providerName= WDTE Project
+
+css1Profile.name = CSS Level 1
+css1Profile.description = \
+ Profile correspondong to the CSS 1.0 specification
+css2Profile.name = CSS Level 2
+css2Profile.description =\
+ Profile correspondong to the CSS 2.0 specification
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="net.sourceforge.phpeclipse.css.core"
+ name="Web Development Tools CSS Core"
+ version="0.0.1"
+ provider-name="WDTE Project"
+ class="net.sourceforge.phpeclipse.css.core.CssCore">
+
+ <runtime>
+ <library name="csscore.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>
+
+ <extension-point id="profiles" name="CSS Profiles" schema="schema/profiles.exsd"/>
+
+ <extension point="org.eclipse.team.core.fileTypes">
+ <fileTypes type="text" extension="css"/>
+ </extension>
+
+ <extension
+ point="net.sourceforge.phpeclipse.css.core.profiles">
+ <profile
+ name="%css1Profile.name"
+ description="%css1Profile.description"
+ class="net.sourceforge.phpeclipse.css.core.profiles.Css1Profile"
+ id="net.sourceforge.phpeclipse.css.core.profiles.css1">
+ </profile>
+ <profile
+ name="%css2Profile.name"
+ description="%css2Profile.description"
+ class="net.sourceforge.phpeclipse.css.core.profiles.Css2Profile"
+ id="net.sourceforge.phpeclipse.css.core.profiles.css2">
+ </profile>
+ </extension>
+
+</plugin>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>\r
+<!-- Schema file written by PDE -->\r
+<schema targetNamespace="net.sf.wdte.css.ui">\r
+<annotation>\r
+ <appInfo>\r
+ <meta.schema plugin="net.sf.wdte.css.ui" id="profiles" name="CSS Profiles"/>\r
+ </appInfo>\r
+ <documentation>\r
+ [Enter description of this extension point.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <element name="extension">\r
+ <complexType>\r
+ <sequence>\r
+ <element ref="profile" minOccurs="1" maxOccurs="unbounded"/>\r
+ </sequence>\r
+ <attribute name="point" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="id" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="name" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ </complexType>\r
+ </element>\r
+\r
+ <element name="profile">\r
+ <complexType>\r
+ <attribute name="id" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="name" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="class" type="string" use="required">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ <attribute name="description" type="string">\r
+ <annotation>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+ </attribute>\r
+ </complexType>\r
+ </element>\r
+\r
+ <annotation>\r
+ <appInfo>\r
+ <meta.section type="since"/>\r
+ </appInfo>\r
+ <documentation>\r
+ [Enter the first release in which this extension point appears.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appInfo>\r
+ <meta.section type="examples"/>\r
+ </appInfo>\r
+ <documentation>\r
+ [Enter extension point usage example here.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appInfo>\r
+ <meta.section type="apiInfo"/>\r
+ </appInfo>\r
+ <documentation>\r
+ [Enter API information here.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appInfo>\r
+ <meta.section type="implementation"/>\r
+ </appInfo>\r
+ <documentation>\r
+ [Enter information about supplied implementation of this extension point.]\r
+ </documentation>\r
+ </annotation>\r
+\r
+ <annotation>\r
+ <appInfo>\r
+ <meta.section type="copyright"/>\r
+ </appInfo>\r
+ <documentation>\r
+ \r
+ </documentation>\r
+ </annotation>\r
+\r
+</schema>\r
--- /dev/null
+/*
+ * 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: CssCore.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core;
+
+import net.sourceforge.phpeclipse.css.core.internal.CssCorePreferences;
+import net.sourceforge.phpeclipse.css.core.internal.profiles.ProfileManager;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class CssCore extends Plugin {
+
+ // Class Variables ---------------------------------------------------------
+
+ /** The shared instance. */
+ private static CssCore plugin;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The profile manager.
+ */
+ private IProfileManager profileManager;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public CssCore() {
+ plugin = this;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the shared instance.
+ */
+ public static CssCore getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the plugin ID.
+ *
+ * @return the plugin ID
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ /**
+ * Returns the object that manages the CSS profiles.
+ *
+ * @return the profile manager
+ */
+ public synchronized IProfileManager getProfileManager() {
+ if (profileManager == null) {
+ profileManager = new ProfileManager(getPluginPreferences());
+ }
+ return profileManager;
+ }
+
+ /**
+ * Writes a status message and the associated exception stack trace (if
+ * provided) to the error log.
+ *
+ * @param status the status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ if (status.getException() != null) {
+ status.getException().printStackTrace(System.err);
+ }
+ }
+
+ /**
+ * Writes the specified error message and exception stack trace to the error
+ * log.
+ *
+ * @param message the error message
+ * @param e the exception that caused the error, or <tt>null</tt> to omit
+ * the stack trace in the log
+ */
+ public static void log(String message, Throwable e) {
+ IStatus status = new Status(IStatus.ERROR, getPluginId(), IStatus.ERROR,
+ message, e);
+ log(status);
+ }
+
+ /**
+ * Writes the specified error message to the error log.
+ *
+ * @param message the error message
+ */
+ public static void log(String message) {
+ IStatus status = new Status(IStatus.ERROR, getPluginId(), IStatus.ERROR,
+ message, null);
+ log(status);
+ }
+
+ /**
+ * Writes the stack trace of the given exception to the error log.
+ *
+ * @param e the exception that caused the error
+ */
+ public static void log(Throwable e) {
+ log(e.getMessage(), e);
+ }
+
+ // Plugin Implementation ---------------------------------------------------
+
+ /*
+ * @see Plugin#initializeDefaultPluginPreferences()
+ */
+ protected void initializeDefaultPluginPreferences() {
+ CssCorePreferences.initializeDefaultValues(getPluginPreferences());
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssCoreMessages.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.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 CssCoreMessages {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Qualified name of the resource bundle containing the localized messages.
+ */
+ private static final String RESOURCE_BUNDLE =
+ "net.sourceforge.phpeclipse.css.core.internal.CssCoreMessages"; //$NON-NLS-1$
+
+ // Class Variables ---------------------------------------------------------
+
+ /**
+ * The resource bundle.
+ */
+ private static ResourceBundle resourceBundle =
+ ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden constructor.
+ */
+ private CssCoreMessages() {
+ // 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);
+ }
+
+}
--- /dev/null
+#
+# 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: CssCoreMessages.properties,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+#
+
+# Problem Messages -------------------------------------------------------------
+
+CssParser.problem.emptyDeclarationValue = Empty declaration value
+CssParser.problem.expectedDeclaration = Expected declaration
+CssParser.problem.expectedProperty = Expected property
+CssParser.problem.expectedSelectorOrAtKeyword = Expected selector or at-keyword
+CssParser.problem.expectedToken = Expected token {0}
+CssParser.problem.illegalPositionForCDC = '-->' may only appear at the beginning of the style sheet
+CssParser.problem.illegalPositionForCDO = '<!--' may only appear at the beginning of the style sheet
+CssParser.problem.nestedComment = Comments cannot be nested
+CssParser.problem.unescapedNewlineInString = Newlines in strings need to be escaped with a backslash
+CssParser.problem.unexpectedEndOfFile = Unexpected end of file
+CssParser.problem.unexpectedToken = Expected {0}
+CssParser.problem.unterminatedComment = Unterminated comment
+CssParser.problem.runawayDeclaration = Runaway declaration?
+CssParser.problem.unterminatedString = Unterminated string
+CssParser.identifier = identifier
+CssParser.number = number
+CssParser.string = string
+
+# Profiles ---------------------------------------------------------------------
+
+CssProfile.category.aural = Aural
+CssProfile.category.box = Boxes and borders
+CssProfile.category.colorAndBackground = Color and background
+CssProfile.category.font = Fonts
+CssProfile.category.generatedContent = Generated content
+CssProfile.category.pagedMedia = Paged media
+CssProfile.category.table = Table
+CssProfile.category.text = Text properties
+CssProfile.category.userInterface = User interface
+CssProfile.category.visualEffects = Visual effects
+CssProfile.category.visualFormatting = Visual formatting
--- /dev/null
+/*
+ * 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: CssCorePreferences.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal;
+
+import org.eclipse.core.runtime.Preferences;
+
+/**
+ * TODO type comment
+ */
+public final class CssCorePreferences {
+
+ // Constants ---------------------------------------------------------------
+
+ public static final String PROFILE =
+ "profile"; //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden constructor.
+ */
+ private CssCorePreferences() {
+ // Hidden
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Initializes the given plugin preferences with the default values.
+ *
+ * @param preferences the preferences to initialize
+ */
+ public static void initializeDefaultValues(Preferences preferences) {
+ preferences.setDefault(PROFILE,
+ "net.sourceforge.phpeclipse.css.core.profiles.css2"); //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*
+ * 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: AbstractRule.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+
+/**
+ *
+ */
+public abstract class AbstractRule extends SourceReference
+ implements IRule {
+
+ // Instance Variables ------------------------------------------------------
+
+ private IStyleSheet styleSheet;
+
+ private IRule parent;
+
+ private List children = new ArrayList();
+
+ private List declarations = new ArrayList();
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document the document that contains the rule
+ * @param styleSheet the style sheet that contains the rule
+ */
+ public AbstractRule(IDocument document, IStyleSheet styleSheet) {
+ this(document, styleSheet, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document the document that contains the rule
+ * @param styleSheet the style sheet that contains the rule
+ * @param parent the parent rule, or <code>null</code> if the rule is at top
+ * level
+ */
+ public AbstractRule(IDocument document, IStyleSheet styleSheet,
+ IRule parent) {
+ super(document);
+ this.styleSheet = styleSheet;
+ this.parent = parent;
+ }
+
+ // IAdaptable Implementation -----------------------------------------------
+
+ /*
+ * @see IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+
+ // IStyleRule Implementation -----------------------------------------------
+
+ /*
+ * @see IRule#getStyleSheet()
+ */
+ public final IStyleSheet getStyleSheet() {
+ return styleSheet;
+ }
+
+ /*
+ * @see IRule#getParent()
+ */
+ public final IRule getParent() {
+ return parent;
+ }
+
+ /*
+ * @see IRule#getChildren()
+ */
+ public final IRule[] getChildren() {
+ return (IRule[]) children.toArray(new IRule[children.size()]);
+ }
+
+ /*
+ * @see IRule#getDeclarationAt(int)
+ */
+ public final IDeclaration getDeclarationAt(int offset) {
+ for (Iterator i = declarations.iterator(); i.hasNext(); ) {
+ IDeclaration declaration = (IDeclaration) i.next();
+ IRegion region = declaration.getSourceRegion();
+ if ((offset > region.getOffset())
+ && (offset < (region.getOffset() + region.getLength()))) {
+ return declaration;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see IRule#getDeclarations()
+ */
+ public final IDeclaration[] getDeclarations() {
+ return (IDeclaration[]) declarations.toArray(
+ new IDeclaration[declarations.size()]);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public final void addChild(IRule rule) {
+ children.add(rule);
+ }
+
+ public final void addDeclaration(IDeclaration declaration) {
+ declarations.add(declaration);
+ }
+
+}
--- /dev/null
+/*
+ * 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: AtRule.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ *
+ */
+public class AtRule extends AbstractRule
+ implements IAtRule {
+
+ // Instance Variables ------------------------------------------------------
+
+ private ISourceReference name;
+
+ private ISourceReference value;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the rule
+ */
+ public AtRule(IDocument document, IStyleSheet styleSheet) {
+ this(document, styleSheet, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the rule
+ * @param parent The parent rule, or <code>null</code> if the rule is at top
+ * level
+ */
+ public AtRule(IDocument document, IStyleSheet styleSheet, IRule parent) {
+ super(document, styleSheet, parent);
+ }
+
+ // IAtRule Implementation --------------------------------------------------
+
+ /*
+ * @see IAtRule#getName()
+ */
+ public final ISourceReference getName() {
+ return name;
+ }
+
+ /*
+ * @see IAtRule#getValue()
+ */
+ public final ISourceReference getValue() {
+ return value;
+ }
+
+ // Public Methods --------------------------------------------------
+
+ public final void setName(ISourceReference name) {
+ this.name = name;
+ }
+
+ public final void setValue(ISourceReference value) {
+ this.value = value;
+ }
+
+}
--- /dev/null
+/*
+ * 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: Declaration.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ *
+ */
+public class Declaration extends SourceReference
+ implements IDeclaration {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The rule that contains this declaration.
+ */
+ private IRule rule;
+
+ /**
+ * The part of the declaration that contains the property name.
+ */
+ private ISourceReference property;
+
+ /**
+ * The value part of the declaration.
+ */
+ private ISourceReference value;
+
+ /**
+ * The priority part of the declaration.
+ */
+ private ISourceReference priority;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document the document that contains the property
+ * @param rule the rule that contains this property, or <code>null</code> if
+ * the declaration does not belong to a specific rule
+ */
+ public Declaration(IDocument document, IRule rule) {
+ super(document);
+ this.rule = rule;
+ }
+
+ // IProperty Implementation ------------------------------------------------
+
+ /*
+ * @see IDeclaration#getRule()
+ */
+ public final IRule getRule() {
+ return rule;
+ }
+
+ /*
+ * @see IDeclaration#getProperty()
+ */
+ public final ISourceReference getProperty() {
+ return property;
+ }
+
+ /*
+ * @see IDeclaration#getValue()
+ */
+ public final ISourceReference getValue() {
+ return value;
+ }
+
+ /*
+ * @see IDeclaration#getPriority()
+ */
+ public final ISourceReference getPriority() {
+ return priority;
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * Sets the property.
+ *
+ * @param property The property to set
+ */
+ public final void setProperty(ISourceReference property) {
+ this.property = property;
+ }
+
+ /**
+ * Sets the value.
+ *
+ * @param value The value to set
+ */
+ public final void setValue(ISourceReference value) {
+ this.value = value;
+ }
+
+ /**
+ * Sets the priority.
+ *
+ * @param priority The priority to set
+ */
+ public final void setPriority(ISourceReference priority) {
+ this.priority = priority;
+ }
+
+}
--- /dev/null
+/*
+ * 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: PropertyInfo.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import net.sourceforge.phpeclipse.css.core.model.IPropertyInfo;
+
+/**
+ *
+ */
+public class PropertyInfo implements IPropertyInfo {
+
+ // Instance Variables ------------------------------------------------------
+
+ private String name;
+
+ private String category;
+
+ private String description;
+
+ private boolean shorthand;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the property
+ * @param category The category of the property
+ */
+ public PropertyInfo(String name, String category) {
+ this(name, category, false);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the property
+ * @param category The category of the property
+ * @param shorthand Whether the property is a shorthand property
+ */
+ public PropertyInfo(String name, String category, boolean shorthand) {
+ this(name, category, null, shorthand);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the property
+ * @param category The category of the property
+ * @param description An optional description of the property
+ * @param shorthand Whether the property is a shorthand property
+ */
+ public PropertyInfo(String name, String category, String description,
+ boolean shorthand) {
+ this.name = name;
+ this.category = category;
+ this.description = description;
+ this.shorthand = shorthand;
+ }
+
+ // IPropertyInfo Implementation --------------------------------------------
+
+ /*
+ * @see IPropertyInfo#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /*
+ * @see IPropertyInfo#getCategory()
+ */
+ public String getCategory() {
+ return category;
+ }
+
+ /*
+ * @see IPropertyInfo#getDescription()
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /*
+ * @see IPropertyInfo#isShorthand()
+ */
+ public boolean isShorthand() {
+ return shorthand;
+ }
+
+}
--- /dev/null
+/*
+ * 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: StyleRule.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ *
+ */
+public class StyleRule extends AbstractRule
+ implements IStyleRule {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The selector.
+ */
+ private ISourceReference selector;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the rule
+ */
+ public StyleRule(IDocument document, IStyleSheet styleSheet) {
+ this(document, styleSheet, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the rule
+ * @param parent The parent rule, or <code>null</code> if the rule is at top
+ * level
+ */
+ public StyleRule(IDocument document, IStyleSheet styleSheet, IRule parent) {
+ super(document, styleSheet, parent);
+ }
+
+ // IStyleRule Implementation -----------------------------------------------
+
+ /**
+ * @see IStyleRule#getSelector()
+ */
+ public final ISourceReference getSelector() {
+ return selector;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public final void setSelector(ISourceReference selector) {
+ this.selector = selector;
+ }
+
+}
--- /dev/null
+/*
+ * 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: StyleSheet.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.css.core.internal.parser.DefaultCssParser;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.core.parser.ICssParser;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IRegion;
+
+/**
+ *
+ */
+public class StyleSheet extends SourceReference
+ implements IStyleSheet, IDocumentListener {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The list of top-level CSS rules defined in the style sheet.
+ */
+ private List rules = new ArrayList();
+
+ private Object dirtyLock = new Object();
+ private boolean dirty = true;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the style sheet
+ */
+ public StyleSheet(IDocument document) {
+ super(document);
+ }
+
+ // IAdaptable Implementation -----------------------------------------------
+
+ /*
+ * @see IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+
+ // IStyleSheet Implementation ----------------------------------------------
+
+ /*
+ * @see IStyleSheet#getRuleAt(int)
+ */
+ public IRule getRuleAt(int offset) {
+ return getRuleAtInternal(getRules(), offset);
+ }
+
+ /*
+ * @see IStyleSheet#getRules()
+ */
+ public IRule[] getRules() {
+ return (IRule[]) rules.toArray(new IRule[rules.size()]);
+ }
+
+ /*
+ * @see IStyleSheet#reconcile(IProblemCollector)
+ */
+ public void reconcile(IProblemCollector problemCollector)
+ throws LexicalErrorException, SyntaxErrorException {
+
+ synchronized (dirtyLock) {
+ if (!dirty) {
+ return;
+ }
+ dirty = false;
+ }
+
+ synchronized (this) {
+ rules.clear();
+ ICssParser parser = new DefaultCssParser();
+ parser.setProblemCollector(problemCollector);
+ parser.setSource(getDocument());
+ rules.addAll(Arrays.asList(parser.parseRules(this)));
+ }
+ }
+
+ // IDocumentListener Implementation ----------------------------------------
+
+ /*
+ * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+ */
+ public void documentAboutToBeChanged(DocumentEvent event) {
+ // do nothing yet
+ }
+
+ /*
+ * @see IDocumentListener#documentChanged(DocumentEvent)
+ */
+ public void documentChanged(DocumentEvent event) {
+ synchronized (dirtyLock) {
+ dirty = true;
+ }
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Adds a rule to the style sheet.
+ *
+ * @param rule The rule to add
+ */
+ public void addRule(IRule rule) {
+ rules.add(rule);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private static IRule getRuleAtInternal(IRule rules[], int offset) {
+ IRule retVal = null;
+ for (int i = 0; i < rules.length; i++) {
+ IRule rule = rules[i];
+ IRegion region = rule.getSourceRegion();
+ if ((offset > region.getOffset())
+ && (offset < (region.getOffset() + region.getLength()))) {
+ if (rule.getChildren().length > 0) {
+ retVal = getRuleAtInternal(rule.getChildren(), offset);
+ if (retVal != null) {
+ break;
+ }
+ }
+ if (retVal == null) {
+ retVal = rule;
+ }
+ }
+ }
+ return retVal;
+ }
+
+}
--- /dev/null
+/*
+ * 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: AbstractProblemReporter.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.parser;
+
+import net.sourceforge.phpeclipse.css.core.internal.CssCoreMessages;
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemReporter;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+
+public abstract class AbstractProblemReporter implements IProblemReporter {
+
+ // Instance Variables ------------------------------------------------------
+
+ protected IDocument document;
+
+ protected IProblemCollector problemCollector = new IProblemCollector() {
+ public void addProblem(IProblem problem) {
+ // do nothing
+ }
+ };
+
+ // IProblemReporter Implementation -----------------------------------------
+
+ /*
+ * @see IProblemReporter#setProblemCollector(IProblemCollector)
+ */
+ public void setProblemCollector(IProblemCollector problemCollector) {
+ this.problemCollector = problemCollector;
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ protected final IProblem createError(String id, IRegion region) {
+ return createError(id, new String[0], region);
+ }
+
+ protected final IProblem createError(String id, String arg,
+ IRegion region) {
+ return createError(id, new String[] {arg}, region);
+ }
+
+ protected final IProblem createError(String id, String args[],
+ IRegion region) {
+ return createProblem(id, args, region, true);
+ }
+
+ protected final IProblem createWarning(String id, IRegion region) {
+ return createWarning(id, new String[0], region);
+ }
+
+ protected final IProblem createWarning(String id, String arg,
+ IRegion region) {
+ return createWarning(id, new String[] {arg}, region);
+ }
+
+ protected final IProblem createWarning(String id, String args[],
+ IRegion region) {
+ return createProblem(id, args, region, false);
+ }
+
+ protected final IProblem reportError(String id, IRegion region) {
+ return reportProblem(createError(id, region));
+ }
+
+ protected final IProblem reportError(String id, String arg,
+ IRegion region) {
+ return reportProblem(createError(id, arg, region));
+ }
+
+ protected final IProblem reportError(String id, String args[],
+ IRegion region) {
+ return reportProblem(createError(id, args, region));
+ }
+
+ protected final IProblem reportWarning(String id, IRegion region) {
+ return reportProblem(createWarning(id, region));
+ }
+
+ protected final IProblem reportWarning(String id, String arg,
+ IRegion region) {
+ return reportProblem(createWarning(id, arg, region));
+ }
+
+ protected final IProblem reportWarning(String id, String args[],
+ IRegion region) {
+ return reportProblem(createWarning(id, args, region));
+ }
+
+ protected final IProblem reportProblem(IProblem problem) {
+ problemCollector.addProblem(problem);
+ return problem;
+ }
+
+ protected final void setDocument(IDocument document) {
+ this.document = document;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private IProblem createProblem(String id, String args[],
+ IRegion region, boolean error) {
+ String message = CssCoreMessages.getString(
+ "CssParser.problem." + id, args); //$NON-NLS-1$
+ int offset = region.getOffset();
+ int lineNumber = -1;
+ try {
+ lineNumber = document.getLineOfOffset(offset);
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ return new DefaultProblem(id, message, null, offset,
+ offset + region.getLength(), lineNumber, error);
+ }
+
+}
--- /dev/null
+/*
+ * 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: DefaultCssParser.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.parser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.css.core.internal.model.AtRule;
+import net.sourceforge.phpeclipse.css.core.internal.model.Declaration;
+import net.sourceforge.phpeclipse.css.core.internal.model.StyleRule;
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.core.parser.ICssParser;
+import net.sourceforge.phpeclipse.css.core.parser.ICssScanner;
+import net.sourceforge.phpeclipse.css.core.parser.ICssTokens;
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * A simple CSS parser implementation.
+ *
+ * TODO At-rules can contain child rules as well as declarations. Currently we
+ * only handle child rules.
+ */
+public class DefaultCssParser extends AbstractProblemReporter
+ implements ICssParser {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The underlying CSS token scanner.
+ */
+ private ICssScanner scanner;
+
+ /**
+ * The token being currently processed.
+ */
+ private int currentToken;
+
+ /**
+ * Whether the parser is currently initializer. Is <code>true</code> as soon
+ * as currentToken has been initialized.
+ */
+ private boolean initialized;
+
+ // ICssParser Implementation -----------------------------------------------
+
+ /**
+ * @see ICssParser#parseRules(IStyleSheet)
+ */
+ public IRule[] parseRules(IStyleSheet styleSheet)
+ throws LexicalErrorException, SyntaxErrorException {
+ List rules = new ArrayList();
+ nextToken();
+ if (currentToken == ICssTokens.CDO) {
+ // ignore an opening SGML comment delimiter at the start of the
+ // style sheet
+ nextToken();
+ }
+ while (currentToken != ICssTokens.EOF) {
+ if (currentToken == ICssTokens.CDC) {
+ // ignore a closing SGML comment delimiter at the end of the
+ // style sheet
+ IProblem problem = createWarning(
+ "illegalPositionForCDC", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ if (nextToken() != ICssTokens.EOF) {
+ reportProblem(problem);
+ }
+ } else if (currentToken == ICssTokens.CDO) {
+ reportWarning("illegalPositionForCDO", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ nextToken();
+ } else {
+ IRule rule = parseRule(styleSheet, null);
+ if (rule != null) {
+ rules.add(rule);
+ } else {
+ break;
+ }
+ }
+ }
+ return (IRule[]) rules.toArray(new IRule[rules.size()]);
+ }
+
+ /**
+ * Parses a CSS rule, which can be either an at-rule like
+ * <code>@import</code> or a normal style rule.
+ *
+ * @param parent the parent rule in which the rule to parse is nested, or
+ * <code>null</code> if the rule to parse is at the top level of the
+ * style sheet
+ * @return the parsed rule
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ public IRule parseRule(IStyleSheet styleSheet, IRule parent)
+ throws LexicalErrorException, SyntaxErrorException {
+ if (!initialized) {
+ nextToken();
+ }
+ if ((currentToken == -1) || (currentToken == '}')) {
+ reportError("expectedRule", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ return null;
+ }
+ switch (currentToken) {
+ case ICssTokens.AT: {
+ return parseAtRule(styleSheet, parent);
+ }
+ default: {
+ return parseStyleRule(styleSheet, parent);
+ }
+ }
+ }
+
+ /**
+ * Parses a CSS selector. The provided reader is expected to be positioned
+ * at the beginning of the selector (leading whitespace will be ignored).
+ *
+ * @return the parsed selector
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ public ISourceReference parseSelector(IRule rule)
+ throws LexicalErrorException, SyntaxErrorException {
+ if (!initialized) {
+ nextToken();
+ }
+ return parseAnythingUpto(new int[] { ICssTokens.LBRACE });
+ }
+
+ /**
+ * Parses a declaration. The provided reader is expected to be positioned at
+ * the beginning of the property name (leading whitespace will be ignored).
+ * The return declaration will start with the start of the property, and
+ * will end at the end of the value, excluding the semicolon, if one is
+ * present.
+ *
+ * @return the parsed style declaration
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ public IDeclaration parseDeclaration(IRule rule)
+ throws LexicalErrorException, SyntaxErrorException {
+ if (!initialized) {
+ nextToken();
+ }
+ if ((currentToken == -1) || (currentToken == '}')) {
+ return null;
+ }
+ Declaration declaration = new Declaration(document, rule);
+ MutableRegion declarationRegion = newRegion();
+
+ // parse the property
+ if (currentToken == ICssTokens.IDENT) {
+ SourceReference property = new SourceReference(document);
+ property.setSourceRegion(scanner.getTokenRegion());
+ declaration.setProperty(property);
+ nextToken(declarationRegion);
+ } else {
+ reportError("expectedProperty", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ }
+
+ // expect a colon to delimit the property from the value
+ if (currentToken == ICssTokens.COLON) {
+ nextToken(declarationRegion);
+ } else {
+ reportError("expectedToken", ":", //$NON-NLS-1$ //$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+
+ // parse the declaration value (excluding the priority)
+ ISourceReference value = parseAnythingUpto(new int[] {
+ ICssTokens.RBRACE, ICssTokens.SEMICOLON, ICssTokens.EXCLAMATION
+ });
+ if (value != null) {
+ declaration.setValue(value);
+ declarationRegion.add(value.getSourceRegion());
+ } else {
+ reportError("emptyDeclarationValue", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ }
+
+ // if present, parse the declaration priority
+ if (currentToken == '!') {
+ SourceReference priority = new SourceReference(document);
+ MutableRegion priorityRegion = newRegion();
+ if (nextToken() == ICssTokens.IDENT) {
+ nextToken(priorityRegion);
+ } else {
+ reportError("priorityExpected", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ }
+ priority.setSourceRegion(priorityRegion);
+ declaration.setPriority(priority);
+ declarationRegion.add(priority.getSourceRegion());
+ }
+
+ declaration.setSourceRegion(declarationRegion);
+ return declaration;
+ }
+
+ /**
+ * @see ICssParser#setProblemCollector(IProblemCollector)
+ */
+ public void setProblemCollector(IProblemCollector problemCollector) {
+ super.setProblemCollector(problemCollector);
+ if (scanner != null) {
+ scanner.setProblemCollector(problemCollector);
+ }
+ }
+
+ /**
+ * @see ICssParser#setSource(IDocument)
+ */
+ public void setSource(IDocument document) {
+ setDocument(document);
+ if (scanner != null) {
+ scanner.setSource(document);
+ }
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ protected ICssScanner createScanner(IDocument document) {
+ ICssScanner retVal = new DefaultCssScanner();
+ retVal.setSource(document);
+ retVal.setProblemCollector(problemCollector);
+ return retVal;
+ }
+
+ /**
+ * Parses a region of the source until one of the specified tokens is
+ * encountered. In addition, this method keeps track of opened parenthesis
+ * and brackets, and will report an error if they are not closed.
+ *
+ * @param tokens an array containing the tokens that should delimit the
+ * range of source to parse
+ * @return the parsed source reference
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ protected final ISourceReference parseAnythingUpto(int tokens[])
+ throws LexicalErrorException, SyntaxErrorException {
+ Arrays.sort(tokens);
+ SourceReference any = null;
+ MutableRegion region = newRegion();
+ while (currentToken != ICssTokens.EOF) {
+ if (Arrays.binarySearch(tokens, currentToken) >= 0) {
+ break;
+ } else {
+ any = new SourceReference(document);
+ if ((currentToken == '(') || (currentToken == '[')) {
+ char peer = CssTextUtils.getPeerCharacter(
+ (char) currentToken);
+ nextToken(region);
+ ISourceReference ref =
+ parseAnythingUpto(new int[] { peer } );
+ if (currentToken != peer) {
+ reportError("expectedToken", //$NON-NLS-1$
+ String.valueOf(peer), scanner.getTokenRegion());
+ }
+ if (ref != null) {
+ region.add(ref.getSourceRegion());
+ }
+ }
+ }
+ nextToken(region);
+ }
+ if (any != null) {
+ any.setSourceRegion(region);
+ }
+ return any;
+ }
+
+ /**
+ * Parses an at-rule.
+ *
+ * @param styleSheet the owning style sheet
+ * @param parent the rule in which the rule to parse is nested, or
+ * <code>null</code> if this rule is at the top level of the style
+ * sheet
+ * @return the parsed rule
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ protected final IAtRule parseAtRule(IStyleSheet styleSheet, IRule parent)
+ throws LexicalErrorException, SyntaxErrorException {
+ AtRule rule = new AtRule(document, styleSheet, parent);
+ MutableRegion ruleRegion = newRegion();
+ if (currentToken == ICssTokens.AT) {
+ nextToken();
+ } else {
+ reportError("expectedToken", "@", //$NON-NLS-1$//$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+ if (currentToken == ICssTokens.IDENT) {
+ SourceReference name = new SourceReference(document);
+ name.setSourceRegion(scanner.getTokenRegion());
+ rule.setName(name);
+ nextToken(ruleRegion);
+ } else {
+ reportError("expectedAtKeyword", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ }
+ if ((currentToken != ICssTokens.LBRACE)
+ && (currentToken != ICssTokens.SEMICOLON)
+ && (currentToken != ICssTokens.EOF)) {
+ ISourceReference value = parseAnythingUpto(new int[] {
+ ICssTokens.LBRACE, ICssTokens.SEMICOLON
+ });
+ rule.setValue(value);
+ ruleRegion.add(value.getSourceRegion());
+ }
+ if (currentToken == ICssTokens.LBRACE) {
+ nextToken(ruleRegion);
+ while (currentToken != ICssTokens.RBRACE) {
+ IRule child = parseRule(styleSheet, rule);
+ if (child != null) {
+ rule.addChild(child);
+ ruleRegion.add(child.getSourceRegion());
+ }
+ if (currentToken == ICssTokens.EOF) {
+ reportError("unexpectedEndOfFile", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ break;
+ }
+ }
+ if (currentToken == ICssTokens.RBRACE) {
+ nextToken(ruleRegion);
+ } else {
+ reportError("expectedToken", "}", //$NON-NLS-1$ //$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+ } else {
+ if ((rule.getValue() == null) && (rule.getChildren().length == 0)) {
+ reportError("expectedValueOrBlock", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ } else if (currentToken != ICssTokens.SEMICOLON) {
+ reportError("expectedToken", ";", //$NON-NLS-1$ //$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+ if (currentToken == ICssTokens.SEMICOLON) {
+ nextToken(ruleRegion);
+ }
+ }
+ rule.setSourceRegion(ruleRegion);
+ return rule;
+ }
+
+ /**
+ * Parses a style rule.
+ *
+ * <p>
+ * This corresponds to the <code>ruleset</code> production in the
+ * specification of the CSS 3 syntax module:
+ * </p>
+ * <pre>
+ * selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*
+ * </pre>
+ *
+ * <p>
+ * <strong>Question</strong>: why is the selector optional in the above
+ * production? In section 4.8 the specification says that <em>"A rule set
+ * (also called 'rule') consists of a selector followed by a declaration
+ * block."</em> So we should be able to assume that there
+ * <strong>must</strong> be a selector, and otherwise report an error.
+ * </p>
+ *
+ * @param parent the parent rule in which the style rule is nested, or
+ * <code>null</code> if the style rule to parse is at the top level
+ * of the style sheet
+ * @return the parsed style rule
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ protected final IStyleRule parseStyleRule(IStyleSheet styleSheet,
+ IRule parent) throws LexicalErrorException, SyntaxErrorException {
+ StyleRule rule = new StyleRule(document, styleSheet, parent);
+ MutableRegion ruleRegion = newRegion();
+ ISourceReference selector = parseSelector(rule);
+ if (selector != null) {
+ rule.setSelector(selector);
+ } else {
+ reportError("expectedSelectorOrAtKeyword", //$NON-NLS-1$
+ scanner.getTokenRegion());
+ }
+ if (currentToken == ICssTokens.LBRACE) {
+ nextToken(ruleRegion);
+ do {
+ IDeclaration declaration = parseDeclaration(rule);
+ if (declaration != null) {
+ rule.addDeclaration(declaration);
+ ruleRegion.add(declaration.getSourceRegion());
+ }
+ if (currentToken == ';') {
+ nextToken(ruleRegion);
+ } else {
+ break;
+ }
+ } while ((currentToken != ICssTokens.RBRACE)
+ && (currentToken != ICssTokens.EOF));
+ if (currentToken == ICssTokens.RBRACE) {
+ nextToken(ruleRegion);
+ } else {
+ reportError("expectedToken", "}", //$NON-NLS-1$ //$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+ } else {
+ reportError("expectedToken", "{", //$NON-NLS-1$ //$NON-NLS-2$
+ scanner.getTokenRegion());
+ }
+ rule.setSourceRegion(ruleRegion);
+ return rule;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private int nextToken() throws LexicalErrorException {
+ return nextToken(null);
+ }
+
+ private int nextToken(MutableRegion region) throws LexicalErrorException {
+ initialized = true;
+ if (scanner == null) {
+ scanner = createScanner(document);
+ }
+ if (region != null) {
+ region.add(scanner.getTokenRegion());
+ }
+ currentToken = scanner.getNextToken();
+ return currentToken;
+ }
+
+ private MutableRegion newRegion() {
+ return new MutableRegion(scanner.getTokenRegion());
+ }
+}
--- /dev/null
+/*
+ * 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: DefaultCssScanner.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.parser;
+
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.core.parser.ICssScanner;
+import net.sourceforge.phpeclipse.css.core.parser.ICssTokens;
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+/**
+ * Default implementation of a lexical scanner for CSS.
+ *
+ * TODO Add support for character escapes and unicode ranges
+ */
+public class DefaultCssScanner extends AbstractProblemReporter
+ implements ICssScanner {
+
+ // Instance Variables ------------------------------------------------------
+
+ private int currentChar;
+
+ private int offset;
+
+ private int tokenOffset;
+
+ // ICssScanner Implementation ----------------------------------------------
+
+ /**
+ * @see ICssScanner#getTokenRegion()
+ */
+ public IRegion getTokenRegion() {
+ return new Region(tokenOffset, offset - tokenOffset);
+ }
+
+ /**
+ * @see ICssScanner#getNextToken()
+ */
+ public int getNextToken() throws LexicalErrorException {
+ if (document == null) {
+ throw new IllegalStateException("Source must be set"); //$NON-NLS-1$
+ }
+ if (currentChar == -1) {
+ return ICssTokens.EOF;
+ }
+ tokenOffset = offset;
+ getNextCharOrEnd();
+ switch (currentChar) {
+ case '@': {
+ return ICssTokens.AT;
+ }
+ case ':': {
+ return ICssTokens.COLON;
+ }
+ case '.': {
+ if (Character.isDigit((char) peekNextChar())) {
+ return handleNumber();
+ }
+ return currentChar;
+ }
+ case '{': {
+ return ICssTokens.LBRACE;
+ }
+ case '[': {
+ return ICssTokens.LBRACKET;
+ }
+ case '(': {
+ return ICssTokens.LPAREN;
+ }
+ case '}': {
+ return ICssTokens.RBRACE;
+ }
+ case ']': {
+ return ICssTokens.RBRACKET;
+ }
+ case ')': {
+ return ICssTokens.RPAREN;
+ }
+ case ';': {
+ return ICssTokens.SEMICOLON;
+ }
+ case '/': {
+ if (peekNextChar() == '*') {
+ getNextCharOrEnd();
+ return handleComment();
+ }
+ return currentChar;
+ }
+ case '\'':
+ case '"': {
+ return handleString((char) currentChar);
+ }
+ case '<': {
+ if (peekNextChar() == '!') {
+ getNextCharOrEnd();
+ return handleCdo();
+ }
+ return currentChar;
+ }
+ case '-': {
+ if (peekNextChar() == '-') {
+ getNextCharOrEnd();
+ return handleCdc();
+ } else if (CssTextUtils.isCssNumberStart((char)
+ peekNextChar())) {
+ return handleNumber();
+ }
+ return currentChar;
+ }
+ default: {
+ if (CssTextUtils.isCssIdentifierStart((char) currentChar)) {
+ return handleIdentifier();
+ } else if (Character.isDigit((char) currentChar)) {
+ return handleNumber();
+ } else if (CssTextUtils.isCssWhitespace((char) currentChar)) {
+ return handleWhitespace();
+ }
+ return currentChar;
+ }
+ }
+ }
+
+ /**
+ * @see ICssScanner#setSource(IDocument)
+ */
+ public void setSource(IDocument document) {
+ super.setDocument(document);
+ currentChar = 0;
+ offset = 0;
+ tokenOffset = 0;
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ protected int handleCdc() throws LexicalErrorException {
+ if (currentChar != '-') {
+ throw new IllegalStateException(
+ "Not at the beginning of a CDC"); //$NON-NLS-1$
+ }
+ if (peekNextChar() != '>') {
+ // not a CDC, rewind and return the start character
+ offset -= 2;
+ return getNextCharOrEnd();
+ }
+ getNextCharOrEnd();
+ return ICssTokens.CDC;
+ }
+
+ protected int handleCdo() throws LexicalErrorException {
+ if (currentChar != '!') {
+ throw new IllegalStateException(
+ "Not at the beginning of a CDO"); //$NON-NLS-1$
+ }
+ if (peekNextChar() != '-') {
+ // not a CDO, rewind and return the start character
+ offset -= 2;
+ return getNextCharOrEnd();
+ }
+ getNextCharOrEnd();
+ if (peekNextChar() != '-') {
+ // not a CDO, rewind and return the start character
+ offset -= "!--".length(); //$NON-NLS-1$
+ return getNextCharOrEnd();
+ }
+ getNextCharOrEnd();
+ return ICssTokens.CDO;
+ }
+
+ protected int handleComment() throws LexicalErrorException {
+ if (currentChar != '*') {
+ throw new IllegalStateException(
+ "Not at the beginning of a comment"); //$NON-NLS-1$
+ }
+ do {
+ do {
+ getNextCharOrError("unterminatedComment"); //$NON-NLS-1$
+ } while (currentChar != '*');
+ getNextCharOrError("unterminatedComment"); //$NON-NLS-1$
+ while (currentChar == '*') {
+ getNextCharOrError("unterminatedComment"); //$NON-NLS-1$
+ }
+ } while (currentChar != '/');
+ return getNextToken();
+ }
+
+ protected int handleIdentifier() throws LexicalErrorException {
+ if (!CssTextUtils.isCssIdentifierStart((char) currentChar)) {
+ throw new IllegalStateException(
+ "Not at the beginning of an identifier"); //$NON-NLS-1$
+ }
+ while (CssTextUtils.isCssIdentifierPart((char) peekNextChar())) {
+ getNextCharOrEnd();
+ }
+ return ICssTokens.IDENT;
+ }
+
+ protected int handleNumber() throws LexicalErrorException {
+ if (!CssTextUtils.isCssNumberStart((char) currentChar)) {
+ throw new IllegalStateException(
+ "Not at the beginning of a number"); //$NON-NLS-1$
+ }
+ while (CssTextUtils.isCssNumberPart((char) peekNextChar())) {
+ getNextCharOrEnd();
+ }
+ if (peekNextChar() == '.') {
+ getNextCharOrEnd();
+ while (Character.isDigit((char) peekNextChar())) {
+ getNextCharOrEnd();
+ }
+ }
+ return ICssTokens.NUM;
+ }
+
+ protected int handleString(char delim) throws LexicalErrorException {
+ if (currentChar != delim) {
+ throw new IllegalStateException(
+ "Not at the beginning of a string"); //$NON-NLS-1$
+ }
+ do {
+ getNextCharOrError("unterminatedString"); //$NON-NLS-1$
+ if (currentChar == '\\') {
+ getNextCharOrEnd();
+ getNextCharOrError("unterminatedString"); //$NON-NLS-1$
+ } else if (currentChar == '\n') {
+ reportError("unescapedNewlineInString", //$NON-NLS-1$
+ new Region(tokenOffset, offset - tokenOffset));
+ }
+ } while (currentChar != delim);
+ return ICssTokens.STRING;
+ }
+
+ protected int handleWhitespace() throws LexicalErrorException {
+ if (!CssTextUtils.isCssWhitespace((char) currentChar)) {
+ throw new IllegalStateException(
+ "Not at the beginning of white space"); //$NON-NLS-1$
+ }
+ while (CssTextUtils.isCssWhitespace((char) peekNextChar())) {
+ getNextCharOrEnd();
+ }
+ return getNextToken();
+ }
+
+ /**
+ * Positions the scanner over the next character in the source and returns
+ * that character. If the end of the source is reached, an 'unexpected end
+ * of file' error is reported.
+ *
+ * @param errorId the ID of the error to report
+ * @return the next character in the source, or -1 if the end of the source
+ * has been reached
+ * @throws LexicalErrorException If the end of the source has been reached
+ * and no problem collector has been configured to collect the
+ * problem
+ */
+ protected final int getNextCharOrError(String errorId)
+ throws LexicalErrorException {
+ getNextCharOrEnd();
+ if (currentChar == -1) {
+ IProblem error = reportError(errorId,
+ new Region(tokenOffset, offset - tokenOffset));
+ throw new LexicalErrorException(error.getMessage());
+ }
+ return currentChar;
+ }
+
+ /**
+ * Positions the scanner over the next character in the source and returns
+ * that character.
+ *
+ * @return the next character in the source, or -1 if the end of the source
+ * has been reached
+ */
+ protected final int getNextCharOrEnd() {
+ try {
+ currentChar = document.getChar(offset);
+ if (currentChar != -1) {
+ offset++;
+ }
+ } catch (BadLocationException e) {
+ currentChar = -1;
+ }
+ return currentChar;
+ }
+
+ /**
+ * Returns the next character in the source without changing the scanners
+ * current position (look ahead).
+ *
+ * @return the next character in the source, or -1 if the end of the source
+ * has been reached
+ */
+ protected final int peekNextChar() {
+ int retVal = -1;
+ try {
+ retVal = document.getChar(offset);
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ return retVal;
+ }
+
+}
--- /dev/null
+/*
+ * 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:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.parser;
+
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+
+public class DefaultProblem implements IProblem {
+
+ // Instance Variables ------------------------------------------------------
+
+ private String id;
+
+ private String message;
+
+ private String originatingFileName;
+
+ private int sourceStart;
+
+ private int sourceEnd;
+
+ private int sourceLineNumber;
+
+ private boolean error;
+
+ // Constructors ------------------------------------------------------------
+
+ public DefaultProblem(String id, String message, String originatingFileName,
+ int sourceStart, int sourceEnd, int sourceLineNumber, boolean error) {
+ this.id = id;
+ this.message = message;
+ this.originatingFileName = originatingFileName;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ this.sourceLineNumber = sourceLineNumber;
+ this.error = error;
+ }
+
+ // IProblem Implementation -------------------------------------------------
+
+ /*
+ * @see IProblem#getID()
+ */
+ public String getId() {
+ return id;
+ }
+
+ /*
+ * @see IProblem#getMessage()
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /*
+ * @see IProblem#getOriginatingFileName()
+ */
+ public String getOriginatingFileName() {
+ return originatingFileName;
+ }
+
+ /*
+ * @see IProblem#getSourceEnd()
+ */
+ public int getSourceEnd() {
+ return sourceEnd;
+ }
+
+ /*
+ * @see IProblem#getSourceLineNumber()
+ */
+ public int getSourceLineNumber() {
+ return sourceLineNumber;
+ }
+
+ /*
+ * @see IProblem#getSourceStart()
+ */
+ public int getSourceStart() {
+ return sourceStart;
+ }
+
+ /*
+ * @see IProblem#isError()
+ */
+ public boolean isError() {
+ return error;
+ }
+
+ /*
+ * @see IProblem#isWarning()
+ */
+ public boolean isWarning() {
+ return !error;
+ }
+
+}
--- /dev/null
+/*
+ * 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: MutableRegion.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.parser;
+
+import org.eclipse.jface.text.IRegion;
+
+/**
+ *
+ */
+public class MutableRegion implements IRegion {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The offset of the region.
+ */
+ private int offset = 0;
+
+ /**
+ * The length of the region.
+ */
+ private int length = 0;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public MutableRegion() {
+ this(0);
+ }
+
+ /**
+ * Constructor with partial initialization.
+ *
+ * @param offset the offset of the region
+ */
+ public MutableRegion(int offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * Constructor with initialization.
+ *
+ * @param offset the offset of the region
+ * @param length the length of the region
+ */
+ public MutableRegion(int offset, int length) {
+ this.offset = offset;
+ this.length = length;
+ }
+
+ /**
+ * Constructor with initialization.
+ *
+ * @param region another region to initialize this region with
+ */
+ public MutableRegion(IRegion region) {
+ this.offset = region.getOffset();
+ this.length = region.getLength();
+ }
+
+ // IRegion Implementation --------------------------------------------------
+
+ /*
+ * @see org.eclipse.jface.text.IRegion#getLength()
+ */
+ public int getLength() {
+ return length;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IRegion#getOffset()
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Adds another region to this region, which will be enlarged so that the
+ * added region completely fits into this region.
+ *
+ * @param region the region to add
+ */
+ public void add(IRegion region) {
+ int start1 = offset;
+ int end1 = offset + length;
+ int start2 = region.getOffset();
+ int end2 = start2 + region.getLength();
+ offset = (start1 < start2) ? start1 : start2;
+ length = (end1 > end2) ? (end1 - offset) : (end2 - offset);
+ }
+
+ /**
+ * Sets the length of the region.
+ *
+ * @param length the length to set
+ */
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ /**
+ * Sets the offset of the region.
+ *
+ * @param offset the offset to set
+ */
+ public void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+}
--- /dev/null
+/*
+ * 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: ProfileDescriptor.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.profiles;
+
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileDescriptor;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+
+
+/**
+ *
+ */
+public class ProfileDescriptor implements IProfileDescriptor {
+
+ // Constants ---------------------------------------------------------------
+
+ private static final String ATTR_ID = "id"; //$NON-NLS-1$
+ private static final String ATTR_NAME = "name"; //$NON-NLS-1$
+ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+ private static final String ATTR_DESCRIPTION = "description"; //$NON-NLS-1$
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The profile ID.
+ */
+ private String id;
+
+ /**
+ * The name of the profile.
+ */
+ private String name;
+
+ /**
+ * The name of the implementation class.
+ */
+ private String className;
+
+ /**
+ * An optional description.
+ */
+ private String description;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param element The configuration element corresponding to the declaration
+ * of the profile
+ */
+ public ProfileDescriptor(IConfigurationElement element) {
+ this.id = element.getAttribute(ATTR_ID);
+ this.name = element.getAttribute(ATTR_NAME);
+ this.className = element.getAttribute(ATTR_CLASS);
+ this.description = element.getAttribute(ATTR_DESCRIPTION);
+ }
+
+ // IProfileDescriptor Implementation ---------------------------------------
+
+ /**
+ * @see IProfileDescriptor#getId()
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @see IProfileDescriptor#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see IProfileDescriptor#getDescription()
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * @see IProfileDescriptor#getClassName()
+ */
+ public String getClassName() {
+ return className;
+ }
+
+}
--- /dev/null
+/*
+ * 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: ProfileManager.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.profiles;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.internal.CssCorePreferences;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileDescriptor;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
+
+/**
+ * Implementation of the <code>IProfileManager</code> interface.
+ */
+public class ProfileManager implements IProfileManager {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * The qualified name used to persist the selected profile on projects and
+ * resources.
+ */
+ public static final QualifiedName PROFILE_PROPERTY =
+ new QualifiedName(CssCore.getPluginId(), "profile"); //$NON-NLS-1$
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The plugin preferences.
+ */
+ private Preferences preferences;
+
+ /**
+ * The profile descriptors, keyed by extension ID.
+ */
+ private Map profileDescriptors;
+
+ /**
+ * Cache of the already loaded profiles.
+ */
+ private Map profiles = new WeakHashMap();
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param preferences the plugin preferences
+ */
+ public ProfileManager(Preferences preferences) {
+ this.preferences = preferences;
+ }
+
+ // IProfileManager Implementation ------------------------------------------
+
+ /**
+ * @see IProfileManager#getProfileDescriptors()
+ */
+ public IProfileDescriptor[] getProfileDescriptors() {
+ if (profileDescriptors == null) {
+ loadProfileExtensions();
+ }
+ List retVal = new ArrayList();
+ retVal.addAll(profileDescriptors.values());
+ return (IProfileDescriptor[]) retVal.toArray(
+ new IProfileDescriptor[retVal.size()]);
+ }
+
+ /**
+ * @see IProfileManager#getProfile(IResource)
+ */
+ public IProfile getProfile(IResource resource) {
+ String profileId = null;
+ if (resource != null) {
+ try {
+ profileId = resource.getPersistentProperty(PROFILE_PROPERTY);
+ } catch (CoreException e) {
+ CssCore.log(
+ "Failed to get profile for resource", e); //$NON-NLS-1$
+ }
+ if (profileId == null) {
+ IProject project = resource.getProject();
+ try {
+ profileId = project.getPersistentProperty(PROFILE_PROPERTY);
+ } catch (CoreException e) {
+ CssCore.log(
+ "Failed to get profile for project", e); //$NON-NLS-1$
+ }
+ }
+ }
+ if (profileId == null) {
+ profileId = preferences.getString(CssCorePreferences.PROFILE);
+ }
+ IProfile profile = getProfile(profileId);
+ return profile;
+ }
+
+ /**
+ * @see IProfileManager#setProfile(IResource, String)
+ */
+ public void setProfile(IResource resource, String profileId) {
+ if (resource != null) {
+ try {
+ resource.setPersistentProperty(
+ ProfileManager.PROFILE_PROPERTY, profileId);
+ } catch (CoreException e) {
+ CssCore.log(
+ "Cannot store profile as resource property", //$NON-NLS-1$
+ e);
+ }
+ } else if (profileId != null) {
+ preferences.setValue(CssCorePreferences.PROFILE, profileId);
+ } else {
+ preferences.setToDefault(CssCorePreferences.PROFILE);
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the profile associated with the specified extension ID. The
+ * profile is instantiated if not already in the cache.
+ *
+ * @param profileId the ID of the extension implementing the profile
+ */
+ private IProfile getProfile(String profileId) {
+ IProfile profile = (IProfile) profiles.get(profileId);
+ if (profile == null) {
+ IProfileDescriptor descriptor = getProfileDescriptor(profileId);
+ if (descriptor == null) {
+ CssCore.log("Profile '" + profileId + //$NON-NLS-1$
+ "' not found."); //$NON-NLS-1$
+ descriptor = getDefaultProfileDescriptor();
+ }
+ if (descriptor != null) {
+ profile = instantiateProfile(descriptor);
+ profiles.put(profileId, profile);
+ }
+ }
+ return profile;
+ }
+
+ /**
+ * Returns the descriptor of the default profile.
+ *
+ * @return the descriptor of the default profile
+ */
+ private IProfileDescriptor getDefaultProfileDescriptor() {
+ String profileId = preferences.getDefaultString(
+ CssCorePreferences.PROFILE);
+ return getProfileDescriptor(profileId);
+ }
+
+ /**
+ * Returns the descriptor of the specified profile.
+ *
+ * @param profileId the ID of the profile
+ * @return the descriptor of the profile with the given ID
+ */
+ private IProfileDescriptor getProfileDescriptor(String profileId) {
+ if (profileDescriptors == null) {
+ loadProfileExtensions();
+ }
+ return (IProfileDescriptor) profileDescriptors.get(profileId);
+ }
+
+ /**
+ * Instantiates and the returns the profile.
+ *
+ * @param descriptor the profile descriptor
+ * @return the instantiated profile, or <code>null</code> if there was a
+ * problem instantiating the profile
+ */
+ private IProfile instantiateProfile(IProfileDescriptor descriptor) {
+ try {
+ Class clazz = Class.forName(descriptor.getClassName());
+ Constructor ctor = clazz.getConstructor(
+ new Class[] { IProfileDescriptor.class });
+ return (IProfile) ctor.newInstance(new Object[] { descriptor });
+ } catch (Exception e) {
+ CssCore.log("Failed to get CSS profile", e); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Initializes the list of available profiles by querying the platform for
+ * extensions of the <em>profiles</em> extension point and storing an
+ * <code>IProfileDescriptor</code> for each extension found.
+ */
+ private void loadProfileExtensions() {
+ profileDescriptors = new HashMap();
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IExtensionPoint extensionPoint = registry.getExtensionPoint(
+ IProfileDescriptor.EXTENSION_POINT_ID);
+ IExtension[] extensions = extensionPoint.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IExtension extension = extensions[i];
+ IConfigurationElement[] elements =
+ extension.getConfigurationElements();
+ for (int j = 0; j < elements.length; j++) {
+ IConfigurationElement element = elements[j];
+ IProfileDescriptor descriptor = new ProfileDescriptor(element);
+ profileDescriptors.put(descriptor.getId(), descriptor);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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: CssCodeReader.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.text;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ *
+ */
+public class CssCodeReader extends Reader {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Constant for configuring a reader to read the document backwards.
+ */
+ public static final int BACKWARD = -1;
+
+ /**
+ * Constant for configuring a reader to read the document forwards.
+ */
+ public static final int FORWARD = 1;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The document to read. Is <code>null</code> when the reader is closed.
+ */
+ private IDocument document;
+
+ /**
+ * The direction in which the document should be read. Can be either
+ * {@link CssCodeReader#BACKWARD} or {@link CssCodeReader#FORWARD}.
+ */
+ private int direction;
+
+ /**
+ * The offset at which to start reading.
+ */
+ private int offset;
+
+ /**
+ * The offset at which to end reading.
+ */
+ private int end = -1;
+
+ /**
+ * Whether comments should be skipped.
+ */
+ private boolean skipComments;
+
+ /**
+ * Whether string literals should be skipped.
+ */
+ private boolean skipStrings;
+
+ /**
+ * Whether whitespace characters should be skipped.
+ */
+ private boolean skipWhitespace;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document the document to read
+ * @param offset the offset at which to start reading
+ */
+ public CssCodeReader(IDocument document, int offset) {
+ this(document, offset, document.getLength() - offset, FORWARD);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document the document to read
+ * @param offset the offset at which to start reading
+ * @param length the number of characters to read at most
+ */
+ public CssCodeReader(IDocument document, int offset, int length) {
+ this(document, offset, length, FORWARD);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document the document to read
+ * @param offset the offset at which to start reading
+ * @param length the number of characters to read at most
+ * @param direction the reading direction (either
+ * {@link CssCodeReader#BACKWARD} or {@link CssCodeReader#FORWARD})
+ */
+ public CssCodeReader(IDocument document, int offset, int length,
+ int direction) {
+ this(document, offset, length, direction, true, false, false);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document the document to read
+ * @param offset the offset at which to start reading
+ * @param length the number of characters to read at most
+ * @param direction the reading direction (either
+ * {@link CssCodeReader#BACKWARD} or {@link CssCodeReader#FORWARD})
+ * @param skipComments whether the reader should skip comments
+ * @param skipStrings whether the reader should skip strings
+ * @param skipWhitespace whether the reader should skip whitespace
+ */
+ public CssCodeReader(IDocument document, int offset, int length,
+ int direction, boolean skipComments, boolean skipStrings,
+ boolean skipWhitespace) {
+ if ((direction != BACKWARD) && (direction != FORWARD)) {
+ throw new IllegalArgumentException();
+ }
+ if ((offset < 0) || (offset > document.getLength())) {
+ throw new IllegalArgumentException();
+ }
+ this.document = document;
+ this.offset = offset;
+ this.direction = direction;
+ if (direction == FORWARD) {
+ end = Math.min(document.getLength(), offset + length);
+ } else {
+ end = Math.max(0, offset - length);
+ }
+ this.skipComments = skipComments;
+ this.skipStrings = skipStrings;
+ this.skipWhitespace = skipWhitespace;
+ }
+
+ // Reader Implementation ---------------------------------------------------
+
+ /**
+ * @see Reader#close()
+ */
+ public void close() {
+ document = null;
+ }
+
+ /**
+ * @see Reader#read(char[], int, int)
+ */
+ public int read(char[] cbuf, int off, int len) throws IOException {
+ for (int i = off; i < off + len; i++) {
+ int c = read();
+ if (c == -1) {
+ if (i == off) {
+ return -1;
+ } else {
+ return i - off;
+ }
+ }
+ cbuf[i] = (char) c;
+ }
+ return len;
+ }
+
+ /**
+ * @see Reader#read()
+ */
+ public int read() throws IOException {
+ if (document == null) {
+ throw new IllegalStateException();
+ }
+ try {
+ if (direction == FORWARD) {
+ return readForwards();
+ } else {
+ return readBackwards();
+ }
+ } catch (BadLocationException ble) {
+ throw new IOException(ble.getMessage());
+ }
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the document that is being read.
+ *
+ * @return The document
+ */
+ public IDocument getDocument() {
+ return document;
+ }
+
+ /**
+ * Returns the offset of the last read character. Should only be called
+ * after read has been called.
+ *
+ * @return The offset of the last read character
+ */
+ public int getOffset() {
+ return (direction == FORWARD) ? offset - 1 : offset;
+ }
+
+ /**
+ * Returns whether the reader is currently configured to skip comments.
+ *
+ * @return <code>true</code> if the reader is skipping comments and
+ * <code>false</code> otherwise
+ */
+ public boolean isSkippingComments() {
+ return skipComments;
+ }
+
+ /**
+ * Configures the reader to skip comment blocks.
+ *
+ * @param skipComments Whether comments should be skipped
+ */
+ public void setSkipComments(boolean skipComments) {
+ this.skipComments = skipComments;
+ }
+
+ /**
+ * Returns whether the reader is currently configured to skip string
+ * literals.
+ *
+ * @return <code>true</code> if the reader is skipping strings and
+ * <code>false</code> otherwise
+ */
+ public boolean isSkippingStrings() {
+ return skipStrings;
+ }
+
+ /**
+ * Configures the reader to skip strings.
+ *
+ * @param skipStrings Whether strings should be skipped
+ */
+ public void setSkipStrings(boolean skipStrings) {
+ this.skipStrings = skipStrings;
+ }
+
+ /**
+ * Returns whether the reader is currently configured to skip whitespace.
+ *
+ * @return <code>true</code> if the reader is skipping whitespace and
+ * <code>false</code> otherwise
+ */
+ public boolean isSkippingWhitespace() {
+ return skipWhitespace;
+ }
+
+ /**
+ * Configures the reader to skip whitespace.
+ *
+ * @param skipWhitespace Whether whitespace should be skipped
+ */
+ public void setSkipWhitespace(boolean skipWhitespace) {
+ this.skipWhitespace = skipWhitespace;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private int readBackwards() throws BadLocationException {
+ while (offset > 0) {
+ offset--;
+ char current = document.getChar(offset);
+ switch (current) {
+ case '/': {
+ if (skipComments && (offset > 1)) {
+ char next = document.getChar(offset - 1);
+ if (next == '*') {
+ // a comment ends, advance to the comment start
+ offset -= 2;
+ skipUntilStartOfComment();
+ continue;
+ }
+ }
+ break;
+ }
+ case '"':
+ case '\'': {
+ if (skipStrings) {
+ offset--;
+ skipUntilStartOfString(current);
+ continue;
+ }
+ break;
+ }
+ default: {
+ if (skipWhitespace && Character.isWhitespace(current)) {
+ continue;
+ }
+ }
+ }
+ return current;
+ }
+ return -1;
+ }
+
+ private int readForwards() throws BadLocationException {
+ while (offset < end) {
+ char current = document.getChar(offset++);
+ switch (current) {
+ case '/': {
+ if (skipComments && (offset < end)) {
+ char next = document.getChar(offset);
+ if (next == '*') {
+ // a comment starts, advance to the comment end
+ offset++;
+ skipUntilEndOfComment();
+ continue;
+ }
+ }
+ break;
+ }
+ case '"':
+ case '\'': {
+ if (skipStrings) {
+ skipUntilEndOfString(current);
+ continue;
+ }
+ break;
+ }
+ default: {
+ if (skipWhitespace && Character.isWhitespace(current)) {
+ offset++;
+ continue;
+ }
+ }
+ }
+ return current;
+ }
+ return -1;
+ }
+
+ private void skipUntilStartOfComment() throws BadLocationException {
+ while (offset > 0) {
+ char current = document.getChar(offset--);
+ if ((current == '*') && (0 <= offset)
+ && (document.getChar(offset) == '/')) {
+ return;
+ }
+ }
+ }
+
+ private void skipUntilEndOfComment() throws BadLocationException {
+ while (offset < end) {
+ char current = document.getChar(offset++);
+ if (current == '*') {
+ if ((offset < end)
+ && (document.getChar(offset) == '/')) {
+ offset++;
+ return;
+ }
+ }
+ }
+ }
+
+ private void skipUntilStartOfString(char delimiter)
+ throws BadLocationException {
+ while (offset > 0) {
+ char current = document.getChar(offset);
+ if (current == delimiter) {
+ if (!((0 <= offset) && document.getChar(offset - 1) == '\\')) {
+ return;
+ }
+ }
+ offset--;
+ }
+ }
+
+ private void skipUntilEndOfString(char delimiter)
+ throws BadLocationException {
+ while (offset < end) {
+ char current = document.getChar(offset++);
+ if (current == '\\') {
+ // ignore escaped characters
+ offset++;
+ } else if (current == delimiter) {
+ return;
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssTextUtils.java,v 1.1 2004-09-02 18:07:13 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.internal.text;
+
+import java.io.IOException;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Various utility methods for handling CSS source.
+ *
+ * TODO Probably refactor so this class isn't needed
+ */
+public final class CssTextUtils {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden.
+ */
+ private CssTextUtils() {
+ // Hidden
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public static int findMatchingClosingPeer(IDocument document, int offset,
+ char openingPeer) {
+ try {
+ CssCodeReader reader = new CssCodeReader(document, offset,
+ document.getLength(), CssCodeReader.FORWARD);
+ char closingChar = getPeerCharacter(openingPeer);
+ int stack = 1;
+ int c = reader.read();
+ while (c != -1) {
+ if ((c == openingPeer) && (c != closingChar)) {
+ stack++;
+ } else if (c == closingChar) {
+ stack--;
+ }
+ if (stack == 0) {
+ return reader.getOffset();
+ }
+ c = reader.read();
+ }
+ } catch (IOException e) {
+ CssCore.log(
+ "Failed to find matching closing peer for '" + //$NON-NLS-1$
+ openingPeer + '\'', e);
+ }
+ return -1;
+ }
+
+ public static int findMatchingOpeningPeer(IDocument document, int offset,
+ char closingPeer) {
+ try {
+ CssCodeReader reader = new CssCodeReader(document, offset + 1,
+ document.getLength(), CssCodeReader.BACKWARD);
+ char openingChar = getPeerCharacter(closingPeer);
+ int stack = 1;
+ int c = reader.read();
+ while (c != -1) {
+ if ((c == closingPeer) && (c != openingChar)) {
+ stack++;
+ } else if (c == openingChar) {
+ stack--;
+ }
+ if (stack == 0) {
+ return reader.getOffset();
+ }
+ c = reader.read();
+ }
+ } catch (IOException e) {
+ CssCore.log(
+ "Failed to find matching opening peer for '" + //$NON-NLS-1$
+ closingPeer + '\'', e);
+ }
+ return -1;
+ }
+
+ public static char getPeerCharacter(char c) {
+ switch (c) {
+ case '{': return '}';
+ case '}': return '{';
+ case '[': return ']';
+ case ']': return '[';
+ case '(': return ')';
+ case ')': return '(';
+ case '"': return '"';
+ case '\'': return '\'';
+ default: return 0;
+ }
+ }
+
+ public static boolean isCssIdentifierPart(char c) {
+ return ((c == '_') || Character.isLetterOrDigit(c) || (c == '-'));
+ }
+
+ public static boolean isCssIdentifierStart(char c) {
+ return ((c == '_') || Character.isLetter(c));
+ }
+
+ public static boolean isCssNumberPart(char c) {
+ return ((c == '.') || Character.isDigit(c));
+ }
+
+ public static boolean isCssNumberStart(char c) {
+ return ((c == '-') || (c == '.') || Character.isDigit(c));
+ }
+
+ public static boolean isCssWhitespace(char c) {
+ return Character.isWhitespace(c);
+ }
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IAtRule.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+
+/**
+ *
+ */
+public interface IAtRule extends IRule {
+
+ ISourceReference getName();
+
+ // TODO Maybe choose a more descriptive term for this property?
+ ISourceReference getValue();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IDeclaration.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+
+/**
+ * Represents a single CSS declaration.
+ */
+public interface IDeclaration extends ISourceReference {
+
+ /**
+ * Returns the rule that contains this declaration.
+ *
+ * @return the rule containing this declaration, or <code>null</code> if the
+ * declaration doesn't belong to a specific rule
+ */
+ IRule getRule();
+
+ /**
+ * Returns the source reference representing the property.
+ *
+ * @return the property
+ */
+ ISourceReference getProperty();
+
+ /**
+ * Returns the source reference consisting of the value assigned to the
+ * property.
+ *
+ * @return the value
+ */
+ ISourceReference getValue();
+
+ /**
+ * Returns the source reference representing the priority (mostly, that will
+ * be "<code>!important</code>") of the declaration, or <code>null</code>
+ * if no special priority was specified.
+ *
+ * @return the priority
+ */
+ ISourceReference getPriority();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IPropertyInfo.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+/**
+ * Encapsulates information about a specific property.
+ */
+public interface IPropertyInfo {
+
+ String getName();
+
+ String getCategory();
+
+ String getDescription();
+
+ boolean isShorthand();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IRule.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ *
+ */
+public interface IRule extends IAdaptable, ISourceReference {
+
+ /**
+ * Returns the style sheet that contains this rule.
+ *
+ * @return the style sheet
+ */
+ IStyleSheet getStyleSheet();
+
+ /**
+ * Returns the rule in which this rule is nested, or <code>null</code> if
+ * this rule is at the top level of the style sheet.
+ *
+ * @return the parent rule
+ */
+ IRule getParent();
+
+ IRule[] getChildren();
+
+ /**
+ * Returns the declaration at the specified offset into the rule.
+ *
+ * @param offset the offset
+ * @return the declaration at the offset, or <code>null</code> if no
+ * declaration is found at that position
+ */
+ IDeclaration getDeclarationAt(int offset);
+
+ IDeclaration[] getDeclarations();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IStyleRule.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+
+/**
+ *
+ */
+public interface IStyleRule extends IRule {
+
+ ISourceReference getSelector();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IStyleSheet.java,v 1.1 2004-09-02 18:07:11 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.model;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+
+import org.eclipse.core.runtime.IAdaptable;
+
+/**
+ *
+ */
+public interface IStyleSheet
+ extends IAdaptable, ISourceReference {
+
+ /**
+ * Returns the rule at the specified offset into the document.
+ *
+ * @param offset the offset
+ * @return the rule at the offset, or <code>null</code> if no rule is found
+ * at that position
+ */
+ IRule getRuleAt(int offset);
+
+ /**
+ * Returns the list of rules in the order they have been defined in the
+ * style sheet.
+ *
+ * @return the list of rules contained by the style sheet
+ */
+ IRule[] getRules();
+
+ void reconcile(IProblemCollector problemCollector)
+ throws LexicalErrorException, SyntaxErrorException;
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: ICssParser.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Interface for classes that implement the parsing of CSS source code into a
+ * syntax tree.
+ *
+ * TODO Add a way to only parse a specific range of an IDocument
+ */
+public interface ICssParser extends IProblemReporter {
+
+ /**
+ * Parses the given document as a CSS style sheet. If a problem collector
+ * is provided, lexical and syntax errors are reported to it rather than
+ * throwing exceptions.
+ *
+ * @return a list containing the parsed style rules
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * lexical scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ IRule[] parseRules(IStyleSheet styleSheet)
+ throws LexicalErrorException, SyntaxErrorException;
+
+ /**
+ * Parses the source at the current position to extract a single rule.
+ *
+ * @param parentRule the parent of the rule to parse, or <code>null</code>
+ * if there is no parent
+ * @return the parsed rule
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * lexical scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ IRule parseRule(IStyleSheet styleSheet, IRule parentRule)
+ throws LexicalErrorException, SyntaxErrorException;
+
+ /**
+ * Parses the source at the current position to extract a selector.
+ *
+ * @return the parsed selector
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * lexical scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ ISourceReference parseSelector(IRule rule)
+ throws LexicalErrorException, SyntaxErrorException;
+
+ /**
+ * Parses the source at the current position to extract a single
+ * declaration.
+ *
+ * @return the parsed declaration
+ * @throws LexicalErrorException if a lexical error is reported by the
+ * lexical scanner
+ * @throws SyntaxErrorException if a syntax error has been encountered from
+ * which recovery is not possible
+ */
+ IDeclaration parseDeclaration(IRule rule)
+ throws LexicalErrorException, SyntaxErrorException;
+
+ /**
+ * Sets the document containing the style sheet source to process.
+ *
+ * @param document the document containing the source
+ */
+ void setSource(IDocument document);
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: ICssScanner.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+
+/**
+ * Interface for classes that implement the lexical scanning of CSS source code.
+ *
+ * TODO Add a way to only parse a specific range of an IDocument
+ */
+public interface ICssScanner extends IProblemReporter {
+
+ // Methods -----------------------------------------------------------------
+
+ /**
+ * Returns the starting position of the current token inside the original
+ * source. This position is zero-based and inclusive. It corresponds to the
+ * position of the first character which is part of this token.
+ *
+ * @return the starting position of the current token inside the original
+ * source
+ */
+ IRegion getTokenRegion();
+
+ /**
+ * Read the next token in the source, and returns the value corresponding
+ * to the symbolic constant corresponding to the token type (as defined by
+ * the constants in this interface), or with read character itself.
+ *
+ * @return the next token
+ * @throws LexicalErrorException in case a lexical error was detected while
+ * trying to retrieve the current token
+ */
+ int getNextToken() throws LexicalErrorException;
+
+ /**
+ * Sets the document that contains the source style sheet.
+ *
+ * TODO Add parameters for range limitation
+ *
+ * @param source The document containing the style sheet source
+ */
+ void setSource(IDocument source);
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: ICssTokens.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+/**
+ * Symbolic constants for tokens generated by the CSS scanner.
+ */
+public interface ICssTokens {
+
+ // Constants ---------------------------------------------------------------
+
+ int EOF = -1;
+
+ int CDO = 1;
+ int CDC = 2;
+
+ int IDENT = 'i';
+ int NUM = 'n';
+ int STRING = 's';
+
+ int AT = '@';
+ int COLON = ':';
+ int LBRACE = '{';
+ int LBRACKET = '[';
+ int LPAREN = '(';
+ int RBRACE = '}';
+ int RBRACKET = ']';
+ int RPAREN = ')';
+ int SEMICOLON = ';';
+ int EXCLAMATION = '!';
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProblem.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+/**
+ *
+ */
+public interface IProblem {
+
+ /**
+ * Returns the problem identifier.
+ *
+ * @return the problem id
+ */
+ String getId();
+
+ /**
+ * Returns a localized, human-readable message string which describes the
+ * problem.
+ *
+ * @return the problem message
+ */
+ String getMessage();
+
+ /**
+ * Returns the file name in which the problem was found.
+ *
+ * @return the file name in which the problem was found
+ */
+ String getOriginatingFileName();
+
+ /**
+ * 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 the start position of the problem (inclusive).
+ *
+ * @return the start position of the problem, or -1 if unknown
+ */
+ int getSourceStart();
+
+ /**
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProblemCollector.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+/**
+ *
+ */
+public interface IProblemCollector {
+
+ /**
+ * Notification of an error or warning.
+ *
+ * @param problem the discovered problem
+ */
+ void addProblem(IProblem problem);
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProblemReporter.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.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);
+
+}
--- /dev/null
+/*
+ * 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: LexicalErrorException.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+/**
+ *
+ */
+public class LexicalErrorException extends Exception {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public LexicalErrorException() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param s the exception message
+ */
+ public LexicalErrorException(String s) {
+ super(s);
+ }
+
+}
--- /dev/null
+/*
+ * 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: SyntaxErrorException.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.parser;
+
+/**
+ *
+ */
+public class SyntaxErrorException extends Exception {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The line number at which the error was detected in the source.
+ */
+ private int lineNumber;
+
+ /**
+ * The offset into the document.
+ */
+ private int offset;
+
+ /**
+ * The length of the source range affected by the syntax error.
+ */
+ private int length;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public SyntaxErrorException() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message the exception message
+ */
+ public SyntaxErrorException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message the exception message
+ * @param lineNumber the line number
+ * @param offset the offset
+ * @param length the length
+ */
+ public SyntaxErrorException(String message, int lineNumber, int offset,
+ int length) {
+ super(message + " (" + lineNumber + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ this.lineNumber = lineNumber;
+ this.offset = offset;
+ this.length = length;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the length of the offending code
+ *
+ * @return the length of the offending code
+ */
+ public final int getLength() {
+ return this.length;
+ }
+
+ /**
+ * Returns the line number at which the error was detected.
+ *
+ * @return the line number
+ */
+ public final int getLineNumber() {
+ return this.lineNumber;
+ }
+
+ /**
+ * Returns the offset of the offending code
+ *
+ * @return the offset of the offending code
+ */
+ public final int getOffset() {
+ return this.offset;
+ }
+
+}
--- /dev/null
+/*
+ * 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: AbstractProfile.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.phpeclipse.css.core.internal.model.PropertyInfo;
+import net.sourceforge.phpeclipse.css.core.model.IPropertyInfo;
+
+/**
+ * Abstract implementation of the <code>IProfile</code> interface.
+ */
+public abstract class AbstractProfile implements IProfile {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated descriptor, as passed into the constructor by the profile
+ * manager when the profile is instantiated.
+ */
+ private IProfileDescriptor descriptor;
+
+ /**
+ * Map of the property names of this profile, containing the
+ * <code>IPropertyInfo</code> objects keyed by property name.
+ */
+ private Map properties = new HashMap();
+
+ /**
+ * Set of the at rule keywords known to the profile.
+ */
+ private Set atKeywords = new HashSet();
+
+ /**
+ * Set of the at pseudo-classes known to the profile.
+ */
+ private Set pseudoClasses = new HashSet();
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param descriptor the profile descriptor
+ */
+ public AbstractProfile(IProfileDescriptor descriptor) {
+ this.descriptor = descriptor;
+ }
+
+ // IProfile Implementation -------------------------------------------------
+
+ /**
+ * @see net.sourceforge.phpeclipse.css.core.profiles.IProfile#getDescriptor()
+ */
+ public final IProfileDescriptor getDescriptor() {
+ return this.descriptor;
+ }
+
+ /**
+ * @see IProfile#getAtKeywords()
+ */
+ public final Collection getAtKeywords() {
+ return Collections.unmodifiableSet(this.atKeywords);
+ }
+
+ /**
+ * @see IProfile#getProperties()
+ */
+ public final Collection getProperties() {
+ return Collections.unmodifiableSet(this.properties.keySet());
+ }
+
+ /**
+ * @see IProfile#getPropertyInfo(java.lang.String)
+ */
+ public final IPropertyInfo getPropertyInfo(String propertyName) {
+ return (IPropertyInfo) this.properties.get(propertyName);
+ }
+
+ /**
+ * @see IProfile#getPseudoClassNames()
+ */
+ public final Collection getPseudoClassNames() {
+ return Collections.unmodifiableSet(this.pseudoClasses);
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ protected final void addAtKeyword(String atKeyword) {
+ this.atKeywords.add(atKeyword);
+ }
+
+ protected final void addProperty(String name, String category) {
+ addProperty(new PropertyInfo(name, category));
+ }
+
+ protected final void addProperty(String name, String category,
+ boolean shorthand) {
+ addProperty(new PropertyInfo(name, category, shorthand));
+ }
+
+ protected final void addProperty(IPropertyInfo info) {
+ this.properties.put(info.getName(), info);
+ }
+
+ protected final void addPseudoClass(String pseudoClass) {
+ this.pseudoClasses.add(pseudoClass);
+ }
+
+}
--- /dev/null
+/*
+ * 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: Css1Profile.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+import net.sourceforge.phpeclipse.css.core.internal.CssCoreMessages;
+
+/**
+ * Implementation of the CSS Level 1 profile
+ * (<a href="http://www.w3.org/TR/CSS1">http://www.w3.org/TR/CSS1</a>).
+ */
+public class Css1Profile extends AbstractProfile {
+
+ // Constants ---------------------------------------------------------------
+
+ protected static final String CATEGORY_BOX =
+ CssCoreMessages.getString("CssProfile.category.box"); //$NON-NLS-1$
+ protected static final String CATEGORY_COLOR_BACKGROUND =
+ CssCoreMessages.getString(
+ "CssProfile.category.colorAndBackground"); //$NON-NLS-1$
+ protected static final String CATEGORY_FONT =
+ CssCoreMessages.getString("CssProfile.category.font"); //$NON-NLS-1$
+ protected static final String CATEGORY_TEXT =
+ CssCoreMessages.getString("CssProfile.category.text"); //$NON-NLS-1$
+ protected static final String CATEGORY_VISUAL_FORMATTING =
+ CssCoreMessages.getString(
+ "CssProfile.category.visualFormatting"); //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ public Css1Profile(IProfileDescriptor descriptor) {
+ super(descriptor);
+ initializeAtKeywords();
+ initializeProperties();
+ initializePseudoClasses();
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private void initializeAtKeywords() {
+ addAtKeyword("import"); //$NON-NLS-1$
+ }
+
+ private void initializeProperties() {
+ addProperty("font", CATEGORY_FONT, true); //$NON-NLS-1$
+ addProperty("font-family", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("font-size", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("font-style", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("font-variant", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("font-weight", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("background", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND, true);
+ addProperty("background-attachment", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND);
+ addProperty("background-color", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND);
+ addProperty("background-image", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND);
+ addProperty("background-position", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND);
+ addProperty("background-repeat", //$NON-NLS-1$
+ CATEGORY_COLOR_BACKGROUND);
+ addProperty("color", CATEGORY_COLOR_BACKGROUND); //$NON-NLS-1$
+ addProperty("border", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("border-bottom", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("border-bottom-width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-color", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-left", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("border-left-width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-right", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("border-right-width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-style", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-top", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("border-top-width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("clear", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("float", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("height", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("margin", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("margin-bottom", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("margin-left", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("margin-right", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("margin-top", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("padding", CATEGORY_BOX, true); //$NON-NLS-1$
+ addProperty("padding-bottom", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("padding-left", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("padding-right", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("padding-top", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("width", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("letter-spacing", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("line-height", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("text-align", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("text-decoration", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("text-indent", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("text-transform", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("vertical-align", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("white-space", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("word-spacing", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("display", //$NON-NLS-1$
+ CATEGORY_VISUAL_FORMATTING);
+ addProperty("list-style", //$NON-NLS-1$
+ CATEGORY_VISUAL_FORMATTING, true);
+ addProperty("list-style-image", //$NON-NLS-1$
+ CATEGORY_VISUAL_FORMATTING);
+ addProperty("list-style-position", //$NON-NLS-1$
+ CATEGORY_VISUAL_FORMATTING);
+ addProperty("list-style-type", //$NON-NLS-1$
+ CATEGORY_VISUAL_FORMATTING);
+ }
+
+ private void initializePseudoClasses() {
+ addPseudoClass("active"); //$NON-NLS-1$
+ addPseudoClass("first-letter"); //$NON-NLS-1$
+ addPseudoClass("first-line"); //$NON-NLS-1$
+ addPseudoClass("link"); //$NON-NLS-1$
+ addPseudoClass("visited"); //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*
+ * 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: Css2Profile.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+import net.sourceforge.phpeclipse.css.core.internal.CssCoreMessages;
+
+/**
+ * Implementation of the CSS Level 2 profile
+ * (<a href="http://www.w3.org/TR/CSS2">http://www.w3.org/TR/CSS2</a>).
+ */
+public class Css2Profile extends Css1Profile {
+
+ // Constants ---------------------------------------------------------------
+
+ protected static final String CATEGORY_AURAL =
+ CssCoreMessages.getString("CssProfile.category.aural"); //$NON-NLS-1$
+ protected static final String CATEGORY_GENERATED_CONTENT =
+ CssCoreMessages.getString(
+ "CssProfile.category.generatedContent"); //$NON-NLS-1$
+ protected static final String CATEGORY_PAGED_MEDIA =
+ CssCoreMessages.getString(
+ "CssProfile.category.pagedMedia"); //$NON-NLS-1$
+ protected static final String CATEGORY_TABLE =
+ CssCoreMessages.getString("CssProfile.category.table"); //$NON-NLS-1$
+ protected static final String CATEGORY_USER_INTERFACE =
+ CssCoreMessages.getString(
+ "CssProfile.category.userInterface"); //$NON-NLS-1$
+ protected static final String CATEGORY_VISUAL_EFFECTS =
+ CssCoreMessages.getString(
+ "CssProfile.category.visualEffects"); //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ public Css2Profile(IProfileDescriptor descriptor) {
+ super(descriptor);
+ initializeAtKeywords();
+ initializeProperties();
+ initializePseudoClasses();
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private void initializeAtKeywords() {
+ addAtKeyword("charset"); //$NON-NLS-1$
+ addAtKeyword("font-face"); //$NON-NLS-1$
+ addAtKeyword("media"); //$NON-NLS-1$
+ addAtKeyword("page"); //$NON-NLS-1$
+ }
+
+ private void initializeProperties() {
+ addProperty("font-stretch", CATEGORY_FONT); //$NON-NLS-1$
+ addProperty("unicode-bidi", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("direction", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("border-bottom-color", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-bottom-style", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-collapse", CATEGORY_TABLE); //$NON-NLS-1$
+ addProperty("border-left-color", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-left-style", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-right-color", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-right-style", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-top-color", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-top-style", CATEGORY_BOX); //$NON-NLS-1$
+ addProperty("border-spacing", CATEGORY_TABLE); //$NON-NLS-1$
+ addProperty("caption-side", CATEGORY_TABLE); //$NON-NLS-1$
+ addProperty("empty-cells", CATEGORY_TABLE); //$NON-NLS-1$
+ addProperty("table-layout", CATEGORY_TABLE); //$NON-NLS-1$
+ addProperty("bottom", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("clip", CATEGORY_VISUAL_EFFECTS); //$NON-NLS-1$
+ addProperty("content", CATEGORY_GENERATED_CONTENT); //$NON-NLS-1$
+ addProperty("counter-increment", //$NON-NLS-1$
+ CATEGORY_GENERATED_CONTENT);
+ addProperty("counter-reset", CATEGORY_GENERATED_CONTENT); //$NON-NLS-1$
+ addProperty("azimuth", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("cue", CATEGORY_AURAL, true); //$NON-NLS-1$
+ addProperty("cue-after", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("cue-before", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("cursor", CATEGORY_USER_INTERFACE); //$NON-NLS-1$
+ addProperty("elevation", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("left", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("max-height", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("max-width", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("min-height", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("min-width", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("orphans", CATEGORY_PAGED_MEDIA); //$NON-NLS-1$
+ addProperty("outline", CATEGORY_USER_INTERFACE); //$NON-NLS-1$
+ addProperty("outline-color", CATEGORY_USER_INTERFACE); //$NON-NLS-1$
+ addProperty("outline-style", CATEGORY_USER_INTERFACE); //$NON-NLS-1$
+ addProperty("outline-width", CATEGORY_USER_INTERFACE); //$NON-NLS-1$
+ addProperty("overflow", CATEGORY_VISUAL_EFFECTS); //$NON-NLS-1$
+ addProperty("page-break-after", CATEGORY_PAGED_MEDIA); //$NON-NLS-1$
+ addProperty("page-break-before", CATEGORY_PAGED_MEDIA); //$NON-NLS-1$
+ addProperty("page-break-inside", CATEGORY_PAGED_MEDIA); //$NON-NLS-1$
+ addProperty("pause", CATEGORY_AURAL, true); //$NON-NLS-1$
+ addProperty("pause-after", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("pause-before", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("pitch", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("pitch-range", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("play-during", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("position", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("quotes", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("richness", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("right", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("speak", CATEGORY_AURAL, true); //$NON-NLS-1$
+ addProperty("speak-header", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("speak-numeral", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("speak-punctuation", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("speech-rate", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("text-shadow", CATEGORY_TEXT); //$NON-NLS-1$
+ addProperty("stress", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("top", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ addProperty("visibility", CATEGORY_VISUAL_EFFECTS); //$NON-NLS-1$
+ addProperty("voice-family", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("volume", CATEGORY_AURAL); //$NON-NLS-1$
+ addProperty("widows", CATEGORY_PAGED_MEDIA); //$NON-NLS-1$
+ addProperty("z-index", CATEGORY_VISUAL_FORMATTING); //$NON-NLS-1$
+ }
+
+ private void initializePseudoClasses() {
+ addPseudoClass("after"); //$NON-NLS-1$
+ addPseudoClass("before"); //$NON-NLS-1$
+ addPseudoClass("first-child"); //$NON-NLS-1$
+ addPseudoClass("focus"); //$NON-NLS-1$
+ addPseudoClass("hover"); //$NON-NLS-1$
+ addPseudoClass("land"); //$NON-NLS-1$
+ addPseudoClass("left"); //$NON-NLS-1$
+ addPseudoClass("right"); //$NON-NLS-1$
+ }
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProfile.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+import java.util.Collection;
+
+import net.sourceforge.phpeclipse.css.core.model.IPropertyInfo;
+
+/**
+ * Interface for extensions that provide information about specific CSS
+ * profiles.
+ *
+ * <b>Note that this interface is very likely to change or even disappear.</b>
+ */
+public interface IProfile {
+
+ IProfileDescriptor getDescriptor();
+
+ Collection getAtKeywords();
+
+ Collection getProperties();
+
+ IPropertyInfo getPropertyInfo(String propertyName);
+
+ Collection getPseudoClassNames();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProfileDescriptor.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+
+/**
+ *
+ */
+public interface IProfileDescriptor {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Symbolic constant for the profiles extension point ID.
+ */
+ String EXTENSION_POINT_ID =
+ "net.sourceforge.phpeclipse.css.core.profiles"; //$NON-NLS-1$
+
+ // Methods -----------------------------------------------------------------
+
+ /**
+ * @return The ID of the extension
+ */
+ String getId();
+
+ /**
+ * @return The display name of the profile
+ */
+ String getName();
+
+ /**
+ * @return A description of the profile
+ */
+ String getDescription();
+
+ /**
+ * @return The name of the class implementing the profile
+ */
+ String getClassName();
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: IProfileManager.java,v 1.1 2004-09-02 18:07:14 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.core.profiles;
+
+import org.eclipse.core.resources.IResource;
+
+/**
+ * Manages the CSS profiles.
+ */
+public interface IProfileManager {
+
+ /**
+ * Returns the list of available profiles.
+ *
+ * @return an array containing the descriptors of all available profiles
+ */
+ IProfileDescriptor[] getProfileDescriptors();
+
+ /**
+ * Returns the profile that is selected for the specified resource or
+ * project.
+ *
+ * @param resource the resource for which the profile should be retrieved,
+ * or <code>null</code> to retrieve the default profile as specified
+ * in the plugin preferences
+ * @return the profile
+ */
+ IProfile getProfile(IResource resource);
+
+ /**
+ * Sets the profile that should be used for the specified resource. If the
+ * resource is an <code>IProject</code>, the profile will be used as the
+ * default profile for all resources in the project. Otherwise, it will be
+ * used only for the resource. If the resource is <code>null</code>, the
+ * profile will be selected as the global default profile.
+ *
+ * @param resource
+ * @param profileId The ID of the profile
+ */
+ void setProfile(IResource resource, String profileId);
+
+}
--- /dev/null
+<?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>
--- /dev/null
+bin
+build
+dist
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>net.sourceforge.phpeclipse.css.ui</name>
+ <comment></comment>
+ <projects>
+ <project>net.sf.wdte.core</project>
+ <project>net.sf.wdte.css.core</project>
+ <project>net.sf.wdte.ui</project>
+ <project>org.eclipse.compare</project>
+ <project>org.eclipse.core.resources</project>
+ <project>org.eclipse.core.runtime.compatibility</project>
+ <project>org.eclipse.help</project>
+ <project>org.eclipse.jface.text</project>
+ <project>org.eclipse.osgi</project>
+ <project>org.eclipse.ui</project>
+ <project>org.eclipse.ui.editors</project>
+ <project>org.eclipse.ui.ide</project>
+ <project>org.eclipse.ui.views</project>
+ <project>org.eclipse.ui.workbench.texteditor</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.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+bin.includes = plugin.xml,\
+ plugin*.properties,\
+ cssui.jar,\
+ icons/,\
+ plugin.properties
+src.includes = schema/,\
+ .classpath,\
+ .project,\
+ build.properties,\
+ plugin.properties,\
+ plugin.xml,\
+ icons/,\
+ src/
+source.cssui.jar = src
+bin.excludes = icons/.cvsignore
--- /dev/null
+#
+# 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 english resources
+#
+# $Id: plugin.properties,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+#
+
+pluginName = Web Development Tools CSS UI
+providerName= WDTE Project
+
+editorName = CSS Editor
+
+editorFontDefinition.label = CSS Editor Text Font
+editorFontDefinition.description = \
+ The CSS editor text font is used by CSS editors.
+compareFontDefinition.label = CSS Compare Text Font
+compareFontDefinition.description = \
+ The CSS compare text font is used by CSS compare/merge editors.
+
+preferencePage.name = CSS
+editorPreferencePage.name = Editor
+
+propertyPage.name = CSS
+
+authoringActions.label = CSS Authoring
+sourceCategory.label = Source
+sourceCategory.description = CSS Source Actions
+sourceMenu.label = &Source
+commentAction.label = Co&mment
+uncommentAction.label = &Uncomment
+shiftLeftAction.label = S&hift Left
+shiftRightAction.label = Sh&ift Right
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="net.sourceforge.phpeclipse.css.ui"
+ name="%pluginName"
+ version="0.0.1"
+ provider-name="%providerName"
+ class="net.sourceforge.phpeclipse.css.ui.CssUI">
+
+ <runtime>
+ <library name="cssui.jar"/>
+ </runtime>
+ <requires>
+ <import plugin="net.sourceforge.phpeclipse.core"/>
+ <import plugin="net.sourceforge.phpeclipse.css.core"/>
+ <import plugin="net.sourceforge.phpeclipse.ui"/>
+ <import plugin="org.eclipse.compare"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.core.filebuffers"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.help"/>
+ <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.core.runtime.adapters">
+ <factory
+ class="net.sourceforge.phpeclipse.css.ui.internal.properties.CssPropertiesAdapterFactory"
+ adaptableType="net.sourceforge.phpeclipse.css.core.model.IRule">
+ <adapter type="org.eclipse.ui.views.properties.IPropertySource"/>
+ </factory>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="%editorName"
+ icon="icons/style_sheet_obj.gif"
+ extensions="css"
+ contributorClass="net.sourceforge.phpeclipse.css.ui.internal.editor.CssEditorActionContributor"
+ class="net.sourceforge.phpeclipse.css.ui.internal.editor.CssEditor"
+ id="net.sourceforge.phpeclipse.css.ui.editor">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.core.filebuffers.documentSetup">
+ <participant
+ extensions="css"
+ class="net.sourceforge.phpeclipse.css.ui.internal.CssDocumentSetupParticipant">
+ </participant>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors.documentProviders">
+ <provider
+ extensions="css"
+ class="net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider"
+ id="net.sourceforge.phpeclipse.css.ui.documentProvider">
+ </provider>
+ </extension>
+ <extension
+ point="org.eclipse.ui.fontDefinitions">
+ <fontDefinition
+ label="%editorFontDefinition.label"
+ defaultsTo="org.eclipse.jface.textfont"
+ id="net.sourceforge.phpeclipse.css.ui.editorfont">
+ <description>
+ %editorFontDefinition.description
+ </description>
+ </fontDefinition>
+ <fontDefinition
+ label="%compareFontDefinition.label"
+ defaultsTo="org.eclipse.compare.contentmergeviewer.TextMergeViewer"
+ id="net.sourceforge.phpeclipse.css.ui.internal.compare.CssMergeViewer">
+ <description>
+ %compareFontDefinition.description
+ </description>
+ </fontDefinition>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ name="%preferencePage.name"
+ category="net.sourceforge.phpeclipse.ui.preferencePage"
+ class="net.sourceforge.phpeclipse.css.ui.internal.preferences.CssPreferencePage"
+ id="net.sourceforge.phpeclipse.css.ui.preferencePage">
+ </page>
+ <page
+ name="%editorPreferencePage.name"
+ category="net.sourceforge.phpeclipse.css.ui.preferencePage"
+ class="net.sourceforge.phpeclipse.css.ui.internal.preferences.CssEditorPreferencePage"
+ id="net.sourceforge.phpeclipse.css.ui.editor.preferencePage">
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.ui.propertyPages">
+<!-- TODO: Only enable the following property page for projects with a
+ future "Web" nature -->
+ <page
+ objectClass="org.eclipse.core.resources.IProject"
+ name="%propertyPage.name"
+ class="net.sourceforge.phpeclipse.css.ui.internal.properties.CssPropertyPage"
+ id="net.sourceforge.phpeclipse.css.ui.propertyPage">
+ </page>
+ <page
+ objectClass="org.eclipse.core.resources.IResource"
+ name="%propertyPage.name"
+ nameFilter="*.css"
+ class="net.sourceforge.phpeclipse.css.ui.internal.properties.CssPropertyPage"
+ id="net.sourceforge.phpeclipse.css.ui.propertyPage">
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <category
+ name="%sourceCategory.label"
+ description="%sourceMenu.description"
+ id="net.sourceforge.phpeclipse.css.ui.sourceCategory">
+ </category>
+ <command
+ name="%commentAction.label"
+ description="%commentAction.description"
+ category="org.eclipse.jdt.ui.category.source"
+ id="net.sourceforge.phpeclipse.css.ui.commentAction">
+ </command>
+ <keyBinding
+ string="Ctrl+/"
+ command="net.sourceforge.phpeclipse.css.ui.commentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ <keyBinding
+ platform="carbon"
+ string="Ctrl+/"
+ command="net.sourceforge.phpeclipse.css.ui.commentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ <keyBinding
+ platform="carbon"
+ string="Command+/"
+ command="net.sourceforge.phpeclipse.css.ui.commentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ <command
+ name="%uncommentAction.label"
+ description="%uncommentAction.description"
+ category="org.eclipse.jdt.ui.category.source"
+ id="net.sourceforge.phpeclipse.css.ui.uncommentAction">
+ </command>
+ <keyBinding
+ string="Ctrl+\"
+ command="net.sourceforge.phpeclipse.css.ui.uncommentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ <keyBinding
+ platform="carbon"
+ string="Ctrl+\"
+ command="net.sourceforge.phpeclipse.css.ui.uncommentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ <keyBinding
+ platform="carbon"
+ string="Command+\"
+ command="net.sourceforge.phpeclipse.css.ui.uncommentAction"
+ configuration="org.eclipse.ui.defaultAcceleratorConfiguration">
+ </keyBinding>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ label="%authoringActions.label"
+ id="net.sourceforge.phpeclipse.css.ui.authoringActions">
+ <menu
+ label="%sourceMenu.label"
+ path="edit"
+ id="net.sourceforge.phpeclipse.css.ui.sourceMenu">
+ <separator
+ name="editGroup">
+ </separator>
+ </menu>
+ <action
+ label="%shiftLeftAction.label"
+ retarget="true"
+ menubarPath="net.sourceforge.phpeclipse.css.ui.sourceMenu/editGroup"
+ id="org.eclipse.ui.edit.text.shiftLeft">
+ </action>
+ <action
+ label="%shiftRightAction.label"
+ retarget="true"
+ menubarPath="net.sourceforge.phpeclipse.css.ui.sourceMenu/editGroup"
+ id="org.eclipse.ui.edit.text.shiftRight">
+ </action>
+ <action
+ definitionId="net.sourceforge.phpeclipse.css.ui.uncommentAction"
+ label="%uncommentAction.label"
+ retarget="true"
+ menubarPath="net.sourceforge.phpeclipse.css.ui.sourceMenu/editGroup"
+ id="net.sourceforge.phpeclipse.css.ui.uncommentAction">
+ </action>
+ <action
+ definitionId="net.sourceforge.phpeclipse.css.ui.commentAction"
+ label="%commentAction.label"
+ retarget="true"
+ menubarPath="net.sourceforge.phpeclipse.css.ui.sourceMenu/editGroup"
+ id="net.sourceforge.phpeclipse.css.ui.commentAction">
+ </action>
+ </actionSet>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSetPartAssociations">
+ <actionSetPartAssociation
+ targetID="net.sourceforge.phpeclipse.css.ui.authoringActions">
+ <part
+ id="net.sourceforge.phpeclipse.css.ui.editor">
+ </part>
+ </actionSetPartAssociation>
+ <actionSetPartAssociation
+ targetID="org.eclipse.ui.edit.text.actionSet.presentation">
+ <part
+ id="net.sourceforge.phpeclipse.css.ui.editor">
+ </part>
+ </actionSetPartAssociation>
+ </extension>
+ <extension
+ point="org.eclipse.compare.contentMergeViewers">
+ <viewer
+ extensions="css"
+ class="net.sourceforge.phpeclipse.css.ui.internal.compare.CssMergeViewerCreator"
+ id="net.sourceforge.phpeclipse.css.ui.compare.contentMergeViewer">
+ </viewer>
+ </extension>
+ <extension
+ point="org.eclipse.compare.structureCreators">
+ <structureCreator
+ extensions="css"
+ class="net.sourceforge.phpeclipse.css.ui.internal.compare.CssStructureCreator"
+ id="net.sourceforge.phpeclipse.css.ui.compare.structureCreator">
+ </structureCreator>
+ </extension>
+
+</plugin>
--- /dev/null
+/*
+ * 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: CssUI.java,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui;
+
+import java.net.URL;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.internal.properties.CssPropertiesAdapterFactory;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.ui.editors.text.TextEditorPreferenceConstants;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class.
+ */
+public final class CssUI extends AbstractUIPlugin {
+
+ // Constants ---------------------------------------------------------------
+
+ public static final String ICON_STYLE_SHEET =
+ "style_sheet_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_AT_RULE =
+ "at_rule_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_STYLE_RULE =
+ "style_rule_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_PROPERTY =
+ "property_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_SHORTHAND =
+ "shorthand_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_PSEUDO_CLASS =
+ "pseudo_class_obj.gif"; //$NON-NLS-1$
+ public static final String ICON_IMPORTANT =
+ "important_obj.gif"; //$NON-NLS-1$
+ 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$
+
+ // Class Variables ---------------------------------------------------------
+
+ /**
+ * Singleton instance of the plugin.
+ */
+ private static CssUI plugin;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The text tools collection.
+ */
+ private CssTextTools textTools;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param descriptor the plugin descriptor.
+ */
+ public CssUI() {
+ plugin = this;
+ }
+
+ // Static Methods ----------------------------------------------------------
+
+ /**
+ * Returns the singleton instance of the plugin.
+ *
+ * @return the plugin instance
+ */
+ public static CssUI getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the plugin ID.
+ *
+ * @return the plugin ID
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the CSS text tools that are used primarily for partitioning and
+ * syntax highlighting of CSS source.
+ *
+ * @return the CSS text tools
+ */
+ public synchronized CssTextTools getTextTools() {
+ if (textTools == null) {
+ textTools = new CssTextTools(getPreferenceStore());
+ }
+ return textTools;
+ }
+
+ /**
+ * 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
+ */
+ public ImageDescriptor getImageDescriptor(String key) {
+ try {
+ URL url = getBundle().getEntry("/icons/" + key); //$NON-NLS-1$
+ return ImageDescriptor.createFromURL(url);
+ } catch (IllegalStateException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Writes a status message and the associated exception stack trace (if
+ * provided) to the error log.
+ *
+ * @param status the status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ if (status.getException() != null) {
+ status.getException().printStackTrace(System.err);
+ }
+ }
+
+ /**
+ * Writes the specified error message and exception stack trace to the error
+ * log.
+ *
+ * @param message the error message
+ * @param e the exception that caused the error, or <tt>null</tt> to omit
+ * the stack trace in the log
+ */
+ public static void log(String message, Throwable e) {
+ IStatus status = new Status(IStatus.ERROR, getPluginId(), IStatus.ERROR,
+ message, e);
+ log(status);
+ }
+
+ /**
+ * Writes the specified error message to the error log.
+ *
+ * @param message the error message
+ */
+ public static void log(String message) {
+ IStatus status = new Status(IStatus.ERROR, getPluginId(), IStatus.ERROR,
+ message, null);
+ log(status);
+ }
+
+ /**
+ * Writes the stack trace of the given exception to the error log.
+ *
+ * @param e the exception that caused the error
+ */
+ public static void log(Throwable e) {
+ log(e.getMessage(), e);
+ }
+
+ // AbstractUIPlugin Implementation -----------------------------------------
+
+ /*
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ CssPropertiesAdapterFactory.register(Platform.getAdapterManager());
+ }
+
+ /*
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ try {
+ if (textTools != null) {
+ textTools.dispose();
+ textTools = null;
+ }
+ } finally {
+ super.stop(context);
+ }
+ }
+
+ /*
+ * @see AbstractUIPlugin#initializeDefaultPreferences(IPreferenceStore)
+ */
+ protected void initializeDefaultPreferences(IPreferenceStore store) {
+ TextEditorPreferenceConstants.initializeDefaultValues(store);
+ CssUIPreferences.initializeDefaultValues(store);
+ }
+
+ /*
+ * @see AbstractUIPlugin#initializeImageRegistry(ImageRegistry)
+ */
+ protected void initializeImageRegistry(ImageRegistry reg) {
+ reg.put(ICON_AT_RULE, getImageDescriptor(ICON_AT_RULE));
+ reg.put(ICON_STYLE_RULE, getImageDescriptor(ICON_STYLE_RULE));
+ reg.put(ICON_STYLE_SHEET, getImageDescriptor(ICON_STYLE_SHEET));
+ reg.put(ICON_PROPERTY, getImageDescriptor(ICON_PROPERTY));
+ reg.put(ICON_SHORTHAND, getImageDescriptor(ICON_SHORTHAND));
+ reg.put(ICON_PSEUDO_CLASS, getImageDescriptor(ICON_PSEUDO_CLASS));
+ reg.put(ICON_IMPORTANT, getImageDescriptor(ICON_IMPORTANT));
+ reg.put(ICON_OVERLAY_ERROR, getImageDescriptor(ICON_OVERLAY_ERROR));
+ reg.put(ICON_OVERLAY_WARNING, getImageDescriptor(ICON_OVERLAY_WARNING));
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssDocumentProvider.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal;
+
+import net.sourceforge.phpeclipse.css.core.internal.model.StyleSheet;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.ui.editors.text.TextFileDocumentProvider;
+
+/**
+ * Document provider for CSS files.
+ *
+ * TODO This class currently doubles as a model manager which will need to be
+ * moved into core at some point, and would make this class pretty much
+ * useless
+ */
+public class CssDocumentProvider extends TextFileDocumentProvider {
+
+ // Inner Classes -----------------------------------------------------------
+
+ private class StyleSheetInfo extends FileInfo {
+ private IStyleSheet styleSheet;
+ }
+
+ // TestFileDocumentProvider Implementation ---------------------------------
+
+ /*
+ * @see TextFileDocumentProvider#createEmptyFileInfo()
+ */
+ protected FileInfo createEmptyFileInfo() {
+ return new StyleSheetInfo();
+ }
+
+ /*
+ * @see TextFileDocumentProvider#createFileInfo(Object)
+ */
+ protected FileInfo createFileInfo(Object element) throws CoreException {
+ FileInfo fileInfo = super.createFileInfo(element);
+ if (!(fileInfo instanceof StyleSheetInfo)) {
+ return null;
+ }
+
+ IDocument document = fileInfo.fTextFileBuffer.getDocument();
+ IStyleSheet styleSheet = createStyleSheet(document);
+ if (styleSheet instanceof IDocumentListener) {
+ document.addDocumentListener((IDocumentListener) styleSheet);
+ }
+ StyleSheetInfo styleSheetInfo = (StyleSheetInfo) fileInfo;
+ styleSheetInfo.styleSheet = styleSheet;
+
+ return styleSheetInfo;
+ }
+
+ /*
+ * @see TextFileDocumentProvider#disposeFileInfo(Object, TextFileDocumentProvider.FileInfo)
+ */
+ protected void disposeFileInfo(Object element, FileInfo info) {
+ if (info instanceof StyleSheetInfo) {
+ IDocument document = getDocument(element);
+ // TODO Check whether this is really necessary, as the document is
+ // always null here
+ if (document != null) {
+ IStyleSheet styleSheet = ((StyleSheetInfo) info).styleSheet;
+ if (styleSheet instanceof IDocumentListener) {
+ document.removeDocumentListener((IDocumentListener)
+ styleSheet);
+ }
+ }
+ }
+ super.disposeFileInfo(element, info);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Creates the parsed style sheet object corresponding to the specified
+ * document.
+ *
+ * @param document the document to parse
+ * @return the parsed style sheet
+ */
+ public IStyleSheet createStyleSheet(IDocument document) {
+ return new StyleSheet(document);
+ }
+
+ /**
+ * Returns the style sheet associated with the specified element.
+ *
+ * @param element the element
+ * @return the style sheet associated with the element
+ */
+ public IStyleSheet getStyleSheet(Object element) {
+ FileInfo info = getFileInfo(element);
+ if (info instanceof StyleSheetInfo) {
+ StyleSheetInfo styleSheetInfo = (StyleSheetInfo) info;
+ return styleSheetInfo.styleSheet;
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssDocumentSetupParticipant.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * Document setup participant that sets up the CSS specific partitioning.
+ */
+public class CssDocumentSetupParticipant implements IDocumentSetupParticipant {
+
+ /*
+ * @see IDocumentSetupParticipant#setup(IDocument)
+ */
+ public void setup(IDocument document) {
+ if (document != null) {
+ CssTextTools tools = CssUI.getDefault().getTextTools();
+ tools.setupDocument(document);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssUIMessages.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.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 CssUIMessages {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Qualified name of the resource bundle containing the localized messages.
+ */
+ private static final String RESOURCE_BUNDLE =
+ "net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages"; //$NON-NLS-1$
+
+ // Class Variables ---------------------------------------------------------
+
+ /**
+ * The resource bundle.
+ */
+ private static ResourceBundle fgResourceBundle =
+ ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden constructor.
+ */
+ private CssUIMessages() {
+ // Hidden
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the resource bundle.
+ *
+ * @return the resource bundle
+ */
+ public static ResourceBundle getResourceBundle() {
+ return fgResourceBundle;
+ }
+
+ /**
+ * 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 fgResourceBundle.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);
+ }
+
+}
--- /dev/null
+#
+# 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 english resources
+#
+# $Id: CssUIMessages.properties,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+#
+
+# Outline Page -----------------------------------------------------------------
+
+CssOutlinePage.sort.image = sort_alpha.gif
+CssOutlinePage.sort.label = Sort
+CssOutlinePage.sort.tooltip = Sort rules alpabetically
+CssOutlinePage.sort.description = Sort rules alpabetically
+CssOutlinePage.linkWithEditor.image = link_editor.gif
+CssOutlinePage.linkWithEditor.label = Link with editor
+CssOutlinePage.linkWithEditor.tooltip = Link with editor
+CssOutlinePage.linkWithEditor.description = Link with editor
+
+# Editor -----------------------------------------------------------------------
+
+CssEditor.comment.label = Comment
+CssEditor.comment.tooltip = Comment Selected Code
+CssEditor.comment.description = Comment Selected Code
+CssEditor.uncomment.label = Uncomment
+CssEditor.uncomment.tooltip = Uncomment Selected Code
+CssEditor.uncomment.description = Uncomment Selected Code
+CssEditor.contentAssist.label = Content Assist@Ctrl+Space
+CssEditor.contentAssist.tooltip = Content Assist
+CssEditor.contentAssist.description = Content Assist
+CssEditor.showSelectedElementOnly.label = Show Source of Selected Rule Only
+CssEditor.showSelectedElementOnly.tooltip = Show Source of Selected Rule Only
+CssEditor.showSelectedElementOnly.description = Show Source of Selected Rule Only
+
+# Compare ----------------------------------------------------------------------
+
+CssMergeViewer.title = CSS Source Compare
+CssStructureViewer.title = CSS Structure Compare
+CssStructureViewer.styleSheet = Stylesheet
+
+# Preference Pages -------------------------------------------------------------
+
+CssPreferencePage.description = CSS settings:
+CssPreferencePage.profile = CSS profile:
+
+CssEditorPreferencePage.description = CSS editor settings:
+CssEditorPreferencePage.empty_input = Empty input
+CssEditorPreferencePage.invalid_input = ''{0}'' is not a valid input.
+
+CssEditorPreferencePage.appearance = Appeara&nce
+CssEditorPreferencePage.appearance.displayedTabWidth = Displayed &tab width:
+CssEditorPreferencePage.appearance.printMarginColumn = Print margin col&umn:
+CssEditorPreferencePage.appearance.showOverviewRuler = Show overview &ruler
+CssEditorPreferencePage.appearance.showLineNumbers = Show lin&e numbers
+CssEditorPreferencePage.appearance.highlightMatchingBrackets = Highlight &matching brackets
+CssEditorPreferencePage.appearance.highlightCurrentLine =Hi&ghlight current line
+CssEditorPreferencePage.appearance.showPrintMargin = Sho&w print margin
+CssEditorPreferencePage.appearance.color = C&olor:
+CssEditorPreferencePage.appearance.colorOptions = Appearance co&lor options:
+CssEditorPreferencePage.appearance.lineNumberForegroundColor = Line number foreground
+CssEditorPreferencePage.appearance.matchingBracketsHighlightColor = Matching brackets highlight
+CssEditorPreferencePage.appearance.currentLineHighlighColor = Current line highlight
+CssEditorPreferencePage.appearance.printMarginColor = Print margin
+
+CssEditorPreferencePage.annotations = Annotation&s
+CssEditorPreferencePage.annotations.analyzeWhileTyping = Analyze annotations &while typing
+CssEditorPreferencePage.annotations.presentationOptions = Annotation &presentation:
+CssEditorPreferencePage.annotations.bookmarks = Bookmarks
+CssEditorPreferencePage.annotations.searchResults = Search Results
+CssEditorPreferencePage.annotations.errors = Errors
+CssEditorPreferencePage.annotations.warnings = Warnings
+CssEditorPreferencePage.annotations.infos = Infos
+CssEditorPreferencePage.annotations.tasks = Tasks
+CssEditorPreferencePage.annotations.others = Others
+CssEditorPreferencePage.annotations.showInText = Show in &text
+CssEditorPreferencePage.annotations.showInOverviewRuler = Show in overview &ruler
+CssEditorPreferencePage.annotations.color = C&olor:
+
+CssEditorPreferencePage.syntax = Synta&x
+CssEditorPreferencePage.syntax.backgroundColor = Background color
+CssEditorPreferencePage.syntax.backgroundColorSystemDefault = System default
+CssEditorPreferencePage.syntax.backgroundColorCustom = Custom:
+CssEditorPreferencePage.syntax.foregroundColor = Foreground:
+CssEditorPreferencePage.syntax.commentColor = Comments
+CssEditorPreferencePage.syntax.propertyNameColor = Property names
+CssEditorPreferencePage.syntax.atKeywordColor = At-keywords
+CssEditorPreferencePage.syntax.pseudoClassColor = Pseudo classes and elements
+CssEditorPreferencePage.syntax.stringColor = Strings
+CssEditorPreferencePage.syntax.defaultColor = Others
+CssEditorPreferencePage.syntax.color = C&olor
+CssEditorPreferencePage.syntax.bold = &Bold
+
+CssEditorPreferencePage.contentAssist = &Content Assist
+CssEditorPreferencePage.contentAssist.insertSingleProposalsAutomatically = Insert single &proposals automatically
+CssEditorPreferencePage.contentAssist.presentProposalsInAlphabeticalOrder = Present proposals in &alphabetical order
+CssEditorPreferencePage.contentAssist.enableAutoActivation = &Enable auto activation
+CssEditorPreferencePage.contentAssist.autoActivationDelay = Auto activation dela&y:
+CssEditorPreferencePage.contentAssist.autoActivationTriggers = Auto activation &triggers:
+CssEditorPreferencePage.contentAssist.colorOptions = Content assist colo&r options:
+CssEditorPreferencePage.contentAssist.color = C&olor:
+CssEditorPreferencePage.contentAssist.backgroundForCompletionProposals = Completion proposal background
+CssEditorPreferencePage.contentAssist.foregroundForCompletionProposals = Completion proposal foreground
+
+CssEditorPreferencePage.typing = T&yping
+CssEditorPreferencePage.typing.insertSpaceForTabs = Ins&ert space for tabs
+CssEditorPreferencePage.typing.closeStrings = Close strin&gs
+CssEditorPreferencePage.typing.closeBracketsAndParens = Close &brackets and parenthesis
+CssEditorPreferencePage.typing.closeBraces = Cl&ose braces
+
+TextStyleFieldsEditor.color = C&olor
+TextStyleFieldsEditor.bold = &Bold
+
+# Property Pages ---------------------------------------------------------------
+
+CssPropertyPage.useWorkspaceSettings = Use &workspace settings
+CssPropertyPage.useProjectSettings = Use project or &workspace settings
+CssPropertyPage.useCustomSettings = Use c&ustom settings
+CssPropertyPage.profile = CSS profile:
--- /dev/null
+/*
+ * 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: CssUIPreferences.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+
+/**
+ *
+ */
+public final class CssUIPreferences {
+
+ // Constants ---------------------------------------------------------------
+
+ // Inherited constants
+
+ public static final String EDITOR_CURRENT_LINE =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE;
+
+ public static final String EDITOR_CURRENT_LINE_COLOR =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
+
+ public static final String EDITOR_TAB_WIDTH =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH;
+
+ public static final String EDITOR_LINE_NUMBER_RULER =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER;
+
+ public static final String EDITOR_LINE_NUMBER_RULER_COLOR =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
+
+ public static final String EDITOR_PRINT_MARGIN =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN;
+
+ public static final String EDITOR_PRINT_MARGIN_COLOR =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
+
+ public static final String EDITOR_PRINT_MARGIN_COLUMN =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
+
+ public static final String EDITOR_OVERVIEW_RULER =
+ AbstractDecoratedTextEditorPreferenceConstants.EDITOR_OVERVIEW_RULER;
+
+ public static final String EDITOR_BACKGROUND_DEFAULT_COLOR =
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT;
+
+ public static final String EDITOR_BACKGROUND_COLOR =
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND;
+
+ public static final String EDITOR_FOREGROUND_COLOR =
+ AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND;
+
+ public static final String EDITOR_FOREGROUND_DEFAULT_COLOR =
+ AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT;
+
+ // Custom constants
+
+ public static final String EDITOR_MATCHING_BRACKETS =
+ "matchingBrackets"; //$NON-NLS-1$
+
+ public static final String EDITOR_MATCHING_BRACKETS_COLOR =
+ "matchingBracketsColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_COMMENT_COLOR =
+ "commentColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_COMMENT_BOLD =
+ "commentBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_PROPERTY_COLOR =
+ "propertyColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_PROPERTY_BOLD =
+ "propertyBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_AT_KEYWORD_COLOR =
+ "atKeywordColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_AT_KEYWORD_BOLD =
+ "atKeywordBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_PSEUDO_CLASS_COLOR =
+ "pseudoClassColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_PSEUDO_CLASS_BOLD =
+ "pseudoClassBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_STRING_COLOR =
+ "stringColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_STRING_BOLD =
+ "stringBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_DEFAULT_COLOR =
+ "defaultColor"; //$NON-NLS-1$
+
+ public static final String EDITOR_DEFAULT_BOLD =
+ "defaultBold"; //$NON-NLS-1$
+
+ public static final String EDITOR_SPACES_FOR_TABS =
+ "spacesForTabs"; //$NON-NLS-1$
+
+ public static final String EDITOR_CLOSE_STRINGS =
+ "closeStrings"; //$NON-NLS-1$
+
+ public static final String EDITOR_CLOSE_BRACKETS_AND_PARENS =
+ "closeBracketsAndParens"; //$NON-NLS-1$
+
+ public static final String EDITOR_CLOSE_BRACES =
+ "closeBraces"; //$NON-NLS-1$
+
+ public static final String EDITOR_SHOW_SELECTED_ELEMENT_ONLY =
+ "showSelectedElementOnly"; //$NON-NLS-1$
+
+ public static final String OUTLINE_LINK_WITH_EDITOR =
+ "linkOutlineWithEditor"; //$NON-NLS-1$
+
+ public static final String OUTLINE_SORT_LEXICALLY =
+ "sortOutlineLexically"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_AUTOACTIVATION =
+ "contentAssistAutoActivation"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_AUTOACTIVATION_DELAY =
+ "contentAssistAutoActivationDelay"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_AUTOACTIVATION_TRIGGERS =
+ "contentAssistAutoActivationTriggers"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_AUTOINSERT =
+ "contentAssistAutoInsert"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_ORDER_PROPOSALS =
+ "contentAssistOrderProposals"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_PROPOSALS_BACKGROUND =
+ "contentAssistProposalsBackground"; //$NON-NLS-1$
+
+ public static final String CONTENTASSIST_PROPOSALS_FOREGROUND =
+ "contentAssistProposalsForeground"; //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden constructor.
+ */
+ private CssUIPreferences() {
+ // Hidden
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Initializes the preference store with the default values.
+ *
+ * @param store The preference store to initialize
+ */
+ public static final void initializeDefaultValues(IPreferenceStore store) {
+
+ // Appearance
+ store.setDefault(EDITOR_TAB_WIDTH, 4);
+ store.setDefault(EDITOR_MATCHING_BRACKETS, true);
+ PreferenceConverter.setDefault(store, EDITOR_MATCHING_BRACKETS_COLOR,
+ new RGB(192, 192, 192));
+
+ // Syntax
+ store.setDefault(EDITOR_FOREGROUND_DEFAULT_COLOR, true);
+ store.setDefault(EDITOR_BACKGROUND_DEFAULT_COLOR, true);
+ PreferenceConverter.setDefault(store, EDITOR_COMMENT_COLOR,
+ new RGB(63, 127, 95));
+ store.setDefault(EDITOR_COMMENT_BOLD, false);
+ PreferenceConverter.setDefault(store, EDITOR_PROPERTY_COLOR,
+ new RGB(127, 0, 85));
+ store.setDefault(EDITOR_PROPERTY_BOLD, true);
+ PreferenceConverter.setDefault(store, EDITOR_AT_KEYWORD_COLOR,
+ new RGB(127, 0, 85));
+ store.setDefault(EDITOR_AT_KEYWORD_BOLD, true);
+ PreferenceConverter.setDefault(store, EDITOR_PSEUDO_CLASS_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_PSEUDO_CLASS_BOLD, false);
+ PreferenceConverter.setDefault(store, EDITOR_STRING_COLOR,
+ new RGB(42, 0, 255));
+ store.setDefault(EDITOR_STRING_BOLD, false);
+ PreferenceConverter.setDefault(store, EDITOR_DEFAULT_COLOR,
+ new RGB(0, 0, 0));
+ store.setDefault(EDITOR_DEFAULT_BOLD, false);
+
+ // Content assist
+ store.setDefault(CONTENTASSIST_AUTOINSERT, false);
+ store.setDefault(CONTENTASSIST_ORDER_PROPOSALS, false);
+ store.setDefault(CONTENTASSIST_AUTOACTIVATION, true);
+ store.setDefault(CONTENTASSIST_AUTOACTIVATION_DELAY, 500);
+ store.setDefault(CONTENTASSIST_AUTOACTIVATION_TRIGGERS,
+ "-@:"); //$NON-NLS-1$
+ PreferenceConverter.setDefault(store,
+ CONTENTASSIST_PROPOSALS_BACKGROUND, new RGB(254, 241, 233));
+ PreferenceConverter.setDefault(store,
+ CONTENTASSIST_PROPOSALS_FOREGROUND, new RGB(0, 0, 0));
+
+ // Typing
+ store.setDefault(EDITOR_TAB_WIDTH, 4);
+ store.setDefault(EDITOR_SPACES_FOR_TABS, false);
+ store.setDefault(EDITOR_CLOSE_STRINGS, true);
+ store.setDefault(EDITOR_CLOSE_BRACKETS_AND_PARENS, true);
+ store.setDefault(EDITOR_CLOSE_BRACES, true);
+
+ // Outline
+ store.setDefault(OUTLINE_SORT_LEXICALLY, false);
+ store.setDefault(OUTLINE_LINK_WITH_EDITOR, false);
+ }
+}
--- /dev/null
+/*
+ * 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: ICssUIHelpContextIds.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+/**
+ * Symbolic constants for the help context IDs.
+ */
+public interface ICssUIHelpContextIds {
+
+ /**
+ * The string with which all other defined ids are prefixed to construct
+ * help context ids.
+ */
+ String PREFIX = CssUI.getPluginId() + "."; //$NON-NLS-1$
+
+ /**
+ * Help context ID for the CSS editor.
+ * Value: <code>"net.sourceforge.phpeclipse.css.ui.editor_context"</code>.
+ */
+ String EDITOR = PREFIX + "css_editor_context"; //$NON-NLS-1$
+
+}
--- /dev/null
+/*
+ * 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: CssMergeViewer.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.compare;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssSourceViewerConfiguration;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.TextMergeViewer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Merge viewer for CSS files.
+ */
+public class CssMergeViewer extends TextMergeViewer {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Alias for the preference constant <code>EDITOR_BACKGROUND_COLOR</code>.
+ */
+ private static final String PREFERENCE_BACKGROUND_COLOR =
+ CssUIPreferences.EDITOR_BACKGROUND_COLOR;
+
+ /**
+ * Alias for the preference constant
+ * <code>EDITOR_BACKGROUND_DEFAULT_COLOR</code>.
+ */
+ private static final String PREFERENCE_BACKGROUND_DEFAULT_COLOR =
+ CssUIPreferences.EDITOR_BACKGROUND_DEFAULT_COLOR;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The preference store.
+ */
+ private IPreferenceStore preferenceStore;
+
+ /**
+ * The listener for changes to the preference store.
+ */
+ private IPropertyChangeListener propertyChangeListener;
+
+ /**
+ * The CSS text tools.
+ */
+ private CssTextTools textTools;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param parent the parent control
+ * @param style SWT style bits for top level composite of this viewer
+ * @param configuration the configuration object
+ */
+ public CssMergeViewer(Composite parent, int style,
+ CompareConfiguration configuration) {
+ super(parent, style, configuration);
+ }
+
+ // TextMergeViewer Implementation ------------------------------------------
+
+ /*
+ * @see TextMergeViewer#configureTextViewer()
+ */
+ protected void configureTextViewer(TextViewer textViewer) {
+
+ CssUI plugin = CssUI.getDefault();
+
+ this.preferenceStore = plugin.getPreferenceStore();
+ if (preferenceStore != null) {
+ propertyChangeListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handlePreferenceStoreChanged(event);
+ }
+ };
+ preferenceStore.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ textTools = plugin.getTextTools();
+ if (textViewer instanceof SourceViewer) {
+ SourceViewer sourceViewer = (SourceViewer) textViewer;
+ sourceViewer.configure(new CssSourceViewerConfiguration(
+ textTools, preferenceStore));
+ }
+
+ updateBackgroundColor();
+ }
+
+ /*
+ * @see TextMergeViewer#getDocumentPartitioner()
+ */
+ protected IDocumentPartitioner getDocumentPartitioner() {
+ return textTools.createDocumentPartitioner();
+ }
+
+ /*
+ * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getTitle()
+ */
+ public String getTitle() {
+ return CssUIMessages.getString(
+ "CssMergeViewer.title"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ContentViewer#handleDispose(org.eclipse.swt.events.DisposeEvent)
+ */
+ protected void handleDispose(DisposeEvent event) {
+ if (propertyChangeListener != null) {
+ if (preferenceStore != null) {
+ preferenceStore.removePropertyChangeListener(
+ propertyChangeListener);
+ }
+ propertyChangeListener = null;
+ }
+ super.handleDispose(event);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Called when the preference store notifies us about a change.
+ *
+ * @param event the change event
+ */
+ protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ if (PREFERENCE_BACKGROUND_COLOR.equals(p)
+ || PREFERENCE_BACKGROUND_DEFAULT_COLOR.equals(p)) {
+ updateBackgroundColor();
+ } else if (textTools.affectsPresentation(event)) {
+ invalidateTextPresentation();
+ }
+ }
+
+ /**
+ * Updates the background color of the merge viewer to the value set in the
+ * preferences.
+ */
+ private void updateBackgroundColor() {
+ boolean defaultBackgroundColor = preferenceStore.getBoolean(
+ PREFERENCE_BACKGROUND_DEFAULT_COLOR);
+ if (defaultBackgroundColor) {
+ setBackgroundColor(null);
+ } else {
+ RGB backgroundColor = PreferenceConverter.getColor(
+ preferenceStore, CssUIPreferences.EDITOR_BACKGROUND_COLOR);
+ setBackgroundColor(backgroundColor);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssMergeViewerCreator.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.compare;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IViewerCreator;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * Factory for creating a CSS merge viewer.
+ */
+public class CssMergeViewerCreator implements IViewerCreator {
+
+ /*
+ * @see IViewerCreator#createViewer(Composite, CompareConfiguration)
+ */
+ public Viewer createViewer(Composite parent, CompareConfiguration config) {
+ return new CssMergeViewer(parent, SWT.NULL, config);
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssNode.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.compare;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.structuremergeviewer.DocumentRangeNode;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ *
+ */
+public class CssNode extends DocumentRangeNode implements ITypedElement {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Type code for the top-level style sheet.
+ */
+ public static final int STYLE_SHEET = 0;
+
+ /**
+ * Type code for at rules.
+ */
+ public static final int AT_RULE = 1;
+
+ /**
+ * Type code for style rules.
+ */
+ public static final int STYLE_RULE = 2;
+
+ /**
+ * Type code for declarations (property-value assignment).
+ */
+ public static final int DECLARATION = 3;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The display name of the node.
+ */
+ private String name;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor for the top-level style sheet node.
+ *
+ * @param document The document
+ */
+ public CssNode(IDocument document) {
+ super(STYLE_SHEET, "root", document, 0, //$NON-NLS-1$
+ document.getLength());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param parent
+ * @param typeCode
+ * @param id
+ * @param name
+ * @param start
+ * @param length
+ */
+ public CssNode(CssNode parent, int typeCode, String id, String name,
+ int start, int length) {
+ super(typeCode, parent.getId() + Integer.toString(typeCode) + id,
+ parent.getDocument(), start, length);
+ this.name = name;
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getName()
+ */
+ public String getName() {
+ if (getTypeCode() == STYLE_SHEET) {
+ return CssUIMessages.getString(
+ "CssStructureViewer.styleSheet"); //$NON-NLS-1$
+ }
+ return name;
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getImage()
+ */
+ public Image getImage() {
+ String key = null;
+ switch (getTypeCode()) {
+ case STYLE_SHEET: {
+ key = CssUI.ICON_STYLE_SHEET;
+ break;
+ }
+ case AT_RULE: {
+ key = CssUI.ICON_AT_RULE;
+ break;
+ }
+ case STYLE_RULE: {
+ key = CssUI.ICON_STYLE_RULE;
+ break;
+ }
+ case DECLARATION: {
+ key = CssUI.ICON_PROPERTY;
+ break;
+ }
+ default: {
+ // we'll just return null
+ }
+ }
+ return CssUI.getDefault().getImageRegistry().get(key);
+ }
+
+ /**
+ * @see org.eclipse.compare.ITypedElement#getType()
+ */
+ public String getType() {
+ return "css"; //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssStructureCreator.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.compare;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.internal.parser.DefaultCssParser;
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.core.parser.ICssParser;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+
+import org.eclipse.compare.IStreamContentAccessor;
+import org.eclipse.compare.internal.DocumentManager;
+import org.eclipse.compare.structuremergeviewer.IStructureComparator;
+import org.eclipse.compare.structuremergeviewer.IStructureCreator;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+
+/**
+ * TODO Check why the root node is not being displayed
+ */
+public class CssStructureCreator implements IStructureCreator {
+
+ // IStructureCreator Implementation ----------------------------------------
+
+ /*
+ * @see IStructureCreator#getName()
+ */
+ public String getName() {
+ return CssUIMessages.getString(
+ "CssStructureViewer.title"); //$NON-NLS-1$
+ }
+
+ /*
+ * @see IStructureCreator#getStructure(Object)
+ */
+ public IStructureComparator getStructure(final Object input) {
+ IDocument doc = DocumentManager.get(input);
+ if (doc == null) {
+ if (input instanceof IStreamContentAccessor) {
+ doc = createDocument((IStreamContentAccessor) input);
+ }
+ }
+ if (doc != null) {
+ CssNode node = new CssNode(doc);
+ ICssParser parser = new DefaultCssParser();
+ parser.setSource(doc);
+ try {
+ IRule[] rules = parser.parseRules(null);
+ for (int i = 0; i < rules.length; i++) {
+ node.addChild(createNode(node, rules[i], new HashMap()));
+ }
+ } catch (LexicalErrorException e) {
+ // just return null
+ } catch (SyntaxErrorException e) {
+ // just return null
+ }
+ return node;
+ }
+ return null;
+ }
+
+ /*
+ * @see IStructureCreator#locate(Object, Object)
+ */
+ public IStructureComparator locate(Object path, Object input) {
+ // TODO Find out what locate() is about and implement the functionality
+ return null;
+ }
+
+ /*
+ * @see IStructureCreator#getContents(Object, boolean)
+ */
+ public String getContents(Object node, boolean ignoreWhitespace) {
+ if (node instanceof CssNode) {
+ CssNode cssNode = (CssNode) node;
+ int ch;
+ InputStream in = null;
+ try {
+ StringBuffer buf = new StringBuffer();
+ in = cssNode.getContents();
+ while ((ch = in.read()) != -1) {
+ if (!ignoreWhitespace
+ || !CssTextUtils.isCssWhitespace((char) ch)) {
+ buf.append((char) ch);
+ }
+ }
+ return buf.toString();
+ } catch (IOException e) {
+ // just return an empty string
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /*
+ * @see IStructureCreator#save(IStructureComparator, Object)
+ */
+ public void save(IStructureComparator node, Object input) {
+ // TODO Find out what save() is about and implement the functionality
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private IDocument createDocument(IStreamContentAccessor content) {
+ IDocument document = null;
+ InputStreamReader in = null;
+ try {
+ in = new InputStreamReader(content.getContents());
+ StringBuffer buf = new StringBuffer();
+ int ch;
+ while ((ch = in.read()) != -1) {
+ buf.append((char) ch);
+ }
+ document = new Document(buf.toString());
+ DocumentManager.put(content, document);
+ CssTextTools tools = CssUI.getDefault().getTextTools();
+ tools.setupDocument(document);
+ } catch (CoreException e) {
+ CssUI.log(e);
+ } catch (IOException e) {
+ CssUI.log(e);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ return document;
+ }
+
+ private CssNode createNode(CssNode parent, IRule rule, Map names) {
+ int typeCode = -1;
+ String name = ""; //$NON-NLS-1$
+ if (rule instanceof IAtRule) {
+ IAtRule atRule = (IAtRule) rule;
+ typeCode = CssNode.AT_RULE;
+ ISourceReference atKeyword = atRule.getName();
+ if (atKeyword != null) {
+ name = atKeyword.getSource();
+ }
+ } else if (rule instanceof IStyleRule) {
+ IStyleRule styleRule = (IStyleRule) rule;
+ typeCode = CssNode.STYLE_RULE;
+ ISourceReference selector = styleRule.getSelector();
+ if (selector != null) {
+ name = selector.getSource();
+ }
+ }
+ String id = name;
+ if (names.containsKey(name)) {
+ Integer count = (Integer) names.get(name);
+ id += count.toString();
+ names.put(name, new Integer(count.intValue() + 1));
+ } else {
+ names.put(name, new Integer(0));
+ }
+ IRegion region = rule.getSourceRegion();
+ CssNode node = new CssNode(parent, typeCode, id, name,
+ region.getOffset(), region.getLength());
+ IRule[] children = rule.getChildren();
+ if (children.length > 0) {
+ Map ruleNames = new HashMap();
+ for (int i = 0; i < children.length; i++) {
+ node.addChild(createNode(node, children[i], ruleNames));
+ }
+ }
+ IDeclaration[] properties = rule.getDeclarations();
+ if (properties.length > 0) {
+ Map propertyNames = new HashMap();
+ for (int i = 0; i < properties.length; i++) {
+ node.addChild(createNode(node, properties[i], propertyNames));
+ }
+ }
+ return node;
+ }
+
+ private CssNode createNode(CssNode parent, IDeclaration declaration,
+ Map names) {
+ String name = ""; //$NON-NLS-1$
+ ISourceReference property = declaration.getProperty();
+ if (property != null) {
+ name = property.getSource();
+ }
+ String id = name;
+ if (names.containsKey(name)) {
+ Integer count = (Integer) names.get(name);
+ id += count.toString();
+ names.put(name, new Integer(count.intValue() + 1));
+ } else {
+ names.put(name, new Integer(0));
+ }
+ IRegion region = declaration.getSourceRegion();
+ return new CssNode(parent, CssNode.DECLARATION, id, name,
+ region.getOffset(), region.getLength());
+ }
+
+}
--- /dev/null
+/*
+ * 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: CommentAction.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * (Heavily inspired by the AddBlockComment class in JDT-UI)
+ */
+public class CommentAction extends TextEditorAction {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param bundle the resource bundle
+ * @param prefix a prefix to be prepended to the various resource keys
+ * (described in <code>ResourceAction</code> constructor), or
+ * <code>null</code> if none
+ * @param editor the text editor
+ */
+ public CommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ // TextEditorAction Implementation -----------------------------------------
+
+ /**
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ if (!isEnabled()) {
+ return;
+ }
+ ITextEditor editor = getTextEditor();
+ if ((editor == null) || !ensureEditable(editor)) {
+ return;
+ }
+ ITextSelection selection = getCurrentSelection();
+ if (!validSelection(selection)) {
+ return;
+ }
+ IDocumentProvider docProvider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ if (docProvider == null || input == null) {
+ return;
+ }
+ IDocument document = docProvider.getDocument(input);
+ if (document == null) {
+ return;
+ }
+ IRewriteTarget target = (IRewriteTarget)
+ editor.getAdapter(IRewriteTarget.class);
+ if (target != null) {
+ target.beginCompoundChange();
+ }
+ try {
+ int offset = selection.getOffset();
+ String start = "/*"; //$NON-NLS-1$
+ document.replace(offset, 0, start);
+ document.replace(offset + selection.getLength() + start.length(), 0,
+ "*/"); //$NON-NLS-1$
+ } catch (BadLocationException e) {
+ // ignore
+ } finally {
+ if (target != null) {
+ target.endCompoundChange();
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.texteditor.TextEditorAction#update()
+ */
+ public void update() {
+ super.update();
+ if (isEnabled()) {
+ if (!validSelection(getCurrentSelection())) {
+ setEnabled(false);
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Ensures that the editor is modifyable. If the editor is an instance of
+ * <code>ITextEditorExtension2</code>, its
+ * <code>validateEditorInputState</code> method is called, otherwise, the
+ * result of <code>isEditable</code> is returned.
+ *
+ * @param editor the editor to be checked
+ * @return <code>true</code> if the editor is editable, <code>false</code>
+ * otherwise
+ */
+ private boolean ensureEditable(ITextEditor editor) {
+ if (editor instanceof ITextEditorExtension2) {
+ ITextEditorExtension2 extension = (ITextEditorExtension2) editor;
+ return extension.validateEditorInputState();
+ }
+ return editor.isEditable();
+ }
+
+ /**
+ * Returns the editor's selection, or <code>null</code> if no selection can
+ * be obtained or the editor is <code>null</code>.
+ *
+ * @return the selection of the action's editor, or <code>null</code>
+ */
+ private ITextSelection getCurrentSelection() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ ISelectionProvider provider = editor.getSelectionProvider();
+ if (provider != null) {
+ ISelection selection = provider.getSelection();
+ if (selection instanceof ITextSelection) {
+ return (ITextSelection) selection;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether <code>selection</code> is valid, i.e. neither
+ * <code>null</code> or empty.
+ *
+ * @param selection the selection to check
+ * @return <code>true</code> if the selection is valid, <code>false</code>
+ * otherwise
+ */
+ private boolean validSelection(ITextSelection selection) {
+ if (selection != null) {
+ return (!selection.isEmpty() && (selection.getLength() > 0));
+ }
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditor.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.internal.ICssUIHelpContextIds;
+import net.sourceforge.phpeclipse.css.ui.internal.outline.CssOutlinePage;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssPairMatcher;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssSourceViewerConfiguration;
+import net.sourceforge.phpeclipse.css.ui.internal.text.IReconcilingParticipant;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+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.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * Implementation of a CSS editor based on the text editor infrastructure
+ * provided by the platform.
+ *
+ * TODO Reacting to every caret move seems rather expensive. Ideally, we'd
+ * collect the caret position changes and react after a specific delay.
+ */
+public class CssEditor 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);
+
+ IRegion selectedRegion = null;
+ if (element instanceof IAtRule) {
+ IAtRule atRule = (IAtRule) element;
+ selectedRegion = atRule.getValue().getSourceRegion();
+ } else if (element instanceof IStyleRule) {
+ IStyleRule styleRule = (IStyleRule) element;
+ selectedRegion = styleRule.getSelector().getSourceRegion();
+ }
+
+ if (selectedRegion != null) {
+ selectAndReveal(selectedRegion.getOffset(),
+ selectedRegion.getLength());
+ }
+ }
+ }
+ }
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Alias for the preference constant <code>OUTLINE_LINK_WITH_EDITOR</code>.
+ */
+ private static final String LINK_WITH_OUTLINE =
+ CssUIPreferences.OUTLINE_LINK_WITH_EDITOR;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated outline page.
+ */
+ CssOutlinePage outlinePage;
+
+ /**
+ * Listens to changes in the outline page's selection to update the editor
+ * selection and highlight range.
+ */
+ private ISelectionChangedListener outlineSelectionChangedListener;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CssEditor() {
+ setSourceViewerConfiguration(
+ new CssSourceViewerConfiguration(
+ CssUI.getDefault().getTextTools(),
+ getPreferenceStore(), this));
+ }
+
+ // AbstractTextEditor Implementation ---------------------------------------
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
+ */
+ protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ if (CssUIPreferences.EDITOR_DEFAULT_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_DEFAULT_BOLD.equals(p) ||
+ CssUIPreferences.EDITOR_COMMENT_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_COMMENT_BOLD.equals(p) ||
+ CssUIPreferences.EDITOR_STRING_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_STRING_BOLD.equals(p) ||
+ CssUIPreferences.EDITOR_PROPERTY_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_PROPERTY_BOLD.equals(p) ||
+ CssUIPreferences.EDITOR_AT_KEYWORD_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_AT_KEYWORD_BOLD.equals(p) ||
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_COLOR.equals(p) ||
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_BOLD.equals(p)
+ ) {
+ return true;
+ }
+
+ return super.affectsTextPresentation(event);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
+ */
+ protected void createActions() {
+ super.createActions();
+
+ IAction action;
+
+ action = new ContentAssistAction(
+ CssUIMessages.getResourceBundle(),
+ "CssEditor.contentAssist.", this); //$NON-NLS-1$
+ action.setActionDefinitionId(
+ ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction(ICssEditorActionConstants.CONTENT_ASSIST, action);
+
+ action = new CommentAction(
+ CssUIMessages.getResourceBundle(),
+ "CssEditor.comment.", this); //$NON-NLS-1$
+ action.setActionDefinitionId(ICssEditorActionDefinitionIds.COMMENT);
+ setAction(ICssEditorActionConstants.COMMENT, action);
+ markAsStateDependentAction(ICssEditorActionConstants.COMMENT, true);
+ markAsSelectionDependentAction(ICssEditorActionConstants.COMMENT, true);
+
+ action = new UncommentAction(
+ CssUIMessages.getResourceBundle(),
+ "CssEditor.uncomment.", this); //$NON-NLS-1$
+ action.setActionDefinitionId(ICssEditorActionDefinitionIds.UNCOMMENT);
+ setAction(ICssEditorActionConstants.UNCOMMENT, action);
+ markAsStateDependentAction(ICssEditorActionConstants.UNCOMMENT, true);
+ markAsSelectionDependentAction(ICssEditorActionConstants.UNCOMMENT,
+ true);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.ExtendedTextEditor#configureSourceViewerDecorationSupport(SourceViewerDecorationSupport)
+ */
+ protected void configureSourceViewerDecorationSupport(
+ SourceViewerDecorationSupport support
+ ) {
+ super.configureSourceViewerDecorationSupport(support);
+
+ support.setCharacterPairMatcher(new CssPairMatcher());
+ support.setMatchingCharacterPainterPreferenceKeys(
+ CssUIPreferences.EDITOR_MATCHING_BRACKETS,
+ CssUIPreferences.EDITOR_MATCHING_BRACKETS_COLOR);
+ support.setSymbolicFontName(getFontPropertyPreferenceKey());
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (IContentOutlinePage.class.equals(adapter)) {
+ if (outlinePage == null) {
+ outlinePage = new CssOutlinePage(this);
+ outlineSelectionChangedListener =
+ new OutlineSelectionChangedListener();
+ outlinePage.addSelectionChangedListener(
+ outlineSelectionChangedListener);
+ }
+
+ return outlinePage;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged()
+ */
+ protected void handleCursorPositionChanged() {
+ super.handleCursorPositionChanged();
+
+ highlightElement(computeHighlightRangeSourceReference(), false);
+ synchronizeOutlinePageSelection();
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.ExtendedTextEditor#initializeEditor()
+ */
+ protected void initializeEditor() {
+ super.initializeEditor();
+
+ setHelpContextId(ICssUIHelpContextIds.EDITOR);
+ setPreferenceStore(CssUI.getDefault().getPreferenceStore());
+ configureInsertMode(SMART_INSERT, true);
+ setInsertMode(SMART_INSERT);
+ }
+
+ // 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 != null) {
+ 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 getRuleAt(caret);
+ }
+
+ /**
+ * 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(
+ outlineSelectionChangedListener);
+ 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(
+ outlineSelectionChangedListener);
+ outlinePage.select(element);
+ outlinePage.addSelectionChangedListener(
+ outlineSelectionChangedListener);
+ }
+ }
+
+ /**
+ * Synchronizes the outliner selection with the currently highlighted source
+ * reference.
+ */
+ public void synchronizeOutlinePage() {
+ ISourceReference element = computeHighlightRangeSourceReference();
+ synchronizeOutlinePage(element);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private IRule getRuleAt(int offset) {
+ IStyleSheet styleSheet = getStyleSheet();
+ if (styleSheet == null) {
+ return null;
+ }
+
+ return styleSheet.getRuleAt(offset);
+ }
+
+ private IStyleSheet getStyleSheet() {
+ if (getDocumentProvider() instanceof CssDocumentProvider) {
+ CssDocumentProvider p = (CssDocumentProvider) getDocumentProvider();
+ return p.getStyleSheet(getEditorInput());
+ }
+
+ return null;
+ }
+
+ void highlightElement(ISourceReference element, boolean moveCursor) {
+ if (element != null) {
+ IRegion highlightRegion = element.getSourceRegion();
+ setHighlightRange(highlightRegion.getOffset(),
+ highlightRegion.getLength(), moveCursor);
+ } else {
+ resetHighlightRange();
+ }
+ }
+
+ void synchronizeOutlinePageSelection() {
+ IPreferenceStore store = getPreferenceStore();
+ if (store != null) {
+ boolean linkWithEditor = store.getBoolean(LINK_WITH_OUTLINE);
+ if (linkWithEditor) {
+ synchronizeOutlinePage(computeHighlightRangeSourceReference());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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: CssEditorActionContributor.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.texteditor.BasicTextEditorActionContributor;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.RetargetTextEditorAction;
+
+/**
+ *
+ */
+public class CssEditorActionContributor
+ extends BasicTextEditorActionContributor {
+
+ // Instance Variables ------------------------------------------------------
+
+ private RetargetTextEditorAction contentAssistAction =
+ new RetargetTextEditorAction(CssUIMessages.getResourceBundle(),
+ "CssEditor.contentAssistProposal."); //$NON-NLS-1$
+
+ private ShowSelectedElementOnlyAction showSelectedElementOnlyAction =
+ new ShowSelectedElementOnlyAction(); //$NON-NLS-1$
+
+ // IEditorActionBarContributor Implementation ------------------------------
+
+ /**
+ * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToMenu(IMenuManager)
+ */
+ public void contributeToMenu(IMenuManager menu) {
+ super.contributeToMenu(menu);
+ IMenuManager editMenu = menu.findMenuUsingPath(
+ IWorkbenchActionConstants.M_EDIT);
+ if (editMenu != null) {
+ editMenu.add(new Separator());
+ editMenu.add(this.contentAssistAction);
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.part.EditorActionBarContributor#contributeToToolBar(IToolBarManager)
+ */
+ public void contributeToToolBar(IToolBarManager toolBarManager) {
+ super.contributeToToolBar(toolBarManager);
+ if (toolBarManager != null) {
+ toolBarManager.add(new Separator());
+ }
+ }
+
+ /**
+ * @see org.eclipse.ui.IEditorActionBarContributor#dispose()
+ */
+ public void dispose() {
+ doSetActiveEditor(null);
+ super.dispose();
+ }
+
+ /**
+ * @see org.eclipse.ui.IEditorActionBarContributor#setActiveEditor(IEditorPart)
+ */
+ public void setActiveEditor(IEditorPart part) {
+ super.setActiveEditor(part);
+ doSetActiveEditor(part);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private void doSetActiveEditor(IEditorPart part) {
+ ITextEditor editor = null;
+ if (part instanceof ITextEditor) {
+ editor = (ITextEditor) part;
+ }
+
+ contentAssistAction.setAction(
+ getAction(editor, ICssEditorActionConstants.CONTENT_ASSIST));
+
+ showSelectedElementOnlyAction.setEditor(editor);
+ showSelectedElementOnlyAction.update();
+
+ IActionBars bars = getActionBars();
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY,
+ showSelectedElementOnlyAction);
+ bars.setGlobalActionHandler(
+ ICssEditorActionDefinitionIds.COMMENT,
+ getAction(editor, ICssEditorActionConstants.COMMENT));
+ bars.setGlobalActionHandler(
+ ICssEditorActionDefinitionIds.UNCOMMENT,
+ getAction(editor, ICssEditorActionConstants.UNCOMMENT));
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.SHIFT_LEFT,
+ getAction(editor, ITextEditorActionConstants.SHIFT_LEFT));
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.SHIFT_RIGHT,
+ getAction(editor, ITextEditorActionConstants.SHIFT_RIGHT));
+ }
+
+}
--- /dev/null
+/*
+ * 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: ICssEditorActionConstants.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+
+/**
+ *
+ */
+public interface ICssEditorActionConstants
+ extends ITextEditorActionConstants {
+
+ /**
+ * Edit menu: name of the standard global action "Content Assist"
+ * (value <code>"ContentAssist"</code>).
+ */
+ String CONTENT_ASSIST = "ContentAssist"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard global action "Comment"
+ * (value <code>"Comment"</code>).
+ */
+ String COMMENT = "Comment"; //$NON-NLS-1$
+
+ /**
+ * Source menu: name of standard global action "Uncomment"
+ * (value <code>"Uncomment"</code>).
+ */
+ String UNCOMMENT = "Uncomment"; //$NON-NLS-1$
+
+}
--- /dev/null
+/*
+ * 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: ICssEditorActionDefinitionIds.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+/**
+ * Action definition IDs used by the CSS editor.
+ */
+public interface ICssEditorActionDefinitionIds
+ extends ITextEditorActionDefinitionIds {
+
+ /**
+ * Action definition ID of the "Source > Comment" action
+ * (value <code>"net.sourceforge.phpeclipse.css.ui.commentAction"</code>).
+ */
+ String COMMENT = "net.sourceforge.phpeclipse.css.ui.commentAction"; //$NON-NLS-1$
+
+ /**
+ * Action definition ID of the "Source > Uncomment" action
+ * (value <code>"net.sourceforge.phpeclipse.css.ui.uncommentAction"</code>).
+ */
+ String UNCOMMENT = "net.sourceforge.phpeclipse.css.ui.uncommentAction"; //$NON-NLS-1$
+
+}
--- /dev/null
+/*
+ * 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: ShowSelectedElementOnlyAction.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * A toolbar action which toggles the presentation model of the connected text
+ * editor. The editor shows either the highlight range only or always the whole
+ * document.
+ *
+ * <p>
+ * This class is an implementation for the retargetable action
+ * <code>TOGGLE_SHOW_SELECTED_ELEMENT_ONLY</code> provided by the platform.
+ * </p>
+ *
+ * @see org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds#TOGGLE_SHOW_SELECTED_ELEMENT_ONLY
+ */
+public class ShowSelectedElementOnlyAction extends TextEditorAction
+ implements IPropertyChangeListener {
+
+ // Instance Variables ------------------------------------------------------
+
+ private IPreferenceStore store;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public ShowSelectedElementOnlyAction() {
+ super(CssUIMessages.getResourceBundle(),
+ "CssEditor.showSelectedElementOnly.", null); //$NON-NLS-1$
+ store = CssUI.getDefault().getPreferenceStore();
+ update();
+ }
+
+ // TextEditor Implementation -----------------------------------------------
+
+ /*
+ * @see org.eclipse.jface.action.IAction#run()
+ */
+ public void run() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ IRegion highlightRange = editor.getHighlightRange();
+ editor.resetHighlightRange();
+ boolean show = !editor.showsHighlightRangeOnly();
+ setChecked(show);
+ editor.showHighlightRangeOnly(show);
+ if (highlightRange != null) {
+ editor.setHighlightRange(highlightRange.getOffset(),
+ highlightRange.getLength(), true);
+ }
+ store.removePropertyChangeListener(this);
+ store.setValue(
+ CssUIPreferences.EDITOR_SHOW_SELECTED_ELEMENT_ONLY, show);
+ store.addPropertyChangeListener(this);
+ }
+ }
+
+ /*
+ * @see TextEditorAction#setEditor(ITextEditor)
+ */
+ public void setEditor(ITextEditor editor) {
+ super.setEditor(editor);
+ if (editor != null) {
+ if (store == null) {
+ store = CssUI.getDefault().getPreferenceStore();
+ store.addPropertyChangeListener(this);
+ }
+ synchronizeWithPreference(editor);
+ } else if (store != null) {
+ store.removePropertyChangeListener(this);
+ store = null;
+ }
+ update();
+ }
+
+ /*
+ * @see org.eclipse.ui.texteditor.IUpdate#update()
+ */
+ public void update() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ setChecked(getTextEditor().showsHighlightRangeOnly());
+ setEnabled(true);
+ } else {
+ setEnabled(false);
+ }
+ }
+
+ // IPropertyChangeListener Implementation ----------------------------------
+
+ /*
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ if (CssUIPreferences.EDITOR_SHOW_SELECTED_ELEMENT_ONLY.equals(p)) {
+ synchronizeWithPreference(getTextEditor());
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Synchronizes the appearance of the editor with what the preference store
+ * contains.
+ *
+ * @param editor the editor to synchronize
+ */
+ private void synchronizeWithPreference(ITextEditor editor) {
+ if (editor != null) {
+ boolean show = this.store.getBoolean(
+ CssUIPreferences.EDITOR_SHOW_SELECTED_ELEMENT_ONLY);
+ setChecked(show);
+ if (show != editor.showsHighlightRangeOnly()) {
+ IRegion highlightRange = editor.getHighlightRange();
+ editor.resetHighlightRange();
+ editor.showHighlightRangeOnly(show);
+ if (highlightRange != null) {
+ editor.setHighlightRange(highlightRange.getOffset(),
+ highlightRange.getLength(), true);
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: UncommentAction.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.editor;
+
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssPartitionScanner;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRewriteTarget;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * (Heavily inspired by the RemoveBlockComment class in JDT-UI)
+ */
+public class UncommentAction extends TextEditorAction {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Creates a new instance.
+ *
+ * @param bundle the resource bundle
+ * @param prefix a prefix to be prepended to the various resource keys
+ * (described in <code>ResourceAction</code> constructor), or
+ * <code>null</code> if none
+ * @param editor the text editor
+ */
+ public UncommentAction(ResourceBundle bundle, String prefix,
+ ITextEditor editor) {
+ super(bundle, prefix, editor);
+ }
+
+ // TextEditorAction Implementation -----------------------------------------
+
+ /**
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ if (!isEnabled()) {
+ return;
+ }
+ ITextEditor editor = getTextEditor();
+ if ((editor == null) || !ensureEditable(editor)) {
+ return;
+ }
+ ITextSelection selection = getCurrentSelection();
+ if (!isValidSelection(selection)) {
+ return;
+ }
+ IDocumentProvider docProvider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ if (docProvider == null || input == null) {
+ return;
+ }
+ IDocument document = docProvider.getDocument(input);
+ if (document == null) {
+ return;
+ }
+ IRewriteTarget target = (IRewriteTarget)
+ editor.getAdapter(IRewriteTarget.class);
+ if (target != null) {
+ target.beginCompoundChange();
+ }
+ try {
+ ITypedRegion region = getBlockCommentRegion(document, selection);
+ if (region != null) {
+ int offset = region.getOffset();
+ document.replace(offset, 2, ""); //$NON-NLS-1$
+ document.replace(offset + region.getLength() - 4, 2,
+ ""); //$NON-NLS-1$
+ }
+ } catch (BadLocationException e) {
+ // ignore
+ } finally {
+ if (target != null) {
+ target.endCompoundChange();
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Ensures that the editor is modifyable. If the editor is an instance of
+ * <code>ITextEditorExtension2</code>, its
+ * <code>validateEditorInputState</code> method is called, otherwise, the
+ * result of <code>isEditable</code> is returned.
+ *
+ * @param editor the editor to be checked
+ * @return <code>true</code> if the editor is editable, <code>false</code>
+ * otherwise
+ */
+ private boolean ensureEditable(ITextEditor editor) {
+ if (editor instanceof ITextEditorExtension2) {
+ ITextEditorExtension2 extension = (ITextEditorExtension2) editor;
+ return extension.validateEditorInputState();
+ }
+ return editor.isEditable();
+ }
+
+ /**
+ * Returns the block comment typed region enclosing the position at the end
+ * of <code>selection</code> or <code>null</code> if there is no block
+ * comment at this position.
+ *
+ * @param selection the caret position (the end of the selection is taken as
+ * the position)
+ * @return the block comment region at the selection's end, or
+ * <code>null</code>
+ */
+ private ITypedRegion getBlockCommentRegion(IDocument document,
+ ITextSelection selection) {
+ try {
+ ITypedRegion region = document.getPartition(
+ selection.getOffset() + selection.getLength());
+ if (CssPartitionScanner.CSS_COMMENT.equals(region.getType())) {
+ return region;
+ }
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ /**
+ * Returns the editor's selection, or <code>null</code> if no selection can
+ * be obtained or the editor is <code>null</code>.
+ *
+ * @return the selection of the action's editor, or <code>null</code>
+ */
+ private ITextSelection getCurrentSelection() {
+ ITextEditor editor = getTextEditor();
+ if (editor != null) {
+ ISelectionProvider provider = editor.getSelectionProvider();
+ if (provider != null) {
+ ISelection selection = provider.getSelection();
+ if (selection instanceof ITextSelection) {
+ return (ITextSelection) selection;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether given selection is valid, i.e. neither <code>null</code>
+ * or empty.
+ *
+ * @param selection the selection to check
+ * @return <code>true</code> if the selection is valid, <code>false</code>
+ * otherwise
+ */
+ private boolean isValidSelection(ITextSelection selection) {
+ if (selection != null) {
+ return (!selection.isEmpty() && (selection.getLength() > 0));
+ }
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssOutlineContentProvider.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.outline;
+
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Content provider for the CSS outline page.
+ */
+public class CssOutlineContentProvider implements ITreeContentProvider {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The parsed style sheet.
+ */
+ private IStyleSheet styleSheet;
+
+ // ITreeContentProvider Implementation -------------------------------------
+
+ /*
+ * ITreeContentProvider#getChildren(Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof IRule) {
+ return ((IRule) parentElement).getChildren();
+ }
+ return new Object[0];
+ }
+
+ /*
+ * @see ITreeContentProvider#getParent(Object)
+ */
+ public Object getParent(Object element) {
+ if (element instanceof IRule) {
+ return ((IRule) element).getParent();
+ }
+ 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) {
+ if (styleSheet != null) {
+ return styleSheet.getRules();
+ }
+ return new Object[0];
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ styleSheet = null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(Viewer, Object, Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (oldInput != newInput) {
+ if (oldInput instanceof IStyleSheet) {
+ styleSheet = null;
+ }
+ if (newInput instanceof IStyleSheet) {
+ IStyleSheet newStyleSheet = (IStyleSheet) newInput;
+ styleSheet = newStyleSheet;
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssOutlineDoubleClickListener.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.outline;
+
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * A double click listener that is intended to be attached to an outline page
+ * displaying CSS elements. If a style rule is double clicked, it will attempt
+ * to show the standard properties view.
+ */
+public class CssOutlineDoubleClickListener implements IDoubleClickListener {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated content outline page.
+ */
+ private ContentOutlinePage outlinePage;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param outlinePage the associated outline page
+ */
+ public CssOutlineDoubleClickListener(ContentOutlinePage outlinePage) {
+ this.outlinePage = outlinePage;
+ }
+
+ // IDoubleClickListener Implementation -------------------------------------
+
+ /*
+ * @see IDoubleClickListener#doubleClick(DoubleClickEvent)
+ */
+ public void doubleClick(DoubleClickEvent event) {
+ Object selectedElement = getSelectedElement(event.getSelection());
+ if (selectedElement instanceof IStyleRule) {
+ showPropertiesView();
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Shows the properties view in the current workbench window.
+ */
+ private void showPropertiesView() {
+ IWorkbenchPage workbenchPage = outlinePage.getSite().getPage();
+ try {
+ workbenchPage.showView(IPageLayout.ID_PROP_SHEET);
+ } catch (PartInitException e) {
+ CssUI.log(
+ "Could not show properties view", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Finds the element that is selected. As this is a double click listener,
+ * only a single element can be selected at once.
+ *
+ * @param selection the selection
+ * @return the selected element
+ */
+ private Object getSelectedElement(ISelection selection) {
+ Object element = null;
+ if (selection instanceof IStructuredSelection) {
+ element = ((IStructuredSelection) selection).getFirstElement();
+ }
+ return element;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssOutlineLabelProvider.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.outline;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Label provider for the CSS outline page.
+ */
+public class CssOutlineLabelProvider extends LabelProvider {
+
+ // LabelProvider Implementation --------------------------------------------
+
+ /**
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
+ */
+ public Image getImage(Object element) {
+ if (element instanceof IStyleRule) {
+ return CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_STYLE_RULE);
+ } else if (element instanceof IAtRule) {
+ return CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_AT_RULE);
+ }
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ StringBuffer text = new StringBuffer();
+ if (element instanceof IStyleRule) {
+ IStyleRule rule = (IStyleRule) element;
+ ISourceReference selector = rule.getSelector();
+ if (selector != null) {
+ text.append(selector.getSource());
+ }
+ } else if (element instanceof IAtRule) {
+ IAtRule rule = (IAtRule) element;
+ ISourceReference name = rule.getName();
+ ISourceReference value = rule.getValue();
+ if (name != null) {
+ text.append(name.getSource());
+ if (value != null) {
+ text.append(' ');
+ }
+ }
+ if (value != null) {
+ text.append(value.getSource());
+ }
+ }
+ return normalizeWhitespace(text.toString());
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Replaces all whitespace characters by regular spaces, and trims excessive
+ * whitespace down to at most one whitespace between non-whitespace
+ * characters.
+ *
+ * @param text The text to normalize
+ * @return The normalized text
+ */
+ public String normalizeWhitespace(String text) {
+ StringBuffer buf = new StringBuffer();
+ boolean previousWasWhitespace = false;
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ if ((c == 9) || (c == 10) || (c == 13)) { // Tab
+ c = ' ';
+ }
+ if ((c != ' ') || !previousWasWhitespace) {
+ buf.append(c);
+ }
+ previousWasWhitespace = (c == ' ');
+ }
+ return buf.toString();
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssOutlinePage.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.outline;
+
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.internal.editor.CssEditor;
+import net.sourceforge.phpeclipse.css.ui.internal.editor.ShowSelectedElementOnlyAction;
+import net.sourceforge.phpeclipse.ui.views.outline.ProblemsLabelDecorator;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.DecoratingLabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.part.IPageSite;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.ResourceAction;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * Implements the outline page associated with the CSS editor.
+ */
+public class CssOutlinePage extends ContentOutlinePage {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Action that activates or deactivates the lexical sorting of elements in
+ * the outline tree viewer.
+ */
+ private class ToggleLexicalSortingAction extends ResourceAction {
+
+ // Constants -----------------------------------------------------------
+
+ private static final int CATEGORY_AT_RULE = 0;
+ private static final int CATEGORY_STYLE_RULE = 1;
+
+ // Instance Variables --------------------------------------------------
+
+ /**
+ * The viewer sorter. At-rules are displayed before style rules,
+ * otherwise the default lexical sorting applies.
+ */
+ private final ViewerSorter sorter = new ViewerSorter() {
+ public int category(Object element) {
+ if (element instanceof IAtRule) {
+ return CATEGORY_AT_RULE;
+ } else {
+ return CATEGORY_STYLE_RULE;
+ }
+ }
+ };
+
+ // Constructors --------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public ToggleLexicalSortingAction() {
+ super(CssUIMessages.getResourceBundle(),
+ "CssOutlinePage.sort."); //$NON-NLS-1$
+ CssUI plugin = CssUI.getDefault();
+ boolean checked = plugin.getPreferenceStore().getBoolean(
+ CssUIPreferences.OUTLINE_SORT_LEXICALLY); //$NON-NLS-1$
+ valueChanged(checked, false);
+ }
+
+ // Action Implementation -----------------------------------------------
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ valueChanged(isChecked(), true);
+ }
+
+ // Private Methods -----------------------------------------------------
+
+ /**
+ * Updates the sorting of the outline.
+ *
+ * @param checked Whether lexical sorting 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() {
+ getTreeViewer().setSorter(checked ? sorter : null);
+ }
+ });
+ if (store) {
+ CssUI plugin = CssUI.getDefault();
+ plugin.getPreferenceStore().setValue(
+ CssUIPreferences.OUTLINE_SORT_LEXICALLY, checked);
+ }
+ }
+
+ }
+
+ /**
+ * This action toggles whether this Java Outline page links its selection
+ * to the active editor.
+ */
+ private class ToggleLinkingAction extends ResourceAction {
+
+ /**
+ * Constructs a new action.
+ */
+ public ToggleLinkingAction() {
+ super(CssUIMessages.getResourceBundle(),
+ "CssOutlinePage.linkWithEditor."); //$NON-NLS-1$
+ CssUI plugin = CssUI.getDefault();
+ boolean checked = plugin.getPreferenceStore().getBoolean(
+ CssUIPreferences.OUTLINE_LINK_WITH_EDITOR); //$NON-NLS-1$
+ valueChanged(checked, false);
+ }
+
+ /*
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ valueChanged(isChecked(), true);
+ }
+
+ // Private Methods -----------------------------------------------------
+
+ /**
+ * Updates the sorting of the outline.
+ *
+ * @param checked Whether lexical sorting 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) {
+ CssUI plugin = CssUI.getDefault();
+ plugin.getPreferenceStore().setValue(
+ CssUIPreferences.OUTLINE_LINK_WITH_EDITOR, checked);
+ }
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated editor.
+ */
+ private CssEditor editor;
+
+ /**
+ * Toolbar action for showing only the selected element in the editor.
+ */
+ private ShowSelectedElementOnlyAction showSelectedElementOnlyAction =
+ new ShowSelectedElementOnlyAction(); //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param editor The associated text editor
+ */
+ public CssOutlinePage(CssEditor 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.addDoubleClickListener(new CssOutlineDoubleClickListener(this));
+ viewer.setContentProvider(new CssOutlineContentProvider());
+ viewer.setLabelProvider(new DecoratingLabelProvider(
+ new CssOutlineLabelProvider(),
+ new ProblemsLabelDecorator(editor)));
+ viewer.setInput(getStyleSheet());
+ }
+
+ /*
+ * @see org.eclipse.ui.part.IPage#dispose()
+ */
+ public void dispose() {
+ if (editor != null) {
+ editor.outlinePageClosed();
+ editor = null;
+ }
+ super.dispose();
+ }
+
+ /*
+ * @see org.eclipse.ui.part.IPageBookViewPage#init(org.eclipse.ui.part.IPageSite)
+ */
+ public void init(IPageSite pageSite) {
+ super.init(pageSite);
+ IActionBars bars = pageSite.getActionBars();
+ bars.setGlobalActionHandler(
+ ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY,
+ showSelectedElementOnlyAction);
+ showSelectedElementOnlyAction.setEditor(editor);
+ showSelectedElementOnlyAction.update();
+ }
+
+ /*
+ * @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 ToggleLexicalSortingAction());
+ toolBarManager.add(new ToggleLinkingAction());
+ }
+ super.makeContributions(menuManager, toolBarManager, statusLineManager);
+ }
+
+ // 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);
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the outline page.
+ */
+ public void update() {
+ IStyleSheet styleSheet = getStyleSheet();
+ if (styleSheet != null) {
+ TreeViewer viewer = getTreeViewer();
+ if (viewer != null) {
+ Control control = viewer.getControl();
+ if ((control != null) && !control.isDisposed()) {
+ control.setRedraw(false);
+ viewer.setInput(styleSheet);
+ viewer.expandAll();
+ control.setRedraw(true);
+ }
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the parsed model of the style sheet that is loaded into the
+ * associated editor.
+ *
+ * @return the parsed style sheet
+ */
+ private IStyleSheet getStyleSheet() {
+ IDocumentProvider provider = editor.getDocumentProvider();
+ if (provider instanceof CssDocumentProvider) {
+ CssDocumentProvider cssProvider = (CssDocumentProvider) provider;
+ return cssProvider.getStyleSheet(editor.getEditorInput());
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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: AbstractConfigurationBlock.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ *
+ */
+abstract class AbstractConfigurationBlock {
+
+ // Instance Variables ------------------------------------------------------
+
+ private IPreferenceStore fPreferenceStore;
+
+ private Map fCheckBoxes = new HashMap();
+ private SelectionListener fCheckBoxListener = new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ Button button = (Button) e.widget;
+ getPreferenceStore().setValue((String) fCheckBoxes.get(button),
+ button.getSelection());
+ }
+ };
+
+ private Map fTextFields = new HashMap();
+ private ModifyListener fTextFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ Text text = (Text) e.widget;
+ getPreferenceStore().setValue((String) fTextFields.get(text),
+ text.getText());
+ }
+ };
+
+ private List fNumberFields = new ArrayList();
+ private ModifyListener fNumberFieldListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ //numberFieldChanged((Text) e.widget);
+ }
+ };
+
+ private Map fLabels = new HashMap();
+
+ // Constructors ------------------------------------------------------------
+
+ public AbstractConfigurationBlock(IPreferenceStore store) {
+ this.fPreferenceStore = store;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public void initializeFields() {
+ for (Iterator i = fCheckBoxes.keySet().iterator(); i.hasNext(); ) {
+ Button button = (Button) i.next();
+ String key = (String) fCheckBoxes.get(button);
+ button.setSelection(getPreferenceStore().getBoolean(key));
+ }
+ for (Iterator i = fTextFields.keySet().iterator(); i.hasNext(); ) {
+ Text text = (Text) i.next();
+ String key = (String) fTextFields.get(text);
+ text.setText(getPreferenceStore().getString(key));
+ }
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ protected final Button addBooleanField(Composite parent, String label,
+ String key, int indentation) {
+
+ Button checkBox = new Button(parent, SWT.CHECK);
+ checkBox.setText(label);
+
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ gd.horizontalSpan = 2;
+ checkBox.setLayoutData(gd);
+ checkBox.addSelectionListener(fCheckBoxListener);
+
+ fCheckBoxes.put(checkBox, key);
+
+ return checkBox;
+ }
+
+ protected final Control addIntegerField(Composite composite, String label,
+ String key, int textLimit, int indentation) {
+
+ Text textControl =
+ addStringField(composite, label, textLimit, indentation);
+ fTextFields.put(textControl, key);
+ fNumberFields.add(textControl);
+ textControl.addModifyListener(fNumberFieldListener);
+
+ return textControl;
+ }
+
+ protected final Control addTextField(Composite composite, String label,
+ String key, int textLimit, int indentation) {
+
+ Text textControl =
+ addStringField(composite, label, textLimit, indentation);
+ fTextFields.put(textControl, key);
+ textControl.addModifyListener(fTextFieldListener);
+
+ return textControl;
+ }
+
+ protected final int convertHeightInCharsToPixels(Control control,
+ int chars) {
+ GC gc = new GC(control);
+ gc.setFont(control.getFont());
+ FontMetrics fontMetrics = gc.getFontMetrics();
+ gc.dispose();
+ if (fontMetrics == null) {
+ return 0;
+ }
+ return Dialog.convertHeightInCharsToPixels(fontMetrics, chars);
+ }
+
+ protected final int convertWidthInCharsToPixels(Control control,
+ int chars) {
+ GC gc = new GC(control);
+ gc.setFont(control.getFont());
+ FontMetrics fontMetrics = gc.getFontMetrics();
+ gc.dispose();
+ if (fontMetrics == null) {
+ return 0;
+ }
+ return Dialog.convertWidthInCharsToPixels(fontMetrics, chars);
+ }
+
+ protected final Control getLabel(Control field) {
+ return (Control) fLabels.get(field);
+ }
+
+ protected final IPreferenceStore getPreferenceStore() {
+ return fPreferenceStore;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private Text addStringField(Composite composite, String label,
+ int textLimit, int indentation) {
+
+ Label labelControl = new Label(composite, SWT.NONE);
+ labelControl.setText(label);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.horizontalIndent = indentation;
+ labelControl.setLayoutData(gd);
+
+ Text textControl = new Text(composite, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ gd.widthHint = convertWidthInCharsToPixels(textControl, textLimit + 1);
+ textControl.setLayoutData(gd);
+ textControl.setTextLimit(textLimit);
+
+ fLabels.put(textControl, labelControl);
+
+ return textControl;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorAnnotationsConfigurationBlock.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
+
+/**
+ *
+ */
+final class CssEditorAnnotationsConfigurationBlock
+ extends AbstractConfigurationBlock {
+
+ // Instance Variables ------------------------------------------------------
+
+ private List fColorList;
+ private String[][] fColorListModel;
+ private ColorSelector fColorSelector;
+ private Button fShowInTextCheckBox;
+ private Button fShowInOverviewRulerCheckBox;
+
+ // Constructors ------------------------------------------------------------
+
+ public CssEditorAnnotationsConfigurationBlock(IPreferenceStore store) {
+ super(store);
+ MarkerAnnotationPreferences preferences =
+ new MarkerAnnotationPreferences();
+ fColorListModel = createAnnotationTypeListModel(preferences);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ Label label = new Label(composite, SWT.LEFT);
+ label.setText(getString("presentationOptions")); //$NON-NLS-1$
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ label.setLayoutData(gridData);
+
+ Composite editorComposite = new Composite(composite, SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ gridData = new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL);
+ gridData.horizontalSpan = 2;
+ editorComposite.setLayoutData(gridData);
+
+ fColorList = new List(editorComposite,
+ SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
+ gridData = new GridData(
+ GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+ gridData.heightHint = convertHeightInCharsToPixels(composite, 8);
+ fColorList.setLayoutData(gridData);
+ fColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ handleAnnotationColorListSelection();
+ }
+ });
+
+ Composite optionsComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ optionsComposite.setLayout(layout);
+ optionsComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ fShowInTextCheckBox = new Button(optionsComposite, SWT.CHECK);
+ fShowInTextCheckBox.setText(getString(
+ "showInText")); //$NON-NLS-1$
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ gridData.horizontalSpan = 2;
+ fShowInTextCheckBox.setLayoutData(gridData);
+ fShowInTextCheckBox.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][2];
+ getPreferenceStore().setValue(key,
+ fShowInTextCheckBox.getSelection());
+ }
+ });
+
+ fShowInOverviewRulerCheckBox = new Button(optionsComposite, SWT.CHECK);
+ fShowInOverviewRulerCheckBox.setText(getString(
+ "showInOverviewRuler")); //$NON-NLS-1$
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ gridData.horizontalSpan = 2;
+ fShowInOverviewRulerCheckBox.setLayoutData(gridData);
+ fShowInOverviewRulerCheckBox.addSelectionListener(
+ new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][3];
+ getPreferenceStore().setValue(key,
+ fShowInOverviewRulerCheckBox.getSelection());
+ }
+ });
+
+ label = new Label(optionsComposite, SWT.LEFT);
+ label.setText(getString("color")); //$NON-NLS-1$
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gridData);
+
+ fColorSelector = new ColorSelector(optionsComposite);
+ Button foregroundColorButton = fColorSelector.getButton();
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ foregroundColorButton.setLayoutData(gridData);
+ foregroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ PreferenceConverter.setValue(getPreferenceStore(), key,
+ fColorSelector.getColorValue());
+ }
+ });
+
+ initialize();
+
+ return composite;
+ }
+
+ // Event Handlers ----------------------------------------------------------
+
+ void handleAnnotationColorListSelection() {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
+ fColorSelector.setColorValue(rgb);
+ key = fColorListModel[i][2];
+ fShowInTextCheckBox.setSelection(getPreferenceStore().getBoolean(key));
+ key = fColorListModel[i][3];
+ fShowInOverviewRulerCheckBox.setSelection(
+ getPreferenceStore().getBoolean(key));
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private String[][] createAnnotationTypeListModel(
+ MarkerAnnotationPreferences preferences) {
+
+ ArrayList listModelItems = new ArrayList();
+ Iterator i = preferences.getAnnotationPreferences().iterator();
+ while (i.hasNext()) {
+ AnnotationPreference info = (AnnotationPreference) i.next();
+ listModelItems.add(new String[] {
+ info.getPreferenceLabel(),
+ info.getColorPreferenceKey(),
+ info.getTextPreferenceKey(),
+ info.getOverviewRulerPreferenceKey()
+ });
+ }
+
+ String[][] listModel = new String[listModelItems.size()][];
+ listModelItems.toArray(listModel);
+ return listModel;
+ }
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage.annotations." + key); //$NON-NLS-1$
+ }
+
+ private void initialize() {
+ for (int i = 0; i < fColorListModel.length; i++) {
+ fColorList.add(fColorListModel[i][0]);
+ }
+ fColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if ((fColorList != null)
+ && !fColorList.isDisposed()) {
+ fColorList.select(0);
+ handleAnnotationColorListSelection();
+ }
+ }
+ });
+ initializeFields();
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorAppearanceConfigurationBlock.java,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+
+/**
+ *
+ */
+final class CssEditorAppearanceConfigurationBlock
+ extends AbstractConfigurationBlock {
+
+ // Instance Variables ------------------------------------------------------
+
+ private List fColorList;
+ private final String[][] fColorListModel = new String[][] {
+ { getString("lineNumberForegroundColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_LINE_NUMBER_RULER_COLOR },
+ { getString("matchingBracketsHighlightColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_MATCHING_BRACKETS_COLOR },
+ { getString("currentLineHighlighColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_CURRENT_LINE_COLOR },
+ { getString("printMarginColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_PRINT_MARGIN_COLOR },
+ };
+ private ColorSelector fColorSelector;
+
+ // Constructors ------------------------------------------------------------
+
+ public CssEditorAppearanceConfigurationBlock(IPreferenceStore store) {
+ super(store);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public Control createControl(Composite parent) {
+
+ Composite control = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ control.setLayout(layout);
+
+ addTextField(control, getString("displayedTabWidth"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_TAB_WIDTH, 3, 0);
+ addTextField(control, getString("printMarginColumn"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_PRINT_MARGIN_COLUMN, 3,
+ 0);
+ addBooleanField(control, getString("showOverviewRuler"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_OVERVIEW_RULER, 0);
+ addBooleanField(control, getString("showLineNumbers"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_LINE_NUMBER_RULER, 0);
+ addBooleanField(control,
+ getString("highlightMatchingBrackets"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_MATCHING_BRACKETS, 0);
+ addBooleanField(control,
+ getString("highlightCurrentLine"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_CURRENT_LINE, 0);
+ addBooleanField(control, getString("showPrintMargin"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_PRINT_MARGIN, 0);
+
+ Label label = new Label(control, SWT.LEFT);
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ gridData.heightHint = convertHeightInCharsToPixels(control, 1) / 2;
+ label.setLayoutData(gridData);
+
+ label = new Label(control, SWT.LEFT);
+ label.setText(getString("colorOptions")); //$NON-NLS-1$
+ gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ label.setLayoutData(gridData);
+
+ Composite editorComposite = new Composite(control, SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ gridData = new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL);
+ gridData.horizontalSpan = 2;
+ editorComposite.setLayoutData(gridData);
+
+ fColorList = new List(editorComposite,
+ SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
+ gridData = new GridData(
+ GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+ gridData.heightHint = convertHeightInCharsToPixels(control, 8);
+ fColorList.setLayoutData(gridData);
+ fColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+ public void widgetSelected(SelectionEvent e) {
+ handleColorListSelection();
+ }
+ });
+
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(getString("color")); //$NON-NLS-1$
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gridData);
+
+ fColorSelector = new ColorSelector(stylesComposite);
+ Button foregroundColorButton = fColorSelector.getButton();
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ foregroundColorButton.setLayoutData(gridData);
+ foregroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ PreferenceConverter.setValue(getPreferenceStore(), key,
+ fColorSelector.getColorValue());
+ }
+ });
+
+ initialize();
+
+ return control;
+ }
+
+ // Event Handlers ----------------------------------------------------------
+
+ void handleColorListSelection() {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
+ fColorSelector.setColorValue(rgb);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage.appearance." + key); //$NON-NLS-1$
+ }
+
+ private void initialize() {
+ for (int i = 0; i < fColorListModel.length; i++) {
+ fColorList.add(fColorListModel[i][0]);
+ }
+ fColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if ((fColorList != null)
+ && !fColorList.isDisposed()) {
+ fColorList.select(0);
+ handleColorListSelection();
+ }
+ }
+ });
+ initializeFields();
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorContentAssistConfigurationBlock.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+
+/**
+ * Configuration block for setting the preferences related to content assist.
+ */
+final class CssEditorContentAssistConfigurationBlock
+ extends AbstractConfigurationBlock {
+
+ // Instance Variables ------------------------------------------------------
+
+ private List fColorList;
+ private final String[][] fColorListModel = new String[][] {
+ { getString("backgroundForCompletionProposals"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_BACKGROUND },
+ { getString("foregroundForCompletionProposals"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_FOREGROUND },
+ };
+ private ColorSelector fColorSelector;
+ private Control fAutoActivationDelayField;
+ private Control fAutoActivationTriggersField;
+
+ // Constructors ------------------------------------------------------------
+
+ public CssEditorContentAssistConfigurationBlock(IPreferenceStore store) {
+ super(store);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ //addCompletionRadioButtons(contentAssistComposite);
+
+ addBooleanField(composite,
+ getString("insertSingleProposalsAutomatically"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_AUTOINSERT, 0);
+ addBooleanField(composite,
+ getString("presentProposalsInAlphabeticalOrder"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_ORDER_PROPOSALS, 0);
+ addBooleanField(composite,
+ getString("enableAutoActivation"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION,
+ 0).addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updateAutoactivationControls();
+ }
+ });
+ fAutoActivationDelayField = addIntegerField(composite,
+ getString("autoActivationDelay"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_DELAY, 4, 0);
+ fAutoActivationTriggersField = addTextField(composite,
+ getString("autoActivationTriggers"), //$NON-NLS-1$
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_TRIGGERS, 4, 0);
+
+ Label label = new Label(composite, SWT.LEFT);
+ label.setText(getString("colorOptions")); //$NON-NLS-1$
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ gridData.horizontalSpan = 2;
+ label.setLayoutData(gridData);
+
+ Composite editorComposite = new Composite(composite, SWT.NONE);
+ layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ gridData = new GridData(
+ GridData.HORIZONTAL_ALIGN_FILL | GridData.FILL_VERTICAL);
+ gridData.horizontalSpan = 2;
+ editorComposite.setLayoutData(gridData);
+
+ fColorList = new List(editorComposite,
+ SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
+ gridData = new GridData(
+ GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
+ gridData.heightHint = convertHeightInCharsToPixels(composite, 8);
+ fColorList.setLayoutData(gridData);
+ fColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+ public void widgetSelected(SelectionEvent e) {
+ handleColorListSelection();
+ }
+ });
+
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(getString("color")); //$NON-NLS-1$
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gridData);
+
+ fColorSelector = new ColorSelector(stylesComposite);
+ Button colorButton = fColorSelector.getButton();
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ colorButton.setLayoutData(gridData);
+ colorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ PreferenceConverter.setValue(getPreferenceStore(), key,
+ fColorSelector.getColorValue());
+ }
+ });
+
+ initialize();
+
+ return composite;
+ }
+
+ // Event Handlers ----------------------------------------------------------
+
+ void handleColorListSelection() {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
+ fColorSelector.setColorValue(rgb);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage.contentAssist." + key); //$NON-NLS-1$
+ }
+
+ private void initialize() {
+ for (int i = 0; i < fColorListModel.length; i++) {
+ fColorList.add(fColorListModel[i][0]);
+ }
+ fColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if ((fColorList != null)
+ && !fColorList.isDisposed()) {
+ fColorList.select(0);
+ handleColorListSelection();
+ }
+ }
+ });
+ initializeFields();
+ }
+
+ private void updateAutoactivationControls() {
+ boolean enabled = getPreferenceStore().getBoolean(
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION);
+ fAutoActivationDelayField.setEnabled(enabled);
+ getLabel(fAutoActivationDelayField).setEnabled(enabled);
+ fAutoActivationTriggersField.setEnabled(enabled);
+ getLabel(fAutoActivationTriggersField).setEnabled(enabled);
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorPreferencePage.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+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.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.MarkerAnnotationPreferences;
+
+/**
+ * Implements the CSS editor preference page.
+ */
+public class CssEditorPreferencePage extends PreferencePage
+ implements IWorkbenchPreferencePage {
+
+ // Instance Variables ------------------------------------------------------
+
+ private OverlayPreferenceStore overlayStore;
+
+ private CssEditorAppearanceConfigurationBlock appearanceBlock;
+ private CssEditorSyntaxConfigurationBlock syntaxBlock;
+ private CssEditorContentAssistConfigurationBlock contentAssistBlock;
+ private CssEditorAnnotationsConfigurationBlock annotationsBlock;
+ private CssEditorTypingConfigurationBlock typingBlock;
+
+ // PreferencePage Implementation -------------------------------------------
+
+ /**
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ TabFolder folder = new TabFolder(parent, SWT.NONE);
+ TabItem item;
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(getString("appearance")); //$NON-NLS-1$
+ item.setControl(createAppearancePage(folder));
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(getString("syntax")); //$NON-NLS-1$
+ item.setControl(createSyntaxPage(folder));
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(getString("contentAssist")); //$NON-NLS-1$
+ item.setControl(createCodeAssistPage(folder));
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(getString("annotations")); //$NON-NLS-1$
+ item.setControl(createAnnotationsPage(folder));
+
+ item = new TabItem(folder, SWT.NONE);
+ item.setText(getString("typing")); //$NON-NLS-1$
+ item.setControl(createTypingPage(folder));
+
+ return folder;
+ }
+
+ /**
+ * @see PreferencePage#dispose()
+ */
+ public void dispose() {
+ if (overlayStore != null) {
+ overlayStore.stopListening();
+ overlayStore = null;
+ }
+ super.dispose();
+ }
+
+ /**
+ * @see PreferencePage#performOk()
+ */
+ public boolean performOk() {
+ overlayStore.propagate();
+ CssUI.getDefault().savePluginPreferences();
+ return true;
+ }
+
+ /**
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ overlayStore.loadDefaults();
+ super.performDefaults();
+ }
+
+ // IWorkbenchPreferencePage Implementation ---------------------------------
+
+ /**
+ * @see IWorkbenchPreferencePage#init(IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ setDescription(getString("description")); //$NON-NLS-1$
+ setPreferenceStore(CssUI.getDefault().getPreferenceStore());
+
+ MarkerAnnotationPreferences preferences =
+ new MarkerAnnotationPreferences();
+ overlayStore = createOverlayStore(preferences);
+ overlayStore.load();
+ overlayStore.startListening();
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private OverlayPreferenceStore createOverlayStore(
+ MarkerAnnotationPreferences preferences) {
+
+ OverlayPreferenceStore store =
+ new OverlayPreferenceStore(getPreferenceStore());
+
+ Iterator e = preferences.getAnnotationPreferences().iterator();
+ while (e.hasNext()) {
+ AnnotationPreference info = (AnnotationPreference) e.next();
+ store.addStringKey(info.getColorPreferenceKey());
+ store.addBooleanKey(info.getTextPreferenceKey());
+ store.addBooleanKey(info.getOverviewRulerPreferenceKey());
+ }
+
+ // Appearance
+ store.addIntKey(CssUIPreferences.EDITOR_TAB_WIDTH);
+ store.addBooleanKey(CssUIPreferences.EDITOR_CURRENT_LINE);
+ store.addStringKey(CssUIPreferences.EDITOR_CURRENT_LINE_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_MATCHING_BRACKETS);
+ store.addStringKey(CssUIPreferences.EDITOR_MATCHING_BRACKETS_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_PRINT_MARGIN);
+ store.addStringKey(CssUIPreferences.EDITOR_PRINT_MARGIN_COLOR);
+ store.addIntKey(CssUIPreferences.EDITOR_PRINT_MARGIN_COLUMN);
+ store.addBooleanKey(CssUIPreferences.EDITOR_OVERVIEW_RULER);
+ store.addStringKey(CssUIPreferences.EDITOR_LINE_NUMBER_RULER_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_LINE_NUMBER_RULER);
+
+ // Syntax coloring
+ store.addStringKey(CssUIPreferences.EDITOR_FOREGROUND_COLOR);
+ store.addBooleanKey(
+ CssUIPreferences.EDITOR_FOREGROUND_DEFAULT_COLOR);
+ store.addStringKey(CssUIPreferences.EDITOR_BACKGROUND_COLOR);
+ store.addBooleanKey(
+ CssUIPreferences.EDITOR_BACKGROUND_DEFAULT_COLOR);
+ store.addStringKey(CssUIPreferences.EDITOR_COMMENT_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_COMMENT_BOLD);
+ store.addStringKey(CssUIPreferences.EDITOR_STRING_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_STRING_BOLD);
+ store.addStringKey(CssUIPreferences.EDITOR_PROPERTY_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_PROPERTY_BOLD);
+ store.addStringKey(CssUIPreferences.EDITOR_AT_KEYWORD_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_AT_KEYWORD_BOLD);
+ store.addStringKey(CssUIPreferences.EDITOR_PSEUDO_CLASS_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_PSEUDO_CLASS_BOLD);
+ store.addStringKey(CssUIPreferences.EDITOR_DEFAULT_COLOR);
+ store.addBooleanKey(CssUIPreferences.EDITOR_DEFAULT_BOLD);
+
+ // Content assist
+ store.addBooleanKey(CssUIPreferences.CONTENTASSIST_AUTOINSERT);
+ store.addBooleanKey(CssUIPreferences.CONTENTASSIST_ORDER_PROPOSALS);
+ store.addBooleanKey(CssUIPreferences.CONTENTASSIST_AUTOACTIVATION);
+ store.addIntKey(
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_DELAY);
+ store.addStringKey(
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_TRIGGERS);
+ store.addStringKey(
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_BACKGROUND);
+ store.addStringKey(
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_FOREGROUND);
+
+ // Typing
+ store.addBooleanKey(CssUIPreferences.EDITOR_SPACES_FOR_TABS);
+ store.addBooleanKey(CssUIPreferences.EDITOR_CLOSE_STRINGS);
+ store.addBooleanKey(
+ CssUIPreferences.EDITOR_CLOSE_BRACKETS_AND_PARENS);
+ store.addBooleanKey(CssUIPreferences.EDITOR_CLOSE_BRACES);
+
+ return store;
+ }
+
+ private Control createAppearancePage(Composite parent) {
+ appearanceBlock =
+ new CssEditorAppearanceConfigurationBlock(overlayStore);
+ return appearanceBlock.createControl(parent);
+ }
+
+ private Control createSyntaxPage(Composite parent) {
+ syntaxBlock = new CssEditorSyntaxConfigurationBlock(overlayStore);
+ return syntaxBlock.createControl(parent);
+ }
+
+ private Control createCodeAssistPage(Composite parent) {
+ contentAssistBlock =
+ new CssEditorContentAssistConfigurationBlock(overlayStore);
+ return contentAssistBlock.createControl(parent);
+ }
+
+ private Control createAnnotationsPage(Composite parent) {
+ annotationsBlock =
+ new CssEditorAnnotationsConfigurationBlock(overlayStore);
+ return annotationsBlock.createControl(parent);
+ }
+
+ private Control createTypingPage(Composite parent) {
+ typingBlock = new CssEditorTypingConfigurationBlock(overlayStore);
+ return typingBlock.createControl(parent);
+ }
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage." + key); //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorSyntaxConfigurationBlock.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+
+/**
+ *
+ */
+final class CssEditorSyntaxConfigurationBlock
+ extends AbstractConfigurationBlock {
+
+ // Instance Variables ------------------------------------------------------
+
+ private Button fBackgroundDefaultRadioButton;
+ private Button fBackgroundCustomRadioButton;
+ private ColorSelector fBackgroundColorSelector;
+ private List fColorList;
+ private final String[][] fColorListModel = new String[][] {
+ { getString("commentColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_COMMENT_COLOR,
+ CssUIPreferences.EDITOR_COMMENT_BOLD },
+ { getString("stringColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_STRING_COLOR,
+ CssUIPreferences.EDITOR_STRING_BOLD },
+ { getString("propertyNameColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_PROPERTY_COLOR,
+ CssUIPreferences.EDITOR_PROPERTY_BOLD },
+ { getString("atKeywordColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_AT_KEYWORD_COLOR,
+ CssUIPreferences.EDITOR_AT_KEYWORD_BOLD },
+ { getString("pseudoClassColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_COLOR,
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_BOLD },
+ { getString("defaultColor"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_DEFAULT_COLOR,
+ CssUIPreferences.EDITOR_DEFAULT_BOLD },
+ };
+ private ColorSelector fColorSelector;
+ private Button fBoldCheckbox;
+
+ // Constructors ------------------------------------------------------------
+
+ public CssEditorSyntaxConfigurationBlock(IPreferenceStore store) {
+ super(store);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout());
+
+ Group backgroundComposite = new Group(composite, SWT.SHADOW_ETCHED_IN);
+ backgroundComposite.setLayout(new RowLayout());
+ backgroundComposite.setText(getString("backgroundColor")); //$NON-NLS-1$
+ SelectionListener backgroundSelectionListener =
+ new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean custom =
+ fBackgroundCustomRadioButton.getSelection();
+ fBackgroundColorSelector.setEnabled(custom);
+ getPreferenceStore().setValue(
+ CssUIPreferences.EDITOR_BACKGROUND_DEFAULT_COLOR,
+ !custom);
+ }
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ };
+ fBackgroundDefaultRadioButton = new Button(backgroundComposite,
+ SWT.RADIO | SWT.LEFT);
+ fBackgroundDefaultRadioButton.setText(getString(
+ "backgroundColorSystemDefault")); //$NON-NLS-1$
+ fBackgroundDefaultRadioButton.addSelectionListener(
+ backgroundSelectionListener);
+ fBackgroundCustomRadioButton = new Button(backgroundComposite,
+ SWT.RADIO | SWT.LEFT);
+ fBackgroundCustomRadioButton.setText(getString(
+ "backgroundColorCustom")); //$NON-NLS-1$
+ fBackgroundCustomRadioButton.addSelectionListener(
+ backgroundSelectionListener);
+
+ fBackgroundColorSelector = new ColorSelector(backgroundComposite);
+ Button backgroundColorButton = fBackgroundColorSelector.getButton();
+ backgroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ PreferenceConverter.setValue(getPreferenceStore(),
+ CssUIPreferences.EDITOR_BACKGROUND_COLOR,
+ fBackgroundColorSelector.getColorValue());
+ }
+ });
+
+ Label label = new Label(composite, SWT.LEFT);
+ label.setText(getString("foregroundColor")); //$NON-NLS-1$
+ label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Composite editorComposite = new Composite(composite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ editorComposite.setLayout(layout);
+ GridData gridData = new GridData(GridData.FILL_BOTH);
+ editorComposite.setLayoutData(gridData);
+
+ fColorList = new List(editorComposite,
+ SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
+ gridData = new GridData(GridData.FILL_BOTH);
+ gridData.heightHint = convertHeightInCharsToPixels(composite, 5);
+ fColorList.setLayoutData(gridData);
+ fColorList.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ public void widgetSelected(SelectionEvent e) {
+ handleSyntaxColorListSelection();
+ }
+ });
+
+ Composite stylesComposite = new Composite(editorComposite, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 2;
+ stylesComposite.setLayout(layout);
+ stylesComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ label = new Label(stylesComposite, SWT.LEFT);
+ label.setText(getString("color")); //$NON-NLS-1$
+ gridData = new GridData();
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ label.setLayoutData(gridData);
+
+ fColorSelector = new ColorSelector(stylesComposite);
+ Button foregroundColorButton = fColorSelector.getButton();
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ foregroundColorButton.setLayoutData(gridData);
+ foregroundColorButton.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ PreferenceConverter.setValue(getPreferenceStore(), key,
+ fColorSelector.getColorValue());
+ }
+ });
+
+ fBoldCheckbox = new Button(stylesComposite, SWT.CHECK);
+ fBoldCheckbox.setText(getString("bold")); //$NON-NLS-1$
+ gridData = new GridData(GridData.FILL_HORIZONTAL);
+ gridData.horizontalAlignment = GridData.BEGINNING;
+ gridData.horizontalSpan = 2;
+ fBoldCheckbox.setLayoutData(gridData);
+ fBoldCheckbox.addSelectionListener(new SelectionListener() {
+ public void widgetDefaultSelected(SelectionEvent e) { }
+ public void widgetSelected(SelectionEvent e) {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][2];
+ getPreferenceStore().setValue(key,
+ fBoldCheckbox.getSelection());
+ }
+ });
+
+ Control previewer =
+ new SyntaxPreviewer(composite, getPreferenceStore()).getControl();
+ gridData = new GridData(GridData.FILL_BOTH);
+ gridData.widthHint = convertWidthInCharsToPixels(composite, 20);
+ gridData.heightHint = convertHeightInCharsToPixels(composite, 5);
+ previewer.setLayoutData(gridData);
+
+ initialize();
+
+ return composite;
+ }
+
+ /**
+ * @see AbstractConfigurationBlock#initializeFields()
+ */
+ public void initializeFields() {
+ super.initializeFields();
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(),
+ CssUIPreferences.EDITOR_BACKGROUND_COLOR);
+ fBackgroundColorSelector.setColorValue(rgb);
+ boolean defaultBackgroud = getPreferenceStore().getBoolean(
+ CssUIPreferences.EDITOR_BACKGROUND_DEFAULT_COLOR);
+ fBackgroundDefaultRadioButton.setSelection(defaultBackgroud);
+ fBackgroundCustomRadioButton.setSelection(!defaultBackgroud);
+ fBackgroundColorSelector.setEnabled(!defaultBackgroud);
+ }
+
+ // Event Handlers ----------------------------------------------------------
+
+ void handleSyntaxColorListSelection() {
+ int i = fColorList.getSelectionIndex();
+ String key = fColorListModel[i][1];
+ RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
+ fColorSelector.setColorValue(rgb);
+ key = fColorListModel[i][2];
+ fBoldCheckbox.setSelection(getPreferenceStore().getBoolean(key));
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage.syntax." + key); //$NON-NLS-1$
+ }
+
+ private void initialize() {
+ for (int i = 0; i < fColorListModel.length; i++) {
+ fColorList.add(fColorListModel[i][0]);
+ }
+ fColorList.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ if ((fColorList != null)
+ && !fColorList.isDisposed()) {
+ fColorList.select(0);
+ handleSyntaxColorListSelection();
+ }
+ }
+ });
+ initializeFields();
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssEditorTypingConfigurationBlock.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ *
+ */
+final class CssEditorTypingConfigurationBlock
+ extends AbstractConfigurationBlock {
+
+ // Constructors ------------------------------------------------------------
+
+ public CssEditorTypingConfigurationBlock(IPreferenceStore store) {
+ super(store);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public Control createControl(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ composite.setLayout(layout);
+
+ addBooleanField(composite,
+ getString("insertSpaceForTabs"), //$NON-NLS-1$
+ CssUIPreferences.EDITOR_SPACES_FOR_TABS, 1);
+ initialize();
+
+ return composite;
+ }
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssEditorPreferencePage.typing." + key); //$NON-NLS-1$
+ }
+
+ private void initialize() {
+ initializeFields();
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssPreferencePage.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.internal.CssCorePreferences;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileDescriptor;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+/**
+ *
+ */
+public class CssPreferencePage extends PreferencePage
+ implements IWorkbenchPreferencePage {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The CSS core preferences.
+ */
+ private Preferences preferences;
+
+ /**
+ * The radio buttons used to select the default profile.
+ */
+ private Button[] profileButtons;
+
+ /**
+ * The ID of the currently selected CSS profile.
+ */
+ private String selectedProfile;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CssPreferencePage() {
+ super(getString("description")); //$NON-NLS-1$
+ preferences = CssCore.getDefault().getPluginPreferences();
+ }
+
+ // PreferencePage Implementation -------------------------------------------
+
+ /*
+ * @see PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ createProfileRadioGroup(composite);
+
+ return composite;
+ }
+
+ /*
+ * @see PreferencePage#performDefaults()
+ */
+ protected void performDefaults() {
+ preferences.setToDefault(CssCorePreferences.PROFILE);
+ selectedProfile = preferences.getString(CssCorePreferences.PROFILE);
+ if (selectedProfile != null) {
+ for (int i = 0; i < profileButtons.length; i++) {
+ Button button = profileButtons[i];
+ if (((String) button.getData()).equals(selectedProfile)) {
+ button.setSelection(true);
+ } else {
+ button.setSelection(false);
+ }
+ }
+ }
+ }
+
+ /*
+ * @see PreferencePage#performOk()
+ */
+ public boolean performOk() {
+ preferences.setValue(CssCorePreferences.PROFILE, selectedProfile);
+ return super.performOk();
+ }
+
+ // IWorkbenchPreferencePage Implementation ---------------------------------
+
+ /**
+ * @see IWorkbenchPreferencePage#init(IWorkbench)
+ */
+ public void init(IWorkbench workbench) {
+ selectedProfile = preferences.getString(CssCorePreferences.PROFILE);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Creates the radio button group for selecting the default CSS profile.
+ *
+ * @param composite the composite to add the group to
+ */
+ private void createProfileRadioGroup(Composite composite) {
+ Group profileGroup = new Group(composite, SWT.SHADOW_ETCHED_IN);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ profileGroup.setLayout(layout);
+ profileGroup.setText(getString("profile")); //$NON-NLS-1$
+
+ IProfileDescriptor[] profiles = getProfileDescriptors();
+ profileButtons = new Button[profiles.length];
+ for (int i = 0; i < profiles.length; i++) {
+ Button button = new Button(profileGroup, SWT.RADIO | SWT.LEFT);
+ button.setText(profiles[i].getName());
+ button.setData(profiles[i].getId());
+ if (profiles[i].getId().equals(selectedProfile)) {
+ button.setSelection(true);
+ }
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ selectedProfile = (String) event.widget.getData();
+ }
+ });
+ profileButtons[i] = button;
+ }
+ }
+
+ /**
+ * Returns all available profile descriptors, alphabetically sorted by
+ * display name.
+ *
+ * @return the profile descriptors
+ */
+ private IProfileDescriptor[] getProfileDescriptors() {
+ IProfileManager mgr = CssCore.getDefault().getProfileManager();
+ IProfileDescriptor[] profiles = mgr.getProfileDescriptors();
+ Arrays.sort(profiles, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((IProfileDescriptor) o1).getName().compareTo(
+ ((IProfileDescriptor) o2).getName());
+ }
+ });
+ return profiles;
+ }
+
+ private static String getString(String key) {
+ return CssUIMessages.getString(
+ "CssPreferencePage." + key); //$NON-NLS-1$
+ }
+
+}
--- /dev/null
+/*
+ * 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: OverlayPreferenceStore.java,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+public class OverlayPreferenceStore implements IPreferenceStore {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Descriptor used to denote data types.
+ */
+ public static final class Type {
+ protected Type() {
+ }
+ }
+
+ /**
+ * Data structure for the overlay key.
+ */
+ public static class OverlayKey {
+
+ private Type fType;
+ private String fKey;
+
+ public OverlayKey(Type type, String key) {
+ this.fType = type;
+ this.fKey = key;
+ }
+ }
+
+ /**
+ * @see IPropertyChangeListener
+ */
+ private class PropertyListener implements IPropertyChangeListener {
+
+ /**
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ OverlayKey key = findOverlayKey(event.getProperty());
+ if (key != null) {
+ propagateProperty(fParent, key, fStore);
+ }
+ }
+ }
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Boolean property type.
+ */
+ public static final Type BOOLEAN = new Type();
+
+ /**
+ * Double property type.
+ */
+ public static final Type DOUBLE = new Type();
+
+ /**
+ * Floating point property type.
+ */
+ public static final Type FLOAT = new Type();
+
+ /**
+ * Integer property type.
+ */
+ public static final Type INT = new Type();
+
+ /**
+ * Long integer property type.
+ */
+ public static final Type LONG = new Type();
+
+ /**
+ * String property type.
+ */
+ public static final Type STRING = new Type();
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The parent preference store.
+ */
+ private IPreferenceStore fParent;
+
+ /**
+ * The underlying preference store.
+ */
+ private IPreferenceStore fStore;
+
+ /**
+ * The keys of this store.
+ */
+ private List fOverlayKeys = new ArrayList();
+
+ /**
+ * The property listener.
+ */
+ private PropertyListener fPropertyListener;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Creates and returns a new overlay preference store.
+ *
+ * @param parent the parent preference store
+ */
+ public OverlayPreferenceStore(IPreferenceStore parent) {
+ this.fParent = parent;
+ fStore = new PreferenceStore();
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ public void addKey(Type type, String key) {
+ this.fOverlayKeys.add(new OverlayKey(type, key));
+ }
+ public void addBooleanKey(String key) {
+ addKey(BOOLEAN, key);
+ }
+ public void addDoubleKey(String key) {
+ addKey(DOUBLE, key);
+ }
+ public void addFloatKey(String key) {
+ addKey(FLOAT, key);
+ }
+ public void addIntKey(String key) {
+ addKey(INT, key);
+ }
+ public void addLongKey(String key) {
+ addKey(LONG, key);
+ }
+ public void addStringKey(String key) {
+ addKey(STRING, key);
+ }
+
+ /**
+ * Propagates all overlay keys from this store to the parent store.
+ */
+ public void propagate() {
+ for (Iterator i = fOverlayKeys.iterator(); i.hasNext(); ) {
+ propagateProperty(fStore, (OverlayKey) i.next(), fParent);
+ }
+ }
+
+ /**
+ * Loads the values from the parent into this store.
+ */
+ public void load() {
+ for (Iterator i = fOverlayKeys.iterator(); i.hasNext(); ) {
+ loadProperty(fParent, (OverlayKey) i.next(), fStore, true);
+ }
+ }
+
+ /**
+ * Loads the default values.
+ */
+ public void loadDefaults() {
+ for (Iterator i = fOverlayKeys.iterator(); i.hasNext(); ) {
+ setToDefault(((OverlayKey) i.next()).fKey);
+ }
+ }
+
+ /**
+ * Starts to listen for changes.
+ */
+ public void startListening() {
+ if (fPropertyListener == null) {
+ fPropertyListener = new PropertyListener();
+ fParent.addPropertyChangeListener(fPropertyListener);
+ }
+ }
+
+ /**
+ * Stops to listen for changes.
+ */
+ public void stopListening() {
+ if (fPropertyListener != null) {
+ fParent.removePropertyChangeListener(fPropertyListener);
+ fPropertyListener = null;
+ }
+ }
+
+ // IPreferenceStore Implementation -----------------------------------------
+
+ /**
+ * @see IPreferenceStore#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
+ */
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ fStore.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * @see IPreferenceStore#removePropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)
+ */
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ fStore.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * @see IPreferenceStore#firePropertyChangeEvent(java.lang.String, java.lang.Object, java.lang.Object)
+ */
+ public void firePropertyChangeEvent(String name, Object oldValue,
+ Object newValue) {
+ fStore.firePropertyChangeEvent(name, oldValue, newValue);
+ }
+
+ /**
+ * @see IPreferenceStore#contains(java.lang.String)
+ */
+ public boolean contains(String name) {
+ return fStore.contains(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getBoolean(java.lang.String)
+ */
+ public boolean getBoolean(String name) {
+ return fStore.getBoolean(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultBoolean(java.lang.String)
+ */
+ public boolean getDefaultBoolean(String name) {
+ return fStore.getDefaultBoolean(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultDouble(java.lang.String)
+ */
+ public double getDefaultDouble(String name) {
+ return fStore.getDefaultDouble(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultFloat(String)
+ */
+ public float getDefaultFloat(String name) {
+ return fStore.getDefaultFloat(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultInt(String)
+ */
+ public int getDefaultInt(String name) {
+ return fStore.getDefaultInt(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultLong(String)
+ */
+ public long getDefaultLong(String name) {
+ return fStore.getDefaultLong(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDefaultString(String)
+ */
+ public String getDefaultString(String name) {
+ return fStore.getDefaultString(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getDouble(String)
+ */
+ public double getDouble(String name) {
+ return fStore.getDouble(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getFloat(String)
+ */
+ public float getFloat(String name) {
+ return fStore.getFloat(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getInt(String)
+ */
+ public int getInt(String name) {
+ return fStore.getInt(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getLong(String)
+ */
+ public long getLong(String name) {
+ return fStore.getLong(name);
+ }
+
+ /**
+ * @see IPreferenceStore#getString(String)
+ */
+ public String getString(String name) {
+ return fStore.getString(name);
+ }
+
+ /**
+ * @see IPreferenceStore#isDefault(String)
+ */
+ public boolean isDefault(String name) {
+ return fStore.isDefault(name);
+ }
+
+ /**
+ * @see IPreferenceStore#needsSaving()
+ */
+ public boolean needsSaving() {
+ return fStore.needsSaving();
+ }
+
+ /**
+ * @see IPreferenceStore#putValue(String, String)
+ */
+ public void putValue(String name, String value) {
+ if (covers(name)) {
+ fStore.putValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, double)
+ */
+ public void setDefault(String name, double value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, float)
+ */
+ public void setDefault(String name, float value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, int)
+ */
+ public void setDefault(String name, int value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, long)
+ */
+ public void setDefault(String name, long value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, String)
+ */
+ public void setDefault(String name, String value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setDefault(String, boolean)
+ */
+ public void setDefault(String name, boolean value) {
+ if (covers(name)) {
+ fStore.setDefault(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setToDefault(String)
+ */
+ public void setToDefault(String name) {
+ fStore.setToDefault(name);
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, double)
+ */
+ public void setValue(String name, double value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, float)
+ */
+ public void setValue(String name, float value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, int)
+ */
+ public void setValue(String name, int value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, long)
+ */
+ public void setValue(String name, long value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, String)
+ */
+ public void setValue(String name, String value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ /**
+ * @see IPreferenceStore#setValue(String, boolean)
+ */
+ public void setValue(String name, boolean value) {
+ if (covers(name)) {
+ fStore.setValue(name, value);
+ }
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ /**
+ * Tries to find and return the overlay key for the given preference key
+ * string.
+ *
+ * @param key the preference key string
+ * @return the overlay key or <code>null</code> if none can be found
+ */
+ protected final OverlayKey findOverlayKey(String key) {
+ for (Iterator i = fOverlayKeys.iterator(); i.hasNext(); ) {
+ OverlayKey k = (OverlayKey) i.next();
+ if (k.fKey.equals(key)) {
+ return k;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Propagates the given overlay key from the orgin to the target preference
+ * store.
+ *
+ * @param origin the source preference store
+ * @param key the overlay key
+ * @param target the preference store to which the key is propagated
+ */
+ protected final void propagateProperty(IPreferenceStore origin,
+ OverlayKey key, IPreferenceStore target) {
+ if (origin.isDefault(key.fKey)) {
+ if (!target.isDefault(key.fKey)) {
+ target.setToDefault(key.fKey);
+ }
+ return;
+ }
+ Type d = key.fType;
+ if (BOOLEAN == d) {
+ boolean originValue = origin.getBoolean(key.fKey);
+ boolean targetValue = target.getBoolean(key.fKey);
+ if (targetValue != originValue) {
+ target.setValue(key.fKey, originValue);
+ }
+ } else if (DOUBLE == d) {
+ double originValue = origin.getDouble(key.fKey);
+ double targetValue = target.getDouble(key.fKey);
+ if (targetValue != originValue) {
+ target.setValue(key.fKey, originValue);
+ }
+ } else if (FLOAT == d) {
+ float originValue = origin.getFloat(key.fKey);
+ float targetValue = target.getFloat(key.fKey);
+ if (targetValue != originValue) {
+ target.setValue(key.fKey, originValue);
+ }
+ } else if (INT == d) {
+ int originValue = origin.getInt(key.fKey);
+ int targetValue = target.getInt(key.fKey);
+ if (targetValue != originValue) {
+ target.setValue(key.fKey, originValue);
+ }
+ } else if (LONG == d) {
+ long originValue = origin.getLong(key.fKey);
+ long targetValue = target.getLong(key.fKey);
+ if (targetValue != originValue) {
+ target.setValue(key.fKey, originValue);
+ }
+ } else if (STRING == d) {
+ String originValue = origin.getString(key.fKey);
+ String targetValue = target.getString(key.fKey);
+ if ((targetValue != null) && (originValue != null)
+ && !targetValue.equals(originValue)) {
+ target.setValue(key.fKey, originValue);
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Tells whether the given preference key string is
+ * covered by this overlay store.
+ *
+ * @param key the preference key string
+ * @return <code>true</code> if this overlay store covers the given key
+ */
+ private boolean covers(String key) {
+ return (findOverlayKey(key) != null);
+ }
+
+ /**
+ * Loads the given key from the orgin into the target.
+ *
+ * @param orgin the source preference store
+ * @param key the overlay key
+ * @param target the preference store to which the key is propagated
+ * @param forceInitialization if <code>true</code> the value in the target
+ * gets initialized before loading
+ */
+ private void loadProperty(IPreferenceStore orgin, OverlayKey key,
+ IPreferenceStore target, boolean forceInitialization) {
+ Type d = key.fType;
+ if (BOOLEAN == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, true);
+ }
+ target.setValue(key.fKey, orgin.getBoolean(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultBoolean(key.fKey));
+ } else if (DOUBLE == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, 1.0D);
+ }
+ target.setValue(key.fKey, orgin.getDouble(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultDouble(key.fKey));
+ } else if (FLOAT == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, 1.0F);
+ }
+ target.setValue(key.fKey, orgin.getFloat(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultFloat(key.fKey));
+ } else if (INT == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, 1);
+ }
+ target.setValue(key.fKey, orgin.getInt(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultInt(key.fKey));
+ } else if (LONG == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, 1L);
+ }
+ target.setValue(key.fKey, orgin.getLong(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultLong(key.fKey));
+ } else if (STRING == d) {
+ if (forceInitialization) {
+ target.setValue(key.fKey, "1"); //$NON-NLS-1$
+ }
+ target.setValue(key.fKey, orgin.getString(key.fKey));
+ target.setDefault(key.fKey, orgin.getDefaultString(key.fKey));
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: SyntaxPreviewer.java,v 1.1 2004-09-02 18:11:50 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.preferences;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssSourceViewerConfiguration;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A previewer for the syntax styling preferences, used to give real time
+ * feedback on changes to the preferences.
+ */
+public class SyntaxPreviewer extends SourceViewer {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Alias for the preference constant <code>EDITOR_BACKGROUND_COLOR</code>.
+ */
+ private static final String BACKGROUND_COLOR =
+ CssUIPreferences.EDITOR_BACKGROUND_COLOR;
+
+ /**
+ * Alias for the preference constant
+ * <code>EDITOR_BACKGROUND_DEFAULT_COLOR</code>.
+ */
+ private static final String BACKGROUND_DEFAULT_COLOR =
+ CssUIPreferences.EDITOR_BACKGROUND_DEFAULT_COLOR;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The preference store used for loading the style settings.
+ */
+ private IPreferenceStore fStore;
+
+ /**
+ * Listener that handles changes to the preference store.
+ */
+ private IPropertyChangeListener fPropertyChangeListener =
+ new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ if (affectsPresentation(event)) {
+ updateColors();
+ }
+ invalidateTextPresentation();
+ }
+ };
+
+ private CssTextTools fTextTools;
+
+ /**
+ * The cached background color of the previewer.
+ */
+ private Color fBackgroundColor;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param parent The parent composite
+ * @param store The preference store to use for loading the style settings
+ */
+ public SyntaxPreviewer(Composite parent, IPreferenceStore store) {
+ super(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+ this.fStore = store;
+ this.fTextTools = new CssTextTools(this.fStore);
+
+ configure(new CssSourceViewerConfiguration(
+ this.fTextTools, this.fStore));
+ setEditable(false);
+ getTextWidget().setFont(JFaceResources.getTextFont());
+
+ IDocument document = new Document(
+ loadTextFromResource("preview.css")); //$NON-NLS-1$
+ this.fTextTools.setupDocument(document);
+ setDocument(document);
+
+ this.fStore.addPropertyChangeListener(this.fPropertyChangeListener);
+ }
+
+ // SourceViewer Implementation ---------------------------------------------
+
+ /**
+ * @see org.eclipse.jface.text.TextViewer#handleDispose()
+ */
+ protected void handleDispose() {
+ if (this.fStore != null) {
+ if (this.fPropertyChangeListener != null) {
+ this.fStore.removePropertyChangeListener(
+ this.fPropertyChangeListener);
+ this.fPropertyChangeListener = null;
+ }
+ this.fStore = null;
+ }
+ if (this.fTextTools != null) {
+ this.fTextTools.dispose();
+ this.fTextTools = null;
+ }
+ if ((this.fBackgroundColor != null)
+ && !this.fBackgroundColor.isDisposed()) {
+ this.fBackgroundColor.dispose();
+ }
+ super.handleDispose();
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private boolean affectsPresentation(PropertyChangeEvent event) {
+ String p = event.getProperty();
+ if (BACKGROUND_COLOR.equals(p)
+ || BACKGROUND_DEFAULT_COLOR.equals(p)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference
+ * store.
+ *
+ * @param key The preference key under which the color is stored
+ * @param display The display
+ * @return The color found, or <code>null</code> if no corresponding
+ * preference is available
+ */
+ private Color createColor(String key, Display display) {
+ Color color = null;
+ if (this.fStore.contains(key)) {
+ RGB rgb = null;
+ if (this.fStore.isDefault(key)) {
+ rgb = PreferenceConverter.getDefaultColor(this.fStore, key);
+ } else {
+ rgb = PreferenceConverter.getColor(this.fStore, key);
+ }
+ if (rgb != null) {
+ color = new Color(display, rgb);
+ }
+ }
+ return color;
+ }
+
+ /**
+ * Loads and returns the text stored in the specified resource.
+ *
+ * @param name The resource name
+ * @return The text loaded from the resource, or an empty string if there
+ * was an error reading the resource contents
+ */
+ private String loadTextFromResource(String name) {
+ String line;
+ String separator = System.getProperty("line.separator"); //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer(512);
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(
+ getClass().getResourceAsStream(name)));
+ while ((line = reader.readLine()) != null) {
+ buffer.append(line);
+ buffer.append(separator);
+ }
+ } catch (IOException io) {
+ CssUI.log(io);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Updates the previewer colors.
+ */
+ private void updateColors() {
+ if (this.fStore != null) {
+ StyledText styledText = getTextWidget();
+ Color color = null;
+ if (!this.fStore.getBoolean(BACKGROUND_DEFAULT_COLOR)) {
+ color = createColor(BACKGROUND_COLOR,
+ styledText.getDisplay());
+ }
+ styledText.setBackground(color);
+ if (this.fBackgroundColor != null) {
+ this.fBackgroundColor.dispose();
+ }
+ this.fBackgroundColor = color;
+ }
+ }
+
+}
--- /dev/null
+@import url("custom.css");\r
+a:link, a:visited {\r
+ /* Make links green, not underlined */\r
+ color: #0F0; text-decoration: none\r
+}\r
--- /dev/null
+/*
+ * 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: CssPropertiesAdapterFactory.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.properties;
+
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ui.views.properties.IPropertySource;
+
+/**
+ * Factory for adapting model elements to property sources.
+ */
+public class CssPropertiesAdapterFactory implements IAdapterFactory {
+
+ // Static Methods ----------------------------------------------------------
+
+ /**
+ * Creates and registers this adapter factory with the given manager.
+ *
+ * @param manager the adapter manager to register with
+ */
+ public static void register(IAdapterManager manager) {
+ CssPropertiesAdapterFactory factory = new CssPropertiesAdapterFactory();
+ manager.registerAdapters(factory, IRule.class);
+ }
+
+ // IAdapterFactory Implementation ------------------------------------------
+
+ /*
+ * @see IAdapterFactory#getAdapter(Object, Class)
+ */
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ if (adapterType == IPropertySource.class) {
+ if (adaptableObject instanceof IRule) {
+ return new CssRulePropertySource((IRule) adaptableObject);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see IAdapterFactory#getAdapterList()
+ */
+ public Class[] getAdapterList() {
+ return new Class[] { IPropertySource.class };
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssPropertyPage.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.properties;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.internal.CssCorePreferences;
+import net.sourceforge.phpeclipse.css.core.internal.profiles.ProfileManager;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileDescriptor;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIMessages;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Property page for CSS projects and files.
+ */
+public class CssPropertyPage extends PropertyPage {
+
+ // Instance Variables ------------------------------------------------------
+
+ private IProfileManager profileManager;
+
+ private boolean useCustomSettings;
+ private Group profileGroup;
+ private Button[] profileButtons;
+ private String selectedProfile;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public CssPropertyPage() {
+ profileManager = CssCore.getDefault().getProfileManager();
+ }
+
+ // PropertyPage Implementation ---------------------------------------------
+
+ /**
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(Composite)
+ */
+ protected Control createContents(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ composite.setLayout(layout);
+
+ Object element = getElement();
+ if (element instanceof IResource) {
+ IResource resource = (IResource) element;
+ try {
+ selectedProfile = resource.getPersistentProperty(
+ ProfileManager.PROFILE_PROPERTY);
+ } catch (CoreException e) {
+ // ignore
+ }
+ }
+ useCustomSettings = (selectedProfile != null);
+ if (selectedProfile == null) {
+ selectedProfile = getInheritedProfile();
+ }
+
+ Button useInheritedSettingsButton =
+ new Button(composite, SWT.RADIO | SWT.LEFT);
+ if (element instanceof IProject) {
+ useInheritedSettingsButton.setText(
+ getString("useWorkspaceSettings")); //$NON-NLS-1$
+ } else if (element instanceof IResource) {
+ useInheritedSettingsButton.setText(
+ getString("useProjectSettings")); //$NON-NLS-1$
+ }
+ useInheritedSettingsButton.setSelection(!useCustomSettings);
+ Button useCustomSettingsButton =
+ new Button(composite, SWT.RADIO | SWT.LEFT);
+ useCustomSettingsButton.setText(
+ getString("useCustomSettings")); //$NON-NLS-1$
+ useCustomSettingsButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ useCustomSettings =
+ ((Button) event.widget).getSelection();
+ updateProfileGroup();
+ }
+ });
+ useCustomSettingsButton.setSelection(useCustomSettings);
+
+ profileGroup = new Group(composite, SWT.SHADOW_ETCHED_IN);
+ layout = new GridLayout();
+ layout.numColumns = 1;
+ profileGroup.setLayout(layout);
+ profileGroup.setText(getString("profile")); //$NON-NLS-1$
+
+ IProfileManager mgr = CssCore.getDefault().getProfileManager();
+ IProfileDescriptor[] profiles = mgr.getProfileDescriptors();
+ Arrays.sort(profiles, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((IProfileDescriptor) o1).getName().compareTo(
+ ((IProfileDescriptor) o2).getName());
+ }
+ });
+
+ profileButtons = new Button[profiles.length];
+ for (int i = 0; i < profiles.length; i++) {
+ Button button = new Button(profileGroup, SWT.RADIO | SWT.LEFT);
+ button.setText(profiles[i].getName());
+ button.setData(profiles[i].getId());
+ if (profiles[i].getId().equals(selectedProfile)) {
+ button.setSelection(true);
+ }
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ selectedProfile = (String) event.widget.getData();
+ }
+ });
+ profileButtons[i] = button;
+ }
+ updateProfileGroup();
+
+ return composite;
+ }
+
+ /**
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ public boolean performOk() {
+ Object element = getElement();
+ if (element instanceof IResource) {
+ IResource resource = (IResource) element;
+ if (useCustomSettings) {
+ profileManager.setProfile(resource, selectedProfile);
+ } else {
+ profileManager.setProfile(resource, null);
+ }
+ }
+ return true;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private String getInheritedProfile() {
+ Object element = getElement();
+ String retVal = null;
+ if (element instanceof IResource) {
+ IProject project = ((IResource) element).getProject();
+ try {
+ retVal = project.getPersistentProperty(
+ ProfileManager.PROFILE_PROPERTY);
+ } catch (CoreException e) {
+ // ignore
+ }
+ }
+ if (retVal == null) {
+ Preferences preferences =
+ CssCore.getDefault().getPluginPreferences();
+ retVal = preferences.getString(CssCorePreferences.PROFILE);
+ }
+ return retVal;
+ }
+
+ private String getString(String key) {
+ return CssUIMessages.getString("CssPropertyPage." + key); //$NON-NLS-1$
+ }
+
+ private void updateProfileGroup() {
+ profileGroup.setEnabled(useCustomSettings);
+ for (int i = 0; i < profileButtons.length; i++) {
+ profileButtons[i].setEnabled(useCustomSettings);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssRulePropertySource.java,v 1.1 2004-09-02 18:11:49 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IPropertyInfo;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.views.properties.IPropertyDescriptor;
+import org.eclipse.ui.views.properties.IPropertySource;
+import org.eclipse.ui.views.properties.PropertyDescriptor;
+
+/**
+ *
+ */
+public class CssRulePropertySource implements IPropertySource {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Extended label provider that decorates the property values with specific
+ * icons when a priority is set.
+ */
+ private static class DeclarationLabelProvider extends LabelProvider {
+
+ /**
+ * The CSS declaration for which a label should be provided.
+ */
+ private IDeclaration declaration;
+
+ /**
+ * Constructor.
+ *
+ * @param declaration the declaration for which to provide a label
+ */
+ public DeclarationLabelProvider(IDeclaration declaration) {
+ this.declaration = declaration;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ILabelProvider#getImage(Object)
+ */
+ public Image getImage(Object element) {
+ if (this.declaration.getPriority() != null) {
+ CssUI plugin = CssUI.getDefault();
+ return plugin.getImageRegistry().get(
+ CssUI.ICON_IMPORTANT);
+ }
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.viewers.ILabelProvider#getText(Object)
+ */
+ public String getText(Object element) {
+ return this.declaration.getValue().getSource();
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The CSS rule for which properties should be provided.
+ */
+ private IRule rule;
+
+ /**
+ * Cached list of property descriptors (<code>IPropertyDescriptor</code>).
+ */
+ private List descriptors;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param styleRule the style rule for which to provide properties
+ */
+ public CssRulePropertySource(IRule styleRule) {
+ this.rule = styleRule;
+ }
+
+ // IPropertySource Implementation ------------------------------------------
+
+ /**
+ * @see IPropertySource#getEditableValue()
+ */
+ public Object getEditableValue() {
+ return null;
+ }
+
+ /**
+ * @see IPropertySource#getPropertyDescriptors()
+ */
+ public IPropertyDescriptor[] getPropertyDescriptors() {
+ if (this.descriptors == null) {
+ IProfileManager mgr = CssCore.getDefault().getProfileManager();
+ IProfile profile = mgr.getProfile(null);
+ this.descriptors = new ArrayList();
+ for (int i = 0; i < this.rule.getDeclarations().length; i++) {
+ IDeclaration declaration = this.rule.getDeclarations()[i];
+ String property = declaration.getProperty().getSource();
+ PropertyDescriptor descriptor = new PropertyDescriptor(
+ new Integer(i), property);
+ descriptor.setLabelProvider(
+ new DeclarationLabelProvider(declaration));
+ IPropertyInfo info = profile.getPropertyInfo(property);
+ if (info != null) {
+ descriptor.setCategory(info.getCategory());
+ }
+ this.descriptors.add(descriptor);
+ }
+ }
+ return (IPropertyDescriptor[]) this.descriptors.toArray(
+ new IPropertyDescriptor[this.descriptors.size()]);
+ }
+
+ /**
+ * @see IPropertySource#getPropertyValue(Object)
+ */
+ public Object getPropertyValue(Object id) {
+ int i = ((Integer) id).intValue();
+ ISourceReference propertyValue =
+ this.rule.getDeclarations()[i].getValue();
+ return propertyValue.getSource();
+ }
+
+ /**
+ * @see IPropertySource#isPropertySet(Object)
+ */
+ public boolean isPropertySet(Object id) {
+ // read-only property
+ return false;
+ }
+
+ /**
+ * @see IPropertySource#resetPropertyValue(Object)
+ */
+ public void resetPropertyValue(Object id) {
+ // read-only property
+ }
+
+ /**
+ * @see IPropertySource#setPropertyValue(Object, Object)
+ */
+ public void setPropertyValue(Object id, Object value) {
+ // read-only property
+ }
+
+}
--- /dev/null
+/*
+ * 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: AbstractCssScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.BufferedRuleBasedScanner;
+import org.eclipse.jface.text.rules.IToken;
+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;
+
+/**
+ *
+ */
+public abstract class AbstractCssScanner extends BufferedRuleBasedScanner {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Internal data structure for associating the various style preferences
+ * of tokens with each other.
+ */
+ private static final class StyleKeys {
+
+ /**
+ * The preference key that determines the foreground color of the token.
+ */
+ private String colorKey;
+
+ /**
+ * The preference key that indicates whether the token is to be
+ * displayed in bold face.
+ */
+ private String boldKey;
+
+ /**
+ * Constructor.
+ *
+ * @param colorKey The color preference key
+ * @param boldKey The preference key determining whether the
+ * corresponding tokens should be rendered bold
+ */
+ private StyleKeys(String colorKey, String boldKey) {
+ this.colorKey = colorKey;
+ this.boldKey = boldKey;
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object o) {
+ if (!(o instanceof StyleKeys)) {
+ return false;
+ }
+ StyleKeys styleKeys = (StyleKeys) o;
+ if (((colorKey != null) && !colorKey.equals(styleKeys.colorKey))
+ || (colorKey != styleKeys.colorKey)) {
+ return false;
+ }
+ if (((boldKey != null) && !boldKey.equals(styleKeys.boldKey))
+ || (boldKey != styleKeys.boldKey)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ int retVal = 17;
+ retVal = (retVal * 37) +
+ (colorKey != null ? colorKey.hashCode() : 0);
+ retVal = (retVal * 37) +
+ (boldKey != null ? boldKey.hashCode() : 0);
+ return retVal;
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The preference store associated with the scanner.
+ */
+ private IPreferenceStore store;
+
+ /**
+ * Listener for preference store changes related to tokens.
+ */
+ private IPropertyChangeListener propertyChangeListener =
+ new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ StyleKeys styleKeys = getStyleKeysContaining(property);
+ if (styleKeys != null) {
+ if (styleKeys.colorKey.equals(property)) {
+ Token token = (Token) tokens.get(styleKeys);
+ handleColorChange(token, event);
+ } else if (styleKeys.boldKey.equals(property)) {
+ Token token = (Token) tokens.get(styleKeys);
+ handleBoldChange(token, event);
+ }
+ }
+ }
+ };
+
+ /**
+ * The shared text colors.
+ */
+ private IColorManager colorManager;
+
+ /**
+ * A map containing the defined tokens keyed by the color preference key.
+ */
+ private Map tokens = new HashMap(4);
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param store the preference store
+ * @param manager the color manager
+ */
+ public AbstractCssScanner(IPreferenceStore store, IColorManager manager) {
+ store.addPropertyChangeListener(propertyChangeListener);
+ this.store = store;
+ this.colorManager = manager;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Adapts the tokens managed by this scanner to changes made to the
+ * corresponding preferences.
+ *
+ * @param event the change event fired by the preference store
+ */
+ public void adaptToPreferenceChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ StyleKeys styleKeys = getStyleKeysContaining(property);
+ if (styleKeys != null) {
+ if (styleKeys.colorKey.equals(property)) {
+ Token token = (Token) tokens.get(styleKeys);
+ handleColorChange(token, event);
+ } else if (styleKeys.boldKey.equals(property)) {
+ Token token = (Token) tokens.get(styleKeys);
+ handleBoldChange(token, event);
+ }
+ }
+ }
+
+ /**
+ * Called to determine whether the change of a specific preference affects
+ * the presentation of the tokens managed by the scanner.
+ *
+ * @param event the preference change event
+ * @return <code>true</code> if the change affects the presentation of one
+ * of the tokens managed by the scanner, <code>false</code>
+ * otherwise
+ */
+ public boolean affectsPresentation(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ return (getStyleKeysContaining(property) != null);
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ /**
+ * Creates a token with the specified color and style as associated text
+ * attribute. The color and style are specified as preference keys.
+ *
+ * @param colorKey The preference key of the color
+ * @param boldKey The preference key of the boolean value that determines
+ * whether the text should be rendered bold, or <code>null</code>
+ * @return the created token
+ */
+ protected final IToken createToken(String colorKey, String boldKey) {
+ RGB rgb = PreferenceConverter.getColor(store, colorKey);
+ colorManager.unbindColor(colorKey);
+ colorManager.bindColor(colorKey, rgb);
+ int style = SWT.NORMAL;
+ if ((boldKey != null) && store.getBoolean(boldKey)) {
+ style |= SWT.BOLD;
+ }
+ IToken token = new Token(new TextAttribute(
+ colorManager.getColor(colorKey), null, style));
+ StyleKeys styleKeys = new StyleKeys(colorKey, boldKey);
+ tokens.put(styleKeys, token);
+ return token;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private StyleKeys getStyleKeysContaining(String key) {
+ for (Iterator i = tokens.keySet().iterator(); i.hasNext(); ) {
+ StyleKeys styleKeys = (StyleKeys) i.next();
+ if (styleKeys.colorKey.equals(key)
+ || styleKeys.boldKey.equals(key)) {
+ return styleKeys;
+ }
+ }
+ return null;
+ }
+
+ private void handleColorChange(Token token, PropertyChangeEvent event) {
+ RGB rgb = null;
+ Object value = event.getNewValue();
+ if (value instanceof RGB) {
+ rgb = (RGB) value;
+ } else if (value instanceof String) {
+ rgb = StringConverter.asRGB((String) value);
+ }
+ if (rgb != null) {
+ String key = event.getProperty();
+ colorManager.unbindColor(key);
+ colorManager.bindColor(key, rgb);
+ Object data = token.getData();
+ if (data instanceof TextAttribute) {
+ TextAttribute oldAttr = (TextAttribute) data;
+ token.setData(new TextAttribute(colorManager.getColor(key),
+ oldAttr.getBackground(), oldAttr.getStyle()));
+ }
+ }
+ }
+
+ private void handleBoldChange(Token token, PropertyChangeEvent event) {
+ boolean bold = false;
+ Object value = event.getNewValue();
+ if (value instanceof Boolean) {
+ bold = ((Boolean) value).booleanValue();
+ } else if (value instanceof String) {
+ StringConverter.asBoolean((String) value);
+ }
+ Object data = token.getData();
+ if (data instanceof TextAttribute) {
+ TextAttribute oldAttr = (TextAttribute) data;
+ boolean wasBold = ((oldAttr.getStyle() & SWT.BOLD) != 0);
+ if (wasBold != bold) {
+ int newStyle = bold ? oldAttr.getStyle() | SWT.BOLD
+ : oldAttr.getStyle() ^ SWT.BOLD;
+ token.setData(new TextAttribute(oldAttr.getForeground(),
+ oldAttr.getBackground(), newStyle));
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: AnnotationAdapter.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.source.Annotation;
+
+/**
+ * Adapts a temporary or persistent annotation to a reconcile result.
+ */
+public abstract class AnnotationAdapter implements IReconcileResult {
+
+ /**
+ * Creates and returns the annotation adapted by this adapter.
+ *
+ * @return an annotation (can be temporary or persistent)
+ */
+ public abstract Annotation createAnnotation();
+
+ /**
+ * The position of the annotation adapted by this adapter.
+ *
+ * @return the position
+ */
+ public abstract Position getPosition();
+
+}
--- /dev/null
+/*
+ * 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: CssAnnotationHover.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+
+/**
+ * Implements simple annotation hover to show the associated messages.
+ */
+public class CssAnnotationHover implements IAnnotationHover {
+ /*
+ * @see IVerticalRulerHover#getHoverInfo(ISourceViewer, int)
+ */
+ public String getHoverInfo(ISourceViewer sourceViewer, int lineNumber) {
+ List annotations = getAnnotationsForLine(sourceViewer, lineNumber);
+ if (annotations != null) {
+ List messages = new ArrayList();
+
+ Iterator e = annotations.iterator();
+ while (e.hasNext()) {
+ Annotation annotation = (Annotation) e.next();
+ String message = annotation.getText();
+ if (message != null) {
+ message = message.trim();
+ if (message.length() > 0) {
+ messages.add(message);
+ }
+ }
+ }
+
+ if (messages.size() == 1) {
+ return (String) messages.get(0);
+ }
+
+ if (messages.size() > 1) {
+ return formatMessages(messages);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Formats multiple annotation messages for display.
+ */
+ private String formatMessages(List messages) {
+ StringBuffer buffer = new StringBuffer();
+
+ Iterator e = messages.iterator();
+ while (e.hasNext()) {
+ buffer.append("- "); //$NON-NLS-1$
+ buffer.append(e.next());
+ buffer.append('\n');
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Returns annotations for the ruler's line of activity.
+ */
+ private List getAnnotationsForLine(ISourceViewer viewer, int line) {
+ IDocument document = viewer.getDocument();
+
+ IAnnotationModel model = viewer.getAnnotationModel();
+ if (model == null) {
+ return null;
+ }
+
+ List retVal = new ArrayList();
+
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+ Position position = model.getPosition(a);
+ if (position != null) {
+ try {
+ int annotationLine = document
+ .getLineOfOffset(position.getOffset());
+ if (annotationLine == line) {
+ retVal.add(a);
+ }
+ } catch (BadLocationException e1) {
+ // ignore
+ }
+ }
+ }
+
+ return retVal;
+ }
+}
--- /dev/null
+/*
+ * 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: CssAutoEditStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultAutoIndentStrategy;
+import org.eclipse.jface.text.DefaultLineTracker;
+import org.eclipse.jface.text.DocumentCommand;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ILineTracker;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.ITextEditorExtension3;
+import org.eclipse.ui.texteditor.ITextEditorExtension3.InsertMode;
+
+/**
+ * Implements various auto-editing aspects for editing CSS:
+ * <ul>
+ * <li>
+ * Smart indenting after opening or closing a block
+ * </li>
+ * <li>
+ * Smart insertion of closing braces
+ * </li>
+ * </ul>
+ * All these only operate when 'Smart Insert' mode is enabled, and the closing
+ * of braces, brackets, parenthesis and strings can be disabled in the editor
+ * preferences.
+ */
+public class CssAutoEditStrategy extends DefaultAutoIndentStrategy {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Alias for the preference constant <code>EDITOR_SPACES_FOR_TABS</code>.
+ */
+ public static final String SPACES_FOR_TABS =
+ CssUIPreferences.EDITOR_SPACES_FOR_TABS;
+
+ /**
+ * Alias for the preference constant <code>EDITOR_TAB_WIDTH</code>.
+ */
+ public static final String TAB_WIDTH =
+ CssUIPreferences.EDITOR_TAB_WIDTH;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The line tracker.
+ */
+ private ILineTracker lineTracker;
+
+ /**
+ * The preference store.
+ */
+ private IPreferenceStore store;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CssAutoEditStrategy() {
+ lineTracker = new DefaultLineTracker();
+ store = CssUI.getDefault().getPreferenceStore();
+ }
+
+ // DefaultAutoIndentStrategy Implementation --------------------------------
+
+ /**
+ * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(IDocument, DocumentCommand)
+ */
+ public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
+ if (isSmartInsertMode()) {
+ if (isNewLine(d, c)) {
+ smartIndentAfterNewLine(d, c);
+ } else if (c.text != null) {
+ if (c.text.length() == 1) {
+ switch (c.text.charAt(0)) {
+ case '}': {
+ smartInsertClosingBrace(d, c);
+ break;
+ }
+ default: {
+ // do nothing
+ }
+ }
+ }
+ if (store.getBoolean(SPACES_FOR_TABS)) {
+ convertTabs(d, c);
+ }
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private void convertTabs(IDocument d, DocumentCommand c) {
+ int index = c.text.indexOf('\t');
+ if (index > -1) {
+ StringBuffer buffer = new StringBuffer();
+ lineTracker.set(c.text);
+ int lines = lineTracker.getNumberOfLines();
+ try {
+ for (int i = 0; i < lines; i++) {
+ int offset = lineTracker.getLineOffset(i);
+ int endOffset = offset + lineTracker.getLineLength(i);
+ String line = c.text.substring(offset, endOffset);
+ int position = 0;
+ if (i == 0) {
+ IRegion firstLine =
+ d.getLineInformationOfOffset(c.offset);
+ position = c.offset - firstLine.getOffset();
+ }
+ int length = line.length();
+ for (int j = 0; j < length; j++) {
+ char ch = line.charAt(j);
+ if (ch == '\t') {
+ int tabWidth = getTabWidth();
+ int remainder = position % tabWidth;
+ remainder = tabWidth - remainder;
+ for (int k = 0; k < remainder; k++) {
+ buffer.append(' ');
+ }
+ position += remainder;
+ } else {
+ buffer.append(ch);
+ position++;
+ }
+ }
+ }
+ c.text = buffer.toString();
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ }
+ }
+
+ private String getIndentOfLine(IDocument d, int line)
+ throws BadLocationException {
+ if (line > -1) {
+ int start = d.getLineOffset(line);
+ int end = start + d.getLineLength(line) - 1;
+ int whiteEnd = findEndOfWhiteSpace(d, start, end);
+ return d.get(start, whiteEnd - start);
+ } else {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ private int getTabWidth() {
+ return store.getInt(TAB_WIDTH);
+ }
+
+ private boolean isNewLine(IDocument d, DocumentCommand c) {
+ if ((c.length == 0) && (c.text != null)) {
+ String[] delimiters = d.getLegalLineDelimiters();
+ for (int i = 0; i < delimiters.length; i++) {
+ if (c.text.equals(delimiters[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isSmartInsertMode() {
+ IWorkbenchWindow window =
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ IEditorPart part = page.getActiveEditor();
+ if (part instanceof ITextEditorExtension3) {
+ InsertMode insertMode =
+ ((ITextEditorExtension3) part).getInsertMode();
+ return (insertMode == ITextEditorExtension3.SMART_INSERT);
+ }
+ }
+ }
+ return false;
+ }
+
+ private String createIndentation(int level) {
+ StringBuffer buf = new StringBuffer();
+ if (store.getBoolean(SPACES_FOR_TABS)) {
+ int tabWidth = getTabWidth();
+ for (int i = 0; i < level * tabWidth; i++) {
+ buf.append(' ');
+ }
+ } else {
+ for (int i = 0; i < level; i++) {
+ buf.append('\t');
+ }
+ }
+ return buf.toString();
+ }
+
+ private void smartInsertClosingBrace(IDocument d, DocumentCommand c) {
+ int docLength = d.getLength();
+ if ((c.offset == -1) || (docLength == 0)) {
+ return;
+ }
+ try {
+ int lineOffset = d.getLineInformationOfOffset(c.offset).getOffset();
+ if (c.offset == findEndOfWhiteSpace(d, lineOffset, c.offset)) {
+ int openingBraceOffset =
+ CssTextUtils.findMatchingOpeningPeer(d, c.offset - 1, '}');
+ if (openingBraceOffset >= 0) {
+ int openingBraceLine =
+ d.getLineOfOffset(openingBraceOffset);
+ StringBuffer buf =
+ new StringBuffer(getIndentOfLine(d, openingBraceLine));
+ buf.append(c.text);
+ c.length += c.offset - lineOffset;
+ c.offset = lineOffset;
+ c.text = buf.toString();
+ }
+ }
+ } catch (BadLocationException e) {
+ CssUI.log(
+ "Failed to smart indent after closing brace", e); //$NON-NLS-1$
+ }
+ }
+
+ private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) {
+ try {
+ int docLength = d.getLength();
+ if ((c.offset == -1) || (docLength == 0)) {
+ return;
+ }
+ StringBuffer buf = new StringBuffer(c.text);
+ if ((c.offset < docLength) && (d.getChar(c.offset - 1) == '}')) {
+ // indent with the same amount used before the block was opened
+ int openingBraceOffset =
+ CssTextUtils.findMatchingOpeningPeer(d, c.offset - 2, '}');
+ if (openingBraceOffset >= 0) {
+ int openingBraceLine =
+ d.getLineOfOffset(openingBraceOffset);
+ buf.append(getIndentOfLine(d, openingBraceLine));
+ }
+ } else if ((c.offset < docLength)
+ && (d.getChar(c.offset - 1) == '{')) {
+ int previousLine = d.getLineOfOffset(c.offset);
+ buf.append(getIndentOfLine(d, previousLine));
+ buf.append(createIndentation(1));
+ } else {
+ int previousLine = d.getLineOfOffset(c.offset);
+ buf.append(getIndentOfLine(d, previousLine));
+ }
+ c.text = buf.toString();
+ } catch (BadLocationException e) {
+ CssUI.log(
+ "Failed to smart indent after new line", e); //$NON-NLS-1$
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssCodeScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+
+/**
+ * Rule based scanner responsible for syntax highlighting CSS source.
+ */
+public class CssCodeScanner extends AbstractCssScanner {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Custom rule that detects the SGML/XML comment delimiters
+ * (<code><!--</code> and <code>--></code> which are allowed at the
+ * beginning and the end of CSS content.
+ */
+ private class CdoCdcRule implements IRule {
+
+ /**
+ * The associated token.
+ */
+ private IToken token;
+
+ /**
+ * Constructor.
+ *
+ * @param token the associated token
+ */
+ public CdoCdcRule(IToken token) {
+ this.token = token;
+ }
+
+ /**
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public synchronized IToken evaluate(ICharacterScanner scanner) {
+ IToken retVal = Token.UNDEFINED;
+ int count = 1;
+ int c = scanner.read();
+ if (c == '<') {
+ count++;
+ c = scanner.read();
+ if (c == '!') {
+ count++;
+ c = scanner.read();
+ if (c == '-') {
+ count++;
+ c = scanner.read();
+ if (c == '-') {
+ return token;
+ }
+ }
+ }
+ } else if (c == '-') {
+ count++;
+ c = scanner.read();
+ if (c == '-') {
+ count++;
+ c = scanner.read();
+ if (c == '>') {
+ return token;
+ }
+ }
+ }
+ while (count-- > 0) {
+ scanner.unread();
+ }
+ return retVal;
+ }
+
+ }
+
+ /**
+ * Custom rule that can detect an at-keyword such as <code>@import</code>.
+ */
+ private class AtKeywordRule implements IRule {
+
+ /**
+ * The associated token.
+ */
+ private IToken token;
+
+ /**
+ * Collection of known at-keywords.
+ */
+ private Collection atKeywords;
+
+ /**
+ * Constructor.
+ *
+ * @param token the associated token
+ */
+ public AtKeywordRule(IToken token) {
+ this.token = token;
+ atKeywords = getProfile().getAtKeywords();
+ }
+
+ /**
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public synchronized IToken evaluate(ICharacterScanner scanner) {
+ IToken retVal = Token.UNDEFINED;
+ int count = 1;
+ int c = scanner.read();
+ if (c == '@') {
+ c = scanner.read();
+ if (CssTextUtils.isCssIdentifierStart((char) c)) {
+ resetBuffer();
+ do {
+ appendToBuffer((char) c);
+ c = scanner.read();
+ count++;
+ } while (CssTextUtils.isCssIdentifierPart((char) c));
+ String candidate = getBufferContent().toLowerCase();
+ if (atKeywords.contains(candidate)) {
+ return token;
+ }
+ }
+ }
+ while (count-- > 0) {
+ scanner.unread();
+ }
+ return retVal;
+ }
+
+ }
+
+ /**
+ * Custom rule that can detect a known property.
+ */
+ private class PropertyRule implements IRule {
+
+ /**
+ * The associated token.
+ */
+ private IToken token;
+
+ /**
+ * Collection of known properties.
+ */
+ private Collection properties;
+
+ /**
+ * Constructor.
+ *
+ * @param token the associated token
+ */
+ public PropertyRule(IToken token) {
+ this.token = token;
+ properties = getProfile().getProperties();
+ }
+
+ /**
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public synchronized IToken evaluate(ICharacterScanner scanner) {
+ IToken retVal = Token.UNDEFINED;
+ int count = 1;
+ int c = scanner.read();
+ if (CssTextUtils.isCssIdentifierStart((char) c)) {
+ resetBuffer();
+ do {
+ appendToBuffer((char) c);
+ c = scanner.read();
+ count++;
+ } while (CssTextUtils.isCssIdentifierPart((char) c));
+ String candidate = getBufferContent().toLowerCase();
+ if (properties.contains(candidate)) {
+ while (CssTextUtils.isCssWhitespace((char) c)) {
+ c = scanner.read();
+ count++;
+ }
+ if (c == ':') {
+ scanner.unread();
+ return token;
+ }
+ }
+ }
+ while (count-- > 0) {
+ scanner.unread();
+ }
+ return retVal;
+ }
+
+ }
+
+ /**
+ * Custom rule that can detect a pseudo-class in a selector.
+ */
+ private class PseudoClassRule implements IRule {
+
+ /**
+ * The associated token.
+ */
+ private IToken token;
+
+ /**
+ * Collection of known pseudo-classes.
+ */
+ private Collection pseudoClasses;
+
+ /**
+ * Constructor.
+ *
+ * @param token the associated token
+ */
+ public PseudoClassRule(IToken token) {
+ this.token = token;
+ pseudoClasses = getProfile().getPseudoClassNames();
+ }
+
+ /**
+ * @see IRule#evaluate(ICharacterScanner)
+ */
+ public synchronized IToken evaluate(ICharacterScanner scanner) {
+ IToken retVal = Token.UNDEFINED;
+ int count = 1;
+ int c = scanner.read();
+ if (c == ':') {
+ c = scanner.read();
+ if (CssTextUtils.isCssIdentifierStart((char) c)) {
+ resetBuffer();
+ do {
+ appendToBuffer((char) c);
+ c = scanner.read();
+ count++;
+ } while (CssTextUtils.isCssIdentifierPart((char) c));
+ String candidate = getBufferContent().toLowerCase();
+ if (pseudoClasses.contains(candidate)) {
+ return token;
+ }
+ }
+ }
+ while (count-- > 0) {
+ scanner.unread();
+ }
+ return retVal;
+ }
+
+ }
+
+ /**
+ * Detects CSS white space.
+ */
+ private static class WhitespaceDetector implements IWhitespaceDetector {
+
+ /**
+ * @see IWhitespaceDetector#isWhitespace(char)
+ */
+ public boolean isWhitespace(char c) {
+ return CssTextUtils.isCssWhitespace(c);
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The current CSS profile.
+ */
+ private IProfile profile;
+
+ /**
+ * Shared buffer used by the word detectors.
+ */
+ private StringBuffer buffer = new StringBuffer();
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param store The preference store
+ * @param manager The color manager
+ * @param profile The CSS profile to use
+ */
+ public CssCodeScanner(IPreferenceStore store, IColorManager manager,
+ IProfile profile) {
+ super(store, manager);
+ this.profile = profile;
+
+ List rules = new ArrayList();
+
+ rules.add(new WhitespaceRule(new WhitespaceDetector()));
+
+ rules.add(new CdoCdcRule(createToken(
+ CssUIPreferences.EDITOR_COMMENT_COLOR,
+ CssUIPreferences.EDITOR_COMMENT_BOLD)));
+ rules.add(new AtKeywordRule(createToken(
+ CssUIPreferences.EDITOR_AT_KEYWORD_COLOR,
+ CssUIPreferences.EDITOR_AT_KEYWORD_BOLD)));
+ rules.add(new PropertyRule(createToken(
+ CssUIPreferences.EDITOR_PROPERTY_COLOR,
+ CssUIPreferences.EDITOR_PROPERTY_BOLD)));
+ rules.add(new PseudoClassRule(createToken(
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_COLOR,
+ CssUIPreferences.EDITOR_PSEUDO_CLASS_BOLD)));
+
+ setRules((IRule[]) rules.toArray(new IRule[rules.size()]));
+
+ setDefaultReturnToken(createToken(
+ CssUIPreferences.EDITOR_DEFAULT_COLOR,
+ CssUIPreferences.EDITOR_DEFAULT_BOLD));
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private IProfile getProfile() {
+ return profile;
+ }
+
+ private void appendToBuffer(char c) {
+ buffer.append(c);
+ }
+
+ private String getBufferContent() {
+ return buffer.toString();
+ }
+
+ private void resetBuffer() {
+ buffer.setLength(0);
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssColorManager.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * CSS color manager.
+ */
+public class CssColorManager implements IColorManager {
+
+ // Instance Variables ------------------------------------------------------
+
+ private Map keyTable = new HashMap(10);
+
+ private Map displayTable = new HashMap(2);
+
+ /**
+ * Flag which tells if the colors are automatically disposed when the
+ * current display gets disposed.
+ */
+ private boolean autoDisposeOnDisplayDispose;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Creates a new CSS color manager which automatically disposes the
+ * allocated colors when the current display gets disposed.
+ */
+ public CssColorManager() {
+ this(true);
+ }
+
+ /**
+ * Creates a new CSS color manager.
+ *
+ * @param autoDisposeOnDisplayDispose if <code>true</code> the color manager
+ * automatically disposes all managed colors when the current display
+ * gets disposed and all calls to
+ * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()}
+ * are ignored.
+ */
+ public CssColorManager(boolean autoDisposeOnDisplayDispose) {
+ this.autoDisposeOnDisplayDispose = autoDisposeOnDisplayDispose;
+ }
+
+ // IColorManager Implementation --------------------------------------------
+
+ /*
+ * @see org.eclipse.jface.text.source.ISharedTextColors#dispose()
+ */
+ public void dispose() {
+ if (!this.autoDisposeOnDisplayDispose) {
+ dispose(Display.getCurrent());
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.ISharedTextColors#getColor(RGB)
+ */
+ public Color getColor(RGB rgb) {
+ if (rgb == null) {
+ return null;
+ }
+ final Display display = Display.getCurrent();
+ Map colorTable = (Map) this.displayTable.get(display);
+ if (colorTable == null) {
+ colorTable = new HashMap(10);
+ this.displayTable.put(display, colorTable);
+ if (this.autoDisposeOnDisplayDispose) {
+ display.disposeExec(new Runnable() {
+ public void run() {
+ dispose(display);
+ }
+ });
+ }
+ }
+ Color color = (Color) colorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ colorTable.put(rgb, color);
+ }
+ return color;
+ }
+
+ /*
+ * @see IColorManager#bindColor(String, RGB)
+ */
+ public void bindColor(String key, RGB rgb) {
+ Object value = this.keyTable.get(key);
+ if (value != null) {
+ throw new IllegalStateException();
+ }
+ this.keyTable.put(key, rgb);
+ }
+
+ /*
+ * @see IColorManager#getColor(String)
+ */
+ public Color getColor(String key) {
+ if (key == null) {
+ return null;
+ }
+ RGB rgb = (RGB) this.keyTable.get(key);
+ return getColor(rgb);
+ }
+
+ /*
+ * @see IColorManager#unbindColor(String)
+ */
+ public void unbindColor(String key) {
+ this.keyTable.remove(key);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private void dispose(Display display) {
+ Map colorTable = (Map) this.displayTable.get(display);
+ if (colorTable != null) {
+ for (Iterator i = colorTable.values().iterator(); i.hasNext(); ) {
+ Color color = (Color) i.next();
+ if (color != null && !color.isDisposed()) {
+ color.dispose();
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssCommentScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.rules.IToken;
+
+/**
+ *
+ */
+public class CssCommentScanner extends AbstractCssScanner {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param store The preference store
+ */
+ public CssCommentScanner(IPreferenceStore store, IColorManager manager) {
+ super(store, manager);
+
+ IToken commentToken = createToken(
+ CssUIPreferences.EDITOR_COMMENT_COLOR,
+ CssUIPreferences.EDITOR_COMMENT_BOLD);
+
+ setDefaultReturnToken(commentToken);
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssContentAssistProcessor.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.core.model.ISourceReference;
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.core.model.IAtRule;
+import net.sourceforge.phpeclipse.css.core.model.IDeclaration;
+import net.sourceforge.phpeclipse.css.core.model.IPropertyInfo;
+import net.sourceforge.phpeclipse.css.core.model.IRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleRule;
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Content assist processor for the CSS editor.
+ *
+ * TODO If a completion proposal is requested before the style sheet has been
+ * reconciled, we might not get any proposals, or they might be false.
+ */
+public class CssContentAssistProcessor implements IContentAssistProcessor {
+
+ // Constants ---------------------------------------------------------------
+
+ private static final String AUTOACTIVATION_TRIGGERS =
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_TRIGGERS;
+
+ private static final String ORDER_PROPOSALS =
+ CssUIPreferences.CONTENTASSIST_ORDER_PROPOSALS;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The preference store.
+ */
+ private IPreferenceStore store;
+
+ /**
+ * The current CSS profile.
+ */
+ private IProfile profile;
+
+ /**
+ * The associated text editor, if any.
+ */
+ private ITextEditor editor;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param profile The CSS profile to use
+ */
+ public CssContentAssistProcessor(IPreferenceStore store, IProfile profile,
+ ITextEditor editor) {
+ this.store = store;
+ this.profile = profile;
+ this.editor = editor;
+ }
+
+ // IContentAssistProcessor -------------------------------------------------
+
+ /*
+ * @see IContentAssistProcessor#computeCompletionProposals
+ */
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer,
+ int documentOffset) {
+ List retVal = Collections.EMPTY_LIST;
+ IDocument document = viewer.getDocument();
+ try {
+ String prefix = getPrefix(document, documentOffset);
+ if (prefix.startsWith("@")) { //$NON-NLS-1$
+ retVal = proposeAtKeywords(document, documentOffset,
+ prefix.substring(1));
+ } else if (prefix.startsWith(":")) { //$NON-NLS-1$
+ retVal = proposePseudoClasses(document, documentOffset,
+ prefix.substring(1));
+ } else {
+ retVal = proposeProperties(document, documentOffset, prefix);
+ }
+ if ((store != null) && store.getBoolean(ORDER_PROPOSALS)) {
+ sortProposals(retVal);
+ }
+ } catch (BadLocationException e) {
+ CssUI.log(
+ "Unable to compute completion proposals", e); //$NON-NLS-1$
+ }
+ return (ICompletionProposal[]) retVal.toArray(
+ new ICompletionProposal[retVal.size()]);
+ }
+
+ /*
+ * @see IContentAssistProcessor#computeContextInformation
+ */
+ public IContextInformation[] computeContextInformation(ITextViewer viewer,
+ int documentOffset) {
+ return new IContextInformation[0];
+ }
+
+ /*
+ * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters
+ */
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ String chars = store.getString(AUTOACTIVATION_TRIGGERS);
+ if (chars == null) {
+ return null;
+ }
+ return chars.toCharArray();
+ }
+
+ /*
+ * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters
+ */
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ /*
+ * @see IContentAssistProcessor#getErrorMessage
+ */
+ public String getErrorMessage() {
+ return null;
+ }
+
+ /*
+ * @see IContentAssistProcessor#getContextInformationValidator
+ */
+ public IContextInformationValidator getContextInformationValidator() {
+ return null;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the part of the word immediately before the position at which
+ * content assist was requested. The prefix is lower-cased before it is
+ * returned, to enable case-insensitive matching.
+ *
+ * @param document the document
+ * @param offset the offset into the document
+ * @return the prefix
+ */
+ private String getPrefix(IDocument document, int offset) {
+ try {
+ int startPos = offset;
+ while (startPos > 0) {
+ char c = document.getChar(startPos - 1);
+ if (!CssTextUtils.isCssIdentifierPart(c)
+ && (c != '@') && (c != ':')) {
+ break;
+ }
+ startPos--;
+ if ((c == '@') || (c == ':')) {
+ break;
+ }
+ }
+ if (startPos < offset) {
+ return document.get(startPos, offset - startPos).toLowerCase();
+ }
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the parsed model of the document loaded in the editor, or
+ * <code>null</code> if the editor hasn't been set or the model couldn't be
+ * retrieved.
+ *
+ * @return the parsed model
+ */
+ private IStyleSheet getStyleSheet() {
+ if (editor != null) {
+ IDocumentProvider provider = editor.getDocumentProvider();
+ if (provider instanceof CssDocumentProvider) {
+ return ((CssDocumentProvider) provider).getStyleSheet(
+ editor.getEditorInput());
+ }
+ }
+ return null;
+ }
+
+ public boolean isAtKeyword(IDocument document, int offset)
+ throws BadLocationException {
+ IStyleSheet styleSheet = getStyleSheet();
+ if (styleSheet != null) {
+ IRule rule = styleSheet.getRuleAt(offset);
+ if (rule instanceof IAtRule) {
+ ISourceReference name = ((IAtRule) rule).getName();
+ if (name != null) {
+ IRegion region = name.getSourceRegion();
+ for (int j = region.getOffset(); j < offset; j++) {
+ char ch = document.getChar(j);
+ if (!CssTextUtils.isCssIdentifierPart(ch)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ } else if (rule == null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether the document contains a property at the specified
+ * offset, or at least whether a property is theoretically allowed at that
+ * offset.
+ *
+ * @param document the document
+ * @param offset the offset into the document
+ * @return <code>true</code> if the specified offset is a legal position for
+ * a property, <code>false</code> otherwise
+ * @throws BadLocationException if there was a problem accessing the
+ * document
+ */
+ public boolean isProperty(IDocument document, int offset)
+ throws BadLocationException {
+ IStyleSheet styleSheet = getStyleSheet();
+ if (styleSheet != null) {
+ IRule rule = styleSheet.getRuleAt(offset);
+ if (rule != null) {
+ IDeclaration declaration = rule.getDeclarationAt(offset);
+ if (declaration != null) {
+ IRegion region = declaration.getSourceRegion();
+ for (int j = region.getOffset(); j < offset; j++) {
+ if (document.getChar(j) == ':') {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ IRegion region = rule.getSourceRegion();
+ for (int j = region.getOffset(); j < offset; j++) {
+ if (document.getChar(j) == '{') {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether the document contains a selector at the specified
+ * offset, or at least whether a selector is theoretically allowed at that
+ * offset.
+ */
+ public boolean isSelector(IDocument document, int offset)
+ throws BadLocationException {
+ IStyleSheet styleSheet = getStyleSheet();
+ if (styleSheet != null) {
+ IRule rule = styleSheet.getRuleAt(offset);
+ if (rule instanceof IStyleRule) {
+ ISourceReference selector = ((IStyleRule) rule).getSelector();
+ if (selector != null) {
+ IRegion region = selector.getSourceRegion();
+ for (int j = region.getOffset(); j < offset; j++) {
+ if (document.getChar(j) == '{') {
+ return false;
+ }
+ }
+ return true;
+ }
+ } else if (rule == null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List proposeAtKeywords(IDocument document, int offset,
+ String prefix) throws BadLocationException {
+ List proposals = new ArrayList();
+ if (isAtKeyword(document, offset)) {
+ Image icon = CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_AT_RULE);
+ Collection atRuleNames = profile.getAtKeywords();
+ for (Iterator i = atRuleNames.iterator(); i.hasNext(); ) {
+ String atRuleName = (String) i.next();
+ if (atRuleName.startsWith(prefix)) {
+ ICompletionProposal proposal = new CompletionProposal(
+ atRuleName, offset - prefix.length(), prefix.length(),
+ atRuleName.length(), icon, atRuleName, null, null);
+ proposals.add(proposal);
+ }
+ }
+ }
+ return proposals;
+ }
+
+ /**
+ * Computes the completion proposals for properties. A property may only
+ * appear at the left-hand side of a declaration, so we check whether the
+ * document offset for which the proposals were requested is a legal
+ * position for a property, and only then compute the actual proposals.
+ *
+ * @param document the document
+ * @param offset the offset into the document at which completion was
+ * requested
+ * @param prefix the string immediately before the offset
+ * @return the list of {@link ICompletionProposal}s
+ */
+ private List proposeProperties(IDocument document, int offset,
+ String prefix) throws BadLocationException {
+ List proposals = new ArrayList();
+ if (isProperty(document, offset - 1)) {
+ Image propertyIcon =
+ CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_PROPERTY);
+ Image shorthandIcon =
+ CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_SHORTHAND);
+ Collection propertyNames = profile.getProperties();
+ for (Iterator i = propertyNames.iterator(); i.hasNext(); ) {
+ String propertyName = (String) i.next();
+ if (propertyName.startsWith(prefix)) {
+ Image icon = propertyIcon;
+ IPropertyInfo info = profile.getPropertyInfo(propertyName);
+ if (info.isShorthand()) {
+ icon = shorthandIcon;
+ }
+ ICompletionProposal proposal = new CompletionProposal(
+ propertyName, offset - prefix.length(),
+ prefix.length(), propertyName.length(), icon,
+ propertyName, null, info.getDescription());
+ proposals.add(proposal);
+ }
+ }
+ }
+ return proposals;
+ }
+
+ private List proposePseudoClasses(IDocument document, int offset,
+ String prefix) throws BadLocationException {
+ List proposals = new ArrayList();
+ if (isSelector(document, offset - 1)) {
+ Image icon = CssUI.getDefault().getImageRegistry().get(
+ CssUI.ICON_PSEUDO_CLASS);
+ Collection pseudoClassNames = profile.getPseudoClassNames();
+ for (Iterator i = pseudoClassNames.iterator(); i.hasNext(); ) {
+ String pseudoClassName = (String) i.next();
+ if (pseudoClassName.startsWith(prefix)) {
+ ICompletionProposal proposal = new CompletionProposal(
+ pseudoClassName, offset - prefix.length(),
+ prefix.length(), pseudoClassName.length(), icon,
+ pseudoClassName, null, null);
+ proposals.add(proposal);
+ }
+ }
+ }
+ return proposals;
+ }
+
+ private void sortProposals(List proposals) {
+ Collections.sort(proposals, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ String s1 = ((ICompletionProposal) o1).getDisplayString();
+ if (s1 == null) {
+ return -1;
+ }
+ String s2 = ((ICompletionProposal) o2).getDisplayString();
+ return s1.compareToIgnoreCase(s2);
+ }
+ });
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssDoubleClickStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.source.ICharacterPairMatcher;
+import org.eclipse.jface.util.Assert;
+
+/**
+ * Strategy for selecting CSS identifiers on double click in the editor.
+ *
+ * This strategy implements selection of CSS identifiers on double click inside
+ * an identifier, as well as selection of blocks delimited by square brackets,
+ * curly braces and parenthesis when the user double clicks directly after
+ * either the opening or the closing delimiter.
+ */
+public class CssDoubleClickStrategy implements ITextDoubleClickStrategy {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The pair matcher used to select ranges delimited by matching pairs of
+ * braces, brackets and parenthesis.
+ */
+ private ICharacterPairMatcher pairMatcher = new CssPairMatcher();
+
+ // ITextDoubleClickStrategy Implementation ---------------------------------
+
+ /*
+ * @see ITextDoubleClickStrategy#doubleClicked(ITextViewer)
+ */
+ public void doubleClicked(ITextViewer viewer) {
+ IDocument document = viewer.getDocument();
+ if (document.getLength() == 0) {
+ return;
+ }
+ int offset = viewer.getSelectedRange().x;
+ Assert.isLegal(offset >= 0,
+ "Double click offset may not be negative"); //$NON-NLS-1$
+ Assert.isLegal(offset <= document.getLength(),
+ "Double click offset out of range"); //$NON-NLS-1$
+ IRegion region = pairMatcher.match(document, offset);
+ if ((region != null) && (region.getLength() >= 2)) {
+ viewer.setSelectedRange(region.getOffset() + 1,
+ region.getLength() - 2);
+ } else {
+ try {
+ region = getSurroundingIdentifier(document, offset);
+ if (region != null) {
+ viewer.setSelectedRange(
+ region.getOffset(), region.getLength());
+ }
+ } catch (BadLocationException e) {
+ CssUI.log("Failed to get surrounding " + //$NON-NLS-1$
+ "word for double click selection"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the region that delimits the identifier surrounding the given
+ * offset into the document. If no identifier is found at the specified
+ * offset, this method returns <code>null</code>.
+ *
+ * @param doc the document
+ * @param offset the zero-based offset into the document
+ * @return the region covered by the identifier, or <code>null</code> if no
+ * identifier was found at that offset
+ */
+ private IRegion getSurroundingIdentifier(IDocument doc, int offset)
+ throws BadLocationException {
+ IRegion retVal = null;
+ int length = doc.getLength();
+ offset = Math.min(offset, length - 1);
+ if (CssTextUtils.isCssIdentifierPart(doc.getChar(offset))) {
+ int start = offset;
+ while (start > 0) {
+ if (!CssTextUtils.isCssIdentifierPart(doc.getChar(start - 1))) {
+ break;
+ }
+ start--;
+ }
+ int end = offset;
+ while (end < (length - 1)) {
+ if (!CssTextUtils.isCssIdentifierPart(doc.getChar(end + 1))) {
+ break;
+ }
+ end++;
+ }
+ retVal = new Region(start, end - start + 1);
+ }
+ return retVal;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssPairMatcher.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import net.sourceforge.phpeclipse.css.core.internal.text.CssTextUtils;
+
+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.eclipse.jface.text.source.ICharacterPairMatcher;
+import org.eclipse.jface.util.Assert;
+
+/**
+ *
+ */
+public class CssPairMatcher implements ICharacterPairMatcher {
+
+ // Constants ---------------------------------------------------------------
+
+ private static final char PAIRS[] = {
+ '{', '}', '(', ')', '[', ']'
+ };
+
+ // Instance Variables ------------------------------------------------------
+
+ private IDocument document;
+
+ private int offset;
+
+ private int anchor;
+
+ // ICharacterPairMatcher Implementation ------------------------------------
+
+ /*
+ * @see ICharacterPairMatcher#clear
+ */
+ public void clear() {
+ document = null;
+ offset = -1;
+ anchor = 0;
+ }
+
+ /*
+ * @see ICharacterPairMatcher#dispose
+ */
+ public void dispose() {
+ document = null;
+ }
+
+ /*
+ * @see ICharacterPairMatcher#match
+ */
+ public IRegion match(IDocument document, int offset) {
+ Assert.isNotNull(document);
+ Assert.isLegal(offset >= 0);
+ this.document = document;
+ this.offset = offset;
+
+ IRegion retVal = null;
+ try {
+ retVal = matchPairsAt();
+ } catch (BadLocationException e) {
+ // ignore, there's probably no matching character to highlight
+ }
+ return retVal;
+ }
+
+ /*
+ * @see ICharacterPairMatcher#getAnchor
+ */
+ public int getAnchor() {
+ return anchor;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ private boolean isClosingCharacter(char ch) {
+ for (int i = 1; i < PAIRS.length; i += 2) {
+ if (ch == PAIRS[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isOpeningCharacter(char ch) {
+ for (int i = 0; i < PAIRS.length; i += 2) {
+ if (ch == PAIRS[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private IRegion matchPairsAt() throws BadLocationException {
+ int startPos = -1, endPos = -1;
+ char prevChar = document.getChar(Math.max(offset - 1, 0));
+ if (isOpeningCharacter(prevChar)) {
+ startPos = offset - 1;
+ if (startPos >= 0) {
+ anchor = LEFT;
+ endPos = CssTextUtils.findMatchingClosingPeer(
+ document, startPos + 1, prevChar);
+ if (endPos > -1) {
+ return new Region(startPos, endPos - startPos + 1);
+ }
+ }
+ }
+ if (isClosingCharacter(prevChar)) {
+ endPos = offset - 1;
+ if (endPos >= 0) {
+ anchor = RIGHT;
+ startPos = CssTextUtils.findMatchingOpeningPeer(
+ document, endPos - 1, prevChar);
+ if (startPos > -1) {
+ return new Region(startPos, endPos - startPos + 1);
+ }
+ }
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssPartitionScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+
+/**
+ *
+ */
+public class CssPartitionScanner extends RuleBasedPartitionScanner {
+
+ // Constants ---------------------------------------------------------------
+
+ public static final String CSS_COMMENT =
+ "__css_comment_partition_content_type"; //$NON-NLS-1$
+
+ public static final String CSS_STRING =
+ "__css_string_partition_content_type"; //$NON-NLS-1$
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ */
+ public CssPartitionScanner() {
+
+ IToken commentToken = new Token(CSS_COMMENT);
+ IToken stringToken = new Token(CSS_STRING);
+
+ List rules = new ArrayList();
+
+ rules.add(new MultiLineRule(
+ "/*", "*/", commentToken)); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // TODO Strings can be continued over a new line using the escape
+ // character (#42613)
+ rules.add(new SingleLineRule(
+ "\"", "\"", stringToken, '\\')); //$NON-NLS-1$ //$NON-NLS-2$
+ rules.add(new SingleLineRule(
+ "'", "'", stringToken, '\\')); //$NON-NLS-1$ //$NON-NLS-2$
+
+ setPredicateRules((IPredicateRule[])
+ rules.toArray(new IPredicateRule[rules.size()]));
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssReconcileStep.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
+import net.sourceforge.phpeclipse.css.core.parser.IProblem;
+import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
+import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
+import net.sourceforge.phpeclipse.css.ui.internal.CssDocumentProvider;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.AbstractReconcileStep;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilableModel;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Implementation of a reconcile step for building the CSS parse tree on changes
+ * to the editor content.
+ */
+public class CssReconcileStep extends AbstractReconcileStep {
+
+ // Inner Classes -----------------------------------------------------------
+
+ /**
+ * Adapts an <code>IStyleSheet</code> to the <code>IReconcilableModel</code>
+ * interface.
+ */
+ private class StyleSheetAdapter implements IReconcilableModel {
+
+ private IStyleSheet styleSheet;
+
+ public StyleSheetAdapter(IStyleSheet styleSheet) {
+ this.styleSheet = styleSheet;
+ }
+
+ public IStyleSheet getStyleSheet() {
+ return styleSheet;
+ }
+
+ }
+
+ /**
+ * Implementation of the problem collector interface for creating problem
+ * annotations when there are problems parsing the style sheet.
+ */
+ private class ProblemCollector implements IProblemCollector {
+
+ /**
+ * The list of problems added to this collector.
+ */
+ private List collectedProblems = new ArrayList();
+
+ /**
+ * @see IProblemCollector#addProblem(IProblem)
+ */
+ public void addProblem(IProblem problem) {
+ collectedProblems.add(problem);
+ }
+
+ /**
+ * Returns the list of problems collected while the CSS source has been
+ * parsed, in the order they were reported. The list returned is
+ * immutable.
+ *
+ * @return the list of collected problems (of type {@link IProblem})
+ */
+ public List getProblems() {
+ return Collections.unmodifiableList(collectedProblems);
+ }
+
+ }
+
+ /**
+ * Adapter that adapts an {@link IProblem} to an {@link Annotation}.
+ */
+ private class ProblemAdapter extends AnnotationAdapter {
+
+ private IProblem problem;
+ private Position position;
+
+ ProblemAdapter(IProblem problem) {
+ this.problem = problem;
+ }
+
+ public Position getPosition() {
+ if (position == null) {
+ position = createPositionFromProblem();
+ }
+ return position;
+ }
+
+ public Annotation createAnnotation() {
+ int start = problem.getSourceStart();
+ if (start < 0) {
+ return null;
+ }
+ int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+ if (length < 0) {
+ return null;
+ }
+ String type = null;
+ if (problem.isWarning()) {
+ type = "org.eclipse.ui.workbench.texteditor.warning"; //$NON-NLS-1$
+ } else if (problem.isError()) {
+ type = "org.eclipse.ui.workbench.texteditor.error"; //$NON-NLS-1$
+ }
+ return new Annotation(type, false, problem.getMessage());
+ }
+
+ private Position createPositionFromProblem() {
+ int start = problem.getSourceStart();
+ if (start < 0) {
+ return null;
+ }
+ int length = problem.getSourceEnd() - problem.getSourceStart() + 1;
+ if (length < 0) {
+ return null;
+ }
+ return new Position(start, length);
+ }
+
+ }
+
+ // Instance Variables ------------------------------------------------------
+
+ private ITextEditor editor;
+
+ private StyleSheetAdapter styleSheetAdapter;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CssReconcileStep(ITextEditor editor) {
+ this.editor = editor;
+ styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param step the step to add to the pipe
+ * @param editor the associated text editor
+ */
+ public CssReconcileStep(IReconcileStep step, ITextEditor editor) {
+ super(step);
+ this.editor = editor;
+ styleSheetAdapter = new StyleSheetAdapter(getStyleSheet());
+ }
+
+ // AbstractReconcileStep Implementation ------------------------------------
+
+ /*
+ * @see AbstractReconcileStep#reconcileModel(DirtyRegion, IRegion)
+ */
+ protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion,
+ IRegion subRegion) {
+ IStyleSheet styleSheet = styleSheetAdapter.getStyleSheet();
+ ProblemCollector problemCollector = new ProblemCollector();
+ try {
+ styleSheet.reconcile(problemCollector);
+ } catch (LexicalErrorException e) {
+ // Already reported to the problem collector
+ } catch (SyntaxErrorException e) {
+ // Already reported to the problem collector
+ }
+ List problems = problemCollector.getProblems();
+ IReconcileResult[] retVal = new IReconcileResult[problems.size()];
+ for (int i = 0; i < problems.size(); i++) {
+ IProblem problem = (IProblem) problems.get(i);
+ retVal[i] = new ProblemAdapter(problem);
+ }
+ return retVal;
+ }
+
+ /*
+ * @see AbstractReconcileStep#getModel()
+ */
+ public IReconcilableModel getModel() {
+ return styleSheetAdapter;
+ }
+
+ // Private Methods Implementation ------------------------------------------
+
+ /**
+ * Retrieve the style sheet associated with the editor input.
+ */
+ private IStyleSheet getStyleSheet() {
+ IDocumentProvider documentProvider = editor.getDocumentProvider();
+ if (documentProvider instanceof CssDocumentProvider) {
+ CssDocumentProvider cssDocumentProvider = (CssDocumentProvider)
+ documentProvider;
+ return cssDocumentProvider.getStyleSheet(editor.getEditorInput());
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssReconcilingStrategy.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcileResult;
+import org.eclipse.jface.text.reconciler.IReconcileStep;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+
+/**
+ * Reconciling strategy for CSS style sheets. This class is responsible for
+ * keeping the parsed model in sync with the text.
+ */
+public class CssReconcilingStrategy
+ implements IReconcilingStrategy, IReconcilingStrategyExtension {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated text editor.
+ */
+ private ITextEditor editor;
+
+ /**
+ * A progress monitor that should be used for long-running operations.
+ */
+ IProgressMonitor progressMonitor;
+
+ /**
+ * The first (and only) reconcile step is the parsing of the style sheet.
+ */
+ private IReconcileStep firstStep;
+
+ // Constructors ------------------------------------------------------------
+
+ public CssReconcilingStrategy(ITextEditor editor) {
+ this.editor = editor;
+ firstStep = new CssReconcileStep(editor);
+ }
+
+ // IReconcilingStrategy Implementation -------------------------------------
+
+ /**
+ * @see IReconcilingStrategy#reconcile(DirtyRegion, IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ removeTemporaryAnnotations();
+ process(firstStep.reconcile(dirtyRegion, subRegion));
+ }
+
+ /**
+ * @see IReconcilingStrategy#reconcile(IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ removeTemporaryAnnotations();
+ process(firstStep.reconcile(partition));
+ }
+
+ /**
+ * @see IReconcilingStrategy#setDocument(IDocument)
+ */
+ public void setDocument(IDocument document) {
+ // FIXME
+ firstStep.setInputModel(null); //new DocumentAdapter(document);
+ }
+
+ // IReconcilingStrategyExtension Implementation ----------------------------
+
+ /**
+ * @see IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ process(firstStep.reconcile(null));
+ }
+
+ /**
+ * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ firstStep.setProgressMonitor(monitor);
+ progressMonitor = monitor;
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the annotation model for the editor input.
+ *
+ * @return the annotation model
+ */
+ IAnnotationModel getAnnotationModel() {
+ IEditorInput input = editor.getEditorInput();
+ return editor.getDocumentProvider().getAnnotationModel(input);
+ }
+
+ /**
+ * Adds results of the reconcilation to the annotation model.
+ */
+ private void process(final IReconcileResult[] results) {
+ if (results == null) {
+ return;
+ }
+
+ IRunnableWithProgress runnable = new WorkspaceModifyOperation() {
+ protected void execute(IProgressMonitor monitor) {
+ for (int i = 0; i < results.length; i++) {
+ if ((progressMonitor != null)
+ && (progressMonitor.isCanceled())) {
+ return;
+ }
+
+ if (!(results[i] instanceof AnnotationAdapter)) {
+ continue;
+ }
+
+ AnnotationAdapter result = (AnnotationAdapter) results[i];
+ Position pos = result.getPosition();
+ Annotation annotation = result.createAnnotation();
+ getAnnotationModel().addAnnotation(annotation, pos);
+ }
+ }
+ };
+
+ try {
+ runnable.run(null);
+ } catch (InvocationTargetException e) {
+ CssUI.log(e);
+ } catch (InterruptedException e) {
+ CssUI.log(e);
+ }
+
+ if (editor instanceof IReconcilingParticipant) {
+ ((IReconcilingParticipant) editor).reconciled();
+ }
+ }
+
+ /*
+ * TODO A "real" implementation must be smarter, i.e. don't remove and add
+ * the annotations which are the same.
+ */
+ private void removeTemporaryAnnotations() {
+ Iterator i = getAnnotationModel().getAnnotationIterator();
+ while (i.hasNext()) {
+ Annotation annotation = (Annotation) i.next();
+ if (!annotation.isPersistent()) {
+ getAnnotationModel().removeAnnotation(annotation);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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: CssSourceViewerConfiguration.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfileManager;
+import net.sourceforge.phpeclipse.css.ui.CssUI;
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.text.CssTextTools;
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.DefaultAutoIndentStrategy;
+import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
+import org.eclipse.jface.text.IAutoIndentStrategy;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Source viewer configuration for CSS. This class takes care of setting up
+ * various aspects of the CSS editor, such as text hovers, syntax highlighting,
+ * reconciling or the double click strategy.
+ */
+public final class CssSourceViewerConfiguration
+ extends TextSourceViewerConfiguration {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Alias for the preference constant <code>CONTENTASSIST_AUTOINSERT</code>.
+ */
+ private static final String AUTOINSERT =
+ CssUIPreferences.CONTENTASSIST_AUTOINSERT;
+
+ /**
+ * Alias for the preference constant
+ * <code>CONTENTASSIST_AUTOACTIVATION</code>.
+ */
+ private static final String AUTOACTIVATION =
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION;
+
+ /**
+ * Alias for the preference constant
+ * <code>CONTENTASSIST_AUTOACTIVATION_DELAY</code>.
+ */
+ private static final String AUTOACTIVATION_DELAY =
+ CssUIPreferences.CONTENTASSIST_AUTOACTIVATION_DELAY;
+
+ /**
+ * Alias for the preference constant
+ * <code>CONTENTASSIST_PROPOSALS_BACKGROUND</code>.
+ */
+ private static final String PROPOSALS_BACKGROUND =
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_BACKGROUND;
+
+ /**
+ * Alias for the preference constant
+ * <code>CONTENTASSIST_PROPOSALS_FOREGROUND</code>.
+ */
+ private static final String PROPOSALS_FOREGROUND =
+ CssUIPreferences.CONTENTASSIST_PROPOSALS_FOREGROUND;
+
+ /**
+ * Alias for the preference constant <code>EDITOR_SPACES_FOR_TABS</code>.
+ */
+ private static final String SPACES_FOR_TABS =
+ CssUIPreferences.EDITOR_SPACES_FOR_TABS;
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The associated editor.
+ */
+ private ITextEditor editor;
+
+ /**
+ * The preference store used.
+ */
+ private IPreferenceStore store;
+
+ /**
+ * The CSS profile.
+ */
+ private IProfile profile;
+
+ /**
+ * The associated text tools.
+ */
+ private CssTextTools textTools;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Default constructor.
+ */
+ public CssSourceViewerConfiguration() {
+ this(CssUI.getDefault().getTextTools());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param textTools the CSS text tools to associate with the source viewer
+ * configuration
+ */
+ public CssSourceViewerConfiguration(CssTextTools textTools) {
+ this(textTools, CssUI.getDefault().getPreferenceStore());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param textTools the CSS text tools to associate with the source viewer
+ * configuration
+ * @param store the preference store
+ */
+ public CssSourceViewerConfiguration(
+ CssTextTools textTools, IPreferenceStore store
+ ) {
+ this(textTools, store, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param textTools the CSS text tools to associate with the source viewer
+ * configuration
+ * @param store the preference store
+ * @param editor the text editor
+ */
+ public CssSourceViewerConfiguration(
+ CssTextTools textTools, IPreferenceStore store, ITextEditor editor
+ ) {
+ this.textTools = textTools;
+ this.store = store;
+ this.editor = editor;
+ }
+
+ // SourceViewerConfiguration Implementation --------------------------------
+
+ /*
+ * @see SourceViewerConfiguration#getAnnotationHover(ISourceViewer)
+ */
+ public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+ return new CssAnnotationHover();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getAutoIndentStrategy(ISourceViewer, String)
+ */
+ public IAutoIndentStrategy getAutoIndentStrategy(
+ ISourceViewer sourceViewer, String contentType
+ ) {
+ if (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) {
+ return new CssAutoEditStrategy();
+ }
+
+ return new DefaultAutoIndentStrategy();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getConfiguredContentTypes(ISourceViewer)
+ */
+ public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+ return new String[] {
+ IDocument.DEFAULT_CONTENT_TYPE,
+ CssPartitionScanner.CSS_COMMENT,
+ CssPartitionScanner.CSS_STRING
+ };
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getContentAssistant(ISourceViewer)
+ */
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ assistant.setContentAssistProcessor(
+ new CssContentAssistProcessor(store, getProfile(), editor),
+ IDocument.DEFAULT_CONTENT_TYPE);
+ assistant.setInformationControlCreator(
+ getInformationControlCreator(sourceViewer));
+ assistant.enableAutoInsert(store.getBoolean(AUTOINSERT));
+ assistant.enableAutoActivation(store.getBoolean(AUTOACTIVATION));
+ assistant.setAutoActivationDelay(store.getInt(AUTOACTIVATION_DELAY));
+ assistant.setContextInformationPopupOrientation(
+ IContentAssistant.CONTEXT_INFO_BELOW);
+ assistant.setProposalPopupOrientation(
+ IContentAssistant.PROPOSAL_STACKED);
+ assistant.setProposalSelectorBackground(getColorManager().getColor(
+ PreferenceConverter.getColor(store, PROPOSALS_BACKGROUND)));
+ assistant.setProposalSelectorForeground(getColorManager().getColor(
+ PreferenceConverter.getColor(store, PROPOSALS_FOREGROUND)));
+ return assistant;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String)
+ */
+ public ITextDoubleClickStrategy getDoubleClickStrategy(
+ ISourceViewer sourceViewer, String contentType
+ ) {
+ if (IDocument.DEFAULT_CONTENT_TYPE.equals(contentType)) {
+ return new CssDoubleClickStrategy();
+ }
+ return new DefaultTextDoubleClickStrategy();
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getIndentPrefixes(ISourceViewer, String)
+ */
+ public String[] getIndentPrefixes(
+ ISourceViewer sourceViewer, String contentType
+ ) {
+ List retVal = new ArrayList();
+ int tabWidth = getTabWidth(sourceViewer);
+ boolean useSpaces = store.getBoolean(SPACES_FOR_TABS);
+ for (int i = 0; i <= tabWidth; i++) {
+ StringBuffer prefix = new StringBuffer();
+ if (useSpaces) {
+ for (int j = 0; j < tabWidth - i; 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');
+ }
+ }
+ retVal.add(prefix.toString());
+ }
+ retVal.add(""); //$NON-NLS-1$
+ return (String[]) retVal.toArray(new String[retVal.size()]);
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getPresentationReconciler(ISourceViewer)
+ */
+ public IPresentationReconciler getPresentationReconciler(
+ ISourceViewer sourceViewer
+ ) {
+ PresentationReconciler reconciler = new PresentationReconciler();
+ DefaultDamagerRepairer dr;
+
+ // Comments
+ dr = new DefaultDamagerRepairer(textTools.getCommentScanner());
+ reconciler.setDamager(dr, CssPartitionScanner.CSS_COMMENT);
+ reconciler.setRepairer(dr, CssPartitionScanner.CSS_COMMENT);
+
+ // Strings
+ dr = new DefaultDamagerRepairer(textTools.getStringScanner());
+ reconciler.setDamager(dr, CssPartitionScanner.CSS_STRING);
+ reconciler.setRepairer(dr, CssPartitionScanner.CSS_STRING);
+
+ // Code
+ dr = new DefaultDamagerRepairer(textTools.getCodeScanner(getProfile()));
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ return reconciler;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getReconciler(ISourceViewer)
+ */
+ public IReconciler getReconciler(ISourceViewer sourceViewer) {
+ if ((editor != null) && editor.isEditable()) {
+ MonoReconciler reconciler = new MonoReconciler(
+ new CssReconcilingStrategy(editor), false);
+ reconciler.setProgressMonitor(new NullProgressMonitor());
+ reconciler.setDelay(500);
+ return reconciler;
+ }
+
+ return null;
+ }
+
+ /*
+ * @see SourceViewerConfiguration#getTextHover(ISourceViewer, String)
+ */
+ public ITextHover getTextHover(
+ ISourceViewer sourceViewer, String contentType
+ ) {
+ if (editor != null) {
+ IDocumentProvider provider = editor.getDocumentProvider();
+ IEditorInput input = editor.getEditorInput();
+ IAnnotationModel model = provider.getAnnotationModel(input);
+ return new CssTextHover(model);
+ }
+
+ return super.getTextHover(sourceViewer, contentType);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Returns the color manager associated with this configuration.
+ *
+ * @return the color manager
+ */
+ private IColorManager getColorManager() {
+ if (textTools != null) {
+ return textTools.getColorManager();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the CSS profile for the resource currently being viewed, or
+ * the default profile if this source viewer configuration isn't associated
+ * with an editor.
+ *
+ * @return the profile
+ */
+ private IProfile getProfile() {
+ if (profile == null) {
+ IResource resource = null;
+ if (editor != null) {
+ IEditorInput input = editor.getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ resource = ((IFileEditorInput) input).getFile();
+ }
+ }
+
+ IProfileManager mgr = CssCore.getDefault().getProfileManager();
+ profile = mgr.getProfile(resource);
+ }
+
+ return profile;
+ }
+}
--- /dev/null
+/*
+ * 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: CssStringScanner.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import net.sourceforge.phpeclipse.css.ui.internal.CssUIPreferences;
+import net.sourceforge.phpeclipse.css.ui.text.IColorManager;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.rules.IToken;
+
+/**
+ *
+ */
+public class CssStringScanner extends AbstractCssScanner {
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param store The preference store
+ */
+ public CssStringScanner(IPreferenceStore store, IColorManager manager) {
+ super(store, manager);
+
+ IToken stringToken = createToken(
+ CssUIPreferences.EDITOR_STRING_COLOR,
+ CssUIPreferences.EDITOR_STRING_BOLD);
+
+ setDefaultReturnToken(stringToken);
+ }
+
+}
--- /dev/null
+/*
+ * 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: CssTextHover.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+
+
+/**
+ * Implements simple annotation hover to show the associated messages.
+ */
+public class CssTextHover implements ITextHover {
+ /**
+ * This hovers annotation model.
+ */
+ private IAnnotationModel model;
+
+ /**
+ * Creates a new annotation hover.
+ *
+ * @param model this hover's annotation model
+ */
+ public CssTextHover(IAnnotationModel model) {
+ this.model = model;
+ }
+
+ /*
+ * @see ITextHover#getHoverInfo(ITextViewer, IRegion)
+ */
+ public String getHoverInfo(ITextViewer textViewer, IRegion region) {
+ Iterator e = model.getAnnotationIterator();
+ while (e.hasNext()) {
+ Annotation a = (Annotation) e.next();
+ Position p = model.getPosition(a);
+ if (p.overlapsWith(region.getOffset(), region.getLength())) {
+ String text = a.getText();
+ if ((text != null) && (text.trim().length() > 0)) {
+ return text;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see ITextHover#getHoverRegion(ITextViewer, int)
+ */
+ public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+ return CssWordFinder.findWord(textViewer.getDocument(), offset);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 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://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Igor Malinin - initial implementation
+ *
+ * $Id: CssWordFinder.java,v 1.1 2004-09-02 18:11:48 jsurfer Exp $
+ */
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+
+/**
+ *
+ *
+ * @author Igor Malinin
+ */
+public class CssWordFinder {
+ public static IRegion findWord(IDocument document, int offset) {
+ int length = document.getLength();
+
+ try {
+ int pos = offset;
+
+ while (pos >= 0) {
+ if (!Character.isUnicodeIdentifierPart(document.getChar(pos))) {
+ break;
+ }
+ --pos;
+ }
+
+ int start = pos;
+
+ pos = offset;
+
+ while (pos < length) {
+ if (!Character.isUnicodeIdentifierPart(document.getChar(pos))) {
+ break;
+ }
+ ++pos;
+ }
+
+ int end = pos;
+
+ if (start == offset) {
+ return new Region(start, end - start);
+ }
+
+ return new Region(start + 1, end - start - 1);
+ } catch (BadLocationException x) {
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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:11:48 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.internal.text;
+
+/**
+ * Interface for classes participating in reconciling.
+ */
+public interface IReconcilingParticipant {
+
+ /**
+ * Called after reconciling has been finished.
+ */
+ void reconciled();
+
+}
--- /dev/null
+/*
+ * 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: CssTextTools.java,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.text;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.css.core.CssCore;
+import net.sourceforge.phpeclipse.css.core.profiles.IProfile;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssCodeScanner;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssColorManager;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssCommentScanner;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssPartitionScanner;
+import net.sourceforge.phpeclipse.css.ui.internal.text.CssStringScanner;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension3;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.DefaultPartitioner;
+import org.eclipse.jface.text.rules.IPartitionTokenScanner;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Tools required to configure a CSS text viewer.
+ *
+ * <p>
+ * The color manager and all scanners exist only one time, i.e. the same
+ * instances are returned to all clients. Thus, clients share those tools.
+ * </p>
+ */
+public class CssTextTools {
+
+ // Instance Variables ------------------------------------------------------
+
+ /**
+ * The preference store to use.
+ */
+ private IPreferenceStore store;
+
+ /**
+ * Listener for changes to the preference store.
+ */
+ private IPropertyChangeListener propertyChangeListener =
+ new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ adaptToPreferenceChange(event);
+ }
+ };
+
+ /**
+ * The color manager.
+ */
+ private IColorManager colorManager;
+
+ /**
+ * The partition scanner.
+ */
+ private CssPartitionScanner partitionScanner;
+
+ /**
+ * Map of the code scanners, keyed by profile ID.
+ */
+ private Map codeScanners = new HashMap();
+
+ /**
+ * The token scanner for syntax highlighting comments in CSS source.
+ */
+ private CssCommentScanner commentScanner;
+
+ /**
+ * The token scanner for syntax highlighting string literals in CSS source.
+ */
+ private CssStringScanner stringScanner;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Creates a new CSS text tools collection.
+ *
+ * @param store the preference store to initialize the text tools. The text
+ * tools instance installs a listener on the passed preference store
+ * to adapt itself to changes in the preference store.
+ */
+ public CssTextTools(IPreferenceStore store) {
+ this(store, true);
+ }
+
+ /**
+ * Creates a new CSS text tools collection.
+ *
+ * @param store the preference store to initialize the text tools. The text
+ * tool instance installs a listener on the passed preference store
+ * to adapt itself to changes in the preference store.
+ * @param autoDisposeOnDisplayDispose if <code>true</code> the color
+ * manager automatically disposes all managed colors when the current
+ * display gets disposed and all calls to
+ * {@link org.eclipse.jface.text.source.ISharedTextColors#dispose()}
+ * are ignored.
+ */
+ public CssTextTools(IPreferenceStore store,
+ boolean autoDisposeOnDisplayDispose) {
+ store.addPropertyChangeListener(propertyChangeListener);
+ this.store = store;
+
+ colorManager = new CssColorManager(autoDisposeOnDisplayDispose);
+ partitionScanner = new CssPartitionScanner();
+ commentScanner = new CssCommentScanner(store, colorManager);
+ stringScanner = new CssStringScanner(store, colorManager);
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns whether the specified change to the preference store would effect
+ * the presentation of CSS text.
+ *
+ * @param event the preference store change event
+ * @return <code>true</code> if the specified event affects the presentation
+ * of CSS text, <code>false</code> otherwise
+ */
+ public boolean affectsPresentation(PropertyChangeEvent event) {
+ for (Iterator i = codeScanners.keySet().iterator(); i.hasNext();) {
+ CssCodeScanner scanner = (CssCodeScanner)
+ codeScanners.get(i.next());
+ if (scanner.affectsPresentation(event)) {
+ return true;
+ }
+ }
+ if (commentScanner.affectsPresentation(event)
+ || stringScanner.affectsPresentation(event)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Factory method for creating a Java-specific document partitioner
+ * using this object's partitions scanner. This method is a
+ * convenience method.
+ *
+ * @return a newly created Java document partitioner
+ */
+ public IDocumentPartitioner createDocumentPartitioner() {
+ String[] types = new String[] {
+ CssPartitionScanner.CSS_COMMENT,
+ CssPartitionScanner.CSS_STRING
+ };
+ return new DefaultPartitioner(getPartitionScanner(), types);
+ }
+
+ /**
+ * Disposes all the individual tools of this tools collection.
+ */
+ public void dispose() {
+
+ // dispose the scanners
+ codeScanners.clear();
+ commentScanner = null;
+ stringScanner = null;
+ partitionScanner = null;
+
+ // dispose the color manager
+ if (colorManager != null) {
+ colorManager.dispose();
+ colorManager = null;
+ }
+
+ // detach from the preference store
+ if (store != null) {
+ store.removePropertyChangeListener(propertyChangeListener);
+ propertyChangeListener = null;
+ store = null;
+ }
+ }
+
+ /**
+ * Returns the color manager which is used to manage
+ * any Java-specific colors needed for such things like syntax highlighting.
+ *
+ * @return the color manager to be used for Java text viewers
+ */
+ public IColorManager getColorManager() {
+ return colorManager;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan CSS source code.
+ *
+ * @param profile the profile for which to retrieve the code scanner
+ * @return a CSS source code scanner
+ */
+ public RuleBasedScanner getCodeScanner(IProfile profile) {
+ if (profile == null) {
+ // use the default profile
+ profile = CssCore.getDefault().getProfileManager().getProfile(null);
+ }
+ String profileId = profile.getDescriptor().getId();
+ RuleBasedScanner codeScanner = (RuleBasedScanner)
+ codeScanners.get(profileId);
+ if (codeScanner == null) {
+ codeScanner = new CssCodeScanner(store, this.colorManager, profile);
+ codeScanners.put(profileId, codeScanner);
+ }
+ return codeScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan CSS comments.
+ *
+ * @return a CSS comment scanner
+ */
+ public RuleBasedScanner getCommentScanner() {
+ return commentScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan CSS strings.
+ *
+ * @return a CSS string scanner
+ */
+ public RuleBasedScanner getStringScanner() {
+ return stringScanner;
+ }
+
+ /**
+ * Returns a scanner which is configured to scan CSS-specific partitions,
+ * which are comments, strings and regular code.
+ *
+ * @return a CSS partition scanner
+ */
+ public IPartitionTokenScanner getPartitionScanner() {
+ return partitionScanner;
+ }
+
+ /**
+ * Sets up the given document for the default partitioning.
+ *
+ * @param document the document to be set up
+ */
+ public void setupDocument(IDocument document) {
+ setupDocument(document, IDocumentExtension3.DEFAULT_PARTITIONING);
+ }
+
+ /**
+ * Sets up the given document for the given partitioning.
+ *
+ * @param document the document to be set up
+ * @param partitioning the document partitioning
+ */
+ public void setupDocument(IDocument document, String partitioning) {
+ IDocumentPartitioner partitioner = createDocumentPartitioner();
+ if (document instanceof IDocumentExtension3) {
+ IDocumentExtension3 extension = (IDocumentExtension3) document;
+ extension.setDocumentPartitioner(partitioning, partitioner);
+ } else {
+ document.setDocumentPartitioner(partitioner);
+ }
+ partitioner.connect(document);
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ /**
+ * Adapts the behavior of the contained components to the change according
+ * to the given event.
+ *
+ * @param event the event to which to adapt
+ */
+ protected void adaptToPreferenceChange(PropertyChangeEvent event) {
+ for (Iterator i = codeScanners.keySet().iterator(); i.hasNext();) {
+ CssCodeScanner scanner = (CssCodeScanner)
+ codeScanners.get(i.next());
+ if (scanner.affectsPresentation(event)) {
+ scanner.adaptToPreferenceChange(event);
+ }
+ }
+ if (commentScanner.affectsPresentation(event)) {
+ commentScanner.adaptToPreferenceChange(event);
+ }
+ if (stringScanner.affectsPresentation(event)) {
+ stringScanner.adaptToPreferenceChange(event);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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: IColorManager.java,v 1.1 2004-09-02 18:11:51 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.css.ui.text;
+
+import org.eclipse.jface.text.source.ISharedTextColors;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * Extends the <code>ISharedTextColors</code> interface by providing methods
+ * to bind and unbind colors to specific keys, and retrieve the colors by key.
+ *
+ * TODO Find out whether this can be replaced with the JFace ColorRegistry
+ */
+public interface IColorManager extends ISharedTextColors {
+
+ /**
+ * Binds a color to the specified key.
+ *
+ * @param key the key to which the color should be bound
+ * @param rgb the color to bind to the key
+ */
+ void bindColor(String key, RGB rgb);
+
+ /**
+ * Returns the color bound to a specific key.
+ *
+ * @param key the key to which the color was previously bound
+ * @return the color bound to the specified key, or <code>null</code> if no
+ * color was bound to that key
+ */
+ Color getColor(String key);
+
+ /**
+ * Unbinds (and disposes) a color.
+ *
+ * @param key the key to which the color was previously bound
+ */
+ void unbindColor(String key);
+
+}
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>net.sourceforge.phpeclipse.html.ui</name>
+ <comment></comment>
+ <projects>
+ <project>net.sf.wdte.ui</project>
+ <project>net.sf.wdte.xml.core</project>
+ <project>net.sf.wdte.xml.ui</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.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+source.htmlui.jar = src/
+output.htmlui.jar = bin/
+bin.includes = plugin.xml,\
+ htmlui.jar
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="net.sourceforge.phpeclipse.html.ui"
+ name="Web Development Tools HTML UI"
+ version="0.0.1"
+ provider-name="WDTE Project"
+ class="net.sourceforge.phpeclipse.html.ui.HTMLUI">
+
+ <runtime>
+ <library name="htmlui.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="net.sourceforge.phpeclipse.xml.ui"/>
+ <import plugin="net.sourceforge.phpeclipse.ui"/>
+ <import plugin="net.sourceforge.phpeclipse.xml.core"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.workbench.texteditor"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.text"/>
+ <import plugin="org.eclipse.ui.editors"/>
+ <import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.ui"/>
+ <import plugin="org.eclipse.core.filebuffers"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ </requires>
+
+
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ name="HTML Editor"
+ icon="icons/full/obj16/html.png"
+ extensions="html, htm, xhtml"
+ class="net.sourceforge.phpeclipse.html.ui.internal.editor.HTMLEditor"
+ id="net.sourceforge.phpeclipse.html.ui.editor">
+ </editor>
+ </extension>
+ <extension
+ point="org.eclipse.core.filebuffers.documentSetup">
+ <participant
+ extensions="html, htm, xhtml"
+ class="net.sourceforge.phpeclipse.html.ui.internal.editor.HTMLDocumentSetupParticipant">
+ </participant>
+ </extension>
+ <extension
+ point="org.eclipse.ui.editors.documentProviders">
+ <provider
+ extensions="html, htm, xhtml"
+ class="net.sourceforge.phpeclipse.html.ui.internal.editor.HTMLDocumentProvider"
+ id="net.sourceforge.phpeclipse.html.ui.documentProvider">
+ </provider>
+ </extension>
+
+
+</plugin>
--- /dev/null
+/*
+ * 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: HTMLUI.java,v 1.1 2004-09-02 18:13:31 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.ui;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class HTMLUI extends AbstractUIPlugin {
+
+ // Class Variables ---------------------------------------------------------
+
+ /** The shared instance. */
+ private static HTMLUI plugin;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * The constructor.
+ */
+ public HTMLUI() {
+ plugin = this;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the shared instance.
+ */
+ public static HTMLUI getDefault() {
+ return plugin;
+ }
+}
--- /dev/null
+/*
+ * 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: HTMLUIMessages.java,v 1.1 2004-09-02 18:13:32 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.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 HTMLUIMessages {
+
+ // Constants ---------------------------------------------------------------
+
+ /**
+ * Qualified name of the resource bundle containing the localized messages.
+ */
+ private static final String RESOURCE_BUNDLE =
+ "net.sourceforge.phpeclipse.html.ui.internal.HTMLUIMessages"; //$NON-NLS-1$
+
+ // Class Variables ---------------------------------------------------------
+
+ /**
+ * The resource bundle.
+ */
+ private static ResourceBundle resourceBundle =
+ ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Hidden constructor.
+ */
+ private HTMLUIMessages() {
+ // 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);
+ }
+
+}
--- /dev/null
+#
+# 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: HTMLUIMessages.properties,v 1.1 2004-09-02 18:13:32 jsurfer Exp $
+#
--- /dev/null
+/*
+ * 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: HTMLDocumentProvider.java,v 1.1 2004-09-02 18:13:32 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentProvider;
+
+/**
+ * Document provider for HTML files.
+ */
+public class HTMLDocumentProvider extends XMLDocumentProvider {
+
+}
--- /dev/null
+/*
+ * 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: HTMLDocumentSetupParticipant.java,v 1.1 2004-09-02 18:13:32 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.ui.internal.editor;
+
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentSetupParticipant;
+
+/**
+ * Document setup participant that sets up the HTML specific partitioning.
+ */
+public class HTMLDocumentSetupParticipant extends XMLDocumentSetupParticipant {
+
+}
--- /dev/null
+/*
+ * 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: HTMLEditor.java,v 1.1 2004-09-02 18:13:32 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.ui.internal.editor;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import net.sourceforge.phpeclipse.html.ui.internal.preview.HTMLPreviewPage;
+import net.sourceforge.phpeclipse.html.ui.internal.text.HTMLConfiguration;
+import net.sourceforge.phpeclipse.ui.views.preview.IBrowserPreviewPage;
+import net.sourceforge.phpeclipse.xml.ui.XMLPlugin;
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLDocumentProvider;
+import net.sourceforge.phpeclipse.xml.ui.internal.editor.XMLEditor;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.texteditor.ContentAssistAction;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+
+
+/**
+ * HTML editor implementation.
+ */
+public class HTMLEditor extends XMLEditor {
+
+ // Instance Variables ------------------------------------------------------
+
+ /** The associated preview page. */
+ private HTMLPreviewPage previewPage;
+
+ // XMLEditor Implementation ------------------------------------------------
+
+ /*
+ * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorSaved()
+ */
+ protected void editorSaved() {
+ if (previewPage != null) {
+ previewPage.update();
+ }
+ }
+
+ /*
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter == IBrowserPreviewPage.class) {
+ if (previewPage == null) {
+ previewPage = createPreviewPage();
+ }
+ return previewPage;
+ }
+ return super.getAdapter(adapter);
+ }
+
+ // Private Methods ---------------------------------------------------------
+
+ /**
+ * Creates the HTML preview page.
+ */
+ private HTMLPreviewPage createPreviewPage() {
+ IEditorInput input = getEditorInput();
+ if (input instanceof IFileEditorInput) {
+ IFile file = ((IFileEditorInput) input).getFile();
+ try {
+ URL location = file.getLocation().toFile().toURL();
+ return new HTMLPreviewPage(location);
+ } catch (MalformedURLException e) { }
+ }
+ return null;
+ }
+ protected void createActions() {
+ super.createActions();
+
+ IAction action = new ContentAssistAction(HTMLEditorMessages.getResourceBundle(),
+ "ContentAssistProposal.", this); //$NON-NLS-1$
+ action
+ .setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+ setAction("ContentAssistProposal", action); //$NON-NLS-1$
+ markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
+
+// IAction action= new TextOperationAction(
+// TemplateMessages.getResourceBundle(),
+// "Editor." + TEMPLATE_PROPOSALS + ".", //$NON-NLS-1$ //$NON-NLS-2$
+// this,
+// ISourceViewer.CONTENTASSIST_PROPOSALS);
+// action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+// setAction(TEMPLATE_PROPOSALS, action);
+// markAsStateDependentAction(TEMPLATE_PROPOSALS, true);
+ }
+ /*
+ * @see org.eclipse.ui.editors.text.TextEditor#initializeEditor()
+ */
+ protected void initializeEditor() {
+ super.initializeEditor();
+
+ XMLTextTools xmlTextTools = XMLPlugin.getDefault().getXMLTextTools();
+ setSourceViewerConfiguration(new HTMLConfiguration(xmlTextTools, this));
+ setDocumentProvider(new XMLDocumentProvider());
+ }
+}
--- /dev/null
+/**********************************************************************
+Copyright (c) 2000, 2002 IBM Corp. 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 implementation
+ Klaus Hartlage - www.eclipseproject.de
+**********************************************************************/
+package net.sourceforge.phpeclipse.html.ui.internal.editor;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class HTMLEditorMessages {
+
+ private static final String RESOURCE_BUNDLE= "net.sourceforge.phpeclipse.html.ui.internal.editor.HTMLEditorMessages";//$NON-NLS-1$
+
+ private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
+
+ private HTMLEditorMessages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return fgResourceBundle.getString(key);
+ } catch (MissingResourceException e) {
+ return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Gets a string from the resource bundle and formats it with arguments
+ */
+ public static String getFormattedString(String key, Object[] args) {
+ return MessageFormat.format(getString(key), args);
+ }
+
+ public static ResourceBundle getResourceBundle() {
+ return fgResourceBundle;
+ }
+}
--- /dev/null
+#############################################################
+#
+# (c) Copyright IBM Corp. 2000, 2001.
+# All Rights Reserved.
+#
+#############################################################
+ContentAssistProposal.label=Content Assist@Ctrl+SPACE
+ContentAssistProposal.tooltip=Content Assist
+ContentAssistProposal.image=
+ContentAssistProposal.description=Content Assist
--- /dev/null
+/*
+ * 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: HTMLPreviewPage.java,v 1.1 2004-09-02 18:13:31 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.html.ui.internal.preview;
+
+import java.net.URL;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.LocationAdapter;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.part.Page;
+import org.eclipse.ui.texteditor.IUpdate;
+
+import net.sourceforge.phpeclipse.ui.views.preview.IBrowserPreviewPage;
+
+/**
+ * Provides a HTML preview page based on the SWT browser control.
+ */
+public class HTMLPreviewPage extends Page
+ implements IBrowserPreviewPage, IUpdate {
+
+ // Instance Variables ------------------------------------------------------
+
+ /** The browser widget. */
+ private Browser browser;
+
+ /** The URL of the resource to preview. */
+ private URL location;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param location the URL of the resource to preview
+ */
+ public HTMLPreviewPage(URL location) {
+ this.location = location;
+ }
+
+ // IPage Implementation ----------------------------------------------------
+
+ /*
+ * @see org.eclipse.ui.part.IPage#createControl(Composite)
+ */
+ public void createControl(Composite parent) {
+ browser = new Browser(parent, SWT.NONE);
+ browser.setLayout(new FillLayout());
+ browser.setUrl(location.toString());
+ browser.addLocationListener(new LocationAdapter() {
+ public void changing(LocationEvent event) {
+ if (event.location != null) {
+ event.doit = false;
+ }
+ }
+ });
+ }
+
+ /*
+ * @see org.eclipse.ui.part.IPage#getControl()
+ */
+ public Control getControl() {
+ return browser;
+ }
+
+ /*
+ * @see org.eclipse.ui.part.IPage#setFocus()
+ */
+ public void setFocus() {
+ browser.setFocus();
+ }
+
+ // IUpdate Implementation --------------------------------------------------
+
+ /*
+ * @see IUpdate#update()
+ */
+ public void update() {
+ browser.refresh();
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * 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.html.ui.internal.text;
+
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.templates.template.BasicCompletionProcessor;
+import net.sourceforge.phpeclipse.ui.templates.template.HTMLContextType;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+
+/**
+ * A completion processor for XML templates.
+ */
+public class HTMLCompletionProcessor extends BasicCompletionProcessor {
+
+ /**
+ * Return the XML context type that is supported by this plugin.
+ */
+ protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) {
+ return WebUI.getDefault().getContextTypeRegistry().getContextType(HTMLContextType.HTML_CONTEXT_TYPE);
+ }
+
+
+}
--- /dev/null
+/*
+ * Created on 25.08.2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sourceforge.phpeclipse.html.ui.internal.text;
+
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLConfiguration;
+import net.sourceforge.phpeclipse.xml.ui.internal.text.XMLPartitionScanner;
+import net.sourceforge.phpeclipse.xml.ui.text.XMLTextTools;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * @author khartlage
+ *
+ * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code Style - Code Templates
+ */
+public class HTMLConfiguration extends XMLConfiguration {
+ public HTMLConfiguration(XMLTextTools tools) {
+ this(tools, null);
+ }
+
+ public HTMLConfiguration(XMLTextTools tools, ITextEditor editor) {
+ super(tools, editor);
+ }
+
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ ContentAssistant assistant = new ContentAssistant();
+ assistant.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+ IContentAssistProcessor processor = new HTMLCompletionProcessor();
+ assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_TAG);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_PI);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_COMMENT);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_DECL);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_TAG);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_ATTRIBUTE);
+ assistant.setContentAssistProcessor(processor, XMLPartitionScanner.XML_CDATA);
+
+ assistant.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
+ assistant.setInformationControlCreator(getInformationControlCreator(sourceViewer));
+
+ return assistant;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>net.sourceforge.phpeclipse.js.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+bin.includes = icons/,\
+ jseditorsrc.zip,\
+ plugin.xml,\
+ plugin.properties,\
+ net.sf.wdte.js.core.jar
+src.includes = src/,\
+ scripts/,\
+ plugin.xml,\
+ build.properties,\
+ .project,\
+ .classpath,\
+ plugin.properties
+source.net.sf.wdte.js.core.jar = src/
+jars.compile.order = net.sf.wdte.js.core.jar
+output.net.sf.wdte.js.core.jar = bin/
--- /dev/null
+#
+# 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:14:39 jsurfer Exp $
+#
+
+pluginName = Web Development Tools JavaScript Core
+providerName= WDTE Project
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="net.sourceforge.phpeclipse.js.core"
+ name="%pluginName"
+ version="0.0.9"
+ provider-name="%providerName"
+ class="net.sourceforge.phpeclipse.js.core.JSCorePlugin">
+
+ <runtime>
+ <library name="net.sourceforge.phpeclipse.js.core.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.swt"/>
+ </requires>
+
+ <extension point="org.eclipse.team.core.fileTypes">
+ <fileTypes type="text" extension="js"/>
+ </extension>
+
+</plugin>
--- /dev/null
+/*
+ * $RCSfile: JSCorePlugin.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.2 2004/05/22 16:14:37 l950637
+ * Adapt for Eclipse 3.0M9
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.3 2003/12/10 20:19:16 agfitzp
+ * 3.0 port
+ *
+ * Revision 1.2 2003/06/21 03:48:51 agfitzp
+ * fixed global variables as functions bug
+ * fixed length calculation of instance variables
+ * Automatic outlining is now a preference
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Plugin;
+
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class JSCorePlugin extends Plugin
+{
+ //The shared instance.
+ private static JSCorePlugin plugin;
+
+ //Resource bundle.
+ private ResourceBundle resourceBundle;
+
+ private boolean defaultsInitialized = false;
+
+ /**
+ * current func list
+ */
+ private List currentFunctions = new LinkedList();
+
+ /**
+ * The constructor.
+ * @param descriptor
+ */
+ public JSCorePlugin() {
+ plugin = this;
+
+ try {
+ resourceBundle = ResourceBundle.getBundle("net.sourceforge.phpeclipse.js.core.JSCorePluginResources");
+ } catch(MissingResourceException x) {
+ resourceBundle = null;
+ }
+ }
+
+ /**
+ * Returns the shared instance.
+ * @return
+ */
+ public static JSCorePlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns the workspace instance.
+ * @return
+ */
+ public static IWorkspace getWorkspace() {
+ return ResourcesPlugin.getWorkspace();
+ }
+
+ /**
+ * Returns the string from the plugin's resource bundle, or 'key' if not found.
+ * @param key
+ *
+ * @return
+ */
+ public static String getResourceString(String key) {
+ ResourceBundle bundle = JSCorePlugin.getDefault().getResourceBundle();
+
+ try {
+ return bundle.getString(key);
+ } catch(MissingResourceException e) {
+ return key;
+ }
+ }
+
+ /**
+ * Returns the plugin's resource bundle,
+ * @return
+ */
+ public ResourceBundle getResourceBundle() {
+ return resourceBundle;
+ }
+
+ /**
+ * Returns the currentFunctions.
+ * @return List
+ */
+ public List getCurrentFunctions() {
+ return currentFunctions;
+ }
+
+ /**
+ * Sets the currentFunctions.
+ * @param currentFunctions The currentFunctions to set
+ */
+ public void setCurrentFunctions(List currentFunctions) {
+ this.currentFunctions = currentFunctions;
+ }
+}
--- /dev/null
+/*
+ * Created on May 15, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *
+ *========================================================================
+*/
+package net.sourceforge.phpeclipse.js.core.model;
+
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSClassElement extends JSElement
+{
+ protected HashMap childrenByName;
+ protected boolean isPrototype = false;
+
+ /**
+ * @param aName
+ * @param offset
+ * @param length
+ */
+ public JSClassElement(IFile aFile, String aName, int offset, int length)
+ {
+ super(aFile, aName, offset, length);
+ childrenByName = new HashMap();
+ }
+
+ public void addChildElement(JSElement anElement)
+ {
+ String elementName = anElement.getName();
+ if(!childrenByName.containsKey(elementName))
+ {
+ this.children.add(anElement);
+ this.childrenByName.put(elementName, anElement);
+ anElement.setParent(this);
+ }
+ }
+
+ public int category()
+ {
+ return CLASS;
+ }
+
+ /**
+ * @return
+ */
+ public boolean isPrototype()
+ {
+ return isPrototype;
+ }
+
+ /**
+ * @param b
+ */
+ public void setPrototype(boolean b)
+ {
+ isPrototype = b;
+ }
+
+}
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSClassMethodElement extends JSFunctionElement
+{
+ public JSClassMethodElement(IFile aFile, String aName, String argumentString, int offset, int length)
+ {
+ super(aFile, aName, argumentString, offset, length);
+ }
+
+
+ public int category()
+ {
+ return CLASS_METHOD;
+ }
+
+}
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSClassVariableElement extends JSElement
+{
+
+ /**
+ * @param aName
+ * @param offset
+ * @param length
+ */
+ public JSClassVariableElement(IFile aFile, String aName, int offset, int length)
+ {
+ super(aFile, aName, offset, length);
+ }
+
+ public int category()
+ {
+ return CLASS_VARIABLE;
+ }
+
+}
--- /dev/null
+/*
+ * $RCSfile: JSElement.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.2 2004/02/27 18:28:10 cell
+ * Make model elements platform objects so they are automatically adapted
+ *
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:08 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.model;
+
+import java.util.List;
+import java.util.LinkedList;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.PlatformObject;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Addi
+ */
+abstract public class JSElement extends PlatformObject
+ implements JSElementCategories
+{
+ protected IFile file;
+ protected String name;
+ protected int offset;
+ protected int numberOfLines;
+ protected int length;
+
+ protected JSElement parent;
+ protected List children;
+
+ /**
+ * Creates a new JSElement and stores parent element and location in the text.
+ *
+ * @param aName text corresponding to the func
+ * @param offset the offset into the text
+ * @param length the length of the element
+ */
+ public JSElement(IFile aFile, String aName, int offset, int length)
+ {
+ this.file = aFile;
+ this.name = aName;
+ this.offset = offset;
+ this.length = length;
+ this.children = new LinkedList();
+ }
+
+ /**
+ * Method declared on IWorkbenchAdapter
+ * @param o
+ *
+ * @return
+ */
+ public String getLabel(Object o)
+ {
+ return name;
+ }
+
+ /**
+ * Returns the number of characters in this section.
+ * @return
+ */
+ public int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * Returns the number of lines in the element.
+ *
+ * @return the number of lines in the element
+ */
+ public int getNumberOfLines()
+ {
+ return numberOfLines;
+ }
+
+ /**
+ * Returns the offset of this section in the file.
+ * @return
+ */
+ public int getStart()
+ {
+ return offset;
+ }
+
+ /**
+ * Sets the number of lines in the element
+ *
+ * @param newNumberOfLines the number of lines in the element
+ */
+ public void setNumberOfLines(int newNumberOfLines)
+ {
+ numberOfLines = newNumberOfLines;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return getLabel(this);
+ }
+
+ /**
+ * @see org.eclipse.ui.model.IWorkbenchAdapter#getChildren(Object)
+ */
+ public Object[] getChildren(Object o)
+ {
+ Object[] result = new Object[children.size()];
+ return children.toArray(result);
+ }
+
+ /**
+ * @see org.eclipse.ui.model.IWorkbenchAdapter#getParent(Object)
+ */
+ public Object getParent(Object o)
+ {
+ return null;
+ }
+
+ /**
+ *
+ * @return A category enumeration for sub-types.
+ */
+ abstract public int category();
+
+ /**
+ * @return
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * @return
+ */
+ public int getOffset()
+ {
+ return offset;
+ }
+
+ /**
+ * @return
+ */
+ public JSElement getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * @param element
+ */
+ protected void setParent(JSElement element)
+ {
+ parent = element;
+ }
+
+ /**
+ * @param anElement
+ * @return
+ */
+ public boolean sharesParentWith(JSElement anElement)
+ {
+ if(parent == null) {
+ return anElement.getParent() == null;
+ }
+
+ return parent.equals(anElement.getParent());
+ }
+
+ /**
+ * @param anElement
+ * @return
+ */
+ public boolean equals(JSElement anElement)
+ {
+ return sharesParentWith(anElement) && name.equals(anElement.getName());
+ }
+
+ /**
+ * @return Returns the file.
+ */
+ public IFile getFile() {
+ return file;
+ }
+
+ /**
+ * @param file The file to set.
+ */
+ protected void setFile(IFile file) {
+ this.file = file;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+/**
+ * @author fitzpata
+ *
+ */
+public interface JSElementCategories
+{
+ static final int CLASS = 1;
+ static final int FUNCTION = 2;
+ static final int VARIABLE = 3;
+ static final int CLASS_VARIABLE = 4;
+ static final int INSTANCE_VARIABLE = 5;
+ static final int CLASS_METHOD = 6;
+ static final int INSTANCE_METHOD = 7;
+}
--- /dev/null
+/*
+ * $RCSfile: JSElementList.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.2 2004/02/27 18:28:10 cell
+ * Make model elements platform objects so they are automatically adapted
+ *
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.1 2003/05/30 20:53:08 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ * Revision 1.1 2003/05/28 15:17:11 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.PlatformObject;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Addi
+ */
+public class JSElementList extends PlatformObject
+{
+ protected List children = new ArrayList();
+
+ /**
+ * Creates a new adaptable list with the given children.
+ */
+ public JSElementList()
+ {
+ }
+
+ /**
+ * Creates a new adaptable list with the given children.
+ * @param newChildren
+ */
+ public JSElementList(JSElement[] newChildren)
+ {
+ for (int i = 0; i < newChildren.length; i++)
+ {
+ children.add(newChildren[i]);
+ }
+ }
+
+ /**
+ * Creates a new adaptable list with the given children.
+ * @param newChildren
+ */
+ public JSElementList(List newChildren)
+ {
+ for (int i = 0; i < newChildren.size(); i++)
+ {
+ children.add(newChildren.get(i));
+ }
+ }
+
+ /**
+ * Adds all the adaptable objects in the given enumeration to this list. Returns this list.
+ * @param iterator
+ *
+ * @return
+ */
+ public JSElementList add(Iterator iterator)
+ {
+ while (iterator.hasNext())
+ {
+ add((JSElement) iterator.next());
+ }
+
+ return this;
+ }
+
+ /**
+ * Adds the given adaptable object to this list. Returns this list.
+ * @param adaptable
+ *
+ * @return
+ */
+ public JSElementList add(JSElement anElement)
+ {
+ children.add(anElement);
+
+ return this;
+ }
+
+ /**
+ * Returns the elements in this list.
+ * @return
+ */
+ public Object[] getChildren()
+ {
+ return children.toArray();
+ }
+
+ /**
+ *
+ *
+ * @param o
+ *
+ * @return
+ */
+ public Object[] getChildren(Object o)
+ {
+ return children.toArray();
+ }
+
+ /**
+ *
+ *
+ * @param object
+ *
+ * @return
+ */
+ public String getLabel(Object object)
+ {
+ return object == null ? "" : object.toString();
+ }
+
+ /**
+ *
+ *
+ * @param object
+ *
+ * @return
+ */
+ public Object getParent(Object object)
+ {
+ return null;
+ }
+
+ /**
+ * Removes the given adaptable object from this list.
+ * @param adaptable
+ */
+ public void remove(JSElement anElement)
+ {
+ children.remove(anElement);
+ }
+
+ /**
+ * Returns the number of items in the list
+ * @return
+ */
+ public int size()
+ {
+ return children.size();
+ }
+
+ public JSElement findEquivilent(JSElement anElement)
+ {
+ for(int i = 0; i < size();i++)
+ {
+ JSElement aCandidate = (JSElement) children.get(i);
+ if(anElement.equals(aCandidate))
+ {
+ return aCandidate;
+ }
+ }
+
+
+ return null;
+ }
+
+ public JSElement get(int index)
+ {
+ if(index >= size())
+ {
+ return null;
+ }
+ return (JSElement) children.get(index);
+ }
+
+ /**
+ * @return
+ */
+ public IAdaptable asAdaptable() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Created on May 15, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ */
+public class JSFunctionElement extends JSElement
+{
+
+ protected String arguments;
+ /**
+ * @param aName
+ * @param offset
+ * @param length
+ */
+ public JSFunctionElement(IFile aFile, String aName, String argumentString, int offset, int length)
+ {
+ super(aFile, aName, offset, length);
+ arguments = argumentString;
+ }
+
+ /**
+ * Method declared on IWorkbenchAdapter
+ * @param o
+ *
+ * @return
+ */
+ public String getLabel(Object o)
+ {
+ String firstPart = name;
+ if(firstPart.length() <= 0){
+ firstPart = "<anonymous>";
+ }
+
+ return firstPart + arguments;
+ }
+
+ public int category()
+ {
+ return FUNCTION;
+ }
+
+ /**
+ * @return
+ */
+ public String getArguments()
+ {
+ return arguments;
+ }
+
+}
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSGlobalVariableElement extends JSElement
+{
+
+ /**
+ * @param aName
+ * @param offset
+ * @param length
+ */
+ public JSGlobalVariableElement(IFile aFile, String aName, int offset, int length)
+ {
+ super(aFile, aName, offset, length);
+ }
+
+ public int category()
+ {
+ return VARIABLE;
+ }
+
+}
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSInstanceMethodElement extends JSFunctionElement
+{
+ public JSInstanceMethodElement(IFile aFile, String aName, String argumentString, int offset, int length)
+ {
+ super(aFile, aName, argumentString, offset, length);
+ }
+
+ public int category()
+ {
+ return INSTANCE_METHOD;
+ }
+
+}
--- /dev/null
+/*
+ * Created on May 20, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * @author fitzpata
+ *
+ */
+public class JSInstanceVariableElement extends JSElement
+{
+
+ /**
+ * @param aName
+ * @param offset
+ * @param length
+ */
+ public JSInstanceVariableElement(IFile aFile, String aName, int offset, int length)
+ {
+ super(aFile, aName, offset, length);
+ }
+
+ public int category()
+ {
+ return INSTANCE_VARIABLE;
+ }
+
+}
--- /dev/null
+/*
+ * $RCSfile: JSParser.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.6 2003/12/10 20:19:16 agfitzp
+ * 3.0 port
+ *
+ * Revision 1.5 2003/06/21 03:48:51 agfitzp
+ * fixed global variables as functions bug
+ * fixed length calculation of instance variables
+ * Automatic outlining is now a preference
+ *
+ * Revision 1.4 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ * Revision 1.3 2003/05/28 20:47:58 agfitzp
+ * Outline the document, not the file.
+ *
+ * Revision 1.2 2003/05/28 15:20:00 agfitzp
+ * Trivial change to test CVS commit
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.js.core.model.*;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.IToken;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Addi
+ */
+public class JSParser
+{
+
+ public static final String FUNCTION = "function";
+
+ /**
+ * line separator
+ */
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ /**
+ * Array of system types to ignore.
+ */
+ private static String[] systemClassNames= {"Array","String"};
+
+
+ protected HashMap systemClassMap = new HashMap();
+
+ protected IFile sourceFile;
+ protected IDocument sourceDocument;
+ protected HashMap functions = new HashMap();
+ protected HashMap classes = new HashMap();
+ protected HashMap globalVariables = new HashMap();
+ protected List elementList = new LinkedList();
+ protected JSSyntaxScanner scanner = new JSSyntaxScanner();
+
+ /**
+ * Constructor for JSParser.
+ */
+ public JSParser()
+ {
+ super();
+
+ int i;
+
+ for(i = 0;i < systemClassNames.length; i++)
+ {
+ String aName = systemClassNames[i];
+ systemClassMap.put(aName, aName);
+ }
+ }
+
+ /**
+ * Returns a string containing the contents of the given file. Returns an empty string if there
+ * were any errors reading the file.
+ * @param file
+ *
+ * @return
+ */
+ protected static String getText(IFile file)
+ {
+ try
+ {
+ InputStream in = file.getContents();
+ return streamToString(in);
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ protected static String streamToString(InputStream in) throws IOException
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int read = in.read(buf);
+
+ while (read > 0)
+ {
+ out.write(buf, 0, read);
+ read = in.read(buf);
+ }
+
+ return out.toString();
+ }
+
+ /**
+ * Skips ahead and finds next non-whitespace token.
+ *
+ */
+ public IToken nextNonWhitespaceToken()
+ {
+ IToken aToken = scanner.nextToken();
+
+ while (!aToken.isEOF() && aToken.isWhitespace())
+ {
+ aToken = scanner.nextToken();
+ }
+
+ return aToken;
+ }
+
+ /**
+ * Parses the input given by the argument.
+ *
+ * @param file the element containing the input text
+ *
+ * @return an element collection representing the parsed input
+ */
+ public List parse(IFile file)
+ {
+ this.sourceFile = file;
+ return parse(new Document(getText(file)));
+ }
+
+ /**
+ * Parses the input given by the argument.
+ *
+ * @param aSourceDocument the element containing the input text
+ *
+ * @return an element collection representing the parsed input
+ */
+ public List parse(IDocument aSourceDocument)
+ {
+ sourceDocument = aSourceDocument;
+
+ scanner.setRange(sourceDocument, 0, sourceDocument.getLength());
+ IToken token = scanner.nextToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (token.equals(JSSyntaxScanner.TOKEN_FUNCTION))
+ {
+ addFunction(expression, offset, length);
+ }
+
+ if (token.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ //We need to check if the token is already a function or class
+ if (functions.containsKey(expression) || classes.containsKey(expression))
+ {
+ token = nextNonWhitespaceToken();
+ if (token.equals(JSSyntaxScanner.TOKEN_MEMBER))
+ {
+ detectInstanceMethod(offset, expression);
+ } else
+ {
+ detectClassMethod(token, offset, expression);
+ }
+ } else
+ {
+ if (expression.equals("var"))
+ {
+ detectGlobalVariable();
+ }
+ }
+ }
+ token = scanner.nextToken();
+ }
+ return elementList;
+ }
+
+ private void addFunction(String expression, int offset, int length)
+ {
+ String functionSignature = getNaked(expression);
+ int braceOffset = functionSignature.indexOf("(");
+ String functionName = functionSignature.substring(0, braceOffset).trim();
+ String arguments =
+ functionSignature.substring(functionSignature.indexOf("("), functionSignature.indexOf(")") + 1);
+
+ if (functionName.indexOf(".") >= 0)
+ {
+ //If the function signature includes .prototype. then it's a member.
+ if (functionName.indexOf(".prototype.") >= 0)
+ {
+ String className = functionName.substring(0, functionName.indexOf("."));
+ String memberName = functionName.substring(functionName.lastIndexOf(".") + 1);
+ JSInstanceMethodElement aMethod =
+ this.addInstanceMethod(memberName, className, arguments, offset, offset, length);
+ detectInstanceMethodContext(className, aMethod);
+ } else
+ {
+ String className = functionName.substring(0, functionName.indexOf("."));
+ if (functions.containsKey(className) || classes.containsKey(className))
+ {
+ String memberName = functionName.substring(functionName.lastIndexOf(".") + 1);
+ JSFunctionElement aMethod =
+ this.addClassMethod(memberName, className, arguments, offset, offset, length);
+ }
+ }
+ } else
+ {
+ if(! functions.containsKey(functionName))
+ {
+ JSFunctionElement aFunction = new JSFunctionElement(this.sourceFile, functionName, arguments, offset, length);
+
+ elementList.add(aFunction);
+ functions.put(functionName, aFunction);
+
+ detectFunctionContext(aFunction);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void checkForSpecialGlobalTypes(JSGlobalVariableElement aVariable)
+ {
+ IToken token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ if(!checkForDynamicClass(aVariable, token))
+ {
+ checkForAnonymousFunction(aVariable, token);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private boolean checkForDynamicClass(JSGlobalVariableElement aVariable, IToken rhsToken)
+ {
+ if (rhsToken.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("new"))
+ {
+ IToken token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ if (token.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ expression = getExpression(offset, length);
+
+ if(! isSystemClass(expression))
+ {
+ JSClassElement aClass = findOrCreateClass(aVariable.getName());
+ if(aClass != null)
+ {
+ //Tell the class it's dynamically declared: what we will parse as class methods & vars are really instance methods & vars
+ aClass.setPrototype(true);
+
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ */
+ private boolean checkForAnonymousFunction(JSGlobalVariableElement aVariable, IToken rhsToken)
+ {
+ if (rhsToken.equals(JSSyntaxScanner.TOKEN_FUNCTION))
+ {
+ String functionName = aVariable.getName();
+ int offset = aVariable.getOffset();
+ int length = aVariable.getLength();
+
+ int functionOffset = scanner.getTokenOffset();
+ int functionLength = scanner.getTokenLength();
+ String functionSignature =
+ getExpression(functionOffset, functionLength);
+ String arguments = getArgumentString(functionSignature);
+
+ JSFunctionElement aFunction = new JSFunctionElement(this.sourceFile, functionName, arguments, offset, functionOffset - offset + functionLength);
+
+ elementList.add(aFunction);
+ functions.put(functionName, aFunction);
+
+ elementList.remove(aVariable);
+ globalVariables.remove(functionName);
+
+ detectFunctionContext(aFunction);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ */
+ private String getExpression(int offset, int length)
+ {
+ String expression;
+ try {
+ expression = sourceDocument.get(offset, length);//sourceBuffer.substring(offset, offset + length);
+ } catch(BadLocationException e)
+ {
+ expression = "";
+ }
+ return expression;
+ }
+
+ /**
+ *
+ */
+ private void detectGlobalVariable()
+ {
+ IToken token;
+ int length;
+ int offset;
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ if (token.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ int varOffset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ String variableName = getExpression(varOffset, length);
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+ if (expression.equals("="))
+ {
+ JSGlobalVariableElement aVariable = addGlobalVariable(variableName, varOffset);
+ checkForSpecialGlobalTypes(aVariable);
+ }
+ }
+ }
+ }
+ }
+
+ private void detectClassMethod(IToken token, int classOffset, String className)
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("."))
+ {
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ String memberName = getExpression(offset, length);
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ expression = getExpression(offset, length);
+ if (expression.equals("="))
+ {
+
+ token = nextNonWhitespaceToken();
+ int tokenOffset = scanner.getTokenOffset();
+ int tokenLength = scanner.getTokenLength();
+
+ if (token.equals(JSSyntaxScanner.TOKEN_FUNCTION))
+ {
+ String functionSignature = getExpression(tokenOffset, tokenLength);
+ String arguments = getArgumentString(functionSignature);
+
+ JSFunctionElement aMethod =
+ addClassMethod(memberName, className, arguments, classOffset, tokenOffset, tokenLength);
+
+
+ } else
+ {
+ addClassVariable(memberName, className, classOffset);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private String getArgumentString(String functionSignature)
+ {
+ return functionSignature.substring(
+ functionSignature.indexOf("("),
+ functionSignature.indexOf(")") + 1);
+ }
+
+ private void detectInstanceMethod(int classOffset, String className)
+ {
+ String expression;
+ IToken token;
+ int length;
+ int offset;
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ expression = getExpression(offset, length);
+
+ if (expression.equals("."))
+ {
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ String memberName = getExpression(offset, length);
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ expression = getExpression(offset, length);
+ if (expression.equals("="))
+ {
+ token = nextNonWhitespaceToken();
+ if (token.equals(JSSyntaxScanner.TOKEN_FUNCTION))
+ {
+ int functionOffset = scanner.getTokenOffset();
+ int functionLength = scanner.getTokenLength();
+ String functionSignature =
+ getExpression(functionOffset, functionLength);
+ String arguments = getArgumentString(functionSignature);
+
+ JSInstanceMethodElement aMethod =
+ addInstanceMethod(
+ memberName,
+ className,
+ arguments,
+ classOffset,
+ functionOffset,
+ functionLength);
+
+ detectInstanceMethodContext(className, aMethod);
+
+ } else
+ {
+ addInstanceVariable(memberName, className, classOffset, (".prototype.").length());
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void parseInstanceMethodContext(String className, JSFunctionElement aMethod)
+ {
+ IToken token;
+
+ token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ // if (token.equals(JSSyntaxScanner.TOKEN_END_CONTEXT))
+ if (expression.equals("}"))
+ {
+ return;
+ } else if (expression.equals("{"))
+ {
+ parseInstanceMethodContext(className, aMethod);
+ } else if (token.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ if (expression.equals("this"))
+ {
+ handleThisReference(className, offset);
+ }
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private void detectInstanceMethodContext(String className, JSFunctionElement aMethod)
+ {
+ IToken token;
+
+ token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ // if (token.equals(JSSyntaxScanner.TOKEN_BEGIN_CONTEXT))
+ if (expression.equals("{"))
+ {
+ parseInstanceMethodContext(className, aMethod);
+ return;
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private void parseClassMethodContext(JSFunctionElement aMethod)
+ {
+ IToken token;
+
+ token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("}"))
+ {
+ return;
+ } else if (expression.equals("{"))
+ {
+ parseClassMethodContext(aMethod);
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private void detectClassMethodContext(JSFunctionElement aMethod)
+ {
+ IToken token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("{"))
+ {
+ parseClassMethodContext(aMethod);
+ return;
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private void handleThisReference(String className, int expressionStart)
+ {
+ IToken token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+
+ String expression = getExpression(offset, length);
+
+ if(expression.equals("."))
+ {
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ int memberStart = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+
+ String memberName = getExpression(memberStart, length);
+
+ token = nextNonWhitespaceToken();
+ if (!token.isEOF())
+ {
+ offset = scanner.getTokenOffset();
+ length = scanner.getTokenLength();
+ expression = getExpression(offset, length);
+
+ if (expression.equals("="))
+ {
+ addInstanceVariable(memberName, className, expressionStart, 1 + 4 - className.length());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void parseFunctionContext(JSFunctionElement aFunction)
+ {
+ IToken token;
+
+ token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("}"))
+ {
+ return;
+ } else if (expression.equals("{"))
+ {
+ parseFunctionContext(aFunction);
+ } else if (token.equals(JSSyntaxScanner.TOKEN_DEFAULT))
+ {
+ if (expression.equals("this"))
+ {
+ handleThisReference(aFunction.getName(), offset);
+ }
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private void detectFunctionContext(JSFunctionElement aFunction)
+ {
+ IToken token = nextNonWhitespaceToken();
+ while (!token.isEOF())
+ {
+ int offset = scanner.getTokenOffset();
+ int length = scanner.getTokenLength();
+ String expression = getExpression(offset, length);
+
+ if (expression.equals("{"))
+ {
+ parseFunctionContext(aFunction);
+ return;
+ }
+
+ token = nextNonWhitespaceToken();
+ }
+ }
+
+ private JSInstanceMethodElement addInstanceMethod(
+ String memberName,
+ String className,
+ String arguments,
+ int classOffset,
+ int functionOffset,
+ int functionLength)
+ {
+ int signatureLength = functionOffset - classOffset + functionLength;
+ JSInstanceMethodElement aMethod =
+ new JSInstanceMethodElement(this.sourceFile, memberName, arguments, classOffset, signatureLength);
+
+ findOrCreateClass(className).addChildElement(aMethod);
+
+ return aMethod;
+ }
+
+ private JSFunctionElement addClassMethod(
+ String memberName,
+ String className,
+ String arguments,
+ int classOffset,
+ int functionOffset,
+ int functionLength)
+ {
+ JSClassElement aClass = findOrCreateClass(className);
+ int signatureLength = functionOffset - classOffset + functionLength;
+ JSFunctionElement aMethod;
+
+ if(aClass.isPrototype()) {
+ aMethod = new JSInstanceMethodElement(this.sourceFile, memberName, arguments, classOffset, signatureLength);
+
+ aClass.addChildElement(aMethod);
+ detectInstanceMethodContext(className, aMethod);
+ } else {
+ aMethod = new JSClassMethodElement(this.sourceFile, memberName, arguments, classOffset, signatureLength);
+
+ aClass.addChildElement(aMethod);
+ detectClassMethodContext(aMethod);
+ }
+
+ return aMethod;
+ }
+
+ /**
+ * @param memberName
+ * @param className
+ * @param classOffset
+ * @return
+ */
+ private JSElement addClassVariable(String memberName, String className, int classOffset)
+ {
+ //One extra char for "."
+ JSElement aVariable;
+ JSClassElement aClass = findOrCreateClass(className);
+
+ if(aClass.isPrototype())
+ {
+ aVariable = new JSInstanceVariableElement(this.sourceFile, memberName, classOffset, className.length() + memberName.length() + 1);
+
+ } else {
+ aVariable = new JSClassVariableElement(this.sourceFile, memberName, classOffset, className.length() + memberName.length() + 1);
+ }
+ aClass.addChildElement(aVariable);
+
+ return aVariable;
+ }
+
+ private JSInstanceVariableElement addInstanceVariable(
+ String memberName,
+ String className,
+ int classOffset,
+ int paddingWidth)
+ {
+ //11 extra chars for ".prototype."
+ JSInstanceVariableElement aVariable =
+ new JSInstanceVariableElement(
+ this.sourceFile,
+ memberName,
+ classOffset,
+ className.length() + memberName.length() + paddingWidth);
+
+ findOrCreateClass(className).addChildElement(aVariable);
+
+ return aVariable;
+ }
+
+ private JSGlobalVariableElement addGlobalVariable(String variableName, int offset)
+ {
+ JSGlobalVariableElement aVariable;
+ if (!globalVariables.containsKey(variableName))
+ {
+ aVariable = new JSGlobalVariableElement(this.sourceFile, variableName, offset, variableName.length());
+
+ elementList.add(aVariable);
+ globalVariables.put(variableName, aVariable);
+ } else
+ {
+ aVariable = (JSGlobalVariableElement) classes.get(variableName);
+ }
+
+ return aVariable;
+ }
+
+ private JSClassElement findOrCreateClass(String className)
+ {
+ JSClassElement aClass = null;
+ if (!classes.containsKey(className))
+ {
+ if(functions.containsKey(className))
+ {
+ //if we're creating a class from an existing function we must
+ //migrate the existing function to become a constructor in the class.
+ JSFunctionElement constructor = (JSFunctionElement) functions.get(className);
+
+ aClass = new JSClassElement(this.sourceFile, className, constructor.getStart(), constructor.getLength());
+ aClass.addChildElement(constructor);
+
+ elementList.remove(constructor);
+ elementList.add(aClass);
+ classes.put(className, aClass);
+ } else if(globalVariables.containsKey(className))
+ {
+ //if we're creating a class from an existing global variable we must
+ //migrate the existing function to become a constructor in the class.
+ JSGlobalVariableElement aVariable = (JSGlobalVariableElement) globalVariables.get(className);
+
+ aClass = new JSClassElement(this.sourceFile, className, aVariable.getStart(), aVariable.getLength());
+
+ elementList.remove(aVariable);
+ elementList.add(aClass);
+ classes.put(className, aClass);
+ globalVariables.remove(className);
+ } else {
+ //The final case is if we have no idea where this class came from, but shouldn't be ignored.
+ aClass = new JSClassElement(this.sourceFile, className, 0, 0);
+
+ elementList.add(aClass);
+ classes.put(className, aClass);
+ }
+ } else
+ {
+ aClass = (JSClassElement) classes.get(className);
+ }
+
+ return aClass;
+ }
+
+ public boolean isSystemClass(String aClassName)
+ {
+ return systemClassMap.containsKey(aClassName);
+ }
+
+ /**
+ * Method getNaked.
+ * @param funcName
+ */
+ private String getNaked(String funcName)
+ {
+ if (funcName == null)
+ {
+ return null;
+ }
+
+ funcName = funcName.trim().substring(FUNCTION.length()).trim();
+ funcName = replaceInString(funcName.trim(), LINE_SEPARATOR, "");
+
+ StringBuffer strBuf = new StringBuffer("");
+ int len = funcName.length();
+ boolean wasSpace = false;
+ for (int i = 0; i < len; i++)
+ {
+ char ch = funcName.charAt(i);
+ if (ch == ' ')
+ {
+ wasSpace = true;
+ } else // not space
+ {
+ if (wasSpace)
+ {
+ strBuf.append(' ');
+ }
+ strBuf.append(ch);
+ wasSpace = false;
+ }
+ }
+ return strBuf.toString();
+ }
+
+ /**
+ * replace in a string a string sequence with another string sequence
+ */
+ public static String replaceInString(String source, String whatBefore, String whatAfter)
+ {
+ if (null == source || source.length() == 0)
+ {
+ return source;
+ }
+ int beforeLen = whatBefore.length();
+ if (beforeLen == 0)
+ {
+ return source;
+ }
+ StringBuffer result = new StringBuffer("");
+ int lastIndex = 0;
+ int index = source.indexOf(whatBefore, lastIndex);
+ while (index >= 0)
+ {
+ result.append(source.substring(lastIndex, index));
+ result.append(whatAfter);
+ lastIndex = index + beforeLen;
+
+ // get next
+ index = source.indexOf(whatBefore, lastIndex);
+ }
+ result.append(source.substring(lastIndex));
+ return result.toString();
+ }
+
+ /**
+ * @return Returns the elementList.
+ */
+ public List getElementList() {
+ return elementList;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * $RCSfile: JSPartitionScanner.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.3 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ * Revision 1.2 2003/05/28 20:47:58 agfitzp
+ * Outline the document, not the file.
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+//import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.rules.*;
+
+/**
+ *
+ *
+ * @author $Author: jsurfer $, $Date: 2004-09-02 18:14:38 $
+ *
+ * @version $Revision: 1.1 $
+ */
+public class JSPartitionScanner extends RuleBasedPartitionScanner {
+ public final static String JS_DEFAULT = "__js_default";
+ public final static String JS_COMMENT = "__js_comment";
+ public final static String JS_KEYWORD = "__js_keyword";
+ public final static String JS_STRING = "__js_string";
+
+ public final static IToken TOKEN_STRING = new Token(JS_STRING);
+ public final static IToken TOKEN_COMMENT = new Token(JS_COMMENT);
+ public final static IToken TOKEN_DEFAULT = new Token(JS_DEFAULT);
+ public final static IToken TOKEN_KEYWORD = new Token(JS_KEYWORD);
+
+ /**
+ * Array of keyword token strings.
+ */
+ private static String[] keywordTokens= {
+ "break",
+ "case", "catch", "continue",
+ "default", "do",
+ "else",
+ "for", "function",
+ "goto",
+ "if", "in",
+ "new",
+ "return",
+ "switch",
+ "this", "throw", "try",
+ "var", "void",
+ "while", "with"
+ };
+
+ /**
+ * Array of constant token strings.
+ */
+ private static String[] constantTokens= { "false", "null", "true" };
+
+
+ /**
+ * Creates a new JSPartitionScanner object.
+ */
+ public JSPartitionScanner() {
+ List rules = new ArrayList();
+
+ rules.add(new MultiLineRule("/*", "*/", TOKEN_COMMENT));
+ rules.add(new SingleLineRule("//", "", TOKEN_COMMENT));
+ rules.add(new SingleLineRule("\"", "\"", TOKEN_STRING, '\\'));
+ rules.add(new SingleLineRule("'", "'", TOKEN_STRING, '\\'));
+
+ PredicateWordRule keywordRule = new PredicateWordRule(new JSWordDetector(), TOKEN_DEFAULT, keywordTokens, TOKEN_KEYWORD);
+ keywordRule.addWords(constantTokens, TOKEN_KEYWORD);
+ rules.add(keywordRule);
+
+ setRuleList(rules);
+ }
+
+
+ private void setRuleList(List rules)
+ {
+ IPredicateRule[] result = new IPredicateRule[rules.size()];
+ rules.toArray(result);
+ setPredicateRules(result);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Created on May 14, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.parser;
+
+/**
+ * @author fitzpata
+ */
+public class JSReferenceDetector extends JSWordDetector {
+ /**
+ * @see IWordDetector#isWordStart
+ * Try to detect tokens starting with a reference operator.
+ */
+ public boolean isWordStart(char c) {
+ return (c == '.');
+ }
+}
--- /dev/null
+/*
+ * $RCSfile: JSScanner.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import java.util.*;
+import org.eclipse.jface.text.rules.*;
+import org.eclipse.jface.text.*;
+
+import org.eclipse.swt.graphics.Color;
+
+/**
+ *
+ *
+ * @author $Author: jsurfer $, $Date: 2004-09-02 18:14:38 $
+ *
+ * @version $Revision: 1.1 $
+ */
+public class JSScanner extends RuleBasedScanner
+{
+ /**
+ * Creates a new JSScanner object.
+ *
+ * @param manager
+ */
+ public JSScanner(Color aColor)
+ {
+ List rules = new ArrayList();
+ IToken procInstr = new Token(new TextAttribute(aColor));
+
+ // Add generic whitespace rule.
+ rules.add(new WhitespaceRule(new JSWhitespaceDetector()));
+
+ IRule[] result = new IRule[rules.size()];
+ rules.toArray(result);
+ setRules(result);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * $RCSfile: JSStringScanner.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.1 2003/05/28 15:17:11 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import org.eclipse.jface.text.*;
+import java.util.*;
+import org.eclipse.jface.text.rules.*;
+
+import org.eclipse.swt.graphics.Color;
+
+
+/**
+ *
+ *
+ * @author $Author: jsurfer $, $Date: 2004-09-02 18:14:38 $
+ *
+ * @version $Revision: 1.1 $
+ */
+public class JSStringScanner extends RuleBasedScanner
+{
+ /**
+ * Creates a new JSFuncScanner object.
+ *
+ * @param manager
+ */
+ public JSStringScanner(Color aColor)
+ {
+ IToken string = new Token(new TextAttribute(aColor));
+ Vector rules = new Vector();
+
+ // Add rule for single and double quotes
+ rules.add(new SingleLineRule("\"", "\"", string, '\\'));
+ rules.add(new SingleLineRule("'", "'", string, '\\'));
+
+
+ // Add generic whitespace rule.
+ rules.add(new WhitespaceRule(new JSWhitespaceDetector()));
+
+ IRule[] result = new IRule[rules.size()];
+ rules.copyInto(result);
+ setRules(result);
+ }
+
+ /**
+ *
+ *
+ * @return
+ */
+ public IToken nextToken()
+ {
+ return super.nextToken();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * $RCSfile: JSSyntaxModelFactory.java,v $
+ *
+ * Copyright 2002 CH-1700 Fribourg, Switzerland All rights reserved.
+ *
+ * ========================================================================
+ * Modifications history
+ * ========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.2 2004/02/27 17:25:25 cell
+ * Fix NPE for files without an extension
+ *
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ * Revision 1.3 2003/05/30 20:53:08 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ * Revision 1.2 2003/05/28 20:47:56 agfitzp Outline the document, not the file.
+ *
+ * Revision 1.1 2003/05/28 15:17:11 agfitzp net.sourceforge.phpeclipse.js.core 0.0.1 code
+ * base
+ *
+ * ========================================================================
+ */
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+
+import net.sourceforge.phpeclipse.js.core.model.*;
+
+/**
+ * @author Addi
+ */
+public class JSSyntaxModelFactory {
+ private static JSSyntaxModelFactory instance = new JSSyntaxModelFactory();
+
+ /**
+ * Creates a new JSSyntaxModelFactory.
+ */
+ private JSSyntaxModelFactory() {
+ }
+ /**
+ * @param adaptable
+ *
+ * @return
+ */
+ public JSElementList getContentOutline(IProject aProject) {
+ return new JSElementList(getSyntacticElements(aProject));
+ }
+
+ /**
+ * @param adaptable
+ *
+ * @return
+ */
+ public JSElementList getContentOutline(IFile adaptable) {
+ return new JSElementList(getSyntacticElements(adaptable));
+ }
+
+ /**
+ * @param document
+ *
+ * @return
+ */
+ public JSElementList getContentOutline(IDocument document) {
+ return new JSElementList(getSyntacticElements(document));
+ }
+
+ /**
+ * Returns the singleton.
+ *
+ * @return
+ */
+ public static JSSyntaxModelFactory getInstance() {
+ return instance;
+ }
+
+ /**
+ * @param file
+ *
+ * @return
+ */
+ private List getSyntacticElements(IProject aProject) {
+ int i;
+ JSParser aParser = new JSParser();
+ Object[] jsFiles = getJSFilesFor(aProject);
+
+ for (i = 0; i < jsFiles.length; i++) {
+ aParser.parse((IFile) jsFiles[i]);
+ }
+ return aParser.getElementList();
+ }
+
+ /**
+ * @param project
+ * @return
+ */
+ private Object[] getJSFilesFor(IProject project) {
+ LinkedList files = new LinkedList();
+ collectJSFiles(project, files);
+ return files.toArray();
+ }
+
+ private void collectJSFiles(IContainer aContainer, LinkedList files) {
+ try {
+ int i;
+ IResource[] members = aContainer.members();
+ for (i = 0; i < members.length; i++) {
+ IResource aResource = members[i];
+ if (aResource.getType() == IResource.FILE) {
+ IFile aFile = (IFile) aResource;
+ String ext = aFile.getFileExtension();
+ if ((ext != null) && ext.equals("js")) {
+ files.add(aFile);
+ }
+ } else if (aResource.getType() == IResource.FOLDER) {
+ collectJSFiles((IFolder) aResource, files);
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ /**
+ * @param file
+ *
+ * @return
+ */
+
+ private List getSyntacticElements(IFile file) {
+ return (new JSParser()).parse(file);
+ }
+
+ /**
+ * @param file
+ *
+ * @return
+ */
+ private List getSyntacticElements(IDocument document) {
+ return (new JSParser()).parse(document);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Created on May 16, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.jface.text.rules.*;
+
+/**
+ * Scanner for detecting syntactic elements: comments, strings, classes, functions
+ *
+ * @author fitzpata
+ *
+ */
+public class JSSyntaxScanner extends BufferedRuleBasedScanner {
+ public final static String JS_DEFAULT = "__js_default";
+ public final static String JS_COMMENT = "__js_comment";
+ public final static String JS_FUNCTION = "__js_function";
+ public final static String JS_STRING = "__js_string";
+ public final static String JS_MEMBER = "__js_member";
+ public final static String JS_PERIOD = "__js_period";
+
+ public final static IToken TOKEN_STRING = new Token(JS_STRING);
+ public final static IToken TOKEN_COMMENT = new Token(JS_COMMENT);
+ public final static IToken TOKEN_DEFAULT = new Token(JS_DEFAULT);
+ public final static IToken TOKEN_FUNCTION = new Token(JS_FUNCTION);
+ public final static IToken TOKEN_MEMBER = new Token(JS_MEMBER);
+ public final static IToken TOKEN_PERIOD = new Token(JS_PERIOD);
+
+ /**
+ * String for detecting member declarations.
+ */
+ private static String memberToken= ".prototype";
+
+ /**
+ * Creates a new JSSyntaxScanner object.
+ */
+ public JSSyntaxScanner() {
+ List rules = new ArrayList();
+
+ rules.add(new MultiLineRule("/*", "*/", TOKEN_COMMENT));
+ rules.add(new SingleLineRule("//", "", TOKEN_COMMENT));
+ rules.add(new SingleLineRule("\"", "\"", TOKEN_STRING, '\\'));
+ rules.add(new SingleLineRule("'", "'", TOKEN_STRING, '\\'));
+
+ rules.add(new WhitespaceRule(new JSWhitespaceDetector()));
+
+ rules.add(new MultiLineRule("function(", ")", TOKEN_FUNCTION));
+ rules.add(new MultiLineRule("function ", ")", TOKEN_FUNCTION));
+
+ rules.add(new WordRule(new JSWordDetector(), TOKEN_DEFAULT));
+ rules.add(new PredicateWordRule(new JSReferenceDetector(), memberToken, TOKEN_MEMBER));
+
+ setRuleList(rules);
+ }
+
+
+ /**
+ * set the rule list
+ * @param rules
+ */
+ private void setRuleList(List rules)
+ {
+ IRule[] result = new IRule[rules.size()];
+ rules.toArray(result);
+ setRules(result);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * $RCSfile: JSWhitespaceDetector.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.1 2003/05/28 15:17:12 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+
+/**
+ *
+ *
+ * @author $Author: jsurfer $, $Date: 2004-09-02 18:14:38 $
+ *
+ * @version $Revision: 1.1 $
+ */
+public class JSWhitespaceDetector implements IWhitespaceDetector
+{
+ /**
+ *
+ *
+ * @param c
+ *
+ * @return
+ */
+ public boolean isWhitespace(char c)
+ {
+ return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Created on May 13, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.parser;
+
+/**
+ * @author fitzpata
+ *
+ */
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * A JavaScript aware word detector.
+ * JavaScript tokens are almost identical to Java so this
+ * class is borrowed from org.eclipse.jdt.internal.ui.text.JavaWordDetector.
+ */
+public class JSWordDetector implements IWordDetector {
+
+ /**
+ * @see IWordDetector#isWordStart
+ * JavaScript tokens are almost identical to Java so for now
+ * we can just borrow this behavior.
+ */
+ public boolean isWordStart(char c) {
+ return Character.isJavaIdentifierStart(c);
+ }
+
+ /**
+ * @see IWordDetector#isWordPart
+ * JavaScript tokens are almost identical to Java so for now
+ * we can just borrow this behavior.
+ */
+ public boolean isWordPart(char c) {
+ return Character.isJavaIdentifierPart(c);
+ }
+}
--- /dev/null
+/*
+ * $RCSfile: NonRuleBasedDamagerRepairer.java,v $
+ *
+ * Copyright 2002
+ * CH-1700 Fribourg, Switzerland
+ * All rights reserved.
+ *
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.1 2003/05/28 15:17:11 agfitzp
+ * net.sourceforge.phpeclipse.js.core 0.0.1 code base
+ *
+ *========================================================================
+*/
+
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.presentation.IPresentationDamager;
+import org.eclipse.jface.text.presentation.IPresentationRepairer;
+//import org.eclipse.jface.util.Assert;
+import org.eclipse.swt.custom.StyleRange;
+
+
+/**
+ *
+ *
+ * @author $Author: jsurfer $, $Date: 2004-09-02 18:14:38 $
+ *
+ * @version $Revision: 1.1 $
+ */
+public class NonRuleBasedDamagerRepairer implements IPresentationDamager, IPresentationRepairer
+{
+ /** The document this object works on */
+ protected IDocument fDocument;
+
+ /** The default text attribute if non is returned as data by the current token */
+ protected TextAttribute fDefaultTextAttribute;
+
+ /**
+ * Constructor for NonRuleBasedDamagerRepairer.
+ * @param defaultTextAttribute
+ */
+ public NonRuleBasedDamagerRepairer(TextAttribute defaultTextAttribute)
+ {
+// Assert.isNotNull(defaultTextAttribute);
+
+ fDefaultTextAttribute = defaultTextAttribute;
+ }
+
+ /**
+ * @see IPresentationRepairer#setDocument(IDocument)
+ */
+ public void setDocument(IDocument document)
+ {
+ fDocument = document;
+ }
+
+ /**
+ * Returns the end offset of the line that contains the specified offset or if the offset is
+ * inside a line delimiter, the end offset of the next line.
+ *
+ * @param offset the offset whose line end offset must be computed
+ *
+ * @return the line end offset for the given offset
+ *
+ * @exception BadLocationException if offset is invalid in the current document
+ */
+ protected int endOfLineOf(int offset) throws BadLocationException
+ {
+ IRegion info = fDocument.getLineInformationOfOffset(offset);
+
+ if(offset <= info.getOffset() + info.getLength())
+ {
+ return info.getOffset() + info.getLength();
+ }
+
+ int line = fDocument.getLineOfOffset(offset);
+
+ try
+ {
+ info = fDocument.getLineInformation(line + 1);
+
+ return info.getOffset() + info.getLength();
+ }
+ catch(BadLocationException x)
+ {
+ return fDocument.getLength();
+ }
+ }
+
+ /**
+ * @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent, boolean)
+ */
+ public IRegion getDamageRegion(ITypedRegion partition, DocumentEvent event,
+ boolean documentPartitioningChanged)
+ {
+ if(!documentPartitioningChanged)
+ {
+ try
+ {
+ IRegion info = fDocument.getLineInformationOfOffset(event.getOffset());
+ int start = Math.max(partition.getOffset(), info.getOffset());
+
+ int end = event.getOffset() +
+ (event.getText() == null ? event.getLength()
+ : event.getText().length());
+
+ if(info.getOffset() <= end && end <= info.getOffset() + info.getLength())
+ {
+ // optimize the case of the same line
+ end = info.getOffset() + info.getLength();
+ }
+ else
+ {
+ end = endOfLineOf(end);
+ }
+
+ end = Math.min(partition.getOffset() + partition.getLength(), end);
+
+ return new Region(start, end - start);
+ }
+ catch(BadLocationException x)
+ {
+ }
+ }
+
+ return partition;
+ }
+
+ /**
+ * @see IPresentationRepairer#createPresentation(TextPresentation, ITypedRegion)
+ */
+ public void createPresentation(TextPresentation presentation, ITypedRegion region)
+ {
+ addRange(presentation, region.getOffset(), region.getLength(), fDefaultTextAttribute);
+ }
+
+ /**
+ * Adds style information to the given text presentation.
+ *
+ * @param presentation the text presentation to be extended
+ * @param offset the offset of the range to be styled
+ * @param length the length of the range to be styled
+ * @param attr the attribute describing the style of the range to be styled
+ */
+ protected void addRange(TextPresentation presentation, int offset, int length,
+ TextAttribute attr)
+ {
+ if(attr != null)
+ {
+ presentation.addStyleRange(
+ new StyleRange(offset, length, attr.getForeground(), attr.getBackground(),
+ attr.getStyle()));
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Created on May 13, 2003
+ *========================================================================
+ * Modifications history
+ *========================================================================
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1 2004/02/26 02:25:42 agfitzp
+ * renamed packages to match xml & css
+ *
+ * Revision 1.1 2004/02/05 03:10:08 agfitzp
+ * Initial Submission
+ *
+ * Revision 1.1.2.1 2003/12/12 21:37:24 agfitzp
+ * Experimental work for Classes view
+ *
+ * Revision 1.2 2003/05/30 20:53:09 agfitzp
+ * 0.0.2 : Outlining is now done as the user types. Some other bug fixes.
+ *
+ *========================================================================
+ */
+package net.sourceforge.phpeclipse.js.core.parser;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.rules.IWordDetector;
+
+/**
+ * @author fitzpata
+ */
+public class PredicateWordRule extends WordRule implements IPredicateRule {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.rules.IPredicateRule#getSuccessToken()
+ */
+
+ protected IToken successToken = Token.UNDEFINED;
+
+ public void addWords(String[] tokens, IToken token)
+ {
+ for (int i = 0; i < tokens.length; i++) {
+ addWord(tokens[i], token);
+ }
+
+ }
+
+ public IToken getSuccessToken() {
+ return successToken;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.rules.IPredicateRule#evaluate(org.eclipse.jface.text.rules.ICharacterScanner, boolean)
+ */
+ public IToken evaluate(ICharacterScanner scanner, boolean resume) {
+ successToken = this.evaluate(scanner, resume);//true);
+ return successToken;
+ }
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the token
+ * associated with the detected word. If no token has been associated, the scanner
+ * will be rolled back and an undefined token will be returned in order to allow
+ * any subsequent rules to analyze the characters.
+ *
+ * @param detector the word detector to be used by this rule, may not be <code>null</code>
+ *
+ * @see #addWord
+ */
+
+ public PredicateWordRule(IWordDetector detector) {
+ super(detector);
+ }
+
+ /**
+ * Creates a rule which, with the help of an word detector, will return the token
+ * associated with the detected word. If no token has been associated, the
+ * specified default token will be returned.
+ *
+ * @param detector the word detector to be used by this rule, may not be <code>null</code>
+ * @param defaultToken the default token to be returned on success
+ * if nothing else is specified, may not be <code>null</code>
+ *
+ * @see #addWord
+ */
+ public PredicateWordRule(IWordDetector detector, IToken defaultToken) {
+ super(detector, defaultToken);
+ }
+
+
+ public PredicateWordRule(IWordDetector detector, String tokenString, IToken tokenType) {
+ super(detector);
+ this.addWord(tokenString, tokenType);
+ }
+
+ public PredicateWordRule(IWordDetector detector, String[] tokens, IToken tokenType) {
+ super(detector);
+ this.addWords(tokens, tokenType);
+ }
+
+ public PredicateWordRule(IWordDetector detector, IToken defaultToken, String[] tokens, IToken tokenType) {
+ super(detector, defaultToken);
+ this.addWords(tokens, tokenType);
+ }
+
+}
--- /dev/null
+<?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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>net.sourceforge.phpeclipse.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+source.webcore.jar = src/
+output.webcore.jar = bin/
+bin.includes = plugin.xml,\
+ webcore.jar
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin
+ id="net.sourceforge.phpeclipse.core"
+ name="Web Development Tools Core"
+ version="0.0.1"
+ provider-name="WDTE Project"
+ class="net.sourceforge.phpeclipse.core.WebCore">
+
+ <runtime>
+ <library name="webcore.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+ <requires>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.eclipse.text"/>
+ </requires>
+
+
+</plugin>
--- /dev/null
+/*
+ * 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: WebCore.java,v 1.1 2004-09-02 18:05:22 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.core;
+
+import org.eclipse.core.runtime.Plugin;
+
+//import net.sourceforge.phpeclipse.core.parser.ISourceParser;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class WebCore extends Plugin {
+
+ // Instance Variables ------------------------------------------------------
+
+ /** The shared instance. */
+ private static WebCore plugin;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * The constructor.
+ */
+ public WebCore() {
+ plugin = this;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Returns the shared instance.
+ */
+ public static WebCore getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Creates and returns a parser that can handle resources of the specified
+ * MIME type.
+ *
+ * @param mimeType the MIME type of the resource for which a parser should
+ * be created
+ * @return the instantiated parser, or <tt>null</tt> if no parser for that
+ * MIME type is registered
+ */
+// public ISourceParser createParser(String mimeType) {
+// return null;
+// }
+}
--- /dev/null
+/*
+ * 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: ISourceModel.java,v 1.1 2004-09-02 18:05:21 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.core.model;
+
+/**
+ *
+ */
+public interface ISourceModel {
+
+ /**
+ * Returns the top-level elements of the source model.
+ *
+ * @return an array of the top-level elements
+ */
+ ISourceReference[] getElements();
+
+ /**
+ * Returns the elements that are direct children of the given element.
+ *
+ * @param element the element for which to return the child elements
+ * @return an array of child elements, or an empty array if the given
+ * element has no children
+ */
+ ISourceReference[] getChildren(ISourceReference element);
+
+ /**
+ * Returns the direct parent element of the specified element.
+ *
+ * @param element the element for which the parent should be returned
+ * @return the parent element, or <tt>null</tt> if the specified element
+ * does not have a parent (meaning it is a top-level element)
+ */
+ ISourceReference getParent(ISourceReference element);
+
+}
--- /dev/null
+/*
+ * 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
+ *
+ * $Id: ISourceReference.java,v 1.1 2004-09-02 18:05:21 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.core.model;
+
+import org.eclipse.jface.text.IRegion;
+
+/**
+ * Common protocol for model elements that have associated source code.
+ */
+public interface ISourceReference {
+
+ /**
+ * Returns the source code associated with this model element.
+ *
+ * <p>
+ * This method extracts the substring from the source buffer containing
+ * this source element. This corresponds to the source regione that would
+ * be returned by {@link ISourceReference#getSourceRegion()}</code>.
+ * </p>
+ *
+ * @return The source code, or <code>null</code> if this element has no
+ * associated source code
+ */
+ String getSource();
+
+ /**
+ * Returns the source range associated with this element.
+ *
+ * @return The source region, or <code>null</code> if this element has no
+ * associated source code
+ */
+ IRegion getSourceRegion();
+
+}
--- /dev/null
+/*
+ * 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: SourceReference.java,v 1.1 2004-09-02 18:05:21 jsurfer Exp $
+ */
+
+package net.sourceforge.phpeclipse.core.model;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+
+/**
+ * Default implementation of {@link ISourceReference} based on
+ * {@link IDocument}.
+ */
+public class SourceReference implements ISourceReference {
+
+ // Instance Variables ------------------------------------------------------
+
+ /** The associated document. */
+ private IDocument document;
+
+ /** The region in the document that maps to the source reference. */
+ private IRegion sourceRegion;
+
+ // Constructors ------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the source reference
+ */
+ public SourceReference(IDocument document) {
+ this(document, 0, 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the source reference
+ */
+ public SourceReference(IDocument document, int offset) {
+ this(document, offset, 0);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param document The document that contains the source reference
+ */
+ public SourceReference(IDocument document, int offset, int length) {
+ this.document = document;
+ this.sourceRegion = new Region(offset, length);
+ }
+
+ // ISourceReference Implementation -----------------------------------------
+
+ /*
+ * @see ISourceReference#getSource()
+ */
+ public String getSource() {
+ try {
+ return document.get(sourceRegion.getOffset(),
+ sourceRegion.getLength());
+ } catch (BadLocationException e) {
+ throw new IllegalStateException(
+ "Model not synchronized with document"); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * @see ISourceReference#getSourceRegion()
+ */
+ public IRegion getSourceRegion() {
+ return sourceRegion;
+ }
+
+ // Public Methods ----------------------------------------------------------
+
+ /**
+ * Sets the source region covered by the element.
+ *
+ * @param offset the offset of the region
+ * @param length the length of the region
+ */
+ public final void setSourceRegion(int offset, int length) {
+ sourceRegion = new Region(offset, length);
+ }
+
+ /**
+ * Sets the source region covered by the element.
+ *
+ * @param region the source region to set
+ */
+ public final void setSourceRegion(IRegion region) {
+ setSourceRegion(region.getOffset(), region.getLength());
+ }
+
+ // Protected Methods -------------------------------------------------------
+
+ /**
+ * Returns the underlying document.
+ *
+ * @return the underlying document
+ */
+ protected final IDocument getDocument() {
+ return document;
+ }
+
+}