168 lines
5.9 KiB
Python
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)
|