Is it possible to make a round Button?

I know this does not seem possible, out-of-the-box - but I also know that SC users are a very creative bunch. Has anyone discovered a way of getting rounded GUI elements?

You can use the Pen class to create abitrary GUI elements, take a look at e.g. Pen.arcTo

Hope it helps you a bit :slight_smile:

1 Like

If you want to save yourself the work of reproducing ALL of the minute behaviors of a button, you can also just use a UserView to draw over the top of an invisible button, but keep the buttons behavior.

(
~button = Button();
~button.alpha = 0;
~button.states = [["", Color.clear, Color.clear], ["", Color.clear, Color.clear]];
~button.fixedHeight = 100;
~button.canFocus = false;
~button.action = {
	"pressed".postln;
};

~button.layout_(VLayout(
	~roundButton = UserView().drawFunc_({
		|v|
		Pen.fillColor = Color.red;
		Pen.addRoundedRect(v.bounds.moveTo(0, 0), 18, 18);
		Pen.fill();
	})
).margins_(0).spacing_(0));

~roundButton.canFocus = true;
~roundButton.acceptsMouse = false;

View().layout_(VLayout(
	~button
)).front;
)

The only thing remaining here is, you’d probably need to add some mouse and focus actions to the Button to change what you’re drawing in the UserView for e.g. mouse up and down, focused / unfocused states.

3 Likes

Here’s a cheesy attempt at moving the button “up” and “down.” Needs improvement but it’s a start.

Hm… actually, it should be rewritten to avoid the use of rotate because this version does not handle rectangular bounds well. Not bad for square bounds, but it doesn’t handle the general case. But I’m out of time for this morning, so I’ll have to leave it as “an exercise for the reader.”

u = UserView(nil, Rect(800, 200, 100, 100)).front;

(
var mouseState = 0;
var background = Color.gray(0.3);
var foreground = Color.white;
var shadow = Color.gray(0.12);
var highlight = Color.gray(0.75);
var font = Font.default.size_(24);

u.background = Color.white;

u.drawFunc = { |view|
	var b = view.bounds.moveTo(0, 0);
	var c = b.center;
	var b2 = b.moveTo(c.x.neg, c.y.neg).insetBy(5, 5);
	var offset = mouseState * 4 - 2;
	var textBounds = "OK".bounds(font);
	
	Pen.translate(c.x, c.y)
	// rotates clockwise
	// unlike... you know... e ^ (i * theta), grr...
	.rotate(-0.8)
	
	.color_(shadow)
	.fillOval(b2.moveBy(0, offset))
	
	.color_(highlight)
	.fillOval(b2.moveBy(0, offset.neg))
	
	.color_(background)
	.fillOval(Rect(b2.left - 1, b2.top + (offset.abs * 0.5), b2.width + 2, b2.height - offset.abs))
	
	.rotate(0.8)
	.stringAtPoint("OK", Point(mouseState, mouseState) * 2 - textBounds.center, font, foreground)
};

u.mouseDownAction = {
	mouseState = 1;
	u.refresh;
};

u.mouseUpAction = {
	mouseState = 0;
	u.refresh;
};

u.refresh;
)

hjh

There’s also RoundButton in the wslib Quark