1 19 20 package org.netbeans.modules.xml.text.completion; 21 22 import java.awt.Container ; 23 import java.awt.event.ActionListener ; 24 import java.lang.reflect.InvocationTargetException ; 25 import javax.swing.JEditorPane ; 26 import javax.swing.Timer ; 27 import javax.swing.event.CaretEvent ; 28 import javax.swing.event.CaretListener ; 29 import javax.swing.text.BadLocationException ; 30 import javax.swing.text.Caret ; 31 import javax.swing.text.Document ; 32 33 import org.netbeans.editor.BaseDocument; 34 import org.netbeans.modules.xml.api.model.GrammarQuery; 35 import org.netbeans.modules.xml.api.model.HintContext; 36 import org.netbeans.modules.xml.text.completion.XMLCompletionQuery; 37 import org.netbeans.modules.xml.text.completion.GrammarManager; 38 import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport; 39 import org.openide.nodes.FilterNode; 40 import org.openide.nodes.Node; 41 import org.openide.nodes.Sheet; 42 import org.openide.windows.TopComponent; 43 import org.openide.util.NbBundle; 44 import org.w3c.dom.DOMException ; 45 46 54 public final class NodeSelector { 55 56 57 private CaretListener caretListener; 58 59 private Timer timerSelNodes; 61 62 63 private int lastCaretOffset = -1; 64 65 66 private static final int SELECTED_NODES_DELAY = 200; 67 68 private JEditorPane pane; 69 70 private XMLSyntaxSupport syntaxSupport; 71 72 private Node originalUINode; 73 74 HintContext hintContext; 75 76 77 public NodeSelector(final JEditorPane pane) { 78 this.pane = pane; 79 80 caretListener = new CaretListener () { 81 public void caretUpdate(CaretEvent e) { 82 restartTimerSelNodes(e.getDot()); 83 } 84 }; 85 86 timerSelNodes = new Timer (100, new java.awt.event.ActionListener () { 87 public void actionPerformed(java.awt.event.ActionEvent e) { 88 if (lastCaretOffset == -1 && pane != null) { 89 Caret caret = pane.getCaret(); 90 if (caret != null) 91 lastCaretOffset = caret.getDot(); 92 } 93 selectElementsAtOffset(lastCaretOffset); 94 } 95 }); 96 timerSelNodes.setInitialDelay(100); 97 timerSelNodes.setRepeats(false); 98 timerSelNodes.restart(); 99 100 pane.addCaretListener(caretListener); 101 102 } 104 105 108 void restartTimerSelNodes(int pos) { 109 timerSelNodes.setInitialDelay(SELECTED_NODES_DELAY); 110 lastCaretOffset = pos; 111 timerSelNodes.restart(); 112 } 113 114 115 synchronized void selectElementsAtOffset(final int offset) { 116 if (syntaxSupport == null) { 117 Document doc = pane.getDocument(); 118 if (doc instanceof BaseDocument) { 119 syntaxSupport = (XMLSyntaxSupport) ((BaseDocument)doc).getSyntaxSupport(); 120 } 121 if (syntaxSupport == null) { 122 return; 123 } 124 } 125 126 Container parent = pane.getParent(); 127 while (parent != null && !(parent instanceof TopComponent)){ 128 parent = parent.getParent(); 129 } 130 if (parent == null) { 131 return; 132 } 133 134 TopComponent topComp = (TopComponent)parent; 135 Node activeNodes[] = topComp.getActivatedNodes(); 136 if (activeNodes == null || activeNodes.length == 0) { 137 return; } 139 140 if (originalUINode == null) { 141 originalUINode = activeNodes[0]; 142 } 143 144 146 GrammarQuery grammarQuery = XMLCompletionQuery.getPerformer(pane.getDocument(), syntaxSupport); 147 if (grammarQuery == null) { 148 return; 149 } 150 151 SyntaxQueryHelper helper = null; 152 try { 153 helper = new SyntaxQueryHelper(syntaxSupport, offset); 154 } catch (BadLocationException e) { 155 topComp.setActivatedNodes(new Node[]{new DelegatingNode(originalUINode, null, null)}); 156 return; 157 } 158 159 Node newUiNode = new DelegatingNode(originalUINode, grammarQuery, helper.getContext()); 160 161 topComp.setActivatedNodes(new Node[]{newUiNode}); 162 } 163 164 private class DelegatingNode extends FilterNode { 165 166 GrammarQuery grammarQuery; 167 168 HintContext hintContext; 169 170 Sheet propSheet; 171 172 public DelegatingNode(Node peer, GrammarQuery grammarQuery, HintContext hintContext) { 173 super(peer); 174 this.grammarQuery = grammarQuery; 175 this.hintContext = hintContext; 176 } 177 178 public java.awt.Component getCustomizer() { 179 if (grammarQuery == null || hintContext == null) { 180 return super.getCustomizer(); 181 } else { 182 return grammarQuery.getCustomizer(hintContext); 183 } 184 } 185 186 public boolean hasCustomizer() { 187 if (grammarQuery == null || hintContext == null) { 188 return super.hasCustomizer(); 189 } else { 190 return grammarQuery.hasCustomizer(hintContext); 191 } 192 } 193 194 public Node.PropertySet[] getPropertySets() { 195 if (propSheet == null) { 196 propSheet = Sheet.createDefault(); 197 Sheet.Set nodePropertySet = propSheet.get(Sheet.PROPERTIES); 198 199 if (grammarQuery != null && hintContext != null) { 200 Node.Property[] nodeProperties = grammarQuery.getProperties(hintContext); 201 if (nodeProperties != null && nodeProperties.length > 0) { 202 nodePropertySet.put(nodeProperties); 204 return propSheet.toArray(); 205 } 206 } 207 208 org.w3c.dom.Element attributeOwningElem = null; 211 if (hintContext != null) { 212 if (hintContext.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { 213 attributeOwningElem = (org.w3c.dom.Element )hintContext; 214 } else if (hintContext.getNodeType() == org.w3c.dom.Node.ATTRIBUTE_NODE) { 215 attributeOwningElem = (org.w3c.dom.Element )((org.w3c.dom.Attr )hintContext).getOwnerElement(); 216 } 217 } 218 219 if (attributeOwningElem != null) { 220 org.w3c.dom.NamedNodeMap attributes = attributeOwningElem.getAttributes(); 222 for (int ind = 0; ind < attributes.getLength(); ind++) { 223 org.w3c.dom.Node node = attributes.item(ind); 224 nodePropertySet.put(new AttributeProperty(attributeOwningElem, node.getNodeName())); 225 } 226 227 } 228 } 229 230 return propSheet.toArray(); 231 } 232 } 233 234 237 private class AttributeProperty extends org.openide.nodes.PropertySupport { 238 private final String propName; 239 private final org.w3c.dom.Element ownerElem; 240 private boolean canWrite = true; 241 242 public AttributeProperty(org.w3c.dom.Element ownerElem, String propName) { 243 super(propName, String .class, propName, propName, true, true); 244 this.ownerElem = ownerElem; 245 this.propName = propName; 246 } 247 248 public void setValue(Object value) { 249 try { 250 ownerElem.setAttribute(propName, (String )value); 251 } catch (DOMException ex) { 252 canWrite = false; 253 } 254 } 255 256 public Object getValue() { 257 try { 258 return ownerElem.getAttribute(propName); 259 } catch (DOMException ex) { 260 canWrite = false; 262 return NbBundle.getMessage(NodeSelector.class, "BK0001"); 263 } 264 } 265 266 270 public boolean canWrite() { 271 return canWrite; 272 } 273 274 } 275 } 276 | Popular Tags |