UI Buttons

From GiderosMobile
Revision as of 15:07, 13 August 2019 by MoKaLux (talk | contribs) (added toggle button)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


Here you will find various resources to help you create buttons in Gideros Studio.


note:You may have to provide your own assets (fonts, gfx, …).

Simple Button

--[[
A generic button class

This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php
(C) 2010 - 2011 Gideros Mobile 
]]

Button = Core.class(Sprite)

function Button:init(upState, downState) -- upstate and downstate are bitmaps
	self.upState = upState
	self.downState = downState
		
	self.focus = false

	-- set the visual state as "up"
	self:updateVisualState(false)

	-- register to all mouse and touch events
	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

function Button:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
end

function Button:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then	
			self.focus = false
			self:updateVisualState(false)
		end
		event:stopPropagation()
	end
end

function Button:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false)
		self:dispatchEvent(Event.new("click"))	-- button is clicked, dispatch "click" event
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function Button:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if touches are cancelled, reset the state of the button
function Button:onTouchesCancel(event)
	if self.focus then
		self.focus = false;
		self:updateVisualState(false)
		event:stopPropagation()
	end
end

-- if state is true show downState else show upState
function Button:updateVisualState(state)
	if state then
		if self:contains(self.upState) then
			self:removeChild(self.upState)
		end
		
		if not self:contains(self.downState) then
			self:addChild(self.downState)
		end
	else
		if self:contains(self.downState) then
			self:removeChild(self.downState)
		end
		
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
	end
end

---- USAGE
---- clickable button (arrow button)
--local arrow = Texture.new("gfx/arrow_right.png")
--local arrow_pressed = Texture.new("gfx/arrow_right_down.png")
--local button = Button.new(Bitmap.new(arrow), Bitmap.new(arrow_pressed))
--button:addEventListener("click", function()
--	-- your code here
--end)


Button with Text

ButtonText = Core.class(Sprite)

function ButtonText:init(text, tfont, tcolor, tscalex, tscaley, upState, downState)
	if text ~= nil then
		self.text = TextField.new(tfont, text, text) -- string
		self.text:setAnchorPoint(0.5, 0.5)
		self.text:setScale(tscalex or 1, tscaley or 1)
		self.text:setTextColor(tcolor or 0xFFFFFF)
		self.textwidth = self.text:getWidth()
		self.textheight = self.text:getHeight()
		self:addChild(self.text)
		self.hastext = true
	else
		self.hastext = false
	end

	if upState ~= nil then
		self.upState = Bitmap.new(Texture.new(upState))-- png path
		self.downState = Bitmap.new(Texture.new(downState or upState)) -- png path
		self.upState:setAnchorPoint(0.5, 0.5)
		self.downState:setAnchorPoint(0.5, 0.5)
		self.bmpwidth = self.upState:getWidth()
		self.bmpheight = self.upState:getHeight()
		self.hasbmp = true
	else
		self.hasbmp = false
	end

	if not self.hastext and not self.hasbmp then
		print("*** ERROR: BUTTONTEXT NEEDS AT LEAST SOME TEXT OR SOME BITMAP! ***")
	end

	if self.hasbmp then
		self:updateVisualState(false)
	end

	self.focus = false

	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

-- BUTTONTEXT FUNCTIONS
function ButtonText:setTextView(xcolor, xscalex, xscaley)
	self.text:setTextColor(xcolor)
	self.text:setScale(xscalex, xscaley)
end

function ButtonText:setText(xtext, xupper)
	if xupper then
		self.text:setText(string.upper(xtext))
	else
		self.text:setText(xtext)
	end
end

function ButtonText:setTextColor(xcolor)
	self.text:setTextColor(xcolor or 0xff0000)
end

function ButtonText:show()
	self:addChild(self.text)
	if self.downState ~= nil then self:addChild(self.downState) end
	if self.upState ~= nil then self:addChild(self.upState) end
end

function ButtonText:hide()
	self:removeChild(self.text)
	if self.downState ~= nil then self:removeChild(self.downState) end
	if self.upState ~= nil then self:removeChild(self.upState) end
end

function ButtonText:updateVisualState(state)
	if self.hasbmp then
		-- if state is true show downState bitmap else show upState bitmap
		if state then
			if self:contains(self.upState) then
				self:removeChild(self.upState)
			end
			
			if not self:contains(self.downState) then
				self:addChild(self.downState)
			end

			if self:contains(self.text) then
				self:addChild(self.text)
			end
		else
			if self:contains(self.downState) then
				self:removeChild(self.downState)
			end
			
			if not self:contains(self.upState) then
				self:addChild(self.upState)
			end

			if self:contains(self.text) then
				self:addChild(self.text)
			end
		end
	end
end

-- BUTTONTEXT LISTENERS
function ButtonText:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		self:updateVisualState(true)
		event:stopPropagation()
	end
end

function ButtonText:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then
			self.focus = false;
			self:updateVisualState(false)
		end
		event:stopPropagation()
	end
end

function ButtonText:onMouseUp(event)
	if self.focus then
		self.focus = false;
		self:updateVisualState(false)
		self:dispatchEvent(Event.new("click"))
		event:stopPropagation()
	end
end

function ButtonText:onTouchesBegin(event)
	-- if button is on focus, stop propagation of touch events
	if self.focus then
		event:stopPropagation()
	end
end

function ButtonText:onTouchesMove(event)
	-- if button is on focus, stop propagation of touch events
	if self.focus then
		event:stopPropagation()
	end
end

function ButtonText:onTouchesEnd(event)
	-- if button is on focus, stop propagation of touch events
	if self.focus then
		event:stopPropagation()
	end
end

function ButtonText:onTouchesCancel(event)
	-- if touches are cancelled, reset the state of the button
	if self.focus then
		self.focus = false;
		self:updateVisualState(false)
		event:stopPropagation()
	end
end

---- USAGE
--local btntext = ButtonText.new("Level 1", nil, 0xFF0000, 3, 3, "gfx/ui/button.png", nil)
--btntext:setPosition(128, 128)
--stage:addChild(btntext)
--btntext:addEventListener("click", function()
--	-- your code here
--end)


Toggle Button

--[[
ToggleButton v1.0
 
v1.0 - 19.3.2013
Initial release
 
Free to modify and use!
Matjaž Bravc
]]

ToggleButton = Core.class(Sprite)

function ToggleButton:init(upState, downState)
	self.upState = upState
	self.downState = downState

	self.pressed = false
	self.focus = false

	self:updateVisualState(self.pressed)

	self:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
	self:addEventListener(Event.MOUSE_MOVE, self.onMouseMove, self)
	self:addEventListener(Event.MOUSE_UP, self.onMouseUp, self)

	self:addEventListener(Event.TOUCHES_BEGIN, self.onTouchesBegin, self)
	self:addEventListener(Event.TOUCHES_MOVE, self.onTouchesMove, self)
	self:addEventListener(Event.TOUCHES_END, self.onTouchesEnd, self)
	self:addEventListener(Event.TOUCHES_CANCEL, self.onTouchesCancel, self)
end

function ToggleButton:onMouseDown(event)
	if self:hitTestPoint(event.x, event.y) then
		self.focus = true
		event:stopPropagation()
	end
end

function ToggleButton:onMouseMove(event)
	if self.focus then
		if not self:hitTestPoint(event.x, event.y) then
			self.focus = false
		end
		event:stopPropagation()
	end
end

function ToggleButton:onMouseUp(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(not self.pressed)
		self:dispatchEvent(Event.new("click"))
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesBegin(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesMove(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if button is on focus, stop propagation of touch events
function ToggleButton:onTouchesEnd(event)
	if self.focus then
		event:stopPropagation()
	end
end

-- if touches are cancelled, reset the state of the button
function ToggleButton:onTouchesCancel(event)
	if self.focus then
		self.focus = false
		self:updateVisualState(false) -- XXX
		event:stopPropagation()
	end
end

-- if state is true show downState else show upState
function ToggleButton:updateVisualState(state)
	self.pressed = state

	-- Modification to allow single state buttons (checkboxes etc)
	if not self.downState then
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
		return
	end

	if self.pressed then
		if self:contains(self.upState) then
			self:removeChild(self.upState)
		end
		if not self:contains(self.downState) then
			self:addChild(self.downState)
		end
	else
		if self:contains(self.downState) then
			self:removeChild(self.downState)
		end
		if not self:contains(self.upState) then
			self:addChild(self.upState)
		end
	end
end

function ToggleButton:isPressed()
	return self.pressed
end

---- USAGE
--local btntoggle = ToggleButton.new(Bitmap.new(Texture.new("gfx/off.png", true)), Bitmap.new(Texture.new("gfx/on.png", true)))
--stage:addChild(btntoggle)
--btntoggle:addEventListener("click", function()
--	print(btntoggle:isPressed())
--end)