c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

text_print_manager.h
Go to the documentation of this file.
1 /* Copyright (C) 2007, 2011 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
32 #include <c++-gtk-utils/cgu_config.h>
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
40 #include <c++-gtk-utils/intrusive_ptr.h>
41 #include <c++-gtk-utils/shared_handle.h>
42 #include <c++-gtk-utils/gobj_handle.h>
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
124 class TextPrintManager: public IntrusiveLockCounter {
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::unique_ptr<std::string> text_u;
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
156 // private constructor
157 TextPrintManager() {}
158 public:
159 #ifndef DOXYGEN_PARSING
160 // this helper class avoids exposing GObject callbacks with C
161 // linkage to the global namespace
162 class CB;
163 friend class CB;
164 #endif
165 /**
166 * This class cannot be copied: it is intended to be held by
167 * IntrusivePtr. The copy constructor is deleted.
168 */
169 TextPrintManager(const TextPrintManager&) = delete;
170
171 /**
172 * This class cannot be copied: it is intended to be held by
173 * IntrusivePtr. The assignment operator is deleted.
174 */
175 TextPrintManager& operator=(const TextPrintManager&) = delete;
176
177 /**
178 * Creates a new TextPrintManager object. No GTK+/GDK functions are
179 * called by this method, and it is thread safe provided that, if it
180 * is called in a thread other than the one in which the GTK+ event
181 * loop runs, Cgu::Notifier::init() has previously been called in the
182 * GTK+ event loop thread.
183 * @param parent The parent of the print dialog which will be created
184 * by the TextPrintManager object (optional, NULL may be passed).
185 * @param font_family If a particular font is wanted, then this can be
186 * entered as the font_family and font_size arguments to this method..
187 * If the default of an empty string for font_family is used, then
188 * printing will use the previous font family setting (if any), or if
189 * not a font of "Mono". The font passed in this method can in any
190 * event be overridden from the "Print font" page in the print dialog.
191 * @param font_size If a particular font is wanted, then this can be
192 * entered as the font_family and font_size arguments to this method..
193 * If the default of 0 for font_size is used, then printing will use
194 * the previous font size setting (if any), or if not a size of
195 * 10. The font passed in this method can in any event be overridden
196 * from the "Print font" page in the print dialog. If a font size is
197 * passed as an argument, then the value must be 0 (default) or
198 * between 8 and 24 (actual).
199 * @exception std::bad_alloc This method might throw std::bad_alloc if
200 * memory is exhausted and the system throws in that case.
201 * @exception Cgu::Thread::MutexError This method might throw
202 * Cgu::Thread::MutexError if initialisation of the contained mutex
203 * fails. (It is often not worth checking for this, as it means
204 * either memory is exhausted or pthread has run out of other
205 * resources to create new mutexes.)
206 * @exception Cgu::PipeError This method might throw Cgu::PipeError if
207 * the contained Notifier object is the first Notifier object in the
208 * program to be constructed and Cgu::Notifier::init() has not
209 * previously been called.
210 */
211 static Cgu::IntrusivePtr<Cgu::TextPrintManager> create_manager(GtkWindow* parent = 0,
212 const std::string& font_family = "",
213 int font_size = 0);
214
215 /**
216 * Runs a page set-up dialog. (If no settings are set using this
217 * dialog, then page defaults will be used with a page margin of 15
218 * millimetres.) In a multi-threaded program, this must be called in
219 * the thread in which the main GTK+ event loop runs. If the program
220 * by which it is called calls GTK+ directly in more than one thread
221 * and thus employs gdk_threads_enter()/gdk_threads_leave() (rather
222 * than, say, Cgu::Notifier or Cgu::Callback::post()), it must also be
223 * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
224 * otherwise than in a GTK+ signal handler. (The best approach
225 * however is for a program only to address GTK+/GDK in the main
226 * program thread, for which purpose this library provides various
227 * functions and classes for inter-thread communication, such as
228 * Cgu::Notifier and Cgu::Callback::post().) It will not throw.
229 * @param parent The parent of the page set-up dialog which will be
230 * created by the TextPrintManager object (optional, NULL may be
231 * passed).
232 */
233 static void page_setup(GtkWindow* parent = 0);
234
235 /**
236 * Sets the text to be printed. This method is thread-safe and may be
237 * called in any thread. No GTK+/GDK functions are called. It will
238 * not throw.
239 * @param text The text to be printed. It must be in valid UTF-8
240 * format. Ownership is taken of the text string (a move operation is
241 * carried out) unless false is returned.
242 * @return Returns true, unless the same TextPrintManager object is
243 * being used to print more than one print job and when this method is
244 * called it is already printing another print job (in which case it
245 * returns false). If it returns false, ownership is not taken of the
246 * text string (it can be reused).
247 */
248 // for efficiency reasons (the string could hold a lot of text and we do not
249 // want more copies than necessary hanging around) the text is passed by
250 // reference (by std::unique_ptr<>). We pass by std::unique_ptr so that the
251 // string cannot be modified after it has been passed to the TextPrintManager
252 // object - we take ownership of it
253 bool set_text(std::unique_ptr<std::string>& text);
254
255 /**
256 * Prints the text set with set_text(). This method is thread-safe
257 * and may be called in any thread (it hands off its work to the main
258 * program thread via a Cgu::Notifier object), unless the program by
259 * which it is called calls GTK+ directly in more than one thread and
260 * thus employs gdk_threads_enter()/gdk_threads_leave() (rather than,
261 * say, Cgu::Notifier or Cgu::Callback::post()), in which case it must
262 * be called in the main GUI thread only and surrounded by
263 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
264 * a GTK+ signal handler. (The best approach however is for a program
265 * only to address GTK+/GDK in the main program thread, for which
266 * purpose this library provides various functions and classes for
267 * inter-thread communication, such as Cgu::Notifier and
268 * Cgu::Callback::post().)
269 * @return Returns true, unless the same TextPrintManager object is
270 * being used to print more than one print job and when this method is
271 * called it is already printing another print job (in which case it
272 * returns false).
273 * @exception std::bad_alloc This method might throw std::bad_alloc if
274 * memory is exhausted and the system throws in that case, but only if
275 * it is called in the main program thread. Otherwise it will not
276 * throw.
277 */
278 bool print();
279
280 /**
281 * Provides a print pre-view of the text set with set_text(). This
282 * method is thread-safe and may be called in any thread (it hands off
283 * its work to the main program thread via a Cgu::Notifier object),
284 * unless the program by which it is called calls GTK+ directly in
285 * more than one thread and thus employs
286 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
287 * Cgu::Notifier or Cgu::Callback::post()), in which case it must be
288 * called in the main GUI thread only and surrounded by
289 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
290 * a GTK+ signal handler. (The best approach however is for a program
291 * only to address GTK+/GDK in the main program thread, for which
292 * purpose this library provides various functions and classes for
293 * inter-thread communication, such as Cgu::Notifier and
294 * Cgu::Callback::post().)
295 * @return Returns true, unless the same TextPrintManager object is
296 * being used to print more than one print job and when this method is
297 * called it is already printing another print job (in which case it
298 * returns false).
299 * @exception std::bad_alloc This method might throw std::bad_alloc if
300 * memory is exhausted and the system throws in that case, but only if
301 * it is called in the main program thread. Otherwise it will not
302 * throw.
303 */
304 bool view();
305
306 /**
307 * Prints the text set with set_text() to file. This method is
308 * thread-safe and may be called in any thread (it hands off its work
309 * to the main program thread via a Cgu::Notifier object), unless the
310 * program by which it is called calls GTK+ directly in more than one
311 * thread and thus employs gdk_threads_enter()/gdk_threads_leave()
312 * (rather than, say, Cgu::Notifier or Cgu::Callback::post()), in
313 * which case it must be called in the main GUI thread only and
314 * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
315 * otherwise than in a GTK+ signal handler. (The best approach
316 * however is for a program only to address GTK+/GDK in the main
317 * program thread, for which purpose this library provides various
318 * functions and classes for inter-thread communication, such as
319 * Cgu::Notifier and Cgu::Callback::post().)
320 * @param filename The filename of the file to which the text is to be
321 * printed.
322 * @return Returns true, unless the same TextPrintManager object is
323 * being used to print more than one print job and when this method is
324 * called it is already printing another print job, or no filename to
325 * print was specified (in either of which case it returns false).
326 * @exception std::bad_alloc This method might throw std::bad_alloc if
327 * memory is exhausted and the system throws in that case.
328 */
329 bool print_to_file(const char* filename);
330
331 /**
332 * The destructor will not throw. It is thread safe (the
333 * TextPrintManager object may be destroyed in any thread), and does
334 * not call any GTK+/GDK functions.
335 */
336 ~TextPrintManager();
337
338 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
339 CGU_GLIB_MEMORY_SLICES_FUNCS
340 #endif
341 };
342
343 #endif // CGU_USE_GTK
344
345 } // namespace Cgu
346
347 #endif // TEXT_PRINTMANAGER_H