Lightningbeam/GUI/Generic/GPrinting.py

168 lines
5.9 KiB
Python

#------------------------------------------------------------------------------
#
# PyGUI - Printing - Generic
#
#------------------------------------------------------------------------------
from __future__ import division
from math import ceil
import cPickle as pickle
from GUI.Properties import overridable_property
from GUI import application
class PageSetup(object):
"""Holder of information specified by the "Page Setup" command."""
paper_name = overridable_property('paper_name')
paper_width = overridable_property('paper_width')
paper_height = overridable_property('paper_height')
left_margin = overridable_property('left_margin')
top_margin = overridable_property('top_margin')
right_margin = overridable_property('right_margin')
bottom_margin = overridable_property('bottom_margin')
orientation = overridable_property('orientation')
paper_size = overridable_property('paper_size')
margins = overridable_property('margins')
page_width = overridable_property('page_width')
page_height = overridable_property('page_height')
page_size = overridable_property('page_size')
page_rect = overridable_property('page_rect')
printable_rect = overridable_property('printable_rect') # May not work
printer_name = overridable_property('printer_name')
_pickle_attributes = ['paper_name', 'paper_size', 'margins',
'printer_name', 'orientation']
def __getstate__(self):
state = {}
for name in self._pickle_attributes:
state[name] = getattr(self, name)
return state
def __setstate__(self, state):
for name, value in state.iteritems():
setattr(self, name, value)
def from_string(s):
"""Restore a pickled PageSetup object from a string."""
return pickle.loads(s)
from_string = staticmethod(from_string)
def to_string(self):
"""Pickle the PageSetup object and return it as a string."""
return pickle.dumps(self, 2)
def get_paper_size(self):
return self.paper_width, self.paper_height
def set_paper_size(self, x):
self.paper_width, self.paper_height = x
def get_margins(self):
return self.left_margin, self.top_margin, self.right_margin, self.bottom_margin
def set_margins(self, x):
self.left_margin, self.top_margin, self.right_margin, self.bottom_margin = x
def get_page_width(self):
return self.paper_width - self.left_margin - self.right_margin
def get_page_height(self):
return self.paper_height - self.top_margin - self.bottom_margin
def get_page_size(self):
return (self.page_width, self.page_height)
def get_page_rect(self):
lm, tm, rm, bm = self.margins
pw, ph = self.paper_size
return (lm, tm, pw - rm, ph - bm)
#------------------------------------------------------------------------------
class Printable(object):
"""Mixin class for components implementing the "Print" command."""
printable = overridable_property('printable', "Whether this component should handle the 'Print' command.")
page_setup = overridable_property('page_setup', "The PageSetup object to use for printing.")
print_title = overridable_property('print_title', "Title for print job.")
_printable = True
def get_printable(self):
return self._printable
def set_printable(self, x):
self._printable = x
def get_print_title(self):
window = self.window
if window:
return window.title
else:
return ""
def get_page_setup(self):
result = None
model = getattr(self, 'model', None)
if model:
result = getattr(model, 'page_setup', None)
if not result:
result = application().page_setup
return result
def setup_menus(self, m):
if self.printable:
m.print_cmd.enabled = True
def print_cmd(self):
if self.printable:
page_setup = self.page_setup
if page_setup:
self.print_view(page_setup)
else:
self.pass_to_next_handler('print_cmd')
#------------------------------------------------------------------------------
class Paginator(object):
"""Used internally. A generic pagination algorithm for printing."""
def __init__(self, view, page_setup):
self.view = view
extent_width, extent_height = view.get_print_extent()
#paper_width, paper_height = page_setup.paper_size
#lm, tm, rm, bm = page_setup.margins
#page_width = int(paper_width - lm - rm)
#page_height = int(paper_height - tm - bm)
page_width, page_height = page_setup.page_size
if page_width <= 0 or page_height <= 0:
from AlertFunctions import stop_alert
stop_alert("Margins are too large for the page size.")
return
self.extent_rect = (0, 0, extent_width, extent_height)
self.page_width = page_width
self.page_height = page_height
self.left_margin = page_setup.left_margin
self.top_margin = page_setup.top_margin
self.pages_wide = int(ceil(extent_width / page_width))
self.pages_high = int(ceil(extent_height / page_height))
self.num_pages = self.pages_wide * self.pages_high
def draw_page(self, canvas, page_num):
row, col = divmod(page_num, self.pages_wide)
view_left = col * self.page_width
view_top = row * self.page_height
view_right = view_left + self.page_width
view_bottom = view_top + self.page_height
view_rect = (view_left, view_top, view_right, view_bottom)
dx = self.left_margin - view_left
dy = self.top_margin - view_top
canvas.translate(dx, dy)
canvas.rectclip(self.extent_rect)
canvas.rectclip(view_rect)
canvas._printing = True
self.view.draw(canvas, view_rect)