Update themed svgs
@@ -5023,5 +5023,79 @@ void BuildBitmapInfo( std::unordered_map<BITMAPS, std::vector<BITMAP_INFO>>& aBi
|
||||
aBitmapInfoCache[BITMAPS::stroke_none].emplace_back( BITMAPS::stroke_none, wxT( "stroke_none_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::twistedpair].emplace_back( BITMAPS::twistedpair, wxT( "twistedpair_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::viacalc].emplace_back( BITMAPS::viacalc, wxT( "viacalc_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_absolute_length_2].emplace_back( BITMAPS::constraint_absolute_length_2, wxT( "constraint_absolute_length_2.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_allowed_orientation].emplace_back( BITMAPS::constraint_allowed_orientation, wxT( "constraint_allowed_orientation.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_basic_clearance].emplace_back( BITMAPS::constraint_basic_clearance, wxT( "constraint_basic_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_board_outline_clearance].emplace_back( BITMAPS::constraint_board_outline_clearance, wxT( "constraint_board_outline_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_clearance].emplace_back( BITMAPS::constraint_clearance, wxT( "constraint_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_copper_to_edge_clearance].emplace_back( BITMAPS::constraint_copper_to_edge_clearance, wxT( "constraint_copper_to_edge_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_copper_to_hole_clearance].emplace_back( BITMAPS::constraint_copper_to_hole_clearance, wxT( "constraint_copper_to_hole_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_creepage_distance].emplace_back( BITMAPS::constraint_creepage_distance, wxT( "constraint_creepage_distance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_size].emplace_back( BITMAPS::constraint_hole_size, wxT( "constraint_hole_size.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_clearance].emplace_back( BITMAPS::constraint_hole_to_hole_clearance, wxT( "constraint_hole_to_hole_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_distance].emplace_back( BITMAPS::constraint_hole_to_hole_distance, wxT( "constraint_hole_to_hole_distance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_length].emplace_back( BITMAPS::constraint_length, wxT( "constraint_length.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair].emplace_back( BITMAPS::constraint_matched_length_diff_pair, wxT( "constraint_matched_length_diff_pair.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_maximum_allowed_deviation].emplace_back( BITMAPS::constraint_maximum_allowed_deviation, wxT( "constraint_maximum_allowed_deviation.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_maximum_via_count].emplace_back( BITMAPS::constraint_maximum_via_count, wxT( "constraint_maximum_via_count.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_angular_ring].emplace_back( BITMAPS::constraint_minimum_angular_ring, wxT( "constraint_minimum_angular_ring.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_annular_width].emplace_back( BITMAPS::constraint_minimum_annular_width, wxT( "constraint_minimum_annular_width.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_clearance].emplace_back( BITMAPS::constraint_minimum_clearance, wxT( "constraint_minimum_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_connection_width].emplace_back( BITMAPS::constraint_minimum_connection_width, wxT( "constraint_minimum_connection_width.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_item_clearance].emplace_back( BITMAPS::constraint_minimum_item_clearance, wxT( "constraint_minimum_item_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_soldermask_silver].emplace_back( BITMAPS::constraint_minimum_soldermask_silver, wxT( "constraint_minimum_soldermask_silver.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_text_height_and_thickness].emplace_back( BITMAPS::constraint_minimum_text_height_and_thickness, wxT( "constraint_minimum_text_height_and_thickness.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_thermal_relief_spoke_count].emplace_back( BITMAPS::constraint_minimum_thermal_relief_spoke_count, wxT( "constraint_minimum_thermal_relief_spoke_count.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_through_hole].emplace_back( BITMAPS::constraint_minimum_through_hole, wxT( "constraint_minimum_through_hole.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_track_width].emplace_back( BITMAPS::constraint_minimum_track_width, wxT( "constraint_minimum_track_width.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_uvia_diameter].emplace_back( BITMAPS::constraint_minimum_uvia_diameter, wxT( "constraint_minimum_uvia_diameter.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_uvia_hole].emplace_back( BITMAPS::constraint_minimum_uvia_hole, wxT( "constraint_minimum_uvia_hole.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_via_diameter].emplace_back( BITMAPS::constraint_minimum_via_diameter, wxT( "constraint_minimum_via_diameter.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_permitted_layers].emplace_back( BITMAPS::constraint_permitted_layers, wxT( "constraint_permitted_layers.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_routing_diff_pair].emplace_back( BITMAPS::constraint_routing_diff_pair, wxT( "constraint_routing_diff_pair.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_routing_width].emplace_back( BITMAPS::constraint_routing_width, wxT( "constraint_routing_width.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_silk_clearance].emplace_back( BITMAPS::constraint_silk_clearance, wxT( "constraint_silk_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_silk_to_soldermask_clearance].emplace_back( BITMAPS::constraint_silk_to_soldermask_clearance, wxT( "constraint_silk_to_soldermask_clearance.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_soldermask_expansion].emplace_back( BITMAPS::constraint_soldermask_expansion, wxT( "constraint_soldermask_expansion.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_solderpaste_expansion].emplace_back( BITMAPS::constraint_solderpaste_expansion, wxT( "constraint_solderpaste_expansion.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_via_style].emplace_back( BITMAPS::constraint_via_style, wxT( "constraint_via_style.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_vias_under_smd].emplace_back( BITMAPS::constraint_vias_under_smd, wxT( "constraint_vias_under_smd.png" ), -1, wxT( "light" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_absolute_length_2].emplace_back( BITMAPS::constraint_absolute_length_2, wxT( "constraint_absolute_length_2_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_allowed_orientation].emplace_back( BITMAPS::constraint_allowed_orientation, wxT( "constraint_allowed_orientation_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_basic_clearance].emplace_back( BITMAPS::constraint_basic_clearance, wxT( "constraint_basic_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_board_outline_clearance].emplace_back( BITMAPS::constraint_board_outline_clearance, wxT( "constraint_board_outline_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_clearance].emplace_back( BITMAPS::constraint_clearance, wxT( "constraint_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_copper_to_edge_clearance].emplace_back( BITMAPS::constraint_copper_to_edge_clearance, wxT( "constraint_copper_to_edge_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_copper_to_hole_clearance].emplace_back( BITMAPS::constraint_copper_to_hole_clearance, wxT( "constraint_copper_to_hole_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_creepage_distance].emplace_back( BITMAPS::constraint_creepage_distance, wxT( "constraint_creepage_distance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_size].emplace_back( BITMAPS::constraint_hole_size, wxT( "constraint_hole_size_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_clearance].emplace_back( BITMAPS::constraint_hole_to_hole_clearance, wxT( "constraint_hole_to_hole_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_hole_to_hole_distance].emplace_back( BITMAPS::constraint_hole_to_hole_distance, wxT( "constraint_hole_to_hole_distance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_length].emplace_back( BITMAPS::constraint_length, wxT( "constraint_length_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_matched_length_diff_pair].emplace_back( BITMAPS::constraint_matched_length_diff_pair, wxT( "constraint_matched_length_diff_pair_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_maximum_allowed_deviation].emplace_back( BITMAPS::constraint_maximum_allowed_deviation, wxT( "constraint_maximum_allowed_deviation_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_maximum_via_count].emplace_back( BITMAPS::constraint_maximum_via_count, wxT( "constraint_maximum_via_count_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_angular_ring].emplace_back( BITMAPS::constraint_minimum_angular_ring, wxT( "constraint_minimum_angular_ring_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_annular_width].emplace_back( BITMAPS::constraint_minimum_annular_width, wxT( "constraint_minimum_annular_width_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_clearance].emplace_back( BITMAPS::constraint_minimum_clearance, wxT( "constraint_minimum_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_connection_width].emplace_back( BITMAPS::constraint_minimum_connection_width, wxT( "constraint_minimum_connection_width_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_item_clearance].emplace_back( BITMAPS::constraint_minimum_item_clearance, wxT( "constraint_minimum_item_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_soldermask_silver].emplace_back( BITMAPS::constraint_minimum_soldermask_silver, wxT( "constraint_minimum_soldermask_silver_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_text_height_and_thickness].emplace_back( BITMAPS::constraint_minimum_text_height_and_thickness, wxT( "constraint_minimum_text_height_and_thickness_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_thermal_relief_spoke_count].emplace_back( BITMAPS::constraint_minimum_thermal_relief_spoke_count, wxT( "constraint_minimum_thermal_relief_spoke_count_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_through_hole].emplace_back( BITMAPS::constraint_minimum_through_hole, wxT( "constraint_minimum_through_hole_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_track_width].emplace_back( BITMAPS::constraint_minimum_track_width, wxT( "constraint_minimum_track_width_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_uvia_diameter].emplace_back( BITMAPS::constraint_minimum_uvia_diameter, wxT( "constraint_minimum_uvia_diameter_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_uvia_hole].emplace_back( BITMAPS::constraint_minimum_uvia_hole, wxT( "constraint_minimum_uvia_hole_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_minimum_via_diameter].emplace_back( BITMAPS::constraint_minimum_via_diameter, wxT( "constraint_minimum_via_diameter_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_permitted_layers].emplace_back( BITMAPS::constraint_permitted_layers, wxT( "constraint_permitted_layers_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_routing_diff_pair].emplace_back( BITMAPS::constraint_routing_diff_pair, wxT( "constraint_routing_diff_pair_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_routing_width].emplace_back( BITMAPS::constraint_routing_width, wxT( "constraint_routing_width_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_silk_clearance].emplace_back( BITMAPS::constraint_silk_clearance, wxT( "constraint_silk_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_silk_to_soldermask_clearance].emplace_back( BITMAPS::constraint_silk_to_soldermask_clearance, wxT( "constraint_silk_to_soldermask_clearance_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_soldermask_expansion].emplace_back( BITMAPS::constraint_soldermask_expansion, wxT( "constraint_soldermask_expansion_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_solderpaste_expansion].emplace_back( BITMAPS::constraint_solderpaste_expansion, wxT( "constraint_solderpaste_expansion_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_via_style].emplace_back( BITMAPS::constraint_via_style, wxT( "constraint_via_style_dark.png" ), -1, wxT( "dark" ) );
|
||||
aBitmapInfoCache[BITMAPS::constraint_vias_under_smd].emplace_back( BITMAPS::constraint_vias_under_smd, wxT( "constraint_vias_under_smd_dark.png" ), -1, wxT( "dark" ) );
|
||||
|
||||
};
|
||||
|
||||
@@ -693,7 +693,7 @@ enum class BITMAPS : unsigned int
|
||||
zoom_selection,
|
||||
|
||||
constraint_basic_clearance,
|
||||
constraint_outline_clearance,
|
||||
constraint_board_outline_clearance,
|
||||
constraint_minimum_clearance,
|
||||
constraint_net_antenna,
|
||||
constraint_short_circuit,
|
||||
@@ -727,7 +727,10 @@ enum class BITMAPS : unsigned int
|
||||
constraint_matched_length_diff_pair,
|
||||
constraint_routing_diff_pair,
|
||||
constraint_routing_width,
|
||||
constraint_clearance,
|
||||
constraint_length,
|
||||
constraint_maximum_via_count,
|
||||
constraint_silk_clearance,
|
||||
constraint_matched_length_all_traces_in_group,
|
||||
constraint_absolute_length,
|
||||
constraint_absolute_length_2,
|
||||
|
||||
@@ -338,7 +338,19 @@ set( PCBNEW_DRC_SRCS
|
||||
drc/rule_editor/drc_re_permitted_layers_panel.cpp
|
||||
drc/rule_editor/drc_re_allowed_orientation_panel_base.cpp
|
||||
drc/rule_editor/drc_re_allowed_orientation_panel.cpp
|
||||
drc/rule_editor/drc_re_bitmap_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_object_selector_panel.cpp
|
||||
drc/rule_editor/drc_re_overlay_field.cpp
|
||||
drc/rule_editor/drc_re_routing_width_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_rtg_diff_pair_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_min_txt_ht_th_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_abs_length_two_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_via_style_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_numeric_input_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_bool_input_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_permitted_layers_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_allowed_orientation_overlay_panel.cpp
|
||||
drc/rule_editor/drc_re_overlay_panel_factory.cpp
|
||||
drc/rule_editor/drc_re_condition_row_panel.cpp
|
||||
drc/rule_editor/drc_re_condition_group_panel.cpp
|
||||
drc/rule_editor/drc_re_custom_rule_panel.cpp
|
||||
|
||||
@@ -52,6 +52,19 @@ public:
|
||||
|
||||
virtual ~DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_absolute_length_2; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_absolute_lenght_2.png (~340x130)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 35, 95, 30, 1 }, // min_length (left arrow)
|
||||
{ 165, 225, 85, 2 }, // opt_length (bottom center arrow)
|
||||
{ 290, 350, 30, 3 }, // max_length (right arrow)
|
||||
};
|
||||
}
|
||||
|
||||
double GetMinimumLength() const { return m_minLength; }
|
||||
|
||||
void SetMinimumLength( double aLength ) { m_minLength = aLength; }
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_abs_length_two_overlay_panel.h"
|
||||
#include "drc_re_abs_length_two_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL::DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA* aData, EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( BITMAPS::constraint_absolute_length_2 );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
m_minLengthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_length" ), positions[0], m_minLengthBinder.get() );
|
||||
|
||||
m_optLengthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "opt_length" ), positions[1], m_optLengthBinder.get() );
|
||||
|
||||
m_maxLengthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_length" ), positions[2], m_maxLengthBinder.get() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_minLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinimumLength() ) );
|
||||
m_optLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetOptimumLength() ) );
|
||||
m_maxLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaximumLength() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_data->SetMinimumLength( pcbIUScale.IUTomm( m_minLengthBinder->GetDoubleValue() ) );
|
||||
m_data->SetOptimumLength( pcbIUScale.IUTomm( m_optLengthBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaximumLength( pcbIUScale.IUTomm( m_maxLengthBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL_H
|
||||
#define DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for absolute length constraints showing min, opt, and max length fields
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
std::unique_ptr<UNIT_BINDER> m_minLengthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_optLengthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxLengthBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL_H
|
||||
@@ -52,6 +52,22 @@ public:
|
||||
|
||||
virtual ~DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_allowed_orientation; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_allowed_orientation.png (~280x180)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
// Checkboxes stacked vertically on the right side
|
||||
return {
|
||||
{ 230, 270, 20, 1 }, // 0 degrees checkbox
|
||||
{ 230, 270, 50, 2 }, // 90 degrees checkbox
|
||||
{ 230, 270, 80, 3 }, // 180 degrees checkbox
|
||||
{ 230, 270, 110, 4 }, // 270 degrees checkbox
|
||||
{ 230, 270, 140, 5 }, // all degrees checkbox
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
VALIDATION_RESULT result;
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_allowed_orientation_overlay_panel.h"
|
||||
#include "drc_re_allowed_orientation_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
|
||||
DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL::DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA* aData ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_zeroDegreesCheckbox( nullptr ),
|
||||
m_ninetyDegreesCheckbox( nullptr ),
|
||||
m_oneEightyDegreesCheckbox( nullptr ),
|
||||
m_twoSeventyDegreesCheckbox( nullptr ),
|
||||
m_allDegreesCheckbox( nullptr )
|
||||
{
|
||||
SetBackgroundBitmap( m_data->GetOverlayBitmap() );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
DRC_RE_OVERLAY_FIELD* field = AddCheckbox( wxS( "zero_degrees" ), positions[0] );
|
||||
m_zeroDegreesCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
field = AddCheckbox( wxS( "ninety_degrees" ), positions[1] );
|
||||
m_ninetyDegreesCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
field = AddCheckbox( wxS( "one_eighty_degrees" ), positions[2] );
|
||||
m_oneEightyDegreesCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
field = AddCheckbox( wxS( "two_seventy_degrees" ), positions[3] );
|
||||
m_twoSeventyDegreesCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
field = AddCheckbox( wxS( "all_degrees" ), positions[4] );
|
||||
m_allDegreesCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data || !m_zeroDegreesCheckbox || !m_ninetyDegreesCheckbox || !m_oneEightyDegreesCheckbox
|
||||
|| !m_twoSeventyDegreesCheckbox || !m_allDegreesCheckbox )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_zeroDegreesCheckbox->SetValue( m_data->GetIsZeroDegreesAllowed() );
|
||||
m_ninetyDegreesCheckbox->SetValue( m_data->GetIsNinetyDegreesAllowed() );
|
||||
m_oneEightyDegreesCheckbox->SetValue( m_data->GetIsOneEightyDegreesAllowed() );
|
||||
m_twoSeventyDegreesCheckbox->SetValue( m_data->GetIsTwoSeventyDegreesAllowed() );
|
||||
m_allDegreesCheckbox->SetValue( m_data->GetIsAllDegreesAllowed() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data || !m_zeroDegreesCheckbox || !m_ninetyDegreesCheckbox || !m_oneEightyDegreesCheckbox
|
||||
|| !m_twoSeventyDegreesCheckbox || !m_allDegreesCheckbox )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_data->SetIsZeroDegreesAllowed( m_zeroDegreesCheckbox->GetValue() );
|
||||
m_data->SetIsNinetyDegreesAllowed( m_ninetyDegreesCheckbox->GetValue() );
|
||||
m_data->SetIsOneEightyDegreesAllowed( m_oneEightyDegreesCheckbox->GetValue() );
|
||||
m_data->SetIsTwoSeventyDegreesAllowed( m_twoSeventyDegreesCheckbox->GetValue() );
|
||||
m_data->SetIsAllDegreesAllowed( m_allDegreesCheckbox->GetValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL_H
|
||||
#define DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL_H
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
class DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA;
|
||||
class wxCheckBox;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for allowed orientation constraints showing checkboxes
|
||||
* for each orientation angle positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA* aData );
|
||||
|
||||
~DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA* m_data;
|
||||
|
||||
wxCheckBox* m_zeroDegreesCheckbox;
|
||||
wxCheckBox* m_ninetyDegreesCheckbox;
|
||||
wxCheckBox* m_oneEightyDegreesCheckbox;
|
||||
wxCheckBox* m_twoSeventyDegreesCheckbox;
|
||||
wxCheckBox* m_allDegreesCheckbox;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL_H
|
||||
@@ -24,11 +24,15 @@
|
||||
#ifndef DRC_RE_BASE_CONSTRAINT_DATA_H_
|
||||
#define DRC_RE_BASE_CONSTRAINT_DATA_H_
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <dialogs/rule_editor_data_base.h>
|
||||
#include "drc_re_overlay_types.h"
|
||||
#include "drc_rule_editor_enums.h"
|
||||
#include <string_utils.h>
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
class DRC_RE_BASE_CONSTRAINT_DATA : public RULE_EDITOR_DATA_BASE
|
||||
{
|
||||
@@ -52,6 +56,23 @@ public:
|
||||
|
||||
virtual wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) { return wxEmptyString; }
|
||||
|
||||
/**
|
||||
* Returns the bitmap to use for the overlay panel background.
|
||||
* Override in derived classes to provide constraint-specific artwork.
|
||||
*
|
||||
* @return BITMAPS enum value for the overlay bitmap, or BITMAPS::INVALID_BITMAP if none.
|
||||
*/
|
||||
virtual BITMAPS GetOverlayBitmap() const { return BITMAPS::INVALID_BITMAP; }
|
||||
|
||||
/**
|
||||
* Returns the field positions for controls overlaid on the constraint bitmap.
|
||||
* Override in derived classes to specify where input fields should be placed.
|
||||
* Each position includes X range, Y coordinate, and tab order for navigation.
|
||||
*
|
||||
* @return Vector of field position specifications, empty if no overlay fields.
|
||||
*/
|
||||
virtual std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const { return {}; }
|
||||
|
||||
/**
|
||||
* Returns just the constraint clauses without the rule wrapper.
|
||||
* Used for merging multiple constraint panels into a single rule.
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_bitmap_overlay_panel.h"
|
||||
#include "drc_re_overlay_field.h"
|
||||
|
||||
#include <bitmaps.h>
|
||||
|
||||
#include <wx/bmpbndl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL::DRC_RE_BITMAP_OVERLAY_PANEL( wxWindow* aParent, wxWindowID aId ) :
|
||||
wxPanel(),
|
||||
m_bitmapId( BITMAPS::INVALID_BITMAP ),
|
||||
m_baseBitmapSize( 0, 0 )
|
||||
{
|
||||
// Must set background style BEFORE creating the window
|
||||
SetBackgroundStyle( wxBG_STYLE_PAINT );
|
||||
Create( aParent, aId );
|
||||
|
||||
Bind( wxEVT_PAINT, &DRC_RE_BITMAP_OVERLAY_PANEL::OnPaint, this );
|
||||
Bind( wxEVT_DPI_CHANGED, &DRC_RE_BITMAP_OVERLAY_PANEL::OnDPIChanged, this );
|
||||
Bind( wxEVT_SYS_COLOUR_CHANGED, &DRC_RE_BITMAP_OVERLAY_PANEL::OnThemeChange, this );
|
||||
}
|
||||
|
||||
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL::~DRC_RE_BITMAP_OVERLAY_PANEL()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::OnPaint( wxPaintEvent& aEvent )
|
||||
{
|
||||
wxPaintDC dc( this );
|
||||
|
||||
if( !m_bitmap.IsOk() )
|
||||
return;
|
||||
|
||||
dc.DrawBitmap( m_bitmap, 0, 0, true );
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::OnDPIChanged( wxDPIChangedEvent& aEvent )
|
||||
{
|
||||
LoadBitmap();
|
||||
PositionFields();
|
||||
Refresh();
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::OnThemeChange( wxSysColourChangedEvent& aEvent )
|
||||
{
|
||||
LoadBitmap();
|
||||
Refresh();
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldFocus( wxFocusEvent& aEvent )
|
||||
{
|
||||
// Platform handles focus ring automatically.
|
||||
// Could add custom highlighting here if needed.
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldBlur( wxFocusEvent& aEvent )
|
||||
{
|
||||
// Platform handles focus ring automatically.
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::SetupFieldStyling( wxControl* aControl )
|
||||
{
|
||||
if( !aControl )
|
||||
return;
|
||||
|
||||
// Bind focus events to track active field
|
||||
aControl->Bind( wxEVT_SET_FOCUS, &DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldFocus, this );
|
||||
aControl->Bind( wxEVT_KILL_FOCUS, &DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldBlur, this );
|
||||
}
|
||||
|
||||
|
||||
double DRC_RE_BITMAP_OVERLAY_PANEL::GetScaleFactor() const
|
||||
{
|
||||
double scale = GetContentScaleFactor();
|
||||
|
||||
// Round to nearest supported bitmap resolution (1.0, 1.5, or 2.0)
|
||||
if( scale < 1.25 )
|
||||
return 1.0;
|
||||
else if( scale < 1.75 )
|
||||
return 1.5;
|
||||
else
|
||||
return 2.0;
|
||||
}
|
||||
|
||||
|
||||
wxPoint DRC_RE_BITMAP_OVERLAY_PANEL::ScalePosition( int aX, int aY ) const
|
||||
{
|
||||
double scale = GetScaleFactor();
|
||||
return wxPoint( static_cast<int>( aX * scale ), static_cast<int>( aY * scale ) );
|
||||
}
|
||||
|
||||
|
||||
wxSize DRC_RE_BITMAP_OVERLAY_PANEL::ScaleSize( int aWidth, int aHeight ) const
|
||||
{
|
||||
double scale = GetScaleFactor();
|
||||
return wxSize( static_cast<int>( aWidth * scale ), static_cast<int>( aHeight * scale ) );
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::LoadBitmap()
|
||||
{
|
||||
if( m_bitmapId == BITMAPS::INVALID_BITMAP )
|
||||
return;
|
||||
|
||||
wxBitmapBundle bundle = KiBitmapBundle( m_bitmapId );
|
||||
|
||||
m_bitmap = bundle.GetBitmapFor( this );
|
||||
m_baseBitmapSize = bundle.GetDefaultSize();
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::SetBackgroundBitmap( BITMAPS aBitmap )
|
||||
{
|
||||
m_bitmapId = aBitmap;
|
||||
LoadBitmap();
|
||||
|
||||
if( m_bitmap.IsOk() )
|
||||
SetMinSize( m_bitmap.GetSize() );
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::PositionFields()
|
||||
{
|
||||
for( const auto& field : m_fields )
|
||||
{
|
||||
const DRC_RE_FIELD_POSITION& pos = field->GetPosition();
|
||||
wxControl* ctrl = field->GetControl();
|
||||
|
||||
if( !ctrl )
|
||||
continue;
|
||||
|
||||
// Calculate scaled position and size
|
||||
wxPoint scaledPos = ScalePosition( pos.xStart, pos.yTop );
|
||||
int width = pos.xEnd - pos.xStart;
|
||||
wxSize scaledSize = ScaleSize( width, ctrl->GetBestSize().GetHeight() );
|
||||
|
||||
// Check bounds
|
||||
if( m_bitmap.IsOk() )
|
||||
{
|
||||
wxSize bmpSize = m_bitmap.GetSize();
|
||||
|
||||
if( scaledPos.x + scaledSize.GetWidth() > bmpSize.GetWidth() ||
|
||||
scaledPos.y + scaledSize.GetHeight() > bmpSize.GetHeight() )
|
||||
{
|
||||
wxLogWarning( "Field '%s' position exceeds bitmap bounds", field->GetFieldId() );
|
||||
}
|
||||
}
|
||||
|
||||
ctrl->SetPosition( scaledPos );
|
||||
ctrl->SetSize( scaledSize );
|
||||
|
||||
// Position label if present
|
||||
if( field->HasLabel() )
|
||||
PositionLabel( field.get() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::PositionLabel( DRC_RE_OVERLAY_FIELD* aField )
|
||||
{
|
||||
wxStaticText* label = aField->GetLabel();
|
||||
wxControl* ctrl = aField->GetControl();
|
||||
|
||||
if( !label || !ctrl )
|
||||
return;
|
||||
|
||||
const DRC_RE_FIELD_POSITION& pos = aField->GetPosition();
|
||||
wxPoint ctrlPos = ctrl->GetPosition();
|
||||
wxSize ctrlSize = ctrl->GetSize();
|
||||
wxSize labelSize = label->GetBestSize();
|
||||
|
||||
wxPoint labelPos;
|
||||
constexpr int GAP = 4;
|
||||
|
||||
switch( pos.labelPosition )
|
||||
{
|
||||
case LABEL_POSITION::LEFT:
|
||||
labelPos.x = ctrlPos.x - labelSize.GetWidth() - GAP;
|
||||
labelPos.y = ctrlPos.y + ( ctrlSize.GetHeight() - labelSize.GetHeight() ) / 2;
|
||||
break;
|
||||
|
||||
case LABEL_POSITION::RIGHT:
|
||||
labelPos.x = ctrlPos.x + ctrlSize.GetWidth() + GAP;
|
||||
labelPos.y = ctrlPos.y + ( ctrlSize.GetHeight() - labelSize.GetHeight() ) / 2;
|
||||
break;
|
||||
|
||||
case LABEL_POSITION::TOP:
|
||||
labelPos.x = ctrlPos.x + ( ctrlSize.GetWidth() - labelSize.GetWidth() ) / 2;
|
||||
labelPos.y = ctrlPos.y - labelSize.GetHeight() - GAP;
|
||||
break;
|
||||
|
||||
case LABEL_POSITION::BOTTOM:
|
||||
labelPos.x = ctrlPos.x + ( ctrlSize.GetWidth() - labelSize.GetWidth() ) / 2;
|
||||
labelPos.y = ctrlPos.y + ctrlSize.GetHeight() + GAP;
|
||||
break;
|
||||
|
||||
case LABEL_POSITION::NONE:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
label->SetPosition( labelPos );
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_BITMAP_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
// Base implementation does nothing; derived classes override to populate fields
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_BITMAP_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
// Base implementation does nothing; derived classes override to read fields
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::ClearFieldErrors()
|
||||
{
|
||||
for( const auto& field : m_fields )
|
||||
field->ShowError( false );
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_BITMAP_OVERLAY_PANEL::ShowFieldError( const wxString& aFieldId )
|
||||
{
|
||||
auto it = m_fieldIdMap.find( aFieldId );
|
||||
|
||||
if( it != m_fieldIdMap.end() )
|
||||
it->second->ShowError( true );
|
||||
}
|
||||
|
||||
|
||||
DRC_RE_OVERLAY_FIELD* DRC_RE_BITMAP_OVERLAY_PANEL::AddCheckbox( const wxString& aId,
|
||||
const DRC_RE_FIELD_POSITION& aPosition )
|
||||
{
|
||||
wxCheckBox* checkbox = new wxCheckBox( this, wxID_ANY, wxEmptyString );
|
||||
|
||||
auto field = std::make_unique<DRC_RE_OVERLAY_FIELD>( this, aId, checkbox, aPosition );
|
||||
DRC_RE_OVERLAY_FIELD* fieldPtr = field.get();
|
||||
|
||||
SetupFieldStyling( checkbox );
|
||||
|
||||
wxPoint pos = ScalePosition( aPosition.xStart, aPosition.yTop );
|
||||
checkbox->SetPosition( pos );
|
||||
|
||||
// Create label if specified
|
||||
fieldPtr->CreateLabel();
|
||||
|
||||
if( fieldPtr->HasLabel() )
|
||||
PositionLabel( fieldPtr );
|
||||
|
||||
m_fieldIdMap[aId] = fieldPtr;
|
||||
m_fields.push_back( std::move( field ) );
|
||||
|
||||
return fieldPtr;
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_BITMAP_OVERLAY_PANEL_H
|
||||
#define DRC_RE_BITMAP_OVERLAY_PANEL_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include "drc_re_content_panel_base.h"
|
||||
#include "drc_re_overlay_field.h"
|
||||
#include "drc_re_overlay_types.h"
|
||||
|
||||
class wxControl;
|
||||
class wxCheckBox;
|
||||
class wxPaintEvent;
|
||||
class wxDPIChangedEvent;
|
||||
class wxSysColourChangedEvent;
|
||||
class wxFocusEvent;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for DRC rule editor panels that display input fields overlaid on a bitmap.
|
||||
*
|
||||
* This class provides infrastructure for creating constraint editor panels where input fields
|
||||
* are precisely positioned over explanatory constraint diagrams. The bitmap serves as a visual
|
||||
* guide showing what each field value represents.
|
||||
*
|
||||
* Derived classes should:
|
||||
* - Call SetBackgroundBitmap() in their constructor to set the diagram
|
||||
* - Create fields using AddField(), AddFieldWithUnits(), or AddCheckbox()
|
||||
* - Override TransferDataToWindow/FromWindow to populate/read field values
|
||||
*/
|
||||
class DRC_RE_BITMAP_OVERLAY_PANEL : public wxPanel,
|
||||
public DRC_RULE_EDITOR_CONTENT_PANEL_BASE
|
||||
{
|
||||
public:
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( wxWindow* aParent, wxWindowID aId = wxID_ANY );
|
||||
|
||||
virtual ~DRC_RE_BITMAP_OVERLAY_PANEL();
|
||||
|
||||
/**
|
||||
* Set the background bitmap for this panel.
|
||||
*
|
||||
* @param aBitmap The BITMAPS enum value identifying the constraint diagram.
|
||||
*/
|
||||
void SetBackgroundBitmap( BITMAPS aBitmap );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
/**
|
||||
* Clear error indicators from all fields.
|
||||
*/
|
||||
void ClearFieldErrors();
|
||||
|
||||
/**
|
||||
* Show an error indicator on the specified field.
|
||||
*
|
||||
* @param aFieldId The string identifier of the field to highlight.
|
||||
*/
|
||||
void ShowFieldError( const wxString& aFieldId );
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Create and position a field control on the bitmap overlay.
|
||||
*
|
||||
* @tparam T The wxWindow-derived control type to create.
|
||||
* @param aId String identifier for this field (used for error display and lookup).
|
||||
* @param aPosition Position specification in 1x bitmap coordinates.
|
||||
* @return Pointer to the created field wrapper.
|
||||
*/
|
||||
template <typename T>
|
||||
DRC_RE_OVERLAY_FIELD* AddField( const wxString& aId, const DRC_RE_FIELD_POSITION& aPosition );
|
||||
|
||||
/**
|
||||
* Create and position a field control with unit binding.
|
||||
*
|
||||
* @tparam T The wxWindow-derived control type to create.
|
||||
* @param aId String identifier for this field.
|
||||
* @param aPosition Position specification in 1x bitmap coordinates.
|
||||
* @param aUnitBinder UNIT_BINDER to associate with this field for unit conversion.
|
||||
* @return Pointer to the created field wrapper.
|
||||
*/
|
||||
template <typename T>
|
||||
DRC_RE_OVERLAY_FIELD* AddFieldWithUnits( const wxString& aId,
|
||||
const DRC_RE_FIELD_POSITION& aPosition,
|
||||
UNIT_BINDER* aUnitBinder );
|
||||
|
||||
/**
|
||||
* Create and position a checkbox control on the bitmap overlay.
|
||||
*
|
||||
* @param aId String identifier for this checkbox.
|
||||
* @param aPosition Position specification in 1x bitmap coordinates.
|
||||
* @return Pointer to the created field wrapper.
|
||||
*/
|
||||
DRC_RE_OVERLAY_FIELD* AddCheckbox( const wxString& aId, const DRC_RE_FIELD_POSITION& aPosition );
|
||||
|
||||
/**
|
||||
* Load the appropriate bitmap variant for the current theme and DPI.
|
||||
*/
|
||||
void LoadBitmap();
|
||||
|
||||
/**
|
||||
* Position all fields based on the current scale factor.
|
||||
*/
|
||||
void PositionFields();
|
||||
|
||||
/**
|
||||
* Get the current DPI scale factor.
|
||||
*
|
||||
* @return Scale factor (1.0, 1.5, or 2.0).
|
||||
*/
|
||||
double GetScaleFactor() const;
|
||||
|
||||
/**
|
||||
* Scale pixel coordinates from 1x bitmap space to current display space.
|
||||
*
|
||||
* @param aX X coordinate in 1x bitmap pixels.
|
||||
* @param aY Y coordinate in 1x bitmap pixels.
|
||||
* @return Scaled position as wxPoint.
|
||||
*/
|
||||
wxPoint ScalePosition( int aX, int aY ) const;
|
||||
|
||||
/**
|
||||
* Scale pixel dimensions from 1x bitmap space to current display space.
|
||||
*
|
||||
* @param aWidth Width in 1x bitmap pixels.
|
||||
* @param aHeight Height in 1x bitmap pixels.
|
||||
* @return Scaled size as wxSize.
|
||||
*/
|
||||
wxSize ScaleSize( int aWidth, int aHeight ) const;
|
||||
|
||||
/**
|
||||
* Apply transparent styling to a field control.
|
||||
*
|
||||
* @param aControl The control to style.
|
||||
*/
|
||||
void SetupFieldStyling( wxControl* aControl );
|
||||
|
||||
private:
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
void OnDPIChanged( wxDPIChangedEvent& aEvent );
|
||||
void OnThemeChange( wxSysColourChangedEvent& aEvent );
|
||||
void OnFieldFocus( wxFocusEvent& aEvent );
|
||||
void OnFieldBlur( wxFocusEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Position a label relative to its field control based on the label position setting.
|
||||
*
|
||||
* @param aField The overlay field containing the label to position.
|
||||
*/
|
||||
void PositionLabel( DRC_RE_OVERLAY_FIELD* aField );
|
||||
|
||||
wxBitmap m_bitmap; ///< Current background bitmap
|
||||
BITMAPS m_bitmapId; ///< BITMAPS enum value
|
||||
wxSize m_baseBitmapSize; ///< Bitmap size at 1x scale
|
||||
std::vector<std::unique_ptr<DRC_RE_OVERLAY_FIELD>> m_fields; ///< All overlay fields
|
||||
std::map<wxString, DRC_RE_OVERLAY_FIELD*> m_fieldIdMap; ///< Field ID to field lookup
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
DRC_RE_OVERLAY_FIELD* DRC_RE_BITMAP_OVERLAY_PANEL::AddField( const wxString& aId,
|
||||
const DRC_RE_FIELD_POSITION& aPosition )
|
||||
{
|
||||
// Create the control
|
||||
T* control = new T( this, wxID_ANY );
|
||||
|
||||
// Create the overlay field wrapper
|
||||
auto field = std::make_unique<DRC_RE_OVERLAY_FIELD>( this, aId, control, aPosition );
|
||||
DRC_RE_OVERLAY_FIELD* fieldPtr = field.get();
|
||||
|
||||
// Set up styling
|
||||
SetupFieldStyling( control );
|
||||
|
||||
// Position the field
|
||||
wxPoint pos = ScalePosition( aPosition.xStart, aPosition.yTop );
|
||||
int width = aPosition.xEnd - aPosition.xStart;
|
||||
wxSize size = ScaleSize( width, control->GetBestSize().GetHeight() );
|
||||
control->SetPosition( pos );
|
||||
control->SetSize( size );
|
||||
|
||||
// Create label if specified
|
||||
fieldPtr->CreateLabel();
|
||||
|
||||
if( fieldPtr->HasLabel() )
|
||||
PositionLabel( fieldPtr );
|
||||
|
||||
// Store in collections
|
||||
m_fieldIdMap[aId] = fieldPtr;
|
||||
m_fields.push_back( std::move( field ) );
|
||||
|
||||
return fieldPtr;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
DRC_RE_OVERLAY_FIELD* DRC_RE_BITMAP_OVERLAY_PANEL::AddFieldWithUnits( const wxString& aId,
|
||||
const DRC_RE_FIELD_POSITION& aPosition,
|
||||
UNIT_BINDER* aUnitBinder )
|
||||
{
|
||||
// Create the field using the base AddField method
|
||||
DRC_RE_OVERLAY_FIELD* field = AddField<T>( aId, aPosition );
|
||||
|
||||
// Associate the unit binder for value conversion
|
||||
field->SetUnitBinder( aUnitBinder );
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
#endif // DRC_RE_BITMAP_OVERLAY_PANEL_H
|
||||
@@ -46,6 +46,17 @@ public:
|
||||
|
||||
virtual ~DRC_RE_BOOL_INPUT_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_vias_under_smd; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_vias_under_SMD.png (~280x160)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 20, 40, 130, 1 }, // checkbox (bottom left corner)
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
// Boolean inputs are always valid - any true/false value is acceptable
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_bool_input_overlay_panel.h"
|
||||
#include "drc_re_bool_input_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
|
||||
DRC_RE_BOOL_INPUT_OVERLAY_PANEL::DRC_RE_BOOL_INPUT_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_BOOL_INPUT_CONSTRAINT_DATA* aData ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_boolInputCheckbox( nullptr )
|
||||
{
|
||||
SetBackgroundBitmap( m_data->GetOverlayBitmap() );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
DRC_RE_OVERLAY_FIELD* field = AddCheckbox( wxS( "bool_input" ), positions[0] );
|
||||
m_boolInputCheckbox = static_cast<wxCheckBox*>( field->GetControl() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_BOOL_INPUT_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data || !m_boolInputCheckbox )
|
||||
return false;
|
||||
|
||||
m_boolInputCheckbox->SetValue( m_data->GetBoolInputValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_BOOL_INPUT_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data || !m_boolInputCheckbox )
|
||||
return false;
|
||||
|
||||
m_data->SetBoolInputValue( m_boolInputCheckbox->GetValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_BOOL_INPUT_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_BOOL_INPUT_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_BOOL_INPUT_OVERLAY_PANEL_H
|
||||
#define DRC_RE_BOOL_INPUT_OVERLAY_PANEL_H
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
class DRC_RE_BOOL_INPUT_CONSTRAINT_DATA;
|
||||
class wxCheckBox;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for boolean input constraints showing a single checkbox
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_BOOL_INPUT_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_BOOL_INPUT_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_BOOL_INPUT_CONSTRAINT_DATA* aData );
|
||||
|
||||
~DRC_RE_BOOL_INPUT_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_BOOL_INPUT_CONSTRAINT_DATA* m_data;
|
||||
|
||||
wxCheckBox* m_boolInputCheckbox;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_BOOL_INPUT_OVERLAY_PANEL_H
|
||||
@@ -54,6 +54,9 @@ public:
|
||||
|
||||
virtual ~DRC_RULE_EDITOR_CONTENT_PANEL_BASE() = default;
|
||||
|
||||
virtual bool TransferDataToWindow() = 0;
|
||||
virtual bool TransferDataFromWindow() = 0;
|
||||
|
||||
virtual bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) = 0;
|
||||
|
||||
virtual wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) = 0;
|
||||
|
||||
@@ -49,6 +49,21 @@ public:
|
||||
|
||||
virtual ~DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override
|
||||
{
|
||||
return BITMAPS::constraint_minimum_text_height_and_thickness;
|
||||
}
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_minimum_text_height_and_thickness.png (~300x200)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 230, 310, 55, 1 }, // min_text_height (right side, vertical dimension)
|
||||
{ 140, 220, 165, 2 }, // min_text_thickness (bottom, horizontal dimension)
|
||||
};
|
||||
}
|
||||
|
||||
double GetMinTextHeight() { return m_minTextHeight; }
|
||||
|
||||
void SetMinTextHeight( double aMinTextHeight ) { m_minTextHeight = aMinTextHeight; }
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_min_txt_ht_th_overlay_panel.h"
|
||||
#include "drc_re_min_txt_ht_th_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL::DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( BITMAPS::constraint_minimum_text_height_and_thickness );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
m_minTextHeightBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_text_height" ), positions[0],
|
||||
m_minTextHeightBinder.get() );
|
||||
|
||||
m_minTextThicknessBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_text_thickness" ), positions[1],
|
||||
m_minTextThicknessBinder.get() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_minTextHeightBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinTextHeight() ) );
|
||||
m_minTextThicknessBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinTextThickness() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_data->SetMinTextHeight( pcbIUScale.IUTomm( m_minTextHeightBinder->GetDoubleValue() ) );
|
||||
m_data->SetMinTextThickness( pcbIUScale.IUTomm( m_minTextThicknessBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL_H
|
||||
#define DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for minimum text height and thickness constraints showing text dimension fields
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
std::unique_ptr<UNIT_BINDER> m_minTextHeightBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_minTextThicknessBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL_H
|
||||
@@ -46,6 +46,17 @@ public:
|
||||
|
||||
virtual ~DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_minimum_track_width; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_minimum_track_width.png (~280x140)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 220, 300, 50, 1 }, // value (right side, near dimension arrow)
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<wxString> GetConstraintClauses( const RULE_GENERATION_CONTEXT& aContext ) const override
|
||||
{
|
||||
wxString code = GetConstraintCode();
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_numeric_input_overlay_panel.h"
|
||||
#include "drc_re_numeric_input_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL::DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA* aData, EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( m_data->GetOverlayBitmap() );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
m_valueBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "value" ), positions[0], m_valueBinder.get() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_valueBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetNumericInputValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
m_data->SetNumericInputValue( pcbIUScale.IUTomm( m_valueBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL_H
|
||||
#define DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for numeric input constraints showing a single numeric value field
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
std::unique_ptr<UNIT_BINDER> m_valueBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL_H
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
const std::map<DRC_RULE_EDITOR_CONSTRAINT_NAME, BITMAPS> NumericConstraintBitMapPairs = {
|
||||
{ BASIC_CLEARANCE, BITMAPS::constraint_basic_clearance },
|
||||
{ BOARD_OUTLINE_CLEARANCE, BITMAPS::constraint_outline_clearance },
|
||||
{ BOARD_OUTLINE_CLEARANCE, BITMAPS::constraint_board_outline_clearance },
|
||||
{ MINIMUM_CLEARANCE, BITMAPS::constraint_minimum_clearance },
|
||||
{ MINIMUM_ITEM_CLEARANCE, BITMAPS::constraint_minimum_item_clearance },
|
||||
{ CREEPAGE_DISTANCE, BITMAPS::constraint_creepage_distance},
|
||||
@@ -47,7 +47,7 @@ const std::map<DRC_RULE_EDITOR_CONSTRAINT_NAME, BITMAPS> NumericConstraintBitMap
|
||||
{ MINIMUM_UVIA_HOLE, BITMAPS::constraint_minimum_uvia_hole },
|
||||
{ MINIMUM_UVIA_DIAMETER, BITMAPS::constraint_minimum_uvia_diameter },
|
||||
{ MINIMUM_VIA_DIAMETER, BITMAPS::constraint_minimum_via_diameter },
|
||||
{ SILK_TO_SILK_CLEARANCE, BITMAPS::constraint_silk_to_silk_clearance },
|
||||
{ SILK_TO_SILK_CLEARANCE, BITMAPS::constraint_silk_clearance },
|
||||
{ SILK_TO_SOLDERMASK_CLEARANCE, BITMAPS::constraint_silk_to_soldermask_clearance },
|
||||
{ MINIMUM_SOLDERMASK_SILVER, BITMAPS::constraint_minimum_soldermask_silver },
|
||||
{ SOLDERMASK_EXPANSION, BITMAPS::constraint_soldermask_expansion },
|
||||
@@ -56,7 +56,7 @@ const std::map<DRC_RULE_EDITOR_CONSTRAINT_NAME, BITMAPS> NumericConstraintBitMap
|
||||
{ MINIMUM_ANGULAR_RING, BITMAPS::constraint_minimum_angular_ring },
|
||||
{ MINIMUM_THERMAL_RELIEF_SPOKE_COUNT, BITMAPS::constraint_minimum_thermal_relief_spoke_count },
|
||||
{ MAXIMUM_VIA_COUNT, BITMAPS::constraint_maximum_via_count },
|
||||
{ ABSOLUTE_LENGTH, BITMAPS::constraint_absolute_length },
|
||||
{ ABSOLUTE_LENGTH, BITMAPS::constraint_length },
|
||||
{ MATCHED_LENGTH_DIFF_PAIR, BITMAPS::constraint_matched_length_diff_pair }
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_overlay_field.h"
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/control.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/window.h>
|
||||
|
||||
|
||||
DRC_RE_OVERLAY_FIELD::DRC_RE_OVERLAY_FIELD( wxWindow* aParent, const wxString& aFieldId,
|
||||
wxControl* aControl,
|
||||
const DRC_RE_FIELD_POSITION& aPosition ) :
|
||||
m_parent( aParent ),
|
||||
m_fieldId( aFieldId ),
|
||||
m_control( aControl ),
|
||||
m_position( aPosition ),
|
||||
m_getter( nullptr ),
|
||||
m_setter( nullptr ),
|
||||
m_unitBinder( nullptr ),
|
||||
m_errorIcon( nullptr ),
|
||||
m_showingError( false ),
|
||||
m_label( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DRC_RE_OVERLAY_FIELD::~DRC_RE_OVERLAY_FIELD()
|
||||
{
|
||||
if( m_errorIcon )
|
||||
{
|
||||
m_errorIcon->Destroy();
|
||||
m_errorIcon = nullptr;
|
||||
}
|
||||
|
||||
if( m_label )
|
||||
{
|
||||
m_label->Destroy();
|
||||
m_label = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_OVERLAY_FIELD::createErrorIcon()
|
||||
{
|
||||
if( m_errorIcon )
|
||||
return;
|
||||
|
||||
m_errorIcon = new wxStaticBitmap( m_parent, wxID_ANY, KiBitmapBundle( BITMAPS::small_warning ) );
|
||||
|
||||
// Position the icon to the right of the control with a small gap
|
||||
wxPoint controlPos = m_control->GetPosition();
|
||||
wxSize controlSize = m_control->GetSize();
|
||||
wxSize iconSize = m_errorIcon->GetSize();
|
||||
|
||||
int iconX = controlPos.x + controlSize.GetWidth() + 4;
|
||||
int iconY = controlPos.y + ( controlSize.GetHeight() - iconSize.GetHeight() ) / 2;
|
||||
|
||||
m_errorIcon->SetPosition( wxPoint( iconX, iconY ) );
|
||||
m_errorIcon->Hide();
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_OVERLAY_FIELD::ShowError( bool aShow )
|
||||
{
|
||||
if( aShow && !m_errorIcon )
|
||||
createErrorIcon();
|
||||
|
||||
if( m_errorIcon )
|
||||
m_errorIcon->Show( aShow );
|
||||
|
||||
m_showingError = aShow;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_OVERLAY_FIELD::TransferToWindow()
|
||||
{
|
||||
if( !m_getter )
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
double value = m_getter();
|
||||
|
||||
if( m_unitBinder )
|
||||
{
|
||||
m_unitBinder->SetDoubleValue( value );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_OVERLAY_FIELD::TransferFromWindow()
|
||||
{
|
||||
if( !m_setter )
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
if( m_unitBinder )
|
||||
{
|
||||
double value = m_unitBinder->GetDoubleValue();
|
||||
m_setter( value );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC_RE_OVERLAY_FIELD::CreateLabel()
|
||||
{
|
||||
if( m_label )
|
||||
return;
|
||||
|
||||
if( m_position.labelText.IsEmpty() || m_position.labelPosition == LABEL_POSITION::NONE )
|
||||
return;
|
||||
|
||||
m_label = new wxStaticText( m_parent, wxID_ANY, m_position.labelText );
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_OVERLAY_FIELD_H
|
||||
#define DRC_RE_OVERLAY_FIELD_H
|
||||
|
||||
#include <functional>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "drc_re_overlay_types.h"
|
||||
|
||||
class wxWindow;
|
||||
class wxControl;
|
||||
class wxStaticBitmap;
|
||||
class wxStaticText;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Wraps a wxControl positioned over a bitmap overlay panel.
|
||||
*
|
||||
* Manages the control's position within the overlay, data binding via lambda functions,
|
||||
* optional UNIT_BINDER integration for unit conversion, and error icon display for
|
||||
* validation feedback.
|
||||
*/
|
||||
class DRC_RE_OVERLAY_FIELD
|
||||
{
|
||||
public:
|
||||
using Getter = std::function<double()>;
|
||||
using Setter = std::function<void( double )>;
|
||||
|
||||
/**
|
||||
* Construct an overlay field wrapping an existing control.
|
||||
*
|
||||
* @param aParent Parent window (typically the overlay panel)
|
||||
* @param aFieldId Unique identifier for this field, used for error mapping
|
||||
* @param aControl The wxControl to wrap and position
|
||||
* @param aPosition Position specification in 1x bitmap coordinates
|
||||
*/
|
||||
DRC_RE_OVERLAY_FIELD( wxWindow* aParent, const wxString& aFieldId, wxControl* aControl,
|
||||
const DRC_RE_FIELD_POSITION& aPosition );
|
||||
|
||||
~DRC_RE_OVERLAY_FIELD();
|
||||
|
||||
/**
|
||||
* @return The wrapped wxControl.
|
||||
*/
|
||||
wxControl* GetControl() const { return m_control; }
|
||||
|
||||
/**
|
||||
* @return The unique field identifier string.
|
||||
*/
|
||||
const wxString& GetFieldId() const { return m_fieldId; }
|
||||
|
||||
/**
|
||||
* @return The field's position specification in 1x bitmap coordinates.
|
||||
*/
|
||||
const DRC_RE_FIELD_POSITION& GetPosition() const { return m_position; }
|
||||
|
||||
/**
|
||||
* Transfer data from the model to the control.
|
||||
*
|
||||
* Uses the getter lambda if set. If a UNIT_BINDER is associated, the value is
|
||||
* passed through SetDoubleValue for unit conversion.
|
||||
*
|
||||
* @return true on success, false if getter throws or is not set
|
||||
*/
|
||||
bool TransferToWindow();
|
||||
|
||||
/**
|
||||
* Transfer data from the control to the model.
|
||||
*
|
||||
* Reads the control value (via UNIT_BINDER if associated) and calls the setter lambda.
|
||||
*
|
||||
* @return true on success, false if setter throws or is not set
|
||||
*/
|
||||
bool TransferFromWindow();
|
||||
|
||||
/**
|
||||
* Set the getter lambda for reading model data.
|
||||
*
|
||||
* @param aGetter Function returning the current model value
|
||||
*/
|
||||
void SetGetter( Getter aGetter ) { m_getter = std::move( aGetter ); }
|
||||
|
||||
/**
|
||||
* Set the setter lambda for writing model data.
|
||||
*
|
||||
* @param aSetter Function accepting the new value from the control
|
||||
*/
|
||||
void SetSetter( Setter aSetter ) { m_setter = std::move( aSetter ); }
|
||||
|
||||
/**
|
||||
* Associate a UNIT_BINDER for unit conversion.
|
||||
*
|
||||
* When set, TransferToWindow and TransferFromWindow use the UNIT_BINDER's
|
||||
* SetDoubleValue and GetDoubleValue methods for proper unit handling.
|
||||
*
|
||||
* @param aBinder The UNIT_BINDER to associate (ownership remains with caller)
|
||||
*/
|
||||
void SetUnitBinder( UNIT_BINDER* aBinder ) { m_unitBinder = aBinder; }
|
||||
|
||||
/**
|
||||
* @return The associated UNIT_BINDER, or nullptr if none.
|
||||
*/
|
||||
UNIT_BINDER* GetUnitBinder() const { return m_unitBinder; }
|
||||
|
||||
/**
|
||||
* Show or hide the error indicator icon adjacent to this field.
|
||||
*
|
||||
* @param aShow true to display the error icon, false to hide it
|
||||
*/
|
||||
void ShowError( bool aShow );
|
||||
|
||||
/**
|
||||
* @return true if the error icon is currently visible.
|
||||
*/
|
||||
bool IsShowingError() const { return m_showingError; }
|
||||
|
||||
/**
|
||||
* @return The label control, or nullptr if no label was created.
|
||||
*/
|
||||
wxStaticText* GetLabel() const { return m_label; }
|
||||
|
||||
/**
|
||||
* @return true if this field has a label.
|
||||
*/
|
||||
bool HasLabel() const { return m_label != nullptr; }
|
||||
|
||||
/**
|
||||
* Create and associate a label with this field.
|
||||
* The label is positioned according to the LABEL_POSITION in the field position struct.
|
||||
*/
|
||||
void CreateLabel();
|
||||
|
||||
private:
|
||||
void createErrorIcon();
|
||||
|
||||
wxWindow* m_parent;
|
||||
wxString m_fieldId;
|
||||
wxControl* m_control;
|
||||
DRC_RE_FIELD_POSITION m_position;
|
||||
|
||||
Getter m_getter;
|
||||
Setter m_setter;
|
||||
UNIT_BINDER* m_unitBinder;
|
||||
|
||||
wxStaticBitmap* m_errorIcon;
|
||||
bool m_showingError;
|
||||
|
||||
wxStaticText* m_label;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_OVERLAY_FIELD_H
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_overlay_panel_factory.h"
|
||||
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include "drc_re_via_style_overlay_panel.h"
|
||||
#include "drc_re_routing_width_overlay_panel.h"
|
||||
#include "drc_re_rtg_diff_pair_overlay_panel.h"
|
||||
#include "drc_re_min_txt_ht_th_overlay_panel.h"
|
||||
#include "drc_re_abs_length_two_overlay_panel.h"
|
||||
#include "drc_re_numeric_input_overlay_panel.h"
|
||||
#include "drc_re_bool_input_overlay_panel.h"
|
||||
#include "drc_re_allowed_orientation_overlay_panel.h"
|
||||
#include "drc_re_permitted_layers_overlay_panel.h"
|
||||
|
||||
#include "drc_re_via_style_constraint_data.h"
|
||||
#include "drc_re_routing_width_constraint_data.h"
|
||||
#include "drc_re_rtg_diff_pair_constraint_data.h"
|
||||
#include "drc_re_min_txt_ht_th_constraint_data.h"
|
||||
#include "drc_re_abs_length_two_constraint_data.h"
|
||||
#include "drc_re_numeric_input_constraint_data.h"
|
||||
#include "drc_re_bool_input_constraint_data.h"
|
||||
#include "drc_re_allowed_orientation_constraint_data.h"
|
||||
#include "drc_re_permitted_layers_constraint_data.h"
|
||||
|
||||
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL*
|
||||
DRC_RE_OVERLAY_PANEL_FACTORY::CreateOverlayPanel( wxWindow* aParent,
|
||||
DRC_RULE_EDITOR_CONSTRAINT_NAME aType,
|
||||
DRC_RE_BASE_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits )
|
||||
{
|
||||
switch( aType )
|
||||
{
|
||||
case VIA_STYLE:
|
||||
return new DRC_RE_VIA_STYLE_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
|
||||
case ROUTING_WIDTH:
|
||||
return new DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
|
||||
case ROUTING_DIFF_PAIR:
|
||||
return new DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
|
||||
case MINIMUM_TEXT_HEIGHT_AND_THICKNESS:
|
||||
return new DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
|
||||
case ABSOLUTE_LENGTH:
|
||||
return new DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
|
||||
case PERMITTED_LAYERS:
|
||||
return new DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA*>( aData ) );
|
||||
|
||||
case ALLOWED_ORIENTATION:
|
||||
return new DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA*>( aData ) );
|
||||
|
||||
default:
|
||||
if( DRC_RULE_EDITOR_UTILS::IsNumericInputType( aType ) )
|
||||
{
|
||||
return new DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA*>( aData ),
|
||||
aUnits );
|
||||
}
|
||||
else if( DRC_RULE_EDITOR_UTILS::IsBoolInputType( aType ) )
|
||||
{
|
||||
return new DRC_RE_BOOL_INPUT_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_cast<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA*>( aData ) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_OVERLAY_PANEL_FACTORY_H
|
||||
#define DRC_RE_OVERLAY_PANEL_FACTORY_H
|
||||
|
||||
#include <eda_units.h>
|
||||
|
||||
#include "drc_rule_editor_enums.h"
|
||||
|
||||
class wxWindow;
|
||||
class DRC_RE_BITMAP_OVERLAY_PANEL;
|
||||
class DRC_RE_BASE_CONSTRAINT_DATA;
|
||||
|
||||
|
||||
/**
|
||||
* Factory for creating overlay panels for DRC constraint editing.
|
||||
*
|
||||
* Maps constraint types to their corresponding bitmap overlay panel classes. The overlay
|
||||
* panels display constraint diagrams with input fields positioned over the artwork.
|
||||
*/
|
||||
class DRC_RE_OVERLAY_PANEL_FACTORY
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create an overlay panel for the given constraint type.
|
||||
*
|
||||
* Returns the appropriate overlay panel subclass based on the constraint type. For
|
||||
* constraints that don't have a specialized overlay panel (e.g., custom rules),
|
||||
* returns nullptr.
|
||||
*
|
||||
* @param aParent The parent window for the overlay panel.
|
||||
* @param aType The constraint type determining which panel class to create.
|
||||
* @param aData The constraint data to bind to the panel. The factory will cast this
|
||||
* to the appropriate derived type based on aType.
|
||||
* @param aUnits The unit system for displaying values. Ignored for constraint types
|
||||
* that don't display dimensional values.
|
||||
* @return The created overlay panel, or nullptr if the constraint type doesn't support
|
||||
* bitmap overlays.
|
||||
*/
|
||||
static DRC_RE_BITMAP_OVERLAY_PANEL* CreateOverlayPanel( wxWindow* aParent,
|
||||
DRC_RULE_EDITOR_CONSTRAINT_NAME aType,
|
||||
DRC_RE_BASE_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
};
|
||||
|
||||
#endif // DRC_RE_OVERLAY_PANEL_FACTORY_H
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_OVERLAY_TYPES_H
|
||||
#define DRC_RE_OVERLAY_TYPES_H
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the position of a label relative to its associated field.
|
||||
*/
|
||||
enum class LABEL_POSITION
|
||||
{
|
||||
NONE, ///< No label
|
||||
LEFT, ///< Label to the left of the field
|
||||
RIGHT, ///< Label to the right of the field
|
||||
TOP, ///< Label above the field
|
||||
BOTTOM ///< Label below the field
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the position and size of a field overlaid on a constraint bitmap.
|
||||
*
|
||||
* All coordinates are in 1x bitmap pixels. When the system selects a higher-resolution
|
||||
* bitmap (1.5x or 2x), these values are automatically scaled at runtime.
|
||||
*/
|
||||
struct DRC_RE_FIELD_POSITION
|
||||
{
|
||||
int xStart; ///< Left edge X coordinate where the field starts
|
||||
int xEnd; ///< Right edge X coordinate where the field ends
|
||||
int yTop; ///< Top edge Y coordinate of the field
|
||||
int tabOrder; ///< Tab navigation order (1-based, lower numbers receive focus first)
|
||||
|
||||
wxString labelText; ///< Optional label text (empty for no label)
|
||||
LABEL_POSITION labelPosition; ///< Position of label relative to field
|
||||
|
||||
DRC_RE_FIELD_POSITION() :
|
||||
xStart( 0 ),
|
||||
xEnd( 0 ),
|
||||
yTop( 0 ),
|
||||
tabOrder( 0 ),
|
||||
labelText(),
|
||||
labelPosition( LABEL_POSITION::NONE )
|
||||
{
|
||||
}
|
||||
|
||||
DRC_RE_FIELD_POSITION( int aXStart, int aXEnd, int aYTop, int aTabOrder,
|
||||
const wxString& aLabelText = wxEmptyString,
|
||||
LABEL_POSITION aLabelPos = LABEL_POSITION::NONE ) :
|
||||
xStart( aXStart ),
|
||||
xEnd( aXEnd ),
|
||||
yTop( aYTop ),
|
||||
tabOrder( aTabOrder ),
|
||||
labelText( aLabelText ),
|
||||
labelPosition( aLabelPos )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DRC_RE_OVERLAY_TYPES_H
|
||||
@@ -47,6 +47,18 @@ public:
|
||||
|
||||
virtual ~DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_permitted_layers; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_permitted_layers.png (~300x170)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 20, 60, 35, 1 }, // top layer checkbox (upper left)
|
||||
{ 20, 60, 120, 2 }, // bottom layer checkbox (lower left)
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
VALIDATION_RESULT result;
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_permitted_layers_overlay_panel.h"
|
||||
#include "drc_re_permitted_layers_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
|
||||
DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL::DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA* aData ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_topLayerCheckbox( nullptr ),
|
||||
m_bottomLayerCheckbox( nullptr )
|
||||
{
|
||||
SetBackgroundBitmap( m_data->GetOverlayBitmap() );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
DRC_RE_OVERLAY_FIELD* topField = AddCheckbox( wxS( "top_layer" ), positions[0] );
|
||||
m_topLayerCheckbox = static_cast<wxCheckBox*>( topField->GetControl() );
|
||||
|
||||
DRC_RE_OVERLAY_FIELD* bottomField = AddCheckbox( wxS( "bottom_layer" ), positions[1] );
|
||||
m_bottomLayerCheckbox = static_cast<wxCheckBox*>( bottomField->GetControl() );
|
||||
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data || !m_topLayerCheckbox || !m_bottomLayerCheckbox )
|
||||
return false;
|
||||
|
||||
m_topLayerCheckbox->SetValue( m_data->GetTopLayerEnabled() );
|
||||
m_bottomLayerCheckbox->SetValue( m_data->GetBottomLayerEnabled() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data || !m_topLayerCheckbox || !m_bottomLayerCheckbox )
|
||||
return false;
|
||||
|
||||
m_data->SetTopLayerEnabled( m_topLayerCheckbox->GetValue() );
|
||||
m_data->SetBottomLayerEnabled( m_bottomLayerCheckbox->GetValue() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL_H
|
||||
#define DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL_H
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
class DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA;
|
||||
class wxCheckBox;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for permitted layers constraints showing checkboxes
|
||||
* for top and bottom layer selection positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA* aData );
|
||||
|
||||
~DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA* m_data;
|
||||
|
||||
wxCheckBox* m_topLayerCheckbox;
|
||||
wxCheckBox* m_bottomLayerCheckbox;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL_H
|
||||
@@ -49,6 +49,19 @@ public:
|
||||
|
||||
virtual ~DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_routing_width; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_routing_width.png bitmap
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 75, 135, 35, 1 }, // min_width (left arrow)
|
||||
{ 145, 205, 85, 2 }, // opt_width (bottom center arrow)
|
||||
{ 215, 275, 35, 3 }, // max_width (right arrow)
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
VALIDATION_RESULT result;
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_routing_width_overlay_panel.h"
|
||||
#include "drc_re_routing_width_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL::DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL(
|
||||
wxWindow* aParent,
|
||||
DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( BITMAPS::constraint_routing_width );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
// Create min width field
|
||||
m_minRoutingWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_width" ), positions[0], m_minRoutingWidthBinder.get() );
|
||||
|
||||
// Create preferred width field
|
||||
m_preferredRoutingWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "pref_width" ), positions[1], m_preferredRoutingWidthBinder.get() );
|
||||
|
||||
// Create max width field
|
||||
m_maxRoutingWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_width" ), positions[2], m_maxRoutingWidthBinder.get() );
|
||||
|
||||
// Position all fields and update the panel layout
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Convert mm values to internal units and set them in the binders
|
||||
m_minRoutingWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinRoutingWidth() ) );
|
||||
m_preferredRoutingWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetPreferredRoutingWidth() ) );
|
||||
m_maxRoutingWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxRoutingWidth() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Read values from binders (in internal units) and convert to mm for storage
|
||||
m_data->SetMinRoutingWidth( pcbIUScale.IUTomm( m_minRoutingWidthBinder->GetDoubleValue() ) );
|
||||
m_data->SetPreferredRoutingWidth( pcbIUScale.IUTomm( m_preferredRoutingWidthBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaxRoutingWidth( pcbIUScale.IUTomm( m_maxRoutingWidthBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL_H
|
||||
#define DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for routing width constraints showing min/preferred/max width fields
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
std::unique_ptr<UNIT_BINDER> m_minRoutingWidthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_preferredRoutingWidthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxRoutingWidthBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL_H
|
||||
@@ -52,6 +52,23 @@ public:
|
||||
|
||||
virtual ~DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_routing_diff_pair; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_routing_diff_pair.png bitmap (~570x160)
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 95, 155, 30, 1 }, // min_width (left side, top arrow)
|
||||
{ 95, 155, 55, 2 }, // opt_width (left side, middle)
|
||||
{ 95, 155, 80, 3 }, // max_width (left side, bottom)
|
||||
{ 195, 255, 30, 4 }, // min_gap (center-left, top)
|
||||
{ 195, 255, 55, 5 }, // opt_gap (center-left, middle)
|
||||
{ 195, 255, 80, 6 }, // max_gap (center-left, bottom)
|
||||
{ 420, 520, 55, 7 }, // max_uncoupled (right side)
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
VALIDATION_RESULT result;
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_rtg_diff_pair_overlay_panel.h"
|
||||
#include "drc_re_rtg_diff_pair_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL::DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL(
|
||||
wxWindow* aParent,
|
||||
DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( BITMAPS::constraint_routing_diff_pair );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
// Create gap fields (min/pref/max)
|
||||
m_minGapBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_gap" ), positions[0], m_minGapBinder.get() );
|
||||
|
||||
m_preferredGapBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "pref_gap" ), positions[1], m_preferredGapBinder.get() );
|
||||
|
||||
m_maxGapBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_gap" ), positions[2], m_maxGapBinder.get() );
|
||||
|
||||
// Create width fields (min/pref/max)
|
||||
m_minWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_width" ), positions[3], m_minWidthBinder.get() );
|
||||
|
||||
m_preferredWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "pref_width" ), positions[4], m_preferredWidthBinder.get() );
|
||||
|
||||
m_maxWidthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_width" ), positions[5], m_maxWidthBinder.get() );
|
||||
|
||||
// Create max uncoupled length field
|
||||
m_maxUncoupledLengthBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_uncoupled" ), positions[6], m_maxUncoupledLengthBinder.get() );
|
||||
|
||||
// Position all fields and update the panel layout
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Convert mm values to internal units and set them in the binders
|
||||
m_minGapBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinGap() ) );
|
||||
m_preferredGapBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetPreferredGap() ) );
|
||||
m_maxGapBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxGap() ) );
|
||||
|
||||
m_minWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinWidth() ) );
|
||||
m_preferredWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetPreferredWidth() ) );
|
||||
m_maxWidthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxWidth() ) );
|
||||
|
||||
m_maxUncoupledLengthBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxUncoupledLength() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Read values from binders (in internal units) and convert to mm for storage
|
||||
m_data->SetMinGap( pcbIUScale.IUTomm( m_minGapBinder->GetDoubleValue() ) );
|
||||
m_data->SetPreferredGap( pcbIUScale.IUTomm( m_preferredGapBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaxGap( pcbIUScale.IUTomm( m_maxGapBinder->GetDoubleValue() ) );
|
||||
|
||||
m_data->SetMinWidth( pcbIUScale.IUTomm( m_minWidthBinder->GetDoubleValue() ) );
|
||||
m_data->SetPreferredWidth( pcbIUScale.IUTomm( m_preferredWidthBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaxWidth( pcbIUScale.IUTomm( m_maxWidthBinder->GetDoubleValue() ) );
|
||||
|
||||
m_data->SetMaxUncoupledLength( pcbIUScale.IUTomm( m_maxUncoupledLengthBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL::ValidateInputs( int* aErrorCount,
|
||||
std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_RTG_DIFF_PAIR_OVERLAY_PANEL_H
|
||||
#define DRC_RE_RTG_DIFF_PAIR_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
/**
|
||||
* Overlay panel for differential pair routing constraints showing gap, width,
|
||||
* and uncoupled length fields positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
std::unique_ptr<UNIT_BINDER> m_minGapBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_preferredGapBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxGapBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_minWidthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_preferredWidthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxWidthBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxUncoupledLengthBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_RTG_DIFF_PAIR_OVERLAY_PANEL_H
|
||||
@@ -51,6 +51,22 @@ public:
|
||||
|
||||
virtual ~DRC_RE_VIA_STYLE_CONSTRAINT_DATA() = default;
|
||||
|
||||
BITMAPS GetOverlayBitmap() const override { return BITMAPS::constraint_via_style; }
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> GetFieldPositions() const override
|
||||
{
|
||||
// Positions measured from constraint_via_style.png bitmap
|
||||
// Format: { xStart, xEnd, yTop, tabOrder }
|
||||
return {
|
||||
{ 260, 340, 25, 1 }, // min_via_diameter (right side, top)
|
||||
{ 260, 340, 55, 2 }, // opt_via_diameter (right side, middle)
|
||||
{ 260, 340, 85, 3 }, // max_via_diameter (right side, bottom)
|
||||
{ 260, 340, 115, 4 }, // min_via_hole (right side, below diameter)
|
||||
{ 260, 340, 145, 5 }, // opt_via_hole
|
||||
{ 260, 340, 175, 6 }, // max_via_hole
|
||||
};
|
||||
}
|
||||
|
||||
VALIDATION_RESULT Validate() const override
|
||||
{
|
||||
VALIDATION_RESULT result;
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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 "drc_re_via_style_overlay_panel.h"
|
||||
#include "drc_re_via_style_constraint_data.h"
|
||||
#include "drc_rule_editor_utils.h"
|
||||
|
||||
#include <base_units.h>
|
||||
#include <widgets/unit_binder.h>
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DRC_RE_VIA_STYLE_OVERLAY_PANEL::DRC_RE_VIA_STYLE_OVERLAY_PANEL(
|
||||
wxWindow* aParent, DRC_RE_VIA_STYLE_CONSTRAINT_DATA* aData, EDA_UNITS aUnits ) :
|
||||
DRC_RE_BITMAP_OVERLAY_PANEL( aParent ),
|
||||
m_data( aData ),
|
||||
m_unitsProvider( pcbIUScale, aUnits )
|
||||
{
|
||||
SetBackgroundBitmap( BITMAPS::constraint_via_style );
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> positions = m_data->GetFieldPositions();
|
||||
|
||||
// Create via diameter fields (min/pref/max)
|
||||
m_minViaDiameterBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_via_diameter" ), positions[0],
|
||||
m_minViaDiameterBinder.get() );
|
||||
|
||||
m_maxViaDiameterBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_via_diameter" ), positions[1],
|
||||
m_maxViaDiameterBinder.get() );
|
||||
|
||||
m_prefViaDiameterBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "pref_via_diameter" ), positions[2],
|
||||
m_prefViaDiameterBinder.get() );
|
||||
|
||||
// Create via hole size fields (min/pref/max)
|
||||
m_minViaHoleSizeBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "min_via_hole" ), positions[3],
|
||||
m_minViaHoleSizeBinder.get() );
|
||||
|
||||
m_maxViaHoleSizeBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "max_via_hole" ), positions[4],
|
||||
m_maxViaHoleSizeBinder.get() );
|
||||
|
||||
m_prefViaHoleSizeBinder = std::make_unique<UNIT_BINDER>(
|
||||
&m_unitsProvider, this, nullptr, nullptr, nullptr, false, false );
|
||||
|
||||
AddFieldWithUnits<wxTextCtrl>( wxS( "pref_via_hole" ), positions[5],
|
||||
m_prefViaHoleSizeBinder.get() );
|
||||
|
||||
// Position all fields and update the panel layout
|
||||
PositionFields();
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_VIA_STYLE_OVERLAY_PANEL::TransferDataToWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Convert mm values to internal units and set them in the unit binders
|
||||
m_minViaDiameterBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinViaDiameter() ) );
|
||||
m_prefViaDiameterBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetPreferredViaDiameter() ) );
|
||||
m_maxViaDiameterBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxViaDiameter() ) );
|
||||
|
||||
m_minViaHoleSizeBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMinViaHoleSize() ) );
|
||||
m_prefViaHoleSizeBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetPreferredViaHoleSize() ) );
|
||||
m_maxViaHoleSizeBinder->SetDoubleValue( pcbIUScale.mmToIU( m_data->GetMaxViaHoleSize() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_VIA_STYLE_OVERLAY_PANEL::TransferDataFromWindow()
|
||||
{
|
||||
if( !m_data )
|
||||
return false;
|
||||
|
||||
// Read values from unit binders and convert from internal units to mm
|
||||
m_data->SetMinViaDiameter( pcbIUScale.IUTomm( m_minViaDiameterBinder->GetDoubleValue() ) );
|
||||
m_data->SetPreferredViaDiameter( pcbIUScale.IUTomm( m_prefViaDiameterBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaxViaDiameter( pcbIUScale.IUTomm( m_maxViaDiameterBinder->GetDoubleValue() ) );
|
||||
|
||||
m_data->SetMinViaHoleSize( pcbIUScale.IUTomm( m_minViaHoleSizeBinder->GetDoubleValue() ) );
|
||||
m_data->SetPreferredViaHoleSize( pcbIUScale.IUTomm( m_prefViaHoleSizeBinder->GetDoubleValue() ) );
|
||||
m_data->SetMaxViaHoleSize( pcbIUScale.IUTomm( m_maxViaHoleSizeBinder->GetDoubleValue() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DRC_RE_VIA_STYLE_OVERLAY_PANEL::ValidateInputs( int* aErrorCount, std::string* aValidationMessage )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
VALIDATION_RESULT result = m_data->Validate();
|
||||
|
||||
if( !result.isValid )
|
||||
{
|
||||
*aErrorCount = result.errors.size();
|
||||
|
||||
for( size_t i = 0; i < result.errors.size(); i++ )
|
||||
*aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( i + 1, result.errors[i] );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
wxString DRC_RE_VIA_STYLE_OVERLAY_PANEL::GenerateRule( const RULE_GENERATION_CONTEXT& aContext )
|
||||
{
|
||||
if( !m_data )
|
||||
return wxEmptyString;
|
||||
|
||||
return m_data->GenerateRule( aContext );
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2024 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
|
||||
*/
|
||||
|
||||
#ifndef DRC_RE_VIA_STYLE_OVERLAY_PANEL_H
|
||||
#define DRC_RE_VIA_STYLE_OVERLAY_PANEL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <units_provider.h>
|
||||
|
||||
#include "drc_re_bitmap_overlay_panel.h"
|
||||
|
||||
enum class EDA_UNITS;
|
||||
|
||||
class DRC_RE_VIA_STYLE_CONSTRAINT_DATA;
|
||||
class UNIT_BINDER;
|
||||
|
||||
|
||||
/**
|
||||
* Overlay panel for via style constraints showing via diameter and hole size fields
|
||||
* positioned over a diagram.
|
||||
*/
|
||||
class DRC_RE_VIA_STYLE_OVERLAY_PANEL : public DRC_RE_BITMAP_OVERLAY_PANEL
|
||||
{
|
||||
public:
|
||||
DRC_RE_VIA_STYLE_OVERLAY_PANEL( wxWindow* aParent,
|
||||
DRC_RE_VIA_STYLE_CONSTRAINT_DATA* aData,
|
||||
EDA_UNITS aUnits );
|
||||
|
||||
~DRC_RE_VIA_STYLE_OVERLAY_PANEL() override = default;
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
bool ValidateInputs( int* aErrorCount, std::string* aValidationMessage ) override;
|
||||
wxString GenerateRule( const RULE_GENERATION_CONTEXT& aContext ) override;
|
||||
|
||||
private:
|
||||
DRC_RE_VIA_STYLE_CONSTRAINT_DATA* m_data;
|
||||
|
||||
UNITS_PROVIDER m_unitsProvider;
|
||||
|
||||
// Unit binders for via diameter fields
|
||||
std::unique_ptr<UNIT_BINDER> m_minViaDiameterBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_prefViaDiameterBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxViaDiameterBinder;
|
||||
|
||||
// Unit binders for via hole size fields
|
||||
std::unique_ptr<UNIT_BINDER> m_minViaHoleSizeBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_prefViaHoleSizeBinder;
|
||||
std::unique_ptr<UNIT_BINDER> m_maxViaHoleSizeBinder;
|
||||
};
|
||||
|
||||
#endif // DRC_RE_VIA_STYLE_OVERLAY_PANEL_H
|
||||
@@ -61,6 +61,19 @@
|
||||
#include <drc/rule_editor/drc_re_allowed_orientation_panel.h>
|
||||
#include <drc/rule_editor/drc_re_custom_rule_panel.h>
|
||||
#include "drc_re_condition_group_panel.h"
|
||||
|
||||
// Overlay panels (new bitmap-based implementation)
|
||||
#include "drc_re_via_style_overlay_panel.h"
|
||||
#include "drc_re_routing_width_overlay_panel.h"
|
||||
#include "drc_re_rtg_diff_pair_overlay_panel.h"
|
||||
#include "drc_re_min_txt_ht_th_overlay_panel.h"
|
||||
#include "drc_re_abs_length_two_overlay_panel.h"
|
||||
#include "drc_re_numeric_input_overlay_panel.h"
|
||||
#include "drc_re_bool_input_overlay_panel.h"
|
||||
#include "drc_re_allowed_orientation_overlay_panel.h"
|
||||
#include "drc_re_permitted_layers_overlay_panel.h"
|
||||
|
||||
#include <eda_units.h>
|
||||
#include "drc_re_numeric_input_constraint_data.h"
|
||||
#include "drc_re_bool_input_constraint_data.h"
|
||||
#include "drc_re_via_style_constraint_data.h"
|
||||
@@ -209,13 +222,17 @@ bool PANEL_DRC_RULE_EDITOR::TransferDataToWindow()
|
||||
m_conditionGroupPanel->ParseCondition( cond );
|
||||
}
|
||||
|
||||
return dynamic_cast<wxPanel*>( m_constraintPanel )->TransferDataToWindow();
|
||||
if( m_constraintPanel )
|
||||
return m_constraintPanel->TransferDataToWindow();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_DRC_RULE_EDITOR::TransferDataFromWindow()
|
||||
{
|
||||
dynamic_cast<wxPanel*>( m_constraintPanel )->TransferDataFromWindow();
|
||||
if( m_constraintPanel )
|
||||
m_constraintPanel->TransferDataFromWindow();
|
||||
|
||||
m_constraintData->SetRuleName( m_nameCtrl->GetValue() );
|
||||
m_constraintData->SetComment( m_commentCtrl->GetValue() );
|
||||
@@ -245,65 +262,68 @@ bool PANEL_DRC_RULE_EDITOR::TransferDataFromWindow()
|
||||
DRC_RULE_EDITOR_CONTENT_PANEL_BASE*
|
||||
PANEL_DRC_RULE_EDITOR::getConstraintPanel( wxWindow* aParent, const DRC_RULE_EDITOR_CONSTRAINT_NAME& aConstraintType )
|
||||
{
|
||||
// Use millimeters as default unit since constraint data stores values in mm
|
||||
EDA_UNITS units = EDA_UNITS::MM;
|
||||
|
||||
switch( aConstraintType )
|
||||
{
|
||||
case VIA_STYLE:
|
||||
return new DRC_RE_VIA_STYLE_PANEL( aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_VIA_STYLE_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
|
||||
case MINIMUM_TEXT_HEIGHT_AND_THICKNESS:
|
||||
return new DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_MIN_TXT_HT_TH_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
|
||||
case ROUTING_DIFF_PAIR:
|
||||
return new DRC_RE_ROUTING_DIFF_PAIR_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_ROUTING_DIFF_PAIR_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
|
||||
case ROUTING_WIDTH:
|
||||
return new DRC_RE_ROUTING_WIDTH_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_ROUTING_WIDTH_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
|
||||
case PERMITTED_LAYERS:
|
||||
return new DRC_RE_PERMITTED_LAYERS_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_PERMITTED_LAYERS_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>( m_constraintData ).get() );
|
||||
|
||||
case ALLOWED_ORIENTATION:
|
||||
return new DRC_RE_ALLOWED_ORIENTATION_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_ALLOWED_ORIENTATION_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( m_constraintData ).get() );
|
||||
|
||||
case CUSTOM_RULE:
|
||||
return new DRC_RE_CUSTOM_RULE_PANEL(
|
||||
aParent, dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
|
||||
case ABSOLUTE_LENGTH:
|
||||
return new DRC_RE_ABSOLUTE_LENGTH_TWO_PANEL(
|
||||
aParent, m_constraintTitle,
|
||||
dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>( m_constraintData ) );
|
||||
return new DRC_RE_ABS_LENGTH_TWO_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
|
||||
default:
|
||||
if( DRC_RULE_EDITOR_UTILS::IsNumericInputType( aConstraintType ) )
|
||||
{
|
||||
DRC_RE_NUMERIC_INPUT_CONSTRAINT_PANEL_PARAMS numericInputParams(
|
||||
*m_constraintTitle, dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( m_constraintData ),
|
||||
aConstraintType, *m_constraintTitle );
|
||||
|
||||
if( aConstraintType == MINIMUM_THERMAL_RELIEF_SPOKE_COUNT || aConstraintType == MAXIMUM_VIA_COUNT )
|
||||
numericInputParams.SetInputIsCount( true );
|
||||
|
||||
return new DRC_RE_NUMERIC_INPUT_PANEL( aParent, numericInputParams );
|
||||
return new DRC_RE_NUMERIC_INPUT_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( m_constraintData ).get(),
|
||||
units );
|
||||
}
|
||||
else if( DRC_RULE_EDITOR_UTILS::IsBoolInputType( aConstraintType ) )
|
||||
{
|
||||
wxString customLabel;
|
||||
|
||||
switch( aConstraintType )
|
||||
{
|
||||
case VIAS_UNDER_SMD: customLabel = "Allow Vias under SMD Pads"; break;
|
||||
default: customLabel = *m_constraintTitle;
|
||||
}
|
||||
|
||||
DRC_RE_BOOL_INPUT_CONSTRAINT_PANEL_PARAMS boolInputParams(
|
||||
*m_constraintTitle, dynamic_pointer_cast<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( m_constraintData ),
|
||||
aConstraintType, customLabel );
|
||||
|
||||
return new DRC_RE_BOOL_INPUT_PANEL( aParent, boolInputParams );
|
||||
return new DRC_RE_BOOL_INPUT_OVERLAY_PANEL(
|
||||
aParent,
|
||||
dynamic_pointer_cast<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( m_constraintData ).get() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -96,6 +96,7 @@ set( QA_PCBNEW_SRCS
|
||||
drc/test_drc_tuning_profiles.cpp
|
||||
drc/test_drc_creepage_issue21482.cpp
|
||||
drc/test_drc_rule_editor.cpp
|
||||
drc/test_drc_bitmap_overlay_panel.cpp
|
||||
|
||||
pcb_io/altium/test_altium_rule_transformer.cpp
|
||||
pcb_io/altium/test_altium_pcblib_import.cpp
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The 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 <boost/test/unit_test.hpp>
|
||||
#include <drc/rule_editor/drc_re_overlay_types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/gdicmn.h>
|
||||
|
||||
|
||||
/**
|
||||
* Helper functions that mirror the logic from DRC_RE_BITMAP_OVERLAY_PANEL.
|
||||
* These allow testing the mathematical operations without requiring wxWidgets GUI.
|
||||
*/
|
||||
namespace BITMAP_OVERLAY_TEST_HELPERS
|
||||
{
|
||||
|
||||
/**
|
||||
* Compute the scale factor from a raw content scale factor.
|
||||
* Mirrors GetScaleFactor() logic from DRC_RE_BITMAP_OVERLAY_PANEL.
|
||||
*/
|
||||
double ComputeScaleFactor( double aRawScale )
|
||||
{
|
||||
if( aRawScale < 1.25 )
|
||||
return 1.0;
|
||||
else if( aRawScale < 1.75 )
|
||||
return 1.5;
|
||||
else
|
||||
return 2.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scale a position from 1x bitmap coordinates to display coordinates.
|
||||
* Mirrors ScalePosition() logic from DRC_RE_BITMAP_OVERLAY_PANEL.
|
||||
*/
|
||||
wxPoint ScalePosition( int aX, int aY, double aScaleFactor )
|
||||
{
|
||||
return wxPoint( static_cast<int>( aX * aScaleFactor ), static_cast<int>( aY * aScaleFactor ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scale a size from 1x bitmap coordinates to display coordinates.
|
||||
* Mirrors ScaleSize() logic from DRC_RE_BITMAP_OVERLAY_PANEL.
|
||||
*/
|
||||
wxSize ScaleSize( int aWidth, int aHeight, double aScaleFactor )
|
||||
{
|
||||
return wxSize( static_cast<int>( aWidth * aScaleFactor ), static_cast<int>( aHeight * aScaleFactor ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a field position exceeds bitmap bounds.
|
||||
* Mirrors bounds check logic from PositionFields() in DRC_RE_BITMAP_OVERLAY_PANEL.
|
||||
*/
|
||||
bool IsOutOfBounds( const wxPoint& aScaledPos, const wxSize& aScaledSize, const wxSize& aBitmapSize )
|
||||
{
|
||||
return ( aScaledPos.x + aScaledSize.GetWidth() > aBitmapSize.GetWidth() ||
|
||||
aScaledPos.y + aScaledSize.GetHeight() > aBitmapSize.GetHeight() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort field positions by tab order.
|
||||
* Mirrors expected keyboard navigation order.
|
||||
*/
|
||||
void SortByTabOrder( std::vector<DRC_RE_FIELD_POSITION>& aPositions )
|
||||
{
|
||||
std::sort( aPositions.begin(), aPositions.end(),
|
||||
[]( const DRC_RE_FIELD_POSITION& a, const DRC_RE_FIELD_POSITION& b )
|
||||
{
|
||||
return a.tabOrder < b.tabOrder;
|
||||
} );
|
||||
}
|
||||
|
||||
} // namespace BITMAP_OVERLAY_TEST_HELPERS
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( DrcBitmapOverlayPanel )
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// T025: ScalePosition Tests
|
||||
// ============================================================================
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ScalePosition_1x )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
double scale = 1.0;
|
||||
|
||||
// Test various positions at 1x scale
|
||||
wxPoint result1 = ScalePosition( 0, 0, scale );
|
||||
BOOST_CHECK_EQUAL( result1.x, 0 );
|
||||
BOOST_CHECK_EQUAL( result1.y, 0 );
|
||||
|
||||
wxPoint result2 = ScalePosition( 100, 50, scale );
|
||||
BOOST_CHECK_EQUAL( result2.x, 100 );
|
||||
BOOST_CHECK_EQUAL( result2.y, 50 );
|
||||
|
||||
wxPoint result3 = ScalePosition( 256, 128, scale );
|
||||
BOOST_CHECK_EQUAL( result3.x, 256 );
|
||||
BOOST_CHECK_EQUAL( result3.y, 128 );
|
||||
|
||||
// Test edge case with odd numbers
|
||||
wxPoint result4 = ScalePosition( 127, 63, scale );
|
||||
BOOST_CHECK_EQUAL( result4.x, 127 );
|
||||
BOOST_CHECK_EQUAL( result4.y, 63 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ScalePosition_1_5x )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
double scale = 1.5;
|
||||
|
||||
// Test various positions at 1.5x scale
|
||||
wxPoint result1 = ScalePosition( 0, 0, scale );
|
||||
BOOST_CHECK_EQUAL( result1.x, 0 );
|
||||
BOOST_CHECK_EQUAL( result1.y, 0 );
|
||||
|
||||
wxPoint result2 = ScalePosition( 100, 50, scale );
|
||||
BOOST_CHECK_EQUAL( result2.x, 150 );
|
||||
BOOST_CHECK_EQUAL( result2.y, 75 );
|
||||
|
||||
wxPoint result3 = ScalePosition( 200, 100, scale );
|
||||
BOOST_CHECK_EQUAL( result3.x, 300 );
|
||||
BOOST_CHECK_EQUAL( result3.y, 150 );
|
||||
|
||||
// Test truncation behavior with odd numbers
|
||||
wxPoint result4 = ScalePosition( 127, 63, scale );
|
||||
BOOST_CHECK_EQUAL( result4.x, static_cast<int>( 127 * 1.5 ) ); // 190
|
||||
BOOST_CHECK_EQUAL( result4.y, static_cast<int>( 63 * 1.5 ) ); // 94
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ScalePosition_2x )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
double scale = 2.0;
|
||||
|
||||
// Test various positions at 2x scale
|
||||
wxPoint result1 = ScalePosition( 0, 0, scale );
|
||||
BOOST_CHECK_EQUAL( result1.x, 0 );
|
||||
BOOST_CHECK_EQUAL( result1.y, 0 );
|
||||
|
||||
wxPoint result2 = ScalePosition( 100, 50, scale );
|
||||
BOOST_CHECK_EQUAL( result2.x, 200 );
|
||||
BOOST_CHECK_EQUAL( result2.y, 100 );
|
||||
|
||||
wxPoint result3 = ScalePosition( 256, 128, scale );
|
||||
BOOST_CHECK_EQUAL( result3.x, 512 );
|
||||
BOOST_CHECK_EQUAL( result3.y, 256 );
|
||||
|
||||
// Test that coordinates double exactly
|
||||
wxPoint result4 = ScalePosition( 127, 63, scale );
|
||||
BOOST_CHECK_EQUAL( result4.x, 254 );
|
||||
BOOST_CHECK_EQUAL( result4.y, 126 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( ScaleSize_AllFactors )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Test size scaling at all three scale factors
|
||||
int width = 80;
|
||||
int height = 24;
|
||||
|
||||
wxSize size1x = ScaleSize( width, height, 1.0 );
|
||||
BOOST_CHECK_EQUAL( size1x.GetWidth(), 80 );
|
||||
BOOST_CHECK_EQUAL( size1x.GetHeight(), 24 );
|
||||
|
||||
wxSize size1_5x = ScaleSize( width, height, 1.5 );
|
||||
BOOST_CHECK_EQUAL( size1_5x.GetWidth(), 120 );
|
||||
BOOST_CHECK_EQUAL( size1_5x.GetHeight(), 36 );
|
||||
|
||||
wxSize size2x = ScaleSize( width, height, 2.0 );
|
||||
BOOST_CHECK_EQUAL( size2x.GetWidth(), 160 );
|
||||
BOOST_CHECK_EQUAL( size2x.GetHeight(), 48 );
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// T026: GetScaleFactor Tests
|
||||
// ============================================================================
|
||||
|
||||
BOOST_AUTO_TEST_CASE( GetScaleFactor_Returns1x_ForLowDPI )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Values below 1.25 should return 1.0
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.0 ), 1.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.1 ), 1.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.24 ), 1.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.249 ), 1.0 );
|
||||
|
||||
// Edge case at boundary (1.25 should NOT return 1.0)
|
||||
BOOST_CHECK( ComputeScaleFactor( 1.25 ) != 1.0 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( GetScaleFactor_Returns1_5x_ForMediumDPI )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Values at or above 1.25 but below 1.75 should return 1.5
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.25 ), 1.5 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.5 ), 1.5 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.74 ), 1.5 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.749 ), 1.5 );
|
||||
|
||||
// Edge case at boundary (1.75 should NOT return 1.5)
|
||||
BOOST_CHECK( ComputeScaleFactor( 1.75 ) != 1.5 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( GetScaleFactor_Returns2x_ForHighDPI )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Values at or above 1.75 should return 2.0
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.75 ), 2.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 2.0 ), 2.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 2.5 ), 2.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 3.0 ), 2.0 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( GetScaleFactor_BoundaryValues )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Test exact boundary values
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.24999 ), 1.0 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.25 ), 1.5 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.74999 ), 1.5 );
|
||||
BOOST_CHECK_EQUAL( ComputeScaleFactor( 1.75 ), 2.0 );
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// T027: Tab Order Sorting Tests
|
||||
// ============================================================================
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_AlreadySorted )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields = {
|
||||
{ 10, 50, 20, 1 }, // tabOrder = 1
|
||||
{ 60, 100, 20, 2 }, // tabOrder = 2
|
||||
{ 110, 150, 20, 3 } // tabOrder = 3
|
||||
};
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
BOOST_CHECK_EQUAL( fields[0].tabOrder, 1 );
|
||||
BOOST_CHECK_EQUAL( fields[1].tabOrder, 2 );
|
||||
BOOST_CHECK_EQUAL( fields[2].tabOrder, 3 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_ReversedOrder )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields = {
|
||||
{ 10, 50, 20, 3 }, // tabOrder = 3
|
||||
{ 60, 100, 20, 2 }, // tabOrder = 2
|
||||
{ 110, 150, 20, 1 } // tabOrder = 1
|
||||
};
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
BOOST_CHECK_EQUAL( fields[0].tabOrder, 1 );
|
||||
BOOST_CHECK_EQUAL( fields[1].tabOrder, 2 );
|
||||
BOOST_CHECK_EQUAL( fields[2].tabOrder, 3 );
|
||||
|
||||
// Verify the associated coordinates moved with the tab order
|
||||
BOOST_CHECK_EQUAL( fields[0].xStart, 110 ); // Was originally tabOrder 1
|
||||
BOOST_CHECK_EQUAL( fields[1].xStart, 60 ); // Was originally tabOrder 2
|
||||
BOOST_CHECK_EQUAL( fields[2].xStart, 10 ); // Was originally tabOrder 3
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_MixedOrder )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields = {
|
||||
{ 10, 50, 20, 5 },
|
||||
{ 60, 100, 40, 1 },
|
||||
{ 110, 150, 60, 3 },
|
||||
{ 160, 200, 80, 2 },
|
||||
{ 210, 250, 100, 4 }
|
||||
};
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
BOOST_CHECK_EQUAL( fields[0].tabOrder, 1 );
|
||||
BOOST_CHECK_EQUAL( fields[1].tabOrder, 2 );
|
||||
BOOST_CHECK_EQUAL( fields[2].tabOrder, 3 );
|
||||
BOOST_CHECK_EQUAL( fields[3].tabOrder, 4 );
|
||||
BOOST_CHECK_EQUAL( fields[4].tabOrder, 5 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_DuplicateOrders )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Duplicate tab orders should maintain relative position (stable sort behavior)
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields = {
|
||||
{ 10, 50, 20, 2 },
|
||||
{ 60, 100, 40, 1 },
|
||||
{ 110, 150, 60, 2 }, // Duplicate tabOrder = 2
|
||||
{ 160, 200, 80, 1 } // Duplicate tabOrder = 1
|
||||
};
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
// All tabOrder 1 fields should come before tabOrder 2 fields
|
||||
BOOST_CHECK_EQUAL( fields[0].tabOrder, 1 );
|
||||
BOOST_CHECK_EQUAL( fields[1].tabOrder, 1 );
|
||||
BOOST_CHECK_EQUAL( fields[2].tabOrder, 2 );
|
||||
BOOST_CHECK_EQUAL( fields[3].tabOrder, 2 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_SingleField )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields = { { 10, 50, 20, 1 } };
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
BOOST_CHECK_EQUAL( fields.size(), 1 );
|
||||
BOOST_CHECK_EQUAL( fields[0].tabOrder, 1 );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( TabOrderSorting_EmptyVector )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
std::vector<DRC_RE_FIELD_POSITION> fields;
|
||||
|
||||
SortByTabOrder( fields );
|
||||
|
||||
BOOST_CHECK( fields.empty() );
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// T028: Bounds Warning Tests
|
||||
// ============================================================================
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_WithinBounds )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field completely within bounds
|
||||
wxPoint pos1( 10, 10 );
|
||||
wxSize size1( 80, 24 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos1, size1, bitmapSize ) );
|
||||
|
||||
// Field at edge of bounds (exactly fitting)
|
||||
wxPoint pos2( 220, 176 );
|
||||
wxSize size2( 80, 24 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos2, size2, bitmapSize ) );
|
||||
|
||||
// Field at origin
|
||||
wxPoint pos3( 0, 0 );
|
||||
wxSize size3( 100, 50 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos3, size3, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_ExceedsWidth )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field exceeds right edge
|
||||
wxPoint pos( 250, 10 );
|
||||
wxSize size( 80, 24 );
|
||||
|
||||
BOOST_CHECK( IsOutOfBounds( pos, size, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_ExceedsHeight )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field exceeds bottom edge
|
||||
wxPoint pos( 10, 180 );
|
||||
wxSize size( 80, 30 );
|
||||
|
||||
BOOST_CHECK( IsOutOfBounds( pos, size, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_ExceedsBothDimensions )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field exceeds both edges
|
||||
wxPoint pos( 250, 180 );
|
||||
wxSize size( 80, 30 );
|
||||
|
||||
BOOST_CHECK( IsOutOfBounds( pos, size, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_FieldLargerThanBitmap )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field larger than entire bitmap
|
||||
wxPoint pos( 0, 0 );
|
||||
wxSize size( 400, 300 );
|
||||
|
||||
BOOST_CHECK( IsOutOfBounds( pos, size, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_AtScaledPositions )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
// Simulate a field at 1x coordinates that fits, but may not fit when scaled
|
||||
int baseX = 250;
|
||||
int baseY = 180;
|
||||
int baseWidth = 40;
|
||||
int baseHeight = 15;
|
||||
|
||||
// At 1x, bitmap is 300x200
|
||||
wxSize bitmap1x( 300, 200 );
|
||||
wxPoint pos1x = ScalePosition( baseX, baseY, 1.0 );
|
||||
wxSize size1x = ScaleSize( baseWidth, baseHeight, 1.0 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos1x, size1x, bitmap1x ) );
|
||||
|
||||
// At 1.5x, bitmap becomes 450x300
|
||||
wxSize bitmap1_5x( 450, 300 );
|
||||
wxPoint pos1_5x = ScalePosition( baseX, baseY, 1.5 );
|
||||
wxSize size1_5x = ScaleSize( baseWidth, baseHeight, 1.5 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos1_5x, size1_5x, bitmap1_5x ) );
|
||||
|
||||
// At 2x, bitmap becomes 600x400
|
||||
wxSize bitmap2x( 600, 400 );
|
||||
wxPoint pos2x = ScalePosition( baseX, baseY, 2.0 );
|
||||
wxSize size2x = ScaleSize( baseWidth, baseHeight, 2.0 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos2x, size2x, bitmap2x ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_EdgeCases )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Field exactly at boundary (should be within bounds)
|
||||
wxPoint posExact( 220, 176 );
|
||||
wxSize sizeExact( 80, 24 );
|
||||
BOOST_CHECK( !IsOutOfBounds( posExact, sizeExact, bitmapSize ) );
|
||||
|
||||
// Field 1 pixel over width
|
||||
wxPoint posOverWidth( 221, 176 );
|
||||
BOOST_CHECK( IsOutOfBounds( posOverWidth, sizeExact, bitmapSize ) );
|
||||
|
||||
// Field 1 pixel over height
|
||||
wxPoint posOverHeight( 220, 177 );
|
||||
BOOST_CHECK( IsOutOfBounds( posOverHeight, sizeExact, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( BoundsWarning_ZeroSizedField )
|
||||
{
|
||||
using namespace BITMAP_OVERLAY_TEST_HELPERS;
|
||||
|
||||
wxSize bitmapSize( 300, 200 );
|
||||
|
||||
// Zero-sized field should never be out of bounds
|
||||
wxPoint pos( 0, 0 );
|
||||
wxSize zeroSize( 0, 0 );
|
||||
BOOST_CHECK( !IsOutOfBounds( pos, zeroSize, bitmapSize ) );
|
||||
|
||||
// Zero-sized field at edge
|
||||
wxPoint posEdge( 300, 200 );
|
||||
BOOST_CHECK( !IsOutOfBounds( posEdge, zeroSize, bitmapSize ) );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -714,6 +714,48 @@ set( BMAPS_256
|
||||
tune_diff_pair_skew_legend
|
||||
)
|
||||
|
||||
# Constraint bitmaps with light/dark theme variants (for DRC rule editor panels)
|
||||
# These are in sources/light/constraints/ and sources/dark/constraints/
|
||||
set( BMAPS_CONSTRAINTS
|
||||
absolute-length-2
|
||||
allowed-orientation
|
||||
basic-clearance
|
||||
board-outline-clearance
|
||||
clearance
|
||||
copper_to_edge_clearance
|
||||
copper-to-hole-clearance
|
||||
creepage-distance
|
||||
hole-size
|
||||
hole-to-hole-clearance
|
||||
hole-to-hole-distance
|
||||
length
|
||||
matched-length-diff-pair
|
||||
maximum-allowed-deviation
|
||||
maximum-via-count
|
||||
minimum-angular-ring
|
||||
minimum-annular-width
|
||||
minimum-clearance
|
||||
minimum-connection-width
|
||||
minimum-item-clearance
|
||||
minimum-soldermask-silver
|
||||
minimum-text-height-and-thickness
|
||||
minimum_thermal_relief_spoke_count
|
||||
minimum-through-hole
|
||||
minimum-track-width
|
||||
minimum-uvia-diameter
|
||||
minimum-uvia-hole
|
||||
minimum-via-diameter
|
||||
permitted-layers
|
||||
routing-diff-pair
|
||||
routing-width
|
||||
silk_clearance
|
||||
silk-to-soldermask-clearance
|
||||
soldermask-expansion
|
||||
solderpaste-expansion
|
||||
via-style
|
||||
vias-under-smd
|
||||
)
|
||||
|
||||
# Images in this section are generated at whatever resolution is set in the source SVG file
|
||||
# Use Inkscape Document Properties > Custom Size to set (make sure units are pixels)
|
||||
# These are used for images in the UI that are not-square or very large (infographics, etc)
|
||||
@@ -944,6 +986,64 @@ function( bitmap_dir pngWidth pngHeight bmapList )
|
||||
endfunction()
|
||||
|
||||
|
||||
# Function bitmap_dir_constraints
|
||||
# Like bitmap_dir but looks for SVGs in sources/${theme}/constraints/ subdirectory.
|
||||
# Used for DRC rule editor constraint overlay panel images that need light/dark variants.
|
||||
# Transforms hyphens to underscores in output names to match BITMAPS enum naming convention.
|
||||
function( bitmap_dir_constraints pngWidth pngHeight bmapList )
|
||||
|
||||
set( pngDir "${CMAKE_CURRENT_SOURCE_DIR}/png" )
|
||||
|
||||
file( MAKE_DIRECTORY ${pngDir} )
|
||||
file( MAKE_DIRECTORY ${TMP_DIR} )
|
||||
|
||||
foreach( theme ${THEMES} )
|
||||
|
||||
if( NOT ${theme} STREQUAL "light" )
|
||||
set( themeTag "_${theme}" )
|
||||
else()
|
||||
set( themeTag "" )
|
||||
endif()
|
||||
|
||||
if( ${pngHeight} EQUAL -1 )
|
||||
set( heightTag "" )
|
||||
else()
|
||||
set( heightTag "_${pngHeight}" )
|
||||
endif()
|
||||
|
||||
foreach( bmn ${bmapList} )
|
||||
|
||||
# Transform hyphens to underscores for the output name to match BITMAPS enum
|
||||
string( REPLACE "-" "_" bmnNormalized "${bmn}" )
|
||||
|
||||
set( svgFile "${CMAKE_CURRENT_SOURCE_DIR}/sources/${theme}/constraints/${bmn}.svg" )
|
||||
set( pngFile "constraint_${bmnNormalized}${themeTag}${heightTag}.png" )
|
||||
set( pngPath "${pngDir}/${pngFile}" )
|
||||
set( tmpFile "${TMP_DIR}/${pngFile}" )
|
||||
|
||||
if( NOT EXISTS ${svgFile} )
|
||||
message( "Warning: Source SVG ${svgFile} does not exist!" )
|
||||
continue()
|
||||
endif()
|
||||
|
||||
svg2png( ${svgFile} ${tmpFile} ${pngWidth} ${pngHeight} )
|
||||
png2png( ${tmpFile} ${pngPath} )
|
||||
|
||||
set( bitmapInfo
|
||||
" aBitmapInfoCache[BITMAPS::constraint_${bmnNormalized}].emplace_back( BITMAPS::constraint_${bmnNormalized}, wxT( \"${pngFile}\" ), ${pngHeight}, wxT( \"${theme}\" ) );\n"
|
||||
)
|
||||
|
||||
set( BITMAP_INFO_LIST "${BITMAP_INFO_LIST}${bitmapInfo}" )
|
||||
list( APPEND ALL_PNGS ${pngPath} )
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
set( ALL_PNGS ${ALL_PNGS} PARENT_SCOPE )
|
||||
set( BITMAP_INFO_LIST ${BITMAP_INFO_LIST} PARENT_SCOPE )
|
||||
|
||||
endfunction()
|
||||
|
||||
|
||||
include( FindUnixCommands )
|
||||
|
||||
if( TAR STREQUAL "TAR-NOTFOUND" )
|
||||
@@ -1070,6 +1170,9 @@ if( MAINTAIN_PNGS )
|
||||
|
||||
bitmap_dir( -1 -1 "${BMAPS_OTHER}" )
|
||||
|
||||
# Constraint bitmaps with light/dark theme variants (DRC rule editor panels)
|
||||
bitmap_dir_constraints( -1 -1 "${BMAPS_CONSTRAINTS}" )
|
||||
|
||||
configure_file( ${BITMAP_INFO_TEMPLATE} ${BITMAP_INFO_FILE} NEWLINE_STYLE UNIX )
|
||||
|
||||
add_custom_target( generate_pngs ALL
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate themed (light/dark) versions of constraint SVGs for KiCad DRC Rule Editor.
|
||||
|
||||
Color palette from https://dev-docs.kicad.org/en/rules-guidelines/icon-design/
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
# Color transformations from light to dark theme (case-insensitive)
|
||||
LIGHT_TO_DARK_COLORS = {
|
||||
'#545454': '#ded3dd', # Primary Gray stroke
|
||||
'#606060': '#606060', # Dense fills - stays same
|
||||
'#b9b9b9': '#e0e0e0', # Accent Grey
|
||||
'#1a81c4': '#42b8eb', # Primary Blue
|
||||
'#39b4ea': '#1a81c4', # Accent Blue (swap)
|
||||
'#bf2641': '#f2647e', # Primary Red
|
||||
'#f3f3f3': '#545454', # Area Fill
|
||||
'#dcdcdc': '#545454', # Light boundary lines
|
||||
'#000000': '#ded3dd', # Black strokes become light
|
||||
'#000fe5': '#42b8eb', # Blue arrows
|
||||
}
|
||||
|
||||
# Files to process - mapping from source name to output name
|
||||
# Format: 'source_filename.svg': 'output-name.svg'
|
||||
CONSTRAINT_FILES = {
|
||||
# Specialized panels
|
||||
'absolute-lenght-2.svg': 'absolute-length-2.svg',
|
||||
'allowed-orientation.svg': 'allowed-orientation.svg',
|
||||
'vias-under-SMD.svg': 'vias-under-smd.svg',
|
||||
'minimum_text_height_and_thickness.svg': 'minimum-text-height-and-thickness.svg',
|
||||
'permitted-layers.svg': 'permitted-layers.svg',
|
||||
'via-style.svg': 'via-style.svg',
|
||||
|
||||
# Numeric input constraints
|
||||
'Basic clearance.svg': 'basic-clearance.svg',
|
||||
'board-outline-clearance.svg': 'board-outline-clearance.svg',
|
||||
'minimum_clearance.svg': 'minimum-clearance.svg',
|
||||
'minimum_item_clearance.svg': 'minimum-item-clearance.svg',
|
||||
'minimum_connection_width.svg': 'minimum-connection-width.svg',
|
||||
'minimum_track_width.svg': 'minimum-track-width.svg',
|
||||
'copper_to_hole_clearance.svg': 'copper-to-hole-clearance.svg',
|
||||
'hole_to_hole_clearance.svg': 'hole-to-hole-clearance.svg',
|
||||
'minimum_annular_width.svg': 'minimum-annular-width.svg',
|
||||
'minimum_through_hole.svg': 'minimum-through-hole.svg',
|
||||
'hole-to-hole-distance.svg': 'hole-to-hole-distance.svg',
|
||||
'minimum_uvia_hole.svg': 'minimum-uvia-hole.svg',
|
||||
'minimum_uvia_diameter.svg': 'minimum-uvia-diameter.svg',
|
||||
'minimum_via_diameter.svg': 'minimum-via-diameter.svg',
|
||||
'silk-to-soldermask-clearance.svg': 'silk-to-soldermask-clearance.svg',
|
||||
'minimum-soldermask-silver.svg': 'minimum-soldermask-silver.svg',
|
||||
'solderpaste-expansion.svg': 'solderpaste-expansion.svg',
|
||||
'maximum_allowed_deviation.svg': 'maximum-allowed-deviation.svg',
|
||||
'minimum-angular-ring.svg': 'minimum-angular-ring.svg',
|
||||
'matched-lenght-diff-pair.svg': 'matched-length-diff-pair.svg',
|
||||
}
|
||||
|
||||
|
||||
def transform_colors_to_dark(svg_content: str) -> str:
|
||||
"""Transform light theme colors to dark theme colors."""
|
||||
result = svg_content
|
||||
|
||||
for light_color, dark_color in LIGHT_TO_DARK_COLORS.items():
|
||||
# Case-insensitive replacement for hex colors
|
||||
pattern = re.compile(re.escape(light_color), re.IGNORECASE)
|
||||
result = pattern.sub(dark_color, result)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def process_svg_files():
|
||||
"""Process all constraint SVGs and create themed versions."""
|
||||
script_dir = Path(__file__).parent
|
||||
source_dir = script_dir / 'sources' / 'constraints'
|
||||
light_dir = script_dir / 'sources' / 'light' / 'constraints'
|
||||
dark_dir = script_dir / 'sources' / 'dark' / 'constraints'
|
||||
|
||||
# Create output directories if they don't exist
|
||||
light_dir.mkdir(parents=True, exist_ok=True)
|
||||
dark_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
processed = 0
|
||||
skipped = 0
|
||||
|
||||
for source_name, output_name in CONSTRAINT_FILES.items():
|
||||
source_path = source_dir / source_name
|
||||
|
||||
if not source_path.exists():
|
||||
print(f"WARNING: Source file not found: {source_name}")
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# Read source SVG
|
||||
with open(source_path, 'r', encoding='utf-8') as f:
|
||||
svg_content = f.read()
|
||||
|
||||
# Write light version (copy as-is, since originals use light theme colors)
|
||||
light_path = light_dir / output_name
|
||||
with open(light_path, 'w', encoding='utf-8') as f:
|
||||
f.write(svg_content)
|
||||
print(f"Created light: {output_name}")
|
||||
|
||||
# Transform and write dark version
|
||||
dark_content = transform_colors_to_dark(svg_content)
|
||||
dark_path = dark_dir / output_name
|
||||
with open(dark_path, 'w', encoding='utf-8') as f:
|
||||
f.write(dark_content)
|
||||
print(f"Created dark: {output_name}")
|
||||
|
||||
processed += 1
|
||||
|
||||
print(f"\nProcessed {processed} files, skipped {skipped}")
|
||||
return processed, skipped
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
process_svg_files()
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 522 B |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 543 B |
|
After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 349 B |
|
After Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 459 B |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 409 B |
|
After Width: | Height: | Size: 410 B |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 537 B |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 505 B |
|
After Width: | Height: | Size: 510 B |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 256 B |
|
After Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 467 B |
|
After Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 332 B |
|
After Width: | Height: | Size: 329 B |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 410 B |
|
After Width: | Height: | Size: 408 B |
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 421 B |
|
After Width: | Height: | Size: 419 B |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 457 B |