| 381 | |
| 382 | |
| 383 | class Section: |
| 384 | def __init__(self): |
| 385 | self.title = '' |
| 386 | self.headers = [] |
| 387 | self.rows = [] |
| 388 | self.indent_level = 0 |
| 389 | self._num_cols = None |
| 390 | self._max_widths = [] |
| 391 | |
| 392 | def __repr__(self): |
| 393 | return ( |
| 394 | "Section(title=%s, headers=%s, indent_level=%s, num_rows=%s)" |
| 395 | % (self.title, self.headers, self.indent_level, len(self.rows)) |
| 396 | ) |
| 397 | |
| 398 | def calculate_column_widths(self, padding=0, max_width=None): |
| 399 | # postcondition: sum(widths) == max_width |
| 400 | unscaled_widths = [w + padding for w in self._max_widths] |
| 401 | if max_width is None: |
| 402 | return unscaled_widths |
| 403 | if not unscaled_widths: |
| 404 | return unscaled_widths |
| 405 | else: |
| 406 | # Compute scale factor for max_width. |
| 407 | scale_factor = max_width / float(sum(unscaled_widths)) |
| 408 | scaled = [int(round(scale_factor * w)) for w in unscaled_widths] |
| 409 | # Once we've scaled the columns, we may be slightly over/under |
| 410 | # the amount we need so we have to adjust the columns. |
| 411 | off_by = sum(scaled) - max_width |
| 412 | while off_by != 0: |
| 413 | iter_order = range(len(scaled)) |
| 414 | if off_by < 0: |
| 415 | iter_order = reversed(iter_order) |
| 416 | for i in iter_order: |
| 417 | if off_by > 0: |
| 418 | scaled[i] -= 1 |
| 419 | off_by -= 1 |
| 420 | else: |
| 421 | scaled[i] += 1 |
| 422 | off_by += 1 |
| 423 | if off_by == 0: |
| 424 | break |
| 425 | return scaled |
| 426 | |
| 427 | def total_width(self, padding=0, with_border=False, outer_padding=0): |
| 428 | total = 0 |
| 429 | # One char on each side == 2 chars total to the width. |
| 430 | border_padding = 2 |
| 431 | for w in self.calculate_column_widths(): |
| 432 | total += w + padding |
| 433 | if with_border: |
| 434 | total += border_padding |
| 435 | total += outer_padding + outer_padding |
| 436 | return max( |
| 437 | get_text_length(self.title) |
| 438 | + border_padding |
| 439 | + outer_padding |
| 440 | + outer_padding, |
no outgoing calls