Mercurial > projects > dwt2
annotate org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/printing/Printer.d @ 113:fb3aa8075988
D2 support for the linux port.
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Wed, 06 Apr 2011 21:57:23 +0200 |
parents | c01d033c633a |
children |
rev | line source |
---|---|
25 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.printing.Printer; | |
14 | |
15 | |
16 | |
17 import org.eclipse.swt.SWT; | |
18 import org.eclipse.swt.SWTError; | |
19 import org.eclipse.swt.SWTException; | |
20 import org.eclipse.swt.graphics.Device; | |
21 import org.eclipse.swt.graphics.DeviceData; | |
22 import org.eclipse.swt.graphics.Font; | |
23 import org.eclipse.swt.graphics.GCData; | |
24 import org.eclipse.swt.graphics.Point; | |
25 import org.eclipse.swt.graphics.Rectangle; | |
49
7a2dd761a8b2
more work until dmd 2.026 linux segfaults.
Frank Benoit <benoit@tionex.de>
parents:
48
diff
changeset
|
26 import org.eclipse.swt.internal.cairo.Cairo : Cairo; |
25 | 27 import org.eclipse.swt.internal.gtk.OS; |
28 import org.eclipse.swt.printing.PrinterData; | |
29 import java.lang.all; | |
30 | |
48 | 31 version(Tango){ |
51 | 32 import tango.util.Convert; |
48 | 33 } else { // Phobos |
51 | 34 import std.conv; |
48 | 35 } |
25 | 36 |
37 | |
38 /** | |
39 * Instances of this class are used to print to a printer. | |
40 * Applications create a GC on a printer using <code>new GC(printer)</code> | |
41 * and then draw on the printer GC using the usual graphics calls. | |
42 * <p> | |
43 * A <code>Printer</code> object may be constructed by providing | |
44 * a <code>PrinterData</code> object which identifies the printer. | |
45 * A <code>PrintDialog</code> presents a print dialog to the user | |
46 * and returns an initialized instance of <code>PrinterData</code>. | |
47 * Alternatively, calling <code>new Printer()</code> will construct a | |
48 * printer object for the user's default printer. | |
49 * </p><p> | |
50 * Application code must explicitly invoke the <code>Printer.dispose()</code> | |
51 * method to release the operating system resources managed by each instance | |
52 * when those instances are no longer required. | |
53 * </p> | |
54 * | |
55 * @see PrinterData | |
56 * @see PrintDialog | |
57 * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a> | |
58 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
59 */ | |
60 public final class Printer : Device { | |
61 static PrinterData [] printerList; | |
62 | |
63 PrinterData data; | |
64 GtkPrinter* printer; | |
65 GtkPrintJob* printJob; | |
66 GtkPrintSettings* settings; | |
67 void* pageSetup; | |
113 | 68 org.eclipse.swt.internal.gtk.OS.cairo_surface_t* surface; |
69 org.eclipse.swt.internal.gtk.OS.cairo_t* cairo; | |
25 | 70 |
71 /** | |
72 * whether or not a GC was created for this printer | |
73 */ | |
74 bool isGCCreated = false; | |
75 Font systemFont; | |
76 | |
77 static String settingsData; | |
78 static int start, end; | |
79 | |
80 static const String GTK_LPR_BACKEND = "GtkPrintBackendLpr"; //$NON-NLS-1$ | |
81 | |
82 static const bool disablePrinting = false;// System.getProperty("org.eclipse.swt.internal.gtk.disablePrinting") !is null; //$NON-NLS-1$ | |
83 | |
84 /** | |
85 * Returns an array of <code>PrinterData</code> objects | |
86 * representing all available printers. | |
87 * | |
88 * @return the list of available printers | |
89 */ | |
90 public static PrinterData[] getPrinterList() { | |
91 printerList = new PrinterData [0]; | |
92 if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || disablePrinting) { | |
93 return printerList; | |
94 } | |
95 if (!OS.g_thread_supported ()) { | |
96 OS.g_thread_init (null); | |
97 } | |
98 OS.gtk_set_locale(); | |
99 int argc = 0; | |
100 if (!OS.gtk_init_check ( &argc, null)) { | |
101 SWT.error (SWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); | |
102 } | |
103 OS.gtk_enumerate_printers(&GtkPrinterFunc_List, null, null, true); | |
104 return printerList; | |
105 } | |
106 | |
107 private static extern(C) int GtkPrinterFunc_List (GtkPrinter* printer, void* user_data) { | |
108 int length_ = printerList.length; | |
109 PrinterData [] newList = new PrinterData [length_ + 1]; | |
110 System.arraycopy (printerList, 0, newList, 0, length_); | |
111 printerList = newList; | |
112 printerList [length_] = printerDataFromGtkPrinter(printer); | |
113 /* | |
114 * Bug in GTK. While performing a gtk_enumerate_printers(), GTK finds all of the | |
115 * available printers from each backend and can hang. If a backend requires more | |
116 * time to gather printer info, GTK will start an event loop waiting for a done | |
117 * signal before continuing. For the Lpr backend, GTK does not send a done signal | |
118 * which means the event loop never ends. The fix is to check to see if the driver | |
119 * is of type Lpr, and stop the enumeration, which exits the event loop. | |
120 */ | |
121 if (printerList[length_].driver.equals(GTK_LPR_BACKEND)) return 1; | |
122 return 0; | |
123 } | |
124 | |
125 /** | |
126 * Returns a <code>PrinterData</code> object representing | |
127 * the default printer or <code>null</code> if there is no | |
128 * printer available on the System. | |
129 * | |
130 * @return the default printer data or null | |
131 * | |
132 * @since 2.1 | |
133 */ | |
134 public static PrinterData getDefaultPrinterData() { | |
135 printerList = new PrinterData [1]; | |
136 if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || disablePrinting) { | |
137 return null; | |
138 } | |
139 if (!OS.g_thread_supported ()) { | |
140 OS.g_thread_init (null); | |
141 } | |
142 OS.gtk_set_locale(); | |
143 int argc = 0; | |
144 if (!OS.gtk_init_check (&argc, null)) { | |
145 SWT.error (SWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); | |
146 } | |
147 OS.gtk_enumerate_printers(&GtkPrinterFunc_Default, null, null, true); | |
148 return printerList[0]; | |
149 } | |
150 | |
151 private static extern(C) int GtkPrinterFunc_Default (GtkPrinter* printer, void* user_data) { | |
152 if (OS.gtk_printer_is_default(printer)) { | |
153 printerList[0] = printerDataFromGtkPrinter(printer); | |
154 return 1; | |
155 } else if (OS.GTK_VERSION < OS.buildVERSION(2, 10, 12) && printerDataFromGtkPrinter(printer).driver.equals (GTK_LPR_BACKEND)) { | |
156 return 1; | |
157 } | |
158 return 0; | |
159 } | |
160 | |
161 GtkPrinter* gtkPrinterFromPrinterData() { | |
162 printer = null; | |
163 OS.gtk_enumerate_printers(&GtkPrinterFunc_FindNamedPrinterFunc, cast(void*)this, null, true); | |
164 return printer; | |
165 } | |
166 | |
167 private static extern(C) int GtkPrinterFunc_FindNamedPrinterFunc (GtkPrinter* printer, void* user_data) { | |
168 return (cast(Printer)user_data).GtkPrinterFunc_FindNamedPrinter( printer, null ); | |
169 } | |
170 int GtkPrinterFunc_FindNamedPrinter (GtkPrinter* printer, void* user_data) { | |
171 PrinterData pd = printerDataFromGtkPrinter(printer); | |
172 if (pd.driver.equals(data.driver) && pd.name.equals(data.name)) { | |
173 this.printer = printer; | |
174 OS.g_object_ref(printer); | |
175 return 1; | |
176 } else if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 12) && pd.driver.equals(GTK_LPR_BACKEND)) { | |
177 return 1; | |
178 } | |
179 return 0; | |
180 } | |
181 | |
182 static PrinterData printerDataFromGtkPrinter(GtkPrinter* printer) { | |
183 auto backend = OS.gtk_printer_get_backend(printer); | |
184 auto address = OS.G_OBJECT_TYPE_NAME(backend); | |
51 | 185 String backendType = fromStringz( address )._idup(); |
25 | 186 |
187 address = OS.gtk_printer_get_name (printer); | |
51 | 188 String name = fromStringz( address )._idup(); |
25 | 189 |
190 return new PrinterData (backendType, name); | |
191 } | |
192 | |
193 /* | |
194 * Restore printer settings and page_setup data from data. | |
195 */ | |
196 static void restore(char[] data, GtkPrintSettings* settings, GtkPageSetup* page_setup) { | |
51 | 197 settingsData = data._idup(); |
25 | 198 start = end = 0; |
199 while (end < settingsData.length && settingsData[end] !is 0) { | |
200 start = end; | |
201 while (end < settingsData.length && settingsData[end] !is 0) end++; | |
202 end++; | |
203 char [] keyBuffer = new char [end - start]; | |
204 System.arraycopy (settingsData, start, keyBuffer, 0, keyBuffer.length); | |
205 start = end; | |
206 while (end < settingsData.length && settingsData[end] !is 0) end++; | |
207 end++; | |
208 char [] valueBuffer = new char [end - start]; | |
209 System.arraycopy (settingsData, start, valueBuffer, 0, valueBuffer.length); | |
210 OS.gtk_print_settings_set(settings, keyBuffer.ptr, valueBuffer.ptr); | |
211 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "{}: {}", keyBuffer, valueBuffer ); | |
212 } | |
213 end++; // skip extra null terminator | |
214 | |
215 /* Retrieve stored page_setup data. | |
216 * Note that page_setup properties must be stored (in PrintDialog) and restored (here) in the same order. | |
217 */ | |
218 OS.gtk_page_setup_set_orientation(page_setup, restoreInt("orientation")); //$NON-NLS-1$ | |
219 OS.gtk_page_setup_set_top_margin(page_setup, restoreDouble("top_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ | |
220 OS.gtk_page_setup_set_bottom_margin(page_setup, restoreDouble("bottom_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ | |
221 OS.gtk_page_setup_set_left_margin(page_setup, restoreDouble("left_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ | |
222 OS.gtk_page_setup_set_right_margin(page_setup, restoreDouble("right_margin"), OS.GTK_UNIT_MM); //$NON-NLS-1$ | |
51 | 223 String name = restoreBytes("paper_size_name", true); //$NON-NLS-1$ |
224 String display_name = restoreBytes("paper_size_display_name", true); //$NON-NLS-1$ | |
225 String ppd_name = restoreBytes("paper_size_ppd_name", true); //$NON-NLS-1$ | |
25 | 226 double width = restoreDouble("paper_size_width"); //$NON-NLS-1$ |
227 double height = restoreDouble("paper_size_height"); //$NON-NLS-1$ | |
228 bool custom = restoreBoolean("paper_size_is_custom"); //$NON-NLS-1$ | |
229 GtkPaperSize* paper_size = null; | |
230 if (custom) { | |
231 if (ppd_name.length > 0) { | |
232 paper_size = OS.gtk_paper_size_new_from_ppd(ppd_name.ptr, display_name.ptr, width, height); | |
233 } else { | |
234 paper_size = OS.gtk_paper_size_new_custom(name.ptr, display_name.ptr, width, height, OS.GTK_UNIT_MM); | |
235 } | |
236 } else { | |
237 paper_size = OS.gtk_paper_size_new(name.ptr); | |
238 } | |
239 OS.gtk_page_setup_set_paper_size(page_setup, paper_size); | |
240 OS.gtk_paper_size_free(paper_size); | |
241 } | |
242 | |
243 static void setScope(GtkPrintSettings* settings, int scope_, int startPage, int endPage) { | |
244 switch (scope_) { | |
245 case PrinterData.ALL_PAGES: | |
246 OS.gtk_print_settings_set_print_pages(settings, OS.GTK_PRINT_PAGES_ALL); | |
247 break; | |
248 case PrinterData.PAGE_RANGE: | |
249 OS.gtk_print_settings_set_print_pages(settings, OS.GTK_PRINT_PAGES_RANGES); | |
250 GtkPageRange pageRange; | |
251 pageRange.start = startPage - 1; | |
252 pageRange.end = endPage - 1; | |
253 OS.gtk_print_settings_set_page_ranges(settings, &pageRange, 1); | |
254 break; | |
255 case PrinterData.SELECTION: | |
256 //TODO: Not correctly implemented. May need new API. For now, set to ALL. (see gtk bug 344519) | |
257 OS.gtk_print_settings_set_print_pages(settings, OS.GTK_PRINT_PAGES_ALL); | |
258 break; | |
259 default: | |
260 } | |
261 } | |
262 | |
263 static DeviceData checkNull (PrinterData data) { | |
264 if (data is null) data = new PrinterData(); | |
265 if (data.driver is null || data.name is null) { | |
266 PrinterData defaultPrinter = getDefaultPrinterData(); | |
267 if (defaultPrinter is null) SWT.error(SWT.ERROR_NO_HANDLES); | |
268 data.driver = defaultPrinter.driver; | |
269 data.name = defaultPrinter.name; | |
270 } | |
271 return data; | |
272 } | |
273 | |
274 /** | |
275 * Constructs a new printer representing the default printer. | |
276 * <p> | |
277 * You must dispose the printer when it is no longer required. | |
278 * </p> | |
279 * | |
280 * @exception SWTError <ul> | |
281 * <li>ERROR_NO_HANDLES - if there are no valid printers | |
282 * </ul> | |
283 * | |
284 * @see Device#dispose | |
285 */ | |
286 public this() { | |
287 this(null); | |
288 } | |
289 | |
290 /** | |
291 * Constructs a new printer given a <code>PrinterData</code> | |
292 * object representing the desired printer. | |
293 * <p> | |
294 * You must dispose the printer when it is no longer required. | |
295 * </p> | |
296 * | |
297 * @param data the printer data for the specified printer | |
298 * | |
299 * @exception IllegalArgumentException <ul> | |
300 * <li>ERROR_INVALID_ARGUMENT - if the specified printer data does not represent a valid printer | |
301 * </ul> | |
302 * @exception SWTError <ul> | |
303 * <li>ERROR_NO_HANDLES - if there are no valid printers | |
304 * </ul> | |
305 * | |
306 * @see Device#dispose | |
307 */ | |
308 public this(PrinterData data) { | |
309 super(checkNull(data)); | |
310 } | |
311 | |
312 static int restoreInt(String key) { | |
51 | 313 String value = restoreBytes(key, false); |
314 return Integer.parseInt( value ); | |
25 | 315 } |
316 | |
317 static double restoreDouble(String key) { | |
51 | 318 String value = restoreBytes(key, false); |
319 return Double.parseDouble( value ); | |
25 | 320 } |
321 | |
322 static bool restoreBoolean(String key) { | |
51 | 323 String value = restoreBytes(key, false); |
324 return Boolean.getBoolean( value ); | |
25 | 325 } |
326 | |
327 static String restoreBytes(String key, bool nullTerminate) { | |
328 //get key | |
329 start = end; | |
330 while (end < settingsData.length && settingsData[end] !is 0) end++; | |
331 end++; | |
332 char [] keyBuffer = new char [end - start]; | |
333 System.arraycopy (settingsData, start, keyBuffer, 0, keyBuffer.length); | |
334 | |
335 //get value | |
336 start = end; | |
337 while (end < settingsData.length && settingsData[end] !is 0) end++; | |
338 int length_ = end - start; | |
339 end++; | |
340 if (nullTerminate) length_++; | |
341 char [] valueBuffer = new char [length_]; | |
342 System.arraycopy (settingsData, start, valueBuffer, 0, length_); | |
343 | |
344 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "{}: {}", keyBuffer, valueBuffer ); | |
345 | |
51 | 346 return cast(String)valueBuffer; |
25 | 347 } |
348 | |
349 /** | |
350 * Returns a reasonable font for applications to use. | |
351 * On some platforms, this will match the "default font" | |
352 * or "system font" if such can be found. This font | |
353 * should not be free'd because it was allocated by the | |
354 * system, not the application. | |
355 * <p> | |
356 * Typically, applications which want the default look | |
357 * should simply not set the font on the widgets they | |
358 * create. Widgets are always created with the correct | |
359 * default font for the class of user-interface component | |
360 * they represent. | |
361 * </p> | |
362 * | |
363 * @return a font | |
364 * | |
365 * @exception SWTException <ul> | |
366 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
367 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
368 * </ul> | |
369 */ | |
370 public override Font getSystemFont () { | |
371 checkDevice (); | |
372 if (systemFont !is null) return systemFont; | |
373 auto style = OS.gtk_widget_get_default_style(); | |
374 auto defaultFont = OS.pango_font_description_copy (OS.gtk_style_get_font_desc (style)); | |
375 return systemFont = Font.gtk_new (this, defaultFont); | |
376 } | |
377 | |
378 /** | |
379 * Invokes platform specific functionality to allocate a new GC handle. | |
380 * <p> | |
381 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
382 * API for <code>Printer</code>. It is marked public only so that it | |
383 * can be shared within the packages provided by SWT. It is not | |
384 * available on all platforms, and should never be called from | |
385 * application code. | |
386 * </p> | |
387 * | |
388 * @param data the platform specific GC data | |
389 * @return the platform specific GC handle | |
390 */ | |
391 public override GdkGC* internal_new_GC(GCData data) { | |
392 auto drawable = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), 1, 1, 1); | |
393 auto gdkGC = OS.gdk_gc_new (drawable); | |
394 if (gdkGC is null) SWT.error (SWT.ERROR_NO_HANDLES); | |
395 if (data !is null) { | |
396 if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT); | |
397 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; | |
398 if ((data.style & mask) is 0) { | |
399 data.style |= SWT.LEFT_TO_RIGHT; | |
400 } | |
401 data.device = this; | |
402 data.drawable = drawable; | |
403 data.background = getSystemColor (SWT.COLOR_WHITE).handle; | |
404 data.foreground = getSystemColor (SWT.COLOR_BLACK).handle; | |
405 data.font = getSystemFont (); | |
406 //TODO: We are supposed to return this in pixels, but GTK_UNIT_PIXELS is currently not implemented (gtk bug 346245) | |
407 data.width = cast(int)OS.gtk_page_setup_get_paper_width (pageSetup, OS.GTK_UNIT_POINTS); | |
408 data.height = cast(int)OS.gtk_page_setup_get_paper_height (pageSetup, OS.GTK_UNIT_POINTS); | |
409 if (cairo is null) SWT.error(SWT.ERROR_NO_HANDLES); | |
410 data.cairo = cairo; | |
411 isGCCreated = true; | |
412 } | |
413 return gdkGC; | |
414 } | |
415 | |
416 /** | |
417 * Invokes platform specific functionality to dispose a GC handle. | |
418 * <p> | |
419 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
420 * API for <code>Printer</code>. It is marked public only so that it | |
421 * can be shared within the packages provided by SWT. It is not | |
422 * available on all platforms, and should never be called from | |
423 * application code. | |
424 * </p> | |
425 * | |
426 * @param hDC the platform specific GC handle | |
427 * @param data the platform specific GC data | |
428 */ | |
429 public override void internal_dispose_GC(GdkGC* gdkGC, GCData data) { | |
430 if (data !is null) isGCCreated = false; | |
431 OS.g_object_unref (gdkGC); | |
432 if (data !is null) { | |
433 if (data.drawable !is null) OS.g_object_unref (data.drawable); | |
434 data.drawable = null; | |
435 data.cairo = null; | |
436 } | |
437 } | |
438 | |
439 /** | |
440 * Releases any internal state prior to destroying this printer. | |
441 * This method is called internally by the dispose | |
442 * mechanism of the <code>Device</code> class. | |
443 */ | |
444 protected override void release () { | |
445 super.release(); | |
446 | |
447 /* Dispose the default font */ | |
448 if (systemFont !is null) systemFont.dispose (); | |
449 systemFont = null; | |
450 } | |
451 | |
452 /** | |
453 * Starts a print job and returns true if the job started successfully | |
454 * and false otherwise. | |
455 * <p> | |
456 * This must be the first method called to initiate a print job, | |
457 * followed by any number of startPage/endPage calls, followed by | |
458 * endJob. Calling startPage, endPage, or endJob before startJob | |
459 * will result in undefined behavior. | |
460 * </p> | |
461 * | |
462 * @param jobName the name of the print job to start | |
463 * @return true if the job started successfully and false otherwise. | |
464 * | |
465 * @exception SWTException <ul> | |
466 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
467 * </ul> | |
468 * | |
469 * @see #startPage | |
470 * @see #endPage | |
471 * @see #endJob | |
472 */ | |
473 public bool startJob(String jobName) { | |
474 checkDevice(); | |
475 char* buffer = toStringz(jobName); | |
476 printJob = OS.gtk_print_job_new (buffer, printer, settings, pageSetup); | |
477 if (printJob is null) return false; | |
478 surface = OS.gtk_print_job_get_surface(printJob, null); | |
479 if (surface is null) { | |
480 OS.g_object_unref(printJob); | |
481 printJob = null; | |
482 return false; | |
483 } | |
484 cairo = Cairo.cairo_create(surface); | |
485 if (cairo is null) { | |
486 OS.g_object_unref(printJob); | |
487 printJob = null; | |
488 return false; | |
489 } | |
490 return true; | |
491 } | |
492 | |
493 /** | |
494 * Destroys the printer handle. | |
495 * This method is called internally by the dispose | |
496 * mechanism of the <code>Device</code> class. | |
497 */ | |
498 protected override void destroy () { | |
499 if (printer !is null) OS.g_object_unref (printer); | |
500 if (settings !is null) OS.g_object_unref (settings); | |
501 if (pageSetup !is null) OS.g_object_unref (pageSetup); | |
502 if (cairo !is null) Cairo.cairo_destroy (cairo); | |
503 if (printJob !is null) OS.g_object_unref (printJob); | |
504 printer = null; | |
505 settings = null; | |
506 pageSetup = null; | |
507 cairo = null; | |
508 printJob = null; | |
509 } | |
510 | |
511 /** | |
512 * Ends the current print job. | |
513 * | |
514 * @exception SWTException <ul> | |
515 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
516 * </ul> | |
517 * | |
518 * @see #startJob | |
519 * @see #startPage | |
520 * @see #endPage | |
521 */ | |
522 public void endJob() { | |
523 checkDevice(); | |
524 if (printJob is null) return; | |
525 Cairo.cairo_surface_finish(surface); | |
526 OS.gtk_print_job_send(printJob, null, null, null ); | |
527 } | |
528 | |
529 /** | |
530 * Cancels a print job in progress. | |
531 * | |
532 * @exception SWTException <ul> | |
533 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
534 * </ul> | |
535 */ | |
536 public void cancelJob() { | |
537 checkDevice(); | |
538 if (printJob is null) return; | |
539 //TODO: Need to implement (waiting on gtk bug 339323) | |
540 //OS.g_object_unref(printJob); | |
541 //printJob = 0; | |
542 } | |
543 | |
544 /** | |
545 * Starts a page and returns true if the page started successfully | |
546 * and false otherwise. | |
547 * <p> | |
548 * After calling startJob, this method may be called any number of times | |
549 * along with a matching endPage. | |
550 * </p> | |
551 * | |
552 * @return true if the page started successfully and false otherwise. | |
553 * | |
554 * @exception SWTException <ul> | |
555 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
556 * </ul> | |
557 * | |
558 * @see #endPage | |
559 * @see #startJob | |
560 * @see #endJob | |
561 */ | |
562 public bool startPage() { | |
563 checkDevice(); | |
564 if (printJob is null) return false; | |
565 double width = OS.gtk_page_setup_get_paper_width (pageSetup, OS.GTK_UNIT_POINTS); | |
566 double height = OS.gtk_page_setup_get_paper_height (pageSetup, OS.GTK_UNIT_POINTS); | |
567 int type = Cairo.cairo_surface_get_type (surface); | |
568 switch (type) { | |
569 case Cairo.CAIRO_SURFACE_TYPE_PS: | |
570 Cairo.cairo_ps_surface_set_size (surface, width, height); | |
571 break; | |
572 case Cairo.CAIRO_SURFACE_TYPE_PDF: | |
573 Cairo.cairo_pdf_surface_set_size (surface, width, height); | |
574 break; | |
575 default: | |
576 } | |
577 return true; | |
578 } | |
579 | |
580 /** | |
581 * Ends the current page. | |
582 * | |
583 * @exception SWTException <ul> | |
584 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
585 * </ul> | |
586 * | |
587 * @see #startPage | |
588 * @see #startJob | |
589 * @see #endJob | |
590 */ | |
591 public void endPage() { | |
592 checkDevice(); | |
593 if (cairo !is null) Cairo.cairo_show_page(cairo); | |
594 } | |
595 | |
596 /** | |
597 * Returns a point whose x coordinate is the horizontal | |
598 * dots per inch of the printer, and whose y coordinate | |
599 * is the vertical dots per inch of the printer. | |
600 * | |
601 * @return the horizontal and vertical DPI | |
602 * | |
603 * @exception SWTException <ul> | |
604 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
605 * </ul> | |
606 */ | |
607 public override Point getDPI() { | |
608 checkDevice(); | |
609 int resolution = OS.gtk_print_settings_get_resolution(settings); | |
610 if (DEBUG) getDwtLogger().info( __FILE__, __LINE__, "print_settings.resolution={}", resolution); | |
611 //TODO: Return 72 (1/72 inch = 1 point) until gtk bug 346245 is fixed | |
612 //TODO: Fix this: gtk_print_settings_get_resolution returns 0? (see gtk bug 346252) | |
613 if (true || resolution is 0) return new Point(72, 72); | |
614 return new Point(resolution, resolution); | |
615 } | |
616 | |
617 /** | |
618 * Returns a rectangle describing the receiver's size and location. | |
619 * <p> | |
620 * For a printer, this is the size of the physical page, in pixels. | |
621 * </p> | |
622 * | |
623 * @return the bounding rectangle | |
624 * | |
625 * @exception SWTException <ul> | |
626 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
627 * </ul> | |
628 * | |
629 * @see #getClientArea | |
630 * @see #computeTrim | |
631 */ | |
632 public override Rectangle getBounds() { | |
633 checkDevice(); | |
634 //TODO: We are supposed to return this in pixels, but GTK_UNIT_PIXELS is currently not implemented (gtk bug 346245) | |
635 double width = OS.gtk_page_setup_get_paper_width (pageSetup, OS.GTK_UNIT_POINTS); | |
636 double height = OS.gtk_page_setup_get_paper_height (pageSetup, OS.GTK_UNIT_POINTS); | |
637 return new Rectangle(0, 0, cast(int) width, cast(int) height); | |
638 } | |
639 | |
640 /** | |
641 * Returns a rectangle which describes the area of the | |
642 * receiver which is capable of displaying data. | |
643 * <p> | |
644 * For a printer, this is the size of the printable area | |
645 * of the page, in pixels. | |
646 * </p> | |
647 * | |
648 * @return the client area | |
649 * | |
650 * @exception SWTException <ul> | |
651 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
652 * </ul> | |
653 * | |
654 * @see #getBounds | |
655 * @see #computeTrim | |
656 */ | |
657 public override Rectangle getClientArea() { | |
658 checkDevice(); | |
659 //TODO: We are supposed to return this in pixels, but GTK_UNIT_PIXELS is currently not implemented (gtk bug 346245) | |
660 double width = OS.gtk_page_setup_get_page_width(pageSetup, OS.GTK_UNIT_POINTS); | |
661 double height = OS.gtk_page_setup_get_page_height(pageSetup, OS.GTK_UNIT_POINTS); | |
662 return new Rectangle(0, 0, cast(int) width, cast(int) height); | |
663 } | |
664 | |
665 /** | |
666 * Given a <em>client area</em> (as described by the arguments), | |
667 * returns a rectangle, relative to the client area's coordinates, | |
668 * that is the client area expanded by the printer's trim (or minimum margins). | |
669 * <p> | |
670 * Most printers have a minimum margin on each edge of the paper where the | |
671 * printer device is unable to print. This margin is known as the "trim." | |
672 * This method can be used to calculate the printer's minimum margins | |
673 * by passing in a client area of 0, 0, 0, 0 and then using the resulting | |
674 * x and y coordinates (which will be <= 0) to determine the minimum margins | |
675 * for the top and left edges of the paper, and the resulting width and height | |
676 * (offset by the resulting x and y) to determine the minimum margins for the | |
677 * bottom and right edges of the paper, as follows: | |
678 * <ul> | |
679 * <li>The left trim width is -x pixels</li> | |
680 * <li>The top trim height is -y pixels</li> | |
681 * <li>The right trim width is (x + width) pixels</li> | |
682 * <li>The bottom trim height is (y + height) pixels</li> | |
683 * </ul> | |
684 * </p> | |
685 * | |
686 * @param x the x coordinate of the client area | |
687 * @param y the y coordinate of the client area | |
688 * @param width the width of the client area | |
689 * @param height the height of the client area | |
690 * @return a rectangle, relative to the client area's coordinates, that is | |
691 * the client area expanded by the printer's trim (or minimum margins) | |
692 * | |
693 * @exception SWTException <ul> | |
694 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li> | |
695 * </ul> | |
696 * | |
697 * @see #getBounds | |
698 * @see #getClientArea | |
699 */ | |
700 public Rectangle computeTrim(int x, int y, int width, int height) { | |
701 checkDevice(); | |
702 //TODO: We are supposed to return this in pixels, but GTK_UNIT_PIXELS is currently not implemented (gtk bug 346245) | |
703 double printWidth = OS.gtk_page_setup_get_page_width(pageSetup, OS.GTK_UNIT_POINTS); | |
704 double printHeight = OS.gtk_page_setup_get_page_height(pageSetup, OS.GTK_UNIT_POINTS); | |
705 double paperWidth = OS.gtk_page_setup_get_paper_width (pageSetup, OS.GTK_UNIT_POINTS); | |
706 double paperHeight = OS.gtk_page_setup_get_paper_height (pageSetup, OS.GTK_UNIT_POINTS); | |
707 double printX = -OS.gtk_page_setup_get_left_margin(pageSetup, OS.GTK_UNIT_POINTS); | |
708 double printY = -OS.gtk_page_setup_get_top_margin(pageSetup, OS.GTK_UNIT_POINTS); | |
709 double hTrim = paperWidth - printWidth; | |
710 double vTrim = paperHeight - printHeight; | |
711 return new Rectangle(x + cast(int)printX, y + cast(int)printY, width + cast(int)hTrim, height + cast(int)vTrim); | |
712 } | |
713 | |
714 /** | |
715 * Creates the printer handle. | |
716 * This method is called internally by the instance creation | |
717 * mechanism of the <code>Device</code> class. | |
718 * @param deviceData the device data | |
719 */ | |
720 protected override void create(DeviceData deviceData) { | |
721 this.data = cast(PrinterData)deviceData; | |
722 if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0) || disablePrinting) SWT.error(SWT.ERROR_NO_HANDLES); | |
723 printer = gtkPrinterFromPrinterData(); | |
724 if (printer is null) SWT.error(SWT.ERROR_NO_HANDLES); | |
725 } | |
726 | |
727 /** | |
728 * Initializes any internal resources needed by the | |
729 * device. | |
730 * <p> | |
731 * This method is called after <code>create</code>. | |
732 * </p><p> | |
733 * If subclasses reimplement this method, they must | |
734 * call the <code>super</code> implementation. | |
735 * </p> | |
736 * | |
737 * @see #create | |
738 */ | |
739 protected override void init_() { | |
740 super.init_ (); | |
741 settings = OS.gtk_print_settings_new(); | |
742 pageSetup = OS.gtk_page_setup_new(); | |
743 if (data.otherData !is null) { | |
744 restore(data.otherData, settings, pageSetup); | |
745 } | |
746 | |
747 /* Set values of settings from PrinterData. */ | |
748 setScope(settings, data.scope_, data.startPage, data.endPage); | |
749 //TODO: Should we look at printToFile, or driver/name for "Print to File", or both? (see gtk bug 345590) | |
750 if (data.printToFile) { | |
751 char* buffer = toStringz( data.fileName ); | |
752 OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); | |
753 } | |
754 if (data.driver.equals("GtkPrintBackendFile") && data.name.equals("Print to File")) { //$NON-NLS-1$ //$NON-NLS-2$ | |
755 char* buffer = toStringz( data.fileName ); | |
756 OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); | |
757 } | |
758 OS.gtk_print_settings_set_n_copies(settings, data.copyCount); | |
759 OS.gtk_print_settings_set_collate(settings, data.collate); | |
760 } | |
761 | |
762 /** | |
763 * Returns a <code>PrinterData</code> object representing the | |
764 * target printer for this print job. | |
765 * | |
766 * @return a PrinterData object describing the receiver | |
767 */ | |
768 public PrinterData getPrinterData() { | |
769 checkDevice(); | |
770 return data; | |
771 } | |
772 | |
773 } |