// This file is part of fityk program. Copyright (C) Marcin Wojdyr
// Licence: GNU General Public License version 2
// $Id: print.cpp 264 2007-03-01 10:10:54Z wojdyr $
/// In this file:
/// printing related utilities
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <vector>
#include <wx/paper.h>
#include <wx/statline.h>
//TODO
#include <wx/generic/printps.h>
#include <wx/generic/prntdlgg.h>
#include "print.h"
#include "cmn.h"
#include "pane.h"
#include "plot.h"
#include "mplot.h"
#include "aplot.h"
using namespace std;
//======================================================================
// PageSetupDialog
//======================================================================
BEGIN_EVENT_TABLE(PageSetupDialog, wxDialog)
EVT_BUTTON(wxID_OK, PageSetupDialog::OnOk)
END_EVENT_TABLE()
PageSetupDialog::PageSetupDialog(wxWindow *parent, PrintManager *print_mgr)
: wxDialog(parent, -1, wxT("Page Setup"),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER),
pm(print_mgr)
{
wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL);
//paper size
wxStaticBoxSizer *sizerp = new wxStaticBoxSizer(wxVERTICAL, this,
wxT("Paper Size"));
wxArrayString paper_sizes;
int paper_sel = 0;
for (size_t i = 0; i < wxThePrintPaperDatabase->GetCount(); ++i) {
wxPrintPaperType *papertype = wxThePrintPaperDatabase->Item(i);
paper_sizes.Add(papertype->GetName());
if (pm->get_print_data().GetPaperId() == papertype->GetId())
paper_sel = i;
}
papers = new wxComboBox(this, -1, _("Paper Size"),
wxDefaultPosition, wxDefaultSize,
paper_sizes, wxCB_READONLY);
papers->SetSelection(paper_sel);
sizerp->Add(papers, 1, wxALL|wxEXPAND, 5);
top_sizer->Add(sizerp, 0, wxALL|wxEXPAND, 5);
//orientation
wxString orient_choices[] = { wxT("Portrait"), wxT("Landscape") };
orientation = new wxRadioBox(this, -1, wxT("Orientation"),
wxDefaultPosition, wxDefaultSize,
2, orient_choices,
2, wxRA_SPECIFY_COLS);
top_sizer->Add(orientation, 0, wxALL|wxEXPAND, 5);
/* TODO what about margins?
wxStaticBox *margbox = new wxStaticBox(this, -1,
wxT("Margins (millimetres)"));
wxStaticBoxSizer *hsizer = new wxStaticBoxSizer(margbox, wxHORIZONTAL);
hsizer->Add(new wxStaticText(this, -1, wxT(" Left")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
left_margin = new SpinCtrl(this, -1, 0, -100, 500);
hsizer->Add(left_margin, 0, wxALL, 5);
hsizer->Add(new wxStaticText(this, -1, wxT(" Right")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
right_margin = new SpinCtrl(this, -1, 0, -100, 500);
hsizer->Add(right_margin, 0, wxALL, 5);
hsizer->Add(new wxStaticText(this, -1, wxT(" Top")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
top_margin = new SpinCtrl(this, -1, 0, -100, 500);
hsizer->Add(top_margin, 0, wxALL, 5);
hsizer->Add(new wxStaticText(this, -1, wxT(" Bottom")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
bottom_margin = new SpinCtrl(this, -1, 0, -100, 500);
hsizer->Add(bottom_margin, 0, wxALL, 5);
top_sizer->Add(hsizer, 0, wxALL|wxEXPAND, 5);
*/
wxBoxSizer *h2sizer = new wxBoxSizer(wxHORIZONTAL);
h2sizer->Add(new wxStaticText(this, -1, wxT("Scale to")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
scale = new SpinCtrl(this, -1, 100, 1, 150);
h2sizer->Add(scale, 0, wxTOP|wxBOTTOM, 5);
h2sizer->Add(new wxStaticText(this, -1, wxT("% of page")),
0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
top_sizer->Add(h2sizer);
keep_ratio = new wxCheckBox(this, -1, wxT("keep width to height ratio"));
top_sizer->Add(keep_ratio, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
wxString color_choices[] = { wxT("black lines on white background"),
wxT("colors from plots on white background") };
colors = new wxRadioBox(this, -1, wxT("Colors"),
wxDefaultPosition, wxDefaultSize,
2, color_choices,
1, wxRA_SPECIFY_COLS);
top_sizer->Add(colors, 0, wxALL|wxEXPAND, 5);
wxStaticBoxSizer *boxsizer = new wxStaticBoxSizer(wxVERTICAL, this,
wxT("Optional elements"));
for (int i = 0; i < 2; ++i) {
plot_aux[i] = new wxCheckBox(this, -1,
wxString::Format(wxT("auxiliary plot %i"), i));
boxsizer->Add(plot_aux[i], 0, wxALL, 5);
}
plot_borders = new wxCheckBox(this, -1, wxT("borders around plots"));
boxsizer->Add(plot_borders, 0, wxALL, 5);
top_sizer->Add(boxsizer, 0, wxALL|wxEXPAND, 5);
top_sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5);
top_sizer->Add(CreateButtonSizer(wxOK|wxCANCEL),
0, wxALL|wxALIGN_CENTER, 5);
SetSizerAndFit(top_sizer);
orientation->SetSelection(pm->landscape ? 1 : 0);
colors->SetSelection(pm->colors ? 1 : 0);
keep_ratio->SetValue(pm->keep_ratio);
scale->SetValue(pm->scale);
for (int i = 0; i < 2; ++i) {
if (pm->plot_pane->aux_visible(i)) {
plot_aux[i]->SetValue(pm->plot_aux[i]);
}
else {
plot_aux[i]->SetValue(false);
plot_aux[i]->Enable(false);
}
}
plot_borders->SetValue(pm->plot_borders);
/*
left_margin->SetValue(pm->get_page_data().GetMarginTopLeft().x);
right_margin->SetValue(pm->get_page_data().GetMarginBottomRight().x);
top_margin->SetValue(pm->get_page_data().GetMarginTopLeft().y);
bottom_margin->SetValue(pm->get_page_data().GetMarginBottomRight().y);
*/
}
void PageSetupDialog::OnOk(wxCommandEvent&)
{
if (papers->GetSelection() != -1) {
wxPrintPaperType *ppt
= wxThePrintPaperDatabase->Item(papers->GetSelection());
if (ppt) {
pm->get_page_data().SetPaperSize(wxSize(ppt->GetWidth()/10,
ppt->GetHeight()/10));
pm->get_print_data().SetPaperId(ppt->GetId());
}
}
pm->landscape = (orientation->GetSelection() == 1);
pm->colors = colors->GetSelection() == 1;
pm->keep_ratio = keep_ratio->GetValue();
pm->scale = scale->GetValue();
for (int i = 0; i < 2; ++i)
pm->plot_aux[i] = plot_aux[i]->GetValue();
pm->plot_borders = plot_borders->GetValue();
/*
pm->get_page_data().GetMarginTopLeft().x = left_margin->GetValue();
pm->get_page_data().GetMarginBottomRight().x = right_margin->GetValue();
pm->get_page_data().GetMarginTopLeft().y = top_margin->GetValue();
pm->get_page_data().GetMarginBottomRight().y = bottom_margin->GetValue();
*/
close_it(this, wxID_OK);
}
//===============================================================
// Printing utilities
//===============================================================
void do_print_plots(wxDC *dc, PrintManager const* pm)
{
// Set the scale and origin
const int space = 10; //vertical space between plots
const int marginX = 50, marginY = 50; //page margins
//width is the same for all plots
int width = pm->plot_pane->GetClientSize().GetWidth();
vector<FPlot*> vp;
vp.push_back(pm->plot_pane->get_plot());
for (int i = 0; i < 2; ++i)
if (pm->plot_pane->aux_visible(i) && pm->plot_aux[i])
vp.push_back(pm->plot_pane->get_aux_plot(i));
int height = -space; //height = sum of all heights + (N-1)*space
for (vector<FPlot*>::const_iterator i = vp.begin(); i != vp.end(); ++i)
height += (*i)->GetClientSize().GetHeight() + space;
int w, h;
dc->GetSize(&w, &h);
fp scaleX = w / (width + 2.*marginX) * pm->scale/100.;
fp scaleY = h / (height + 2.*marginY) * pm->scale/100.;
if (pm->keep_ratio) {
if (scaleX > scaleY)
scaleX = scaleY;
else
scaleY = scaleX;
}
dc->SetUserScale (scaleX, scaleY);
const int posX = iround((w - width * scaleX) / 2.);
int posY = iround((h - height * scaleY) / 2.);
//drawing all visible plots, every at different posY
for (vector<FPlot*>::const_iterator i = vp.begin(); i != vp.end(); ++i) {
dc->SetDeviceOrigin (posX, posY);
if (pm->plot_borders && i != vp.begin()) {
int Y = -space/2;
dc->DrawLine(0, Y, width, Y);
}
int plot_height = (*i)->GetClientSize().GetHeight();
dc->SetClippingRegion(0, 0, width, plot_height);
(*i)->draw(*dc, !pm->colors);
dc->DestroyClippingRegion();
posY += iround((plot_height+space) * scaleY);
}
}
//===============================================================
FPrintout::FPrintout(PrintManager const* print_manager)
: wxPrintout(wxT("fityk")), pm(print_manager)
{}
bool FPrintout::OnPrintPage(int page)
{
if (page != 1)
return false;
wxDC *dc = GetDC();
if (!dc)
return false;
do_print_plots(dc, pm);
return true;
}
//===============================================================
class FPreviewFrame : public wxPreviewFrame
{
public:
FPreviewFrame(wxPrintPreview* preview, wxWindow* parent)
: wxPreviewFrame (preview, parent, wxT("Print Preview"),
wxDefaultPosition, wxSize(600, 550)) {}
void CreateControlBar() {
m_controlBar = new wxPreviewControlBar(m_printPreview,
wxPREVIEW_PRINT|wxPREVIEW_ZOOM, this);
m_controlBar->CreateButtons();
m_controlBar->SetZoomControl(110);
}
};
//===============================================================
PrintManager::PrintManager(PlotPane* pane)
: plot_pane(pane), print_data(0), page_setup_data(0)
{
read_settings(wxConfig::Get());
}
PrintManager::~PrintManager()
{
save_settings(wxConfig::Get());
if (print_data)
delete print_data;
if (page_setup_data)
delete page_setup_data;
}
void PrintManager::save_settings(wxConfigBase *cf) const
{
cf->Write(wxT("/print/colors"), colors);
cf->Write(wxT("/print/scale"), scale);
cf->Write(wxT("/print/keepRatio"), keep_ratio);
cf->Write(wxT("/print/plotBorders"), plot_borders);
for (int i = 0; i < 2; ++i)
cf->Write(wxString::Format(wxT("/print/plotAux%i"), i), plot_aux[i]);
cf->Write(wxT("/print/landscape"), landscape);
}
void PrintManager::read_settings(wxConfigBase *cf)
{
colors = cfg_read_bool(cf, wxT("/print/colors"), false);
scale = cf->Read(wxT("/print/scale"), 100);
keep_ratio = cfg_read_bool(cf, wxT("/print/keepRatio"), false);
plot_borders = cfg_read_bool(cf, wxT("/print/plotBorders"), true);
for (int i = 0; i < 2; ++i)
plot_aux[i] = cfg_read_bool(cf,
wxString::Format(wxT("/print/plotAux%i"), i), true);
landscape = cfg_read_bool(cf, wxT("/print/landscape"), true);
}
wxPrintData& PrintManager::get_print_data()
{
if (!print_data) {
print_data = new wxPrintData;
print_data->SetOrientation(landscape ? wxLANDSCAPE : wxPORTRAIT);
}
return *print_data;
}
wxPageSetupDialogData& PrintManager::get_page_data()
{
if (!page_setup_data)
page_setup_data = new wxPageSetupDialogData;
return *page_setup_data;
}
void PrintManager::printPreview()
{
// Pass two printout objects: for preview, and possible printing.
wxPrintDialogData print_dialog_data(get_print_data());
wxPrintPreview *preview = new wxPrintPreview (new FPrintout(this),
new FPrintout(this),
&print_dialog_data);
if (!preview->Ok()) {
delete preview;
wxMessageBox(wxT("There was a problem previewing.\n")
wxT("Perhaps your current printer is not set correctly?"),
wxT("Previewing"), wxOK);
return;
}
FPreviewFrame *preview_frame = new FPreviewFrame (preview, 0);
preview_frame->Centre(wxBOTH);
preview_frame->Initialize();
preview_frame->Show(true);
}
void PrintManager::pageSetup()
{
PageSetupDialog dlg(0, this);
dlg.ShowModal();
/*
* Old standard wxWidgets "page setup" dlg worked in this way:
if (!page_setup_data)
page_setup_data = new wxPageSetupDialogData(get_print_data());
else
(*page_setup_data) = get_print_data();
wxPageSetupDialog page_setup_dialog(this, page_setup_data);
page_setup_dialog.ShowModal();
get_print_data()=page_setup_dialog.GetPageSetupData().GetPrintData();
(*page_setup_data) = page_setup_dialog.GetPageSetupData();
*/
}
void PrintManager::print()
{
wxPrintDialogData print_dialog_data(get_print_data());
print_dialog_data.SetFromPage(1);
print_dialog_data.SetToPage(1);
print_dialog_data.EnablePageNumbers(false);
print_dialog_data.EnableSelection(false);
wxPrinter printer (&print_dialog_data);
FPrintout printout(this);
bool r = printer.Print(0, &printout, true);
if (r) {
get_print_data() = printer.GetPrintDialogData().GetPrintData();
landscape = (get_print_data().GetOrientation() == wxLANDSCAPE);
}
else if (wxPrinter::GetLastError() == wxPRINTER_ERROR)
wxMessageBox(wxT("There was a problem printing.\nPerhaps your current ")
wxT("printer is not set correctly?"),
wxT("Printing"), wxOK);
}
void PrintManager::print_to_psfile()
{
wxFileDialog dialog(0, wxT("PostScript file"), wxT(""), wxT(""),
wxT("*.ps"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if (dialog.ShowModal() != wxID_OK)
return;
get_print_data().SetPrintMode(wxPRINT_MODE_FILE);
get_print_data().SetFilename(dialog.GetPath());
wxPrintDialogData print_dialog_data(get_print_data());
print_dialog_data.SetFromPage(1);
print_dialog_data.SetToPage(1);
wxPostScriptPrinter printer (&print_dialog_data);
FPrintout printout(this);
bool r = printer.Print(0, &printout, false);
if (!r)
wxMessageBox(wxT("Can't save plots as a file:\n") + dialog.GetPath(),
wxT("Exporting to PostScript"), wxOK|wxICON_ERROR);
}
syntax highlighted by Code2HTML, v. 0.9.1