1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/generic/printps.cpp
3// Purpose:     Postscript print/preview framework
4// Author:      Julian Smart
5// Modified by:
6// Created:     04/01/98
7// RCS-ID:      $Id: printps.cpp 42522 2006-10-27 13:07:40Z JS $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16    #pragma hdrstop
17#endif
18
19// ============================================================================
20// declarations
21// ============================================================================
22
23// ----------------------------------------------------------------------------
24// headers
25// ----------------------------------------------------------------------------
26
27#if wxUSE_PRINTING_ARCHITECTURE && wxUSE_POSTSCRIPT && (!defined(__WXMSW__) || wxUSE_POSTSCRIPT_ARCHITECTURE_IN_MSW)
28
29#ifndef WX_PRECOMP
30    #include "wx/utils.h"
31    #include "wx/dc.h"
32    #include "wx/app.h"
33    #include "wx/msgdlg.h"
34    #include "wx/intl.h"
35    #include "wx/progdlg.h"
36    #include "wx/log.h"
37    #include "wx/dcprint.h"
38#endif
39
40#include "wx/generic/printps.h"
41#include "wx/printdlg.h"
42#include "wx/generic/prntdlgg.h"
43#include "wx/generic/progdlgg.h"
44#include "wx/paper.h"
45
46#include <stdlib.h>
47
48// ----------------------------------------------------------------------------
49// wxWin macros
50// ----------------------------------------------------------------------------
51
52    IMPLEMENT_DYNAMIC_CLASS(wxPostScriptPrinter, wxPrinterBase)
53    IMPLEMENT_CLASS(wxPostScriptPrintPreview, wxPrintPreviewBase)
54
55// ============================================================================
56// implementation
57// ============================================================================
58
59// ----------------------------------------------------------------------------
60// Printer
61// ----------------------------------------------------------------------------
62
63wxPostScriptPrinter::wxPostScriptPrinter(wxPrintDialogData *data)
64                   : wxPrinterBase(data)
65{
66}
67
68wxPostScriptPrinter::~wxPostScriptPrinter()
69{
70}
71
72bool wxPostScriptPrinter::Print(wxWindow *parent, wxPrintout *printout, bool prompt)
73{
74    sm_abortIt = false;
75    sm_abortWindow = (wxWindow *) NULL;
76
77    if (!printout)
78    {
79        sm_lastError = wxPRINTER_ERROR;
80        return false;
81    }
82
83    printout->SetIsPreview(false);
84
85    if (m_printDialogData.GetMinPage() < 1)
86        m_printDialogData.SetMinPage(1);
87    if (m_printDialogData.GetMaxPage() < 1)
88        m_printDialogData.SetMaxPage(9999);
89
90    // Create a suitable device context
91    wxDC *dc;
92    if (prompt)
93    {
94        dc = PrintDialog(parent);
95        if (!dc)
96            return false;
97    }
98    else
99    {
100        dc = new wxPostScriptDC(GetPrintDialogData().GetPrintData());
101    }
102
103    // May have pressed cancel.
104    if (!dc || !dc->Ok())
105    {
106        if (dc) delete dc;
107        sm_lastError = wxPRINTER_ERROR;
108        return false;
109    }
110
111    wxSize ScreenPixels = wxGetDisplaySize();
112    wxSize ScreenMM = wxGetDisplaySizeMM();
113
114    printout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()),
115                            (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) );
116    printout->SetPPIPrinter( wxPostScriptDC::GetResolution(),
117                             wxPostScriptDC::GetResolution() );
118
119    // Set printout parameters
120    printout->SetDC(dc);
121
122    int w, h;
123    dc->GetSize(&w, &h);
124    printout->SetPageSizePixels((int)w, (int)h);
125    printout->SetPaperRectPixels(wxRect(0, 0, w, h));
126    int mw, mh;
127    dc->GetSizeMM(&mw, &mh);
128    printout->SetPageSizeMM((int)mw, (int)mh);
129
130    // Create an abort window
131    wxBeginBusyCursor();
132
133    printout->OnPreparePrinting();
134
135    // Get some parameters from the printout, if defined
136    int fromPage, toPage;
137    int minPage, maxPage;
138    printout->GetPageInfo(&minPage, &maxPage, &fromPage, &toPage);
139
140    if (maxPage == 0)
141    {
142        sm_lastError = wxPRINTER_ERROR;
143        wxEndBusyCursor();
144        return false;
145    }
146
147    // Only set min and max, because from and to have been
148    // set by the user
149    m_printDialogData.SetMinPage(minPage);
150    m_printDialogData.SetMaxPage(maxPage);
151
152    if (m_printDialogData.GetFromPage() < minPage)
153        m_printDialogData.SetFromPage( minPage );
154    if (m_printDialogData.GetToPage() > maxPage)
155        m_printDialogData.SetToPage( maxPage );
156
157    int
158       pagesPerCopy = m_printDialogData.GetToPage()-m_printDialogData.GetFromPage()+1,
159       totalPages = pagesPerCopy * m_printDialogData.GetNoCopies(),
160       printedPages = 0;
161    // Open the progress bar dialog
162    wxProgressDialog *progressDialog = new wxProgressDialog (
163       printout->GetTitle(),
164       _("Printing..."),
165       totalPages,
166       parent,
167       wxPD_CAN_ABORT|wxPD_AUTO_HIDE|wxPD_APP_MODAL);
168
169    printout->OnBeginPrinting();
170
171    sm_lastError = wxPRINTER_NO_ERROR;
172
173    bool keepGoing = true;
174
175    int copyCount;
176    for (copyCount = 1; copyCount <= m_printDialogData.GetNoCopies(); copyCount ++)
177    {
178        if (!printout->OnBeginDocument(m_printDialogData.GetFromPage(), m_printDialogData.GetToPage()))
179        {
180            wxEndBusyCursor();
181            wxLogError(_("Could not start printing."));
182            sm_lastError = wxPRINTER_ERROR;
183            break;
184        }
185        if (sm_abortIt)
186        {
187            sm_lastError = wxPRINTER_CANCELLED;
188            break;
189        }
190
191        int pn;
192        for (pn = m_printDialogData.GetFromPage(); keepGoing && (pn <= m_printDialogData.GetToPage()) && printout->HasPage(pn);
193        pn++)
194        {
195            if (sm_abortIt)
196            {
197                keepGoing = false;
198                sm_lastError = wxPRINTER_CANCELLED;
199                break;
200            }
201            else
202            {
203               wxString msg;
204               msg.Printf(_("Printing page %d..."), printedPages+1);
205               if(progressDialog->Update(printedPages++, msg))
206               {
207                  dc->StartPage();
208                  printout->OnPrintPage(pn);
209                  dc->EndPage();
210               }
211               else
212               {
213                  sm_abortIt = true;
214                  sm_lastError = wxPRINTER_CANCELLED;
215                  keepGoing = false;
216               }
217            }
218            wxYield();
219        }
220        printout->OnEndDocument();
221    }
222
223    printout->OnEndPrinting();
224    delete progressDialog;
225
226    wxEndBusyCursor();
227
228    delete dc;
229
230    return (sm_lastError == wxPRINTER_NO_ERROR);
231}
232
233wxDC* wxPostScriptPrinter::PrintDialog(wxWindow *parent)
234{
235    wxDC* dc = (wxDC*) NULL;
236
237    wxGenericPrintDialog dialog( parent, &m_printDialogData );
238    if (dialog.ShowModal() == wxID_OK)
239    {
240        dc = dialog.GetPrintDC();
241        m_printDialogData = dialog.GetPrintDialogData();
242
243        if (dc == NULL)
244            sm_lastError = wxPRINTER_ERROR;
245        else
246            sm_lastError = wxPRINTER_NO_ERROR;
247    }
248    else
249        sm_lastError = wxPRINTER_CANCELLED;
250
251    return dc;
252}
253
254bool wxPostScriptPrinter::Setup(wxWindow *WXUNUSED(parent))
255{
256#if 0
257    wxGenericPrintDialog* dialog = new wxGenericPrintDialog(parent, & m_printDialogData);
258    dialog->GetPrintDialogData().SetSetupDialog(true);
259
260    int ret = dialog->ShowModal();
261
262    if (ret == wxID_OK)
263    {
264        m_printDialogData = dialog->GetPrintDialogData();
265    }
266
267    dialog->Destroy();
268
269    return (ret == wxID_OK);
270#endif
271
272    return false;
273}
274
275// ----------------------------------------------------------------------------
276// Print preview
277// ----------------------------------------------------------------------------
278
279void wxPostScriptPrintPreview::Init(wxPrintout * WXUNUSED(printout),
280                                    wxPrintout * WXUNUSED(printoutForPrinting))
281{
282    // Have to call it here since base constructor can't call it
283    DetermineScaling();
284}
285
286wxPostScriptPrintPreview::wxPostScriptPrintPreview(wxPrintout *printout,
287                                                   wxPrintout *printoutForPrinting,
288                                                   wxPrintDialogData *data)
289                        : wxPrintPreviewBase(printout, printoutForPrinting, data)
290{
291    Init(printout, printoutForPrinting);
292}
293
294wxPostScriptPrintPreview::wxPostScriptPrintPreview(wxPrintout *printout,
295                                                   wxPrintout *printoutForPrinting,
296                                                   wxPrintData *data)
297                        : wxPrintPreviewBase(printout, printoutForPrinting, data)
298{
299    Init(printout, printoutForPrinting);
300}
301
302wxPostScriptPrintPreview::~wxPostScriptPrintPreview()
303{
304}
305
306bool wxPostScriptPrintPreview::Print(bool interactive)
307{
308    if (!m_printPrintout)
309        return false;
310
311    // Assume that on Unix, the preview may use the PostScript
312    // (generic) version, but printing using the native system is required.
313    // TODO: make a generic print preview class from which wxPostScriptPrintPreview
314    // is derived.
315#ifdef __UNIX__
316    wxPrinter printer(& m_printDialogData);
317#else
318    wxPostScriptPrinter printer(& m_printDialogData);
319#endif
320    return printer.Print(m_previewFrame, m_printPrintout, interactive);
321}
322
323void wxPostScriptPrintPreview::DetermineScaling()
324{
325    wxPaperSize paperType = m_printDialogData.GetPrintData().GetPaperId();
326    if (paperType == wxPAPER_NONE)
327        paperType = wxPAPER_NONE;
328
329    wxPrintPaperType *paper = wxThePrintPaperDatabase->FindPaperType(paperType);
330    if (!paper)
331        paper = wxThePrintPaperDatabase->FindPaperType(wxPAPER_A4);
332
333    if (paper)
334    {
335        wxSize ScreenPixels = wxGetDisplaySize();
336        wxSize ScreenMM = wxGetDisplaySizeMM();
337
338        m_previewPrintout->SetPPIScreen( (int) ((ScreenPixels.GetWidth() * 25.4) / ScreenMM.GetWidth()),
339                                         (int) ((ScreenPixels.GetHeight() * 25.4) / ScreenMM.GetHeight()) );
340        m_previewPrintout->SetPPIPrinter(wxPostScriptDC::GetResolution(), wxPostScriptDC::GetResolution());
341
342        wxSize sizeDevUnits(paper->GetSizeDeviceUnits());
343        sizeDevUnits.x = (wxCoord)((float)sizeDevUnits.x * wxPostScriptDC::GetResolution() / 72.0);
344        sizeDevUnits.y = (wxCoord)((float)sizeDevUnits.y * wxPostScriptDC::GetResolution() / 72.0);
345        wxSize sizeTenthsMM(paper->GetSize());
346        wxSize sizeMM(sizeTenthsMM.x / 10, sizeTenthsMM.y / 10);
347
348        // If in landscape mode, we need to swap the width and height.
349        if ( m_printDialogData.GetPrintData().GetOrientation() == wxLANDSCAPE )
350        {
351            m_pageWidth = sizeDevUnits.y;
352            m_pageHeight = sizeDevUnits.x;
353            m_previewPrintout->SetPageSizeMM(sizeMM.y, sizeMM.x);
354        }
355        else
356        {
357            m_pageWidth = sizeDevUnits.x;
358            m_pageHeight = sizeDevUnits.y;
359            m_previewPrintout->SetPageSizeMM(sizeMM.x, sizeMM.y);
360        }
361        m_previewPrintout->SetPageSizePixels(m_pageWidth, m_pageHeight);
362        m_previewPrintout->SetPaperRectPixels(wxRect(0, 0, m_pageWidth, m_pageHeight));
363
364        // At 100%, the page should look about page-size on the screen.
365        m_previewScaleX = (float)0.8 * 72.0 / (float)wxPostScriptDC::GetResolution();
366        m_previewScaleY = m_previewScaleX;
367    }
368}
369
370#endif
371