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
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
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