Fixed #14429: Printing a large table in wxRichTextCtrl fails
[wxWidgets.git] / src / richtext / richtextprint.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextprint.cpp
3 // Purpose: Rich text printing classes
4 // Author: Julian Smart
5 // Created: 2006-10-24
6 // RCS-ID: $Id$
7 // Copyright: (c) Julian Smart
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_RICHTEXT && 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 #endif
27
28 #include "wx/datetime.h"
29 #include "wx/print.h"
30 #include "wx/printdlg.h"
31 #include "wx/richtext/richtextprint.h"
32 #include "wx/wfstream.h"
33
34 /*!
35 * wxRichTextPrintout
36 */
37
38 wxRichTextPrintout::wxRichTextPrintout(const wxString& title) : wxPrintout(title)
39 {
40 m_numPages = wxRICHTEXT_PRINT_MAX_PAGES;
41
42 SetMargins(); // to default values
43 }
44
45 wxRichTextPrintout::~wxRichTextPrintout()
46 {
47 }
48
49 void wxRichTextPrintout::OnPreparePrinting()
50 {
51 wxBusyCursor wait;
52
53 m_numPages = 1;
54
55 m_pageBreaksStart.Clear();
56 m_pageBreaksEnd.Clear();
57 m_pageYOffsets.Clear();
58
59 int lastStartPos = 0;
60
61 wxRect rect, headerRect, footerRect;
62
63 /// Sets the DC scaling and returns important page rectangles
64 CalculateScaling(GetDC(), rect, headerRect, footerRect);
65
66 if (GetRichTextBuffer())
67 {
68 GetRichTextBuffer()->Invalidate(wxRICHTEXT_ALL);
69
70 wxRichTextDrawingContext context(GetRichTextBuffer());
71 GetRichTextBuffer()->Layout(*GetDC(), context, rect, rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT);
72
73 // Now calculate the page breaks
74
75 int yOffset = 0;
76
77 wxRichTextLine* lastLine = NULL;
78
79 wxRichTextObjectList::compatibility_iterator node = GetRichTextBuffer()->GetChildren().GetFirst();
80 while (node)
81 {
82 // child is a paragraph
83 wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
84 wxASSERT (child != NULL);
85 if (child)
86 {
87 wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst();
88 while (node2)
89 {
90 wxRichTextLine* line = node2->GetData();
91
92 int lineY = child->GetPosition().y + line->GetPosition().y - yOffset;
93 bool hasHardPageBreak = ((node2 == child->GetLines().GetFirst()) && child->GetAttributes().HasPageBreak());
94
95 // Break the page if either we're going off the bottom, or this paragraph specifies
96 // an explicit page break
97
98 if (((lineY + line->GetSize().y) > rect.GetBottom()) || hasHardPageBreak)
99 {
100 // Only if we're not at the start of the document, and
101 // even then, only if either it's a hard break or if the object
102 // can fit in a whole page (otherwise there's no point in making
103 // the rest of this page blank).
104 if (lastLine && (hasHardPageBreak || (line->GetSize().y <= rect.GetHeight())))
105 {
106 // New page starting at this line
107 int newY = rect.y;
108
109 // We increase the offset by the difference between new and old positions
110
111 int increaseOffsetBy = lineY - newY;
112 yOffset += increaseOffsetBy;
113
114 m_pageBreaksStart.Add(lastStartPos);
115 m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd());
116 m_pageYOffsets.Add(yOffset);
117
118 lastStartPos = line->GetAbsoluteRange().GetStart();
119 m_numPages ++;
120 }
121
122 lastLine = line;
123
124 // Now create page breaks for the rest of the line, if it's larger than the page height
125 int contentLeft = line->GetSize().y - rect.GetHeight();
126 while (contentLeft >= 0)
127 {
128 yOffset += rect.GetHeight();
129 contentLeft -= rect.GetHeight();
130
131 m_pageBreaksStart.Add(lastStartPos);
132 m_pageBreaksEnd.Add(lastLine->GetAbsoluteRange().GetEnd());
133 m_pageYOffsets.Add(yOffset);
134
135 m_numPages ++;
136 }
137 }
138
139 lastLine = line;
140
141 node2 = node2->GetNext();
142 }
143 }
144
145 node = node->GetNext();
146 }
147
148 // Closing page break
149 if (m_pageBreaksStart.GetCount() == 0 || (m_pageBreaksEnd[m_pageBreaksEnd.GetCount()-1] < (GetRichTextBuffer()->GetOwnRange().GetEnd()-1)))
150 {
151 m_pageBreaksStart.Add(lastStartPos);
152 m_pageBreaksEnd.Add(GetRichTextBuffer()->GetOwnRange().GetEnd());
153 m_pageYOffsets.Add(yOffset);
154 }
155 }
156 }
157
158 bool wxRichTextPrintout::OnBeginDocument(int startPage, int endPage)
159 {
160 if (!wxPrintout::OnBeginDocument(startPage, endPage)) return false;
161
162 return true;
163 }
164
165 bool wxRichTextPrintout::OnPrintPage(int page)
166 {
167 wxDC *dc = GetDC();
168 if (dc)
169 {
170 if (HasPage(page))
171 RenderPage(dc, page);
172 return true;
173 }
174 else return false;
175 }
176
177 void wxRichTextPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
178 {
179 *minPage = 1;
180 *maxPage = m_numPages;
181 *selPageFrom = 1;
182 *selPageTo = m_numPages;
183 }
184
185 bool wxRichTextPrintout::HasPage(int pageNum)
186 {
187 return pageNum > 0 && pageNum <= m_numPages;
188 }
189
190 void wxRichTextPrintout::RenderPage(wxDC *dc, int page)
191 {
192 if (!GetRichTextBuffer())
193 return;
194
195 wxBusyCursor wait;
196
197 wxRect textRect, headerRect, footerRect;
198
199 /// Sets the DC scaling and returns important page rectangles
200 CalculateScaling(dc, textRect, headerRect, footerRect);
201
202 if (page > 1 || m_headerFooterData.GetShowOnFirstPage())
203 {
204 if (m_headerFooterData.GetFont().IsOk())
205 dc->SetFont(m_headerFooterData.GetFont());
206 else
207 dc->SetFont(*wxNORMAL_FONT);
208 if (m_headerFooterData.GetTextColour().IsOk())
209 dc->SetTextForeground(m_headerFooterData.GetTextColour());
210 else
211 dc->SetTextForeground(*wxBLACK);
212 dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
213
214 // Draw header, if any
215 wxRichTextOddEvenPage oddEven = ((page % 2) == 1) ? wxRICHTEXT_PAGE_ODD : wxRICHTEXT_PAGE_EVEN;
216
217 wxString headerTextCentre = m_headerFooterData.GetHeaderText(oddEven, wxRICHTEXT_PAGE_CENTRE);
218 wxString headerTextLeft = m_headerFooterData.GetHeaderText(oddEven, wxRICHTEXT_PAGE_LEFT);
219 wxString headerTextRight = m_headerFooterData.GetHeaderText(oddEven, wxRICHTEXT_PAGE_RIGHT);
220
221 if (!headerTextLeft.IsEmpty())
222 {
223 SubstituteKeywords(headerTextLeft, GetTitle(), page, m_numPages);
224
225 //int tx, ty;
226 //dc->GetTextExtent(headerTextLeft, & tx, & ty);
227
228 int x = headerRect.GetLeft();
229 int y = headerRect.GetX();
230 dc->DrawText(headerTextLeft, x, y);
231 }
232 if (!headerTextCentre.IsEmpty())
233 {
234 SubstituteKeywords(headerTextCentre, GetTitle(), page, m_numPages);
235
236 int tx, ty;
237 dc->GetTextExtent(headerTextCentre, & tx, & ty);
238
239 int x = headerRect.GetWidth()/2 - tx/2 + headerRect.GetLeft();
240 int y = headerRect.GetY();
241 dc->DrawText(headerTextCentre, x, y);
242 }
243 if (!headerTextRight.IsEmpty())
244 {
245 SubstituteKeywords(headerTextRight, GetTitle(), page, m_numPages);
246
247 int tx, ty;
248 dc->GetTextExtent(headerTextRight, & tx, & ty);
249
250 int x = headerRect.GetRight() - tx;
251 int y = headerRect.GetY();
252 dc->DrawText(headerTextRight, x, y);
253 }
254
255 // Draw footer, if any
256 wxString footerTextCentre = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_CENTRE);
257 wxString footerTextLeft = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_LEFT);
258 wxString footerTextRight = m_headerFooterData.GetFooterText(oddEven, wxRICHTEXT_PAGE_RIGHT);
259
260 if (!footerTextLeft.IsEmpty())
261 {
262 SubstituteKeywords(footerTextLeft, GetTitle(), page, m_numPages);
263
264 int tx, ty;
265 dc->GetTextExtent(footerTextLeft, & tx, & ty);
266
267 int x = footerRect.GetLeft();
268 int y = footerRect.GetBottom() - ty;
269 dc->DrawText(footerTextLeft, x, y);
270 }
271 if (!footerTextCentre.IsEmpty())
272 {
273 SubstituteKeywords(footerTextCentre, GetTitle(), page, m_numPages);
274
275 int tx, ty;
276 dc->GetTextExtent(footerTextCentre, & tx, & ty);
277
278 int x = footerRect.GetWidth()/2 - tx/2 + footerRect.GetLeft();
279 int y = footerRect.GetBottom() - ty;
280 dc->DrawText(footerTextCentre, x, y);
281 }
282 if (!footerTextRight.IsEmpty())
283 {
284 SubstituteKeywords(footerTextRight, GetTitle(), page, m_numPages);
285
286 int tx, ty;
287 dc->GetTextExtent(footerTextRight, & tx, & ty);
288
289 int x = footerRect.GetRight() - tx;
290 int y = footerRect.GetBottom() - ty;
291 dc->DrawText(footerTextRight, x, y);
292 }
293 }
294
295 wxRichTextRange rangeToDraw(m_pageBreaksStart[page-1], m_pageBreaksEnd[page-1]);
296
297 wxPoint oldOrigin = dc->GetLogicalOrigin();
298 double scaleX, scaleY;
299 dc->GetUserScale(& scaleX, & scaleY);
300
301 int yOffset = 0;
302 if (page > 1)
303 yOffset = m_pageYOffsets[page-2];
304
305 if (yOffset != oldOrigin.y)
306 dc->SetLogicalOrigin(oldOrigin.x, oldOrigin.y + yOffset);
307
308 dc->SetClippingRegion(wxRect(textRect.x, textRect.y + yOffset, textRect.width, textRect.height));
309
310 wxRichTextDrawingContext context(GetRichTextBuffer());
311 GetRichTextBuffer()->Draw(*dc, context, rangeToDraw, wxRichTextSelection(), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE|wxRICHTEXT_DRAW_PRINT /* flags */);
312
313 dc->DestroyClippingRegion();
314
315 if (yOffset != oldOrigin.y)
316 dc->SetLogicalOrigin(oldOrigin.x, oldOrigin.y);
317 }
318
319 void wxRichTextPrintout::SetMargins(int top, int bottom, int left, int right)
320 {
321 m_marginTop = top;
322 m_marginBottom = bottom;
323 m_marginLeft = left;
324 m_marginRight = right;
325 }
326
327 /// Calculate scaling and rectangles, setting the device context scaling
328 void wxRichTextPrintout::CalculateScaling(wxDC* dc, wxRect& textRect, wxRect& headerRect, wxRect& footerRect)
329 {
330 // Get the logical pixels per inch of screen and printer
331 int ppiScreenX, ppiScreenY;
332 GetPPIScreen(&ppiScreenX, &ppiScreenY);
333 int ppiPrinterX, ppiPrinterY;
334 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
335
336 // This scales the DC so that the printout roughly represents the
337 // the screen scaling.
338 float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
339
340 // Now we have to check in case our real page size is reduced
341 // (e.g. because we're drawing to a print preview memory DC)
342 int pageWidth, pageHeight;
343 int w, h;
344 dc->GetSize(&w, &h);
345 GetPageSizePixels(&pageWidth, &pageHeight);
346
347 // If printer pageWidth == current DC width, then this doesn't
348 // change. But w might be the preview bitmap width, so scale down.
349 float previewScale = (float)(w/(float)pageWidth);
350 float overallScale = scale * previewScale;
351
352 // The dimensions used for indentation etc. have to be unscaled
353 // during printing to be correct when scaling is applied.
354 // Also, correct the conversions in wxRTC using DC instead of print DC.
355 m_richTextBuffer->SetScale(scale * float(dc->GetPPI().x)/float(ppiPrinterX));
356
357 // Calculate margins
358 int marginLeft = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginLeft);
359 int marginTop = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginTop);
360 int marginRight = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginRight);
361 int marginBottom = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_marginBottom);
362
363 // Header and footer margins
364 int headerMargin = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_headerFooterData.GetHeaderMargin());
365 int footerMargin = wxRichTextObject::ConvertTenthsMMToPixels(ppiPrinterX, m_headerFooterData.GetFooterMargin());
366
367 dc->SetUserScale(overallScale, overallScale);
368
369 wxRect rect((int) (marginLeft/scale), (int) (marginTop/scale),
370 (int) ((pageWidth - marginLeft - marginRight)/scale), (int)((pageHeight - marginTop - marginBottom)/scale));
371
372 headerRect = wxRect(0, 0, 0, 0);
373
374 if (!m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT).IsEmpty() ||
375 !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_CENTRE).IsEmpty() ||
376 !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_RIGHT).IsEmpty() ||
377
378 !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_LEFT).IsEmpty() ||
379 !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_CENTRE).IsEmpty() ||
380 !m_headerFooterData.GetHeaderText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_RIGHT).IsEmpty())
381 {
382 if (m_headerFooterData.GetFont().IsOk())
383 dc->SetFont(m_headerFooterData.GetFont());
384 else
385 dc->SetFont(*wxNORMAL_FONT);
386
387 int charHeight = dc->GetCharHeight();
388
389 int headerHeight = (int) (charHeight + headerMargin/scale);
390
391 headerRect = wxRect(rect.x, rect.y, rect.width, headerHeight);
392
393 rect.y += headerHeight;
394 rect.height -= headerHeight;
395 }
396
397 footerRect = wxRect(0, 0, 0, 0);
398
399 if (!m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT).IsEmpty() ||
400 !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_CENTRE).IsEmpty() ||
401 !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_RIGHT).IsEmpty() ||
402
403 !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_LEFT).IsEmpty() ||
404 !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_CENTRE).IsEmpty() ||
405 !m_headerFooterData.GetFooterText(wxRICHTEXT_PAGE_EVEN, wxRICHTEXT_PAGE_RIGHT).IsEmpty())
406 {
407 if (m_headerFooterData.GetFont().IsOk())
408 dc->SetFont(m_headerFooterData.GetFont());
409 else
410 dc->SetFont(*wxNORMAL_FONT);
411
412 int charHeight = dc->GetCharHeight();
413
414 int footerHeight = (int) (charHeight + footerMargin/scale);
415
416 footerRect = wxRect(rect.x, rect.y + rect.height, rect.width, footerHeight);
417
418 rect.height -= footerHeight;
419 }
420
421 textRect = rect;
422 }
423
424 bool wxRichTextPrintout::SubstituteKeywords(wxString& str, const wxString& title, int pageNum, int pageCount)
425 {
426 wxString num;
427
428 num.Printf(wxT("%i"), pageNum);
429 str.Replace(wxT("@PAGENUM@"), num);
430
431 num.Printf(wxT("%lu"), (unsigned long) pageCount);
432 str.Replace(wxT("@PAGESCNT@"), num);
433
434 wxDateTime now = wxDateTime::Now();
435
436 str.Replace(wxT("@DATE@"), now.FormatDate());
437 str.Replace(wxT("@TIME@"), now.FormatTime());
438
439 str.Replace(wxT("@TITLE@"), title);
440
441 return true;
442 }
443
444 /*!
445 * wxRichTextPrinting
446 */
447
448 wxRichTextPrinting::wxRichTextPrinting(const wxString& name, wxWindow *parentWindow)
449 {
450 m_richTextBufferPrinting = NULL;
451 m_richTextBufferPreview = NULL;
452
453 m_parentWindow = parentWindow;
454 m_title = name;
455 m_printData = NULL;
456
457 m_previewRect = wxRect(wxPoint(100, 100), wxSize(800, 800));
458
459 m_pageSetupData = new wxPageSetupDialogData;
460 m_pageSetupData->EnableMargins(true);
461 m_pageSetupData->SetMarginTopLeft(wxPoint(25, 25));
462 m_pageSetupData->SetMarginBottomRight(wxPoint(25, 25));
463 }
464
465 wxRichTextPrinting::~wxRichTextPrinting()
466 {
467 delete m_printData;
468 delete m_pageSetupData;
469 delete m_richTextBufferPrinting;
470 delete m_richTextBufferPreview;
471 }
472
473 wxPrintData *wxRichTextPrinting::GetPrintData()
474 {
475 if (m_printData == NULL)
476 m_printData = new wxPrintData();
477 return m_printData;
478 }
479
480 /// Set print and page setup data
481 void wxRichTextPrinting::SetPrintData(const wxPrintData& printData)
482 {
483 (*GetPrintData()) = printData;
484 }
485
486 void wxRichTextPrinting::SetPageSetupData(const wxPageSetupDialogData& pageSetupData)
487 {
488 (*GetPageSetupData()) = pageSetupData;
489 }
490
491 /// Set the rich text buffer pointer, deleting the existing object if present
492 void wxRichTextPrinting::SetRichTextBufferPrinting(wxRichTextBuffer* buf)
493 {
494 if (m_richTextBufferPrinting)
495 {
496 delete m_richTextBufferPrinting;
497 m_richTextBufferPrinting = NULL;
498 }
499 m_richTextBufferPrinting = buf;
500 }
501
502 void wxRichTextPrinting::SetRichTextBufferPreview(wxRichTextBuffer* buf)
503 {
504 if (m_richTextBufferPreview)
505 {
506 delete m_richTextBufferPreview;
507 m_richTextBufferPreview = NULL;
508 }
509 m_richTextBufferPreview = buf;
510 }
511
512 bool wxRichTextPrinting::PreviewFile(const wxString& richTextFile)
513 {
514 SetRichTextBufferPreview(new wxRichTextBuffer);
515
516 if (!m_richTextBufferPreview->LoadFile(richTextFile))
517 {
518 SetRichTextBufferPreview(NULL);
519 return false;
520 }
521 else
522 SetRichTextBufferPrinting(new wxRichTextBuffer(*m_richTextBufferPreview));
523
524 wxRichTextPrintout *p1 = CreatePrintout();
525 p1->SetRichTextBuffer(m_richTextBufferPreview);
526
527 wxRichTextPrintout *p2 = CreatePrintout();
528 p2->SetRichTextBuffer(m_richTextBufferPrinting);
529 return DoPreview(p1, p2);
530 }
531
532 bool wxRichTextPrinting::PreviewBuffer(const wxRichTextBuffer& buffer)
533 {
534 SetRichTextBufferPreview(new wxRichTextBuffer(buffer));
535 SetRichTextBufferPrinting(new wxRichTextBuffer(buffer));
536
537 wxRichTextPrintout *p1 = CreatePrintout();
538 p1->SetRichTextBuffer(m_richTextBufferPreview);
539
540 wxRichTextPrintout *p2 = CreatePrintout();
541 p2->SetRichTextBuffer(m_richTextBufferPrinting);
542
543 return DoPreview(p1, p2);
544 }
545
546 bool wxRichTextPrinting::PrintFile(const wxString& richTextFile, bool showPrintDialog)
547 {
548 SetRichTextBufferPrinting(new wxRichTextBuffer);
549
550 if (!m_richTextBufferPrinting->LoadFile(richTextFile))
551 {
552 SetRichTextBufferPrinting(NULL);
553 return false;
554 }
555
556 wxRichTextPrintout *p = CreatePrintout();
557 p->SetRichTextBuffer(m_richTextBufferPrinting);
558
559 bool ret = DoPrint(p, showPrintDialog);
560 delete p;
561 return ret;
562 }
563
564 bool wxRichTextPrinting::PrintBuffer(const wxRichTextBuffer& buffer, bool showPrintDialog)
565 {
566 SetRichTextBufferPrinting(new wxRichTextBuffer(buffer));
567
568 wxRichTextPrintout *p = CreatePrintout();
569 p->SetRichTextBuffer(m_richTextBufferPrinting);
570
571 bool ret = DoPrint(p, showPrintDialog);
572 delete p;
573 return ret;
574 }
575
576 bool wxRichTextPrinting::DoPreview(wxRichTextPrintout *printout1, wxRichTextPrintout *printout2)
577 {
578 // Pass two printout objects: for preview, and possible printing.
579 wxPrintDialogData printDialogData(*GetPrintData());
580 wxPrintPreview *preview = new wxPrintPreview(printout1, printout2, &printDialogData);
581 if (!preview->IsOk())
582 {
583 delete preview;
584 return false;
585 }
586
587 wxPreviewFrame *frame = new wxPreviewFrame(preview, m_parentWindow,
588 m_title + _(" Preview"),
589 m_previewRect.GetPosition(), m_previewRect.GetSize());
590 frame->Centre(wxBOTH);
591 frame->Initialize();
592 frame->Show(true);
593 return true;
594 }
595
596 bool wxRichTextPrinting::DoPrint(wxRichTextPrintout *printout, bool showPrintDialog)
597 {
598 wxPrintDialogData printDialogData(*GetPrintData());
599 wxPrinter printer(&printDialogData);
600
601 if (!printer.Print(m_parentWindow, printout, showPrintDialog))
602 {
603 return false;
604 }
605
606 (*GetPrintData()) = printer.GetPrintDialogData().GetPrintData();
607 return true;
608 }
609
610 void wxRichTextPrinting::PageSetup()
611 {
612 if (!GetPrintData()->IsOk())
613 {
614 wxLogError(_("There was a problem during page setup: you may need to set a default printer."));
615 return;
616 }
617
618 m_pageSetupData->SetPrintData(*GetPrintData());
619 wxPageSetupDialog pageSetupDialog(m_parentWindow, m_pageSetupData);
620
621 if (pageSetupDialog.ShowModal() == wxID_OK)
622 {
623 (*GetPrintData()) = pageSetupDialog.GetPageSetupData().GetPrintData();
624 (*m_pageSetupData) = pageSetupDialog.GetPageSetupData();
625 }
626 }
627
628 wxRichTextPrintout *wxRichTextPrinting::CreatePrintout()
629 {
630 wxRichTextPrintout *p = new wxRichTextPrintout(m_title);
631
632 p->SetHeaderFooterData(GetHeaderFooterData());
633 p->SetMargins(10*m_pageSetupData->GetMarginTopLeft().y,
634 10*m_pageSetupData->GetMarginBottomRight().y,
635 10*m_pageSetupData->GetMarginTopLeft().x,
636 10*m_pageSetupData->GetMarginBottomRight().x);
637
638 return p;
639 }
640
641 /// Set/get header text, e.g. wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT
642 void wxRichTextPrinting::SetHeaderText(const wxString& text, wxRichTextOddEvenPage page, wxRichTextPageLocation location)
643 {
644 m_headerFooterData.SetHeaderText(text, page, location);
645 }
646
647 wxString wxRichTextPrinting::GetHeaderText(wxRichTextOddEvenPage page, wxRichTextPageLocation location) const
648 {
649 return m_headerFooterData.GetHeaderText(page, location);
650 }
651
652 /// Set/get footer text, e.g. wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT
653 void wxRichTextPrinting::SetFooterText(const wxString& text, wxRichTextOddEvenPage page, wxRichTextPageLocation location)
654 {
655 m_headerFooterData.SetFooterText(text, page, location);
656 }
657
658 wxString wxRichTextPrinting::GetFooterText(wxRichTextOddEvenPage page, wxRichTextPageLocation location) const
659 {
660 return m_headerFooterData.GetFooterText(page, location);
661 }
662
663 /*!
664 * Header/footer data
665 */
666
667 IMPLEMENT_CLASS(wxRichTextHeaderFooterData, wxObject)
668
669 /// Copy
670 void wxRichTextHeaderFooterData::Copy(const wxRichTextHeaderFooterData& data)
671 {
672 int i;
673 for (i = 0; i < 12; i++)
674 m_text[i] = data.m_text[i];
675 m_font = data.m_font;
676 m_colour = data.m_colour;
677 m_headerMargin = data.m_headerMargin;
678 m_footerMargin = data.m_footerMargin;
679 m_showOnFirstPage = data.m_showOnFirstPage;
680 }
681
682 /// Set/get text
683 void wxRichTextHeaderFooterData::SetText(const wxString& text, int headerFooter, wxRichTextOddEvenPage page, wxRichTextPageLocation location)
684 {
685 int idx = headerFooter + (2 * (int) page) + (4 * (int) location);
686 wxASSERT( idx >= 0 && idx < 12 );
687
688 if (idx >= 0 && idx < 12)
689 m_text[idx] = text;
690 }
691
692 wxString wxRichTextHeaderFooterData::GetText(int headerFooter, wxRichTextOddEvenPage page, wxRichTextPageLocation location) const
693 {
694 int idx = headerFooter + (2 * (int) page) + (4 * (int) location);
695 wxASSERT( idx >= 0 && idx < 12 );
696
697 if (idx >= 0 && idx < 12)
698 return m_text[idx];
699 else
700 return wxEmptyString;
701 }
702
703 /// Set/get header text, e.g. wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT
704 void wxRichTextHeaderFooterData::SetHeaderText(const wxString& text, wxRichTextOddEvenPage page, wxRichTextPageLocation location)
705 {
706 if (page == wxRICHTEXT_PAGE_ALL)
707 {
708 SetText(text, 0, wxRICHTEXT_PAGE_ODD, location);
709 SetText(text, 0, wxRICHTEXT_PAGE_EVEN, location);
710 }
711 else
712 SetText(text, 0, page, location);
713 }
714
715 wxString wxRichTextHeaderFooterData::GetHeaderText(wxRichTextOddEvenPage page, wxRichTextPageLocation location) const
716 {
717 return GetText(0, page, location);
718 }
719
720 /// Set/get footer text, e.g. wxRICHTEXT_PAGE_ODD, wxRICHTEXT_PAGE_LEFT
721 void wxRichTextHeaderFooterData::SetFooterText(const wxString& text, wxRichTextOddEvenPage page, wxRichTextPageLocation location)
722 {
723 if (page == wxRICHTEXT_PAGE_ALL)
724 {
725 SetText(text, 1, wxRICHTEXT_PAGE_ODD, location);
726 SetText(text, 1, wxRICHTEXT_PAGE_EVEN, location);
727 }
728 else
729 SetText(text, 1, page, location);
730 }
731
732 wxString wxRichTextHeaderFooterData::GetFooterText(wxRichTextOddEvenPage page, wxRichTextPageLocation location) const
733 {
734 return GetText(1, page, location);
735 }
736
737 /// Clear all text
738 void wxRichTextHeaderFooterData::Clear()
739 {
740 int i;
741 for (i = 0; i < 12; i++)
742 m_text[i] = wxEmptyString;
743 }
744
745 #endif // wxUSE_RICHTEXT & wxUSE_PRINTING_ARCHITECTURE
746