1 19 20 package org.netbeans.editor.ext; 21 22 import java.io.CharArrayWriter ; 23 import java.io.Writer ; 24 import java.io.IOException ; 25 import java.util.Map ; 26 import java.util.HashMap ; 27 import java.util.List ; 28 import java.util.ArrayList ; 29 import java.util.Iterator ; 30 import javax.swing.text.Document ; 31 import javax.swing.text.BadLocationException ; 32 import javax.swing.text.JTextComponent ; 33 import org.netbeans.editor.BaseKit; 34 import org.netbeans.editor.BaseDocument; 35 import org.netbeans.editor.Formatter; 36 import org.netbeans.editor.Settings; 37 import org.netbeans.editor.SettingsUtil; 38 import org.netbeans.editor.SettingsChangeEvent; 39 import org.netbeans.editor.Utilities; 40 import org.netbeans.editor.GuardedException; 41 import org.netbeans.editor.Acceptor; 42 import org.netbeans.editor.AcceptorFactory; 43 import org.netbeans.editor.Syntax; 44 45 69 70 public class ExtFormatter extends Formatter implements FormatLayer { 71 72 73 private List formatLayerList = new ArrayList (); 74 75 76 private static final Object NULL_VALUE = new Object (); 77 78 79 private HashMap settingsMap = new HashMap (); 80 81 85 private HashMap customSettingsNamesMap = new HashMap (); 86 87 private Acceptor indentHotCharsAcceptor; 88 private boolean reindentWithTextBefore; 89 90 public ExtFormatter(Class kitClass) { 91 super(kitClass); 92 93 initFormatLayers(); 94 } 95 96 97 protected void initFormatLayers() { 98 } 99 100 104 public String getName() { 105 return getKitClass().getName().substring( 106 getKitClass().getName().lastIndexOf('.') + 1); 107 } 108 109 public void settingsChange(SettingsChangeEvent evt) { 110 super.settingsChange(evt); 111 String settingName = (evt != null) ? evt.getSettingName() : null; 112 113 Class kitClass = getKitClass(); 114 Iterator eit = settingsMap.entrySet().iterator(); 115 while (eit.hasNext()) { 116 Map.Entry e = (Map.Entry )eit.next(); 117 if (settingName == null || e.getKey().equals(e.getKey())) { 118 if (!customSettingsNamesMap.containsKey(e.getKey())) { e.setValue(Settings.getValue(kitClass, (String )e.getKey())); 120 } 121 } 122 } 123 124 indentHotCharsAcceptor = SettingsUtil.getAcceptor(kitClass, 125 ExtSettingsNames.INDENT_HOT_CHARS_ACCEPTOR, 126 AcceptorFactory.FALSE); 127 128 reindentWithTextBefore = SettingsUtil.getBoolean(kitClass, 129 ExtSettingsNames.REINDENT_WITH_TEXT_BEFORE, 130 false); 131 } 132 133 136 public Object getSettingValue(String settingName) { 137 synchronized (Settings.class) { 138 Object value = settingsMap.get(settingName); 139 if (value == null && !customSettingsNamesMap.containsKey(settingName)) { 140 value = Settings.getValue(getKitClass(), settingName); 141 if (value == null) { 142 value = NULL_VALUE; 143 } 144 settingsMap.put(settingName, value); 145 } 146 return (value != NULL_VALUE) ? value : null; 147 } 148 } 149 150 157 public void setSettingValue(String settingName, Object settingValue) { 158 synchronized (Settings.class) { 159 customSettingsNamesMap.put(settingName, settingName); 160 settingsMap.put(settingName, settingValue); 161 } 162 } 163 164 166 public synchronized void addFormatLayer(FormatLayer layer) { 167 formatLayerList.add(layer); 168 } 169 170 174 public synchronized boolean replaceFormatLayer(String layerName, FormatLayer layer) { 175 int cnt = formatLayerList.size(); 176 for (int i = 0; i < cnt; i++) { 177 if (layerName.equals(((FormatLayer)formatLayerList.get(i)).getName())) { 178 formatLayerList.set(i, layer); 179 return true; 180 } 181 } 182 return false; 183 } 184 185 187 public synchronized void removeFormatLayer(String layerName) { 188 Iterator it = formatLayerIterator(); 189 while (it.hasNext()) { 190 if (layerName.equals(((FormatLayer)it.next()).getName())) { 191 it.remove(); 192 return; 193 } 194 } 195 } 196 197 199 public Iterator formatLayerIterator() { 200 return formatLayerList.iterator(); 201 } 202 203 207 public boolean isSimple() { 208 return false; 209 } 210 211 212 public synchronized void format(FormatWriter fw) { 213 boolean done = false; 214 int safetyCounter = 0; 215 do { 216 fw.setChainModified(false); 218 fw.setRestartFormat(false); 219 220 Iterator it = formatLayerIterator(); 221 while (it.hasNext()) { 222 ((FormatLayer)it.next()).format(fw); 223 if (fw.isRestartFormat()) { 224 break; 225 } 226 } 227 228 if (!it.hasNext() && !fw.isRestartFormat()) { 229 done = true; 230 } 231 232 if (safetyCounter > 1000) { new Exception ("Indentation infinite loop detected").printStackTrace(); break; 235 } 236 } while (!done); 237 } 238 239 248 public Writer reformat(BaseDocument doc, int startOffset, int endOffset, 249 boolean indentOnly) throws BadLocationException , IOException { 250 CharArrayWriter cw = new CharArrayWriter (); 251 Writer w = createWriter(doc, startOffset, cw); 252 FormatWriter fw = (w instanceof FormatWriter) ? (FormatWriter)w : null; 253 254 boolean fix5620 = true; 256 if (fw != null) { 257 fw.setIndentOnly(indentOnly); 258 if (fix5620) { 259 fw.setReformatting(true); } 261 } 262 263 w.write(doc.getChars(startOffset, endOffset - startOffset)); 264 w.close(); 265 266 if (!fix5620 || fw == null) { String out = new String (cw.toCharArray()); 268 doc.remove(startOffset, endOffset - startOffset); 269 doc.insertString(startOffset, out, null); 270 } 271 272 return w; 273 } 274 275 276 public int reformat(BaseDocument doc, int startOffset, int endOffset) 277 throws BadLocationException { 278 try { 279 javax.swing.text.Position pos = doc.createPosition(endOffset); 280 reformat(doc, startOffset, endOffset, false); 281 return pos.getOffset() - startOffset; 282 } catch (IOException e) { 283 e.printStackTrace(); 284 return 0; 285 } 286 } 287 288 298 public int[] getReformatBlock(JTextComponent target, String typedText) { 299 if (indentHotCharsAcceptor == null) { settingsChange(null); 301 } 302 303 if (indentHotCharsAcceptor.accept(typedText.charAt(0))) { 304 311 if(!reindentWithTextBefore) { 312 if(hasTextBefore(target, typedText)) { 313 return null; 314 } 315 } 316 int dotPos = target.getCaret().getDot(); 317 return new int[] { Math.max(dotPos - 1, 0), dotPos }; 318 319 } else { 320 return null; 321 } 322 } 323 324 protected boolean hasTextBefore(JTextComponent target, String typedText) { 325 BaseDocument doc = Utilities.getDocument(target); 326 int dotPos = target.getCaret().getDot(); 327 try { 328 int fnw = Utilities.getRowFirstNonWhite(doc, dotPos); 329 return dotPos != fnw+typedText.length(); 330 } catch (BadLocationException e) { 331 return false; 332 } 333 } 334 335 337 public Writer createWriter(Document doc, int offset, Writer writer) { 338 return new FormatWriter(this, doc, offset, writer, false); 339 } 340 341 347 public int indentLine(Document doc, int offset) { 348 if (doc instanceof BaseDocument) { 349 try { 350 BaseDocument bdoc = (BaseDocument)doc; 351 int lineStart = Utilities.getRowStart(bdoc, offset); 352 int nextLineStart = Utilities.getRowStart(bdoc, offset, 1); 353 if (nextLineStart < 0) { nextLineStart = bdoc.getLength(); 355 } 356 reformat(bdoc, lineStart, nextLineStart, false); 357 return Utilities.getRowEnd(bdoc, lineStart); 358 } catch (GuardedException e) { 359 java.awt.Toolkit.getDefaultToolkit().beep(); 360 361 } catch (BadLocationException e) { 362 Utilities.annotateLoggable(e); 363 } catch (IOException e) { 364 Utilities.annotateLoggable(e); 365 } 366 367 return offset; 368 369 } 370 371 return super.indentLine(doc, offset); 372 } 373 374 375 protected int getEOLOffset(BaseDocument bdoc, int offset) throws BadLocationException { 376 return Utilities.getRowEnd(bdoc, offset); 377 } 378 379 386 public int indentNewLine(Document doc, int offset) { 387 if (doc instanceof BaseDocument) { 388 BaseDocument bdoc = (BaseDocument)doc; 389 boolean newLineInserted = false; 390 391 bdoc.atomicLock(); 392 try { 393 bdoc.insertString(offset, "\n", null); offset++; 395 newLineInserted = true; 396 397 int eolOffset = Utilities.getRowEnd(bdoc, offset); 398 399 Writer w = reformat(bdoc, offset, eolOffset, true); 402 403 eolOffset = Utilities.getRowFirstNonWhite(bdoc, offset); 405 if (eolOffset < 0) { eolOffset = getEOLOffset(bdoc, offset); 407 } 408 409 offset = eolOffset; 410 411 if (w instanceof FormatWriter) { 413 offset += ((FormatWriter)w).getIndentShift(); 414 } 415 416 } catch (GuardedException e) { 417 if (!newLineInserted) { 421 java.awt.Toolkit.getDefaultToolkit().beep(); 422 } 423 424 } catch (BadLocationException e) { 425 Utilities.annotateLoggable(e); 426 } catch (IOException e) { 427 Utilities.annotateLoggable(e); 428 } finally { 429 bdoc.atomicUnlock(); 430 } 431 432 } else { try { 434 doc.insertString (offset, "\n", null); offset++; 436 } catch (BadLocationException ex) { 437 } 438 } 439 440 return offset; 441 } 442 443 450 protected boolean acceptSyntax(Syntax syntax) { 451 return true; 452 } 453 454 455 public static class Simple extends ExtFormatter { 456 457 public Simple(Class kitClass) { 458 super(kitClass); 459 } 460 461 public boolean isSimple() { 462 return true; 463 } 464 465 466 protected int getEOLOffset(BaseDocument bdoc, int offset) throws BadLocationException { 467 return offset; 468 } 469 470 } 471 472 } 473 | Popular Tags |