You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
501 lines
17 KiB
501 lines
17 KiB
6 years ago
|
--[[
|
||
|
This file contains code that that allows many different miniwindow plugins
|
||
|
to maintain the same UI theme, as long as they follow certain guidelines.
|
||
|
We can use this to get a base set of colors, standard display elements,
|
||
|
and title fonts that get used everywhere in order to unify the visual style
|
||
|
and provide a way to customize that style easily.
|
||
|
|
||
|
Steps for use: (also see https://github.com/fiendish/aardwolfclientpackage/wiki/Miniwindow-Color-Themes )
|
||
|
1) Inside your plugins, require this file at the very beginning of your script section.
|
||
|
2) Use variable names as spelled out in lua/mw_themes/Charcoal.lua for colorization within the "Theme." namespace, e.g. Theme.BODY_TEXT etc.
|
||
|
3) Use the shared graphics functions defined below for drawing various elements with the current color theme.
|
||
|
Some of the functions are not for drawing things. You can ignore them.
|
||
|
4) Four things make a miniwindow fit the theme: The border, the titlebar, the resize widget, and the general colors being used.
|
||
|
The border, titlebar, resize widget, and 3D boxes all have special draw functions included below. The colors are defined in the theme files.
|
||
|
4) Optional: Make your own themes (clone one of the files in lua/mw_themes and customize your colors).
|
||
|
5) Optional: If your plugin wants to preserve state between theme changes (changing theme reloads the plugin),
|
||
|
you can detect whether the plugin is closing because of a theme change with GetVariable(Theme.reloading_variable).
|
||
|
--]]
|
||
|
require "checkplugin"
|
||
|
require "movewindow"
|
||
|
|
||
|
dofile(GetInfo(60) .. "aardwolf_colors.lua");
|
||
|
|
||
|
module ("Theme", package.seeall)
|
||
|
|
||
|
function b9315e040989d3f81f4328d6()
|
||
|
-- used for theme system detection
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
theme_dir = GetInfo(66).."lua\\mw_themes\\"
|
||
|
theme_file = "Charcoal.lua"
|
||
|
|
||
|
function get_theme()
|
||
|
return theme_file
|
||
|
end
|
||
|
|
||
|
reloading_variable = "aard_theme_just_reloading"
|
||
|
|
||
|
function just_reloading()
|
||
|
SetVariable(reloading_variable, 1)
|
||
|
end
|
||
|
|
||
|
local default_theme = {
|
||
|
LOGO_OPACITY = 0.02,
|
||
|
|
||
|
PRIMARY_BODY = 0x0c0c0c,
|
||
|
SECONDARY_BODY = 0x777777,
|
||
|
BODY_TEXT = 0xe8e8e8,
|
||
|
|
||
|
CLICKABLE = 0x666666,
|
||
|
CLICKABLE_HOVER = 0x444444,
|
||
|
CLICKABLE_HOT = 0x40406b,
|
||
|
CLICKABLE_TEXT = 0xc8c8c8,
|
||
|
CLICKABLE_HOVER_TEXT = 0xdddddd,
|
||
|
CLICKABLE_HOT_TEXT = 0xcfc5df,
|
||
|
|
||
|
TITLE_PADDING = 2,
|
||
|
|
||
|
THREE_D_HIGHLIGHT = 0xe8e8e8,
|
||
|
|
||
|
THREE_D_GRADIENT = miniwin.gradient_vertical,
|
||
|
THREE_D_GRADIENT_FIRST = 0xcdced1,
|
||
|
THREE_D_GRADIENT_SECOND = 0x8c8c8c,
|
||
|
THREE_D_GRADIENT_ONLY_IN_TITLE = false,
|
||
|
|
||
|
THREE_D_SOFTSHADOW = 0x606060,
|
||
|
THREE_D_HARDSHADOW = 0x303030,
|
||
|
THREE_D_SURFACE_DETAIL = 0x050505,
|
||
|
|
||
|
SCROLL_TRACK_COLOR1 = 0x444444,
|
||
|
SCROLL_TRACK_COLOR2 = 0x888888,
|
||
|
VERTICAL_TRACK_BRUSH = miniwin.brush_hatch_forwards_diagonal,
|
||
|
|
||
|
DYNAMIC_BUTTON_PADDING = 20,
|
||
|
RESIZER_SIZE = 16
|
||
|
}
|
||
|
|
||
|
function load_theme(file)
|
||
|
local file_loaded, data_from_file = pcall(dofile, theme_dir..file)
|
||
|
|
||
|
-- init defaults
|
||
|
for k,v in pairs(default_theme) do
|
||
|
Theme[k] = v
|
||
|
end
|
||
|
|
||
|
if file_loaded then
|
||
|
if type(data_from_file) == "table" then
|
||
|
for k,v in pairs(data_from_file) do
|
||
|
Theme[k] = v
|
||
|
end
|
||
|
theme_file = file
|
||
|
else
|
||
|
print("Error loading theme file: ", theme_dir..file)
|
||
|
print("This theme file is invalid. Please delete it and select a different theme.")
|
||
|
print()
|
||
|
end
|
||
|
else
|
||
|
print("Error loading theme file: ", theme_dir..file)
|
||
|
print(data_from_file) -- error message
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- junk files that should not have existed in the first place
|
||
|
local bad_shas = {
|
||
|
["default.lua"] = {
|
||
|
["d189be39efb49730537c8ada65fbd5382d3e44ad"] = true,
|
||
|
["39d9b7fc4d571ac62d1005b52f8da43c4b7827e1"] = true,
|
||
|
["774bdd2f098f1c4fe81d9a6b8eb5bfad6bd79c51"] = true,
|
||
|
["b7fd919be678f0c7b1c52bea644f183a7b9397f1"] = true,
|
||
|
["acc1d615901050b2faa50e1b0497ee30b72f5118"] = true,
|
||
|
["ac993b349691eb51e472ca5b1b0ae18a03943bf2"] = true,
|
||
|
["0cd5bcca0723a57eabedd08a9cfa6f4ec93ea469"] = true
|
||
|
},
|
||
|
["dark_pony.lua"] = {
|
||
|
["d189be39efb49730537c8ada65fbd5382d3e44ad"] = true
|
||
|
},
|
||
|
["Joker.lua"] = {
|
||
|
["17fa722746df781326b100744dd790c66721b749"] = true,
|
||
|
["b2b83804ce87eb889127658cb80c9d23d76082b4"] = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
require "gitsha"
|
||
|
function theme_has_bad_sha(filename)
|
||
|
return bad_shas[filename] and bad_shas[filename][gitsha(theme_dir..filename)]
|
||
|
end
|
||
|
|
||
|
local theme_controller_ID = "b9315e040989d3f81f4328d6"
|
||
|
local theme_controller_name = "aard_Theme_Controller"
|
||
|
if (GetPluginID() ~= theme_controller_ID) then
|
||
|
if not IsPluginInstalled(theme_controller_ID) then
|
||
|
local inner_action = [[DoAfterSpecial(0.1, 'require \'checkplugin\';do_plugin_check_now(\']]..theme_controller_ID..[[\', \']]..theme_controller_name..[[\')', sendto.script)]]
|
||
|
|
||
|
-- execute_in_global_space(inner_action)
|
||
|
local prefix = GetAlphaOption("script_prefix")
|
||
|
local action = [[
|
||
|
SetAlphaOption("script_prefix", "/")
|
||
|
Execute("/]] .. inner_action:gsub("\\", "\\\\") .. [[")
|
||
|
SetAlphaOption("script_prefix", "]] .. prefix:gsub("\\", "\\\\") .. [[")
|
||
|
]]
|
||
|
DoAfterSpecial(0.1, action, sendto.script)
|
||
|
end
|
||
|
|
||
|
local maybe_theme_file = GetPluginVariable(theme_controller_ID, "theme_file") or theme_file
|
||
|
|
||
|
if not theme_has_bad_sha(maybe_theme_file) then
|
||
|
theme_file = maybe_theme_file
|
||
|
end
|
||
|
|
||
|
load_theme(theme_file)
|
||
|
end
|
||
|
|
||
|
-- Replacement for WindowRectOp action 5, which allows for a 3D look while maintaining color theme.
|
||
|
function Draw3DRect (win, left, top, right, bottom, depressed)
|
||
|
local gradient = (not THREE_D_GRADIENT_ONLY_IN_TITLE or __theme_istitle) and THREE_D_GRADIENT or false
|
||
|
__theme_istitle = false
|
||
|
|
||
|
if right > 0 then
|
||
|
right = right + 1
|
||
|
end
|
||
|
if bottom > 0 then
|
||
|
bottom = bottom + 1
|
||
|
end
|
||
|
|
||
|
if gradient and (THREE_D_GRADIENT_FIRST == THREE_D_GRADIENT_SECOND) then
|
||
|
gradient = false
|
||
|
end
|
||
|
|
||
|
if (gradient == 1) or (gradient == 2) or (gradient == 3) then
|
||
|
WindowGradient(win, left, top, right, bottom,
|
||
|
THREE_D_GRADIENT_FIRST,
|
||
|
THREE_D_GRADIENT_SECOND,
|
||
|
gradient)
|
||
|
else
|
||
|
WindowRectOp(win, 2, left, top, right, bottom, THREE_D_GRADIENT_FIRST)
|
||
|
end
|
||
|
|
||
|
if not depressed then
|
||
|
WindowLine(win, left+1, top+1, right, top+1, THREE_D_HIGHLIGHT, 0x0200, 1)
|
||
|
WindowLine(win, left+1, top+1, left+1, bottom, THREE_D_HIGHLIGHT, 0x0200, 1)
|
||
|
|
||
|
WindowLine(win, left, bottom-2, right, bottom-2, THREE_D_SOFTSHADOW, 0x0200, 1)
|
||
|
WindowLine(win, right-2, top, right-2, bottom-2, THREE_D_SOFTSHADOW, 0x0200, 1)
|
||
|
|
||
|
WindowLine(win, left, bottom-1, right, bottom-1, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
WindowLine(win, right-1, top, right-1, bottom-1, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
else
|
||
|
WindowLine(win, left, top+1, right, top+1, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
WindowLine(win, left+1, top, left+1, bottom, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
|
||
|
WindowLine(win, left, top, right, top, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
WindowLine(win, left, top, left, bottom, THREE_D_HARDSHADOW, 0x0200, 1)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function Draw3DTextBox(win, font, left, top, text, utf8)
|
||
|
local right = left + WindowTextWidth(win, font, text)
|
||
|
local bottom = top + TextHeight(win, font)
|
||
|
Draw3DRect(win, left, top, right+3, bottom+3)
|
||
|
WindowText(win, font, text, left+2, top+2, right+1, bottom+1, THREE_D_SURFACE_DETAIL, utf8)
|
||
|
return right-left
|
||
|
end
|
||
|
|
||
|
function DrawTextBox(win, font, left, top, text, utf8, outlined, bgcolor, textcolor)
|
||
|
if nil == bgcolor then
|
||
|
bgcolor = CLICKABLE
|
||
|
end
|
||
|
if nil == textcolor then
|
||
|
textcolor = CLICKABLE_TEXT
|
||
|
end
|
||
|
local right = left + WindowTextWidth(win, font, text) + 4
|
||
|
local bottom = top + TextHeight(win, font)
|
||
|
WindowRectOp(win, 2, left, top+1, right, bottom+2, bgcolor)
|
||
|
if outlined then
|
||
|
WindowRectOp(win, 1, left-1, top, right+1, bottom+3, textcolor)
|
||
|
end
|
||
|
WindowText(win, font, text, left+2, top+1, right, bottom+1, textcolor, utf8)
|
||
|
return right-left
|
||
|
end
|
||
|
|
||
|
function AddResizeTag(win, type, x1, y1, mousedown_callback, dragmove_callback, dragrelease_callback)
|
||
|
local x1, y1 = DrawResizeTag(win, type, x1, y1)
|
||
|
|
||
|
-- Add handler hotspots
|
||
|
if WindowMoveHotspot(win, "resize", x1, y1, 0, 0) ~= 0 then
|
||
|
WindowAddHotspot(win, "resize", x1, y1, 0, 0, nil, nil, mousedown_callback, nil, nil, "", 6, 0)
|
||
|
WindowDragHandler(win, "resize", dragmove_callback, dragrelease_callback, 0)
|
||
|
end
|
||
|
|
||
|
return x1, y1
|
||
|
end
|
||
|
|
||
|
function DrawResizeTag(win, type, x1, y1)
|
||
|
local x2, y2
|
||
|
if not (x1 and y1) then
|
||
|
x2 = WindowInfo(win, 3) - 3
|
||
|
y2 = WindowInfo(win, 4) - 3
|
||
|
x1 = x2 - RESIZER_SIZE + 1
|
||
|
y1 = y2 - RESIZER_SIZE + 1
|
||
|
else
|
||
|
x2 = x1 + RESIZER_SIZE
|
||
|
y2 = y1 + RESIZER_SIZE
|
||
|
end
|
||
|
|
||
|
local m = 2
|
||
|
local n = 2
|
||
|
if (type == 2) or (type == "full") then
|
||
|
Draw3DRect(win, x1, y1, x2, y2, false)
|
||
|
while (x1+m < x2 and y1+n+1 < y2) do
|
||
|
WindowLine(win, x1+m-1, y2-2, x2-1, y1+n-2, THREE_D_HIGHLIGHT, 0, 1)
|
||
|
WindowLine(win, x1+m, y2-2, x2-1, y1+n-1, THREE_D_HARDSHADOW, 0, 1)
|
||
|
WindowLine(win, x1+m+1, y2-2, x2-1, y1+n, THREE_D_GRADIENT_FIRST, 0, 1)
|
||
|
m = m+3
|
||
|
n = n+3
|
||
|
end
|
||
|
WindowSetPixel(win, x2-2, y2-2, THREE_D_HIGHLIGHT)
|
||
|
else
|
||
|
while (x1+m < x2 and y1+n+1 < y2) do
|
||
|
WindowLine(win, x1+m, y2-1, x2, y1+n-1, THREE_D_HIGHLIGHT, 0, 1)
|
||
|
WindowLine(win, x1+m+1, y2-1, x2, y1+n, THREE_D_HARDSHADOW, 0, 1)
|
||
|
WindowLine(win, x1+m+2, y2-1, x2, y1+n+1, THREE_D_GRADIENT_FIRST, 0, 1)
|
||
|
m = m+3
|
||
|
n = n+3
|
||
|
end
|
||
|
WindowLine(win, x1, y2, x2, y2, THREE_D_HARDSHADOW, 0, 1)
|
||
|
WindowLine(win, x2, y1, x2, y2+1, THREE_D_HARDSHADOW, 0, 1)
|
||
|
WindowSetPixel(win, x2-1, y2-1, THREE_D_HIGHLIGHT)
|
||
|
end
|
||
|
return x1, y1
|
||
|
end
|
||
|
|
||
|
function TextHeight(win, font)
|
||
|
return WindowFontInfo(win, font, 1)
|
||
|
end
|
||
|
|
||
|
-- title_alignment can be "left", "right", or "center" (the default)
|
||
|
function DressWindow(win, font, title, title_alignment)
|
||
|
local l, t, r, b = DrawBorder(win)
|
||
|
|
||
|
if title and (title ~= "") then
|
||
|
t = DrawTitleBar(win, font, title, title_alignment)
|
||
|
if t > 1 then
|
||
|
movewindow.add_drag_handler(win, 0, 0, 0, t)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return l, t, r, b
|
||
|
end
|
||
|
|
||
|
function DrawTitleBar(win, font, title, text_alignment)
|
||
|
local title_lines
|
||
|
if type(title) == "string" then
|
||
|
title_lines = utils.split(title, "\n")
|
||
|
else
|
||
|
title_lines = title
|
||
|
end
|
||
|
|
||
|
local line_height = 0
|
||
|
local title_height = 0
|
||
|
if font and title_lines then
|
||
|
line_height = TextHeight(win, font)
|
||
|
if line_height == nil then
|
||
|
return (2*TITLE_PADDING)
|
||
|
end
|
||
|
title_height = (2*TITLE_PADDING) + (line_height * #title_lines)
|
||
|
end
|
||
|
|
||
|
__theme_istitle = true
|
||
|
Draw3DRect(
|
||
|
win,
|
||
|
-1,
|
||
|
-1,
|
||
|
WindowInfo(win, 3)-1,
|
||
|
title_height,
|
||
|
false
|
||
|
)
|
||
|
|
||
|
local first_color = nil
|
||
|
local txt = nil
|
||
|
for i,v in ipairs(title_lines) do
|
||
|
if type(v) == "table" then
|
||
|
txt = strip_colours_from_styles(v)
|
||
|
else
|
||
|
txt = v
|
||
|
end
|
||
|
local width = WindowTextWidth(win, font, txt)
|
||
|
|
||
|
local text_left = (WindowInfo(win, 3) - width) / 2 -- default text align center
|
||
|
if text_alignment == "left" then
|
||
|
text_left = TITLE_PADDING + 2
|
||
|
elseif text_alignment == "right" then
|
||
|
text_left = WindowInfo(win, 3) - width - TITLE_PADDING
|
||
|
end
|
||
|
local text_right = math.min(text_left + width, WindowInfo(win, 3) - TITLE_PADDING - 2)
|
||
|
|
||
|
local text_top = (line_height * (i-1)) + TITLE_PADDING
|
||
|
if type(v) == "string" then
|
||
|
WindowText(win, font, v, text_left, text_top, text_right, title_height, THREE_D_SURFACE_DETAIL)
|
||
|
else
|
||
|
-- The colors of all styles matching the first style color get stripped out and replaced with the default title color
|
||
|
for i,w in ipairs(v) do
|
||
|
first_color = first_color or w.textcolour
|
||
|
if w.textcolour == first_color then
|
||
|
w.textcolour = THREE_D_SURFACE_DETAIL
|
||
|
end
|
||
|
end
|
||
|
WindowTextFromStyles(win, font, v, text_left, text_top, text_right, title_height, true)
|
||
|
end
|
||
|
end
|
||
|
return title_height
|
||
|
end
|
||
|
|
||
|
function DrawBorder(win)
|
||
|
local r = WindowInfo(win, 3)-3
|
||
|
local b = WindowInfo(win, 4)-3
|
||
|
WindowRectOp(win, 1, 0, 0, 0, 0, THREE_D_HIGHLIGHT)
|
||
|
WindowRectOp(win, 1, 1, 1, -1, -1, THREE_D_SOFTSHADOW)
|
||
|
return 2, 2, r, b
|
||
|
end
|
||
|
|
||
|
function OutlinedText(win, font, text, startx, starty, endx, endy, color, outline_color, utf8, thickness)
|
||
|
if thickness == nil then
|
||
|
thickness = 1
|
||
|
end
|
||
|
if outline_color == nil then
|
||
|
outline_color = THREE_D_HARDSHADOW
|
||
|
end
|
||
|
local right = nil
|
||
|
for xi = -thickness,thickness do
|
||
|
for yi = -thickness,thickness do
|
||
|
right = WindowText(win, font, text, startx+xi, starty+yi, endx+1, endy+1, outline_color, utf8)
|
||
|
end
|
||
|
end
|
||
|
local right = WindowText(win, font, text, startx+1, starty+1, endx, endy, outline_color, utf8)
|
||
|
WindowText(win, font, text, startx, starty, endx, endy, color, utf8)
|
||
|
return right
|
||
|
end
|
||
|
|
||
|
function WindowTextFromStyles(win, font, styles, left, top, right, bottom, utf8)
|
||
|
for i,v in ipairs(styles) do
|
||
|
left = left + WindowText(win, font, v.text, left, top, right, bottom, v.textcolour or BODY_TEXT, utf8)
|
||
|
end
|
||
|
return left
|
||
|
end
|
||
|
|
||
|
-- text with a black outline
|
||
|
function OutlinedTextFromStyles(win, font, styles, startx, starty, endx, endy, outline_color, utf8, thickness)
|
||
|
if thickness == nil then
|
||
|
thickness = 1
|
||
|
end
|
||
|
if outline_color == nil then
|
||
|
outline_color = THREE_D_HARDSHADOW
|
||
|
end
|
||
|
local text = strip_colours_from_styles(styles)
|
||
|
local right = nil
|
||
|
for xi = -thickness,thickness do
|
||
|
for yi = -thickness,thickness do
|
||
|
right = WindowText(win, font, text, startx+xi, starty+yi, endx+1, endy+1, outline_color, utf8)
|
||
|
end
|
||
|
end
|
||
|
WindowTextFromStyles(win, font, styles, startx, starty, endx, endy, utf8)
|
||
|
return right
|
||
|
end
|
||
|
|
||
|
-- Based on mw.lua's popup function, but with theme colors
|
||
|
function Popup(win, -- window name to use
|
||
|
font_id, -- font to use for each body line
|
||
|
info, -- table of lines to show (plain text or styles)
|
||
|
left, top, -- preferred location
|
||
|
stay_left_of, -- guidance for keeping the popup visible
|
||
|
stay_right_of) -- guidance for keeping the popup visible
|
||
|
|
||
|
local BORDER_WIDTH = 2
|
||
|
|
||
|
assert(WindowInfo (win, 1), "Window " .. win .. " must already exist")
|
||
|
assert(WindowFontInfo (win, font_id, 1), "No font " .. font_id .. " in " .. win)
|
||
|
|
||
|
local font_height = WindowFontInfo (win, font_id, 1)
|
||
|
local font_leading = WindowFontInfo (win, font_id, 4) + WindowFontInfo (win, font_id, 5)
|
||
|
|
||
|
-- find text width - minus colour codes
|
||
|
local infowidth = 0
|
||
|
local infoheight = 0
|
||
|
|
||
|
-- calculate remaining width and height
|
||
|
for _, v in ipairs (info) do
|
||
|
if type(v) == "table" then
|
||
|
txt = strip_colours_from_styles(v)
|
||
|
else
|
||
|
txt = strip_colours(v)
|
||
|
end
|
||
|
infowidth = math.max (infowidth, WindowTextWidth (win, font_id, txt))
|
||
|
infoheight = infoheight + font_height
|
||
|
end -- for
|
||
|
|
||
|
infowidth = infowidth + (2 * BORDER_WIDTH) + -- leave room for border
|
||
|
WindowFontInfo (win, font_id, 6) -- one character width extra
|
||
|
|
||
|
infoheight = infoheight + (2 * BORDER_WIDTH) + -- leave room for border
|
||
|
font_leading + -- plus leading below bottom line,
|
||
|
10 -- and 5 pixels top and bottom
|
||
|
|
||
|
-- if align_right then
|
||
|
-- left = left - infowidth
|
||
|
-- end -- if align_right
|
||
|
|
||
|
-- if align_bottom then
|
||
|
-- top = top - infoheight
|
||
|
-- end -- if align_bottom
|
||
|
|
||
|
top = math.min(top, GetInfo(280) - infoheight)
|
||
|
top = math.max(0, top)
|
||
|
if left < stay_left_of then
|
||
|
if left+infowidth > stay_left_of then
|
||
|
left = stay_left_of - infowidth
|
||
|
end
|
||
|
if left < 0 then
|
||
|
left = stay_right_of
|
||
|
end
|
||
|
else
|
||
|
if left < stay_right_of then
|
||
|
left = stay_right_of
|
||
|
end
|
||
|
if (left + infowidth) > GetInfo(281) then
|
||
|
left = stay_left_of - infowidth
|
||
|
end
|
||
|
end
|
||
|
WindowCreate(win,
|
||
|
left, top, -- where
|
||
|
infowidth, -- width (gap of 5 pixels per side)
|
||
|
infoheight, -- height
|
||
|
miniwin.pos_top_left, -- position mode: can't be 0 to 3
|
||
|
miniwin.create_absolute_location + miniwin.create_transparent,
|
||
|
SECONDARY_BODY)
|
||
|
|
||
|
WindowCircleOp(win, miniwin.circle_round_rectangle,
|
||
|
BORDER_WIDTH, BORDER_WIDTH, -BORDER_WIDTH, -BORDER_WIDTH, -- border inset
|
||
|
THREE_D_HIGHLIGHT, miniwin.pen_solid, BORDER_WIDTH, -- line
|
||
|
PRIMARY_BODY, miniwin.brush_solid, -- fill
|
||
|
5, 5) -- diameter of ellipse
|
||
|
|
||
|
local x = BORDER_WIDTH + WindowFontInfo (win, font_id, 6) / 2 -- start 1/2 character in
|
||
|
local y = BORDER_WIDTH + 5 -- skip border, and leave 5 pixel gap
|
||
|
|
||
|
-- show each line
|
||
|
for _, line in ipairs(info) do
|
||
|
if type(line) == "string" then
|
||
|
WindowText(win, font_id, line, x, y, 0, 0, BODY_TEXT)
|
||
|
else
|
||
|
WindowTextFromStyles(win, font_id, line, x, y, 0, 0)
|
||
|
end
|
||
|
|
||
|
y = y + font_height
|
||
|
end -- for
|
||
|
|
||
|
-- display popup window
|
||
|
WindowShow(win, true)
|
||
|
|
||
|
end -- popup
|