1 7 8 package javax.swing.plaf.synth; 9 10 import java.awt.Component ; 11 import java.awt.Container ; 12 import java.awt.Adjustable ; 13 import java.awt.event.*; 14 import java.awt.Graphics ; 15 import java.awt.Dimension ; 16 import java.awt.Font ; 17 import java.awt.FontMetrics ; 18 import java.awt.Rectangle ; 19 import java.awt.Point ; 20 import java.awt.Insets ; 21 import java.awt.Color ; 22 import java.awt.IllegalComponentStateException ; 23 import java.awt.Polygon ; 24 import java.beans.*; 25 import java.util.Dictionary ; 26 import java.util.Enumeration ; 27 import javax.swing.border.AbstractBorder ; 28 import javax.swing.*; 29 import javax.swing.event.*; 30 import javax.swing.plaf.*; 31 import javax.swing.plaf.basic.BasicSliderUI ; 32 import sun.swing.plaf.synth.SynthUI; 33 import com.sun.java.swing.SwingUtilities2; 34 35 36 42 class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, 43 SynthUI { 44 protected Dimension contentDim = new Dimension (); 45 protected Rectangle valueRect = new Rectangle (); 46 protected boolean paintValue; 47 48 private int trackHeight; 49 private int trackBorder; 50 private int thumbWidth; 51 private int thumbHeight; 52 53 private SynthStyle style; 54 private SynthStyle sliderTrackStyle; 55 private SynthStyle sliderThumbStyle; 56 57 58 private transient boolean thumbActive; 59 60 public static ComponentUI createUI(JComponent c) { 64 return new SynthSliderUI ((JSlider)c); 65 } 66 67 public SynthSliderUI(JSlider c) { 68 super(c); 69 } 70 71 protected void installDefaults(JSlider slider) { 72 updateStyle(slider); 73 } 74 75 protected void uninstallDefaults() { 76 SynthContext context = getContext(slider, ENABLED); 77 style.uninstallDefaults(context); 78 context.dispose(); 79 style = null; 80 81 context = getContext(slider, Region.SLIDER_TRACK, ENABLED); 82 sliderTrackStyle.uninstallDefaults(context); 83 context.dispose(); 84 sliderTrackStyle = null; 85 86 context = getContext(slider, Region.SLIDER_THUMB, ENABLED); 87 sliderThumbStyle.uninstallDefaults(context); 88 context.dispose(); 89 sliderThumbStyle = null; 90 } 91 92 protected void installListeners(JSlider slider) { 93 super.installListeners(slider); 94 slider.addPropertyChangeListener(this); 95 } 96 97 protected void uninstallListeners() { 98 slider.removePropertyChangeListener(this); 99 super.uninstallListeners(slider); 100 } 101 102 private void updateStyle(JSlider c) { 103 SynthContext context = getContext(c, ENABLED); 104 SynthStyle oldStyle = style; 105 style = SynthLookAndFeel.updateStyle(context, this); 106 107 if (style != oldStyle) { 108 thumbWidth = 109 style.getInt(context, "Slider.thumbWidth", 30); 110 111 thumbHeight = 112 style.getInt(context, "Slider.thumbHeight", 14); 113 114 trackBorder = 115 style.getInt(context, "Slider.trackBorder", 1); 116 117 trackHeight = thumbHeight + trackBorder * 2; 118 119 paintValue = style.getBoolean(context, 120 "Slider.paintValue", true); 121 if (oldStyle != null) { 122 uninstallKeyboardActions(c); 123 installKeyboardActions(c); 124 } 125 } 126 context.dispose(); 127 128 context = getContext(c, Region.SLIDER_TRACK, ENABLED); 129 sliderTrackStyle = 130 SynthLookAndFeel.updateStyle(context, this); 131 context.dispose(); 132 133 context = getContext(c, Region.SLIDER_THUMB, ENABLED); 134 sliderThumbStyle = 135 SynthLookAndFeel.updateStyle(context, this); 136 context.dispose(); 137 } 138 139 protected TrackListener createTrackListener(JSlider s) { 140 return new SynthTrackListener(); 141 } 142 143 private void updateThumbState(int x, int y) { 144 setThumbActive(thumbRect.contains(x, y)); 145 } 146 147 private void setThumbActive(boolean active) { 148 if (thumbActive != active) { 149 thumbActive = active; 150 slider.repaint(thumbRect); 151 } 152 } 153 154 public Dimension getPreferredSize(JComponent c) { 155 recalculateIfInsetsChanged(); 156 Dimension d = new Dimension (contentDim); 157 if (slider.getOrientation() == JSlider.VERTICAL) { 158 d.height = 200; 159 } else { 160 d.width = 200; 161 } 162 return d; 163 } 164 165 public Dimension getMinimumSize(JComponent c) { 166 recalculateIfInsetsChanged(); 167 Dimension d = new Dimension (contentDim); 168 if (slider.getOrientation() == JSlider.VERTICAL) { 169 d.height = thumbRect.height + insetCache.top + insetCache.bottom; 170 } else { 171 d.width = thumbRect.width + insetCache.left + insetCache.right; 172 } 173 return d; 174 } 175 176 protected void calculateGeometry() { 177 layout(); 178 calculateThumbLocation(); 179 } 180 181 protected void layout() { 182 SynthContext context = getContext(slider); 183 SynthGraphicsUtils synthGraphics = style.getGraphicsUtils(context); 184 185 Dimension size = getThumbSize(); 187 thumbRect.setSize(size.width, size.height); 188 189 Insets trackInsets = new Insets (0, 0, 0, 0); 191 SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK); 192 style.getInsets(trackContext, trackInsets); 193 trackContext.dispose(); 194 195 if (slider.getOrientation() == JSlider.HORIZONTAL) { 196 valueRect.height = 0; 199 if (paintValue) { 200 valueRect.height = 201 synthGraphics.getMaximumCharHeight(context); 202 } 203 204 trackRect.height = trackHeight; 205 206 tickRect.height = 0; 207 if (slider.getPaintTicks()) { 208 tickRect.height = getTickLength(); 209 } 210 211 labelRect.height = 0; 212 if (slider.getPaintLabels()) { 213 labelRect.height = getHeightOfTallestLabel(); 214 } 215 216 contentDim.height = valueRect.height + trackRect.height 217 + trackInsets.top + trackInsets.bottom 218 + tickRect.height + labelRect.height + 4; 219 contentDim.width = slider.getWidth() - insetCache.left 220 - insetCache.right; 221 222 223 int centerY = slider.getHeight() / 2 - contentDim.height / 2; 224 225 valueRect.x = trackRect.x = tickRect.x = labelRect.x = 227 insetCache.left; 228 valueRect.width = trackRect.width = 229 tickRect.width = labelRect.width = contentDim.width; 230 231 valueRect.y = centerY; 232 centerY += valueRect.height + 2; 233 234 trackRect.y = centerY + trackInsets.top; 235 centerY += trackRect.height + trackInsets.top + trackInsets.bottom; 236 237 tickRect.y = centerY; 238 centerY += tickRect.height + 2; 239 240 labelRect.y = centerY; 241 centerY += labelRect.height; 242 } else { 243 trackRect.width = trackHeight; 246 247 tickRect.width = 0; 248 if (slider.getPaintTicks()) { 249 tickRect.width = getTickLength(); 250 } 251 252 labelRect.width = 0; 253 if (slider.getPaintLabels()) { 254 labelRect.width = getWidthOfWidestLabel(); 255 } 256 257 valueRect.y = insetCache.top; 258 valueRect.height = 0; 259 if (paintValue) { 260 valueRect.height = 261 synthGraphics.getMaximumCharHeight(context); 262 } 263 264 contentDim.width = trackRect.width + trackInsets.left 265 + trackInsets.right + tickRect.width 266 + labelRect.width + 2 + insetCache.left + insetCache.right; 267 contentDim.height = slider.getHeight() 268 - insetCache.top - insetCache.bottom; 269 270 int startX = slider.getWidth() / 2 - contentDim.width / 2; 271 272 FontMetrics fm = slider.getFontMetrics(slider.getFont()); 274 valueRect.width = Math.max( 275 synthGraphics.computeStringWidth(context, slider.getFont(), 276 fm, "" + slider.getMaximum()), 277 synthGraphics.computeStringWidth(context, slider.getFont(), 278 fm, "" + slider.getMinimum())); 279 280 if (valueRect.width > (trackRect.width + trackInsets.left 284 + trackInsets.right)) { 285 int diff = (valueRect.width - (trackRect.width 286 + trackInsets.left + trackInsets.right)) / 2; 287 contentDim.width += diff; 288 startX += diff; 289 } 290 291 trackRect.y = tickRect.y = labelRect.y = 293 valueRect.y + valueRect.height; 294 trackRect.height = tickRect.height = labelRect.height = 295 contentDim.height - valueRect.height; 296 297 if (SynthLookAndFeel.isLeftToRight(slider)) { 298 trackRect.x = startX + trackInsets.left; 299 startX += trackRect.width + trackInsets.right + 300 trackInsets.left; 301 302 tickRect.x = startX; 303 startX += tickRect.width + 2; 304 305 labelRect.x = startX; 306 } else { 307 labelRect.x = startX; 308 startX += labelRect.width + 2; 309 310 tickRect.x = startX; 311 startX += tickRect.width + trackInsets.left; 312 313 trackRect.x = startX; 314 } 315 } 316 context.dispose(); 317 } 318 319 protected void calculateThumbLocation() { 320 if (slider.getSnapToTicks()) { 321 int sliderValue = slider.getValue(); 322 int snappedValue = sliderValue; 323 int majorTickSpacing = slider.getMajorTickSpacing(); 324 int minorTickSpacing = slider.getMinorTickSpacing(); 325 int tickSpacing = 0; 326 327 if (minorTickSpacing > 0) { 328 tickSpacing = minorTickSpacing; 329 } else if (majorTickSpacing > 0) { 330 tickSpacing = majorTickSpacing; 331 } 332 333 if (tickSpacing != 0) { 334 if ((sliderValue - slider.getMinimum()) % tickSpacing != 0) { 336 float temp = (float)(sliderValue - slider.getMinimum()) 337 / (float)tickSpacing; 338 int whichTick = Math.round( temp ); 339 snappedValue = 340 slider.getMinimum() + (whichTick * tickSpacing); 341 } 342 343 if (snappedValue != sliderValue) { 344 slider.setValue(snappedValue); 345 } 346 } 347 } 348 349 if (slider.getOrientation() == JSlider.HORIZONTAL) { 350 int valuePosition = xPositionForValue(slider.getValue()); 351 thumbRect.x = valuePosition - (thumbRect.width / 2); 352 thumbRect.y = trackRect.y + trackBorder; 353 } else { 354 int valuePosition = yPositionForValue(slider.getValue()); 355 thumbRect.x = trackRect.x + trackBorder; 356 thumbRect.y = valuePosition - (thumbRect.height / 2); 357 } 358 } 359 360 protected void calculateTickRect() { 361 if (slider.getOrientation() == JSlider.HORIZONTAL) { 362 tickRect.x = trackRect.x; 363 tickRect.y = trackRect.y + trackRect.height + 2 + getTickLength(); 364 tickRect.width = trackRect.width; 365 tickRect.height = getTickLength(); 366 367 if (!slider.getPaintTicks()) { 368 --tickRect.y; 369 tickRect.height = 0; 370 } 371 } else { 372 if (SynthLookAndFeel.isLeftToRight(slider)) { 373 tickRect.x = trackRect.x + trackRect.width; 374 tickRect.width = getTickLength(); 375 } else { 376 tickRect.width = getTickLength(); 377 tickRect.x = trackRect.x - tickRect.width; 378 } 379 tickRect.y = trackRect.y; 380 tickRect.height = trackRect.height; 381 382 if (!slider.getPaintTicks()) { 383 --tickRect.x; 384 tickRect.width = 0; 385 } 386 } 387 } 388 389 private static Rectangle unionRect = new Rectangle (); 390 391 public void setThumbLocation(int x, int y) { 392 super.setThumbLocation(x, y); 393 slider.repaint(valueRect.x, valueRect.y, 396 valueRect.width, valueRect.height); 397 setThumbActive(false); 398 } 399 400 protected int xPositionForValue(int value) { 401 int min = slider.getMinimum(); 402 int max = slider.getMaximum(); 403 int trackLeft = trackRect.x + thumbRect.width / 2 + trackBorder; 404 int trackRight = trackRect.x + trackRect.width - thumbRect.width / 2 405 - trackBorder; 406 int trackLength = trackRight - trackLeft; 407 double valueRange = (double)max - (double)min; 408 double pixelsPerValue = (double)trackLength / valueRange; 409 int xPosition; 410 411 if (!drawInverted()) { 412 xPosition = trackLeft; 413 xPosition += Math.round( pixelsPerValue * ((double)value - min)); 414 } else { 415 xPosition = trackRight; 416 xPosition -= Math.round( pixelsPerValue * ((double)value - min)); 417 } 418 419 xPosition = Math.max(trackLeft, xPosition); 420 xPosition = Math.min(trackRight, xPosition); 421 422 return xPosition; 423 } 424 425 protected int yPositionForValue(int value) { 426 int min = slider.getMinimum(); 427 int max = slider.getMaximum(); 428 int trackTop = trackRect.y + thumbRect.height / 2 + trackBorder; 429 int trackBottom = trackRect.y + trackRect.height 430 - thumbRect.height / 2 - trackBorder; 431 int trackLength = trackBottom - trackTop; 432 double valueRange = (double)max - (double)min; 433 double pixelsPerValue = (double)trackLength / (double)valueRange; 434 int yPosition; 435 436 if (!drawInverted()) { 437 yPosition = trackTop; 438 yPosition += Math.round(pixelsPerValue * ((double)max - value)); 439 } else { 440 yPosition = trackTop; 441 yPosition += Math.round(pixelsPerValue * ((double)value - min)); 442 } 443 444 yPosition = Math.max(trackTop, yPosition); 445 yPosition = Math.min(trackBottom, yPosition); 446 447 return yPosition; 448 } 449 450 455 public int valueForYPosition(int yPos) { 456 int value; 457 int minValue = slider.getMinimum(); 458 int maxValue = slider.getMaximum(); 459 int trackTop = trackRect.y + thumbRect.height / 2 + trackBorder; 460 int trackBottom = trackRect.y + trackRect.height 461 - thumbRect.height / 2 - trackBorder; 462 int trackLength = trackBottom - trackTop; 463 464 if (yPos <= trackTop) { 465 value = drawInverted() ? minValue : maxValue; 466 } else if (yPos >= trackBottom) { 467 value = drawInverted() ? maxValue : minValue; 468 } else { 469 int distanceFromTrackTop = yPos - trackTop; 470 double valueRange = (double)maxValue - (double)minValue; 471 double valuePerPixel = valueRange / (double)trackLength; 472 int valueFromTrackTop = 473 (int)Math.round(distanceFromTrackTop * valuePerPixel); 474 value = drawInverted() ? 475 minValue + valueFromTrackTop : maxValue - valueFromTrackTop; 476 } 477 return value; 478 } 479 480 485 public int valueForXPosition(int xPos) { 486 int value; 487 int minValue = slider.getMinimum(); 488 int maxValue = slider.getMaximum(); 489 int trackLeft = trackRect.x + thumbRect.width / 2 + trackBorder; 490 int trackRight = trackRect.x + trackRect.width 491 - thumbRect.width / 2 - trackBorder; 492 int trackLength = trackRight - trackLeft; 493 494 if (xPos <= trackLeft) { 495 value = drawInverted() ? maxValue : minValue; 496 } else if (xPos >= trackRight) { 497 value = drawInverted() ? minValue : maxValue; 498 } else { 499 int distanceFromTrackLeft = xPos - trackLeft; 500 double valueRange = (double)maxValue - (double)minValue; 501 double valuePerPixel = valueRange / (double)trackLength; 502 int valueFromTrackLeft = 503 (int)Math.round(distanceFromTrackLeft * valuePerPixel); 504 value = drawInverted() ? 505 maxValue - valueFromTrackLeft : minValue + valueFromTrackLeft; 506 } 507 return value; 508 } 509 510 protected Dimension getThumbSize() { 511 Dimension size = new Dimension (); 512 513 if (slider.getOrientation() == JSlider.VERTICAL) { 514 size.width = thumbHeight; 515 size.height = thumbWidth; 516 } else { 517 size.width = thumbWidth; 518 size.height = thumbHeight; 519 } 520 return size; 521 } 522 523 protected void recalculateIfInsetsChanged() { 524 SynthContext context = getContext(slider); 525 Insets newInsets = style.getInsets(context, null); 526 if (!newInsets.equals(insetCache)) { 527 insetCache = newInsets; 528 calculateGeometry(); 529 } 530 context.dispose(); 531 } 532 533 public Region getRegion(JComponent c) { 534 return SynthLookAndFeel.getRegion(c); 535 } 536 537 public SynthContext getContext(JComponent c) { 538 return getContext(c, getComponentState(c)); 539 } 540 541 public SynthContext getContext(JComponent c, int state) { 542 return SynthContext.getContext(SynthContext .class, c, 543 SynthLookAndFeel.getRegion(c), style, state); 544 } 545 546 public SynthContext getContext(JComponent c, Region subregion) { 547 return getContext(c, subregion, getComponentState(c, subregion)); 548 } 549 550 private SynthContext getContext(JComponent c, Region subregion, int state) { 551 SynthStyle style = null; 552 Class klass = SynthContext .class; 553 554 if (subregion == Region.SLIDER_TRACK) { 555 style = sliderTrackStyle; 556 } else if (subregion == Region.SLIDER_THUMB) { 557 style = sliderThumbStyle; 558 } 559 return SynthContext.getContext(klass, c, subregion, style, state); 560 } 561 562 public int getComponentState(JComponent c) { 563 return SynthLookAndFeel.getComponentState(c); 564 } 565 566 private int getComponentState(JComponent c, Region region) { 567 if (region == Region.SLIDER_THUMB && thumbActive &&c.isEnabled()) { 568 return MOUSE_OVER; 569 } 570 return SynthLookAndFeel.getComponentState(c); 571 } 572 573 public void update(Graphics g, JComponent c) { 574 SynthContext context = getContext(c); 575 SynthLookAndFeel.update(context, g); 576 context.getPainter().paintSliderBackground(context, 577 g, 0, 0, c.getWidth(), c.getHeight()); 578 paint(context, g); 579 context.dispose(); 580 } 581 582 public void paint(Graphics g, JComponent c) { 583 SynthContext context = getContext(c); 584 paint(context, g); 585 context.dispose(); 586 } 587 588 public void paint(SynthContext context, Graphics g) { 589 recalculateIfInsetsChanged(); 590 recalculateIfOrientationChanged(); 591 Rectangle clip = g.getClipBounds(); 592 593 if (paintValue) { 594 FontMetrics fm = SwingUtilities2.getFontMetrics(slider, g); 595 valueRect.x = (thumbRect.x + (thumbRect.width / 2)) - 596 context.getStyle().getGraphicsUtils(context). 597 computeStringWidth(context, g.getFont(), fm, 598 "" + slider.getValue()) / 2; 599 g.setColor(context.getStyle().getColor( 600 context, ColorType.TEXT_FOREGROUND)); 601 context.getStyle().getGraphicsUtils(context).paintText( 602 context, g, "" + slider.getValue(), valueRect.x, 603 valueRect.y, -1); 604 } 605 606 SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK); 607 paintTrack(subcontext, g, trackRect); 608 subcontext.dispose(); 609 610 subcontext = getContext(slider, Region.SLIDER_THUMB); 611 paintThumb(subcontext, g, thumbRect); 612 subcontext.dispose(); 613 614 if (slider.getPaintTicks() && clip.intersects(tickRect)) { 615 paintTicks(g); 616 } 617 618 if (slider.getPaintLabels() && clip.intersects(labelRect)) { 619 paintLabels(g); 620 } 621 } 622 623 public void paintBorder(SynthContext context, Graphics g, int x, 624 int y, int w, int h) { 625 context.getPainter().paintSliderBorder(context, g, x, y, w, h); 626 } 627 628 public void paintThumb(SynthContext context, Graphics g, 629 Rectangle thumbBounds) { 630 int orientation = slider.getOrientation(); 631 SynthLookAndFeel.updateSubregion(context, g, thumbBounds); 632 context.getPainter().paintSliderThumbBackground(context, g, 633 thumbBounds.x, thumbBounds.y, thumbBounds.width, 634 thumbBounds.height, orientation); 635 context.getPainter().paintSliderThumbBorder(context, g, 636 thumbBounds.x, thumbBounds.y, thumbBounds.width, 637 thumbBounds.height, orientation); 638 } 639 640 public void paintTrack(SynthContext context, Graphics g, 641 Rectangle trackBounds) { 642 SynthLookAndFeel.updateSubregion(context, g, trackBounds); 643 context.getPainter().paintSliderTrackBackground(context, g, 644 trackBounds.x, trackBounds.y, trackBounds.width, 645 trackBounds.height); 646 context.getPainter().paintSliderTrackBorder(context, g, 647 trackBounds.x, trackBounds.y, trackBounds.width, 648 trackBounds.height); 649 } 650 651 public void propertyChange(PropertyChangeEvent e) { 652 if (SynthLookAndFeel.shouldUpdateStyle(e)) { 653 updateStyle((JSlider)e.getSource()); 654 } 655 } 656 657 663 protected class SynthTrackListener extends TrackListener { 664 665 public void mouseExited(MouseEvent e) { 666 setThumbActive(false); 667 } 668 669 public void mouseReleased(MouseEvent e) { 670 super.mouseReleased(e); 671 updateThumbState(e.getX(), e.getY()); 672 } 673 674 public void mouseDragged(MouseEvent e) { 675 SynthScrollBarUI ui; 676 int thumbMiddle = 0; 677 678 if (!slider.isEnabled()) { 679 return; 680 } 681 682 currentMouseX = e.getX(); 683 currentMouseY = e.getY(); 684 685 if (!isDragging()) { 686 return; 687 } 688 689 slider.setValueIsAdjusting(true); 690 691 switch (slider.getOrientation()) { 692 case JSlider.VERTICAL: 693 int halfThumbHeight = thumbRect.height / 2; 694 int thumbTop = e.getY() - offset; 695 int trackTop = trackRect.y; 696 int trackBottom = trackRect.y + trackRect.height 697 - halfThumbHeight - trackBorder; 698 int vMax = yPositionForValue(slider.getMaximum() - 699 slider.getExtent()); 700 701 if (drawInverted()) { 702 trackBottom = vMax; 703 } else { 704 trackTop = vMax; 705 } 706 thumbTop = Math.max(thumbTop, trackTop - halfThumbHeight); 707 thumbTop = Math.min(thumbTop, trackBottom - halfThumbHeight); 708 709 setThumbLocation(thumbRect.x, thumbTop); 710 711 thumbMiddle = thumbTop + halfThumbHeight; 712 slider.setValue(valueForYPosition(thumbMiddle)); 713 break; 714 case JSlider.HORIZONTAL: 715 int halfThumbWidth = thumbRect.width / 2; 716 int thumbLeft = e.getX() - offset; 717 int trackLeft = trackRect.x + halfThumbWidth + trackBorder; 718 int trackRight = trackRect.x + trackRect.width 719 - halfThumbWidth - trackBorder; 720 int hMax = xPositionForValue(slider.getMaximum() - 721 slider.getExtent()); 722 723 if (drawInverted()) { 724 trackLeft = hMax; 725 } else { 726 trackRight = hMax; 727 } 728 thumbLeft = Math.max(thumbLeft, trackLeft - halfThumbWidth); 729 thumbLeft = Math.min(thumbLeft, trackRight - halfThumbWidth); 730 731 setThumbLocation(thumbLeft, thumbRect.y); 732 733 thumbMiddle = thumbLeft + halfThumbWidth; 734 slider.setValue(valueForXPosition(thumbMiddle)); 735 break; 736 default: 737 return; 738 } 739 740 if (slider.getValueIsAdjusting()) { 741 setThumbActive(true); 742 } 743 } 744 745 public void mouseMoved(MouseEvent e) { 746 updateThumbState(e.getX(), e.getY()); 747 } 748 } 749 } 750 | Popular Tags |