1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   Printing.cpp
6 
7   Dominic Mazzoni
8 
9 *******************************************************************//*!
10 
11 \class AudacityPrintout
12 \brief Derived from wxPrintout, this class helps with printing.
13 
14 *//*******************************************************************/
15 
16 
17 
18 #include "Printing.h"
19 
20 #include <wx/defs.h>
21 #include <wx/dc.h>
22 #include <wx/intl.h>
23 #include <wx/print.h>
24 #include <wx/printdlg.h>
25 
26 #include "AColor.h"
27 #include "ProjectWindows.h"
28 #include "TrackArtist.h"
29 #include "ViewInfo.h"
30 #include "Track.h"
31 #include "widgets/Ruler.h"
32 #include "widgets/AudacityMessageBox.h"
33 
34 #include "TrackPanelDrawingContext.h"
35 
36 #include "tracks/ui/TrackView.h"
37 
38 // Globals, so that we remember settings from session to session
gPrintData()39 wxPrintData &gPrintData()
40 {
41    static wxPrintData theData;
42    return theData;
43 }
44 
45 class AudacityPrintout final : public wxPrintout
46 {
47  public:
AudacityPrintout(wxString title,TrackList * tracks,TrackPanel & panel)48    AudacityPrintout(wxString title,
49                     TrackList *tracks, TrackPanel &panel):
50       wxPrintout(title),
51       mTracks(tracks)
52       , mPanel(panel)
53    {
54    }
55    bool OnPrintPage(int page);
56    bool HasPage(int page);
57    bool OnBeginDocument(int startPage, int endPage);
58    void GetPageInfo(int *minPage, int *maxPage,
59                     int *selPageFrom, int *selPageTo);
60 
61  private:
62    TrackPanel &mPanel;
63    TrackList *mTracks;
64 };
65 
OnPrintPage(int WXUNUSED (page))66 bool AudacityPrintout::OnPrintPage(int WXUNUSED(page))
67 {
68    wxDC *dc = GetDC();
69    if (!dc)
70       return false;
71 
72    int width, height;
73    dc->GetSize(&width, &height);
74 
75    int rulerScreenHeight = 40;
76    int screenTotalHeight =
77       TrackView::GetTotalHeight( *mTracks ) + rulerScreenHeight;
78 
79    double scale = height / (double)screenTotalHeight;
80 
81    int rulerPageHeight = (int)(rulerScreenHeight * scale);
82    Ruler ruler;
83    ruler.SetBounds(0, 0, width, rulerPageHeight);
84    ruler.SetOrientation(wxHORIZONTAL);
85    ruler.SetRange(0.0, mTracks->GetEndTime());
86    ruler.SetFormat(Ruler::TimeFormat);
87    ruler.SetLabelEdges(true);
88    ruler.Draw(*dc);
89 
90    TrackArtist artist( &mPanel );
91    artist.SetBackgroundBrushes(*wxWHITE_BRUSH, *wxWHITE_BRUSH,
92                                *wxWHITE_PEN, *wxWHITE_PEN);
93    const double screenDuration = mTracks->GetEndTime();
94    SelectedRegion region{};
95    artist.pSelectedRegion = &region;
96    ZoomInfo zoomInfo(0.0, width / screenDuration);
97    artist.pZoomInfo = &zoomInfo;
98    int y = rulerPageHeight;
99 
100    for (auto n : mTracks->Any()) {
101       auto &view = TrackView::Get( *n );
102       wxRect r;
103       r.x = 0;
104       r.y = 0;
105       r.width = width;
106       // Note that the views as printed might not have the same proportional
107       // heights as displayed on the screen, because the fixed-sized separators
108       // are counted in those heights but not printed
109       auto trackHeight = (int)(view.GetHeight() * scale);
110       r.height = trackHeight;
111 
112       const auto subViews = view.GetSubViews( r );
113       if (subViews.empty())
114          continue;
115 
116       auto iter = subViews.begin(), end = subViews.end(), next = iter;
117       auto yy = iter->first;
118       for ( ; iter != end; iter = next ) {
119          ++next;
120          auto nextY = ( next == end )
121             ? trackHeight
122             : next->first;
123          r.y = y + yy;
124          r.SetHeight( nextY - yy );
125          yy = nextY;
126 
127          TrackPanelDrawingContext context{
128             *dc, {}, {}, &artist
129          };
130          iter->second->Draw( context, r, TrackArtist::PassTracks );
131       }
132 
133       dc->SetPen(*wxBLACK_PEN);
134       AColor::Line(*dc, 0, y, width, y);
135 
136       y += trackHeight;
137    };
138 
139    return true;
140 }
141 
HasPage(int page)142 bool AudacityPrintout::HasPage(int page)
143 {
144    return (page==1);
145 }
146 
OnBeginDocument(int startPage,int endPage)147 bool AudacityPrintout::OnBeginDocument(int startPage, int endPage)
148 {
149    return wxPrintout::OnBeginDocument(startPage, endPage);
150 }
151 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)152 void AudacityPrintout::GetPageInfo(int *minPage, int *maxPage,
153                                    int *selPageFrom, int *selPageTo)
154 {
155    *minPage = 1;
156    *maxPage = 1;
157    *selPageFrom = 1;
158    *selPageTo = 1;
159 }
160 
HandlePageSetup(wxWindow * parent)161 void HandlePageSetup(wxWindow *parent)
162 {
163    wxPageSetupData pageSetupData;
164 
165    wxPageSetupDialog pageSetupDialog(parent, &pageSetupData);
166    pageSetupDialog.ShowModal();
167 
168    gPrintData() = pageSetupDialog.GetPageSetupData().GetPrintData();
169 }
170 
HandlePrint(wxWindow * parent,const wxString & name,TrackList * tracks,TrackPanel & panel)171 void HandlePrint(
172    wxWindow *parent, const wxString &name, TrackList *tracks,
173    TrackPanel &panel)
174 {
175    wxPrintDialogData printDialogData(gPrintData());
176 
177    wxPrinter printer(&printDialogData);
178    AudacityPrintout printout(name, tracks, panel);
179    if (!printer.Print(parent, &printout, true)) {
180       if (wxPrinter::GetLastError() == wxPRINTER_ERROR) {
181          AudacityMessageBox(
182             XO("There was a problem printing."),
183             XO("Print"),
184             wxOK);
185       }
186       else {
187          // Do nothing, the user cancelled...
188       }
189    }
190    else {
191       gPrintData() = printer.GetPrintDialogData().GetPrintData();
192    }
193 }
194