1 7 package javax.swing.text; 8 9 import java.io.Serializable ; 10 import java.lang.reflect.*; 11 import java.text.ParseException ; 12 import javax.swing.*; 13 import javax.swing.text.*; 14 15 42 public class DefaultFormatter extends JFormattedTextField.AbstractFormatter 43 implements Cloneable , Serializable { 44 45 private boolean allowsInvalid; 46 47 48 private boolean overwriteMode; 49 50 51 private boolean commitOnEdit; 52 53 54 private Class valueClass; 55 56 57 private NavigationFilter navigationFilter; 58 59 60 private DocumentFilter documentFilter; 61 62 63 transient ReplaceHolder replaceHolder; 64 65 66 69 public DefaultFormatter() { 70 overwriteMode = true; 71 allowsInvalid = true; 72 } 73 74 104 public void install(JFormattedTextField ftf) { 105 super.install(ftf); 106 positionCursorAtInitialLocation(); 107 } 108 109 123 public void setCommitsOnValidEdit(boolean commit) { 124 commitOnEdit = commit; 125 } 126 127 133 public boolean getCommitsOnValidEdit() { 134 return commitOnEdit; 135 } 136 137 144 public void setOverwriteMode(boolean overwriteMode) { 145 this.overwriteMode = overwriteMode; 146 } 147 148 153 public boolean getOverwriteMode() { 154 return overwriteMode; 155 } 156 157 167 public void setAllowsInvalid(boolean allowsInvalid) { 168 this.allowsInvalid = allowsInvalid; 169 } 170 171 177 public boolean getAllowsInvalid() { 178 return allowsInvalid; 179 } 180 181 189 public void setValueClass(Class <?> valueClass) { 190 this.valueClass = valueClass; 191 } 192 193 198 public Class <?> getValueClass() { 199 return valueClass; 200 } 201 202 216 public Object stringToValue(String string) throws ParseException { 217 Class vc = getValueClass(); 218 JFormattedTextField ftf = getFormattedTextField(); 219 220 if (vc == null && ftf != null) { 221 Object value = ftf.getValue(); 222 223 if (value != null) { 224 vc = value.getClass(); 225 } 226 } 227 if (vc != null) { 228 Constructor cons; 229 230 try { 231 cons = vc.getConstructor(new Class [] { String .class }); 232 233 } catch (NoSuchMethodException nsme) { 234 cons = null; 235 } 236 237 if (cons != null) { 238 try { 239 return cons.newInstance(new Object [] { string }); 240 } catch (Throwable ex) { 241 throw new ParseException ("Error creating instance", 0); 242 } 243 } 244 } 245 return string; 246 } 247 248 256 public String valueToString(Object value) throws ParseException { 257 if (value == null) { 258 return ""; 259 } 260 return value.toString(); 261 } 262 263 269 protected DocumentFilter getDocumentFilter() { 270 if (documentFilter == null) { 271 documentFilter = new DefaultDocumentFilter(); 272 } 273 return documentFilter; 274 } 275 276 282 protected NavigationFilter getNavigationFilter() { 283 if (navigationFilter == null) { 284 navigationFilter = new DefaultNavigationFilter(); 285 } 286 return navigationFilter; 287 } 288 289 294 public Object clone() throws CloneNotSupportedException { 295 DefaultFormatter formatter = (DefaultFormatter )super.clone(); 296 297 formatter.navigationFilter = null; 298 formatter.documentFilter = null; 299 formatter.replaceHolder = null; 300 return formatter; 301 } 302 303 304 307 void positionCursorAtInitialLocation() { 308 JFormattedTextField ftf = getFormattedTextField(); 309 if (ftf != null) { 310 ftf.setCaretPosition(getInitialVisualPosition()); 311 } 312 } 313 314 318 int getInitialVisualPosition() { 319 return getNextNavigatableChar(0, 1); 320 } 321 322 328 boolean isNavigatable(int offset) { 329 return true; 330 } 331 332 337 boolean isLegalInsertText(String text) { 338 return true; 339 } 340 341 345 private int getNextNavigatableChar(int offset, int direction) { 346 int max = getFormattedTextField().getDocument().getLength(); 347 348 while (offset >= 0 && offset < max) { 349 if (isNavigatable(offset)) { 350 return offset; 351 } 352 offset += direction; 353 } 354 return offset; 355 } 356 357 363 String getReplaceString(int offset, int deleteLength, 364 String replaceString) { 365 String string = getFormattedTextField().getText(); 366 String result; 367 368 result = string.substring(0, offset); 369 if (replaceString != null) { 370 result += replaceString; 371 } 372 if (offset + deleteLength < string.length()) { 373 result += string.substring(offset + deleteLength); 374 } 375 return result; 376 } 377 378 383 boolean isValidEdit(ReplaceHolder rh) { 384 if (!getAllowsInvalid()) { 385 String newString = getReplaceString(rh.offset, rh.length, rh.text); 386 387 try { 388 rh.value = stringToValue(newString); 389 390 return true; 391 } catch (ParseException pe) { 392 return false; 393 } 394 } 395 return true; 396 } 397 398 401 void commitEdit() throws ParseException { 402 JFormattedTextField ftf = getFormattedTextField(); 403 404 if (ftf != null) { 405 ftf.commitEdit(); 406 } 407 } 408 409 414 void updateValue() { 415 updateValue(null); 416 } 417 418 423 void updateValue(Object value) { 424 try { 425 if (value == null) { 426 String string = getFormattedTextField().getText(); 427 428 value = stringToValue(string); 429 } 430 431 if (getCommitsOnValidEdit()) { 432 commitEdit(); 433 } 434 setEditValid(true); 435 } catch (ParseException pe) { 436 setEditValid(false); 437 } 438 } 439 440 446 int getNextCursorPosition(int offset, int direction) { 447 int newOffset = getNextNavigatableChar(offset, direction); 448 int max = getFormattedTextField().getDocument().getLength(); 449 450 if (!getAllowsInvalid()) { 451 if (direction == -1 && offset == newOffset) { 452 newOffset = getNextNavigatableChar(newOffset, 1); 455 if (newOffset >= max) { 456 newOffset = offset; 457 } 458 } 459 else if (direction == 1 && newOffset >= max) { 460 newOffset = getNextNavigatableChar(max - 1, -1); 462 if (newOffset < max) { 463 newOffset++; 464 } 465 } 466 } 467 return newOffset; 468 } 469 470 473 void repositionCursor(int offset, int direction) { 474 getFormattedTextField().getCaret().setDot(getNextCursorPosition 475 (offset, direction)); 476 } 477 478 479 482 int getNextVisualPositionFrom(JTextComponent text, int pos, 483 Position.Bias bias, int direction, 484 Position.Bias [] biasRet) 485 throws BadLocationException { 486 int value = text.getUI().getNextVisualPositionFrom(text, pos, bias, 487 direction, biasRet); 488 489 if (value == -1) { 490 return -1; 491 } 492 if (!getAllowsInvalid() && (direction == SwingConstants.EAST || 493 direction == SwingConstants.WEST)) { 494 int last = -1; 495 496 while (!isNavigatable(value) && value != last) { 497 last = value; 498 value = text.getUI().getNextVisualPositionFrom( 499 text, value, bias, direction,biasRet); 500 } 501 int max = getFormattedTextField().getDocument().getLength(); 502 if (last == value || value == max) { 503 if (value == 0) { 504 biasRet[0] = Position.Bias.Forward; 505 value = getInitialVisualPosition(); 506 } 507 if (value >= max && max > 0) { 508 biasRet[0] = Position.Bias.Forward; 510 value = getNextNavigatableChar(max - 1, -1) + 1; 511 } 512 } 513 } 514 return value; 515 } 516 517 521 boolean canReplace(ReplaceHolder rh) { 522 return isValidEdit(rh); 523 } 524 525 528 void replace(DocumentFilter.FilterBypass fb, int offset, 529 int length, String text, 530 AttributeSet attrs) throws BadLocationException { 531 ReplaceHolder rh = getReplaceHolder(fb, offset, length, text, attrs); 532 533 replace(rh); 534 } 535 536 546 boolean replace(ReplaceHolder rh) throws BadLocationException { 547 boolean valid = true; 548 int direction = 1; 549 550 if (rh.length > 0 && (rh.text == null || rh.text.length() == 0) && 551 (getFormattedTextField().getSelectionStart() != rh.offset || 552 rh.length > 1)) { 553 direction = -1; 554 } 555 556 if (getOverwriteMode() && rh.text != null) { 557 rh.length = Math.min(Math.max(rh.length, rh.text.length()), 558 rh.fb.getDocument().getLength() - rh.offset); 559 } 560 if ((rh.text != null && !isLegalInsertText(rh.text)) || 561 !canReplace(rh) || 562 (rh.length == 0 && (rh.text == null || rh.text.length() == 0))) { 563 valid = false; 564 } 565 if (valid) { 566 int cursor = rh.cursorPosition; 567 568 rh.fb.replace(rh.offset, rh.length, rh.text, rh.attrs); 569 if (cursor == -1) { 570 cursor = rh.offset; 571 if (direction == 1 && rh.text != null) { 572 cursor = rh.offset + rh.text.length(); 573 } 574 } 575 updateValue(rh.value); 576 repositionCursor(cursor, direction); 577 return true; 578 } 579 else { 580 invalidEdit(); 581 } 582 return false; 583 } 584 585 589 void setDot(NavigationFilter.FilterBypass fb, int dot, Position.Bias bias){ 590 fb.setDot(dot, bias); 591 } 592 593 597 void moveDot(NavigationFilter.FilterBypass fb, int dot, 598 Position.Bias bias) { 599 fb.moveDot(dot, bias); 600 } 601 602 603 607 ReplaceHolder getReplaceHolder(DocumentFilter.FilterBypass fb, int offset, 608 int length, String text, 609 AttributeSet attrs) { 610 if (replaceHolder == null) { 611 replaceHolder = new ReplaceHolder(); 612 } 613 replaceHolder.reset(fb, offset, length, text, attrs); 614 return replaceHolder; 615 } 616 617 618 622 static class ReplaceHolder { 623 624 DocumentFilter.FilterBypass fb; 625 626 int offset; 627 628 int length; 629 630 String text; 631 632 AttributeSet attrs; 633 634 Object value; 635 640 int cursorPosition; 641 642 void reset(DocumentFilter.FilterBypass fb, int offset, int length, 643 String text, AttributeSet attrs) { 644 this.fb = fb; 645 this.offset = offset; 646 this.length = length; 647 this.text = text; 648 this.attrs = attrs; 649 this.value = null; 650 cursorPosition = -1; 651 } 652 } 653 654 655 659 private class DefaultNavigationFilter extends NavigationFilter 660 implements Serializable { 661 public void setDot(FilterBypass fb, int dot, Position.Bias bias) { 662 JTextComponent tc = DefaultFormatter.this.getFormattedTextField(); 663 if (tc.composedTextExists()) { 664 fb.setDot(dot, bias); 666 } else { 667 DefaultFormatter.this.setDot(fb, dot, bias); 668 } 669 } 670 671 public void moveDot(FilterBypass fb, int dot, Position.Bias bias) { 672 JTextComponent tc = DefaultFormatter.this.getFormattedTextField(); 673 if (tc.composedTextExists()) { 674 fb.moveDot(dot, bias); 676 } else { 677 DefaultFormatter.this.moveDot(fb, dot, bias); 678 } 679 } 680 681 public int getNextVisualPositionFrom(JTextComponent text, int pos, 682 Position.Bias bias, 683 int direction, 684 Position.Bias [] biasRet) 685 throws BadLocationException { 686 if (text.composedTextExists()) { 687 return text.getUI().getNextVisualPositionFrom( 689 text, pos, bias, direction, biasRet); 690 } else { 691 return DefaultFormatter.this.getNextVisualPositionFrom( 692 text, pos, bias, direction, biasRet); 693 } 694 } 695 } 696 697 698 702 private class DefaultDocumentFilter extends DocumentFilter implements 703 Serializable { 704 public void remove(FilterBypass fb, int offset, int length) throws 705 BadLocationException { 706 JTextComponent tc = DefaultFormatter.this.getFormattedTextField(); 707 if (tc.composedTextExists()) { 708 fb.remove(offset, length); 710 } else { 711 DefaultFormatter.this.replace(fb, offset, length, null, null); 712 } 713 } 714 715 public void insertString(FilterBypass fb, int offset, 716 String string, AttributeSet attr) throws 717 BadLocationException { 718 JTextComponent tc = DefaultFormatter.this.getFormattedTextField(); 719 if (tc.composedTextExists() || 720 Utilities.isComposedTextAttributeDefined(attr)) { 721 fb.insertString(offset, string, attr); 723 } else { 724 DefaultFormatter.this.replace(fb, offset, 0, string, attr); 725 } 726 } 727 728 public void replace(FilterBypass fb, int offset, int length, 729 String text, AttributeSet attr) throws 730 BadLocationException { 731 JTextComponent tc = DefaultFormatter.this.getFormattedTextField(); 732 if (tc.composedTextExists() || 733 Utilities.isComposedTextAttributeDefined(attr)) { 734 fb.replace(offset, length, text, attr); 736 } else { 737 DefaultFormatter.this.replace(fb, offset, length, text, attr); 738 } 739 } 740 } 741 } 742 | Popular Tags |