1 /*
2 / DialogsGraph.cpp
3 / graphics dialog classes
4 /
5 / version 1.7, 2013 May 8
6 /
7 / Author: Sandro Furieri a-furieri@lqt.it
8 /
9 / Copyright (C) 2010-2013  Alessandro Furieri
10 /
11 /    This program is free software: you can redistribute it and/or modify
12 /    it under the terms of the GNU General Public License as published by
13 /    the Free Software Foundation, either version 3 of the License, or
14 /    (at your option) any later version.
15 /
16 /    This program is distributed in the hope that it will be useful,
17 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 /    GNU General Public License for more details.
20 /
21 /    You should have received a copy of the GNU General Public License
22 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 /
24 */
25 
26 #include "Classdef.h"
27 
28 #include "wx/spinctrl.h"
29 #include "wx/filedlg.h"
30 #include "wx/filename.h"
31 #include "wx/colordlg.h"
32 #include "wx/clipbrd.h"
33 
34 #include <gaiagraphics.h>
35 
36 #if defined(_WIN32) || defined (__MINGW32__)
37 #define FORMAT_64	"%I64d"
38 #else
39 #define FORMAT_64	"%lld"
40 #endif
41 
Create(MyFrame * parent,wxString & table,wxString & column,int null_count,int text_count,int integer_count,int real_count,int blob_count,double min,double max,double avg,double stddev_pop,double stddev_samp,double var_pop,double var_samp,int distinct_values)42 bool ColumnStatsDialog::Create(MyFrame * parent, wxString & table,
43                                wxString & column, int null_count,
44                                int text_count, int integer_count,
45                                int real_count, int blob_count, double min,
46                                double max, double avg, double stddev_pop,
47                                double stddev_samp, double var_pop,
48                                double var_samp, int distinct_values)
49 {
50 //
51 // creating the dialog
52 //
53   MainFrame = parent;
54   Table = table;
55   Column = column;
56   NullValues = null_count;
57   TextValues = text_count;
58   IntegerValues = integer_count;
59   RealValues = real_count;
60   BlobValues = blob_count;
61   Min = min;
62   Max = max;
63   Avg = avg;
64   StdDevPop = stddev_pop;
65   StdDevSamp = stddev_samp;
66   VarPop = var_pop;
67   VarSamp = var_samp;
68   DistinctValues = distinct_values;
69   if (wxDialog::Create(parent, wxID_ANY, wxT("Column statistic snapshot")) ==
70       false)
71     return false;
72 // populates individual controls
73   CreateControls();
74 // sets dialog sizer
75   GetSizer()->Fit(this);
76   GetSizer()->SetSizeHints(this);
77 // centers the dialog window
78   Centre();
79   return true;
80 }
81 
CreateControls()82 void ColumnStatsDialog::CreateControls()
83 {
84 //
85 // creating individual control and setting initial values
86 //
87   char dummy[256];
88   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
89   this->SetSizer(topSizer);
90   wxBoxSizer *boxSizer = new wxBoxSizer(wxVERTICAL);
91   topSizer->Add(boxSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
92 // First row: TABLE name
93   wxBoxSizer *tableSizer = new wxBoxSizer(wxHORIZONTAL);
94   boxSizer->Add(tableSizer, 0, wxALIGN_RIGHT | wxALL, 0);
95   wxStaticText *tableLabel =
96     new wxStaticText(this, wxID_STATIC, wxT("&Table name:"));
97   tableSizer->Add(tableLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
98   wxTextCtrl *tableCtrl = new wxTextCtrl(this, wxID_ANY, Table,
99                                          wxDefaultPosition, wxSize(350, 22),
100                                          wxTE_READONLY);
101   tableCtrl->Enable(false);
102   tableSizer->Add(tableCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
103 // second row: COLUMN name
104   wxBoxSizer *colSizer = new wxBoxSizer(wxHORIZONTAL);
105   boxSizer->Add(colSizer, 0, wxALIGN_RIGHT | wxALL, 0);
106   wxStaticText *colLabel =
107     new wxStaticText(this, wxID_STATIC, wxT("&Column name:"));
108   colSizer->Add(colLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
109   wxTextCtrl *colCtrl = new wxTextCtrl(this, wxID_ANY, Column,
110                                        wxDefaultPosition, wxSize(350, 22),
111                                        wxTE_READONLY);
112   colCtrl->Enable(false);
113   colSizer->Add(colCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
114 // third row: total rows
115   wxBoxSizer *rowSizer = new wxBoxSizer(wxHORIZONTAL);
116   boxSizer->Add(rowSizer, 0, wxALIGN_RIGHT | wxALL, 0);
117   wxStaticText *rowLabel =
118     new wxStaticText(this, wxID_STATIC, wxT("&Total values:"));
119   rowSizer->Add(rowLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
120   sprintf(dummy, "%d",
121           NullValues + TextValues + IntegerValues + RealValues + BlobValues);
122   wxString rows = wxString::FromUTF8(dummy);
123   wxTextCtrl *rowCtrl = new wxTextCtrl(this, wxID_ANY, rows,
124                                        wxDefaultPosition, wxSize(350, 22),
125                                        wxTE_READONLY);
126   rowCtrl->Enable(false);
127   rowSizer->Add(rowCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
128   if (NullValues > 0)
129     {
130       // NULL values count
131       wxBoxSizer *nullSizer = new wxBoxSizer(wxHORIZONTAL);
132       boxSizer->Add(nullSizer, 0, wxALIGN_RIGHT | wxALL, 0);
133       wxStaticText *nullLabel =
134         new wxStaticText(this, wxID_STATIC, wxT("&NULL values:"));
135       nullSizer->Add(nullLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
136       sprintf(dummy, "%d", NullValues);
137       wxString nulls = wxString::FromUTF8(dummy);
138       wxTextCtrl *nullCtrl = new wxTextCtrl(this, wxID_ANY, nulls,
139                                             wxDefaultPosition, wxSize(350, 22),
140                                             wxTE_READONLY);
141       nullCtrl->Enable(false);
142       nullSizer->Add(nullCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
143     }
144   if (TextValues > 0)
145     {
146       // TEXT values count
147       wxBoxSizer *textSizer = new wxBoxSizer(wxHORIZONTAL);
148       boxSizer->Add(textSizer, 0, wxALIGN_RIGHT | wxALL, 0);
149       wxStaticText *textLabel =
150         new wxStaticText(this, wxID_STATIC, wxT("&TEXT values:"));
151       textSizer->Add(textLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
152       sprintf(dummy, "%d", TextValues);
153       wxString texts = wxString::FromUTF8(dummy);
154       wxTextCtrl *textCtrl = new wxTextCtrl(this, wxID_ANY, texts,
155                                             wxDefaultPosition, wxSize(350, 22),
156                                             wxTE_READONLY);
157       textCtrl->Enable(false);
158       textSizer->Add(textCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
159     }
160   if (IntegerValues > 0)
161     {
162       // INTEGER values count
163       wxBoxSizer *intSizer = new wxBoxSizer(wxHORIZONTAL);
164       boxSizer->Add(intSizer, 0, wxALIGN_RIGHT | wxALL, 0);
165       wxStaticText *intLabel =
166         new wxStaticText(this, wxID_STATIC, wxT("&INTEGER values:"));
167       intSizer->Add(intLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
168       sprintf(dummy, "%d", IntegerValues);
169       wxString ints = wxString::FromUTF8(dummy);
170       wxTextCtrl *intCtrl = new wxTextCtrl(this, wxID_ANY, ints,
171                                            wxDefaultPosition, wxSize(350, 22),
172                                            wxTE_READONLY);
173       intCtrl->Enable(false);
174       intSizer->Add(intCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
175     }
176   if (RealValues > 0)
177     {
178       // REAL values count
179       wxBoxSizer *realSizer = new wxBoxSizer(wxHORIZONTAL);
180       boxSizer->Add(realSizer, 0, wxALIGN_RIGHT | wxALL, 0);
181       wxStaticText *realLabel =
182         new wxStaticText(this, wxID_STATIC, wxT("&REAL values:"));
183       realSizer->Add(realLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
184       sprintf(dummy, "%d", RealValues);
185       wxString reals = wxString::FromUTF8(dummy);
186       wxTextCtrl *realCtrl = new wxTextCtrl(this, wxID_ANY, reals,
187                                             wxDefaultPosition, wxSize(350, 22),
188                                             wxTE_READONLY);
189       realCtrl->Enable(false);
190       realSizer->Add(realCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
191     }
192   if (BlobValues > 0)
193     {
194       // BLOB values count
195       wxBoxSizer *blobSizer = new wxBoxSizer(wxHORIZONTAL);
196       boxSizer->Add(blobSizer, 0, wxALIGN_RIGHT | wxALL, 0);
197       wxStaticText *blobLabel =
198         new wxStaticText(this, wxID_STATIC, wxT("&BLOB values:"));
199       blobSizer->Add(blobLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
200       sprintf(dummy, "%d", BlobValues);
201       wxString blobs = wxString::FromUTF8(dummy);
202       wxTextCtrl *blobCtrl = new wxTextCtrl(this, wxID_ANY, blobs,
203                                             wxDefaultPosition, wxSize(350, 22),
204                                             wxTE_READONLY);
205       blobCtrl->Enable(false);
206       blobSizer->Add(blobCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
207     }
208 // statistical group box
209   wxStaticBox *statBox = new wxStaticBox(this, wxID_STATIC,
210                                          wxT("Data distribution snapshot"),
211                                          wxDefaultPosition,
212                                          wxDefaultSize);
213   wxBoxSizer *statSizer = new wxStaticBoxSizer(statBox, wxVERTICAL);
214   boxSizer->Add(statSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
215 // distinct values count
216   wxBoxSizer *distSizer = new wxBoxSizer(wxHORIZONTAL);
217   statSizer->Add(distSizer, 0, wxALIGN_CENTER | wxALL, 0);
218   wxStaticText *distLabel =
219     new wxStaticText(this, wxID_STATIC, wxT("&DISTINCT values:"));
220   distSizer->Add(distLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
221   sprintf(dummy, "%d", DistinctValues);
222   wxString dists = wxString::FromUTF8(dummy);
223   wxTextCtrl *distCtrl = new wxTextCtrl(this, wxID_ANY, dists,
224                                         wxDefaultPosition, wxSize(150, 22),
225                                         wxTE_READONLY);
226   distCtrl->Enable(false);
227   distSizer->Add(distCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
228 
229   if ((IntegerValues + RealValues) > 1)
230     {
231       // statistic analysis: MinMax range
232       wxStaticBox *rangeBox = new wxStaticBox(this, wxID_STATIC,
233                                               wxT("Data range"),
234                                               wxDefaultPosition,
235                                               wxDefaultSize);
236       wxBoxSizer *rngSizer = new wxStaticBoxSizer(rangeBox, wxVERTICAL);
237       statSizer->Add(rngSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
238       wxBoxSizer *minMaxSizer = new wxBoxSizer(wxHORIZONTAL);
239       rngSizer->Add(minMaxSizer, 0, wxALIGN_CENTER | wxALL, 0);
240       wxStaticText *minLabel =
241         new wxStaticText(this, wxID_STATIC, wxT("&Min:"));
242       minMaxSizer->Add(minLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
243       sprintf(dummy, "%1.18f", Min);
244       CleanDecimals(dummy);
245       wxString min = wxString::FromUTF8(dummy);
246       wxTextCtrl *minCtrl = new wxTextCtrl(this, wxID_ANY, min,
247                                            wxDefaultPosition, wxSize(150, 22),
248                                            wxTE_READONLY);
249       minCtrl->Enable(false);
250       minMaxSizer->Add(minCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
251       wxStaticText *maxLabel =
252         new wxStaticText(this, wxID_STATIC, wxT("&Max:"));
253       minMaxSizer->Add(maxLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
254       sprintf(dummy, "%1.18f", Max);
255       CleanDecimals(dummy);
256       wxString max = wxString::FromUTF8(dummy);
257       wxTextCtrl *maxCtrl = new wxTextCtrl(this, wxID_ANY, max,
258                                            wxDefaultPosition, wxSize(150, 22),
259                                            wxTE_READONLY);
260       maxCtrl->Enable(false);
261       minMaxSizer->Add(maxCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
262       // statistic analysis: Average
263       wxBoxSizer *avgSizer = new wxBoxSizer(wxHORIZONTAL);
264       statSizer->Add(avgSizer, 0, wxALIGN_CENTER | wxALL, 0);
265       wxStaticText *avgLabel =
266         new wxStaticText(this, wxID_STATIC, wxT("&Average:"));
267       avgSizer->Add(avgLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
268       sprintf(dummy, "%1.4f", Avg);
269       CleanDecimals(dummy);
270       wxString avg = wxString::FromUTF8(dummy);
271       wxTextCtrl *avgCtrl = new wxTextCtrl(this, wxID_ANY, avg,
272                                            wxDefaultPosition, wxSize(150, 22),
273                                            wxTE_READONLY);
274       avgCtrl->Enable(false);
275       avgSizer->Add(avgCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
276       // statistic analysis: Standard Deviation
277       wxStaticBox *stdDevBox = new wxStaticBox(this, wxID_STATIC,
278                                                wxT("Standard deviation"),
279                                                wxDefaultPosition,
280                                                wxDefaultSize);
281       wxBoxSizer *stdSizer = new wxStaticBoxSizer(stdDevBox, wxVERTICAL);
282       statSizer->Add(stdSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
283       wxBoxSizer *stdDevSizer = new wxBoxSizer(wxHORIZONTAL);
284       stdSizer->Add(stdDevSizer, 0, wxALIGN_CENTER | wxALL, 0);
285       wxStaticText *devPopLabel =
286         new wxStaticText(this, wxID_STATIC, wxT("&Pop:"));
287       stdDevSizer->Add(devPopLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
288       sprintf(dummy, "%1.4f", StdDevPop);
289       CleanDecimals(dummy);
290       wxString stdPop = wxString::FromUTF8(dummy);
291       wxTextCtrl *stdPopCtrl = new wxTextCtrl(this, wxID_ANY, stdPop,
292                                               wxDefaultPosition, wxSize(150,
293                                                                         22),
294                                               wxTE_READONLY);
295       stdPopCtrl->Enable(false);
296       stdDevSizer->Add(stdPopCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
297       wxStaticText *stdSampLabel =
298         new wxStaticText(this, wxID_STATIC, wxT("&Samp:"));
299       stdDevSizer->Add(stdSampLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
300       sprintf(dummy, "%1.4f", StdDevSamp);
301       CleanDecimals(dummy);
302       wxString stdSamp = wxString::FromUTF8(dummy);
303       wxTextCtrl *stdSampCtrl = new wxTextCtrl(this, wxID_ANY, stdSamp,
304                                                wxDefaultPosition, wxSize(150,
305                                                                          22),
306                                                wxTE_READONLY);
307       stdSampCtrl->Enable(false);
308       stdDevSizer->Add(stdSampCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
309       // statistic analysis: Variance
310       wxStaticBox *varBox = new wxStaticBox(this, wxID_STATIC,
311                                             wxT("Variance"),
312                                             wxDefaultPosition,
313                                             wxDefaultSize);
314       wxBoxSizer *varianceSizer = new wxStaticBoxSizer(varBox, wxVERTICAL);
315       statSizer->Add(varianceSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
316       wxBoxSizer *varSizer = new wxBoxSizer(wxHORIZONTAL);
317       varianceSizer->Add(varSizer, 0, wxALIGN_CENTER | wxALL, 0);
318       wxStaticText *varPopLabel =
319         new wxStaticText(this, wxID_STATIC, wxT("&Pop:"));
320       varSizer->Add(varPopLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
321       sprintf(dummy, "%1.4f", VarPop);
322       CleanDecimals(dummy);
323       wxString varPop = wxString::FromUTF8(dummy);
324       wxTextCtrl *varPopCtrl = new wxTextCtrl(this, wxID_ANY, varPop,
325                                               wxDefaultPosition, wxSize(150,
326                                                                         22),
327                                               wxTE_READONLY);
328       varPopCtrl->Enable(false);
329       varSizer->Add(varPopCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
330       wxStaticText *varSampLabel =
331         new wxStaticText(this, wxID_STATIC, wxT("&Samp:"));
332       varSizer->Add(varSampLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
333       sprintf(dummy, "%1.4f", VarSamp);
334       CleanDecimals(dummy);
335       wxString varSamp = wxString::FromUTF8(dummy);
336       wxTextCtrl *varSampCtrl = new wxTextCtrl(this, wxID_ANY, varSamp,
337                                                wxDefaultPosition, wxSize(150,
338                                                                          22),
339                                                wxTE_READONLY);
340       varSampCtrl->Enable(false);
341       varSizer->Add(varSampCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
342     }
343 // buttons
344   wxBoxSizer *buttonBox = new wxBoxSizer(wxHORIZONTAL);
345   boxSizer->Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
346   wxButton *chart = new wxButton(this, ID_STAT_CHART, wxT("&Show chart"));
347   buttonBox->Add(chart, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
348   wxButton *exit = new wxButton(this, wxID_OK, wxT("&Exit"));
349   buttonBox->Add(exit, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
350 // appends event handler for OK button
351   Connect(ID_STAT_CHART, wxEVT_COMMAND_BUTTON_CLICKED,
352           (wxObjectEventFunction) & ColumnStatsDialog::OnShowChart);
353   Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED,
354           (wxObjectEventFunction) & ColumnStatsDialog::OnExit);
355 }
356 
CleanDecimals(char * str)357 void ColumnStatsDialog::CleanDecimals(char *str)
358 {
359 // suppressing not significative decimal digits
360   int i;
361   int len = strlen(str);
362   for (i = len - 1; i >= 0; i--)
363     {
364       if (str[i] == '0')
365         str[i] = '\0';
366       else
367         break;
368     }
369   len = strlen(str);
370   if (str[len - 1] == '.')
371     str[len - 1] = '\0';
372 }
373 
OnShowChart(wxCommandEvent & WXUNUSED (event))374 void ColumnStatsDialog::OnShowChart(wxCommandEvent & WXUNUSED(event))
375 {
376 //
377 // showing a chart:
378 //
379   bool numeric = false;
380   StatsChartDialog dlg;
381   if (IntegerValues > 0 || RealValues > 0)
382     numeric = true;
383   dlg.Create(this, MainFrame, Table, Column, numeric, Min, Max);
384   dlg.ShowModal();
385 }
386 
OnExit(wxCommandEvent & WXUNUSED (event))387 void ColumnStatsDialog::OnExit(wxCommandEvent & WXUNUSED(event))
388 {
389 //
390 // all done:
391 //
392   wxDialog::EndModal(wxID_OK);
393 }
394 
Create(ColumnStatsDialog * parent,MyFrame * granny,wxString & table,wxString & column,bool numeric,double min,double max)395 bool StatsChartDialog::Create(ColumnStatsDialog * parent, MyFrame * granny,
396                               wxString & table, wxString & column, bool numeric,
397                               double min, double max)
398 {
399 //
400 // creating the dialog
401 //
402   MainFrame = granny;
403   Table = table;
404   Column = column;
405   NumericData = numeric;
406   Min = min;
407   Max = max;
408   if (wxDialog::Create(parent, wxID_ANY, wxT("Chart preview")) == false)
409     return false;
410 // populates individual controls
411   CreateControls();
412 // sets dialog sizer
413   GetSizer()->Fit(this);
414   GetSizer()->SetSizeHints(this);
415 // centers the dialog window
416   Centre();
417   return true;
418 }
419 
CreateControls()420 void StatsChartDialog::CreateControls()
421 {
422 //
423 // creating individual control and setting initial values
424 //
425   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
426   this->SetSizer(topSizer);
427   wxBoxSizer *boxSizer = new wxBoxSizer(wxVERTICAL);
428   topSizer->Add(boxSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
429 // First row: TABLE name
430   wxBoxSizer *tableSizer = new wxBoxSizer(wxHORIZONTAL);
431   boxSizer->Add(tableSizer, 0, wxALIGN_RIGHT | wxALL, 0);
432   wxStaticText *tableLabel =
433     new wxStaticText(this, wxID_STATIC, wxT("&Table name:"));
434   tableSizer->Add(tableLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
435   wxTextCtrl *tableCtrl = new wxTextCtrl(this, wxID_ANY, Table,
436                                          wxDefaultPosition, wxSize(350, 22),
437                                          wxTE_READONLY);
438   tableCtrl->Enable(false);
439   tableSizer->Add(tableCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
440 // second row: COLUMN name
441   wxBoxSizer *colSizer = new wxBoxSizer(wxHORIZONTAL);
442   boxSizer->Add(colSizer, 0, wxALIGN_RIGHT | wxALL, 0);
443   wxStaticText *colLabel =
444     new wxStaticText(this, wxID_STATIC, wxT("&Column name:"));
445   colSizer->Add(colLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
446   wxTextCtrl *colCtrl = new wxTextCtrl(this, wxID_ANY, Column,
447                                        wxDefaultPosition, wxSize(350, 22),
448                                        wxTE_READONLY);
449   colCtrl->Enable(false);
450   colSizer->Add(colCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
451 // third row: Chart params
452   wxStaticBox *optBox = new wxStaticBox(this, wxID_STATIC,
453                                         wxT("Chart settings"),
454                                         wxDefaultPosition,
455                                         wxDefaultSize);
456   wxBoxSizer *optSizer = new wxStaticBoxSizer(optBox, wxVERTICAL);
457   boxSizer->Add(optSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
458   wxBoxSizer *chartSizer = new wxBoxSizer(wxHORIZONTAL);
459   optSizer->Add(chartSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
460   wxString type[3];
461   type[0] = wxT("&Histogram");
462   type[1] = wxT("&Line chart");
463   type[2] = wxT("&Pie chart");
464   TypeCtrl = new wxRadioBox(this, ID_CHART_TYPE,
465                             wxT("&Type"),
466                             wxDefaultPosition,
467                             wxDefaultSize, 3, type, 1, wxRA_SPECIFY_COLS);
468   chartSizer->Add(TypeCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
469   TypeCtrl->SetSelection(0);
470   Histogram = true;
471   LineChart = false;
472   PieChart = false;
473   wxString size[5];
474   size[0] = wxT("&256");
475   size[1] = wxT("&512");
476   size[2] = wxT("&1024");
477   size[3] = wxT("&2048");
478   size[4] = wxT("&4196");
479   SizeCtrl = new wxRadioBox(this, ID_CHART_SIZE,
480                             wxT("&Dimension [pixels]"),
481                             wxDefaultPosition,
482                             wxDefaultSize, 5, size, 1, wxRA_SPECIFY_COLS);
483   chartSizer->Add(SizeCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
484   SizeCtrl->SetSelection(0);
485   wxBoxSizer *mixSizer = new wxBoxSizer(wxVERTICAL);
486   chartSizer->Add(mixSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
487   wxString mode[2];
488   mode[0] = wxT("&by intervals");
489   mode[1] = wxT("&by unique values");
490   ModeCtrl = new wxRadioBox(this, ID_CHART_MODE,
491                             wxT("&Mode"),
492                             wxDefaultPosition,
493                             wxDefaultSize, 2, mode, 1, wxRA_SPECIFY_COLS);
494   mixSizer->Add(ModeCtrl, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
495   if (NumericData == true)
496     {
497       ModeCtrl->SetSelection(0);
498       ByInterval = true;
499   } else
500     {
501       ModeCtrl->SetSelection(1);
502       ModeCtrl->Enable(false);
503       ByInterval = false;
504     }
505   wxBoxSizer *classSizer = new wxBoxSizer(wxHORIZONTAL);
506   mixSizer->Add(classSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
507   wxStaticText *classLabel =
508     new wxStaticText(this, wxID_STATIC, wxT("&Classes:"));
509   classSizer->Add(classLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
510   ClassCtrl = new wxSpinCtrl(this, ID_CHART_CLASS, wxT("10"),
511                              wxDefaultPosition, wxSize(80, 20),
512                              wxSP_ARROW_KEYS, 2, 1000, 10);
513   classSizer->Add(ClassCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
514   Classes = 10;
515 
516 // creating a control to show the Chart preview
517   wxStaticBox *exBox = new wxStaticBox(this, wxID_ANY,
518                                        wxT("Chart preview"),
519                                        wxDefaultPosition, wxDefaultSize);
520   wxBoxSizer *showSizer = new wxStaticBoxSizer(exBox, wxHORIZONTAL);
521   boxSizer->Add(showSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
522   ChartShow = new wxStaticBitmap(this, wxID_ANY,
523                                  wxBitmap(), wxDefaultPosition, wxSize(256,
524                                                                        256),
525                                  wxBORDER_SUNKEN);
526   showSizer->Add(ChartShow, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
527 
528 // buttons
529   wxStaticBox *btnBox = new wxStaticBox(this, wxID_STATIC,
530                                         wxT("Export as"),
531                                         wxDefaultPosition,
532                                         wxDefaultSize);
533   wxBoxSizer *btnSizer = new wxStaticBoxSizer(btnBox, wxVERTICAL);
534   showSizer->Add(btnSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
535   wxBoxSizer *buttonBox = new wxBoxSizer(wxVERTICAL);
536   btnSizer->Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
537   wxButton *copy = new wxButton(this, ID_CHART_COPY, wxT("&Copy"));
538   buttonBox->Add(copy, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
539   wxButton *png = new wxButton(this, ID_CHART_PNG, wxT("&PNG"));
540   buttonBox->Add(png, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
541   wxButton *svg = new wxButton(this, ID_CHART_SVG, wxT("&SVG"));
542   buttonBox->Add(svg, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
543   wxButton *pdf = new wxButton(this, ID_CHART_PDF, wxT("&PDF"));
544   buttonBox->Add(pdf, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
545   wxBoxSizer *exitBox = new wxBoxSizer(wxHORIZONTAL);
546   boxSizer->Add(exitBox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
547   wxButton *exit = new wxButton(this, wxID_OK, wxT("&Exit"));
548   exitBox->Add(exit, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
549 // appends event handler for OK button
550   Connect(ID_CHART_COPY, wxEVT_COMMAND_BUTTON_CLICKED,
551           (wxObjectEventFunction) & StatsChartDialog::OnChartCopy);
552   Connect(ID_CHART_PNG, wxEVT_COMMAND_BUTTON_CLICKED,
553           (wxObjectEventFunction) & StatsChartDialog::OnChartPng);
554   Connect(ID_CHART_SVG, wxEVT_COMMAND_BUTTON_CLICKED,
555           (wxObjectEventFunction) & StatsChartDialog::OnChartSvg);
556   Connect(ID_CHART_PDF, wxEVT_COMMAND_BUTTON_CLICKED,
557           (wxObjectEventFunction) & StatsChartDialog::OnChartPdf);
558   Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED,
559           (wxObjectEventFunction) & StatsChartDialog::OnExit);
560   Connect(ID_CHART_TYPE, wxEVT_COMMAND_RADIOBOX_SELECTED,
561           (wxObjectEventFunction) & StatsChartDialog::OnChartTypeChanged);
562   Connect(ID_CHART_MODE, wxEVT_COMMAND_RADIOBOX_SELECTED,
563           (wxObjectEventFunction) & StatsChartDialog::OnChartModeChanged);
564   Connect(ID_CHART_CLASS, wxEVT_COMMAND_TEXT_UPDATED,
565           (wxObjectEventFunction) & StatsChartDialog::OnChartClassesChanged);
566 // showing the current preview
567   ReloadData();
568   UpdatePreview();
569 }
570 
OnChartTypeChanged(wxCommandEvent & WXUNUSED (event))571 void StatsChartDialog::OnChartTypeChanged(wxCommandEvent & WXUNUSED(event))
572 {
573 // chart type radiobox changed
574   switch (TypeCtrl->GetSelection())
575     {
576       case 0:
577         Histogram = true;
578         LineChart = false;
579         PieChart = false;
580         break;
581       case 1:
582         Histogram = false;
583         LineChart = true;
584         PieChart = false;
585         break;
586       case 2:
587         Histogram = false;
588         LineChart = false;
589         PieChart = true;
590         break;
591     };
592   UpdatePreview();
593 }
594 
OnChartModeChanged(wxCommandEvent & WXUNUSED (event))595 void StatsChartDialog::OnChartModeChanged(wxCommandEvent & WXUNUSED(event))
596 {
597 // chart mode radiobox changed
598   switch (ModeCtrl->GetSelection())
599     {
600       case 0:
601         ByInterval = true;
602         break;
603       case 1:
604         ByInterval = false;
605         break;
606     };
607   ReloadData();
608   UpdatePreview();
609 }
610 
OnChartClassesChanged(wxCommandEvent & WXUNUSED (event))611 void StatsChartDialog::OnChartClassesChanged(wxCommandEvent & WXUNUSED(event))
612 {
613 //
614 // Classes selection changed
615 //
616   Classes = ClassCtrl->GetValue();
617   ReloadData();
618   UpdatePreview();
619 }
620 
UpdatePreview()621 void StatsChartDialog::UpdatePreview()
622 {
623 // showing an empty preview chart
624   wxBitmap bmp;
625   ChartShow->SetBitmap(bmp);
626   if (ChartData.IsValid() != true)
627     return;
628 
629 // updating the Chart Preview
630   if (ByInterval == true)
631     {
632       if (Histogram == true)
633         DoIntervalHistogram(256, 256, CHART_TARGET_IS_PREVIEW, 8);
634       if (LineChart == true)
635         DoIntervalLineChart(256, 256, CHART_TARGET_IS_PREVIEW, 8);
636       if (PieChart == true)
637         DoIntervalPieChart(256, 256, CHART_TARGET_IS_PREVIEW, 8);
638   } else
639     {
640       if (Histogram == true)
641         DoUniqueHistogram(256, 256, CHART_TARGET_IS_PREVIEW, 8);
642       if (LineChart == true)
643         DoUniqueLineChart(256, 256, CHART_TARGET_IS_PREVIEW, 8);
644       if (PieChart == true)
645         DoUniquePieChart(256, 256, CHART_TARGET_IS_PREVIEW, 8);
646     }
647 }
648 
ReloadData()649 void StatsChartDialog::ReloadData()
650 {
651 // reloading Char Data
652   if (ChartData.Check(ByInterval, Classes) == true)
653     return;                     /* still valid Data */
654 
655   ::wxBeginBusyCursor();
656   ChartData.CleanData();
657   if (ByInterval == true)
658     PrepareDataByInterval(Classes);
659   else
660     PrepareDataByUniqueValue(Classes);
661   ::wxEndBusyCursor();
662 
663   if (ChartData.IsValid() != true)
664     {
665       wxMessageBox(wxT("Unable to retrieve column data"),
666                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
667       return;
668     }
669 }
670 
OnChartCopy(wxCommandEvent & WXUNUSED (event))671 void StatsChartDialog::OnChartCopy(wxCommandEvent & WXUNUSED(event))
672 {
673 // copying the current Chart to the Clipboard
674   int hsize;
675   int vsize;
676   int font_size;
677   if (ChartData.IsValid() != true)
678     return;
679   switch (SizeCtrl->GetSelection())
680     {
681       case 0:
682         hsize = 256;
683         vsize = 256;
684         font_size = 8;
685         break;
686       case 1:
687         hsize = 512;
688         vsize = 512;
689         font_size = 8;
690         break;
691       case 2:
692         hsize = 1024;
693         vsize = 1024;
694         font_size = 10;
695         break;
696       case 3:
697         hsize = 2048;
698         vsize = 2048;
699         font_size = 12;
700         break;
701       case 4:
702         hsize = 4196;
703         vsize = 4196;
704         font_size = 12;
705         break;
706     };
707 
708 // exporting the Chart as COPY
709   if (ByInterval == true)
710     {
711       if (Histogram == true)
712         DoIntervalHistogram(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
713       if (LineChart == true)
714         DoIntervalLineChart(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
715       if (PieChart == true)
716         DoIntervalPieChart(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
717   } else
718     {
719       if (Histogram == true)
720         DoUniqueHistogram(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
721       if (LineChart == true)
722         DoUniqueLineChart(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
723       if (PieChart == true)
724         DoUniquePieChart(hsize, vsize, CHART_TARGET_IS_COPY, font_size);
725     }
726 }
727 
OnChartPng(wxCommandEvent & WXUNUSED (event))728 void StatsChartDialog::OnChartPng(wxCommandEvent & WXUNUSED(event))
729 {
730 // exporting the current Chart as PNG
731   int hsize;
732   int vsize;
733   int font_size;
734   if (ChartData.IsValid() != true)
735     return;
736   switch (SizeCtrl->GetSelection())
737     {
738       case 0:
739         hsize = 256;
740         vsize = 256;
741         font_size = 8;
742         break;
743       case 1:
744         hsize = 512;
745         vsize = 512;
746         font_size = 8;
747         break;
748       case 2:
749         hsize = 1024;
750         vsize = 1024;
751         font_size = 10;
752         break;
753       case 3:
754         hsize = 2048;
755         vsize = 2048;
756         font_size = 12;
757         break;
758       case 4:
759         hsize = 4196;
760         vsize = 4196;
761         font_size = 12;
762         break;
763     };
764 
765 // asking an export path
766   int ret;
767   wxString lastDir;
768   wxString fileList = wxT("PNG Image (*.png)|*.png");
769   wxFileDialog fileDialog(MainFrame, wxT("saving the current Chart as PNG"),
770                           wxT(""), wxT("ChartExport"), fileList,
771                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
772                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
773   lastDir = MainFrame->GetLastDirectory();
774   if (lastDir.Len() >= 1)
775     fileDialog.SetDirectory(lastDir);
776   ret = fileDialog.ShowModal();
777   if (ret == wxID_OK)
778     {
779       wxFileName file(fileDialog.GetPath());
780       lastDir = file.GetPath();
781       MainFrame->SetLastDirectory(lastDir);
782       wxString path = file.GetPath();
783       path += file.GetPathSeparator();
784       path += file.GetName();
785       path += wxT(".png");
786       ExportPath = path;
787   } else
788     return;
789 
790 
791 // exporting the Chart as PNG
792   if (ByInterval == true)
793     {
794       if (Histogram == true)
795         DoIntervalHistogram(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
796       if (LineChart == true)
797         DoIntervalLineChart(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
798       if (PieChart == true)
799         DoIntervalPieChart(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
800   } else
801     {
802       if (Histogram == true)
803         DoUniqueHistogram(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
804       if (LineChart == true)
805         DoUniqueLineChart(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
806       if (PieChart == true)
807         DoUniquePieChart(hsize, vsize, CHART_TARGET_IS_PNG, font_size);
808     }
809 }
810 
OnChartSvg(wxCommandEvent & WXUNUSED (event))811 void StatsChartDialog::OnChartSvg(wxCommandEvent & WXUNUSED(event))
812 {
813 // exporting the current Chart as SVG
814   int hsize;
815   int vsize;
816   int font_size;
817   if (ChartData.IsValid() != true)
818     return;
819   switch (SizeCtrl->GetSelection())
820     {
821       case 0:
822         hsize = 256;
823         vsize = 256;
824         font_size = 8;
825         break;
826       case 1:
827         hsize = 512;
828         vsize = 512;
829         font_size = 8;
830         break;
831       case 2:
832         hsize = 1024;
833         vsize = 1024;
834         font_size = 10;
835         break;
836       case 3:
837         hsize = 2048;
838         vsize = 2048;
839         font_size = 12;
840         break;
841       case 4:
842         hsize = 4196;
843         vsize = 4196;
844         font_size = 12;
845         break;
846     };
847 
848 // asking an export path
849   int ret;
850   wxString lastDir;
851   wxString fileList = wxT("SVG Vector Image (*.svg)|*.svg");
852   wxFileDialog fileDialog(MainFrame, wxT("saving the current Chart as SVG"),
853                           wxT(""), wxT("ChartExport"), fileList,
854                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
855                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
856   lastDir = MainFrame->GetLastDirectory();
857   if (lastDir.Len() >= 1)
858     fileDialog.SetDirectory(lastDir);
859   ret = fileDialog.ShowModal();
860   if (ret == wxID_OK)
861     {
862       wxFileName file(fileDialog.GetPath());
863       lastDir = file.GetPath();
864       MainFrame->SetLastDirectory(lastDir);
865       wxString path = file.GetPath();
866       path += file.GetPathSeparator();
867       path += file.GetName();
868       path += wxT(".svg");
869       ExportPath = path;
870   } else
871     return;
872 
873 
874 // exporting the Chart as SVG
875   if (ByInterval == true)
876     {
877       if (Histogram == true)
878         DoIntervalHistogram(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
879       if (LineChart == true)
880         DoIntervalLineChart(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
881       if (PieChart == true)
882         DoIntervalPieChart(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
883   } else
884     {
885       if (Histogram == true)
886         DoUniqueHistogram(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
887       if (LineChart == true)
888         DoUniqueLineChart(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
889       if (PieChart == true)
890         DoUniquePieChart(hsize, vsize, CHART_TARGET_IS_SVG, font_size);
891     };
892 }
893 
OnChartPdf(wxCommandEvent & WXUNUSED (event))894 void StatsChartDialog::OnChartPdf(wxCommandEvent & WXUNUSED(event))
895 {
896 // exporting the current Chart as PDF
897   int hsize = (int) (12.8 * 300.0);
898   int vsize = (int) (9.0 * 300.0);
899   hsize -= 100;                 // margin
900   vsize -= 100;                 // margin
901   if (ChartData.IsValid() != true)
902     return;
903 
904 // asking an export path
905   int ret;
906   wxString lastDir;
907   wxString fileList = wxT("PDF Document (*.pdf)|*.pdf");
908   wxFileDialog fileDialog(MainFrame, wxT("saving the current Chart as PDF"),
909                           wxT(""), wxT("ChartExport"), fileList,
910                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
911                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
912   lastDir = MainFrame->GetLastDirectory();
913   if (lastDir.Len() >= 1)
914     fileDialog.SetDirectory(lastDir);
915   ret = fileDialog.ShowModal();
916   if (ret == wxID_OK)
917     {
918       wxFileName file(fileDialog.GetPath());
919       lastDir = file.GetPath();
920       MainFrame->SetLastDirectory(lastDir);
921       wxString path = file.GetPath();
922       path += file.GetPathSeparator();
923       path += file.GetName();
924       path += wxT(".pdf");
925       ExportPath = path;
926   } else
927     return;
928 
929 
930 // exporting the Chart as PDF
931   if (ByInterval == true)
932     {
933       if (Histogram == true)
934         DoIntervalHistogram(hsize, vsize, CHART_TARGET_IS_PDF, 120);
935       if (LineChart == true)
936         DoIntervalLineChart(hsize, vsize, CHART_TARGET_IS_PDF, 120);
937       if (PieChart == true)
938         DoIntervalPieChart(hsize, vsize, CHART_TARGET_IS_PDF, 120);
939   } else
940     {
941       if (Histogram == true)
942         DoUniqueHistogram(hsize, vsize, CHART_TARGET_IS_PDF, 120);
943       if (LineChart == true)
944         DoUniqueLineChart(hsize, vsize, CHART_TARGET_IS_PDF, 120);
945       if (PieChart == true)
946         DoUniquePieChart(hsize, vsize, CHART_TARGET_IS_PDF, 120);
947     };
948 }
949 
PrepareDataByInterval(int classes)950 void StatsChartDialog::PrepareDataByInterval(int classes)
951 {
952 // feeding class data by intervals
953   char sql[4196];
954   char table[1024];
955   char column[1024];
956   int ret;
957   char err_msg[2048];
958   sqlite3_stmt *stmt;
959   sqlite3 *sqlite = MainFrame->GetSqlite();
960 
961   ChartData.Create(Min, Max, classes);
962 
963   strcpy(table, Table.ToUTF8());
964   strcpy(column, Column.ToUTF8());
965   MainFrame->DoubleQuotedSql(table);
966   MainFrame->DoubleQuotedSql(column);
967   sprintf(sql, "SELECT %s FROM %s", column, table);
968   ret = sqlite3_prepare_v2(sqlite, sql, strlen(sql), &stmt, NULL);
969   if (ret != SQLITE_OK)
970     {
971       sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(sqlite));
972       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
973                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
974       return;
975     }
976   while (1)
977     {
978       //
979       // fetching the result set rows
980       //
981       ret = sqlite3_step(stmt);
982       if (ret == SQLITE_DONE)
983         break;                  // end of result set
984       if (ret == SQLITE_ROW)
985         {
986           //
987           // fetching a row
988           //
989           double value;
990           if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER)
991             {
992               sqlite3_int64 intval = sqlite3_column_int64(stmt, 0);
993               value = intval;
994               ChartData.Add(value);
995             }
996           if (sqlite3_column_type(stmt, 0) == SQLITE_FLOAT)
997             {
998               value = sqlite3_column_double(stmt, 0);
999               ChartData.Add(value);
1000             }
1001       } else
1002         {
1003           sqlite3_finalize(stmt);
1004           sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(sqlite));
1005           wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
1006                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1007           return;
1008         }
1009     }
1010   sqlite3_finalize(stmt);
1011   ChartData.SetValid();
1012 }
1013 
PrepareDataByUniqueValue(int classes)1014 void StatsChartDialog::PrepareDataByUniqueValue(int classes)
1015 {
1016 // feeding class data by unique values
1017   char sql[4196];
1018   char table[1024];
1019   char column[1024];
1020   int ret;
1021   char err_msg[2048];
1022   sqlite3_stmt *stmt;
1023   sqlite3 *sqlite = MainFrame->GetSqlite();
1024   ChartData.Create(classes);
1025 
1026   strcpy(table, Table.ToUTF8());
1027   strcpy(column, Column.ToUTF8());
1028   MainFrame->DoubleQuotedSql(table);
1029   MainFrame->DoubleQuotedSql(column);
1030   sprintf(sql, "SELECT %s, Count(*) FROM %s GROUP BY %s", column, table,
1031           column);
1032   strcat(sql, " ORDER BY 2 DESC");
1033   ret = sqlite3_prepare_v2(sqlite, sql, strlen(sql), &stmt, NULL);
1034   if (ret != SQLITE_OK)
1035     {
1036       sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(sqlite));
1037       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
1038                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1039       return;
1040     }
1041   while (1)
1042     {
1043       //
1044       // fetching the result set rows
1045       //
1046       ret = sqlite3_step(stmt);
1047       if (ret == SQLITE_DONE)
1048         break;                  // end of result set
1049       if (ret == SQLITE_ROW)
1050         {
1051           //
1052           // fetching a row
1053           //
1054           bool valid = false;
1055           wxString value;
1056           char dummy[128];
1057           if (sqlite3_column_type(stmt, 0) == SQLITE_INTEGER)
1058             {
1059               sqlite3_int64 intval = sqlite3_column_int64(stmt, 0);
1060               sprintf(dummy, FORMAT_64, intval);
1061               value = wxString::FromUTF8(dummy);
1062               valid = true;
1063             }
1064           if (sqlite3_column_type(stmt, 0) == SQLITE_FLOAT)
1065             {
1066               double dblval = sqlite3_column_double(stmt, 0);
1067               sprintf(dummy, "%1.18f", dblval);
1068               CleanDecimals(dummy);
1069               value = wxString::FromUTF8(dummy);
1070               valid = true;
1071             }
1072           if (sqlite3_column_type(stmt, 0) == SQLITE_TEXT)
1073             {
1074               const char *txtval = (const char *) sqlite3_column_text(stmt, 0);
1075               value = wxString::FromUTF8(txtval);
1076               valid = true;
1077             }
1078           if (valid == true)
1079             {
1080               int count = sqlite3_column_int(stmt, 1);
1081               ChartData.Add(value, count);
1082             }
1083 
1084       } else
1085         {
1086           sqlite3_finalize(stmt);
1087           sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(sqlite));
1088           wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
1089                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1090           return;
1091         }
1092     }
1093   sqlite3_finalize(stmt);
1094   ChartData.SetValid();
1095 }
1096 
DoIntervalHistogram(int hsize,int vsize,int target,int font_size)1097 void StatsChartDialog::DoIntervalHistogram(int hsize, int vsize, int target,
1098                                            int font_size)
1099 {
1100 // generating an Histogram (Interval values)
1101   unsigned char *rgb_array = NULL;
1102   const void *gr = NULL;
1103   const void *font = NULL;
1104   const void *font_big = NULL;
1105   int idx;
1106   int start_x;
1107   int end_x;
1108   int start_y;
1109   int end_y;
1110   double base_x;
1111   double step_x;
1112   double base_y;
1113   double vspan;
1114   double height;
1115   char title[1024];
1116   char text[1024];
1117   char table[1024];
1118   char column[1024];
1119   double txtWidth;
1120   double txtHeight;
1121   double titleHeight;
1122   double pre_x;
1123   double pre_y;
1124   double post_x;
1125   double post_y;
1126   int title_x;
1127   int title_y;
1128   double labelWidth = 0.0;
1129   double labelBase;
1130   double labelStep;
1131   wxColour colors[8];
1132   int color_idx;
1133   MyChartScaleLabels scaleLabels;
1134   MyChartScaleLabel *pLab;
1135   double scaleWidth = 0.0;
1136 
1137 // color palette
1138   colors[0] = wxColour(255, 255, 240);
1139   colors[1] = wxColour(255, 240, 255);
1140   colors[2] = wxColour(240, 255, 255);
1141   colors[3] = wxColour(240, 240, 240);
1142   colors[4] = wxColour(255, 192, 192);
1143   colors[5] = wxColour(192, 255, 192);
1144   colors[6] = wxColour(192, 192, 255);
1145   colors[7] = wxColour(192, 192, 192);
1146 
1147 // graphics initialization
1148   if (target == CHART_TARGET_IS_SVG)
1149     {
1150       char xpath[2024];
1151       strcpy(xpath, ExportPath.ToUTF8());
1152       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
1153   } else if (target == CHART_TARGET_IS_PDF)
1154     {
1155       char xpath[2024];
1156       strcpy(xpath, ExportPath.ToUTF8());
1157       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
1158                              &gr);
1159   } else
1160     gGraphCreateContext(hsize, vsize, &gr);
1161 
1162 // background initialization
1163   gGraphSetBrush(gr, 255, 255, 255, 255);
1164   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
1165 
1166 // font setup
1167   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
1168                    &font);
1169   gGraphFontSetColor(font, 0, 0, 0, 255);
1170   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
1171                    &font_big);
1172   gGraphFontSetColor(font_big, 0, 0, 0, 255);
1173 
1174 // computing TEXT sizes
1175   strcpy(table, Table.ToUTF8());
1176   strcpy(column, Column.ToUTF8());
1177   MainFrame->DoubleQuotedSql(table);
1178   MainFrame->DoubleQuotedSql(column);
1179   sprintf(title, "Dataset: %s.%s     [interval values]", table, column);
1180   gGraphSetFont(gr, font_big);
1181   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
1182                       &post_x, &post_y);
1183   title_x = (hsize - (int) txtWidth) / 2;
1184   title_y = 5 + (int) titleHeight;
1185 // measuring class labels
1186   gGraphSetFont(gr, font);
1187   sprintf(text, "%1.4f", Min);
1188   CleanDecimals(text);
1189   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1190                       &post_y);
1191   labelWidth = txtWidth;
1192   sprintf(text, "%1.4f", Min + ((Max - Min) / 4.0));
1193   CleanDecimals(text);
1194   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1195                       &post_y);
1196   if (txtWidth > labelWidth)
1197     labelWidth = txtWidth;
1198   sprintf(text, "%1.4f", Min + ((Max - Min) / 2.0));
1199   CleanDecimals(text);
1200   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1201                       &post_y);
1202   if (txtWidth > labelWidth)
1203     labelWidth = txtWidth;
1204   sprintf(text, "%1.4f", Min + (((Max - Min) / 4.0) * 3.0));
1205   CleanDecimals(text);
1206   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1207                       &post_y);
1208   if (txtWidth > labelWidth)
1209     labelWidth = txtWidth;
1210   sprintf(text, "%1.4f", Max);
1211   CleanDecimals(text);
1212   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1213                       &post_y);
1214   if (txtWidth > labelWidth)
1215     labelWidth = txtWidth;
1216 
1217   start_y = vsize - 10 - (int) labelWidth;
1218   end_y = 10 + (int) titleHeight;
1219   vspan = start_y - end_y;
1220   base_y = start_y;
1221 
1222 // building and measuring  the 'scale' labels
1223   scaleLabels.Initialize(vspan, ChartData.GetMaxFreq());
1224   pLab = scaleLabels.GetFirst();
1225   while (pLab)
1226     {
1227       gGraphSetFont(gr, font);
1228       strcpy(text, pLab->GetLabel().ToUTF8());
1229       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1230                           &post_x, &post_y);
1231       if (txtWidth > scaleWidth)
1232         scaleWidth = txtWidth;
1233       pLab = pLab->GetNext();
1234     }
1235 
1236   start_x = 10 + (int) scaleWidth;
1237   end_x = hsize - 10;
1238   base_x = start_x;
1239   step_x = (double) (end_x - start_x) / (double) (ChartData.GetNumClasses());
1240   labelBase = base_x + (step_x / 2.0);
1241   labelStep = (end_x - start_x - step_x) / 4;
1242 
1243 // title output
1244   gGraphSetFont(gr, font_big);
1245   gGraphDrawText(gr, title, title_x, title_y, 0.0);
1246 // class labels output
1247   gGraphSetFont(gr, font);
1248   sprintf(text, "%1.4f", Min);
1249   CleanDecimals(text);
1250   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1251                       &post_y);
1252   gGraphDrawText(gr, text, labelBase + txtHeight,
1253                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1254   labelBase += labelStep;
1255   sprintf(text, "%1.4f", Min + ((Max - Min) / 4.0));
1256   CleanDecimals(text);
1257   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1258                       &post_y);
1259   gGraphDrawText(gr, text, labelBase + txtHeight,
1260                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1261   labelBase += labelStep;
1262   sprintf(text, "%1.4f", Min + ((Max - Min) / 2.0));
1263   CleanDecimals(text);
1264   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1265                       &post_y);
1266   gGraphDrawText(gr, text, labelBase + txtHeight,
1267                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1268   labelBase += labelStep;
1269   sprintf(text, "%1.4f", Min + (((Max - Min) / 4.0) * 3.0));
1270   CleanDecimals(text);
1271   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1272                       &post_y);
1273   gGraphDrawText(gr, text, labelBase + txtHeight,
1274                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1275   labelBase += labelStep;
1276   sprintf(text, "%1.4f", Max);
1277   CleanDecimals(text);
1278   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1279                       &post_y);
1280   gGraphDrawText(gr, text, labelBase + txtHeight,
1281                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1282 
1283   for (idx = 0; idx < ChartData.GetNumClasses(); idx++)
1284     {
1285       // drawing bars
1286       MyChartIntervalClass *p = ChartData.GetClass(idx);
1287       gGraphSetPen(gr, 0, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
1288       color_idx = idx % 8;
1289       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
1290                      colors[color_idx].Blue(), 255);
1291       height =
1292         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
1293       gGraphDrawRectangle(gr, base_x, base_y - height, step_x, height);
1294       base_x += step_x;
1295     }
1296 // drawing 'scale' labels
1297   pLab = scaleLabels.GetFirst();
1298   while (pLab)
1299     {
1300       gGraphSetFont(gr, font);
1301       strcpy(text, pLab->GetLabel().ToUTF8());
1302       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1303                           &post_x, &post_y);
1304       gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
1305                      base_y - pLab->GetPosition() + (txtHeight / 2.0), 0.0);
1306       gGraphSetPen(gr, 255, 128, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
1307       gGraphStrokeLine(gr, start_x, base_y - pLab->GetPosition(), end_x,
1308                        base_y - pLab->GetPosition());
1309       pLab = pLab->GetNext();
1310     }
1311 // marking the ZERO baseline
1312   gGraphSetFont(gr, font);
1313   strcpy(text, "0");
1314   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1315                       &post_y);
1316   gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
1317                  base_y + (txtHeight / 2.0), 0.0);
1318   gGraphSetPen(gr, 255, 128, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
1319   gGraphStrokeLine(gr, start_x, base_y, end_x, base_y);
1320 
1321 // graphics finalization
1322   gGraphDestroyFont(font);
1323   gGraphDestroyFont(font_big);
1324   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
1325       || target == CHART_TARGET_IS_PREVIEW)
1326     gGraphGetContextRgbArray(gr, &rgb_array);
1327   if (target == CHART_TARGET_IS_SVG)
1328     gGraphDestroySvgContext(gr);
1329   else if (target == CHART_TARGET_IS_PDF)
1330     gGraphDestroyPdfContext(gr);
1331   else
1332     gGraphDestroyContext(gr);
1333 
1334   if (target == CHART_TARGET_IS_PNG)
1335     {
1336       if (rgb_array)
1337         {
1338           // creating the Image from RGB array
1339           const void *img =
1340             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
1341           if (img)
1342             {
1343               char xpath[2024];
1344               strcpy(xpath, ExportPath.ToUTF8());
1345               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
1346                 {
1347                   wxString msg =
1348                     wxT
1349                     ("An error occurred while saving\nthe current Char as PNG");
1350                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1351                                MainFrame);
1352                 }
1353               gGraphDestroyImage(img);
1354             }
1355         }
1356     }
1357   if (target == CHART_TARGET_IS_PREVIEW)
1358     {
1359       if (rgb_array)
1360         {
1361           // creating the Image from RGB array
1362           wxImage img(hsize, vsize);
1363           img.SetData(rgb_array);
1364           wxBitmap bmp(img);
1365           ChartShow->SetBitmap(bmp);
1366         }
1367     }
1368   if (target == CHART_TARGET_IS_COPY)
1369     {
1370       if (rgb_array)
1371         {
1372           // creating the Image from RGB array
1373           wxImage img(hsize, vsize);
1374           img.SetData(rgb_array);
1375           if (wxTheClipboard->Open())
1376             {
1377               wxTheClipboard->SetData(new wxBitmapDataObject(img));
1378               wxTheClipboard->Close();
1379             }
1380         }
1381     }
1382 }
1383 
DoIntervalLineChart(int hsize,int vsize,int target,int font_size)1384 void StatsChartDialog::DoIntervalLineChart(int hsize, int vsize, int target,
1385                                            int font_size)
1386 {
1387 // generating a Line Chart (Interval values)
1388   unsigned char *rgb_array = NULL;
1389   const void *gr = NULL;
1390   const void *font = NULL;
1391   const void *font_big = NULL;
1392   int idx;
1393   int start_x;
1394   int end_x;
1395   int start_y;
1396   int end_y;
1397   double base_x;
1398   double step_x;
1399   double base_y;
1400   double vspan;
1401   double height;
1402   char title[1024];
1403   char table[1024];
1404   char column[1024];
1405   char text[1024];
1406   double txtWidth;
1407   double txtHeight;
1408   double titleHeight;
1409   double pre_x;
1410   double pre_y;
1411   double post_x;
1412   double post_y;
1413   int title_x;
1414   int title_y;
1415   double labelWidth = 0.0;
1416   double labelBase;
1417   double labelStep;
1418   MyChartScaleLabels scaleLabels;
1419   MyChartScaleLabel *pLab;
1420   double scaleWidth = 0.0;
1421 
1422 // graphics initialization
1423   if (target == CHART_TARGET_IS_SVG)
1424     {
1425       char xpath[2024];
1426       strcpy(xpath, ExportPath.ToUTF8());
1427       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
1428   } else if (target == CHART_TARGET_IS_PDF)
1429     {
1430       char xpath[2024];
1431       strcpy(xpath, ExportPath.ToUTF8());
1432       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
1433                              &gr);
1434   } else
1435     gGraphCreateContext(hsize, vsize, &gr);
1436 
1437 // background initialization
1438   gGraphSetBrush(gr, 255, 255, 255, 255);
1439   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
1440 
1441 // font setup
1442   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
1443                    &font);
1444   gGraphFontSetColor(font, 0, 0, 0, 255);
1445   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
1446                    &font_big);
1447   gGraphFontSetColor(font_big, 0, 0, 0, 255);
1448 
1449 // computing TEXT sizes
1450   strcpy(table, Table.ToUTF8());
1451   strcpy(column, Column.ToUTF8());
1452   MainFrame->DoubleQuotedSql(table);
1453   MainFrame->DoubleQuotedSql(column);
1454   sprintf(title, "Dataset: %s.%s     [interval values]", table, column);
1455   gGraphSetFont(gr, font_big);
1456   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
1457                       &post_x, &post_y);
1458   title_x = (hsize - (int) txtWidth) / 2;
1459   title_y = 5 + (int) titleHeight;
1460 // measuring class labels
1461   gGraphSetFont(gr, font);
1462   sprintf(text, "%1.4f", Min);
1463   CleanDecimals(text);
1464   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1465                       &post_y);
1466   labelWidth = txtWidth;
1467   sprintf(text, "%1.4f", Min + ((Max - Min) / 4.0));
1468   CleanDecimals(text);
1469   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1470                       &post_y);
1471   if (txtWidth > labelWidth)
1472     labelWidth = txtWidth;
1473   sprintf(text, "%1.4f", Min + ((Max - Min) / 2.0));
1474   CleanDecimals(text);
1475   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1476                       &post_y);
1477   if (txtWidth > labelWidth)
1478     labelWidth = txtWidth;
1479   sprintf(text, "%1.4f", Min + (((Max - Min) / 4.0) * 3.0));
1480   CleanDecimals(text);
1481   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1482                       &post_y);
1483   if (txtWidth > labelWidth)
1484     labelWidth = txtWidth;
1485   sprintf(text, "%1.4f", Max);
1486   CleanDecimals(text);
1487   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1488                       &post_y);
1489   if (txtWidth > labelWidth)
1490     labelWidth = txtWidth;
1491 
1492   start_y = vsize - 10 - (int) labelWidth;
1493   end_y = 10 + (int) titleHeight;
1494   vspan = start_y - end_y;
1495   base_y = start_y;
1496 
1497 // building and measuring  the 'scale' labels
1498   scaleLabels.Initialize(vspan, ChartData.GetMaxFreq());
1499   pLab = scaleLabels.GetFirst();
1500   while (pLab)
1501     {
1502       gGraphSetFont(gr, font);
1503       strcpy(text, pLab->GetLabel().ToUTF8());
1504       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1505                           &post_x, &post_y);
1506       if (txtWidth > scaleWidth)
1507         scaleWidth = txtWidth;
1508       pLab = pLab->GetNext();
1509     }
1510 
1511   start_x = 10 + (int) scaleWidth;
1512   end_x = hsize - 10;
1513   base_x = start_x;
1514   step_x = (double) (end_x - start_x) / (double) (ChartData.GetNumClasses());
1515   labelBase = base_x + (step_x / 2.0);
1516   labelStep = (end_x - start_x - step_x) / 4;
1517 
1518 // title output
1519   gGraphSetFont(gr, font_big);
1520   gGraphDrawText(gr, title, title_x, title_y, 0.0);
1521 // class labels output
1522   gGraphSetFont(gr, font);
1523   sprintf(text, "%1.4f", Min);
1524   CleanDecimals(text);
1525   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1526                       &post_y);
1527   gGraphDrawText(gr, text, labelBase + txtHeight,
1528                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1529   labelBase += labelStep;
1530   sprintf(text, "%1.4f", Min + ((Max - Min) / 4.0));
1531   CleanDecimals(text);
1532   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1533                       &post_y);
1534   gGraphDrawText(gr, text, labelBase + txtHeight,
1535                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1536   labelBase += labelStep;
1537   sprintf(text, "%1.4f", Min + ((Max - Min) / 2.0));
1538   CleanDecimals(text);
1539   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1540                       &post_y);
1541   gGraphDrawText(gr, text, labelBase + txtHeight,
1542                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1543   labelBase += labelStep;
1544   sprintf(text, "%1.4f", Min + (((Max - Min) / 4.0) * 3.0));
1545   CleanDecimals(text);
1546   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1547                       &post_y);
1548   gGraphDrawText(gr, text, labelBase + txtHeight,
1549                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1550   labelBase += labelStep;
1551   sprintf(text, "%1.4f", Max);
1552   CleanDecimals(text);
1553   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1554                       &post_y);
1555   gGraphDrawText(gr, text, labelBase + txtHeight,
1556                  vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
1557 
1558   for (idx = 0; idx < ChartData.GetNumClasses(); idx++)
1559     {
1560       MyChartIntervalClass *p = ChartData.GetClass(idx);
1561       height =
1562         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
1563       gGraphSetPen(gr, 192, 192, 192, 255, 1, GGRAPH_PENSTYLE_DOT);
1564       gGraphStrokeLine(gr, base_x + (step_x / 2.0), start_y,
1565                        base_x + (step_x / 2.0), base_y - height);
1566       base_x += step_x;
1567     }
1568   base_x = start_x;
1569   for (idx = 0; idx < ChartData.GetNumClasses(); idx++)
1570     {
1571       MyChartIntervalClass *p = ChartData.GetClass(idx);
1572       height =
1573         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
1574       if (idx == 0)
1575         gGraphMoveToPoint(gr, base_x + (step_x / 2.0), base_y - height);
1576       else
1577         gGraphAddLineToPath(gr, base_x + (step_x / 2.0), base_y - height);
1578       base_x += step_x;
1579     }
1580   gGraphSetPen(gr, 255, 0, 0, 255, 2, GGRAPH_PENSTYLE_SOLID);
1581   gGraphStrokePath(gr, GGRAPH_CLEAR_PATH);
1582 
1583 // drawing 'scale' labels
1584   pLab = scaleLabels.GetFirst();
1585   while (pLab)
1586     {
1587       gGraphSetFont(gr, font);
1588       strcpy(text, pLab->GetLabel().ToUTF8());
1589       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1590                           &post_x, &post_y);
1591       gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
1592                      base_y - pLab->GetPosition() + (txtHeight / 2.0), 0.0);
1593       gGraphSetPen(gr, 128, 255, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
1594       gGraphStrokeLine(gr, start_x, base_y - pLab->GetPosition(), end_x,
1595                        base_y - pLab->GetPosition());
1596       pLab = pLab->GetNext();
1597     }
1598 // marking the ZERO baseline
1599   gGraphSetFont(gr, font);
1600   strcpy(text, "0");
1601   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
1602                       &post_y);
1603   gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
1604                  base_y + (txtHeight / 2.0), 0.0);
1605   gGraphSetPen(gr, 128, 255, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
1606   gGraphStrokeLine(gr, start_x, base_y, end_x, base_y);
1607 
1608 // graphics finalization
1609   gGraphDestroyFont(font);
1610   gGraphDestroyFont(font_big);
1611   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
1612       || target == CHART_TARGET_IS_PREVIEW)
1613     gGraphGetContextRgbArray(gr, &rgb_array);
1614   if (target == CHART_TARGET_IS_SVG)
1615     gGraphDestroySvgContext(gr);
1616   else if (target == CHART_TARGET_IS_PDF)
1617     gGraphDestroyPdfContext(gr);
1618   else
1619     gGraphDestroyContext(gr);
1620 
1621   if (target == CHART_TARGET_IS_PNG)
1622     {
1623       if (rgb_array)
1624         {
1625           // creating the Image from RGB array
1626           const void *img =
1627             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
1628           if (img)
1629             {
1630               char xpath[2024];
1631               strcpy(xpath, ExportPath.ToUTF8());
1632               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
1633                 {
1634                   wxString msg =
1635                     wxT
1636                     ("An error occurred while saving\nthe current Char as PNG");
1637                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1638                                MainFrame);
1639                 }
1640               gGraphDestroyImage(img);
1641             }
1642         }
1643     }
1644   if (target == CHART_TARGET_IS_PREVIEW)
1645     {
1646       if (rgb_array)
1647         {
1648           // creating the Image from RGB array
1649           wxImage img(hsize, vsize);
1650           img.SetData(rgb_array);
1651           wxBitmap bmp(img);
1652           ChartShow->SetBitmap(bmp);
1653         }
1654     }
1655   if (target == CHART_TARGET_IS_COPY)
1656     {
1657       if (rgb_array)
1658         {
1659           // creating the Image from RGB array
1660           wxImage img(hsize, vsize);
1661           img.SetData(rgb_array);
1662           if (wxTheClipboard->Open())
1663             {
1664               wxTheClipboard->SetData(new wxBitmapDataObject(img));
1665               wxTheClipboard->Close();
1666             }
1667         }
1668     }
1669 }
1670 
DoIntervalPieChart(int hsize,int vsize,int target,int font_size)1671 void StatsChartDialog::DoIntervalPieChart(int hsize, int vsize, int target,
1672                                           int font_size)
1673 {
1674 // generating a Pie Chart (Interval values)
1675   unsigned char *rgb_array = NULL;
1676   const void *gr = NULL;
1677   const void *font = NULL;
1678   const void *font_big = NULL;
1679   int idx;
1680   double radius_x;
1681   double radius_y;
1682   double radius;
1683   double cx;
1684   double cy;
1685   double from;
1686   double step;
1687   char title[1024];
1688   char table[1024];
1689   char column[1024];
1690   double txtWidth;
1691   double txtHeight;
1692   double titleHeight;
1693   double pre_x;
1694   double pre_y;
1695   double post_x;
1696   double post_y;
1697   int title_x;
1698   int title_y;
1699   wxColour colors[8];
1700   int color_idx;
1701   MyPieChartLabels labels;
1702   MyPieChartLabel *pLab;
1703   char text[1024];
1704   double lx;
1705   double ly;
1706   double base_y;
1707   double step_y;
1708   double labelWidth = 0.0;
1709 
1710 // color palette
1711   colors[0] = wxColour(255, 255, 240);
1712   colors[1] = wxColour(255, 240, 255);
1713   colors[2] = wxColour(240, 255, 255);
1714   colors[3] = wxColour(240, 240, 240);
1715   colors[4] = wxColour(255, 192, 192);
1716   colors[5] = wxColour(192, 255, 192);
1717   colors[6] = wxColour(192, 192, 255);
1718   colors[7] = wxColour(192, 192, 192);
1719 
1720 // graphics initialization
1721   if (target == CHART_TARGET_IS_SVG)
1722     {
1723       char xpath[2024];
1724       strcpy(xpath, ExportPath.ToUTF8());
1725       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
1726   } else if (target == CHART_TARGET_IS_PDF)
1727     {
1728       char xpath[2024];
1729       strcpy(xpath, ExportPath.ToUTF8());
1730       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
1731                              &gr);
1732   } else
1733     gGraphCreateContext(hsize, vsize, &gr);
1734 
1735 // background initialization
1736   gGraphSetBrush(gr, 255, 255, 255, 255);
1737   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
1738 
1739 // font setup
1740   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
1741                    &font);
1742   gGraphFontSetColor(font, 0, 0, 0, 255);
1743   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
1744                    &font_big);
1745   gGraphFontSetColor(font_big, 0, 0, 0, 255);
1746 
1747 // computing TEXT sizes
1748   strcpy(table, Table.ToUTF8());
1749   strcpy(column, Column.ToUTF8());
1750   MainFrame->DoubleQuotedSql(table);
1751   MainFrame->DoubleQuotedSql(column);
1752   sprintf(title, "Dataset: %s.%s     [interval values]", table, column);
1753   gGraphSetFont(gr, font_big);
1754   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
1755                       &post_x, &post_y);
1756   title_x = (hsize - (int) txtWidth) / 2;
1757   title_y = 5 + (int) titleHeight;
1758   for (idx = 0; idx < ChartData.GetNumClasses(); idx++)
1759     {
1760       // measuring labels
1761       MyChartIntervalClass *p = ChartData.GetClass(idx);
1762       gGraphSetFont(gr, font);
1763       sprintf(text, "%1.4f", p->GetMin() + ((p->GetMax() - p->GetMin()) / 2.0));
1764       CleanDecimals(text);
1765       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1766                           &post_x, &post_y);
1767       if (txtWidth > labelWidth)
1768         labelWidth = txtWidth;
1769     }
1770 
1771   cx = (double) hsize / 2.0;
1772   cy = (double) vsize / 2.0;
1773   cy += (double) (titleHeight + 10) / 2.0;
1774   radius_x = (double) (hsize - 20) / 2.0;
1775   radius_x -= labelWidth + 10;
1776   radius_y = (double) (vsize - titleHeight - 20) / 2.0;
1777   if (radius_x <= radius_y)
1778     radius = radius_x;
1779   else
1780     radius = radius_y;
1781 
1782 // title output
1783   gGraphSetFont(gr, font_big);
1784   gGraphDrawText(gr, title, title_x, title_y, 0.0);
1785 
1786   from = 0.0;
1787   for (idx = 0; idx < ChartData.GetNumClasses(); idx++)
1788     {
1789       MyChartIntervalClass *p = ChartData.GetClass(idx);
1790       gGraphSetPen(gr, 0, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
1791       color_idx = idx % 8;
1792       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
1793                      colors[color_idx].Blue(), 255);
1794       step =
1795         (M_PI * 2.0) *
1796         ((double) (p->GetCount() / (double) (ChartData.GetTotFreq())));
1797       gGraphDrawCircleSector(gr, cx, cy, radius, from, from + step);
1798       sprintf(text, "%1.4f", p->GetMin() + ((p->GetMax() - p->GetMin()) / 2.0));
1799       CleanDecimals(text);
1800       lx = cx + (radius * 0.90) * cos(from + (step / 2.0));
1801       ly = cy + (radius * 0.90) * sin(from + (step / 2.0));
1802       labels.Add(text, lx, ly);
1803       from += step;
1804     }
1805 // printing class labels
1806   labels.Sort(cx);
1807   step_y = (double) (vsize - 50) / (double) (labels.GetNumLeftLabels() - 1);
1808   base_y = 25.0;
1809   for (idx = 0; idx < labels.GetNumLeftLabels(); idx++)
1810     {
1811       // printing Left labels
1812       pLab = labels.GetLeftLabel(idx);
1813       strcpy(text, pLab->GetLabel().ToUTF8());
1814       gGraphSetFont(gr, font);
1815       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1816                           &post_x, &post_y);
1817       gGraphDrawText(gr, text, 10, base_y + (txtHeight / 2.0), 0.0);
1818       gGraphSetPen(gr, 255, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
1819       gGraphStrokeLine(gr, 10 + txtWidth, base_y, pLab->GetX(), pLab->GetY());
1820       base_y += step_y;
1821     }
1822   step_y = (double) (vsize - 50) / (double) (labels.GetNumRightLabels() - 1);
1823   base_y = 25.0;
1824   for (idx = 0; idx < labels.GetNumRightLabels(); idx++)
1825     {
1826       // printing Right labels
1827       pLab = labels.GetRightLabel(idx);
1828       strcpy(text, pLab->GetLabel().ToUTF8());
1829       gGraphSetFont(gr, font);
1830       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
1831                           &post_x, &post_y);
1832       gGraphDrawText(gr, text, hsize - txtWidth - 10,
1833                      base_y + (txtHeight / 2.0), 0.0);
1834       gGraphSetPen(gr, 255, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
1835       gGraphStrokeLine(gr, hsize - txtWidth - 10, base_y, pLab->GetX(),
1836                        pLab->GetY());
1837       base_y += step_y;
1838     }
1839 
1840 // graphics finalization
1841   gGraphDestroyFont(font);
1842   gGraphDestroyFont(font_big);
1843   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
1844       || target == CHART_TARGET_IS_PREVIEW)
1845     gGraphGetContextRgbArray(gr, &rgb_array);
1846   if (target == CHART_TARGET_IS_SVG)
1847     gGraphDestroySvgContext(gr);
1848   else if (target == CHART_TARGET_IS_PDF)
1849     gGraphDestroyPdfContext(gr);
1850   else
1851     gGraphDestroyContext(gr);
1852 
1853   if (target == CHART_TARGET_IS_PNG)
1854     {
1855       if (rgb_array)
1856         {
1857           // creating the Image from RGB array
1858           const void *img =
1859             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
1860           if (img)
1861             {
1862               char xpath[2024];
1863               strcpy(xpath, ExportPath.ToUTF8());
1864               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
1865                 {
1866                   wxString msg =
1867                     wxT
1868                     ("An error occurred while saving\nthe current Char as PNG");
1869                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
1870                                MainFrame);
1871                 }
1872               gGraphDestroyImage(img);
1873             }
1874         }
1875     }
1876   if (target == CHART_TARGET_IS_PREVIEW)
1877     {
1878       if (rgb_array)
1879         {
1880           // creating the Image from RGB array
1881           wxImage img(hsize, vsize);
1882           img.SetData(rgb_array);
1883           wxBitmap bmp(img);
1884           ChartShow->SetBitmap(bmp);
1885         }
1886     }
1887   if (target == CHART_TARGET_IS_COPY)
1888     {
1889       if (rgb_array)
1890         {
1891           // creating the Image from RGB array
1892           wxImage img(hsize, vsize);
1893           img.SetData(rgb_array);
1894           if (wxTheClipboard->Open())
1895             {
1896               wxTheClipboard->SetData(new wxBitmapDataObject(img));
1897               wxTheClipboard->Close();
1898             }
1899         }
1900     }
1901 }
1902 
DoUniqueHistogram(int hsize,int vsize,int target,int font_size)1903 void StatsChartDialog::DoUniqueHistogram(int hsize, int vsize, int target,
1904                                          int font_size)
1905 {
1906 // generating an Histogram (Unique values)
1907   unsigned char *rgb_array = NULL;
1908   const void *gr = NULL;
1909   const void *font = NULL;
1910   const void *font_big = NULL;
1911   int idx;
1912   MyChartUniqueClass *p;
1913   int start_x;
1914   int end_x;
1915   int start_y;
1916   int end_y;
1917   double base_x;
1918   double step_x;
1919   double base_y;
1920   double vspan;
1921   double height;
1922   char title[1024];
1923   char table[1024];
1924   char column[1024];
1925   char text[1024];
1926   double txtWidth;
1927   double txtHeight;
1928   double titleHeight;
1929   double pre_x;
1930   double pre_y;
1931   double post_x;
1932   double post_y;
1933   int title_x;
1934   int title_y;
1935   double labelWidth = 0.0;
1936   int others = 0;
1937   wxColour colors[8];
1938   int color_idx;
1939   MyChartScaleLabels scaleLabels;
1940   MyChartScaleLabel *pLab;
1941   double scaleWidth = 0.0;
1942 
1943 // color palette
1944   colors[0] = wxColour(255, 255, 240);
1945   colors[1] = wxColour(255, 240, 255);
1946   colors[2] = wxColour(240, 255, 255);
1947   colors[3] = wxColour(240, 240, 240);
1948   colors[4] = wxColour(255, 192, 192);
1949   colors[5] = wxColour(192, 255, 192);
1950   colors[6] = wxColour(192, 192, 255);
1951   colors[7] = wxColour(192, 192, 192);
1952 
1953 // graphics initialization
1954   if (target == CHART_TARGET_IS_SVG)
1955     {
1956       char xpath[2024];
1957       strcpy(xpath, ExportPath.ToUTF8());
1958       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
1959   } else if (target == CHART_TARGET_IS_PDF)
1960     {
1961       char xpath[2024];
1962       strcpy(xpath, ExportPath.ToUTF8());
1963       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
1964                              &gr);
1965   } else
1966     gGraphCreateContext(hsize, vsize, &gr);
1967 
1968 // background initialization
1969   gGraphSetBrush(gr, 255, 255, 255, 255);
1970   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
1971 
1972 // font setup
1973   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
1974                    &font);
1975   gGraphFontSetColor(font, 0, 0, 0, 255);
1976   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
1977                    &font_big);
1978   gGraphFontSetColor(font_big, 0, 0, 0, 255);
1979 
1980   if (ChartData.GetOtherUniquesFreq() > 0)
1981     others = 1;
1982 // computing TEXT sizes
1983   strcpy(table, Table.ToUTF8());
1984   strcpy(column, Column.ToUTF8());
1985   MainFrame->DoubleQuotedSql(table);
1986   MainFrame->DoubleQuotedSql(column);
1987   sprintf(title, "Dataset: %s.%s     [unique values]", table, column);
1988   gGraphSetFont(gr, font_big);
1989   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
1990                       &post_x, &post_y);
1991   title_x = (hsize - (int) txtWidth) / 2;
1992   title_y = 5 + (int) titleHeight;
1993 // measuring class labels
1994   p = ChartData.GetFirst();
1995   while (p)
1996     {
1997       gGraphSetFont(gr, font);
1998       strcpy(text, p->GetValue().ToUTF8());
1999       if (strlen(text) > 10)
2000         {
2001           text[10] = '.';
2002           text[11] = '.';
2003           text[12] = '\0';      // truncating to max 10 chars
2004         }
2005       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2006                           &post_x, &post_y);
2007       if (txtWidth > labelWidth)
2008         labelWidth = txtWidth;
2009       p = p->GetNext();
2010     }
2011   if (others)
2012     {
2013       // including the 'any other' class
2014       gGraphSetFont(gr, font);
2015       gGraphGetTextExtent(gr, "AnyOther", &pre_x, &pre_y, &txtWidth, &txtHeight,
2016                           &post_x, &post_y);
2017       if (txtWidth > labelWidth)
2018         labelWidth = txtWidth;
2019     }
2020 
2021   start_y = vsize - 10 - (int) labelWidth;
2022   end_y = 10 + (int) titleHeight;
2023   vspan = start_y - end_y;
2024   base_y = start_y;
2025 
2026 // building and measuring  the 'scale' labels
2027   scaleLabels.Initialize(vspan, ChartData.GetMaxFreq());
2028   pLab = scaleLabels.GetFirst();
2029   while (pLab)
2030     {
2031       gGraphSetFont(gr, font);
2032       strcpy(text, pLab->GetLabel().ToUTF8());
2033       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2034                           &post_x, &post_y);
2035       if (txtWidth > scaleWidth)
2036         scaleWidth = txtWidth;
2037       pLab = pLab->GetNext();
2038     }
2039 
2040   start_x = 10 + (int) scaleWidth;
2041   end_x = hsize - 10;
2042   base_x = start_x;
2043   step_x =
2044     (double) (end_x - start_x) / (double) (ChartData.GetNumClasses() + others);
2045 
2046 // title output
2047   gGraphSetFont(gr, font_big);
2048   gGraphDrawText(gr, title, title_x, title_y, 0.0);
2049 // class labels output
2050   p = ChartData.GetFirst();
2051   while (p)
2052     {
2053       gGraphSetFont(gr, font);
2054       strcpy(text, p->GetValue().ToUTF8());
2055       if (strlen(text) > 10)
2056         {
2057           text[10] = '.';
2058           text[11] = '.';
2059           text[12] = '\0';      // truncating to max 10 chars
2060         }
2061       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2062                           &post_x, &post_y);
2063       gGraphDrawText(gr, text, base_x + (txtHeight / 2.0) + (step_x / 2.0),
2064                      vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
2065       base_x += step_x;
2066       p = p->GetNext();
2067     }
2068   if (others)
2069     {
2070       // including the 'any other' class
2071       gGraphSetFont(gr, font);
2072       gGraphGetTextExtent(gr, "AnyOther", &pre_x, &pre_y, &txtWidth, &txtHeight,
2073                           &post_x, &post_y);
2074       gGraphDrawText(gr, "AnyOther",
2075                      base_x + (txtHeight / 2.0) + (step_x / 2.0),
2076                      vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
2077     }
2078 
2079   idx = 0;
2080   base_x = start_x;
2081   p = ChartData.GetFirst();
2082   while (p)
2083     {
2084       gGraphSetPen(gr, 0, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
2085       color_idx = idx % 8;
2086       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
2087                      colors[color_idx].Blue(), 255);
2088       height =
2089         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
2090       gGraphDrawRectangle(gr, base_x, base_y - height, step_x, height);
2091       base_x += step_x;
2092       idx++;
2093       p = p->GetNext();
2094     }
2095   if (others)
2096     {
2097       // other unclassified values
2098       color_idx = idx % 8;
2099       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
2100                      colors[color_idx].Blue(), 255);
2101       height =
2102         vspan *
2103         ((double)
2104          (ChartData.GetOtherUniquesFreq() / (double) (ChartData.GetMaxFreq())));
2105       gGraphDrawRectangle(gr, base_x, base_y - height, step_x, height);
2106     }
2107 // drawing 'scale' labels
2108   pLab = scaleLabels.GetFirst();
2109   while (pLab)
2110     {
2111       gGraphSetFont(gr, font);
2112       strcpy(text, pLab->GetLabel().ToUTF8());
2113       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2114                           &post_x, &post_y);
2115       gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
2116                      base_y - pLab->GetPosition() + (txtHeight / 2.0), 0.0);
2117       gGraphSetPen(gr, 255, 128, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
2118       gGraphStrokeLine(gr, start_x, base_y - pLab->GetPosition(), end_x,
2119                        base_y - pLab->GetPosition());
2120       pLab = pLab->GetNext();
2121     }
2122 // marking the ZERO baseline
2123   gGraphSetFont(gr, font);
2124   strcpy(text, "0");
2125   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
2126                       &post_y);
2127   gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
2128                  base_y + (txtHeight / 2.0), 0.0);
2129   gGraphSetPen(gr, 255, 128, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
2130   gGraphStrokeLine(gr, start_x, base_y, end_x, base_y);
2131 
2132 // graphics finalization
2133   gGraphDestroyFont(font);
2134   gGraphDestroyFont(font_big);
2135   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
2136       || target == CHART_TARGET_IS_PREVIEW)
2137     gGraphGetContextRgbArray(gr, &rgb_array);
2138   if (target == CHART_TARGET_IS_SVG)
2139     gGraphDestroySvgContext(gr);
2140   else if (target == CHART_TARGET_IS_PDF)
2141     gGraphDestroyPdfContext(gr);
2142   else
2143     gGraphDestroyContext(gr);
2144 
2145   if (target == CHART_TARGET_IS_PNG)
2146     {
2147       if (rgb_array)
2148         {
2149           // creating the Image from RGB array
2150           const void *img =
2151             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
2152           if (img)
2153             {
2154               char xpath[2024];
2155               strcpy(xpath, ExportPath.ToUTF8());
2156               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
2157                 {
2158                   wxString msg =
2159                     wxT
2160                     ("An error occurred while saving\nthe current Char as PNG");
2161                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
2162                                MainFrame);
2163                 }
2164               gGraphDestroyImage(img);
2165             }
2166         }
2167     }
2168   if (target == CHART_TARGET_IS_PREVIEW)
2169     {
2170       if (rgb_array)
2171         {
2172           // creating the Image from RGB array
2173           wxImage img(hsize, vsize);
2174           img.SetData(rgb_array);
2175           wxBitmap bmp(img);
2176           ChartShow->SetBitmap(bmp);
2177         }
2178     }
2179   if (target == CHART_TARGET_IS_COPY)
2180     {
2181       if (rgb_array)
2182         {
2183           // creating the Image from RGB array
2184           wxImage img(hsize, vsize);
2185           img.SetData(rgb_array);
2186           if (wxTheClipboard->Open())
2187             {
2188               wxTheClipboard->SetData(new wxBitmapDataObject(img));
2189               wxTheClipboard->Close();
2190             }
2191         }
2192     }
2193 }
2194 
DoUniqueLineChart(int hsize,int vsize,int target,int font_size)2195 void StatsChartDialog::DoUniqueLineChart(int hsize, int vsize, int target,
2196                                          int font_size)
2197 {
2198 // generating a Line Chart (Unique values)
2199   unsigned char *rgb_array = NULL;
2200   const void *gr = NULL;
2201   const void *font = NULL;
2202   const void *font_big = NULL;
2203   int idx;
2204   MyChartUniqueClass *p;
2205   int start_x;
2206   int end_x;
2207   int start_y;
2208   int end_y;
2209   double base_x;
2210   double step_x;
2211   double base_y;
2212   double vspan;
2213   double height;
2214   char title[1024];
2215   char table[1024];
2216   char column[1024];
2217   char text[1024];
2218   double txtWidth;
2219   double txtHeight;
2220   double titleHeight;
2221   double pre_x;
2222   double pre_y;
2223   double post_x;
2224   double post_y;
2225   int title_x;
2226   int title_y;
2227   double labelWidth = 0.0;
2228   int others = 0;
2229   MyChartScaleLabels scaleLabels;
2230   MyChartScaleLabel *pLab;
2231   double scaleWidth = 0.0;
2232 
2233 // graphics initialization
2234   if (target == CHART_TARGET_IS_SVG)
2235     {
2236       char xpath[2024];
2237       strcpy(xpath, ExportPath.ToUTF8());
2238       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
2239   } else if (target == CHART_TARGET_IS_PDF)
2240     {
2241       char xpath[2024];
2242       strcpy(xpath, ExportPath.ToUTF8());
2243       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
2244                              &gr);
2245   } else
2246     gGraphCreateContext(hsize, vsize, &gr);
2247 
2248 // background initialization
2249   gGraphSetBrush(gr, 255, 255, 255, 255);
2250   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
2251 
2252 // font setup
2253   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
2254                    &font);
2255   gGraphFontSetColor(font, 0, 0, 0, 255);
2256   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
2257                    &font_big);
2258   gGraphFontSetColor(font_big, 0, 0, 0, 255);
2259 
2260   if (ChartData.GetOtherUniquesFreq() > 0)
2261     others = 1;
2262 // computing TEXT sizes
2263   strcpy(table, Table.ToUTF8());
2264   strcpy(column, Column.ToUTF8());
2265   MainFrame->DoubleQuotedSql(table);
2266   MainFrame->DoubleQuotedSql(column);
2267   sprintf(title, "Dataset: %s.%s     [unique values]", table, column);
2268   gGraphSetFont(gr, font_big);
2269   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
2270                       &post_x, &post_y);
2271   title_x = (hsize - (int) txtWidth) / 2;
2272   title_y = 5 + (int) titleHeight;
2273 // measuring class labels
2274   p = ChartData.GetFirst();
2275   while (p)
2276     {
2277       gGraphSetFont(gr, font);
2278       strcpy(text, p->GetValue().ToUTF8());
2279       if (strlen(text) > 10)
2280         {
2281           text[10] = '.';
2282           text[11] = '.';
2283           text[12] = '\0';      // truncating to max 10 chars
2284         }
2285       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2286                           &post_x, &post_y);
2287       if (txtWidth > labelWidth)
2288         labelWidth = txtWidth;
2289       p = p->GetNext();
2290     }
2291   if (others)
2292     {
2293       // including the 'any other' class
2294       gGraphSetFont(gr, font);
2295       gGraphGetTextExtent(gr, "AnyOther", &pre_x, &pre_y, &txtWidth, &txtHeight,
2296                           &post_x, &post_y);
2297       if (txtWidth > labelWidth)
2298         labelWidth = txtWidth;
2299     }
2300 
2301   start_y = vsize - 10 - (int) labelWidth;
2302   end_y = 10 + (int) titleHeight;
2303   vspan = start_y - end_y;
2304   base_y = start_y;
2305 
2306 // building and measuring  the 'scale' labels
2307   scaleLabels.Initialize(vspan, ChartData.GetMaxFreq());
2308   pLab = scaleLabels.GetFirst();
2309   while (pLab)
2310     {
2311       gGraphSetFont(gr, font);
2312       strcpy(text, pLab->GetLabel().ToUTF8());
2313       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2314                           &post_x, &post_y);
2315       if (txtWidth > scaleWidth)
2316         scaleWidth = txtWidth;
2317       pLab = pLab->GetNext();
2318     }
2319 
2320   start_x = 10 + (int) scaleWidth;
2321   end_x = hsize - 10;
2322   base_x = start_x;
2323   step_x =
2324     (double) (end_x - start_x) / (double) (ChartData.GetNumClasses() + others);
2325 
2326 // title output
2327   gGraphSetFont(gr, font_big);
2328   gGraphDrawText(gr, title, title_x, title_y, 0.0);
2329 // class labels output
2330   p = ChartData.GetFirst();
2331   while (p)
2332     {
2333       gGraphSetFont(gr, font);
2334       strcpy(text, p->GetValue().ToUTF8());
2335       if (strlen(text) > 10)
2336         {
2337           text[10] = '.';
2338           text[11] = '.';
2339           text[12] = '\0';      // truncating to max 10 chars
2340         }
2341       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2342                           &post_x, &post_y);
2343       gGraphDrawText(gr, text, base_x + (txtHeight / 2.0) + (step_x / 2.0),
2344                      vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
2345       base_x += step_x;
2346       p = p->GetNext();
2347     }
2348   if (others)
2349     {
2350       // including the 'any other' class
2351       gGraphSetFont(gr, font);
2352       gGraphGetTextExtent(gr, "AnyOther", &pre_x, &pre_y, &txtWidth, &txtHeight,
2353                           &post_x, &post_y);
2354       gGraphDrawText(gr, "AnyOther",
2355                      base_x + (txtHeight / 2.0) + (step_x / 2.0),
2356                      vsize - labelWidth + txtWidth - 5, M_PI + (M_PI / 2.0));
2357     }
2358 
2359   idx = 0;
2360   base_x = start_x;
2361   p = ChartData.GetFirst();
2362   while (p)
2363     {
2364       height =
2365         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
2366       gGraphSetPen(gr, 192, 192, 192, 255, 1, GGRAPH_PENSTYLE_DOT);
2367       gGraphStrokeLine(gr, base_x + (step_x / 2.0), start_y,
2368                        base_x + (step_x / 2.0), base_y - height);
2369       base_x += step_x;
2370       idx++;
2371       p = p->GetNext();
2372     }
2373   if (others)
2374     {
2375       // other unclassified values
2376       height =
2377         vspan *
2378         ((double)
2379          (ChartData.GetOtherUniquesFreq() / (double) (ChartData.GetMaxFreq())));
2380       gGraphStrokeLine(gr, base_x + (step_x / 2.0), start_y,
2381                        base_x + (step_x / 2.0), base_y - height);
2382     }
2383   idx = 0;
2384   base_x = start_x;
2385   p = ChartData.GetFirst();
2386   while (p)
2387     {
2388       height =
2389         vspan * ((double) (p->GetCount() / (double) (ChartData.GetMaxFreq())));
2390       if (idx == 0)
2391         gGraphMoveToPoint(gr, base_x + (step_x / 2.0), base_y - height);
2392       else
2393         gGraphAddLineToPath(gr, base_x + (step_x / 2.0), base_y - height);
2394       base_x += step_x;
2395       idx++;
2396       p = p->GetNext();
2397     }
2398   if (others)
2399     {
2400       // other unclassified values
2401       height =
2402         vspan *
2403         ((double)
2404          (ChartData.GetOtherUniquesFreq() / (double) (ChartData.GetMaxFreq())));
2405       gGraphAddLineToPath(gr, base_x + (step_x / 2.0), base_y - height);
2406     }
2407   gGraphSetPen(gr, 255, 0, 0, 255, 2, GGRAPH_PENSTYLE_SOLID);
2408   gGraphStrokePath(gr, GGRAPH_CLEAR_PATH);
2409 
2410 // drawing 'scale' labels
2411   pLab = scaleLabels.GetFirst();
2412   while (pLab)
2413     {
2414       gGraphSetFont(gr, font);
2415       strcpy(text, pLab->GetLabel().ToUTF8());
2416       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2417                           &post_x, &post_y);
2418       gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
2419                      base_y - pLab->GetPosition() + (txtHeight / 2.0), 0.0);
2420       gGraphSetPen(gr, 128, 255, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
2421       gGraphStrokeLine(gr, start_x, base_y - pLab->GetPosition(), end_x,
2422                        base_y - pLab->GetPosition());
2423       pLab = pLab->GetNext();
2424     }
2425 // marking the ZERO baseline
2426   gGraphSetFont(gr, font);
2427   strcpy(text, "0");
2428   gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight, &post_x,
2429                       &post_y);
2430   gGraphDrawText(gr, text, scaleWidth - txtWidth + 5,
2431                  base_y + (txtHeight / 2.0), 0.0);
2432   gGraphSetPen(gr, 128, 255, 128, 255, 1, GGRAPH_PENSTYLE_DOT);
2433   gGraphStrokeLine(gr, start_x, base_y, end_x, base_y);
2434 
2435 // graphics finalization
2436   gGraphDestroyFont(font);
2437   gGraphDestroyFont(font_big);
2438   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
2439       || target == CHART_TARGET_IS_PREVIEW)
2440     gGraphGetContextRgbArray(gr, &rgb_array);
2441   if (target == CHART_TARGET_IS_SVG)
2442     gGraphDestroySvgContext(gr);
2443   else if (target == CHART_TARGET_IS_PDF)
2444     gGraphDestroyPdfContext(gr);
2445   else
2446     gGraphDestroyContext(gr);
2447 
2448   if (target == CHART_TARGET_IS_PNG)
2449     {
2450       if (rgb_array)
2451         {
2452           // creating the Image from RGB array
2453           const void *img =
2454             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
2455           if (img)
2456             {
2457               char xpath[2024];
2458               strcpy(xpath, ExportPath.ToUTF8());
2459               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
2460                 {
2461                   wxString msg =
2462                     wxT
2463                     ("An error occurred while saving\nthe current Char as PNG");
2464                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
2465                                MainFrame);
2466                 }
2467               gGraphDestroyImage(img);
2468             }
2469         }
2470     }
2471   if (target == CHART_TARGET_IS_PREVIEW)
2472     {
2473       if (rgb_array)
2474         {
2475           // creating the Image from RGB array
2476           wxImage img(hsize, vsize);
2477           img.SetData(rgb_array);
2478           wxBitmap bmp(img);
2479           ChartShow->SetBitmap(bmp);
2480         }
2481     }
2482   if (target == CHART_TARGET_IS_COPY)
2483     {
2484       if (rgb_array)
2485         {
2486           // creating the Image from RGB array
2487           wxImage img(hsize, vsize);
2488           img.SetData(rgb_array);
2489           if (wxTheClipboard->Open())
2490             {
2491               wxTheClipboard->SetData(new wxBitmapDataObject(img));
2492               wxTheClipboard->Close();
2493             }
2494         }
2495     }
2496 }
2497 
DoUniquePieChart(int hsize,int vsize,int target,int font_size)2498 void StatsChartDialog::DoUniquePieChart(int hsize, int vsize, int target,
2499                                         int font_size)
2500 {
2501 // generating a Pie Chart (Unique values)
2502   unsigned char *rgb_array = NULL;
2503   const void *gr = NULL;
2504   const void *font = NULL;
2505   const void *font_big = NULL;
2506   int idx;
2507   MyChartUniqueClass *p;
2508   double radius_x;
2509   double radius_y;
2510   double radius;
2511   double cx;
2512   double cy;
2513   double from;
2514   double step;
2515   char title[1024];
2516   char table[1024];
2517   char column[1024];
2518   double txtWidth;
2519   double txtHeight;
2520   double titleHeight;
2521   double pre_x;
2522   double pre_y;
2523   double post_x;
2524   double post_y;
2525   int title_x;
2526   int title_y;
2527   wxColour colors[8];
2528   int color_idx;
2529   MyPieChartLabels labels;
2530   MyPieChartLabel *pLab;
2531   char text[1024];
2532   double lx;
2533   double ly;
2534   double base_y;
2535   double step_y;
2536   double labelWidth = 0.0;
2537   int others = 0;
2538 
2539 // color palette
2540   colors[0] = wxColour(255, 255, 240);
2541   colors[1] = wxColour(255, 240, 255);
2542   colors[2] = wxColour(240, 255, 255);
2543   colors[3] = wxColour(240, 240, 240);
2544   colors[4] = wxColour(255, 192, 192);
2545   colors[5] = wxColour(192, 255, 192);
2546   colors[6] = wxColour(192, 192, 255);
2547   colors[7] = wxColour(192, 192, 192);
2548 
2549 // graphics initialization
2550   if (target == CHART_TARGET_IS_SVG)
2551     {
2552       char xpath[2024];
2553       strcpy(xpath, ExportPath.ToUTF8());
2554       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
2555   } else if (target == CHART_TARGET_IS_PDF)
2556     {
2557       char xpath[2024];
2558       strcpy(xpath, ExportPath.ToUTF8());
2559       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
2560                              &gr);
2561   } else
2562     gGraphCreateContext(hsize, vsize, &gr);
2563 
2564 // background initialization
2565   gGraphSetBrush(gr, 255, 255, 255, 255);
2566   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
2567 
2568 // font setup
2569   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_NORMAL,
2570                    &font);
2571   gGraphFontSetColor(font, 0, 0, 0, 255);
2572   gGraphCreateFont(font_size, GGRAPH_FONTSTYLE_NORMAL, GGRAPH_FONTWEIGHT_BOLD,
2573                    &font_big);
2574   gGraphFontSetColor(font_big, 0, 0, 0, 255);
2575 
2576   if (ChartData.GetOtherUniquesFreq() > 0)
2577     others = 1;
2578 // computing TEXT sizes
2579   strcpy(table, Table.ToUTF8());
2580   strcpy(column, Column.ToUTF8());
2581   MainFrame->DoubleQuotedSql(table);
2582   MainFrame->DoubleQuotedSql(column);
2583   sprintf(title, "Dataset: %s.%s     [unique values]", table, column);
2584   gGraphSetFont(gr, font_big);
2585   gGraphGetTextExtent(gr, title, &pre_x, &pre_y, &txtWidth, &titleHeight,
2586                       &post_x, &post_y);
2587   title_x = (hsize - (int) txtWidth) / 2;
2588   title_y = 5 + (int) titleHeight;
2589   p = ChartData.GetFirst();
2590   while (p)
2591     {
2592       // measuring labels
2593       gGraphSetFont(gr, font);
2594       strcpy(text, p->GetValue().ToUTF8());
2595       if (strlen(text) > 10)
2596         {
2597           text[10] = '.';
2598           text[11] = '.';
2599           text[12] = '\0';      // truncating to max 10 chars
2600         }
2601       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2602                           &post_x, &post_y);
2603       if (txtWidth > labelWidth)
2604         labelWidth = txtWidth;
2605       p = p->GetNext();
2606     }
2607   if (others)
2608     {
2609       gGraphGetTextExtent(gr, "AnyOther", &pre_x, &pre_y, &txtWidth, &txtHeight,
2610                           &post_x, &post_y);
2611       if (txtWidth > labelWidth)
2612         labelWidth = txtWidth;
2613     }
2614 
2615   cx = (double) hsize / 2.0;
2616   cy = (double) vsize / 2.0;
2617   cy += (double) (titleHeight + 10) / 2.0;
2618   radius_x = (double) (hsize - 20) / 2.0;
2619   radius_x -= labelWidth + 10;
2620   radius_y = (double) (vsize - titleHeight - 20) / 2.0;
2621   if (radius_x <= radius_y)
2622     radius = radius_x;
2623   else
2624     radius = radius_y;
2625 
2626 // title output
2627   gGraphSetFont(gr, font_big);
2628   gGraphDrawText(gr, title, title_x, title_y, 0.0);
2629 
2630   from = 0.0;
2631   idx = 0;
2632   p = ChartData.GetFirst();
2633   while (p)
2634     {
2635       gGraphSetPen(gr, 0, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
2636       color_idx = idx % 8;
2637       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
2638                      colors[color_idx].Blue(), 255);
2639       step =
2640         (M_PI * 2.0) *
2641         ((double) (p->GetCount() / (double) (ChartData.GetTotFreq())));
2642       gGraphDrawCircleSector(gr, cx, cy, radius, from, from + step);
2643       strcpy(text, p->GetValue().ToUTF8());
2644       if (strlen(text) > 10)
2645         {
2646           text[10] = '.';
2647           text[11] = '.';
2648           text[12] = '\0';      // truncating to max 10 chars
2649         }
2650       lx = cx + (radius * 0.90) * cos(from + (step / 2.0));
2651       ly = cy + (radius * 0.90) * sin(from + (step / 2.0));
2652       labels.Add(text, lx, ly);
2653       from += step;
2654       idx++;
2655       p = p->GetNext();
2656     }
2657   if (others)
2658     {
2659       // other unclassified values
2660       color_idx = idx % 8;
2661       gGraphSetBrush(gr, colors[color_idx].Red(), colors[color_idx].Green(),
2662                      colors[color_idx].Blue(), 255);
2663       step =
2664         (M_PI * 2.0) *
2665         ((double)
2666          (ChartData.GetOtherUniquesFreq() / (double) (ChartData.GetTotFreq())));
2667       gGraphDrawCircleSector(gr, cx, cy, radius, from, from + step);
2668       lx = cx + (radius * 0.90) * cos(from + (step / 2.0));
2669       ly = cy + (radius * 0.90) * sin(from + (step / 2.0));
2670       labels.Add("AnyOther", lx, ly);
2671     }
2672 // printing class labels
2673   labels.Sort(cx);
2674   step_y = (double) (vsize - 50) / (double) (labels.GetNumLeftLabels() - 1);
2675   base_y = 25.0;
2676   for (idx = 0; idx < labels.GetNumLeftLabels(); idx++)
2677     {
2678       // printing Left labels
2679       pLab = labels.GetLeftLabel(idx);
2680       strcpy(text, pLab->GetLabel().ToUTF8());
2681       gGraphSetFont(gr, font);
2682       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2683                           &post_x, &post_y);
2684       gGraphDrawText(gr, text, 10, base_y + (txtHeight / 2.0), 0.0);
2685       gGraphSetPen(gr, 255, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
2686       gGraphStrokeLine(gr, 10 + txtWidth, base_y, pLab->GetX(), pLab->GetY());
2687       base_y += step_y;
2688     }
2689   step_y = (double) (vsize - 50) / (double) (labels.GetNumRightLabels() - 1);
2690   base_y = 25.0;
2691   for (idx = 0; idx < labels.GetNumRightLabels(); idx++)
2692     {
2693       // printing Right labels
2694       pLab = labels.GetRightLabel(idx);
2695       strcpy(text, pLab->GetLabel().ToUTF8());
2696       gGraphSetFont(gr, font);
2697       gGraphGetTextExtent(gr, text, &pre_x, &pre_y, &txtWidth, &txtHeight,
2698                           &post_x, &post_y);
2699       gGraphDrawText(gr, text, hsize - txtWidth - 10,
2700                      base_y + (txtHeight / 2.0), 0.0);
2701       gGraphSetPen(gr, 255, 0, 0, 255, 1, GGRAPH_PENSTYLE_SOLID);
2702       gGraphStrokeLine(gr, hsize - txtWidth - 10, base_y, pLab->GetX(),
2703                        pLab->GetY());
2704       base_y += step_y;
2705     }
2706 
2707 // graphics finalization
2708   gGraphDestroyFont(font);
2709   gGraphDestroyFont(font_big);
2710   if (target == CHART_TARGET_IS_COPY || target == CHART_TARGET_IS_PNG
2711       || target == CHART_TARGET_IS_PREVIEW)
2712     gGraphGetContextRgbArray(gr, &rgb_array);
2713   if (target == CHART_TARGET_IS_SVG)
2714     gGraphDestroySvgContext(gr);
2715   else if (target == CHART_TARGET_IS_PDF)
2716     gGraphDestroyPdfContext(gr);
2717   else
2718     gGraphDestroyContext(gr);
2719 
2720   if (target == CHART_TARGET_IS_PNG)
2721     {
2722       if (rgb_array)
2723         {
2724           // creating the Image from RGB array
2725           const void *img =
2726             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
2727           if (img)
2728             {
2729               char xpath[2024];
2730               strcpy(xpath, ExportPath.ToUTF8());
2731               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
2732                 {
2733                   wxString msg =
2734                     wxT
2735                     ("An error occurred while saving\nthe current Char as PNG");
2736                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
2737                                MainFrame);
2738                 }
2739               gGraphDestroyImage(img);
2740             }
2741         }
2742     }
2743   if (target == CHART_TARGET_IS_PREVIEW)
2744     {
2745       if (rgb_array)
2746         {
2747           // creating the Image from RGB array
2748           wxImage img(hsize, vsize);
2749           img.SetData(rgb_array);
2750           wxBitmap bmp(img);
2751           ChartShow->SetBitmap(bmp);
2752         }
2753     }
2754   if (target == CHART_TARGET_IS_COPY)
2755     {
2756       if (rgb_array)
2757         {
2758           // creating the Image from RGB array
2759           wxImage img(hsize, vsize);
2760           img.SetData(rgb_array);
2761           if (wxTheClipboard->Open())
2762             {
2763               wxTheClipboard->SetData(new wxBitmapDataObject(img));
2764               wxTheClipboard->Close();
2765             }
2766         }
2767     }
2768 }
2769 
CleanDecimals(char * str)2770 void StatsChartDialog::CleanDecimals(char *str)
2771 {
2772 // suppressing not significative decimal digits
2773   int i;
2774   int len = strlen(str);
2775   for (i = len - 1; i >= 0; i--)
2776     {
2777       if (str[i] == '0')
2778         str[i] = '\0';
2779       else
2780         break;
2781     }
2782   len = strlen(str);
2783   if (str[len - 1] == '.')
2784     str[len - 1] = '\0';
2785 }
2786 
OnExit(wxCommandEvent & WXUNUSED (event))2787 void StatsChartDialog::OnExit(wxCommandEvent & WXUNUSED(event))
2788 {
2789 //
2790 // all done:
2791 //
2792   wxDialog::EndModal(wxID_OK);
2793 }
2794 
Create(MyFrame * parent,wxString & table,wxString & column,double minx,double miny,double maxx,double maxy)2795 bool MapPreviewDialog::Create(MyFrame * parent, wxString & table,
2796                               wxString & column, double minx, double miny,
2797                               double maxx, double maxy)
2798 {
2799 //
2800 // creating the dialog
2801 //
2802   MainFrame = parent;
2803   Table = table;
2804   Column = column;
2805   MinX = minx;
2806   MinY = miny;
2807   MaxX = maxx;
2808   MaxY = maxy;
2809   LineColor = wxColour(0, 0, 0);
2810   FillColor = wxColour(192, 192, 192);
2811   if (wxDialog::Create(parent, wxID_ANY, wxT("Map preview")) == false)
2812     return false;
2813 // populates individual controls
2814   CreateControls();
2815 // sets dialog sizer
2816   GetSizer()->Fit(this);
2817   GetSizer()->SetSizeHints(this);
2818 // centers the dialog window
2819   Centre();
2820   return true;
2821 }
2822 
CreateControls()2823 void MapPreviewDialog::CreateControls()
2824 {
2825 //
2826 // creating individual control and setting initial values
2827 //
2828   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
2829   this->SetSizer(topSizer);
2830   wxBoxSizer *boxSizer = new wxBoxSizer(wxVERTICAL);
2831   topSizer->Add(boxSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
2832 // First row: TABLE name
2833   wxBoxSizer *tableSizer = new wxBoxSizer(wxHORIZONTAL);
2834   boxSizer->Add(tableSizer, 0, wxALIGN_RIGHT | wxALL, 0);
2835   wxStaticText *tableLabel =
2836     new wxStaticText(this, wxID_STATIC, wxT("&Table name:"));
2837   tableSizer->Add(tableLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2838   wxTextCtrl *tableCtrl = new wxTextCtrl(this, wxID_ANY, Table,
2839                                          wxDefaultPosition, wxSize(350, 22),
2840                                          wxTE_READONLY);
2841   tableCtrl->Enable(false);
2842   tableSizer->Add(tableCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
2843 // second row: COLUMN name
2844   wxBoxSizer *colSizer = new wxBoxSizer(wxHORIZONTAL);
2845   boxSizer->Add(colSizer, 0, wxALIGN_RIGHT | wxALL, 0);
2846   wxStaticText *colLabel =
2847     new wxStaticText(this, wxID_STATIC, wxT("&Column name:"));
2848   colSizer->Add(colLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2849   wxTextCtrl *colCtrl = new wxTextCtrl(this, wxID_ANY, Column,
2850                                        wxDefaultPosition, wxSize(350, 22),
2851                                        wxTE_READONLY);
2852   colCtrl->Enable(false);
2853   colSizer->Add(colCtrl, 0, wxALIGN_RIGHT | wxALL, 5);
2854 // third row: Graphics params
2855   wxStaticBox *optBox = new wxStaticBox(this, wxID_STATIC,
2856                                         wxT("Graphics"),
2857                                         wxDefaultPosition,
2858                                         wxDefaultSize);
2859   wxBoxSizer *optSizer = new wxStaticBoxSizer(optBox, wxVERTICAL);
2860   boxSizer->Add(optSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2861   wxBoxSizer *graphSizer = new wxBoxSizer(wxHORIZONTAL);
2862   optSizer->Add(graphSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2863   wxString size[5];
2864   size[0] = wxT("&256");
2865   size[1] = wxT("&512");
2866   size[2] = wxT("&1024");
2867   size[3] = wxT("&2048");
2868   size[4] = wxT("&4196");
2869   SizeCtrl = new wxRadioBox(this, ID_CHART_SIZE,
2870                             wxT("&Dimension [pixels]"),
2871                             wxDefaultPosition,
2872                             wxDefaultSize, 5, size, 1, wxRA_SPECIFY_COLS);
2873   graphSizer->Add(SizeCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2874   SizeCtrl->SetSelection(0);
2875   wxBoxSizer *mixSizer = new wxBoxSizer(wxVERTICAL);
2876   graphSizer->Add(mixSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2877   wxBoxSizer *ptSizer = new wxBoxSizer(wxHORIZONTAL);
2878   mixSizer->Add(ptSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2879   wxString symbol[2];
2880   symbol[0] = wxT("&Circle");
2881   symbol[1] = wxT("&Square");
2882   SymbolCtrl = new wxRadioBox(this, ID_MAP_SYMBOL,
2883                               wxT("&Point Symbol"),
2884                               wxDefaultPosition,
2885                               wxDefaultSize, 2, symbol, 1, wxRA_SPECIFY_ROWS);
2886   ptSizer->Add(SymbolCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2887   SymbolCtrl->SetSelection(0);
2888   wxBoxSizer *szSizer = new wxBoxSizer(wxHORIZONTAL);
2889   ptSizer->Add(szSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
2890   wxStaticText *szLabel =
2891     new wxStaticText(this, wxID_STATIC, wxT("&Symbol size:"));
2892   szSizer->Add(szLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2893   SymSizeCtrl = new wxSpinCtrl(this, ID_MAP_SYM_SIZE, wxT("3"),
2894                                wxDefaultPosition, wxSize(50, 20),
2895                                wxSP_ARROW_KEYS, 1, 32, 3);
2896   szSizer->Add(SymSizeCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2897   wxBoxSizer *lnpgSizer = new wxBoxSizer(wxHORIZONTAL);
2898   mixSizer->Add(lnpgSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2899   wxString fill[2];
2900   fill[0] = wxT("&Yes");
2901   fill[1] = wxT("&No");
2902   FillCtrl = new wxRadioBox(this, ID_MAP_FILL,
2903                             wxT("&Interior filling"),
2904                             wxDefaultPosition,
2905                             wxDefaultSize, 2, fill, 1, wxRA_SPECIFY_ROWS);
2906   lnpgSizer->Add(FillCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2907   FillCtrl->SetSelection(0);
2908   wxBoxSizer *thkSizer = new wxBoxSizer(wxHORIZONTAL);
2909   lnpgSizer->Add(thkSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
2910   wxStaticText *thickLabel =
2911     new wxStaticText(this, wxID_STATIC, wxT("&Line thickness:"));
2912   thkSizer->Add(thickLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2913   ThicknessCtrl = new wxSpinCtrl(this, ID_MAP_THICKNESS, wxT("1"),
2914                                  wxDefaultPosition, wxSize(50, 20),
2915                                  wxSP_ARROW_KEYS, 1, 32, 1);
2916   thkSizer->Add(ThicknessCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2917   wxBoxSizer *colorSizer = new wxBoxSizer(wxHORIZONTAL);
2918   mixSizer->Add(colorSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2919   wxBitmap lineBmp;
2920   GetButtonBitmap(LineColor, lineBmp);
2921   LineColorCtrl = new wxBitmapButton(this, ID_MAP_LINE_COL, lineBmp);
2922   colorSizer->Add(LineColorCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2923   wxBitmap fillBmp;
2924   GetButtonBitmap(FillColor, fillBmp);
2925   FillColorCtrl = new wxBitmapButton(this, ID_MAP_FILL_COL, fillBmp);
2926   colorSizer->Add(FillColorCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2927 
2928 // creating a control to show the Map preview
2929   wxStaticBox *exBox = new wxStaticBox(this, wxID_ANY,
2930                                        wxT("Map preview"),
2931                                        wxDefaultPosition, wxDefaultSize);
2932   wxBoxSizer *showSizer = new wxStaticBoxSizer(exBox, wxHORIZONTAL);
2933   boxSizer->Add(showSizer, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
2934   MapShow = new wxStaticBitmap(this, wxID_ANY,
2935                                wxBitmap(), wxDefaultPosition, wxSize(256, 256),
2936                                wxBORDER_SUNKEN);
2937   showSizer->Add(MapShow, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2938 
2939 // buttons
2940   wxStaticBox *btnBox = new wxStaticBox(this, wxID_STATIC,
2941                                         wxT("Export as"),
2942                                         wxDefaultPosition,
2943                                         wxDefaultSize);
2944   wxBoxSizer *btnSizer = new wxStaticBoxSizer(btnBox, wxVERTICAL);
2945   showSizer->Add(btnSizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2946   wxBoxSizer *buttonBox = new wxBoxSizer(wxVERTICAL);
2947   btnSizer->Add(buttonBox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
2948   wxButton *copy = new wxButton(this, ID_MAP_COPY, wxT("&Copy"));
2949   buttonBox->Add(copy, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2950   wxButton *png = new wxButton(this, ID_MAP_PNG, wxT("&PNG"));
2951   buttonBox->Add(png, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2952   wxButton *svg = new wxButton(this, ID_MAP_SVG, wxT("&SVG"));
2953   buttonBox->Add(svg, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2954   wxButton *pdf = new wxButton(this, ID_MAP_PDF, wxT("&PDF"));
2955   buttonBox->Add(pdf, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2956   wxBoxSizer *exitBox = new wxBoxSizer(wxHORIZONTAL);
2957   boxSizer->Add(exitBox, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
2958   wxButton *exit = new wxButton(this, wxID_OK, wxT("&Exit"));
2959   exitBox->Add(exit, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
2960 // appends event handler for OK button
2961   Connect(ID_MAP_COPY, wxEVT_COMMAND_BUTTON_CLICKED,
2962           (wxObjectEventFunction) & MapPreviewDialog::OnMapCopy);
2963   Connect(ID_MAP_PNG, wxEVT_COMMAND_BUTTON_CLICKED,
2964           (wxObjectEventFunction) & MapPreviewDialog::OnMapPng);
2965   Connect(ID_MAP_SVG, wxEVT_COMMAND_BUTTON_CLICKED,
2966           (wxObjectEventFunction) & MapPreviewDialog::OnMapSvg);
2967   Connect(ID_MAP_PDF, wxEVT_COMMAND_BUTTON_CLICKED,
2968           (wxObjectEventFunction) & MapPreviewDialog::OnMapPdf);
2969   Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED,
2970           (wxObjectEventFunction) & MapPreviewDialog::OnExit);
2971   Connect(ID_MAP_LINE_COL, wxEVT_COMMAND_BUTTON_CLICKED,
2972           (wxObjectEventFunction) & MapPreviewDialog::OnLineColor);
2973   Connect(ID_MAP_FILL_COL, wxEVT_COMMAND_BUTTON_CLICKED,
2974           (wxObjectEventFunction) & MapPreviewDialog::OnFillColor);
2975   Connect(ID_MAP_SYMBOL, wxEVT_COMMAND_RADIOBOX_SELECTED,
2976           (wxObjectEventFunction) & MapPreviewDialog::OnSymbolTypeChanged);
2977   Connect(ID_MAP_FILL, wxEVT_COMMAND_RADIOBOX_SELECTED,
2978           (wxObjectEventFunction) & MapPreviewDialog::OnLineThicknessChanged);
2979   Connect(ID_MAP_THICKNESS, wxEVT_COMMAND_TEXT_UPDATED,
2980           (wxObjectEventFunction) & MapPreviewDialog::OnLineThicknessChanged);
2981   Connect(ID_MAP_SIZE, wxEVT_COMMAND_TEXT_UPDATED,
2982           (wxObjectEventFunction) & MapPreviewDialog::OnSymbolSizeChanged);
2983 // showing the current preview
2984   UpdatePreview();
2985 }
2986 
GetButtonBitmap(wxColour & color,wxBitmap & bmp)2987 void MapPreviewDialog::GetButtonBitmap(wxColour & color, wxBitmap & bmp)
2988 {
2989 // creating a Bitmap representing some Color
2990   bmp = wxBitmap(64, 24);
2991   wxMemoryDC *dc = new wxMemoryDC(bmp);
2992   dc->SetBrush(wxBrush(color));
2993   dc->DrawRectangle(-1, -1, 66, 26);
2994   delete dc;
2995 }
2996 
OnLineColor(wxCommandEvent & WXUNUSED (event))2997 void MapPreviewDialog::OnLineColor(wxCommandEvent & WXUNUSED(event))
2998 {
2999 // color selection
3000   wxColourData initColor;
3001   int ret;
3002   initColor.SetChooseFull(false);
3003   initColor.SetColour(LineColor);
3004   wxColourDialog colorDialog(this, &initColor);
3005   ret = colorDialog.ShowModal();
3006   if (ret == wxID_OK)
3007     {
3008       wxColourData colorData = colorDialog.GetColourData();
3009       wxColour color = colorData.GetColour();
3010       LineColor = wxColour(color.Red(), color.Green(), color.Blue());
3011       wxBitmap bmp;
3012       GetButtonBitmap(LineColor, bmp);
3013       LineColorCtrl->SetBitmapLabel(bmp);
3014     }
3015   UpdatePreview();
3016 }
3017 
OnFillColor(wxCommandEvent & WXUNUSED (event))3018 void MapPreviewDialog::OnFillColor(wxCommandEvent & WXUNUSED(event))
3019 {
3020 // color selection
3021   wxColourData initColor;
3022   int ret;
3023   initColor.SetChooseFull(false);
3024   initColor.SetColour(FillColor);
3025   wxColourDialog colorDialog(this, &initColor);
3026   ret = colorDialog.ShowModal();
3027   if (ret == wxID_OK)
3028     {
3029       wxColourData colorData = colorDialog.GetColourData();
3030       wxColour color = colorData.GetColour();
3031       FillColor = wxColour(color.Red(), color.Green(), color.Blue());
3032       wxBitmap bmp;
3033       GetButtonBitmap(FillColor, bmp);
3034       FillColorCtrl->SetBitmapLabel(bmp);
3035     }
3036   UpdatePreview();
3037 }
3038 
OnSymbolTypeChanged(wxCommandEvent & WXUNUSED (event))3039 void MapPreviewDialog::OnSymbolTypeChanged(wxCommandEvent & WXUNUSED(event))
3040 {
3041 // symbol type radiobox changed
3042   UpdatePreview();
3043 }
3044 
OnFillModeChanged(wxCommandEvent & WXUNUSED (event))3045 void MapPreviewDialog::OnFillModeChanged(wxCommandEvent & WXUNUSED(event))
3046 {
3047 // fill mode radiobox changed
3048   UpdatePreview();
3049 }
3050 
OnSymbolSizeChanged(wxCommandEvent & WXUNUSED (event))3051 void MapPreviewDialog::OnSymbolSizeChanged(wxCommandEvent & WXUNUSED(event))
3052 {
3053 // symbol type spincontrol changed
3054   UpdatePreview();
3055 }
3056 
OnLineThicknessChanged(wxCommandEvent & WXUNUSED (event))3057 void MapPreviewDialog::OnLineThicknessChanged(wxCommandEvent & WXUNUSED(event))
3058 {
3059 // line thickness spincontrol changed
3060   UpdatePreview();
3061 }
3062 
UpdatePreview()3063 void MapPreviewDialog::UpdatePreview()
3064 {
3065 // showing an empty preview map
3066   wxBitmap bmp;
3067   MapShow->SetBitmap(bmp);
3068 
3069 // updating the Map Preview
3070   DoMap(256, 256, MAP_TARGET_IS_PREVIEW);
3071 }
3072 
DoMap(int hsize,int vsize,int target)3073 void MapPreviewDialog::DoMap(int hsize, int vsize, int target)
3074 {
3075 // drawing the map preview
3076   const void *gr = NULL;
3077   unsigned char *rgb_array = NULL;
3078   char table[1024];
3079   char column[1024];
3080   char sql[4196];
3081   int ret;
3082   char err_msg[2048];
3083   sqlite3_stmt *stmt;
3084   int horz;
3085   int vert;
3086   int h_shift;
3087   int v_shift;
3088   double ratio;
3089   double ext_x = MaxX - MinX;
3090   double ext_y = MaxY - MinY;
3091   bool circle;
3092   int symbol_size;
3093   bool fill;
3094   int thickness;
3095 
3096 // computing the rendering ratio
3097   if (ext_x > ext_y)
3098     {
3099       ratio = ext_x / (double) (hsize - 20);
3100       if ((ext_y / ratio) > vsize)
3101         ratio = ext_y / (double) (vsize - 20);
3102   } else
3103     {
3104       ratio = ext_y / (double) (vsize - 20);
3105       if ((ext_x / ratio) > hsize)
3106         ratio = ext_x / (double) (hsize - 20);
3107     }
3108   horz = (int) (ext_x / ratio);
3109   vert = (int) (ext_y / ratio);
3110   horz += 20;
3111   vert += 20;
3112   h_shift = (hsize - horz) / 2;
3113   v_shift = (vsize - vert) / 2;
3114 
3115 // retrieving current graphic settings
3116   switch (SymbolCtrl->GetSelection())
3117     {
3118       case 0:
3119         circle = true;
3120         break;
3121       case 1:
3122         circle = false;
3123         break;
3124     };
3125   switch (FillCtrl->GetSelection())
3126     {
3127       case 0:
3128         fill = true;
3129         break;
3130       case 1:
3131         fill = false;
3132         break;
3133     };
3134   symbol_size = SymSizeCtrl->GetValue();
3135   thickness = ThicknessCtrl->GetValue();
3136 
3137 // graphics initialization
3138   if (target == MAP_TARGET_IS_SVG)
3139     {
3140       char xpath[2024];
3141       strcpy(xpath, ExportPath.ToUTF8());
3142       gGraphCreateSvgContext(xpath, hsize, vsize, &gr);
3143   } else if (target == MAP_TARGET_IS_PDF)
3144     {
3145       char xpath[2024];
3146       strcpy(xpath, ExportPath.ToUTF8());
3147       gGraphCreatePdfContext(xpath, hsize + 100, vsize + 100, hsize, vsize,
3148                              &gr);
3149   } else
3150     gGraphCreateContext(hsize, vsize, &gr);
3151 
3152 // background initialization
3153   gGraphSetBrush(gr, 255, 255, 255, 255);
3154   gGraphDrawRectangle(gr, -1, -1, hsize + 2, vsize + 2);
3155 
3156 // setting standard graphic setting
3157   gGraphSetPen(gr, LineColor.Red(), LineColor.Green(), LineColor.Blue(), 255,
3158                thickness, GGRAPH_PENSTYLE_SOLID);
3159   gGraphSetBrush(gr, FillColor.Red(), FillColor.Green(), FillColor.Blue(), 255);
3160 
3161   ::wxBeginBusyCursor();
3162   strcpy(table, Table.ToUTF8());
3163   strcpy(column, Column.ToUTF8());
3164   MainFrame->DoubleQuotedSql(table);
3165   MainFrame->DoubleQuotedSql(column);
3166   sprintf(sql, "SELECT %s FROM %s", column, table);
3167   ret =
3168     sqlite3_prepare_v2(MainFrame->GetSqlite(), sql, strlen(sql), &stmt, NULL);
3169   if (ret != SQLITE_OK)
3170     {
3171       sprintf(err_msg, "SQL error: %s", sqlite3_errmsg(MainFrame->GetSqlite()));
3172       wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
3173                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
3174       ::wxEndBusyCursor();
3175       return;
3176     }
3177   while (1)
3178     {
3179       //
3180       // fetching the result set rows
3181       //
3182       ret = sqlite3_step(stmt);
3183       if (ret == SQLITE_DONE)
3184         break;                  // end of result set
3185       if (ret == SQLITE_ROW)
3186         {
3187           //
3188           // fetching a row
3189           //
3190           gaiaGeomCollPtr geom = NULL;
3191           if (sqlite3_column_type(stmt, 0) == SQLITE_BLOB)
3192             {
3193               // fetching Geometry
3194               int x;
3195               int y;
3196               const void *blob = sqlite3_column_blob(stmt, 0);
3197               int blob_size = sqlite3_column_bytes(stmt, 0);
3198               geom =
3199                 gaiaFromSpatiaLiteBlobWkb((const unsigned char *) blob,
3200                                           blob_size);
3201               if (geom)
3202                 {
3203                   // drawing the geometric entity
3204                   gaiaPolygonPtr pg = geom->FirstPolygon;
3205                   while (pg)
3206                     {
3207                       // drawing a POLYGON
3208                       int iv;
3209                       double dx;
3210                       double dy;
3211                       double z;
3212                       double m;
3213                       int x;
3214                       int y;
3215                       int lastX = 0;
3216                       int lastY = 0;
3217                       int ib;
3218                       gaiaRingPtr ring = pg->Exterior;
3219                       // exterior border
3220                       for (iv = 0; iv < ring->Points; iv++)
3221                         {
3222                           if (ring->DimensionModel == GAIA_XY_Z)
3223                             {
3224                               gaiaGetPointXYZ(ring->Coords, iv, &dx, &dy, &z);
3225                           } else if (ring->DimensionModel == GAIA_XY_M)
3226                             {
3227                               gaiaGetPointXYM(ring->Coords, iv, &dx, &dy, &m);
3228                           } else if (ring->DimensionModel == GAIA_XY_Z_M)
3229                             {
3230                               gaiaGetPointXYZM(ring->Coords, iv, &dx, &dy, &z,
3231                                                &m);
3232                           } else
3233                             {
3234                               gaiaGetPoint(ring->Coords, iv, &dx, &dy);
3235                             }
3236                           x = (int) ((dx - MinX) / ratio);
3237                           y = vert - (int) ((dy - MinY) / ratio);
3238                           x += h_shift;
3239                           y += v_shift;
3240                           if (iv == 0)
3241                             {
3242                               gGraphMoveToPoint(gr, x, y);
3243                               lastX = x;
3244                               lastY = y;
3245                           } else
3246                             {
3247                               if (x == lastX && y == lastY)
3248                                 ;
3249                               else
3250                                 {
3251                                   gGraphAddLineToPath(gr, x, y);
3252                                   lastX = x;
3253                                   lastY = y;
3254                                 }
3255                             }
3256                         }
3257                       gGraphCloseSubpath(gr);
3258                       for (ib = 0; ib < pg->NumInteriors; ib++)
3259                         {
3260                           // interior borders
3261                           ring = pg->Interiors + ib;
3262                           for (iv = 0; iv < ring->Points; iv++)
3263                             {
3264                               if (ring->DimensionModel == GAIA_XY_Z)
3265                                 {
3266                                   gaiaGetPointXYZ(ring->Coords, iv, &dx, &dy,
3267                                                   &z);
3268                               } else if (ring->DimensionModel == GAIA_XY_M)
3269                                 {
3270                                   gaiaGetPointXYM(ring->Coords, iv, &dx, &dy,
3271                                                   &m);
3272                               } else if (ring->DimensionModel == GAIA_XY_Z_M)
3273                                 {
3274                                   gaiaGetPointXYZM(ring->Coords, iv, &dx, &dy,
3275                                                    &z, &m);
3276                               } else
3277                                 {
3278                                   gaiaGetPoint(ring->Coords, iv, &dx, &dy);
3279                                 }
3280                               x = (int) ((dx - MinX) / ratio);
3281                               y = vert - (int) ((dy - MinY) / ratio);
3282                               x += h_shift;
3283                               y += v_shift;
3284                               if (iv == 0)
3285                                 {
3286                                   gGraphMoveToPoint(gr, x, y);
3287                                   lastX = x;
3288                                   lastY = y;
3289                               } else
3290                                 {
3291                                   if (x == lastX && y == lastY)
3292                                     ;
3293                                   else
3294                                     {
3295                                       gGraphAddLineToPath(gr, x, y);
3296                                       lastX = x;
3297                                       lastY = y;
3298                                     }
3299                                 }
3300                             }
3301                           gGraphCloseSubpath(gr);
3302                         }
3303                       if (fill == true)
3304                         gGraphFillPath(gr, GGRAPH_PRESERVE_PATH);
3305                       gGraphStrokePath(gr, GGRAPH_CLEAR_PATH);
3306                       pg = pg->Next;
3307                     }
3308                   gaiaLinestringPtr ln = geom->FirstLinestring;
3309                   while (ln)
3310                     {
3311                       // drawing a LINESTRING
3312                       int iv;
3313                       double dx;
3314                       double dy;
3315                       double z;
3316                       double m;
3317                       int x;
3318                       int y;
3319                       int lastX = 0;
3320                       int lastY = 0;
3321                       for (iv = 0; iv < ln->Points; iv++)
3322                         {
3323                           if (ln->DimensionModel == GAIA_XY_Z)
3324                             {
3325                               gaiaGetPointXYZ(ln->Coords, iv, &dx, &dy, &z);
3326                           } else if (ln->DimensionModel == GAIA_XY_M)
3327                             {
3328                               gaiaGetPointXYM(ln->Coords, iv, &dx, &dy, &m);
3329                           } else if (ln->DimensionModel == GAIA_XY_Z_M)
3330                             {
3331                               gaiaGetPointXYZM(ln->Coords, iv, &dx, &dy, &z,
3332                                                &m);
3333                           } else
3334                             {
3335                               gaiaGetPoint(ln->Coords, iv, &dx, &dy);
3336                             }
3337                           x = (int) ((dx - MinX) / ratio);
3338                           y = vert - (int) ((dy - MinY) / ratio);
3339                           x += h_shift;
3340                           y += v_shift;
3341                           if (iv == 0)
3342                             {
3343                               gGraphMoveToPoint(gr, x, y);
3344                               lastX = x;
3345                               lastY = y;
3346                           } else
3347                             {
3348                               if (x == lastX && y == lastY)
3349                                 ;
3350                               else
3351                                 {
3352                                   gGraphAddLineToPath(gr, x, y);
3353                                   lastX = x;
3354                                   lastY = y;
3355                                 }
3356                             }
3357                         }
3358                       gGraphStrokePath(gr, GGRAPH_CLEAR_PATH);
3359                       ln = ln->Next;
3360                     }
3361                   gaiaPointPtr pt = geom->FirstPoint;
3362                   while (pt)
3363                     {
3364                       // drawing a POINT
3365                       x = (int) ((pt->X - MinX) / ratio);
3366                       y = vsize - (int) ((pt->Y - MinY) / ratio);
3367                       x += h_shift;
3368                       y += v_shift;
3369                       if (circle == false)
3370                         gGraphDrawRectangle(gr, x - symbol_size,
3371                                             y - symbol_size, symbol_size * 2,
3372                                             symbol_size * 2);
3373                       else
3374                         gGraphDrawEllipse(gr, x - symbol_size, y - symbol_size,
3375                                           symbol_size * 2, symbol_size * 2);
3376                       pt = pt->Next;
3377                     }
3378                   gaiaFreeGeomColl(geom);
3379                 }
3380             }
3381       } else
3382         {
3383           sqlite3_finalize(stmt);
3384           sprintf(err_msg, "SQL error: %s",
3385                   sqlite3_errmsg(MainFrame->GetSqlite()));
3386           wxMessageBox(wxT("SQLite SQL error: ") + wxString::FromUTF8(err_msg),
3387                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
3388           ::wxEndBusyCursor();
3389           return;
3390         }
3391     }
3392   sqlite3_finalize(stmt);
3393   ::wxEndBusyCursor();
3394 
3395 // graphics finalization
3396   if (target == MAP_TARGET_IS_COPY || target == MAP_TARGET_IS_PNG
3397       || target == MAP_TARGET_IS_PREVIEW)
3398     gGraphGetContextRgbArray(gr, &rgb_array);
3399   if (target == MAP_TARGET_IS_SVG)
3400     gGraphDestroySvgContext(gr);
3401   else if (target == MAP_TARGET_IS_PDF)
3402     gGraphDestroyPdfContext(gr);
3403   else
3404     gGraphDestroyContext(gr);
3405 
3406   if (target == MAP_TARGET_IS_PNG)
3407     {
3408       if (rgb_array)
3409         {
3410           // creating the Image from RGB array
3411           const void *img =
3412             gGraphCreateRgbImageFromBitmap(rgb_array, hsize, vsize);
3413           if (img)
3414             {
3415               char xpath[2024];
3416               strcpy(xpath, ExportPath.ToUTF8());
3417               if (gGraphImageToPngFile(img, xpath, 6, 0, 0) != GGRAPH_OK)
3418                 {
3419                   wxString msg =
3420                     wxT
3421                     ("An error occurred while saving\nthe current Map as PNG");
3422                   wxMessageBox(msg, wxT("spatialite_gui"), wxOK | wxICON_ERROR,
3423                                MainFrame);
3424                 }
3425               gGraphDestroyImage(img);
3426             }
3427         }
3428     }
3429   if (target == MAP_TARGET_IS_PREVIEW)
3430     {
3431       if (rgb_array)
3432         {
3433           // creating the Image from RGB array
3434           wxImage img(hsize, vsize);
3435           img.SetData(rgb_array);
3436           wxBitmap bmp(img);
3437           MapShow->SetBitmap(bmp);
3438         }
3439     }
3440   if (target == MAP_TARGET_IS_COPY)
3441     {
3442       if (rgb_array)
3443         {
3444           // creating the Image from RGB array
3445           wxImage img(hsize, vsize);
3446           img.SetData(rgb_array);
3447           if (wxTheClipboard->Open())
3448             {
3449               wxTheClipboard->SetData(new wxBitmapDataObject(img));
3450               wxTheClipboard->Close();
3451             }
3452         }
3453     }
3454 }
3455 
OnMapCopy(wxCommandEvent & WXUNUSED (event))3456 void MapPreviewDialog::OnMapCopy(wxCommandEvent & WXUNUSED(event))
3457 {
3458 // copying the current Map to the Clipboard
3459   int hsize;
3460   int vsize;
3461   switch (SizeCtrl->GetSelection())
3462     {
3463       case 0:
3464         hsize = 256;
3465         vsize = 256;
3466         break;
3467       case 1:
3468         hsize = 512;
3469         vsize = 512;
3470         break;
3471       case 2:
3472         hsize = 1024;
3473         vsize = 1024;
3474         break;
3475       case 3:
3476         hsize = 2048;
3477         vsize = 2048;
3478         break;
3479       case 4:
3480         hsize = 4196;
3481         vsize = 4196;
3482         break;
3483     };
3484 
3485 // exporting the Map as COPY
3486   DoMap(hsize, vsize, MAP_TARGET_IS_COPY);
3487 }
3488 
OnMapPng(wxCommandEvent & WXUNUSED (event))3489 void MapPreviewDialog::OnMapPng(wxCommandEvent & WXUNUSED(event))
3490 {
3491 // exporting the current Chart as PNG
3492   int hsize;
3493   int vsize;
3494   switch (SizeCtrl->GetSelection())
3495     {
3496       case 0:
3497         hsize = 256;
3498         vsize = 256;
3499         break;
3500       case 1:
3501         hsize = 512;
3502         vsize = 512;
3503         break;
3504       case 2:
3505         hsize = 1024;
3506         vsize = 1024;
3507         break;
3508       case 3:
3509         hsize = 2048;
3510         vsize = 2048;
3511         break;
3512       case 4:
3513         hsize = 4196;
3514         vsize = 4196;
3515         break;
3516     };
3517 
3518 // asking an export path
3519   int ret;
3520   wxString lastDir;
3521   wxString fileList = wxT("PNG Image (*.png)|*.png");
3522   wxFileDialog fileDialog(MainFrame, wxT("saving the current Map as PNG"),
3523                           wxT(""), wxT("MapExport"), fileList,
3524                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
3525                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
3526   lastDir = MainFrame->GetLastDirectory();
3527   if (lastDir.Len() >= 1)
3528     fileDialog.SetDirectory(lastDir);
3529   ret = fileDialog.ShowModal();
3530   if (ret == wxID_OK)
3531     {
3532       wxFileName file(fileDialog.GetPath());
3533       lastDir = file.GetPath();
3534       MainFrame->SetLastDirectory(lastDir);
3535       wxString path = file.GetPath();
3536       path += file.GetPathSeparator();
3537       path += file.GetName();
3538       path += wxT(".png");
3539       ExportPath = path;
3540   } else
3541     return;
3542 
3543 // exporting the Map as PNG
3544   DoMap(hsize, vsize, MAP_TARGET_IS_PNG);
3545 }
3546 
OnMapSvg(wxCommandEvent & WXUNUSED (event))3547 void MapPreviewDialog::OnMapSvg(wxCommandEvent & WXUNUSED(event))
3548 {
3549 // exporting the current Map as SVG
3550   int hsize;
3551   int vsize;
3552   switch (SizeCtrl->GetSelection())
3553     {
3554       case 0:
3555         hsize = 256;
3556         vsize = 256;
3557         break;
3558       case 1:
3559         hsize = 512;
3560         vsize = 512;
3561         break;
3562       case 2:
3563         hsize = 1024;
3564         vsize = 1024;
3565         break;
3566       case 3:
3567         hsize = 2048;
3568         vsize = 2048;
3569         break;
3570       case 4:
3571         hsize = 4196;
3572         vsize = 4196;
3573         break;
3574     };
3575 
3576 // asking an export path
3577   int ret;
3578   wxString lastDir;
3579   wxString fileList = wxT("SVG Vector Image (*.svg)|*.svg");
3580   wxFileDialog fileDialog(MainFrame, wxT("saving the current Map as SVG"),
3581                           wxT(""), wxT("MapExport"), fileList,
3582                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
3583                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
3584   lastDir = MainFrame->GetLastDirectory();
3585   if (lastDir.Len() >= 1)
3586     fileDialog.SetDirectory(lastDir);
3587   ret = fileDialog.ShowModal();
3588   if (ret == wxID_OK)
3589     {
3590       wxFileName file(fileDialog.GetPath());
3591       lastDir = file.GetPath();
3592       MainFrame->SetLastDirectory(lastDir);
3593       wxString path = file.GetPath();
3594       path += file.GetPathSeparator();
3595       path += file.GetName();
3596       path += wxT(".svg");
3597       ExportPath = path;
3598   } else
3599     return;
3600 
3601 
3602 // exporting the Map as SVG
3603   DoMap(hsize, vsize, MAP_TARGET_IS_SVG);
3604 }
3605 
OnMapPdf(wxCommandEvent & WXUNUSED (event))3606 void MapPreviewDialog::OnMapPdf(wxCommandEvent & WXUNUSED(event))
3607 {
3608 // exporting the current Map as PDF
3609   double ext_x = MaxX - MinX;
3610   double ext_y = MaxY - MinY;
3611   int hsize = (int) (12.8 * 300.0);
3612   int vsize = (int) (9.0 * 300.0);
3613   hsize -= 100;                 // margin
3614   vsize -= 100;                 // margin
3615 
3616   if (ext_y > ext_x)
3617     {
3618       // portrait, not landscape orientation
3619       int swap = hsize;
3620       hsize = vsize;
3621       vsize = swap;
3622     }
3623 // asking an export path
3624   int ret;
3625   wxString lastDir;
3626   wxString fileList = wxT("PDF Document (*.pdf)|*.pdf");
3627   wxFileDialog fileDialog(MainFrame, wxT("saving the current Map as PDF"),
3628                           wxT(""), wxT("MapExport"), fileList,
3629                           wxFD_SAVE | wxFD_OVERWRITE_PROMPT,
3630                           wxDefaultPosition, wxDefaultSize, wxT("filedlg"));
3631   lastDir = MainFrame->GetLastDirectory();
3632   if (lastDir.Len() >= 1)
3633     fileDialog.SetDirectory(lastDir);
3634   ret = fileDialog.ShowModal();
3635   if (ret == wxID_OK)
3636     {
3637       wxFileName file(fileDialog.GetPath());
3638       lastDir = file.GetPath();
3639       MainFrame->SetLastDirectory(lastDir);
3640       wxString path = file.GetPath();
3641       path += file.GetPathSeparator();
3642       path += file.GetName();
3643       path += wxT(".pdf");
3644       ExportPath = path;
3645   } else
3646     return;
3647 
3648 
3649 // exporting the Map as PDF
3650   DoMap(hsize, vsize, MAP_TARGET_IS_PDF);
3651 }
3652 
OnExit(wxCommandEvent & WXUNUSED (event))3653 void MapPreviewDialog::OnExit(wxCommandEvent & WXUNUSED(event))
3654 {
3655 //
3656 // all done:
3657 //
3658   wxDialog::EndModal(wxID_OK);
3659 }
3660