mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Make EvTable respect col-widths while retaining total table width.
Resolves #1614.
This commit is contained in:
parent
060cfde23e
commit
9bbfc422ee
3 changed files with 79 additions and 21 deletions
|
|
@ -253,7 +253,7 @@ class CmdMail(default_cmds.MuxCommand):
|
|||
index += 1
|
||||
|
||||
table.reformat_column(0, width=6)
|
||||
table.reformat_column(1, width=17)
|
||||
table.reformat_column(1, width=18)
|
||||
table.reformat_column(2, width=34)
|
||||
table.reformat_column(3, width=13)
|
||||
table.reformat_column(4, width=7)
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ class TestMail(CommandTest):
|
|||
"You have received a new @mail from TestAccount2(account 2)|You sent your message.", caller=self.account2)
|
||||
self.call(mail.CmdMail(), "TestAccount=Message 1", "You sent your message.", caller=self.account2)
|
||||
self.call(mail.CmdMail(), "TestAccount=Message 2", "You sent your message.", caller=self.account2)
|
||||
self.call(mail.CmdMail(), "", "| ID: From: Subject:", caller=self.account)
|
||||
self.call(mail.CmdMail(), "", "| ID: From: Subject:", caller=self.account)
|
||||
self.call(mail.CmdMail(), "2", "From: TestAccount2", caller=self.account)
|
||||
self.call(mail.CmdMail(), "/forward TestAccount2 = 1/Forward message", "You sent your message.|Message forwarded.", caller=self.account)
|
||||
self.call(mail.CmdMail(), "/reply 2=Reply Message2", "You sent your message.", caller=self.account)
|
||||
|
|
|
|||
|
|
@ -893,6 +893,9 @@ class EvColumn(object):
|
|||
|
||||
"""
|
||||
col = self.column
|
||||
# fixed options for the column will override those requested in the call!
|
||||
# this is particularly relevant to things like width/height, to avoid
|
||||
# fixed-widths columns from being auto-balanced
|
||||
kwargs.update(self.options)
|
||||
# use fixed width or adjust to the largest cell
|
||||
if "width" not in kwargs:
|
||||
|
|
@ -1283,25 +1286,59 @@ class EvTable(object):
|
|||
cwidths_min = [max(cell.get_min_width() for cell in col) for col in self.worktable]
|
||||
cwmin = sum(cwidths_min)
|
||||
|
||||
if cwmin > width:
|
||||
# we cannot shrink any more
|
||||
raise Exception("Cannot shrink table width to %s. Minimum size is %s." % (self.width, cwmin))
|
||||
# get which cols have separately set widths - these should be locked
|
||||
# note that we need to remove cwidths_min for each lock to avoid counting
|
||||
# it twice (in cwmin and in locked_cols)
|
||||
locked_cols = {icol: col.options['width'] - cwidths_min[icol]
|
||||
for icol, col in enumerate(self.worktable) if 'width' in col.options}
|
||||
locked_width = sum(locked_cols.values())
|
||||
|
||||
excess = width - cwmin - locked_width
|
||||
|
||||
if len(locked_cols) >= ncols and excess:
|
||||
# we can't adjust the width at all - all columns are locked
|
||||
raise Exception("Cannot balance table to width %s - "
|
||||
"all columns have a set, fixed width summing to %s!" % (
|
||||
self.width, sum(cwidths)))
|
||||
|
||||
if excess < 0:
|
||||
# the locked cols makes it impossible
|
||||
raise Exception("Cannot shrink table width to %s. "
|
||||
"Minimum size (and/or fixed-width columns) "
|
||||
"sets minimum at %s." % (self.width, cwmin + locked_width))
|
||||
|
||||
excess = width - cwmin
|
||||
if self.evenwidth:
|
||||
# make each column of equal width
|
||||
for _ in range(excess):
|
||||
# use cwidths as a work-array to track weights
|
||||
cwidths = copy(cwidths_min)
|
||||
correction = 0
|
||||
while correction < excess:
|
||||
# flood-fill the minimum table starting with the smallest columns
|
||||
ci = cwidths_min.index(min(cwidths_min))
|
||||
cwidths_min[ci] += 1
|
||||
ci = cwidths.index(min(cwidths))
|
||||
if ci in locked_cols:
|
||||
# locked column, make sure it's not picked again
|
||||
cwidths[ci] += 9999
|
||||
cwidths_min[ci] = locked_cols[ci]
|
||||
else:
|
||||
cwidths_min[ci] += 1
|
||||
correction += 1
|
||||
cwidths = cwidths_min
|
||||
else:
|
||||
# make each column expand more proportional to their data size
|
||||
for _ in range(excess):
|
||||
# we use cwidth as a work-array to track weights
|
||||
correction = 0
|
||||
while correction < excess:
|
||||
# fill wider columns first
|
||||
ci = cwidths.index(max(cwidths))
|
||||
cwidths_min[ci] += 1
|
||||
cwidths[ci] -= 3
|
||||
if ci in locked_cols:
|
||||
# locked column, make sure it's not picked again
|
||||
cwidths[ci] -= 9999
|
||||
cwidths_min[ci] = locked_cols[ci]
|
||||
else:
|
||||
cwidths_min[ci] += 1
|
||||
correction += 1
|
||||
# give a just changed col less prio next run
|
||||
cwidths[ci] -= 3
|
||||
cwidths = cwidths_min
|
||||
|
||||
# reformat worktable (for width align)
|
||||
|
|
@ -1323,28 +1360,46 @@ class EvTable(object):
|
|||
for cell in (col[iy] for col in self.worktable)) for iy in range(nrowmax)]
|
||||
chmin = sum(cheights_min)
|
||||
|
||||
# get which cols have separately set heights - these should be locked
|
||||
# note that we need to remove cheights_min for each lock to avoid counting
|
||||
# it twice (in chmin and in locked_cols)
|
||||
locked_cols = {icol: col.options['height'] - cheights_min[icol]
|
||||
for icol, col in enumerate(self.worktable) if 'height' in col.options}
|
||||
locked_height = sum(locked_cols.values())
|
||||
|
||||
excess = self.height - chmin - locked_height
|
||||
|
||||
if chmin > self.height:
|
||||
# we cannot shrink any more
|
||||
raise Exception("Cannot shrink table height to %s. Minimum size is %s." % (self.height, chmin))
|
||||
raise Exception("Cannot shrink table height to %s. Minimum "
|
||||
"size (and/or fixed-height rows) sets minimum at %s." % (
|
||||
self.height, chmin + locked_height))
|
||||
|
||||
# now we add all the extra height up to the desired table-height.
|
||||
# We do this so that the tallest cells gets expanded first (and
|
||||
# thus avoid getting cropped)
|
||||
|
||||
excess = self.height - chmin
|
||||
even = self.height % 2 == 0
|
||||
for position in range(excess):
|
||||
correction = 0
|
||||
while correction < excess:
|
||||
# expand the cells with the most rows first
|
||||
if 0 <= position < nrowmax and nrowmax > 1:
|
||||
if 0 <= correction < nrowmax and nrowmax > 1:
|
||||
# avoid adding to header first round (looks bad on very small tables)
|
||||
ci = cheights[1:].index(max(cheights[1:])) + 1
|
||||
else:
|
||||
ci = cheights.index(max(cheights))
|
||||
cheights_min[ci] += 1
|
||||
if ci == 0 and self.header:
|
||||
# it doesn't look very good if header expands too fast
|
||||
cheights[ci] -= 2 if even else 3
|
||||
cheights[ci] -= 2 if even else 1
|
||||
if ci in locked_cols:
|
||||
# locked row, make sure it's not picked again
|
||||
cheights[ci] -= 9999
|
||||
cheights_min[ci] = locked_cols[ci]
|
||||
else:
|
||||
cheights_min[ci] += 1
|
||||
# change balance
|
||||
if ci == 0 and self.header:
|
||||
# it doesn't look very good if header expands too fast
|
||||
cheights[ci] -= 2 if even else 3
|
||||
cheights[ci] -= 2 if even else 1
|
||||
correction += 1
|
||||
cheights = cheights_min
|
||||
|
||||
# we must tell cells to crop instead of expanding
|
||||
|
|
@ -1554,6 +1609,8 @@ class EvTable(object):
|
|||
"""
|
||||
if index > len(self.table):
|
||||
raise Exception("Not a valid column index")
|
||||
# we update the columns' options which means eventual width/height
|
||||
# will be 'locked in' and withstand auto-balancing width/height from the table later
|
||||
self.table[index].options.update(kwargs)
|
||||
self.table[index].reformat(**kwargs)
|
||||
|
||||
|
|
@ -1569,6 +1626,7 @@ class EvTable(object):
|
|||
|
||||
def __str__(self):
|
||||
"""print table (this also balances it)"""
|
||||
# h = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
return str(unicode(ANSIString("\n").join([line for line in self._generate_lines()])))
|
||||
|
||||
def __unicode__(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue