Exemple #1
0
    def keep_in_frame(self, widget, width, height, paragraphs, mode, persistent=False):
        keep = KeepInFrame(width, height, paragraphs, mode=mode)
        keep.canv = self.canvas
        keep.wrap(self.calculate_size(widget.width), self.calculate_size(widget.height))

        if persistent:
            widget.keep = keep

        return keep
Exemple #2
0
    def keep_in_frame(self, widget, width, height, paragraphs, mode, persistent=False):
        keep = KeepInFrame(width, height, paragraphs, mode=mode)
        keep.canv = self.canvas
        keep.wrap(self.calculate_size(widget.width), self.calculate_size(widget.height))

        if persistent:
            widget.keep = keep

        return keep
 def wrap(self, awidth, aheight):
     self.maxHeight = aheight
     self.maxWidth = awidth
     w, h = KeepInFrame.wrap(self, awidth, aheight)
     if w < awidth and h < aheight:
         self._scale = max(w / awidth, h / aheight)
     return w, h
Exemple #4
0
 def wrap(self, awidth, aheight):
     self.maxHeight = aheight
     self.maxWidth = awidth
     w, h = KeepInFrame.wrap(self, awidth, aheight)
     if w < awidth and h < aheight:
         self._scale = max(w / awidth, h / aheight)
     return w, h
Exemple #5
0
class Div(Flowable):
    def __init__(self,
                 story,
                 height=None,
                 width=None,
                 pos_x=None,
                 pos_y=None,
                 frame_attrs=freeze({}),
                 attributes=freeze({}),
                 pto_trailer=None,
                 pto_header=None):
        Flowable.__init__(self)
        # get on story
        self.div_story = story
        # set frame style
        self.frame_attrs = {
            'leftPadding': 0,
            'bottomPadding': 0,
            'rightPadding': 0,
            'topPadding': 0,
            'showBoundary': 0
        }
        # PTO initialisation
        self.pto_trailer = pto_trailer
        self.pto_header = pto_header

        if frame_attrs is not None:
            self.frame_attrs.update(frame_attrs)

        for margin in ('topMargin', 'bottomMargin', 'leftMargin',
                       'rightMargin'):
            if margin in self.frame_attrs:
                del self.frame_attrs[margin]

        border = self.frame_attrs['showBoundary']
        if isinstance(border, ShowBoundaryValue):
            border = border.width
        if border:
            for padding_attr in FRAME_PADDINGS_KEYS:
                self.frame_attrs[padding_attr] += border
        self.frame_width = width

        # Overflow
        # TODO to improve
        self.keep_in_frame = None
        style = attribute_style_to_dict(attributes.get((None, 'style'), ''))
        self.overflow = style.get('overflow-y', None)
        if self.overflow == 'hidden':
            self.overflow = 'truncate'
        else:
            self.overflow = None

    def draw(self):
        # set position for the frame
        self.pos_x, self.pos_y = self._get_current_position(self.canv)
        # XXX This is false, height=drawHeigh and drawHeight should take into
        # account the frame padding
        height = (self.drawHeight + self.frame_attrs['leftPadding'] +
                  self.frame_attrs['rightPadding'])
        width = (self.drawWidth + self.frame_attrs['topPadding'] +
                 self.frame_attrs['bottomPadding'])

        self.frame = Frame(self.pos_x, self.pos_y, width, height,
                           **self.frame_attrs)
        if self.overflow:
            # Hack, We lie by setting the new created frame as default frame
            # of the doc template
            # To avoid problems when calling keep_in_frame.wrap
            # See platypus.flowables "def _listWrapOn"
            _doctemplate = self.canv._doctemplate
            # save state
            current_frame = getattr(_doctemplate, 'frame', None)
            _doctemplate.frame = self.frame

            # Check if PTO is defined
            if self.pto_trailer or self.pto_header:
                ptocontainer = PTOContainer(self.div_story[:],
                                            self.pto_trailer, self.pto_header)
                ptocontainer.canv = self.canv
                pto_size = ptocontainer.wrap(self.drawWidth, self.drawHeight)
                # XXX Round the height to avoid problems with decimal
                if int(pto_size[1]) > int(self.drawHeight):
                    pto_story = ptocontainer.split(self.drawWidth,
                                                   self.drawHeight)
                    self.frame.addFromList(pto_story, self.canv)
                else:
                    self.frame.addFromList([self.keep_in_frame], self.canv)
            else:
                self.frame.addFromList([self.keep_in_frame], self.canv)
            # restore state
            if current_frame:
                _doctemplate.frame = current_frame
        else:
            self.frame.addFromList(self.div_story[:], self.canv)

    def wrap(self, availWidth, availHeight):
        canv = self.canv
        if self.overflow:
            if self.keep_in_frame is None:
                # FIXME if the availHeight is very small
                # We consider that there is no enough space
                # and we calculate the real size of the flowables
                if availHeight <= 0:
                    width, height = self._get_real_size(availWidth)
                else:
                    width, height = availWidth, availHeight

                # Dirty hack, get the current frame height and use it
                # if height is too small
                main_frame_height = self._get_main_frame_height(
                    availHeight, 0.8)
                if height == -1e-06:
                    height = main_frame_height
                else:
                    height = min(height, main_frame_height)

                self.keep_in_frame = KeepInFrame(width,
                                                 height,
                                                 self.div_story[:],
                                                 mode=self.overflow)
            else:
                width, height = availWidth, availHeight
                # FIXME Usefull ?
                # Dirty hack, get the current frame height and use it
                # if height is too small
                main_frame_height = self._get_main_frame_height(
                    availHeight, 0.8)
                if height == -1e-06:
                    height = main_frame_height
                else:
                    height = min(height, main_frame_height)

            # Set the canva
            self.keep_in_frame.canv = canv

            # Hack, We remove the attribute _doctemplate of the canv
            # To avoid problems when calling keep_in_frame.wrap
            # See platypus.flowables "def _listWrapOn"
            if hasattr(canv, '_doctemplate'):
                _doctemplate = canv._doctemplate
                # Remove _doctemplate
                canv._doctemplate = None
            w, h = self.keep_in_frame.wrap(width, height)
            if hasattr(canv, '_doctemplate'):
                # Restore _doctemplate
                canv._doctemplate = _doctemplate

            self.drawWidth, self.drawHeight = w, h
        else:
            width, height = self._get_real_size(availWidth)
            self.drawWidth, self.drawHeight = width, height

        return self.drawWidth, self.drawHeight

    def getSpaceBefore(self):
        if self.overflow and self.keep_in_frame:
            return self.keep_in_frame.getSpaceBefore()

        # XXX default value
        return 0

    def getSpaceAfter(self):
        if self.overflow and self.keep_in_frame:
            return self.keep_in_frame.getSpaceAfter()

        # XXX default value
        return 0

    def _get_real_size(self, availWidth, availHeight=10000000):
        """By default we use a fake height to calculate the real
        height of the flowables"""
        self.drawWidth = self.width or availWidth
        self.drawWidth -= self.frame_attrs['leftPadding']
        self.drawWidth -= self.frame_attrs['rightPadding']
        self.drawHeight = 0
        at_top = True
        for element in self.div_story[:]:
            if at_top:
                at_top = False
            else:
                self.drawHeight += element.getSpaceBefore()
            flowHeight = element.wrap(availWidth,
                                      availHeight - self.drawHeight)[1]
            self.drawHeight += flowHeight
            self.drawHeight += element.getSpaceAfter()
        self.drawHeight += self.frame_attrs['topPadding']
        self.drawHeight += self.frame_attrs['bottomPadding']
        return (self.drawWidth, self.drawHeight)

    def _align_frame(self, available_width, hAlign):
        if hAlign == 'CENTER':
            self.pox_x = (available_width - self.frame_width) / 2 + self.pos_x
        elif hAlign == 'RIGHT':
            self.pos_x = available_width - self.frame_width + self.pox_x

    def _get_current_position(self, canv):
        return (canv._x, canv._y)

    def _get_current_absolute_position(self, canv):
        return canv.absolutePosition(canv._x, canv._y)

    def _get_main_frame_height(self, default, ratio=0.9):
        if self.canv is None:
            return default
        value = self.canv._doctemplate.main_frame_attr.get('height', default)
        return value * ratio
Exemple #6
0
class Div(Flowable):

    def __init__(self, story, height=None, width=None, pos_x=None, pos_y=None,
                 frame_attrs=freeze({}), attributes=freeze({}), pto_trailer=None,
                 pto_header=None):
        Flowable.__init__(self)
        # get on story
        self.div_story = story
        # set frame style
        self.frame_attrs = {'leftPadding': 0, 'bottomPadding': 0,
                           'rightPadding': 0, 'topPadding': 0,
                           'showBoundary': 0}
        # PTO initialisation
        self.pto_trailer = pto_trailer
        self.pto_header = pto_header

        if frame_attrs is not None:
            self.frame_attrs.update(frame_attrs)

        for margin in ('topMargin', 'bottomMargin', 'leftMargin',
                       'rightMargin'):
            if margin in self.frame_attrs:
                del self.frame_attrs[margin]

        border = self.frame_attrs['showBoundary']
        if isinstance(border, ShowBoundaryValue):
            border = border.width
        if border:
            for padding_attr in FRAME_PADDINGS_KEYS:
                self.frame_attrs[padding_attr] += border
        self.frame_width = width

        # Overflow
        # TODO to improve
        self.keep_in_frame = None
        style = attribute_style_to_dict(attributes.get((None, 'style'), ''))
        self.overflow = style.get('overflow-y', None)
        if self.overflow == 'hidden':
            self.overflow = 'truncate'
        else:
            self.overflow = None


    def draw(self):
        # set position for the frame
        self.pos_x, self.pos_y = self._get_current_position(self.canv)
        # XXX This is false, height=drawHeigh and drawHeight should take into
        # account the frame padding
        height = (self.drawHeight + self.frame_attrs['leftPadding'] +
                  self.frame_attrs['rightPadding'])
        width = (self.drawWidth + self.frame_attrs['topPadding'] +
                 self.frame_attrs['bottomPadding'])

        self.frame = Frame(self.pos_x, self.pos_y, width, height,
                           **self.frame_attrs)
        if self.overflow:
            # Hack, We lie by setting the new created frame as default frame
            # of the doc template
            # To avoid problems when calling keep_in_frame.wrap
            # See platypus.flowables "def _listWrapOn"
            _doctemplate = self.canv._doctemplate
            # save state
            current_frame = getattr(_doctemplate, 'frame', None)
            _doctemplate.frame = self.frame

            # Check if PTO is defined
            if self.pto_trailer or self.pto_header:
                ptocontainer = PTOContainer(self.div_story[:],
                                            self.pto_trailer, self.pto_header)
                ptocontainer.canv = self.canv
                pto_size = ptocontainer.wrap(self.drawWidth, self.drawHeight)
                # XXX Round the height to avoid problems with decimal
                if int(pto_size[1]) > int(self.drawHeight):
                    pto_story = ptocontainer.split(self.drawWidth,
                                                   self.drawHeight)
                    self.frame.addFromList(pto_story, self.canv)
                else:
                    self.frame.addFromList([self.keep_in_frame], self.canv)
            else:
                self.frame.addFromList([self.keep_in_frame], self.canv)
            # restore state
            if current_frame:
                _doctemplate.frame = current_frame
        else:
            self.frame.addFromList(self.div_story[:], self.canv)


    def wrap(self, availWidth, availHeight):
        canv = self.canv
        if self.overflow:
            if self.keep_in_frame is None:
                # FIXME if the availHeight is very small
                # We consider that there is no enough space
                # and we calculate the real size of the flowables
                if availHeight <= 0:
                    width, height = self._get_real_size(availWidth)
                else:
                    width, height = availWidth, availHeight

                # Dirty hack, get the current frame height and use it
                # if height is too small
                main_frame_height = self._get_main_frame_height(availHeight,
                                                                0.8)
                if height == -1e-06:
                    height = main_frame_height
                else:
                    height = min(height, main_frame_height)

                self.keep_in_frame = KeepInFrame(width, height,
                                                 self.div_story[:],
                                                 mode=self.overflow)
            else:
                width, height = availWidth, availHeight
                # FIXME Usefull ?
                # Dirty hack, get the current frame height and use it
                # if height is too small
                main_frame_height = self._get_main_frame_height(availHeight,
                                                                0.8)
                if height == -1e-06:
                    height = main_frame_height
                else:
                    height = min(height, main_frame_height)

            # Set the canva
            self.keep_in_frame.canv = canv

            # Hack, We remove the attribute _doctemplate of the canv
            # To avoid problems when calling keep_in_frame.wrap
            # See platypus.flowables "def _listWrapOn"
            if hasattr(canv, '_doctemplate'):
                _doctemplate = canv._doctemplate
                # Remove _doctemplate
                canv._doctemplate = None
            w, h = self.keep_in_frame.wrap(width, height)
            if hasattr(canv, '_doctemplate'):
                # Restore _doctemplate
                canv._doctemplate = _doctemplate

            self.drawWidth, self.drawHeight = w, h
        else:
            width, height = self._get_real_size(availWidth)
            self.drawWidth, self.drawHeight = width, height

        return self.drawWidth, self.drawHeight


    def getSpaceBefore(self):
        if self.overflow and self.keep_in_frame:
            return self.keep_in_frame.getSpaceBefore()

        # XXX default value
        return 0


    def getSpaceAfter(self):
        if self.overflow and self.keep_in_frame:
            return self.keep_in_frame.getSpaceAfter()

        # XXX default value
        return 0


    def _get_real_size(self, availWidth, availHeight=10000000):
        """By default we use a fake height to calculate the real
        height of the flowables"""
        self.drawWidth = self.width or availWidth
        self.drawWidth -= self.frame_attrs['leftPadding']
        self.drawWidth -= self.frame_attrs['rightPadding']
        self.drawHeight = 0
        at_top = True
        for element in self.div_story[:]:
            if at_top:
                at_top = False
            else:
                self.drawHeight += element.getSpaceBefore()
            flowHeight = element.wrap(availWidth,
                                      availHeight-self.drawHeight)[1]
            self.drawHeight += flowHeight
            self.drawHeight += element.getSpaceAfter()
        self.drawHeight += self.frame_attrs['topPadding']
        self.drawHeight += self.frame_attrs['bottomPadding']
        return (self.drawWidth, self.drawHeight)


    def _align_frame(self, available_width, hAlign):
        if hAlign == 'CENTER':
            self.pox_x = (available_width - self.frame_width) / 2 + self.pos_x
        elif hAlign == 'RIGHT':
            self.pos_x = available_width - self.frame_width + self.pox_x


    def _get_current_position(self, canv):
        return (canv._x, canv._y)


    def _get_current_absolute_position(self, canv):
        return canv.absolutePosition(canv._x, canv._y)


    def _get_main_frame_height(self, default, ratio=0.9):
        if self.canv is None:
            return default
        value = self.canv._doctemplate.main_frame_attr.get('height', default)
        return value * ratio