diff options
Diffstat (limited to 'pcbnew/dialogs/dialog_print_using_printer.cpp')
-rw-r--r-- | pcbnew/dialogs/dialog_print_using_printer.cpp | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/pcbnew/dialogs/dialog_print_using_printer.cpp b/pcbnew/dialogs/dialog_print_using_printer.cpp new file mode 100644 index 0000000..05b7d62 --- /dev/null +++ b/pcbnew/dialogs/dialog_print_using_printer.cpp @@ -0,0 +1,518 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr + * Copyright (C) 1992-2015 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 + */ + +// Set this to 1 if you want to test PostScript printing under MSW. +//#define wxTEST_POSTSCRIPT_IN_MSW 1 + +#include <fctsys.h> +#include <kiface_i.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <wxPcbStruct.h> +#include <base_units.h> + +#include <printout_controler.h> +#include <pcbnew.h> +#include <pcbplot.h> + +#include <class_board.h> + +#include <dialog_print_using_printer_base.h> + + +#define PEN_WIDTH_MAX_VALUE ( KiROUND( 5 * IU_PER_MM ) ) +#define PEN_WIDTH_MIN_VALUE ( KiROUND( 0.005 * IU_PER_MM ) ) + + +extern int g_DrawDefaultLineThickness; + +// Local variables +static LSET s_SelectedLayers; +static double s_ScaleList[] = +{ 0, 0.5, 0.7, 0.999, 1.0, 1.4, 2.0, 3.0, 4.0 }; + +// Define min et max reasonable values for print scale +#define MIN_SCALE 0.01 +#define MAX_SCALE 100.0 + +// static print data and page setup data, to remember settings during the session +static wxPrintData* s_PrintData; +static wxPageSetupDialogData* s_pageSetupData = (wxPageSetupDialogData*) NULL; + +static PRINT_PARAMETERS s_Parameters; + + +/** + * Dialog to print schematic. Class derived from DIALOG_PRINT_USING_PRINTER_base + * created by wxFormBuilder + */ +class DIALOG_PRINT_USING_PRINTER : public DIALOG_PRINT_USING_PRINTER_base +{ +public: + DIALOG_PRINT_USING_PRINTER( PCB_EDIT_FRAME* parent ); + + bool IsMirrored() { return m_Print_Mirror->IsChecked(); } + bool ExcludeEdges() { return m_Exclude_Edges_Pcb->IsChecked(); } + bool PrintUsingSinglePage() { return m_PagesOption->GetSelection(); } + int SetLayerSetFromListSelection(); + + +private: + + PCB_EDIT_FRAME* m_parent; + wxConfigBase* m_config; + wxCheckBox* m_BoxSelectLayer[LAYER_ID_COUNT]; + static bool m_ExcludeEdgeLayer; + + void OnCloseWindow( wxCloseEvent& event ); + void OnPageSetup( wxCommandEvent& event ); + void OnPrintPreview( wxCommandEvent& event ); + void OnPrintButtonClick( wxCommandEvent& event ); + void OnScaleSelectionClick( wxCommandEvent& event ); + + void OnButtonCancelClick( wxCommandEvent& event ) { Close(); } + void SetPrintParameters( ); + void SetPenWidth(); + void initValues( ); +}; + + +bool DIALOG_PRINT_USING_PRINTER::m_ExcludeEdgeLayer; + + +void PCB_EDIT_FRAME::ToPrinter( wxCommandEvent& event ) +{ + const PAGE_INFO& pageInfo = GetPageSettings(); + + if( s_PrintData == NULL ) // First print + { + s_PrintData = new wxPrintData(); + + if( !s_PrintData->Ok() ) + { + DisplayError( this, _( "Error Init Printer info" ) ); + } + s_PrintData->SetQuality( wxPRINT_QUALITY_HIGH ); // Default resolution = HIGH; + } + + if( s_pageSetupData == NULL ) + s_pageSetupData = new wxPageSetupDialogData( *s_PrintData ); + + s_pageSetupData->SetPaperId( pageInfo.GetPaperId() ); + s_pageSetupData->GetPrintData().SetOrientation( pageInfo.GetWxOrientation() ); + + if( pageInfo.IsCustom() ) + { + if( pageInfo.IsPortrait() ) + s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetWidthMils() ), + Mils2mm( pageInfo.GetHeightMils() ) ) ); + else + s_pageSetupData->SetPaperSize( wxSize( Mils2mm( pageInfo.GetHeightMils() ), + Mils2mm( pageInfo.GetWidthMils() ) ) ); + } + + *s_PrintData = s_pageSetupData->GetPrintData(); + + DIALOG_PRINT_USING_PRINTER dlg( this ); + + dlg.ShowModal(); +} + + +DIALOG_PRINT_USING_PRINTER::DIALOG_PRINT_USING_PRINTER( PCB_EDIT_FRAME* parent ) : + DIALOG_PRINT_USING_PRINTER_base( parent ) +{ + m_parent = parent; + m_config = Kiface().KifaceSettings(); + memset( m_BoxSelectLayer, 0, sizeof( m_BoxSelectLayer ) ); + + initValues( ); + + GetSizer()->SetSizeHints( this ); + Center(); +#ifdef __WXMAC__ + /* Problems with modal on wx-2.9 - Anyway preview is standard for OSX */ + m_buttonPreview->Hide(); +#endif + + GetSizer()->Fit( this ); +} + + +void DIALOG_PRINT_USING_PRINTER::initValues( ) +{ + wxString msg; + BOARD* board = m_parent->GetBoard(); + + s_Parameters.m_PageSetupData = s_pageSetupData; + + // Create layer list. + wxString layerKey; + + LSEQ seq = board->GetEnabledLayers().UIOrder(); + + for( ; seq; ++seq ) + { + LAYER_ID layer = *seq; + + m_BoxSelectLayer[layer] = new wxCheckBox( this, -1, board->GetLayerName( layer ) ); + + if( IsCopperLayer( layer ) ) + m_CopperLayersBoxSizer->Add( m_BoxSelectLayer[layer], 0, wxGROW | wxALL, 1 ); + else + m_TechnicalLayersBoxSizer->Add( m_BoxSelectLayer[layer], 0, wxGROW | wxALL, 1 ); + + layerKey.Printf( OPTKEY_LAYERBASE, layer ); + + bool option; + + if( m_config->Read( layerKey, &option ) ) + m_BoxSelectLayer[layer]->SetValue( option ); + else + { + if( s_SelectedLayers[layer] ) + m_BoxSelectLayer[layer]->SetValue( true ); + } + } + + // Option for excluding contents of "Edges Pcb" layer + m_Exclude_Edges_Pcb->Show( true ); + + // Read the scale adjust option + int scale_idx = 4; // default selected scale = ScaleList[4] = 1.000 + + if( m_config ) + { + m_config->Read( OPTKEY_PRINT_X_FINESCALE_ADJ, &s_Parameters.m_XScaleAdjust ); + m_config->Read( OPTKEY_PRINT_Y_FINESCALE_ADJ, &s_Parameters.m_YScaleAdjust ); + m_config->Read( OPTKEY_PRINT_SCALE, &scale_idx ); + m_config->Read( OPTKEY_PRINT_PAGE_FRAME, &s_Parameters.m_Print_Sheet_Ref, 1); + m_config->Read( OPTKEY_PRINT_MONOCHROME_MODE, &s_Parameters.m_Print_Black_and_White, 1); + m_config->Read( OPTKEY_PRINT_PAGE_PER_LAYER, &s_Parameters.m_OptionPrintPage, 0); + int tmp; + m_config->Read( OPTKEY_PRINT_PADS_DRILL, &tmp, PRINT_PARAMETERS::SMALL_DRILL_SHAPE ); + s_Parameters.m_DrillShapeOpt = (PRINT_PARAMETERS::DrillShapeOptT) tmp; + + // Test for a reasonable scale value. Set to 1 if problem + if( s_Parameters.m_XScaleAdjust < MIN_SCALE || + s_Parameters.m_YScaleAdjust < MIN_SCALE || + s_Parameters.m_XScaleAdjust > MAX_SCALE || + s_Parameters.m_YScaleAdjust > MAX_SCALE ) + s_Parameters.m_XScaleAdjust = s_Parameters.m_YScaleAdjust = 1.0; + + s_SelectedLayers = LSET(); + + for( seq.Rewind(); seq; ++seq ) + { + LAYER_ID layer = *seq; + + wxString layerKey; + bool option; + + layerKey.Printf( OPTKEY_LAYERBASE, layer ); + + option = false; + if( m_config->Read( layerKey, &option ) ) + { + m_BoxSelectLayer[layer]->SetValue( option ); + if( option ) + s_SelectedLayers.set( layer ); + } + } + } + + m_ScaleOption->SetSelection( scale_idx ); + scale_idx = m_ScaleOption->GetSelection(); + s_Parameters.m_PrintScale = s_ScaleList[scale_idx]; + m_Print_Mirror->SetValue(s_Parameters.m_PrintMirror); + m_Exclude_Edges_Pcb->SetValue(m_ExcludeEdgeLayer); + m_Print_Sheet_Ref->SetValue( s_Parameters.m_Print_Sheet_Ref ); + + // Options to plot pads and vias holes + m_Drill_Shape_Opt->SetSelection( s_Parameters.m_DrillShapeOpt ); + + if( s_Parameters.m_Print_Black_and_White ) + m_ModeColorOption->SetSelection( 1 ); + else + m_ModeColorOption->SetSelection( 0 ); + + m_PagesOption->SetSelection(s_Parameters.m_OptionPrintPage); + s_Parameters.m_PenDefaultSize = g_DrawDefaultLineThickness; + AddUnitSymbol( *m_TextPenWidth, g_UserUnit ); + m_DialogPenWidth->SetValue( + StringFromValue( g_UserUnit, s_Parameters.m_PenDefaultSize ) ); + + // Create scale adjust option + msg.Printf( wxT( "%f" ), s_Parameters.m_XScaleAdjust ); + m_FineAdjustXscaleOpt->SetValue( msg ); + + msg.Printf( wxT( "%f" ), s_Parameters.m_YScaleAdjust ); + m_FineAdjustYscaleOpt->SetValue( msg ); + + bool enable = (s_Parameters.m_PrintScale == 1.0); + m_FineAdjustXscaleOpt->Enable(enable); + m_FineAdjustYscaleOpt->Enable(enable); +} + + +int DIALOG_PRINT_USING_PRINTER::SetLayerSetFromListSelection() +{ + int page_count = 0; + + s_Parameters.m_PrintMaskLayer = LSET(); + + for( unsigned ii = 0; ii < DIM(m_BoxSelectLayer); ++ii ) + { + if( !m_BoxSelectLayer[ii] ) + continue; + + if( m_BoxSelectLayer[ii]->IsChecked() ) + { + page_count++; + s_Parameters.m_PrintMaskLayer.set( ii ); + } + } + + // In Pcbnew force the EDGE layer to be printed or not with the other layers + m_ExcludeEdgeLayer = m_Exclude_Edges_Pcb->IsChecked(); + if( m_ExcludeEdgeLayer ) + s_Parameters.m_Flags = 0; + else + s_Parameters.m_Flags = 1; + + s_Parameters.m_PageCount = page_count; + + return page_count; +} + + +void DIALOG_PRINT_USING_PRINTER::OnCloseWindow( wxCloseEvent& event ) +{ + SetPrintParameters(); + + if( m_config ) + { + ConfigBaseWriteDouble( m_config, OPTKEY_PRINT_X_FINESCALE_ADJ, + s_Parameters.m_XScaleAdjust ); + ConfigBaseWriteDouble( m_config, OPTKEY_PRINT_Y_FINESCALE_ADJ, + s_Parameters.m_YScaleAdjust ); + m_config->Write( OPTKEY_PRINT_SCALE, m_ScaleOption->GetSelection() ); + m_config->Write( OPTKEY_PRINT_PAGE_FRAME, s_Parameters.m_Print_Sheet_Ref); + m_config->Write( OPTKEY_PRINT_MONOCHROME_MODE, s_Parameters.m_Print_Black_and_White); + m_config->Write( OPTKEY_PRINT_PAGE_PER_LAYER, s_Parameters.m_OptionPrintPage ); + m_config->Write( OPTKEY_PRINT_PADS_DRILL, (long) s_Parameters.m_DrillShapeOpt ); + wxString layerKey; + + for( unsigned layer = 0; layer < DIM(m_BoxSelectLayer); ++layer ) + { + if( !m_BoxSelectLayer[layer] ) + continue; + + layerKey.Printf( OPTKEY_LAYERBASE, layer ); + m_config->Write( layerKey, m_BoxSelectLayer[layer]->IsChecked() ); + } + } + + EndModal( 0 ); +} + + +void DIALOG_PRINT_USING_PRINTER::SetPrintParameters( ) +{ + PCB_PLOT_PARAMS plot_opts = m_parent->GetPlotSettings(); + + s_Parameters.m_PrintMirror = m_Print_Mirror->GetValue(); + s_Parameters.m_Print_Sheet_Ref = m_Print_Sheet_Ref->GetValue(); + s_Parameters.m_Print_Black_and_White = + m_ModeColorOption->GetSelection() != 0; + + s_Parameters.m_DrillShapeOpt = + (PRINT_PARAMETERS::DrillShapeOptT) m_Drill_Shape_Opt->GetSelection(); + + if( m_PagesOption ) + s_Parameters.m_OptionPrintPage = m_PagesOption->GetSelection() != 0; + + SetLayerSetFromListSelection(); + + int idx = m_ScaleOption->GetSelection(); + s_Parameters.m_PrintScale = s_ScaleList[idx]; + plot_opts.SetScale( s_Parameters.m_PrintScale ); + + if( m_FineAdjustXscaleOpt ) + { + if( s_Parameters.m_XScaleAdjust > MAX_SCALE || + s_Parameters.m_YScaleAdjust > MAX_SCALE ) + DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very large value" ) ); + + m_FineAdjustXscaleOpt->GetValue().ToDouble( &s_Parameters.m_XScaleAdjust ); + } + + if( m_FineAdjustYscaleOpt ) + { + // Test for a reasonable scale value + if( s_Parameters.m_XScaleAdjust < MIN_SCALE || + s_Parameters.m_YScaleAdjust < MIN_SCALE ) + DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very small value" ) ); + + m_FineAdjustYscaleOpt->GetValue().ToDouble( &s_Parameters.m_YScaleAdjust ); + } + + plot_opts.SetFineScaleAdjustX( s_Parameters.m_XScaleAdjust ); + plot_opts.SetFineScaleAdjustY( s_Parameters.m_YScaleAdjust ); + + m_parent->SetPlotSettings( plot_opts ); + + SetPenWidth(); +} + + +void DIALOG_PRINT_USING_PRINTER::SetPenWidth() +{ + // Get the new pen width value, and verify min et max value + // NOTE: s_Parameters.m_PenDefaultSize is in internal units + + s_Parameters.m_PenDefaultSize = ValueFromTextCtrl( *m_DialogPenWidth ); + + if( s_Parameters.m_PenDefaultSize > PEN_WIDTH_MAX_VALUE ) + { + s_Parameters.m_PenDefaultSize = PEN_WIDTH_MAX_VALUE; + } + + if( s_Parameters.m_PenDefaultSize < PEN_WIDTH_MIN_VALUE ) + { + s_Parameters.m_PenDefaultSize = PEN_WIDTH_MIN_VALUE; + } + + g_DrawDefaultLineThickness = s_Parameters.m_PenDefaultSize; + + m_DialogPenWidth->SetValue( + StringFromValue( g_UserUnit, s_Parameters.m_PenDefaultSize ) ); +} + +void DIALOG_PRINT_USING_PRINTER::OnScaleSelectionClick( wxCommandEvent& event ) +{ + double scale = s_ScaleList[m_ScaleOption->GetSelection()]; + bool enable = (scale == 1.0); + + if( m_FineAdjustXscaleOpt ) + m_FineAdjustXscaleOpt->Enable(enable); + if( m_FineAdjustYscaleOpt ) + m_FineAdjustYscaleOpt->Enable(enable); +} + + +void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event ) +{ + wxPageSetupDialog pageSetupDialog( this, s_pageSetupData ); + pageSetupDialog.ShowModal(); + + (*s_PrintData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData(); + (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData(); +} + + +void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event ) +{ + SetPrintParameters( ); + + // If no layer selected, we have no plot. prompt user if it happens + // because he could think there is a bug in Pcbnew: + if( s_Parameters.m_PrintMaskLayer == 0 ) + { + DisplayError( this, _( "No layer selected" ) ); + return; + } + + // Pass two printout objects: for preview, and possible printing. + wxString title = _( "Print Preview" ); + wxPrintPreview* preview = + new wxPrintPreview( new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_parent, title ), + new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_parent, title ), + s_PrintData ); + + if( preview == NULL ) + { + DisplayError( this, wxT( "An error occurred attempting to show the print preview window." ) ); + return; + } + + // Uses the parent position and size. + wxPoint WPos = m_parent->GetPosition(); + wxSize WSize = m_parent->GetSize(); + + preview->SetZoom( 100 ); + + wxPreviewFrame* frame = new wxPreviewFrame( preview, this, title, WPos, WSize ); + frame->SetMinSize( wxSize( 550, 350 ) ); + frame->Center(); + + // 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. + // An other 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 ); + + frame->Raise(); // Needed on Ubuntu/Unity to display the frame + frame->Show( true ); +} + + +void DIALOG_PRINT_USING_PRINTER::OnPrintButtonClick( wxCommandEvent& event ) +{ + SetPrintParameters( ); + + // If no layer selected, we have no plot. prompt user if it happens + // because he could think there is a bug in Pcbnew: + if( s_Parameters.m_PrintMaskLayer == 0 ) + { + DisplayError( this, _( "No layer selected." ) ); + return; + } + + wxPrintDialogData printDialogData( *s_PrintData ); + + wxPrinter printer( &printDialogData ); + + wxString title = _( "Print" ); + BOARD_PRINTOUT_CONTROLLER printout( s_Parameters, m_parent, title ); + + if( !printer.Print( this, &printout, true ) ) + { + if( wxPrinter::GetLastError() == wxPRINTER_ERROR ) + DisplayError( this, _( "There was a problem printing." ) ); + + return; + } + else + { + *s_PrintData = printer.GetPrintDialogData().GetPrintData(); + } +} |