GRAphical Programming for Eiffel index contents

Appendix J. Printing from GRAPE Applications

Surely GRAPE allows you to print everything. GRAPE concept of printers and printing is based on idea of Graphic context (GC), which is similar to window drawing. You can feel difference between printing and window drawing only in GC obtaining. GRAPE supports document-orienting model of printing. It means, that you must divide printer preparation and document preparation.

Printing example

At first let's see detailed printing process step-by-step. Making printable document. Here is the source code of printable document:

-- example of printable document
class DOCUMENT

inherit
   -- to make document printable you must inherit it from
   -- PRINTABLE_OBJECT
   PRINTABLE_OBJECT
     -- this is list of functions, you need to redefine.
     -- printing subsystem call it to print document
     redefine begin_print, end_print, on_print, has_page, num_pages
     end
feature

   begin_print( gc : GRAPHICS_CONTEXT ) is
   -- here you can prepare document to printing on graphic context
   -- retrieve all subdocuments, create pen and so on.
     do
     end

   end_print() is
   -- here you can release resources after printing
     do
     end

   on_print( gc : GRAPHICS_CONTEXT, page : INTEGER ) is
   -- main feature of printing document
   -- here you must print page number 'page' on gc
     do
       inspect
         page
       when 1 then
         print_1(gc);
       when 2 then
         print_2(gc);
       when 3 then
         print_3(gc);
       else
       end
     end

   has_page( page : INTEGER ) : BOOLEAN is
   -- this procedure calls before page printing
   -- return False, if page not ready and it will be skipped
     do
     Result := (page >= 1) and then (page <= 3);
     end

   num_pages() : INTEGER is
   -- return number of pages, you have in document
   -- you can count it via Client Area calculation.
     do
       Result := 3;
     end

   print_1( gc : GRAPHICS_CONTEXT) is
     do
       gc.put_string("Page 1 test", 20, 20);
     end

   print_2( gc : GRAPHICS_CONTEXT) is
     do
       gc.put_string("Page 2 test", 20, 20);
       gc.paint_circle(100, 100, 50);
     end

   print_3( gc : GRAPHICS_CONTEXT) is
     do
       gc.put_string("Page 3 test", 20, 20);
       gc.paint_rectangle(50, 50, 150, 150);
     end

end -- class DOCUMENT

Second part is insert code,  which is used to call printing into your program. As an example let's consider feature print_doc:

print_doc(doc : DOCUMENT) is
   local
     pr : PRINTER;
   do
     -- create printer based on default system printer
     !!pr.make_default;
     -- bind printer to document
     pr.set_printable_object(doc);
     -- print document
     pr.print("Test printing");
     -- release resources after printing
     pr.close;
   end

Document preparation

To make document printable, you must inherit it from PRINTABLE_OBJECT class. Then you must redefine some features. Here is the list of them in order they called.

begin_print( gc : GRAPHICS_CONTEXT )

First feature called for document. Allows you to initialize printing process, for example creating pens, brushes. Also allows you to calculate number of pages in your document. Use gc.client_area() to obtain size of one page.

num_pages() : INTEGER

Returns number of pages in document. Now you know how to calculate it. This function is called twice - after binding document to printer and before real printing. First call sets initial range of pages, then you can change it.

has_page( page : INTEGER ) : BOOLEAN

Calls before each page printing. Allows you to print pages you need and make sophisticated page selections, not only from-to scheme.

on_print( gc : GRAPHICS_CONTEXT, page : INTEGER )

Core function. Really prints page number 'page' on 'gc'. Uses usual graphic primitives on this gc, don't worry about real destination of primitives call.

How to choose printer

Now, your document is ready to print. What about printer selection? Really you have many ways to select printer for you action. All of them create and modify PRINTING_DEVICE object.

make_default
make ( driver, device, port : STRING )

To create printing device you can use creation functions make_default, make or choose printer dialog box. First way is the simplest, the additional parameters are not required. The second requires knowledge of driver, device and port name for printer. It's very system-dependent feature. The third call is discussed in the chapter about standard dialogs.

is_initialized : BOOLEAN
get_driver_name : STRING
get_device_name : STRING
get_port_name : STRING

After creation you can test device's name, driver's name and port name. You can also test device for correct initialization.

set_orientation ( val : INTEGER )
get_orientation : INTEGER

These calls allow you to select and test printer's orientation. Constants for this features are: 0 for portrait and 1 for landscape.

destroy

Releases printer after printing. For cases when you have no need to do it see below.

Class PRINTER

Really, you have no need in changing printer parameters. All work can be made in class PRINTER. It is the binder, which binds together printing device and printable document.

make_default ()
make ( p_device : PRINTING_DEVICE )

Creation features. First allows you to forget about printing device at all.

set_printable_object( p_printable : PRINTABLE_OBJECT )
get_printable_object() : PRINTABLE_OBJECT

Features to work with printable object. Bind it to PRINTER after creation.

get_printing_device() : PRINTING_DEVICE
get_default_printing_device() : PRINTING_DEVICE

Can be used for printing with low-level work devices.

set_orientation( p_orientation : INTEGER )
orientation() : INTEGER
PORTRAIT : INTEGER is 0;
LANDSCAPE : INTEGER is 1;
set_number_of_copies( p_copies : INTEGER )
set_range_of_pages( p_from, p_to : INTEGER )
from_page, to_page : INTEGER;
set_collate_copies( p_flag : BOOLEAN )
collate_copies : BOOLEAN;

Printing options. Allow you to setup orientation of document, number of copies and their range. Also allow you to select order of copies (document-by-document or the same pages in one time). It's usage is more preferable than changing it for PRINTING_DEVICE.

print( p_document_name : STRING )

Main feature. Start printing. Parameter is printing task name for system print manager.

close()

Releases printer resources. Calls destroy feature for printing device.

Useful add-on

You can also use print previewer. It's complicated class with simple interface. To use it, you must create print previewer dialog with printer as parameter, and execute this dialog. Look at sample function:

preview_print_doc is
   local
     pr : PRINTER;
     doc : DOCUMENT
     ppv : PRINT_PREVIEWER;
     i : INTEGER;
   do
     !!pr.make_default;
     !!doc;
     pr.set_printable_object(doc);
     !!ppv.make(pr);
     i := execute(ppv);
   end

© Object Tools -- info@object-tools.com -- December 1999