Creating my custom widget-like group

Hi,
I am considering to create a reusable custom widget for display of a value next to a symbol.
Something that can be used for scores, counts of diamonds/stars/… , a time counter.
Representing what this looks like in ASCII art:
(S) 12345 or (S 13456) = (S) is the symbol, (—) maybe a bounding box

Questions:

  1. Is there something that already exists (with 1 creation function) that I should use?
  2. Solar2D Group objects don’t have a width/height by default, but widget.Button does.
    Can simply set/maintain a width/height property manually for my group, or is something more sophisticated needed?

I appreciate your help for getting me on the right path (I’m new to Solar2D).
Thanks! -ivec

I’m not aware of something that already does this, but it should be pretty simple. If I understand you right, you want something that can work like this:

local scoreWidgetMaker = require "scoreWidgetMaker"
local scoreWidget = scoreWidgetMaker.new({image = "symbol.png", defaultScore = 0})
scoreWidget.setScore(10)

If so, then make a file called scoreWidgetMaker.lua (or whatever you want to call it), and put this in it:

local scoreWidgetMaker = {}


function scoreWidgetMaker.new(params)
	local group = display.newGroup()
	local symbol = display.newImage(params.image)
	local text = display.newText({text = params.defaultScore})
	group:insert(symbol)
	group:insert(text)
	-- set sizes and positions of symbol and text, etc
	
	function group.getScore()
		return text.text
	end
	
	function group.setScore(newScore)
		text.text = newScore
		-- since score can be string of varyiable length, you'll need to reposition things here.
	end
	
	return group
end


return scoreWidgetMaker

I haven’t tested but it looks ok. Obviously, it’s not finished, you’ll have to put in the details yourself to get it to work the way you want.

Thank you Hasty for your responsiveness.

A key question I had is: how can I manage (make available) a width and height for my group-based widget? To support screen rotation/orientation, I have a layout function that positions a collection of widgets (e.g. even spacing …). It works smoothly with the provided widget.button, button.width and button.height return expected values. But a Group does not have a width or height.

When I set-up the elements of my widget-group, can I just manually set values group.width and group.height to make these attributes available to users of my widget? Or is something more complex needed?

Display Groups do have width and height, but they are basically reflecting what’s inside the group. If you have a single rectangle of 50 for its width and height, then that’ll be the same values when you access these properties for the group. You can change these properties of the group but it will change the way the objects look.

A good usage for groups is to have all its children sit at 0,0 or an offset of these, and then position/rotate the group as needed.

--[[
display.newImageText({
				img="",
				imgDir="",
				text="",
				textFont="",
				textSize=
			}, x, y, w, h)
]]--
display.newImageText = function(ImageTextOptions, x, y, w, h) 
	local Options = ImageTextOptions or {}
	local Image = Options.img or "Icon.png"
	local ImageDir = Options.imgDir or system.ResourceDirectory
	local Text = Options.text or "Test"
	local TextFont = Options.textFont or native.systemFont
	local TextSize = Options.textSize or 18
	local newGroup = display.newGroup()
	newGroup.anchorChildren = true
	newGroup.x = x
	newGroup.y = y
	newGroup.img = display.newImage(newGroup, Image, ImageDir, 0, 0 )
	newGroup.img.width = w
	newGroup.img.height = h
	local TextSettings = {
		text = Text,     
		x = 0,
		y = 0,
		font = TextFont,   
		fontSize = TextSize,
		align = "center"
	}
	newGroup.text = display.newText(TextSettings)
	newGroup:insert(newGroup.text)
	newGroup.text:setFillColor(0,0,0)
	
	return newGroup
end



local MyButton = display.newImageText({
		text="my Button",
	}, _W*0.5, _H*0.5, 35, 25) -- set there **width or height** manually
MyButton.text.size = 28
MyButton.img.width = 200 -- set there **width** manually
MyButton.img.height = 200 -- set there **height** manually
--MyButton:removeSelf() -- or remove Group of objs
--MyButton=nil

Thank you Juni, Redbol,
It looks like all should be easier than I though: the width and height of a group automatically reflect the contained items - which might just work for me.

At the level above the widgets, when the screen is resized (rotated or other), I now use the function below to help reposition my widgets dynamically across the top of the screen.

Great people and support in this forum - thank you for your time ! -ivec

function M.screenBox()
	local scrL = display.safeScreenOriginX;
	local scrT = display.safeScreenOriginY;
	return {
		L = scrL,
		T = scrT,
		R = scrL + display.safeActualContentWidth,
		B = scrT + display.safeActualContentHeight,
	}
end
-- Utility to reposition widgets at the top of a screen/box, e.g. when screen is resized:
--     layoutItems( nil, box, widget1, 5, widget2, nil, widget3, nil )
-- A "number" value indicates a fixed spacing between two items; the 'extra' space is shared across the "nil" entries
-- Note: it seems wiser to use e.g. -1 as a value, instead of nil, for "variable spacing"
function M.layoutItems(box,...)
	local defSpc = 10
	local refW = box.R-box.L
	local totW = 0
	local maxH = 1
	local nilCnt = 0
	local altSpc=nil
	-- scan through the provided elements to compute total width
	for i=1,#arg do local v = arg[i] --i,v in ipairs(arg) do
		--for i,v in ipairs(arg) do  -- the "iterator" version seems to stop at the first 'nil' element...
		local t = type(v) -- string number table nil
		if t=="table" then
			totW = totW + (altSpc or defSpc) + v.width
			altSpc=nil
			maxH = math.max(maxH,v.height)
		elseif t=="nil" then
			nilCnt = nilCnt+1
		elseif t=="number" then
			altSpc=v
		end
	end
	totW = totW + (altSpc or defSpc)
	local scal = (totW>refW) and (refW/totW) or nil -- scaling if exceeded length
	local nilSpc = (totW<refW) and (refW-totW)/nilCnt or 0  -- note: at least one "nil" is required
	local xPos = box.L
	local yPos = box.T + 0.5*maxH
	altSpc=nil
	-- position the widgets
	for i=1,#arg do local v = arg[i] --i,v in ipairs(arg) do
		local t = type(v) -- string number table nil
		if t=="table" then
			local w = v.width
			xPos = xPos + (altSpc or defSpc) + w
			altSpc=nil
			v.x = xPos-0.5*w -- could test 'anchor' to position accordingly
			v.y = yPos
		elseif t=="nil" then
			xPos = xPos+nilSpc
		elseif t=="number" then
			altSpc=v
		end
	end
	box.T = box.T + maxH
end