diff --git a/data/core/docview.lua b/data/core/docview.lua index 7697dbbe..8f8c77ff 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -98,18 +98,15 @@ end function DocView:get_scrollable_size() - local xmargin = 3 * self:get_font():get_width(' ') -- from DocView:scroll_to_make_visible - local long_line = 1 - for l,_ in pairs(self.doc.long_lines.line_numbers) do -- get any of the longest lines - long_line = l - break - end - local size_v = self:get_line_height() * (#self.doc.lines - 1) + self.size.y - local size_h = self:get_col_x_offset(long_line, self.doc.long_lines.length) - + self.size.x - (self.size.x - self:get_gutter_width()) + xmargin - return size_v, size_h + return self:get_line_height() * (#self.doc.lines - 1) + self.size.y end +function DocView:get_h_scrollable_size() + local xmargin = 3 * self:get_font():get_width(' ') -- from DocView:scroll_to_make_visible + local long_line = next(self.doc.long_lines.line_numbers) or 1 + return self:get_col_x_offset(long_line, self.doc.long_lines.length) + + self:get_gutter_width() + xmargin +end function DocView:get_font() return style[self.font] @@ -281,8 +278,8 @@ end function DocView:on_mouse_moved(x, y, ...) DocView.super.on_mouse_moved(self, x, y, ...) - local overlap_v, overlap_h = self:scrollbar_overlaps_point(x, y) - if overlap_v or overlap_h or self.dragging_v_scrollbar or self.dragging_h_scrollbar then + if self:scrollbar_overlaps_point(x, y) or self.dragging_scrollbar + or self:h_scrollbar_overlaps_point(x, y) or self.dragging_h_scrollbar then self.cursor = "arrow" else self.cursor = "ibeam" @@ -453,6 +450,7 @@ function DocView:draw() core.pop_clip_rect() self:draw_scrollbar() + self:draw_h_scrollbar() end diff --git a/data/core/view.lua b/data/core/view.lua index 292284e1..52a5ddfd 100644 --- a/data/core/view.lua +++ b/data/core/view.lua @@ -51,77 +51,84 @@ function View:get_name() return "---" end --- Returns `y, x` for compatibility + function View:get_scrollable_size() - return math.huge, 0 -- TODO: invert y and x + return math.huge end -function View:get_scrollbar_rect() -- TODO: make plugins use `View:get_scrollbars_rect` - local rect = self:get_get_scrollbars_rect() - return rect.x, rect.y, rect.w, rect.h +function View:get_h_scrollable_size() + return 0 end -function View:get_scrollbars_rect() - local v_sizes = { x = 0, y = 0, w = 0, h = 0 } - local h_sizes = { x = 0, y = 0, w = 0, h = 0 } - local v_sz, h_sz = self:get_scrollable_size() - h_sz = h_sz or 0 -- FIXME: not every subclass returns the second value - if v_sz > self.size.y and v_sz ~= math.huge then - local h = math.max(20, self.size.y * self.size.y / v_sz) - v_sizes.x = self.position.x + self.size.x - style.scrollbar_size - v_sizes.y = self.position.y + self.scroll.y * (self.size.y - h) / (v_sz - self.size.y) - v_sizes.w = style.scrollbar_size - v_sizes.h = h +function View:get_scrollbar_rect() + local sz = self:get_scrollable_size() + if sz <= self.size.y or sz == math.huge then + return 0, 0, 0, 0 end + local h = math.max(20, self.size.y * self.size.y / sz) + return + self.position.x + self.size.x - style.scrollbar_size, + self.position.y + self.scroll.y * (self.size.y - h) / (sz - self.size.y), + style.scrollbar_size, + h +end - if h_sz > self.size.x and h_sz ~= math.huge then - local w = math.max(20, self.size.x * self.size.x / h_sz) - h_sizes.x = self.position.x + self.scroll.x * (self.size.x - w) / (h_sz - self.size.x) - h_sizes.y = self.position.y + self.size.y - style.scrollbar_size - h_sizes.w = w - h_sizes.h = style.scrollbar_size + +function View:get_h_scrollbar_rect() + local sz = self:get_h_scrollable_size() + if sz <= self.size.x or sz == math.huge then + return 0, 0, 0, 0 end - - return v_sizes, h_sizes + local w = math.max(20, self.size.x * self.size.x / sz) + return + self.position.x + self.scroll.x * (self.size.x - w) / (sz - self.size.x), + self.position.y + self.size.y - style.scrollbar_size, + w, + style.scrollbar_size end function View:scrollbar_overlaps_point(x, y) - local v, h = self:get_scrollbars_rect() - local v_overlap = x >= v.x - v.w * 3 and x < v.x + v.w and y >= v.y and y < v.y + v.h - local h_overlap = x >= h.x and x < h.x + h.w and y >= h.y - h.h * 3 and y <= h.y + h.h - return v_overlap, not v_overlap and h_overlap -- precedence to vertical scrollbar + local sx, sy, sw, sh = self:get_scrollbar_rect() + return x >= sx - sw * 3 and x < sx + sw and y >= sy and y <= sy + sh +end + + +function View:h_scrollbar_overlaps_point(x, y) + local sx, sy, sw, sh = self:get_h_scrollbar_rect() + return x >= sx and x <= sx + sw and y > sy - sh * 3 and y <= sy + sh end function View:on_mouse_pressed(button, x, y, clicks) - self.dragging_v_scrollbar, self.dragging_h_scrollbar = self:scrollbar_overlaps_point(x, y) - self.dragging_scrollbar = self.dragging_v_scrollbar -- TODO: make plugins use `self.dragging_v_scrollbar` - return self.dragging_v_scrollbar or self.dragging_h_scrollbar + if self:scrollbar_overlaps_point(x, y) then + self.dragging_scrollbar = true + return true + elseif self:h_scrollbar_overlaps_point(x, y) then + self.dragging_h_scrollbar = true + return true + end end function View:on_mouse_released(button, x, y) - self.dragging_v_scrollbar = false + self.dragging_scrollbar = false self.dragging_h_scrollbar = false - self.dragging_scrollbar = self.dragging_v_scrollbar -- TODO: make plugins use `self.dragging_v_scrollbar` end function View:on_mouse_moved(x, y, dx, dy) - if self.dragging_v_scrollbar then - local v_sz,_ = self:get_scrollable_size() - local delta = v_sz / self.size.y * dy + if self.dragging_scrollbar then + local delta = self:get_scrollable_size() / self.size.y * dy self.scroll.to.y = self.scroll.to.y + delta elseif self.dragging_h_scrollbar then - local _,h_sz = self:get_scrollable_size() - local delta = h_sz / self.size.x * dx + local delta = self:get_h_scrollable_size() / self.size.x * dx self.scroll.to.x = self.scroll.to.x + delta end - self.hovered_v_scrollbar, self.hovered_h_scrollbar = self:scrollbar_overlaps_point(x, y) - self.hovered_scrollbar = self.hovered_v_scrollbar -- TODO: make plugins use `self.hovered_v_scrollbar` + self.hovered_scrollbar = self:scrollbar_overlaps_point(x, y) + self.hovered_h_scrollbar = self:h_scrollbar_overlaps_point(x, y) end @@ -156,10 +163,8 @@ end function View:clamp_scroll_position() - local scrollsize_y, scrollsize_x = self:get_scrollable_size() - scrollsize_x = scrollsize_x or 0 -- FIXME: not every subclass returns the second value - local max_x = scrollsize_x - self.size.x - local max_y = scrollsize_y - self.size.y + local max_x = self:get_h_scrollable_size() - self.size.x + local max_y = self:get_scrollable_size() - self.size.y self.scroll.to.x = common.clamp(self.scroll.to.x, 0, max_x) self.scroll.to.y = common.clamp(self.scroll.to.y, 0, max_y) end @@ -180,13 +185,19 @@ end function View:draw_scrollbar() - local v, h = self:get_scrollbars_rect() - local v_highlight = self.hovered_v_scrollbar or self.dragging_v_scrollbar - local h_highlight = self.hovered_h_scrollbar or self.dragging_h_scrollbar - local v_color = v_highlight and style.scrollbar2 or style.scrollbar - local h_color = h_highlight and style.scrollbar2 or style.scrollbar - renderer.draw_rect(v.x, v.y, v.w, v.h, v_color) - renderer.draw_rect(h.x, h.y, h.w, h.h, h_color) + local x, y, w, h = self:get_scrollbar_rect() + local highlight = self.hovered_scrollbar or self.dragging_scrollbar + local color = highlight and style.scrollbar2 or style.scrollbar + renderer.draw_rect(x, y, w, h, color) +end + + +function View:draw_h_scrollbar() + local x, y, w, h = self:get_h_scrollbar_rect() + local highlight = self.hovered_h_scrollbar and not self.hovered_scrollbar + or self.dragging_h_scrollbar + local color = highlight and style.scrollbar2 or style.scrollbar + renderer.draw_rect(x, y, w, h, color) end