Mercurial > projects > dwt-linux
annotate dwt/printing/PrintDialog.d @ 240:ce446666f5a2
Update to SWT 3.4M7
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 12 May 2008 19:13:01 +0200 |
parents | 380bad9f6852 |
children | 5a30aa9820f3 |
rev | line source |
---|---|
115
52b32f5cb1e0
many file checked for switch default
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
1 /******************************************************************************* |
91 | 2 * Copyright (c) 2000, 2007 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 | |
108 | 10 * Port to the D programming language: |
11 * Frank Benoit <benoit@tionex.de> | |
91 | 12 *******************************************************************************/ |
13 module dwt.printing.PrintDialog; | |
14 | |
15 | |
16 | |
17 import dwt.DWT; | |
18 import dwt.DWTException; | |
240 | 19 import dwt.internal.LONG; |
91 | 20 import dwt.internal.gtk.OS; |
21 import dwt.widgets.Dialog; | |
22 import dwt.widgets.Display; | |
23 import dwt.widgets.Shell; | |
24 import dwt.widgets.Widget; | |
25 import dwt.printing.Printer; | |
26 import dwt.printing.PrinterData; | |
200
08789b28bdf3
import dwt.dwthelper.utils now explicit
Frank Benoit <benoit@tionex.de>
parents:
195
diff
changeset
|
27 import dwt.dwthelper.utils; |
91 | 28 |
29 import tango.util.Convert; | |
30 import Math = tango.math.Math; | |
31 static import tango.stdc.stringz; | |
32 | |
33 /** | |
34 * Instances of this class allow the user to select | |
35 * a printer and various print-related parameters | |
36 * prior to starting a print job. | |
37 * <p> | |
38 * IMPORTANT: This class is intended to be subclassed <em>only</em> | |
39 * within the DWT implementation. | |
40 * </p> | |
41 */ | |
42 public class PrintDialog : Dialog { | |
240 | 43 PrinterData printerData; |
91 | 44 int scope_ = PrinterData.ALL_PAGES; |
45 int startPage = 1, endPage = 1; | |
46 bool printToFile = false; | |
47 | |
48 GtkPrintUnixDialog* handle; | |
49 int index; | |
50 char [] settingsData; | |
51 | |
240 | 52 static const String GET_MODAL_DIALOG = "dwt.internal.gtk.getModalDialog"; |
53 static const String SET_MODAL_DIALOG = "dwt.internal.gtk.setModalDialog"; | |
54 static const String ADD_IDLE_PROC_KEY = "dwt.internal.gtk.addIdleProc"; | |
55 static const String REMOVE_IDLE_PROC_KEY = "dwt.internal.gtk.removeIdleProc"; | |
56 static const String GET_EMISSION_PROC_KEY = "dwt.internal.gtk.getEmissionProc"; | |
91 | 57 /** |
58 * Constructs a new instance of this class given only its parent. | |
59 * | |
60 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
61 * | |
62 * @exception IllegalArgumentException <ul> | |
63 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
64 * </ul> | |
65 * @exception DWTException <ul> | |
66 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
67 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
68 * </ul> | |
69 * | |
70 * @see DWT | |
71 * @see Widget#checkSubclass | |
72 * @see Widget#getStyle | |
73 */ | |
74 public this (Shell parent) { | |
75 this (parent, DWT.PRIMARY_MODAL); | |
76 } | |
77 | |
78 /** | |
79 * Constructs a new instance of this class given its parent | |
80 * and a style value describing its behavior and appearance. | |
81 * <p> | |
82 * The style value is either one of the style constants defined in | |
83 * class <code>DWT</code> which is applicable to instances of this | |
84 * class, or must be built by <em>bitwise OR</em>'ing together | |
85 * (that is, using the <code>int</code> "|" operator) two or more | |
86 * of those <code>DWT</code> style constants. The class description | |
87 * lists the style constants that are applicable to the class. | |
88 * Style bits are also inherited from superclasses. | |
89 * </p> | |
90 * | |
91 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
92 * @param style the style of control to construct | |
93 * | |
94 * @exception IllegalArgumentException <ul> | |
95 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
96 * </ul> | |
97 * @exception DWTException <ul> | |
98 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
99 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
100 * </ul> | |
101 * | |
102 * @see DWT | |
103 * @see Widget#checkSubclass | |
104 * @see Widget#getStyle | |
105 */ | |
106 public this (Shell parent, int style) { | |
240 | 107 super (parent, parent is null? style : checkStyleBit (parent, style)); |
91 | 108 checkSubclass (); |
109 } | |
110 | |
240 | 111 /** |
112 * Sets the printer data that will be used when the dialog | |
113 * is opened. | |
114 * | |
115 * @param data the data that will be used when the dialog is opened | |
116 * | |
117 * @since 3.4 | |
118 */ | |
119 public void setPrinterData(PrinterData data) { | |
120 this.printerData = data; | |
121 } | |
122 | |
123 /** | |
124 * Returns the printer data that will be used when the dialog | |
125 * is opened. | |
126 * | |
127 * @return the data that will be used when the dialog is opened | |
128 * | |
129 * @since 3.4 | |
130 */ | |
131 public PrinterData getPrinterData() { | |
132 return printerData; | |
133 } | |
134 | |
135 static int checkBits (int style, int int0, int int1, int int2, int int3, int int4, int int5) { | |
136 int mask = int0 | int1 | int2 | int3 | int4 | int5; | |
137 if ((style & mask) is 0) style |= int0; | |
138 if ((style & int0) !is 0) style = (style & ~mask) | int0; | |
139 if ((style & int1) !is 0) style = (style & ~mask) | int1; | |
140 if ((style & int2) !is 0) style = (style & ~mask) | int2; | |
141 if ((style & int3) !is 0) style = (style & ~mask) | int3; | |
142 if ((style & int4) !is 0) style = (style & ~mask) | int4; | |
143 if ((style & int5) !is 0) style = (style & ~mask) | int5; | |
144 return style; | |
145 } | |
146 | |
147 static int checkStyleBit (Shell parent, int style) { | |
148 style &= ~DWT.MIRRORED; | |
149 if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) { | |
150 if (parent !is null) { | |
151 if ((parent.getStyle () & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT; | |
152 if ((parent.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT; | |
153 } | |
154 } | |
155 return checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); | |
91 | 156 } |
157 | |
158 /** | |
159 * Returns the print job scope that the user selected | |
160 * before pressing OK in the dialog. This will be one | |
161 * of the following values: | |
162 * <dl> | |
163 * <dt><code>ALL_PAGES</code></dt> | |
164 * <dd>Print all pages in the current document</dd> | |
165 * <dt><code>PAGE_RANGE</code></dt> | |
166 * <dd>Print the range of pages specified by startPage and endPage</dd> | |
167 * <dt><code>SELECTION</code></dt> | |
168 * <dd>Print the current selection</dd> | |
169 * </dl> | |
170 * | |
171 * @return the scope setting that the user selected | |
172 */ | |
173 public int getScope() { | |
174 return scope_; | |
175 } | |
176 | |
177 /** | |
178 * Sets the scope of the print job. The user will see this | |
179 * setting when the dialog is opened. This can have one of | |
180 * the following values: | |
181 * <dl> | |
182 * <dt><code>ALL_PAGES</code></dt> | |
183 * <dd>Print all pages in the current document</dd> | |
184 * <dt><code>PAGE_RANGE</code></dt> | |
185 * <dd>Print the range of pages specified by startPage and endPage</dd> | |
186 * <dt><code>SELECTION</code></dt> | |
187 * <dd>Print the current selection</dd> | |
188 * </dl> | |
189 * | |
190 * @param scope the scope setting when the dialog is opened | |
191 */ | |
192 public void setScope(int scope_) { | |
193 this.scope_ = scope_; | |
194 } | |
195 | |
196 /** | |
197 * Returns the start page setting that the user selected | |
198 * before pressing OK in the dialog. | |
199 * <p> | |
200 * This value can be from 1 to the maximum number of pages for the platform. | |
201 * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. | |
202 * </p> | |
203 * | |
204 * @return the start page setting that the user selected | |
205 */ | |
206 public int getStartPage() { | |
207 return startPage; | |
208 } | |
209 | |
210 /** | |
211 * Sets the start page that the user will see when the dialog | |
212 * is opened. | |
213 * <p> | |
214 * This value can be from 1 to the maximum number of pages for the platform. | |
215 * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. | |
216 * </p> | |
217 * | |
218 * @param startPage the startPage setting when the dialog is opened | |
219 */ | |
220 public void setStartPage(int startPage) { | |
221 this.startPage = startPage; | |
222 } | |
223 | |
224 /** | |
225 * Returns the end page setting that the user selected | |
226 * before pressing OK in the dialog. | |
227 * <p> | |
228 * This value can be from 1 to the maximum number of pages for the platform. | |
229 * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. | |
230 * </p> | |
231 * | |
232 * @return the end page setting that the user selected | |
233 */ | |
234 public int getEndPage() { | |
235 return endPage; | |
236 } | |
237 | |
238 /** | |
239 * Sets the end page that the user will see when the dialog | |
240 * is opened. | |
241 * <p> | |
242 * This value can be from 1 to the maximum number of pages for the platform. | |
243 * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. | |
244 * </p> | |
245 * | |
246 * @param endPage the end page setting when the dialog is opened | |
247 */ | |
248 public void setEndPage(int endPage) { | |
249 this.endPage = endPage; | |
250 } | |
251 | |
252 /** | |
253 * Returns the 'Print to file' setting that the user selected | |
254 * before pressing OK in the dialog. | |
255 * | |
256 * @return the 'Print to file' setting that the user selected | |
257 */ | |
258 public bool getPrintToFile() { | |
259 return printToFile; | |
260 } | |
261 | |
262 /** | |
263 * Sets the 'Print to file' setting that the user will see | |
264 * when the dialog is opened. | |
265 * | |
266 * @param printToFile the 'Print to file' setting when the dialog is opened | |
267 */ | |
268 public void setPrintToFile(bool printToFile) { | |
269 this.printToFile = printToFile; | |
270 } | |
271 | |
272 /** | |
273 * Makes the receiver visible and brings it to the front | |
274 * of the display. | |
275 * | |
276 * @return a printer data object describing the desired print job parameters | |
277 * | |
278 * @exception DWTException <ul> | |
279 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
280 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
281 * </ul> | |
282 */ | |
283 public PrinterData open() { | |
284 if (OS.GTK_VERSION < OS.buildVERSION (2, 10, 0)) { | |
285 return Printer.getDefaultPrinterData(); | |
286 } else { | |
287 char* titleBytes = tango.stdc.stringz.toStringz( getText() ); | |
288 auto topHandle = getParent().handle; | |
289 while (topHandle !is null && !OS.GTK_IS_WINDOW(topHandle)) { | |
290 topHandle = OS.gtk_widget_get_parent(topHandle); | |
291 } | |
292 handle = cast(GtkPrintUnixDialog*)OS.gtk_print_unix_dialog_new(titleBytes, cast(GtkWindow*)topHandle); | |
293 | |
294 //TODO: Not currently implemented. May need new API. For now, disable 'Current' in the dialog. (see gtk bug 344519) | |
295 OS.gtk_print_unix_dialog_set_current_page(handle, -1); | |
296 | |
297 OS.gtk_print_unix_dialog_set_manual_capabilities(handle, | |
298 OS.GTK_PRINT_CAPABILITY_COLLATE | OS.GTK_PRINT_CAPABILITY_COPIES | OS.GTK_PRINT_CAPABILITY_PAGE_SET); | |
299 | |
300 /* Set state into print dialog settings. */ | |
301 auto settings = OS.gtk_print_settings_new(); | |
302 auto page_setup = OS.gtk_page_setup_new(); | |
240 | 303 |
304 if (printerData !is null) { | |
305 if (printerData.otherData !is null) { | |
306 Printer.restore(printerData.otherData, settings, page_setup); | |
307 } | |
308 /* Set values of settings from PrinterData. */ | |
309 Printer.setScope(settings, printerData.scope_, printerData.startPage, printerData.endPage); | |
310 //TODO: Should we look at printToFile, or driver/name for "Print to File", or both? (see gtk bug 345590) | |
311 if (printerData.printToFile) { | |
312 char* buffer = tango.stdc.stringz.toStringz(printerData.fileName); | |
313 OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); | |
314 } | |
315 if (printerData.driver.equals("GtkPrintBackendFile") && printerData.name.equals("Print to File")) { //$NON-NLS-1$ //$NON-NLS-2$ | |
316 char* buffer = tango.stdc.stringz.toStringz(printerData.fileName); | |
317 OS.gtk_print_settings_set(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr, buffer); | |
318 } | |
319 OS.gtk_print_settings_set_n_copies(settings, printerData.copyCount); | |
320 OS.gtk_print_settings_set_collate(settings, printerData.collate); | |
321 } | |
322 | |
91 | 323 Printer.setScope(settings, scope_, startPage, endPage); |
240 | 324 |
91 | 325 if (printToFile) { |
326 char* buffer = tango.stdc.stringz.toStringz( "Print to File" ); //$NON-NLS-1$ | |
327 OS.gtk_print_settings_set_printer(settings, buffer); | |
328 } | |
329 OS.gtk_print_unix_dialog_set_settings(handle, settings); | |
330 OS.gtk_print_unix_dialog_set_page_setup(handle, page_setup); | |
331 OS.g_object_unref(settings); | |
332 OS.g_object_unref(page_setup); | |
333 | |
334 PrinterData data = null; | |
335 //TODO: Handle 'Print Preview' (GTK_RESPONSE_APPLY). | |
336 Display display = getParent() !is null ? getParent().getDisplay (): Display.getCurrent (); | |
240 | 337 |
338 int signalId = 0; | |
339 int /*long*/ hookId = 0; | |
340 if ((getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { | |
341 signalId = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET()); | |
342 hookId = OS.g_signal_add_emission_hook (signalId, 0, cast(GSignalEmissionHook)cast(void*)(cast(LONG) display.getData (GET_EMISSION_PROC_KEY)).value, handle, null); | |
343 } | |
91 | 344 display.setData (ADD_IDLE_PROC_KEY, null); |
240 | 345 Object oldModal = null; |
346 if (OS.gtk_window_get_modal (handle)) { | |
347 oldModal = display.getData (GET_MODAL_DIALOG); | |
348 display.setData (SET_MODAL_DIALOG, this); | |
349 } | |
350 int response = OS.gtk_dialog_run (handle); | |
351 if (OS.gtk_window_get_modal (handle)) { | |
352 display.setData (SET_MODAL_DIALOG, oldModal); | |
353 } | |
354 if ((getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { | |
355 OS.g_signal_remove_emission_hook (signalId, hookId); | |
356 } | |
357 if (response is OS.GTK_RESPONSE_OK) { | |
91 | 358 auto printer = OS.gtk_print_unix_dialog_get_selected_printer(handle); |
359 if (printer !is null) { | |
240 | 360 |
91 | 361 /* Get state from print dialog. */ |
362 settings = OS.gtk_print_unix_dialog_get_settings(handle); // must unref | |
363 page_setup = OS.gtk_print_unix_dialog_get_page_setup(handle); // do not unref | |
364 data = Printer.printerDataFromGtkPrinter(printer); | |
365 int print_pages = OS.gtk_print_settings_get_print_pages(settings); | |
366 switch (print_pages) { | |
367 case OS.GTK_PRINT_PAGES_ALL: | |
368 scope_ = PrinterData.ALL_PAGES; | |
369 break; | |
370 case OS.GTK_PRINT_PAGES_RANGES: | |
371 scope_ = PrinterData.PAGE_RANGE; | |
372 int num_ranges; | |
373 auto page_ranges = OS.gtk_print_settings_get_page_ranges(settings, &num_ranges); | |
374 int length = num_ranges; | |
375 int min = int.max, max = 0; | |
376 for (int i = 0; i < length; i++) { | |
377 min = Math.min(min, page_ranges[i].start + 1); | |
378 max = Math.max(max, page_ranges[i].end + 1); | |
379 } | |
380 OS.g_free(page_ranges); | |
381 startPage = min is int.max ? 1 : min; | |
382 endPage = max is 0 ? 1 : max; | |
383 break; | |
384 case OS.GTK_PRINT_PAGES_CURRENT: | |
385 //TODO: Disabled in dialog (see above). This code will not run. (see gtk bug 344519) | |
386 scope_ = PrinterData.SELECTION; | |
387 startPage = endPage = OS.gtk_print_unix_dialog_get_current_page(handle); | |
388 break; | |
115
52b32f5cb1e0
many file checked for switch default
Frank Benoit <benoit@tionex.de>
parents:
108
diff
changeset
|
389 default: |
91 | 390 } |
391 | |
195 | 392 printToFile = ( data.name.equals("Print to File")); //$NON-NLS-1$ |
91 | 393 if (printToFile) { |
394 auto address = OS.gtk_print_settings_get(settings, OS.GTK_PRINT_SETTINGS_OUTPUT_URI.ptr); | |
158
de2578a843a7
Tango update to rev 3158, TracedException>Exception, fromUtf8z>fromStringz,Fix Bug in MenuItem Thanx to nascent for the report.
Frank Benoit <benoit@tionex.de>
parents:
152
diff
changeset
|
395 data.fileName = tango.stdc.stringz.fromStringz( address).dup; |
91 | 396 } |
397 | |
398 data.scope_ = scope_; | |
399 data.startPage = startPage; | |
400 data.endPage = endPage; | |
401 data.printToFile = printToFile; | |
402 data.copyCount = OS.gtk_print_settings_get_n_copies(settings); | |
403 data.collate = cast(bool)OS.gtk_print_settings_get_collate(settings); | |
404 | |
405 /* Save other print_settings data as key/value pairs in otherData. */ | |
406 index = 0; | |
407 settingsData = new char[1024]; | |
408 settingsData[] = '\0'; | |
409 OS.gtk_print_settings_foreach (settings, &GtkPrintSettingsFunc, cast(void*)this ); | |
410 index++; // extra null terminator after print_settings and before page_setup | |
411 | |
412 /* Save page_setup data as key/value pairs in otherData. | |
413 * Note that page_setup properties must be stored and restored in the same order. | |
414 */ | |
415 store("orientation", OS.gtk_page_setup_get_orientation(page_setup)); //$NON-NLS-1$ | |
416 store("top_margin", OS.gtk_page_setup_get_top_margin(page_setup, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
417 store("bottom_margin", OS.gtk_page_setup_get_bottom_margin(page_setup, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
418 store("left_margin", OS.gtk_page_setup_get_left_margin(page_setup, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
419 store("right_margin", OS.gtk_page_setup_get_right_margin(page_setup, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
420 auto paper_size = OS.gtk_page_setup_get_paper_size(page_setup); //$NON-NLS-1$ | |
421 storeBytes("paper_size_name", OS.gtk_paper_size_get_name(paper_size)); //$NON-NLS-1$ | |
422 storeBytes("paper_size_display_name", OS.gtk_paper_size_get_display_name(paper_size)); //$NON-NLS-1$ | |
423 storeBytes("paper_size_ppd_name", OS.gtk_paper_size_get_ppd_name(paper_size)); //$NON-NLS-1$ | |
424 store("paper_size_width", OS.gtk_paper_size_get_width(paper_size, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
425 store("paper_size_height", OS.gtk_paper_size_get_height(paper_size, OS.GTK_UNIT_MM)); //$NON-NLS-1$ | |
426 store("paper_size_is_custom", OS.gtk_paper_size_is_custom(paper_size)); //$NON-NLS-1$ | |
427 data.otherData = settingsData; | |
428 OS.g_object_unref(settings); | |
429 } | |
430 } | |
431 display.setData (REMOVE_IDLE_PROC_KEY, null); | |
432 OS.gtk_widget_destroy (handle); | |
433 return data; | |
434 } | |
435 } | |
436 | |
437 private static extern(C) void GtkPrintSettingsFunc (char* key, char* value, void* data) { | |
438 (cast(PrintDialog)data).GtkPrintSettingsMeth(key, value ); | |
439 } | |
440 | |
441 void GtkPrintSettingsMeth (char* key, char* value) { | |
158
de2578a843a7
Tango update to rev 3158, TracedException>Exception, fromUtf8z>fromStringz,Fix Bug in MenuItem Thanx to nascent for the report.
Frank Benoit <benoit@tionex.de>
parents:
152
diff
changeset
|
442 store( tango.stdc.stringz.fromStringz(key).dup, tango.stdc.stringz.fromStringz(value).dup ); |
91 | 443 } |
444 | |
238 | 445 void store(String key, int value) { |
446 store(key, to!(String)(value)); | |
91 | 447 } |
448 | |
238 | 449 void store(String key, double value) { |
450 store(key, to!(String)(value)); | |
91 | 451 } |
452 | |
238 | 453 void store(String key, bool value) { |
454 store(key, to!(String)(value)); | |
91 | 455 } |
456 | |
238 | 457 void storeBytes(String key, char* value) { |
158
de2578a843a7
Tango update to rev 3158, TracedException>Exception, fromUtf8z>fromStringz,Fix Bug in MenuItem Thanx to nascent for the report.
Frank Benoit <benoit@tionex.de>
parents:
152
diff
changeset
|
458 store(key, tango.stdc.stringz.fromStringz(value).dup ); |
91 | 459 } |
460 | |
238 | 461 void store(char [] key, String value) { |
91 | 462 int length = key.length + 1 + value.length + 1; |
463 if (index + length + 1 > settingsData.length) { | |
464 char [] newData = new char[settingsData.length + Math.max(length + 1, 1024)]; | |
465 newData[] = '\0'; | |
466 System.arraycopy (settingsData, 0, newData, 0, settingsData.length); | |
467 settingsData = newData; | |
468 } | |
469 System.arraycopy (key, 0, settingsData, index, key.length); | |
470 index += key.length + 1; // null terminated | |
471 System.arraycopy (value, 0, settingsData, index, value.length); | |
472 index += value.length + 1; // null terminated | |
473 } | |
474 } |