001package jmri.jmrit.throttle; 002 003import java.awt.*; 004import java.awt.geom.GeneralPath; 005 006import javax.swing.*; 007import javax.swing.plaf.basic.BasicSliderUI; 008 009/** 010 * A custom slider UI to be used for throttle control panel speed slider 011 * Very graphical display to be used on a large screen 012 * 013 * @author Lionel Jeanson - 2018 014 * 015 */ 016 017public class ControlPanelCustomSliderUI extends BasicSliderUI { 018 019 // Color are coming from the Tango themes color palette (as well as icons on the Throttle window, for look consistency) 020 private final static Color TRACK_COLOR_BACK = new Color(0x88, 0x8a, 0x85, 0x88); 021 private final static Color TRACK_COLOR_FRONT = new Color(0xf5, 0x79, 0x00, 0xCC); 022 private final static Color TRACK_COLOR_FRONT_DISABLED = new Color(0xf5, 0xf5, 0xf5, 0xCC); 023 private final static Color TRACK_COLOR_TICKS = new Color(0x888a85); 024 private final static Color THUMB_INNER_COLOR_STOP = new Color(0xcc0000); 025 private final static Color THUMB_INNER_COLOR_RUN = new Color(0xd7d27A); 026 private final static Color THUMB_INNER_COLOR_DISABLED = new Color(0x101010); 027 private final static Color THUMB_CONTOUR_COLOR = new Color(0x555753); 028 029 public ControlPanelCustomSliderUI(JSlider b) { 030 super(b); 031 } 032 033 @Override 034 public void paint(Graphics g, JComponent c) { 035 if (g instanceof Graphics2D) { 036 Graphics2D g2d = (Graphics2D) g; 037 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 038 } 039 super.paint(g,c); 040 } 041 042 @Override 043 protected Dimension getThumbSize() { 044 if (slider.getOrientation() == SwingConstants.HORIZONTAL) { 045 return new Dimension(16, contentRect.height - tickRect.height - labelRect.height -trackBuffer*2); 046 } else { 047 return new Dimension(contentRect.width - tickRect.width - labelRect.width - trackBuffer*2, 16); 048 } 049 } 050 051 @Override 052 public void paintTrack(Graphics g) { 053 if (!(g instanceof Graphics2D)) { 054 return; 055 } 056 Graphics2D g2d = (Graphics2D) g; 057 Paint oldPaint = g2d.getPaint(); 058 // Track back rectangle 059 g2d.setPaint(TRACK_COLOR_BACK); 060 g2d.fillRect(trackRect.x, trackRect.y, trackRect.width, trackRect.height); 061 // Track ticks 062 int[] ticksAt = { 3*slider.getMinimum()/4, slider.getMinimum()/2 , slider.getMinimum()/4, 0, slider.getMaximum()/4, slider.getMaximum()/2, 3*slider.getMaximum()/4 }; 063 // only if it fits 064 g2d.setPaint(TRACK_COLOR_TICKS); 065 if (slider.getOrientation() == SwingConstants.VERTICAL && trackRect.height > ticksAt.length*8) { 066 for (int n : ticksAt ) { 067 g2d.drawLine( trackRect.x , 068 trackRect.y + trackRect.height / ((slider.getMaximum()-slider.getMinimum())/(slider.getMaximum())) - n*trackRect.height / (slider.getMaximum()-slider.getMinimum()) , 069 trackRect.x + trackRect.width-1, 070 trackRect.y + trackRect.height / ((slider.getMaximum()-slider.getMinimum())/(slider.getMaximum())) - n*trackRect.height / (slider.getMaximum()-slider.getMinimum()) ); 071 } 072 } else if (slider.getOrientation() == SwingConstants.HORIZONTAL && trackRect.width > ticksAt.length*8) { 073 for (int n : ticksAt ) { 074 g2d.drawLine( trackRect.x + trackRect.width - trackRect.width / ((slider.getMaximum()-slider.getMinimum())/(slider.getMaximum())) + n*trackRect.width / (slider.getMaximum()-slider.getMinimum()) , 075 trackRect.y, 076 trackRect.x + trackRect.width - trackRect.width / ((slider.getMaximum()-slider.getMinimum())/(slider.getMaximum())) + n*trackRect.width / (slider.getMaximum()-slider.getMinimum()), 077 trackRect.y + trackRect.height ); 078 } 079 } 080 // Track front 081 if (slider.isEnabled()) { 082 g2d.setPaint(TRACK_COLOR_FRONT); 083 } else { 084 g2d.setPaint(TRACK_COLOR_FRONT_DISABLED); 085 } 086 if (slider.getOrientation() == SwingConstants.HORIZONTAL) { 087 if (slider.getMinimum()<0 && slider.getMaximum()>0) { 088 double doublerel0Pos = Math.abs((double)slider.getMinimum()) / ((double)slider.getMaximum() - (double)slider.getMinimum()); 089 double x0 = trackRect.x + trackRect.width * doublerel0Pos; 090 double widthRect = thumbRect.x + (double)thumbRect.width/2 - x0; 091 if (widthRect>0) { 092 g2d.fillRect( (int)Math.round(x0), trackRect.y, (int)Math.round(widthRect), trackRect.height ); 093 } else { 094 g2d.fillRect( (int)Math.round(x0+widthRect), trackRect.y, (int)Math.round(-widthRect), trackRect.height ); 095 } 096 } else { 097 g2d.fillRect(trackRect.x, trackRect.y, thumbRect.x-thumbRect.width/2, trackRect.height ); 098 } 099 } else { 100 if (slider.getMinimum()<0 && slider.getMaximum()>0) { 101 double doublerel0Pos = Math.abs((double)slider.getMaximum()) / ((double)slider.getMaximum() - (double)slider.getMinimum()); 102 double y0 = trackRect.y + trackRect.height * doublerel0Pos ; 103 double heightRect = thumbRect.y + (double)thumbRect.height/2 - y0; 104 if (heightRect>0) { 105 g2d.fillRect( trackRect.x, (int)Math.round(y0), trackRect.width, (int)Math.round(heightRect)); 106 } else { 107 g2d.fillRect( trackRect.x, (int)Math.round(y0+heightRect), trackRect.width, (int)Math.round(-heightRect)); 108 } 109 } else { 110 g2d.fillRect(trackRect.x, thumbRect.y +thumbRect.height/2, trackRect.width, trackRect.height - ( thumbRect.y-trackRect.y +thumbRect.height/2) ); 111 } 112 } 113 g2d.setPaint(oldPaint); 114 } 115 116 @Override 117 public void paintThumb(Graphics g) { 118 if (!(g instanceof Graphics2D)) { 119 return; 120 } 121 Graphics2D g2d = (Graphics2D) g; 122 Paint oldPaint = g2d.getPaint(); 123 int x1 = thumbRect.x + 3; 124 int x2 = thumbRect.x + thumbRect.width - 5; 125 int y1 = thumbRect.y+1; 126 int y2 = thumbRect.y+thumbRect.height-2; 127 if (slider.getOrientation() == SwingConstants.HORIZONTAL) { 128 x1 = thumbRect.x + 1; 129 x2 = thumbRect.x + thumbRect.width - 2; 130 y1 = thumbRect.y+3; 131 y2 = thumbRect.y+thumbRect.height-5; 132 } 133 GeneralPath shape = new GeneralPath(GeneralPath.WIND_EVEN_ODD); 134 shape.moveTo(x1, y1); 135 shape.lineTo(x2, y1); 136 shape.lineTo(x2, y2); 137 shape.lineTo(x1, y2); 138 shape.closePath(); 139 if (slider.isEnabled()) { 140 if (slider.getValue()==0) { 141 g2d.setPaint(THUMB_INNER_COLOR_STOP); 142 } else { 143 g2d.setPaint( new Color(THUMB_INNER_COLOR_RUN.getRed() - Math.abs(slider.getValue())*100/slider.getMaximum(),THUMB_INNER_COLOR_RUN.getGreen(), THUMB_INNER_COLOR_RUN.getBlue() - Math.abs(slider.getValue()*100/slider.getMaximum()) )); 144 } 145 } else { 146 g2d.setPaint(THUMB_INNER_COLOR_DISABLED); 147 } 148 g2d.fill(shape); 149 Stroke old = g2d.getStroke(); 150 g2d.setStroke(new BasicStroke(2f)); 151 g2d.setPaint(THUMB_CONTOUR_COLOR); 152 g2d.draw(shape); 153 g2d.setStroke(old); 154 g2d.setPaint(oldPaint); 155 } 156}