1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors.
5  * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
6  * Copyright (C) 2016 Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <memory>
23 #include <utility>
24 
25 #include "pcbnew_settings.h"
26 #include <board.h>
27 #include <footprint.h>
28 #include <eda_draw_frame.h>
29 #include <footprint_preview_panel.h>
30 #include <fp_lib_table.h>
31 #include <kiway.h>
32 #include <math/box2.h>
33 #include <pcb_painter.h>
34 #include <pcb_draw_panel_gal.h>
35 #include <pcb_edit_frame.h>
36 #include <pgm_base.h>
37 #include <settings/settings_manager.h>
38 #include <view/view.h>
39 #include <wx/stattext.h>
40 #include <zoom_defines.h>
41 
FOOTPRINT_PREVIEW_PANEL(KIWAY * aKiway,wxWindow * aParent,std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> aOpts,GAL_TYPE aGalType)42 FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent,
43                                                   std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> aOpts,
44                                                   GAL_TYPE aGalType ) :
45         PCB_DRAW_PANEL_GAL( aParent, -1, wxPoint( 0, 0 ), wxSize( 200, 200 ), *aOpts, aGalType ),
46         KIWAY_HOLDER( aKiway, KIWAY_HOLDER::PANEL ),
47         m_displayOptions( std::move( aOpts ) ),
48         m_currentFootprint( nullptr )
49 {
50     SetStealsFocus( false );
51     ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
52     EnableScrolling( false, false );    // otherwise Zoom Auto disables GAL canvas
53 
54     m_dummyBoard = std::make_unique<BOARD>();
55     UpdateColors();
56     SyncLayersVisibility( m_dummyBoard.get() );
57 
58     Raise();
59     Show( true );
60     StartDrawing();
61 }
62 
63 
~FOOTPRINT_PREVIEW_PANEL()64 FOOTPRINT_PREVIEW_PANEL::~FOOTPRINT_PREVIEW_PANEL( )
65 {
66     if( m_currentFootprint )
67     {
68         GetView()->Remove( m_currentFootprint.get() );
69         GetView()->Clear();
70         m_currentFootprint->SetParent( nullptr );
71     }
72 }
73 
74 
GetBackgroundColor()75 const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetBackgroundColor()
76 {
77     KIGFX::PAINTER* painter = GetView()->GetPainter();
78     auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
79 
80     return settings->GetBackgroundColor();
81 }
82 
83 
GetForegroundColor()84 const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetForegroundColor()
85 {
86     KIGFX::PAINTER* painter = GetView()->GetPainter();
87     auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
88 
89     return settings->GetCursorColor();
90 }
91 
92 
renderFootprint(std::shared_ptr<FOOTPRINT> aFootprint)93 void FOOTPRINT_PREVIEW_PANEL::renderFootprint( std::shared_ptr<FOOTPRINT> aFootprint )
94 {
95     if( m_currentFootprint )
96     {
97         GetView()->Remove( m_currentFootprint.get() );
98         GetView()->Clear();
99         m_currentFootprint->SetParent( nullptr );
100     }
101 
102     m_currentFootprint = aFootprint;
103 
104     if( !m_currentFootprint )
105         return;
106 
107     m_currentFootprint->SetParent( m_dummyBoard.get() );
108 
109     // Ensure we are not using the high contrast mode to display the selected footprint
110     KIGFX::PAINTER* painter = GetView()->GetPainter();
111     auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
112     settings->SetContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL );
113 
114     GetView()->Add( m_currentFootprint.get() );
115     GetView()->SetVisible( m_currentFootprint.get(), true );
116     GetView()->Update( m_currentFootprint.get(), KIGFX::ALL );
117 
118     BOX2I bbox = m_currentFootprint->ViewBBox();
119     bbox.Merge( m_currentFootprint->Value().ViewBBox() );
120     bbox.Merge( m_currentFootprint->Reference().ViewBBox() );
121 
122     if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
123     {
124         // Autozoom
125         GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
126 
127         // Add a margin
128         GetView()->SetScale( GetView()->GetScale() * 0.7 );
129 
130         Refresh();
131     }
132 }
133 
134 
DisplayFootprint(const LIB_ID & aFPID)135 bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
136 {
137     FP_LIB_TABLE* fptbl = Prj().PcbFootprintLibs();
138 
139     try
140     {
141         const FOOTPRINT* fp = fptbl->GetEnumeratedFootprint( aFPID.GetLibNickname(), aFPID.GetLibItemName() );
142 
143         if( fp )
144             m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate() ) );
145         else
146             m_currentFootprint.reset();
147     }
148     catch( ... )
149     {
150         m_currentFootprint.reset();
151     }
152 
153     renderFootprint( m_currentFootprint );
154     Refresh();
155 
156     return m_currentFootprint != nullptr;
157 }
158 
159 
GetWindow()160 wxWindow* FOOTPRINT_PREVIEW_PANEL::GetWindow()
161 {
162     return static_cast<wxWindow*>( this );
163 }
164 
165 
New(KIWAY * aKiway,wxWindow * aParent)166 FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent )
167 {
168     PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
169 
170     if( cfg->m_Window.grid.sizes.empty() )
171         cfg->m_Window.grid.sizes = cfg->DefaultGridSizeList();
172 
173     // Currently values read from config file are not used because the user cannot
174     // change this config
175     //if( cfg->m_Window.zoom_factors.empty() )
176     {
177         cfg->m_Window.zoom_factors = { ZOOM_LIST_PCBNEW };
178     }
179 
180     std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> gal_opts;
181 
182     gal_opts = std::make_unique<KIGFX::GAL_DISPLAY_OPTIONS>();
183     gal_opts->ReadConfig( *Pgm().GetCommonSettings(), cfg->m_Window, aParent );
184 
185     auto canvasType = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
186     auto panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, std::move( gal_opts ), canvasType );
187 
188     panel->UpdateColors();
189 
190     const GRID_SETTINGS& gridCfg = cfg->m_Window.grid;
191 
192     panel->GetGAL()->SetGridVisibility( gridCfg.show );
193 
194     //Bounds checking cannot include number of elements as an index!
195     int gridIdx = std::max( 0, std::min( gridCfg.last_size_idx, (int) gridCfg.sizes.size() - 1 ) );
196     int gridSize = (int) ValueFromString( EDA_UNITS::MILS, gridCfg.sizes[ gridIdx ] );
197     panel->GetGAL()->SetGridSize( VECTOR2D( gridSize, gridSize ) );
198 
199     return panel;
200 }
201