PageRenderTime 43ms CodeModel.GetById 16ms 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
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  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. package sidekick.css;
  22. //{{{ Imports
  23. import java.io.*;
  24. import java.util.*;
  25. import java.util.regex.*;
  26. import org.apache.xerces.parsers.*;
  27. import org.gjt.sp.jedit.*;
  28. import org.gjt.sp.jedit.buffer.JEditBuffer;
  29. import org.gjt.sp.util.Log;
  30. import org.gjt.sp.jedit.textarea.*;
  31. import org.w3c.dom.*;
  32. import org.xml.sax.InputSource;
  33. import org.xml.sax.SAXException;
  34. import sidekick.SideKickCompletion;
  35. import xml.Resolver;
  36. //}}}
  37. public class CssSideKickCompletion extends SideKickCompletion {
  38. public final static String SPECIAL_URL_PROP = "url...";
  39. public static String QUOTE;
  40. private static boolean choosingFile = false;
  41. //{{{ CssSideKickCompletion constructor
  42. public CssSideKickCompletion(List completions, String word, boolean selectedProperty) {
  43. super(jEdit.getActiveView(), word, completions);
  44. this.selectedProperty = selectedProperty;
  45. if (!inited) {
  46. readConfig();
  47. }
  48. } //}}}
  49. //{{{ readConfig() method
  50. public static void readConfig() {
  51. QUOTE = jEdit.getProperty(CssSideKickPlugin.OPTION_PREFIX + "quote");
  52. } //}}}
  53. //{{{ insert() method
  54. public void insert(int index) {
  55. String selected = String.valueOf(get(index));
  56. JEditBuffer buffer = textArea.getBuffer();
  57. int caret = textArea.getCaretPosition();
  58. int moveCaret = 0;
  59. // when "url..." confirmed by ENTER, the this method is called twice
  60. // it seem as a Sidekick's bug to me.
  61. if (choosingFile) {
  62. return;
  63. }
  64. // If selected property, handle colon
  65. if (selectedProperty && jEdit.getBooleanProperty(CssSideKickPlugin.OPTION_PREFIX + "colon")) {
  66. String textAfter = buffer.getText(caret, buffer.getLength() - caret - 1);
  67. // If isn't colon after caret, add one after property.
  68. // Otherwise check, if do we have between property and that colon some mess
  69. // and if we haven't, move caret after colon
  70. if (canAddColon(textAfter)) {
  71. selected += ":";
  72. if (jEdit.getBooleanProperty(CssSideKickPlugin.OPTION_PREFIX + "space-after-colon")) {
  73. selected += " ";
  74. }
  75. } else if (Pattern.compile("^\\s*:").matcher(textAfter).find()) {
  76. moveCaret = textAfter.indexOf(":") + 1;
  77. }
  78. } else if (selected.equals("url")) {
  79. selected = "url(" + QUOTE + QUOTE + ")";
  80. moveCaret = -2;
  81. } else if (selected.equals(SPECIAL_URL_PROP)){
  82. choosingFile = true;
  83. selected = "url(" + QUOTE + Utils.chooseFileAndGetRelativePath() + QUOTE + ")";
  84. choosingFile = false;
  85. }
  86. Selection s = textArea.getSelectionAtOffset(caret);
  87. int start = (s == null ? caret : s.getStart());
  88. int end = (s == null ? caret : s.getEnd());
  89. try {
  90. buffer.beginCompoundEdit();
  91. buffer.remove(start - text.length(),text.length());
  92. buffer.insert(start - text.length(),selected);
  93. } finally {
  94. buffer.endCompoundEdit();
  95. }
  96. textArea.setCaretPosition(end + selected.length() + moveCaret - text.length());
  97. } //}}}
  98. //{{{ getCssProperties() method
  99. public static HashMap getCssProperties() {
  100. return cssProperties;
  101. } //}}}
  102. //{{{ getCssUnits() method
  103. public static ArrayList getCssUnits() {
  104. return cssUnits;
  105. } //}}}
  106. //{{{ setInitialized() method
  107. public static void setInitialized(boolean initialized) {
  108. CssSideKickCompletion.initialized = initialized;
  109. } //}}}
  110. //{{{ initialized() method
  111. public static boolean initialized() {
  112. return initialized;
  113. } //}}}
  114. //{{{ initialize() method
  115. public static void initialize() {
  116. setInitialized(true);
  117. readCompletionConfig();
  118. }
  119. //}}}
  120. //{{{ Private members
  121. private boolean selectedProperty;
  122. private static ArrayList<String> cssUnits;
  123. private static HashMap<String,ArrayList<String>> cssProperties;
  124. private static boolean initialized;
  125. /* private static String COMPLETION_CONFIG_FILE = jEdit.getSettingsDirectory()
  126. + File.separator
  127. + jEdit.getProperty(CssSideKickPlugin.OPTION_PREFIX + "completion-config"); */
  128. private static final String COMPLETION_CONFIG_FILE = "jeditresource:/XML.jar!/xml/completion/css-complete.xml";
  129. private static Pattern HAS_PROP_COLON = Pattern.compile("^[^;}]*:");
  130. private static boolean inited;
  131. //{{{ canAddColon() method
  132. private static boolean canAddColon(String textAfterCaret) {
  133. return !HAS_PROP_COLON.matcher(textAfterCaret).find();
  134. } //}}}
  135. //{{{ readCompletionConfig() method
  136. private static void readCompletionConfig() {
  137. try {
  138. Log.log(Log.DEBUG, CssSideKickCompletion.class, "Parsing configuration file: " + COMPLETION_CONFIG_FILE);
  139. DOMParser parser = new DOMParser();
  140. parser.setEntityResolver(Resolver.instance());
  141. InputSource source = Resolver.instance().resolveEntity(null, COMPLETION_CONFIG_FILE );
  142. parser.parse(source);
  143. Document doc = parser.getDocument();
  144. initCssUnits(doc);
  145. initCssProperties(doc);
  146. Log.log(Log.DEBUG,
  147. CssSideKickCompletion.class,
  148. "Parsing done, found " + cssProperties.size() + " css properties and " + cssUnits.size() + " css units");
  149. } catch (FileNotFoundException e) {
  150. GUIUtilities.error(jEdit.getActiveView(),
  151. "csssidekick.config-io-error",
  152. new String[]{
  153. e.getMessage()
  154. });
  155. } catch (IOException e) {
  156. GUIUtilities.error(jEdit.getActiveView(),
  157. "csssidekick.config-io-error",
  158. new String[]{
  159. e.getMessage()
  160. });
  161. Log.log(Log.ERROR, CssSideKickCompletion.class, e);
  162. } catch (SAXException e) {
  163. GUIUtilities.error(jEdit.getActiveView(),
  164. "csssidekick.config-xml-error",
  165. new String[]{e.getMessage()});
  166. Log.log(Log.ERROR, CssSideKickCompletion.class, e);
  167. } catch (Exception e) {
  168. Log.log(Log.ERROR, CssSideKickCompletion.class, e);
  169. }
  170. } //}}}
  171. //{{{ initCssProperties() method
  172. private static void initCssProperties(Document doc) {
  173. cssProperties = new HashMap<String,ArrayList<String>>();
  174. NodeList propertiesElements = doc.getElementsByTagName("properties");
  175. if (propertiesElements.getLength() != 1) {
  176. // throw new Exception("No <properties> found");
  177. }
  178. NodeList properties = ((Element)propertiesElements.item(0)).getElementsByTagName("property");
  179. int propCount = properties.getLength();
  180. // loop properties
  181. for (int i = 0; i < propCount; i++) {
  182. Element propEle = (Element) properties.item(i);
  183. String propName = propEle.getAttribute("name");
  184. NodeList values = propEle.getElementsByTagName("*");
  185. int valCount = values.getLength();
  186. ArrayList<String> valList = new ArrayList<String>();
  187. // loop values
  188. for (int j = 0; j < valCount; j++) {
  189. Element ele = (Element) values.item(j);
  190. String name = ele.getAttribute("name");
  191. if (ele.getTagName().equals("include")) {
  192. NodeList incValues = doc.getElementById(name).getElementsByTagName("value");
  193. int incValCount = incValues.getLength();
  194. // loop included values
  195. for (int k = 0; k < incValCount; k++) {
  196. Element incValEle = (Element)incValues.item(k);
  197. String incValText = incValEle.getFirstChild().getNodeValue();
  198. if (incValText.equals("url")) {
  199. valList.add(SPECIAL_URL_PROP);
  200. }
  201. valList.add(incValText);
  202. }
  203. continue;
  204. }
  205. String valText = ele.getFirstChild().getNodeValue();
  206. if (valText.equals("url")) {
  207. valList.add(SPECIAL_URL_PROP);
  208. }
  209. valList.add(valText);
  210. }
  211. cssProperties.put(propName, valList);
  212. }
  213. } //}}}
  214. //{{{ initCssUnits() method
  215. private static void initCssUnits(Document doc) {
  216. cssUnits = new ArrayList<String>();
  217. NodeList unitsElements = doc.getElementsByTagName("units");
  218. NodeList units = ((Element)unitsElements.item(0)).getElementsByTagName("unit");
  219. int unitsCount = units.getLength();
  220. for (int i = 0; i < unitsCount; i++) {
  221. Element unitEle = (Element)units.item(i);
  222. String unitText = unitEle.getFirstChild().getNodeValue();
  223. cssUnits.add(unitText);
  224. }
  225. } //}}}
  226. //}}}
  227. }