]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/dcprint.cpp
Correct the drawing of check tools with a drop down button in wxAuiToolBar.
[wxWidgets.git] / src / osx / carbon / dcprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/carbon/dcprint.cpp
3 // Purpose:     wxPrinterDC class
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     01/02/97
7 // RCS-ID:      $Id$
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 #if wxUSE_PRINTING_ARCHITECTURE
16
17 #ifdef __BORLANDC__
18     #pragma hdrstop
19 #endif
20
21 #include "wx/dcprint.h"
22
23 #ifndef WX_PRECOMP
24     #include "wx/msgdlg.h"
25     #include "wx/math.h"
26 #endif
27
28 #include "wx/osx/private.h"
29 #include "wx/osx/private/print.h"
30 #include "wx/osx/dcprint.h"
31 #include "wx/graphics.h"
32
33 IMPLEMENT_ABSTRACT_CLASS(wxPrinterDCImpl, wxGCDCImpl)
34
35 class wxNativePrinterDC
36 {
37 public :
38     wxNativePrinterDC() {}
39     virtual ~wxNativePrinterDC() {}
40     virtual bool StartDoc(  wxPrinterDC* dc , const wxString& message ) = 0;
41     virtual void EndDoc( wxPrinterDC* dc ) = 0;
42     virtual void StartPage( wxPrinterDC* dc ) = 0;
43     virtual void EndPage( wxPrinterDC* dc ) = 0;
44     virtual void GetSize( int *w , int *h) const = 0 ;
45     virtual wxSize GetPPI() const = 0 ;
46
47     // returns 0 in case of no Error, otherwise platform specific error codes
48     virtual wxUint32 GetStatus() const = 0 ;
49     bool IsOk() { return GetStatus() == 0 ; }
50
51     static wxNativePrinterDC* Create(wxPrintData* data) ;
52 } ;
53
54 class wxMacCarbonPrinterDC : public wxNativePrinterDC
55 {
56 public :
57     wxMacCarbonPrinterDC( wxPrintData* data ) ;
58     virtual ~wxMacCarbonPrinterDC() ;
59     virtual bool StartDoc(  wxPrinterDC* dc , const wxString& message ) ;
60     virtual void EndDoc( wxPrinterDC* dc ) ;
61     virtual void StartPage( wxPrinterDC* dc ) ;
62     virtual void EndPage( wxPrinterDC* dc ) ;
63     virtual wxUint32 GetStatus() const { return m_err ; }
64     virtual void GetSize( int *w , int *h) const ;
65     virtual wxSize GetPPI() const ;
66 private :
67     wxCoord m_maxX ;
68     wxCoord m_maxY ;
69     wxSize  m_ppi ;
70     OSStatus m_err ;
71 } ;
72
73 wxMacCarbonPrinterDC::wxMacCarbonPrinterDC( wxPrintData* data )
74 {
75     m_err = noErr ;
76     wxOSXPrintData *native = (wxOSXPrintData*) data->GetNativeData() ;
77
78     PMRect rPage;
79     m_err = PMGetAdjustedPageRect(native->GetPageFormat(), &rPage);
80     if ( m_err != noErr )
81         return;
82
83     m_maxX = wxCoord(rPage.right - rPage.left) ;
84     m_maxY = wxCoord(rPage.bottom - rPage.top);
85
86     PMResolution res;
87     PMPrinter printer;
88     m_err = PMSessionGetCurrentPrinter(native->GetPrintSession(), &printer);
89     if ( m_err == noErr )
90     {
91 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
92         if ( PMPrinterGetOutputResolution != NULL )
93         {
94             {
95                 m_err = PMPrinterGetOutputResolution( printer, native->GetPrintSettings(), &res) ;
96                 if ( m_err == -9589 /* kPMKeyNotFound */ )
97                 {
98                     m_err = noErr ;
99                     res.hRes = res.vRes = 300;
100                 }
101             }
102         }
103         else
104 #endif
105         {
106 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
107             m_err = PMPrinterGetPrinterResolution(printer, kPMCurrentValue, &res);
108             if ( m_err != noErr )
109             {
110                 m_err = PMGetResolution((PMPageFormat) (native->GetPageFormat()), &res);
111             }
112 #endif
113         }
114     }
115
116     m_maxX = wxCoord((double)m_maxX * res.hRes / 72.0);
117     m_maxY = wxCoord((double)m_maxY * res.vRes / 72.0);
118
119     m_ppi = wxSize(int(res.hRes), int(res.vRes));
120 }
121
122 wxMacCarbonPrinterDC::~wxMacCarbonPrinterDC()
123 {
124 }
125
126 wxNativePrinterDC* wxNativePrinterDC::Create(wxPrintData* data)
127 {
128     return new wxMacCarbonPrinterDC(data) ;
129 }
130
131 bool wxMacCarbonPrinterDC::StartDoc(  wxPrinterDC* dc , const wxString& message  )
132 {
133     if ( m_err )
134         return false ;
135
136     wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
137     wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
138
139     PMPrintSettingsSetJobName(native->GetPrintSettings(), wxCFStringRef(message));
140
141     m_err = PMSessionBeginCGDocumentNoDialog(native->GetPrintSession(),
142               native->GetPrintSettings(),
143               native->GetPageFormat());
144     if ( m_err != noErr )
145         return false;
146
147     PMRect rPage;
148     m_err = PMGetAdjustedPageRect(native->GetPageFormat(), &rPage);
149     if ( m_err != noErr )
150         return false ;
151
152     m_maxX = wxCoord(rPage.right - rPage.left) ;
153     m_maxY = wxCoord(rPage.bottom - rPage.top);
154
155     PMResolution res;
156     PMPrinter printer;
157
158     m_err = PMSessionGetCurrentPrinter(native->GetPrintSession(), &printer);
159     if (m_err == noErr)
160     {
161 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
162         if ( PMPrinterGetOutputResolution != NULL )
163         {
164             m_err = PMPrinterGetOutputResolution( printer, native->GetPrintSettings(), &res) ;
165             if ( m_err == -9589 /* kPMKeyNotFound */ )
166             {
167                 m_err = noErr ;
168                 res.hRes = res.vRes = 300;
169             }
170         }
171         else
172 #endif
173         {
174 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
175             if ( PMPrinterGetPrinterResolution(printer, kPMCurrentValue, &res) != noErr )
176             {
177                 res.hRes = res.vRes = 300;
178             }
179 #endif
180         }
181     }
182
183     m_maxX = wxCoord((double)m_maxX * res.hRes / 72.0);
184     m_maxY = wxCoord((double)m_maxY * res.vRes / 72.0);
185
186     m_ppi = wxSize(int(res.hRes), int(res.vRes));
187     return true ;
188 }
189
190 void wxMacCarbonPrinterDC::EndDoc( wxPrinterDC* dc )
191 {
192     if ( m_err )
193         return ;
194
195     wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
196     wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
197
198     m_err = PMSessionEndDocumentNoDialog(native->GetPrintSession());
199 }
200
201 void wxMacCarbonPrinterDC::StartPage( wxPrinterDC* dc )
202 {
203     if ( m_err )
204         return ;
205
206     wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
207     wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
208
209     m_err = PMSessionBeginPageNoDialog(native->GetPrintSession(),
210                  native->GetPageFormat(),
211                  NULL);
212
213     CGContextRef pageContext;
214
215     if ( m_err == noErr )
216     {
217         m_err = PMSessionGetCGGraphicsContext(native->GetPrintSession(),
218                                             &pageContext );
219     }
220
221     if ( m_err != noErr )
222     {
223         PMSessionEndPageNoDialog(native->GetPrintSession());
224         PMSessionEndDocumentNoDialog(native->GetPrintSession());
225     }
226     else
227     {
228         PMRect paperRect ;
229         m_err = PMGetAdjustedPaperRect( native->GetPageFormat() , &paperRect ) ;
230         // make sure (0,0) is at the upper left of the printable area (wx conventions)
231         // Core Graphics initially has the lower left of the paper as 0,0
232         if ( !m_err )
233             CGContextTranslateCTM( pageContext , (CGFloat) -paperRect.left , (CGFloat) paperRect.bottom ) ;
234
235         // since this is a non-critical error, we set the flag back
236         m_err = noErr ;
237
238         // Leopard deprecated PMSetResolution() which will not be available in 64 bit mode, so we avoid using it.
239         // To set the proper drawing resolution, the docs suggest the use of CGContextScaleCTM(), so here we go; as a
240         // consequence though, PMGetAdjustedPaperRect() and PMGetAdjustedPageRect() return unscaled rects, so we
241         // have to manually scale them later.
242         CGContextScaleCTM( pageContext, 72.0 / (double)m_ppi.x, -72.0 / (double)m_ppi.y);
243
244         impl->SetGraphicsContext( wxGraphicsContext::CreateFromNative( pageContext ) );
245     }
246 }
247
248 void wxMacCarbonPrinterDC::EndPage( wxPrinterDC* dc )
249 {
250     if ( m_err )
251         return ;
252
253     wxPrinterDCImpl *impl = (wxPrinterDCImpl*) dc->GetImpl();
254     wxOSXPrintData *native = (wxOSXPrintData*) impl->GetPrintData().GetNativeData() ;
255
256     m_err = PMSessionEndPageNoDialog(native->GetPrintSession());
257     if ( m_err != noErr )
258     {
259         PMSessionEndDocumentNoDialog(native->GetPrintSession());
260     }
261     // the cg context we got when starting the page isn't valid anymore, so replace it
262     impl->SetGraphicsContext( wxGraphicsContext::Create() );
263 }
264
265 void wxMacCarbonPrinterDC::GetSize( int *w , int *h) const
266 {
267     if ( w )
268         *w = m_maxX ;
269     if ( h )
270         *h = m_maxY ;
271 }
272
273 wxSize wxMacCarbonPrinterDC::GetPPI() const
274 {
275      return m_ppi ;
276 };
277
278 //
279 //
280 //
281
282 wxPrinterDCImpl::wxPrinterDCImpl( wxPrinterDC *owner, const wxPrintData& printdata )
283    : wxGCDCImpl( owner )
284 {
285     m_ok = false ;
286     m_printData = printdata ;
287     m_printData.ConvertToNative() ;
288     m_nativePrinterDC = wxNativePrinterDC::Create( &m_printData ) ;
289     if ( m_nativePrinterDC )
290     {
291         m_ok = m_nativePrinterDC->IsOk() ;
292         if ( !m_ok )
293         {
294             wxString message ;
295             message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
296             wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
297             dialog.ShowModal();
298         }
299         else
300         {
301             wxSize sz = GetPPI();
302             m_mm_to_pix_x = mm2inches * sz.x;
303             m_mm_to_pix_y = mm2inches * sz.y;
304         }
305         // we need at least a measuring context because people start measuring before a page
306         // gets printed at all
307         SetGraphicsContext( wxGraphicsContext::Create() );
308     }
309 }
310
311 wxSize wxPrinterDCImpl::GetPPI() const
312 {
313     return m_nativePrinterDC->GetPPI() ;
314 }
315
316 wxPrinterDCImpl::~wxPrinterDCImpl()
317 {
318     delete m_nativePrinterDC ;
319 }
320
321 bool wxPrinterDCImpl::StartDoc( const wxString& message )
322 {
323     wxASSERT_MSG( IsOk() , wxT("Called wxPrinterDC::StartDoc from an invalid object") ) ;
324
325     if ( !m_ok )
326         return false ;
327
328     if ( m_nativePrinterDC->StartDoc( (wxPrinterDC*) GetOwner(), message ) )
329     {
330         // in case we have to do additional things when successful
331     }
332     m_ok = m_nativePrinterDC->IsOk() ;
333     if ( !m_ok )
334     {
335         wxString message ;
336         message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
337         wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
338         dialog.ShowModal();
339     }
340
341     return m_ok ;
342 }
343
344 void wxPrinterDCImpl::EndDoc(void)
345 {
346     if ( !m_ok )
347         return ;
348
349     m_nativePrinterDC->EndDoc( (wxPrinterDC*) GetOwner() ) ;
350     m_ok = m_nativePrinterDC->IsOk() ;
351
352     if ( !m_ok )
353     {
354         wxString message ;
355         message.Printf( wxT("Print Error %u"), m_nativePrinterDC->GetStatus() ) ;
356         wxMessageDialog dialog( NULL , message , wxEmptyString, wxICON_HAND | wxOK) ;
357         dialog.ShowModal();
358     }
359 }
360
361 wxRect wxPrinterDCImpl::GetPaperRect() const
362 {
363     wxCoord w, h;
364     GetOwner()->GetSize(&w, &h);
365     wxRect pageRect(0, 0, w, h);
366     wxOSXPrintData *native = (wxOSXPrintData*) m_printData.GetNativeData() ;
367     OSStatus err = noErr ;
368     PMRect rPaper;
369     err = PMGetAdjustedPaperRect(native->GetPageFormat(), &rPaper);
370     if ( err != noErr )
371         return pageRect;
372
373     wxSize ppi = GetOwner()->GetPPI();
374     rPaper.right *= (ppi.x / 72.0);
375     rPaper.bottom *= (ppi.y / 72.0);
376     rPaper.left *= (ppi.x / 72.0);
377     rPaper.top *= (ppi.y / 72.0);
378
379     return wxRect(wxCoord(rPaper.left), wxCoord(rPaper.top),
380         wxCoord(rPaper.right - rPaper.left), wxCoord(rPaper.bottom - rPaper.top));
381 }
382
383 void wxPrinterDCImpl::StartPage()
384 {
385     if ( !m_ok )
386         return ;
387
388     m_logicalFunction = wxCOPY;
389     //  m_textAlignment = wxALIGN_TOP_LEFT;
390     m_backgroundMode = wxTRANSPARENT;
391
392     m_textForegroundColour = *wxBLACK;
393     m_textBackgroundColour = *wxWHITE;
394     m_pen = *wxBLACK_PEN;
395     m_font = *wxNORMAL_FONT;
396     m_brush = *wxTRANSPARENT_BRUSH;
397     m_backgroundBrush = *wxWHITE_BRUSH;
398
399     m_nativePrinterDC->StartPage( (wxPrinterDC*) GetOwner() ) ;
400     m_ok = m_nativePrinterDC->IsOk() ;
401
402 }
403
404 void wxPrinterDCImpl::EndPage()
405 {
406     if ( !m_ok )
407         return ;
408
409     m_nativePrinterDC->EndPage( (wxPrinterDC*) GetOwner() );
410     m_ok = m_nativePrinterDC->IsOk() ;
411 }
412
413 void wxPrinterDCImpl::DoGetSize(int *width, int *height) const
414 {
415     wxCHECK_RET( m_ok , wxT("GetSize() doesn't work without a valid wxPrinterDC") );
416     m_nativePrinterDC->GetSize(width,  height ) ;
417 }
418
419 #endif