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