Source code for AutoArchive._infrastructure.ui.multi_field_line

# multi_field_line.py
#
# Project: AutoArchive
# License: GNU GPLv3
#
# Copyright (C) 2003 - 2014 Róbert Čerňanský



""":class:`MultiFieldLine` class, :data:`FieldStretchiness` enum and :class:`DisplayField` namedtuple."""



__all__ = ["MultiFieldLine", "FieldStretchiness", "DisplayField"]



# {{{ INCLUDES

from collections import namedtuple
from AutoArchive._infrastructure.py_additions import Enum

# }}} INCLUDES



# {{{ CONSTANTS

#: Display field stretchiness.
FieldStretchiness = Enum(
    "Normal",
    "Medium",
    "Low"
)

# }}} CONSTANTS



# {{{ CLASSES

[docs]class MultiFieldLine: """A line of text that consists of multiple fields. :param fields: Parts that together assembles the line. :type fields: ``Sequence<DisplayField>`` :param referenceLineWidth: Total physical width of the line used as a reference for computing physical widths based on relative widths of fields and re-computing them to a different total size in :meth:`computeFieldWidths`. :type referenceLineWidth: ``int``""" __MAX_STRETCHINESS_CONSTANT = 1000 def __init__(self, fields, referenceLineWidth = 1000): self.__fields = fields self.__referenceLineWidth = referenceLineWidth @property def fields(self): """Gets fields that this line consists of. :rtype: ``Sequence<DisplayField>``""" return self.__fields # SMELL: This should return a structure of text and width. Full DisplayField is not necessary. Then the fields # property can be removed.
[docs] def computeFieldWidths(self, physicalLineWidth): """Computes physical width for each field. Widths are computed based on relative widths and stretchiness so that total line width is no bigger than passes ``physicalLineWidth``. :param physicalLineWidth: Actual total line width (in the same units as ``referenceLineWidth``. :type physicalLineWidth: ``int`` :return: Sequence of physical widths in the same order as :attr:`fields`. :rtype: ``list<int>``""" referenceToPhysical = physicalLineWidth / self.__referenceLineWidth # we are abusing DisplayField here by storing physical (reference) width in widthWeight referenceFields = [DisplayField(f.text, f.widthWeight * self.__referenceLineWidth, f.stretchiness) for f in self.__fields] lowStretchedFields = [f for f in referenceFields if f.stretchiness == FieldStretchiness.Low] lowStretchedPhysicalWidths = [f.widthWeight * self.__applyStretchiness(referenceToPhysical, f.stretchiness) for f in lowStretchedFields] referenceToPhysicalNoLow = (physicalLineWidth - sum(lowStretchedPhysicalWidths)) / \ (self.__referenceLineWidth - sum((f.widthWeight for f in lowStretchedFields))) mediumStretchedFields = [f for f in referenceFields if f.stretchiness == FieldStretchiness.Medium] mediumStretchedPhysicalWidths = [ f.widthWeight * self.__applyStretchiness(referenceToPhysicalNoLow, f.stretchiness) for f in mediumStretchedFields] referenceToPhysicalNoLowMedium = (physicalLineWidth - (sum(lowStretchedPhysicalWidths) + sum(mediumStretchedPhysicalWidths))) / (self.__referenceLineWidth - (sum((f.widthWeight for f in lowStretchedFields)) + sum((f.widthWeight for f in mediumStretchedFields)))) normalStretchedFields = [f for f in referenceFields if f.stretchiness == FieldStretchiness.Normal] normalStretchedPhysicalWidths = [ f.widthWeight * self.__applyStretchiness(referenceToPhysicalNoLowMedium, f.stretchiness) for f in normalStretchedFields] # assemble list of widths in order that corresponds to self.__fields widths = [] lowIdx = 0 mediumIdx = 0 normalIdx = 0 for field in self.__fields: if field.stretchiness == FieldStretchiness.Low: widths.append(round(lowStretchedPhysicalWidths[lowIdx])) lowIdx += 1 elif field.stretchiness == FieldStretchiness.Medium: widths.append(round(mediumStretchedPhysicalWidths[mediumIdx])) mediumIdx += 1 elif field.stretchiness == FieldStretchiness.Normal: widths.append(round(normalStretchedPhysicalWidths[normalIdx])) normalIdx += 1 return widths
def __applyStretchiness(self, coefficient, stretchiness): stretchinessConstant = self.__quantifyStretchiness(stretchiness) return (1 - coefficient) * (stretchinessConstant / self.__MAX_STRETCHINESS_CONSTANT) + coefficient @staticmethod def __quantifyStretchiness(stretchiness): if stretchiness == FieldStretchiness.Normal: return 0 if stretchiness == FieldStretchiness.Medium: return 100 if stretchiness == FieldStretchiness.Low: return 900
DisplayField = namedtuple("DisplayField", "text widthWeight stretchiness") """One part of a multi-field line. :param text: Text that shall be displayed in the field. :type text: ``str`` :param widthWeight: Number from 0 to 1 which represents relative width of the field. 0 means zero width and 1 means maximal width. :type widthWeight: ``float`` :param stretchiness: Determines how much the field change its size when the actual total line width changes. :type stretchiness: :data:`FieldStretchiness`""" # }}} CLASSES