]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmprint.cpp
Swap client data pointers in wxRearrangeList too.
[wxWidgets.git] / src / html / htmprint.cpp
CommitLineData
3ce369e6 1/////////////////////////////////////////////////////////////////////////////
93763ad5 2// Name: src/html/htmprint.cpp
3ce369e6
VS
3// Purpose: html printing classes
4// Author: Vaclav Slavik
5// Created: 25/09/99
6// RCS-ID: $Id$
7// Copyright: (c) Vaclav Slavik, 1999
65571936 8// Licence: wxWindows licence
3ce369e6
VS
9/////////////////////////////////////////////////////////////////////////////
10
3ce369e6
VS
11// For compilers that support precompilation, includes "wx/wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
93763ad5 15 #pragma hdrstop
3ce369e6
VS
16#endif
17
93763ad5
WS
18#if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
19
3ce369e6 20#ifndef WX_PRECOMP
04dbb646
VZ
21 #include "wx/log.h"
22 #include "wx/intl.h"
5438a566 23 #include "wx/dc.h"
9eddec69 24 #include "wx/settings.h"
706e740f 25 #include "wx/msgdlg.h"
02761f6c 26 #include "wx/module.h"
c14dc554 27 #include "wx/sizer.h"
3ce369e6
VS
28#endif
29
3ce369e6
VS
30#include "wx/print.h"
31#include "wx/printdlg.h"
32#include "wx/html/htmprint.h"
33#include "wx/wxhtml.h"
34#include "wx/wfstream.h"
fc48f78f 35#include "wx/infobar.h"
3ce369e6
VS
36
37
7258d995
VS
38// default font size of normal text (HTML font size 0) for printing, in points:
39#define DEFAULT_PRINT_FONT_SIZE 12
40
41
c44a49b8
VS
42// CSS specification offer following guidance on dealing with pixel sizes
43// when printing at
44// http://www.w3.org/TR/2004/CR-CSS21-20040225/syndata.html#length-units:
45//
46// Pixel units are relative to the resolution of the viewing device, i.e.,
47// most often a computer display. If the pixel density of the output
48// device is very different from that of a typical computer display, the
49// user agent should rescale pixel values. It is recommended that the [
50// reference pixel] be the visual angle of one pixel on a device with a
51// pixel density of 96dpi and a distance from the reader of an arm's
52// length. For a nominal arm's length of 28 inches, the visual angle is
53// therefore about 0.0213 degrees.
54//
55// For reading at arm's length, 1px thus corresponds to about 0.26 mm
56// (1/96 inch). When printed on a laser printer, meant for reading at a
57// little less than arm's length (55 cm, 21 inches), 1px is about 0.20 mm.
58// On a 300 dots-per-inch (dpi) printer, that may be rounded up to 3 dots
59// (0.25 mm); on a 600 dpi printer, it can be rounded to 5 dots.
60//
61// See also http://trac.wxwidgets.org/ticket/10942.
62#define TYPICAL_SCREEN_DPI 96.0
63
3ce369e6
VS
64//--------------------------------------------------------------------------------
65// wxHtmlDCRenderer
66//--------------------------------------------------------------------------------
67
68
69wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
70{
71 m_DC = NULL;
72 m_Width = m_Height = 0;
73 m_Cells = NULL;
bc55e31b 74 m_Parser = new wxHtmlWinParser();
3ce369e6 75 m_FS = new wxFileSystem();
4f9297b0 76 m_Parser->SetFS(m_FS);
7258d995 77 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
3ce369e6
VS
78}
79
80
81
82wxHtmlDCRenderer::~wxHtmlDCRenderer()
83{
84 if (m_Cells) delete m_Cells;
85 if (m_Parser) delete m_Parser;
86 if (m_FS) delete m_FS;
87}
88
89
90
c44a49b8 91void wxHtmlDCRenderer::SetDC(wxDC *dc, double pixel_scale, double font_scale)
3ce369e6 92{
3ce369e6 93 m_DC = dc;
c44a49b8 94 m_Parser->SetDC(m_DC, pixel_scale, font_scale);
3ce369e6
VS
95}
96
97
98
99void wxHtmlDCRenderer::SetSize(int width, int height)
100{
131fc120
VS
101 wxCHECK_RET( width, "width must be non-zero" );
102 wxCHECK_RET( height, "height must be non-zero" );
103
edbd0635
VS
104 m_Width = width;
105 m_Height = height;
3ce369e6
VS
106}
107
108
3ce369e6
VS
109void wxHtmlDCRenderer::SetHtmlText(const wxString& html, const wxString& basepath, bool isdir)
110{
131fc120
VS
111 wxCHECK_RET( m_DC, "SetDC() must be called before SetHtmlText()" );
112 wxCHECK_RET( m_Width, "SetSize() must be called before SetHtmlText()" );
3ce369e6 113
131fc120 114 wxDELETE(m_Cells);
04dbb646 115
4f9297b0
VS
116 m_FS->ChangePathTo(basepath, isdir);
117 m_Cells = (wxHtmlContainerCell*) m_Parser->Parse(html);
118 m_Cells->SetIndent(0, wxHTML_INDENT_ALL, wxHTML_UNITS_PIXELS);
119 m_Cells->Layout(m_Width);
3ce369e6
VS
120}
121
122
fbfb8bcc 123void wxHtmlDCRenderer::SetFonts(const wxString& normal_face, const wxString& fixed_face,
4eecf115
VS
124 const int *sizes)
125{
126 m_Parser->SetFonts(normal_face, fixed_face, sizes);
131fc120
VS
127
128 if ( m_Cells )
10e5c7ea 129 m_Cells->Layout(m_Width);
131fc120 130 // else: SetHtmlText() not yet called, no need for relayout
4eecf115
VS
131}
132
10e5c7ea
VS
133void wxHtmlDCRenderer::SetStandardFonts(int size,
134 const wxString& normal_face,
135 const wxString& fixed_face)
7acd3625 136{
10e5c7ea 137 m_Parser->SetStandardFonts(size, normal_face, fixed_face);
131fc120
VS
138
139 if ( m_Cells )
10e5c7ea 140 m_Cells->Layout(m_Width);
131fc120 141 // else: SetHtmlText() not yet called, no need for relayout
7acd3625
RD
142}
143
fd0bab43
VZ
144int wxHtmlDCRenderer::Render(int x, int y,
145 wxArrayInt& known_pagebreaks,
146 int from, int dont_render, int to)
3ce369e6 147{
131fc120
VS
148 wxCHECK_MSG( m_Cells, 0, "SetHtmlText() must be called before Render()" );
149 wxCHECK_MSG( m_DC, 0, "SetDC() must be called before Render()" );
04dbb646 150
131fc120 151 int pbreak, hght;
04dbb646 152
edbd0635 153 pbreak = (int)(from + m_Height);
fd0bab43 154 while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks)) {}
edbd0635 155 hght = pbreak - from;
fd0bab43
VZ
156 if(to < hght)
157 hght = to;
04dbb646
VZ
158
159 if (!dont_render)
4f9297b0 160 {
f30e67db
VS
161 wxHtmlRenderingInfo rinfo;
162 wxDefaultHtmlRenderingStyle rstyle;
163 rinfo.SetStyle(&rstyle);
4f9297b0 164 m_DC->SetBrush(*wxWHITE_BRUSH);
2a2e4f4a 165 m_DC->SetClippingRegion(x, y, m_Width, hght);
04dbb646 166 m_Cells->Draw(*m_DC,
36c4ff4d 167 x, (y - from),
26fba7b2 168 y, y + hght,
f30e67db 169 rinfo);
2a2e4f4a 170 m_DC->DestroyClippingRegion();
3ce369e6 171 }
04dbb646 172
4f9297b0 173 if (pbreak < m_Cells->GetHeight()) return pbreak;
3ce369e6
VS
174 else return GetTotalHeight();
175}
176
4209475c
VZ
177int wxHtmlDCRenderer::GetTotalWidth() const
178{
179 return m_Cells ? m_Cells->GetWidth() : 0;
180}
3ce369e6 181
4209475c 182int wxHtmlDCRenderer::GetTotalHeight() const
3ce369e6 183{
4209475c 184 return m_Cells ? m_Cells->GetHeight() : 0;
3ce369e6
VS
185}
186
187
3ce369e6
VS
188//--------------------------------------------------------------------------------
189// wxHtmlPrintout
190//--------------------------------------------------------------------------------
191
192
fa10c70c 193wxList wxHtmlPrintout::m_Filters;
3ce369e6
VS
194
195wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title)
196{
197 m_Renderer = new wxHtmlDCRenderer;
198 m_RendererHdr = new wxHtmlDCRenderer;
efba2b89 199 m_NumPages = wxHTML_PRINT_MAX_PAGES;
d1da8872 200 m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true;
3ce369e6
VS
201 m_Headers[0] = m_Headers[1] = wxEmptyString;
202 m_Footers[0] = m_Footers[1] = wxEmptyString;
203 m_HeaderHeight = m_FooterHeight = 0;
204 SetMargins(); // to default values
7258d995 205 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
3ce369e6
VS
206}
207
208
209
210wxHtmlPrintout::~wxHtmlPrintout()
211{
212 delete m_Renderer;
213 delete m_RendererHdr;
214}
215
fa10c70c
JS
216void wxHtmlPrintout::CleanUpStatics()
217{
222ed1d6 218 WX_CLEAR_LIST(wxList, m_Filters);
fa10c70c 219}
3ce369e6 220
fa10c70c
JS
221// Adds input filter
222void wxHtmlPrintout::AddFilter(wxHtmlFilter *filter)
223{
224 m_Filters.Append(filter);
225}
3ce369e6 226
4209475c
VZ
227bool
228wxHtmlPrintout::CheckFit(const wxSize& pageArea, const wxSize& docArea) const
229{
fc48f78f
VZ
230 // Nothing to do if the contents fits horizontally.
231 if ( docArea.x <= pageArea.x )
232 return true;
233
234 // Otherwise warn the user more or less intrusively depending on whether
235 // we're previewing or printing:
236 if ( wxPrintPreview * const preview = GetPreview() )
237 {
238 // Don't annoy the user too much when previewing by using info bar
239 // instead of a dialog box.
240#if wxUSE_INFOBAR
241 wxFrame * const parent = preview->GetFrame();
242 wxCHECK_MSG( parent, false, "No parent preview frame?" );
243
244 wxSizer * const sizer = parent->GetSizer();
245 wxCHECK_MSG( sizer, false, "Preview frame should be using sizers" );
246
247 wxInfoBar * const bar = new wxInfoBar(parent);
248 sizer->Add(bar, wxSizerFlags().Expand());
249
250 // Note that the message here is similar to the one below but not
251 // exactly the same, notably we don't use the document title here
252 // because it's already clear which document it pertains to and the
253 // title may be long enough to make the text not fit in the window.
254 bar->ShowMessage
255 (
256 _("This document doesn't fit on the page horizontally and "
257 "will be truncated when it is printed."),
258 wxICON_WARNING
259 );
260#endif // wxUSE_INFOBAR
261 }
262 else // We're going to really print and not just preview.
4209475c 263 {
fc48f78f
VZ
264 // This is our last chance to warn the user that the output will be
265 // mangled so do show a message box.
4209475c
VZ
266 wxMessageDialog
267 dlg
268 (
269 NULL,
270 wxString::Format
271 (
272 _("The document \"%s\" doesn't fit on the page "
273 "horizontally and will be truncated if printed.\n"
274 "\n"
275 "Would you like to proceed with printing it nevertheless?"),
276 GetTitle()
277 ),
278 _("Printing"),
9b95e87c 279 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION
4209475c
VZ
280 );
281 dlg.SetExtendedMessage
282 (
283 _("If possible, try changing the layout parameters to "
39dfe3d4 284 "make the printout more narrow.")
4209475c 285 );
3fff7533 286 dlg.SetOKLabel(wxID_PRINT);
4209475c 287
9b95e87c 288 if ( dlg.ShowModal() == wxID_CANCEL )
4209475c
VZ
289 return false;
290 }
291
292 return true;
293}
294
d2b354f9 295void wxHtmlPrintout::OnPreparePrinting()
3ce369e6 296{
5a21001c 297 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
3ce369e6 298 float ppmm_h, ppmm_v;
04dbb646 299
3ce369e6
VS
300 GetPageSizePixels(&pageWidth, &pageHeight);
301 GetPageSizeMM(&mm_w, &mm_h);
302 ppmm_h = (float)pageWidth / mm_w;
303 ppmm_v = (float)pageHeight / mm_h;
304
edbd0635
VS
305 int ppiPrinterX, ppiPrinterY;
306 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
e822d1bd 307 wxUnusedVar(ppiPrinterX);
edbd0635
VS
308 int ppiScreenX, ppiScreenY;
309 GetPPIScreen(&ppiScreenX, &ppiScreenY);
e822d1bd 310 wxUnusedVar(ppiScreenX);
edbd0635 311
4f9297b0 312 GetDC()->GetSize(&dc_w, &dc_h);
edbd0635 313
9f7e7edb
VS
314 GetDC()->SetUserScale((double)dc_w / (double)pageWidth,
315 (double)dc_h / (double)pageHeight);
edbd0635 316
3ce369e6 317 /* prepare headers/footers renderer: */
04dbb646 318
c44a49b8
VS
319 m_RendererHdr->SetDC(GetDC(),
320 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
321 (double)ppiPrinterY / (double)ppiScreenY);
04dbb646 322 m_RendererHdr->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
68be9f09 323 (int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom)));
04dbb646 324 if (m_Headers[0] != wxEmptyString)
4f9297b0
VS
325 {
326 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[0], 1));
327 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
3ce369e6 328 }
04dbb646 329 else if (m_Headers[1] != wxEmptyString)
4f9297b0
VS
330 {
331 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[1], 1));
332 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
3ce369e6 333 }
04dbb646 334 if (m_Footers[0] != wxEmptyString)
4f9297b0
VS
335 {
336 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[0], 1));
337 m_FooterHeight = m_RendererHdr->GetTotalHeight();
3ce369e6 338 }
04dbb646 339 else if (m_Footers[1] != wxEmptyString)
4f9297b0
VS
340 {
341 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[1], 1));
342 m_FooterHeight = m_RendererHdr->GetTotalHeight();
3ce369e6 343 }
04dbb646 344
3ce369e6 345 /* prepare main renderer: */
c44a49b8
VS
346 m_Renderer->SetDC(GetDC(),
347 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
348 (double)ppiPrinterY / (double)ppiScreenY);
4209475c
VZ
349
350 const int printAreaW = int(ppmm_h * (mm_w - m_MarginLeft - m_MarginRight));
351 int printAreaH = int(ppmm_v * (mm_h - m_MarginTop - m_MarginBottom));
352 if ( m_HeaderHeight )
7ff1542d 353 printAreaH -= int(m_HeaderHeight + m_MarginSpace * ppmm_v);
4209475c 354 if ( m_FooterHeight )
7ff1542d 355 printAreaH -= int(m_FooterHeight + m_MarginSpace * ppmm_v);
4209475c
VZ
356
357 m_Renderer->SetSize(printAreaW, printAreaH);
4f9297b0 358 m_Renderer->SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir);
4209475c
VZ
359
360 if ( CheckFit(wxSize(printAreaW, printAreaH),
361 wxSize(m_Renderer->GetTotalWidth(),
fc48f78f 362 m_Renderer->GetTotalHeight())) || IsPreview() )
4209475c
VZ
363 {
364 // do paginate the document
365 CountPages();
366 }
367 //else: if we don't call CountPages() m_PageBreaks remains empty and our
368 // GetPageInfo() will return 0 as max page and so nothing will be
369 // printed
d2b354f9
JS
370}
371
372bool wxHtmlPrintout::OnBeginDocument(int startPage, int endPage)
373{
d1da8872 374 if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false;
d2b354f9 375
d1da8872 376 return true;
3ce369e6
VS
377}
378
379
380bool wxHtmlPrintout::OnPrintPage(int page)
381{
382 wxDC *dc = GetDC();
9695c53a 383 if (dc && dc->IsOk())
4f9297b0 384 {
3ce369e6
VS
385 if (HasPage(page))
386 RenderPage(dc, page);
d1da8872 387 return true;
04dbb646 388 }
d1da8872 389 else return false;
3ce369e6
VS
390}
391
392
393void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
394{
395 *minPage = 1;
b4a980f4 396 if ( m_NumPages >= (signed)m_PageBreaks.GetCount()-1)
fd0bab43
VZ
397 *maxPage = m_NumPages;
398 else
b4a980f4 399 *maxPage = (signed)m_PageBreaks.GetCount()-1;
3ce369e6 400 *selPageFrom = 1;
b4a980f4 401 *selPageTo = (signed)m_PageBreaks.GetCount()-1;
3ce369e6
VS
402}
403
404
405
406bool wxHtmlPrintout::HasPage(int pageNum)
407{
b4a980f4 408 return pageNum > 0 && (unsigned)pageNum < m_PageBreaks.GetCount();
3ce369e6
VS
409}
410
411
412
413void wxHtmlPrintout::SetHtmlText(const wxString& html, const wxString &basepath, bool isdir)
414{
415 m_Document = html;
416 m_BasePath = basepath;
417 m_BasePathIsDir = isdir;
418}
419
3ce369e6
VS
420void wxHtmlPrintout::SetHtmlFile(const wxString& htmlfile)
421{
422 wxFileSystem fs;
72b1ad5c 423 wxFSFile *ff;
d1da8872 424
72b1ad5c
VS
425 if (wxFileExists(htmlfile))
426 ff = fs.OpenFile(wxFileSystem::FileNameToURL(htmlfile));
427 else
428 ff = fs.OpenFile(htmlfile);
04dbb646 429
f5ba273e 430 if (ff == NULL)
04dbb646 431 {
f5ba273e
VS
432 wxLogError(htmlfile + _(": file does not exist!"));
433 return;
434 }
04dbb646 435
d1da8872 436 bool done = false;
fa10c70c
JS
437 wxHtmlFilterHTML defaultFilter;
438 wxString doc;
439
222ed1d6 440 wxList::compatibility_iterator node = m_Filters.GetFirst();
fa10c70c
JS
441 while (node)
442 {
443 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
444 if (h->CanRead(*ff))
445 {
446 doc = h->ReadFile(*ff);
d1da8872 447 done = true;
fa10c70c
JS
448 break;
449 }
450 node = node->GetNext();
451 }
452
453 if (!done)
454 doc = defaultFilter.ReadFile(*ff);
d1da8872
WS
455
456 SetHtmlText(doc, htmlfile, false);
2b5f62a0 457 delete ff;
3ce369e6
VS
458}
459
460
461
462void wxHtmlPrintout::SetHeader(const wxString& header, int pg)
463{
04dbb646 464 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 465 m_Headers[0] = header;
04dbb646 466 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
467 m_Headers[1] = header;
468}
469
470
471
472void wxHtmlPrintout::SetFooter(const wxString& footer, int pg)
473{
04dbb646 474 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 475 m_Footers[0] = footer;
04dbb646 476 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
477 m_Footers[1] = footer;
478}
479
480
481
482void wxHtmlPrintout::CountPages()
483{
484 wxBusyCursor wait;
485 int pageWidth, pageHeight, mm_w, mm_h;
486 float ppmm_h, ppmm_v;
487
488 GetPageSizePixels(&pageWidth, &pageHeight);
489 GetPageSizeMM(&mm_w, &mm_h);
490 ppmm_h = (float)pageWidth / mm_w;
491 ppmm_v = (float)pageHeight / mm_h;
492
493 int pos = 0;
3ce369e6 494 m_NumPages = 0;
fd0bab43 495 // m_PageBreaks[0] = 0;
04dbb646 496
fd0bab43
VZ
497 m_PageBreaks.Clear();
498 m_PageBreaks.Add( 0);
04dbb646 499 do
4f9297b0 500 {
04dbb646 501 pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
fd0bab43
VZ
502 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight),
503 m_PageBreaks,
504 pos, true, INT_MAX);
505 m_PageBreaks.Add( pos);
b4a980f4 506 if( m_PageBreaks.GetCount() > wxHTML_PRINT_MAX_PAGES)
fd0bab43 507 {
a1d5a293 508 wxMessageBox( _("HTML pagination algorithm generated more than the allowed maximum number of pages and it can't continue any longer!"),
fd0bab43
VZ
509 _("Warning"), wxCANCEL | wxICON_ERROR );
510 break;
511 }
4f9297b0 512 } while (pos < m_Renderer->GetTotalHeight());
3ce369e6
VS
513}
514
515
516
517void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
518{
519 wxBusyCursor wait;
520
5a21001c 521 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
3ce369e6
VS
522 float ppmm_h, ppmm_v;
523
524 GetPageSizePixels(&pageWidth, &pageHeight);
525 GetPageSizeMM(&mm_w, &mm_h);
526 ppmm_h = (float)pageWidth / mm_w;
527 ppmm_v = (float)pageHeight / mm_h;
4f9297b0 528 dc->GetSize(&dc_w, &dc_h);
3ce369e6 529
edbd0635
VS
530 int ppiPrinterX, ppiPrinterY;
531 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
999836aa 532 wxUnusedVar(ppiPrinterX);
edbd0635
VS
533 int ppiScreenX, ppiScreenY;
534 GetPPIScreen(&ppiScreenX, &ppiScreenY);
999836aa 535 wxUnusedVar(ppiScreenX);
edbd0635 536
9f7e7edb
VS
537 dc->SetUserScale((double)dc_w / (double)pageWidth,
538 (double)dc_h / (double)pageHeight);
04dbb646 539
c44a49b8
VS
540 m_Renderer->SetDC(dc,
541 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
542 (double)ppiPrinterY / (double)ppiScreenY);
04dbb646 543
04ee05f9 544 dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
3ce369e6 545
04dbb646 546 m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
fd0bab43 547 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks,
d1da8872 548 m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
04dbb646 549
fd0bab43 550
c44a49b8
VS
551 m_RendererHdr->SetDC(dc,
552 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
553 (double)ppiPrinterY / (double)ppiScreenY);
04dbb646 554 if (m_Headers[page % 2] != wxEmptyString)
4f9297b0
VS
555 {
556 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
fd0bab43 557 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks);
3ce369e6 558 }
04dbb646 559 if (m_Footers[page % 2] != wxEmptyString)
4f9297b0
VS
560 {
561 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
fd0bab43 562 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks);
3ce369e6
VS
563 }
564}
565
566
567
568wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
569{
570 wxString r = instr;
571 wxString num;
04dbb646 572
66a77a74
OK
573 num.Printf(wxT("%i"), page);
574 r.Replace(wxT("@PAGENUM@"), num);
3ce369e6 575
b4a980f4 576 num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.GetCount() - 1));
66a77a74 577 r.Replace(wxT("@PAGESCNT@"), num);
3ce369e6 578
766571a7
VZ
579 const wxDateTime now = wxDateTime::Now();
580 r.Replace(wxT("@DATE@"), now.FormatDate());
581 r.Replace(wxT("@TIME@"), now.FormatTime());
582
583 r.Replace(wxT("@TITLE@"), GetTitle());
584
3ce369e6
VS
585 return r;
586}
587
588
589
590void wxHtmlPrintout::SetMargins(float top, float bottom, float left, float right, float spaces)
591{
592 m_MarginTop = top;
593 m_MarginBottom = bottom;
594 m_MarginLeft = left;
595 m_MarginRight = right;
596 m_MarginSpace = spaces;
597}
598
599
600
601
fbfb8bcc 602void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
4eecf115
VS
603 const int *sizes)
604{
605 m_Renderer->SetFonts(normal_face, fixed_face, sizes);
606 m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
607}
3ce369e6 608
10e5c7ea
VS
609void wxHtmlPrintout::SetStandardFonts(int size,
610 const wxString& normal_face,
611 const wxString& fixed_face)
7acd3625 612{
10e5c7ea
VS
613 m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
614 m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
7acd3625
RD
615}
616
617
4eecf115
VS
618
619//----------------------------------------------------------------------------
3ce369e6 620// wxHtmlEasyPrinting
4eecf115 621//----------------------------------------------------------------------------
3ce369e6
VS
622
623
a5ae8241 624wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
3ce369e6 625{
a5ae8241 626 m_ParentWindow = parentWindow;
3ce369e6 627 m_Name = name;
632783de 628 m_PrintData = NULL;
3ce369e6
VS
629 m_PageSetupData = new wxPageSetupDialogData;
630 m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
04dbb646 631
d1da8872 632 m_PageSetupData->EnableMargins(true);
04dbb646 633 m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
4f9297b0 634 m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
4eecf115 635
7258d995 636 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
3ce369e6
VS
637}
638
639
640
641wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
642{
643 delete m_PrintData;
644 delete m_PageSetupData;
645}
646
647
632783de
VS
648wxPrintData *wxHtmlEasyPrinting::GetPrintData()
649{
650 if (m_PrintData == NULL)
651 m_PrintData = new wxPrintData();
652 return m_PrintData;
653}
654
3ce369e6 655
f6bcfd97 656bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
3ce369e6
VS
657{
658 wxHtmlPrintout *p1 = CreatePrintout();
4f9297b0 659 p1->SetHtmlFile(htmlfile);
3ce369e6 660 wxHtmlPrintout *p2 = CreatePrintout();
4f9297b0 661 p2->SetHtmlFile(htmlfile);
f6bcfd97 662 return DoPreview(p1, p2);
3ce369e6
VS
663}
664
665
666
f6bcfd97 667bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
3ce369e6
VS
668{
669 wxHtmlPrintout *p1 = CreatePrintout();
d1da8872 670 p1->SetHtmlText(htmltext, basepath, true);
3ce369e6 671 wxHtmlPrintout *p2 = CreatePrintout();
d1da8872 672 p2->SetHtmlText(htmltext, basepath, true);
f6bcfd97 673 return DoPreview(p1, p2);
3ce369e6
VS
674}
675
676
677
f6bcfd97 678bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
3ce369e6
VS
679{
680 wxHtmlPrintout *p = CreatePrintout();
4f9297b0 681 p->SetHtmlFile(htmlfile);
453507f2
VS
682 bool ret = DoPrint(p);
683 delete p;
684 return ret;
3ce369e6
VS
685}
686
687
688
f6bcfd97 689bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
3ce369e6
VS
690{
691 wxHtmlPrintout *p = CreatePrintout();
d1da8872 692 p->SetHtmlText(htmltext, basepath, true);
453507f2
VS
693 bool ret = DoPrint(p);
694 delete p;
695 return ret;
3ce369e6
VS
696}
697
698
699
f6bcfd97 700bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
3ce369e6
VS
701{
702 // Pass two printout objects: for preview, and possible printing.
632783de 703 wxPrintDialogData printDialogData(*GetPrintData());
3ce369e6 704 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
04dbb646 705 if (!preview->Ok())
4f9297b0 706 {
3ce369e6 707 delete preview;
d1da8872 708 return false;
3ce369e6 709 }
3ca6a5f0 710
a5ae8241 711 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
04dbb646 712 m_Name + _(" Preview"),
3ca6a5f0 713 wxPoint(100, 100), wxSize(650, 500));
4f9297b0
VS
714 frame->Centre(wxBOTH);
715 frame->Initialize();
d1da8872
WS
716 frame->Show(true);
717 return true;
3ce369e6
VS
718}
719
720
721
f6bcfd97 722bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
3ce369e6 723{
632783de 724 wxPrintDialogData printDialogData(*GetPrintData());
3ce369e6
VS
725 wxPrinter printer(&printDialogData);
726
d1da8872 727 if (!printer.Print(m_ParentWindow, printout, true))
f6bcfd97 728 {
d1da8872 729 return false;
f6bcfd97 730 }
3ca6a5f0 731
632783de 732 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
d1da8872 733 return true;
3ce369e6
VS
734}
735
736
737
3ce369e6
VS
738
739void wxHtmlEasyPrinting::PageSetup()
740{
632783de 741 if (!GetPrintData()->Ok())
58cf0491 742 {
936b18ac 743 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
58cf0491
JS
744 return;
745 }
746
632783de 747 m_PageSetupData->SetPrintData(*GetPrintData());
a5ae8241 748 wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
3ce369e6 749
04dbb646 750 if (pageSetupDialog.ShowModal() == wxID_OK)
4f9297b0 751 {
632783de 752 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
3ce369e6
VS
753 (*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
754 }
755}
756
757
758
759void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
760{
04dbb646 761 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 762 m_Headers[0] = header;
04dbb646 763 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
764 m_Headers[1] = header;
765}
766
767
768
769void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
770{
04dbb646 771 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 772 m_Footers[0] = footer;
04dbb646 773 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
774 m_Footers[1] = footer;
775}
776
777
fbfb8bcc 778void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
4eecf115
VS
779 const int *sizes)
780{
10e5c7ea 781 m_fontMode = FontMode_Explicit;
4eecf115
VS
782 m_FontFaceNormal = normal_face;
783 m_FontFaceFixed = fixed_face;
784
785 if (sizes)
786 {
787 m_FontsSizes = m_FontsSizesArr;
788 for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
789 }
790 else
791 m_FontsSizes = NULL;
792}
793
10e5c7ea
VS
794void wxHtmlEasyPrinting::SetStandardFonts(int size,
795 const wxString& normal_face,
796 const wxString& fixed_face)
7acd3625 797{
10e5c7ea
VS
798 m_fontMode = FontMode_Standard;
799 m_FontFaceNormal = normal_face;
800 m_FontFaceFixed = fixed_face;
801 m_FontsSizesArr[0] = size;
7acd3625
RD
802}
803
3ce369e6
VS
804
805wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
806{
807 wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
04dbb646 808
10e5c7ea
VS
809 if (m_fontMode == FontMode_Explicit)
810 {
811 p->SetFonts(m_FontFaceNormal, m_FontFaceFixed, m_FontsSizes);
812 }
813 else // FontMode_Standard
814 {
815 p->SetStandardFonts(m_FontsSizesArr[0],
816 m_FontFaceNormal, m_FontFaceFixed);
817 }
4eecf115 818
4f9297b0
VS
819 p->SetHeader(m_Headers[0], wxPAGE_EVEN);
820 p->SetHeader(m_Headers[1], wxPAGE_ODD);
821 p->SetFooter(m_Footers[0], wxPAGE_EVEN);
822 p->SetFooter(m_Footers[1], wxPAGE_ODD);
823
824 p->SetMargins(m_PageSetupData->GetMarginTopLeft().y,
825 m_PageSetupData->GetMarginBottomRight().y,
826 m_PageSetupData->GetMarginTopLeft().x,
827 m_PageSetupData->GetMarginBottomRight().x);
04dbb646 828
3ce369e6
VS
829 return p;
830}
831
fa10c70c
JS
832// A module to allow initialization/cleanup
833// without calling these functions from app.cpp or from
834// the user's application.
835
836class wxHtmlPrintingModule: public wxModule
837{
838DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
839public:
840 wxHtmlPrintingModule() : wxModule() {}
d1da8872 841 bool OnInit() { return true; }
fa10c70c
JS
842 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
843};
844
845IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
846
3ce369e6 847
0cecad31
VS
848// This hack forces the linker to always link in m_* files
849// (wxHTML doesn't work without handlers from these files)
850#include "wx/html/forcelnk.h"
851FORCE_WXHTML_MODULES()
3ce369e6 852
72cdf4c9 853#endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE