		/***********************/
		/* fichier pcbplot.cpp */
		/***********************/

#include "fctsys.h"
#include "gr_basic.h"

#include "common.h"
#include "plot_common.h"
#include "pcbnew.h"
#include "pcbplot.h"
#include "worksheet.h"
#include "id.h"

#include "protos.h"

#define PLOT_DEFAULT_MARGE 300	// mils

/* variables locale : */
long s_SelectedLayers = CUIVRE_LAYER | CMP_LAYER |
					SILKSCREEN_LAYER_CMP | SILKSCREEN_LAYER_CU;

/* Routines Locales */

enum id_plotps
{
	ID_CLOSE_PLOT = 8020,
	ID_DRILL_SHAPE_OPT,
	ID_SCALE_OPT,
	ID_ROTATE_OPT,
	ID_MIROR_OPT,
	ID_EXEC_PLOT,
	ID_PLOT_MODE_OPT,
	ID_MASKVIA_OPT,
	ID_PLOT_CENTRE_OPT,
	ID_SEL_PLOT_FORMAT,
	ID_SEL_GERBER_FORMAT,
	ID_SAVE_OPT_PLOT,
	ID_PRINT_REF,
	ID_PRINT_VALUE,
	ID_PRINT_MODULE_TEXTS,
	ID_FORCE_PRINT_INVISIBLE_TEXT,
	ID_PRINT_PAD_ON_SILKSCREEN,
	ID_FORCE_PRINT_PAD,
	ID_CREATE_DRILL_FILE
};


	/*******************************/
	/* Dialog box for plot control */
	/*******************************/

class WinEDA_PlotFrame: public wxDialog
{
public:
	WinEDA_BasePcbFrame * m_Parent;
	wxButton * m_MergePlotButton;
	wxCheckBox * m_BoxSelecLayer[32];
	wxRadioBox * m_PlotFormatOpt;
	wxRadioBox * m_Drill_Shape_Opt;
	wxRadioBox * m_Scale_Opt;
	wxRadioBox * m_PlotModeOpt;
	wxCheckBox * m_PlotMirorOpt;
	wxCheckBox * m_PlotNoViaOnMaskOpt;
	wxCheckBox * m_HPGL_PlotCenter_Opt;
	wxCheckBox * m_Plot_Sheet_Ref;
	wxCheckBox * m_Plot_Invisible_Text;
	wxCheckBox * m_Plot_Text_Value;
	wxCheckBox * m_Plot_Text_Ref;
	wxCheckBox * m_Plot_Text_Div;
	wxCheckBox * m_Plot_Pads_on_Silkscreen;
	wxCheckBox * m_Force_Plot_Pads;
	WinEDA_ValueCtrl * m_GerbSpotSizeMinOpt;
	WinEDA_ValueCtrl * m_LinesWidth;
	WinEDA_ValueCtrl * m_HPGLPenSizeOpt;
	WinEDA_ValueCtrl * m_HPGLPenSpeedOpt;
	WinEDA_ValueCtrl * m_HPGLPenOverlayOpt;
	WinEDA_DFloatValueCtrl * m_FineAdjustXscaleOpt, * m_FineAdjustYscaleOpt;
	double m_XScaleAdjust, m_YScaleAdjust;
	int m_PlotFormat;

public:
	WinEDA_PlotFrame(WinEDA_BasePcbFrame * parent);
private:
	void Plot(wxCommandEvent & event);
	void OnQuit(wxCommandEvent & event);
	void SetCommands(wxCommandEvent & event);
	void SaveOptPlot(wxCommandEvent & event);
	void CreateDrillFile(wxCommandEvent & event);
	DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(WinEDA_PlotFrame, wxDialog)
	EVT_BUTTON(ID_CLOSE_PLOT, WinEDA_PlotFrame::OnQuit)
	EVT_BUTTON(ID_EXEC_PLOT, WinEDA_PlotFrame::Plot)
	EVT_BUTTON(ID_SAVE_OPT_PLOT, WinEDA_PlotFrame::SaveOptPlot)
	EVT_BUTTON(ID_CREATE_DRILL_FILE, WinEDA_PlotFrame::CreateDrillFile)
	EVT_RADIOBOX(ID_SEL_PLOT_FORMAT, WinEDA_PlotFrame::SetCommands)
END_EVENT_TABLE()



#define UNITS_MILS 1000
#define H_SIZE 640
#define V_SIZE 430
WinEDA_PlotFrame::WinEDA_PlotFrame(WinEDA_BasePcbFrame * parent):
				wxDialog(parent, -1, _("Plot"),
				wxPoint(-1,-1), wxSize(H_SIZE, V_SIZE),
				wxDEFAULT_DIALOG_STYLE)
{
wxPoint pos;
wxButton * Button;
int ii, jj, bottom = V_SIZE;
#define DELTA_Y 16

	m_Parent = parent;
	SetFont(*g_DialogFont);
	Centre();
	m_PlotFormat = format_plot;
	m_Plot_Sheet_Ref = NULL;

	pos.x = 360; pos.y = 5;
wxString fmtmsg[4] = { wxT("HPGL"), wxT("GERBER"), wxT("Postscript"), wxT("Postscript A4") };
	m_PlotFormatOpt = new wxRadioBox(this, ID_SEL_PLOT_FORMAT,
			_("Plot Format"), pos, wxSize(-1,-1),
			4, fmtmsg, 1, wxRA_SPECIFY_COLS);
	switch ( m_PlotFormat )
	{
		case PLOT_FORMAT_HPGL:
			m_PlotFormatOpt->SetSelection(0); break;
		case PLOT_FORMAT_POST:
			m_PlotFormatOpt->SetSelection(2); break;
		case PLOT_FORMAT_GERBER:
			m_PlotFormatOpt->SetSelection(1); break;
		case PLOT_FORMAT_POST_A4:
			m_PlotFormatOpt->SetSelection(3); break;
	}

	/* Creation des menus d'option du format GERBER */
	m_PlotFormatOpt->GetSize(&ii, &jj);
	pos.y += jj + 10;
	m_GerbSpotSizeMinOpt = new WinEDA_ValueCtrl(this, _("Spot min"),
			spot_mini, UnitMetric, pos, UNITS_MILS);

	/* Creation des menus d'option du format HPGL */
	pos.y += m_GerbSpotSizeMinOpt->GetDimension().y + 8;
	m_HPGLPenSizeOpt = new WinEDA_ValueCtrl(this, _("Pen Size"),
			g_HPGL_Pen_Diam, UnitMetric, pos, UNITS_MILS);

	pos.y += m_HPGLPenSizeOpt->GetDimension().y + 8;
	/* unites standards = cm  pour vitesse plume en HPLG */
	m_HPGLPenSpeedOpt = new WinEDA_ValueCtrl(this, _("Pen Speed (cm/s)"),
			g_HPGL_Pen_Speed, CENTIMETRE, pos, 1);
	m_HPGLPenSpeedOpt->SetToolTip(_("Set pen speed in cm/s"));

	pos.y += m_HPGLPenSpeedOpt->GetDimension().y + 8;
	m_HPGLPenOverlayOpt = new WinEDA_ValueCtrl(this, _("Pen Ovr"),
			g_HPGL_Pen_Recouvrement, UnitMetric, pos, UNITS_MILS);
	m_HPGLPenOverlayOpt->SetToolTip(_("Set plot overlay for filling"));

	pos.y += m_HPGLPenOverlayOpt->GetDimension().y + 8;
	m_LinesWidth = new WinEDA_ValueCtrl(this, _("Lines Width"),
			g_PlotLine_Width, UnitMetric, pos, PCB_INTERNAL_UNIT);
	m_LinesWidth->SetToolTip(_("Set width for lines in Line plot mode"));
	pos.y += m_LinesWidth->GetDimension().y + 8;
	bottom = MAX (bottom, pos.y);

	/* Creation des boutons de commande */
	pos.x = 475; pos.y = 5;
	Button = new wxButton(this, ID_EXEC_PLOT,
						_("Plot"), pos);
	Button->SetForegroundColour(*wxRED);

	pos.y += Button->GetSize().y + 5;
	Button = new wxButton(this,	ID_CLOSE_PLOT,
						_("Cancel"), pos);
	Button->SetForegroundColour(*wxBLUE);

	pos.y += Button->GetSize().y + 5;
	Button = new wxButton(this,	ID_SAVE_OPT_PLOT,
						_("Save options"), pos);
	Button->SetForegroundColour(wxColour(0,80,0) );

	pos.y += Button->GetSize().y + 5;
	Button = new wxButton(this,	ID_CREATE_DRILL_FILE,
						_("Create Drill File"), pos);
	Button->SetForegroundColour(wxColour(0,80,80) );



	// Create scale adjust option
	m_XScaleAdjust = m_YScaleAdjust = 1.0;
	if ( m_Parent->m_Parent->m_EDA_Config )
	{
		m_Parent->m_Parent->m_EDA_Config->Read(wxT("PlotXFineScaleAdj"), &m_XScaleAdjust);
		m_Parent->m_Parent->m_EDA_Config->Read(wxT("PlotYFineScaleAdj"), &m_YScaleAdjust);
	}
	pos.y += Button->GetSize().y + 15;
	m_FineAdjustXscaleOpt = new WinEDA_DFloatValueCtrl(this, _("X Scale Adjust"), m_XScaleAdjust, pos);
	m_FineAdjustXscaleOpt->SetToolTip(_("Set X scale adjust for exact scale plotting"));
	pos.y += m_FineAdjustXscaleOpt->GetDimension().y + 5;
	m_FineAdjustYscaleOpt = new WinEDA_DFloatValueCtrl(this, _("Y Scale Adjust"), m_YScaleAdjust, pos);
	m_FineAdjustYscaleOpt->SetToolTip(_("Set Y scale adjust for exact scale plotting"));


	/* Creation de la liste des layers */
	pos.x = 5; jj = pos.y = 5;
	int mask = 1;
	for ( ii = 0; ii < NB_LAYERS; ii++, mask <<= 1 )
	{
		if ( ii == 16 ) { pos.x += 90; jj = pos.y; pos.y = 5; }
		m_BoxSelecLayer[ii] = new wxCheckBox(this, -1,
					ReturnPcbLayerName(ii), pos);
		if ( mask & s_SelectedLayers) m_BoxSelecLayer[ii]->SetValue(TRUE);
		pos.y += 16;
	}

	// Option d'impression du cartouche:
	pos.x = 5; pos.y = jj + 10;
	if ( m_Parent->m_Print_Sheet_Ref )
		{
		m_Plot_Sheet_Ref = new wxCheckBox(this, ID_PRINT_REF, _("Print Sheet Ref"),
			pos);
		m_Plot_Sheet_Ref->SetValue(Plot_Sheet_Ref);
		pos.y += DELTA_Y + 2;
		}
	else Plot_Sheet_Ref = FALSE;

	// Option d'impression des pads sur toutes les couches
	m_Plot_Pads_on_Silkscreen = new wxCheckBox(this,
			ID_PRINT_PAD_ON_SILKSCREEN, _("Print Pads on Silkscreen"),
			pos);
	m_Plot_Pads_on_Silkscreen->SetValue(PlotPadsOnSilkLayer);
	m_Plot_Pads_on_Silkscreen->SetToolTip(
		_("Enable/disable print/plot pads on Silkscreen layers") );

	pos.y += DELTA_Y;
	m_Force_Plot_Pads = new wxCheckBox(this, ID_FORCE_PRINT_PAD, _("Always Print Pads"),
			pos);
	m_Force_Plot_Pads->SetValue(Plot_Pads_All_Layers);
    m_Force_Plot_Pads->SetToolTip(_("Force print/plot pads on ALL layers") );

	// Options d'impression des textes modules
	pos.y += DELTA_Y;
	m_Plot_Text_Value = new wxCheckBox(this, ID_PRINT_VALUE, _("Print Module Value"),
			pos);
	m_Plot_Text_Value->SetValue(Sel_Texte_Valeur);
	m_Plot_Text_Value->SetToolTip(
		_("Enable/disable print/plot module value on Silkscreen layers") );

	pos.y += DELTA_Y;
	m_Plot_Text_Ref = new wxCheckBox(this, ID_PRINT_REF, _("Print Module Reference"),
			pos);
	m_Plot_Text_Ref->SetValue(Sel_Texte_Reference);
	m_Plot_Text_Ref->SetToolTip(
		_("Enable/disable print/plot module reference on Silkscreen layers") );

	pos.y += DELTA_Y;
	m_Plot_Text_Div = new wxCheckBox(this, ID_PRINT_MODULE_TEXTS,
			_("Print other module texts"),
			pos);
	m_Plot_Text_Div->SetValue(Sel_Texte_Divers);
	m_Plot_Text_Div->SetToolTip(
		_("Enable/disable print/plot module field texts on Silkscreen layers") );

	pos.y += DELTA_Y;
	m_Plot_Invisible_Text = new wxCheckBox(this,
			ID_FORCE_PRINT_INVISIBLE_TEXT, _("Force Print Invisible Texts"),
			pos);
	m_Plot_Invisible_Text->SetValue(Sel_Texte_Invisible);
	m_Plot_Invisible_Text->SetToolTip(
		_("Force print/plot module invisible texts on Silkscreen layers") );


	pos.x = 230; pos.y = 5;
wxString drillmsg[3] = { _("No Drill mark"), _("Small mark"), _("Real Drill") };
	m_Drill_Shape_Opt = new wxRadioBox(this, ID_DRILL_SHAPE_OPT,
			_("Pads Drill Opt"), pos, wxSize(-1,-1),
			3, drillmsg, 1, wxRA_SPECIFY_COLS);
	m_Drill_Shape_Opt->SetSelection(g_DrillShapeOpt);

	m_Drill_Shape_Opt->GetSize(&ii, &jj);
	pos.y += 15 + jj;
wxString scalemsg[5] =
	{ _("Auto scale"), _("Scale 1"), _("Scale 1.5"), _("Scale 2"), _("Scale 3") };
	m_Scale_Opt = new wxRadioBox(this, ID_SCALE_OPT,
			_("Scale Opt"), pos, wxSize(-1,-1),
			5, scalemsg, 1, wxRA_SPECIFY_COLS);
	m_Scale_Opt->SetSelection(g_PlotScaleOpt);


	m_Scale_Opt->GetSize(&ii, &jj);
	pos.y += jj + 15;
wxString list_opt3[3] = {_("Line"), _("Filled"), _("Sketch") };
	m_PlotModeOpt = new wxRadioBox(this, ID_PLOT_MODE_OPT, _("Plot mode"),
				pos, wxDefaultSize,
				3, list_opt3, 1);
	m_PlotModeOpt->SetSelection(Plot_Mode);

	m_PlotModeOpt->GetSize(&ii, &jj);
	pos.y += jj + 15;
	m_PlotMirorOpt = new wxCheckBox(this, ID_MIROR_OPT,
						_("Plot Mirror"), pos);
	m_PlotMirorOpt->SetValue(Plot_Set_MIROIR);

	pos.y += 17;
	m_PlotNoViaOnMaskOpt = new wxCheckBox(this, ID_MASKVIA_OPT,
						_("Vias on Mask"), pos);
	m_PlotNoViaOnMaskOpt->SetValue(g_DrawViaOnMaskLayer);
 	m_PlotNoViaOnMaskOpt->SetToolTip(
		_("Print/plot vias on mask layers. They are in this case not protected") );


	pos.y += 17;
	m_HPGL_PlotCenter_Opt = new wxCheckBox(this, ID_PLOT_CENTRE_OPT,
						_("Org = Centre"), pos);
	m_HPGL_PlotCenter_Opt->SetValue(HPGL_Org_Centre);
	m_HPGL_PlotCenter_Opt->SetToolTip(_("Draw origin ( 0,0 )in on sheet center") );

	pos.y += 20;
	if ( bottom < pos.y ) bottom = pos.y;

	SetClientSize(wxSize(H_SIZE, bottom) );

	// Mise a jour des activations des menus:
wxCommandEvent event;
	SetCommands(event);
}

/***************************************************************/
void  WinEDA_PlotFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
/***************************************************************/
{
    Close(true);    // true is to force the frame to close
}



/*********************************************************/
void WinEDA_PlotFrame::CreateDrillFile(wxCommandEvent & event)
/*********************************************************/
/* Create the board drill file used with gerber documents
*/
{
	((WinEDA_PcbFrame * )m_Parent)->InstallDrillFrame(event);
}

/*********************************************************/
void WinEDA_PlotFrame::SetCommands(wxCommandEvent & event)
/*********************************************************/
/* active ou désactive les différents menus d'option selon le standard choisi
*/
{
int format;
int format_list[] =
	{PLOT_FORMAT_HPGL, PLOT_FORMAT_GERBER, PLOT_FORMAT_POST, PLOT_FORMAT_POST_A4
	};

	format = format_list[m_PlotFormatOpt->GetSelection()];

	switch ( format  )
		{
		case PLOT_FORMAT_POST_A4:
		case PLOT_FORMAT_POST:
			m_Drill_Shape_Opt->Enable(TRUE);
			m_PlotModeOpt->Enable(TRUE);
			m_PlotMirorOpt->Enable(TRUE);
			m_GerbSpotSizeMinOpt->Enable(FALSE);
			m_LinesWidth->Enable(TRUE);
			m_HPGLPenSizeOpt->Enable(FALSE);
			m_HPGLPenSpeedOpt->Enable(FALSE);
			m_HPGLPenOverlayOpt->Enable(FALSE);
			m_HPGL_PlotCenter_Opt->Enable(FALSE);
			m_Plot_Sheet_Ref->Enable(TRUE);
			m_Scale_Opt->Enable(TRUE);
			m_FineAdjustXscaleOpt->Enable(TRUE);
			m_FineAdjustYscaleOpt->Enable(TRUE);
			m_PlotFormat = PLOT_FORMAT_POST;
			if ( format == PLOT_FORMAT_POST_A4 ) g_ForcePlotPS_On_A4 = TRUE;
			else g_ForcePlotPS_On_A4 = FALSE;
			break;

		case PLOT_FORMAT_GERBER:
			m_Drill_Shape_Opt->Enable(FALSE);
			m_PlotModeOpt->Enable(FALSE);
			m_PlotMirorOpt->Enable(FALSE);
			m_GerbSpotSizeMinOpt->Enable(TRUE);
			m_LinesWidth->Enable(TRUE);
			m_HPGLPenSizeOpt->Enable(FALSE);
			m_HPGLPenSpeedOpt->Enable(FALSE);
			m_HPGLPenOverlayOpt->Enable(FALSE);
			m_HPGL_PlotCenter_Opt->Enable(FALSE);
			m_Plot_Sheet_Ref->Enable(FALSE);
			m_Scale_Opt->Enable(FALSE);
			m_FineAdjustXscaleOpt->Enable(FALSE);
			m_FineAdjustYscaleOpt->Enable(FALSE);
			m_PlotFormat = PLOT_FORMAT_GERBER;
			break;

		case PLOT_FORMAT_HPGL:
			m_PlotMirorOpt->Enable(TRUE);
			m_Drill_Shape_Opt->Enable(FALSE);
			m_PlotModeOpt->Enable(TRUE);
			m_GerbSpotSizeMinOpt->Enable(FALSE);
			m_LinesWidth->Enable(FALSE);
			m_HPGLPenSizeOpt->Enable(TRUE);
			m_HPGLPenSpeedOpt->Enable(TRUE);
			m_HPGLPenOverlayOpt->Enable(TRUE);
			m_HPGL_PlotCenter_Opt->Enable(TRUE);
			m_Plot_Sheet_Ref->Enable(TRUE);
			m_Scale_Opt->Enable(TRUE);
			m_FineAdjustXscaleOpt->Enable(FALSE);
			m_FineAdjustYscaleOpt->Enable(FALSE);
			m_PlotFormat = PLOT_FORMAT_HPGL;
			break;
		}
	format_plot = m_PlotFormat;
}

/*********************************************************/
void WinEDA_PlotFrame::SaveOptPlot(wxCommandEvent & event)
/*********************************************************/
{
	if ( m_Plot_Sheet_Ref )
		Plot_Sheet_Ref = m_Plot_Sheet_Ref->GetValue();

	PlotPadsOnSilkLayer = m_Plot_Pads_on_Silkscreen->GetValue();
	Plot_Pads_All_Layers = m_Force_Plot_Pads->GetValue();

	Sel_Texte_Valeur = m_Plot_Text_Value->GetValue();
	Sel_Texte_Reference = m_Plot_Text_Ref->GetValue();
	Sel_Texte_Divers = m_Plot_Text_Div->GetValue();
	Sel_Texte_Invisible = m_Plot_Invisible_Text->GetValue();

	g_PlotScaleOpt = m_Scale_Opt->GetSelection();
	g_DrillShapeOpt = m_Drill_Shape_Opt->GetSelection();
	Plot_Set_MIROIR = m_PlotMirorOpt->GetValue();
	if ( Plot_Set_MIROIR ) g_PlotOrient = PLOT_MIROIR;
	else g_PlotOrient = 0;
	Plot_Mode = m_PlotModeOpt->GetSelection();
	g_DrawViaOnMaskLayer = m_PlotNoViaOnMaskOpt->GetValue();
	spot_mini = m_GerbSpotSizeMinOpt->GetValue();
	g_HPGL_Pen_Diam = m_HPGLPenSizeOpt->GetValue();
	g_HPGL_Pen_Speed = m_HPGLPenSpeedOpt->GetValue();
	g_HPGL_Pen_Recouvrement = m_HPGLPenOverlayOpt->GetValue();
	HPGL_Org_Centre = m_HPGL_PlotCenter_Opt->GetValue();
	g_PlotLine_Width = m_LinesWidth->GetValue();

	m_XScaleAdjust = m_FineAdjustXscaleOpt->GetValue();
	m_YScaleAdjust = m_FineAdjustYscaleOpt->GetValue();
	if ( m_Parent->m_Parent->m_EDA_Config )
	{
		m_Parent->m_Parent->m_EDA_Config->Write(wxT("PlotXFineScaleAdj"), m_XScaleAdjust);
		m_Parent->m_Parent->m_EDA_Config->Write(wxT("PlotYFineScaleAdj"), m_YScaleAdjust);
	}
}

/***************************************************/
void WinEDA_PlotFrame::Plot(wxCommandEvent & event)
/***************************************************/
{
int layer_to_plot;
wxString FullFileName, BaseFileName;
wxString ext;

	SaveOptPlot(event);

	switch ( g_PlotScaleOpt )
		{
		default:
			Scale_X = Scale_Y = 1;
			break;

		case 2:
			Scale_X = Scale_Y = 1.5;
			break;

		case 3:
			Scale_X = Scale_Y = 2;
			break;

		case 4:
			Scale_X = Scale_Y = 3;
			break;

		}

		Scale_X *= m_XScaleAdjust;
		Scale_Y *= m_YScaleAdjust;

	BaseFileName = m_Parent->GetScreen()->m_FileName;
	ChangeFileNameExt( BaseFileName, wxT("-") );

	switch ( m_PlotFormat)
		{
		case PLOT_FORMAT_POST:
			ext = wxT(".ps");
			break;

		case PLOT_FORMAT_GERBER:
			ext = wxT(".pho");
			break;

		case PLOT_FORMAT_HPGL:
			ext = wxT(".plt");
			break;
		}

	int mask = 1;
	s_SelectedLayers = 0;

	for ( layer_to_plot = 0; layer_to_plot < 29; layer_to_plot++, mask <<= 1 )
	{
		if ( m_BoxSelecLayer[layer_to_plot]->GetValue() )
		{
			s_SelectedLayers |= mask;
			/* Calcul du nom du fichier */
			FullFileName =  BaseFileName +ReturnPcbLayerName(layer_to_plot, TRUE) + ext;
			switch ( m_PlotFormat)
			{
				case PLOT_FORMAT_POST:
					m_Parent->Genere_PS(FullFileName, layer_to_plot);
					break;

				case PLOT_FORMAT_GERBER:
					m_Parent->Genere_GERBER(FullFileName, layer_to_plot);
					break;

				case PLOT_FORMAT_HPGL:
					m_Parent->Genere_HPGL(FullFileName, layer_to_plot);
					break;

			}
		}
	}

	Close(TRUE);
}


/**************************************************************/
void WinEDA_BasePcbFrame::ToPlotter(wxCommandEvent& event)
/***************************************************************/
{
	WinEDA_PlotFrame * frame = new WinEDA_PlotFrame(this);
	frame->ShowModal(); frame->Destroy();
}


