Mercurial > projects > dwt-win
changeset 152:cc00a2772bf4
PrintDialog
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Wed, 13 Feb 2008 17:40:04 +0100 |
parents | af0e7b559478 |
children | 6fbc419f4acd |
files | dwt/printing/PrintDialog.d |
diffstat | 1 files changed, 339 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/printing/PrintDialog.d Wed Feb 13 17:40:04 2008 +0100 @@ -0,0 +1,339 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwt.printing.PrintDialog; + + +import dwt.DWT; +import dwt.DWTException; +import dwt.internal.win32.OS; +import dwt.widgets.Control; +import dwt.widgets.Dialog; +import dwt.widgets.Display; +import dwt.widgets.Shell; +import dwt.widgets.Widget; + +import dwt.printing.Printer; +import dwt.printing.PrinterData; + +import dwt.dwthelper.utils; + +/** + * Instances of this class allow the user to select + * a printer and various print-related parameters + * prior to starting a print job. + * <p> + * IMPORTANT: This class is intended to be subclassed <em>only</em> + * within the DWT implementation. + * </p> + */ + +public class PrintDialog : Dialog { + int scope_ = PrinterData.ALL_PAGES; + int startPage = 1, endPage = 1; + bool printToFile = false; + +/** + * Constructs a new instance of this class given only its parent. + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + * + * @see DWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public this (Shell parent) { + this (parent, DWT.PRIMARY_MODAL); +} + +/** + * Constructs a new instance of this class given its parent + * and a style value describing its behavior and appearance. + * <p> + * The style value is either one of the style constants defined in + * class <code>DWT</code> which is applicable to instances of this + * class, or must be built by <em>bitwise OR</em>'ing together + * (that is, using the <code>int</code> "|" operator) two or more + * of those <code>DWT</code> style constants. The class description + * lists the style constants that are applicable to the class. + * Style bits are also inherited from superclasses. + * </p> + * + * @param parent a composite control which will be the parent of the new instance (cannot be null) + * @param style the style of control to construct + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> + * </ul> + * @exception DWTException <ul> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> + * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> + * </ul> + * + * @see DWT + * @see Widget#checkSubclass + * @see Widget#getStyle + */ +public this (Shell parent, int style) { + super (parent, style); + checkSubclass (); +} + +/** + * Returns the print job scope that the user selected + * before pressing OK in the dialog. This will be one + * of the following values: + * <dl> + * <dt><code>ALL_PAGES</code></dt> + * <dd>Print all pages in the current document</dd> + * <dt><code>PAGE_RANGE</code></dt> + * <dd>Print the range of pages specified by startPage and endPage</dd> + * <dt><code>SELECTION</code></dt> + * <dd>Print the current selection</dd> + * </dl> + * + * @return the scope setting that the user selected + */ +public int getScope() { + return scope_; +} + +/** + * Sets the scope of the print job. The user will see this + * setting when the dialog is opened. This can have one of + * the following values: + * <dl> + * <dt><code>ALL_PAGES</code></dt> + * <dd>Print all pages in the current document</dd> + * <dt><code>PAGE_RANGE</code></dt> + * <dd>Print the range of pages specified by startPage and endPage</dd> + * <dt><code>SELECTION</code></dt> + * <dd>Print the current selection</dd> + * </dl> + * + * @param scope the scope setting when the dialog is opened + */ +public void setScope(int scope_) { + this.scope_ = scope_; +} + +/** + * Returns the start page setting that the user selected + * before pressing OK in the dialog. + * <p> + * This value can be from 1 to the maximum number of pages for the platform. + * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. + * </p> + * + * @return the start page setting that the user selected + */ +public int getStartPage() { + return startPage; +} + +/** + * Sets the start page that the user will see when the dialog + * is opened. + * <p> + * This value can be from 1 to the maximum number of pages for the platform. + * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. + * </p> + * + * @param startPage the startPage setting when the dialog is opened + */ +public void setStartPage(int startPage) { + this.startPage = startPage; +} + +/** + * Returns the end page setting that the user selected + * before pressing OK in the dialog. + * <p> + * This value can be from 1 to the maximum number of pages for the platform. + * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. + * </p> + * + * @return the end page setting that the user selected + */ +public int getEndPage() { + return endPage; +} + +/** + * Sets the end page that the user will see when the dialog + * is opened. + * <p> + * This value can be from 1 to the maximum number of pages for the platform. + * Note that it is only valid if the scope is <code>PAGE_RANGE</code>. + * </p> + * + * @param endPage the end page setting when the dialog is opened + */ +public void setEndPage(int endPage) { + this.endPage = endPage; +} + +/** + * Returns the 'Print to file' setting that the user selected + * before pressing OK in the dialog. + * + * @return the 'Print to file' setting that the user selected + */ +public bool getPrintToFile() { + return printToFile; +} + +/** + * Sets the 'Print to file' setting that the user will see + * when the dialog is opened. + * + * @param printToFile the 'Print to file' setting when the dialog is opened + */ +public void setPrintToFile(bool printToFile) { + this.printToFile = printToFile; +} + +protected void checkSubclass() { + char[] name = this.classinfo.name; + char[] validName = PrintDialog.classinfo.name; + if (validName!=/*eq*/name) { + DWT.error(DWT.ERROR_INVALID_SUBCLASS); + } +} + +/** + * Makes the receiver visible and brings it to the front + * of the display. + * + * @return a printer data object describing the desired print job parameters + * + * @exception DWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + */ +public PrinterData open() { + PRINTDLG pd; + pd.lStructSize = PRINTDLG.sizeof; + Control parent = getParent(); + if (parent !is null) pd.hwndOwner = parent.handle; + pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE; + if (printToFile) pd.Flags |= OS.PD_PRINTTOFILE; + switch (scope_) { + case PrinterData.PAGE_RANGE: pd.Flags |= OS.PD_PAGENUMS; break; + case PrinterData.SELECTION: pd.Flags |= OS.PD_SELECTION; break; + default: pd.Flags |= OS.PD_ALLPAGES; + } + pd.nMinPage = 1; + pd.nMaxPage = cast(ushort)-1; + pd.nFromPage = cast(short) Math.min (0xFFFF, Math.max (1, startPage)); + pd.nToPage = cast(short) Math.min (0xFFFF, Math.max (1, endPage)); + + Display display = parent.getDisplay(); + Shell [] shells = display.getShells(); + if ((getStyle() & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { + for (int i=0; i<shells.length; i++) { + if (shells[i].isEnabled() && shells[i] !is parent) { + shells[i].setEnabled(false); + } else { + shells[i] = null; + } + } + } + PrinterData data = null; + char[] key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$ + Object oldValue = display.getData(key); + display.setData(key, new ValueWrapperBool(true)); + bool success = cast(bool)OS.PrintDlg(&pd); + display.setData(key, oldValue); + if ((getStyle() & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { + for (int i=0; i<shells.length; i++) { + if (shells[i] !is null && !shells[i].isDisposed ()) { + shells[i].setEnabled(true); + } + } + } + + if (success) { + /* Get driver and device from the DEVNAMES struct */ + auto hMem = pd.hDevNames; + /* Ensure size is a multiple of 2 bytes on UNICODE platforms */ + int size = OS.GlobalSize(hMem) / TCHAR.sizeof * TCHAR.sizeof; + auto ptr = OS.GlobalLock(hMem); + short[4] offsets; + OS.MoveMemory(offsets.ptr, ptr, 2 * offsets.length); + TCHAR[] buffer = NewTCHARs(0, size); + OS.MoveMemory(buffer.ptr, ptr, size); + OS.GlobalUnlock(hMem); + + int driverOffset = offsets[0]; + int i = 0; + while (driverOffset + i < size) { + if (buffer[driverOffset + i] is 0) break; + i++; + } + char[] driver = TCHARsToStr( buffer[driverOffset .. driverOffset+i] ); + + int deviceOffset = offsets[1]; + i = 0; + while (deviceOffset + i < size) { + if (buffer[deviceOffset + i] is 0) break; + i++; + } + char[] device = TCHARsToStr( buffer[deviceOffset .. deviceOffset+i] ); + + int outputOffset = offsets[2]; + i = 0; + while (outputOffset + i < size) { + if (buffer[outputOffset + i] is 0) break; + i++; + } + char[] output = TCHARsToStr( buffer[outputOffset .. outputOffset+i] ); + + /* Create PrinterData object and set fields from PRINTDLG */ + data = new PrinterData(driver, device); + if ((pd.Flags & OS.PD_PAGENUMS) !is 0) { + data.scope_ = PrinterData.PAGE_RANGE; + data.startPage = pd.nFromPage & 0xFFFF; + data.endPage = pd.nToPage & 0xFFFF; + } else if ((pd.Flags & OS.PD_SELECTION) !is 0) { + data.scope_ = PrinterData.SELECTION; + } + data.printToFile = (pd.Flags & OS.PD_PRINTTOFILE) !is 0; + if (data.printToFile) data.fileName = output; + data.copyCount = pd.nCopies; + data.collate = (pd.Flags & OS.PD_COLLATE) !is 0; + + /* Bulk-save the printer-specific settings in the DEVMODE struct */ + hMem = pd.hDevMode; + size = OS.GlobalSize(hMem); + ptr = OS.GlobalLock(hMem); + data.otherData = new byte[size]; + OS.MoveMemory(data.otherData.ptr, ptr, size); + OS.GlobalUnlock(hMem); + + endPage = data.endPage; + printToFile = data.printToFile; + scope_ = data.scope_; + startPage = data.startPage; + } + return data; +} +}