Today I hacked together a little code to try out an idea I had. It's not much at this point, just two types (one inherited from the other), but with some work I think it would become an easy way to create and use miniwindows, as well as derive your own custom types of miniwindows. This is what I have so far:
Window = {
new = function(name)
local o = setmetatable({}, Window)
o.name = name
o.x = 0
o.y = 0
o.width = 1
o.height = 1
-- Dummy window.
WindowCreate(o.name, 0, 0, 1, 1, 0, 0, 0)
return o
end,
__index = {
Clear = function(self, color)
WindowRectOp(self.name, 2, 0, 0, 0, 0, color or 0x000000)
end,
Show = function(self, bShow)
WindowShow(self.name, bShow)
end,
SelectFont = function(self, fontname, fontsize)
local fid = nil
local fontlist = WindowFontList(self.name)
if fontlist then
for _,v in ipairs(fontlist) do
if WindowFontInfo(self.name, v, 21) == fontname and
WindowFontInfo(self.name, v, 8) == fontsize then
break
end
end
if not fid then
fid = self.name .. "-f" .. #fontlist+1
WindowFont(self.name, fid, fontname, fontsize, false, false, false, false, 1, 0)
end
else
fid = self.name .. "-f1"
WindowFont(self.name, fid, fontname, fontsize, false, false, false, false, 1, 0)
end
return fid
end,
},
}
setmetatable(Window, {__index = Window.__index})
CharacterGrid = {
new = function(name, width, height, font, px)
local o = Window.new(name)
setmetatable(o, CharacterGrid)
o.mapwidth = width
o.mapheight = height
o.font = {
name = font or "fixedsys",
id = nil,
size = px or 10,
width = 1,
height = 1,
}
o.grid = {
}
o.font.id = o:SelectFont(o.font.name, o.font.size)
return o
end,
-- "Instance" methods
__index = {
DrawCell = function(self, cell, x, y)
-- Index into the appropriate cell, and add for the window edge
local x = self.font.width*x + 1
local y = self.font.height*y + 1
WindowText(self.name, self.font.id, cell.char, x, y, 0, 0, cell.style, false)
end,
DrawRow = function(self, line, row)
for i = 1, math.min(table.getn(line), self.mapwidth) do
self:DrawCell(line[i], i-1, row)
end
end,
DrawGrid = function(self)
self.font.id = self:SelectFont(self.font.name, self.font.size)
self.font.width = WindowTextWidth(self.name, self.font.id, "#")
self.font.height = WindowFontInfo(self.name, self.font.id, 1)
self.width = self.font.width * self.mapwidth;
self.height = self.font.height * self.mapheight;
WindowCreate(self.name, self.x, self.y, self.width, self.height, 6, 2, 0x000000)
WindowPosition(self.name, self.x, self.y, 6, 2)
for i = 1, math.min(table.getn(self.grid), self.mapheight) do
self:DrawRow(self.grid[i], i-1)
end
end,
Draw = function(self)
self:Clear(0x000000)
self:DrawGrid()
end,
},
}
setmetatable(CharacterGrid.__index, Window)
setmetatable(CharacterGrid, {__index = CharacterGrid.__index})
This code defines two types, one a generic Window and the other a derived CharacterGrid. The CharacterGrid itself is adapted directly from a table I use in my MapWindow plugin. It's quite easy to use, as it hides the complex details away. The grid table itself is table of lines, which are tables of cells, which store 'char' and 'style' (color) information.
The implementations of the two widget types do leave something to be desired at the moment, but the interface that you use to manipulate the grid is simple.
grid = CharacterGrid.new("TestGrid", 5, 5)
grid.x = 10
grid.y = 10
for i = 1, 5 do
local line = {}
for j = 1, 5 do
line[j] = {char = "X", style = 0xFF0000}
end
grid.grid[i] = line
end
grid:Draw()
grid:Show(true)
Running this code produces a stamp-like 5x5 grid of blue X's. (I admit I was slightly surprised by this; I expected red. But I digress) Any thoughts and/or contributions would be appreciated, because while I'd love to see a set of MUSHclient window widgets, it's not something I'd care to undertake on my own. |