intial source from ttp://www.sf.net/projects/wdte
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.css.core / src / net / sourceforge / phpeclipse / css / core / internal / model / StyleSheet.java
1 /*
2  * Copyright (c) 2003-2004 Christopher Lenz and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     Christopher Lenz - initial API and implementation
10  * 
11  * $Id: StyleSheet.java,v 1.1 2004-09-02 18:07:12 jsurfer Exp $
12  */
13
14 package net.sourceforge.phpeclipse.css.core.internal.model;
15
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.List;
19
20 import net.sourceforge.phpeclipse.core.model.SourceReference;
21 import net.sourceforge.phpeclipse.css.core.internal.parser.DefaultCssParser;
22 import net.sourceforge.phpeclipse.css.core.model.IRule;
23 import net.sourceforge.phpeclipse.css.core.model.IStyleSheet;
24 import net.sourceforge.phpeclipse.css.core.parser.ICssParser;
25 import net.sourceforge.phpeclipse.css.core.parser.IProblemCollector;
26 import net.sourceforge.phpeclipse.css.core.parser.LexicalErrorException;
27 import net.sourceforge.phpeclipse.css.core.parser.SyntaxErrorException;
28
29 import org.eclipse.core.runtime.Platform;
30 import org.eclipse.jface.text.DocumentEvent;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IDocumentListener;
33 import org.eclipse.jface.text.IRegion;
34
35 /**
36  * 
37  */
38 public class StyleSheet extends SourceReference
39         implements IStyleSheet, IDocumentListener {
40
41         // Instance Variables ------------------------------------------------------
42
43         /**
44          * The list of top-level CSS rules defined in the style sheet.
45          */
46         private List rules = new ArrayList();
47
48         private Object dirtyLock = new Object();
49         private boolean dirty = true;
50
51         // Constructors ------------------------------------------------------------
52
53         /**
54          * Constructor.
55          * 
56          * @param document The document that contains the style sheet
57          */
58         public StyleSheet(IDocument document) {
59                 super(document);
60         }
61
62         // IAdaptable Implementation -----------------------------------------------
63
64         /*
65          * @see IAdaptable#getAdapter(Class)
66          */
67         public Object getAdapter(Class adapter) {
68                 return Platform.getAdapterManager().getAdapter(this, adapter);
69         }
70
71         // IStyleSheet Implementation ----------------------------------------------
72
73         /*
74          * @see IStyleSheet#getRuleAt(int)
75          */
76         public IRule getRuleAt(int offset) {
77                 return getRuleAtInternal(getRules(), offset);
78         }
79
80         /*
81          * @see IStyleSheet#getRules()
82          */
83         public IRule[] getRules() {
84                 return (IRule[]) rules.toArray(new IRule[rules.size()]);
85         }
86
87         /*
88          * @see IStyleSheet#reconcile(IProblemCollector)
89          */
90         public void reconcile(IProblemCollector problemCollector)
91                 throws LexicalErrorException, SyntaxErrorException {
92                 
93                 synchronized (dirtyLock) {
94                         if (!dirty) {
95                                 return;
96                         }
97                         dirty = false;
98                 }
99
100                 synchronized (this) {
101                         rules.clear();
102                         ICssParser parser = new DefaultCssParser();
103                         parser.setProblemCollector(problemCollector);
104                         parser.setSource(getDocument());
105                         rules.addAll(Arrays.asList(parser.parseRules(this)));
106                 }
107         }
108
109         // IDocumentListener Implementation ----------------------------------------
110
111         /*
112          * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
113          */
114         public void documentAboutToBeChanged(DocumentEvent event) {
115                 // do nothing yet
116         }
117
118         /*
119          * @see IDocumentListener#documentChanged(DocumentEvent)
120          */
121         public void documentChanged(DocumentEvent event) {
122                 synchronized (dirtyLock) {
123                         dirty = true;
124                 }
125         }
126
127         // Public Methods ----------------------------------------------------------
128
129         /**
130          * Adds a rule to the style sheet.
131          * 
132          * @param rule The rule to add
133          */
134         public void addRule(IRule rule) {
135                 rules.add(rule);
136         }
137
138         // Private Methods ---------------------------------------------------------
139
140         private static IRule getRuleAtInternal(IRule rules[], int offset) {
141                 IRule retVal = null;
142                 for (int i = 0; i < rules.length; i++) {
143                         IRule rule = rules[i];
144                         IRegion region = rule.getSourceRegion();
145                         if ((offset > region.getOffset())
146                          && (offset < (region.getOffset() + region.getLength()))) {
147                                 if (rule.getChildren().length > 0) {
148                                         retVal = getRuleAtInternal(rule.getChildren(), offset);
149                                         if (retVal != null) {
150                                                 break;
151                                         }
152                                 }
153                                 if (retVal == null) {
154                                         retVal = rule;
155                                 }
156                         }
157                 }
158                 return retVal;
159         }
160
161 }