diff --git a/data/core/statusview.lua b/data/core/statusview.lua index 02b089bb..395dbe0a 100644 --- a/data/core/statusview.lua +++ b/data/core/statusview.lua @@ -9,33 +9,28 @@ local LogView = require "core.logview" local View = require "core.view" local Object = require "core.object" + ---@alias StatusView.styledtext table ----@alias StatusView.itemscb fun():StatusView.styledtext,StatusView.styledtext ----@alias StatusView.clickcb fun(button: string, x: number, y: number) ----@alias StatusView.predicate fun():boolean ---A status bar implementation for lite, check core.status_view. ---@class StatusView : View ----@field private items StatusView.item[] ----@field private hovered_item StatusView.item +---@field private items StatusView.Item[] +---@field private active_items StatusView.Item[] +---@field private hovered_item StatusView.Item ---@field private message_timeout number ---@field private message StatusView.styledtext ---@field private tooltip_mode boolean ---@field private tooltip StatusView.styledtext +---@field private left_width number +---@field private right_width number +---@field private r_left_width number +---@field private r_right_width number +---@field private left_xoffset number +---@field private right_xoffset number +---@field private dragged_panel '"left"' | '"right"' +---@field private hide_messages boolean local StatusView = View:extend() ----@class StatusView.item ----@field predicate StatusView.predicate ----@field items StatusView.itemscb ----@field onclick StatusView.clickcb ----@field tooltip string | nil ----@field lx number ----@field lw number ----@field rx number ----@field rw number ----@field active boolean -StatusView.item = {} - ---Space separator ---@type string StatusView.separator = " " @@ -44,6 +39,107 @@ StatusView.separator = " " ---@type string StatusView.separator2 = " | " +---@alias StatusView.Item.separator +---|>'StatusView.separator' # Space separator +---| 'StatusView.separator2' # Pipe separator + +---@alias StatusView.Item.predicate fun():boolean +---@alias StatusView.Item.onclick fun(button: string, x: number, y: number) +---@alias StatusView.Item.getitem fun():StatusView.styledtext,StatusView.styledtext +---@alias StatusView.Item.ondraw fun(x, y, h, calc_only: boolean):number + +---@class StatusView.Item : Object +---@field name string +---@field predicate StatusView.Item.predicate +---@field alignment StatusView.Item.alignment +---@field tooltip string | nil +---@field command string | nil @Command to perform when the item is clicked. +---@field on_click StatusView.Item.onclick | nil @Function called when item is clicked and no command is set. +---@field on_draw StatusView.Item.ondraw | nil @Custom drawing that when passed calc true should return the needed width for drawing and when false should draw. +---@field background_color renderer.color | nil +---@field visible boolean +---@field separator StatusView.Item.separator +---@field private active boolean +---@field private x number +---@field private w number +---@field private deprecated boolean +---@field private cached_item StatusView.styledtext +StatusView.Item = Object:extend() + +---Flag to tell the item should me aligned on left side of status bar. +---@type number +StatusView.Item.LEFT = 1 + +---Flag to tell the item should me aligned on right side of status bar. +---@type number +StatusView.Item.RIGHT = 2 + +---@alias StatusView.Item.alignment +---|>'StatusView.Item.LEFT' +---| 'StatusView.Item.RIGHT' + +---Constructor +---@param predicate string | table | StatusView.Item.predicate +---@param name string +---@param alignment StatusView.Item.alignment +---@param command string | StatusView.Item.onclick +---@param tooltip? string | nil +function StatusView.Item:new(predicate, name, alignment, command, tooltip) + self:set_predicate(predicate) + self.name = name + self.alignment = alignment or StatusView.Item.LEFT + self.command = type(command) == "string" and command or nil + self.tooltip = tooltip or "" + self.on_click = type(command) == "function" and command or nil + self.on_draw = nil + self.background_color = nil + self.visible = true + self.active = false + self.x = 0 + self.w = 0 + self.separator = StatusView.separator +end + +---Called by the status bar each time that the item needs to be rendered, +---if on_draw() is set this function is obviated. +---@return StatusView.styledtext +function StatusView.Item:get_item() return {} end + +---Do not show the item on the status bar. +function StatusView.Item:hide() self.visible = false end + +---Show the item on the status bar. +function StatusView.Item:show() self.visible = true end + +---Function assiged by default when user provides a nil predicate. +local function predicate_always_true() return true end + +---A condition to evaluate if the item should be displayed. If a string +---is given it is treated as a require import that should return a valid object +---which is checked against the current active view, the sames applies if a +---table is given. A function that returns a boolean can be used instead to +---perform a custom evaluation, setting to nil means always evaluates to true. +---@param predicate string | table | StatusView.Item.predicate +function StatusView.Item:set_predicate(predicate) + predicate = predicate or predicate_always_true + if type(predicate) == "string" then + predicate = require(predicate) + end + if type(predicate) == "table" then + local class = predicate + predicate = function() return core.active_view:is(class) end + end + self.predicate = predicate +end + + +---Predicated used on the default docview widgets. +---@return boolean +local function predicate_docview() + return core.active_view:is(DocView) + and not core.active_view:is(CommandView) +end + ---Constructor function StatusView:new() @@ -53,57 +149,228 @@ function StatusView:new() self.tooltip_mode = false self.tooltip = {} self.items = {} + self.active_items = {} self.hovered_item = {} self.pointer = {x = 0, y = 0} + self.left_width = 0 + self.right_width = 0 + self.r_left_width = 0 + self.r_right_width = 0 + self.left_xoffset = 0 + self.right_xoffset = 0 + self.dragged_panel = "" + self.hide_messages = false + + self:register_docview_items() + self:register_command_items() +end + +---The predefined status bar items displayed when a document view is active. +function StatusView:register_docview_items() + if self:get_item("doc:file") then return end self:add_item( + predicate_docview, + "doc:file", + StatusView.Item.LEFT, function() - return core.active_view:is(DocView) and - not core.active_view:is(CommandView) - end, - self.get_doc_items + local dv = core.active_view + return { + dv.doc:is_dirty() and style.accent or style.text, style.icon_font, "f", + style.dim, style.font, self.separator2, style.text, + dv.doc.filename and style.text or style.dim, dv.doc:get_name() + } + end ) - self:add_item("core.commandview", self.get_command_items) + self:add_item( + predicate_docview, + "doc:position", + StatusView.Item.LEFT, + function() + local dv = core.active_view + local line, col = dv.doc:get_selection() + return { + line, + ":", + col > config.line_limit and style.accent or style.text, col, + style.text, + self.separator, + string.format("%.f%%", line / #dv.doc.lines * 100) + } + end, + "doc:go-to-line" + ).tooltip = "line : column" + + self:add_item( + predicate_docview, + "doc:indentation", + StatusView.Item.RIGHT, + function() + local dv = core.active_view + local indent_type, indent_size, indent_confirmed = dv.doc:get_indent_info() + local indent_label = (indent_type == "hard") and "tabs: " or "spaces: " + return { + style.text, indent_label, indent_size + } + end, + function(button, x, y) + if button == "left" then + command.perform "indent:set-file-indent-size" + elseif button == "right" then + command.perform "indent:set-file-indent-type" + end + end + ).separator = self.separator2 + + self:add_item( + predicate_docview, + "doc:lines", + StatusView.Item.RIGHT, + function() + local dv = core.active_view + return { + style.text, + style.icon_font, "g", + style.font, style.dim, self.separator2, style.text, + #dv.doc.lines, " lines", + } + end + ).separator = self.separator2 + + self:add_item( + predicate_docview, + "doc:line-ending", + StatusView.Item.RIGHT, + function() + local dv = core.active_view + return { + dv.doc.crlf and "CRLF" or "LF" + } + end, + "doc:toggle-line-ending" + ) +end + + +---The predefined status bar items displayed when a command view is active. +function StatusView:register_command_items() + if self:get_item("command:files") then return end + + self:add_item( + "core.commandview", + "command:files", + StatusView.Item.RIGHT, + function() + return { + style.icon_font, "g", + style.font, style.dim, self.separator2, + #core.docs, style.text, " / ", + #core.project_files, " files" + } + end + ) end ---Adds an item to be rendered in the status bar. ----@param predicate string | table | StatusView.predicate : ----A coindition to evaluate if the item should be displayed. If a string ----is given it is treated as a file that returns a valid object which is ----checked against the current active view, the sames applies if a table is ----given. A function can be used instead to perform a custom evaluation. ----@param itemscb StatusView.itemscb : ----This function should return two tables of StatusView.styledtext elements ----for both left and right, empty tables are allowed. +---@param predicate string | table | StatusView.Item.predicate : +---A condition to evaluate if the item should be displayed. If a string +---is given it is treated as a require import that should return a valid object +---which is checked against the current active view, the sames applies if a +---table is given. A function that returns a boolean can be used instead to +---perform a custom evaluation, setting to nil means always evaluates to true. +---@param name string A unique name to identify the item on the status bar. +---@param alignment StatusView.Item.alignment +---@param getitem StatusView.Item.getitem : +---A function that should return a StatusView.styledtext element, +---returning empty table is allowed. +---@param command? string | StatusView.Item.onclick : +---The name of a valid registered command or a callback function to execute +---when the item is clicked. ---@param pos? integer : ---The position in which to insert the given item on the internal table, ---a value of -1 inserts the item at the end which is the default. A value ---of 1 will insert the item at the beggining. ----@param onclick? StatusView.clickcb Executed when user clicks the item ---@param tooltip? string Displayed when mouse hovers the item -function StatusView:add_item(predicate, itemscb, pos, onclick, tooltip) - predicate = predicate or always_true - if type(predicate) == "string" then - predicate = require(predicate) - end - if type(predicate) == "table" then - local class = predicate - predicate = function() return core.active_view:is(class) end - end - ---@type StatusView.item - local item = { - predicate = predicate, - items = itemscb, - onclick = onclick, - tooltip = tooltip - } - pos = type(pos) == "nil" and -1 or math.abs(tonumber(pos)) +---@return StatusView.Item +function StatusView:add_item(predicate, name, alignment, getitem, command, pos, tooltip) + assert(self:get_item(name) == nil, "status item already exists: " .. name) + ---@type StatusView.Item + local item = StatusView.Item(predicate, name, alignment, command, tooltip) + item.get_item = getitem + pos = type(pos) == "nil" and -1 or tonumber(pos) if pos == -1 then table.insert(self.items, item) else - table.insert(self.items, pos, item) + table.insert(self.items, math.abs(pos), item) + end + return item +end + + +---Get an item associated object or nil if not found. +---@param name string +---@return StatusView.Item | nil +function StatusView:get_item(name) + for _, item in ipairs(self.items) do + if item.name == name then return item end + end + return nil +end + + +---Get a list of items. +---@param alignment? StatusView.Item.alignment +---@return StatusView.Item[] +function StatusView:get_items_list(alignment) + if alignment then + local items = {} + for _, item in ipairs(self.items) do + if item.alignment == alignment then + table.insert(items, item) + end + end + return items + end + return self.items +end + + +---Hides the given items from the status view or all if no names given. +---@param names table | string | nil +function StatusView:hide_items(names) + if type(names) == "string" then + names = {names} + end + if not names then + for _, item in ipairs(self.items) do + item:hide() + end + return + end + for _, name in ipairs(names) do + local item = self:get_item(name) + if item then item:hide() end + end +end + + +---Shows the given items from the status view or all if no names given. +---@param names table | string | nil +function StatusView:show_items(names) + if type(names) == "string" then + names = {names} + end + if not names then + for _, item in ipairs(self.items) do + item:show() + end + return + end + for _, name in ipairs(names) do + local item = self:get_item(name) + if item then item:show() end end end @@ -113,6 +380,7 @@ end ---@param icon_color renderer.color ---@param text string function StatusView:show_message(icon, icon_color, text) + if self.hide_messages then return end self.message = { icon_color, style.icon_font, icon, style.dim, style.font, StatusView.separator2, style.text, text @@ -121,6 +389,13 @@ function StatusView:show_message(icon, icon_color, text) end +---Enable or disable system wide messages on the status bar. +---@param enable boolean +function StatusView:display_messages(enable) + self.hide_messages = not enable +end + + ---Activates tooltip mode displaying only the given ---text until StatusView:remove_tooltip() is called. ---@param text string | StatusView.styledtext @@ -174,8 +449,9 @@ end ---@param items StatusView.styledtext ---@param right_align boolean ---@param yoffset number -function StatusView:draw_items(items, right_align, yoffset) +function StatusView:draw_items(items, right_align, xoffset, yoffset) local x, y = self:get_content_offset() + x = x + (xoffset or 0) y = y + (yoffset or 0) if right_align then local w = draw_items(self, items, 0, 0, text_width) @@ -189,7 +465,7 @@ end ---Draw the tooltip of a given status bar item. ----@param item StatusView.item +---@param item StatusView.Item function StatusView:draw_item_tooltip(item) core.root_view:defer_draw(function() local text = item.tooltip @@ -203,7 +479,7 @@ function StatusView:draw_item_tooltip(item) end renderer.draw_rect( - x, + x + style.padding.x, self.position.y - h - (style.padding.y * 2), w + (style.padding.x * 2), h + (style.padding.y * 2), @@ -213,7 +489,7 @@ function StatusView:draw_item_tooltip(item) renderer.draw_text( style.font, text, - x + style.padding.x, + x + (style.padding.x * 2), self.position.y - h - style.padding.y, style.text ) @@ -221,141 +497,6 @@ function StatusView:draw_item_tooltip(item) end ----The predefined status bar items displayed when a document view is active. ----@return table left ----@return table right -function StatusView:get_doc_items() - local dv = core.active_view - local line, col = dv.doc:get_selection() - local dirty = dv.doc:is_dirty() - local indent_type, indent_size, indent_confirmed = dv.doc:get_indent_info() - local indent_label = (indent_type == "hard") and "tabs: " or "spaces: " - local indent_size_str = tostring(indent_size) .. (indent_confirmed and "" or "*") or "unknown" - - return { - dirty and style.accent or style.text, style.icon_font, "f", - style.dim, style.font, self.separator2, style.text, - dv.doc.filename and style.text or style.dim, dv.doc:get_name(), - style.text, - self.separator, - "line: ", line, - self.separator, - col > config.line_limit and style.accent or style.text, "col: ", col, - style.text, - self.separator, - string.format("%.f%%", line / #dv.doc.lines * 100), - }, { - style.text, indent_label, indent_size, - style.dim, self.separator2, style.text, - style.icon_font, "g", - style.font, style.dim, self.separator2, style.text, - #dv.doc.lines, " lines", - self.separator, - dv.doc.crlf and "CRLF" or "LF" - } -end - - ----The predefined status bar items displayed when a command view is active. ----@return table left ----@return table right -function StatusView:get_command_items() - return {}, { - style.icon_font, "g", - style.font, style.dim, self.separator2, - #core.docs, style.text, " / ", - #core.project_files, " files" - } -end - - ----Helper function to copy a styled text table into another. ----@param t1 StatusView.styledtext ----@param t2 StatusView.styledtext -local function table_add(t1, t2) - for i, value in ipairs(t2) do - table.insert(t1, value) - end -end - - ----Get the styled text that will be displayed on the left side or ----right side of the status bar checking their predicates and performing ----positioning calculations for proper functioning of tooltips and clicks. ----@return StatusView.styledtext left ----@return StatusView.styledtext right -function StatusView:get_items_from_list() - local left, right = {}, {} - - local x = self:get_content_offset() - - local rx = x + self.size.x - local lx = x + style.padding.x - local rw, lw = 0, 0 - - ---@class items - ---@field item StatusView.item - local items = {} - - -- calculate left and right width - for _, item in ipairs(self.items) do - if item.predicate(self) then - item.active = true - - local litems, ritems = item.items(self) - - if #litems > 0 then - item.lw = draw_items(self, litems, 0, 0, text_width) - item.lx = lx - lw = lw + item.lw - lx = lx + item.lw - end - - if #ritems > 0 then - item.rw = draw_items(self, ritems, 0, 0, text_width) - item.rx = rx - rw = rw + item.rw - rx = rx + item.rw - end - - if #litems > 0 or #ritems > 0 then - table.insert(items, { - item = item, - left = litems, - right = ritems - }) - end - else - item.active = false - end - end - - -- load deprecated items for compatibility - local dleft, dright = self:get_items(true) - if #dright > 0 then - rw = rw + draw_items(self, dright, 0, 0, text_width) - end - - rw = rw < (self.size.x / 2) and rw or self.size.x / 2 - - for _, item in ipairs(items) do - if #item.left > 0 then - table_add(left, item.left) - end - if #item.right > 0 then - -- re-calculate x position now that we have the total width - item.item.rx = item.item.rx - rw - style.padding.x - table_add(right, item.right) - end - end - - table_add(left, dleft) - table_add(right, dright) - - return left, right -end - - ---Older method of retrieving the status bar items and which is now ---deprecated in favour of core.status_view:add_item(). ---@deprecated @@ -370,7 +511,210 @@ function StatusView:get_items(nowarn) ) self.get_items_warn = true end - return {}, {} + return {"{:dummy:}"}, {"{:dummy:}"} +end + + +---Helper function to copy a styled text table into another. +---@param t1 StatusView.styledtext +---@param t2 StatusView.styledtext +local function table_add(t1, t2) + for i, value in ipairs(t2) do + table.insert(t1, value) + end +end + + +---Helper function to merge deprecated items to a temp items table. +---@param destination table +---@param items StatusView.styledtext +---@param alignment StatusView.Item.alignment +local function merge_deprecated_items(destination, items, alignment) + local start = true + local items_start, items_end = {}, {} + for i, value in ipairs(items) do + if value ~= "{:dummy:}" then + if start then + table.insert(items_start, i, value) + else + table.insert(items_end, value) + end + else + start = false + end + end + + local position = alignment == StatusView.Item.LEFT and "left" or "right" + + local item_start = StatusView.Item( + predicate_always_true, + "deprecated:"..position.."-start", + alignment + ) + item_start.get_item = items_start + + local item_end = StatusView.Item( + predicate_always_true, + "deprecated:"..position.."-end", + alignment + ) + item_end.get_item = items_end + + table.insert(destination, 1, item_start) + table.insert(destination, item_end) +end + + +---@param self StatusView +---@param styled_text StatusView.styledtext +---@param separator string +local function add_spacing(self, styled_text, separator) + if + Object.is(styled_text[1], renderer.font) + or + ( + styled_text[2] ~= self.separator + or + styled_text[2] ~= self.separator2 + ) + then + if separator == self.separator2 then + table.insert(styled_text, 1, style.dim) + else + table.insert(styled_text, 1, style.text) + end + table.insert(styled_text, 2, separator) + end +end + + +---@param self StatusView +---@param styled_text StatusView.styledtext +local function remove_spacing(self, styled_text) + if + not Object.is(styled_text[1], renderer.font) + and + type(styled_text[1]) == "table" + and + ( + styled_text[2] == self.separator + or + styled_text[2] == self.separator2 + ) + then + table.remove(styled_text, 1) + table.remove(styled_text, 1) + end + + if + not Object.is(styled_text[#styled_text-1], renderer.font) + and + type(styled_text[#styled_text-1]) == "table" + and + ( + styled_text[#styled_text] == self.separator + or + styled_text[#styled_text] == self.separator2 + ) + then + table.remove(styled_text, #styled_text) + table.remove(styled_text, #styled_text) + end +end + + +---Get the styled text that will be displayed on the left side or +---right side of the status bar checking their predicates and performing +---positioning calculations for proper functioning of tooltips and clicks. +---@return StatusView.styledtext left +---@return StatusView.styledtext right +function StatusView:update_active_items() + local left, right = {}, {} + + local x = self:get_content_offset() + + local rx = x + self.size.x + local lx = x + local rw, lw = 0, 0 + + self.active_items = {} + + ---@type StatusView.Item[] + local combined_items = {} + table_add(combined_items, self.items) + + -- load deprecated items for compatibility + local dleft, dright = self:get_items(true) + merge_deprecated_items(combined_items, dleft, StatusView.Item.LEFT) + merge_deprecated_items(combined_items, dright, StatusView.Item.RIGHT) + + local lfirst, rfirst = true, true + + -- calculate left and right width + for _, item in ipairs(combined_items) do + item.cached_item = {} + if item.visible and item.predicate(self) then + local styled_text = type(item.get_item) == "function" + and item.get_item(self) or item.get_item + + if #styled_text > 0 then + remove_spacing(self, styled_text) + end + + if #styled_text > 0 or item.on_draw then + item.active = true + if item.alignment == StatusView.Item.LEFT then + if not lfirst then + add_spacing(self, styled_text, item.separator, true) + else + lfirst = false + end + item.w = item.on_draw and + item.on_draw(lx, self.position.y, self.size.y, true) + or + draw_items(self, styled_text, 0, 0, text_width) + item.x = lx + lw = lw + item.w + lx = lx + item.w + else + if not rfirst then + add_spacing(self, styled_text, item.separator, true) + else + rfirst = false + end + item.w = item.on_draw and + item.on_draw(rx, self.position.y, self.size.y, true) + or + draw_items(self, styled_text, 0, 0, text_width) + item.x = rx + rw = rw + item.w + rx = rx + item.w + end + item.cached_item = styled_text + table.insert(self.active_items, item) + else + item.active = false + end + else + item.active = false + end + end + + self.r_left_width, self.r_right_width = lw, rw + + if lw + rw + (style.padding.x * 2) > self.size.x then + lw = self.size.x / 2 - (style.padding.x * 2) + rw = self.size.x / 2 - (style.padding.x * 2) + end + + self.left_width, self.right_width = lw, rw + + for _, item in ipairs(self.active_items) do + if item.alignment == StatusView.Item.RIGHT then + -- re-calculate x position now that we have the total width + item.x = item.x - rw - (style.padding.x * 2) + end + end end @@ -380,6 +724,7 @@ function StatusView:on_mouse_pressed() and not core.active_view:is(LogView) then command.perform "core:open-log" end + self.mouse_pressed = true return true end @@ -387,15 +732,18 @@ end function StatusView:on_mouse_moved(x, y, dx, dy) StatusView.super.on_mouse_moved(self, x, y, dx, dy) - if y < self.position.y then self.hovered_item = {} return end + if y < self.position.y or system.get_time() <= self.message_timeout then + self.hovered_item = {} return + end for _, item in ipairs(self.items) do - if item.onclick and item.active then - if - (item.lx and x > item.lx and (item.lx + item.lw) > x) - or - (item.rx and x > item.rx and (item.rx + item.rw) > x) - then + if + item.visible and item.active + and + (item.command or item.on_click or item.tooltip ~= "") + then + local item_x = item.x + style.padding.x + if x > item_x and (item_x + item.w) > x then self.pointer.x = x self.pointer.y = y if self.hovered_item ~= item then @@ -412,15 +760,18 @@ end function StatusView:on_mouse_released(button, x, y) StatusView.super.on_mouse_released(self, button, x, y) - if y < self.position.y or not self.hovered_item.onclick then return end + self.mouse_pressed = false + + if y < self.position.y or not self.hovered_item.active then return end local item = self.hovered_item - if - (item.lx and x > item.lx and (item.lx + item.lw) > x) - or - (item.rx and x > item.rx and (item.rx + item.rw) > x) - then - self.hovered_item.onclick(button, x, y) + local item_x = item.x + style.padding.x + if x > item_x and (item_x + item.w) > x then + if item.command then + command.perform(item.command) + elseif item.on_click then + self.hovered_item.on_click(button, x, y) + end end end @@ -435,24 +786,74 @@ function StatusView:update() end StatusView.super.update(self) + + self:update_active_items() end function StatusView:draw() self:draw_background(style.background2) - if self.message then - self:draw_items(self.message, false, self.size.y) - end - - if self.tooltip_mode then + if self.message and system.get_time() <= self.message_timeout then + self:draw_items(self.message, false, 0, self.size.y) + elseif self.tooltip_mode then self:draw_items(self.tooltip) else - local left, right = self:get_items_from_list() - self:draw_items(left) - self:draw_items(right, true) - if self.hovered_item.tooltip then - self:draw_item_tooltip(self.hovered_item) + if #self.active_items > 0 then + --- draw left pane + core.push_clip_rect( + 0, self.position.y, + self.left_width + style.padding.x, self.size.y + ) + for _, item in ipairs(self.active_items) do + if item.alignment == StatusView.Item.LEFT then + if type(item.background_color) == "table" then + renderer.draw_rect( + item.x + style.padding.x, self.position.y, + item.w, self.size.y, item.background_color + ) + end + if item.on_draw then + core.push_clip_rect(item.x + style.padding.x, self.position.y, item.w, self.size.y) + item.on_draw(item.x + style.padding.x, self.position.y, self.size.y) + core.pop_clip_rect() + else + self:draw_items(item.cached_item, false, item.x) + end + end + end + core.pop_clip_rect() + + --- draw right pane + core.push_clip_rect( + self.size.x - (self.right_width + style.padding.x), self.position.y, + self.right_width + style.padding.x, self.size.y + ) + local rx = 0 + for _, item in ipairs(self.active_items) do + if item.alignment == StatusView.Item.RIGHT then + if type(item.background_color) == "table" then + renderer.draw_rect( + item.x + style.padding.x, self.position.y, + item.w, self.size.y, item.background_color + ) + end + if item.on_draw then + core.push_clip_rect(item.x + style.padding.x, self.position.y, item.w, self.size.y) + item.on_draw(item.x + style.padding.x, self.position.y, self.size.y) + core.pop_clip_rect() + else + self:draw_items(item.cached_item, false, item.x) + end + rx = rx + item.w + end + end + core.pop_clip_rect() + + -- draw tooltip + if self.hovered_item.tooltip ~= "" and self.hovered_item.active then + self:draw_item_tooltip(self.hovered_item) + end end end end