Notify user less intrusively about overflow when previewing HTML printouts.
[wxWidgets.git] / src / html / htmprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/html/htmprint.cpp
3 // Purpose: html printing classes
4 // Author: Vaclav Slavik
5 // Created: 25/09/99
6 // RCS-ID: $Id$
7 // Copyright: (c) Vaclav Slavik, 1999
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
19
20 #ifndef WX_PRECOMP
21 #include "wx/log.h"
22 #include "wx/intl.h"
23 #include "wx/dc.h"
24 #include "wx/settings.h"
25 #include "wx/msgdlg.h"
26 #include "wx/module.h"
27 #endif
28
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"
34 #include "wx/infobar.h"
35
36
37 // default font size of normal text (HTML font size 0) for printing, in points:
38 #define DEFAULT_PRINT_FONT_SIZE 12
39
40
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
63 //--------------------------------------------------------------------------------
64 // wxHtmlDCRenderer
65 //--------------------------------------------------------------------------------
66
67
68 wxHtmlDCRenderer::wxHtmlDCRenderer() : wxObject()
69 {
70 m_DC = NULL;
71 m_Width = m_Height = 0;
72 m_Cells = NULL;
73 m_Parser = new wxHtmlWinParser();
74 m_FS = new wxFileSystem();
75 m_Parser->SetFS(m_FS);
76 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
77 }
78
79
80
81 wxHtmlDCRenderer::~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
90 void wxHtmlDCRenderer::SetDC(wxDC *dc, double pixel_scale, double font_scale)
91 {
92 m_DC = dc;
93 m_Parser->SetDC(m_DC, pixel_scale, font_scale);
94 }
95
96
97
98 void wxHtmlDCRenderer::SetSize(int width, int height)
99 {
100 wxCHECK_RET( width, "width must be non-zero" );
101 wxCHECK_RET( height, "height must be non-zero" );
102
103 m_Width = width;
104 m_Height = height;
105 }
106
107
108 void wxHtmlDCRenderer::SetHtmlText(const wxString& html, const wxString& basepath, bool isdir)
109 {
110 wxCHECK_RET( m_DC, "SetDC() must be called before SetHtmlText()" );
111 wxCHECK_RET( m_Width, "SetSize() must be called before SetHtmlText()" );
112
113 wxDELETE(m_Cells);
114
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);
119 }
120
121
122 void wxHtmlDCRenderer::SetFonts(const wxString& normal_face, const wxString& fixed_face,
123 const int *sizes)
124 {
125 m_Parser->SetFonts(normal_face, fixed_face, sizes);
126
127 if ( m_Cells )
128 m_Cells->Layout(m_Width);
129 // else: SetHtmlText() not yet called, no need for relayout
130 }
131
132 void wxHtmlDCRenderer::SetStandardFonts(int size,
133 const wxString& normal_face,
134 const wxString& fixed_face)
135 {
136 m_Parser->SetStandardFonts(size, normal_face, fixed_face);
137
138 if ( m_Cells )
139 m_Cells->Layout(m_Width);
140 // else: SetHtmlText() not yet called, no need for relayout
141 }
142
143 int wxHtmlDCRenderer::Render(int x, int y,
144 wxArrayInt& known_pagebreaks,
145 int from, int dont_render, int to)
146 {
147 wxCHECK_MSG( m_Cells, 0, "SetHtmlText() must be called before Render()" );
148 wxCHECK_MSG( m_DC, 0, "SetDC() must be called before Render()" );
149
150 int pbreak, hght;
151
152 pbreak = (int)(from + m_Height);
153 while (m_Cells->AdjustPagebreak(&pbreak, known_pagebreaks)) {}
154 hght = pbreak - from;
155 if(to < hght)
156 hght = to;
157
158 if (!dont_render)
159 {
160 wxHtmlRenderingInfo rinfo;
161 wxDefaultHtmlRenderingStyle rstyle;
162 rinfo.SetStyle(&rstyle);
163 m_DC->SetBrush(*wxWHITE_BRUSH);
164 m_DC->SetClippingRegion(x, y, m_Width, hght);
165 m_Cells->Draw(*m_DC,
166 x, (y - from),
167 y, y + hght,
168 rinfo);
169 m_DC->DestroyClippingRegion();
170 }
171
172 if (pbreak < m_Cells->GetHeight()) return pbreak;
173 else return GetTotalHeight();
174 }
175
176 int wxHtmlDCRenderer::GetTotalWidth() const
177 {
178 return m_Cells ? m_Cells->GetWidth() : 0;
179 }
180
181 int wxHtmlDCRenderer::GetTotalHeight() const
182 {
183 return m_Cells ? m_Cells->GetHeight() : 0;
184 }
185
186
187 //--------------------------------------------------------------------------------
188 // wxHtmlPrintout
189 //--------------------------------------------------------------------------------
190
191
192 wxList wxHtmlPrintout::m_Filters;
193
194 wxHtmlPrintout::wxHtmlPrintout(const wxString& title) : wxPrintout(title)
195 {
196 m_Renderer = new wxHtmlDCRenderer;
197 m_RendererHdr = new wxHtmlDCRenderer;
198 m_NumPages = wxHTML_PRINT_MAX_PAGES;
199 m_Document = m_BasePath = wxEmptyString; m_BasePathIsDir = true;
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
204 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
205 }
206
207
208
209 wxHtmlPrintout::~wxHtmlPrintout()
210 {
211 delete m_Renderer;
212 delete m_RendererHdr;
213 }
214
215 void wxHtmlPrintout::CleanUpStatics()
216 {
217 WX_CLEAR_LIST(wxList, m_Filters);
218 }
219
220 // Adds input filter
221 void wxHtmlPrintout::AddFilter(wxHtmlFilter *filter)
222 {
223 m_Filters.Append(filter);
224 }
225
226 bool
227 wxHtmlPrintout::CheckFit(const wxSize& pageArea, const wxSize& docArea) const
228 {
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.
262 {
263 // This is our last chance to warn the user that the output will be
264 // mangled so do show a message box.
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"),
278 wxOK | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION
279 );
280 dlg.SetExtendedMessage
281 (
282 _("If possible, try changing the layout parameters to "
283 "make the printout more narrow.")
284 );
285 dlg.SetOKLabel(wxID_PRINT);
286
287 if ( dlg.ShowModal() == wxID_CANCEL )
288 return false;
289 }
290
291 return true;
292 }
293
294 void wxHtmlPrintout::OnPreparePrinting()
295 {
296 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
297 float ppmm_h, ppmm_v;
298
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
304 int ppiPrinterX, ppiPrinterY;
305 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
306 wxUnusedVar(ppiPrinterX);
307 int ppiScreenX, ppiScreenY;
308 GetPPIScreen(&ppiScreenX, &ppiScreenY);
309 wxUnusedVar(ppiScreenX);
310
311 GetDC()->GetSize(&dc_w, &dc_h);
312
313 GetDC()->SetUserScale((double)dc_w / (double)pageWidth,
314 (double)dc_h / (double)pageHeight);
315
316 /* prepare headers/footers renderer: */
317
318 m_RendererHdr->SetDC(GetDC(),
319 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
320 (double)ppiPrinterY / (double)ppiScreenY);
321 m_RendererHdr->SetSize((int) (ppmm_h * (mm_w - m_MarginLeft - m_MarginRight)),
322 (int) (ppmm_v * (mm_h - m_MarginTop - m_MarginBottom)));
323 if (m_Headers[0] != wxEmptyString)
324 {
325 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[0], 1));
326 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
327 }
328 else if (m_Headers[1] != wxEmptyString)
329 {
330 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[1], 1));
331 m_HeaderHeight = m_RendererHdr->GetTotalHeight();
332 }
333 if (m_Footers[0] != wxEmptyString)
334 {
335 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[0], 1));
336 m_FooterHeight = m_RendererHdr->GetTotalHeight();
337 }
338 else if (m_Footers[1] != wxEmptyString)
339 {
340 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[1], 1));
341 m_FooterHeight = m_RendererHdr->GetTotalHeight();
342 }
343
344 /* prepare main renderer: */
345 m_Renderer->SetDC(GetDC(),
346 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
347 (double)ppiPrinterY / (double)ppiScreenY);
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 )
352 printAreaH -= int(m_HeaderHeight + m_MarginSpace * ppmm_v);
353 if ( m_FooterHeight )
354 printAreaH -= int(m_FooterHeight + m_MarginSpace * ppmm_v);
355
356 m_Renderer->SetSize(printAreaW, printAreaH);
357 m_Renderer->SetHtmlText(m_Document, m_BasePath, m_BasePathIsDir);
358
359 if ( CheckFit(wxSize(printAreaW, printAreaH),
360 wxSize(m_Renderer->GetTotalWidth(),
361 m_Renderer->GetTotalHeight())) || IsPreview() )
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
369 }
370
371 bool wxHtmlPrintout::OnBeginDocument(int startPage, int endPage)
372 {
373 if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false;
374
375 return true;
376 }
377
378
379 bool wxHtmlPrintout::OnPrintPage(int page)
380 {
381 wxDC *dc = GetDC();
382 if (dc && dc->IsOk())
383 {
384 if (HasPage(page))
385 RenderPage(dc, page);
386 return true;
387 }
388 else return false;
389 }
390
391
392 void wxHtmlPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
393 {
394 *minPage = 1;
395 if ( m_NumPages >= (signed)m_PageBreaks.GetCount()-1)
396 *maxPage = m_NumPages;
397 else
398 *maxPage = (signed)m_PageBreaks.GetCount()-1;
399 *selPageFrom = 1;
400 *selPageTo = (signed)m_PageBreaks.GetCount()-1;
401 }
402
403
404
405 bool wxHtmlPrintout::HasPage(int pageNum)
406 {
407 return pageNum > 0 && (unsigned)pageNum < m_PageBreaks.GetCount();
408 }
409
410
411
412 void 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
419 void wxHtmlPrintout::SetHtmlFile(const wxString& htmlfile)
420 {
421 wxFileSystem fs;
422 wxFSFile *ff;
423
424 if (wxFileExists(htmlfile))
425 ff = fs.OpenFile(wxFileSystem::FileNameToURL(htmlfile));
426 else
427 ff = fs.OpenFile(htmlfile);
428
429 if (ff == NULL)
430 {
431 wxLogError(htmlfile + _(": file does not exist!"));
432 return;
433 }
434
435 bool done = false;
436 wxHtmlFilterHTML defaultFilter;
437 wxString doc;
438
439 wxList::compatibility_iterator node = m_Filters.GetFirst();
440 while (node)
441 {
442 wxHtmlFilter *h = (wxHtmlFilter*) node->GetData();
443 if (h->CanRead(*ff))
444 {
445 doc = h->ReadFile(*ff);
446 done = true;
447 break;
448 }
449 node = node->GetNext();
450 }
451
452 if (!done)
453 doc = defaultFilter.ReadFile(*ff);
454
455 SetHtmlText(doc, htmlfile, false);
456 delete ff;
457 }
458
459
460
461 void wxHtmlPrintout::SetHeader(const wxString& header, int pg)
462 {
463 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
464 m_Headers[0] = header;
465 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
466 m_Headers[1] = header;
467 }
468
469
470
471 void wxHtmlPrintout::SetFooter(const wxString& footer, int pg)
472 {
473 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
474 m_Footers[0] = footer;
475 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
476 m_Footers[1] = footer;
477 }
478
479
480
481 void 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;
493 m_NumPages = 0;
494 // m_PageBreaks[0] = 0;
495
496 m_PageBreaks.Clear();
497 m_PageBreaks.Add( 0);
498 do
499 {
500 pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
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);
505 if( m_PageBreaks.GetCount() > wxHTML_PRINT_MAX_PAGES)
506 {
507 wxMessageBox( _("HTML pagination algorithm generated more than the allowed maximum number of pages and it can't continue any longer!"),
508 _("Warning"), wxCANCEL | wxICON_ERROR );
509 break;
510 }
511 } while (pos < m_Renderer->GetTotalHeight());
512 }
513
514
515
516 void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
517 {
518 wxBusyCursor wait;
519
520 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
521 float ppmm_h, ppmm_v;
522
523 GetPageSizePixels(&pageWidth, &pageHeight);
524 GetPageSizeMM(&mm_w, &mm_h);
525 ppmm_h = (float)pageWidth / mm_w;
526 ppmm_v = (float)pageHeight / mm_h;
527 dc->GetSize(&dc_w, &dc_h);
528
529 int ppiPrinterX, ppiPrinterY;
530 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
531 wxUnusedVar(ppiPrinterX);
532 int ppiScreenX, ppiScreenY;
533 GetPPIScreen(&ppiScreenX, &ppiScreenY);
534 wxUnusedVar(ppiScreenX);
535
536 dc->SetUserScale((double)dc_w / (double)pageWidth,
537 (double)dc_h / (double)pageHeight);
538
539 m_Renderer->SetDC(dc,
540 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
541 (double)ppiPrinterY / (double)ppiScreenY);
542
543 dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
544
545 m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
546 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks,
547 m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
548
549
550 m_RendererHdr->SetDC(dc,
551 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
552 (double)ppiPrinterY / (double)ppiScreenY);
553 if (m_Headers[page % 2] != wxEmptyString)
554 {
555 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
556 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks);
557 }
558 if (m_Footers[page % 2] != wxEmptyString)
559 {
560 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
561 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks);
562 }
563 }
564
565
566
567 wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
568 {
569 wxString r = instr;
570 wxString num;
571
572 num.Printf(wxT("%i"), page);
573 r.Replace(wxT("@PAGENUM@"), num);
574
575 num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.GetCount() - 1));
576 r.Replace(wxT("@PAGESCNT@"), num);
577
578 const wxDateTime now = wxDateTime::Now();
579 r.Replace(wxT("@DATE@"), now.FormatDate());
580 r.Replace(wxT("@TIME@"), now.FormatTime());
581
582 r.Replace(wxT("@TITLE@"), GetTitle());
583
584 return r;
585 }
586
587
588
589 void wxHtmlPrintout::SetMargins(float top, float bottom, float left, float right, float spaces)
590 {
591 m_MarginTop = top;
592 m_MarginBottom = bottom;
593 m_MarginLeft = left;
594 m_MarginRight = right;
595 m_MarginSpace = spaces;
596 }
597
598
599
600
601 void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
602 const int *sizes)
603 {
604 m_Renderer->SetFonts(normal_face, fixed_face, sizes);
605 m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
606 }
607
608 void wxHtmlPrintout::SetStandardFonts(int size,
609 const wxString& normal_face,
610 const wxString& fixed_face)
611 {
612 m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
613 m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
614 }
615
616
617
618 //----------------------------------------------------------------------------
619 // wxHtmlEasyPrinting
620 //----------------------------------------------------------------------------
621
622
623 wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
624 {
625 m_ParentWindow = parentWindow;
626 m_Name = name;
627 m_PrintData = NULL;
628 m_PageSetupData = new wxPageSetupDialogData;
629 m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
630
631 m_PageSetupData->EnableMargins(true);
632 m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
633 m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
634
635 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
636 }
637
638
639
640 wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
641 {
642 delete m_PrintData;
643 delete m_PageSetupData;
644 }
645
646
647 wxPrintData *wxHtmlEasyPrinting::GetPrintData()
648 {
649 if (m_PrintData == NULL)
650 m_PrintData = new wxPrintData();
651 return m_PrintData;
652 }
653
654
655 bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
656 {
657 wxHtmlPrintout *p1 = CreatePrintout();
658 p1->SetHtmlFile(htmlfile);
659 wxHtmlPrintout *p2 = CreatePrintout();
660 p2->SetHtmlFile(htmlfile);
661 return DoPreview(p1, p2);
662 }
663
664
665
666 bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
667 {
668 wxHtmlPrintout *p1 = CreatePrintout();
669 p1->SetHtmlText(htmltext, basepath, true);
670 wxHtmlPrintout *p2 = CreatePrintout();
671 p2->SetHtmlText(htmltext, basepath, true);
672 return DoPreview(p1, p2);
673 }
674
675
676
677 bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
678 {
679 wxHtmlPrintout *p = CreatePrintout();
680 p->SetHtmlFile(htmlfile);
681 bool ret = DoPrint(p);
682 delete p;
683 return ret;
684 }
685
686
687
688 bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
689 {
690 wxHtmlPrintout *p = CreatePrintout();
691 p->SetHtmlText(htmltext, basepath, true);
692 bool ret = DoPrint(p);
693 delete p;
694 return ret;
695 }
696
697
698
699 bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
700 {
701 // Pass two printout objects: for preview, and possible printing.
702 wxPrintDialogData printDialogData(*GetPrintData());
703 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
704 if (!preview->Ok())
705 {
706 delete preview;
707 return false;
708 }
709
710 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
711 m_Name + _(" Preview"),
712 wxPoint(100, 100), wxSize(650, 500));
713 frame->Centre(wxBOTH);
714 frame->Initialize();
715 frame->Show(true);
716 return true;
717 }
718
719
720
721 bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
722 {
723 wxPrintDialogData printDialogData(*GetPrintData());
724 wxPrinter printer(&printDialogData);
725
726 if (!printer.Print(m_ParentWindow, printout, true))
727 {
728 return false;
729 }
730
731 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
732 return true;
733 }
734
735
736
737
738 void wxHtmlEasyPrinting::PageSetup()
739 {
740 if (!GetPrintData()->Ok())
741 {
742 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
743 return;
744 }
745
746 m_PageSetupData->SetPrintData(*GetPrintData());
747 wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
748
749 if (pageSetupDialog.ShowModal() == wxID_OK)
750 {
751 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
752 (*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
753 }
754 }
755
756
757
758 void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
759 {
760 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
761 m_Headers[0] = header;
762 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
763 m_Headers[1] = header;
764 }
765
766
767
768 void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
769 {
770 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
771 m_Footers[0] = footer;
772 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
773 m_Footers[1] = footer;
774 }
775
776
777 void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
778 const int *sizes)
779 {
780 m_fontMode = FontMode_Explicit;
781 m_FontFaceNormal = normal_face;
782 m_FontFaceFixed = fixed_face;
783
784 if (sizes)
785 {
786 m_FontsSizes = m_FontsSizesArr;
787 for (int i = 0; i < 7; i++) m_FontsSizes[i] = sizes[i];
788 }
789 else
790 m_FontsSizes = NULL;
791 }
792
793 void wxHtmlEasyPrinting::SetStandardFonts(int size,
794 const wxString& normal_face,
795 const wxString& fixed_face)
796 {
797 m_fontMode = FontMode_Standard;
798 m_FontFaceNormal = normal_face;
799 m_FontFaceFixed = fixed_face;
800 m_FontsSizesArr[0] = size;
801 }
802
803
804 wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
805 {
806 wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
807
808 if (m_fontMode == FontMode_Explicit)
809 {
810 p->SetFonts(m_FontFaceNormal, m_FontFaceFixed, m_FontsSizes);
811 }
812 else // FontMode_Standard
813 {
814 p->SetStandardFonts(m_FontsSizesArr[0],
815 m_FontFaceNormal, m_FontFaceFixed);
816 }
817
818 p->SetHeader(m_Headers[0], wxPAGE_EVEN);
819 p->SetHeader(m_Headers[1], wxPAGE_ODD);
820 p->SetFooter(m_Footers[0], wxPAGE_EVEN);
821 p->SetFooter(m_Footers[1], wxPAGE_ODD);
822
823 p->SetMargins(m_PageSetupData->GetMarginTopLeft().y,
824 m_PageSetupData->GetMarginBottomRight().y,
825 m_PageSetupData->GetMarginTopLeft().x,
826 m_PageSetupData->GetMarginBottomRight().x);
827
828 return p;
829 }
830
831 // A module to allow initialization/cleanup
832 // without calling these functions from app.cpp or from
833 // the user's application.
834
835 class wxHtmlPrintingModule: public wxModule
836 {
837 DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
838 public:
839 wxHtmlPrintingModule() : wxModule() {}
840 bool OnInit() { return true; }
841 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
842 };
843
844 IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
845
846
847 // This hack forces the linker to always link in m_* files
848 // (wxHTML doesn't work without handlers from these files)
849 #include "wx/html/forcelnk.h"
850 FORCE_WXHTML_MODULES()
851
852 #endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE