PageRenderTime 93ms CodeModel.GetById 79ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/XML/sidekick/css/CssSideKickCompletion.java

#
Java | 285 lines | 177 code | 58 blank | 50 comment | 23 complexity | bff666af55ef22502c4d50315243363d MD5 | raw file
  1/**
  2 * CssSideKickCompletion.java
  3 * :folding=explicit:collapseFolds=1:
  4 *
  5 * Copyright (C) 2006 Jakub Roztocil
  6 *
  7 * This program is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU General Public License
  9 * as published by the Free Software Foundation; either version 2
 10 * of the License, or any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 20 */
 21
 22package sidekick.css;
 23
 24//{{{ Imports
 25import java.io.*;
 26import java.util.*;
 27import java.util.regex.*;
 28import org.apache.xerces.parsers.*;
 29import org.gjt.sp.jedit.*;
 30import org.gjt.sp.jedit.buffer.JEditBuffer;
 31import org.gjt.sp.util.Log;
 32import org.gjt.sp.jedit.textarea.*;
 33import org.w3c.dom.*;
 34import org.xml.sax.InputSource;
 35import org.xml.sax.SAXException;
 36import sidekick.SideKickCompletion;
 37import xml.Resolver;
 38//}}}
 39
 40
 41public class CssSideKickCompletion extends SideKickCompletion {
 42
 43	public final static String SPECIAL_URL_PROP = "url...";
 44	public static String QUOTE;
 45	private static boolean choosingFile = false;
 46
 47	//{{{ CssSideKickCompletion constructor
 48	public CssSideKickCompletion(List completions, String word, boolean selectedProperty) {
 49		super(jEdit.getActiveView(), word, completions);
 50		this.selectedProperty = selectedProperty;
 51		if (!inited) {
 52			readConfig();
 53		}
 54	} //}}}
 55
 56	//{{{ readConfig() method
 57	public static void readConfig() {
 58		QUOTE = jEdit.getProperty(CssSideKickPlugin.OPTION_PREFIX + "quote");
 59	} //}}}
 60
 61	//{{{ insert() method
 62	public void insert(int index) {
 63
 64		String selected = String.valueOf(get(index));
 65		JEditBuffer buffer = textArea.getBuffer();
 66		int caret = textArea.getCaretPosition();
 67		int moveCaret = 0;
 68		
 69		// when "url..." confirmed by ENTER, the this method is called twice
 70		// it seem as a Sidekick's bug to me.
 71		if (choosingFile) {
 72			return;
 73		}
 74
 75
 76		// If selected property, handle colon
 77		if (selectedProperty && jEdit.getBooleanProperty(CssSideKickPlugin.OPTION_PREFIX + "colon")) {
 78
 79			String textAfter = buffer.getText(caret, buffer.getLength() - caret - 1);
 80
 81			// If isn't colon after caret, add one after property.
 82			// Otherwise check, if do we have between property and that colon some mess
 83			// and if we haven't, move caret after colon
 84			if (canAddColon(textAfter)) {
 85				selected += ":";
 86				if (jEdit.getBooleanProperty(CssSideKickPlugin.OPTION_PREFIX + "space-after-colon")) {
 87					selected += " ";
 88				}
 89			} else if (Pattern.compile("^\\s*:").matcher(textAfter).find()) {
 90				moveCaret = textAfter.indexOf(":") + 1;
 91			}
 92
 93		} else if (selected.equals("url")) {
 94
 95			selected = "url(" + QUOTE + QUOTE + ")";
 96			moveCaret = -2;
 97
 98		} else if (selected.equals(SPECIAL_URL_PROP)){
 99			choosingFile = true;
100			selected = "url(" + QUOTE + Utils.chooseFileAndGetRelativePath() + QUOTE + ")";
101			choosingFile = false;
102
103		}
104
105
106
107		Selection s = textArea.getSelectionAtOffset(caret);
108		int start = (s == null ? caret : s.getStart());
109		int end = (s == null ? caret : s.getEnd());
110		try {
111			buffer.beginCompoundEdit();
112			buffer.remove(start - text.length(),text.length());
113			buffer.insert(start - text.length(),selected);
114		} finally {
115			buffer.endCompoundEdit();
116		}
117		textArea.setCaretPosition(end + selected.length() + moveCaret - text.length());
118	} //}}}
119
120	
121	//{{{ getCssProperties() method
122	public static HashMap getCssProperties() {
123		return cssProperties;
124	} //}}}
125	
126	//{{{ getCssUnits() method
127	public static ArrayList getCssUnits() {
128		return cssUnits;
129	} //}}}
130	
131	//{{{ setInitialized() method
132	public static void setInitialized(boolean initialized) {
133		CssSideKickCompletion.initialized = initialized;
134	} //}}}
135	
136	//{{{ initialized() method
137	public static boolean initialized() {
138		return initialized;
139	} //}}}
140	
141	//{{{ initialize() method
142	public static void initialize() {
143		setInitialized(true);
144		readCompletionConfig();
145	}
146	//}}}
147	
148	
149	//{{{ Private members
150
151	private boolean selectedProperty;
152	
153	
154	private static ArrayList<String> cssUnits;
155	private static HashMap<String,ArrayList<String>> cssProperties;
156	
157	private static boolean initialized;
158	/* private static String COMPLETION_CONFIG_FILE = jEdit.getSettingsDirectory() 
159													+ File.separator 
160													+ jEdit.getProperty(CssSideKickPlugin.OPTION_PREFIX + "completion-config"); */
161	private static final String COMPLETION_CONFIG_FILE = "jeditresource:/XML.jar!/xml/completion/css-complete.xml";
162	
163	private static Pattern HAS_PROP_COLON = Pattern.compile("^[^;}]*:");
164	private static boolean inited;
165
166	//{{{ canAddColon() method
167	private static boolean canAddColon(String textAfterCaret) {
168		return !HAS_PROP_COLON.matcher(textAfterCaret).find();
169	} //}}}
170
171	//{{{ readCompletionConfig() method
172	private static void readCompletionConfig() {
173		try {
174			Log.log(Log.DEBUG, CssSideKickCompletion.class, "Parsing configuration file: " + COMPLETION_CONFIG_FILE);
175			DOMParser parser = new DOMParser();
176			parser.setEntityResolver(Resolver.instance());
177			InputSource source = Resolver.instance().resolveEntity(null, COMPLETION_CONFIG_FILE );
178			parser.parse(source);
179			Document doc = parser.getDocument();
180			initCssUnits(doc);
181			initCssProperties(doc);
182
183			Log.log(Log.DEBUG,
184					CssSideKickCompletion.class,
185					"Parsing done, found " + cssProperties.size() + " css properties and " + cssUnits.size() + " css units");
186
187		} catch (FileNotFoundException e) {
188			GUIUtilities.error(jEdit.getActiveView(),
189								"csssidekick.config-io-error",
190								new String[]{
191									e.getMessage()
192								});
193		} catch (IOException e) {
194
195			GUIUtilities.error(jEdit.getActiveView(),
196								"csssidekick.config-io-error",
197								new String[]{
198									e.getMessage()
199								});
200			Log.log(Log.ERROR, CssSideKickCompletion.class, e);
201		} catch (SAXException e) {
202			GUIUtilities.error(jEdit.getActiveView(),
203								"csssidekick.config-xml-error",
204								new String[]{e.getMessage()});
205			Log.log(Log.ERROR, CssSideKickCompletion.class, e);
206		} catch (Exception e) {
207			Log.log(Log.ERROR, CssSideKickCompletion.class, e);
208		}
209	} //}}}
210
211	//{{{ initCssProperties() method
212	private static void initCssProperties(Document doc) {
213		cssProperties = new HashMap<String,ArrayList<String>>();
214
215		NodeList propertiesElements = doc.getElementsByTagName("properties");
216		if (propertiesElements.getLength() != 1) {
217			// throw new Exception("No <properties> found");
218		}
219
220		NodeList properties = ((Element)propertiesElements.item(0)).getElementsByTagName("property");
221		int propCount = properties.getLength();
222
223		// loop properties
224		for (int i = 0; i < propCount; i++) {
225
226			Element propEle = (Element) properties.item(i);
227			String propName = propEle.getAttribute("name");
228
229			NodeList values = propEle.getElementsByTagName("*");
230			int valCount = values.getLength();
231			ArrayList<String> valList = new ArrayList<String>();
232
233			// loop values
234			for (int j = 0; j < valCount; j++) {
235				Element ele = (Element) values.item(j);
236				String name = ele.getAttribute("name");
237
238				if (ele.getTagName().equals("include")) {
239
240					NodeList incValues = doc.getElementById(name).getElementsByTagName("value");
241					int incValCount = incValues.getLength();
242
243					// loop included values
244					for (int k = 0; k < incValCount; k++) {
245						Element incValEle = (Element)incValues.item(k);
246						String incValText = incValEle.getFirstChild().getNodeValue();
247						if (incValText.equals("url")) {
248							valList.add(SPECIAL_URL_PROP);
249						}
250						valList.add(incValText);
251					}
252					continue;
253				}
254
255				String valText = ele.getFirstChild().getNodeValue();
256				if (valText.equals("url")) {
257					valList.add(SPECIAL_URL_PROP);
258				}
259				valList.add(valText);
260
261			}
262
263			cssProperties.put(propName, valList);
264		}
265
266	} //}}}
267
268	//{{{ initCssUnits() method
269	private static void initCssUnits(Document doc) {
270
271		cssUnits = new ArrayList<String>();
272		NodeList unitsElements = doc.getElementsByTagName("units");
273		NodeList units = ((Element)unitsElements.item(0)).getElementsByTagName("unit");
274		int unitsCount = units.getLength();
275		for (int i = 0; i < unitsCount; i++) {
276			Element unitEle = (Element)units.item(i);
277			String unitText = unitEle.getFirstChild().getNodeValue();
278			cssUnits.add(unitText);
279		}
280
281	} //}}}
282
283	//}}}
284
285}