OpenCPN Partial API docs
printtable.cpp
1 /******************************************************************************
2  *
3  * Project: OpenCPN
4  * Purpose: OpenCPN Route table printout
5  * Author: Pavel Saviankou
6  *
7  ***************************************************************************
8  * Copyright (C) 2012 by David S. Register *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the *
22  * Free Software Foundation, Inc., *
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24  ***************************************************************************
25  *
26  */
27 #include <iostream>
28 #include <sstream>
29 #include <vector>
30 #include <algorithm>
31 
32 #include <wx/wxprec.h>
33 
34 #ifndef WX_PRECOMP
35 #include <wx/wx.h>
36 #endif // precompiled headers
37 #ifdef __WXMSW__
38 //#include "c:\\Program Files\\visual leak detector\\include\\vld.h"
39 #endif
40 
41 #include <wx/print.h>
42 #include <wx/printdlg.h>
43 #include <wx/artprov.h>
44 #include <wx/stdpaths.h>
45 #include <wx/intl.h>
46 #include <wx/listctrl.h>
47 #include <wx/aui/aui.h>
48 #include <wx/dialog.h>
49 #include <wx/progdlg.h>
50 #include <wx/brush.h>
51 #include <wx/colour.h>
52 #include <wx/tokenzr.h>
53 
54 #if wxCHECK_VERSION(2, 9, 0)
55 #include <wx/dialog.h>
56 #else
57 // #include "scrollingdialog.h"
58 #endif
59 
60 #include "dychart.h"
61 
62 #ifdef __WXMSW__
63 #include <stdlib.h>
64 #include <math.h>
65 #include <time.h>
66 #include <psapi.h>
67 #endif
68 
69 #ifndef __WXMSW__
70 #include <signal.h>
71 #include <setjmp.h>
72 #endif
73 
74 #include "printtable.h"
75 
76 using namespace std;
77 
78 void PrintCell::Init(const wxString& _content, wxDC* _dc, int _width,
79  int _cellpadding, bool _bold_font) {
80  bold_font = _bold_font;
81  dc = _dc;
82  width = _width;
83  cellpadding = _cellpadding;
84  content = _content;
85  page = 1;
86  Adjust();
87 };
88 
89 void PrintCell::Adjust() {
90  wxFont orig_font = dc->GetFont();
91  wxFont _font = orig_font;
92  if (bold_font) {
93  _font.SetWeight(wxFONTWEIGHT_BOLD);
94  }
95  dc->SetFont(_font);
96  vector<wxString> list;
97  list.push_back(wxString());
98  wxString separator = wxT(" ");
99  wxStringTokenizer tokenizer(content, separator, wxTOKEN_RET_DELIMS);
100  int words_number = 0;
101  while (tokenizer.HasMoreTokens()) {
102  wxString token = tokenizer.GetNextToken();
103  wxCoord h = 0;
104  wxCoord w = 0;
105  wxString tmp = list[list.size() - 1];
106  wxString tmp2 = tmp + token;
107  words_number++;
108  dc->GetMultiLineTextExtent(tmp2, &w, &h);
109  if ((w < width - 2 * cellpadding) || words_number == 1) {
110  list[list.size() - 1] = tmp2;
111  } else {
112  list.push_back(wxString());
113  }
114  }
115 
116  for (size_t i = 0; i < list.size() - 1; i++) {
117  modified_content = modified_content + list[i] + _T('\n');
118  }
119  // now add last element without new line
120  modified_content = modified_content + list[list.size() - 1];
121 
122  wxCoord h = 0;
123  wxCoord w = 0;
124  dc->GetMultiLineTextExtent(modified_content, &w, &h);
125  SetHeight(h + 8);
126 
127  dc->SetFont(orig_font);
128 }
129 
130 Table::Table() {
131  nrows = 0;
132  ncols = 0;
133  data.clear();
134  state = TABLE_SETUP_WIDTHS;
135  create_next_row = true;
136 }
137 
138 Table::~Table() {
139  for (vector<vector<wxString> >::iterator iter = data.begin();
140  iter != data.end(); iter++) {
141  (*iter).clear();
142  }
143  data.clear();
144 }
145 
146 void Table::Start() {
147  if (create_next_row) {
148  NewRow();
149  create_next_row = false;
150  }
151 }
152 
153 void Table::NewRow() {
154  vector<wxString> empty_row;
155  data.push_back(empty_row);
156 }
157 
158 Table& Table::operator<<(const double& cellcontent) {
159  if (state == TABLE_SETUP_WIDTHS) {
160  widths.push_back(cellcontent);
161  return *this;
162  }
163  if (state == TABLE_FILL_DATA) {
164  stringstream sstr;
165  sstr << cellcontent;
166  string _cellcontent = sstr.str();
167  Start();
168  wxString _str(_cellcontent.c_str(), wxConvUTF8);
169  data[data.size() - 1].push_back(_str);
170  }
171  return *this;
172 }
173 
174 Table& Table::operator<<(const wxString& cellcontent) {
175  Start();
176  if (state == TABLE_FILL_HEADER) { // if we start to fill with string data, we
177  // change state automatically.
178  header.push_back(cellcontent);
179  return *this;
180  }
181  if (state == TABLE_SETUP_WIDTHS) { // if we start to fill with string data,
182  // we change state automatically.
183  state = TABLE_FILL_DATA;
184  }
185 
186  if ((cellcontent == "\n")) {
187  create_next_row = true;
188  return *this;
189  }
190  data[data.size() - 1].push_back(cellcontent);
191  return *this;
192 }
193 
194 Table& Table::operator<<(const int& cellcontent) {
195  if (state == TABLE_SETUP_WIDTHS) {
196  widths.push_back((double)cellcontent);
197  return *this;
198  }
199  if (state == TABLE_FILL_DATA) {
200  stringstream sstr;
201  sstr << cellcontent;
202  string _cellcontent = sstr.str();
203  Start();
204  wxString _str(_cellcontent.c_str(), wxConvUTF8);
205  data[data.size() - 1].push_back(_str);
206  }
207  return *this;
208 }
209 
210 ostream& operator<<(ostream& out, Table& table) {
211  vector<vector<wxString> >& data = table.GetData();
212 
213  for (vector<vector<wxString> >::iterator iter = data.begin();
214  iter != data.end(); iter++) {
215  vector<wxString> row = (*iter);
216  for (vector<wxString>::iterator rowiter = row.begin(); rowiter != row.end();
217  rowiter++) {
218  out << (*rowiter).fn_str() << " ";
219  }
220  out << endl;
221  }
222  return out;
223 }
224 
225 PrintTable::PrintTable() : Table() { rows_heights.clear(); }
226 
227 void PrintTable::AdjustCells(wxDC* dc, int marginX, int marginY) {
228  number_of_pages = -1;
229  contents.clear();
230  int sum = 0;
231  for (size_t j = 0; j < widths.size(); j++) {
232  sum += widths[j];
233  }
234 
235  int w, h;
236  dc->GetSize(&w, &h);
237 
238  double scale_x, scale_y;
239  dc->GetUserScale(&scale_x, &scale_y);
240  w /= scale_x;
241  h /= scale_y;
242 
243  int width = w - 4 * marginX;
244  header_height = -1;
245  for (size_t j = 0; j < header.size(); j++) {
246  int cell_width = (int)((double)width * widths[j] / sum);
247  PrintCell cell_content;
248  cell_content.Init(header[j], dc, cell_width, 10, true);
249  header_content.push_back(cell_content);
250  header_height = std::max(header_height, cell_content.GetHeight());
251  }
252 
253  for (size_t i = 0; i < data.size(); i++) {
254  vector<wxString> row = data[i];
255  vector<PrintCell> contents_row;
256  int max_height = -1;
257  for (size_t j = 0; j < row.size(); j++) {
258  int cell_width = (int)((double)width * widths[j] / sum);
259  PrintCell cell_content;
260  cell_content.Init(row[j], dc, cell_width, 10);
261  contents_row.push_back(cell_content);
262  max_height = std::max(max_height, cell_content.GetHeight());
263  }
264  rows_heights.push_back(max_height);
265  contents.push_back(contents_row);
266  }
267 
268  int stripped_page = h - 4 * marginY - header_height;
269  int current_page = 1;
270  int current_y = 0;
271  for (size_t i = 0; i < data.size(); i++) {
272  int row_height = rows_heights[i];
273  if (row_height + current_y > stripped_page) {
274  current_page++;
275  current_y = row_height;
276  } else {
277  current_y += row_height;
278  }
279  int row_page = current_page;
280  vector<PrintCell>& contents_row = contents[i];
281  for (size_t j = 0; j < contents_row.size(); j++) {
282  contents_row[j].SetPage(row_page);
283  contents_row[j].SetHeight(row_height);
284  }
285  number_of_pages = std::max(row_page, number_of_pages);
286  }
287 }
This class takes multilined string and modifies it to fit into given width for given device.
Definition: printtable.h:113
Represents a NxM simple table with captions.
Definition: printtable.h:69