Gtk+ printing dialog highlevel thoughts

(cc:ing some people who I think might be interested in this)
I've just started looking at doing a printing dialog for Gtk+
2.10. For some background thoughts from owen, see:

I've started studying various platform APIs and UIs, cups, PPDs, etc,
preparing for this. To compare various platform and application
printing dialogs I have put together a set of screenshots from
Linux/OSX/Windows at:

I'm going to start on a very high level, discussing the general API
and implementation. The dialog contents and layout details can be
discussed later.

There are various use cases for a printing dialog. Here is a shot at
listing the important ones:

* Simple incremental print
  For example a raw text editor. The document isn't affected by the
  printer/page details, and we don't do e.g. pagination until print 
  time. No customization of print dialogs needed.

* Simple page-oriented document print
  WYSIWYG page editing where pagination and other things are affected
  by printer settings (such as page size) and are done before actual
  printing. No customization of print dialogs needed.

* standard printing with customization
  The app uses the standard way to print, but needs some custom
  widgetry in the printing dialog(s). (for instance: scaling,
  positioning, headers/footers, HTML frame handling, etc)

* Printing photos
  This is (these days) a pretty common task, but substantially
  different from what the traditional print dialogs are made to
  support. We could make this a standard type of dialog simplifying
  such printing. See the e.g. the "easy" print dialog in OSX in
  the screenshots above.

* Using the Gtk+ dialog as a native print dialog
  For instance, OOo could use the Gtk+ print dialog for its printing
  UI on Linux/Unix, but then not use the Gtk+ print system (cairo) to
  print, instead going directly to the lowlevel printing system and
  use its own postscript generation.

* Printing without a UI
  Its very useful for applications to be able to print without opening
  a dialog. For instance by passing "--print <file>" on the command
  line. In this case it would be nice if the Gtk+ printing system
  supported a headless mode that didn't need a connection to the
  Display, but still allowed one to use the same printing code.

One important question that owen brough up is the "Can we/can we not
use the native UI?". If we go with native dialogs we loose a certain
amount of customizability, we get a bit more non-standard APIs
(i.e. we're unable to use GtkDialog derived objects), and we're a bit
limited in what the dialogs can do (least-common denominator of
features, although we might be able to do better with some work).

My opinion is that we should go with native dialogs. Printing dialogs
are already confusing enough that having to learn a totally new one is
a pain, and its probably gonna be very hard to make a print dialog
that works right on Windows, because I don't think all the required
APIs are availible. Furthermore, you'd loose driver-specific additions
to the printer dialogs that are availible in Windows/OSX.

I've been talking to the Tor on Win32 and Andersca on OSX, and both
think it should be possible (but not tested yet) to embedd gtk+
widgets into a native dialog, so if we're lucky we can allow some
generic way of adding custom widgets to the dialog. (Given the APIs on
OSX and Win32 this will likely be in the form of an extra tab page.)
If there is some simple common feature we want to support that is
missing on a particular platform we could customize the native dialog
from gtk itself so that all gtk apps would use the same ui for it, and
its availible on all platforms.

It might be wise to allow some amount of access to the
platform-specific objects so that advanced applications can do more
advanced customization using #ifdef.

The print dialog implementation has two parts. First the generic
portable API with implementations for the platform native dialogs, 
then the "native" dialog for Unix. In order to support the "Using the
Gtk+ dialog as a native print dialog" use-case we probably need to
expose this as a platform-specific api, with accessors similar to the
ones we have for accessing e.g. the win32 print dialog object. 

Both Windows and OSX have a standard "Page Setup" dialog. This is
typically used in the page-oriented document use-case where you need
some page/printer information before working on the
document. libgnomeui doesn't currently have anything like this, and
neither does KDE (although Qt4 has one).

I think we should have a Page Setup dialog, supporting the native
dialogs of the platforms. While using the native dialog here is less
important, since it does less "magic" than the print dialog, and there
is already a considerable amount of variation in this dialog I think
its important that at least simple print applications look "normal" on
the platform.

I think that we should set up the print dialogs such that you are
not required to use this page setup dialog, since many apps are gonna
want a totally custom page setup dialog. For instance, if a
work-processor supports per-page orientation and page size the default 
dialog just won't work. One possibility here is to expose both a
native dialog and a Gtk+ one. Then we can allow the gtk+ one to be
more customizable.

Another important feature that the generic API has to support is
some form of printing feedback (spinning icon while printing) and job
cancellation support.

I think the general print model should go something like:
* create a print job
* set settings on it (page settings etc)
* call the print method, bringing up the print dialog
* user sets options in dialog, presses print
* internally we get the underlying native object to print to (hDC,
  NSView, cups printer + PPD)
* internally we create a cairo context for the native object and
  pass it to the app
* the app draws stuff to the cairo context, possibly using some
  furter information from the print dialog result

The last drawing part can be done in several ways. Either procedurally
(just draw all the pages in order), or with some form of callback
driven system. The callbacks could either always be called in page
incremental order, or it could be random access given a page number as
argument. I think the callback driven, random access model is the
best. It allows us to handle things like "nr of copies" and collation
perfectly invisible from the app. It does put some higher demands on
simpler applications, i.e. you have to do pagination fully up-front,
but in almost all cases you want to do that anyway (e.g. to have "page
nr x of X" headers) so I don't think that is a problem.

Having a random access model allows us to easily do inline
mini-previews if we want to, which is nice. We probably should also
have a well defined API for "full size" print preview. This could
launch a document viewer (evince?) like OSX does, or use a normal
in-app dialog, in fact it could do different things on different

While this callback based, draw via cairo model is very nice for most
apps we still have to support some way to pass raw data to the
printer, in order to support the "Using the Gtk+ dialog as a native
print dialog" use-case. I think the best way to do this is to make
apps like this use the platform-specific (i.e. linux/cups only) dialog
API to show the dialog, and then just have it read the cups data from
the dialog and send data to cups manually.

We're gonna need various objects and interfaces in the API. I think we
need at least these public ones:
* a print job object, encapsulating the whole print process
* data information objects, storing information about the paper setup
  and printer details. I think its might be a good idea to split this
  up into two objects, one for page setup and one for print
  settings. Some APIs do this, some don't. I'm not sure of the
  pros/cons yet.
* printing callback object (or interface)
* objects for the non-native dialogs
* printer object, and a way to enumerate these
  (I'm not acutally sure a printer object is needed in the portable
   API. Maybe we can get away with hiding the actual printer selection
   in the printer dialog. This needs thinking.)

One interesting question about the data information objects is how much
we expose of them, and how. In many cases you don't actually need to
read that data to know how to print the document. For instance, if you
selected "staple" or "glossy finish" in the print dialog that just
gets passed to the printer, and doesn't affect the app. Even things
like "nr of pages" or collation doesn't affect things in a callback
driven model. However, apps still want to do things like save the last
used printer info, and save printer/page information in the
document. The information you get from the page setup dialog clearly
has to be standard and easily accessible to apps as it affects the
page layout, but some of the stuff that the print dialog sets up are
very esoteric. We should probably have ways to serialize these things
(in an as cross-platform way as possible so you can move documents
between platforms) without having to know what every setting means.

I'll continue to look into this, fleshing out my ideas even more. Any
feedback would be appreciated. 

 Alexander Larsson                                            Red Hat, Inc 
                   alexl redhat com    alla lysator liu se 
He's a jaded guitar-strumming barbarian moving from town to town, helping folk 
in trouble. She's a warm-hearted cat-loving magician's assistant with someone 
else's memories. They fight crime! 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]