View Javadoc
1   package com.bric.multislider;
2   
3   import java.awt.BasicStroke;
4   import java.awt.Color;
5   import java.awt.Dimension;
6   import java.awt.Graphics2D;
7   import java.awt.Rectangle;
8   import java.awt.RenderingHints;
9   import java.awt.Shape;
10  import java.awt.geom.Point2D;
11  import java.awt.geom.Rectangle2D;
12  import java.awt.geom.RoundRectangle2D;
13  
14  public class DefaultMultiThumbSliderUi<T> extends MultiThumbSliderUi<T>
15  {
16  
17      protected int FOCUS_PADDING = 3;
18  
19      protected Color trackHighlightColor = new Color(0, 0, 0, 140);
20  
21      public DefaultMultiThumbSliderUi(MultiThumbSlider<T> slider)
22      {
23          super(slider);
24          this.DEPTH = 10;
25      }
26  
27      protected boolean isTrackHighlightActive()
28      {
29          return this.slider.getThumbCount() == 2;
30      }
31  
32      @Override
33      protected int getPreferredComponentDepth()
34      {
35          return 20;
36      }
37  
38      @Override
39      protected Dimension getThumbSize(int thumbIndex)
40      {
41          Thumb thumb = getThumb(thumbIndex);
42          if (Thumb.Hourglass.equals(thumb))
43          {
44              return new Dimension(8, 16);
45          }
46          else if (Thumb.Triangle.equals(thumb))
47          {
48              return new Dimension(10, 18);
49          }
50          else if (Thumb.Rectangle.equals(thumb))
51          {
52              return new Dimension(10, 20);
53          }
54          else
55          {
56              return new Dimension(16, 16);
57          }
58      }
59  
60      @Override
61      protected void paintTrack(Graphics2D g)
62      {
63          Shape trackOutline = getTrackOutline();
64          g = (Graphics2D) g.create();
65          g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
66          g.setColor(new Color(0xBBBBBB));
67          g.fill(trackOutline);
68          Graphics2D g2 = (Graphics2D) g.create();
69          g2.clip(trackOutline);
70          g2.setColor(new Color(0xAAAAAA));
71          g2.setStroke(new BasicStroke(2));
72          for (float y = 0; y < .5f; y += .1f)
73          {
74              g2.draw(trackOutline);
75              g2.translate(0, .1f);
76          }
77          g2.dispose();
78  
79          paintTrackHighlight(g);
80  
81          g.setColor(new Color(0x888888));
82          g.setStroke(new BasicStroke(1));
83          g.draw(trackOutline);
84  
85          if (this.slider.isPaintTicks())
86          {
87              g.setColor(new Color(0x777777));
88              g.setStroke(new BasicStroke(1));
89              paintTick(g, .25f, 0, 4, true);
90              paintTick(g, .5f, 0, 4, true);
91              paintTick(g, .75f, 0, 4, true);
92              paintTick(g, 0f, 0, 4, true);
93              ;
94              paintTick(g, 1f, 0, 4, true);
95          }
96          g.dispose();
97      }
98  
99      /**
100      * This optional method highlights the space on the track (by simply adding a shadow) between two thumbs.
101      * @param g graphics
102      */
103     protected void paintTrackHighlight(Graphics2D g)
104     {
105         if (!isTrackHighlightActive())
106             return;
107         g = (Graphics2D) g.create();
108         Point2D p1 = getThumbCenter(0);
109         Point2D p2 = getThumbCenter(1);
110         Shape outline;
111         if (this.slider.getOrientation() == MultiThumbSlider.HORIZONTAL)
112         {
113             float minX = (float) Math.min(p1.getX(), p2.getX());
114             float maxX = (float) Math.max(p1.getX(), p2.getX());
115             outline = new Rectangle2D.Float(minX, this.trackRect.y, maxX - minX, this.trackRect.height);
116         }
117         else
118         {
119             float minY = (float) Math.min(p1.getY(), p2.getY());
120             float maxY = (float) Math.max(p1.getY(), p2.getY());
121             outline = new Rectangle2D.Float(this.trackRect.x, minY, this.trackRect.width, maxY - minY);
122         }
123         g.setColor(this.trackHighlightColor);
124         g.fill(outline);
125         g.dispose();
126     }
127 
128     protected void paintTick(Graphics2D g, float f, int d1, int d2, boolean mirror)
129     {
130         if (this.slider.getOrientation() == MultiThumbSlider.HORIZONTAL)
131         {
132             int x = (int) (this.trackRect.x + this.trackRect.width * f + .5f);
133             int y = this.trackRect.y + this.trackRect.height;
134             g.drawLine(x, y + d1, x, y + d2);
135             if (mirror)
136             {
137                 y = this.trackRect.y;
138                 g.drawLine(x, y - d1, x, y - d2);
139             }
140         }
141         else
142         {
143             int y = (int) (this.trackRect.y + this.trackRect.height * f + .5f);
144             int x = this.trackRect.x + this.trackRect.width;
145             g.drawLine(x + d1, y, x + d2, y);
146             if (mirror)
147             {
148                 x = this.trackRect.x;
149                 g.drawLine(x - d1, y, x - d2, y);
150             }
151         }
152     }
153 
154     @Override
155     protected void paintFocus(Graphics2D g)
156     {
157         Shape trackOutline = getTrackOutline();
158         g = (Graphics2D) g.create();
159         PlafPaintUtils.paintFocus(g, trackOutline, this.FOCUS_PADDING);
160         g.dispose();
161     }
162 
163     @Override
164     protected Rectangle calculateTrackRect()
165     {
166         int k = (int) (10 + this.FOCUS_PADDING + .5);
167         if (this.slider.getOrientation() == MultiThumbSlider.HORIZONTAL)
168         {
169             return new Rectangle(k, this.slider.getHeight() / 2 - this.DEPTH / 2, this.slider.getWidth() - 2 * k - 1,
170                     this.DEPTH);
171         }
172         else
173         {
174             return new Rectangle(this.slider.getWidth() / 2 - this.DEPTH / 2, k, this.DEPTH,
175                     this.slider.getHeight() - 2 * k - 1);
176         }
177     }
178 
179     protected Shape getTrackOutline()
180     {
181         this.trackRect = calculateTrackRect();
182         float k = Math.max(10, this.FOCUS_PADDING) + 1;
183         int z = 3;
184         if (this.slider.getOrientation() == MultiThumbSlider.VERTICAL)
185         {
186             return new RoundRectangle2D.Float(this.trackRect.x, this.trackRect.y - z, this.trackRect.width,
187                     this.trackRect.height + 2 * z, k, k);
188         }
189         return new RoundRectangle2D.Float(this.trackRect.x - z, this.trackRect.y, this.trackRect.width + 2 * z,
190                 this.trackRect.height, k, k);
191     }
192 
193     @Override
194     protected void paintThumbs(Graphics2D g)
195     {
196         float[] values = this.slider.getThumbPositions();
197         for (int a = 0; a < values.length; a++)
198         {
199             float darkness = a == this.slider.getSelectedThumb() ? 1 : this.thumbIndications[a] * .5f;
200             paintThumb(g, a, darkness);
201         }
202     }
203 
204     protected void paintThumb(Graphics2D g, int thumbIndex, float selected)
205     {
206         g = (Graphics2D) g.create();
207         g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
208         Shape outline = getThumbShape(thumbIndex);
209         int gray = (int) ((1 - selected) * 100 + 30);
210         g.setColor(new Color(gray, gray, gray));
211         g.fill(outline);
212         gray = (int) ((1 - selected) * 100);
213         g.setColor(new Color(gray, gray, gray));
214         g.draw(outline);
215         g.dispose();
216     }
217 }