root/dwt/printing/PrintDialog.d

Revision 246:fd9c62a2998e, 12.2 kB (checked in by Frank Benoit <benoit@tionex.de>, 5 months ago)

Updater SWT 3.4M7 to 3.4

Line 
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 dwt.printing.PrintDialog;
14
15
16 import dwt.DWT;
17 import dwt.DWTException;
18 import dwt.internal.win32.OS;
19 import dwt.widgets.Control;
20 import dwt.widgets.Dialog;
21 import dwt.widgets.Display;
22 import dwt.widgets.Shell;
23 import dwt.widgets.Widget;
24
25 import dwt.printing.Printer;
26 import dwt.printing.PrinterData;
27
28 import dwt.dwthelper.utils;
29
30 /**
31  * Instances of this class allow the user to select
32  * a printer and various print-related parameters
33  * prior to starting a print job.
34  * <p>
35  * IMPORTANT: This class is intended to be subclassed <em>only</em>
36  * within the DWT implementation.
37  * </p>
38  *
39  * @see <a href="http://www.eclipse.org/swt/snippets/#printing">Printing snippets</a>
40  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample, Dialog tab</a>
41  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
42  */
43
44 public class PrintDialog : Dialog {
45     PrinterData printerData;
46     int scope_ = PrinterData.ALL_PAGES;
47     int startPage = 1, endPage = 1;
48     bool printToFile = false;
49
50 /**
51  * Constructs a new instance of this class given only its parent.
52  *
53  * @param parent a composite control which will be the parent of the new instance (cannot be null)
54  *
55  * @exception IllegalArgumentException <ul>
56  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
57  * </ul>
58  * @exception DWTException <ul>
59  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
60  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
61  * </ul>
62  *
63  * @see DWT
64  * @see Widget#checkSubclass
65  * @see Widget#getStyle
66  */
67 public this (Shell parent) {
68     this (parent, DWT.PRIMARY_MODAL);
69 }
70
71 /**
72  * Constructs a new instance of this class given its parent
73  * and a style value describing its behavior and appearance.
74  * <p>
75  * The style value is either one of the style constants defined in
76  * class <code>DWT</code> which is applicable to instances of this
77  * class, or must be built by <em>bitwise OR</em>'ing together
78  * (that is, using the <code>int</code> "|" operator) two or more
79  * of those <code>DWT</code> style constants. The class description
80  * lists the style constants that are applicable to the class.
81  * Style bits are also inherited from superclasses.
82  * </p>
83  *
84  * @param parent a composite control which will be the parent of the new instance (cannot be null)
85  * @param style the style of control to construct
86  *
87  * @exception IllegalArgumentException <ul>
88  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
89  * </ul>
90  * @exception DWTException <ul>
91  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
92  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
93  * </ul>
94  *
95  * @see DWT
96  * @see Widget#checkSubclass
97  * @see Widget#getStyle
98  */
99 public this (Shell parent, int style) {
100     super (parent, style);
101     checkSubclass ();
102 }
103
104 /**
105  * Sets the printer data that will be used when the dialog
106  * is opened.
107  *
108  * @param data the data that will be used when the dialog is opened
109  *
110  * @since 3.4
111  */
112 public void setPrinterData(PrinterData data) {
113     this.printerData = data;
114 }
115
116 /**
117  * Returns the printer data that will be used when the dialog
118  * is opened.
119  *
120  * @return the data that will be used when the dialog is opened
121  *
122  * @since 3.4
123  */
124 public PrinterData getPrinterData() {
125     return printerData;
126 }
127
128 /**
129  * Returns the print job scope that the user selected
130  * before pressing OK in the dialog. This will be one
131  * of the following values:
132  * <dl>
133  * <dt><code>PrinterData.ALL_PAGES</code></dt>
134  * <dd>Print all pages in the current document</dd>
135  * <dt><code>PrinterData.PAGE_RANGE</code></dt>
136  * <dd>Print the range of pages specified by startPage and endPage</dd>
137  * <dt><code>PrinterData.SELECTION</code></dt>
138  * <dd>Print the current selection</dd>
139  * </dl>
140  *
141  * @return the scope setting that the user selected
142  */
143 public int getScope() {
144     return scope_;
145 }
146
147 /**
148  * Sets the scope of the print job. The user will see this
149  * setting when the dialog is opened. This can have one of
150  * the following values:
151  * <dl>
152  * <dt><code>PrinterData.ALL_PAGES</code></dt>
153  * <dd>Print all pages in the current document</dd>
154  * <dt><code>PrinterData.PAGE_RANGE</code></dt>
155  * <dd>Print the range of pages specified by startPage and endPage</dd>
156  * <dt><code>PrinterData.SELECTION</code></dt>
157  * <dd>Print the current selection</dd>
158  * </dl>
159  *
160  * @param scope the scope setting when the dialog is opened
161  */
162 public void setScope(int scope_) {
163     this.scope_ = scope_;
164 }
165
166 /**
167  * Returns the start page setting that the user selected
168  * before pressing OK in the dialog.
169  * <p>
170  * This value can be from 1 to the maximum number of pages for the platform.
171  * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
172  * </p>
173  *
174  * @return the start page setting that the user selected
175  */
176 public int getStartPage() {
177     return startPage;
178 }
179
180 /**
181  * Sets the start page that the user will see when the dialog
182  * is opened.
183  * <p>
184  * This value can be from 1 to the maximum number of pages for the platform.
185  * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
186  * </p>
187  *
188  * @param startPage the startPage setting when the dialog is opened
189  */
190 public void setStartPage(int startPage) {
191     this.startPage = startPage;
192 }
193
194 /**
195  * Returns the end page setting that the user selected
196  * before pressing OK in the dialog.
197  * <p>
198  * This value can be from 1 to the maximum number of pages for the platform.
199  * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
200  * </p>
201  *
202  * @return the end page setting that the user selected
203  */
204 public int getEndPage() {
205     return endPage;
206 }
207
208 /**
209  * Sets the end page that the user will see when the dialog
210  * is opened.
211  * <p>
212  * This value can be from 1 to the maximum number of pages for the platform.
213  * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
214  * </p>
215  *
216  * @param endPage the end page setting when the dialog is opened
217  */
218 public void setEndPage(int endPage) {
219     this.endPage = endPage;
220 }
221
222 /**
223  * Returns the 'Print to file' setting that the user selected
224  * before pressing OK in the dialog.
225  *
226  * @return the 'Print to file' setting that the user selected
227  */
228 public bool getPrintToFile() {
229     return printToFile;
230 }
231
232 /**
233  * Sets the 'Print to file' setting that the user will see
234  * when the dialog is opened.
235  *
236  * @param printToFile the 'Print to file' setting when the dialog is opened
237  */
238 public void setPrintToFile(bool printToFile) {
239     this.printToFile = printToFile;
240 }
241
242 protected void checkSubclass() {
243     String name = this.classinfo.name;
244     String validName = PrintDialog.classinfo.name;
245     if (validName!=/*eq*/name) {
246         DWT.error(DWT.ERROR_INVALID_SUBCLASS);
247     }
248 }
249
250 /**
251  * Makes the receiver visible and brings it to the front
252  * of the display.
253  *
254  * @return a printer data object describing the desired print job parameters
255  *
256  * @exception DWTException <ul>
257  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
258  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
259  * </ul>
260  */
261 public PrinterData open() {
262     PRINTDLG pd;
263     pd.lStructSize = PRINTDLG.sizeof;
264     Control parent = getParent();
265     if (parent !is null) pd.hwndOwner = parent.handle;
266     void* lpInitData;
267     auto hHeap = OS.GetProcessHeap();
268     if (printerData !is null) {
269         byte buffer [] = printerData.otherData;
270         if (buffer !is null && buffer.length !is 0) {
271             /* If user setup info from a previous print dialog was specified, restore the DEVMODE struct. */
272             lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length);
273             OS.MoveMemory(lpInitData, buffer.ptr, buffer.length);
274             pd.hDevMode = lpInitData;
275         }
276     }
277     pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE;
278     if (printToFile) pd.Flags |= OS.PD_PRINTTOFILE;
279     switch (scope_) {
280         case PrinterData.PAGE_RANGE: pd.Flags |= OS.PD_PAGENUMS; break;
281         case PrinterData.SELECTION: pd.Flags |= OS.PD_SELECTION; break;
282         default: pd.Flags |= OS.PD_ALLPAGES;
283     }
284     pd.nMinPage = 1;
285     pd.nMaxPage = cast(ushort)-1;
286     pd.nFromPage = cast(short) Math.min (0xFFFF, Math.max (1, startPage));
287     pd.nToPage = cast(short) Math.min (0xFFFF, Math.max (1, endPage));
288
289     Display display = parent.getDisplay();
290     Shell [] shells = display.getShells();
291     if ((getStyle() & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
292         for (int i=0; i<shells.length; i++) {
293             if (shells[i].isEnabled() && shells[i] !is parent) {
294                 shells[i].setEnabled(false);
295             } else {
296                 shells[i] = null;
297             }
298         }
299     }
300     PrinterData data = null;
301     String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
302     Object oldValue = display.getData(key);
303     display.setData(key, new ValueWrapperBool(true));
304     bool success = cast(bool)OS.PrintDlg(&pd);
305     display.setData(key, oldValue);
306     if ((getStyle() & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
307         for (int i=0; i<shells.length; i++) {
308             if (shells[i] !is null && !shells[i].isDisposed ()) {
309                 shells[i].setEnabled(true);
310             }
311         }
312     }
313
314     if (success) {
315         /* Get driver and device from the DEVNAMES struct */
316         auto hMem = pd.hDevNames;
317         /* Ensure size is a multiple of 2 bytes on UNICODE platforms */
318         int size = OS.GlobalSize(hMem) / TCHAR.sizeof * TCHAR.sizeof;
319         auto ptr = OS.GlobalLock(hMem);
320         short[4] offsets;
321         OS.MoveMemory(offsets.ptr, ptr, 2 * offsets.length);
322         TCHAR[] buffer = NewTCHARs(0, size);
323         OS.MoveMemory(buffer.ptr, ptr, size);
324         OS.GlobalUnlock(hMem);
325
326         int driverOffset = offsets[0];
327         int i = 0;
328         while (driverOffset + i < size) {
329             if (buffer[driverOffset + i] is 0) break;
330             i++;
331         }
332         String driver = TCHARsToStr( buffer[driverOffset .. driverOffset+i] );
333
334         int deviceOffset = offsets[1];
335         i = 0;
336         while (deviceOffset + i < size) {
337             if (buffer[deviceOffset + i] is 0) break;
338             i++;
339         }
340         String device = TCHARsToStr( buffer[deviceOffset .. deviceOffset+i] );
341
342         int outputOffset = offsets[2];
343         i = 0;
344         while (outputOffset + i < size) {
345             if (buffer[outputOffset + i] is 0) break;
346             i++;
347         }
348         String output = TCHARsToStr( buffer[outputOffset .. outputOffset+i] );
349
350         /* Create PrinterData object and set fields from PRINTDLG */
351         data = new PrinterData(driver, device);
352         if ((pd.Flags & OS.PD_PAGENUMS) !is 0) {
353             data.scope_ = PrinterData.PAGE_RANGE;
354             data.startPage = pd.nFromPage & 0xFFFF;
355             data.endPage = pd.nToPage & 0xFFFF;
356         } else if ((pd.Flags & OS.PD_SELECTION) !is 0) {
357             data.scope_ = PrinterData.SELECTION;
358         }
359         data.printToFile = (pd.Flags & OS.PD_PRINTTOFILE) !is 0;
360         if (data.printToFile) data.fileName = output;
361         data.copyCount = pd.nCopies;
362         data.collate = (pd.Flags & OS.PD_COLLATE) !is 0;
363
364         /* Bulk-save the printer-specific settings in the DEVMODE struct */
365         hMem = pd.hDevMode;
366         size = OS.GlobalSize(hMem);
367         ptr = OS.GlobalLock(hMem);
368         data.otherData = new byte[size];
369         OS.MoveMemory(data.otherData.ptr, ptr, size);
370         OS.GlobalUnlock(hMem);
371         if (lpInitData !is null) OS.HeapFree(hHeap, 0, lpInitData);
372
373         endPage = data.endPage;
374         printToFile = data.printToFile;
375         scope_ = data.scope_;
376         startPage = data.startPage;
377     }
378     return data;
379 }
380 }
Note: See TracBrowser for help on using the browser.