c++-gtk-utils
text_print_manager.h
Go to the documentation of this file.
1 /* Copyright (C) 2007 to 2010 and 2013 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 */
24 
25 #ifndef CGU_TEXT_PRINTMANAGER_H
26 #define CGU_TEXT_PRINTMANAGER_H
27 
28 #include <vector>
29 #include <string>
30 #include <memory>
31 
33 
34 #ifdef CGU_USE_GTK
35 #include <gtk/gtk.h>
36 #include <pango/pango-layout.h>
37 #include <glib-object.h>
38 #endif
39 
43 #include <c++-gtk-utils/notifier.h>
44 #include <c++-gtk-utils/mutex.h>
45 
46 
47 namespace Cgu {
48 
49 #if defined(DOXYGEN_PARSING) || defined(CGU_USE_GTK)
50 
51 #ifndef DOXYGEN_PARSING
52 
53 // deleter functor for SharedHandle
54 class TPMPangoLayoutIterFree {
55 public:
56  void operator()(PangoLayoutIter* obj_p) {
57  if (obj_p) {
58  pango_layout_iter_free(obj_p);
59  }
60  }
61 };
62 
63 typedef SharedHandle<PangoLayoutIter*, TPMPangoLayoutIterFree> TPMPangoLayoutIterSharedHandle;
64 
65 #endif // DOXYGEN_PARSING
66 
67 /**
68  * @class TextPrintManager text_print_manager.h c++-gtk-utils/text_print_manager.h
69  * @brief A class to print plain text using the GTK+ print system.
70  *
71  * The TextPrintManager class prints text (say, from a GtkTextBuffer
72  * object or from a plain text file) using the GTK+ printer interface.
73  * To obtain a TextPrintManager object, call
74  * TextPrintManager::create_manager(). TextPrintManager::set_text()
75  * passes the text to be printed. The text passed with
76  * TextPrintManager::set_text() must form valid UTF-8 (all ASCII
77  * characters form valid UTF-8). To print the text entered, call
78  * TextPrintManager::print(). The TextPrintManager::view() and
79  * TextPrintManager::print_to_file() methods are also available.
80  *
81  * The TextPrintManager::page_setup() method can be used as a callback
82  * to display a document page setup dialog prior to printing, and this
83  * method should only be called in the thread in which the main GTK+
84  * event loop runs. It is a static method (a TextPrintManager object
85  * does not need to have been created before it is called).
86  *
87  * Once TextPrintManager::print(), TextPrintManager::view() or
88  * TextPrintManager::print_to_file() has been called, the
89  * TextPrintManager class owns a reference to itself and so manages
90  * its own lifetime - so once one of the methods has been called it
91  * doesn't matter if the IntrusivePtr object returned by
92  * TextPrintManager::create_manager() goes out of scope (however, once
93  * TextPrintManager::print(), TextPrintManager::view() or
94  * TextPrintManager::print_to_file() has been called, the object will
95  * not be deleted until both printing has completed or failed AND the
96  * IntrusivePtr object returned by TextPrintManager::create_manager()
97  * has gone out of scope or has been reset()).
98  *
99  * Normally, a user would probably only want to use any one
100  * TextPrintManager object to print a single print job (it has been
101  * designed with that in mind). Nevertheless, if a reference to the
102  * object is kept alive via an active IntrusivePtr object, it can be
103  * used to print more than one print job. However, if that is done it
104  * is not possible to called TextPrintManager::print()
105  * TextPrintManager::view(), TextPrintManager::print_to_file() or
106  * TextPrintManager::set_text() until the previous print job (if any)
107  * has been dispatched to the GTK+ print system (or cancelled). If
108  * the TextPrintManager object is not ready because it is in the
109  * middle of handling an earlier print job, then the call to
110  * TextPrintManager::print(), TextPrintManager::view(),
111  * TextPrintManager::print_to_file() or TextPrintManager::set_text()
112  * will return false; if however the new print job was successfully
113  * started or text successfully set, they will return true. It is not
114  * necessary to check the return value of these methods for the first
115  * print job despatched by any one TextPrintManager object.
116  *
117  * TextPrintManager::print_to_file() will also return false if no file
118  * name to which to print was specified.
119  *
120  * This class is not compiled into the library if the library is built
121  * with the \--without-gtk configuration option.
122  */
123 
125  enum Mode {print_mode, view_mode, file_mode} mode;
126 
127  Thread::Mutex mutex;
128  GtkWindow* parent_p;
129  GobjHandle<PangoLayout> text_layout_h;
130  int current_line;
131  TPMPangoLayoutIterSharedHandle current_line_iter_h;
132  std::auto_ptr<std::string> text_a;
133  std::string file_name;
134  std::vector<int> pages;
135  Notifier print_notifier;
136  std::string font_family;
137  int font_size;
138  bool ready;
139  bool cancelled_when_drawing;
140 
141  GobjHandle<GtkWidget> font_entry_h;
142  GobjHandle<GtkWidget> font_size_spin_button_h;
143 
144  static GobjHandle<GtkPrintSettings> print_settings_h;
145  static GobjHandle<GtkPageSetup> page_setup_h;
146  static std::string default_font_family;
147  static int default_font_size;
148 
149  void paginate(GtkPrintContext*);
150  void print_text();
151  void begin_print_impl(GtkPrintOperation*, GtkPrintContext*);
152  void draw_page_impl(GtkPrintOperation*, GtkPrintContext*, int);
153  GObject* create_custom_widget_impl(GtkPrintOperation*);
154  static void strip(std::string&);
155  // private constructor
156  TextPrintManager() {}
157  // and this class may not be copied
159  TextPrintManager& operator=(const TextPrintManager&);
160 public:
161 #ifndef DOXYGEN_PARSING
162  // this helper class avoids exposing GObject callbacks with C
163  // linkage to the global namespace
164  class CB;
165  friend class CB;
166 #endif
167 
168 /**
169  * Creates a new TextPrintManager object. No GTK+/GDK functions are
170  * called by this method, and it is thread safe provided that, if it
171  * is called in a thread other than the one in which the GTK+ event
172  * loop runs, Cgu::Notifier::init() has previously been called in the
173  * GTK+ event loop thread.
174  * @param parent The parent of the print dialog which will be created
175  * by the TextPrintManager object (optional, NULL may be passed).
176  * @param font_family If a particular font is wanted, then this can be
177  * entered as the font_family and font_size arguments to this method..
178  * If the default of an empty string for font_family is used, then
179  * printing will use the previous font family setting (if any), or if
180  * not a font of "Mono". The font passed in this method can in any
181  * event be overridden from the "Print font" page in the print dialog.
182  * @param font_size If a particular font is wanted, then this can be
183  * entered as the font_family and font_size arguments to this method..
184  * If the default of 0 for font_size is used, then printing will use
185  * the previous font size setting (if any), or if not a size of
186  * 10. The font passed in this method can in any event be overridden
187  * from the "Print font" page in the print dialog. If a font size is
188  * passed as an argument, then the value must be 0 (default) or
189  * between 8 and 24 (actual).
190  * @exception std::bad_alloc This method might throw std::bad_alloc if
191  * memory is exhausted and the system throws in that case.
192  * @exception Cgu::Thread::MutexError This method might throw
193  * Cgu::Thread::MutexError if initialisation of the contained mutex
194  * fails. (It is often not worth checking for this, as it means
195  * either memory is exhausted or pthread has run out of other
196  * resources to create new mutexes.)
197  * @exception Cgu::PipeError This method might throw Cgu::PipeError if
198  * the contained Notifier object is the first Notifier object in the
199  * program to be constructed and Cgu::Notifier::init() has not
200  * previously been called.
201  */
202  static Cgu::IntrusivePtr<Cgu::TextPrintManager> create_manager(GtkWindow* parent = 0,
203  const std::string& font_family = "",
204  int font_size = 0);
205 
206 /**
207  * Runs a page set-up dialog. (If no settings are set using this
208  * dialog, then page defaults will be used with a page margin of 15
209  * millimetres.) In a multi-threaded program, this must be called in
210  * the thread in which the main GTK+ event loop runs. If the program
211  * by which it is called calls GTK+ directly in more than one thread
212  * and thus employs gdk_threads_enter()/gdk_threads_leave() (rather
213  * than, say, Cgu::Notifier or Cgu::Callback::post()), it must also be
214  * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
215  * otherwise than in a GTK+ signal handler. (The best approach
216  * however is for a program only to address GTK+/GDK in the main
217  * program thread, for which purpose this library provides various
218  * functions and classes for inter-thread communication, such as
219  * Cgu::Notifier and Cgu::Callback::post().) It will not throw.
220  * @param parent The parent of the page set-up dialog which will be
221  * created by the TextPrintManager object (optional, NULL may be
222  * passed).
223  */
224  static void page_setup(GtkWindow* parent = 0);
225 
226 /**
227  * Sets the text to be printed. This method is thread-safe and may be
228  * called in any thread. No GTK+/GDK functions are called. It will
229  * not throw.
230  * @param text The text to be printed. It must be in valid UTF-8
231  * format. Ownership is taken of the text string (a move operation is
232  * carried out) unless false is returned.
233  * @return Returns true, unless the same TextPrintManager object is
234  * being used to print more than one print job and when this method is
235  * called it is already printing another print job (in which case it
236  * returns false). If it returns false, ownership is not taken of the
237  * text string (it can be reused).
238  */
239  // for efficiency reasons (the string could hold a lot of text and we do not
240  // want more copies than necessary hanging around) the text is passed by
241  // reference (by std::auto_ptr<>). We pass by std::auto_ptr so that the
242  // string cannot be modified after it has been passed to the TextPrintManager
243  // object - we take ownership of it
244  bool set_text(std::auto_ptr<std::string>& text);
245 
246 /**
247  * Prints the text set with set_text(). This method is thread-safe
248  * and may be called in any thread (it hands off its work to the main
249  * program thread via a Cgu::Notifier object), unless the program by
250  * which it is called calls GTK+ directly in more than one thread and
251  * thus employs gdk_threads_enter()/gdk_threads_leave() (rather than,
252  * say, Cgu::Notifier or Cgu::Callback::post()), in which case it must
253  * be called in the main GUI thread only and surrounded by
254  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
255  * a GTK+ signal handler. (The best approach however is for a program
256  * only to address GTK+/GDK in the main program thread, for which
257  * purpose this library provides various functions and classes for
258  * inter-thread communication, such as Cgu::Notifier and
259  * Cgu::Callback::post().)
260  * @return Returns true, unless the same TextPrintManager object is
261  * being used to print more than one print job and when this method is
262  * called it is already printing another print job (in which case it
263  * returns false).
264  * @exception std::bad_alloc This method might throw std::bad_alloc if
265  * memory is exhausted and the system throws in that case, but only if
266  * it is called in the main program thread. Otherwise it will not
267  * throw.
268  */
269  bool print();
270 
271 /**
272  * Provides a print pre-view of the text set with set_text(). This
273  * method is thread-safe and may be called in any thread (it hands off
274  * its work to the main program thread via a Cgu::Notifier object),
275  * unless the program by which it is called calls GTK+ directly in
276  * more than one thread and thus employs
277  * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
278  * Cgu::Notifier or Cgu::Callback::post()), in which case it must be
279  * called in the main GUI thread only and surrounded by
280  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
281  * a GTK+ signal handler. (The best approach however is for a program
282  * only to address GTK+/GDK in the main program thread, for which
283  * purpose this library provides various functions and classes for
284  * inter-thread communication, such as Cgu::Notifier and
285  * Cgu::Callback::post().)
286  * @return Returns true, unless the same TextPrintManager object is
287  * being used to print more than one print job and when this method is
288  * called it is already printing another print job (in which case it
289  * returns false).
290  * @exception std::bad_alloc This method might throw std::bad_alloc if
291  * memory is exhausted and the system throws in that case, but only if
292  * it is called in the main program thread. Otherwise it will not
293  * throw.
294  */
295  bool view();
296 
297 /**
298  * Prints the text set with set_text() to file. This method is
299  * thread-safe and may be called in any thread (it hands off its work
300  * to the main program thread via a Cgu::Notifier object), unless the
301  * program by which it is called calls GTK+ directly in more than one
302  * thread and thus employs gdk_threads_enter()/gdk_threads_leave()
303  * (rather than, say, Cgu::Notifier or Cgu::Callback::post()), in
304  * which case it must be called in the main GUI thread only and
305  * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
306  * otherwise than in a GTK+ signal handler. (The best approach
307  * however is for a program only to address GTK+/GDK in the main
308  * program thread, for which purpose this library provides various
309  * functions and classes for inter-thread communication, such as
310  * Cgu::Notifier and Cgu::Callback::post().)
311  * @param filename The filename of the file to which the text is to be
312  * printed.
313  * @return Returns true, unless the same TextPrintManager object is
314  * being used to print more than one print job and when this method is
315  * called it is already printing another print job, or no filename to
316  * print was specified (in either of which case it returns false).
317  * @exception std::bad_alloc This method might throw std::bad_alloc if
318  * memory is exhausted and the system throws in that case.
319  */
320  bool print_to_file(const char* filename);
321 
322 /**
323  * The destructor will not throw. It is thread safe (the
324  * TextPrintManager object may be destroyed in any thread), and does
325  * not call any GTK+/GDK functions.
326  */
328 
329 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
331 #endif
332 };
333 
334 #endif // CGU_USE_GTK
335 
336 } // namespace Cgu
337 
338 #endif // TEXT_PRINTMANAGER_H
Cgu::TextPrintManager::set_text
bool set_text(std::auto_ptr< std::string > &text)
Cgu
Definition: application.h:45
Cgu::TextPrintManager::page_setup
static void page_setup(GtkWindow *parent=0)
Cgu::GobjHandle< PangoLayout >
Cgu::IntrusivePtr
This is a smart pointer for managing objects allocated on freestore which maintain their own referenc...
Definition: intrusive_ptr.h:106
Cgu::TextPrintManager::print_to_file
bool print_to_file(const char *filename)
Cgu::TextPrintManager
A class to print plain text using the GTK+ print system.
Definition: text_print_manager.h:124
intrusive_ptr.h
Cgu::Notifier
Provides thread-safe signalling between a worker thread and the main program thread.
Definition: notifier.h:181
gobj_handle.h
Cgu::TextPrintManager::create_manager
static Cgu::IntrusivePtr< Cgu::TextPrintManager > create_manager(GtkWindow *parent=0, const std::string &font_family="", int font_size=0)
Cgu::TextPrintManager::~TextPrintManager
~TextPrintManager()
notifier.h
This file provides a Notifier class to provide thread-safe signalling between a worker thread and the...
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
shared_handle.h
Cgu::IntrusiveLockCounter
This is a counter class providing the ref() and unref() functions required by IntrusivePtr,...
Definition: intrusive_ptr.h:317
mutex.h
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Cgu::TextPrintManager::print
bool print()
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:109
cgu_config.h
Cgu::TextPrintManager::view
bool view()