// Using Proto and chucklib storage for GUIs // Transport controls // James Harkins ( // definitions... kind of wordy but you know how it goes Proto({ ~triangle = { |rect, color, pointsLeft = false| var top = rect.top, bottom = rect.bottom, left, right, halfy = (top + bottom) / 2; if(pointsLeft) { left = rect.right; right = rect.left; } { left = rect.left; right = rect.right; }; GUI.pen.color_(color) .moveTo(left@top) .lineTo(right@halfy) .lineTo(left@bottom) .lineTo(left@top) .fill; }; ~rightTri = { |rect, color, orientation = \bottomLeft| var pt1, pt2, pt3; switch(orientation) { \bottomLeft } { pt1 = rect.leftBottom; pt2 = rect.leftTop; pt3 = rect.rightBottom; } { \topLeft } { pt1 = rect.leftBottom; pt2 = rect.leftTop; pt3 = rect.rightTop; } { \topRight } { pt1 = rect.leftTop; pt2 = rect.rightBottom; pt3 = rect.rightTop; } { \bottomRight } { pt1 = rect.leftBottom; pt2 = rect.rightBottom; pt3 = rect.rightTop; }; GUI.pen.color_(color) .moveTo(pt1) .lineTo(pt2) .lineTo(pt3) .lineTo(pt1) .fill; }; ~border = { |rect, thickness, outerColor| GUI.pen.color_(outerColor) .fillRect(Rect(rect.left, rect.top, rect.width, thickness)) .fillRect(Rect(rect.left, rect.bottom - thickness, rect.width, thickness)) .fillRect(Rect(rect.left, rect.top, thickness, rect.height)) .fillRect(Rect(rect.right - thickness, rect.top, thickness, rect.height)) }; ~border3d = { |rect, thickness, innerColor, leftTopBlend (Color.white), rightBottomBlend (Color.black)| var shaded = innerColor.blend(rightBottomBlend, 0.5); GUI.pen.color_(innerColor.blend(leftTopBlend, 0.5)) .fillRect(Rect(rect.left, rect.top, rect.width, thickness)) .fillRect(Rect(rect.left, rect.top, thickness, rect.height)) .color_(shaded) .fillRect(Rect(rect.left + thickness, rect.bottom - thickness, rect.width - thickness, thickness)) .fillRect(Rect(rect.right - thickness, rect.top + thickness, thickness, rect.height - thickness)); ~rightTri.(Rect(rect.left, rect.bottom - thickness, thickness, thickness), shaded, \bottomRight); ~rightTri.(Rect(rect.right - thickness, rect.top, thickness, thickness), shaded, \bottomRight); }; }) => PR(\penUtils); PR(\penUtils).clone({ ~prep = { |window, bounds, color| ~bounds = bounds; ~view = GUI.userView.new(window, bounds); ~drawFunc = e(~drawFunc); ~drawPressedFunc = e(~drawPressedFunc); ~view .drawFunc_(~drawFunc) .canFocus_(false) .mouseDownAction_(e { |view| view.drawFunc_(~drawPressedFunc) .refresh; }) .mouseUpAction_(e { |view, x, y, modifiers| view.drawFunc_(~drawFunc) .refresh; if(view.bounds.containsPoint(x@y)) { ~action.(view, x, y, modifiers); }; }) .refresh; // other init? currentEnvironment }; ~background = Color.gray(0.7); ~thickness = 2; ~offset = 2; ~draw = { |bounds, pressed = false| var leftTopColor, rightBottomColor; if(pressed) { leftTopColor = Color.black; rightBottomColor = Color.white; } { leftTopColor = Color.white; rightBottomColor = Color.black; }; GUI.pen.color_(~background) .fillRect(~view.bounds); ~border3d.(~view.bounds, ~thickness, ~background, leftTopColor, rightBottomColor); ~drawContents.(bounds, pressed); }; ~drawContents = { |bounds, pressed| var str = ~string ? "test"; GUI.pen.color_(Color.black); GUI.pen.stringCenteredIn(str, bounds); }; ~drawFunc = { |view| ~draw.(view.bounds) }; // +1, -1? Jury's out ~drawPressedFunc = { |view| ~draw.(view.bounds.moveBy(~offset ? 1, ~offset ? 1), true) }; }) => PR(\userButton); PR(\userButton).clone({ ~state = 0; ~playArrowColor = Color.green(0.5); ~pauseBarColor = Color.gray(0.3); ~drawContents = { |bounds, pressed| bounds = bounds.insetBy(bounds.width * 0.2, bounds.height * 0.2); if(~state == 0) { ~triangle.(bounds, ~playArrowColor); } { bounds.width = ~view.bounds.width * 0.2; GUI.pen.color_(~pauseBarColor) .fillRect(bounds) .fillRect(bounds.moveBy(bounds.width * 2, 0)) }; }; ~action = { ~state = 1 - ~state; ~view.refresh; ~userAction.(); }; }) => PR(\playPauseButton); PR(\userButton).clone({ ~arrowColor = Color.gray(0.3); ~drawContents = { |bounds, pressed| var halfwidth, midx; bounds = bounds.insetBy(bounds.width * 0.2, bounds.height * 0.2); halfwidth = bounds.width * 0.5; midx = bounds.left + halfwidth; ~triangle.(bounds.copy.left_(midx).width_(halfwidth), ~arrowColor, true); ~triangle.(bounds.copy.width_(halfwidth), ~arrowColor, true); GUI.pen.fillRect(Rect(bounds.left - (halfwidth*0.2), bounds.top, halfwidth*0.2, bounds.height)); }; }) => PR(\gotoBeginningButton); PR(\userButton).clone({ ~arrowColor = Color.gray(0.3); ~drawContents = { |bounds, pressed| bounds = bounds.insetBy(bounds.width * 0.2, bounds.height * 0.2); ~triangle.(bounds, ~arrowColor, true); GUI.pen.fillRect(Rect(bounds.left - (bounds.width*0.1), bounds.top, bounds.width*0.1, bounds.height)); }; }) => PR(\backOneSectionButton); PR(\userButton).clone({ ~arrowColor = Color.gray(0.3); ~drawContents = { |bounds, pressed| bounds = bounds.insetBy(bounds.width * 0.2, bounds.height * 0.2); ~triangle.(bounds, ~arrowColor); GUI.pen.fillRect(Rect(bounds.right, bounds.top, bounds.width*0.1, bounds.height)); }; }) => PR(\fwdOneSectionButton); ) ( // make a simple window with transport controls -- doesn't do anything until you hook up actions f = FlowView.new; PR(\gotoBeginningButton).copy.prep(f, 80@80); PR(\backOneSectionButton).copy.prep(f, 80@80); PR(\playPauseButton).copy.prep(f, 80@80); PR(\fwdOneSectionButton).copy.prep(f, 80@80); )