How to make a button

From MiniScript Wiki
Revision as of 14:43, 30 August 2024 by JoeStrout (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

There are several ways to make a clickable button in Mini Micro. All methods involve drawing some clickable area on the screen, detecting when that area has been clicked, and then tracking the mouse while the button remains down.

For proper button behavior, the button should change in some way (appear darker or shift/scale) to indicate it is pressed, as long as the button is held down but only while the mouse is within the button bounds. If the mouse is dragged outside the bounds, the button should pop back up, and if released in this state it should not count as a click (this is how a user can "cancel" a button click if they realize they made a mistake before releasing the mouse button).

Using a Sprite and No Import Modules

The core of this technique is described in How to detect a click on a sprite. But in the example code below, we make it a bit more general, adding an isClicked method to the Sprite class that can perform button behavior for any sprite. Then the main program needs only call isClicked on each button sprite whenever the mouse button goes down, and handle the button click if this method returns true.

clear

// Prepare the sprite we want to use as a button.
button = new Sprite
button.image = file.loadImage("/sys/pics/Block3.png")
button.x = 350; button.y = 550
display(4).sprites.push button

// Function to check for clicks, with button behavior.
// (Call this when the mouse button is pressed.)
Sprite.isClicked = function
	// Ensure the self has a bounds.
	if not self.localBounds then
		self.localBounds = new Bounds
		self.localBounds.width = self.image.width
		self.localBounds.height = self.image.height
	end if
	// Track the mouse until the button is released,
	// showing the button as "pressed" whenever the
	// mouse is within the self bounds.
	while mouse.button
		if self.contains(mouse) then
			self.tint = color.silver
		else
			self.tint = color.white
		end if
		yield
	end while
	self.tint = color.white
	// Return whether the mouse was released within bounds.
	return self.contains(mouse)
end function

// Main loop.
while true  // (press Control-C to exit)
	yield
	if mouse.button then
		// The mouse button is down.  Check each of our buttons, 
		// and do whatever they should do if clicked.
		if button.isClicked then
			print "Button clicked!"
		end if
	end if
end while

ButtonClick.gif

Using a Sprite and the events module

The events module in /sys/lib/events provides a framework for event-driven programming. With this approach, you use a subclass of Sprite (called EventSprite) which has methods like onMouseOver, onMouseExit, onDrag, and onDragEnd. By implementing the drag events, we can get proper button behavior. The effect looks just like the example above, but requires less code and is a little neater. It also integrates better with any other event-based code that may be running at the same time.

import "events"
clear

button = new events.EventSprite
button.image = file.loadImage("/sys/pics/Block3.png")
button.x = 350; button.y = 550
button.onDrag = function
	if self.contains(mouse) then
		self.tint = color.silver
	else
		self.tint = color.white
	end if
end function
button.onDragEnd = function
	if self.tint == color.silver then
		self.action
		self.tint = color.white
	end if	
end function
button.action = function
	print "Button clicked!"
end function
button.start

events.eventLoop.run

Using a DialogButton on the text display

You can also make a button on the text display, using special characters (char(57856) and char(57857)) to draw the button endcaps. The textUtil module in /sys/lib/textUtil provides a DialogButton class that provides drawing, hit detection, and mouse-tracking in a convenient way. This is often used along with the Dialog class, but it doesn't have to be; DialogButton can be used on its own, as shown here.

import "textUtil"
clear

button = new textUtil.DialogButton
button.caption = "Click Me"
button.x = 15; button.y = 22
button.draw

row = 25
while true  // (press Control-C to exit)
	yield
	if button.contains(mouse) and button.trackHit then
		text.row = row; print "Clicked!"
		row -= 1
	end if
end while

TextButtonClick.gif