]> git.saurik.com Git - wxWidgets.git/blob - src/html/htmprint.cpp
Added wxRichTextTableBlock class to help with table UI operations
[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 // Copyright: (c) Vaclav Slavik, 1999
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx/wx.h".
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #if wxUSE_HTML && wxUSE_PRINTING_ARCHITECTURE && wxUSE_STREAMS
18
19 #ifndef WX_PRECOMP
20 #include "wx/log.h"
21 #include "wx/intl.h"
22 #include "wx/dc.h"
23 #include "wx/settings.h"
24 #include "wx/msgdlg.h"
25 #include "wx/module.h"
26 #include "wx/sizer.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, m_Height)) {}
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 = INT_MAX;
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
495 m_PageBreaks.Clear();
496 m_PageBreaks.Add( 0);
497 do
498 {
499 pos = m_Renderer->Render((int)( ppmm_h * m_MarginLeft),
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);
504 } while (pos < m_Renderer->GetTotalHeight());
505 }
506
507
508
509 void wxHtmlPrintout::RenderPage(wxDC *dc, int page)
510 {
511 wxBusyCursor wait;
512
513 int pageWidth, pageHeight, mm_w, mm_h, dc_w, dc_h;
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;
520 dc->GetSize(&dc_w, &dc_h);
521
522 int ppiPrinterX, ppiPrinterY;
523 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
524 wxUnusedVar(ppiPrinterX);
525 int ppiScreenX, ppiScreenY;
526 GetPPIScreen(&ppiScreenX, &ppiScreenY);
527 wxUnusedVar(ppiScreenX);
528
529 dc->SetUserScale((double)dc_w / (double)pageWidth,
530 (double)dc_h / (double)pageHeight);
531
532 m_Renderer->SetDC(dc,
533 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
534 (double)ppiPrinterY / (double)ppiScreenY);
535
536 dc->SetBackgroundMode(wxTRANSPARENT);
537
538 m_Renderer->Render((int) (ppmm_h * m_MarginLeft),
539 (int) (ppmm_v * (m_MarginTop + (m_HeaderHeight == 0 ? 0 : m_MarginSpace)) + m_HeaderHeight), m_PageBreaks,
540 m_PageBreaks[page-1], false, m_PageBreaks[page]-m_PageBreaks[page-1]);
541
542
543 m_RendererHdr->SetDC(dc,
544 (double)ppiPrinterY / TYPICAL_SCREEN_DPI,
545 (double)ppiPrinterY / (double)ppiScreenY);
546 if (m_Headers[page % 2] != wxEmptyString)
547 {
548 m_RendererHdr->SetHtmlText(TranslateHeader(m_Headers[page % 2], page));
549 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (ppmm_v * m_MarginTop), m_PageBreaks);
550 }
551 if (m_Footers[page % 2] != wxEmptyString)
552 {
553 m_RendererHdr->SetHtmlText(TranslateHeader(m_Footers[page % 2], page));
554 m_RendererHdr->Render((int) (ppmm_h * m_MarginLeft), (int) (pageHeight - ppmm_v * m_MarginBottom - m_FooterHeight), m_PageBreaks);
555 }
556 }
557
558
559
560 wxString wxHtmlPrintout::TranslateHeader(const wxString& instr, int page)
561 {
562 wxString r = instr;
563 wxString num;
564
565 num.Printf(wxT("%i"), page);
566 r.Replace(wxT("@PAGENUM@"), num);
567
568 num.Printf(wxT("%lu"), (unsigned long)(m_PageBreaks.GetCount() - 1));
569 r.Replace(wxT("@PAGESCNT@"), num);
570
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
577 return r;
578 }
579
580
581
582 void 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
594 void wxHtmlPrintout::SetFonts(const wxString& normal_face, const wxString& fixed_face,
595 const int *sizes)
596 {
597 m_Renderer->SetFonts(normal_face, fixed_face, sizes);
598 m_RendererHdr->SetFonts(normal_face, fixed_face, sizes);
599 }
600
601 void wxHtmlPrintout::SetStandardFonts(int size,
602 const wxString& normal_face,
603 const wxString& fixed_face)
604 {
605 m_Renderer->SetStandardFonts(size, normal_face, fixed_face);
606 m_RendererHdr->SetStandardFonts(size, normal_face, fixed_face);
607 }
608
609
610
611 //----------------------------------------------------------------------------
612 // wxHtmlEasyPrinting
613 //----------------------------------------------------------------------------
614
615
616 wxHtmlEasyPrinting::wxHtmlEasyPrinting(const wxString& name, wxWindow *parentWindow)
617 {
618 m_ParentWindow = parentWindow;
619 m_Name = name;
620 m_PrintData = NULL;
621 m_PageSetupData = new wxPageSetupDialogData;
622 m_Headers[0] = m_Headers[1] = m_Footers[0] = m_Footers[1] = wxEmptyString;
623
624 m_PageSetupData->EnableMargins(true);
625 m_PageSetupData->SetMarginTopLeft(wxPoint(25, 25));
626 m_PageSetupData->SetMarginBottomRight(wxPoint(25, 25));
627
628 SetStandardFonts(DEFAULT_PRINT_FONT_SIZE);
629 }
630
631
632
633 wxHtmlEasyPrinting::~wxHtmlEasyPrinting()
634 {
635 delete m_PrintData;
636 delete m_PageSetupData;
637 }
638
639
640 wxPrintData *wxHtmlEasyPrinting::GetPrintData()
641 {
642 if (m_PrintData == NULL)
643 m_PrintData = new wxPrintData();
644 return m_PrintData;
645 }
646
647
648 bool wxHtmlEasyPrinting::PreviewFile(const wxString &htmlfile)
649 {
650 wxHtmlPrintout *p1 = CreatePrintout();
651 p1->SetHtmlFile(htmlfile);
652 wxHtmlPrintout *p2 = CreatePrintout();
653 p2->SetHtmlFile(htmlfile);
654 return DoPreview(p1, p2);
655 }
656
657
658
659 bool wxHtmlEasyPrinting::PreviewText(const wxString &htmltext, const wxString &basepath)
660 {
661 wxHtmlPrintout *p1 = CreatePrintout();
662 p1->SetHtmlText(htmltext, basepath, true);
663 wxHtmlPrintout *p2 = CreatePrintout();
664 p2->SetHtmlText(htmltext, basepath, true);
665 return DoPreview(p1, p2);
666 }
667
668
669
670 bool wxHtmlEasyPrinting::PrintFile(const wxString &htmlfile)
671 {
672 wxHtmlPrintout *p = CreatePrintout();
673 p->SetHtmlFile(htmlfile);
674 bool ret = DoPrint(p);
675 delete p;
676 return ret;
677 }
678
679
680
681 bool wxHtmlEasyPrinting::PrintText(const wxString &htmltext, const wxString &basepath)
682 {
683 wxHtmlPrintout *p = CreatePrintout();
684 p->SetHtmlText(htmltext, basepath, true);
685 bool ret = DoPrint(p);
686 delete p;
687 return ret;
688 }
689
690
691
692 bool wxHtmlEasyPrinting::DoPreview(wxHtmlPrintout *printout1, wxHtmlPrintout *printout2)
693 {
694 // Pass two printout objects: for preview, and possible printing.
695 wxPrintDialogData printDialogData(*GetPrintData());
696 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
697 if (!preview->IsOk())
698 {
699 delete preview;
700 return false;
701 }
702
703 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_ParentWindow,
704 m_Name + _(" Preview"),
705 wxPoint(100, 100), wxSize(650, 500));
706 frame->Centre(wxBOTH);
707 frame->Initialize();
708 frame->Show(true);
709 return true;
710 }
711
712
713
714 bool wxHtmlEasyPrinting::DoPrint(wxHtmlPrintout *printout)
715 {
716 wxPrintDialogData printDialogData(*GetPrintData());
717 wxPrinter printer(&printDialogData);
718
719 if (!printer.Print(m_ParentWindow, printout, true))
720 {
721 return false;
722 }
723
724 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
725 return true;
726 }
727
728
729
730
731 void wxHtmlEasyPrinting::PageSetup()
732 {
733 if (!GetPrintData()->IsOk())
734 {
735 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
736 return;
737 }
738
739 m_PageSetupData->SetPrintData(*GetPrintData());
740 wxPageSetupDialog pageSetupDialog(m_ParentWindow, m_PageSetupData);
741
742 if (pageSetupDialog.ShowModal() == wxID_OK)
743 {
744 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
745 (*m_PageSetupData) = pageSetupDialog.GetPageSetupData();
746 }
747 }
748
749
750
751 void wxHtmlEasyPrinting::SetHeader(const wxString& header, int pg)
752 {
753 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
754 m_Headers[0] = header;
755 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
756 m_Headers[1] = header;
757 }
758
759
760
761 void wxHtmlEasyPrinting::SetFooter(const wxString& footer, int pg)
762 {
763 if (pg == wxPAGE_ALL || pg == wxPAGE_EVEN)
764 m_Footers[0] = footer;
765 if (pg == wxPAGE_ALL || pg == wxPAGE_ODD)
766 m_Footers[1] = footer;
767 }
768
769
770 void wxHtmlEasyPrinting::SetFonts(const wxString& normal_face, const wxString& fixed_face,
771 const int *sizes)
772 {
773 m_fontMode = FontMode_Explicit;
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
786 void wxHtmlEasyPrinting::SetStandardFonts(int size,
787 const wxString& normal_face,
788 const wxString& fixed_face)
789 {
790 m_fontMode = FontMode_Standard;
791 m_FontFaceNormal = normal_face;
792 m_FontFaceFixed = fixed_face;
793 m_FontsSizesArr[0] = size;
794 }
795
796
797 wxHtmlPrintout *wxHtmlEasyPrinting::CreatePrintout()
798 {
799 wxHtmlPrintout *p = new wxHtmlPrintout(m_Name);
800
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 }
810
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);
820
821 return p;
822 }
823
824 // A module to allow initialization/cleanup
825 // without calling these functions from app.cpp or from
826 // the user's application.
827
828 class wxHtmlPrintingModule: public wxModule
829 {
830 DECLARE_DYNAMIC_CLASS(wxHtmlPrintingModule)
831 public:
832 wxHtmlPrintingModule() : wxModule() {}
833 bool OnInit() { return true; }
834 void OnExit() { wxHtmlPrintout::CleanUpStatics(); }
835 };
836
837 IMPLEMENT_DYNAMIC_CLASS(wxHtmlPrintingModule, wxModule)
838
839
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"
843 FORCE_WXHTML_MODULES()
844
845 #endif // wxUSE_HTML & wxUSE_PRINTING_ARCHITECTURE