package displayShelf; import f3.ui.*; import f3.ui.canvas.*; import java.lang.Math; public class ITunesScrollBar extends CompositeNode { public attribute width: Number; public attribute itemCount: Number; public attribute selection: Number; public attribute viewSize: Number; public attribute viewportWidth: Number; public attribute borderColor: Paint; public attribute highlightColor: Paint; public attribute selectedHighlightColor: Paint; public attribute color: Paint; public attribute runColor: Paint; public attribute pageSize: Integer; } attribute ITunesScrollBar.borderColor = new Color(.7, .7, .7, 1); attribute ITunesScrollBar.highlightColor = new Color(0.15, 0.15, 0.15, 1); attribute ITunesScrollBar.selectedHighlightColor = white; attribute ITunesScrollBar.color = black; attribute ITunesScrollBar.runColor = new Color(.5, .5, .5, .5); attribute ITunesScrollBar.pageSize = 5; function ITunesScrollBar.composeNode() = Group { var strokeWidth = 1.5 var runWidth = bind width - 40 var thumbWidth = bind viewportWidth/viewSize*runWidth var autorepeat = 400 content: [Clip { var: self var pressed = bind false var pressHover = bind pressed and self.hover onMousePressed: operation(e) { pressed = true; } onMouseReleased: operation(e) { pressed = false; } trigger on (newValue = pressHover) { if (newValue) { var n = selection-1; if (n >= 0) { selection = [n..0] dur n*autorepeat linear while pressHover; } } } shape: Subtract { shape1: Rect { height: 16 width: 30 arcHeight: 20 arcWidth: 20 } shape2: Ellipse { cx: 28 cy: 8 radiusX: 8 radiusY: 8 } } content: [Rect { height: 16 width: 30 arcHeight: 20 arcWidth: 20 fill: bind if pressHover then highlightColor else color selectable: true }, Rect { transform: translate(3, 1) height: 5 width: 24 arcHeight: 12 arcWidth: 12 fill: highlightColor }, Polygon { transform: translate(12, 8) valign: CENTER halign: CENTER fill: bind if pressHover then selectedHighlightColor else borderColor points: [8, 0, 8, 8, 0, 4] }] }, Clip { transform: bind translate(width-7, 0) halign: TRAILING var: self var pressed = bind false var pressHover = bind pressed and self.hover onMousePressed: operation(e) { pressed = true; } onMouseReleased: operation(e) { pressed = false; } trigger on (newValue = pressHover) { if (newValue) { var n = selection+1; if (n <= itemCount-1) { var count = itemCount-n-1; selection = [n.. selectionX; pressed = true; } onMouseReleased: operation(e:CanvasMouseEvent) { pressed = false; } trigger on (newValue = pressHover) { if (newValue) { if (up) { var n = selection+pageSize; for (i in [n,n+pageSize..itemCount+pageSize]) (dur autorepeat*(itemCount-n)/pageSize linear while pressHover) { selection = Math.min(itemCount-1, i); } } else { var n = selection-pageSize; for (i in [n,n-pageSize..-pageSize]) (dur autorepeat*n/pageSize linear while pressHover) { selection = Math.max(0, i); } } } } }, Rect { height: 16 width: bind width stroke: borderColor strokeWidth: strokeWidth arcHeight: 20 arcWidth: 20 }, Group { transform: translate(20, 0) content: Group { var w = bind runWidth - thumbWidth var tx = Translate {x: bind selection/(itemCount-1)*w, y: 0} transform: tx var: self var dragX = 0 var startX = 0 onMousePressed: operation(e) { startX = tx.x; dragX = 0; } onMouseDragged: operation(e:CanvasMouseEvent) { dragX += e.localDragTranslation.x; var x = startX + dragX; var p = x/w; if (p < 0) { p = 0; } if (p > 1) { p = 1; } selection = (p*(itemCount-1)).intValue(); } content: [Rect { selectable: true arcHeight: 20 arcWidth: 20 fill: color stroke: borderColor strokeWidth: strokeWidth height: 16 width: bind thumbWidth }, Rect { transform: translate(4, 1.5) height: 5 width: bind thumbWidth-8 arcHeight: 12 arcWidth: 12 fill: highlightColor }] } }] };