#!/usr/bin/env python
# -*- Mode: Python; py-indent-offset: 4 -*-
# vim: tabstop=4 shiftwidth=4 expandtab
#
# Copyright (C) 2010 Red Hat, Inc., John (J5) Palmieri <johnp@redhat.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
# USA

title = "Printing"
description = """
GtkPrintOperation offers a simple API to support printing in a cross-platform way.
"""

from gi.repository import Gtk, GLib, Pango, PangoCairo
import math
import os


class PrintingApp:
    HEADER_HEIGHT = 10 * 72 / 25.4
    HEADER_GAP = 3 * 72 / 25.4

    def __init__(self):
        self.operation = Gtk.PrintOperation()
        print_data = {'filename': os.path.abspath(__file__),
                      'font_size': 12.0,
                      'lines_per_page': 0,
                      'lines': None,
                      'num_lines': 0,
                      'num_pages': 0
                     }

        self.operation.connect('begin-print', self.begin_print, print_data)
        self.operation.connect('draw-page', self.draw_page, print_data)
        self.operation.connect('end-print', self.end_print, print_data)

        self.operation.set_use_full_page(False)
        self.operation.set_unit(Gtk.Unit.POINTS)
        self.operation.set_embed_page_setup(True)

        settings = Gtk.PrintSettings()

        dir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS)
        if dir is None:
            dir = GLib.get_home_dir()
        if settings.get(Gtk.PRINT_SETTINGS_OUTPUT_FILE_FORMAT) == 'ps':
            ext = '.ps'
        elif settings.get(Gtk.PRINT_SETTINGS_OUTPUT_FILE_FORMAT) == 'svg':
            ext = '.svg'
        else:
            ext = '.pdf'

        uri = "file://%s/gtk-demo%s" % (dir, ext)
        settings.set(Gtk.PRINT_SETTINGS_OUTPUT_URI, uri)
        self.operation.set_print_settings(settings)

    def run(self, parent=None):
        result = self.operation.run(Gtk.PrintOperationAction.PRINT_DIALOG, parent)

        if result == Gtk.PrintOperationResult.ERROR:
            message = self.operation.get_error()

            dialog = Gtk.MessageDialog(parent,
                                       0,
                                       Gtk.MessageType.ERROR,
                                       Gtk.ButtonsType.CLOSE,
                                       message)

            dialog.run()
            dialog.destroy()

        Gtk.main_quit()

    def begin_print(self, operation, print_ctx, print_data):
        height = print_ctx.get_height() - self.HEADER_HEIGHT - self.HEADER_GAP
        print_data['lines_per_page'] = \
            math.floor(height / print_data['font_size'])

        file_path = print_data['filename']
        if not os.path.isfile(file_path):
            file_path = os.path.join('demos', file_path)
            if not os.path.isfile(file_path):
                raise Exception("file not found: %s" % (file_path, ))

        # in reality you should most likely not read the entire
        # file into a buffer
        source_file = open(file_path, 'r')
        s = source_file.read()
        print_data['lines'] = s.split('\n')

        print_data['num_lines'] = len(print_data['lines'])
        print_data['num_pages'] = \
            (print_data['num_lines'] - 1) / print_data['lines_per_page'] + 1

        operation.set_n_pages(print_data['num_pages'])

    def draw_page(self, operation, print_ctx, page_num, print_data):
        cr = print_ctx.get_cairo_context()
        width = print_ctx.get_width()

        cr.rectangle(0, 0, width, self.HEADER_HEIGHT)
        cr.set_source_rgb(0.8, 0.8, 0.8)
        cr.fill_preserve()

        cr.set_source_rgb(0, 0, 0)
        cr.set_line_width(1)
        cr.stroke()

        layout = print_ctx.create_pango_layout()
        desc = Pango.FontDescription('sans 14')
        layout.set_font_description(desc)

        layout.set_text(print_data['filename'], -1)
        (text_width, text_height) = layout.get_pixel_size()

        if text_width > width:
            layout.set_width(width)
            layout.set_ellipsize(Pango.EllipsizeMode.START)
            (text_width, text_height) = layout.get_pixel_size()

        cr.move_to((width - text_width) / 2,
                   (self.HEADER_HEIGHT - text_height) / 2)
        PangoCairo.show_layout(cr, layout)

        page_str = "%d/%d" % (page_num + 1, print_data['num_pages'])
        layout.set_text(page_str, -1)

        layout.set_width(-1)
        (text_width, text_height) = layout.get_pixel_size()
        cr.move_to(width - text_width - 4,
                   (self.HEADER_HEIGHT - text_height) / 2)
        PangoCairo.show_layout(cr, layout)

        layout = print_ctx.create_pango_layout()

        desc = Pango.FontDescription('monospace')
        desc.set_size(print_data['font_size'] * Pango.SCALE)
        layout.set_font_description(desc)

        cr.move_to(0, self.HEADER_HEIGHT + self.HEADER_GAP)
        lines_pp = int(print_data['lines_per_page'])
        num_lines = print_data['num_lines']
        data_lines = print_data['lines']
        font_size = print_data['font_size']
        line = page_num * lines_pp

        for i in range(lines_pp):
            if line >= num_lines:
                break

            layout.set_text(data_lines[line], -1)
            PangoCairo.show_layout(cr, layout)
            cr.rel_move_to(0, font_size)
            line += 1

    def end_print(self, operation, print_ctx, print_data):
        pass


def main(demoapp=None):
    app = PrintingApp()
    GLib.idle_add(app.run, demoapp.window)
    Gtk.main()


if __name__ == '__main__':
    main()
