]> git.saurik.com Git - wxWidgets.git/blame - src/html/htmprint.cpp
Change wxNotebook selection before sending page changed event in wxMSW.
[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;
9899a70b 199 m_NumPages = INT_MAX;
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;
04dbb646 495
fd0bab43
VZ
496 m_PageBreaks.Clear();
497 m_PageBreaks.Add( 0);
04dbb646 498 do
4f9297b0 499 {
04dbb646 500 pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
fd0bab43
VZ
501 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight),
502 m_PageBreaks,
503 pos, true, INT_MAX);
504 m_PageBreaks.Add( pos);
4f9297b0 505 } while (pos < m_Renderer->GetTotalHeight());
3ce369e6
VS
506}
507
508
509
510void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
511{
512 wxBusyCursor wait;
513
5a21001c 514 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
3ce369e6
VS
515 float ppmm_h, ppmm_v;
516
517 GetPageSizePixels(&pageWidth, &pageHeight);
518 GetPageSizeMM(&mm_w, &mm_h);
519 ppmm_h = (float)pageWidth / mm_w;
520 ppmm_v = (float)pageHeight / mm_h;
4f9297b0 521 dc->GetSize(&dc_w, &dc_h);
3ce369e6 522
edbd0635
VS
523 int ppiPrinterX, ppiPrinterY;
524 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
999836aa 525 wxUnusedVar(ppiPrinterX);
edbd0635
VS
526 int ppiScreenX, ppiScreenY;
527 GetPPIScreen(&ppiScreenX, &ppiScreenY);
999836aa 528 wxUnusedVar(ppiScreenX);
edbd0635 529
9f7e7edb
VS
530 dc->SetUserScale((double)dc_w / (double)pageWidth,
531 (double)dc_h / (double)pageHeight);
04dbb646 532
c44a49b8
VS
533 m_Renderer->SetDC(dc,
534 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
535 (double)ppiPrinterY / (double)ppiScreenY);
04dbb646 536
04ee05f9 537 dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
3ce369e6 538
04dbb646 539 m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
fd0bab43 540 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks,
d1da8872 541 m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
04dbb646 542
fd0bab43 543
c44a49b8
VS
544 m_RendererHdr->SetDC(dc,
545 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
546 (double)ppiPrinterY / (double)ppiScreenY);
04dbb646 547 if (m_Headers[page % 2] != wxEmptyString)
4f9297b0
VS
548 {
549 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
fd0bab43 550 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks);
3ce369e6 551 }
04dbb646 552 if (m_Footers[page % 2] != wxEmptyString)
4f9297b0
VS
553 {
554 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
fd0bab43 555 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks);
3ce369e6
VS
556 }
557}
558
559
560
561wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
562{
563 wxString r = instr;
564 wxString num;
04dbb646 565
66a77a74
OK
566 num.Printf(wxT("%i"), page);
567 r.Replace(wxT("@PAGENUM@"), num);
3ce369e6 568
b4a980f4 569 num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.GetCount() - 1));
66a77a74 570 r.Replace(wxT("@PAGESCNT@"), num);
3ce369e6 571
766571a7
VZ
572 const wxDateTime now = wxDateTime::Now();
573 r.Replace(wxT("@DATE@"), now.FormatDate());
574 r.Replace(wxT("@TIME@"), now.FormatTime());
575
576 r.Replace(wxT("@TITLE@"), GetTitle());
577
3ce369e6
VS
578 return r;
579}
580
581
582
583void wxHtmlPrintout::SetMargins(float top, float bottom, float left, float right, float spaces)
584{
585 m_MarginTop = top;
586 m_MarginBottom = bottom;
587 m_MarginLeft = left;
588 m_MarginRight = right;
589 m_MarginSpace = spaces;
590}
591
592
593
594
fbfb8bcc 595void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
4eecf115
VS
596 const int *sizes)
597{
598 m_Renderer->SetFonts(normal_face, fixed_face, sizes);
599 m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
600}
3ce369e6 601
10e5c7ea
VS
602void wxHtmlPrintout::SetStandardFonts(int size,
603 const wxString& normal_face,
604 const wxString& fixed_face)
7acd3625 605{
10e5c7ea
VS
606 m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
607 m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
7acd3625
RD
608}
609
610
4eecf115
VS
611
612//----------------------------------------------------------------------------
3ce369e6 613// wxHtmlEasyPrinting
4eecf115 614//----------------------------------------------------------------------------
3ce369e6
VS
615
616
a5ae8241 617wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
3ce369e6 618{
a5ae8241 619 m_ParentWindow = parentWindow;
3ce369e6 620 m_Name = name;
632783de 621 m_PrintData = NULL;
3ce369e6
VS
622 m_PageSetupData = new wxPageSetupDialogData;
623 m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
04dbb646 624
d1da8872 625 m_PageSetupData->EnableMargins(true);
04dbb646 626 m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
4f9297b0 627 m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
4eecf115 628
7258d995 629 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
3ce369e6
VS
630}
631
632
633
634wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
635{
636 delete m_PrintData;
637 delete m_PageSetupData;
638}
639
640
632783de
VS
641wxPrintData *wxHtmlEasyPrinting::GetPrintData()
642{
643 if (m_PrintData == NULL)
644 m_PrintData = new wxPrintData();
645 return m_PrintData;
646}
647
3ce369e6 648
f6bcfd97 649bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
3ce369e6
VS
650{
651 wxHtmlPrintout *p1 = CreatePrintout();
4f9297b0 652 p1->SetHtmlFile(htmlfile);
3ce369e6 653 wxHtmlPrintout *p2 = CreatePrintout();
4f9297b0 654 p2->SetHtmlFile(htmlfile);
f6bcfd97 655 return DoPreview(p1, p2);
3ce369e6
VS
656}
657
658
659
f6bcfd97 660bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
3ce369e6
VS
661{
662 wxHtmlPrintout *p1 = CreatePrintout();
d1da8872 663 p1->SetHtmlText(htmltext, basepath, true);
3ce369e6 664 wxHtmlPrintout *p2 = CreatePrintout();
d1da8872 665 p2->SetHtmlText(htmltext, basepath, true);
f6bcfd97 666 return DoPreview(p1, p2);
3ce369e6
VS
667}
668
669
670
f6bcfd97 671bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
3ce369e6
VS
672{
673 wxHtmlPrintout *p = CreatePrintout();
4f9297b0 674 p->SetHtmlFile(htmlfile);
453507f2
VS
675 bool ret = DoPrint(p);
676 delete p;
677 return ret;
3ce369e6
VS
678}
679
680
681
f6bcfd97 682bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
3ce369e6
VS
683{
684 wxHtmlPrintout *p = CreatePrintout();
d1da8872 685 p->SetHtmlText(htmltext, basepath, true);
453507f2
VS
686 bool ret = DoPrint(p);
687 delete p;
688 return ret;
3ce369e6
VS
689}
690
691
692
f6bcfd97 693bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
3ce369e6
VS
694{
695 // Pass two printout objects: for preview, and possible printing.
632783de 696 wxPrintDialogData printDialogData(*GetPrintData());
3ce369e6 697 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
04dbb646 698 if (!preview->Ok())
4f9297b0 699 {
3ce369e6 700 delete preview;
d1da8872 701 return false;
3ce369e6 702 }
3ca6a5f0 703
a5ae8241 704 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
04dbb646 705 m_Name + _(" Preview"),
3ca6a5f0 706 wxPoint(100, 100), wxSize(650, 500));
4f9297b0
VS
707 frame->Centre(wxBOTH);
708 frame->Initialize();
d1da8872
WS
709 frame->Show(true);
710 return true;
3ce369e6
VS
711}
712
713
714
f6bcfd97 715bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
3ce369e6 716{
632783de 717 wxPrintDialogData printDialogData(*GetPrintData());
3ce369e6
VS
718 wxPrinter printer(&printDialogData);
719
d1da8872 720 if (!printer.Print(m_ParentWindow, printout, true))
f6bcfd97 721 {
d1da8872 722 return false;
f6bcfd97 723 }
3ca6a5f0 724
632783de 725 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
d1da8872 726 return true;
3ce369e6
VS
727}
728
729
730
3ce369e6
VS
731
732void wxHtmlEasyPrinting::PageSetup()
733{
632783de 734 if (!GetPrintData()->Ok())
58cf0491 735 {
936b18ac 736 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
58cf0491
JS
737 return;
738 }
739
632783de 740 m_PageSetupData->SetPrintData(*GetPrintData());
a5ae8241 741 wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
3ce369e6 742
04dbb646 743 if (pageSetupDialog.ShowModal() == wxID_OK)
4f9297b0 744 {
632783de 745 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
3ce369e6
VS
746 (*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
747 }
748}
749
750
751
752void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
753{
04dbb646 754 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 755 m_Headers[0] = header;
04dbb646 756 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
757 m_Headers[1] = header;
758}
759
760
761
762void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
763{
04dbb646 764 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
3ce369e6 765 m_Footers[0] = footer;
04dbb646 766 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
3ce369e6
VS
767 m_Footers[1] = footer;
768}
769
770
fbfb8bcc 771void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
4eecf115
VS
772 const int *sizes)
773{
10e5c7ea 774 m_fontMode = FontMode_Explicit;
4eecf115
VS
775 m_FontFaceNormal = normal_face;
776 m_FontFaceFixed = fixed_face;
777
778 if (sizes)
779 {
780 m_FontsSizes = m_FontsSizesArr;
781 for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
782 }
783 else
784 m_FontsSizes = NULL;
785}
786
10e5c7ea
VS
787void wxHtmlEasyPrinting::SetStandardFonts(int size,
788 const wxString& normal_face,
789 const wxString& fixed_face)
7acd3625 790{
10e5c7ea
VS
791 m_fontMode = FontMode_Standard;
792 m_FontFaceNormal = normal_face;
793 m_FontFaceFixed = fixed_face;
794 m_FontsSizesArr[0] = size;
7acd3625
RD
795}
796
3ce369e6
VS
797
798wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
799{
800 wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
04dbb646 801
10e5c7ea
VS
802 if (m_fontMode == FontMode_Explicit)
803 {
804 p->SetFonts(m_FontFaceNormal, m_FontFaceFixed, m_FontsSizes);
805 }
806 else // FontMode_Standard
807 {
808 p->SetStandardFonts(m_FontsSizesArr[0],
809 m_FontFaceNormal, m_FontFaceFixed);
810 }
4eecf115 811
4f9297b0
VS
812 p->SetHeader(m_Headers[0], wxPAGE_EVEN);
813 p->SetHeader(m_Headers[1], wxPAGE_ODD);
814 p->SetFooter(m_Footers[0], wxPAGE_EVEN);
815 p->SetFooter(m_Footers[1], wxPAGE_ODD);
816
817 p->SetMargins(m_PageSetupData->GetMarginTopLeft().y,
818 m_PageSetupData->GetMarginBottomRight().y,
819 m_PageSetupData->GetMarginTopLeft().x,
820 m_PageSetupData->GetMarginBottomRight().x);
04dbb646 821
3ce369e6
VS
822 return p;
823}
824
fa10c70c
JS
825// A module to allow initialization/cleanup
826// without calling these functions from app.cpp or from
827// the user's application.
828
829class wxHtmlPrintingModule: public wxModule
830{
831DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
832public:
833 wxHtmlPrintingModule() : wxModule() {}
d1da8872 834 bool OnInit() { return true; }
fa10c70c
JS
835 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
836};
837
838IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
839
3ce369e6 840
0cecad31
VS
841// This hack forces the linker to always link in m_* files
842// (wxHTML doesn't work without handlers from these files)
843#include "wx/html/forcelnk.h"
844FORCE_WXHTML_MODULES()
3ce369e6 845
72cdf4c9 846#endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE