001package polaris.sdk.ui.controls;
002import polaris.sdk.ui.*;
003
004/** Identical absolute drag mapping for horizontal and vertical scrollbars, without a grab jump. */
005public class ScrollBar extends Slider {
006 private boolean vertical=true;private float page=.25f,grab,shown;private boolean painted;
007 public ScrollBar(){w=14;h=130;value=0;}
008 public ScrollBar vertical(boolean v){vertical=v;return this;}
009 public ScrollBar page(float ratio){if(!Float.isFinite(ratio))throw new IllegalArgumentException("page");page=Math.max(.04f,Math.min(1,ratio));return this;}
010 private float length(){return vertical?h:w;}
011 private float thumbLength(){return Math.min(length(),Math.max(18,length()*page));}
012 private float origin(){return vertical?ay:ax;}
013 private void drag(float pointer){float travel=length()-thumbLength();double old=value;value(travel<=0?min:min+Math.max(0,Math.min(1,(pointer-origin()-grab)/travel))*(max-min));if(value!=old)changed();}
014 @Override public void event(UiEvent e){
015  float pointer=vertical?e.y:e.x;
016  if(e.type==UiEvent.Type.DOWN&&e.button==1){downX=pointer;pointerMoved=false;float start=origin()+(length()-thumbLength())*(painted?shown:fraction());boolean onThumb=pointer>=start&&pointer<=start+thumbLength();grab=onThumb?pointer-start:thumbLength()/2;pressed=true;if(!onThumb)drag(pointer);e.handled=true;return;}
017  if(e.type==UiEvent.Type.MOVE&&pressed){pointerMoved|=Math.abs(pointer-downX)>.0001f;if(pointerMoved)drag(pointer);e.handled=true;return;}
018  if(e.type==UiEvent.Type.UP&&e.button==1&&pressed){if(pointerMoved||Math.abs(pointer-downX)>.0001f)drag(pointer);pressed=false;e.handled=true;return;}
019  if(e.type==UiEvent.Type.KEY&&vertical&&(e.key==38||e.key==40)){double old=value;value(value+(e.key==40?step:-step));if(old!=value)changed();e.handled=true;return;}
020  super.event(e);
021 }
022 @Override protected void paint(Painter p){
023  shown=MotionValue.clamp(follow("scrollThumb",fraction(),72));painted=true;
024  p.fill(ax,ay,w,h,Math.min(6,Math.min(w,h)/2),Theme.alpha(theme().field,.65f));
025  float travel=length()-thumbLength(),radius=Math.min(5,Math.min(w,h)/2);
026  if(vertical)glassPart(p,ax+1,ay+travel*shown,Math.max(0,w-2),thumbLength(),radius,.42f+pressAmount()*.03f,theme().accent,1,theme().blur);
027  else glassPart(p,ax+travel*shown,ay+1,thumbLength(),Math.max(0,h-2),radius,.42f+pressAmount()*.03f,theme().accent,1,theme().blur);
028 }
029}