Use the new region function everywhere
Centralizes window layout calculation and no longer assumes tab bar geometry
This commit is contained in:
parent
b6188bf436
commit
4f12c91fff
5 changed files with 83 additions and 55 deletions
|
|
@ -609,11 +609,11 @@ render(double now) {
|
|||
w->viewport_size_dirty = false;
|
||||
}
|
||||
unsigned int active_window_id = 0;
|
||||
render_os_window(w, now, &active_window_id);
|
||||
Tab *active_tab = w->tabs + w->active_tab;
|
||||
BorderRects *br = &active_tab->border_rects;
|
||||
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, w->viewport_width, w->viewport_height);
|
||||
if (TD.screen && w->num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, w, true);
|
||||
render_os_window(w, now, &active_window_id);
|
||||
swap_window_buffers(w);
|
||||
w->last_active_tab = w->active_tab; w->last_num_tabs = w->num_tabs; w->last_active_window_id = active_window_id;
|
||||
br->is_dirty = false;
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@
|
|||
from itertools import islice
|
||||
|
||||
from .constants import WindowGeometry
|
||||
from .fast_data_types import pt_to_px, viewport_for_window
|
||||
from .fast_data_types import pt_to_px, viewport_for_window, Region
|
||||
|
||||
viewport_width = viewport_height = available_height = 400
|
||||
central = Region((0, 0, 199, 199, 200, 200))
|
||||
cell_width = cell_height = 20
|
||||
|
||||
|
||||
def layout_dimension(length, cell_length, number_of_windows=1, border_length=0, margin_length=0, padding_length=0, left_align=False):
|
||||
def layout_dimension(start_at, length, cell_length, number_of_windows=1, border_length=0, margin_length=0, padding_length=0, left_align=False):
|
||||
number_of_cells = length // cell_length
|
||||
border_length += padding_length
|
||||
space_needed_for_border = number_of_windows * 2 * border_length
|
||||
|
|
@ -24,7 +24,9 @@ def layout_dimension(length, cell_length, number_of_windows=1, border_length=0,
|
|||
extra = length - number_of_cells * cell_length
|
||||
cells_per_window = number_of_cells // number_of_windows
|
||||
extra -= space_needed
|
||||
pos = 0 if left_align else (extra // 2)
|
||||
pos = start_at
|
||||
if not left_align:
|
||||
pos += extra // 2
|
||||
pos += border_length + margin_length
|
||||
inner_length = cells_per_window * cell_length
|
||||
window_length = 2 * (border_length + margin_length) + inner_length
|
||||
|
|
@ -73,30 +75,30 @@ def remove_window(self, windows, window, active_window_idx):
|
|||
|
||||
def xlayout(self, num):
|
||||
return layout_dimension(
|
||||
viewport_width, cell_width, num, self.border_width,
|
||||
central.left, central.width, cell_width, num, self.border_width,
|
||||
margin_length=self.margin_width, padding_length=self.padding_width)
|
||||
|
||||
def ylayout(self, num, left_align=True):
|
||||
return layout_dimension(
|
||||
available_height, cell_height, num, self.border_width, left_align=left_align,
|
||||
central.top, central.height, cell_height, num, self.border_width, left_align=left_align,
|
||||
margin_length=self.margin_width, padding_length=self.padding_width)
|
||||
|
||||
def simple_blank_rects(self, first_window, last_window):
|
||||
br, vh = self.blank_rects, available_height
|
||||
left_blank_rect(first_window, br, vh), top_blank_rect(first_window, br, vh), right_blank_rect(last_window, br, vh)
|
||||
br = self.blank_rects
|
||||
left_blank_rect(first_window, br), top_blank_rect(first_window, br), right_blank_rect(last_window, br)
|
||||
|
||||
def between_blank_rect(self, left_window, right_window):
|
||||
self.blank_rects.append(Rect(left_window.geometry.right, 0, right_window.geometry.left, available_height))
|
||||
self.blank_rects.append(Rect(left_window.geometry.right, central.top, right_window.geometry.left, central.bottom + 1))
|
||||
|
||||
def bottom_blank_rect(self, window):
|
||||
self.blank_rects.append(Rect(window.geometry.left, window.geometry.bottom, window.geometry.right, available_height))
|
||||
self.blank_rects.append(Rect(window.geometry.left, window.geometry.bottom, window.geometry.right, central.bottom + 1))
|
||||
|
||||
def set_active_window(self, windows, active_window_idx):
|
||||
pass
|
||||
|
||||
def __call__(self, windows, active_window_idx):
|
||||
global viewport_width, viewport_height, cell_width, cell_height, available_height
|
||||
viewport_width, viewport_height, available_height, cell_width, cell_height = viewport_for_window(self.os_window_id)
|
||||
global central, cell_width, cell_height
|
||||
central, tab_bar, vw, vh, cell_width, cell_height = viewport_for_window(self.os_window_id)
|
||||
self.do_layout(windows, active_window_idx)
|
||||
|
||||
def do_layout(self, windows, active_window_idx):
|
||||
|
|
@ -108,35 +110,38 @@ def window_geometry(xstart, xnum, ystart, ynum):
|
|||
|
||||
|
||||
def layout_single_window(margin_length, padding_length):
|
||||
xstart, xnum = next(layout_dimension(viewport_width, cell_width, margin_length=margin_length, padding_length=padding_length))
|
||||
ystart, ynum = next(layout_dimension(available_height, cell_height, margin_length=margin_length, padding_length=padding_length))
|
||||
xstart, xnum = next(layout_dimension(central.left, central.width, cell_width, margin_length=margin_length, padding_length=padding_length))
|
||||
ystart, ynum = next(layout_dimension(central.top, central.height, cell_height, margin_length=margin_length, padding_length=padding_length))
|
||||
return window_geometry(xstart, xnum, ystart, ynum)
|
||||
|
||||
|
||||
def left_blank_rect(w, rects, vh):
|
||||
if w.geometry.left > 0:
|
||||
rects.append(Rect(0, 0, w.geometry.left, vh))
|
||||
def left_blank_rect(w, rects):
|
||||
lt = w.geometry.left
|
||||
if lt > central.left:
|
||||
rects.append(Rect(central.left, central.top, lt, central.bottom + 1))
|
||||
|
||||
|
||||
def right_blank_rect(w, rects, vh):
|
||||
if w.geometry.right < viewport_width:
|
||||
rects.append(Rect(w.geometry.right, 0, viewport_width, vh))
|
||||
def right_blank_rect(w, rects):
|
||||
r = w.geometry.right
|
||||
if r < central.right:
|
||||
rects.append(Rect(r, central.top, central.right + 1, central.bottom + 1))
|
||||
|
||||
|
||||
def top_blank_rect(w, rects, vh):
|
||||
if w.geometry.top > 0:
|
||||
rects.append(Rect(0, 0, viewport_width, w.geometry.top))
|
||||
def top_blank_rect(w, rects):
|
||||
t = w.geometry.top
|
||||
if t > central.top:
|
||||
rects.append(Rect(central.left, central.top, central.right + 1, t))
|
||||
|
||||
|
||||
def bottom_blank_rect(w, rects, vh):
|
||||
if w.geometry.bottom < available_height:
|
||||
rects.append(Rect(0, w.geometry.bottom, viewport_width, vh))
|
||||
def bottom_blank_rect(w, rects):
|
||||
b = w.geometry.bottom
|
||||
if b < central.bottom:
|
||||
rects.append(Rect(central.left, b, central.right + 1, central.bottom + 1))
|
||||
|
||||
|
||||
def blank_rects_for_window(w):
|
||||
ans = []
|
||||
vh = available_height
|
||||
left_blank_rect(w, ans, vh), top_blank_rect(w, ans, vh), right_blank_rect(w, ans, vh), bottom_blank_rect(w, ans, vh)
|
||||
left_blank_rect(w, ans), top_blank_rect(w, ans), right_blank_rect(w, ans), bottom_blank_rect(w, ans)
|
||||
return ans
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -379,15 +379,38 @@ PYWRAP1(set_tab_bar_render_data) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyTypeObject RegionType;
|
||||
static PyStructSequence_Field region_fields[] = {
|
||||
{"left", ""}, {"top", ""}, {"right", ""}, {"bottom", ""}, {"width", ""}, {"height", ""}, {NULL, NULL}
|
||||
};
|
||||
static PyStructSequence_Desc region_desc = {"Region", NULL, region_fields, 6};
|
||||
|
||||
static inline PyObject*
|
||||
wrap_region(Region *r) {
|
||||
PyObject *ans = PyStructSequence_New(&RegionType);
|
||||
if (ans) {
|
||||
PyStructSequence_SET_ITEM(ans, 0, PyLong_FromUnsignedLong(r->left));
|
||||
PyStructSequence_SET_ITEM(ans, 1, PyLong_FromUnsignedLong(r->top));
|
||||
PyStructSequence_SET_ITEM(ans, 2, PyLong_FromUnsignedLong(r->right));
|
||||
PyStructSequence_SET_ITEM(ans, 3, PyLong_FromUnsignedLong(r->bottom));
|
||||
PyStructSequence_SET_ITEM(ans, 4, PyLong_FromUnsignedLong(r->right - r->left + 1));
|
||||
PyStructSequence_SET_ITEM(ans, 5, PyLong_FromUnsignedLong(r->bottom - r->top + 1));
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
PYWRAP1(viewport_for_window) {
|
||||
id_type os_window_id = 0;
|
||||
int vw = 100, vh = 100;
|
||||
PA("|K", &os_window_id);
|
||||
Region central = {0}, tab_bar = {0};
|
||||
WITH_OS_WINDOW(os_window_id)
|
||||
int available_height = os_window->viewport_height;
|
||||
if (os_window->num_tabs > 1) available_height -= global_state.cell_height;
|
||||
return Py_BuildValue("iiiII", os_window->viewport_width, os_window->viewport_height, available_height, global_state.cell_width, global_state.cell_height);
|
||||
os_window_regions(os_window, ¢ral, &tab_bar);
|
||||
vw = os_window->viewport_width; vh = os_window->viewport_height;
|
||||
goto end;
|
||||
END_WITH_OS_WINDOW
|
||||
return Py_BuildValue("iiII", 400, 400, global_state.cell_width, global_state.cell_height);
|
||||
end:
|
||||
return Py_BuildValue("NNiiII", wrap_region(¢ral), wrap_region(&tab_bar), vw, vh, global_state.cell_width, global_state.cell_height);
|
||||
}
|
||||
|
||||
PYWRAP1(set_dpi_from_os_window) {
|
||||
|
|
@ -529,6 +552,9 @@ bool
|
|||
init_state(PyObject *module) {
|
||||
global_state.cell_width = 1; global_state.cell_height = 1;
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
if (PyStructSequence_InitType2(&RegionType, ®ion_desc) != 0) return false;
|
||||
Py_INCREF((PyObject *) &RegionType);
|
||||
PyModule_AddObject(module, "Region", (PyObject *) &RegionType);
|
||||
return true;
|
||||
}
|
||||
// }}}
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ def __init__(self, os_window_id, opts):
|
|||
self.num_tabs = 1
|
||||
self.cell_width = 1
|
||||
self.data_buffer_size = 0
|
||||
self.layout_changed = None
|
||||
self.laid_out_once = False
|
||||
self.dirty = True
|
||||
self.screen = s = Screen(None, 1, 10)
|
||||
s.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
|
||||
|
|
@ -271,25 +271,29 @@ def as_rgb(x):
|
|||
self.active_bg = as_rgb(color_as_int(opts.active_tab_background))
|
||||
self.active_fg = as_rgb(color_as_int(opts.active_tab_foreground))
|
||||
|
||||
def layout(self, viewport_width, viewport_height, cell_width, cell_height):
|
||||
def layout(self):
|
||||
central, tab_bar, vw, vh, cell_width, cell_height = viewport_for_window(self.os_window_id)
|
||||
if tab_bar.width < 2:
|
||||
return
|
||||
self.cell_width = cell_width
|
||||
s = self.screen
|
||||
viewport_width = tab_bar.width
|
||||
ncells = viewport_width // cell_width
|
||||
s.resize(1, ncells)
|
||||
s.reset_mode(DECAWM)
|
||||
self.layout_changed = True
|
||||
self.laid_out_once = True
|
||||
margin = (viewport_width - ncells * cell_width) // 2
|
||||
self.window_geometry = g = WindowGeometry(
|
||||
margin, viewport_height - cell_height, viewport_width - margin, viewport_height, s.columns, s.lines)
|
||||
margin, tab_bar.top, viewport_width - margin, tab_bar.bottom, s.columns, s.lines)
|
||||
if margin > 0:
|
||||
self.tab_bar_blank_rects = (Rect(0, g.top, g.left, g.bottom), Rect(g.right - 1, g.top, viewport_width, g.bottom))
|
||||
else:
|
||||
self.tab_bar_blank_rects = ()
|
||||
self.screen_geometry = sg = calculate_gl_geometry(g, viewport_width, viewport_height, cell_width, cell_height)
|
||||
self.screen_geometry = sg = calculate_gl_geometry(g, vw, vh, cell_width, cell_height)
|
||||
set_tab_bar_render_data(self.os_window_id, sg.xstart, sg.ystart, sg.dx, sg.dy, self.screen)
|
||||
|
||||
def update(self, data):
|
||||
if self.layout_changed is None:
|
||||
if not self.laid_out_once:
|
||||
return
|
||||
s = self.screen
|
||||
s.cursor.x = 0
|
||||
|
|
@ -337,31 +341,35 @@ def __init__(self, os_window_id, opts, args, startup_session):
|
|||
self.opts, self.args = opts, args
|
||||
self.tabs = []
|
||||
self.tab_bar = TabBar(self.os_window_id, opts)
|
||||
self.tab_bar.layout(*self.tab_bar_layout_data)
|
||||
self.active_tab_idx = 0
|
||||
|
||||
for t in startup_session.tabs:
|
||||
self._add_tab(Tab(self, session_tab=t))
|
||||
self._set_active_tab(max(0, min(startup_session.active_tab_idx, len(self.tabs) - 1)))
|
||||
if len(self.tabs) > 1:
|
||||
self.tabbar_visibility_changed()
|
||||
self.update_tab_bar()
|
||||
|
||||
def refresh_sprite_positions(self):
|
||||
self.tab_bar.screen.refresh_sprite_positions()
|
||||
|
||||
def _add_tab(self, tab):
|
||||
before = len(self.tabs)
|
||||
self.tabs.append(tab)
|
||||
if len(self.tabs) > 1 and before < 2:
|
||||
self.tabbar_visibility_changed()
|
||||
|
||||
def _remove_tab(self, tab):
|
||||
before = len(self.tabs)
|
||||
remove_tab(self.os_window_id, tab.id)
|
||||
self.tabs.remove(tab)
|
||||
if len(self.tabs) < 2 and before > 1:
|
||||
self.tabbar_visibility_changed()
|
||||
|
||||
def _set_active_tab(self, idx):
|
||||
self.active_tab_idx = idx
|
||||
set_active_tab(self.os_window_id, idx)
|
||||
|
||||
def tabbar_visibility_changed(self):
|
||||
self.tab_bar.layout()
|
||||
self.resize(only_tabs=True)
|
||||
glfw_post_empty_event()
|
||||
|
||||
|
|
@ -371,7 +379,7 @@ def update_tab_bar(self):
|
|||
|
||||
def resize(self, only_tabs=False):
|
||||
if not only_tabs:
|
||||
self.tab_bar.layout(*self.tab_bar_layout_data)
|
||||
self.tab_bar.layout()
|
||||
self.update_tab_bar()
|
||||
for tab in self.tabs:
|
||||
tab.relayout()
|
||||
|
|
@ -433,27 +441,16 @@ def title_changed(self, new_title):
|
|||
self.update_tab_bar()
|
||||
|
||||
def new_tab(self, special_window=None, cwd_from=None):
|
||||
needs_resize = len(self.tabs) == 1
|
||||
idx = len(self.tabs)
|
||||
self._add_tab(Tab(self, special_window=special_window, cwd_from=cwd_from))
|
||||
self._set_active_tab(idx)
|
||||
self.update_tab_bar()
|
||||
if needs_resize:
|
||||
self.tabbar_visibility_changed()
|
||||
|
||||
def remove(self, tab):
|
||||
needs_resize = len(self.tabs) == 2
|
||||
self._remove_tab(tab)
|
||||
self._set_active_tab(max(0, min(self.active_tab_idx, len(self.tabs) - 1)))
|
||||
self.update_tab_bar()
|
||||
tab.destroy()
|
||||
if needs_resize:
|
||||
self.tabbar_visibility_changed()
|
||||
|
||||
@property
|
||||
def tab_bar_layout_data(self):
|
||||
vw, vh, ah, cw, ch = viewport_for_window(self.os_window_id)
|
||||
return vw, vh, cw, ch
|
||||
|
||||
@property
|
||||
def tab_bar_data(self):
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ def refresh(self):
|
|||
wakeup()
|
||||
|
||||
def update_position(self, window_geometry):
|
||||
vw, vh, ah, cw, ch = viewport_for_window(self.os_window_id)
|
||||
central, tab_bar, vw, vh, cw, ch = viewport_for_window(self.os_window_id)
|
||||
self.screen_geometry = sg = calculate_gl_geometry(window_geometry, vw, vh, cw, ch)
|
||||
return sg
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue