mirror of
https://github.com/airstruck/luigi.git
synced 2026-01-09 15:58:22 +00:00
decouple icon from text, see #19
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
return { style = 'dialog',
|
return { style = 'dialog',
|
||||||
{ style = 'dialogHead', text = 'About LUIGI' },
|
{ style = 'dialogHead', text = 'About LUIGI' },
|
||||||
{ style = 'dialogBody', padding = 24, icon = 'logo.png', text = [[
|
{ style = 'dialogBody', padding = 24, icon = 'logo.png', align = 'middle right',
|
||||||
|
textOffset = { -250, 0 },
|
||||||
|
text = [[
|
||||||
Lovely User Interfaces for Game Inventors
|
Lovely User Interfaces for Game Inventors
|
||||||
|
|
||||||
Copyright (c) 2015 airstruck
|
Copyright (c) 2015 airstruck
|
||||||
]] },
|
]]
|
||||||
|
},
|
||||||
{ style = 'dialogFoot',
|
{ style = 'dialogFoot',
|
||||||
{}, -- spacer
|
{}, -- spacer
|
||||||
{ style = 'dialogButton', id = 'closeButton', text = 'Close' }
|
{ style = 'dialogButton', id = 'closeButton', text = 'Close' }
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ return { id = 'mainWindow',
|
|||||||
{ text = 'Use monospace font', id = 'mono' }
|
{ text = 'Use monospace font', id = 'mono' }
|
||||||
},
|
},
|
||||||
{ style = 'listThing', align = 'middle center',
|
{ style = 'listThing', align = 'middle center',
|
||||||
text = 'Try the scroll wheel on this area.', },
|
text = 'Try the scroll wheel on this area.' },
|
||||||
{ style = 'listThing', align = 'middle center',
|
{ style = 'listThing', align = 'middle center',
|
||||||
text = 'This text is centered, and in the middle vertically.' },
|
text = 'This text is centered, and in the middle vertically.' },
|
||||||
{ style = 'listThing', align = 'middle left',
|
{ style = 'listThing', align = 'middle left',
|
||||||
@@ -73,10 +73,10 @@ return { id = 'mainWindow',
|
|||||||
{ text = 'Use sans-serif font', id = 'sans2' },
|
{ text = 'Use sans-serif font', id = 'sans2' },
|
||||||
{ text = 'Use monospace font', id = 'mono2' }
|
{ text = 'Use monospace font', id = 'mono2' }
|
||||||
},
|
},
|
||||||
{ value = 1, text = 'Thing One' },
|
{ value = 1, text = 'First stepper item' },
|
||||||
{ value = 2, text = 'Thing Two' },
|
{ value = 2, text = 'Item two' },
|
||||||
{ value = 3, text = 'Thing Three' },
|
{ value = 3, text = 'Third stepper item' },
|
||||||
{ value = 4, text = 'Thing Four' },
|
{ value = 4, text = 'Item four' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ to recalculate their size and position.
|
|||||||
local ROOT = (...):gsub('[^.]*$', '')
|
local ROOT = (...):gsub('[^.]*$', '')
|
||||||
|
|
||||||
local Shortcut = require(ROOT .. 'shortcut')
|
local Shortcut = require(ROOT .. 'shortcut')
|
||||||
|
local Cleaner = require(ROOT .. 'cleaner')
|
||||||
|
|
||||||
local Attribute = {}
|
local Attribute = {}
|
||||||
|
|
||||||
@@ -161,8 +162,10 @@ Attribute.style = {}
|
|||||||
|
|
||||||
function Attribute.style.set (widget, value)
|
function Attribute.style.set (widget, value)
|
||||||
widget.attributes.style = value
|
widget.attributes.style = value
|
||||||
widget.fontData = nil
|
-- Cleaner.mark(widget, 'fontData')
|
||||||
widget.textData = nil
|
-- Cleaner.mark(widget, 'textData')
|
||||||
|
Cleaner.mark(widget, 'fontData')
|
||||||
|
Cleaner.mark(widget, 'textData')
|
||||||
widget.reshape(widget.parent or widget)
|
widget.reshape(widget.parent or widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -291,7 +294,7 @@ Attribute.flow = {}
|
|||||||
|
|
||||||
function Attribute.flow.set (widget, value)
|
function Attribute.flow.set (widget, value)
|
||||||
widget.attributes.flow = value
|
widget.attributes.flow = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
widget.reshape(widget.parent or widget)
|
widget.reshape(widget.parent or widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -310,12 +313,13 @@ with this widget.
|
|||||||
Attribute.width = {}
|
Attribute.width = {}
|
||||||
|
|
||||||
function Attribute.width.set (widget, value)
|
function Attribute.width.set (widget, value)
|
||||||
if value ~= 'auto' then
|
-- value ~= 'auto' then
|
||||||
|
if type(value) == 'number' then
|
||||||
value = value and math.max(value, widget.minwidth or 0)
|
value = value and math.max(value, widget.minwidth or 0)
|
||||||
end
|
end
|
||||||
widget.attributes.width = value
|
widget.attributes.width = value
|
||||||
if widget.wrap then
|
if widget.wrap then
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
widget.reshape(widget.parent or widget)
|
widget.reshape(widget.parent or widget)
|
||||||
end
|
end
|
||||||
@@ -398,8 +402,10 @@ this widget's `text`.
|
|||||||
Attribute.font = {}
|
Attribute.font = {}
|
||||||
|
|
||||||
local function resetFont (widget)
|
local function resetFont (widget)
|
||||||
rawset(widget, 'fontData', nil)
|
-- rawset(widget, 'fontData', nil)
|
||||||
rawset(widget, 'textData', nil)
|
-- rawset(widget, 'textData', nil)
|
||||||
|
Cleaner.mark(widget, 'fontData')
|
||||||
|
Cleaner.mark(widget, 'textData')
|
||||||
for _, child in ipairs(widget) do
|
for _, child in ipairs(widget) do
|
||||||
resetFont(child)
|
resetFont(child)
|
||||||
end
|
end
|
||||||
@@ -432,8 +438,8 @@ Attribute.size = {}
|
|||||||
|
|
||||||
function Attribute.size.set (widget, value)
|
function Attribute.size.set (widget, value)
|
||||||
widget.attributes.size = value
|
widget.attributes.size = value
|
||||||
widget.fontData = nil
|
Cleaner.mark(widget, 'fontData')
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
|
|
||||||
Attribute.size.get = cascade
|
Attribute.size.get = cascade
|
||||||
@@ -456,7 +462,7 @@ Attribute.text = {}
|
|||||||
|
|
||||||
function Attribute.text.set (widget, value)
|
function Attribute.text.set (widget, value)
|
||||||
widget.attributes.text = value
|
widget.attributes.text = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
@@ -472,7 +478,7 @@ Attribute.color = {}
|
|||||||
|
|
||||||
function Attribute.color.set (widget, value)
|
function Attribute.color.set (widget, value)
|
||||||
widget.attributes.color = value
|
widget.attributes.color = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
|
|
||||||
Attribute.color.get = cascade
|
Attribute.color.get = cascade
|
||||||
@@ -494,7 +500,7 @@ Attribute.align = {}
|
|||||||
|
|
||||||
function Attribute.align.set (widget, value)
|
function Attribute.align.set (widget, value)
|
||||||
widget.attributes.align = value
|
widget.attributes.align = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
|
|
||||||
Attribute.align.get = cascade
|
Attribute.align.get = cascade
|
||||||
@@ -514,11 +520,34 @@ Attribute.wrap = {}
|
|||||||
|
|
||||||
function Attribute.wrap.set (widget, value)
|
function Attribute.wrap.set (widget, value)
|
||||||
widget.attributes.wrap = value
|
widget.attributes.wrap = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
end
|
end
|
||||||
|
|
||||||
Attribute.wrap.get = cascade
|
Attribute.wrap.get = cascade
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Text offset.
|
||||||
|
|
||||||
|
@attrib textOffset
|
||||||
|
--]]--
|
||||||
|
Attribute.textOffset = {}
|
||||||
|
|
||||||
|
function Attribute.textOffset.set (widget, value)
|
||||||
|
widget.attributes.textOffset = value
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Icon offset.
|
||||||
|
|
||||||
|
@attrib iconOffset
|
||||||
|
--]]--
|
||||||
|
Attribute.iconOffset = {}
|
||||||
|
|
||||||
|
function Attribute.iconOffset.set (widget, value)
|
||||||
|
widget.attributes.iconOffset = value
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
Visual Attributes.
|
Visual Attributes.
|
||||||
|
|
||||||
@@ -563,7 +592,7 @@ Attribute.margin = {}
|
|||||||
|
|
||||||
function Attribute.margin.set (widget, value)
|
function Attribute.margin.set (widget, value)
|
||||||
widget.attributes.margin = value
|
widget.attributes.margin = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
widget:reshape()
|
widget:reshape()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -580,7 +609,7 @@ Attribute.padding = {}
|
|||||||
|
|
||||||
function Attribute.padding.set (widget, value)
|
function Attribute.padding.set (widget, value)
|
||||||
widget.attributes.padding = value
|
widget.attributes.padding = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
widget:reshape()
|
widget:reshape()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -595,7 +624,8 @@ Attribute.icon = {}
|
|||||||
|
|
||||||
function Attribute.icon.set (widget, value)
|
function Attribute.icon.set (widget, value)
|
||||||
widget.attributes.icon = value
|
widget.attributes.icon = value
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
|
widget.iconData = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
luigi/cleaner.lua
Normal file
32
luigi/cleaner.lua
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
local Cleaner = {}
|
||||||
|
|
||||||
|
local marked = {}
|
||||||
|
local watched = setmetatable({}, { __mode = 'k' })
|
||||||
|
|
||||||
|
function Cleaner.mark (t, key)
|
||||||
|
local length = #marked
|
||||||
|
local keys = watched[t]
|
||||||
|
if not keys then
|
||||||
|
keys = {}
|
||||||
|
watched[t] = keys
|
||||||
|
elseif keys[key] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
keys[key] = true
|
||||||
|
local i = length + 1
|
||||||
|
marked[i] = t
|
||||||
|
marked[i + 1] = key
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cleaner.clean ()
|
||||||
|
for i = #marked - 1, 1, -2 do
|
||||||
|
local t = marked[i]
|
||||||
|
local key = marked[i + 1]
|
||||||
|
t[key] = nil
|
||||||
|
marked[i] = nil
|
||||||
|
marked[i + 1] = nil
|
||||||
|
watched[t][key] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Cleaner
|
||||||
@@ -7,6 +7,7 @@ return function (config)
|
|||||||
local lineColor = config.lineColor or { 220, 220, 220 }
|
local lineColor = config.lineColor or { 220, 220, 220 }
|
||||||
local textColor = config.textColor or { 0, 0, 0 }
|
local textColor = config.textColor or { 0, 0, 0 }
|
||||||
local highlight = config.highlight or { 0x19, 0xAE, 0xFF }
|
local highlight = config.highlight or { 0x19, 0xAE, 0xFF }
|
||||||
|
local spacing = config.spacing or 2
|
||||||
|
|
||||||
local button_pressed = resources .. 'button_pressed.png'
|
local button_pressed = resources .. 'button_pressed.png'
|
||||||
local button_focused = resources .. 'button_focused.png'
|
local button_focused = resources .. 'button_focused.png'
|
||||||
@@ -54,6 +55,14 @@ return function (config)
|
|||||||
return self.value and check_checked or check_unchecked
|
return self.value and check_checked or check_unchecked
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function getCheckTextOffset (self)
|
||||||
|
local align = self.align or ''
|
||||||
|
local icon = self:getIcon()
|
||||||
|
if not icon then return { 0, 0 } end
|
||||||
|
local width = icon:getWidth() + spacing * 2
|
||||||
|
return { align:find 'right' and -width or width, 0 }
|
||||||
|
end
|
||||||
|
|
||||||
local function getControlHeight (self)
|
local function getControlHeight (self)
|
||||||
return self.flow == 'x' and self._defaultDimension
|
return self.flow == 'x' and self._defaultDimension
|
||||||
end
|
end
|
||||||
@@ -120,15 +129,14 @@ return function (config)
|
|||||||
width = getControlWidth,
|
width = getControlWidth,
|
||||||
color = textColor,
|
color = textColor,
|
||||||
align = 'center middle',
|
align = 'center middle',
|
||||||
margin = 2,
|
margin = spacing,
|
||||||
color = textColor,
|
color = textColor,
|
||||||
solid = true,
|
solid = true,
|
||||||
_defaultDimension = 36,
|
_defaultDimension = 36,
|
||||||
},
|
},
|
||||||
|
|
||||||
Line = {
|
Line = {
|
||||||
margin = 0,
|
margin = spacing + 2,
|
||||||
padding = 4,
|
|
||||||
align = 'left middle',
|
align = 'left middle',
|
||||||
_defaultDimension = 24,
|
_defaultDimension = 24,
|
||||||
},
|
},
|
||||||
@@ -145,6 +153,7 @@ return function (config)
|
|||||||
type = { 'Line', 'Control' },
|
type = { 'Line', 'Control' },
|
||||||
focusable = true,
|
focusable = true,
|
||||||
icon = getCheckIcon,
|
icon = getCheckIcon,
|
||||||
|
textOffset = getCheckTextOffset,
|
||||||
},
|
},
|
||||||
label = {
|
label = {
|
||||||
type = { 'Line', 'Control' },
|
type = { 'Line', 'Control' },
|
||||||
@@ -159,13 +168,13 @@ return function (config)
|
|||||||
icon = resources .. 'triangle_right.png',
|
icon = resources .. 'triangle_right.png',
|
||||||
},
|
},
|
||||||
['menu.item'] = {
|
['menu.item'] = {
|
||||||
padding = 4,
|
padding = spacing * 2,
|
||||||
height = 24,
|
height = 24,
|
||||||
align = 'left middle',
|
align = 'left middle',
|
||||||
background = getMenuItemBackground,
|
background = getMenuItemBackground,
|
||||||
},
|
},
|
||||||
panel = {
|
panel = {
|
||||||
padding = 2,
|
padding = spacing,
|
||||||
background = backColor,
|
background = backColor,
|
||||||
color = textColor,
|
color = textColor,
|
||||||
solid = true,
|
solid = true,
|
||||||
@@ -183,6 +192,7 @@ return function (config)
|
|||||||
type = { 'Line', 'Control' },
|
type = { 'Line', 'Control' },
|
||||||
focusable = true,
|
focusable = true,
|
||||||
icon = getRadioIcon,
|
icon = getRadioIcon,
|
||||||
|
textOffset = getCheckTextOffset,
|
||||||
},
|
},
|
||||||
sash = {
|
sash = {
|
||||||
background = getSashBackground,
|
background = getSashBackground,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ local Backend = require(ROOT .. 'backend')
|
|||||||
local Base = require(ROOT .. 'base')
|
local Base = require(ROOT .. 'base')
|
||||||
local Event = require(ROOT .. 'event')
|
local Event = require(ROOT .. 'event')
|
||||||
local Shortcut = require(ROOT .. 'shortcut')
|
local Shortcut = require(ROOT .. 'shortcut')
|
||||||
|
local Cleaner = require(ROOT .. 'cleaner')
|
||||||
|
|
||||||
local Input = Base:extend()
|
local Input = Base:extend()
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ function Input:handleDisplay (layout)
|
|||||||
local root = layout.root
|
local root = layout.root
|
||||||
if root then root:paint() end
|
if root then root:paint() end
|
||||||
Event.Display:emit(layout)
|
Event.Display:emit(layout)
|
||||||
|
Cleaner.clean()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Input:handleKeyPress (layout, key, x, y)
|
function Input:handleKeyPress (layout, key, x, y)
|
||||||
@@ -147,7 +149,10 @@ function Input:handlePressStart (layout, button, x, y, widget, shortcut)
|
|||||||
-- if hit then
|
-- if hit then
|
||||||
self.pressedWidgets[button] = widget
|
self.pressedWidgets[button] = widget
|
||||||
self.passedWidgets[button] = widget
|
self.passedWidgets[button] = widget
|
||||||
widget.pressed[button] = true
|
-- widget.pressed[button] = true
|
||||||
|
for ancestor in widget:eachAncestor(true) do
|
||||||
|
ancestor.pressed[button] = true
|
||||||
|
end
|
||||||
if button == 'left' then
|
if button == 'left' then
|
||||||
widget:focus()
|
widget:focus()
|
||||||
end
|
end
|
||||||
@@ -167,7 +172,10 @@ function Input:handlePressEnd (layout, button, x, y, widget, shortcut)
|
|||||||
local hit, widget = checkHit(widget or layout:getWidgetAt(x, y), layout)
|
local hit, widget = checkHit(widget or layout:getWidgetAt(x, y), layout)
|
||||||
local wasPressed = originWidget.pressed[button]
|
local wasPressed = originWidget.pressed[button]
|
||||||
if hit then
|
if hit then
|
||||||
originWidget.pressed[button] = nil
|
-- originWidget.pressed[button] = nil
|
||||||
|
for ancestor in originWidget:eachAncestor(true) do
|
||||||
|
ancestor.pressed[button] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
widget:bubbleEvent('PressEnd', {
|
widget:bubbleEvent('PressEnd', {
|
||||||
hit = hit,
|
hit = hit,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ local Event = require(ROOT .. 'event')
|
|||||||
local Widget = require(ROOT .. 'widget')
|
local Widget = require(ROOT .. 'widget')
|
||||||
local Input = require(ROOT .. 'input')
|
local Input = require(ROOT .. 'input')
|
||||||
local Style = require(ROOT .. 'style')
|
local Style = require(ROOT .. 'style')
|
||||||
|
local Cleaner = require(ROOT .. 'cleaner')
|
||||||
|
|
||||||
local Layout = Base:extend()
|
local Layout = Base:extend()
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@ function Layout:createWidget (data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function clearWidget (widget)
|
local function clearWidget (widget)
|
||||||
widget.textData = nil
|
Cleaner.mark(widget, 'textData')
|
||||||
widget.fontData = nil
|
widget.fontData = nil
|
||||||
widget.position = {}
|
widget.position = {}
|
||||||
widget.dimensions = {}
|
widget.dimensions = {}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ local Text = Backend.Text
|
|||||||
|
|
||||||
local Painter = Base:extend()
|
local Painter = Base:extend()
|
||||||
|
|
||||||
local imageCache = {}
|
local imageCache = setmetatable({}, { __mode = 'v' })
|
||||||
-- local sliceCache = {}
|
-- local sliceCache = {}
|
||||||
|
|
||||||
function Painter:constructor (widget)
|
function Painter:constructor (widget)
|
||||||
@@ -199,8 +199,70 @@ function Painter:paintIconAndText ()
|
|||||||
Backend.pop()
|
Backend.pop()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Painter:paintText ()
|
||||||
|
local widget = self.widget
|
||||||
|
if not widget.text then return end
|
||||||
|
|
||||||
|
local align = widget.align
|
||||||
|
local text = widget:getText()
|
||||||
|
local x, y, w, h = widget:getRectangle(true, true)
|
||||||
|
local offset = widget.textOffset
|
||||||
|
local ox, oy = 0, 0
|
||||||
|
if offset then
|
||||||
|
ox, oy = offset[1] or 0, offset[2] or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- horizontal alignment for non-wrapped text
|
||||||
|
if align:find 'right' then
|
||||||
|
x = x + (w - text:getWidth())
|
||||||
|
elseif align:find 'center' then
|
||||||
|
x = x + (w - text:getWidth()) * 0.5
|
||||||
|
end
|
||||||
|
|
||||||
|
if align:find 'middle' then
|
||||||
|
local textHeight = text:getHeight()
|
||||||
|
y = y + (h - textHeight) * 0.5
|
||||||
|
elseif align:find 'bottom' then
|
||||||
|
local textHeight = text:getHeight()
|
||||||
|
y = y + h - textHeight
|
||||||
|
end
|
||||||
|
|
||||||
|
local sx, sy = widget.scrollX or 0, widget.scrollY or 0
|
||||||
|
Backend.draw(text, x + ox - sx, y + oy - sy)
|
||||||
|
|
||||||
|
-- widget.innerHeight = text:getHeight()
|
||||||
|
-- widget.innerWidth = text:getWidth()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Painter:paintIcon ()
|
||||||
|
local widget = self.widget
|
||||||
|
if not widget.icon then return end
|
||||||
|
|
||||||
|
local align = widget.align
|
||||||
|
local icon = widget:getIcon()
|
||||||
|
local x, y, w, h = widget:getRectangle(true, true)
|
||||||
|
|
||||||
|
if align:find 'right' then
|
||||||
|
x = x + (w - icon:getWidth())
|
||||||
|
elseif align:find 'center' then
|
||||||
|
x = x + (w - icon:getWidth()) * 0.5
|
||||||
|
end
|
||||||
|
|
||||||
|
if align:find 'middle' then
|
||||||
|
local iconHeight = icon:getHeight()
|
||||||
|
y = y + (h - iconHeight) * 0.5
|
||||||
|
elseif align:find 'bottom' then
|
||||||
|
local iconHeight = icon:getHeight()
|
||||||
|
y = y + h - iconHeight
|
||||||
|
end
|
||||||
|
|
||||||
|
Backend.draw(icon, x, y)
|
||||||
|
end
|
||||||
|
|
||||||
function Painter:paintChildren ()
|
function Painter:paintChildren ()
|
||||||
for i, child in ipairs(self.widget) do
|
local widget = self.widget
|
||||||
|
for i, child in ipairs(widget) do
|
||||||
child:paint()
|
child:paint()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -225,7 +287,9 @@ function Painter:paint ()
|
|||||||
self:paintBackground()
|
self:paintBackground()
|
||||||
self:paintOutline()
|
self:paintOutline()
|
||||||
self:paintSlices()
|
self:paintSlices()
|
||||||
self:paintIconAndText()
|
-- self:paintIconAndText()
|
||||||
|
self:paintIcon()
|
||||||
|
self:paintText()
|
||||||
self:paintChildren()
|
self:paintChildren()
|
||||||
|
|
||||||
Backend.pop()
|
Backend.pop()
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ local Backend = require(ROOT .. 'backend')
|
|||||||
local Event = require(ROOT .. 'event')
|
local Event = require(ROOT .. 'event')
|
||||||
local Attribute = require(ROOT .. 'attribute')
|
local Attribute = require(ROOT .. 'attribute')
|
||||||
local Painter = require(ROOT .. 'painter')
|
local Painter = require(ROOT .. 'painter')
|
||||||
|
local Cleaner = require(ROOT .. 'cleaner')
|
||||||
local Font = Backend.Font
|
local Font = Backend.Font
|
||||||
|
local Text = Backend.Text
|
||||||
|
|
||||||
local Widget = {}
|
local Widget = {}
|
||||||
|
|
||||||
@@ -230,7 +232,7 @@ local function metaCall (Widget, layout, self)
|
|||||||
|
|
||||||
for k, v in ipairs(self) do
|
for k, v in ipairs(self) do
|
||||||
self[k] = v.isWidget and v or metaCall(Widget, self.layout, v)
|
self[k] = v.isWidget and v or metaCall(Widget, self.layout, v)
|
||||||
self[k].parent = self
|
v.parent = self
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -285,6 +287,10 @@ function Widget:bubbleEvent (eventName, data)
|
|||||||
data = data or {}
|
data = data or {}
|
||||||
data.target = self
|
data.target = self
|
||||||
for ancestor in self:eachAncestor(true) do
|
for ancestor in self:eachAncestor(true) do
|
||||||
|
if ancestor ~= self and ancestor.unified then
|
||||||
|
data.innerTarget = self
|
||||||
|
return ancestor:bubbleEvent(eventName, data)
|
||||||
|
end
|
||||||
local result = event:emit(ancestor, data)
|
local result = event:emit(ancestor, data)
|
||||||
if result ~= nil then return result end
|
if result ~= nil then return result end
|
||||||
end
|
end
|
||||||
@@ -400,6 +406,16 @@ function Widget:getPreviousNeighbor ()
|
|||||||
return layout.root
|
return layout.root
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Widget:registerChild (data)
|
||||||
|
local layout = self.layout
|
||||||
|
local child = data and data.isWidget and data or Widget(layout, data or {})
|
||||||
|
|
||||||
|
child.parent = self
|
||||||
|
child.layout = self.layout
|
||||||
|
|
||||||
|
return child
|
||||||
|
end
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
Add a child to this widget.
|
Add a child to this widget.
|
||||||
|
|
||||||
@@ -410,12 +426,8 @@ A widget or definition table representing a widget.
|
|||||||
The newly added child widget.
|
The newly added child widget.
|
||||||
--]]--
|
--]]--
|
||||||
function Widget:addChild (data)
|
function Widget:addChild (data)
|
||||||
local layout = self.layout
|
local child = self:registerChild(data)
|
||||||
local child = data and data.isWidget and data or Widget(layout, data or {})
|
|
||||||
|
|
||||||
self[#self + 1] = child
|
self[#self + 1] = child
|
||||||
child.parent = self
|
|
||||||
child.layout = self.layout
|
|
||||||
|
|
||||||
return child
|
return child
|
||||||
end
|
end
|
||||||
@@ -491,7 +503,6 @@ function Widget:calculateDimension (name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local size = (parentDimension - claimed) / unsized
|
local size = (parentDimension - claimed) / unsized
|
||||||
|
|
||||||
size = math.max(size, min)
|
size = math.max(size, min)
|
||||||
self.dimensions[name] = size
|
self.dimensions[name] = size
|
||||||
return size
|
return size
|
||||||
@@ -568,6 +579,14 @@ function Widget:calculateDimensionMinimum (name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not self.wrap then
|
||||||
|
if name == 'width' then
|
||||||
|
value = math.max(value, self:getText():getWidth())
|
||||||
|
else
|
||||||
|
value = math.max(value, self:getText():getHeight())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if value > 0 then
|
if value > 0 then
|
||||||
local space = (self.margin or 0) * 2 + (self.padding or 0) * 2
|
local space = (self.margin or 0) * 2 + (self.padding or 0) * 2
|
||||||
value = value + space
|
value = value + space
|
||||||
@@ -636,7 +655,8 @@ function Widget:getContentWidth ()
|
|||||||
width = math.max(width, child:getWidth())
|
width = math.max(width, child:getWidth())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return width
|
-- return width
|
||||||
|
return math.max(width, self:getText():getWidth())
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
@@ -659,16 +679,65 @@ function Widget:getContentHeight ()
|
|||||||
height = math.max(height, child:getHeight())
|
height = math.max(height, child:getHeight())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return height
|
-- return height
|
||||||
|
return math.max(height, self:getText():getHeight())
|
||||||
|
end
|
||||||
|
|
||||||
|
local imageCache = setmetatable({}, { __mode = 'v' })
|
||||||
|
|
||||||
|
local function loadImage (path)
|
||||||
|
local cached = imageCache[path]
|
||||||
|
if not cached then
|
||||||
|
cached = Backend.Image(path)
|
||||||
|
imageCache[path] = cached
|
||||||
|
end
|
||||||
|
|
||||||
|
return cached
|
||||||
|
end
|
||||||
|
|
||||||
|
function Widget:getIcon ()
|
||||||
|
if self.lastIcon ~= self.icon or not self.iconData then
|
||||||
|
self.lastIcon = self.icon
|
||||||
|
self.iconData = loadImage(self.icon)
|
||||||
|
end
|
||||||
|
return self.iconData
|
||||||
end
|
end
|
||||||
|
|
||||||
function Widget:getFont ()
|
function Widget:getFont ()
|
||||||
if not self.fontData then
|
if self.fontData then return self.fontData end
|
||||||
self.fontData = Font(self.font, self.size)
|
self.fontData = Font(self.font, self.size)
|
||||||
end
|
|
||||||
return self.fontData
|
return self.fontData
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Widget:getText ()
|
||||||
|
if self.textData then return self.textData end
|
||||||
|
|
||||||
|
local font = self:getFont()
|
||||||
|
|
||||||
|
if self.wrap then
|
||||||
|
-- horizontal alignment
|
||||||
|
local align = self.align
|
||||||
|
if align:find 'right' then
|
||||||
|
align = 'right'
|
||||||
|
elseif align:find 'center' then
|
||||||
|
align = 'center'
|
||||||
|
elseif align:find 'justify' then
|
||||||
|
align = 'justify'
|
||||||
|
else
|
||||||
|
align = 'left'
|
||||||
|
end
|
||||||
|
-- wrap limit
|
||||||
|
local x, y, w, h = self:getRectangle(true, true)
|
||||||
|
local offset = self.textOffset and self.textOffset[1] or 0
|
||||||
|
local limit = w - math.abs(offset)
|
||||||
|
self.textData = Text(font, self.text or '', self.color, align, limit)
|
||||||
|
else
|
||||||
|
self.textData = Text(font, self.text or '', self.color)
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.textData
|
||||||
|
end
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
Get x/y/width/height values describing a rectangle within the widget.
|
Get x/y/width/height values describing a rectangle within the widget.
|
||||||
|
|
||||||
@@ -772,7 +841,7 @@ function Widget:reshape ()
|
|||||||
self.position = {}
|
self.position = {}
|
||||||
self.dimensions = {}
|
self.dimensions = {}
|
||||||
|
|
||||||
self.textData = nil
|
Cleaner.mark(self, 'textData')
|
||||||
|
|
||||||
Event.Reshape:emit(self, { target = self })
|
Event.Reshape:emit(self, { target = self })
|
||||||
for _, child in ipairs(self) do
|
for _, child in ipairs(self) do
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ standard themes, the widget's value should be indicated in some other way.
|
|||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
return function (self)
|
return function (self)
|
||||||
|
|
||||||
self:onPress(function (event)
|
self:onPress(function (event)
|
||||||
if event.button ~= 'left' then return end
|
if event.button ~= 'left' then return end
|
||||||
self.value = not self.value
|
self.value = not self.value
|
||||||
|
|||||||
@@ -37,22 +37,10 @@ local function addLayoutChildren (self)
|
|||||||
for index, child in ipairs(self.items) do
|
for index, child in ipairs(self.items) do
|
||||||
child.type = child.type or 'menu.item'
|
child.type = child.type or 'menu.item'
|
||||||
root:addChild(child)
|
root:addChild(child)
|
||||||
local childHeight = child:getHeight()
|
|
||||||
height = height + childHeight
|
|
||||||
if child.type == 'menu.item' then
|
|
||||||
local font = child:getFont()
|
|
||||||
local pad = child.padding or 0
|
|
||||||
local tw = font:getAdvance(child[2].text)
|
|
||||||
+ pad * 2 + childHeight
|
|
||||||
local kw = font:getAdvance(child[3].text)
|
|
||||||
+ pad * 2 + childHeight
|
|
||||||
textWidth = math.max(textWidth, tw)
|
|
||||||
keyWidth = math.max(keyWidth, kw)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
root.height = height
|
root.height = 'auto'
|
||||||
root.width = textWidth + keyWidth + (root.padding or 0)
|
root.width = 'auto'
|
||||||
|
|
||||||
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
||||||
local w = isSubmenu and self:getWidth() or 0
|
local w = isSubmenu and self:getWidth() or 0
|
||||||
@@ -141,22 +129,20 @@ local function registerLayoutEvents (self)
|
|||||||
menuLayout:onPress(function (event)
|
menuLayout:onPress(function (event)
|
||||||
-- if event.button ~= 'left' then return end
|
-- if event.button ~= 'left' then return end
|
||||||
if not checkMouseButton(self, event) then return end
|
if not checkMouseButton(self, event) then return end
|
||||||
for widget in event.target:eachAncestor(true) do
|
local widget = event.target
|
||||||
if widget.type == 'menu.item' and #widget.items == 0 then
|
if widget.type == 'menu.item' and #widget.items == 0 then
|
||||||
menuLayout:hide()
|
menuLayout:hide()
|
||||||
deactivateSiblings(self.rootMenu[1])
|
deactivateSiblings(self.rootMenu[1])
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
menuLayout:onPressEnd(function (event)
|
menuLayout:onPressEnd(function (event)
|
||||||
-- if event.button ~= 'left' then return end
|
-- if event.button ~= 'left' then return end
|
||||||
if not checkMouseButton(self, event) then return end
|
if not checkMouseButton(self, event) then return end
|
||||||
for widget in event.target:eachAncestor(true) do
|
local widget = event.target
|
||||||
if widget.type == 'menu.item' and #widget.items == 0
|
if widget.type == 'menu.item' and #widget.items == 0
|
||||||
and event.target ~= event.origin then
|
and event.target ~= event.origin then
|
||||||
widget:bubbleEvent('Press', event)
|
widget:bubbleEvent('Press', event)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -164,12 +150,12 @@ local function registerLayoutEvents (self)
|
|||||||
menuLayout:onPressEnter(activate)
|
menuLayout:onPressEnter(activate)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function nothing () end
|
||||||
|
|
||||||
local function initialize (self)
|
local function initialize (self)
|
||||||
local font = self:getFont()
|
|
||||||
local pad = self.padding or 0
|
|
||||||
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
local isSubmenu = self.parentMenu and self.parentMenu.parentMenu
|
||||||
local text, shortcut, icon = self.text or '', self.shortcut or '', self.icon
|
local text, shortcut, icon = self.text or '', self.shortcut or '', self.icon
|
||||||
local textWidth = font:getAdvance(text) + pad * 2
|
-- local textWidth = font:getAdvance(text) + pad * 2
|
||||||
|
|
||||||
if isSubmenu then
|
if isSubmenu then
|
||||||
local edgeType
|
local edgeType
|
||||||
@@ -177,27 +163,36 @@ local function initialize (self)
|
|||||||
shortcut = ' '
|
shortcut = ' '
|
||||||
edgeType = 'menu.expander'
|
edgeType = 'menu.expander'
|
||||||
else
|
else
|
||||||
shortcut = Shortcut.stringify(shortcut)
|
shortcut = ' ' .. Shortcut.stringify(shortcut)
|
||||||
end
|
end
|
||||||
|
self.unified = true
|
||||||
|
self.height = 'auto' -- font:getLineHeight() + pad * 2
|
||||||
self.flow = 'x'
|
self.flow = 'x'
|
||||||
self:addChild { icon = icon, width = self.height }
|
self:addChild {
|
||||||
self:addChild { text = text, width = textWidth }
|
width = function () return self:getHeight() end,
|
||||||
|
icon = function () return self.icon end,
|
||||||
|
align = 'middle left',
|
||||||
|
}
|
||||||
|
self:addChild {
|
||||||
|
width = 'auto',
|
||||||
|
text = function () return self.text end
|
||||||
|
}
|
||||||
self:addChild {
|
self:addChild {
|
||||||
type = edgeType,
|
type = edgeType,
|
||||||
text = shortcut,
|
text = shortcut,
|
||||||
align = 'middle right',
|
align = 'middle right',
|
||||||
minwidth = self.height,
|
minwidth = function () return self:getHeight() end,
|
||||||
color = function ()
|
color = function ()
|
||||||
local c = self.color or { 0, 0, 0 }
|
local c = self.color or { 0, 0, 0 }
|
||||||
return { c[1], c[2], c[3], (c[4] or 256) / 2 }
|
return { c[1], c[2], c[3], (c[4] or 256) / 2 }
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
self.icon = nil
|
self.painter.paintText = nothing
|
||||||
self.text = nil
|
self.painter.paintIcon = nothing
|
||||||
else
|
else
|
||||||
-- top level menu
|
-- self.width = textWidth
|
||||||
self.width = textWidth + pad * 2
|
self.width = 'auto'
|
||||||
self.align = 'middle center'
|
self.align = 'middle center'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user