1 package prefuse.util.ui; 2 3 import java.awt.BasicStroke ; 4 import java.awt.Color ; 5 import java.awt.Cursor ; 6 import java.awt.Dimension ; 7 import java.awt.Graphics ; 8 import java.awt.Graphics2D ; 9 import java.awt.Rectangle ; 10 import java.awt.event.KeyEvent ; 11 import java.awt.event.KeyListener ; 12 import java.awt.event.MouseEvent ; 13 import java.awt.event.MouseListener ; 14 import java.awt.event.MouseMotionListener ; 15 import java.util.ArrayList ; 16 import java.util.Iterator ; 17 18 import javax.swing.BoundedRangeModel ; 19 import javax.swing.DefaultBoundedRangeModel ; 20 import javax.swing.JComponent ; 21 import javax.swing.event.ChangeEvent ; 22 import javax.swing.event.ChangeListener ; 23 24 34 public class JRangeSlider extends JComponent 35 implements MouseListener , MouseMotionListener , KeyListener 36 { 37 52 53 final public static int VERTICAL = 0; 54 final public static int HORIZONTAL = 1; 55 final public static int LEFTRIGHT_TOPBOTTOM = 0; 56 final public static int RIGHTLEFT_BOTTOMTOP = 1; 57 58 final public static int PREFERRED_BREADTH = 16; 59 final public static int PREFERRED_LENGTH = 300; 60 final protected static int ARROW_SZ = 16; 61 final protected static int ARROW_WIDTH = 8; 62 final protected static int ARROW_HEIGHT = 4; 63 64 protected BoundedRangeModel model; 65 protected int orientation; 66 protected int direction; 67 protected boolean empty; 68 protected int increment = 1; 69 protected int minExtent = 0; 71 protected ArrayList listeners = new ArrayList (); 72 protected ChangeEvent changeEvent = null; 73 protected ChangeListener lstnr; 74 75 protected Color thumbColor = new Color (150,180,220); 76 77 79 88 public JRangeSlider(int minimum, int maximum, int lowValue, int highValue, int orientation) { 89 this(new DefaultBoundedRangeModel (lowValue,highValue,minimum,maximum), 90 orientation,LEFTRIGHT_TOPBOTTOM); 91 } 92 93 103 public JRangeSlider(int minimum, int maximum, int lowValue, int highValue, int orientation, int direction) { 104 this(new DefaultBoundedRangeModel (lowValue, highValue, minimum, maximum), 105 orientation, direction); 106 } 107 108 115 public JRangeSlider(BoundedRangeModel model, int orientation, int direction) { 116 super.setFocusable(true); 117 this.model = model; 118 this.orientation = orientation; 119 this.direction = direction; 120 121 setForeground(Color.LIGHT_GRAY); 122 123 this.lstnr = createListener(); 124 model.addChangeListener(lstnr); 125 126 addMouseListener(this); 127 addMouseMotionListener(this); 128 addKeyListener(this); 129 } 130 131 135 protected ChangeListener createListener() { 136 return new RangeSliderChangeListener(); 137 } 138 139 143 protected class RangeSliderChangeListener implements ChangeListener { 144 public void stateChanged(ChangeEvent e) { 145 fireChangeEvent(); 146 } 147 } 148 149 153 public int getLowValue() { 154 return model.getValue(); 155 } 156 157 162 public void setLowValue(int lowValue) { 163 int e = (model.getValue()-lowValue)+model.getExtent(); 164 model.setRangeProperties(lowValue, e, 165 model.getMinimum(), model.getMaximum(), false); 166 model.setValue(lowValue); 167 } 168 169 173 public int getHighValue() { 174 return model.getValue()+model.getExtent(); 175 } 176 177 182 public void setHighValue(int highValue) { 183 model.setExtent(highValue-model.getValue()); 184 } 185 186 191 public void setRange(int lowValue, int highValue) { 192 model.setRangeProperties(lowValue, highValue-lowValue, 193 model.getMinimum(), model.getMaximum(), false); 194 } 195 196 200 public int getMinimum() { 201 return model.getMinimum(); 202 } 203 204 208 public void setMinimum(int minimum) { 209 model.setMinimum(minimum); 210 } 211 212 216 public int getMaximum() { 217 return model.getMaximum(); 218 } 219 220 224 public void setMaximum(int maximum) { 225 model.setMaximum(maximum); 226 } 227 228 234 public void setMinExtent(int minExtent) { 235 this.minExtent = minExtent; 236 } 237 238 242 public void setEmpty(boolean empty) { 243 this.empty = empty; 244 repaint(); 245 } 246 247 252 public Color getThumbColor() { 253 return thumbColor; 254 } 255 256 261 public void setThumbColor(Color thumbColor) { 262 this.thumbColor = thumbColor; 263 } 264 265 269 public BoundedRangeModel getModel() { 270 return model; 271 } 272 273 277 public void setModel(BoundedRangeModel brm) { 278 model.removeChangeListener(lstnr); 279 model = brm; 280 model.addChangeListener(lstnr); 281 repaint(); 282 } 283 284 288 public void addChangeListener(ChangeListener cl) { 289 if ( !listeners.contains(cl) ) 290 listeners.add(cl); 291 } 292 293 297 public void removeChangeListener(ChangeListener cl) { 298 listeners.remove(cl); 299 } 300 301 304 protected void fireChangeEvent() { 305 repaint(); 306 if ( changeEvent == null ) 307 changeEvent = new ChangeEvent (this); 308 Iterator iter = listeners.iterator(); 309 while ( iter.hasNext() ) 310 ((ChangeListener )iter.next()).stateChanged(changeEvent); 311 } 312 313 316 public Dimension getPreferredSize() { 317 if (orientation == VERTICAL) { 318 return new Dimension (PREFERRED_BREADTH, PREFERRED_LENGTH); 319 } 320 else { 321 return new Dimension (PREFERRED_LENGTH, PREFERRED_BREADTH); 322 } 323 } 324 325 328 334 protected void customPaint(Graphics2D g, int width, int height) { 335 } 338 339 342 public void paintComponent(Graphics g) { 343 Rectangle bounds = getBounds(); 344 int width = (int)bounds.getWidth() - 1; 345 int height = (int)bounds.getHeight() - 1; 346 347 int min = toScreen(getLowValue()); 348 int max = toScreen(getHighValue()); 349 350 if (empty) { 352 if (direction == LEFTRIGHT_TOPBOTTOM) { 353 min = ARROW_SZ; 354 max = (orientation == VERTICAL) ? height-ARROW_SZ : width-ARROW_SZ; 355 } 356 else { 357 min = (orientation == VERTICAL) ? height-ARROW_SZ : width-ARROW_SZ; 358 max = ARROW_SZ; 359 } 360 } 361 362 Graphics2D g2 = (Graphics2D )g; 363 g2.setColor(getBackground()); 364 g2.fillRect(0, 0, width, height); 365 g2.setColor(getForeground()); 366 g2.drawRect(0, 0, width, height); 367 368 customPaint(g2, width, height); 369 370 g2.setStroke(new BasicStroke (1)); 372 if (orientation == VERTICAL) { 373 if (direction == LEFTRIGHT_TOPBOTTOM) { 374 g2.setColor(getForeground()); 375 g2.fillRect(0, min - ARROW_SZ, width, ARROW_SZ-1); 376 paint3DRectLighting(g2,0,min-ARROW_SZ,width,ARROW_SZ-1); 377 378 if ( thumbColor != null ) { 379 g2.setColor(thumbColor); 380 g2.fillRect(0, min, width, max - min-1); 381 paint3DRectLighting(g2,0,min,width,max-min-1); 382 } 383 384 g2.setColor(getForeground()); 385 g2.fillRect(0, max, width, ARROW_SZ-1); 386 paint3DRectLighting(g2,0,max,width,ARROW_SZ-1); 387 388 g2.setColor(Color.black); 390 paintArrow(g2, (width-ARROW_WIDTH) / 2.0, min - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, true); 391 paintArrow(g2, (width-ARROW_WIDTH) / 2.0, max + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, false); 392 } 393 else { 394 g2.setColor(getForeground()); 395 g2.fillRect(0, min, width, ARROW_SZ-1); 396 paint3DRectLighting(g2,0,min,width,ARROW_SZ-1); 397 398 if ( thumbColor != null ) { 399 g2.setColor(thumbColor); 400 g2.fillRect(0, max, width, min-max-1); 401 paint3DRectLighting(g2,0,max,width,min-max-1); 402 } 403 404 g2.setColor(getForeground()); 405 g2.fillRect(0, max-ARROW_SZ, width, ARROW_SZ-1); 406 paint3DRectLighting(g2,0,max-ARROW_SZ,width,ARROW_SZ-1); 407 408 g2.setColor(Color.black); 410 paintArrow(g2, (width-ARROW_WIDTH) / 2.0, min + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, false); 411 paintArrow(g2, (width-ARROW_WIDTH) / 2.0, max - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, ARROW_WIDTH, ARROW_HEIGHT, true); 412 } 413 } 414 else { 415 if (direction == LEFTRIGHT_TOPBOTTOM) { 416 g2.setColor(getForeground()); 417 g2.fillRect(min - ARROW_SZ, 0, ARROW_SZ-1, height); 418 paint3DRectLighting(g2,min-ARROW_SZ,0,ARROW_SZ-1,height); 419 420 if ( thumbColor != null ) { 421 g2.setColor(thumbColor); 422 g2.fillRect(min, 0, max - min - 1, height); 423 paint3DRectLighting(g2,min,0,max-min-1,height); 424 } 425 426 g2.setColor(getForeground()); 427 g2.fillRect(max, 0, ARROW_SZ-1, height); 428 paint3DRectLighting(g2,max,0,ARROW_SZ-1,height); 429 430 g2.setColor(Color.black); 432 paintArrow(g2, min - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, (height-ARROW_WIDTH) / 2.0, ARROW_HEIGHT, ARROW_WIDTH, true); 433 paintArrow(g2, max + (ARROW_SZ-ARROW_HEIGHT) / 2.0, (height-ARROW_WIDTH) / 2.0, ARROW_HEIGHT, ARROW_WIDTH, false); 434 } 435 else { 436 g2.setColor(getForeground()); 437 g2.fillRect(min, 0, ARROW_SZ - 1, height); 438 paint3DRectLighting(g2,min,0,ARROW_SZ-1,height); 439 440 if ( thumbColor != null ) { 441 g2.setColor(thumbColor); 442 g2.fillRect(max, 0, min - max - 1, height); 443 paint3DRectLighting(g2,max,0,min-max-1,height); 444 } 445 446 g2.setColor(getForeground()); 447 g2.fillRect(max-ARROW_SZ, 0, ARROW_SZ-1, height); 448 paint3DRectLighting(g2,max-ARROW_SZ,0,ARROW_SZ-1,height); 449 450 g2.setColor(Color.black); 452 paintArrow(g2, min + (ARROW_SZ-ARROW_HEIGHT) / 2.0, (height-ARROW_WIDTH) / 2.0, ARROW_HEIGHT, ARROW_WIDTH, true); 453 paintArrow(g2, max - ARROW_SZ + (ARROW_SZ-ARROW_HEIGHT) / 2.0, (height-ARROW_WIDTH) / 2.0, ARROW_HEIGHT, ARROW_WIDTH, false); 454 } 455 } 456 } 457 458 463 protected void paintArrow(Graphics2D g2, double x, double y, int w, int h, 464 boolean topDown) 465 { 466 int intX = (int)(x+0.5); 467 int intY = (int)(y+0.5); 468 469 if (orientation == VERTICAL) { 470 if (w % 2 == 0) { 471 w = w - 1; 472 } 473 474 if (topDown) { 475 for(int i=0; i<(w/2+1); i++) { 476 g2.drawLine(intX+i,intY+i,intX+w-i-1,intY+i); 477 } 478 } 479 else { 480 for(int i=0; i<(w/2+1); i++) { 481 g2.drawLine(intX+w/2-i,intY+i,intX+w-w/2+i-1,intY+i); 482 } 483 } 484 } 485 else { 486 if (h % 2 == 0) { 487 h = h - 1; 488 } 489 490 if (topDown) { 491 for(int i=0; i<(h/2+1); i++) { 492 g2.drawLine(intX+i,intY+i,intX+i,intY+h-i-1); 493 } 494 } 495 else { 496 for(int i=0; i<(h/2+1); i++) { 497 g2.drawLine(intX+i,intY+h/2-i,intX+i,intY+h-h/2+i-1); 498 } 499 } 500 } 501 } 502 503 506 protected void paint3DRectLighting(Graphics2D g2, int x, int y, 507 int width, int height) 508 { 509 g2.setColor(Color.white); 510 g2.drawLine(x+1,y+1,x+1,y+height-1); 511 g2.drawLine(x+1,y+1,x+width-1,y+1); 512 g2.setColor(Color.gray); 513 g2.drawLine(x+1,y+height-1,x+width-1,y+height-1); 514 g2.drawLine(x+width-1,y+1,x+width-1,y+height-1); 515 g2.setColor(Color.darkGray); 516 g2.drawLine(x,y+height,x+width,y+height); 517 g2.drawLine(x+width,y,x+width,y+height); 518 } 519 520 523 protected int toLocal(int xOrY) { 524 Dimension sz = getSize(); 525 int min = getMinimum(); 526 double scale; 527 if (orientation == VERTICAL) { 528 scale = (sz.height - (2 * ARROW_SZ)) / (double) (getMaximum() - min); 529 } 530 else { 531 scale = (sz.width - (2 * ARROW_SZ)) / (double) (getMaximum() - min); 532 } 533 534 if (direction == LEFTRIGHT_TOPBOTTOM) { 535 return (int) (((xOrY - ARROW_SZ) / scale) + min + 0.5); 536 } 537 else { 538 if (orientation == VERTICAL) { 539 return (int) ((sz.height - xOrY - ARROW_SZ) / scale + min + 0.5); 540 } 541 else { 542 return (int) ((sz.width - xOrY - ARROW_SZ) / scale + min + 0.5); 543 } 544 } 545 } 546 547 550 protected int toScreen(int xOrY) { 551 Dimension sz = getSize(); 552 int min = getMinimum(); 553 double scale; 554 if (orientation == VERTICAL) { 555 scale = (sz.height - (2 * ARROW_SZ)) / (double) (getMaximum() - min); 556 } 557 else { 558 scale = (sz.width - (2 * ARROW_SZ)) / (double) (getMaximum() - min); 559 } 560 561 if (direction == LEFTRIGHT_TOPBOTTOM) { 564 return (int)(ARROW_SZ + ((xOrY - min) * scale) + 0.5); 565 } 566 else { 567 if (orientation == VERTICAL) { 568 return (int)(sz.height-(xOrY - min) * scale - ARROW_SZ + 0.5); 569 } 570 else { 571 return (int)(sz.width-(xOrY - min) * scale - ARROW_SZ + 0.5); 572 } 573 } 574 } 575 576 579 protected double toScreenDouble(int xOrY) { 580 Dimension sz = getSize(); 581 int min = getMinimum(); 582 double scale; 583 if (orientation == VERTICAL) { 584 scale = (sz.height - (2 * ARROW_SZ)) / (double) (getMaximum()+1 - min); 585 } 586 else { 587 scale = (sz.width - (2 * ARROW_SZ)) / (double) (getMaximum()+1 - min); 588 } 589 590 if (direction == LEFTRIGHT_TOPBOTTOM) { 593 return ARROW_SZ + ((xOrY - min) * scale); 594 } 595 else { 596 if (orientation == VERTICAL) { 597 return sz.height-(xOrY - min) * scale - ARROW_SZ; 598 } 599 else { 600 return sz.width-(xOrY - min) * scale - ARROW_SZ; 601 } 602 } 603 } 604 605 606 609 static final int PICK_NONE = 0; 610 static final int PICK_LEFT_OR_TOP = 1; 611 static final int PICK_THUMB = 2; 612 static final int PICK_RIGHT_OR_BOTTOM = 3; 613 int pick; 614 int pickOffsetLow; 615 int pickOffsetHigh; 616 int mouse; 617 618 private int pickHandle(int xOrY) { 619 int min = toScreen(getLowValue()); 620 int max = toScreen(getHighValue()); 621 int pick = PICK_NONE; 622 623 if (direction == LEFTRIGHT_TOPBOTTOM) { 624 if ((xOrY > (min - ARROW_SZ)) && (xOrY < min)) { 625 pick = PICK_LEFT_OR_TOP; 626 } else if ((xOrY >= min) && (xOrY <= max)) { 627 pick = PICK_THUMB; 628 } else if ((xOrY > max) && (xOrY < (max + ARROW_SZ))) { 629 pick = PICK_RIGHT_OR_BOTTOM; 630 } 631 } 632 else { 633 if ((xOrY > min) && (xOrY < (min + ARROW_SZ))) { 634 pick = PICK_LEFT_OR_TOP; 635 } else if ((xOrY <= min) && (xOrY >= max)) { 636 pick = PICK_THUMB; 637 } else if ((xOrY > (max - ARROW_SZ) && (xOrY < max))) { 638 pick = PICK_RIGHT_OR_BOTTOM; 639 } 640 } 641 642 return pick; 643 } 644 645 private void offset(int dxOrDy) { 646 model.setValue(model.getValue()+dxOrDy); 647 } 648 649 652 public void mousePressed(MouseEvent e) { 653 if (orientation == VERTICAL) { 654 pick = pickHandle(e.getY()); 655 pickOffsetLow = e.getY() - toScreen(getLowValue()); 656 pickOffsetHigh = e.getY() - toScreen(getHighValue()); 657 mouse = e.getY(); 658 } 659 else { 660 pick = pickHandle(e.getX()); 661 pickOffsetLow = e.getX() - toScreen(getLowValue()); 662 pickOffsetHigh = e.getX() - toScreen(getHighValue()); 663 mouse = e.getX(); 664 } 665 repaint(); 666 } 667 668 671 public void mouseDragged(MouseEvent e) { 672 requestFocus(); 673 int value = (orientation == VERTICAL) ? e.getY() : e.getX(); 674 675 int minimum = getMinimum(); 676 int maximum = getMaximum(); 677 int lowValue = getLowValue(); 678 int highValue = getHighValue(); 679 680 switch (pick) { 681 case PICK_LEFT_OR_TOP: 682 int low = toLocal(value-pickOffsetLow); 683 684 if (low < minimum) { 685 low = minimum; 686 } 687 if (low > maximum) { 688 low = maximum; 689 } 690 if (low > highValue-minExtent) { 691 low = highValue-minExtent; 692 } 693 setLowValue(low); 694 break; 695 696 case PICK_RIGHT_OR_BOTTOM: 697 int high = toLocal(value-pickOffsetHigh); 698 699 if (high < minimum) { 700 high = minimum; 701 } 702 if (high > maximum) { 703 high = maximum; 704 } 705 if (high < lowValue+minExtent) { 706 high = lowValue+minExtent; 707 } 708 setHighValue(high); 709 break; 710 711 case PICK_THUMB: 712 int dxOrDy = toLocal(value - pickOffsetLow) - lowValue; 713 if ((dxOrDy < 0) && ((lowValue + dxOrDy) < minimum)) { 714 dxOrDy = minimum - lowValue; 715 } 716 if ((dxOrDy > 0) && ((highValue + dxOrDy) > maximum)) { 717 dxOrDy = maximum - highValue; 718 } 719 if (dxOrDy != 0) { 720 offset(dxOrDy); 721 } 722 break; 723 } 724 } 725 726 729 public void mouseReleased(MouseEvent e) { 730 pick = PICK_NONE; 731 repaint(); 732 } 733 734 737 public void mouseMoved(MouseEvent e) { 738 if (orientation == VERTICAL) { 739 switch (pickHandle(e.getY())) { 740 case PICK_LEFT_OR_TOP: 741 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 742 break; 743 case PICK_RIGHT_OR_BOTTOM: 744 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 745 break; 746 case PICK_THUMB: 747 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 748 break; 749 case PICK_NONE : 750 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 751 break; 752 } 753 } 754 else { 755 switch (pickHandle(e.getX())) { 756 case PICK_LEFT_OR_TOP: 757 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 758 break; 759 case PICK_RIGHT_OR_BOTTOM: 760 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 761 break; 762 case PICK_THUMB: 763 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 764 break; 765 case PICK_NONE : 766 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 767 break; 768 } 769 } 770 } 771 772 775 public void mouseClicked(MouseEvent e) { 776 } 777 780 public void mouseEntered(MouseEvent e) { 781 } 782 785 public void mouseExited(MouseEvent e) { 786 } 787 788 private void grow(int increment) { 789 model.setRangeProperties(model.getValue()-increment, 790 model.getExtent()+2*increment, 791 model.getMinimum(), model.getMaximum(), false); 792 } 793 794 797 public void keyPressed(KeyEvent e) { 798 int kc = e.getKeyCode(); 799 boolean v = (orientation == VERTICAL); 800 boolean d = (kc == KeyEvent.VK_DOWN); 801 boolean u = (kc == KeyEvent.VK_UP); 802 boolean l = (kc == KeyEvent.VK_LEFT); 803 boolean r = (kc == KeyEvent.VK_RIGHT); 804 805 int minimum = getMinimum(); 806 int maximum = getMaximum(); 807 int lowValue = getLowValue(); 808 int highValue = getHighValue(); 809 810 if ( v&&r || !v&&u ) { 811 if ( lowValue-increment >= minimum && 812 highValue+increment <= maximum ) { 813 grow(increment); 814 } 815 } else if ( v&&l || !v&&d ) { 816 if ( highValue-lowValue >= 2*increment ) { 817 grow(-1*increment); 818 } 819 } else if ( v&&d || !v&&l ) { 820 if ( lowValue-increment >= minimum ) { 821 offset(-increment); 822 } 823 } else if ( v&&u || !v&&r ) { 824 if ( highValue+increment <= maximum ) { 825 offset(increment); 826 } 827 } 828 } 829 830 833 public void keyReleased(KeyEvent e) { 834 } 835 838 public void keyTyped(KeyEvent e) { 839 } 840 841 } | Popular Tags |