initial release
This commit is contained in:
313
cosmic rage/lua/tabbed_window.lua
Normal file
313
cosmic rage/lua/tabbed_window.lua
Normal file
@@ -0,0 +1,313 @@
|
||||
-- tabbed_window.lua
|
||||
|
||||
--[[
|
||||
|
||||
Author: Nick Gammon
|
||||
Date: 7th February 2018
|
||||
|
||||
Generic tabbed miniwindow drawer.
|
||||
|
||||
Exposed functions:
|
||||
|
||||
init (context) -- call once (from OnPluginInstall), supply:
|
||||
|
||||
context.win -- window ID for this tabbed window
|
||||
context.tabfont -- table of font info for non-active tabs (name, size, unicode, bold, italic)
|
||||
context.activefont -- table of font info for the selected tab (name, size, unicode, bold, italic)
|
||||
context.titlefont -- table of font info for the title bar (name, size, unicode, bold, italic)
|
||||
context.colours -- table of assorted colours (see below for examples)
|
||||
context.window -- table (width and height) of the desired window size
|
||||
context.tab_filler -- gap between tabs
|
||||
context.can_move -- can window be dragged around?
|
||||
context.active_tab -- the currently active tab
|
||||
context.tabs -- table of tables - one per tab (name, handler)
|
||||
|
||||
draw_window (context, which_tab) -- draws the window with which_tab as the active tab
|
||||
hide_window (context) -- hides this window
|
||||
save_state (context) -- for saving the window position (call from OnPluginSaveState)
|
||||
|
||||
Exposed variables:
|
||||
|
||||
VERSION -- version of this module
|
||||
|
||||
--]]
|
||||
|
||||
module (..., package.seeall)
|
||||
|
||||
VERSION = 1.1 -- -- for querying by plugins
|
||||
|
||||
require "movewindow" -- load the movewindow.lua module
|
||||
|
||||
local default_context = {
|
||||
|
||||
-- window ID
|
||||
win = "tabbed_window_" .. GetUniqueID (),
|
||||
|
||||
-- font for inactive tab text
|
||||
tabfont = {
|
||||
id = "fn",
|
||||
name = "Lucida Console",
|
||||
size = 10, -- points
|
||||
unicode = false, -- Unicode?
|
||||
bold = false, -- make bold?
|
||||
italic = false, -- make italic?
|
||||
}, -- end of tabfont
|
||||
|
||||
-- font for active tab text
|
||||
activefont = {
|
||||
id = "fa",
|
||||
name = "Lucida Console",
|
||||
size = 10, -- points
|
||||
unicode = false, -- Unicode?
|
||||
bold = false, -- make bold?
|
||||
italic = false, -- make italic?
|
||||
}, -- end of activefont
|
||||
|
||||
-- font for title text
|
||||
titlefont = {
|
||||
id = "ft",
|
||||
name = "Lucida Console",
|
||||
size = 12, -- points
|
||||
unicode = false, -- Unicode?
|
||||
bold = true, -- make bold?
|
||||
italic = false, -- make italic?
|
||||
}, -- end of titlefont
|
||||
|
||||
colours = {
|
||||
background = ColourNameToRGB ("lightskyblue"), -- entire window background
|
||||
frame = ColourNameToRGB ("mediumorchid"), -- frame around window
|
||||
title_bar = ColourNameToRGB ("palegoldenrod"), -- behind the title
|
||||
title = ColourNameToRGB ("mediumblue"), -- title text
|
||||
tab = ColourNameToRGB ("green"), -- tab background
|
||||
tab_text = ColourNameToRGB ("white"), -- inactive tab text
|
||||
active_tab_text = ColourNameToRGB ("lightgreen"), -- active tab text
|
||||
upper_line = ColourNameToRGB ("lightgray"), -- line above tab text
|
||||
lower_line = ColourNameToRGB ("lightgray"), -- line below tab text
|
||||
vertical_line = ColourNameToRGB ("lightgray"), -- line between tabs
|
||||
}, -- end of colours
|
||||
|
||||
-- miniwindow size
|
||||
window = {
|
||||
width = 300,
|
||||
height = 200,
|
||||
}, -- end of window info
|
||||
|
||||
-- gap between text in tabs
|
||||
tab_filler = 10,
|
||||
|
||||
-- can it be moved?
|
||||
can_move = true,
|
||||
|
||||
-- which tab is active
|
||||
active_tab = 1,
|
||||
|
||||
-- tabs
|
||||
-- table of tabs. For each one supply a table containing a name and a handler,
|
||||
-- eg. { name = "Circle", handler = DrawCircle },
|
||||
|
||||
tabs = { },
|
||||
|
||||
|
||||
} -- end of default_context
|
||||
|
||||
-- -------------------------------------------------------------------------------
|
||||
-- init - initialize this module ready for use (do once)
|
||||
-- -------------------------------------------------------------------------------
|
||||
function init (context)
|
||||
|
||||
-- make copy of colours, sizes etc.
|
||||
assert (type (context) == "table", "No 'context' table supplied to tabbed_window.")
|
||||
|
||||
-- force some context defaults if not supplied
|
||||
for k, v in pairs (default_context) do
|
||||
|
||||
-- some context items are tables so copy the table entries
|
||||
if type (v) == 'table' then
|
||||
if type (context [k]) ~= 'table' then
|
||||
assert (context [k] == nil, "tabbed window context item '" .. k .. "' should be a table or nil")
|
||||
context [k] = { } -- make table if required
|
||||
end -- not having a table there
|
||||
for k1, v1 in pairs (v) do
|
||||
context [k] [k1] = context [k] [k1] or v1
|
||||
end -- for each sub-table item
|
||||
else
|
||||
context [k] = context [k] or v
|
||||
end -- if table or not
|
||||
end -- for
|
||||
|
||||
if next (context.tabs) == nil then
|
||||
ColourNote ("orange", "", "Warning: no tabs define for tabbed window")
|
||||
end -- if
|
||||
|
||||
-- install the window movement handler, get back the window position
|
||||
context.windowinfo = movewindow.install (context.win, miniwin.pos_top_left, 0) -- default to top left
|
||||
|
||||
-- save a bit of typing
|
||||
local windowinfo = context.windowinfo
|
||||
local win = context.win
|
||||
local tabfont = context.tabfont
|
||||
local activefont = context.activefont
|
||||
local titlefont = context.titlefont
|
||||
local window = context.window
|
||||
local colours = context.colours
|
||||
|
||||
-- make window so I can grab the font info
|
||||
WindowCreate (win,
|
||||
windowinfo.window_left,
|
||||
windowinfo.window_top,
|
||||
window.width,
|
||||
window.height,
|
||||
windowinfo.window_mode,
|
||||
windowinfo.window_flags,
|
||||
colours.background)
|
||||
|
||||
WindowFont (win, tabfont.id, tabfont.name, tabfont.size, tabfont.bold, tabfont.italic, false, false, 0, 0)
|
||||
tabfont.height = WindowFontInfo (win, tabfont.id, 1) -- height
|
||||
WindowFont (win, activefont.id, activefont.name, activefont.size, activefont.bold, activefont.italic, false, false, 0, 0)
|
||||
activefont.height = WindowFontInfo (win, activefont.id, 1) -- height
|
||||
WindowFont (win, titlefont.id, titlefont.name, titlefont.size, titlefont.bold, titlefont.italic, false, false, 0, 0)
|
||||
titlefont.height = WindowFontInfo (win, titlefont.id, 1) -- height
|
||||
|
||||
context.client_bottom = context.window.height - context.tabfont.height - 8
|
||||
|
||||
end -- init
|
||||
|
||||
function save_state (context)
|
||||
-- save window current location for next time
|
||||
movewindow.save_state (context.win)
|
||||
end -- save_state
|
||||
|
||||
-- -------------------------------------------------------------------------------
|
||||
-- draw_window - draw the tabbed window
|
||||
-- -------------------------------------------------------------------------------
|
||||
function draw_window (context, whichTab)
|
||||
|
||||
context.active_tab = whichTab
|
||||
|
||||
-- save a bit of typing
|
||||
local windowinfo = context.windowinfo
|
||||
local win = context.win
|
||||
local tabfont = context.tabfont
|
||||
local activefont = context.activefont
|
||||
local titlefont = context.titlefont
|
||||
local window = context.window
|
||||
local colours = context.colours
|
||||
local tabs = context.tabs
|
||||
local client_bottom = context.client_bottom
|
||||
local tab_filler = context.tab_filler
|
||||
|
||||
-- clear window
|
||||
WindowRectOp (win, miniwin.rect_fill, 0, 0, 0, 0, colours.background)
|
||||
WindowDeleteAllHotspots (win)
|
||||
|
||||
-- draw drag bar rectangle
|
||||
WindowRectOp (win, miniwin.rect_fill, 1, 1, 0, titlefont.height + 2, colours.title_bar)
|
||||
|
||||
-- add the drag handler so they can move the window around
|
||||
if context.can_move then
|
||||
movewindow.add_drag_handler (win, 0, 0, 0, titlefont.height)
|
||||
end -- if can move the window
|
||||
|
||||
local thisTab = tabs [whichTab]
|
||||
|
||||
if not thisTab then
|
||||
ColourNote ("orange", "", "Tab " .. whichTab .. " does not exist")
|
||||
return
|
||||
end -- no such tab
|
||||
|
||||
-- find title width so we can center it
|
||||
local title_width = WindowTextWidth (win, titlefont.id, thisTab.name, titlefont.unicode)
|
||||
|
||||
-- draw title
|
||||
WindowText(win, titlefont.id, thisTab.name, (window.width - title_width )/ 2 + 1, 1, 0, 0, colours.title, titlefont.unicode)
|
||||
|
||||
-- frame window
|
||||
WindowRectOp (win, miniwin.rect_frame, 0, 0, 0, 0, colours.frame)
|
||||
|
||||
-- draw tabs
|
||||
|
||||
local left = 1
|
||||
|
||||
-- we have to make a function to handle each tabbed window, so its
|
||||
-- name must include the window ID
|
||||
local mouse_down_function_name = "tabbed_window_mouse_down_handler_" .. win
|
||||
|
||||
-- the function will have the context as a closure
|
||||
getfenv () [mouse_down_function_name] = function (flags, hotspot_id)
|
||||
local whichTab = string.match (hotspot_id, "^hs(%d)$")
|
||||
if not whichTab then -- tab unknown for some reason
|
||||
ColourNote ("orange", "", "Mousedown tab unknown " .. hotspot_id)
|
||||
return
|
||||
end -- if
|
||||
|
||||
draw_window (context, tonumber (whichTab))
|
||||
|
||||
end -- mouse_down_function_name
|
||||
|
||||
for k, v in ipairs (tabs) do
|
||||
local tab_width
|
||||
|
||||
if k == whichTab then
|
||||
tab_width = WindowTextWidth (win, activefont.id, v.name, activefont.unicode)
|
||||
else
|
||||
tab_width = WindowTextWidth (win, tabfont.id, v.name, tabfont.unicode)
|
||||
end -- if
|
||||
|
||||
-- tab background
|
||||
WindowRectOp (win, miniwin.rect_fill, left, client_bottom, left + tab_width + tab_filler, window.height - 1, colours.tab)
|
||||
|
||||
-- tab text
|
||||
if k == whichTab then
|
||||
WindowText(win, activefont.id, v.name, left + tab_filler / 2, client_bottom + 4, 0, 0, colours.active_tab_text, activefont.unicode)
|
||||
else
|
||||
WindowText(win, tabfont.id, v.name, left + tab_filler / 2, client_bottom + 4, 0, 0, colours.tab_text, tabfont.unicode)
|
||||
end -- if
|
||||
|
||||
-- draw upper line if not active tab
|
||||
if k ~= whichTab then
|
||||
WindowLine(win, left, client_bottom + 2, left + tab_width + tab_filler, client_bottom + 2,
|
||||
colours.upper_line, miniwin.pen_solid, 2)
|
||||
end -- if not active
|
||||
|
||||
-- draw lower line
|
||||
WindowLine(win, left, window.height - 1, left + tab_width + tab_filler, window.height - 1,
|
||||
colours.lower_line, miniwin.pen_solid, 1)
|
||||
|
||||
-- draw vertical lines
|
||||
WindowLine(win, left, client_bottom + 2, left, window.height - 1,
|
||||
colours.vertical_line, miniwin.pen_solid, 1)
|
||||
WindowLine(win, left + tab_width + tab_filler, client_bottom + 2, left + tab_width + tab_filler, window.height - 1,
|
||||
colours.vertical_line, miniwin.pen_solid, 1)
|
||||
|
||||
-- now add a hotspot for this tab
|
||||
WindowAddHotspot(win, "hs" .. k,
|
||||
left, client_bottom, left + tab_width + tab_filler, window.height - 1, -- rectangle
|
||||
"", -- mouseover
|
||||
"", -- cancelmouseover
|
||||
"tabbed_window." .. mouse_down_function_name,
|
||||
"", -- cancelmousedown
|
||||
"", -- mouseup
|
||||
"Show " .. v.name .. " tab", -- tooltip text
|
||||
miniwin.cursor_hand, 0) -- hand cursor
|
||||
|
||||
left = left + tab_width + tab_filler
|
||||
|
||||
end -- for each tab
|
||||
|
||||
-- call handler to draw rest of window
|
||||
local handler = thisTab.handler
|
||||
if handler then
|
||||
handler (win, 1, titlefont.height + 2, window.width - 1, client_bottom, context)
|
||||
else
|
||||
ColourNote ("orange", "", "No tab handler for " .. thisTab.name)
|
||||
end -- if
|
||||
|
||||
WindowShow (win, true)
|
||||
end -- draw_window
|
||||
|
||||
-- -------------------------------------------------------------------------------
|
||||
-- hide_window - hide the tabbed window
|
||||
-- -------------------------------------------------------------------------------
|
||||
function hide_window (context)
|
||||
WindowShow (context.win, false)
|
||||
end -- hide_window
|
||||
Reference in New Issue
Block a user