/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.TXT for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #include #include #include #include #include #include #include #include "dialog_print_using_printer_base.h" #include #include #include #include #include "sch_printout.h" class DIALOG_PRINT_USING_PRINTER : public DIALOG_PRINT_USING_PRINTER_BASE { public: DIALOG_PRINT_USING_PRINTER( SCH_EDIT_FRAME* aParent ); ~DIALOG_PRINT_USING_PRINTER() override; protected: void OnOutputChoice( wxCommandEvent& event ) override; void OnUseColorThemeChecked( wxCommandEvent& event ) override; private: bool TransferDataToWindow() override; bool TransferDataFromWindow() override; void OnPageSetup( wxCommandEvent& event ) override; void OnPrintPreview( wxCommandEvent& event ) override; void SavePrintOptions(); SCH_EDIT_FRAME* m_parent; bool m_useCairo; }; /** * Custom schematic print preview frame. * This derived preview frame remembers its size and position during a session */ class SCH_PREVIEW_FRAME : public wxPreviewFrame { public: SCH_PREVIEW_FRAME( wxPrintPreview* aPreview, wxWindow* aParent, const wxString& aTitle, const wxPoint& aPos = wxDefaultPosition, const wxSize& aSize = wxDefaultSize ) : wxPreviewFrame( aPreview, aParent, aTitle, aPos, aSize ) { } bool Show( bool show ) override { bool ret; // Show or hide the window. If hiding, save current position and size. // If showing, use previous position and size. if( show ) { ret = wxPreviewFrame::Show( show ); if( s_size.x != 0 && s_size.y != 0 ) SetSize( s_pos.x, s_pos.y, s_size.x, s_size.y, 0 ); } else { // Save the dialog's position & size before hiding s_size = GetSize(); s_pos = GetPosition(); ret = wxPreviewFrame::Show( show ); } return ret; } private: static wxPoint s_pos; static wxSize s_size; }; wxPoint SCH_PREVIEW_FRAME::s_pos; wxSize SCH_PREVIEW_FRAME::s_size; DIALOG_PRINT_USING_PRINTER::DIALOG_PRINT_USING_PRINTER( SCH_EDIT_FRAME* aParent ) : DIALOG_PRINT_USING_PRINTER_BASE( aParent ), m_parent( aParent ) { wxASSERT( aParent ); m_useCairo = ADVANCED_CFG::GetCfg().m_EnableEeschemaPrintCairo; SetupStandardButtons( { { wxID_OK, _( "Print" ) }, { wxID_APPLY, _( "Print Preview" ) }, { wxID_CANCEL, _( "Close" ) } } ); #ifdef __WXMAC__ // Problems with modal on wx-2.9 - Anyway preview is standard for OSX m_sdbSizer1Apply->Hide(); #endif #if defined(__WXGTK__) // Preview using Cairo does not work on GTK, // but this platform provide native print preview if( m_useCairo ) m_sdbSizer1Apply->Hide(); #endif m_sdbSizer1OK->SetFocus(); finishDialogSettings(); } DIALOG_PRINT_USING_PRINTER::~DIALOG_PRINT_USING_PRINTER() { SavePrintOptions(); } bool DIALOG_PRINT_USING_PRINTER::TransferDataToWindow() { EESCHEMA_SETTINGS* cfg = m_parent->eeconfig(); if( cfg->m_Printing.monochrome ) { m_checkBackgroundColor->SetValue( false ); m_checkBackgroundColor->Enable( false ); } m_checkReference->SetValue( cfg->m_Printing.title_block ); m_colorPrint->SetSelection( cfg->m_Printing.monochrome ? 1 : 0 ); m_checkBackgroundColor->SetValue( cfg->m_Printing.background ); m_checkUseColorTheme->SetValue( cfg->m_Printing.use_theme ); m_colorTheme->Clear(); int width = 0; int height = 0; int minwidth = width; wxString target = cfg->m_Printing.use_theme ? cfg->m_Printing.color_theme : cfg->m_ColorTheme; for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() ) { int pos = m_colorTheme->Append( settings->GetName(), static_cast( settings ) ); if( settings->GetFilename() == target ) m_colorTheme->SetSelection( pos ); m_colorTheme->GetTextExtent( settings->GetName(), &width, &height ); minwidth = std::max( minwidth, width ); } m_colorTheme->SetMinSize( wxSize( minwidth + 50, -1 ) ); m_colorTheme->Enable( cfg->m_Printing.use_theme ); // Initialize page specific print setup dialog settings. const PAGE_INFO& pageInfo = m_parent->GetScreen()->GetPageSettings(); wxPageSetupDialogData& pageSetupDialogData = m_parent->GetPageSetupData(); pageSetupDialogData.SetPaperId( pageInfo.GetPaperId() ); if( pageInfo.IsCustom() ) { if( pageInfo.IsPortrait() ) pageSetupDialogData.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ), EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) ); else pageSetupDialogData.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ), EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) ); } pageSetupDialogData.GetPrintData().SetOrientation( pageInfo.GetWxOrientation() ); Layout(); return true; } void DIALOG_PRINT_USING_PRINTER::OnUseColorThemeChecked( wxCommandEvent& event ) { m_colorTheme->Enable( m_checkUseColorTheme->GetValue() ); } void DIALOG_PRINT_USING_PRINTER::OnOutputChoice( wxCommandEvent& event ) { long sel = event.GetSelection(); m_checkBackgroundColor->Enable( sel == 0 ); if( sel ) m_checkBackgroundColor->SetValue( false ); else m_checkBackgroundColor->SetValue( m_parent->eeconfig()->m_Printing.background ); } void DIALOG_PRINT_USING_PRINTER::SavePrintOptions() { EESCHEMA_SETTINGS* cfg = m_parent->eeconfig(); cfg->m_Printing.monochrome = !!m_colorPrint->GetSelection(); cfg->m_Printing.title_block = m_checkReference->IsChecked(); if( m_checkBackgroundColor->IsEnabled() ) cfg->m_Printing.background = m_checkBackgroundColor->IsChecked(); else cfg->m_Printing.background = false; cfg->m_Printing.use_theme = m_checkUseColorTheme->IsChecked(); COLOR_SETTINGS* theme = static_cast( m_colorTheme->GetClientData( m_colorTheme->GetSelection() ) ); if( theme && m_checkUseColorTheme->IsChecked() ) cfg->m_Printing.color_theme = theme->GetFilename(); } void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event ) { wxPageSetupDialog pageSetupDialog( this, &m_parent->GetPageSetupData() ); pageSetupDialog.ShowModal(); m_parent->GetPageSetupData() = pageSetupDialog.GetPageSetupDialogData(); } void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event ) { SavePrintOptions(); // Pass two printout objects: for preview, and possible printing. wxString title = _( "Preview" ); wxPrintPreview* preview = new wxPrintPreview( new SCH_PRINTOUT( m_parent, title, m_useCairo ), new SCH_PRINTOUT( m_parent, title, m_useCairo ), &m_parent->GetPageSetupData().GetPrintData() ); preview->SetZoom( 100 ); SCH_PREVIEW_FRAME* frame = new SCH_PREVIEW_FRAME( preview, this, title ); // On wxGTK, set the flag wxTOPLEVEL_EX_DIALOG is mandatory, if we want // close the frame using the X box in caption, when the preview frame is run // from a dialog frame->SetExtraStyle( frame->GetExtraStyle() | wxTOPLEVEL_EX_DIALOG ); // We use here wxPreviewFrame_WindowModal option to make the wxPrintPreview frame // modal for its caller only. // another reason is the fact when closing the frame without this option, // all top level frames are reenabled. // With this option, only the parent is reenabled. // Reenabling all top level frames should be made by the parent dialog. frame->InitializeWithModality( wxPreviewFrame_WindowModal ); // on first invocation in this runtime session, set to 3/4 size of parent, // but will be changed in Show() if not first time as will position. // Must be called after InitializeWithModality because otherwise in some wxWidget // versions it is not always taken in account frame->SetMinSize( wxSize( 650, 500 ) ); frame->SetSize( (m_parent->GetSize() * 3) / 4 ); frame->Raise(); // Needed on Ubuntu/Unity to display the frame frame->Show( true ); } bool DIALOG_PRINT_USING_PRINTER::TransferDataFromWindow() { if( Pgm().m_Printing ) { DisplayError( this, _( "Previous print job not yet complete." ) ); return false; } SavePrintOptions(); int sheet_count = m_parent->Schematic().Root().CountSheets(); wxPrintData data = m_parent->GetPageSetupData().GetPrintData(); #if defined( __WXGTK__ ) && !wxCHECK_VERSION( 3, 2, 3 ) // In GTK, the default bottom margin is bigger by 0.31 inches for // Letter, Legal, A4 paper sizes (see gtk_paper_size_get_default_bottom_margin). // // wxWidgets doesn't handle this properly when paper is in // landscape orientation. // // Using custom page size avoids the problematic // gtk_page_setup_set_paper_size_and_default_margins call in wxWidgets. wxPaperSize paperId = data.GetPaperId(); const wxChar* paperType = nullptr; // clang-format off std::set letterSizes = { // na_letter wxPAPER_LETTER, wxPAPER_LETTERSMALL, wxPAPER_NOTE, wxPAPER_LETTER_TRANSVERSE, wxPAPER_LETTER_ROTATED }; std::set legalSizes = { // na_legal wxPAPER_LEGAL }; std::set a4Sizes = { // iso_a4 wxPAPER_A4, wxPAPER_A4SMALL, wxPAPER_A4_TRANSVERSE, wxPAPER_A4_ROTATED }; // clang-format on if( letterSizes.count( paperId ) ) paperType = PAGE_INFO::USLetter; else if( legalSizes.count( paperId ) ) paperType = PAGE_INFO::USLegal; else if( a4Sizes.count( paperId ) ) paperType = PAGE_INFO::A4; if( paperType ) { PAGE_INFO pageInfo( paperType, data.GetOrientation() == wxPORTRAIT ); if( pageInfo.IsPortrait() ) data.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ), EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ) ) ); else data.SetPaperSize( wxSize( EDA_UNIT_UTILS::Mils2mm( pageInfo.GetHeightMils() ), EDA_UNIT_UTILS::Mils2mm( pageInfo.GetWidthMils() ) ) ); data.SetOrientation( pageInfo.GetWxOrientation() ); data.SetPaperId( wxPAPER_NONE ); } #endif wxPrintDialogData printDialogData( data ); printDialogData.SetMaxPage( sheet_count ); if( sheet_count > 1 ) printDialogData.EnablePageNumbers( true ); wxPrinter printer( &printDialogData ); SCH_PRINTOUT printout( m_parent, _( "Print Schematic" ), m_useCairo ); Pgm().m_Printing = true; { if( !printer.Print( this, &printout, true ) ) { if( wxPrinter::GetLastError() == wxPRINTER_ERROR ) DisplayError( this, _( "An error occurred attempting to print the schematic." ) ); } else { m_parent->GetPageSetupData() = printer.GetPrintDialogData().GetPrintData(); } } Pgm().m_Printing = false; return true; } int InvokeDialogPrintUsingPrinter( SCH_EDIT_FRAME* aCaller ) { DIALOG_PRINT_USING_PRINTER dlg( aCaller ); return dlg.ShowModal(); }