1 19 20 package org.netbeans.editor; 21 22 import java.util.Map ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.io.IOException ; 26 import java.io.Writer ; 27 import java.io.CharArrayWriter ; 28 import javax.swing.text.Document ; 29 import javax.swing.text.JTextComponent ; 30 import javax.swing.text.BadLocationException ; 31 import org.netbeans.lib.editor.util.CharSequenceUtilities; 32 import org.netbeans.lib.editor.util.swing.DocumentUtilities; 33 34 43 44 public class Formatter implements SettingsChangeListener { 45 46 private static Map kitClass2Formatter = new HashMap (); 47 48 49 public static synchronized Formatter getFormatter(Class kitClass) { 50 Formatter f = (Formatter)kitClass2Formatter.get(kitClass); 51 if (f == null) { 52 f = BaseKit.getKit(kitClass).createFormatter(); 53 kitClass2Formatter.put(kitClass, f); 54 } 55 return f; 56 } 57 58 63 public static synchronized void setFormatter(Class kitClass, Formatter formatter) { 64 kitClass2Formatter.put(kitClass, formatter); 65 } 66 67 68 69 private static final int ISC_MAX_TAB_SIZE = 16; 70 71 72 private static final int ISC_MAX_INDENT_SIZE = 32; 73 74 75 private static final String [][] indentStringCache 76 = new String [ISC_MAX_TAB_SIZE][]; 77 78 79 private final Class kitClass; 80 81 82 private boolean inited; 83 84 private int tabSize; 85 86 private boolean customTabSize; 87 88 private Integer shiftWidth; 89 90 private boolean customShiftWidth; 91 92 private boolean expandTabs; 93 94 private boolean customExpandTabs; 95 96 private int spacesPerTab; 97 98 private boolean customSpacesPerTab; 99 100 104 public Formatter(Class kitClass) { 105 this.kitClass = kitClass; 106 Settings.addSettingsChangeListener(this); 107 } 108 109 110 public Class getKitClass() { 111 return kitClass; 112 } 113 114 public void settingsChange(SettingsChangeEvent evt) { 115 String settingName = (evt != null) ? evt.getSettingName() : null; 116 if (!inited || settingName == null || SettingsNames.TAB_SIZE.equals(settingName)) { 117 if (!customTabSize) { 118 tabSize = SettingsUtil.getInteger(kitClass, SettingsNames.TAB_SIZE, 119 SettingsDefaults.defaultTabSize); 120 } 121 } 122 123 if (!customShiftWidth) { 125 Object shw = Settings.getValue(kitClass, SettingsNames.INDENT_SHIFT_WIDTH); 126 if (shw instanceof Integer ) { 127 shiftWidth = (Integer )shw; 128 } 129 } 130 131 if (!inited || settingName == null || SettingsNames.EXPAND_TABS.equals(settingName)) { 132 if (!customExpandTabs) { 133 expandTabs = SettingsUtil.getBoolean(kitClass, SettingsNames.EXPAND_TABS, 134 SettingsDefaults.defaultExpandTabs); 135 } 136 } 137 if (!inited || settingName == null || SettingsNames.SPACES_PER_TAB.equals(settingName)) { 138 if (!customSpacesPerTab) { 139 spacesPerTab = SettingsUtil.getInteger(kitClass, SettingsNames.SPACES_PER_TAB, 140 SettingsDefaults.defaultSpacesPerTab); 141 } 142 } 143 144 inited = true; 145 } 146 147 158 public int getTabSize() { 159 if (!customTabSize && !inited) { 160 settingsChange(null); 161 } 162 163 return tabSize; 164 } 165 166 173 public void setTabSize(int tabSize) { 174 customTabSize = true; 175 this.tabSize = tabSize; 176 } 177 178 179 186 public int getShiftWidth() { 187 if (!customShiftWidth && !inited) { 188 settingsChange(null); 189 } 190 191 return (shiftWidth != null) ? shiftWidth.intValue() : getSpacesPerTab(); 192 } 193 194 199 public void setShiftWidth(int shiftWidth) { 200 customShiftWidth = true; 201 if (this.shiftWidth == null || this.shiftWidth.intValue() != shiftWidth) { 202 this.shiftWidth = new Integer (shiftWidth); 203 } 204 } 205 206 207 public boolean expandTabs() { 208 if (!customExpandTabs && !inited) { 209 settingsChange(null); 210 } 211 212 return expandTabs; 213 } 214 215 public void setExpandTabs(boolean expandTabs) { 216 customExpandTabs = true; 217 this.expandTabs = expandTabs; 218 } 219 220 223 public int getSpacesPerTab() { 224 if (!customSpacesPerTab && !inited) { 225 settingsChange(null); 226 } 227 228 return spacesPerTab; 229 } 230 231 public void setSpacesPerTab(int spacesPerTab) { 232 customSpacesPerTab = true; 233 this.spacesPerTab = spacesPerTab; 234 } 235 236 static String getIndentString(int indent, boolean expandTabs, int tabSize) { 237 if (indent <= 0) { 238 return ""; 239 } 240 241 if (expandTabs) { tabSize = 0; 243 } 244 245 synchronized (Settings.class) { 246 boolean large = (tabSize >= indentStringCache.length) 247 || (indent > ISC_MAX_INDENT_SIZE); String indentString = null; 249 String [] tabCache = null; 250 if (!large) { 251 tabCache = indentStringCache[tabSize]; if (tabCache == null) { 253 tabCache = new String [ISC_MAX_INDENT_SIZE]; 254 indentStringCache[tabSize] = tabCache; 255 } 256 indentString = tabCache[indent - 1]; 257 } 258 259 if (indentString == null) { 260 indentString = Analyzer.getIndentString(indent, expandTabs, tabSize); 261 262 if (!large) { 263 tabCache[indent - 1] = indentString; 264 } 265 } 266 267 return indentString; 268 } 269 } 270 271 public String getIndentString(BaseDocument doc, int indent) { 272 return getIndentString(indent, expandTabs(), doc.getTabSize()); 273 } 274 275 276 281 public String getIndentString(int indent) { 282 return getIndentString(indent, expandTabs(), getTabSize()); 283 } 284 285 291 public void insertTabString(BaseDocument doc, int dotPos) 292 throws BadLocationException { 293 doc.atomicLock(); 294 try { 295 int rsPos = Utilities.getRowStart(doc, dotPos); 297 int startPos = Utilities.getFirstNonWhiteBwd(doc, dotPos, rsPos); 298 startPos = (startPos >= 0) ? (startPos + 1) : rsPos; 299 300 int startCol = Utilities.getVisualColumn(doc, startPos); 301 int endCol = Utilities.getNextTabColumn(doc, dotPos); 302 String tabStr = Analyzer.getWhitespaceString(startCol, endCol, expandTabs(), doc.getTabSize()); 303 304 char[] removeChars = doc.getChars(startPos, dotPos - startPos); 306 int ind = 0; 307 while (ind < removeChars.length && removeChars[ind] == tabStr.charAt(ind)) { 308 ind++; 309 } 310 311 startPos += ind; 312 doc.remove(startPos, dotPos - startPos); 313 doc.insertString(startPos, tabStr.substring(ind), null); 314 315 } finally { 316 doc.atomicUnlock(); 317 } 318 } 319 320 323 public void changeRowIndent(BaseDocument doc, int pos, int newIndent) 324 throws BadLocationException { 325 doc.atomicLock(); 326 try { 327 if (newIndent < 0) { 328 newIndent = 0; 329 } 330 int firstNW = Utilities.getRowFirstNonWhite(doc, pos); 331 if (firstNW == -1) { firstNW = Utilities.getRowEnd(doc, pos); 333 } 334 int replacePos = Utilities.getRowStart(doc, pos); 335 int removeLen = firstNW - replacePos; 336 CharSequence removeText = DocumentUtilities.getText(doc, replacePos, removeLen); 337 String newIndentText = getIndentString(doc, newIndent); 338 if (CharSequenceUtilities.startsWith(newIndentText, removeText)) { 339 newIndentText = newIndentText.substring(removeLen); 341 replacePos += removeLen; 342 removeLen = 0; 343 } else if (CharSequenceUtilities.endsWith(newIndentText, removeText)) { 344 newIndentText = newIndentText.substring(0, newIndentText.length() - removeLen); 346 removeLen = 0; 347 } 348 349 if (removeLen != 0) { 350 doc.remove(replacePos, removeLen); 351 } 352 353 doc.insertString(replacePos, newIndentText, null); 354 } finally { 355 doc.atomicUnlock(); 356 } 357 } 358 359 367 public void changeBlockIndent(BaseDocument doc, int startPos, int endPos, 368 int shiftCnt) throws BadLocationException { 369 370 371 GuardedDocument gdoc = (doc instanceof GuardedDocument) 372 ? (GuardedDocument)doc : null; 373 if (gdoc != null){ 374 for (int i = startPos; i<endPos; i++){ 375 if (gdoc.isPosGuarded(i)){ 376 java.awt.Toolkit.getDefaultToolkit().beep(); 377 return; 378 } 379 } 380 } 381 382 doc.atomicLock(); 383 try { 384 385 int indentDelta = shiftCnt * doc.getShiftWidth(); 386 if (endPos > 0 && Utilities.getRowStart(doc, endPos) == endPos) { 387 endPos--; 388 } 389 390 int pos = Utilities.getRowStart(doc, startPos ); 391 for (int lineCnt = Utilities.getRowCount(doc, startPos, endPos); 392 lineCnt > 0; lineCnt-- 393 ) { 394 int indent = Utilities.getRowIndent(doc, pos); 395 if (Utilities.isRowWhite(doc, pos)) { 396 indent = -indentDelta; } 398 changeRowIndent(doc, pos, Math.max(indent + indentDelta, 0)); 399 pos = Utilities.getRowStart(doc, pos, +1); 400 } 401 402 } finally { 403 doc.atomicUnlock(); 404 } 405 } 406 407 408 public void shiftLine(BaseDocument doc, int dotPos, boolean right) 409 throws BadLocationException { 410 int ind = doc.getShiftWidth(); 411 if (!right) { 412 ind = -ind; 413 } 414 415 if (Utilities.isRowWhite(doc, dotPos)) { 416 ind += Utilities.getVisualColumn(doc, dotPos); 417 } else { 418 ind += Utilities.getRowIndent(doc, dotPos); 419 } 420 ind = Math.max(ind, 0); 421 changeRowIndent(doc, dotPos, ind); 422 } 423 424 430 public int reformat(BaseDocument doc, int startOffset, int endOffset) 431 throws BadLocationException { 432 try { 433 CharArrayWriter cw = new CharArrayWriter (); 434 Writer w = createWriter(doc, startOffset, cw); 435 w.write(doc.getChars(startOffset, endOffset - startOffset)); 436 w.close(); 437 String out = new String (cw.toCharArray()); 438 doc.remove(startOffset, endOffset - startOffset); 439 doc.insertString(startOffset, out, null); 440 return out.length(); 441 } catch (IOException e) { 442 Utilities.annotateLoggable(e); 443 return 0; 444 } 445 } 446 447 453 public int indentLine(Document doc, int offset) { 454 return offset; 455 } 456 457 464 public int indentNewLine(Document doc, int offset) { 465 try { 466 doc.insertString(offset, "\n", null); offset++; 468 469 } catch (GuardedException e) { 470 java.awt.Toolkit.getDefaultToolkit().beep(); 471 472 } catch (BadLocationException e) { 473 Utilities.annotateLoggable(e); 474 } 475 476 return offset; 477 } 478 479 496 public Writer createWriter(Document doc, int offset, Writer writer) { 497 return writer; 498 } 499 500 } 501 | Popular Tags |