You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
8.6 KiB

6 years ago
5 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The 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. #include <memory>
  22. #include <utility>
  23. #include "pcbnew_settings.h"
  24. #include <advanced_config.h>
  25. #include <base_units.h>
  26. #include <board.h>
  27. #include <footprint.h>
  28. #include <pad.h>
  29. #include <pcb_dimension.h>
  30. #include <dpi_scaling_common.h>
  31. #include <eda_draw_frame.h>
  32. #include <footprint_preview_panel.h>
  33. #include <fp_lib_table.h>
  34. #include <gal/graphics_abstraction_layer.h>
  35. #include <kiway.h>
  36. #include <math/box2.h>
  37. #include <pcb_painter.h>
  38. #include <pcb_draw_panel_gal.h>
  39. #include <pcb_edit_frame.h>
  40. #include <pgm_base.h>
  41. #include <settings/settings_manager.h>
  42. #include <view/view.h>
  43. #include <wx/stattext.h>
  44. #include <dialog_shim.h>
  45. #include <project_pcb.h>
  46. FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aParent,
  47. UNITS_PROVIDER* aUnitsProvider,
  48. std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> aOpts,
  49. GAL_TYPE aGalType ) :
  50. PCB_DRAW_PANEL_GAL( aParent, -1, wxPoint( 0, 0 ), wxSize( 200, 200 ), *aOpts, aGalType ),
  51. KIWAY_HOLDER( aKiway, KIWAY_HOLDER::PANEL ),
  52. m_displayOptions( std::move( aOpts ) )
  53. {
  54. SetStealsFocus( false );
  55. ShowScrollbars( wxSHOW_SB_NEVER, wxSHOW_SB_NEVER );
  56. EnableScrolling( false, false ); // otherwise Zoom Auto disables GAL canvas
  57. m_userUnits = aUnitsProvider->GetUserUnits();
  58. m_dummyBoard = std::make_unique<BOARD>();
  59. m_dummyBoard->SetUserUnits( m_userUnits );
  60. m_dummyBoard->SetBoardUse( BOARD_USE::FPHOLDER );
  61. UpdateColors();
  62. SyncLayersVisibility( m_dummyBoard.get() );
  63. Raise();
  64. Show( true );
  65. StartDrawing();
  66. }
  67. FOOTPRINT_PREVIEW_PANEL::~FOOTPRINT_PREVIEW_PANEL( )
  68. {
  69. ClearViewAndData();
  70. }
  71. void FOOTPRINT_PREVIEW_PANEL::ClearViewAndData()
  72. {
  73. m_dummyBoard->DetachAllFootprints();
  74. if( m_currentFootprint )
  75. GetView()->Remove( m_currentFootprint.get() );
  76. if( m_otherFootprint )
  77. GetView()->Remove( m_otherFootprint.get() );
  78. GetView()->Clear();
  79. m_currentFootprint = nullptr;
  80. m_otherFootprint = nullptr;
  81. }
  82. const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetBackgroundColor() const
  83. {
  84. KIGFX::PAINTER* painter = GetView()->GetPainter();
  85. auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
  86. return settings->GetBackgroundColor();
  87. }
  88. const COLOR4D& FOOTPRINT_PREVIEW_PANEL::GetForegroundColor() const
  89. {
  90. KIGFX::PAINTER* painter = GetView()->GetPainter();
  91. auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
  92. return settings->GetLayerColor( F_Fab );
  93. }
  94. void FOOTPRINT_PREVIEW_PANEL::renderFootprint( std::shared_ptr<FOOTPRINT> aFootprint )
  95. {
  96. m_dummyBoard->Add( aFootprint.get() );
  97. INSPECTOR_FUNC inspector =
  98. [&]( EDA_ITEM* descendant, void* aTestData )
  99. {
  100. static_cast<PCB_DIMENSION_BASE*>( descendant )->UpdateUnits();
  101. return INSPECT_RESULT::CONTINUE;
  102. };
  103. aFootprint->Visit( inspector, nullptr, { PCB_DIM_LEADER_T,
  104. PCB_DIM_ALIGNED_T,
  105. PCB_DIM_ORTHOGONAL_T,
  106. PCB_DIM_CENTER_T,
  107. PCB_DIM_RADIAL_T } );
  108. for( PAD* pad : aFootprint->Pads() )
  109. pad->SetPinFunction( m_pinFunctions[ pad->GetNumber() ] );
  110. // Ensure we are not using the high contrast mode to display the selected footprint
  111. KIGFX::PAINTER* painter = GetView()->GetPainter();
  112. auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
  113. settings->m_ContrastModeDisplay = HIGH_CONTRAST_MODE::NORMAL;
  114. GetView()->Add( aFootprint.get() );
  115. GetView()->SetVisible( aFootprint.get(), true );
  116. GetView()->Update( aFootprint.get(), KIGFX::ALL );
  117. }
  118. void FOOTPRINT_PREVIEW_PANEL::fitToCurrentFootprint()
  119. {
  120. bool includeText = m_currentFootprint->TextOnly();
  121. BOX2I bbox = m_currentFootprint->GetBoundingBox( includeText );
  122. if( bbox.GetSize().x > 0 && bbox.GetSize().y > 0 )
  123. {
  124. // Autozoom
  125. GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) );
  126. // Add a margin
  127. GetView()->SetScale( GetView()->GetScale() * 0.7 );
  128. Refresh();
  129. }
  130. }
  131. bool FOOTPRINT_PREVIEW_PANEL::DisplayFootprint( const LIB_ID& aFPID )
  132. {
  133. m_dummyBoard->DetachAllFootprints();
  134. if( m_currentFootprint )
  135. GetView()->Remove( m_currentFootprint.get() );
  136. GetView()->Clear();
  137. FP_LIB_TABLE* fptbl = PROJECT_PCB::PcbFootprintLibs( &Prj() );
  138. try
  139. {
  140. const FOOTPRINT* fp = fptbl->GetEnumeratedFootprint( aFPID.GetLibNickname(), aFPID.GetLibItemName() );
  141. if( fp )
  142. m_currentFootprint.reset( static_cast<FOOTPRINT*>( fp->Duplicate( IGNORE_PARENT_GROUP ) ) );
  143. else
  144. m_currentFootprint.reset();
  145. }
  146. catch( ... )
  147. {
  148. m_currentFootprint.reset();
  149. }
  150. if( m_currentFootprint )
  151. {
  152. renderFootprint( m_currentFootprint );
  153. fitToCurrentFootprint();
  154. }
  155. ForceRefresh();
  156. return m_currentFootprint != nullptr;
  157. }
  158. void FOOTPRINT_PREVIEW_PANEL::DisplayFootprints( std::shared_ptr<FOOTPRINT> aFootprintA,
  159. std::shared_ptr<FOOTPRINT> aFootprintB )
  160. {
  161. m_dummyBoard->DetachAllFootprints();
  162. if( m_currentFootprint )
  163. GetView()->Remove( m_currentFootprint.get() );
  164. if( m_otherFootprint )
  165. GetView()->Remove( m_otherFootprint.get() );
  166. GetView()->Clear();
  167. m_currentFootprint = aFootprintA;
  168. m_otherFootprint = aFootprintB;
  169. if( m_currentFootprint )
  170. {
  171. wxASSERT( m_otherFootprint );
  172. renderFootprint( m_currentFootprint );
  173. renderFootprint( m_otherFootprint );
  174. fitToCurrentFootprint();
  175. }
  176. Layout();
  177. Show();
  178. }
  179. void FOOTPRINT_PREVIEW_PANEL::RefreshAll()
  180. {
  181. GetView()->UpdateAllItems( KIGFX::REPAINT );
  182. ForceRefresh();
  183. }
  184. FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow* aParent,
  185. UNITS_PROVIDER* aUnitsProvider )
  186. {
  187. PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
  188. std::unique_ptr<GAL_DISPLAY_OPTIONS_IMPL> gal_opts;
  189. gal_opts = std::make_unique<GAL_DISPLAY_OPTIONS_IMPL>();
  190. gal_opts->ReadConfig( *Pgm().GetCommonSettings(), cfg->m_Window, aParent );
  191. auto galType = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
  192. FOOTPRINT_PREVIEW_PANEL* panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, aUnitsProvider,
  193. std::move( gal_opts ), galType );
  194. panel->UpdateColors();
  195. const GRID_SETTINGS& gridCfg = cfg->m_Window.grid;
  196. panel->GetGAL()->SetGridVisibility( gridCfg.show );
  197. //Bounds checking cannot include number of elements as an index!
  198. int gridIdx = std::clamp( gridCfg.last_size_idx, 0, (int) gridCfg.grids.size() - 1 );
  199. double gridSizeX = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MILS,
  200. gridCfg.grids[gridIdx].x );
  201. double gridSizeY = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, EDA_UNITS::MILS,
  202. gridCfg.grids[gridIdx].y );
  203. panel->GetGAL()->SetGridSize( VECTOR2D( gridSizeX, gridSizeY ) );
  204. auto painter = static_cast<KIGFX::PCB_PAINTER*>( panel->GetView()->GetPainter() );
  205. auto settings = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( painter->GetSettings() );
  206. settings->SetHighlight( false );
  207. settings->SetNetColorMode( NET_COLOR_MODE::OFF );
  208. return panel;
  209. }