c++-gtk-utils
|
00001 /* Copyright (C) 2007 to 2011 Chris Vine 00002 00003 The library comprised in this file or of which this file is part is 00004 distributed by Chris Vine under the GNU Lesser General Public 00005 License as follows: 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public License 00009 as published by the Free Software Foundation; either version 2.1 of 00010 the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, but 00013 WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License, version 2.1, for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License, version 2.1, along with this library (see the file LGPL.TXT 00019 which came with this source code package in the c++-gtk-utils 00020 sub-directory); if not, write to the Free Software Foundation, Inc., 00021 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. 00022 00023 */ 00024 00025 #ifndef CGU_TEXT_PRINTMANAGER_H 00026 #define CGU_TEXT_PRINTMANAGER_H 00027 00028 #include <vector> 00029 #include <string> 00030 #include <memory> 00031 00032 #include <gtk/gtk.h> 00033 #include <pango/pango-layout.h> 00034 #include <glib-object.h> 00035 00036 00037 #include <c++-gtk-utils/intrusive_ptr.h> 00038 #include <c++-gtk-utils/shared_handle.h> 00039 #include <c++-gtk-utils/gobj_handle.h> 00040 #include <c++-gtk-utils/notifier.h> 00041 #include <c++-gtk-utils/mutex.h> 00042 #include <c++-gtk-utils/cgu_config.h> 00043 00044 00045 namespace Cgu { 00046 00047 #ifndef DOXYGEN_PARSING 00048 00049 // deleter functor for SharedHandle 00050 class TPMPangoLayoutIterFree { 00051 public: 00052 void operator()(PangoLayoutIter* obj_p) { 00053 if (obj_p) { 00054 pango_layout_iter_free(obj_p); 00055 } 00056 } 00057 }; 00058 00059 typedef SharedHandle<PangoLayoutIter*, TPMPangoLayoutIterFree> TPMPangoLayoutIterSharedHandle; 00060 00061 #endif // DOXYGEN_PARSING 00062 00063 /** 00064 * @class TextPrintManager text_print_manager.h c++-gtk-utils/text_print_manager.h 00065 * @brief A class to print plain text using the GTK+ print system. 00066 * 00067 * The TextPrintManager class prints text (say, from a GtkTextBuffer 00068 * object or from a plain text file) using the GTK+ printer interface. 00069 * To obtain a TextPrintManager object, call 00070 * TextPrintManager::create_manager(). TextPrintManager::set_text() 00071 * passes the text to be printed. The text passed with 00072 * TextPrintManager::set_text() must form valid UTF-8 (all ASCII 00073 * characters form valid UTF-8). To print the text entered, call 00074 * TextPrintManager::print(). The TextPrintManager::view() and 00075 * TextPrintManager::print_to_file() methods are also available. 00076 * 00077 * The TextPrintManager::page_setup() method can be used as a callback 00078 * to display a document page setup dialog prior to printing, and this 00079 * method should only be called in the thread in which the main GTK+ 00080 * event loop runs. It is a static method (a TextPrintManager object 00081 * does not need to have been created before it is called). 00082 * 00083 * Once TextPrintManager::print(), TextPrintManager::view() or 00084 * TextPrintManager::print_to_file() has been called, the 00085 * TextPrintManager class owns a reference to itself and so manages 00086 * its own lifetime - so once one of the methods has been called it 00087 * doesn't matter if the IntrusivePtr object returned by 00088 * TextPrintManager::create_manager() goes out of scope (however, once 00089 * TextPrintManager::print(), TextPrintManager::view() or 00090 * TextPrintManager::print_to_file() has been called, the object will 00091 * not be deleted until both printing has completed or failed AND the 00092 * IntrusivePtr object returned by TextPrintManager::create_manager() 00093 * has gone out of scope or has been reset()). 00094 * 00095 * Normally, a user would probably only want to use any one 00096 * TextPrintManager object to print a single print job (it has been 00097 * designed with that in mind). Nevertheless, if a reference to the 00098 * object is kept alive via an active IntrusivePtr object, it can be 00099 * used to print more than one print job. However, if that is done it 00100 * is not possible to called TextPrintManager::print() 00101 * TextPrintManager::view(), TextPrintManager::print_to_file() or 00102 * TextPrintManager::set_text() until the previous print job (if any) 00103 * has been dispatched to the GTK+ print system (or cancelled). If 00104 * the TextPrintManager object is not ready because it is in the 00105 * middle of handling an earlier print job, then the call to 00106 * TextPrintManager::print(), TextPrintManager::view(), 00107 * TextPrintManager::print_to_file() or TextPrintManager::set_text() 00108 * will return false; if however the new print job was successfully 00109 * started or text successfully set, they will return true. It is not 00110 * necessary to check the return value of these methods for the first 00111 * print job despatched by any one TextPrintManager object. 00112 * 00113 * TextPrintManager::print_to_file() will also return false if no file 00114 * name to which to print was specified. 00115 */ 00116 00117 class TextPrintManager: public IntrusiveLockCounter { 00118 enum Mode {print_mode, view_mode, file_mode} mode; 00119 00120 Thread::Mutex mutex; 00121 GtkWindow* parent_p; 00122 GobjHandle<PangoLayout> text_layout_h; 00123 int current_line; 00124 TPMPangoLayoutIterSharedHandle current_line_iter_h; 00125 std::unique_ptr<std::string> text_u; 00126 std::string file_name; 00127 std::vector<int> pages; 00128 Notifier print_notifier; 00129 std::string font_family; 00130 int font_size; 00131 bool ready; 00132 bool cancelled_when_drawing; 00133 00134 GobjHandle<GtkWidget> font_entry_h; 00135 GobjHandle<GtkWidget> font_size_spin_button_h; 00136 00137 static GobjHandle<GtkPrintSettings> print_settings_h; 00138 static GobjHandle<GtkPageSetup> page_setup_h; 00139 static std::string default_font_family; 00140 static int default_font_size; 00141 00142 void paginate(GtkPrintContext*); 00143 void print_text(); 00144 void begin_print_impl(GtkPrintOperation*, GtkPrintContext*); 00145 void draw_page_impl(GtkPrintOperation*, GtkPrintContext*, int); 00146 GObject* create_custom_widget_impl(GtkPrintOperation*); 00147 static void strip(std::string&); 00148 00149 // private constructor 00150 TextPrintManager() {} 00151 public: 00152 #ifndef DOXYGEN_PARSING 00153 // this helper class avoids exposing GObject callbacks with C 00154 // linkage to the global namespace 00155 class CB; 00156 friend class CB; 00157 #endif 00158 /** 00159 * This class cannot be copied: it is intended to be held by 00160 * IntrusivePtr. The copy constructor is deleted. 00161 */ 00162 TextPrintManager(const TextPrintManager&) = delete; 00163 00164 /** 00165 * This class cannot be copied: it is intended to be held by 00166 * IntrusivePtr. The assignment operator is deleted. 00167 */ 00168 TextPrintManager& operator=(const TextPrintManager&) = delete; 00169 00170 /** 00171 * Creates a new TextPrintManager object. No GTK+/GDK functions are 00172 * called by this method, and it is thread safe provided that, if it 00173 * is called in a thread other than the one in which the GTK+ event 00174 * loop runs, Cgu::Notifier::init() has previously been called in the 00175 * GTK+ event loop thread. 00176 * @param parent The parent of the print dialog which will be created 00177 * by the TextPrintManager object (optional, NULL may be passed). 00178 * @param font_family If a particular font is wanted, then this can be 00179 * entered as the font_family and font_size arguments to this method.. 00180 * If the default of an empty string for font_family is used, then 00181 * printing will use the previous font family setting (if any), or if 00182 * not a font of "Mono". The font passed in this method can in any 00183 * event be overridden from the "Print font" page in the print dialog. 00184 * @param font_size If a particular font is wanted, then this can be 00185 * entered as the font_family and font_size arguments to this method.. 00186 * If the default of 0 for font_size is used, then printing will use 00187 * the previous font size setting (if any), or if not a size of 00188 * 10. The font passed in this method can in any event be overridden 00189 * from the "Print font" page in the print dialog. If a font size is 00190 * passed as an argument, then the value must be 0 (default) or 00191 * between 8 and 24 (actual). 00192 * @exception std::bad_alloc This method might throw std::bad_alloc if 00193 * memory is exhausted and the system throws in that case. 00194 * @exception Cgu::Thread::MutexError This method might throw 00195 * Cgu::Thread::MutexError if initialisation of the contained mutex 00196 * fails. (It is often not worth checking for this, as it means 00197 * either memory is exhausted or pthread has run out of other 00198 * resources to create new mutexes.) 00199 * @exception Cgu::PipeError This method might throw Cgu::PipeError if 00200 * the contained Notifier object is the first Notifier object in the 00201 * program to be constructed and Cgu::Notifier::init() has not 00202 * previously been called. 00203 */ 00204 static Cgu::IntrusivePtr<Cgu::TextPrintManager> create_manager(GtkWindow* parent = 0, 00205 const std::string& font_family = "", 00206 int font_size = 0); 00207 00208 /** 00209 * Runs a page set-up dialog. (If no settings are set using this 00210 * dialog, then page defaults will be used with a page margin of 15 00211 * millimetres.) In a multi-threaded program, this must be called in 00212 * the thread in which the main GTK+ event loop runs. If the program 00213 * by which it is called calls GTK+ directly in more than one thread 00214 * and thus employs gdk_threads_enter()/gdk_threads_leave() (rather 00215 * than, say, Cgu::Notifier or Cgu::Callback::post()), it must also be 00216 * surrounded by gdk_threads_enter()/gdk_threads_leave() if called 00217 * otherwise than in a GTK+ signal handler. (The best approach 00218 * however is for a program only to address GTK+/GDK in the main 00219 * program thread, for which purpose this library provides various 00220 * functions and classes for inter-thread communication, such as 00221 * Cgu::Notifier and Cgu::Callback::post().) It will not throw. 00222 * @param parent The parent of the page set-up dialog which will be 00223 * created by the TextPrintManager object (optional, NULL may be 00224 * passed). 00225 */ 00226 static void page_setup(GtkWindow* parent = 0); 00227 00228 /** 00229 * Sets the text to be printed. This method is thread-safe and may be 00230 * called in any thread. No GTK+/GDK functions are called. It will 00231 * not throw. 00232 * @param text The text to be printed. It must be in valid UTF-8 00233 * format. Ownership is taken of the text string (a move operation is 00234 * carried out) unless false is returned. 00235 * @return Returns true, unless the same TextPrintManager object is 00236 * being used to print more than one print job and when this method is 00237 * called it is already printing another print job (in which case it 00238 * returns false). If it returns false, ownership is not taken of the 00239 * text string (it can be reused). 00240 * @note If the library is compiled using the --with-auto-ptr 00241 * configuration option, then this function's signature is bool 00242 * set_text(std::auto_ptr<std::string>& text) in order to retain 00243 * compatibility with the 1.2 series of the library. 00244 */ 00245 // for efficiency reasons (the string could hold a lot of text and we do not 00246 // want more copies than necessary hanging around) the text is passed by 00247 // reference (by std::unique_ptr<>). We pass by std::unique_ptr so that the 00248 // string cannot be modified after it has been passed to the TextPrintManager 00249 // object - we take ownership of it 00250 #ifdef CGU_USE_AUTO_PTR 00251 bool set_text(std::auto_ptr<std::string>& text); 00252 #else 00253 bool set_text(std::unique_ptr<std::string>& text); 00254 #endif 00255 00256 /** 00257 * Prints the text set with set_text(). This method is thread-safe 00258 * and may be called in any thread (it hands off its work to the main 00259 * program thread via a Cgu::Notifier object), unless the program by 00260 * which it is called calls GTK+ directly in more than one thread and 00261 * thus employs gdk_threads_enter()/gdk_threads_leave() (rather than, 00262 * say, Cgu::Notifier or Cgu::Callback::post()), in which case it must 00263 * be called in the main GUI thread only and surrounded by 00264 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in 00265 * a GTK+ signal handler. (The best approach however is for a program 00266 * only to address GTK+/GDK in the main program thread, for which 00267 * purpose this library provides various functions and classes for 00268 * inter-thread communication, such as Cgu::Notifier and 00269 * Cgu::Callback::post().) 00270 * @return Returns true, unless the same TextPrintManager object is 00271 * being used to print more than one print job and when this method is 00272 * called it is already printing another print job (in which case it 00273 * returns false). 00274 * @exception std::bad_alloc This method might throw std::bad_alloc if 00275 * memory is exhausted and the system throws in that case, but only if 00276 * it is called in the main program thread. Otherwise it will not 00277 * throw. 00278 */ 00279 bool print(); 00280 00281 /** 00282 * Provides a print pre-view of the text set with set_text(). This 00283 * method is thread-safe and may be called in any thread (it hands off 00284 * its work to the main program thread via a Cgu::Notifier object), 00285 * unless the program by which it is called calls GTK+ directly in 00286 * more than one thread and thus employs 00287 * gdk_threads_enter()/gdk_threads_leave() (rather than, say, 00288 * Cgu::Notifier or Cgu::Callback::post()), in which case it must be 00289 * called in the main GUI thread only and surrounded by 00290 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in 00291 * a GTK+ signal handler. (The best approach however is for a program 00292 * only to address GTK+/GDK in the main program thread, for which 00293 * purpose this library provides various functions and classes for 00294 * inter-thread communication, such as Cgu::Notifier and 00295 * Cgu::Callback::post().) 00296 * @return Returns true, unless the same TextPrintManager object is 00297 * being used to print more than one print job and when this method is 00298 * called it is already printing another print job (in which case it 00299 * returns false). 00300 * @exception std::bad_alloc This method might throw std::bad_alloc if 00301 * memory is exhausted and the system throws in that case, but only if 00302 * it is called in the main program thread. Otherwise it will not 00303 * throw. 00304 */ 00305 bool view(); 00306 00307 /** 00308 * Prints the text set with set_text() to file. This method is 00309 * thread-safe and may be called in any thread (it hands off its work 00310 * to the main program thread via a Cgu::Notifier object), unless the 00311 * program by which it is called calls GTK+ directly in more than one 00312 * thread and thus employs gdk_threads_enter()/gdk_threads_leave() 00313 * (rather than, say, Cgu::Notifier or Cgu::Callback::post()), in 00314 * which case it must be called in the main GUI thread only and 00315 * surrounded by gdk_threads_enter()/gdk_threads_leave() if called 00316 * otherwise than in a GTK+ signal handler. (The best approach 00317 * however is for a program only to address GTK+/GDK in the main 00318 * program thread, for which purpose this library provides various 00319 * functions and classes for inter-thread communication, such as 00320 * Cgu::Notifier and Cgu::Callback::post().) 00321 * @param filename The filename of the file to which the text is to be 00322 * printed. 00323 * @return Returns true, unless the same TextPrintManager object is 00324 * being used to print more than one print job and when this method is 00325 * called it is already printing another print job, or no filename to 00326 * print was specified (in either of which case it returns false). 00327 * @exception std::bad_alloc This method might throw std::bad_alloc if 00328 * memory is exhausted and the system throws in that case. 00329 */ 00330 bool print_to_file(const char* filename); 00331 00332 /** 00333 * The destructor will not throw. It is thread safe (the 00334 * TextPrintManager object may be destroyed in any thread), and does 00335 * not call any GTK+/GDK functions. 00336 */ 00337 ~TextPrintManager(); 00338 00339 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT 00340 CGU_GLIB_MEMORY_SLICES_FUNCS 00341 #endif 00342 }; 00343 00344 } // namespace Cgu 00345 00346 #endif // TEXT_PRINTMANAGER_H