diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp index 757fd0e81c..914bb92f2b 100644 --- a/common/advanced_config.cpp +++ b/common/advanced_config.cpp @@ -48,10 +48,10 @@ static const wxChar AdvancedConfigMask[] = wxT( "KICAD_ADVANCED_CONFIG" ); */ namespace AC_STACK { - static constexpr int min_stack = 32 * 4096; - static constexpr int default_stack = 256 * 4096; - static constexpr int max_stack = 4096 * 4096; -} +static constexpr int min_stack = 32 * 4096; +static constexpr int default_stack = 256 * 4096; +static constexpr int max_stack = 4096 * 4096; +} // namespace AC_STACK /** * List of known keys for advanced configuration options. @@ -144,7 +144,7 @@ static const wxChar EnableVariantsUI[] = wxT( "EnableVariantsUI" ); static const wxChar EnableUseAuiPerspective[] = wxT( "EnableUseAuiPerspective" ); static const wxChar HistoryLockStaleTimeout[] = wxT( "HistoryLockStaleTimeout" ); -} // namespace KEYS +} // namespace AC_KEYS /** @@ -174,21 +174,12 @@ wxString dumpParamCfg( const PARAM_CFG& aParam ) switch( aParam.m_Type ) { case paramcfg_id::PARAM_INT: - case paramcfg_id::PARAM_INT_WITH_SCALE: - s << *static_cast( aParam ).m_Pt_param; - break; - case paramcfg_id::PARAM_DOUBLE: - s << *static_cast( aParam ).m_Pt_param; - break; - case paramcfg_id::PARAM_WXSTRING: - s << *static_cast( aParam ).m_Pt_param; - break; - case paramcfg_id::PARAM_FILENAME: - s << *static_cast( aParam ).m_Pt_param; - break; + case paramcfg_id::PARAM_INT_WITH_SCALE: s << *static_cast( aParam ).m_Pt_param; break; + case paramcfg_id::PARAM_DOUBLE: s << *static_cast( aParam ).m_Pt_param; break; + case paramcfg_id::PARAM_WXSTRING: s << *static_cast( aParam ).m_Pt_param; break; + case paramcfg_id::PARAM_FILENAME: s << *static_cast( aParam ).m_Pt_param; break; case paramcfg_id::PARAM_BOOL: - s << ( *static_cast( aParam ).m_Pt_param ? wxS( "true" ) - : wxS( "false" ) ); + s << ( *static_cast( aParam ).m_Pt_param ? wxS( "true" ) : wxS( "false" ) ); break; default: s << wxS( "Unsupported PARAM_CFG variant: " ) << aParam.m_Type; } @@ -231,71 +222,71 @@ ADVANCED_CFG::ADVANCED_CFG() // Init defaults - this is done in case the config doesn't exist, // then the values will remain as set here. - m_CoroutineStackSize = AC_STACK::default_stack; - m_ShowRouterDebugGraphics = false; - m_EnableRouterDump = false; - m_HyperZoom = false; - m_DrawArcAccuracy = 10.0; - m_DrawArcCenterMaxAngle = 50.0; - m_MaxTangentAngleDeviation = 1.0; - m_MaxTrackLengthToKeep = 0.0005; - m_ExtraZoneDisplayModes = false; + m_CoroutineStackSize = AC_STACK::default_stack; + m_ShowRouterDebugGraphics = false; + m_EnableRouterDump = false; + m_HyperZoom = false; + m_DrawArcAccuracy = 10.0; + m_DrawArcCenterMaxAngle = 50.0; + m_MaxTangentAngleDeviation = 1.0; + m_MaxTrackLengthToKeep = 0.0005; + m_ExtraZoneDisplayModes = false; m_DrawTriangulationOutlines = false; - m_ExtraClearance = 0.0005; - m_EnableCreepageSlot = false; - m_DRCEpsilon = 0.0005; // 0.5um is small enough not to materially violate - // any constraints. - m_SliverWidthTolerance = 0.08; - m_SliverMinimumLength = 0.0008; - m_SliverAngleTolerance = 20.0; + m_ExtraClearance = 0.0005; + m_EnableCreepageSlot = false; + m_DRCEpsilon = 0.0005; // 0.5um is small enough not to materially violate + // any constraints. + m_SliverWidthTolerance = 0.08; + m_SliverMinimumLength = 0.0008; + m_SliverAngleTolerance = 20.0; - m_HoleWallThickness = 0.020; // IPC-6012 says 15-18um; Cadence says at least - // 0.020 for a Class 2 board and at least 0.025 - // for Class 3. + m_HoleWallThickness = 0.020; // IPC-6012 says 15-18um; Cadence says at least + // 0.020 for a Class 2 board and at least 0.025 + // for Class 3. - m_MinPlotPenWidth = 0.0212; // 1 pixel at 1200dpi. + m_MinPlotPenWidth = 0.0212; // 1 pixel at 1200dpi. - m_DebugZoneFiller = false; - m_DebugPDFWriter = false; - m_PDFStrokeFontWidthFactor = .12; // default 12% of EM - m_PDFStrokeFontXOffset = 0.1; - m_PDFStrokeFontYOffset = 0.35; + m_DebugZoneFiller = false; + m_DebugPDFWriter = false; + m_PDFStrokeFontWidthFactor = .12; // default 12% of EM + m_PDFStrokeFontXOffset = 0.1; + m_PDFStrokeFontYOffset = 0.35; m_PDFStrokeFontBoldMultiplier = 1.8; m_PDFStrokeFontKerningFactor = 1.0; - m_UsePdfPrint = false; - m_SmallDrillMarkSize = 0.35; - m_HotkeysDumper = false; - m_DrawBoundingBoxes = false; - m_MsgPanelShowUuids = 0; - m_ShowPcbnewExportNetlist = false; - m_Skip3DModelFileCache = false; - m_Skip3DModelMemoryCache = false; - m_HideVersionFromTitle = false; - m_ShowEventCounters = false; - m_AllowManualCanvasScale = false; - m_CompactSave = false; - m_UpdateUIEventInterval = 0; - m_ShowRepairSchematic = false; - m_EnablePcbDesignBlocks = true; - m_EnableGenerators = false; - m_EnableLibWithText = false; - m_EnableLibDir = false; + m_UsePdfPrint = false; + m_SmallDrillMarkSize = 0.35; + m_HotkeysDumper = false; + m_DrawBoundingBoxes = false; + m_MsgPanelShowUuids = 0; + m_ShowPcbnewExportNetlist = false; + m_Skip3DModelFileCache = false; + m_Skip3DModelMemoryCache = false; + m_HideVersionFromTitle = false; + m_ShowEventCounters = false; + m_AllowManualCanvasScale = false; + m_CompactSave = false; + m_UpdateUIEventInterval = 0; + m_ShowRepairSchematic = false; + m_EnablePcbDesignBlocks = true; + m_EnableGenerators = false; + m_EnableLibWithText = false; + m_EnableLibDir = false; - m_3DRT_BevelHeight_um = 30; - m_3DRT_BevelExtentFactor = 1.0 / 16.0; + m_3DRT_BevelHeight_um = 30; + m_3DRT_BevelExtentFactor = 1.0 / 16.0; - m_EnableAPILogging = false; + m_EnableAPILogging = false; - m_Use3DConnexionDriver = true; + m_Use3DConnexionDriver = true; - m_IncrementalConnectivity = true; + m_IncrementalConnectivity = true; - m_DisambiguationMenuDelay = 500; + m_DisambiguationMenuDelay = 500; m_PcbSelectionVisibilityRatio = 1.0; - m_FontErrorSize = 2; + m_FontErrorSize = 2; m_OcePluginLinearDeflection = 0.14; m_OcePluginAngularDeflection = 30; @@ -309,7 +300,7 @@ ADVANCED_CFG::ADVANCED_CFG() m_MinorSchematicGraphSize = 10000; - m_ResolveTextRecursionDepth = 3; + m_ResolveTextRecursionDepth = 6; m_EnableExtensionSnaps = true; m_ExtensionSnapTimeoutMs = 500; @@ -364,7 +355,7 @@ void ADVANCED_CFG::Reload() void ADVANCED_CFG::Save() { - wxFileName k_advanced = getAdvancedCfgFilename(); + wxFileName k_advanced = getAdvancedCfgFilename(); wxFileConfig file_cfg( wxS( "" ), wxS( "" ), k_advanced.GetFullPath() ); wxConfigSaveSetups( &file_cfg, m_entries ); @@ -390,8 +381,7 @@ void ADVANCED_CFG::loadFromConfigFile() return; } - wxLogTrace( AdvancedConfigMask, wxS( "Loading advanced config from: %s" ), - k_advanced.GetFullPath() ); + wxLogTrace( AdvancedConfigMask, wxS( "Loading advanced config from: %s" ), k_advanced.GetFullPath() ); wxFileConfig file_cfg( wxS( "" ), wxS( "" ), k_advanced.GetFullPath() ); loadSettings( file_cfg ); @@ -402,310 +392,267 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) { m_entries.clear(); - m_entries.push_back( std::make_unique( true, AC_KEYS::ExtraFillMargin, - &m_ExtraClearance, - m_ExtraClearance, 0.0, 1.0 ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::ExtraFillMargin, &m_ExtraClearance, + m_ExtraClearance, 0.0, 1.0 ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableCreepageSlot, - &m_EnableCreepageSlot, m_EnableCreepageSlot ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DRCEpsilon, - &m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DRCSliverWidthTolerance, - &m_SliverWidthTolerance, m_SliverWidthTolerance, - 0.01, 0.25 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DRCSliverMinimumLength, - &m_SliverMinimumLength, m_SliverMinimumLength, - 1e-9, 10 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DRCSliverAngleTolerance, - &m_SliverAngleTolerance, m_SliverAngleTolerance, - 1.0, 90.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::HoleWallThickness, - &m_HoleWallThickness, m_HoleWallThickness, - 0.0, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::CoroutineStackSize, - &m_CoroutineStackSize, AC_STACK::default_stack, - AC_STACK::min_stack, AC_STACK::max_stack ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::UpdateUIEventInterval, - &m_UpdateUIEventInterval, m_UpdateUIEventInterval, - -1, 100000 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ShowRouterDebugGraphics, - &m_ShowRouterDebugGraphics, - m_ShowRouterDebugGraphics ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableRouterDump, - &m_EnableRouterDump, m_EnableRouterDump ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::HyperZoom, - &m_HyperZoom, m_HyperZoom ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::CompactFileSave, - &m_CompactSave, m_CompactSave ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DrawArcAccuracy, - &m_DrawArcAccuracy, m_DrawArcAccuracy, - 0.0, 100000.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DrawArcCenterStartEndMaxAngle, - &m_DrawArcCenterMaxAngle, - m_DrawArcCenterMaxAngle, 0.0, 100000.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MaxTangentTrackAngleDeviation, - &m_MaxTangentAngleDeviation, - m_MaxTangentAngleDeviation, 0.0, 90.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MaxTrackLengthToKeep, - &m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep, - 0.0, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ExtraZoneDisplayModes, - &m_ExtraZoneDisplayModes, - m_ExtraZoneDisplayModes ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::StrokeTriangulation, - &m_DrawTriangulationOutlines, - m_DrawTriangulationOutlines ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MinPlotPenWidth, - &m_MinPlotPenWidth, m_MinPlotPenWidth, - 0.0, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DebugZoneFiller, - &m_DebugZoneFiller, m_DebugZoneFiller ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DebugPDFWriter, - &m_DebugPDFWriter, m_DebugPDFWriter ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontWidthFactor, - &m_PDFStrokeFontWidthFactor, m_PDFStrokeFontWidthFactor ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontXOffset, - &m_PDFStrokeFontXOffset, m_PDFStrokeFontXOffset ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontYOffset, - &m_PDFStrokeFontYOffset, m_PDFStrokeFontYOffset ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontBoldMultiplier, - &m_PDFStrokeFontBoldMultiplier, m_PDFStrokeFontBoldMultiplier ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontKerningFactor, - &m_PDFStrokeFontKerningFactor, m_PDFStrokeFontKerningFactor ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::UsePdfPrint, - &m_UsePdfPrint, m_UsePdfPrint ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::SmallDrillMarkSize, - &m_SmallDrillMarkSize, m_SmallDrillMarkSize, - 0.0, 3.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::HotkeysDumper, - &m_HotkeysDumper, m_HotkeysDumper ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DrawBoundingBoxes, - &m_DrawBoundingBoxes, m_DrawBoundingBoxes ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ShowPcbnewExportNetlist, - &m_ShowPcbnewExportNetlist, - m_ShowPcbnewExportNetlist ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::Skip3DModelFileCache, - &m_Skip3DModelFileCache, m_Skip3DModelFileCache ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::Skip3DModelMemoryCache, - &m_Skip3DModelMemoryCache, - m_Skip3DModelMemoryCache ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::HideVersionFromTitle, - &m_HideVersionFromTitle, m_HideVersionFromTitle ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ShowRepairSchematic, - &m_ShowRepairSchematic, m_ShowRepairSchematic ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ShowEventCounters, - &m_ShowEventCounters, m_ShowEventCounters ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::AllowManualCanvasScale, - &m_AllowManualCanvasScale, - m_AllowManualCanvasScale ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::V3DRT_BevelHeight_um, - &m_3DRT_BevelHeight_um, m_3DRT_BevelHeight_um, - 0, std::numeric_limits::max(), - AC_GROUPS::V3D_RayTracing ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::V3DRT_BevelExtentFactor, - &m_3DRT_BevelExtentFactor, - m_3DRT_BevelExtentFactor, 0.0, 100.0, - AC_GROUPS::V3D_RayTracing ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::Use3DConnexionDriver, - &m_Use3DConnexionDriver, m_Use3DConnexionDriver ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::IncrementalConnectivity, - &m_IncrementalConnectivity, - m_IncrementalConnectivity ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::DisambiguationTime, - &m_DisambiguationMenuDelay, - m_DisambiguationMenuDelay, - 50, 10000 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnablePcbDesignBlocks, &m_EnablePcbDesignBlocks, - m_EnablePcbDesignBlocks ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableGenerators, - &m_EnableGenerators, m_EnableGenerators ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableAPILogging, - &m_EnableAPILogging, m_EnableAPILogging ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableLibWithText, - &m_EnableLibWithText, m_EnableLibWithText ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableLibDir, - &m_EnableLibDir, m_EnableLibDir ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::PcbSelectionVisibilityRatio, - &m_PcbSelectionVisibilityRatio, - m_PcbSelectionVisibilityRatio, 0.0, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::FontErrorSize, - &m_FontErrorSize, - m_FontErrorSize, 0.01, 100 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::OcePluginLinearDeflection, - &m_OcePluginLinearDeflection, - m_OcePluginLinearDeflection, 0.01, 1.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::OcePluginAngularDeflection, - &m_OcePluginAngularDeflection, - m_OcePluginAngularDeflection, 0.01, 360.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::TriangulateSimplificationLevel, - &m_TriangulateSimplificationLevel, - m_TriangulateSimplificationLevel, 5, 1000 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::TriangulateMinimumArea, - &m_TriangulateMinimumArea, - m_TriangulateMinimumArea, 25, 100000 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableCacheFriendlyFracture, - &m_EnableCacheFriendlyFracture, - m_EnableCacheFriendlyFracture ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MaxFileSystemWatchers, - &m_MaxFilesystemWatchers, m_MaxFilesystemWatchers, - 0, 2147483647 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MinorSchematicGraphSize, - &m_MinorSchematicGraphSize, - m_MinorSchematicGraphSize, - 0, 2147483647 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ResolveTextRecursionDepth, - &m_ResolveTextRecursionDepth, - m_ResolveTextRecursionDepth, 0, 10 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableExtensionSnaps, - &m_EnableExtensionSnaps, - m_EnableExtensionSnaps ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ExtensionSnapTimeoutMs, - &m_ExtensionSnapTimeoutMs, - m_ExtensionSnapTimeoutMs, 0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::ExtensionSnapActivateOnHover, - &m_ExtensionSnapActivateOnHover, - m_ExtensionSnapActivateOnHover ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::EnableSnapAnchorsDebug, - &m_EnableSnapAnchorsDebug, - m_EnableSnapAnchorsDebug ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::SnapHysteresis, - &m_SnapHysteresis, m_SnapHysteresis, - 0, 100 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::SnapToAnchorMargin, - &m_SnapToAnchorMargin, m_SnapToAnchorMargin, - 1.0, 2.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MinParallelAngle, - &m_MinParallelAngle, m_MinParallelAngle, - 0.0, 45.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::HoleWallPaintingMultiplier, - &m_HoleWallPaintingMultiplier, - m_HoleWallPaintingMultiplier, - 0.1, 100.0 ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MsgPanelShowUuids, - &m_MsgPanelShowUuids, - m_MsgPanelShowUuids ) ); - - m_entries.push_back( std::make_unique( true, AC_KEYS::MaximumThreads, - &m_MaximumThreads, m_MaximumThreads, - 0, 500 ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableCreepageSlot, &m_EnableCreepageSlot, + m_EnableCreepageSlot ) ); m_entries.push_back( - std::make_unique( true, AC_KEYS::NetInspectorBulkUpdateOptimisationThreshold, - &m_NetInspectorBulkUpdateOptimisationThreshold, - m_NetInspectorBulkUpdateOptimisationThreshold, 0, 1000 ) ); + std::make_unique( true, AC_KEYS::DRCEpsilon, &m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::DRCSliverWidthTolerance, &m_SliverWidthTolerance, m_SliverWidthTolerance, 0.01, 0.25 ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::DRCSliverMinimumLength, &m_SliverMinimumLength, m_SliverMinimumLength, 1e-9, 10 ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::DRCSliverAngleTolerance, &m_SliverAngleTolerance, m_SliverAngleTolerance, 1.0, 90.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::HoleWallThickness, &m_HoleWallThickness, + m_HoleWallThickness, 0.0, 1.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::CoroutineStackSize, &m_CoroutineStackSize, + AC_STACK::default_stack, AC_STACK::min_stack, + AC_STACK::max_stack ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::UpdateUIEventInterval, &m_UpdateUIEventInterval, m_UpdateUIEventInterval, -1, 100000 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ShowRouterDebugGraphics, + &m_ShowRouterDebugGraphics, m_ShowRouterDebugGraphics ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableRouterDump, &m_EnableRouterDump, + m_EnableRouterDump ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::HyperZoom, &m_HyperZoom, m_HyperZoom ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::CompactFileSave, &m_CompactSave, m_CompactSave ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::DrawArcAccuracy, &m_DrawArcAccuracy, + m_DrawArcAccuracy, 0.0, 100000.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::DrawArcCenterStartEndMaxAngle, + &m_DrawArcCenterMaxAngle, m_DrawArcCenterMaxAngle, 0.0, + 100000.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MaxTangentTrackAngleDeviation, + &m_MaxTangentAngleDeviation, m_MaxTangentAngleDeviation, + 0.0, 90.0 ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::MaxTrackLengthToKeep, &m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep, 0.0, 1.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ExtraZoneDisplayModes, + &m_ExtraZoneDisplayModes, m_ExtraZoneDisplayModes ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::StrokeTriangulation, &m_DrawTriangulationOutlines, m_DrawTriangulationOutlines ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MinPlotPenWidth, &m_MinPlotPenWidth, + m_MinPlotPenWidth, 0.0, 1.0 ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::DebugZoneFiller, &m_DebugZoneFiller, m_DebugZoneFiller ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::DebugPDFWriter, &m_DebugPDFWriter, m_DebugPDFWriter ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::PDFStrokeFontWidthFactor, &m_PDFStrokeFontWidthFactor, m_PDFStrokeFontWidthFactor ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontXOffset, + &m_PDFStrokeFontXOffset, m_PDFStrokeFontXOffset ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontYOffset, + &m_PDFStrokeFontYOffset, m_PDFStrokeFontYOffset ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::PDFStrokeFontBoldMultiplier, + &m_PDFStrokeFontBoldMultiplier, + m_PDFStrokeFontBoldMultiplier ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::PDFStrokeFontKerningFactor, &m_PDFStrokeFontKerningFactor, m_PDFStrokeFontKerningFactor ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::UsePdfPrint, &m_UsePdfPrint, m_UsePdfPrint ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::SmallDrillMarkSize, &m_SmallDrillMarkSize, + m_SmallDrillMarkSize, 0.0, 3.0 ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::HotkeysDumper, &m_HotkeysDumper, m_HotkeysDumper ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::DrawBoundingBoxes, &m_DrawBoundingBoxes, + m_DrawBoundingBoxes ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ShowPcbnewExportNetlist, + &m_ShowPcbnewExportNetlist, m_ShowPcbnewExportNetlist ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::Skip3DModelFileCache, &m_Skip3DModelFileCache, + m_Skip3DModelFileCache ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::Skip3DModelMemoryCache, + &m_Skip3DModelMemoryCache, m_Skip3DModelMemoryCache ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::HideVersionFromTitle, &m_HideVersionFromTitle, + m_HideVersionFromTitle ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ShowRepairSchematic, &m_ShowRepairSchematic, + m_ShowRepairSchematic ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ShowEventCounters, &m_ShowEventCounters, + m_ShowEventCounters ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::AllowManualCanvasScale, + &m_AllowManualCanvasScale, m_AllowManualCanvasScale ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::V3DRT_BevelHeight_um, &m_3DRT_BevelHeight_um, + m_3DRT_BevelHeight_um, 0, std::numeric_limits::max(), + AC_GROUPS::V3D_RayTracing ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::V3DRT_BevelExtentFactor, + &m_3DRT_BevelExtentFactor, m_3DRT_BevelExtentFactor, 0.0, + 100.0, AC_GROUPS::V3D_RayTracing ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::Use3DConnexionDriver, &m_Use3DConnexionDriver, + m_Use3DConnexionDriver ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::IncrementalConnectivity, + &m_IncrementalConnectivity, m_IncrementalConnectivity ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::DisambiguationTime, &m_DisambiguationMenuDelay, + m_DisambiguationMenuDelay, 50, 10000 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnablePcbDesignBlocks, + &m_EnablePcbDesignBlocks, m_EnablePcbDesignBlocks ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableGenerators, &m_EnableGenerators, + m_EnableGenerators ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableAPILogging, &m_EnableAPILogging, + m_EnableAPILogging ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableLibWithText, &m_EnableLibWithText, + m_EnableLibWithText ) ); + + m_entries.push_back( + std::make_unique( true, AC_KEYS::EnableLibDir, &m_EnableLibDir, m_EnableLibDir ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::PcbSelectionVisibilityRatio, + &m_PcbSelectionVisibilityRatio, + m_PcbSelectionVisibilityRatio, 0.0, 1.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::FontErrorSize, &m_FontErrorSize, + m_FontErrorSize, 0.01, 100 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::OcePluginLinearDeflection, + &m_OcePluginLinearDeflection, m_OcePluginLinearDeflection, + 0.01, 1.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::OcePluginAngularDeflection, + &m_OcePluginAngularDeflection, + m_OcePluginAngularDeflection, 0.01, 360.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::TriangulateSimplificationLevel, + &m_TriangulateSimplificationLevel, + m_TriangulateSimplificationLevel, 5, 1000 ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::TriangulateMinimumArea, &m_TriangulateMinimumArea, m_TriangulateMinimumArea, 25, 100000 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableCacheFriendlyFracture, + &m_EnableCacheFriendlyFracture, + m_EnableCacheFriendlyFracture ) ); + + m_entries.push_back( std::make_unique( + true, AC_KEYS::MaxFileSystemWatchers, &m_MaxFilesystemWatchers, m_MaxFilesystemWatchers, 0, 2147483647 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MinorSchematicGraphSize, + &m_MinorSchematicGraphSize, m_MinorSchematicGraphSize, 0, + 2147483647 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ResolveTextRecursionDepth, + &m_ResolveTextRecursionDepth, m_ResolveTextRecursionDepth, 0, + 10 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableExtensionSnaps, &m_EnableExtensionSnaps, + m_EnableExtensionSnaps ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ExtensionSnapTimeoutMs, + &m_ExtensionSnapTimeoutMs, m_ExtensionSnapTimeoutMs, 0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::ExtensionSnapActivateOnHover, + &m_ExtensionSnapActivateOnHover, + m_ExtensionSnapActivateOnHover ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::EnableSnapAnchorsDebug, + &m_EnableSnapAnchorsDebug, m_EnableSnapAnchorsDebug ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::SnapHysteresis, &m_SnapHysteresis, + m_SnapHysteresis, 0, 100 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::SnapToAnchorMargin, &m_SnapToAnchorMargin, + m_SnapToAnchorMargin, 1.0, 2.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MinParallelAngle, &m_MinParallelAngle, + m_MinParallelAngle, 0.0, 45.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::HoleWallPaintingMultiplier, + &m_HoleWallPaintingMultiplier, + m_HoleWallPaintingMultiplier, 0.1, 100.0 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MsgPanelShowUuids, &m_MsgPanelShowUuids, + m_MsgPanelShowUuids ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::MaximumThreads, &m_MaximumThreads, + m_MaximumThreads, 0, 500 ) ); + + m_entries.push_back( std::make_unique( true, AC_KEYS::NetInspectorBulkUpdateOptimisationThreshold, + &m_NetInspectorBulkUpdateOptimisationThreshold, + m_NetInspectorBulkUpdateOptimisationThreshold, 0, 1000 ) ); m_entries.push_back( std::make_unique( true, AC_KEYS::ExcludeFromSimulationLineWidth, - &m_ExcludeFromSimulationLineWidth, - m_ExcludeFromSimulationLineWidth, 1, 100 ) ); + &m_ExcludeFromSimulationLineWidth, + m_ExcludeFromSimulationLineWidth, 1, 100 ) ); - m_entries.push_back( std::make_unique( true, - AC_KEYS::SimulatorMultiRunCombinationLimit, - &m_SimulatorMultiRunCombinationLimit, - m_SimulatorMultiRunCombinationLimit, 1, 100 ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::SimulatorMultiRunCombinationLimit, + &m_SimulatorMultiRunCombinationLimit, + m_SimulatorMultiRunCombinationLimit, 1, 100 ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::GitIconRefreshInterval, - &m_GitIconRefreshInterval, - m_GitIconRefreshInterval, 0, 100000 ) ); + m_entries.push_back( std::make_unique( + true, AC_KEYS::GitIconRefreshInterval, &m_GitIconRefreshInterval, m_GitIconRefreshInterval, 0, 100000 ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::ConfigurableToolbars, - &m_ConfigurableToolbars, - m_ConfigurableToolbars ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::ConfigurableToolbars, &m_ConfigurableToolbars, + m_ConfigurableToolbars ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::MaxPastedTextLength, - &m_MaxPastedTextLength, - m_MaxPastedTextLength, 0, 100000 ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::MaxPastedTextLength, &m_MaxPastedTextLength, + m_MaxPastedTextLength, 0, 100000 ) ); m_entries.push_back( std::make_unique( true, AC_KEYS::PNSProcessClusterTimeout, - &m_PNSProcessClusterTimeout, 100, 10, 10000 ) ); + &m_PNSProcessClusterTimeout, 100, 10, 10000 ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::ImportSkipComponentBodies, - &m_ImportSkipComponentBodies, - m_ImportSkipComponentBodies ) ); + m_entries.push_back( std::make_unique( + true, AC_KEYS::ImportSkipComponentBodies, &m_ImportSkipComponentBodies, m_ImportSkipComponentBodies ) ); - m_entries.push_back( std::make_unique( true, AC_KEYS::ScreenDPI, - &m_ScreenDPI, m_ScreenDPI, - 50, 500 ) ); + m_entries.push_back( + std::make_unique( true, AC_KEYS::ScreenDPI, &m_ScreenDPI, m_ScreenDPI, 50, 500 ) ); m_entries.push_back( std::make_unique( true, AC_KEYS::EnableVariantsUI, &m_EnableVariantsUI, m_EnableVariantsUI ) ); m_entries.push_back( std::make_unique( true, AC_KEYS::EnableUseAuiPerspective, - &m_EnableUseAuiPerspective, - m_EnableUseAuiPerspective ) ); + &m_EnableUseAuiPerspective, m_EnableUseAuiPerspective ) ); m_entries.push_back( std::make_unique( true, AC_KEYS::HistoryLockStaleTimeout, - &m_HistoryLockStaleTimeout, m_HistoryLockStaleTimeout, - 10, 86400 ) ); // 10 seconds to 24 hours + &m_HistoryLockStaleTimeout, m_HistoryLockStaleTimeout, 10, + 86400 ) ); // 10 seconds to 24 hours // Special case for trace mask setting...we just grab them and set them immediately // Because we even use wxLogTrace inside of advanced config - m_entries.push_back( std::make_unique( true, AC_KEYS::TraceMasks, &m_traceMasks, - wxS( "" ) ) ); + m_entries.push_back( std::make_unique( true, AC_KEYS::TraceMasks, &m_traceMasks, wxS( "" ) ) ); // Load the config from file wxConfigLoadSetups( &aCfg, m_entries ); @@ -721,6 +668,5 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg ) dumpCfg( m_entries ); - wxLogTrace( kicadTraceCoroutineStack, wxT( "Using coroutine stack size %d" ), - m_CoroutineStackSize ); + wxLogTrace( kicadTraceCoroutineStack, wxT( "Using coroutine stack size %d" ), m_CoroutineStackSize ); } diff --git a/common/common.cpp b/common/common.cpp index c9ae8ce855..d578dbb599 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -28,9 +28,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -48,10 +50,10 @@ enum Bracket { Bracket_None, - Bracket_Normal = ')', - Bracket_Curly = '}', -#ifdef __WINDOWS__ - Bracket_Windows = '%', // yeah, Windows people are a bit strange ;-) + Bracket_Normal = ')', + Bracket_Curly = '}', +#ifdef __WINDOWS__ + Bracket_Windows = '%', // yeah, Windows people are a bit strange ;-) #endif Bracket_Max }; @@ -59,56 +61,145 @@ enum Bracket wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject, int aFlags ) { - std::function projectResolver = - [&]( wxString* token ) -> bool - { - return aProject->TextVarResolver( token ); - }; + std::function projectResolver = [&]( wxString* token ) -> bool + { + return aProject->TextVarResolver( token ); + }; return ExpandTextVars( aSource, &projectResolver, aFlags ); } -wxString ExpandTextVars( const wxString& aSource, - const std::function* aResolver, int aFlags ) +wxString ExpandTextVars( const wxString& aSource, const std::function* aResolver, int aFlags, + int aDepth ) { wxString newbuf; size_t sourceLen = aSource.length(); - newbuf.Alloc( sourceLen ); // best guess (improves performance) + newbuf.Alloc( sourceLen ); // best guess (improves performance) + + // Get the maximum recursion depth from advanced config + const int maxDepth = ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth; for( size_t i = 0; i < sourceLen; ++i ) { - if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' ) + // Handle escaped variable references: \${...} or \@{...} + // Use a temporary placeholder to prevent re-expansion in multi-pass loops + if( aSource[i] == '\\' && i + 1 < sourceLen ) { + if( ( aSource[i + 1] == '$' || aSource[i + 1] == '@' ) && i + 2 < sourceLen && aSource[i + 2] == '{' ) + { + // Replace \${ with \x01ESC_DOLLAR{ and \@{ with \x01ESC_AT{ + // Also escape any inner ${...} or @{...} to prevent partial evaluation + newbuf.append( wxT( "\x01ESC_" ) ); + if( aSource[i + 1] == '$' ) + newbuf.append( wxT( "DOLLAR{" ) ); + else + newbuf.append( wxT( "AT{" ) ); + i += 2; + + int braceDepth = 1; + for( i = i + 1; i < sourceLen && braceDepth > 0; ++i ) + { + if( aSource[i] == '{' ) + braceDepth++; + else if( aSource[i] == '}' ) + braceDepth--; + + // Escape any inner ${...} or @{...} sequences + if( ( aSource[i] == '$' || aSource[i] == '@' ) && i + 1 < sourceLen && aSource[i + 1] == '{' ) + { + newbuf.append( wxT( "\x01ESC_" ) ); + if( aSource[i] == '$' ) + newbuf.append( wxT( "DOLLAR{" ) ); + else + newbuf.append( wxT( "AT{" ) ); + i++; // Skip the '{' + } + else + { + newbuf.append( aSource[i] ); + } + } + i--; // Adjust because loop will increment + continue; + } + } + + if( ( aSource[i] == '$' || aSource[i] == '@' ) && i + 1 < sourceLen && aSource[i + 1] == '{' ) + { + bool isMathExpr = ( aSource[i] == '@' ); wxString token; + int braceDepth = 1; // Track brace depth for nested expressions like @{${VAR}} for( i = i + 2; i < sourceLen; ++i ) { - if( aSource[i] == '}' ) - break; - else + if( aSource[i] == '{' ) + { + braceDepth++; token.append( aSource[i] ); + } + else if( aSource[i] == '}' ) + { + braceDepth--; + if( braceDepth == 0 ) + break; // Found the matching closing brace + else + token.append( aSource[i] ); + } + else + { + token.append( aSource[i] ); + } } if( token.IsEmpty() ) continue; - if( ( aFlags & FOR_ERC_DRC ) == 0 && ( token.StartsWith( wxS( "ERC_WARNING" ) ) - || token.StartsWith( wxS( "ERC_ERROR" ) ) - || token.StartsWith( wxS( "DRC_WARNING" ) ) - || token.StartsWith( wxS( "DRC_ERROR" ) ) ) ) + // For math expressions @{...}, recursively expand any nested ${...} variables + // but DON'T evaluate the math - leave that for EvaluateText() called by the user + if( isMathExpr ) { - // Only show user-defined warnings/errors during ERC/DRC + if( ( token.Contains( wxT( "${" ) ) || token.Contains( wxT( "@{" ) ) ) && aDepth < maxDepth ) + { + token = ExpandTextVars( token, aResolver, aFlags, aDepth + 1 ); + } + + // Return the expression with variables expanded but NOT evaluated + // The caller will use EvaluateText() to handle the math evaluation + newbuf.append( wxT( "@{" ) + token + wxT( "}" ) ); } - else if( aResolver && (*aResolver)( &token ) ) + else // Variable reference ${...} { - newbuf.append( token ); - } - else - { - // Token not resolved: leave the reference unchanged - newbuf.append( "${" + token + "}" ); + // Recursively expand nested variables BEFORE passing to resolver + // This ensures innermost variables are expanded first (standard evaluation order) + if( ( token.Contains( wxT( "${" ) ) || token.Contains( wxT( "@{" ) ) ) && aDepth < maxDepth ) + { + token = ExpandTextVars( token, aResolver, aFlags, aDepth + 1 ); + + // Also evaluate math expressions after expanding variables + if( token.Contains( wxT( "@{" ) ) ) + { + static EXPRESSION_EVALUATOR evaluator; + token = evaluator.Evaluate( token ); + } + } + + if( ( aFlags & FOR_ERC_DRC ) == 0 + && ( token.StartsWith( wxS( "ERC_WARNING" ) ) || token.StartsWith( wxS( "ERC_ERROR" ) ) + || token.StartsWith( wxS( "DRC_WARNING" ) ) || token.StartsWith( wxS( "DRC_ERROR" ) ) ) ) + { + // Only show user-defined warnings/errors during ERC/DRC + } + else if( aResolver && ( *aResolver )( &token ) ) + { + newbuf.append( token ); + } + else + { + // Token not resolved: leave the reference unchanged + newbuf.append( "${" + token + "}" ); + } } } else @@ -117,18 +208,42 @@ wxString ExpandTextVars( const wxString& aSource, } } + // Don't convert markers back yet - they need to survive multi-pass loops + // The conversion happens in GetShownText() after all expansion is done return newbuf; } +wxString ResolveTextVars( const wxString& aSource, const std::function* aResolver, int& aDepth ) +{ + // Multi-pass resolution to handle nested variables like ${J601:UNIT(${ROW})} + // and math expressions like @{${ROW}-1} + wxString text = aSource; + const int maxDepth = ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth; + + static EXPRESSION_EVALUATOR evaluator; + + while( ( text.Contains( wxT( "${" ) ) || text.Contains( wxT( "@{" ) ) ) && ++aDepth <= maxDepth ) + { + text = ExpandTextVars( text, aResolver ); + text = evaluator.Evaluate( text ); // Evaluate math expressions + } + + // Final pass: convert escaped variables back to literals + text.Replace( wxT( "\x01ESC_DOLLAR{" ), wxT( "${" ) ); + text.Replace( wxT( "\x01ESC_AT{" ), wxT( "@{" ) ); + + return text; +} + + wxString GetGeneratedFieldDisplayName( const wxString& aSource ) { - std::function tokenExtractor = - [&]( wxString* token ) -> bool - { - *token = *token; // token value is the token name - return true; - }; + std::function tokenExtractor = [&]( wxString* token ) -> bool + { + *token = *token; // token value is the token name + return true; + }; return ExpandTextVars( aSource, &tokenExtractor ); } @@ -153,40 +268,38 @@ wxString DescribeRef( const wxString& aRef ) // // Stolen from wxExpandEnvVars and then heavily optimized // -wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, - std::set* aSet = nullptr ) +wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, std::set* aSet = nullptr ) { // If the same string is inserted twice, we have a loop if( aSet ) { - if( auto [ _, result ] = aSet->insert( str ); !result ) + if( auto [_, result] = aSet->insert( str ); !result ) return str; } size_t strlen = str.length(); wxString strResult; - strResult.Alloc( strlen ); // best guess (improves performance) + strResult.Alloc( strlen ); // best guess (improves performance) - auto getVersionedEnvVar = - []( const wxString& aMatch, wxString& aResult ) -> bool + auto getVersionedEnvVar = []( const wxString& aMatch, wxString& aResult ) -> bool + { + for( const wxString& var : ENV_VAR::GetPredefinedEnvVars() ) + { + if( var.Matches( aMatch ) ) { - for ( const wxString& var : ENV_VAR::GetPredefinedEnvVars() ) - { - if( var.Matches( aMatch ) ) - { - const auto value = ENV_VAR::GetEnvVar( var ); + const auto value = ENV_VAR::GetEnvVar( var ); - if( !value ) - continue; + if( !value ) + continue; - aResult += *value; - return true; - } - } + aResult += *value; + return true; + } + } - return false; - }; + return false; + }; for( size_t n = 0; n < strlen; n++ ) { @@ -207,28 +320,27 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, } else #endif // __WINDOWS__ - if( n == strlen - 1 ) - { - bracket = Bracket_None; - } - else - { - switch( str[n + 1].GetValue() ) + if( n == strlen - 1 ) { - case wxT( '(' ): - bracket = Bracket_Normal; - str_n = str[++n]; // skip the bracket - break; - - case wxT( '{' ): - bracket = Bracket_Curly; - str_n = str[++n]; // skip the bracket - break; - - default: bracket = Bracket_None; } - } + else + { + switch( str[n + 1].GetValue() ) + { + case wxT( '(' ): + bracket = Bracket_Normal; + str_n = str[++n]; // skip the bracket + break; + + case wxT( '{' ): + bracket = Bracket_Curly; + str_n = str[++n]; // skip the bracket + break; + + default: bracket = Bracket_None; + } + } size_t m = n + 1; @@ -252,7 +364,7 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, // NB: use wxGetEnv instead of wxGetenv as otherwise variables // set through wxSetEnv may not be read correctly! - bool expanded = false; + bool expanded = false; wxString tmp = strVarName; if( aProject && aProject->TextVarResolver( &tmp ) ) @@ -269,8 +381,7 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, // If the user has the older location defined, that will be matched // first above. But if they do not, this will ensure that their board still // displays correctly - else if( strVarName.Contains( "KISYS3DMOD") - || strVarName.Matches( "KICAD*_3DMODEL_DIR" ) ) + else if( strVarName.Contains( "KISYS3DMOD" ) || strVarName.Matches( "KICAD*_3DMODEL_DIR" ) ) { if( getVersionedEnvVar( "KICAD*_3DMODEL_DIR", strResult ) ) expanded = true; @@ -293,11 +404,11 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, else { // variable doesn't exist => don't change anything -#ifdef __WINDOWS__ - if ( bracket != Bracket_Windows ) +#ifdef __WINDOWS__ + if( bracket != Bracket_Windows ) #endif - if ( bracket != Bracket_None ) - strResult << str[n - 1]; + if( bracket != Bracket_None ) + strResult << str[n - 1]; strResult << str_n << strVarName; } @@ -305,7 +416,7 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, // check the closing bracket if( bracket != Bracket_None ) { - if( m == strlen || str_m != (wxChar)bracket ) + if( m == strlen || str_m != (wxChar) bracket ) { // under MSW it's common to have '%' characters in the registry // and it's annoying to have warnings about them each time, so @@ -316,27 +427,27 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, #ifndef __WINDOWS__ wxLogWarning( _( "Environment variables expansion failed: missing '%c' " "at position %u in '%s'." ), - (char)bracket, (unsigned int) (m + 1), str.c_str() ); + (char) bracket, (unsigned int) ( m + 1 ), str.c_str() ); #endif // __WINDOWS__ } else { // skip closing bracket unless the variables wasn't expanded if( !expanded ) - strResult << (wxChar)bracket; + strResult << (wxChar) bracket; m++; } } - n = m - 1; // skip variable name + n = m - 1; // skip variable name str_n = str[n]; } - break; + break; case wxT( '\\' ): // backslash can be used to suppress special meaning of % and $ - if( n < strlen - 1 && (str[n + 1] == wxT( '%' ) || str[n + 1] == wxT( '$' ) ) ) + if( n < strlen - 1 && ( str[n + 1] == wxT( '%' ) || str[n + 1] == wxT( '$' ) ) ) { str_n = str[++n]; strResult += str_n; @@ -346,14 +457,13 @@ wxString KIwxExpandEnvVars( const wxString& str, const PROJECT* aProject, KI_FALLTHROUGH; - default: - strResult += str_n; + default: strResult += str_n; } } std::set loop_check; - auto first_pos = strResult.find_first_of( wxS( "{(%" ) ); - auto last_pos = strResult.find_last_of( wxS( "})%" ) ); + auto first_pos = strResult.find_first_of( wxS( "{(%" ) ); + auto last_pos = strResult.find_last_of( wxS( "})%" ) ); if( first_pos != strResult.npos && last_pos != strResult.npos && first_pos != last_pos ) strResult = KIwxExpandEnvVars( strResult, aProject, aSet ? aSet : &loop_check ); @@ -383,9 +493,7 @@ const wxString ResolveUriByEnvVars( const wxString& aUri, const PROJECT* aProjec } -bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName, - const wxString& aBaseFilename, - REPORTER* aReporter ) +bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName, const wxString& aBaseFilename, REPORTER* aReporter ) { wxString msg; wxString baseFilePath = wxFileName( aBaseFilename ).GetPath(); @@ -396,8 +504,7 @@ bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName, { if( aReporter ) { - msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ), - aTargetFullFileName->GetPath(), + msg.Printf( _( "Cannot make path '%s' absolute with respect to '%s'." ), aTargetFullFileName->GetPath(), baseFilePath ); aReporter->Report( msg, RPT_SEVERITY_ERROR ); } @@ -493,15 +600,10 @@ bool matchWild( const char* pat, const char* text, bool dot_special ) return !*pat; } - const char *m = pat, - *n = text, - *ma = nullptr, - *na = nullptr; - int just = 0, - acount = 0, - count = 0; + const char *m = pat, *n = text, *ma = nullptr, *na = nullptr; + int just = 0, acount = 0, count = 0; - if( dot_special && (*n == '.') ) + if( dot_special && ( *n == '.' ) ) { /* Never match so that hidden Unix files * are never found. */ @@ -569,7 +671,7 @@ bool matchWild( const char* pat, const char* text, bool dot_special ) } else { - not_matched: + not_matched: /* * If there are no more characters in the @@ -654,8 +756,7 @@ long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec ) // Get the file size (partial) as well to check for sneaky changes. timestamp += findData.nFileSizeLow; - } - while ( FindNextFile( fileHandle, &findData ) != 0 ); + } while( FindNextFile( fileHandle, &findData ) != 0 ); } FindClose( fileHandle ); @@ -680,15 +781,15 @@ long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec ) if( wxCRT_Lstat( entry_path.c_str(), &entry_stat ) == 0 ) { // Timestamp the source file, not the symlink - if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK + if( S_ISLNK( entry_stat.st_mode ) ) // wxFILE_EXISTS_SYMLINK { - char buffer[ PATH_MAX + 1 ]; + char buffer[PATH_MAX + 1]; ssize_t pathLen = readlink( entry_path.c_str(), buffer, PATH_MAX ); if( pathLen > 0 ) { struct stat linked_stat; - buffer[ pathLen ] = '\0'; + buffer[pathLen] = '\0'; entry_path = dir_path + buffer; if( wxCRT_Lstat( entry_path.c_str(), &linked_stat ) == 0 ) @@ -703,7 +804,7 @@ long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec ) } } - if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists() + if( S_ISREG( entry_stat.st_mode ) ) // wxFileExists() { timestamp += entry_stat.st_mtime * 1000; @@ -731,10 +832,10 @@ bool WarnUserIfOperatingSystemUnsupported() if( !KIPLATFORM::APP::IsOperatingSystemUnsupported() ) return false; - wxMessageDialog dialog( nullptr, _( "This operating system is not supported " - "by KiCad and its dependencies." ), - _( "Unsupported Operating System" ), - wxOK | wxICON_EXCLAMATION ); + wxMessageDialog dialog( nullptr, + _( "This operating system is not supported " + "by KiCad and its dependencies." ), + _( "Unsupported Operating System" ), wxOK | wxICON_EXCLAMATION ); dialog.SetExtendedMessage( _( "Any issues with KiCad on this system cannot " "be reported to the official bugtracker." ) ); diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 752d764a11..6d51681703 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -22,27 +22,27 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include // for max -#include // for NULL -#include // for swap +#include // for max +#include // for NULL +#include // for swap #include #include #include #include #include -#include // for EDA_TEXT, TEXT_EFFECTS, GR_TEXT_VJUSTIF... -#include // for COLOR4D, COLOR4D::BLACK +#include // for EDA_TEXT, TEXT_EFFECTS, GR_TEXT_VJUSTIF... +#include // for COLOR4D, COLOR4D::BLACK #include #include -#include // for UnescapeString +#include // for UnescapeString #include -#include // for KiROUND +#include // for KiROUND #include #include #include #include -#include // for RotatePoint +#include // for RotatePoint #include #include #include @@ -55,9 +55,9 @@ #include #include -#include // for wxASSERT +#include // for wxASSERT #include -#include // for wxURL +#include // for wxURL #include #include "font/kicad_font_name.h" #include "font/fontconfig.h" @@ -117,7 +117,7 @@ EDA_TEXT::EDA_TEXT( const EDA_IU_SCALE& aIuScale, const wxString& aText ) : EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) : - m_IuScale( aText.m_IuScale ) + m_IuScale( aText.m_IuScale ) { m_text = aText.m_text; m_shown_text = aText.m_shown_text; @@ -195,7 +195,7 @@ EDA_TEXT& EDA_TEXT::operator=( const EDA_TEXT& aText ) } -void EDA_TEXT::Serialize( google::protobuf::Any &aContainer ) const +void EDA_TEXT::Serialize( google::protobuf::Any& aContainer ) const { using namespace kiapi::common; types::Text text; @@ -209,11 +209,9 @@ void EDA_TEXT::Serialize( google::protobuf::Any &aContainer ) const if( GetFont() ) attrs->set_font_name( GetFont()->GetName().ToStdString() ); - attrs->set_horizontal_alignment( - ToProtoEnum( GetHorizJustify() ) ); + attrs->set_horizontal_alignment( ToProtoEnum( GetHorizJustify() ) ); - attrs->set_vertical_alignment( - ToProtoEnum( GetVertJustify() ) ); + attrs->set_vertical_alignment( ToProtoEnum( GetVertJustify() ) ); attrs->mutable_angle()->set_value_degrees( GetTextAngleDegrees() ); attrs->set_line_spacing( GetLineSpacing() ); @@ -231,7 +229,7 @@ void EDA_TEXT::Serialize( google::protobuf::Any &aContainer ) const } -bool EDA_TEXT::Deserialize( const google::protobuf::Any &aContainer ) +bool EDA_TEXT::Deserialize( const google::protobuf::Any& aContainer ) { using namespace kiapi::common; types::Text text; @@ -257,9 +255,8 @@ bool EDA_TEXT::Deserialize( const google::protobuf::Any &aContainer ) if( !text.attributes().font_name().empty() ) { - attrs.m_Font = KIFONT::FONT::GetFont( - wxString( text.attributes().font_name().c_str(), wxConvUTF8 ), attrs.m_Bold, - attrs.m_Italic ); + attrs.m_Font = KIFONT::FONT::GetFont( wxString( text.attributes().font_name().c_str(), wxConvUTF8 ), + attrs.m_Bold, attrs.m_Italic ); } attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T ); @@ -268,8 +265,8 @@ bool EDA_TEXT::Deserialize( const google::protobuf::Any &aContainer ) attrs.m_Halign = FromProtoEnum( text.attributes().horizontal_alignment() ); - attrs.m_Valign = FromProtoEnum( - text.attributes().vertical_alignment() ); + attrs.m_Valign = + FromProtoEnum( text.attributes().vertical_alignment() ); SetAttributes( attrs ); } @@ -519,8 +516,7 @@ bool EDA_TEXT::ResolveFont( const std::vector* aEmbeddedFonts ) { if( !m_unresolvedFontName.IsEmpty() ) { - m_attributes.m_Font = KIFONT::FONT::GetFont( m_unresolvedFontName, IsBold(), IsItalic(), - aEmbeddedFonts ); + m_attributes.m_Font = KIFONT::FONT::GetFont( m_unresolvedFontName, IsBold(), IsItalic(), aEmbeddedFonts ); if( !m_render_cache.empty() ) m_render_cache_font = m_attributes.m_Font; @@ -553,8 +549,7 @@ void EDA_TEXT::SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize ) int min = m_IuScale.get().mmToIU( TEXT_MIN_SIZE_MM ); int max = m_IuScale.get().mmToIU( TEXT_MAX_SIZE_MM ); - aNewSize = VECTOR2I( std::clamp( aNewSize.x, min, max ), - std::clamp( aNewSize.y, min, max ) ); + aNewSize = VECTOR2I( std::clamp( aNewSize.x, min, max ), std::clamp( aNewSize.y, min, max ) ); } m_attributes.m_Size = aNewSize; @@ -641,7 +636,7 @@ void EDA_TEXT::cacheShownText() else { m_shown_text = UnescapeString( m_text ); - m_shown_text_has_text_var_refs = m_shown_text.Contains( wxT( "${" ) ); + m_shown_text_has_text_var_refs = m_shown_text.Contains( wxT( "${" ) ) || m_shown_text.Contains( wxT( "@{" ) ); } ClearRenderCache(); @@ -693,18 +688,14 @@ void EDA_TEXT::ClearBoundingBoxCache() std::vector>* -EDA_TEXT::GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolvedText, - const VECTOR2I& aOffset ) const +EDA_TEXT::GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolvedText, const VECTOR2I& aOffset ) const { if( aFont->IsOutline() ) { EDA_ANGLE resolvedAngle = GetDrawRotation(); - if( m_render_cache.empty() - || m_render_cache_font != aFont - || m_render_cache_text != forResolvedText - || m_render_cache_angle != resolvedAngle - || m_render_cache_offset != aOffset ) + if( m_render_cache.empty() || m_render_cache_font != aFont || m_render_cache_text != forResolvedText + || m_render_cache_angle != resolvedAngle || m_render_cache_offset != aOffset ) { m_render_cache.clear(); @@ -713,8 +704,7 @@ EDA_TEXT::GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolved attrs.m_Angle = resolvedAngle; - font->GetLinesAsGlyphs( &m_render_cache, forResolvedText, GetDrawPos() + aOffset, - attrs, getFontMetrics() ); + font->GetLinesAsGlyphs( &m_render_cache, forResolvedText, GetDrawPos() + aOffset, attrs, getFontMetrics() ); m_render_cache_font = aFont; m_render_cache_angle = resolvedAngle; m_render_cache_text = forResolvedText; @@ -728,8 +718,8 @@ EDA_TEXT::GetRenderCache( const KIFONT::FONT* aFont, const wxString& forResolved } -void EDA_TEXT::SetupRenderCache( const wxString& aResolvedText, const KIFONT::FONT* aFont, - const EDA_ANGLE& aAngle, const VECTOR2I& aOffset ) +void EDA_TEXT::SetupRenderCache( const wxString& aResolvedText, const KIFONT::FONT* aFont, const EDA_ANGLE& aAngle, + const VECTOR2I& aOffset ) { m_render_cache_text = aResolvedText; m_render_cache_font = aFont; @@ -758,22 +748,22 @@ BOX2I EDA_TEXT::GetTextBox( const RENDER_SETTINGS* aSettings, int aLine ) const { std::lock_guard bboxLock( m_bbox_cacheMutex ); - auto cache_it = m_bbox_cache.find( aLine ); + auto cache_it = m_bbox_cache.find( aLine ); if( cache_it != m_bbox_cache.end() && cache_it->second.m_pos == drawPos ) return cache_it->second.m_bbox; } - BOX2I bbox; - wxArrayString strings; - wxString text = GetShownText( true ); - int thickness = GetEffectiveTextPenWidth(); + BOX2I bbox; + wxArrayString strings; + wxString text = GetShownText( true ); + int thickness = GetEffectiveTextPenWidth(); if( IsMultilineAllowed() ) { wxStringSplit( text, strings, '\n' ); - if( strings.GetCount() ) // GetCount() == 0 for void strings with multilines allowed + if( strings.GetCount() ) // GetCount() == 0 for void strings with multilines allowed { if( aLine >= 0 && ( aLine < static_cast( strings.GetCount() ) ) ) text = strings.Item( aLine ); @@ -840,45 +830,35 @@ BOX2I EDA_TEXT::GetTextBox( const RENDER_SETTINGS* aSettings, int aLine ) const break; - case GR_TEXT_H_ALIGN_CENTER: - bbox.SetX( bbox.GetX() - ( bbox.GetWidth() - italicOffset ) / 2 ); - break; + case GR_TEXT_H_ALIGN_CENTER: bbox.SetX( bbox.GetX() - ( bbox.GetWidth() - italicOffset ) / 2 ); break; case GR_TEXT_H_ALIGN_RIGHT: if( !IsMirrored() ) bbox.SetX( bbox.GetX() - ( bbox.GetWidth() - italicOffset ) ); break; - case GR_TEXT_H_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } switch( GetVertJustify() ) { - case GR_TEXT_V_ALIGN_TOP: - bbox.Offset( 0, -fudgeFactor ); - break; + case GR_TEXT_V_ALIGN_TOP: bbox.Offset( 0, -fudgeFactor ); break; - case GR_TEXT_V_ALIGN_CENTER: - bbox.SetY( bbox.GetY() - bbox.GetHeight() / 2 ); - break; + case GR_TEXT_V_ALIGN_CENTER: bbox.SetY( bbox.GetY() - bbox.GetHeight() / 2 ); break; case GR_TEXT_V_ALIGN_BOTTOM: bbox.SetY( bbox.GetY() - bbox.GetHeight() ); bbox.Offset( 0, fudgeFactor ); break; - case GR_TEXT_V_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } - bbox.Normalize(); // Make h and v sizes always >= 0 + bbox.Normalize(); // Make h and v sizes always >= 0 { std::lock_guard bboxLock( m_bbox_cacheMutex ); - m_bbox_cache[ aLine ] = { drawPos, bbox }; + m_bbox_cache[aLine] = { drawPos, bbox }; } return bbox; @@ -909,7 +889,7 @@ void EDA_TEXT::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, if( IsMultilineAllowed() ) { std::vector positions; - wxArrayString strings; + wxArrayString strings; wxStringSplit( GetShownText( true ), strings, '\n' ); positions.reserve( strings.Count() ); @@ -929,10 +909,10 @@ void EDA_TEXT::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, void EDA_TEXT::GetLinePositions( const RENDER_SETTINGS* aSettings, std::vector& aPositions, int aLineCount ) const { - VECTOR2I pos = GetDrawPos(); // Position of first line of the multiline text according - // to the center of the multiline text block + VECTOR2I pos = GetDrawPos(); // Position of first line of the multiline text according + // to the center of the multiline text block - VECTOR2I offset; // Offset to next line. + VECTOR2I offset; // Offset to next line. offset.y = GetInterline( aSettings ); @@ -940,20 +920,13 @@ void EDA_TEXT::GetLinePositions( const RENDER_SETTINGS* aSettings, std::vectorGetPrintDC(); int penWidth = GetEffectiveTextPenWidth( aSettings->GetDefaultPenWidth() ); @@ -984,8 +957,8 @@ void EDA_TEXT::printOneLineOfText( const RENDER_SETTINGS* aSettings, const VECTO KIFONT::FONT* font = GetDrawFont( aSettings ); - GRPrintText( DC, aOffset + aPos, aColor, aText, GetDrawRotation(), size, GetHorizJustify(), - GetVertJustify(), penWidth, IsItalic(), IsBold(), font, getFontMetrics() ); + GRPrintText( DC, aOffset + aPos, aColor, aText, GetDrawRotation(), size, GetHorizJustify(), GetVertJustify(), + penWidth, IsItalic(), IsBold(), font, getFontMetrics() ); } @@ -999,12 +972,7 @@ wxString EDA_TEXT::GetTextStyleName() const if( IsBold() ) style += 2; - wxString stylemsg[4] = { - _("Normal"), - _("Italic"), - _("Bold"), - _("Bold+Italic") - }; + wxString stylemsg[4] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold+Italic" ) }; return stylemsg[style]; } @@ -1052,15 +1020,8 @@ void EDA_TEXT::SetFontProp( const wxString& aFontName ) bool EDA_TEXT::IsDefaultFormatting() const { - return ( !IsMirrored() - && GetHorizJustify() == GR_TEXT_H_ALIGN_CENTER - && GetVertJustify() == GR_TEXT_V_ALIGN_CENTER - && GetAutoThickness() - && !IsItalic() - && !IsBold() - && !IsMultilineAllowed() - && GetFontName().IsEmpty() - ); + return ( !IsMirrored() && GetHorizJustify() == GR_TEXT_H_ALIGN_CENTER && GetVertJustify() == GR_TEXT_V_ALIGN_CENTER + && GetAutoThickness() && !IsItalic() && !IsBold() && !IsMultilineAllowed() && GetFontName().IsEmpty() ); } @@ -1074,20 +1035,18 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aControlBits ) const aFormatter->Print( "(face %s)", aFormatter->Quotew( GetFont()->NameAsToken() ).c_str() ); // Text size - aFormatter->Print( "(size %s %s)", - EDA_UNIT_UTILS::FormatInternalUnits( m_IuScale, GetTextHeight() ).c_str(), + aFormatter->Print( "(size %s %s)", EDA_UNIT_UTILS::FormatInternalUnits( m_IuScale, GetTextHeight() ).c_str(), EDA_UNIT_UTILS::FormatInternalUnits( m_IuScale, GetTextWidth() ).c_str() ); if( GetLineSpacing() != 1.0 ) { - aFormatter->Print( "(line_spacing %s)", - FormatDouble2Str( GetLineSpacing() ).c_str() ); + aFormatter->Print( "(line_spacing %s)", FormatDouble2Str( GetLineSpacing() ).c_str() ); } if( !GetAutoThickness() ) { aFormatter->Print( "(thickness %s)", - EDA_UNIT_UTILS::FormatInternalUnits( m_IuScale, GetTextThickness() ).c_str() ); + EDA_UNIT_UTILS::FormatInternalUnits( m_IuScale, GetTextThickness() ).c_str() ); } if( IsBold() ) @@ -1098,19 +1057,16 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aControlBits ) const if( !( aControlBits & CTL_OMIT_COLOR ) && GetTextColor() != COLOR4D::UNSPECIFIED ) { - aFormatter->Print( "(color %d %d %d %s)", - KiROUND( GetTextColor().r * 255.0 ), - KiROUND( GetTextColor().g * 255.0 ), - KiROUND( GetTextColor().b * 255.0 ), + aFormatter->Print( "(color %d %d %d %s)", KiROUND( GetTextColor().r * 255.0 ), + KiROUND( GetTextColor().g * 255.0 ), KiROUND( GetTextColor().b * 255.0 ), FormatDouble2Str( GetTextColor().a ).c_str() ); } - aFormatter->Print( ")"); // (font + aFormatter->Print( ")" ); // (font - if( IsMirrored() || GetHorizJustify() != GR_TEXT_H_ALIGN_CENTER - || GetVertJustify() != GR_TEXT_V_ALIGN_CENTER ) + if( IsMirrored() || GetHorizJustify() != GR_TEXT_H_ALIGN_CENTER || GetVertJustify() != GR_TEXT_V_ALIGN_CENTER ) { - aFormatter->Print( "(justify"); + aFormatter->Print( "(justify" ); if( GetHorizJustify() != GR_TEXT_H_ALIGN_CENTER ) aFormatter->Print( GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT ? " left" : " right" ); @@ -1131,8 +1087,7 @@ void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aControlBits ) const } -std::shared_ptr EDA_TEXT::GetEffectiveTextShape( bool aTriangulate, - const BOX2I& aBBox, +std::shared_ptr EDA_TEXT::GetEffectiveTextShape( bool aTriangulate, const BOX2I& aBBox, const EDA_ANGLE& aAngle ) const { std::shared_ptr shape = std::make_shared(); @@ -1241,7 +1196,7 @@ bool EDA_TEXT::ValidateHyperlink( const wxString& aURL ) wxURI uri; - return( uri.Create( aURL ) && uri.HasScheme() ); + return ( uri.Create( aURL ) && uri.HasScheme() ); } double EDA_TEXT::Levenshtein( const EDA_TEXT& aOther ) const @@ -1257,7 +1212,7 @@ double EDA_TEXT::Levenshtein( const EDA_TEXT& aOther ) const return 0.0; // Create a matrix to store the distance values - std::vector> distance(m + 1, std::vector(n + 1)); + std::vector> distance( m + 1, std::vector( n + 1 ) ); // Initialize the matrix for( int i = 0; i <= m; i++ ) @@ -1276,8 +1231,7 @@ double EDA_TEXT::Levenshtein( const EDA_TEXT& aOther ) const } else { - distance[i][j] = std::min( { distance[i - 1][j], distance[i][j - 1], - distance[i - 1][j - 1] } ) + 1; + distance[i][j] = std::min( { distance[i - 1][j], distance[i][j - 1], distance[i - 1][j - 1] } ) + 1; } } } @@ -1335,18 +1289,18 @@ static struct EDA_TEXT_DESC // places leads to duplicate symbols. auto& h_inst = ENUM_MAP::Instance(); - if( h_inst.Choices().GetCount() == 0) + if( h_inst.Choices().GetCount() == 0 ) { - h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) ); + h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) ); h_inst.Map( GR_TEXT_H_ALIGN_CENTER, _HKI( "Center" ) ); - h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) ); + h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) ); } auto& v_inst = ENUM_MAP::Instance(); - if( v_inst.Choices().GetCount() == 0) + if( v_inst.Choices().GetCount() == 0 ) { - v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) ); + v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) ); v_inst.Map( GR_TEXT_V_ALIGN_CENTER, _HKI( "Center" ) ); v_inst.Map( GR_TEXT_V_ALIGN_BOTTOM, _HKI( "Bottom" ) ); } @@ -1354,97 +1308,93 @@ static struct EDA_TEXT_DESC PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); REGISTER_TYPE( EDA_TEXT ); - propMgr.AddProperty( new PROPERTY( _HKI( "Orientation" ), - &EDA_TEXT::SetTextAngleDegrees, &EDA_TEXT::GetTextAngleDegrees, - PROPERTY_DISPLAY::PT_DEGREE ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Orientation" ), &EDA_TEXT::SetTextAngleDegrees, + &EDA_TEXT::GetTextAngleDegrees, + PROPERTY_DISPLAY::PT_DEGREE ) ); const wxString textProps = _HKI( "Text Properties" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Text" ), - &EDA_TEXT::SetText, &EDA_TEXT::GetText ), + propMgr.AddProperty( new PROPERTY( _HKI( "Text" ), &EDA_TEXT::SetText, &EDA_TEXT::GetText ), + textProps ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Font" ), &EDA_TEXT::SetFontProp, + &EDA_TEXT::GetFontProp ), + textProps ) + .SetIsHiddenFromRulesEditor() + .SetChoicesFunc( + []( INSPECTABLE* aItem ) + { + EDA_ITEM* eda_item = static_cast( aItem ); + wxPGChoices fonts; + std::vector fontNames; + + Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ), + eda_item->GetEmbeddedFonts() ); + + if( IsEeschemaType( eda_item->Type() ) ) + fonts.Add( _( "Default Font" ) ); + + fonts.Add( KICAD_FONT_NAME ); + + for( const std::string& fontName : fontNames ) + fonts.Add( wxString( fontName ) ); + + return fonts; + } ); + + propMgr.AddProperty( new PROPERTY( _HKI( "Auto Thickness" ), &EDA_TEXT::SetAutoThickness, + &EDA_TEXT::GetAutoThickness ), + textProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Thickness" ), &EDA_TEXT::SetTextThickness, + &EDA_TEXT::GetTextThicknessProperty, + PROPERTY_DISPLAY::PT_SIZE ), + textProps ); + propMgr.AddProperty( + new PROPERTY( _HKI( "Italic" ), &EDA_TEXT::SetItalic, &EDA_TEXT::IsItalic ), + textProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Bold" ), &EDA_TEXT::SetBold, &EDA_TEXT::IsBold ), + textProps ); + propMgr.AddProperty( + new PROPERTY( _HKI( "Mirrored" ), &EDA_TEXT::SetMirrored, &EDA_TEXT::IsMirrored ), textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Font" ), - &EDA_TEXT::SetFontProp, &EDA_TEXT::GetFontProp ), - textProps ) - .SetIsHiddenFromRulesEditor() - .SetChoicesFunc( []( INSPECTABLE* aItem ) - { - EDA_ITEM* eda_item = static_cast( aItem ); - wxPGChoices fonts; - std::vector fontNames; + auto isField = []( INSPECTABLE* aItem ) -> bool + { + if( EDA_ITEM* item = dynamic_cast( aItem ) ) + return item->Type() == SCH_FIELD_T || item->Type() == PCB_FIELD_T; - Fontconfig()->ListFonts( fontNames, - std::string( Pgm().GetLanguageTag().utf8_str() ), - eda_item->GetEmbeddedFonts() ); + return false; + }; - if( IsEeschemaType( eda_item->Type() ) ) - fonts.Add( _( "Default Font" ) ); + propMgr.AddProperty( + new PROPERTY( _HKI( "Visible" ), &EDA_TEXT::SetVisible, &EDA_TEXT::IsVisible ), + textProps ) + .SetAvailableFunc( isField ); - fonts.Add( KICAD_FONT_NAME ); + propMgr.AddProperty( new PROPERTY( _HKI( "Width" ), &EDA_TEXT::SetTextWidth, + &EDA_TEXT::GetTextWidth, PROPERTY_DISPLAY::PT_SIZE ), + textProps ); - for( const std::string& fontName : fontNames ) - fonts.Add( wxString( fontName ) ); - - return fonts; - } ); - - propMgr.AddProperty( new PROPERTY( _HKI( "Auto Thickness" ), - &EDA_TEXT::SetAutoThickness, &EDA_TEXT::GetAutoThickness ), - textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Thickness" ), - &EDA_TEXT::SetTextThickness, &EDA_TEXT::GetTextThicknessProperty, - PROPERTY_DISPLAY::PT_SIZE ), - textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Italic" ), - &EDA_TEXT::SetItalic, - &EDA_TEXT::IsItalic ), - textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Bold" ), - &EDA_TEXT::SetBold, &EDA_TEXT::IsBold ), - textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Mirrored" ), - &EDA_TEXT::SetMirrored, &EDA_TEXT::IsMirrored ), - textProps ); - - auto isField = - []( INSPECTABLE* aItem ) -> bool - { - if( EDA_ITEM* item = dynamic_cast( aItem ) ) - return item->Type() == SCH_FIELD_T || item->Type() == PCB_FIELD_T; - - return false; - }; - - propMgr.AddProperty( new PROPERTY( _HKI( "Visible" ), - &EDA_TEXT::SetVisible, &EDA_TEXT::IsVisible ), - textProps ) - .SetAvailableFunc( isField ); - - propMgr.AddProperty( new PROPERTY( _HKI( "Width" ), - &EDA_TEXT::SetTextWidth, &EDA_TEXT::GetTextWidth, - PROPERTY_DISPLAY::PT_SIZE ), - textProps ); - - propMgr.AddProperty( new PROPERTY( _HKI( "Height" ), - &EDA_TEXT::SetTextHeight, &EDA_TEXT::GetTextHeight, - PROPERTY_DISPLAY::PT_SIZE ), - textProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Height" ), &EDA_TEXT::SetTextHeight, + &EDA_TEXT::GetTextHeight, PROPERTY_DISPLAY::PT_SIZE ), + textProps ); propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Horizontal Justification" ), - &EDA_TEXT::SetHorizJustify, &EDA_TEXT::GetHorizJustify ), - textProps ); + &EDA_TEXT::SetHorizJustify, + &EDA_TEXT::GetHorizJustify ), + textProps ); propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Vertical Justification" ), - &EDA_TEXT::SetVertJustify, &EDA_TEXT::GetVertJustify ), + &EDA_TEXT::SetVertJustify, + &EDA_TEXT::GetVertJustify ), + textProps ); + + propMgr.AddProperty( + new PROPERTY( _HKI( "Color" ), &EDA_TEXT::SetTextColor, &EDA_TEXT::GetTextColor ), textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Color" ), - &EDA_TEXT::SetTextColor, &EDA_TEXT::GetTextColor ), - textProps ); - - propMgr.AddProperty( new PROPERTY( _HKI( "Hyperlink" ), - &EDA_TEXT::SetHyperlink, &EDA_TEXT::GetHyperlink ), - textProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Hyperlink" ), &EDA_TEXT::SetHyperlink, + &EDA_TEXT::GetHyperlink ), + textProps ); } } _EDA_TEXT_DESC; diff --git a/common/text_eval/text_eval_parser.cpp b/common/text_eval/text_eval_parser.cpp index 67fcbe977c..8dc18eafed 100644 --- a/common/text_eval/text_eval_parser.cpp +++ b/common/text_eval/text_eval_parser.cpp @@ -30,29 +30,22 @@ thread_local ERROR_COLLECTOR* g_errorCollector = nullptr; class DATE_UTILS { private: - static constexpr int epochYear = 1970; - static constexpr std::array daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - static constexpr std::array monthNames = { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" - }; - static constexpr std::array monthAbbrev = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" - }; - static constexpr std::array weekdayNames = { - "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" - }; + static constexpr int epochYear = 1970; + static constexpr std::array daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + static constexpr std::array monthNames = { "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" }; + static constexpr std::array monthAbbrev = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static constexpr std::array weekdayNames = { "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; static auto isLeapYear( int aYear ) -> bool { return ( aYear % 4 == 0 && aYear % 100 != 0 ) || ( aYear % 400 == 0 ); } - static auto daysInYear( int aYear ) -> int - { - return isLeapYear( aYear ) ? 366 : 365; - } + static auto daysInYear( int aYear ) -> int { return isLeapYear( aYear ) ? 366 : 365; } static auto daysInMonthForYear( int aMonth, int aYear ) -> int { @@ -93,7 +86,7 @@ public: } int day = remainingDays + 1; - return {year, month, day}; + return { year, month, day }; } static auto YmdToDays( int aYear, int aMonth, int aDay ) -> int @@ -121,8 +114,8 @@ public: static auto ParseDate( const std::string& aDateStr ) -> std::optional { std::istringstream iss( aDateStr ); - std::string token; - std::vector parts; + std::string token; + std::vector parts; char separator = 0; bool isCjkFormat = false; @@ -136,9 +129,8 @@ public: bool hasKoreanDay = aDateStr.find( "일" ) != std::string::npos; // Check if we have any CJK date format (pure or mixed) - if( (hasChineseYear || hasKoreanYear) && - (hasChineseMonth || hasKoreanMonth) && - (hasChineseDay || hasKoreanDay) ) + if( ( hasChineseYear || hasKoreanYear ) && ( hasChineseMonth || hasKoreanMonth ) + && ( hasChineseDay || hasKoreanDay ) ) { // CJK format: Support pure Chinese, pure Korean, or mixed formats isCjkFormat = true; @@ -166,8 +158,10 @@ public: try { int year = std::stoi( aDateStr.substr( 0, yearPos ) ); - int month = std::stoi( aDateStr.substr( yearPos + 3, monthPos - yearPos - 3 ) ); // 3 bytes for CJK year marker - int day = std::stoi( aDateStr.substr( monthPos + 3, dayPos - monthPos - 3 ) ); // 3 bytes for CJK month marker + int month = std::stoi( + aDateStr.substr( yearPos + 3, monthPos - yearPos - 3 ) ); // 3 bytes for CJK year marker + int day = std::stoi( + aDateStr.substr( monthPos + 3, dayPos - monthPos - 3 ) ); // 3 bytes for CJK month marker parts = { year, month, day }; } @@ -282,14 +276,17 @@ public: else if( aFormat == "EU" || aFormat == "european" ) return fmt::format( "{:02d}/{:02d}/{:04d}", day, month, year ); else if( aFormat == "long" ) - return fmt::format( "{} {}, {}", monthNames[month-1], day, year ); + return fmt::format( "{} {}, {}", monthNames[month - 1], day, year ); else if( aFormat == "short" ) - return fmt::format( "{} {}, {}", monthAbbrev[month-1], day, year ); - else if( aFormat == "Chinese" || aFormat == "chinese" || aFormat == "CN" || aFormat == "cn" || aFormat == "中文" ) + return fmt::format( "{} {}, {}", monthAbbrev[month - 1], day, year ); + else if( aFormat == "Chinese" || aFormat == "chinese" || aFormat == "CN" || aFormat == "cn" + || aFormat == "中文" ) return fmt::format( "{}年{:02d}月{:02d}日", year, month, day ); - else if( aFormat == "Japanese" || aFormat == "japanese" || aFormat == "JP" || aFormat == "jp" || aFormat == "日本語" ) + else if( aFormat == "Japanese" || aFormat == "japanese" || aFormat == "JP" || aFormat == "jp" + || aFormat == "日本語" ) return fmt::format( "{}年{:02d}月{:02d}日", year, month, day ); - else if( aFormat == "Korean" || aFormat == "korean" || aFormat == "KR" || aFormat == "kr" || aFormat == "한국어" ) + else if( aFormat == "Korean" || aFormat == "korean" || aFormat == "KR" || aFormat == "kr" + || aFormat == "한국어" ) return fmt::format( "{}년 {:02d}월 {:02d}일", year, month, day ); else return fmt::format( "{:04d}-{:02d}-{:02d}", year, month, day ); @@ -324,338 +321,346 @@ EVAL_VISITOR::EVAL_VISITOR( VariableCallback aVariableCallback, ERROR_COLLECTOR& m_variableCallback( std::move( aVariableCallback ) ), m_errors( aErrorCollector ), m_gen( m_rd() ) -{} +{ +} auto EVAL_VISITOR::operator()( const NODE& aNode ) const -> Result +{ + switch( aNode.type ) { - switch( aNode.type ) + case NodeType::Number: return MakeValue( std::get( aNode.data ) ); + + case NodeType::String: return MakeValue( std::get( aNode.data ) ); + + case NodeType::Var: + { + const auto& varName = std::get( aNode.data ); + + // Use callback to resolve variable + if( m_variableCallback ) + return m_variableCallback( varName ); + + return MakeError( fmt::format( "No variable resolver configured for: {}", varName ) ); + } + + case NodeType::BinOp: + { + const auto& binop = std::get( aNode.data ); + auto leftResult = binop.left->Accept( *this ); + if( !leftResult ) + return leftResult; + + auto rightResult = binop.right ? binop.right->Accept( *this ) : MakeValue( 0.0 ); + if( !rightResult ) + return rightResult; + + // Special handling for string concatenation with + + if( binop.op == '+' ) { - case NodeType::Number: - return MakeValue( std::get( aNode.data ) ); + const auto& leftVal = leftResult.GetValue(); + const auto& rightVal = rightResult.GetValue(); - case NodeType::String: - return MakeValue( std::get( aNode.data ) ); - - case NodeType::Var: - { - const auto& varName = std::get( aNode.data ); - - // Use callback to resolve variable - if( m_variableCallback ) - return m_variableCallback( varName ); - - return MakeError( fmt::format( "No variable resolver configured for: {}", varName ) ); - } - - case NodeType::BinOp: - { - const auto& binop = std::get( aNode.data ); - auto leftResult = binop.left->Accept( *this ); - if( !leftResult ) - return leftResult; - - auto rightResult = binop.right ? - binop.right->Accept( *this ) : MakeValue( 0.0 ); - if( !rightResult ) - return rightResult; - - // Special handling for string concatenation with + - if( binop.op == '+' ) + // If either operand is a string, concatenate + if( std::holds_alternative( leftVal ) || std::holds_alternative( rightVal ) ) { - const auto& leftVal = leftResult.GetValue(); - const auto& rightVal = rightResult.GetValue(); - - // If either operand is a string, concatenate - if( std::holds_alternative( leftVal ) || - std::holds_alternative( rightVal ) ) - { - return MakeValue( VALUE_UTILS::ConcatStrings( leftVal, rightVal ) ); - } + return MakeValue( VALUE_UTILS::ConcatStrings( leftVal, rightVal ) ); } - - // Otherwise, perform arithmetic - return VALUE_UTILS::ArithmeticOp( leftResult.GetValue(), rightResult.GetValue(), binop.op ); } - case NodeType::Function: + // Special handling for string comparisons with == and != + if( binop.op == 3 || binop.op == 4 ) // == or != { - const auto& func = std::get( aNode.data ); - return evaluateFunction( func ); + const auto& leftVal = leftResult.GetValue(); + const auto& rightVal = rightResult.GetValue(); + + // If both operands are strings, do string comparison + if( std::holds_alternative( leftVal ) && std::holds_alternative( rightVal ) ) + { + bool equal = std::get( leftVal ) == std::get( rightVal ); + double result = ( binop.op == 3 ) ? ( equal ? 1.0 : 0.0 ) : ( equal ? 0.0 : 1.0 ); + return MakeValue( result ); + } } - default: - return MakeError( "Cannot evaluate this node type" ); - } + // Otherwise, perform arithmetic + return VALUE_UTILS::ArithmeticOp( leftResult.GetValue(), rightResult.GetValue(), binop.op ); + } + + case NodeType::Function: + { + const auto& func = std::get( aNode.data ); + return evaluateFunction( func ); + } + + default: return MakeError( "Cannot evaluate this node type" ); + } } auto EVAL_VISITOR::evaluateFunction( const FUNC_DATA& aFunc ) const -> Result { - const auto& name = aFunc.name; - const auto& args = aFunc.args; + const auto& name = aFunc.name; + const auto& args = aFunc.args; - // Zero-argument functions - if( args.empty() ) + // Zero-argument functions + if( args.empty() ) + { + if( name == "today" ) + return MakeValue( static_cast( DATE_UTILS::GetCurrentDays() ) ); + else if( name == "now" ) + return MakeValue( DATE_UTILS::GetCurrentTimestamp() ); + else if( name == "random" ) { - if( name == "today" ) - return MakeValue( static_cast( DATE_UTILS::GetCurrentDays() ) ); - else if( name == "now" ) - return MakeValue( DATE_UTILS::GetCurrentTimestamp() ); - else if( name == "random" ) - { - std::uniform_real_distribution dis( 0.0, 1.0 ); - return MakeValue( dis( m_gen ) ); - } + std::uniform_real_distribution dis( 0.0, 1.0 ); + return MakeValue( dis( m_gen ) ); + } + } + + // Evaluate arguments to mixed types + std::vector argValues; + argValues.reserve( args.size() ); + + for( const auto& arg : args ) + { + auto result = arg->Accept( *this ); + if( !result ) + return result; + + argValues.push_back( result.GetValue() ); + } + + const auto argc = argValues.size(); + + // String formatting functions (return strings!) + if( name == "format" && argc >= 1 ) + { + auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !numResult ) + return MakeError( numResult.GetError() ); + + const auto value = numResult.GetValue(); + int decimals = 2; + if( argc > 1 ) + { + auto decResult = VALUE_UTILS::ToDouble( argValues[1] ); + if( decResult ) + decimals = static_cast( decResult.GetValue() ); } - // Evaluate arguments to mixed types - std::vector argValues; - argValues.reserve( args.size() ); + return MakeValue( fmt::format( "{:.{}f}", value, decimals ) ); + } + else if( name == "currency" && argc >= 1 ) + { + auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !numResult ) + return MakeError( numResult.GetError() ); - for( const auto& arg : args ) + const auto amount = numResult.GetValue(); + const auto symbol = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "$"; + + return MakeValue( fmt::format( "{}{:.2f}", symbol, amount ) ); + } + else if( name == "fixed" && argc >= 1 ) + { + auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !numResult ) + return MakeError( numResult.GetError() ); + + const auto value = numResult.GetValue(); + int decimals = 2; + if( argc > 1 ) { - auto result = arg->Accept( *this ); - if( !result ) - return result; - - argValues.push_back( result.GetValue() ); + auto decResult = VALUE_UTILS::ToDouble( argValues[1] ); + if( decResult ) + decimals = static_cast( decResult.GetValue() ); } - const auto argc = argValues.size(); + return MakeValue( fmt::format( "{:.{}f}", value, decimals ) ); + } - // String formatting functions (return strings!) - if( name == "format" && argc >= 1 ) - { - auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !numResult ) - return MakeError( numResult.GetError() ); + // Date formatting functions (return strings!) + else if( name == "dateformat" && argc >= 1 ) + { + auto dateResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !dateResult ) + return MakeError( dateResult.GetError() ); - const auto value = numResult.GetValue(); - int decimals = 2; - if( argc > 1 ) - { - auto decResult = VALUE_UTILS::ToDouble( argValues[1] ); - if( decResult ) - decimals = static_cast( decResult.GetValue() ); - } + const auto days = static_cast( dateResult.GetValue() ); + const auto format = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "ISO"; - return MakeValue( fmt::format( "{:.{}f}", value, decimals ) ); - } - else if( name == "currency" && argc >= 1 ) - { - auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !numResult ) - return MakeError( numResult.GetError() ); + return MakeValue( DATE_UTILS::FormatDate( days, format ) ); + } + else if( name == "datestring" && argc == 1 ) + { + auto dateStr = VALUE_UTILS::ToString( argValues[0] ); + auto daysResult = DATE_UTILS::ParseDate( dateStr ); - const auto amount = numResult.GetValue(); - const auto symbol = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "$"; + if( !daysResult ) + return MakeError( "Invalid date format: " + dateStr ); - return MakeValue( fmt::format( "{}{:.2f}", symbol, amount ) ); - } - else if( name == "fixed" && argc >= 1 ) - { - auto numResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !numResult ) - return MakeError( numResult.GetError() ); + return MakeValue( static_cast( daysResult.value() ) ); + } + else if( name == "weekdayname" && argc == 1 ) + { + auto dateResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !dateResult ) + return MakeError( dateResult.GetError() ); - const auto value = numResult.GetValue(); - int decimals = 2; - if( argc > 1 ) - { - auto decResult = VALUE_UTILS::ToDouble( argValues[1] ); - if( decResult ) - decimals = static_cast( decResult.GetValue() ); - } + const auto days = static_cast( dateResult.GetValue() ); + return MakeValue( DATE_UTILS::GetWeekdayName( days ) ); + } - return MakeValue( fmt::format( "{:.{}f}", value, decimals ) ); - } - - // Date formatting functions (return strings!) - else if( name == "dateformat" && argc >= 1 ) - { - auto dateResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !dateResult ) - return MakeError( dateResult.GetError() ); - - const auto days = static_cast( dateResult.GetValue() ); - const auto format = argc > 1 ? VALUE_UTILS::ToString( argValues[1] ) : "ISO"; - - return MakeValue( DATE_UTILS::FormatDate( days, format ) ); - } - else if( name == "datestring" && argc == 1 ) - { - auto dateStr = VALUE_UTILS::ToString( argValues[0] ); - auto daysResult = DATE_UTILS::ParseDate( dateStr ); - - if( !daysResult ) - return MakeError( "Invalid date format: " + dateStr ); - - return MakeValue( static_cast( daysResult.value() ) ); - } - else if( name == "weekdayname" && argc == 1 ) - { - auto dateResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !dateResult ) - return MakeError( dateResult.GetError() ); - - const auto days = static_cast( dateResult.GetValue() ); - return MakeValue( DATE_UTILS::GetWeekdayName( days ) ); - } - - // String functions (return strings!) - else if( name == "upper" && argc == 1 ) - { - auto str = VALUE_UTILS::ToString( argValues[0] ); - std::transform( str.begin(), str.end(), str.begin(), ::toupper ); - return MakeValue( str ); - } - else if( name == "lower" && argc == 1 ) - { - auto str = VALUE_UTILS::ToString( argValues[0] ); - std::transform( str.begin(), str.end(), str.begin(), ::tolower ); - return MakeValue( str ); - } - else if( name == "concat" && argc >= 2 ) - { - std::string result; - for( const auto& val : argValues ) - result += VALUE_UTILS::ToString( val ); - - return MakeValue( result ); - } - else if( name == "beforefirst" && argc == 2 ) - { - wxString result = VALUE_UTILS::ToString( argValues[0] ); - - result = result.BeforeFirst( VALUE_UTILS::ToChar( argValues[1] ) ); - return MakeValue( result.ToStdString() ); - } - else if( name == "beforelast" && argc == 2 ) - { - wxString result = VALUE_UTILS::ToString( argValues[0] ); - - result = result.BeforeLast( VALUE_UTILS::ToChar( argValues[1] ) ); - return MakeValue( result.ToStdString() ); - } - else if( name == "afterfirst" && argc == 2 ) - { - wxString result = VALUE_UTILS::ToString( argValues[0] ); - - result = result.AfterFirst( VALUE_UTILS::ToChar( argValues[1] ) ); - return MakeValue( result.ToStdString() ); - } - else if( name == "afterlast" && argc == 2 ) - { - wxString result = VALUE_UTILS::ToString( argValues[0] ); - - result = result.AfterLast( VALUE_UTILS::ToChar( argValues[1] ) ); - return MakeValue( result.ToStdString() ); - } - - // Conditional functions (handle mixed types) - if( name == "if" && argc == 3 ) - { - // Convert only the condition to a number - auto conditionResult = VALUE_UTILS::ToDouble( argValues[0] ); - if( !conditionResult ) - return MakeError( conditionResult.GetError() ); - - const auto condition = conditionResult.GetValue() != 0.0; - return MakeValue( condition ? argValues[1] : argValues[2] ); - } - - // Mathematical functions (return numbers) - convert args to doubles first - std::vector numArgs; - for( const auto& val : argValues ) - { - auto numResult = VALUE_UTILS::ToDouble( val ); - if( !numResult ) - return MakeError( numResult.GetError() ); - - numArgs.push_back( numResult.GetValue() ); - } - - // Mathematical function implementations - if( name == "abs" && argc == 1 ) - return MakeValue( std::abs( numArgs[0] ) ); - else if( name == "sum" && argc >= 1 ) - return MakeValue( std::accumulate( numArgs.begin(), numArgs.end(), 0.0 ) ); - else if( name == "round" && argc >= 1 ) - { - const auto value = numArgs[0]; - const auto precision = argc > 1 ? static_cast( numArgs[1] ) : 0; - const auto multiplier = std::pow( 10.0, precision ); - return MakeValue( std::round( value * multiplier ) / multiplier ); - } - else if( name == "sqrt" && argc == 1 ) - { - if( numArgs[0] < 0 ) - return MakeError( "Square root of negative number" ); - - return MakeValue( std::sqrt( numArgs[0] ) ); - } - else if( name == "pow" && argc == 2 ) - return MakeValue( std::pow( numArgs[0], numArgs[1] ) ); - else if( name == "floor" && argc == 1 ) - return MakeValue( std::floor( numArgs[0] ) ); - else if( name == "ceil" && argc == 1 ) - return MakeValue( std::ceil( numArgs[0] ) ); - else if( name == "min" && argc >= 1 ) - return MakeValue( *std::min_element( numArgs.begin(), numArgs.end() ) ); - else if( name == "max" && argc >= 1 ) - return MakeValue( *std::max_element( numArgs.begin(), numArgs.end() ) ); - else if( name == "avg" && argc >= 1 ) - { - const auto sum = std::accumulate( numArgs.begin(), numArgs.end(), 0.0 ); - return MakeValue( sum / static_cast( argc ) ); - } - - return MakeError( fmt::format( "Unknown function: {} with {} arguments", name, argc ) ); -} - -auto DOC_PROCESSOR::Process( const DOC& aDoc, VariableCallback aVariableCallback ) - -> std::pair + // String functions (return strings!) + else if( name == "upper" && argc == 1 ) + { + auto str = VALUE_UTILS::ToString( argValues[0] ); + std::transform( str.begin(), str.end(), str.begin(), ::toupper ); + return MakeValue( str ); + } + else if( name == "lower" && argc == 1 ) + { + auto str = VALUE_UTILS::ToString( argValues[0] ); + std::transform( str.begin(), str.end(), str.begin(), ::tolower ); + return MakeValue( str ); + } + else if( name == "concat" && argc >= 2 ) { std::string result; - auto localErrors = ERROR_COLLECTOR{}; - EVAL_VISITOR evaluator{ std::move( aVariableCallback ), localErrors }; - bool hadErrors = aDoc.HasErrors(); + for( const auto& val : argValues ) + result += VALUE_UTILS::ToString( val ); - for( const auto& node : aDoc.GetNodes() ) + return MakeValue( result ); + } + else if( name == "beforefirst" && argc == 2 ) + { + wxString result = VALUE_UTILS::ToString( argValues[0] ); + + result = result.BeforeFirst( VALUE_UTILS::ToChar( argValues[1] ) ); + return MakeValue( result.ToStdString() ); + } + else if( name == "beforelast" && argc == 2 ) + { + wxString result = VALUE_UTILS::ToString( argValues[0] ); + + result = result.BeforeLast( VALUE_UTILS::ToChar( argValues[1] ) ); + return MakeValue( result.ToStdString() ); + } + else if( name == "afterfirst" && argc == 2 ) + { + wxString result = VALUE_UTILS::ToString( argValues[0] ); + + result = result.AfterFirst( VALUE_UTILS::ToChar( argValues[1] ) ); + return MakeValue( result.ToStdString() ); + } + else if( name == "afterlast" && argc == 2 ) + { + wxString result = VALUE_UTILS::ToString( argValues[0] ); + + result = result.AfterLast( VALUE_UTILS::ToChar( argValues[1] ) ); + return MakeValue( result.ToStdString() ); + } + + // Conditional functions (handle mixed types) + if( name == "if" && argc == 3 ) + { + // Convert only the condition to a number + auto conditionResult = VALUE_UTILS::ToDouble( argValues[0] ); + if( !conditionResult ) + return MakeError( conditionResult.GetError() ); + + const auto condition = conditionResult.GetValue() != 0.0; + return MakeValue( condition ? argValues[1] : argValues[2] ); + } + + // Mathematical functions (return numbers) - convert args to doubles first + std::vector numArgs; + for( const auto& val : argValues ) + { + auto numResult = VALUE_UTILS::ToDouble( val ); + if( !numResult ) + return MakeError( numResult.GetError() ); + + numArgs.push_back( numResult.GetValue() ); + } + + // Mathematical function implementations + if( name == "abs" && argc == 1 ) + return MakeValue( std::abs( numArgs[0] ) ); + else if( name == "sum" && argc >= 1 ) + return MakeValue( std::accumulate( numArgs.begin(), numArgs.end(), 0.0 ) ); + else if( name == "round" && argc >= 1 ) + { + const auto value = numArgs[0]; + const auto precision = argc > 1 ? static_cast( numArgs[1] ) : 0; + const auto multiplier = std::pow( 10.0, precision ); + return MakeValue( std::round( value * multiplier ) / multiplier ); + } + else if( name == "sqrt" && argc == 1 ) + { + if( numArgs[0] < 0 ) + return MakeError( "Square root of negative number" ); + + return MakeValue( std::sqrt( numArgs[0] ) ); + } + else if( name == "pow" && argc == 2 ) + return MakeValue( std::pow( numArgs[0], numArgs[1] ) ); + else if( name == "floor" && argc == 1 ) + return MakeValue( std::floor( numArgs[0] ) ); + else if( name == "ceil" && argc == 1 ) + return MakeValue( std::ceil( numArgs[0] ) ); + else if( name == "min" && argc >= 1 ) + return MakeValue( *std::min_element( numArgs.begin(), numArgs.end() ) ); + else if( name == "max" && argc >= 1 ) + return MakeValue( *std::max_element( numArgs.begin(), numArgs.end() ) ); + else if( name == "avg" && argc >= 1 ) + { + const auto sum = std::accumulate( numArgs.begin(), numArgs.end(), 0.0 ); + return MakeValue( sum / static_cast( argc ) ); + } + + return MakeError( fmt::format( "Unknown function: {} with {} arguments", name, argc ) ); +} + +auto DOC_PROCESSOR::Process( const DOC& aDoc, VariableCallback aVariableCallback ) -> std::pair +{ + std::string result; + auto localErrors = ERROR_COLLECTOR{}; + EVAL_VISITOR evaluator{ std::move( aVariableCallback ), localErrors }; + bool hadErrors = aDoc.HasErrors(); + + for( const auto& node : aDoc.GetNodes() ) + { + switch( node->type ) { - switch( node->type ) + case NodeType::Text: result += std::get( node->data ); break; + + case NodeType::Calc: + { + const auto& calcData = std::get( node->data ); + auto evalResult = calcData.left->Accept( evaluator ); + + if( evalResult ) + result += VALUE_UTILS::ToString( evalResult.GetValue() ); + else { - case NodeType::Text: - result += std::get( node->data ); - break; - - case NodeType::Calc: - { - const auto& calcData = std::get( node->data ); - auto evalResult = calcData.left->Accept( evaluator ); - - if( evalResult ) - result += VALUE_UTILS::ToString( evalResult.GetValue() ); - else - { - // Don't add error formatting to result - errors go to error vector only - // The higher level will return original input unchanged if there are errors - hadErrors = true; - } - break; - } - - default: - result += "[Unknown node type]"; + // Don't add error formatting to result - errors go to error vector only + // The higher level will return original input unchanged if there are errors hadErrors = true; - break; } + break; } - return { std::move( result ), hadErrors || localErrors.HasErrors() }; + default: + result += "[Unknown node type]"; + hadErrors = true; + break; + } + } + + return { std::move( result ), hadErrors || localErrors.HasErrors() }; } auto DOC_PROCESSOR::ProcessWithDetails( const DOC& aDoc, VariableCallback aVariableCallback ) - -> std::tuple, bool> + -> std::tuple, bool> { auto [result, hadErrors] = Process( aDoc, std::move( aVariableCallback ) ); auto allErrors = aDoc.GetErrors(); diff --git a/common/text_eval/text_eval_wrapper.cpp b/common/text_eval/text_eval_wrapper.cpp index aa30a3bb97..bcec675c45 100644 --- a/common/text_eval/text_eval_wrapper.cpp +++ b/common/text_eval/text_eval_wrapper.cpp @@ -42,7 +42,7 @@ namespace KI_EVAL #ifdef __GNUC__ #pragma GCC diagnostic pop #endif -} +} // namespace KI_EVAL #include #include @@ -79,375 +79,376 @@ enum class TextEvalToken : int }; // UTF-8 <-> UTF-32 conversion utilities -namespace utf8_utils { +namespace utf8_utils +{ - // Concept for UTF-8 byte validation - template - concept Utf8Byte = std::same_as || std::same_as || std::same_as; +// Concept for UTF-8 byte validation +template +concept Utf8Byte = std::same_as || std::same_as || std::same_as; - // UTF-8 validation and conversion - class UTF8_CONVERTER +// UTF-8 validation and conversion +class UTF8_CONVERTER +{ +private: + // UTF-8 byte classification using bit operations + static constexpr bool is_ascii( std::byte b ) noexcept { return ( b & std::byte{ 0x80 } ) == std::byte{ 0x00 }; } + + static constexpr bool is_continuation( std::byte b ) noexcept { - private: - // UTF-8 byte classification using bit operations - static constexpr bool is_ascii( std::byte b ) noexcept + return ( b & std::byte{ 0xC0 } ) == std::byte{ 0x80 }; + } + + static constexpr int sequence_length( std::byte first ) noexcept + { + if( is_ascii( first ) ) + return 1; + if( ( first & std::byte{ 0xE0 } ) == std::byte{ 0xC0 } ) + return 2; + if( ( first & std::byte{ 0xF0 } ) == std::byte{ 0xE0 } ) + return 3; + if( ( first & std::byte{ 0xF8 } ) == std::byte{ 0xF0 } ) + return 4; + return 0; // Invalid + } + +public: + // Convert UTF-8 string to UTF-32 codepoints using C++20 ranges + static std::u32string to_utf32( std::string_view utf8 ) + { + std::u32string result; + result.reserve( utf8.size() ); // Conservative estimate + + auto bytes = std::as_bytes( std::span{ utf8.data(), utf8.size() } ); + + for( size_t i = 0; i < bytes.size(); ) { - return ( b & std::byte{ 0x80 } ) == std::byte{ 0x00 }; - } + std::byte first = bytes[i]; + int len = sequence_length( first ); - static constexpr bool is_continuation( std::byte b ) noexcept - { - return ( b & std::byte{ 0xC0 } ) == std::byte{ 0x80 }; - } - - static constexpr int sequence_length( std::byte first ) noexcept - { - if( is_ascii( first ) ) - return 1; - if( ( first & std::byte{ 0xE0 } ) == std::byte{ 0xC0 } ) - return 2; - if( ( first & std::byte{ 0xF0 } ) == std::byte{ 0xE0 } ) - return 3; - if( ( first & std::byte{ 0xF8 } ) == std::byte{ 0xF0 } ) - return 4; - return 0; // Invalid - } - - public: - // Convert UTF-8 string to UTF-32 codepoints using C++20 ranges - static std::u32string to_utf32( std::string_view utf8 ) - { - std::u32string result; - result.reserve( utf8.size() ); // Conservative estimate - - auto bytes = std::as_bytes( std::span{ utf8.data(), utf8.size() } ); - - for( size_t i = 0; i < bytes.size(); ) + if( len == 0 || i + len > bytes.size() ) { - std::byte first = bytes[i]; - int len = sequence_length( first ); + // Invalid sequence - insert replacement character + result.push_back( U'\uFFFD' ); + i++; + continue; + } - if( len == 0 || i + len > bytes.size() ) + char32_t codepoint = 0; + + switch( len ) + { + case 1: codepoint = std::to_integer( first ); break; + + case 2: + { + if( !is_continuation( bytes[i + 1] ) ) { - // Invalid sequence - insert replacement character result.push_back( U'\uFFFD' ); i++; continue; } + codepoint = ( std::to_integer( first & std::byte{ 0x1F } ) << 6 ) + | std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ); + break; + } - char32_t codepoint = 0; + case 3: + { + if( !is_continuation( bytes[i + 1] ) || !is_continuation( bytes[i + 2] ) ) + { + result.push_back( U'\uFFFD' ); + i++; + continue; + } + codepoint = ( std::to_integer( first & std::byte{ 0x0F } ) << 12 ) + | ( std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ) << 6 ) + | std::to_integer( bytes[i + 2] & std::byte{ 0x3F } ); + break; + } - switch( len ) + case 4: + { + if( !is_continuation( bytes[i + 1] ) || !is_continuation( bytes[i + 2] ) + || !is_continuation( bytes[i + 3] ) ) { - case 1: codepoint = std::to_integer( first ); break; + result.push_back( U'\uFFFD' ); + i++; + continue; + } + codepoint = ( std::to_integer( first & std::byte{ 0x07 } ) << 18 ) + | ( std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ) << 12 ) + | ( std::to_integer( bytes[i + 2] & std::byte{ 0x3F } ) << 6 ) + | std::to_integer( bytes[i + 3] & std::byte{ 0x3F } ); + break; + } + } - case 2: - { - if( !is_continuation( bytes[i + 1] ) ) - { - result.push_back( U'\uFFFD' ); - i++; - continue; - } - codepoint = ( std::to_integer( first & std::byte{ 0x1F } ) << 6 ) - | std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ); - break; - } + // Validate codepoint range + if( codepoint > 0x10FFFF || ( codepoint >= 0xD800 && codepoint <= 0xDFFF ) ) + { + result.push_back( U'\uFFFD' ); // Replacement character + } + else if( len == 2 && codepoint < 0x80 ) + { + result.push_back( U'\uFFFD' ); // Overlong encoding + } + else if( len == 3 && codepoint < 0x800 ) + { + result.push_back( U'\uFFFD' ); // Overlong encoding + } + else if( len == 4 && codepoint < 0x10000 ) + { + result.push_back( U'\uFFFD' ); // Overlong encoding + } + else + { + result.push_back( codepoint ); + } - case 3: - { - if( !is_continuation( bytes[i + 1] ) || !is_continuation( bytes[i + 2] ) ) - { - result.push_back( U'\uFFFD' ); - i++; - continue; - } - codepoint = ( std::to_integer( first & std::byte{ 0x0F } ) << 12 ) - | ( std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ) << 6 ) - | std::to_integer( bytes[i + 2] & std::byte{ 0x3F } ); - break; - } + i += len; + } - case 4: - { - if( !is_continuation( bytes[i + 1] ) || !is_continuation( bytes[i + 2] ) - || !is_continuation( bytes[i + 3] ) ) - { - result.push_back( U'\uFFFD' ); - i++; - continue; - } - codepoint = ( std::to_integer( first & std::byte{ 0x07 } ) << 18 ) - | ( std::to_integer( bytes[i + 1] & std::byte{ 0x3F } ) << 12 ) - | ( std::to_integer( bytes[i + 2] & std::byte{ 0x3F } ) << 6 ) - | std::to_integer( bytes[i + 3] & std::byte{ 0x3F } ); - break; - } - } + return result; + } - // Validate codepoint range - if( codepoint > 0x10FFFF || ( codepoint >= 0xD800 && codepoint <= 0xDFFF ) ) + // Convert UTF-32 to UTF-8 + static std::string to_utf8( std::u32string_view utf32 ) + { + std::string result; + result.reserve( utf32.size() * 4 ); // Maximum possible size + + for( char32_t cp : utf32 ) + { + if( cp <= 0x7F ) + { + // 1-byte sequence + result.push_back( static_cast( cp ) ); + } + else if( cp <= 0x7FF ) + { + // 2-byte sequence + result.push_back( static_cast( 0xC0 | ( cp >> 6 ) ) ); + result.push_back( static_cast( 0x80 | ( cp & 0x3F ) ) ); + } + else if( cp <= 0xFFFF ) + { + // 3-byte sequence + if( cp >= 0xD800 && cp <= 0xDFFF ) { - result.push_back( U'\uFFFD' ); // Replacement character - } - else if( len == 2 && codepoint < 0x80 ) - { - result.push_back( U'\uFFFD' ); // Overlong encoding - } - else if( len == 3 && codepoint < 0x800 ) - { - result.push_back( U'\uFFFD' ); // Overlong encoding - } - else if( len == 4 && codepoint < 0x10000 ) - { - result.push_back( U'\uFFFD' ); // Overlong encoding + // Surrogate pair - invalid in UTF-32 + result.append( "\uFFFD" ); // Replacement character in UTF-8 } else { - result.push_back( codepoint ); - } - - i += len; - } - - return result; - } - - // Convert UTF-32 to UTF-8 - static std::string to_utf8( std::u32string_view utf32 ) - { - std::string result; - result.reserve( utf32.size() * 4 ); // Maximum possible size - - for( char32_t cp : utf32 ) - { - if( cp <= 0x7F ) - { - // 1-byte sequence - result.push_back( static_cast( cp ) ); - } - else if( cp <= 0x7FF ) - { - // 2-byte sequence - result.push_back( static_cast( 0xC0 | ( cp >> 6 ) ) ); - result.push_back( static_cast( 0x80 | ( cp & 0x3F ) ) ); - } - else if( cp <= 0xFFFF ) - { - // 3-byte sequence - if( cp >= 0xD800 && cp <= 0xDFFF ) - { - // Surrogate pair - invalid in UTF-32 - result.append( "\uFFFD" ); // Replacement character in UTF-8 - } - else - { - result.push_back( static_cast( 0xE0 | ( cp >> 12 ) ) ); - result.push_back( static_cast( 0x80 | ( ( cp >> 6 ) & 0x3F ) ) ); - result.push_back( static_cast( 0x80 | ( cp & 0x3F ) ) ); - } - } - else if( cp <= 0x10FFFF ) - { - // 4-byte sequence - result.push_back( static_cast( 0xF0 | ( cp >> 18 ) ) ); - result.push_back( static_cast( 0x80 | ( ( cp >> 12 ) & 0x3F ) ) ); + result.push_back( static_cast( 0xE0 | ( cp >> 12 ) ) ); result.push_back( static_cast( 0x80 | ( ( cp >> 6 ) & 0x3F ) ) ); result.push_back( static_cast( 0x80 | ( cp & 0x3F ) ) ); } - else - { - // Invalid codepoint - result.append( "\uFFFD" ); // Replacement character in UTF-8 - } } - - return result; - } - }; - - template - concept UnicodeCodepoint = std::same_as; - - struct CHARACTER_CLASSIFIER { - static constexpr bool is_whitespace(UnicodeCodepoint auto cp) noexcept { - // Unicode whitespace categories - return cp == U' ' || cp == U'\t' || cp == U'\r' || cp == U'\n' || - cp == U'\f' || cp == U'\v' || cp == U'\u00A0' || // Non-breaking space - cp == U'\u2000' || cp == U'\u2001' || cp == U'\u2002' || cp == U'\u2003' || - cp == U'\u2004' || cp == U'\u2005' || cp == U'\u2006' || cp == U'\u2007' || - cp == U'\u2008' || cp == U'\u2009' || cp == U'\u200A' || cp == U'\u2028' || - cp == U'\u2029' || cp == U'\u202F' || cp == U'\u205F' || cp == U'\u3000'; + else if( cp <= 0x10FFFF ) + { + // 4-byte sequence + result.push_back( static_cast( 0xF0 | ( cp >> 18 ) ) ); + result.push_back( static_cast( 0x80 | ( ( cp >> 12 ) & 0x3F ) ) ); + result.push_back( static_cast( 0x80 | ( ( cp >> 6 ) & 0x3F ) ) ); + result.push_back( static_cast( 0x80 | ( cp & 0x3F ) ) ); + } + else + { + // Invalid codepoint + result.append( "\uFFFD" ); // Replacement character in UTF-8 + } } - static constexpr bool is_digit(UnicodeCodepoint auto cp) noexcept { - return cp >= U'0' && cp <= U'9'; - } + return result; + } +}; - static constexpr bool is_ascii_alpha(UnicodeCodepoint auto cp) noexcept { - return (cp >= U'a' && cp <= U'z') || (cp >= U'A' && cp <= U'Z'); - } +template +concept UnicodeCodepoint = std::same_as; - static constexpr bool is_alpha(UnicodeCodepoint auto cp) noexcept { - // Basic Latin + extended Unicode letter ranges - return is_ascii_alpha(cp) || (cp >= 0x80 && cp <= 0x10FFFF && cp != 0xFFFD); - } - - static constexpr bool is_alnum(UnicodeCodepoint auto cp) noexcept { - return is_alpha(cp) || is_digit(cp); - } - }; - - struct SI_PREFIX_HANDLER +struct CHARACTER_CLASSIFIER +{ + static constexpr bool is_whitespace( UnicodeCodepoint auto cp ) noexcept { - struct PREFIX - { - char32_t symbol; - double multiplier; - }; + // Unicode whitespace categories + return cp == U' ' || cp == U'\t' || cp == U'\r' || cp == U'\n' || cp == U'\f' || cp == U'\v' || cp == U'\u00A0' + || // Non-breaking space + cp == U'\u2000' || cp == U'\u2001' || cp == U'\u2002' || cp == U'\u2003' || cp == U'\u2004' + || cp == U'\u2005' || cp == U'\u2006' || cp == U'\u2007' || cp == U'\u2008' || cp == U'\u2009' + || cp == U'\u200A' || cp == U'\u2028' || cp == U'\u2029' || cp == U'\u202F' || cp == U'\u205F' + || cp == U'\u3000'; + } - static constexpr std::array prefixes = { { - {U'a', 1e-18}, - {U'f', 1e-15}, - {U'p', 1e-12}, - {U'n', 1e-9}, - {U'u', 1e-6}, {U'µ', 1e-6}, {U'μ', 1e-6}, // Various micro symbols - {U'm', 1e-3}, - {U'k', 1e3}, {U'K', 1e3}, - {U'M', 1e6}, - {U'G', 1e9}, - {U'T', 1e12}, - {U'P', 1e15}, - {U'E', 1e18} - } }; + static constexpr bool is_digit( UnicodeCodepoint auto cp ) noexcept { return cp >= U'0' && cp <= U'9'; } - static constexpr bool is_si_prefix( UnicodeCodepoint auto cp ) noexcept - { - return std::ranges::any_of( prefixes, + static constexpr bool is_ascii_alpha( UnicodeCodepoint auto cp ) noexcept + { + return ( cp >= U'a' && cp <= U'z' ) || ( cp >= U'A' && cp <= U'Z' ); + } + + static constexpr bool is_alpha( UnicodeCodepoint auto cp ) noexcept + { + // Basic Latin + extended Unicode letter ranges + return is_ascii_alpha( cp ) || ( cp >= 0x80 && cp <= 0x10FFFF && cp != 0xFFFD ); + } + + static constexpr bool is_alnum( UnicodeCodepoint auto cp ) noexcept { return is_alpha( cp ) || is_digit( cp ); } +}; + +struct SI_PREFIX_HANDLER +{ + struct PREFIX + { + char32_t symbol; + double multiplier; + }; + + static constexpr std::array prefixes = { { { U'a', 1e-18 }, + { U'f', 1e-15 }, + { U'p', 1e-12 }, + { U'n', 1e-9 }, + { U'u', 1e-6 }, + { U'µ', 1e-6 }, + { U'μ', 1e-6 }, // Various micro symbols + { U'm', 1e-3 }, + { U'k', 1e3 }, + { U'K', 1e3 }, + { U'M', 1e6 }, + { U'G', 1e9 }, + { U'T', 1e12 }, + { U'P', 1e15 }, + { U'E', 1e18 } } }; + + static constexpr bool is_si_prefix( UnicodeCodepoint auto cp ) noexcept + { + return std::ranges::any_of( prefixes, + [cp]( const PREFIX& p ) + { + return p.symbol == cp; + } ); + } + + static constexpr double get_multiplier( UnicodeCodepoint auto cp ) noexcept + { + auto it = std::ranges::find_if( prefixes, [cp]( const PREFIX& p ) { return p.symbol == cp; } ); - } - - static constexpr double get_multiplier( UnicodeCodepoint auto cp ) noexcept - { - auto it = std::ranges::find_if( prefixes, - [cp]( const PREFIX& p ) - { - return p.symbol == cp; - } ); - return it != prefixes.end() ? it->multiplier : 1.0; - } - }; -} + return it != prefixes.end() ? it->multiplier : 1.0; + } +}; +} // namespace utf8_utils // Unit conversion utilities for the text evaluator -namespace KIEVAL_UNIT_CONV { +namespace KIEVAL_UNIT_CONV +{ - // Internal unit enum matching NUMERIC_EVALUATOR - enum class Unit { - Invalid, - UM, - MM, - CM, - Inch, - Mil, - Degrees, - SI, - Femtoseconds, - Picoseconds, - PsPerInch, - PsPerCm, - PsPerMm - }; +// Internal unit enum matching NUMERIC_EVALUATOR +enum class Unit +{ + Invalid, + UM, + MM, + CM, + Inch, + Mil, + Degrees, + SI, + Femtoseconds, + Picoseconds, + PsPerInch, + PsPerCm, + PsPerMm +}; - // Convert EDA_UNITS to internal Unit enum - Unit edaUnitsToInternal( EDA_UNITS aUnits ) +// Convert EDA_UNITS to internal Unit enum +Unit edaUnitsToInternal( EDA_UNITS aUnits ) +{ + switch( aUnits ) { - switch( aUnits ) - { - case EDA_UNITS::MM: return Unit::MM; - case EDA_UNITS::MILS: return Unit::Mil; - case EDA_UNITS::INCH: return Unit::Inch; - case EDA_UNITS::DEGREES: return Unit::Degrees; - case EDA_UNITS::FS: return Unit::Femtoseconds; - case EDA_UNITS::PS: return Unit::Picoseconds; - case EDA_UNITS::PS_PER_INCH: return Unit::PsPerInch; - case EDA_UNITS::PS_PER_CM: return Unit::PsPerCm; - case EDA_UNITS::PS_PER_MM: return Unit::PsPerMm; - case EDA_UNITS::UM: return Unit::UM; - case EDA_UNITS::CM: return Unit::CM; - case EDA_UNITS::UNSCALED: return Unit::SI; - default: return Unit::MM; - } - } - - // Parse unit from string using centralized registry - Unit parseUnit( const std::string& aUnitStr ) - { - auto evalUnit = text_eval_units::UnitRegistry::parseUnit( aUnitStr ); - - // Convert text_eval_units::Unit to KIEVAL_UNIT_CONV::Unit - switch( evalUnit ) - { - case text_eval_units::Unit::MM: return Unit::MM; - case text_eval_units::Unit::CM: return Unit::CM; - case text_eval_units::Unit::INCH: return Unit::Inch; - case text_eval_units::Unit::INCH_QUOTE: return Unit::Inch; - case text_eval_units::Unit::MIL: return Unit::Mil; - case text_eval_units::Unit::THOU: return Unit::Mil; - case text_eval_units::Unit::UM: return Unit::UM; - case text_eval_units::Unit::DEG: return Unit::Degrees; - case text_eval_units::Unit::DEGREE_SYMBOL: return Unit::Degrees; - case text_eval_units::Unit::PS: return Unit::Picoseconds; - case text_eval_units::Unit::FS: return Unit::Femtoseconds; - case text_eval_units::Unit::PS_PER_IN: return Unit::PsPerInch; - case text_eval_units::Unit::PS_PER_CM: return Unit::PsPerCm; - case text_eval_units::Unit::PS_PER_MM: return Unit::PsPerMm; - default: return Unit::Invalid; - } - } - - // Get conversion factor from one unit to another (based on numeric_evaluator logic) - double getConversionFactor( Unit aFromUnit, Unit aToUnit ) - { - if( aFromUnit == aToUnit ) - return 1.0; - - // Convert to MM first, then to target unit - double toMM = 1.0; - switch( aFromUnit ) - { - case Unit::Inch: toMM = 25.4; break; - case Unit::Mil: toMM = 25.4 / 1000.0; break; - case Unit::UM: toMM = 1.0 / 1000.0; break; - case Unit::MM: toMM = 1.0; break; - case Unit::CM: toMM = 10.0; break; - default: return 1.0; // No conversion for other units - } - - double fromMM = 1.0; - switch( aToUnit ) - { - case Unit::Inch: fromMM = 1.0 / 25.4; break; - case Unit::Mil: fromMM = 1000.0 / 25.4; break; - case Unit::UM: fromMM = 1000.0; break; - case Unit::MM: fromMM = 1.0; break; - case Unit::CM: fromMM = 1.0 / 10.0; break; - default: return 1.0; // No conversion for other units - } - - return toMM * fromMM; - } - - // Convert a value with units to the default units using centralized registry - double convertToDefaultUnits( double aValue, const std::string& aUnitStr, EDA_UNITS aDefaultUnits ) - { - return text_eval_units::UnitRegistry::convertToEdaUnits( aValue, aUnitStr, aDefaultUnits ); + case EDA_UNITS::MM: return Unit::MM; + case EDA_UNITS::MILS: return Unit::Mil; + case EDA_UNITS::INCH: return Unit::Inch; + case EDA_UNITS::DEGREES: return Unit::Degrees; + case EDA_UNITS::FS: return Unit::Femtoseconds; + case EDA_UNITS::PS: return Unit::Picoseconds; + case EDA_UNITS::PS_PER_INCH: return Unit::PsPerInch; + case EDA_UNITS::PS_PER_CM: return Unit::PsPerCm; + case EDA_UNITS::PS_PER_MM: return Unit::PsPerMm; + case EDA_UNITS::UM: return Unit::UM; + case EDA_UNITS::CM: return Unit::CM; + case EDA_UNITS::UNSCALED: return Unit::SI; + default: return Unit::MM; } } +// Parse unit from string using centralized registry +Unit parseUnit( const std::string& aUnitStr ) +{ + auto evalUnit = text_eval_units::UnitRegistry::parseUnit( aUnitStr ); + + // Convert text_eval_units::Unit to KIEVAL_UNIT_CONV::Unit + switch( evalUnit ) + { + case text_eval_units::Unit::MM: return Unit::MM; + case text_eval_units::Unit::CM: return Unit::CM; + case text_eval_units::Unit::INCH: return Unit::Inch; + case text_eval_units::Unit::INCH_QUOTE: return Unit::Inch; + case text_eval_units::Unit::MIL: return Unit::Mil; + case text_eval_units::Unit::THOU: return Unit::Mil; + case text_eval_units::Unit::UM: return Unit::UM; + case text_eval_units::Unit::DEG: return Unit::Degrees; + case text_eval_units::Unit::DEGREE_SYMBOL: return Unit::Degrees; + case text_eval_units::Unit::PS: return Unit::Picoseconds; + case text_eval_units::Unit::FS: return Unit::Femtoseconds; + case text_eval_units::Unit::PS_PER_IN: return Unit::PsPerInch; + case text_eval_units::Unit::PS_PER_CM: return Unit::PsPerCm; + case text_eval_units::Unit::PS_PER_MM: return Unit::PsPerMm; + default: return Unit::Invalid; + } +} + +// Get conversion factor from one unit to another (based on numeric_evaluator logic) +double getConversionFactor( Unit aFromUnit, Unit aToUnit ) +{ + if( aFromUnit == aToUnit ) + return 1.0; + + // Convert to MM first, then to target unit + double toMM = 1.0; + switch( aFromUnit ) + { + case Unit::Inch: toMM = 25.4; break; + case Unit::Mil: toMM = 25.4 / 1000.0; break; + case Unit::UM: toMM = 1.0 / 1000.0; break; + case Unit::MM: toMM = 1.0; break; + case Unit::CM: toMM = 10.0; break; + default: return 1.0; // No conversion for other units + } + + double fromMM = 1.0; + switch( aToUnit ) + { + case Unit::Inch: fromMM = 1.0 / 25.4; break; + case Unit::Mil: fromMM = 1000.0 / 25.4; break; + case Unit::UM: fromMM = 1000.0; break; + case Unit::MM: fromMM = 1.0; break; + case Unit::CM: fromMM = 1.0 / 10.0; break; + default: return 1.0; // No conversion for other units + } + + return toMM * fromMM; +} + +// Convert a value with units to the default units using centralized registry +double convertToDefaultUnits( double aValue, const std::string& aUnitStr, EDA_UNITS aDefaultUnits ) +{ + return text_eval_units::UnitRegistry::convertToEdaUnits( aValue, aUnitStr, aDefaultUnits ); +} +} // namespace KIEVAL_UNIT_CONV + class KIEVAL_TEXT_TOKENIZER { @@ -458,22 +459,19 @@ private: EXPRESSION // Inside @{...} or ${...} - alphabetic should be IDENTIFIER tokens }; - std::u32string m_text; - size_t m_pos{ 0 }; - size_t m_line{ 1 }; - size_t m_column{ 1 }; - TOKENIZER_CONTEXT m_context{ TOKENIZER_CONTEXT::TEXT }; - int m_braceNestingLevel{ 0 }; // Track nesting level of expressions + std::u32string m_text; + size_t m_pos{ 0 }; + size_t m_line{ 1 }; + size_t m_column{ 1 }; + TOKENIZER_CONTEXT m_context{ TOKENIZER_CONTEXT::TEXT }; + int m_braceNestingLevel{ 0 }; // Track nesting level of expressions calc_parser::ERROR_COLLECTOR* m_errorCollector{ nullptr }; - EDA_UNITS m_defaultUnits{ EDA_UNITS::MM }; // Add default units for conversion + EDA_UNITS m_defaultUnits{ EDA_UNITS::MM }; // Add default units for conversion using CLASSIFIER = utf8_utils::CHARACTER_CLASSIFIER; using SI_HANDLER = utf8_utils::SI_PREFIX_HANDLER; - [[nodiscard]] char32_t current_char() const noexcept - { - return m_pos < m_text.size() ? m_text[m_pos] : U'\0'; - } + [[nodiscard]] char32_t current_char() const noexcept { return m_pos < m_text.size() ? m_text[m_pos] : U'\0'; } [[nodiscard]] char32_t peek_char( size_t offset = 1 ) const noexcept { @@ -549,13 +547,13 @@ private: switch( escaped ) { - case U'n': content.push_back( U'\n' ); break; - case U't': content.push_back( U'\t' ); break; - case U'r': content.push_back( U'\r' ); break; + case U'n': content.push_back( U'\n' ); break; + case U't': content.push_back( U'\t' ); break; + case U'r': content.push_back( U'\r' ); break; case U'\\': content.push_back( U'\\' ); break; - case U'"': content.push_back( U'"' ); break; + case U'"': content.push_back( U'"' ); break; case U'\'': content.push_back( U'\'' ); break; - case U'0': content.push_back( U'\0' ); break; + case U'0': content.push_back( U'\0' ); break; case U'x': { // Hexadecimal escape \xHH @@ -564,9 +562,8 @@ private: for( int i = 0; i < 2 && m_pos < m_text.size(); ++i ) { char32_t hex_char = current_char(); - if( ( hex_char >= U'0' && hex_char <= U'9' ) - || ( hex_char >= U'A' && hex_char <= U'F' ) - || ( hex_char >= U'a' && hex_char <= U'f' ) ) + if( ( hex_char >= U'0' && hex_char <= U'9' ) || ( hex_char >= U'A' && hex_char <= U'F' ) + || ( hex_char >= U'a' && hex_char <= U'f' ) ) { hex.push_back( hex_char ); advance_position(); @@ -619,13 +616,16 @@ private: } } - if (m_pos < m_text.size() && current_char() == quote_char) { + if( m_pos < m_text.size() && current_char() == quote_char ) + { advance_position(); // Skip closing quote - } else { - add_error("Missing closing quote in string literal"); + } + else + { + add_error( "Missing closing quote in string literal" ); } - return make_string_token(utf8_utils::UTF8_CONVERTER::to_utf8(content)); + return make_string_token( utf8_utils::UTF8_CONVERTER::to_utf8( content ) ); } [[nodiscard]] calc_parser::TOKEN_TYPE parse_number() @@ -633,7 +633,6 @@ private: std::u32string number_text; number_text.reserve( 32 ); - bool has_decimal = false; double multiplier = 1.0; // Parse integer part @@ -653,7 +652,6 @@ private: if( c == U'.' || ( c == U',' && m_context != TOKENIZER_CONTEXT::EXPRESSION ) ) { number_text.push_back( U'.' ); - has_decimal = true; advance_position(); } else if( m_context == TOKENIZER_CONTEXT::EXPRESSION && CLASSIFIER::is_alpha( c ) ) @@ -681,7 +679,7 @@ private: // Check if we have a valid unit if( !potential_unit.empty() ) { - std::string unit_str = utf8_utils::UTF8_CONVERTER::to_utf8( potential_unit ); + std::string unit_str = utf8_utils::UTF8_CONVERTER::to_utf8( potential_unit ); KIEVAL_UNIT_CONV::Unit parsed_unit = KIEVAL_UNIT_CONV::parseUnit( unit_str ); if( parsed_unit != KIEVAL_UNIT_CONV::Unit::Invalid ) @@ -689,40 +687,133 @@ private: // This is a valid unit - don't treat the first character as SI prefix // The unit parsing will happen later } - else if( SI_HANDLER::is_si_prefix( c ) && !has_decimal ) + else if( SI_HANDLER::is_si_prefix( c ) ) { // Not a valid unit, so treat as SI prefix multiplier = SI_HANDLER::get_multiplier( c ); - number_text.push_back( U'.' ); - has_decimal = true; advance_position(); } } - else if( SI_HANDLER::is_si_prefix( c ) && !has_decimal ) + else if( SI_HANDLER::is_si_prefix( c ) ) { // No alphabetic characters following, so treat as SI prefix multiplier = SI_HANDLER::get_multiplier( c ); - number_text.push_back( U'.' ); - has_decimal = true; advance_position(); } } - else if( SI_HANDLER::is_si_prefix( c ) && !has_decimal ) + else if( SI_HANDLER::is_si_prefix( c ) ) { // In text context, treat as SI prefix multiplier = SI_HANDLER::get_multiplier( c ); - number_text.push_back( U'.' ); - has_decimal = true; advance_position(); } } // Parse fractional part - while (m_pos < m_text.size() && CLASSIFIER::is_digit(current_char())) { - number_text.push_back(current_char()); + while( m_pos < m_text.size() && CLASSIFIER::is_digit( current_char() ) ) + { + number_text.push_back( current_char() ); advance_position(); } + // Check for scientific notation (e.g., 1e-3, 3.5E6) + if( m_pos < m_text.size() ) + { + char32_t c = current_char(); + + if( c == U'e' || c == U'E' ) + { + // Look ahead to see if this is scientific notation (followed by +, -, or digit) + size_t temp_pos = m_pos + 1; + bool is_scientific = false; + + if( temp_pos < m_text.size() ) + { + char32_t next = m_text[temp_pos]; + if( next == U'+' || next == U'-' || CLASSIFIER::is_digit( next ) ) + { + is_scientific = true; + } + } + + if( is_scientific ) + { + // Parse scientific notation exponent + number_text.push_back( c ); // Add 'e' or 'E' + advance_position(); + + // Optional sign + if( m_pos < m_text.size() && ( current_char() == U'+' || current_char() == U'-' ) ) + { + number_text.push_back( current_char() ); + advance_position(); + } + + // Exponent digits (required) + if( m_pos < m_text.size() && CLASSIFIER::is_digit( current_char() ) ) + { + while( m_pos < m_text.size() && CLASSIFIER::is_digit( current_char() ) ) + { + number_text.push_back( current_char() ); + advance_position(); + } + } + else + { + // Invalid scientific notation - will fail in conversion + add_error( "Invalid scientific notation: missing exponent digits" ); + } + } + } + } + + // Check for SI prefix after fractional part (for numbers like 0.3M) + if( m_pos < m_text.size() && multiplier == 1.0 ) + { + char32_t c = current_char(); + + if( m_context == TOKENIZER_CONTEXT::EXPRESSION && CLASSIFIER::is_alpha( c ) ) + { + // Look ahead to check for unit vs SI prefix + std::u32string potential_unit; + size_t temp_pos = m_pos; + + while( temp_pos < m_text.size() ) + { + char32_t unit_char = m_text[temp_pos]; + + if( CLASSIFIER::is_alpha( unit_char ) || unit_char == U'"' || unit_char == U'\'' ) + { + potential_unit.push_back( unit_char ); + temp_pos++; + } + else + { + break; + } + } + + if( !potential_unit.empty() ) + { + std::string unit_str = utf8_utils::UTF8_CONVERTER::to_utf8( potential_unit ); + KIEVAL_UNIT_CONV::Unit parsed_unit = KIEVAL_UNIT_CONV::parseUnit( unit_str ); + + if( parsed_unit == KIEVAL_UNIT_CONV::Unit::Invalid && SI_HANDLER::is_si_prefix( c ) ) + { + // Not a valid unit, so treat as SI prefix + multiplier = SI_HANDLER::get_multiplier( c ); + advance_position(); + } + } + } + else if( SI_HANDLER::is_si_prefix( c ) ) + { + // In text context, treat as SI prefix + multiplier = SI_HANDLER::get_multiplier( c ); + advance_position(); + } + } + // Convert to double safely auto number_str = utf8_utils::UTF8_CONVERTER::to_utf8( number_text ); double value = 0.0; @@ -784,7 +875,7 @@ private: if( !unit_text.empty() ) { // Convert unit text to string and try to parse it - std::string unit_str = utf8_utils::UTF8_CONVERTER::to_utf8( unit_text ); + std::string unit_str = utf8_utils::UTF8_CONVERTER::to_utf8( unit_text ); KIEVAL_UNIT_CONV::Unit parsed_unit = KIEVAL_UNIT_CONV::parseUnit( unit_str ); if( parsed_unit != KIEVAL_UNIT_CONV::Unit::Invalid ) @@ -806,41 +897,44 @@ private: } } - return make_number_token(value); + return make_number_token( value ); } - [[nodiscard]] calc_parser::TOKEN_TYPE parse_identifier() { + [[nodiscard]] calc_parser::TOKEN_TYPE parse_identifier() + { std::u32string identifier; - identifier.reserve(64); + identifier.reserve( 64 ); - while (m_pos < m_text.size() && - (CLASSIFIER::is_alnum(current_char()) || current_char() == U'_')) { - identifier.push_back(current_char()); + while( m_pos < m_text.size() && ( CLASSIFIER::is_alnum( current_char() ) || current_char() == U'_' ) ) + { + identifier.push_back( current_char() ); advance_position(); } - return make_string_token(utf8_utils::UTF8_CONVERTER::to_utf8(identifier)); + return make_string_token( utf8_utils::UTF8_CONVERTER::to_utf8( identifier ) ); } - [[nodiscard]] calc_parser::TOKEN_TYPE parse_text_content() { + [[nodiscard]] calc_parser::TOKEN_TYPE parse_text_content() + { std::u32string text; - text.reserve(256); + text.reserve( 256 ); - while (m_pos < m_text.size()) { + while( m_pos < m_text.size() ) + { char32_t current = current_char(); char32_t next = peek_char(); // Stop at special sequences - if ((current == U'@' && next == U'{') || - (current == U'$' && next == U'{')) { + if( ( current == U'@' && next == U'{' ) || ( current == U'$' && next == U'{' ) ) + { break; } - text.push_back(current); + text.push_back( current ); advance_position(); } - return make_string_token(utf8_utils::UTF8_CONVERTER::to_utf8(text)); + return make_string_token( utf8_utils::UTF8_CONVERTER::to_utf8( text ) ); } public: @@ -938,23 +1032,26 @@ public: // Single character tokens (only in expression context) if( m_context == TOKENIZER_CONTEXT::EXPRESSION ) { - static constexpr std::array, 11> single_char_tokens{{ - {U'(', TextEvalToken::LPAREN}, - {U')', TextEvalToken::RPAREN}, - {U'+', TextEvalToken::PLUS}, - {U'-', TextEvalToken::MINUS}, - {U'*', TextEvalToken::MULTIPLY}, - {U'/', TextEvalToken::DIVIDE}, - {U'%', TextEvalToken::MODULO}, - {U'^', TextEvalToken::POWER}, - {U',', TextEvalToken::COMMA}, - {U'<', TextEvalToken::LT}, - {U'>', TextEvalToken::GT} - }}; + static constexpr std::array, 11> single_char_tokens{ + { { U'(', TextEvalToken::LPAREN }, + { U')', TextEvalToken::RPAREN }, + { U'+', TextEvalToken::PLUS }, + { U'-', TextEvalToken::MINUS }, + { U'*', TextEvalToken::MULTIPLY }, + { U'/', TextEvalToken::DIVIDE }, + { U'%', TextEvalToken::MODULO }, + { U'^', TextEvalToken::POWER }, + { U',', TextEvalToken::COMMA }, + { U'<', TextEvalToken::LT }, + { U'>', TextEvalToken::GT } } + }; if( auto it = std::ranges::find_if( single_char_tokens, - [current]( const auto& pair ) { return pair.first == current; } ); - it != single_char_tokens.end() ) + [current]( const auto& pair ) + { + return pair.first == current; + } ); + it != single_char_tokens.end() ) { advance_position(); token_value = make_string_token( utf8_utils::UTF8_CONVERTER::to_utf8( std::u32string{ current } ) ); @@ -997,7 +1094,7 @@ public: return token_value.text[0] == U'\0' ? TextEvalToken::ENDS : TextEvalToken::TEXT; } - [[nodiscard]] bool has_more_tokens() const noexcept { return m_pos < m_text.size(); } + [[nodiscard]] bool has_more_tokens() const noexcept { return m_pos < m_text.size(); } [[nodiscard]] constexpr size_t get_line() const noexcept { return m_line; } [[nodiscard]] constexpr size_t get_column() const noexcept { return m_column; } }; @@ -1005,17 +1102,16 @@ public: EXPRESSION_EVALUATOR::EXPRESSION_EVALUATOR( bool aClearVariablesOnEvaluate ) : m_clearVariablesOnEvaluate( aClearVariablesOnEvaluate ), m_useCustomCallback( false ), - m_defaultUnits( EDA_UNITS::MM ) // Default to millimeters + m_defaultUnits( EDA_UNITS::MM ) // Default to millimeters { m_lastErrors = std::make_unique(); } -EXPRESSION_EVALUATOR::EXPRESSION_EVALUATOR( VariableCallback aVariableCallback, - bool aClearVariablesOnEvaluate ) : +EXPRESSION_EVALUATOR::EXPRESSION_EVALUATOR( VariableCallback aVariableCallback, bool aClearVariablesOnEvaluate ) : m_clearVariablesOnEvaluate( aClearVariablesOnEvaluate ), m_customCallback( std::move( aVariableCallback ) ), m_useCustomCallback( true ), - m_defaultUnits( EDA_UNITS::MM ) // Default to millimeters + m_defaultUnits( EDA_UNITS::MM ) // Default to millimeters { m_lastErrors = std::make_unique(); } @@ -1029,7 +1125,7 @@ EXPRESSION_EVALUATOR::EXPRESSION_EVALUATOR( EDA_UNITS aUnits, bool aClearVariabl } EXPRESSION_EVALUATOR::EXPRESSION_EVALUATOR( EDA_UNITS aUnits, VariableCallback aVariableCallback, - bool aClearVariablesOnEvaluate ) : + bool aClearVariablesOnEvaluate ) : m_clearVariablesOnEvaluate( aClearVariablesOnEvaluate ), m_customCallback( std::move( aVariableCallback ) ), m_useCustomCallback( true ), @@ -1165,7 +1261,7 @@ bool EXPRESSION_EVALUATOR::HasVariable( const wxString& aName ) const wxString EXPRESSION_EVALUATOR::GetVariable( const wxString& aName ) const { std::string name = wxStringToStdString( aName ); - auto it = m_variables.find( name ); + auto it = m_variables.find( name ); if( it != m_variables.end() ) { if( std::holds_alternative( it->second ) ) @@ -1210,21 +1306,21 @@ void EXPRESSION_EVALUATOR::SetVariables( const std::unordered_map emptyNumVars; + std::unordered_map emptyNumVars; std::unordered_map emptyStringVars; return Evaluate( aInput, emptyNumVars, emptyStringVars ); } -wxString EXPRESSION_EVALUATOR::Evaluate( const wxString& aInput, - const std::unordered_map& aTempVariables ) +wxString EXPRESSION_EVALUATOR::Evaluate( const wxString& aInput, + const std::unordered_map& aTempVariables ) { std::unordered_map emptyStringVars; return Evaluate( aInput, aTempVariables, emptyStringVars ); } -wxString EXPRESSION_EVALUATOR::Evaluate( const wxString& aInput, - const std::unordered_map& aTempNumericVars, - const std::unordered_map& aTempStringVars ) +wxString EXPRESSION_EVALUATOR::Evaluate( const wxString& aInput, + const std::unordered_map& aTempNumericVars, + const std::unordered_map& aTempStringVars ) { // Clear previous errors ClearErrors(); @@ -1233,8 +1329,8 @@ wxString EXPRESSION_EVALUATOR::Evaluate( const wxString& aInput, wxString processedInput = expandVariablesOutsideExpressions( aInput, aTempNumericVars, aTempStringVars ); // Convert processed input to std::string - std::string input = wxStringToStdString( processedInput ); // Create combined callback for all variable sources - auto combinedCallback = createCombinedCallback( &aTempNumericVars, &aTempStringVars ); + std::string input = wxStringToStdString( processedInput ); // Create combined callback for all variable sources + auto combinedCallback = createCombinedCallback( &aTempNumericVars, &aTempStringVars ); // Evaluate using parser auto [result, hadErrors] = evaluateWithParser( input, combinedCallback ); @@ -1332,8 +1428,8 @@ bool EXPRESSION_EVALUATOR::TestExpression( const wxString& aExpression ) // Filter out "Test mode - no variables available" errors, look for syntax errors for( const auto& error : errors ) { - if( error.find( "Syntax error" ) != std::string::npos || - error.find( "Parser failed" ) != std::string::npos ) + if( error.find( "Syntax error" ) != std::string::npos + || error.find( "Parser failed" ) != std::string::npos ) { return false; // Found syntax error } @@ -1360,7 +1456,7 @@ size_t EXPRESSION_EVALUATOR::CountExpressions( const wxString& aInput ) const std::vector EXPRESSION_EVALUATOR::ExtractExpressions( const wxString& aInput ) const { std::vector expressions; - size_t pos = 0; + size_t pos = 0; while( ( pos = aInput.find( "@{", pos ) ) != wxString::npos ) { @@ -1392,18 +1488,17 @@ wxString EXPRESSION_EVALUATOR::stdStringToWxString( const std::string& aStdStr ) } wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( - const wxString& aInput, - const std::unordered_map& aTempNumericVars, - const std::unordered_map& aTempStringVars ) const + const wxString& aInput, const std::unordered_map& aTempNumericVars, + const std::unordered_map& aTempStringVars ) const { wxString result = aInput; - size_t pos = 0; + size_t pos = 0; // Track positions of @{} expressions to avoid substituting inside them std::vector> expressionRanges; // Find all @{} expression ranges - while( (pos = result.find( "@{", pos )) != std::string::npos ) + while( ( pos = result.find( "@{", pos ) ) != std::string::npos ) { size_t start = pos; size_t braceCount = 1; @@ -1429,7 +1524,7 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( // Now find and replace ${variable} patterns that are NOT inside @{} expressions pos = 0; - while( (pos = result.find( "${", pos )) != std::string::npos ) + while( ( pos = result.find( "${", pos ) ) != std::string::npos ) { // Check if this ${} is inside any @{} expression bool insideExpression = false; @@ -1451,7 +1546,7 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( { // Check what comes after the closing brace size_t afterBrace = closePos + 1; - bool followedByUnit = false; + bool followedByUnit = false; if( afterBrace < result.length() ) { @@ -1459,8 +1554,8 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( const auto units = text_eval_units::UnitRegistry::getAllUnitStrings(); for( const auto& unit : units ) { - if( afterBrace + unit.length() <= result.length() && - result.substr( afterBrace, unit.length() ) == unit ) + if( afterBrace + unit.length() <= result.length() + && result.substr( afterBrace, unit.length() ) == unit ) { followedByUnit = true; break; @@ -1493,7 +1588,7 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( // Extract variable name wxString varName = result.substr( pos + 2, closePos - pos - 2 ); wxString replacement; - bool found = false; + bool found = false; // Check temporary string variables first auto stringIt = aTempStringVars.find( varName ); @@ -1515,7 +1610,7 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( { // Check instance variables std::string stdVarName = wxStringToStdString( varName ); - auto instIt = m_variables.find( stdVarName ); + auto instIt = m_variables.find( stdVarName ); if( instIt != m_variables.end() ) { const calc_parser::Value& value = instIt->second; @@ -1552,11 +1647,12 @@ wxString EXPRESSION_EVALUATOR::expandVariablesOutsideExpressions( return result; } -EXPRESSION_EVALUATOR::VariableCallback EXPRESSION_EVALUATOR::createCombinedCallback( - const std::unordered_map* aTempNumericVars, - const std::unordered_map* aTempStringVars ) const +EXPRESSION_EVALUATOR::VariableCallback +EXPRESSION_EVALUATOR::createCombinedCallback( const std::unordered_map* aTempNumericVars, + const std::unordered_map* aTempStringVars ) const { - return [this, aTempNumericVars, aTempStringVars]( const std::string& aVarName ) -> calc_parser::Result + return [this, aTempNumericVars, + aTempStringVars]( const std::string& aVarName ) -> calc_parser::Result { // Priority 1: Custom callback (if set) if( m_useCustomCallback && m_customCallback ) @@ -1604,29 +1700,27 @@ EXPRESSION_EVALUATOR::VariableCallback EXPRESSION_EVALUATOR::createCombinedCallb wxString testString = wxString::Format( "${%s}", varName ); // Create a resolver that will return true if the variable was found - bool wasResolved = false; - std::function resolver = - [&wasResolved]( wxString* token ) -> bool - { - // If we get here, ExpandTextVars found the variable and wants to resolve it - // For our purposes, we just want to know if it exists, so return false - // to keep the original ${varname} format, and set our flag - wasResolved = true; - return false; // Don't replace, just detect - }; + bool wasResolved = false; + std::function resolver = [&wasResolved]( wxString* token ) -> bool + { + // If we get here, ExpandTextVars found the variable and wants to resolve it + // For our purposes, we just want to know if it exists, so return false + // to keep the original ${varname} format, and set our flag + wasResolved = true; + return false; // Don't replace, just detect + }; wxString expandedResult = ExpandTextVars( testString, &resolver ); if( wasResolved ) { // Variable exists in KiCad's system, now get its actual value - std::function valueResolver = - []( wxString* token ) -> bool - { - // Let ExpandTextVars resolve this normally - // We'll get the resolved value in token - return false; // Use default resolution - }; + std::function valueResolver = []( wxString* token ) -> bool + { + // Let ExpandTextVars resolve this normally + // We'll get the resolved value in token + return false; // Use default resolution + }; wxString resolvedValue = ExpandTextVars( testString, &valueResolver ); @@ -1639,7 +1733,8 @@ EXPRESSION_EVALUATOR::VariableCallback EXPRESSION_EVALUATOR::createCombinedCallb try { double numValue; - auto result = fast_float::from_chars( resolvedStd.data(), resolvedStd.data() + resolvedStd.size(), numValue ); + auto result = fast_float::from_chars( resolvedStd.data(), + resolvedStd.data() + resolvedStd.size(), numValue ); if( result.ec != std::errc() || result.ptr != resolvedStd.data() + resolvedStd.size() ) throw std::invalid_argument( fmt::format( "Cannot convert '{}' to number", resolvedStd ) ); @@ -1666,44 +1761,48 @@ EXPRESSION_EVALUATOR::VariableCallback EXPRESSION_EVALUATOR::createCombinedCallb } // No variable found anywhere - return calc_parser::MakeError( - fmt::format( "Undefined variable: {}", aVarName ) ); + return calc_parser::MakeError( fmt::format( "Undefined variable: {}", aVarName ) ); }; } -std::pair EXPRESSION_EVALUATOR::evaluateWithParser( - const std::string& aInput, - VariableCallback aVariableCallback) +std::pair EXPRESSION_EVALUATOR::evaluateWithParser( const std::string& aInput, + VariableCallback aVariableCallback ) { - try { + try + { // Try partial error recovery first - auto [partialResult, partialHadErrors] = evaluateWithPartialErrorRecovery(aInput, aVariableCallback); + auto [partialResult, partialHadErrors] = evaluateWithPartialErrorRecovery( aInput, aVariableCallback ); // If partial recovery made any progress (result differs from input), use it - if (partialResult != aInput) { + if( partialResult != aInput ) + { // Partial recovery made progress - always report errors collected during partial recovery - return {std::move(partialResult), partialHadErrors}; + return { std::move( partialResult ), partialHadErrors }; } // If no progress was made, try original full parsing approach as fallback - return evaluateWithFullParser(aInput, std::move(aVariableCallback)); - - } catch (const std::bad_alloc&) { - if (m_lastErrors) { - m_lastErrors->AddError("Out of memory"); + return evaluateWithFullParser( aInput, std::move( aVariableCallback ) ); + } + catch( const std::bad_alloc& ) + { + if( m_lastErrors ) + { + m_lastErrors->AddError( "Out of memory" ); } - return {aInput, true}; - } catch (const std::exception& e) { - if (m_lastErrors) { - m_lastErrors->AddError(fmt::format("Exception: {}", e.what())); + return { aInput, true }; + } + catch( const std::exception& e ) + { + if( m_lastErrors ) + { + m_lastErrors->AddError( fmt::format( "Exception: {}", e.what() ) ); } - return {aInput, true}; + return { aInput, true }; } } -std::pair EXPRESSION_EVALUATOR::evaluateWithPartialErrorRecovery( - const std::string& aInput, - VariableCallback aVariableCallback) +std::pair +EXPRESSION_EVALUATOR::evaluateWithPartialErrorRecovery( const std::string& aInput, VariableCallback aVariableCallback ) { std::string result = aInput; bool hadAnyErrors = false; @@ -1911,8 +2010,9 @@ std::pair EXPRESSION_EVALUATOR::evaluateWithFullParser( const } } -NUMERIC_EVALUATOR_COMPAT::NUMERIC_EVALUATOR_COMPAT( EDA_UNITS aUnits ) - : m_evaluator( aUnits ), m_lastValid( false ) +NUMERIC_EVALUATOR_COMPAT::NUMERIC_EVALUATOR_COMPAT( EDA_UNITS aUnits ) : + m_evaluator( aUnits ), + m_lastValid( false ) { } @@ -1960,7 +2060,10 @@ bool NUMERIC_EVALUATOR_COMPAT::Process( const wxString& aString ) // Sort variable names by length (longest first) to avoid partial replacements std::sort( varNames.begin(), varNames.end(), - []( const wxString& a, const wxString& b ) { return a.length() > b.length(); } ); + []( const wxString& a, const wxString& b ) + { + return a.length() > b.length(); + } ); // Replace bare variable names with ${variable} syntax for( const auto& varName : varNames ) diff --git a/eeschema/dialogs/dialog_tablecell_properties.cpp b/eeschema/dialogs/dialog_tablecell_properties.cpp index 45955369a1..36ff30f45c 100644 --- a/eeschema/dialogs/dialog_tablecell_properties.cpp +++ b/eeschema/dialogs/dialog_tablecell_properties.cpp @@ -28,15 +28,19 @@ #include #include #include +#include #include #include +#include #include -DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( SCH_EDIT_FRAME* aFrame, - std::vector aCells ) : - DIALOG_TABLECELL_PROPERTIES_BASE( aFrame ), m_frame( aFrame ), m_table( nullptr ), +DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( SCH_EDIT_FRAME* aFrame, std::vector aCells ) : + DIALOG_TABLECELL_PROPERTIES_BASE( aFrame ), + m_frame( aFrame ), + m_table( nullptr ), m_cells( std::move( aCells ) ), m_scintillaTricks( nullptr ), + m_helpWindow( nullptr ), m_textSize( aFrame, m_textSizeLabel, m_textSizeCtrl, m_textSizeUnits ), m_marginLeft( aFrame, nullptr, m_marginLeftCtrl, nullptr ), m_marginTop( aFrame, nullptr, m_marginTopCtrl, m_marginTopUnits ), @@ -117,10 +121,12 @@ DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( SCH_EDIT_FRAME* DIALOG_TABLECELL_PROPERTIES::~DIALOG_TABLECELL_PROPERTIES() { delete m_scintillaTricks; + + if( m_helpWindow ) + m_helpWindow->Destroy(); } -void DIALOG_TABLECELL_PROPERTIES::getContextualTextVars( const wxString& aCrossRef, - wxArrayString* aTokens ) +void DIALOG_TABLECELL_PROPERTIES::getContextualTextVars( const wxString& aCrossRef, wxArrayString* aTokens ) { SCHEMATIC* schematic = m_table->Schematic(); @@ -212,8 +218,7 @@ bool DIALOG_TABLECELL_PROPERTIES::TransferDataToWindow() } else { - if( cell->GetFont() != m_fontCtrl->GetFontSelection( cell->IsBold(), - cell->IsItalic() ) ) + if( cell->GetFont() != m_fontCtrl->GetFontSelection( cell->IsBold(), cell->IsItalic() ) ) m_fontCtrl->SetSelection( -1 ); if( cell->GetTextWidth() != m_textSize.GetValue() ) @@ -267,18 +272,18 @@ bool DIALOG_TABLECELL_PROPERTIES::TransferDataToWindow() switch( hAlign ) { - case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break; - case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break; - case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break; - case GR_TEXT_H_ALIGN_INDETERMINATE: break; + case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break; + case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break; + case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break; + case GR_TEXT_H_ALIGN_INDETERMINATE: break; } switch( vAlign ) { - case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break; - case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break; - case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break; - case GR_TEXT_V_ALIGN_INDETERMINATE: break; + case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break; + case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break; + case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break; + case GR_TEXT_V_ALIGN_INDETERMINATE: break; } } @@ -436,4 +441,17 @@ void DIALOG_TABLECELL_PROPERTIES::onMultiLineTCLostFocus( wxFocusEvent& event ) m_scintillaTricks->CancelAutocomplete(); event.Skip(); +} + + +void DIALOG_TABLECELL_PROPERTIES::OnFormattingHelp( wxHyperlinkEvent& aEvent ) +{ + if( m_helpWindow ) + { + m_helpWindow->Raise(); + m_helpWindow->Show( true ); + return; + } + + m_helpWindow = SCH_TEXT::ShowSyntaxHelp( this ); } \ No newline at end of file diff --git a/eeschema/dialogs/dialog_tablecell_properties.h b/eeschema/dialogs/dialog_tablecell_properties.h index 71bdd34ad6..2a60ee21f8 100644 --- a/eeschema/dialogs/dialog_tablecell_properties.h +++ b/eeschema/dialogs/dialog_tablecell_properties.h @@ -32,6 +32,7 @@ class SCH_EDIT_FRAME; class SCH_TABLE; class SCH_TABLECELL; class SCINTILLA_TRICKS; +class HTML_MESSAGE_BOX; class DIALOG_TABLECELL_PROPERTIES : public DIALOG_TABLECELL_PROPERTIES_BASE { @@ -57,32 +58,34 @@ private: bool TransferDataToWindow() override; bool TransferDataFromWindow() override; - void onHAlignButton( wxCommandEvent &aEvent ); - void onVAlignButton( wxCommandEvent &aEvent ); - void onTextColorPopup( wxCommandEvent &aEvent ) override; - void onFillColorPopup( wxCommandEvent &aEvent ) override; + void onHAlignButton( wxCommandEvent& aEvent ); + void onVAlignButton( wxCommandEvent& aEvent ); + void onTextColorPopup( wxCommandEvent& aEvent ) override; + void onFillColorPopup( wxCommandEvent& aEvent ) override; void onEditTable( wxCommandEvent& aEvent ) override; + void OnFormattingHelp( wxHyperlinkEvent& aEvent ) override; void OnSystemColourChanged( wxSysColourChangedEvent& event ); void UpdateTheme( void ); -private: - SCH_EDIT_FRAME* m_frame; - SCH_TABLE* m_table; - std::vector m_cells; - SCINTILLA_TRICKS* m_scintillaTricks; - UNIT_BINDER m_textSize; - UNIT_BINDER m_marginLeft; - UNIT_BINDER m_marginTop; - UNIT_BINDER m_marginRight; - UNIT_BINDER m_marginBottom; - wxStyledTextCtrl* m_cellText; +private: + SCH_EDIT_FRAME* m_frame; + SCH_TABLE* m_table; + std::vector m_cells; + SCINTILLA_TRICKS* m_scintillaTricks; + HTML_MESSAGE_BOX* m_helpWindow; + + UNIT_BINDER m_textSize; + UNIT_BINDER m_marginLeft; + UNIT_BINDER m_marginTop; + UNIT_BINDER m_marginRight; + UNIT_BINDER m_marginBottom; + wxStyledTextCtrl* m_cellText; enum TABLECELL_PROPS_RETVALUE m_returnValue; // the option that closed the dialog }; - #endif // DIALOG_TABLECELL_PROPERTIES_H diff --git a/eeschema/dialogs/dialog_tablecell_properties_base.cpp b/eeschema/dialogs/dialog_tablecell_properties_base.cpp index 433c32d499..c93b5e9a63 100644 --- a/eeschema/dialogs/dialog_tablecell_properties_base.cpp +++ b/eeschema/dialogs/dialog_tablecell_properties_base.cpp @@ -14,400 +14,440 @@ /////////////////////////////////////////////////////////////////////////// -DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, + const wxString& title, const wxPoint& pos, + const wxSize& size, long style ) : + DIALOG_SHIM( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bMainSizer; - bMainSizer = new wxBoxSizer( wxVERTICAL ); - - m_infoBar = new WX_INFOBAR( this ); - m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); - m_infoBar->SetEffectDuration( 500 ); - m_infoBar->Hide(); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + m_infoBar = new WX_INFOBAR( this ); + m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); + m_infoBar->SetEffectDuration( 500 ); + m_infoBar->Hide(); + + bMainSizer->Add( m_infoBar, 0, wxEXPAND | wxBOTTOM, 5 ); + + wxBoxSizer* bSizer151; + bSizer151 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer16; + bSizer16 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer18; + bSizer18 = new wxBoxSizer( wxVERTICAL ); + + m_cellTextLabel = new wxStaticText( this, wxID_ANY, _( "Cell contents:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_cellTextLabel->Wrap( -1 ); + bSizer18->Add( m_cellTextLabel, 0, wxALL, 5 ); - bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 ); + m_cellTextCtrl = + new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString ); + m_cellTextCtrl->SetUseTabs( false ); + m_cellTextCtrl->SetTabWidth( 4 ); + m_cellTextCtrl->SetIndent( 4 ); + m_cellTextCtrl->SetTabIndents( false ); + m_cellTextCtrl->SetBackSpaceUnIndents( false ); + m_cellTextCtrl->SetViewEOL( false ); + m_cellTextCtrl->SetViewWhiteSpace( false ); + m_cellTextCtrl->SetMarginWidth( 2, 0 ); + m_cellTextCtrl->SetIndentationGuides( false ); + m_cellTextCtrl->SetReadOnly( false ); + m_cellTextCtrl->SetMarginWidth( 1, 0 ); + m_cellTextCtrl->SetMarginWidth( 0, 0 ); + { + wxFont font = wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, + wxFONTWEIGHT_NORMAL, false, wxEmptyString ); + m_cellTextCtrl->StyleSetFont( wxSTC_STYLE_DEFAULT, font ); + } + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); + m_cellTextCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); + m_cellTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, + wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); + m_cellTextCtrl->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + m_cellTextCtrl->SetMinSize( wxSize( 200, 100 ) ); - wxBoxSizer* bSizer151; - bSizer151 = new wxBoxSizer( wxVERTICAL ); + bSizer18->Add( m_cellTextCtrl, 1, wxEXPAND | wxALL, 5 ); - wxBoxSizer* bSizer16; - bSizer16 = new wxBoxSizer( wxHORIZONTAL ); - wxBoxSizer* bSizer18; - bSizer18 = new wxBoxSizer( wxVERTICAL ); + bSizer16->Add( bSizer18, 1, wxEXPAND | wxRIGHT, 10 ); - m_cellTextLabel = new wxStaticText( this, wxID_ANY, _("Cell contents:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_cellTextLabel->Wrap( -1 ); - bSizer18->Add( m_cellTextLabel, 0, wxALL, 5 ); + wxBoxSizer* bSizer17; + bSizer17 = new wxBoxSizer( wxVERTICAL ); - m_cellTextCtrl = new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString ); - m_cellTextCtrl->SetUseTabs( false ); - m_cellTextCtrl->SetTabWidth( 4 ); - m_cellTextCtrl->SetIndent( 4 ); - m_cellTextCtrl->SetTabIndents( false ); - m_cellTextCtrl->SetBackSpaceUnIndents( false ); - m_cellTextCtrl->SetViewEOL( false ); - m_cellTextCtrl->SetViewWhiteSpace( false ); - m_cellTextCtrl->SetMarginWidth( 2, 0 ); - m_cellTextCtrl->SetIndentationGuides( false ); - m_cellTextCtrl->SetReadOnly( false ); - m_cellTextCtrl->SetMarginWidth( 1, 0 ); - m_cellTextCtrl->SetMarginWidth( 0, 0 ); - { - wxFont font = wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ); - m_cellTextCtrl->StyleSetFont( wxSTC_STYLE_DEFAULT, font ); - } - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); - m_cellTextCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); - m_cellTextCtrl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); - m_cellTextCtrl->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); - m_cellTextCtrl->SetMinSize( wxSize( 200,100 ) ); + wxBoxSizer* bSizer13; + bSizer13 = new wxBoxSizer( wxVERTICAL ); - bSizer18->Add( m_cellTextCtrl, 1, wxEXPAND | wxALL, 5 ); + bSizer13->Add( 0, 20, 0, 0, 5 ); - bSizer16->Add( bSizer18, 1, wxEXPAND|wxRIGHT, 10 ); + wxFlexGridSizer* fgTextStyleSizer; + fgTextStyleSizer = new wxFlexGridSizer( 0, 2, 5, 5 ); + fgTextStyleSizer->SetFlexibleDirection( wxBOTH ); + fgTextStyleSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - wxBoxSizer* bSizer17; - bSizer17 = new wxBoxSizer( wxVERTICAL ); + wxStaticText* hAlignLabel; + hAlignLabel = new wxStaticText( this, wxID_ANY, _( "Horizontal alignment:" ), wxDefaultPosition, wxDefaultSize, 0 ); + hAlignLabel->Wrap( -1 ); + hAlignLabel->SetToolTip( _( "Horizontal alignment" ) ); - wxBoxSizer* bSizer13; - bSizer13 = new wxBoxSizer( wxVERTICAL ); + fgTextStyleSizer->Add( hAlignLabel, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5 ); + wxBoxSizer* hAlignButtons; + hAlignButtons = new wxBoxSizer( wxHORIZONTAL ); - bSizer13->Add( 0, 20, 0, 0, 5 ); + m_hAlignLeft = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignLeft->SetToolTip( _( "Align left" ) ); - wxFlexGridSizer* fgTextStyleSizer; - fgTextStyleSizer = new wxFlexGridSizer( 0, 2, 5, 5 ); - fgTextStyleSizer->SetFlexibleDirection( wxBOTH ); - fgTextStyleSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + hAlignButtons->Add( m_hAlignLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxStaticText* hAlignLabel; - hAlignLabel = new wxStaticText( this, wxID_ANY, _("Horizontal alignment:"), wxDefaultPosition, wxDefaultSize, 0 ); - hAlignLabel->Wrap( -1 ); - hAlignLabel->SetToolTip( _("Horizontal alignment") ); + m_hAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignCenter->SetToolTip( _( "Align horizontal center" ) ); - fgTextStyleSizer->Add( hAlignLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + hAlignButtons->Add( m_hAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* hAlignButtons; - hAlignButtons = new wxBoxSizer( wxHORIZONTAL ); + m_hAlignRight = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignRight->SetToolTip( _( "Align right" ) ); - m_hAlignLeft = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignLeft->SetToolTip( _("Align left") ); + hAlignButtons->Add( m_hAlignRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_hAlignLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_hAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignCenter->SetToolTip( _("Align horizontal center") ); + fgTextStyleSizer->Add( hAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_hAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); + vAlignLabel = new wxStaticText( this, wxID_ANY, _( "Vertical alignment:" ), wxDefaultPosition, wxDefaultSize, 0 ); + vAlignLabel->Wrap( -1 ); + vAlignLabel->SetToolTip( _( "Vertical alignment" ) ); - m_hAlignRight = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignRight->SetToolTip( _("Align right") ); + fgTextStyleSizer->Add( vAlignLabel, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5 ); - hAlignButtons->Add( m_hAlignRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* vAlignButtons; + vAlignButtons = new wxBoxSizer( wxHORIZONTAL ); + m_vAlignTop = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignTop->SetToolTip( _( "Align top" ) ); - fgTextStyleSizer->Add( hAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); + vAlignButtons->Add( m_vAlignTop, 0, wxALIGN_CENTER_VERTICAL, 5 ); - vAlignLabel = new wxStaticText( this, wxID_ANY, _("Vertical alignment:"), wxDefaultPosition, wxDefaultSize, 0 ); - vAlignLabel->Wrap( -1 ); - vAlignLabel->SetToolTip( _("Vertical alignment") ); + m_vAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignCenter->SetToolTip( _( "Align vertical center" ) ); - fgTextStyleSizer->Add( vAlignLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 ); + vAlignButtons->Add( m_vAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* vAlignButtons; - vAlignButtons = new wxBoxSizer( wxHORIZONTAL ); + m_vAlignBottom = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignBottom->SetToolTip( _( "Align bottom" ) ); - m_vAlignTop = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignTop->SetToolTip( _("Align top") ); + vAlignButtons->Add( m_vAlignBottom, 0, wxALIGN_CENTER_VERTICAL, 5 ); - vAlignButtons->Add( m_vAlignTop, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_vAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignCenter->SetToolTip( _("Align vertical center") ); + fgTextStyleSizer->Add( vAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); - vAlignButtons->Add( m_vAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_vAlignBottom = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignBottom->SetToolTip( _("Align bottom") ); + bSizer13->Add( fgTextStyleSizer, 0, wxEXPAND, 5 ); - vAlignButtons->Add( m_vAlignBottom, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bMargins; + bMargins = new wxBoxSizer( wxVERTICAL ); - fgTextStyleSizer->Add( vAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bMargins->Add( 0, 10, 0, wxEXPAND, 5 ); + wxGridBagSizer* gbFontSizer; + gbFontSizer = new wxGridBagSizer( 6, 5 ); + gbFontSizer->SetFlexibleDirection( wxBOTH ); + gbFontSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbFontSizer->SetEmptyCellSize( wxSize( -1, 5 ) ); - bSizer13->Add( fgTextStyleSizer, 0, wxEXPAND, 5 ); + m_styleLabel = new wxStaticText( this, wxID_ANY, _( "Style:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_styleLabel->Wrap( -1 ); + gbFontSizer->Add( m_styleLabel, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxTOP, 1 ); - wxBoxSizer* bMargins; - bMargins = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bSizer14; + bSizer14 = new wxBoxSizer( wxHORIZONTAL ); + m_bold = new wxCheckBox( this, wxID_ANY, _( "Bold" ), wxDefaultPosition, wxDefaultSize, + wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER ); + bSizer14->Add( m_bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bMargins->Add( 0, 10, 0, wxEXPAND, 5 ); + m_italic = new wxCheckBox( this, wxID_ANY, _( "Italic" ), wxDefaultPosition, wxDefaultSize, + wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER ); + bSizer14->Add( m_italic, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 45 ); - wxGridBagSizer* gbFontSizer; - gbFontSizer = new wxGridBagSizer( 6, 5 ); - gbFontSizer->SetFlexibleDirection( wxBOTH ); - gbFontSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbFontSizer->SetEmptyCellSize( wxSize( -1,5 ) ); - m_styleLabel = new wxStaticText( this, wxID_ANY, _("Style:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_styleLabel->Wrap( -1 ); - gbFontSizer->Add( m_styleLabel, wxGBPosition( 3, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxTOP, 1 ); + gbFontSizer->Add( bSizer14, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND | wxTOP, 1 ); - wxBoxSizer* bSizer14; - bSizer14 = new wxBoxSizer( wxHORIZONTAL ); + m_fontLabel = new wxStaticText( this, wxID_ANY, _( "Font:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_fontLabel->Wrap( -1 ); + gbFontSizer->Add( m_fontLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxLEFT, 1 ); - m_bold = new wxCheckBox( this, wxID_ANY, _("Bold"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER ); - bSizer14->Add( m_bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxString m_fontCtrlChoices[] = { _( "Default Font" ), _( "KiCad Font" ) }; + int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString ); + m_fontCtrl = new FONT_CHOICE( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, + m_fontCtrlChoices, 0 ); + m_fontCtrl->SetSelection( 0 ); + gbFontSizer->Add( m_fontCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 ); - m_italic = new wxCheckBox( this, wxID_ANY, _("Italic"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER ); - bSizer14->Add( m_italic, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 45 ); + m_textSizeLabel = new wxStaticText( this, wxID_ANY, _( "Size:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_textSizeLabel->Wrap( -1 ); + gbFontSizer->Add( m_textSizeLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + wxBoxSizer* bSizer15; + bSizer15 = new wxBoxSizer( wxHORIZONTAL ); - gbFontSizer->Add( bSizer14, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP, 1 ); + m_textSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), 0 ); + bSizer15->Add( m_textSizeCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_fontLabel = new wxStaticText( this, wxID_ANY, _("Font:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_fontLabel->Wrap( -1 ); - gbFontSizer->Add( m_fontLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 ); + m_textSizeUnits = new wxStaticText( this, wxID_ANY, _( "mm" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_textSizeUnits->Wrap( -1 ); + bSizer15->Add( m_textSizeUnits, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 3 ); - wxString m_fontCtrlChoices[] = { _("Default Font"), _("KiCad Font") }; - int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString ); - m_fontCtrl = new FONT_CHOICE( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, m_fontCtrlChoices, 0 ); - m_fontCtrl->SetSelection( 0 ); - gbFontSizer->Add( m_fontCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); - m_textSizeLabel = new wxStaticText( this, wxID_ANY, _("Size:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_textSizeLabel->Wrap( -1 ); - gbFontSizer->Add( m_textSizeLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + gbFontSizer->Add( bSizer15, wxGBPosition( 2, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* bSizer15; - bSizer15 = new wxBoxSizer( wxHORIZONTAL ); - m_textSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 ); - bSizer15->Add( m_textSizeCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + gbFontSizer->AddGrowableCol( 1 ); - m_textSizeUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); - m_textSizeUnits->Wrap( -1 ); - bSizer15->Add( m_textSizeUnits, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 3 ); + bMargins->Add( gbFontSizer, 0, wxEXPAND | wxBOTTOM, 5 ); + wxFlexGridSizer* fgColorSizer; + fgColorSizer = new wxFlexGridSizer( 0, 2, 4, 5 ); + fgColorSizer->SetFlexibleDirection( wxBOTH ); + fgColorSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbFontSizer->Add( bSizer15, wxGBPosition( 2, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL, 5 ); + m_textColorLabel = new wxStaticText( this, wxID_ANY, _( "Text color:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_textColorLabel->Wrap( -1 ); + fgColorSizer->Add( m_textColorLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_textColorBook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + wxPanel* textColorPopupPanel; + textColorPopupPanel = new wxPanel( m_textColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer20; + bSizer20 = new wxBoxSizer( wxVERTICAL ); - gbFontSizer->AddGrowableCol( 1 ); + wxString m_textColorPopupChoices[] = { _( "-- mixed values --" ), _( "Set Color..." ) }; + int m_textColorPopupNChoices = sizeof( m_textColorPopupChoices ) / sizeof( wxString ); + m_textColorPopup = new wxChoice( textColorPopupPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, + m_textColorPopupNChoices, m_textColorPopupChoices, 0 ); + m_textColorPopup->SetSelection( 0 ); + bSizer20->Add( m_textColorPopup, 0, 0, 5 ); - bMargins->Add( gbFontSizer, 0, wxEXPAND|wxBOTTOM, 5 ); - wxFlexGridSizer* fgColorSizer; - fgColorSizer = new wxFlexGridSizer( 0, 2, 4, 5 ); - fgColorSizer->SetFlexibleDirection( wxBOTH ); - fgColorSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + textColorPopupPanel->SetSizer( bSizer20 ); + textColorPopupPanel->Layout(); + bSizer20->Fit( textColorPopupPanel ); + m_textColorBook->AddPage( textColorPopupPanel, _( "a page" ), false ); + textColorSwatchPanel = new wxPanel( m_textColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer222; + bSizer222 = new wxBoxSizer( wxHORIZONTAL ); - m_textColorLabel = new wxStaticText( this, wxID_ANY, _("Text color:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_textColorLabel->Wrap( -1 ); - fgColorSizer->Add( m_textColorLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_panelTextColor = new wxPanel( textColorSwatchPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxBORDER_SIMPLE | wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer221; + bSizer221 = new wxBoxSizer( wxVERTICAL ); - m_textColorBook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - wxPanel* textColorPopupPanel; - textColorPopupPanel = new wxPanel( m_textColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer20; - bSizer20 = new wxBoxSizer( wxVERTICAL ); + m_textColorSwatch = new COLOR_SWATCH( m_panelTextColor, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer221->Add( m_textColorSwatch, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL, 5 ); - wxString m_textColorPopupChoices[] = { _("-- mixed values --"), _("Set Color...") }; - int m_textColorPopupNChoices = sizeof( m_textColorPopupChoices ) / sizeof( wxString ); - m_textColorPopup = new wxChoice( textColorPopupPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_textColorPopupNChoices, m_textColorPopupChoices, 0 ); - m_textColorPopup->SetSelection( 0 ); - bSizer20->Add( m_textColorPopup, 0, 0, 5 ); + m_panelTextColor->SetSizer( bSizer221 ); + m_panelTextColor->Layout(); + bSizer221->Fit( m_panelTextColor ); + bSizer222->Add( m_panelTextColor, 0, wxALIGN_CENTER_VERTICAL, 5 ); - textColorPopupPanel->SetSizer( bSizer20 ); - textColorPopupPanel->Layout(); - bSizer20->Fit( textColorPopupPanel ); - m_textColorBook->AddPage( textColorPopupPanel, _("a page"), false ); - textColorSwatchPanel = new wxPanel( m_textColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer222; - bSizer222 = new wxBoxSizer( wxHORIZONTAL ); - m_panelTextColor = new wxPanel( textColorSwatchPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer221; - bSizer221 = new wxBoxSizer( wxVERTICAL ); + textColorSwatchPanel->SetSizer( bSizer222 ); + textColorSwatchPanel->Layout(); + bSizer222->Fit( textColorSwatchPanel ); + m_textColorBook->AddPage( textColorSwatchPanel, _( "a page" ), false ); - m_textColorSwatch = new COLOR_SWATCH( m_panelTextColor, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer221->Add( m_textColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgColorSizer->Add( m_textColorBook, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_fillColorLabel = new wxStaticText( this, wxID_ANY, _( "Background fill:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_fillColorLabel->Wrap( -1 ); + fgColorSizer->Add( m_fillColorLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_panelTextColor->SetSizer( bSizer221 ); - m_panelTextColor->Layout(); - bSizer221->Fit( m_panelTextColor ); - bSizer222->Add( m_panelTextColor, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_fillColorBook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + wxPanel* fillColorPopupPanel; + fillColorPopupPanel = new wxPanel( m_fillColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer211; + bSizer211 = new wxBoxSizer( wxVERTICAL ); + wxString m_fillColorPopupChoices[] = { _( "-- mixed values --" ), _( "Set Color..." ) }; + int m_fillColorPopupNChoices = sizeof( m_fillColorPopupChoices ) / sizeof( wxString ); + m_fillColorPopup = new wxChoice( fillColorPopupPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, + m_fillColorPopupNChoices, m_fillColorPopupChoices, 0 ); + m_fillColorPopup->SetSelection( 0 ); + bSizer211->Add( m_fillColorPopup, 0, 0, 5 ); - textColorSwatchPanel->SetSizer( bSizer222 ); - textColorSwatchPanel->Layout(); - bSizer222->Fit( textColorSwatchPanel ); - m_textColorBook->AddPage( textColorSwatchPanel, _("a page"), false ); - fgColorSizer->Add( m_textColorBook, 0, wxALIGN_CENTER_VERTICAL, 5 ); + fillColorPopupPanel->SetSizer( bSizer211 ); + fillColorPopupPanel->Layout(); + bSizer211->Fit( fillColorPopupPanel ); + m_fillColorBook->AddPage( fillColorPopupPanel, _( "a page" ), false ); + fillColorSwatchPanel = new wxPanel( m_fillColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer23; + bSizer23 = new wxBoxSizer( wxHORIZONTAL ); - m_fillColorLabel = new wxStaticText( this, wxID_ANY, _("Background fill:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_fillColorLabel->Wrap( -1 ); - fgColorSizer->Add( m_fillColorLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_panelFillColor = new wxPanel( fillColorSwatchPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxBORDER_SIMPLE | wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer22; + bSizer22 = new wxBoxSizer( wxVERTICAL ); - m_fillColorBook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - wxPanel* fillColorPopupPanel; - fillColorPopupPanel = new wxPanel( m_fillColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer211; - bSizer211 = new wxBoxSizer( wxVERTICAL ); + m_fillColorSwatch = new COLOR_SWATCH( m_panelFillColor, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer22->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL, 5 ); - wxString m_fillColorPopupChoices[] = { _("-- mixed values --"), _("Set Color...") }; - int m_fillColorPopupNChoices = sizeof( m_fillColorPopupChoices ) / sizeof( wxString ); - m_fillColorPopup = new wxChoice( fillColorPopupPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fillColorPopupNChoices, m_fillColorPopupChoices, 0 ); - m_fillColorPopup->SetSelection( 0 ); - bSizer211->Add( m_fillColorPopup, 0, 0, 5 ); + m_panelFillColor->SetSizer( bSizer22 ); + m_panelFillColor->Layout(); + bSizer22->Fit( m_panelFillColor ); + bSizer23->Add( m_panelFillColor, 0, wxALIGN_CENTER_VERTICAL, 5 ); - fillColorPopupPanel->SetSizer( bSizer211 ); - fillColorPopupPanel->Layout(); - bSizer211->Fit( fillColorPopupPanel ); - m_fillColorBook->AddPage( fillColorPopupPanel, _("a page"), false ); - fillColorSwatchPanel = new wxPanel( m_fillColorBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer23; - bSizer23 = new wxBoxSizer( wxHORIZONTAL ); - m_panelFillColor = new wxPanel( fillColorSwatchPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer22; - bSizer22 = new wxBoxSizer( wxVERTICAL ); + fillColorSwatchPanel->SetSizer( bSizer23 ); + fillColorSwatchPanel->Layout(); + bSizer23->Fit( fillColorSwatchPanel ); + m_fillColorBook->AddPage( fillColorSwatchPanel, _( "a page" ), false ); - m_fillColorSwatch = new COLOR_SWATCH( m_panelFillColor, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - bSizer22->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 ); + fgColorSizer->Add( m_fillColorBook, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_panelFillColor->SetSizer( bSizer22 ); - m_panelFillColor->Layout(); - bSizer22->Fit( m_panelFillColor ); - bSizer23->Add( m_panelFillColor, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bMargins->Add( fgColorSizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 20 ); - fillColorSwatchPanel->SetSizer( bSizer23 ); - fillColorSwatchPanel->Layout(); - bSizer23->Fit( fillColorSwatchPanel ); - m_fillColorBook->AddPage( fillColorSwatchPanel, _("a page"), false ); + bMargins->Add( 0, 5, 0, wxEXPAND, 5 ); - fgColorSizer->Add( m_fillColorBook, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxGridSizer* gMarginsSizer; + gMarginsSizer = new wxGridSizer( 0, 3, 4, 2 ); + wxStaticText* marginsLabel; + marginsLabel = new wxStaticText( this, wxID_ANY, _( "Cell margins:" ), wxDefaultPosition, wxDefaultSize, 0 ); + marginsLabel->Wrap( -1 ); + gMarginsSizer->Add( marginsLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bMargins->Add( fgColorSizer, 0, wxEXPAND|wxTOP|wxBOTTOM, 20 ); + m_marginTopCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginTopCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_marginTopUnits = new wxStaticText( this, wxID_ANY, _( "mm" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_marginTopUnits->Wrap( -1 ); + gMarginsSizer->Add( m_marginTopUnits, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 2 ); - bMargins->Add( 0, 5, 0, wxEXPAND, 5 ); + m_marginLeftCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginLeftCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxGridSizer* gMarginsSizer; - gMarginsSizer = new wxGridSizer( 0, 3, 4, 2 ); - wxStaticText* marginsLabel; - marginsLabel = new wxStaticText( this, wxID_ANY, _("Cell margins:"), wxDefaultPosition, wxDefaultSize, 0 ); - marginsLabel->Wrap( -1 ); - gMarginsSizer->Add( marginsLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); - m_marginTopCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginTopCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_marginRightCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginRightCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_marginTopUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); - m_marginTopUnits->Wrap( -1 ); - gMarginsSizer->Add( m_marginTopUnits, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 2 ); - m_marginLeftCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginLeftCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + m_marginBottomCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginBottomCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); - m_marginRightCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginRightCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bMargins->Add( gMarginsSizer, 0, wxEXPAND, 5 ); - gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + bSizer13->Add( bMargins, 1, wxEXPAND | wxALL, 5 ); - m_marginBottomCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginBottomCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer17->Add( bSizer13, 1, wxEXPAND | wxTOP | wxRIGHT | wxLEFT, 5 ); - bMargins->Add( gMarginsSizer, 0, wxEXPAND, 5 ); + bSizer16->Add( bSizer17, 1, wxEXPAND | wxLEFT, 5 ); - bSizer13->Add( bMargins, 1, wxEXPAND|wxALL, 5 ); + bSizer151->Add( bSizer16, 1, wxEXPAND, 5 ); - bSizer17->Add( bSizer13, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + bMainSizer->Add( bSizer151, 1, wxEXPAND | wxLEFT, 5 ); - bSizer16->Add( bSizer17, 1, wxEXPAND|wxLEFT, 5 ); + wxBoxSizer* bButtons; + bButtons = new wxBoxSizer( wxHORIZONTAL ); + m_editTable = new wxButton( this, wxID_ANY, _( "Edit Table..." ), wxDefaultPosition, wxDefaultSize, 0 ); + m_editTable->SetToolTip( _( "Edit table properties and cell contents" ) ); - bSizer151->Add( bSizer16, 1, wxEXPAND, 5 ); + bButtons->Add( m_editTable, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10 ); + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _( "Syntax help" ), wxEmptyString, wxDefaultPosition, + wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _( "Show syntax help window" ) ); - bMainSizer->Add( bSizer151, 1, wxEXPAND|wxLEFT, 5 ); + bButtons->Add( m_syntaxHelp, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10 ); - wxBoxSizer* bButtons; - bButtons = new wxBoxSizer( wxHORIZONTAL ); - m_editTable = new wxButton( this, wxID_ANY, _("Edit Table..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_editTable->SetToolTip( _("Edit table properties and cell contents") ); + bButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - bButtons->Add( m_editTable, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 10 ); + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); + bButtons->Add( m_sdbSizer1, 0, wxEXPAND | wxALL, 5 ); - bButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - m_sdbSizer1 = new wxStdDialogButtonSizer(); - m_sdbSizer1OK = new wxButton( this, wxID_OK ); - m_sdbSizer1->AddButton( m_sdbSizer1OK ); - m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); - m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); - m_sdbSizer1->Realize(); + bMainSizer->Add( bButtons, 0, wxEXPAND, 5 ); - bButtons->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 ); + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); - bMainSizer->Add( bButtons, 0, wxEXPAND, 5 ); - - - this->SetSizer( bMainSizer ); - this->Layout(); - bMainSizer->Fit( this ); - - // Connect Events - this->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ) ); - m_textColorPopup->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextColorPopup ), NULL, this ); - m_fillColorPopup->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onFillColorPopup ), NULL, this ); - m_editTable->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); + // Connect Events + this->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ) ); + m_syntaxHelp->Connect( wxEVT_COMMAND_HYPERLINK, + wxHyperlinkEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnFormattingHelp ), NULL, this ); + m_textColorPopup->Connect( wxEVT_COMMAND_CHOICE_SELECTED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextColorPopup ), NULL, + this ); + m_fillColorPopup->Connect( wxEVT_COMMAND_CHOICE_SELECTED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onFillColorPopup ), NULL, + this ); + m_editTable->Connect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); } DIALOG_TABLECELL_PROPERTIES_BASE::~DIALOG_TABLECELL_PROPERTIES_BASE() { - // Disconnect Events - this->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ) ); - m_textColorPopup->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextColorPopup ), NULL, this ); - m_fillColorPopup->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onFillColorPopup ), NULL, this ); - m_editTable->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); - + // Disconnect Events + this->Disconnect( wxEVT_KILL_FOCUS, + wxFocusEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onMultiLineTCLostFocus ) ); + m_syntaxHelp->Disconnect( wxEVT_COMMAND_HYPERLINK, + wxHyperlinkEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnFormattingHelp ), NULL, + this ); + m_textColorPopup->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextColorPopup ), NULL, + this ); + m_fillColorPopup->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onFillColorPopup ), NULL, + this ); + m_editTable->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); } diff --git a/eeschema/dialogs/dialog_tablecell_properties_base.h b/eeschema/dialogs/dialog_tablecell_properties_base.h index 9b0c83014f..6ada2096dd 100644 --- a/eeschema/dialogs/dialog_tablecell_properties_base.h +++ b/eeschema/dialogs/dialog_tablecell_properties_base.h @@ -24,6 +24,7 @@ class WX_INFOBAR; #include #include #include +#include #include #include #include @@ -45,61 +46,62 @@ class WX_INFOBAR; /////////////////////////////////////////////////////////////////////////////// class DIALOG_TABLECELL_PROPERTIES_BASE : public DIALOG_SHIM { - private: +private: +protected: + WX_INFOBAR* m_infoBar; + wxStaticText* m_cellTextLabel; + wxStyledTextCtrl* m_cellTextCtrl; + wxHyperlinkCtrl* m_syntaxHelp; + BITMAP_BUTTON* m_hAlignLeft; + BITMAP_BUTTON* m_hAlignCenter; + BITMAP_BUTTON* m_hAlignRight; + wxStaticText* vAlignLabel; + BITMAP_BUTTON* m_vAlignTop; + BITMAP_BUTTON* m_vAlignCenter; + BITMAP_BUTTON* m_vAlignBottom; + wxStaticText* m_styleLabel; + wxCheckBox* m_bold; + wxCheckBox* m_italic; + wxStaticText* m_fontLabel; + FONT_CHOICE* m_fontCtrl; + wxStaticText* m_textSizeLabel; + wxTextCtrl* m_textSizeCtrl; + wxStaticText* m_textSizeUnits; + wxStaticText* m_textColorLabel; + wxSimplebook* m_textColorBook; + wxChoice* m_textColorPopup; + wxPanel* textColorSwatchPanel; + wxPanel* m_panelTextColor; + COLOR_SWATCH* m_textColorSwatch; + wxStaticText* m_fillColorLabel; + wxSimplebook* m_fillColorBook; + wxChoice* m_fillColorPopup; + wxPanel* fillColorSwatchPanel; + wxPanel* m_panelFillColor; + COLOR_SWATCH* m_fillColorSwatch; + wxTextCtrl* m_marginTopCtrl; + wxStaticText* m_marginTopUnits; + wxTextCtrl* m_marginLeftCtrl; + wxTextCtrl* m_marginRightCtrl; + wxTextCtrl* m_marginBottomCtrl; + wxButton* m_editTable; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; - protected: - WX_INFOBAR* m_infoBar; - wxStaticText* m_cellTextLabel; - wxStyledTextCtrl* m_cellTextCtrl; - BITMAP_BUTTON* m_hAlignLeft; - BITMAP_BUTTON* m_hAlignCenter; - BITMAP_BUTTON* m_hAlignRight; - wxStaticText* vAlignLabel; - BITMAP_BUTTON* m_vAlignTop; - BITMAP_BUTTON* m_vAlignCenter; - BITMAP_BUTTON* m_vAlignBottom; - wxStaticText* m_styleLabel; - wxCheckBox* m_bold; - wxCheckBox* m_italic; - wxStaticText* m_fontLabel; - FONT_CHOICE* m_fontCtrl; - wxStaticText* m_textSizeLabel; - wxTextCtrl* m_textSizeCtrl; - wxStaticText* m_textSizeUnits; - wxStaticText* m_textColorLabel; - wxSimplebook* m_textColorBook; - wxChoice* m_textColorPopup; - wxPanel* textColorSwatchPanel; - wxPanel* m_panelTextColor; - COLOR_SWATCH* m_textColorSwatch; - wxStaticText* m_fillColorLabel; - wxSimplebook* m_fillColorBook; - wxChoice* m_fillColorPopup; - wxPanel* fillColorSwatchPanel; - wxPanel* m_panelFillColor; - COLOR_SWATCH* m_fillColorSwatch; - wxTextCtrl* m_marginTopCtrl; - wxStaticText* m_marginTopUnits; - wxTextCtrl* m_marginLeftCtrl; - wxTextCtrl* m_marginRightCtrl; - wxTextCtrl* m_marginBottomCtrl; - wxButton* m_editTable; - wxStdDialogButtonSizer* m_sdbSizer1; - wxButton* m_sdbSizer1OK; - wxButton* m_sdbSizer1Cancel; - - // Virtual event handlers, override them in your derived class - virtual void onMultiLineTCLostFocus( wxFocusEvent& event ) { event.Skip(); } - virtual void onTextColorPopup( wxCommandEvent& event ) { event.Skip(); } - virtual void onFillColorPopup( wxCommandEvent& event ) { event.Skip(); } - virtual void onEditTable( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onMultiLineTCLostFocus( wxFocusEvent& event ) { event.Skip(); } + virtual void OnFormattingHelp( wxHyperlinkEvent& event ) { event.Skip(); } + virtual void onTextColorPopup( wxCommandEvent& event ) { event.Skip(); } + virtual void onFillColorPopup( wxCommandEvent& event ) { event.Skip(); } + virtual void onEditTable( wxCommandEvent& event ) { event.Skip(); } - public: - - DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Table Cell Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~DIALOG_TABLECELL_PROPERTIES_BASE(); +public: + DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, + const wxString& title = _( "Table Cell Properties" ), + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), + long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ); + ~DIALOG_TABLECELL_PROPERTIES_BASE(); }; - diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp index 840fc33711..f6b5c05456 100644 --- a/eeschema/lib_symbol.cpp +++ b/eeschema/lib_symbol.cpp @@ -62,21 +62,14 @@ wxString LIB_SYMBOL::GetShownDescription( int aDepth ) const wxString LIB_SYMBOL::GetShownKeyWords( int aDepth ) const { - static EXPRESSION_EVALUATOR evaluator; - wxString text = GetKeyWords(); - std::function libSymbolResolver = - [&]( wxString* token ) -> bool - { - return ResolveTextVar( token, aDepth + 1 ); - }; + std::function libSymbolResolver = [&]( wxString* token ) -> bool + { + return ResolveTextVar( token, aDepth + 1 ); + }; - while( text.Contains( wxT( "${" ) ) && aDepth++ <= ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &libSymbolResolver ); - - if( text.Contains( wxT( "@{" ) ) ) - text = evaluator.Evaluate( text ); + text = ResolveTextVars( text, &libSymbolResolver, aDepth ); return text; } @@ -110,7 +103,7 @@ std::vector LIB_SYMBOL::GetSearchTerms() void LIB_SYMBOL::GetChooserFields( std::map& aColumnMap ) { - for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD* field = static_cast( &item ); @@ -129,9 +122,7 @@ bool operator<( const LIB_SYMBOL& aItem1, const LIB_SYMBOL& aItem2 ) /// http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared struct null_deleter { - void operator()(void const *) const - { - } + void operator()( void const* ) const {} }; @@ -139,27 +130,26 @@ LIB_SYMBOL::LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent, LEGACY_SYMBO SYMBOL( LIB_SYMBOL_T ), m_me( this, null_deleter() ) { - m_lastModDate = 0; - m_unitCount = 1; - m_demorgan = false; - m_pinNameOffset = schIUScale.MilsToIU( DEFAULT_PIN_NAME_OFFSET ); - m_options = ENTRY_NORMAL; - m_unitsLocked = false; + m_lastModDate = 0; + m_unitCount = 1; + m_demorgan = false; + m_pinNameOffset = schIUScale.MilsToIU( DEFAULT_PIN_NAME_OFFSET ); + m_options = ENTRY_NORMAL; + m_unitsLocked = false; m_duplicatePinNumbersAreJumpers = false; - auto addField = - [&]( FIELD_T id, bool visible ) - { - SCH_FIELD* field = new SCH_FIELD( this, id ); - field->SetVisible( visible ); - m_drawings[SCH_FIELD_T].push_back( field ); - }; + auto addField = [&]( FIELD_T id, bool visible ) + { + SCH_FIELD* field = new SCH_FIELD( this, id ); + field->SetVisible( visible ); + m_drawings[SCH_FIELD_T].push_back( field ); + }; // construct only the mandatory fields - addField( FIELD_T::REFERENCE, true ); - addField( FIELD_T::VALUE, true ); - addField( FIELD_T::FOOTPRINT, false ); - addField( FIELD_T::DATASHEET, false ); + addField( FIELD_T::REFERENCE, true ); + addField( FIELD_T::VALUE, true ); + addField( FIELD_T::FOOTPRINT, false ); + addField( FIELD_T::DATASHEET, false ); addField( FIELD_T::DESCRIPTION, false ); SetName( aName ); @@ -173,16 +163,16 @@ LIB_SYMBOL::LIB_SYMBOL( const LIB_SYMBOL& aSymbol, LEGACY_SYMBOL_LIB* aLibrary ) EMBEDDED_FILES( aSymbol ), m_me( this, null_deleter() ) { - m_library = aLibrary; - m_name = aSymbol.m_name; - m_fpFilters = wxArrayString( aSymbol.m_fpFilters ); - m_unitCount = aSymbol.m_unitCount; - m_demorgan = aSymbol.m_demorgan; - m_unitsLocked = aSymbol.m_unitsLocked; - m_lastModDate = aSymbol.m_lastModDate; - m_options = aSymbol.m_options; - m_libId = aSymbol.m_libId; - m_keyWords = aSymbol.m_keyWords; + m_library = aLibrary; + m_name = aSymbol.m_name; + m_fpFilters = wxArrayString( aSymbol.m_fpFilters ); + m_unitCount = aSymbol.m_unitCount; + m_demorgan = aSymbol.m_demorgan; + m_unitsLocked = aSymbol.m_unitsLocked; + m_lastModDate = aSymbol.m_lastModDate; + m_options = aSymbol.m_options; + m_libId = aSymbol.m_libId; + m_keyWords = aSymbol.m_keyWords; m_jumperPinGroups = aSymbol.m_jumperPinGroups; m_duplicatePinNumbersAreJumpers = aSymbol.m_duplicatePinNumbersAreJumpers; @@ -222,16 +212,16 @@ const LIB_SYMBOL& LIB_SYMBOL::operator=( const LIB_SYMBOL& aSymbol ) SYMBOL::operator=( aSymbol ); - m_library = aSymbol.m_library; - m_name = aSymbol.m_name; - m_fpFilters = wxArrayString( aSymbol.m_fpFilters ); - m_unitCount = aSymbol.m_unitCount; - m_demorgan = aSymbol.m_demorgan; + m_library = aSymbol.m_library; + m_name = aSymbol.m_name; + m_fpFilters = wxArrayString( aSymbol.m_fpFilters ); + m_unitCount = aSymbol.m_unitCount; + m_demorgan = aSymbol.m_demorgan; m_unitsLocked = aSymbol.m_unitsLocked; m_lastModDate = aSymbol.m_lastModDate; - m_options = aSymbol.m_options; - m_libId = aSymbol.m_libId; - m_keyWords = aSymbol.m_keyWords; + m_options = aSymbol.m_options; + m_libId = aSymbol.m_libId; + m_keyWords = aSymbol.m_keyWords; m_jumperPinGroups = aSymbol.m_jumperPinGroups; m_duplicatePinNumbersAreJumpers = aSymbol.m_duplicatePinNumbersAreJumpers; @@ -331,7 +321,7 @@ wxString LIB_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) cons else if( IsMultiBodyStyle() ) { if( aBodyStyle <= (int) m_bodyStyleNames.size() ) - return m_bodyStyleNames[aBodyStyle-1]; + return m_bodyStyleNames[aBodyStyle - 1]; } return wxT( "?" ); @@ -354,9 +344,9 @@ void LIB_SYMBOL::SetParent( LIB_SYMBOL* aParent ) } -std::unique_ptr< LIB_SYMBOL > LIB_SYMBOL::Flatten() const +std::unique_ptr LIB_SYMBOL::Flatten() const { - std::unique_ptr< LIB_SYMBOL > retv; + std::unique_ptr retv; if( IsDerived() ) { @@ -381,7 +371,7 @@ std::unique_ptr< LIB_SYMBOL > LIB_SYMBOL::Flatten() const } // Grab all the rest of derived symbol fields. - for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { const SCH_FIELD* field = static_cast( &item ); @@ -394,11 +384,11 @@ std::unique_ptr< LIB_SYMBOL > LIB_SYMBOL::Flatten() const SCH_FIELD* parentField = retv->GetField( field->GetName() ); - if( !parentField ) // Derived symbol field does not exist in parent symbol. + if( !parentField ) // Derived symbol field does not exist in parent symbol. { retv->AddDrawItem( newField ); } - else // Derived symbol field overrides the parent symbol field. + else // Derived symbol field overrides the parent symbol field. { retv->RemoveDrawItem( parentField ); retv->AddDrawItem( newField ); @@ -533,8 +523,7 @@ bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const if( field.GetId() == FIELD_T::FOOTPRINT ) footprint = field.GetShownText( nullptr, false, aDepth + 1 ); - if( token->IsSameAs( field.GetCanonicalName().Upper() ) - || token->IsSameAs( field.GetName(), false ) ) + if( token->IsSameAs( field.GetCanonicalName().Upper() ) || token->IsSameAs( field.GetName(), false ) ) { *token = field.GetShownText( nullptr, false, aDepth + 1 ); return true; @@ -543,12 +532,9 @@ bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const } // Consider missing simulation fields as empty, not un-resolved - if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) - || token->IsSameAs( wxT( "SIM.TYPE" ) ) - || token->IsSameAs( wxT( "SIM.PINS" ) ) - || token->IsSameAs( wxT( "SIM.PARAMS" ) ) - || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) - || token->IsSameAs( wxT( "SIM.NAME" ) ) ) + if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) ) + || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) ) + || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) ) { *token = wxEmptyString; return true; @@ -559,7 +545,7 @@ bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const wxArrayString parts = wxSplit( footprint, ':' ); if( parts.Count() > 0 ) - *token = parts[ 0 ]; + *token = parts[0]; else *token = wxEmptyString; @@ -570,7 +556,7 @@ bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const wxArrayString parts = wxSplit( footprint, ':' ); if( parts.Count() > 1 ) - *token = parts[ std::min( 1, (int) parts.size() - 1 ) ]; + *token = parts[std::min( 1, (int) parts.size() - 1 )]; else *token = wxEmptyString; @@ -621,8 +607,8 @@ bool LIB_SYMBOL::ResolveTextVar( wxString* token, int aDepth ) const } -void LIB_SYMBOL::Plot( PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed ) +void LIB_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) { wxASSERT( aPlotter != nullptr ); @@ -635,7 +621,7 @@ void LIB_SYMBOL::Plot( PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS& if( aDimmed ) { - color.Desaturate( ); + color.Desaturate(); color = color.Mix( bg, 0.5f ); } @@ -663,8 +649,8 @@ void LIB_SYMBOL::Plot( PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS& } -void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, + int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) { wxASSERT( aPlotter != nullptr ); @@ -677,13 +663,13 @@ void LIB_SYMBOL::PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT if( aDimmed ) { - color.Desaturate( ); + color.Desaturate(); color = color.Mix( bg, 0.5f ); } aPlotter->SetColor( color ); - for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD& field = static_cast( item ); @@ -756,7 +742,7 @@ void LIB_SYMBOL::RemoveDrawItem( SCH_ITEM* aItem ) return; } - LIB_ITEMS& items = m_drawings[ aItem->Type() ]; + LIB_ITEMS& items = m_drawings[aItem->Type()]; for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ ) { @@ -809,10 +795,12 @@ std::vector LIB_SYMBOL::GetGraphicalPins( int aUnit, int aBodyStyle ) // TODO: get rid of const_cast. (It used to be a C-style cast so was less noticeable.) SCH_PIN* pin = const_cast( static_cast( &item ) ); - wxLogTrace( traceStackedPins, - wxString::Format( "GetGraphicalPins: lib='%s' unit=%d body=%d -> include pin name='%s' number='%s' shownNum='%s'", - GetLibId().Format().wx_str(), aUnit, aBodyStyle, - pin->GetName(), pin->GetNumber(), pin->GetShownNumber() ) ); + wxLogTrace( + traceStackedPins, + wxString::Format( + "GetGraphicalPins: lib='%s' unit=%d body=%d -> include pin name='%s' number='%s' shownNum='%s'", + GetLibId().Format().wx_str(), aUnit, aBodyStyle, pin->GetName(), pin->GetNumber(), + pin->GetShownNumber() ) ); pins.push_back( pin ); } @@ -883,7 +871,7 @@ std::vector LIB_SYMBOL::GetLogicalPins( int aUnit, int for( SCH_PIN* pin : GetGraphicalPins( aUnit, aBodyStyle ) ) { - bool valid = false; + bool valid = false; std::vector expanded = pin->GetStackedPinNumbers( &valid ); if( valid && !expanded.empty() ) @@ -892,16 +880,14 @@ std::vector LIB_SYMBOL::GetLogicalPins( int aUnit, int { out.push_back( LOGICAL_PIN{ pin, num } ); wxLogTrace( traceStackedPins, - wxString::Format( "GetLogicalPins: base='%s' -> '%s'", - pin->GetShownNumber(), num ) ); + wxString::Format( "GetLogicalPins: base='%s' -> '%s'", pin->GetShownNumber(), num ) ); } } else { out.push_back( LOGICAL_PIN{ pin, pin->GetShownNumber() } ); wxLogTrace( traceStackedPins, - wxString::Format( "GetLogicalPins: base='%s' (no expansion)", - pin->GetShownNumber() ) ); + wxString::Format( "GetLogicalPins: base='%s' (no expansion)", pin->GetShownNumber() ) ); } } @@ -915,7 +901,7 @@ int LIB_SYMBOL::GetPinCount() for( SCH_PIN* pin : GetGraphicalPins( 0 /* all units */, 1 /* single body style */ ) ) { - int pinCount = pin->GetStackedPinCount(); + int pinCount = pin->GetStackedPinCount(); count += pinCount; } @@ -938,8 +924,8 @@ SCH_PIN* LIB_SYMBOL::GetPin( const wxString& aNumber, int aUnit, int aBodyStyle } -bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, - bool aTestType, bool aTestOrientation, bool aTestLength ) const +bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, bool aTestNames, bool aTestType, + bool aTestOrientation, bool aTestLength ) const { for( const SCH_PIN* pin : GetGraphicalPins() ) { @@ -975,8 +961,7 @@ bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, continue; // Same orientation? - if( aTestOrientation - && ( pin->GetOrientation() != otherPin->GetOrientation() ) ) + if( aTestOrientation && ( pin->GetOrientation() != otherPin->GetOrientation() ) ) continue; // Same length? @@ -984,7 +969,7 @@ bool LIB_SYMBOL::PinsConflictWith( const LIB_SYMBOL& aOtherPart, bool aTestNums, continue; foundMatch = true; - break; // Match found so search is complete. + break; // Match found so search is complete. } if( !foundMatch ) @@ -1009,7 +994,7 @@ std::vector LIB_SYMBOL::GetPins() const const BOX2I LIB_SYMBOL::GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields, bool aIgnoreLabelsOnInvisiblePins ) const { - BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works + BOX2I bBox; // Start with a fresh BOX2I so the Merge algorithm works if( std::shared_ptr parent = m_parent.lock() ) bBox = parent->GetUnitBoundingBox( aUnit, aBodyStyle, aIgnoreHiddenFields, aIgnoreLabelsOnInvisiblePins ); @@ -1089,7 +1074,7 @@ const BOX2I LIB_SYMBOL::GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aInc void LIB_SYMBOL::deleteAllFields() { - m_drawings[ SCH_FIELD_T ].clear(); + m_drawings[SCH_FIELD_T].clear(); } @@ -1118,7 +1103,7 @@ void LIB_SYMBOL::SetFields( const std::vector& aFieldsList ) void LIB_SYMBOL::GetFields( std::vector& aList, bool aVisibleOnly ) const { - for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { const SCH_FIELD* field = static_cast( &item ); @@ -1152,9 +1137,9 @@ void LIB_SYMBOL::CopyFields( std::vector& aList ) int LIB_SYMBOL::GetNextFieldOrdinal() const { - int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id + int ordinal = 42; // Arbitrarily larger than any mandatory FIELD_T id - for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) ordinal = std::max( ordinal, static_cast( &item )->GetOrdinal() + 1 ); return ordinal; @@ -1163,7 +1148,7 @@ int LIB_SYMBOL::GetNextFieldOrdinal() const const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const { - for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { const SCH_FIELD* field = static_cast( &item ); @@ -1177,7 +1162,7 @@ const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) { - for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD* field = static_cast( &item ); @@ -1191,7 +1176,7 @@ SCH_FIELD* LIB_SYMBOL::GetField( FIELD_T aFieldType ) const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const { - for( const SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( const SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { const SCH_FIELD& field = static_cast( item ); @@ -1205,7 +1190,7 @@ const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) const SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) { - for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD& field = static_cast( item ); @@ -1219,7 +1204,7 @@ SCH_FIELD* LIB_SYMBOL::GetField( const wxString& aFieldName ) SCH_FIELD* LIB_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) { - for( SCH_ITEM& item : m_drawings[ SCH_FIELD_T ] ) + for( SCH_ITEM& item : m_drawings[SCH_FIELD_T] ) { SCH_FIELD& field = static_cast( item ); @@ -1368,14 +1353,13 @@ void LIB_SYMBOL::ClearEditFlags() } -SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, - const VECTOR2I& aPoint ) +SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint ) { for( SCH_ITEM& item : m_drawings ) { if( ( aUnit && item.m_unit && aUnit != item.m_unit ) - || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle ) - || ( item.Type() != aType && aType != TYPE_NOT_INIT ) ) + || ( aBodyStyle && item.m_bodyStyle && aBodyStyle != item.m_bodyStyle ) + || ( item.Type() != aType && aType != TYPE_NOT_INIT ) ) { continue; } @@ -1388,8 +1372,8 @@ SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, } -SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, - const VECTOR2I& aPoint, const TRANSFORM& aTransform ) +SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint, + const TRANSFORM& aTransform ) { /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const * VECTOR2I& pt ) to search items. @@ -1408,8 +1392,7 @@ SCH_ITEM* LIB_SYMBOL::LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, } -INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, - const std::vector& aScanTypes ) +INSPECT_RESULT LIB_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector& aScanTypes ) { // The part itself is never inspected, only its children for( SCH_ITEM& item : m_drawings ) @@ -1496,7 +1479,7 @@ void LIB_SYMBOL::SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool a { if( aDuplicateDrawItems || aDuplicatePins ) { - std::vector tmp; // Temporarily store the duplicated pins here. + std::vector tmp; // Temporarily store the duplicated pins here. for( SCH_ITEM& item : m_drawings ) { @@ -1543,9 +1526,8 @@ std::vector LIB_SYMBOL::GetUnitDrawItems( int aUnit, int aBodyStyle ) if( item.Type() == SCH_FIELD_T ) continue; - if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) - || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle ) - || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) ) + if( ( aBodyStyle == -1 && item.GetUnit() == aUnit ) || ( aUnit == -1 && item.GetBodyStyle() == aBodyStyle ) + || ( aUnit == item.GetUnit() && aBodyStyle == item.GetBodyStyle() ) ) { unitItems.push_back( &item ); } @@ -1568,10 +1550,10 @@ std::vector LIB_SYMBOL::GetUnitDrawItems() int bodyStyle = item.GetBodyStyle(); auto it = std::find_if( units.begin(), units.end(), - [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a ) - { - return a.m_unit == unit && a.m_bodyStyle == bodyStyle; - } ); + [unit, bodyStyle]( const LIB_SYMBOL_UNIT& a ) + { + return a.m_unit == unit && a.m_bodyStyle == bodyStyle; + } ); if( it == units.end() ) { @@ -1591,9 +1573,11 @@ std::vector LIB_SYMBOL::GetUnitDrawItems() } - - -#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); } +#define REPORT( msg ) \ + { \ + if( aReporter ) \ + aReporter->Report( msg ); \ + } #define ITEM_DESC( item ) ( item )->GetItemDescription( &unitsProvider, false ) int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aReporter ) const @@ -1647,11 +1631,11 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it ) { if( it->Type() == SCH_SHAPE_T ) - aShapes.insert( &(*it) ); + aShapes.insert( &( *it ) ); else if( it->Type() == SCH_FIELD_T ) - aFields.insert( static_cast( &(*it) ) ); + aFields.insert( static_cast( &( *it ) ) ); else if( it->Type() == SCH_PIN_T ) - aPins.insert( static_cast( &(*it) ) ); + aPins.insert( static_cast( &( *it ) ) ); } std::set bShapes; @@ -1661,11 +1645,11 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR for( auto it = aRhs.m_drawings.begin(); it != aRhs.m_drawings.end(); ++it ) { if( it->Type() == SCH_SHAPE_T ) - bShapes.insert( &(*it) ); + bShapes.insert( &( *it ) ); else if( it->Type() == SCH_FIELD_T ) - bFields.insert( static_cast( &(*it) ) ); + bFields.insert( static_cast( &( *it ) ) ); else if( it->Type() == SCH_PIN_T ) - bPins.insert( static_cast( &(*it) ) ); + bPins.insert( static_cast( &( *it ) ) ); } if( int tmp = static_cast( aShapes.size() - bShapes.size() ) ) @@ -1680,11 +1664,10 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR { for( auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ ) { - if( int tmp2 = (*aIt)->compare( *(*bIt), aCompareFlags ) ) + if( int tmp2 = ( *aIt )->compare( *( *bIt ), aCompareFlags ) ) { retv = tmp2; - REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), - ITEM_DESC( *aIt ), + REPORT( wxString::Format( _( "Graphic item differs: %s; %s." ), ITEM_DESC( *aIt ), ITEM_DESC( *bIt ) ) ); if( !aReporter ) @@ -1708,9 +1691,7 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR else if( int tmp = aPin->SCH_ITEM::compare( *bPin, aCompareFlags ) ) { retv = tmp; - REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), - aPin->GetNumber(), - ITEM_DESC( aPin ), + REPORT( wxString::Format( _( "Pin %s differs: %s; %s" ), aPin->GetNumber(), ITEM_DESC( aPin ), ITEM_DESC( bPin ) ) ); if( !aReporter ) @@ -1770,10 +1751,8 @@ int LIB_SYMBOL::Compare( const LIB_SYMBOL& aRhs, int aCompareFlags, REPORTER* aR if( tmp != 0 ) { retv = tmp; - REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), - aField->GetName( false ), - ITEM_DESC( aField ), - ITEM_DESC( bField ) ) ); + REPORT( wxString::Format( _( "Field '%s' differs: %s; %s." ), aField->GetName( false ), + ITEM_DESC( aField ), ITEM_DESC( bField ) ) ); if( !aReporter ) return retv; @@ -2032,10 +2011,9 @@ std::set LIB_SYMBOL::GetFonts() const if( auto* font = text.GetFont(); font && !font->IsStroke() ) { auto* outline = static_cast( font ); - auto permission = outline->GetEmbeddingPermission(); + auto permission = outline->GetEmbeddingPermission(); - if( permission == EMBEDDING_PERMISSION::EDITABLE - || permission == EMBEDDING_PERMISSION::INSTALLABLE ) + if( permission == EMBEDDING_PERMISSION::EDITABLE || permission == EMBEDDING_PERMISSION::INSTALLABLE ) { fonts.insert( outline ); } @@ -2080,93 +2058,97 @@ static struct LIB_SYMBOL_DESC const wxString groupFields = _HKI( "Fields" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Reference" ), - &LIB_SYMBOL::SetRefProp, &LIB_SYMBOL::GetRefProp ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Value" ), - &LIB_SYMBOL::SetValueProp, &LIB_SYMBOL::GetValueProp ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Footprint" ), - &LIB_SYMBOL::SetFootprintProp, &LIB_SYMBOL::GetFootprintProp ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Datasheet" ), - &LIB_SYMBOL::SetDatasheetProp, &LIB_SYMBOL::GetDatasheetProp ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Keywords" ), - &LIB_SYMBOL::SetKeywordsProp, &LIB_SYMBOL::GetKeywordsProp ), - groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Reference" ), &LIB_SYMBOL::SetRefProp, + &LIB_SYMBOL::GetRefProp ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Value" ), &LIB_SYMBOL::SetValueProp, + &LIB_SYMBOL::GetValueProp ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Footprint" ), &LIB_SYMBOL::SetFootprintProp, + &LIB_SYMBOL::GetFootprintProp ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Datasheet" ), &LIB_SYMBOL::SetDatasheetProp, + &LIB_SYMBOL::GetDatasheetProp ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Keywords" ), &LIB_SYMBOL::SetKeywordsProp, + &LIB_SYMBOL::GetKeywordsProp ), + groupFields ); const wxString groupSymbolDef = _HKI( "Symbol Definition" ); propMgr.AddProperty( new PROPERTY( _HKI( "Define as Power Symbol" ), - &LIB_SYMBOL::SetPowerSymbolProp, &LIB_SYMBOL::GetPowerSymbolProp ), - groupSymbolDef ); + &LIB_SYMBOL::SetPowerSymbolProp, + &LIB_SYMBOL::GetPowerSymbolProp ), + groupSymbolDef ); propMgr.AddProperty( new PROPERTY( _HKI( "Define as Local Power Symbol" ), - &LIB_SYMBOL::SetLocalPowerSymbolProp, &LIB_SYMBOL::GetLocalPowerSymbolProp ), - groupSymbolDef ); + &LIB_SYMBOL::SetLocalPowerSymbolProp, + &LIB_SYMBOL::GetLocalPowerSymbolProp ), + groupSymbolDef ); const wxString groupPinDisplay = _HKI( "Pin Display" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Show Pin Number" ), - &SYMBOL::SetShowPinNumbers, &SYMBOL::GetShowPinNumbers ), - groupPinDisplay ); - propMgr.AddProperty( new PROPERTY( _HKI( "Show Pin Name" ), - &SYMBOL::SetShowPinNames, &SYMBOL::GetShowPinNames ), - groupPinDisplay ); + propMgr.AddProperty( new PROPERTY( _HKI( "Show Pin Number" ), &SYMBOL::SetShowPinNumbers, + &SYMBOL::GetShowPinNumbers ), + groupPinDisplay ); + propMgr.AddProperty( new PROPERTY( _HKI( "Show Pin Name" ), &SYMBOL::SetShowPinNames, + &SYMBOL::GetShowPinNames ), + groupPinDisplay ); propMgr.AddProperty( new PROPERTY( _HKI( "Place Pin Names Inside" ), - &LIB_SYMBOL::SetPinNamesInsideProp, &LIB_SYMBOL::GetPinNamesInsideProp ), - groupPinDisplay ); - propMgr.AddProperty( new PROPERTY( _HKI( "Pin Name Position Offset" ), - &SYMBOL::SetPinNameOffset, &SYMBOL::GetPinNameOffset, - PROPERTY_DISPLAY::PT_SIZE ), - groupPinDisplay ); + &LIB_SYMBOL::SetPinNamesInsideProp, + &LIB_SYMBOL::GetPinNamesInsideProp ), + groupPinDisplay ); + propMgr.AddProperty( new PROPERTY( _HKI( "Pin Name Position Offset" ), &SYMBOL::SetPinNameOffset, + &SYMBOL::GetPinNameOffset, PROPERTY_DISPLAY::PT_SIZE ), + groupPinDisplay ); const wxString groupAttributes = _HKI( "Attributes" ); propMgr.AddProperty( new PROPERTY( _HKI( "Exclude from Simulation" ), - &LIB_SYMBOL::SetExcludedFromSimProp, &LIB_SYMBOL::GetExcludedFromSimProp ), - groupAttributes ); - propMgr.AddProperty( new PROPERTY( _HKI( "Exclude from Board" ), - &SYMBOL::SetExcludedFromBoard, &SYMBOL::GetExcludedFromBoard ), - groupAttributes ); + &LIB_SYMBOL::SetExcludedFromSimProp, + &LIB_SYMBOL::GetExcludedFromSimProp ), + groupAttributes ); + propMgr.AddProperty( new PROPERTY( _HKI( "Exclude from Board" ), &SYMBOL::SetExcludedFromBoard, + &SYMBOL::GetExcludedFromBoard ), + groupAttributes ); propMgr.AddProperty( new PROPERTY( _HKI( "Exclude from Bill of Materials" ), - &LIB_SYMBOL::SetExcludedFromBOMProp, &LIB_SYMBOL::GetExcludedFromBOMProp ), - groupAttributes ); + &LIB_SYMBOL::SetExcludedFromBOMProp, + &LIB_SYMBOL::GetExcludedFromBOMProp ), + groupAttributes ); const wxString groupUnits = _HKI( "Units and Body Styles" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Number of Symbol Units" ), - &LIB_SYMBOL::SetUnitProp, &LIB_SYMBOL::GetUnitProp ), - groupUnits ); + propMgr.AddProperty( new PROPERTY( _HKI( "Number of Symbol Units" ), &LIB_SYMBOL::SetUnitProp, + &LIB_SYMBOL::GetUnitProp ), + groupUnits ); propMgr.AddProperty( new PROPERTY( _HKI( "Units are Interchangeable" ), - &LIB_SYMBOL::SetUnitsInterchangeableProp, &LIB_SYMBOL::GetUnitsInterchangeableProp ), - groupUnits ); + &LIB_SYMBOL::SetUnitsInterchangeableProp, + &LIB_SYMBOL::GetUnitsInterchangeableProp ), + groupUnits ); - auto multiBodyStyle = - [=]( INSPECTABLE* aItem ) -> bool - { - if( LIB_SYMBOL* symbol = dynamic_cast( aItem ) ) - return symbol->IsMultiBodyStyle(); + auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool + { + if( LIB_SYMBOL* symbol = dynamic_cast( aItem ) ) + return symbol->IsMultiBodyStyle(); - return false; - }; + return false; + }; - propMgr.AddProperty( new PROPERTY( _HKI( "Body Styles" ), - &LIB_SYMBOL::SetBodyStyleProp, &LIB_SYMBOL::GetBodyStyleProp ), - groupUnits ) + propMgr.AddProperty( new PROPERTY( _HKI( "Body Styles" ), &LIB_SYMBOL::SetBodyStyleProp, + &LIB_SYMBOL::GetBodyStyleProp ), + groupUnits ) .SetAvailableFunc( multiBodyStyle ) - .SetChoicesFunc( []( INSPECTABLE* aItem ) - { - wxPGChoices choices; + .SetChoicesFunc( + []( INSPECTABLE* aItem ) + { + wxPGChoices choices; - if( LIB_SYMBOL* symbol = dynamic_cast( aItem ) ) - { - for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ ) - choices.Add( symbol->GetBodyStyleDescription( ii, false ) ); - } + if( LIB_SYMBOL* symbol = dynamic_cast( aItem ) ) + { + for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ ) + choices.Add( symbol->GetBodyStyleDescription( ii, false ) ); + } - return choices; - } ); + return choices; + } ); } } _LIB_SYMBOL_DESC; - diff --git a/eeschema/sch_field.cpp b/eeschema/sch_field.cpp index 0dc560e531..776fb09c14 100644 --- a/eeschema/sch_field.cpp +++ b/eeschema/sch_field.cpp @@ -27,7 +27,7 @@ #include #include -#include // for ExpandTextVars +#include // for ExpandTextVars #include #include #include @@ -70,7 +70,7 @@ SCH_FIELD::SCH_FIELD( SCH_ITEM* aParent, FIELD_T aFieldId, const wxString& aName else SetName( GetDefaultFieldName( aFieldId, DO_TRANSLATE ) ); - setId( aFieldId ); // will also set the layer + setId( aFieldId ); // will also set the layer SetVisible( true ); if( aParent && aParent->Schematic() ) @@ -105,15 +105,15 @@ SCH_FIELD::SCH_FIELD( const SCH_FIELD& aField ) : SCH_ITEM( aField ), EDA_TEXT( aField ) { - m_private = aField.m_private; - setId( aField.m_id ); // will also set the layer - m_ordinal = aField.m_ordinal; - m_name = aField.m_name; - m_showName = aField.m_showName; - m_allowAutoPlace = aField.m_allowAutoPlace; + m_private = aField.m_private; + setId( aField.m_id ); // will also set the layer + m_ordinal = aField.m_ordinal; + m_name = aField.m_name; + m_showName = aField.m_showName; + m_allowAutoPlace = aField.m_allowAutoPlace; m_isGeneratedField = aField.m_isGeneratedField; - m_autoAdded = aField.m_autoAdded; - m_showInChooser = aField.m_showInChooser; + m_autoAdded = aField.m_autoAdded; + m_showInChooser = aField.m_showInChooser; m_renderCache.clear(); @@ -136,12 +136,12 @@ SCH_FIELD& SCH_FIELD::operator=( const SCH_FIELD& aField ) { EDA_TEXT::operator=( aField ); - m_private = aField.m_private; - setId( aField.m_id ); // will also set the layer - m_ordinal = aField.m_ordinal; - m_name = aField.m_name; - m_showName = aField.m_showName; - m_allowAutoPlace = aField.m_allowAutoPlace; + m_private = aField.m_private; + setId( aField.m_id ); // will also set the layer + m_ordinal = aField.m_ordinal; + m_name = aField.m_name; + m_showName = aField.m_showName; + m_allowAutoPlace = aField.m_allowAutoPlace; m_isGeneratedField = aField.m_isGeneratedField; m_renderCache.clear(); @@ -190,61 +190,56 @@ wxString SCH_FIELD::GetShownName() const wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const { - std::function libSymbolResolver = - [&]( wxString* token ) -> bool - { - LIB_SYMBOL* symbol = static_cast( m_parent ); - return symbol->ResolveTextVar( token, aDepth + 1 ); - }; + std::function libSymbolResolver = [&]( wxString* token ) -> bool + { + LIB_SYMBOL* symbol = static_cast( m_parent ); + return symbol->ResolveTextVar( token, aDepth + 1 ); + }; - std::function symbolResolver = - [&]( wxString* token ) -> bool - { - SCH_SYMBOL* symbol = static_cast( m_parent ); - return symbol->ResolveTextVar( aPath, token, aDepth + 1 ); - }; + std::function symbolResolver = [&]( wxString* token ) -> bool + { + SCH_SYMBOL* symbol = static_cast( m_parent ); + return symbol->ResolveTextVar( aPath, token, aDepth + 1 ); + }; - std::function schematicResolver = - [&]( wxString* token ) -> bool - { - if( !aPath ) - return false; + std::function schematicResolver = [&]( wxString* token ) -> bool + { + if( !aPath ) + return false; - if( SCHEMATIC* schematic = Schematic() ) - return schematic->ResolveTextVar( aPath, token, aDepth + 1 ); + if( SCHEMATIC* schematic = Schematic() ) + return schematic->ResolveTextVar( aPath, token, aDepth + 1 ); - return false; - }; + return false; + }; - std::function sheetResolver = - [&]( wxString* token ) -> bool - { - if( !aPath ) - return false; + std::function sheetResolver = [&]( wxString* token ) -> bool + { + if( !aPath ) + return false; - SCH_SHEET* sheet = static_cast( m_parent ); + SCH_SHEET* sheet = static_cast( m_parent ); - SCHEMATIC* schematic = Schematic(); - SCH_SHEET_PATH path = *aPath; - path.push_back( sheet ); + SCHEMATIC* schematic = Schematic(); + SCH_SHEET_PATH path = *aPath; + path.push_back( sheet ); - bool retval = sheet->ResolveTextVar( &path, token, aDepth + 1 ); + bool retval = sheet->ResolveTextVar( &path, token, aDepth + 1 ); - if( schematic ) - retval |= schematic->ResolveTextVar( &path, token, aDepth + 1 ); + if( schematic ) + retval |= schematic->ResolveTextVar( &path, token, aDepth + 1 ); - return retval; - }; + return retval; + }; - std::function labelResolver = - [&]( wxString* token ) -> bool - { - if( !aPath ) - return false; + std::function labelResolver = [&]( wxString* token ) -> bool + { + if( !aPath ) + return false; - SCH_LABEL_BASE* label = static_cast( m_parent ); - return label->ResolveTextVar( aPath, token, aDepth + 1 ); - }; + SCH_LABEL_BASE* label = static_cast( m_parent ); + return label->ResolveTextVar( aPath, token, aDepth + 1 ); + }; wxString variantName; @@ -258,30 +253,35 @@ wxString SCH_FIELD::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraT if( HasTextVars() ) { - while( text.Contains( wxT( "${" ) ) && aDepth++ <= ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) + // Create a unified resolver that delegates to the appropriate resolver based on parent type + std::function fieldResolver = [&]( wxString* token ) -> bool { + bool resolved = false; + if( m_parent && m_parent->Type() == LIB_SYMBOL_T ) - text = ExpandTextVars( text, &libSymbolResolver ); + resolved = libSymbolResolver( token ); else if( m_parent && m_parent->Type() == SCH_SYMBOL_T ) - text = ExpandTextVars( text, &symbolResolver ); + resolved = symbolResolver( token ); else if( m_parent && m_parent->Type() == SCH_SHEET_T ) - text = ExpandTextVars( text, &sheetResolver ); + resolved = sheetResolver( token ); else if( m_parent && m_parent->IsType( labelTypes ) ) - text = ExpandTextVars( text, &labelResolver ); + resolved = labelResolver( token ); else if( Schematic() ) { - text = ExpandTextVars( text, &Schematic()->Project() ); - text = ExpandTextVars( text, &schematicResolver ); + // Project-level and schematic-level variables + resolved = Schematic()->Project().TextVarResolver( token ); + resolved |= schematicResolver( token ); } - } + + return resolved; + }; + + text = ResolveTextVars( text, &fieldResolver, aDepth ); } if( m_id == FIELD_T::SHEET_FILENAME && aAllowExtraText && !IsNameShown() ) text = _( "File:" ) + wxS( " " ) + text; - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); - return text; } @@ -292,11 +292,8 @@ wxString SCH_FIELD::GetShownText( bool aAllowExtraText, int aDepth ) const { const SCH_SHEET_PATH& currentSheet = schematic->CurrentSheet(); wxLogTrace( traceSchFieldRendering, - "GetShownText (no path arg): field=%s, current sheet path='%s', size=%zu, empty=%d", - GetName(), - currentSheet.Path().AsString(), - currentSheet.size(), - currentSheet.empty() ? 1 : 0 ); + "GetShownText (no path arg): field=%s, current sheet path='%s', size=%zu, empty=%d", GetName(), + currentSheet.Path().AsString(), currentSheet.size(), currentSheet.empty() ? 1 : 0 ); return GetShownText( ¤tSheet, aAllowExtraText, aDepth ); } else @@ -351,8 +348,7 @@ void SCH_FIELD::ClearRenderCache() std::vector>* -SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forPosition, - TEXT_ATTRIBUTES& aAttrs ) const +SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forPosition, TEXT_ATTRIBUTES& aAttrs ) const { KIFONT::FONT* font = GetDrawFont( nullptr ); @@ -364,8 +360,7 @@ SCH_FIELD::GetRenderCache( const wxString& forResolvedText, const VECTOR2I& forP { m_renderCache.clear(); - outlineFont->GetLinesAsGlyphs( &m_renderCache, forResolvedText, forPosition, aAttrs, - GetFontMetrics() ); + outlineFont->GetLinesAsGlyphs( &m_renderCache, forResolvedText, forPosition, aAttrs, GetFontMetrics() ); m_renderCachePos = forPosition; m_renderCacheValid = true; @@ -448,8 +443,7 @@ SCH_LAYER_ID SCH_FIELD::GetDefaultLayer() const { if( m_parent && m_parent->Type() == SCH_LABEL_T ) { - if( GetCanonicalName() == wxT( "Netclass" ) - || GetCanonicalName() == wxT( "Component Class" ) ) + if( GetCanonicalName() == wxT( "Netclass" ) || GetCanonicalName() == wxT( "Component Class" ) ) { return LAYER_NETCLASS_REFS; } @@ -457,13 +451,13 @@ SCH_LAYER_ID SCH_FIELD::GetDefaultLayer() const switch( m_id ) { - case FIELD_T::REFERENCE: return LAYER_REFERENCEPART; - case FIELD_T::VALUE: return LAYER_VALUEPART; - case FIELD_T::SHEET_NAME: return LAYER_SHEETNAME; - case FIELD_T::SHEET_FILENAME: return LAYER_SHEETFILENAME; - case FIELD_T::SHEET_USER: return LAYER_SHEETFIELDS; + case FIELD_T::REFERENCE: return LAYER_REFERENCEPART; + case FIELD_T::VALUE: return LAYER_VALUEPART; + case FIELD_T::SHEET_NAME: return LAYER_SHEETNAME; + case FIELD_T::SHEET_FILENAME: return LAYER_SHEETFILENAME; + case FIELD_T::SHEET_USER: return LAYER_SHEETFIELDS; case FIELD_T::INTERSHEET_REFS: return LAYER_INTERSHEET_REFS; - default: return LAYER_FIELDS; + default: return LAYER_FIELDS; } } @@ -477,7 +471,7 @@ EDA_ANGLE SCH_FIELD::GetDrawRotation() const { SCH_SYMBOL* parentSymbol = static_cast( m_parent ); - if( parentSymbol && parentSymbol->GetTransform().y1 ) // Rotate symbol 90 degrees. + if( parentSymbol && parentSymbol->GetTransform().y1 ) // Rotate symbol 90 degrees. { if( orient.IsHorizontal() ) orient = ANGLE_VERTICAL; @@ -535,8 +529,7 @@ bool SCH_FIELD::IsHorizJustifyFlipped() const return render_center.y < pos.y; else return render_center.x > pos.x; - default: - return false; + default: return false; } } @@ -553,8 +546,7 @@ void SCH_FIELD::SetEffectiveHorizJustify( GR_TEXT_H_ALIGN_T aJustify ) case GR_TEXT_H_ALIGN_RIGHT: actualJustify = IsHorizJustifyFlipped() ? GR_TEXT_H_ALIGN_LEFT : GR_TEXT_H_ALIGN_RIGHT; break; - default: - actualJustify = aJustify; + default: actualJustify = aJustify; } SetHorizJustify( actualJustify ); @@ -565,12 +557,9 @@ GR_TEXT_H_ALIGN_T SCH_FIELD::GetEffectiveHorizJustify() const { switch( GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: - return IsHorizJustifyFlipped() ? GR_TEXT_H_ALIGN_RIGHT : GR_TEXT_H_ALIGN_LEFT; - case GR_TEXT_H_ALIGN_RIGHT: - return IsHorizJustifyFlipped() ? GR_TEXT_H_ALIGN_LEFT : GR_TEXT_H_ALIGN_RIGHT; - default: - return GR_TEXT_H_ALIGN_CENTER; + case GR_TEXT_H_ALIGN_LEFT: return IsHorizJustifyFlipped() ? GR_TEXT_H_ALIGN_RIGHT : GR_TEXT_H_ALIGN_LEFT; + case GR_TEXT_H_ALIGN_RIGHT: return IsHorizJustifyFlipped() ? GR_TEXT_H_ALIGN_LEFT : GR_TEXT_H_ALIGN_RIGHT; + default: return GR_TEXT_H_ALIGN_CENTER; } } @@ -592,8 +581,7 @@ bool SCH_FIELD::IsVertJustifyFlipped() const return render_center.x > pos.x; else return render_center.y > pos.y; - default: - return false; + default: return false; } } @@ -610,8 +598,7 @@ void SCH_FIELD::SetEffectiveVertJustify( GR_TEXT_V_ALIGN_T aJustify ) case GR_TEXT_V_ALIGN_BOTTOM: actualJustify = IsVertJustifyFlipped() ? GR_TEXT_V_ALIGN_TOP : GR_TEXT_V_ALIGN_BOTTOM; break; - default: - actualJustify = aJustify; + default: actualJustify = aJustify; } SetVertJustify( actualJustify ); @@ -622,12 +609,9 @@ GR_TEXT_V_ALIGN_T SCH_FIELD::GetEffectiveVertJustify() const { switch( GetVertJustify() ) { - case GR_TEXT_V_ALIGN_TOP: - return IsVertJustifyFlipped() ? GR_TEXT_V_ALIGN_BOTTOM : GR_TEXT_V_ALIGN_TOP; - case GR_TEXT_V_ALIGN_BOTTOM: - return IsVertJustifyFlipped() ? GR_TEXT_V_ALIGN_TOP : GR_TEXT_V_ALIGN_BOTTOM; - default: - return GR_TEXT_V_ALIGN_CENTER; + case GR_TEXT_V_ALIGN_TOP: return IsVertJustifyFlipped() ? GR_TEXT_V_ALIGN_BOTTOM : GR_TEXT_V_ALIGN_TOP; + case GR_TEXT_V_ALIGN_BOTTOM: return IsVertJustifyFlipped() ? GR_TEXT_V_ALIGN_TOP : GR_TEXT_V_ALIGN_BOTTOM; + default: return GR_TEXT_V_ALIGN_CENTER; } } @@ -689,8 +673,7 @@ bool SCH_FIELD::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) co } -void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, - wxStyledTextEvent &aEvent ) const +void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, wxStyledTextEvent& aEvent ) const { SCH_ITEM* parent = dynamic_cast( GetParent() ); SCHEMATIC* schematic = parent ? parent->Schematic() : nullptr; @@ -710,20 +693,17 @@ void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, if( key == '\n' ) { wxString text = scintilla->GetText(); - int currpos = scintilla->GetCurrentPos(); + int currpos = scintilla->GetCurrentPos(); text.Replace( wxS( "\n" ), wxS( "" ) ); scintilla->SetText( text ); - scintilla->GotoPos( currpos-1 ); + scintilla->GotoPos( currpos - 1 ); return; } - auto textVarRef = - [&]( int pt ) - { - return pt >= 2 - && scintilla->GetCharAt( pt - 2 ) == '$' - && scintilla->GetCharAt( pt - 1 ) == '{'; - }; + auto textVarRef = [&]( int pt ) + { + return pt >= 2 && scintilla->GetCharAt( pt - 2 ) == '$' && scintilla->GetCharAt( pt - 1 ) == '{'; + }; // Check for cross-reference if( start > 1 && scintilla->GetCharAt( start - 1 ) == ':' ) @@ -776,9 +756,9 @@ void SCH_FIELD::OnScintillaCharAdded( SCINTILLA_TRICKS* aScintillaTricks, for( size_t jj = 0; jj < refs.GetCount(); jj++ ) { - if( refs[ jj ].GetSymbol()->GetRef( &refs[ jj ].GetSheetPath(), true ) == ref ) + if( refs[jj].GetSymbol()->GetRef( &refs[jj].GetSheetPath(), true ) == ref ) { - refSymbol = refs[ jj ].GetSymbol(); + refSymbol = refs[jj].GetSymbol(); break; } } @@ -897,8 +877,7 @@ void SCH_FIELD::Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) break; case GR_TEXT_H_ALIGN_CENTER: - case GR_TEXT_H_ALIGN_INDETERMINATE: - break; + case GR_TEXT_H_ALIGN_INDETERMINATE: break; } SetTextAngle( ANGLE_HORIZONTAL ); @@ -920,8 +899,7 @@ void SCH_FIELD::Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) break; case GR_TEXT_H_ALIGN_CENTER: - case GR_TEXT_H_ALIGN_INDETERMINATE: - break; + case GR_TEXT_H_ALIGN_INDETERMINATE: break; } SetTextAngle( ANGLE_VERTICAL ); @@ -980,14 +958,11 @@ wxString SCH_FIELD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFu if( content.IsEmpty() ) { - return wxString::Format( _( "Field %s (empty)" ), - UnescapeString( GetName() ) ); + return wxString::Format( _( "Field %s (empty)" ), UnescapeString( GetName() ) ); } else { - return wxString::Format( _( "Field %s '%s'" ), - UnescapeString( GetName() ), - content ); + return wxString::Format( _( "Field %s '%s'" ), UnescapeString( GetName() ), content ); } } @@ -1009,21 +984,21 @@ void SCH_FIELD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorMessageTextFromValue( GetTextWidth() ) ); - switch ( GetHorizJustify() ) + switch( GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: msg = _( "Left" ); break; - case GR_TEXT_H_ALIGN_CENTER: msg = _( "Center" ); break; - case GR_TEXT_H_ALIGN_RIGHT: msg = _( "Right" ); break; + case GR_TEXT_H_ALIGN_LEFT: msg = _( "Left" ); break; + case GR_TEXT_H_ALIGN_CENTER: msg = _( "Center" ); break; + case GR_TEXT_H_ALIGN_RIGHT: msg = _( "Right" ); break; case GR_TEXT_H_ALIGN_INDETERMINATE: msg = INDETERMINATE_STATE; break; } aList.emplace_back( _( "H Justification" ), msg ); - switch ( GetVertJustify() ) + switch( GetVertJustify() ) { - case GR_TEXT_V_ALIGN_TOP: msg = _( "Top" ); break; - case GR_TEXT_V_ALIGN_CENTER: msg = _( "Center" ); break; - case GR_TEXT_V_ALIGN_BOTTOM: msg = _( "Bottom" ); break; + case GR_TEXT_V_ALIGN_TOP: msg = _( "Top" ); break; + case GR_TEXT_V_ALIGN_CENTER: msg = _( "Center" ); break; + case GR_TEXT_V_ALIGN_BOTTOM: msg = _( "Bottom" ); break; case GR_TEXT_V_ALIGN_INDETERMINATE: msg = INDETERMINATE_STATE; break; } @@ -1063,9 +1038,8 @@ void SCH_FIELD::DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const for( int i = 0; i < (int) pages.size(); ++i ) { - menu.Append( i + START_ID, wxString::Format( _( "Go to Page %s (%s)" ), - pages[i].first, - pages[i].second ) ); + menu.Append( i + START_ID, + wxString::Format( _( "Go to Page %s (%s)" ), pages[i].first, pages[i].second ) ); } menu.AppendSeparator(); @@ -1074,7 +1048,7 @@ void SCH_FIELD::DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const int sel = aFrame->GetPopupMenuSelectionFromUser( menu ) - START_ID; if( sel >= 0 && sel < (int) pages.size() ) - href = wxT( "#" ) + pages[ sel ].first; + href = wxT( "#" ) + pages[sel].first; else if( sel == 999 ) href = SCH_NAVIGATE_TOOL::g_BackLink; } @@ -1153,9 +1127,9 @@ BITMAPS SCH_FIELD::GetMenuImage() const switch( m_id ) { case FIELD_T::REFERENCE: return BITMAPS::edit_comp_ref; - case FIELD_T::VALUE: return BITMAPS::edit_comp_value; + case FIELD_T::VALUE: return BITMAPS::edit_comp_value; case FIELD_T::FOOTPRINT: return BITMAPS::edit_comp_footprint; - default: return BITMAPS::text; + default: return BITMAPS::text; } } @@ -1195,7 +1169,7 @@ bool SCH_FIELD::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co if( GetShownText( true ).IsEmpty() ) return false; - if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) ) + if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) ) return false; BOX2I rect = aRect; @@ -1220,7 +1194,7 @@ bool SCH_FIELD::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const if( GetShownText( true ).IsEmpty() ) return false; - if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) ) + if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) ) return false; BOX2I bbox = GetBoundingBox(); @@ -1235,8 +1209,8 @@ bool SCH_FIELD::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const } -void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) { wxString text; @@ -1249,10 +1223,11 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& return; SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter ); - COLOR4D color = renderSettings->GetLayerColor( GetLayer() ); - int penWidth = GetEffectiveTextPenWidth( renderSettings->GetDefaultPenWidth() ); + COLOR4D color = renderSettings->GetLayerColor( GetLayer() ); + int penWidth = GetEffectiveTextPenWidth( renderSettings->GetDefaultPenWidth() ); - COLOR4D bg = renderSettings->GetBackgroundColor();; + COLOR4D bg = renderSettings->GetBackgroundColor(); + ; if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() ) bg = COLOR4D::WHITE; @@ -1262,7 +1237,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& if( aDimmed ) { - color.Desaturate( ); + color.Desaturate(); color = color.Mix( bg, 0.5f ); } @@ -1280,7 +1255,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& GR_TEXT_H_ALIGN_T hjustify = GetHorizJustify(); GR_TEXT_V_ALIGN_T vjustify = GetVertJustify(); - if( renderSettings->m_Transform.y1 ) // Rotate symbol 90 deg. + if( renderSettings->m_Transform.y1 ) // Rotate symbol 90 deg. { if( orient.IsHorizontal() ) orient = ANGLE_VERTICAL; @@ -1312,7 +1287,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& } else if( m_parent && m_parent->Type() == SCH_DIRECTIVE_LABEL_T ) { - SCH_DIRECTIVE_LABEL* label = static_cast( m_parent ); + SCH_DIRECTIVE_LABEL* label = static_cast( m_parent ); std::shared_ptr nc = label->GetEffectiveNetClass(); if( nc && ( nc->GetSchematicColor() != COLOR4D::UNSPECIFIED ) && aPlotter->GetColorMode() ) @@ -1338,7 +1313,7 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& label->GetIntersheetRefs( &Schematic()->CurrentSheet(), &pages ); - for( const auto& [ pageNumber, sheetName ] : pages ) + for( const auto& [pageNumber, sheetName] : pages ) pageHrefs.push_back( wxT( "#" ) + pageNumber ); BOX2I bbox = GetBoundingBox(); @@ -1394,14 +1369,9 @@ VECTOR2I SCH_FIELD::GetParentPosition() const bool SCH_FIELD::IsMandatory() const { - return m_id == FIELD_T::REFERENCE - || m_id == FIELD_T::VALUE - || m_id == FIELD_T::FOOTPRINT - || m_id == FIELD_T::DATASHEET - || m_id == FIELD_T::DESCRIPTION - || m_id == FIELD_T::SHEET_NAME - || m_id == FIELD_T::SHEET_FILENAME - || m_id == FIELD_T::INTERSHEET_REFS; + return m_id == FIELD_T::REFERENCE || m_id == FIELD_T::VALUE || m_id == FIELD_T::FOOTPRINT + || m_id == FIELD_T::DATASHEET || m_id == FIELD_T::DESCRIPTION || m_id == FIELD_T::SHEET_NAME + || m_id == FIELD_T::SHEET_FILENAME || m_id == FIELD_T::INTERSHEET_REFS; } @@ -1428,7 +1398,7 @@ bool SCH_FIELD::operator<( const SCH_ITEM& aItem ) const } -bool SCH_FIELD::operator==(const SCH_ITEM& aOther) const +bool SCH_FIELD::operator==( const SCH_ITEM& aOther ) const { if( Type() != aOther.Type() ) return false; @@ -1555,7 +1525,7 @@ int SCH_FIELD::compare( const SCH_ITEM& aOther, int aCompareFlags ) const return retv; } } - else // assume we're sorting + else // assume we're sorting { if( m_id != tmp->m_id ) return (int) m_id - (int) tmp->m_id; @@ -1606,19 +1576,14 @@ wxString SCH_FIELD::getUnescapedText( const SCH_SHEET_PATH* aPath, const wxStrin wxString retv = EDA_TEXT::GetShownText( false ); wxLogTrace( traceSchFieldRendering, - "getUnescapedText: field=%s, parent=%p, aPath=%p, path_empty=%d, initial_text='%s'", - GetName(), - m_parent, - aPath, - aPath ? (aPath->empty() ? 1 : 0) : -1, - retv ); + "getUnescapedText: field=%s, parent=%p, aPath=%p, path_empty=%d, initial_text='%s'", GetName(), + m_parent, aPath, aPath ? ( aPath->empty() ? 1 : 0 ) : -1, retv ); // Special handling for parent object field instance and variant information. // Only use the path if it's non-empty; an empty path can't match any instances if( m_parent && aPath && !aPath->empty() ) { - wxLogTrace( traceSchFieldRendering, - " Path is valid and non-empty, parent type=%d", m_parent->Type() ); + wxLogTrace( traceSchFieldRendering, " Path is valid and non-empty, parent type=%d", m_parent->Type() ); switch( m_parent->Type() ) { @@ -1628,15 +1593,12 @@ wxString SCH_FIELD::getUnescapedText( const SCH_SHEET_PATH* aPath, const wxStrin { if( m_id == FIELD_T::REFERENCE ) { - wxLogTrace( traceSchFieldRendering, - " Calling GetRef for symbol %s on path %s", - symbol->m_Uuid.AsString(), - aPath->Path().AsString() ); + wxLogTrace( traceSchFieldRendering, " Calling GetRef for symbol %s on path %s", + symbol->m_Uuid.AsString(), aPath->Path().AsString() ); retv = symbol->GetRef( aPath, true ); - wxLogTrace( traceSchFieldRendering, - " GetRef returned: '%s'", retv ); + wxLogTrace( traceSchFieldRendering, " GetRef returned: '%s'", retv ); } else if( !aVariantName.IsEmpty() ) { @@ -1653,11 +1615,9 @@ wxString SCH_FIELD::getUnescapedText( const SCH_SHEET_PATH* aPath, const wxStrin break; } - case SCH_SHEET_T: - break; + case SCH_SHEET_T: break; - default: - break; + default: break; } } @@ -1674,18 +1634,18 @@ static struct SCH_FIELD_DESC // places leads to duplicate symbols. auto& h_inst = ENUM_MAP::Instance(); - if( h_inst.Choices().GetCount() == 0) + if( h_inst.Choices().GetCount() == 0 ) { - h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) ); + h_inst.Map( GR_TEXT_H_ALIGN_LEFT, _HKI( "Left" ) ); h_inst.Map( GR_TEXT_H_ALIGN_CENTER, _HKI( "Center" ) ); - h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) ); + h_inst.Map( GR_TEXT_H_ALIGN_RIGHT, _HKI( "Right" ) ); } auto& v_inst = ENUM_MAP::Instance(); - if( v_inst.Choices().GetCount() == 0) + if( v_inst.Choices().GetCount() == 0 ) { - v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) ); + v_inst.Map( GR_TEXT_V_ALIGN_TOP, _HKI( "Top" ) ); v_inst.Map( GR_TEXT_V_ALIGN_CENTER, _HKI( "Center" ) ); v_inst.Map( GR_TEXT_V_ALIGN_BOTTOM, _HKI( "Bottom" ) ); } @@ -1699,25 +1659,23 @@ static struct SCH_FIELD_DESC const wxString textProps = _HKI( "Text Properties" ); - auto horiz = new PROPERTY_ENUM( - _HKI( "Horizontal Justification" ), &SCH_FIELD::SetEffectiveHorizJustify, - &SCH_FIELD::GetEffectiveHorizJustify ); + auto horiz = new PROPERTY_ENUM( _HKI( "Horizontal Justification" ), + &SCH_FIELD::SetEffectiveHorizJustify, + &SCH_FIELD::GetEffectiveHorizJustify ); - propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ), horiz, - textProps ); + propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Horizontal Justification" ), horiz, textProps ); - auto vert = new PROPERTY_ENUM( - _HKI( "Vertical Justification" ), &SCH_FIELD::SetEffectiveVertJustify, - &SCH_FIELD::GetEffectiveVertJustify ); + auto vert = new PROPERTY_ENUM( _HKI( "Vertical Justification" ), + &SCH_FIELD::SetEffectiveVertJustify, + &SCH_FIELD::GetEffectiveVertJustify ); - propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ), vert, - textProps ); + propMgr.ReplaceProperty( TYPE_HASH( EDA_TEXT ), _HKI( "Vertical Justification" ), vert, textProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Show Field Name" ), - &SCH_FIELD::SetNameShown, &SCH_FIELD::IsNameShown ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Show Field Name" ), &SCH_FIELD::SetNameShown, + &SCH_FIELD::IsNameShown ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Allow Autoplacement" ), - &SCH_FIELD::SetCanAutoplace, &SCH_FIELD::CanAutoplace ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Allow Autoplacement" ), &SCH_FIELD::SetCanAutoplace, + &SCH_FIELD::CanAutoplace ) ); propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) ); @@ -1726,36 +1684,34 @@ static struct SCH_FIELD_DESC propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), - &SCH_FIELD::SetSchTextSize, &SCH_FIELD::GetSchTextSize, PROPERTY_DISPLAY::PT_SIZE ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), &SCH_FIELD::SetSchTextSize, + &SCH_FIELD::GetSchTextSize, PROPERTY_DISPLAY::PT_SIZE ), + _HKI( "Text Properties" ) ); propMgr.Mask( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) ); - auto isNotGeneratedField = - []( INSPECTABLE* aItem ) -> bool - { - if( SCH_FIELD* field = dynamic_cast( aItem ) ) - return !field->IsGeneratedField(); + auto isNotGeneratedField = []( INSPECTABLE* aItem ) -> bool + { + if( SCH_FIELD* field = dynamic_cast( aItem ) ) + return !field->IsGeneratedField(); - return true; - }; + return true; + }; propMgr.OverrideWriteability( TYPE_HASH( SCH_FIELD ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ), isNotGeneratedField ); - auto isNonMandatoryField = - []( INSPECTABLE* aItem ) -> bool - { - if( SCH_FIELD* field = dynamic_cast( aItem ) ) - return !field->IsMandatory(); + auto isNonMandatoryField = []( INSPECTABLE* aItem ) -> bool + { + if( SCH_FIELD* field = dynamic_cast( aItem ) ) + return !field->IsMandatory(); - return false; - }; + return false; + }; - propMgr.OverrideAvailability( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), - _HKI( "Private" ), isNonMandatoryField ); + propMgr.OverrideAvailability( TYPE_HASH( SCH_FIELD ), TYPE_HASH( SCH_ITEM ), _HKI( "Private" ), + isNonMandatoryField ); } } _SCH_FIELD_DESC; diff --git a/eeschema/sch_label.cpp b/eeschema/sch_label.cpp index 36c2356248..517211dc70 100644 --- a/eeschema/sch_label.cpp +++ b/eeschema/sch_label.cpp @@ -61,51 +61,48 @@ * others are the corners coordinates in reduced units * the real coordinate is the reduced coordinate * text half size */ -static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 }; -static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 }; -static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 }; -static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 }; +static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 }; +static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 }; +static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 }; +static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 }; -static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 }; -static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 }; -static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 }; -static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 }; +static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 }; +static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 }; +static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 }; +static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 }; -static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 }; -static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 }; -static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 }; -static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 }; +static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 }; +static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 }; +static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 }; +static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 }; -static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 }; -static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 }; -static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 }; -static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 }; +static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 }; +static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 }; +static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 }; +static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 }; -static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 }; -static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 }; -static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 }; -static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 }; +static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 }; +static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 }; +static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 }; +static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 }; -static int* TemplateShape[5][4] = -{ - { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM }, - { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM }, - { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM }, - { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM }, - { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM } -}; +static int* TemplateShape[5][4] = { { TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM }, + { TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM }, + { TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM }, + { Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM }, + { TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM } }; wxString getElectricalTypeLabel( LABEL_FLAG_SHAPE aType ) { switch( aType ) { - case LABEL_FLAG_SHAPE::L_INPUT: return _( "Input" ); - case LABEL_FLAG_SHAPE::L_OUTPUT: return _( "Output" ); - case LABEL_FLAG_SHAPE::L_BIDI: return _( "Bidirectional" ); - case LABEL_FLAG_SHAPE::L_TRISTATE: return _( "Tri-State" ); + case LABEL_FLAG_SHAPE::L_INPUT: return _( "Input" ); + case LABEL_FLAG_SHAPE::L_OUTPUT: return _( "Output" ); + case LABEL_FLAG_SHAPE::L_BIDI: return _( "Bidirectional" ); + case LABEL_FLAG_SHAPE::L_TRISTATE: return _( "Tri-State" ); case LABEL_FLAG_SHAPE::L_UNSPECIFIED: return _( "Passive" ); - default: return wxT( "???" ); + default: return wxT( "???" ); } } @@ -116,10 +113,10 @@ SPIN_STYLE SPIN_STYLE::RotateCCW() switch( m_spin ) { - case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::BOTTOM; break; - case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::RIGHT; break; - case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::UP; break; - case SPIN_STYLE::UP: newSpin = SPIN_STYLE::LEFT; break; + case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::BOTTOM; break; + case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::RIGHT; break; + case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::UP; break; + case SPIN_STYLE::UP: newSpin = SPIN_STYLE::LEFT; break; } return SPIN_STYLE( newSpin ); @@ -132,10 +129,10 @@ SPIN_STYLE SPIN_STYLE::MirrorX() switch( m_spin ) { - case SPIN_STYLE::UP: newSpin = SPIN_STYLE::BOTTOM; break; - case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::UP; break; - case SPIN_STYLE::LEFT: break; - case SPIN_STYLE::RIGHT: break; + case SPIN_STYLE::UP: newSpin = SPIN_STYLE::BOTTOM; break; + case SPIN_STYLE::BOTTOM: newSpin = SPIN_STYLE::UP; break; + case SPIN_STYLE::LEFT: break; + case SPIN_STYLE::RIGHT: break; } return SPIN_STYLE( newSpin ); @@ -148,10 +145,10 @@ SPIN_STYLE SPIN_STYLE::MirrorY() switch( m_spin ) { - case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::RIGHT; break; - case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::LEFT; break; - case SPIN_STYLE::UP: break; - case SPIN_STYLE::BOTTOM: break; + case SPIN_STYLE::LEFT: newSpin = SPIN_STYLE::RIGHT; break; + case SPIN_STYLE::RIGHT: newSpin = SPIN_STYLE::LEFT; break; + case SPIN_STYLE::UP: break; + case SPIN_STYLE::BOTTOM: break; } return SPIN_STYLE( newSpin ); @@ -270,7 +267,7 @@ bool SCH_LABEL_BASE::IsType( const std::vector& aScanTypes ) const } } - if ( scanType == SCH_LABEL_LOCATE_BUS_T ) + if( scanType == SCH_LABEL_LOCATE_BUS_T ) { for( SCH_ITEM* connection : item_set ) { @@ -399,26 +396,24 @@ void SCH_LABEL_BASE::SetSpinStyle( SPIN_STYLE aSpinStyle ) // Thus we want to left justify text up against the anchor if we are on the right switch( aSpinStyle ) { - default: - wxFAIL_MSG( "Bad spin style" ); - KI_FALLTHROUGH; + default: wxFAIL_MSG( "Bad spin style" ); KI_FALLTHROUGH; - case SPIN_STYLE::RIGHT: // Horiz Normal Orientation + case SPIN_STYLE::RIGHT: // Horiz Normal Orientation SetTextAngle( ANGLE_HORIZONTAL ); SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break; - case SPIN_STYLE::UP: // Vert Orientation UP + case SPIN_STYLE::UP: // Vert Orientation UP SetTextAngle( ANGLE_VERTICAL ); SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break; - case SPIN_STYLE::LEFT: // Horiz Orientation - Right justified + case SPIN_STYLE::LEFT: // Horiz Orientation - Right justified SetTextAngle( ANGLE_HORIZONTAL ); SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break; - case SPIN_STYLE::BOTTOM: // Vert Orientation BOTTOM + case SPIN_STYLE::BOTTOM: // Vert Orientation BOTTOM SetTextAngle( ANGLE_VERTICAL ); SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break; @@ -457,10 +452,10 @@ VECTOR2I SCH_LABEL_BASE::GetSchematicTextOffset( const RENDER_SETTINGS* aSetting switch( GetSpinStyle() ) { case SPIN_STYLE::UP: - case SPIN_STYLE::BOTTOM: text_offset.x = -dist; break; // Vert Orientation + case SPIN_STYLE::BOTTOM: text_offset.x = -dist; break; // Vert Orientation default: case SPIN_STYLE::LEFT: - case SPIN_STYLE::RIGHT: text_offset.y = -dist; break; // Horiz Orientation + case SPIN_STYLE::RIGHT: text_offset.y = -dist; break; // Horiz Orientation } return text_offset; @@ -521,7 +516,7 @@ void SCH_LABEL_BASE::MirrorSpinStyle( bool aLeftRight ) for( SCH_FIELD& field : m_fields ) { if( ( aLeftRight && field.GetTextAngle().IsHorizontal() ) - || ( !aLeftRight && field.GetTextAngle().IsVertical() ) ) + || ( !aLeftRight && field.GetTextAngle().IsVertical() ) ) { if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT ) field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); @@ -530,7 +525,7 @@ void SCH_LABEL_BASE::MirrorSpinStyle( bool aLeftRight ) } VECTOR2I pos = field.GetTextPos(); - VECTOR2I delta = (VECTOR2I)GetPosition() - pos; + VECTOR2I delta = (VECTOR2I) GetPosition() - pos; if( aLeftRight ) pos.x = GetPosition().x + delta.x; @@ -678,7 +673,7 @@ void SCH_LABEL_BASE::AutoplaceFields( SCH_SCREEN* aScreen, AUTOPLACE_ALGO aAlgo field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); if( field.GetId() == FIELD_T::INTERSHEET_REFS ) - offset.x = - ( labelLen + margin ); + offset.x = -( labelLen + margin ); else offset.y = accumulated + field.GetTextHeight() / 2; @@ -689,7 +684,7 @@ void SCH_LABEL_BASE::AutoplaceFields( SCH_SCREEN* aScreen, AUTOPLACE_ALGO aAlgo field.SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); if( field.GetId() == FIELD_T::INTERSHEET_REFS ) - offset.y = - ( labelLen + margin ); + offset.y = -( labelLen + margin ); else offset.x = accumulated + field.GetTextHeight() / 2; @@ -729,8 +724,7 @@ void SCH_LABEL_BASE::AutoplaceFields( SCH_SCREEN* aScreen, AUTOPLACE_ALGO aAlgo } -void SCH_LABEL_BASE::GetIntersheetRefs( const SCH_SHEET_PATH* aPath, - std::vector>* pages ) +void SCH_LABEL_BASE::GetIntersheetRefs( const SCH_SHEET_PATH* aPath, std::vector>* pages ) { wxCHECK( pages, /* void */ ); @@ -760,7 +754,7 @@ void SCH_LABEL_BASE::GetIntersheetRefs( const SCH_SHEET_PATH* aPath, std::map sheetNames = Schematic()->GetVirtualPageToSheetNamesMap(); for( int pageNum : pageListCopy ) - pages->push_back( { sheetPages[ pageNum ], sheetNames[ pageNum ] } ); + pages->push_back( { sheetPages[pageNum], sheetNames[pageNum] } ); } } } @@ -784,8 +778,7 @@ void SCH_LABEL_BASE::GetContextualTextVars( wxArrayString* aVars ) const } -bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, - int aDepth ) const +bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const { static wxRegEx operatingPoint( wxT( "^" "OP" @@ -827,7 +820,7 @@ bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* toke } if( ( Type() == SCH_GLOBAL_LABEL_T || Type() == SCH_HIER_LABEL_T || Type() == SCH_SHEET_PIN_T ) - && token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) ) + && token->IsSameAs( wxT( "CONNECTION_TYPE" ) ) ) { const SCH_LABEL_BASE* label = static_cast( this ); *token = getElectricalTypeLabel( label->GetShape() ); @@ -916,7 +909,7 @@ bool SCH_LABEL_BASE::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* toke return true; } - for( const SCH_FIELD& field : m_fields) + for( const SCH_FIELD& field : m_fields ) { if( token->IsSameAs( field.GetName() ) ) { @@ -969,25 +962,17 @@ void SCH_LABEL_BASE::cacheShownText() } -wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, - int aDepth ) const +wxString SCH_LABEL_BASE::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const { - std::function textResolver = - [&]( wxString* token ) -> bool - { - return ResolveTextVar( aPath, token, aDepth + 1 ); - }; + std::function textResolver = [&]( wxString* token ) -> bool + { + return ResolveTextVar( aPath, token, aDepth + 1 ); + }; wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); if( HasTextVars() ) - { - if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &textResolver ); - } - - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); + text = ResolveTextVars( text, &textResolver, aDepth ); return text; } @@ -1008,11 +993,10 @@ bool SCH_LABEL_BASE::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData } const SCH_SEARCH_DATA* searchData = dynamic_cast( &aSearchData ); - SCH_CONNECTION* connection = nullptr; - SCH_SHEET_PATH* sheetPath = reinterpret_cast( aAuxData ); + SCH_CONNECTION* connection = nullptr; + SCH_SHEET_PATH* sheetPath = reinterpret_cast( aAuxData ); - if( searchData && searchData->searchNetNames && sheetPath - && ( connection = Connection( sheetPath ) ) ) + if( searchData && searchData->searchNetNames && sheetPath && ( connection = Connection( sheetPath ) ) ) { if( connection->IsBus() ) { @@ -1052,8 +1036,7 @@ bool SCH_LABEL_BASE::Replace( const EDA_SEARCH_DATA& aSearchData, void* aAuxData } -INSPECT_RESULT SCH_LABEL_BASE::Visit( INSPECTOR aInspector, void* testData, - const std::vector& aScanTypes ) +INSPECT_RESULT SCH_LABEL_BASE::Visit( INSPECTOR aInspector, void* testData, const std::vector& aScanTypes ) { if( IsType( aScanTypes ) ) { @@ -1092,11 +1075,7 @@ std::vector SCH_LABEL_BASE::GetConnectionPoints() const std::vector SCH_LABEL_BASE::ViewGetLayers() const { - return { LAYER_DANGLING, - LAYER_DEVICE, - LAYER_NETCLASS_REFS, - LAYER_FIELDS, - LAYER_SELECTION_SHADOWS }; + return { LAYER_DANGLING, LAYER_DEVICE, LAYER_NETCLASS_REFS, LAYER_FIELDS, LAYER_SELECTION_SHADOWS }; } @@ -1250,13 +1229,12 @@ bool SCH_LABEL_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) c bool SCH_LABEL_BASE::UpdateDanglingState( std::vector& aItemListByType, - std::vector& aItemListByPos, - const SCH_SHEET_PATH* aPath ) + std::vector& aItemListByPos, const SCH_SHEET_PATH* aPath ) { bool previousState = m_isDangling; VECTOR2I text_pos = GetTextPos(); m_isDangling = true; - m_connectionType = CONNECTION_TYPE::NONE; + m_connectionType = CONNECTION_TYPE::NONE; for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos ); it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ ) @@ -1298,8 +1276,7 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector& aItemL int accuracy = 1; // We have rounding issues with an accuracy of 0 - m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(), - accuracy ); + m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(), accuracy ); if( m_isDangling ) continue; @@ -1328,8 +1305,7 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector& aItemL int accuracy = 1; // We have rounding issues with an accuracy of 0 - m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), - nextItem.GetPosition(), accuracy ); + m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(), accuracy ); if( m_isDangling ) continue; @@ -1357,8 +1333,7 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector& aItemL } -bool SCH_LABEL_BASE::HasConnectivityChanges( const SCH_ITEM* aItem, - const SCH_SHEET_PATH* aInstance ) const +bool SCH_LABEL_BASE::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const { // Do not compare to ourself. if( aItem == this || !IsConnectable() ) @@ -1400,11 +1375,11 @@ void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetName() : _( "Default" ) ); wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) }; - int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; + int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; aList.emplace_back( _( "Style" ), textStyle[style] ); aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) ); switch( GetSpinStyle() ) { - case SPIN_STYLE::LEFT: msg = _( "Align right" ); break; - case SPIN_STYLE::UP: msg = _( "Align bottom" ); break; - case SPIN_STYLE::RIGHT: msg = _( "Align left" ); break; - case SPIN_STYLE::BOTTOM: msg = _( "Align top" ); break; - default: msg = wxT( "???" ); break; + case SPIN_STYLE::LEFT: msg = _( "Align right" ); break; + case SPIN_STYLE::UP: msg = _( "Align bottom" ); break; + case SPIN_STYLE::RIGHT: msg = _( "Align left" ); break; + case SPIN_STYLE::BOTTOM: msg = _( "Align top" ); break; + default: msg = wxT( "???" ); break; } aList.emplace_back( _( "Justification" ), msg ); @@ -1452,8 +1427,8 @@ void SCH_LABEL_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector s_poly; @@ -1554,20 +1529,16 @@ void SCH_LABEL_BASE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_O if( connection ) { - properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), - _( "Net" ), - connection->Name() ) ); + properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Net" ), connection->Name() ) ); - properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), - _( "Resolved netclass" ), + properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Resolved netclass" ), GetEffectiveNetClass()->GetHumanReadableName() ) ); } for( const SCH_FIELD& field : GetFields() ) { - properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), - field.GetName(), - field.GetShownText( false ) ) ); + properties.emplace_back( + wxString::Format( wxT( "!%s = %s" ), field.GetName(), field.GetShownText( false ) ) ); } if( !properties.empty() ) @@ -1598,13 +1569,13 @@ void SCH_LABEL_BASE::SetAutoRotateOnPlacement( bool autoRotate ) SCH_LABEL::SCH_LABEL( const VECTOR2I& pos, const wxString& text ) : SCH_LABEL_BASE( pos, text, SCH_LABEL_T ) { - m_layer = LAYER_LOCLABEL; - m_shape = LABEL_FLAG_SHAPE::L_INPUT; + m_layer = LAYER_LOCLABEL; + m_shape = LABEL_FLAG_SHAPE::L_INPUT; m_isDangling = true; } -void SCH_LABEL::Serialize( google::protobuf::Any &aContainer ) const +void SCH_LABEL::Serialize( google::protobuf::Any& aContainer ) const { kiapi::schematic::types::LocalLabel label; @@ -1615,7 +1586,7 @@ void SCH_LABEL::Serialize( google::protobuf::Any &aContainer ) const } -bool SCH_LABEL::Deserialize( const google::protobuf::Any &aContainer ) +bool SCH_LABEL::Deserialize( const google::protobuf::Any& aContainer ) { kiapi::schematic::types::LocalLabel label; @@ -1660,8 +1631,7 @@ const BOX2I SCH_LABEL::GetBodyBoundingBox( const RENDER_SETTINGS* aSettings ) co wxString SCH_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const { - return wxString::Format( _( "Label '%s'" ), - aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) ); + return wxString::Format( _( "Label '%s'" ), aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ) ); } @@ -1674,9 +1644,9 @@ BITMAPS SCH_LABEL::GetMenuImage() const SCH_DIRECTIVE_LABEL::SCH_DIRECTIVE_LABEL( const VECTOR2I& pos ) : SCH_LABEL_BASE( pos, wxEmptyString, SCH_DIRECTIVE_LABEL_T ) { - m_layer = LAYER_NETCLASS_REFS; - m_shape = LABEL_FLAG_SHAPE::F_ROUND; - m_pinLength = schIUScale.MilsToIU( 100 ); + m_layer = LAYER_NETCLASS_REFS; + m_shape = LABEL_FLAG_SHAPE::F_ROUND; + m_pinLength = schIUScale.MilsToIU( 100 ); m_symbolSize = schIUScale.MilsToIU( 20 ); m_isDangling = true; } @@ -1701,13 +1671,13 @@ SCH_DIRECTIVE_LABEL::SCH_DIRECTIVE_LABEL( const SCH_DIRECTIVE_LABEL& aClassLabel } -void SCH_DIRECTIVE_LABEL::Serialize( google::protobuf::Any &aContainer ) const +void SCH_DIRECTIVE_LABEL::Serialize( google::protobuf::Any& aContainer ) const { // TODO } -bool SCH_DIRECTIVE_LABEL::Deserialize( const google::protobuf::Any &aContainer ) +bool SCH_DIRECTIVE_LABEL::Deserialize( const google::protobuf::Any& aContainer ) { // TODO return false; @@ -1735,7 +1705,7 @@ void SCH_DIRECTIVE_LABEL::MirrorSpinStyle( bool aLeftRight ) for( SCH_FIELD& field : m_fields ) { if( ( aLeftRight && field.GetTextAngle().IsHorizontal() ) - || ( !aLeftRight && field.GetTextAngle().IsVertical() ) ) + || ( !aLeftRight && field.GetTextAngle().IsVertical() ) ) { if( field.GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT ) field.SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); @@ -1744,7 +1714,7 @@ void SCH_DIRECTIVE_LABEL::MirrorSpinStyle( bool aLeftRight ) } VECTOR2I pos = field.GetTextPos(); - VECTOR2I delta = (VECTOR2I)GetPosition() - pos; + VECTOR2I delta = (VECTOR2I) GetPosition() - pos; if( aLeftRight ) pos.x = GetPosition().x + delta.x; @@ -1806,9 +1776,8 @@ void SCH_DIRECTIVE_LABEL::MirrorVertically( int aCenter ) } -void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, - std::vector& aPoints, - const VECTOR2I& aPos ) const +void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector& aPoints, + const VECTOR2I& aPos ) const { int symbolSize = m_symbolSize; @@ -1816,47 +1785,44 @@ void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSett switch( m_shape ) { - case LABEL_FLAG_SHAPE::F_DOT: - symbolSize = KiROUND( symbolSize * 0.7 ); - KI_FALLTHROUGH; + case LABEL_FLAG_SHAPE::F_DOT: symbolSize = KiROUND( symbolSize * 0.7 ); KI_FALLTHROUGH; case LABEL_FLAG_SHAPE::F_ROUND: // First 3 points are used for generating shape - aPoints.emplace_back( VECTOR2I( 0, 0 ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) ); + aPoints.emplace_back( VECTOR2I( 0, 0 ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) ); // These points are just used to bulk out the bounding box - aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) ); - aPoints.emplace_back( VECTOR2I( m_symbolSize, m_pinLength + symbolSize ) ); + aPoints.emplace_back( VECTOR2I( -m_symbolSize, m_pinLength ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength ) ); + aPoints.emplace_back( VECTOR2I( m_symbolSize, m_pinLength + symbolSize ) ); break; case LABEL_FLAG_SHAPE::F_DIAMOND: - aPoints.emplace_back( VECTOR2I( 0, 0 ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); - aPoints.emplace_back( VECTOR2I( -2 * m_symbolSize, m_pinLength ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength + symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 2 * m_symbolSize, m_pinLength ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 0, 0 ) ); + aPoints.emplace_back( VECTOR2I( 0, 0 ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( -2 * m_symbolSize, m_pinLength ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength + symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 2 * m_symbolSize, m_pinLength ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 0, 0 ) ); break; case LABEL_FLAG_SHAPE::F_RECTANGLE: symbolSize = KiROUND( symbolSize * 0.8 ); - aPoints.emplace_back( VECTOR2I( 0, 0 ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 0, 0 ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength - symbolSize ) ); aPoints.emplace_back( VECTOR2I( -2 * symbolSize, m_pinLength + symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength + symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength - symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); - aPoints.emplace_back( VECTOR2I( 0, 0 ) ); + aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength + symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 2 * symbolSize, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 0, m_pinLength - symbolSize ) ); + aPoints.emplace_back( VECTOR2I( 0, 0 ) ); break; - default: - break; + default: break; } // Rotate outlines and move corners to real position @@ -1865,10 +1831,10 @@ void SCH_DIRECTIVE_LABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSett switch( GetSpinStyle() ) { default: - case SPIN_STYLE::LEFT: break; - case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break; - case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break; - case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break; + case SPIN_STYLE::LEFT: break; + case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break; + case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break; + case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break; } aPoint += aPos; @@ -1943,14 +1909,11 @@ wxString SCH_DIRECTIVE_LABEL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider if( content.IsEmpty() ) { - return wxString::Format( _( "Directive Label [%s (empty)]" ), - UnescapeString( m_fields[0].GetName() ) ); + return wxString::Format( _( "Directive Label [%s (empty)]" ), UnescapeString( m_fields[0].GetName() ) ); } else { - return wxString::Format( _( "Directive Label [%s %s]" ), - UnescapeString( m_fields[0].GetName() ), - content ); + return wxString::Format( _( "Directive Label [%s %s]" ), UnescapeString( m_fields[0].GetName() ), content ); } } } @@ -1989,14 +1952,14 @@ bool SCH_DIRECTIVE_LABEL::IsDangling() const SCH_GLOBALLABEL::SCH_GLOBALLABEL( const VECTOR2I& pos, const wxString& text ) : SCH_LABEL_BASE( pos, text, SCH_GLOBAL_LABEL_T ) { - m_layer = LAYER_GLOBLABEL; - m_shape = LABEL_FLAG_SHAPE::L_BIDI; + m_layer = LAYER_GLOBLABEL; + m_shape = LABEL_FLAG_SHAPE::L_BIDI; m_isDangling = true; SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); - m_fields.emplace_back( SCH_FIELD( this, FIELD_T::INTERSHEET_REFS, - ::GetDefaultFieldName( FIELD_T::INTERSHEET_REFS, false ) ) ); + m_fields.emplace_back( + SCH_FIELD( this, FIELD_T::INTERSHEET_REFS, ::GetDefaultFieldName( FIELD_T::INTERSHEET_REFS, false ) ) ); m_fields.back().SetText( wxT( "${INTERSHEET_REFS}" ) ); m_fields.back().SetVisible( false ); m_fields.back().SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); @@ -2010,13 +1973,13 @@ SCH_GLOBALLABEL::SCH_GLOBALLABEL( const SCH_GLOBALLABEL& aGlobalLabel ) : } -void SCH_GLOBALLABEL::Serialize( google::protobuf::Any &aContainer ) const +void SCH_GLOBALLABEL::Serialize( google::protobuf::Any& aContainer ) const { // TODO } -bool SCH_GLOBALLABEL::Deserialize( const google::protobuf::Any &aContainer ) +bool SCH_GLOBALLABEL::Deserialize( const google::protobuf::Any& aContainer ) { // TODO return false; @@ -2051,21 +2014,20 @@ VECTOR2I SCH_GLOBALLABEL::GetSchematicTextOffset( const RENDER_SETTINGS* aSettin case LABEL_FLAG_SHAPE::L_INPUT: case LABEL_FLAG_SHAPE::L_BIDI: case LABEL_FLAG_SHAPE::L_TRISTATE: - horiz += GetTextHeight() * 3 / 4; // Use three-quarters-height as proxy for triangle size + horiz += GetTextHeight() * 3 / 4; // Use three-quarters-height as proxy for triangle size break; case LABEL_FLAG_SHAPE::L_OUTPUT: case LABEL_FLAG_SHAPE::L_UNSPECIFIED: - default: - break; + default: break; } switch( GetSpinStyle() ) { default: - case SPIN_STYLE::LEFT: return VECTOR2I( -horiz, vert ); - case SPIN_STYLE::UP: return VECTOR2I( vert, -horiz ); - case SPIN_STYLE::RIGHT: return VECTOR2I( horiz, vert ); + case SPIN_STYLE::LEFT: return VECTOR2I( -horiz, vert ); + case SPIN_STYLE::UP: return VECTOR2I( vert, -horiz ); + case SPIN_STYLE::RIGHT: return VECTOR2I( horiz, vert ); case SPIN_STYLE::BOTTOM: return VECTOR2I( vert, horiz ); } } @@ -2078,8 +2040,7 @@ void SCH_GLOBALLABEL::SetSpinStyle( SPIN_STYLE aSpinStyle ) } -bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, - int aDepth ) const +bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, int aDepth ) const { wxCHECK( aPath, false ); @@ -2115,8 +2076,7 @@ bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* tok if( ( settings.m_IntersheetRefsFormatShort ) && ( pageListCopy.size() > 2 ) ) { - ref.Append( wxString::Format( wxT( "%s..%s" ), - sheetPages[pageListCopy.front()], + ref.Append( wxString::Format( wxT( "%s..%s" ), sheetPages[pageListCopy.front()], sheetPages[pageListCopy.back()] ) ); } else @@ -2139,24 +2099,18 @@ bool SCH_GLOBALLABEL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* tok std::vector SCH_GLOBALLABEL::ViewGetLayers() const { - return { LAYER_DANGLING, - LAYER_GLOBLABEL, - LAYER_DEVICE, - LAYER_INTERSHEET_REFS, - LAYER_NETCLASS_REFS, - LAYER_FIELDS, - LAYER_SELECTION_SHADOWS }; + return { LAYER_DANGLING, LAYER_GLOBLABEL, LAYER_DEVICE, LAYER_INTERSHEET_REFS, + LAYER_NETCLASS_REFS, LAYER_FIELDS, LAYER_SELECTION_SHADOWS }; } -void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, - std::vector& aPoints, - const VECTOR2I& aPos ) const +void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings, std::vector& aPoints, + const VECTOR2I& aPos ) const { - int margin = GetLabelBoxExpansion( aRenderSettings ); - int halfSize = ( GetTextHeight() / 2 ) + margin; + int margin = GetLabelBoxExpansion( aRenderSettings ); + int halfSize = ( GetTextHeight() / 2 ) + margin; int linewidth = GetPenWidth(); - int symb_len = GetTextBox( aRenderSettings ).GetWidth() + 2 * margin; + int symb_len = GetTextBox( aRenderSettings ).GetWidth() + 2 * margin; int x = symb_len + linewidth + 3; int y = halfSize + linewidth + 3; @@ -2165,11 +2119,11 @@ void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings // Create outline shape : 6 points aPoints.emplace_back( VECTOR2I( 0, 0 ) ); - aPoints.emplace_back( VECTOR2I( 0, -y ) ); // Up - aPoints.emplace_back( VECTOR2I( -x, -y ) ); // left - aPoints.emplace_back( VECTOR2I( -x, 0 ) ); // Up left - aPoints.emplace_back( VECTOR2I( -x, y ) ); // left down - aPoints.emplace_back( VECTOR2I( 0, y ) ); // down + aPoints.emplace_back( VECTOR2I( 0, -y ) ); // Up + aPoints.emplace_back( VECTOR2I( -x, -y ) ); // left + aPoints.emplace_back( VECTOR2I( -x, 0 ) ); // Up left + aPoints.emplace_back( VECTOR2I( -x, y ) ); // left down + aPoints.emplace_back( VECTOR2I( 0, y ) ); // down int x_offset = 0; @@ -2180,9 +2134,7 @@ void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings aPoints[0].x += halfSize; break; - case LABEL_FLAG_SHAPE::L_OUTPUT: - aPoints[3].x -= halfSize; - break; + case LABEL_FLAG_SHAPE::L_OUTPUT: aPoints[3].x -= halfSize; break; case LABEL_FLAG_SHAPE::L_BIDI: case LABEL_FLAG_SHAPE::L_TRISTATE: @@ -2192,8 +2144,7 @@ void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings break; case LABEL_FLAG_SHAPE::L_UNSPECIFIED: - default: - break; + default: break; } // Rotate outlines and move corners in real position @@ -2204,10 +2155,10 @@ void SCH_GLOBALLABEL::CreateGraphicShape( const RENDER_SETTINGS* aRenderSettings switch( GetSpinStyle() ) { default: - case SPIN_STYLE::LEFT: break; - case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break; - case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break; - case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break; + case SPIN_STYLE::LEFT: break; + case SPIN_STYLE::UP: RotatePoint( aPoint, -ANGLE_90 ); break; + case SPIN_STYLE::RIGHT: RotatePoint( aPoint, ANGLE_180 ); break; + case SPIN_STYLE::BOTTOM: RotatePoint( aPoint, ANGLE_90 ); break; } aPoint += aPos; @@ -2233,19 +2184,19 @@ BITMAPS SCH_GLOBALLABEL::GetMenuImage() const SCH_HIERLABEL::SCH_HIERLABEL( const VECTOR2I& pos, const wxString& text, KICAD_T aType ) : SCH_LABEL_BASE( pos, text, aType ) { - m_layer = LAYER_HIERLABEL; - m_shape = LABEL_FLAG_SHAPE::L_INPUT; + m_layer = LAYER_HIERLABEL; + m_shape = LABEL_FLAG_SHAPE::L_INPUT; m_isDangling = true; } -void SCH_HIERLABEL::Serialize( google::protobuf::Any &aContainer ) const +void SCH_HIERLABEL::Serialize( google::protobuf::Any& aContainer ) const { // TODO } -bool SCH_HIERLABEL::Deserialize( const google::protobuf::Any &aContainer ) +bool SCH_HIERLABEL::Deserialize( const google::protobuf::Any& aContainer ) { // TODO return false; @@ -2259,16 +2210,15 @@ void SCH_HIERLABEL::SetSpinStyle( SPIN_STYLE aSpinStyle ) } -void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, - std::vector& aPoints, const VECTOR2I& aPos ) const +void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector& aPoints, + const VECTOR2I& aPos ) const { CreateGraphicShape( aSettings, aPoints, aPos, m_shape ); } -void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, - std::vector& aPoints, const VECTOR2I& aPos, - LABEL_FLAG_SHAPE aShape ) const +void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, std::vector& aPoints, + const VECTOR2I& aPos, LABEL_FLAG_SHAPE aShape ) const { int* Template = TemplateShape[static_cast( aShape )][static_cast( GetSpinStyle() )]; int halfSize = GetTextHeight() / 2; @@ -2280,10 +2230,10 @@ void SCH_HIERLABEL::CreateGraphicShape( const RENDER_SETTINGS* aSettings, for( int ii = 0; ii < imax; ii++ ) { VECTOR2I corner; - corner.x = ( halfSize * (*Template) ) + aPos.x; + corner.x = ( halfSize * ( *Template ) ) + aPos.x; Template++; - corner.y = ( halfSize * (*Template) ) + aPos.y; + corner.y = ( halfSize * ( *Template ) ) + aPos.y; Template++; aPoints.push_back( corner ); @@ -2296,13 +2246,13 @@ const BOX2I SCH_HIERLABEL::GetBodyBoundingBox( const RENDER_SETTINGS* aSettings int penWidth = GetEffectiveTextPenWidth(); int margin = GetTextOffset(); - int x = GetTextPos().x; - int y = GetTextPos().y; + int x = GetTextPos().x; + int y = GetTextPos().y; int height = GetTextHeight() + penWidth + margin; int length = GetTextBox( aSettings ).GetWidth(); - length += height; // add height for triangular shapes + length += height; // add height for triangular shapes int dx, dy; @@ -2347,17 +2297,17 @@ const BOX2I SCH_HIERLABEL::GetBodyBoundingBox( const RENDER_SETTINGS* aSettings VECTOR2I SCH_HIERLABEL::GetSchematicTextOffset( const RENDER_SETTINGS* aSettings ) const { VECTOR2I text_offset; - int dist = GetTextOffset( aSettings ); + int dist = GetTextOffset( aSettings ); dist += GetTextWidth(); switch( GetSpinStyle() ) { default: - case SPIN_STYLE::LEFT: text_offset.x = -dist; break; // Orientation horiz normale - case SPIN_STYLE::UP: text_offset.y = -dist; break; // Orientation vert UP - case SPIN_STYLE::RIGHT: text_offset.x = dist; break; // Orientation horiz inverse - case SPIN_STYLE::BOTTOM: text_offset.y = dist; break; // Orientation vert BOTTOM + case SPIN_STYLE::LEFT: text_offset.x = -dist; break; // Orientation horiz normale + case SPIN_STYLE::UP: text_offset.y = -dist; break; // Orientation vert UP + case SPIN_STYLE::RIGHT: text_offset.x = dist; break; // Orientation horiz inverse + case SPIN_STYLE::BOTTOM: text_offset.y = dist; break; // Orientation vert BOTTOM } return text_offset; @@ -2381,9 +2331,9 @@ HTML_MESSAGE_BOX* SCH_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow ) { wxString msg = #include "sch_text_help_md.h" - ; + ; - HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( nullptr, _( "Syntax Help" ) ); + HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( aParentWindow, _( "Syntax Help" ) ); wxSize sz( 320, 320 ); dlg->SetMinSize( dlg->ConvertDialogToPixels( sz ) ); @@ -2406,11 +2356,11 @@ static struct SCH_LABEL_DESC if( labelShapeEnum.Choices().GetCount() == 0 ) { - labelShapeEnum.Map( LABEL_SHAPE::LABEL_INPUT, _HKI( "Input" ) ) - .Map( LABEL_SHAPE::LABEL_OUTPUT, _HKI( "Output" ) ) - .Map( LABEL_SHAPE::LABEL_BIDI, _HKI( "Bidirectional" ) ) - .Map( LABEL_SHAPE::LABEL_TRISTATE, _HKI( "Tri-state" ) ) - .Map( LABEL_SHAPE::LABEL_PASSIVE, _HKI( "Passive" ) ); + labelShapeEnum.Map( LABEL_SHAPE::LABEL_INPUT, _HKI( "Input" ) ) + .Map( LABEL_SHAPE::LABEL_OUTPUT, _HKI( "Output" ) ) + .Map( LABEL_SHAPE::LABEL_BIDI, _HKI( "Bidirectional" ) ) + .Map( LABEL_SHAPE::LABEL_TRISTATE, _HKI( "Tri-state" ) ) + .Map( LABEL_SHAPE::LABEL_PASSIVE, _HKI( "Passive" ) ); } PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); @@ -2435,17 +2385,16 @@ static struct SCH_LABEL_DESC propMgr.InheritsAfter( TYPE_HASH( SCH_HIERLABEL ), TYPE_HASH( SCH_LABEL_BASE ) ); propMgr.InheritsAfter( TYPE_HASH( SCH_GLOBALLABEL ), TYPE_HASH( SCH_LABEL_BASE ) ); - auto hasLabelShape = - []( INSPECTABLE* aItem ) -> bool - { - if( SCH_LABEL_BASE* label = dynamic_cast( aItem ) ) - return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } ); + auto hasLabelShape = []( INSPECTABLE* aItem ) -> bool + { + if( SCH_LABEL_BASE* label = dynamic_cast( aItem ) ) + return label->IsType( { SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_SHEET_PIN_T } ); - return false; - }; + return false; + }; - propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Shape" ), - &SCH_LABEL_BASE::SetLabelShape, &SCH_LABEL_BASE::GetLabelShape ) ) + propMgr.AddProperty( new PROPERTY_ENUM( + _HKI( "Shape" ), &SCH_LABEL_BASE::SetLabelShape, &SCH_LABEL_BASE::GetLabelShape ) ) .SetAvailableFunc( hasLabelShape ); propMgr.Mask( TYPE_HASH( SCH_LABEL_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); @@ -2461,10 +2410,10 @@ static struct SCH_DIRECTIVE_LABEL_DESC if( flagShapeEnum.Choices().GetCount() == 0 ) { - flagShapeEnum.Map( FLAG_SHAPE::FLAG_DOT, _HKI( "Dot" ) ) - .Map( FLAG_SHAPE::FLAG_CIRCLE, _HKI( "Circle" ) ) - .Map( FLAG_SHAPE::FLAG_DIAMOND, _HKI( "Diamond" ) ) - .Map( FLAG_SHAPE::FLAG_RECTANGLE, _HKI( "Rectangle" ) ); + flagShapeEnum.Map( FLAG_SHAPE::FLAG_DOT, _HKI( "Dot" ) ) + .Map( FLAG_SHAPE::FLAG_CIRCLE, _HKI( "Circle" ) ) + .Map( FLAG_SHAPE::FLAG_DIAMOND, _HKI( "Diamond" ) ) + .Map( FLAG_SHAPE::FLAG_RECTANGLE, _HKI( "Rectangle" ) ); } PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); @@ -2475,12 +2424,12 @@ static struct SCH_DIRECTIVE_LABEL_DESC propMgr.InheritsAfter( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( SCH_LABEL_BASE ) ); - propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Shape" ), - &SCH_DIRECTIVE_LABEL::SetFlagShape, &SCH_DIRECTIVE_LABEL::GetFlagShape ) ); + propMgr.AddProperty( new PROPERTY_ENUM( + _HKI( "Shape" ), &SCH_DIRECTIVE_LABEL::SetFlagShape, &SCH_DIRECTIVE_LABEL::GetFlagShape ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Pin length" ), - &SCH_DIRECTIVE_LABEL::SetPinLength, &SCH_DIRECTIVE_LABEL::GetPinLength, - PROPERTY_DISPLAY::PT_SIZE ) ); + propMgr.AddProperty( new PROPERTY( + _HKI( "Pin length" ), &SCH_DIRECTIVE_LABEL::SetPinLength, &SCH_DIRECTIVE_LABEL::GetPinLength, + PROPERTY_DISPLAY::PT_SIZE ) ); propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Text" ) ); propMgr.Mask( TYPE_HASH( SCH_DIRECTIVE_LABEL ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) ); diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp index 581f6b4831..077e0c6564 100644 --- a/eeschema/sch_symbol.cpp +++ b/eeschema/sch_symbol.cpp @@ -75,30 +75,28 @@ SCH_SYMBOL::SCH_SYMBOL() : } -SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId, - const SCH_SHEET_PATH* aSheet, int aUnit, int aBodyStyle, - const VECTOR2I& aPosition, EDA_ITEM* aParent ) : +SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId, const SCH_SHEET_PATH* aSheet, int aUnit, + int aBodyStyle, const VECTOR2I& aPosition, EDA_ITEM* aParent ) : SYMBOL( aParent, SCH_SYMBOL_T ) { Init( aPosition ); - m_unit = aUnit; + m_unit = aUnit; m_bodyStyle = aBodyStyle; - m_lib_id = aLibId; + m_lib_id = aLibId; - std::unique_ptr< LIB_SYMBOL > part; + std::unique_ptr part; part = aSymbol.Flatten(); part->SetParent(); SetLibSymbol( part.release() ); // Copy fields from the library symbol - UpdateFields( aSheet, - true, /* update style */ - false, /* update ref */ - false, /* update other fields */ - true, /* reset ref */ - true /* reset other fields */ ); + UpdateFields( aSheet, true, /* update style */ + false, /* update ref */ + false, /* update other fields */ + true, /* reset ref */ + true /* reset other fields */ ); m_prefix = UTIL::GetRefDesPrefix( m_part->GetReferenceField().GetText() ); @@ -113,8 +111,8 @@ SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const LIB_ID& aLibId, } -SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet, - const PICKED_SYMBOL& aSel, const VECTOR2I& aPosition, EDA_ITEM* aParent ) : +SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet, const PICKED_SYMBOL& aSel, + const VECTOR2I& aPosition, EDA_ITEM* aParent ) : SCH_SYMBOL( aSymbol, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, aPosition, aParent ) { // Set any fields that were modified as part of the symbol selection @@ -131,13 +129,13 @@ SCH_SYMBOL::SCH_SYMBOL( const LIB_SYMBOL& aSymbol, const SCH_SHEET_PATH* aSheet, SCH_SYMBOL::SCH_SYMBOL( const SCH_SYMBOL& aSymbol ) : SYMBOL( aSymbol ) { - m_parent = aSymbol.m_parent; - m_pos = aSymbol.m_pos; - m_unit = aSymbol.m_unit; - m_bodyStyle = aSymbol.m_bodyStyle; - m_lib_id = aSymbol.m_lib_id; + m_parent = aSymbol.m_parent; + m_pos = aSymbol.m_pos; + m_unit = aSymbol.m_unit; + m_bodyStyle = aSymbol.m_bodyStyle; + m_lib_id = aSymbol.m_lib_id; m_isInNetlist = aSymbol.m_isInNetlist; - m_DNP = aSymbol.m_DNP; + m_DNP = aSymbol.m_DNP; const_cast( m_Uuid ) = aSymbol.m_Uuid; @@ -174,28 +172,27 @@ SCH_SYMBOL::~SCH_SYMBOL() void SCH_SYMBOL::Init( const VECTOR2I& pos ) { - m_layer = LAYER_DEVICE; - m_pos = pos; - m_unit = 1; // In multi unit chip - which unit to draw. - m_bodyStyle = BODY_STYLE::BASE; // De Morgan Handling + m_layer = LAYER_DEVICE; + m_pos = pos; + m_unit = 1; // In multi unit chip - which unit to draw. + m_bodyStyle = BODY_STYLE::BASE; // De Morgan Handling // The rotation/mirror transformation matrix. pos normal m_transform = TRANSFORM(); - auto addField = - [&]( FIELD_T id, SCH_LAYER_ID layer ) - { - m_fields.emplace_back( this, id, GetCanonicalFieldName( id ) ); - m_fields.back().SetTextPos( pos ); - m_fields.back().SetLayer( layer ); - }; + auto addField = [&]( FIELD_T id, SCH_LAYER_ID layer ) + { + m_fields.emplace_back( this, id, GetCanonicalFieldName( id ) ); + m_fields.back().SetTextPos( pos ); + m_fields.back().SetLayer( layer ); + }; // construct only the mandatory fields - addField( FIELD_T::REFERENCE, LAYER_REFERENCEPART ); - addField( FIELD_T::VALUE, LAYER_VALUEPART ); - addField( FIELD_T::FOOTPRINT, LAYER_FIELDS ); - addField( FIELD_T::DATASHEET, LAYER_FIELDS ); - addField( FIELD_T::DESCRIPTION, LAYER_FIELDS ); + addField( FIELD_T::REFERENCE, LAYER_REFERENCEPART ); + addField( FIELD_T::VALUE, LAYER_VALUEPART ); + addField( FIELD_T::FOOTPRINT, LAYER_FIELDS ); + addField( FIELD_T::DATASHEET, LAYER_FIELDS ); + addField( FIELD_T::DESCRIPTION, LAYER_FIELDS ); m_prefix = wxString( wxT( "U" ) ); m_isInNetlist = true; @@ -312,25 +309,25 @@ wxString SCH_SYMBOL::GetDatasheet() const void SCH_SYMBOL::UpdatePins() { - std::map altPinMap; - std::map altPinDefs; - std::map> pinUuidMap; - std::set unassignedSchPins; - std::set unassignedLibPins; + std::map altPinMap; + std::map altPinDefs; + std::map> pinUuidMap; + std::set unassignedSchPins; + std::set unassignedLibPins; for( const std::unique_ptr& pin : m_pins ) { - pinUuidMap[ pin->GetNumber() ].insert( pin.get() ); + pinUuidMap[pin->GetNumber()].insert( pin.get() ); unassignedSchPins.insert( pin.get() ); if( !pin->GetAlt().IsEmpty() ) { - altPinMap[ pin->GetNumber() ] = pin->GetAlt(); + altPinMap[pin->GetNumber()] = pin->GetAlt(); auto altDefIt = pin->GetAlternates().find( pin->GetAlt() ); if( altDefIt != pin->GetAlternates().end() ) - altPinDefs[ pin->GetNumber() ] = altDefIt->second; + altPinDefs[pin->GetNumber()] = altDefIt->second; } pin->SetLibPin( nullptr ); @@ -381,7 +378,7 @@ void SCH_SYMBOL::UpdatePins() if( defIt != altPinDefs.end() ) { - for( const auto& [ name, alt ] : pin->GetAlternates() ) + for( const auto& [name, alt] : pin->GetAlternates() ) { if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type ) { @@ -395,7 +392,7 @@ void SCH_SYMBOL::UpdatePins() pin->SetAlt( altName ); } - m_pinMap[ libPin ] = pin; + m_pinMap[libPin] = pin; } // Add any pins that were not found in the symbol @@ -416,7 +413,7 @@ void SCH_SYMBOL::UpdatePins() pin = m_pins.emplace_back( std::make_unique( SCH_PIN( this, libPin ) ) ).get(); } - m_pinMap[ libPin ] = pin; + m_pinMap[libPin] = pin; pin->GetAlternates() = libPin->GetAlternates(); pin->SetLibPin( libPin ); pin->SetPosition( libPin->GetPosition() ); @@ -436,7 +433,7 @@ void SCH_SYMBOL::UpdatePins() if( defIt != altPinDefs.end() ) { - for( const auto& [ name, alt ] : pin->GetAlternates() ) + for( const auto& [name, alt] : pin->GetAlternates() ) { if( alt.m_Shape == defIt->second.m_Shape && alt.m_Type == defIt->second.m_Type ) { @@ -473,7 +470,6 @@ void SCH_SYMBOL::UpdatePins() for( std::unique_ptr& pin : m_pins ) pin->SetSelected(); } - } @@ -536,8 +532,7 @@ wxString SCH_SYMBOL::GetBodyStyleDescription( int aBodyStyle, bool aLabel ) cons } -bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath, - bool aTestFromEnd ) const +bool SCH_SYMBOL::GetInstance( SCH_SYMBOL_INSTANCE& aInstance, const KIID_PATH& aSheetPath, bool aTestFromEnd ) const { for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences ) { @@ -570,16 +565,15 @@ void SCH_SYMBOL::RemoveInstance( const KIID_PATH& aInstancePath ) { // Search for an existing path and remove it if found // (search from back to avoid invalidating iterator on remove) - for( int ii = (int) m_instanceReferences.size() - 1; ii >= 0; --ii ) + for( int ii = m_instanceReferences.size() - 1; ii >= 0; --ii ) { if( m_instanceReferences[ii].m_Path == aInstancePath ) { - wxLogTrace( traceSchSheetPaths, wxS( "Removing symbol instance:\n" - " sheet path %s\n" - " reference %s, unit %d from symbol %s." ), - aInstancePath.AsString(), - m_instanceReferences[ii].m_Reference, - m_instanceReferences[ii].m_Unit, + wxLogTrace( traceSchSheetPaths, + wxS( "Removing symbol instance:\n" + " sheet path %s\n" + " reference %s, unit %d from symbol %s." ), + aInstancePath.AsString(), m_instanceReferences[ii].m_Reference, m_instanceReferences[ii].m_Unit, m_Uuid.AsString() ); m_instanceReferences.erase( m_instanceReferences.begin() + ii ); @@ -603,23 +597,23 @@ void SCH_SYMBOL::AddHierarchicalReference( const SCH_SYMBOL_INSTANCE& aInstance { RemoveInstance( aInstance.m_Path ); - wxLogTrace( traceSchSheetPaths, wxS( "Adding symbol '%s' instance:\n" - " sheet path '%s'\n" - " reference '%s'\n" - " unit %d\n" ), - m_Uuid.AsString(), - aInstance.m_Path.AsString(), - aInstance.m_Reference, - aInstance.m_Unit ); + SCH_SYMBOL_INSTANCE instance = aInstance; - m_instanceReferences.push_back( aInstance ); + wxLogTrace( traceSchSheetPaths, + wxS( "Adding symbol '%s' instance:\n" + " sheet path '%s'\n" + " reference '%s'\n" + " unit %d\n" ), + m_Uuid.AsString(), instance.m_Path.AsString(), instance.m_Reference, instance.m_Unit ); + + m_instanceReferences.push_back( instance ); // This should set the default instance to the first saved instance data for each symbol // when importing sheets. if( m_instanceReferences.size() == 1 ) { - GetField( FIELD_T::REFERENCE )->SetText( aInstance.m_Reference ); - m_unit = aInstance.m_Unit; + GetField( FIELD_T::REFERENCE )->SetText( instance.m_Reference ); + m_unit = instance.m_Unit; } } @@ -630,17 +624,15 @@ const wxString SCH_SYMBOL::GetRef( const SCH_SHEET_PATH* sheet, bool aIncludeUni wxString ref; wxString subRef; - wxLogTrace( traceSchSymbolRef, - "GetRef for symbol %s on path %s (sheet path has %zu sheets)", - m_Uuid.AsString(), path.AsString(), sheet->size() ); + wxLogTrace( traceSchSymbolRef, "GetRef for symbol %s on path %s (sheet path has %zu sheets)", m_Uuid.AsString(), + path.AsString(), sheet->size() ); - wxLogTrace( traceSchSymbolRef, " Symbol has %zu instance references", - m_instanceReferences.size() ); + wxLogTrace( traceSchSymbolRef, " Symbol has %zu instance references", m_instanceReferences.size() ); for( const SCH_SYMBOL_INSTANCE& instance : m_instanceReferences ) { - wxLogTrace( traceSchSymbolRef, " Instance: path=%s, ref=%s", - instance.m_Path.AsString(), instance.m_Reference ); + wxLogTrace( traceSchSymbolRef, " Instance: path=%s, ref=%s", instance.m_Path.AsString(), + instance.m_Reference ); if( instance.m_Path == path ) { @@ -717,7 +709,7 @@ void SCH_SYMBOL::SetRef( const SCH_SHEET_PATH* sheet, const wxString& ref ) m_prefix = wxT( "U" ); // Power symbols have references starting with # and are not included in netlists - m_isInNetlist = ! ref.StartsWith( wxT( "#" ) ); + m_isInNetlist = !ref.StartsWith( wxT( "#" ) ); } @@ -881,8 +873,7 @@ void SCH_SYMBOL::SetDNP( bool aEnable, const SCH_SHEET_PATH& aInstance, const st } -void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, - const wxString& aVariantName ) +void SCH_SYMBOL::SetExcludedFromBOM( bool aEnable, const SCH_SHEET_PATH* aInstance, const wxString& aVariantName ) { if( !aInstance ) { @@ -1039,8 +1030,7 @@ void SCH_SYMBOL::SetUnitSelection( int aUnitSelection ) } -const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, - bool aAllowExtraText ) const +const wxString SCH_SYMBOL::GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, bool aAllowExtraText ) const { if( aResolve ) return GetField( FIELD_T::VALUE )->GetShownText( aPath, aAllowExtraText ); @@ -1161,8 +1151,8 @@ SCH_FIELD* SCH_SYMBOL::FindFieldCaseInsensitive( const wxString& aFieldName ) } -void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef, - bool aUpdateOtherFields, bool aResetRef, bool aResetOtherFields ) +void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, bool aUpdateRef, bool aUpdateOtherFields, + bool aResetRef, bool aResetOtherFields ) { if( m_part ) { @@ -1227,8 +1217,7 @@ void SCH_SYMBOL::UpdateFields( const SCH_SHEET_PATH* aPath, bool aUpdateStyle, b } -void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& aCommit, - PROPERTY_BASE* aProperty ) +void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& aCommit, PROPERTY_BASE* aProperty ) { bool updateValue = true; bool updateExclFromBOM = true; @@ -1247,12 +1236,7 @@ void SCH_SYMBOL::SyncOtherUnits( const SCH_SHEET_PATH& aSourceSheet, SCH_COMMIT& updatePins = false; } - if( !updateValue - && !updateExclFromBOM - && !updateExclFromBoard - && !updateDNP - && !updateOtherFields - && !updatePins ) + if( !updateValue && !updateExclFromBOM && !updateExclFromBoard && !updateDNP && !updateOtherFields && !updatePins ) { return; } @@ -1371,10 +1355,8 @@ const SCH_PIN* SCH_SYMBOL::GetPin( const VECTOR2I& aPos ) const { for( const std::unique_ptr& pin : m_pins ) { - int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() - : GetUnit(); - int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() - : GetBodyStyle(); + int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit(); + int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle(); if( pin_unit > 0 && pin_unit != GetUnit() ) continue; @@ -1457,14 +1439,13 @@ std::vector SCH_SYMBOL::GetPins() const void SCH_SYMBOL::swapData( SCH_ITEM* aItem ) { - wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T, - wxT( "Cannot swap data with invalid symbol." ) ); + wxCHECK_RET( aItem != nullptr && aItem->Type() == SCH_SYMBOL_T, wxT( "Cannot swap data with invalid symbol." ) ); SCH_SYMBOL* symbol = static_cast( aItem ); std::swap( m_lib_id, symbol->m_lib_id ); - m_pins.swap( symbol->m_pins ); // std::vector's swap() + m_pins.swap( symbol->m_pins ); // std::vector's swap() for( std::unique_ptr& pin : symbol->m_pins ) pin->SetParent( symbol ); @@ -1482,7 +1463,7 @@ void SCH_SYMBOL::swapData( SCH_ITEM* aItem ) std::swap( m_unit, symbol->m_unit ); std::swap( m_bodyStyle, symbol->m_bodyStyle ); - m_fields.swap( symbol->m_fields ); // std::vector's swap() + m_fields.swap( symbol->m_fields ); // std::vector's swap() for( SCH_FIELD& field : symbol->m_fields ) field.SetParent( symbol ); @@ -1543,9 +1524,9 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i { static wxRegEx operatingPoint( wxT( "^" "OP" - "(:[^.]*)?" // pin - "(.([0-9])?" // precisionStr - "([a-zA-Z]*))?" // rangeStr + "(:[^.]*)?" // pin + "(.([0-9])?" // precisionStr + "([a-zA-Z]*))?" // rangeStr "$" ) ); wxCHECK( aPath, false ); @@ -1575,8 +1556,8 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i simLibMgr.SetFilesStack( std::move( embeddedFilesStack ) ); NULL_REPORTER devnull; - SIM_MODEL& model = simLibMgr.CreateModel( aPath, const_cast( *this ), - true, aDepth + 1, devnull ).model; + SIM_MODEL& model = + simLibMgr.CreateModel( aPath, const_cast( *this ), true, aDepth + 1, devnull ).model; SPICE_ITEM spiceItem; spiceItem.refName = GetRef( aPath ); @@ -1598,7 +1579,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i } else { - pin = pin.SubString( 1, -1 ); // Strip ':' from front + pin = pin.SubString( 1, -1 ); // Strip ':' from front for( const std::reference_wrapper& modelPin : model.GetPins() ) { @@ -1633,8 +1614,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i for( const SCH_FIELD& field : m_fields ) { - wxString fieldName = field.IsMandatory() ? field.GetCanonicalName() - : field.GetName(); + wxString fieldName = field.IsMandatory() ? field.GetCanonicalName() : field.GetName(); wxString textToken = field.GetText(); textToken.Replace( " ", wxEmptyString ); @@ -1656,22 +1636,18 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i } // Consider missing simulation fields as empty, not un-resolved - if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) - || token->IsSameAs( wxT( "SIM.TYPE" ) ) - || token->IsSameAs( wxT( "SIM.PINS" ) ) - || token->IsSameAs( wxT( "SIM.PARAMS" ) ) - || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) - || token->IsSameAs( wxT( "SIM.NAME" ) ) ) + if( token->IsSameAs( wxT( "SIM.DEVICE" ) ) || token->IsSameAs( wxT( "SIM.TYPE" ) ) + || token->IsSameAs( wxT( "SIM.PINS" ) ) || token->IsSameAs( wxT( "SIM.PARAMS" ) ) + || token->IsSameAs( wxT( "SIM.LIBRARY" ) ) || token->IsSameAs( wxT( "SIM.NAME" ) ) ) { *token = wxEmptyString; return true; } for( const TEMPLATE_FIELDNAME& templateFieldname : - schematic->Settings().m_TemplateFieldNames.GetTemplateFieldNames() ) + schematic->Settings().m_TemplateFieldNames.GetTemplateFieldNames() ) { - if( token->IsSameAs( templateFieldname.m_Name ) - || token->IsSameAs( templateFieldname.m_Name.Upper() ) ) + if( token->IsSameAs( templateFieldname.m_Name ) || token->IsSameAs( templateFieldname.m_Name.Upper() ) ) { // If we didn't find it in the fields list then it isn't set on this symbol. // Just return an empty string. @@ -1687,7 +1663,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i wxArrayString parts = wxSplit( footprint, ':' ); if( parts.Count() > 0 ) - *token = parts[ 0 ]; + *token = parts[0]; else *token = wxEmptyString; @@ -1700,7 +1676,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i wxArrayString parts = wxSplit( footprint, ':' ); if( parts.Count() > 1 ) - *token = parts[ std::min( 1, (int) parts.size() - 1 ) ]; + *token = parts[std::min( 1, (int) parts.size() - 1 )]; else *token = wxEmptyString; @@ -1772,33 +1748,35 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i return true; } - else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) ) - || token->StartsWith( wxT( "NET_NAME(" ) ) - || token->StartsWith( wxT( "NET_CLASS(" ) ) - || token->StartsWith( wxT( "PIN_NAME(" ) ) - || token->StartsWith( wxT( "UNIT(" ) ) ) + else if( token->StartsWith( wxT( "SHORT_NET_NAME(" ) ) || token->StartsWith( wxT( "NET_NAME(" ) ) + || token->StartsWith( wxT( "NET_CLASS(" ) ) || token->StartsWith( wxT( "PIN_NAME(" ) ) + || token->StartsWith( wxT( "PIN_BASE_NAME(" ) ) || token->StartsWith( wxT( "PIN_ALT_LIST(" ) ) + || token->StartsWith( wxT( "UNIT(" ) ) ) { wxString pinNumber = token->AfterFirst( '(' ); pinNumber = pinNumber.BeforeLast( ')' ); + bool isUnitFunction = token->StartsWith( wxT( "UNIT(" ) ); + // First, try to find the pin in the current unit (for backward compatibility) // For UNIT(), always search all pins to find which unit the pin belongs to - std::vector pinsToSearch = token->StartsWith( wxT( "UNIT(" ) ) - ? GetAllLibPins() - : GetPins( aPath ); + std::vector pinsToSearch = isUnitFunction ? GetAllLibPins() : GetPins( aPath ); for( SCH_PIN* pin : pinsToSearch ) { if( pin->GetNumber() == pinNumber ) { - if( token->StartsWith( wxT( "UNIT(" ) ) ) + if( isUnitFunction ) { // Return the full unit reference (e.g., "J601A") - int pinUnit = pin->GetUnit(); + int pinUnit = pin->GetUnit(); + wxString result; if( pinUnit > 0 ) - *token = GetRef( aPath, false ) + SubReference( pinUnit, false ); + result = GetRef( aPath, false ) + SubReference( pinUnit, false ); else - *token = GetRef( aPath, false ); + result = GetRef( aPath, false ); + + *token = result; return true; } else if( token->StartsWith( wxT( "PIN_NAME" ) ) ) @@ -1806,6 +1784,26 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt(); return true; } + else if( token->StartsWith( wxT( "PIN_BASE_NAME" ) ) ) + { + *token = pin->GetBaseName(); + return true; + } + else if( token->StartsWith( wxT( "PIN_ALT_LIST" ) ) ) + { + // Build complete list: base name first, then all alternates + wxString altList = pin->GetBaseName(); + + const std::map& alts = pin->GetAlternates(); + for( const auto& [altName, altDef] : alts ) + { + altList += wxT( ", " ); + altList += altName; + } + + *token = altList; + return true; + } SCH_CONNECTION* conn = pin->Connection( aPath ); @@ -1829,23 +1827,99 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i } // If pin not found in current unit, search all units (auto-resolution) - if( !token->StartsWith( wxT( "UNIT(" ) ) ) + if( !isUnitFunction ) { for( SCH_PIN* pin : GetAllLibPins() ) { if( pin->GetNumber() == pinNumber ) { - if( token->StartsWith( wxT( "PIN_NAME" ) ) ) + // For PIN_BASE_NAME and PIN_ALT_LIST, we can use library data + if( token->StartsWith( wxT( "PIN_BASE_NAME" ) ) ) { - *token = pin->GetAlt().IsEmpty() ? pin->GetName() : pin->GetAlt(); + *token = pin->GetBaseName(); + return true; + } + else if( token->StartsWith( wxT( "PIN_ALT_LIST" ) ) ) + { + // Build complete list: base name first, then all alternates + wxString altList = pin->GetBaseName(); + + const std::map& alts = pin->GetAlternates(); + for( const auto& [altName, altDef] : alts ) + { + altList += wxT( ", " ); + altList += altName; + } + + *token = altList; return true; } - // For net-related functions, we need to find the correct sheet path - // that has this pin's unit selected - // Note: This is a simplification - in practice we may need to search - // for the actual instance with this unit - SCH_CONNECTION* conn = pin->Connection( aPath ); + // For net-related functions, find which sheet path has this pin's unit + int pinUnit = pin->GetUnit(); + + // Search all sheets for a symbol with our reference and the correct unit + // This is needed because each unit of a multi-unit symbol is a separate object + SCH_SHEET_PATH targetPath; + SCH_SYMBOL* targetSymbol = nullptr; + + if( Schematic() ) + { + for( const SCH_SHEET_PATH& sheetPath : Schematic()->Hierarchy() ) + { + for( SCH_ITEM* item : sheetPath.LastScreen()->Items().OfType( SCH_SYMBOL_T ) ) + { + SCH_SYMBOL* symbol = static_cast( item ); + + // Check if this symbol has the same reference designator and the correct unit + if( symbol->GetRef( &sheetPath, false ) == GetRef( aPath, false ) + && symbol->GetUnitSelection( &sheetPath ) == pinUnit ) + { + targetPath = sheetPath; // Copy the sheet path + targetSymbol = symbol; + break; + } + } + + if( targetSymbol ) + break; + } + } + + if( !targetSymbol ) + { + // Unit not placed on any sheet + *token = wxString::Format( wxT( "" ), SubReference( pinUnit, false ) ); + return true; + } + + // Get the pin from the actual instance symbol we found + // Match by pin number, not by pointer, since the library pins are different objects + SCH_PIN* instancePin = nullptr; + for( SCH_PIN* candidate : targetSymbol->GetPins( &targetPath ) ) + { + if( candidate->GetNumber() == pinNumber ) + { + instancePin = candidate; + break; + } + } + + if( !instancePin ) + { + *token = wxEmptyString; + return true; + } + + // PIN_NAME doesn't need connection data, just instance pin + if( token->StartsWith( wxT( "PIN_NAME" ) ) ) + { + *token = instancePin->GetAlt().IsEmpty() ? instancePin->GetName() : instancePin->GetAlt(); + return true; + } + + // Now get the connection from the correct sheet path + SCH_CONNECTION* conn = instancePin->Connection( &targetPath ); if( !conn ) *token = wxEmptyString; @@ -1860,7 +1934,7 @@ bool SCH_SYMBOL::ResolveTextVar( const SCH_SHEET_PATH* aPath, wxString* token, i else if( token->StartsWith( wxT( "NET_NAME" ) ) ) *token = conn->Name(); else if( token->StartsWith( wxT( "NET_CLASS" ) ) ) - *token = pin->GetEffectiveNetClass( aPath )->GetName(); + *token = instancePin->GetEffectiveNetClass( &targetPath )->GetName(); return true; } @@ -1897,7 +1971,7 @@ void SCH_SYMBOL::ClearAnnotation( const SCH_SHEET_PATH* aSheetPath, bool aResetP { for( SCH_SYMBOL_INSTANCE& instance : m_instanceReferences ) { - if( instance.m_Reference.IsEmpty() || aResetPrefix) + if( instance.m_Reference.IsEmpty() || aResetPrefix ) instance.m_Reference = UTIL::GetRefDesUnannotated( m_prefix ); else instance.m_Reference = UTIL::GetRefDesUnannotated( instance.m_Reference ); @@ -1941,44 +2015,44 @@ bool SCH_SYMBOL::AddSheetPathReferenceEntryIfMissing( const KIID_PATH& aSheetPat void SCH_SYMBOL::SetOrientation( int aOrientation ) { TRANSFORM temp = TRANSFORM(); - bool transform = false; + bool transform = false; switch( aOrientation ) { case SYM_ORIENT_0: - case SYM_NORMAL: // default transform matrix + case SYM_NORMAL: // default transform matrix m_transform = TRANSFORM(); break; - case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation) - temp.x1 = 0; - temp.y1 = 1; - temp.x2 = -1; - temp.y2 = 0; + case SYM_ROTATE_COUNTERCLOCKWISE: // Rotate + (incremental rotation) + temp.x1 = 0; + temp.y1 = 1; + temp.x2 = -1; + temp.y2 = 0; transform = true; break; - case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation) - temp.x1 = 0; - temp.y1 = -1; - temp.x2 = 1; - temp.y2 = 0; + case SYM_ROTATE_CLOCKWISE: // Rotate - (incremental rotation) + temp.x1 = 0; + temp.y1 = -1; + temp.x2 = 1; + temp.y2 = 0; transform = true; break; - case SYM_MIRROR_Y: // Mirror Y (incremental transform) - temp.x1 = -1; - temp.y1 = 0; - temp.x2 = 0; - temp.y2 = 1; + case SYM_MIRROR_Y: // Mirror Y (incremental transform) + temp.x1 = -1; + temp.y1 = 0; + temp.x2 = 0; + temp.y2 = 1; transform = true; break; - case SYM_MIRROR_X: // Mirror X (incremental transform) - temp.x1 = 1; - temp.y1 = 0; - temp.x2 = 0; - temp.y2 = -1; + case SYM_MIRROR_X: // Mirror X (incremental transform) + temp.x1 = 1; + temp.y1 = 0; + temp.x2 = 0; + temp.y2 = -1; transform = true; break; @@ -1998,65 +2072,65 @@ void SCH_SYMBOL::SetOrientation( int aOrientation ) SetOrientation( SYM_ROTATE_CLOCKWISE ); break; - case ( SYM_ORIENT_0 + SYM_MIRROR_X ): + case( SYM_ORIENT_0 + SYM_MIRROR_X ): SetOrientation( SYM_ORIENT_0 ); SetOrientation( SYM_MIRROR_X ); break; - case ( SYM_ORIENT_0 + SYM_MIRROR_Y ): + case( SYM_ORIENT_0 + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_0 ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_0 + SYM_MIRROR_X + SYM_MIRROR_Y ): + case( SYM_ORIENT_0 + SYM_MIRROR_X + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_0 ); SetOrientation( SYM_MIRROR_X ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_90 + SYM_MIRROR_X ): + case( SYM_ORIENT_90 + SYM_MIRROR_X ): SetOrientation( SYM_ORIENT_90 ); SetOrientation( SYM_MIRROR_X ); break; - case ( SYM_ORIENT_90 + SYM_MIRROR_Y ): + case( SYM_ORIENT_90 + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_90 ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_90 + SYM_MIRROR_X + SYM_MIRROR_Y ): + case( SYM_ORIENT_90 + SYM_MIRROR_X + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_90 ); SetOrientation( SYM_MIRROR_X ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_180 + SYM_MIRROR_X ): + case( SYM_ORIENT_180 + SYM_MIRROR_X ): SetOrientation( SYM_ORIENT_180 ); SetOrientation( SYM_MIRROR_X ); break; - case ( SYM_ORIENT_180 + SYM_MIRROR_Y ): + case( SYM_ORIENT_180 + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_180 ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_180 + SYM_MIRROR_X + SYM_MIRROR_Y ): + case( SYM_ORIENT_180 + SYM_MIRROR_X + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_180 ); SetOrientation( SYM_MIRROR_X ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_270 + SYM_MIRROR_X ): + case( SYM_ORIENT_270 + SYM_MIRROR_X ): SetOrientation( SYM_ORIENT_270 ); SetOrientation( SYM_MIRROR_X ); break; - case ( SYM_ORIENT_270 + SYM_MIRROR_Y ): + case( SYM_ORIENT_270 + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_270 ); SetOrientation( SYM_MIRROR_Y ); break; - case ( SYM_ORIENT_270 + SYM_MIRROR_X + SYM_MIRROR_Y ): + case( SYM_ORIENT_270 + SYM_MIRROR_X + SYM_MIRROR_Y ): SetOrientation( SYM_ORIENT_270 ); SetOrientation( SYM_MIRROR_X ); SetOrientation( SYM_MIRROR_Y ); @@ -2100,24 +2174,21 @@ int SCH_SYMBOL::GetOrientation() const if( s_transformToOrientationCache.count( m_transform ) ) return s_transformToOrientationCache.at( m_transform ); - int rotate_values[] = - { - SYM_ORIENT_0, - SYM_ORIENT_90, - SYM_ORIENT_180, - SYM_ORIENT_270, - SYM_MIRROR_X + SYM_ORIENT_0, - SYM_MIRROR_X + SYM_ORIENT_90, - SYM_MIRROR_X + SYM_ORIENT_270, - SYM_MIRROR_Y, - SYM_MIRROR_Y + SYM_ORIENT_0, - SYM_MIRROR_Y + SYM_ORIENT_90, - SYM_MIRROR_Y + SYM_ORIENT_180, - SYM_MIRROR_Y + SYM_ORIENT_270 - }; + int rotate_values[] = { SYM_ORIENT_0, + SYM_ORIENT_90, + SYM_ORIENT_180, + SYM_ORIENT_270, + SYM_MIRROR_X + SYM_ORIENT_0, + SYM_MIRROR_X + SYM_ORIENT_90, + SYM_MIRROR_X + SYM_ORIENT_270, + SYM_MIRROR_Y, + SYM_MIRROR_Y + SYM_ORIENT_0, + SYM_MIRROR_Y + SYM_ORIENT_90, + SYM_MIRROR_Y + SYM_ORIENT_180, + SYM_MIRROR_Y + SYM_ORIENT_270 }; // Try to find the current transform option: - TRANSFORM transform = m_transform; + TRANSFORM transform = m_transform; SCH_SYMBOL temp( *this ); temp.SetParentGroup( nullptr ); @@ -2139,29 +2210,25 @@ int SCH_SYMBOL::GetOrientation() const } -#if defined(DEBUG) +#if defined( DEBUG ) void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const { // for now, make it look like XML: - NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() - << " ref=\"" << TO_UTF8( GetField( FIELD_T::REFERENCE )->GetName() ) - << '"' << " chipName=\"" - << GetLibId().Format().wx_str() << '"' << m_pos - << " layer=\"" << m_layer - << '"' << ">\n"; + NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << " ref=\"" + << TO_UTF8( GetField( FIELD_T::REFERENCE )->GetName() ) << '"' << " chipName=\"" + << GetLibId().Format().wx_str() << '"' << m_pos << " layer=\"" << m_layer << '"' + << ">\n"; // skip the reference, it's been output already. - for( int i = 1; i < (int) GetFields().size(); ++i ) + for( int i = 1; i < (int) GetFields().size(); ++i ) { const wxString& value = GetFields()[i].GetText(); if( !value.IsEmpty() ) { - NestedSpace( nestLevel + 1, os ) << "\n"; + NestedSpace( nestLevel + 1, os ) << "\n"; } } @@ -2173,13 +2240,12 @@ void SCH_SYMBOL::Show( int nestLevel, std::ostream& os ) const BOX2I SCH_SYMBOL::doGetBoundingBox( bool aIncludePins, bool aIncludeFields ) const { - BOX2I bBox; + BOX2I bBox; if( m_part ) bBox = m_part->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false ); else - bBox = LIB_SYMBOL::GetDummy()->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, - false ); + bBox = LIB_SYMBOL::GetDummy()->GetBodyBoundingBox( m_unit, m_bodyStyle, aIncludePins, false ); bBox = m_transform.TransformCoordinate( bBox ); bBox.Normalize(); @@ -2232,29 +2298,28 @@ void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector( aFrame ); SCH_SHEET_PATH* currentSheet = schframe ? &schframe->GetCurrentSheet() : nullptr; - auto addExcludes = - [&]() - { - wxArrayString msgs; + auto addExcludes = [&]() + { + wxArrayString msgs; - if( GetExcludedFromSim() ) - msgs.Add( _( "Simulation" ) ); + if( GetExcludedFromSim() ) + msgs.Add( _( "Simulation" ) ); - if( GetExcludedFromBOM() ) - msgs.Add( _( "BOM" ) ); + if( GetExcludedFromBOM() ) + msgs.Add( _( "BOM" ) ); - if( GetExcludedFromBoard() ) - msgs.Add( _( "Board" ) ); + if( GetExcludedFromBoard() ) + msgs.Add( _( "Board" ) ); - if( GetDNP( currentSheet ) ) - msgs.Add( _( "DNP" ) ); + if( GetDNP( currentSheet ) ) + msgs.Add( _( "DNP" ) ); - msg = wxJoin( msgs, '|' ); - msg.Replace( '|', wxS( ", " ) ); + msg = wxJoin( msgs, '|' ); + msg.Replace( '|', wxS( ", " ) ); - if( !msg.empty() ) - aList.emplace_back( _( "Exclude from" ), msg ); - }; + if( !msg.empty() ) + aList.emplace_back( _( "Exclude from" ), msg ); + }; // part and alias can differ if alias is not the root if( m_part ) @@ -2269,19 +2334,16 @@ void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetText() ) ); addExcludes(); - aList.emplace_back( _( "Name" ), - KIUI::EllipsizeStatusText( aFrame, - GetLibId().GetLibItemName() ) ); + aList.emplace_back( _( "Name" ), KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) ); } -#if 0 // Display symbol flags, for debug only +#if 0 // Display symbol flags, for debug only aList.emplace_back( _( "flags" ), wxString::Format( "%X", GetEditFlags() ) ); #endif @@ -2289,7 +2351,7 @@ void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector parent = m_part->GetParent().lock(); + std::shared_ptr parent = m_part->GetParent().lock(); if( parent ) msg = parent->GetName(); @@ -2315,8 +2377,7 @@ void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetText(), + aList.emplace_back( _( "Description" ) + wxT( ": " ) + GetField( FIELD_T::DESCRIPTION )->GetText(), _( "Keywords" ) + wxT( ": " ) + m_part->GetKeyWords() ); } } @@ -2325,11 +2386,9 @@ void SCH_SYMBOL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetText() ) ); + aList.emplace_back( _( "Value" ), KIUI::EllipsizeStatusText( aFrame, GetField( FIELD_T::VALUE )->GetText() ) ); addExcludes(); - aList.emplace_back( _( "Name" ), - KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) ); + aList.emplace_back( _( "Name" ), KIUI::EllipsizeStatusText( aFrame, GetLibId().GetLibItemName() ) ); wxString libNickname = GetLibId().GetLibNickname(); @@ -2366,7 +2425,7 @@ void SCH_SYMBOL::MirrorHorizontally( int aCenter ) SetOrientation( SYM_MIRROR_Y ); MIRROR( m_pos.x, aCenter ); - dx -= m_pos.x; // dx,0 is the move vector for this transform + dx -= m_pos.x; // dx,0 is the move vector for this transform for( SCH_FIELD& field : m_fields ) { @@ -2384,7 +2443,7 @@ void SCH_SYMBOL::MirrorVertically( int aCenter ) SetOrientation( SYM_MIRROR_X ); MIRROR( m_pos.y, aCenter ); - dy -= m_pos.y; // 0,dy is the move vector for this transform + dy -= m_pos.y; // 0,dy is the move vector for this transform for( SCH_FIELD& field : m_fields ) { @@ -2440,7 +2499,7 @@ bool SCH_SYMBOL::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) c } -void SCH_SYMBOL::GetEndPoints( std::vector & aItemList ) +void SCH_SYMBOL::GetEndPoints( std::vector& aItemList ) { for( std::unique_ptr& pin : m_pins ) { @@ -2456,8 +2515,7 @@ void SCH_SYMBOL::GetEndPoints( std::vector & aItemList ) bool SCH_SYMBOL::UpdateDanglingState( std::vector& aItemListByType, - std::vector& aItemListByPos, - const SCH_SHEET_PATH* aPath ) + std::vector& aItemListByPos, const SCH_SHEET_PATH* aPath ) { bool changed = false; @@ -2494,8 +2552,7 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector& aItemListB do_break = true; break; - default: - break; + default: break; } if( do_break ) @@ -2518,8 +2575,7 @@ VECTOR2I SCH_SYMBOL::GetPinPhysicalPosition( const SCH_PIN* aPin ) const } -bool SCH_SYMBOL::HasConnectivityChanges( const SCH_ITEM* aItem, - const SCH_SHEET_PATH* aInstance ) const +bool SCH_SYMBOL::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const { // Do not compare to ourself. if( aItem == this ) @@ -2553,8 +2609,7 @@ bool SCH_SYMBOL::HasConnectivityChanges( const SCH_ITEM* aItem, return true; // Power symbol value field changes are connectivity changes. - if( IsPower() - && ( GetValue( true, aInstance, false ) != symbol->GetValue( true, aInstance, false ) ) ) + if( IsPower() && ( GetValue( true, aInstance, false ) != symbol->GetValue( true, aInstance, false ) ) ) return true; if( m_pins.size() != symbol->m_pins.size() ) @@ -2578,10 +2633,8 @@ std::vector SCH_SYMBOL::GetConnectionPoints() const { // Collect only pins attached to the current unit and convert. // others are not associated to this symbol instance - int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() - : GetUnit(); - int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() - : GetBodyStyle(); + int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit(); + int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle(); if( pin_unit > 0 && pin_unit != GetUnit() ) continue; @@ -2618,8 +2671,7 @@ wxString SCH_SYMBOL::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aF } -INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, - const std::vector& aScanTypes ) +INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, const std::vector& aScanTypes ) { for( KICAD_T scanType : aScanTypes ) { @@ -2670,10 +2722,8 @@ INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, { // Collect only pins attached to the current unit and convert. // others are not associated to this symbol instance - int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() - : GetUnit(); - int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() - : GetBodyStyle(); + int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit(); + int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle(); if( pin_unit > 0 && pin_unit != GetUnit() ) continue; @@ -2691,7 +2741,7 @@ INSPECT_RESULT SCH_SYMBOL::Visit( INSPECTOR aInspector, void* aTestData, } -bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const +bool SCH_SYMBOL::operator<( const SCH_ITEM& aItem ) const { if( Type() != aItem.Type() ) return Type() < aItem.Type(); @@ -2709,7 +2759,7 @@ bool SCH_SYMBOL::operator <( const SCH_ITEM& aItem ) const if( m_pos.y != symbol->m_pos.y ) return m_pos.y < symbol->m_pos.y; - return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort + return m_Uuid < aItem.m_Uuid; // Ensure deterministic sort } @@ -2745,23 +2795,22 @@ bool SCH_SYMBOL::operator!=( const SCH_SYMBOL& aSymbol ) const SCH_SYMBOL& SCH_SYMBOL::operator=( const SCH_SYMBOL& aSymbol ) { wxCHECK_MSG( Type() == aSymbol.Type(), *this, - wxT( "Cannot assign object type " ) + aSymbol.GetClass() + wxT( " to type " ) + - GetClass() ); + wxT( "Cannot assign object type " ) + aSymbol.GetClass() + wxT( " to type " ) + GetClass() ); if( &aSymbol != this ) { SYMBOL::operator=( aSymbol ); - m_lib_id = aSymbol.m_lib_id; + m_lib_id = aSymbol.m_lib_id; m_part.reset( aSymbol.m_part ? new LIB_SYMBOL( *aSymbol.m_part ) : nullptr ); - m_pos = aSymbol.m_pos; - m_unit = aSymbol.m_unit; + m_pos = aSymbol.m_pos; + m_unit = aSymbol.m_unit; m_bodyStyle = aSymbol.m_bodyStyle; m_transform = aSymbol.m_transform; m_instanceReferences = aSymbol.m_instanceReferences; - m_fields = aSymbol.m_fields; // std::vector's assignment operator + m_fields = aSymbol.m_fields; // std::vector's assignment operator // Reparent fields after assignment to new symbol. for( SCH_FIELD& field : m_fields ) @@ -2842,8 +2891,8 @@ bool SCH_SYMBOL::IsInNetlist() const } -void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) { if( aBackground ) return; @@ -2857,10 +2906,10 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& std::vector tempPins = tempSymbol.GetGraphicalPins( GetUnit(), GetBodyStyle() ); // Copy the pin info from the symbol to the temp pins - for( unsigned i = 0; i < tempPins.size(); ++ i ) + for( unsigned i = 0; i < tempPins.size(); ++i ) { - SCH_PIN* symbolPin = GetPin( libPins[ i ] ); - SCH_PIN* tempPin = tempPins[ i ]; + SCH_PIN* symbolPin = GetPin( libPins[i] ); + SCH_PIN* tempPin = tempPins[i]; tempPin->SetName( symbolPin->GetShownName() ); tempPin->SetType( symbolPin->GetType() ); @@ -2888,14 +2937,12 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& for( bool local_background : { true, false } ) { - tempSymbol.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), - m_pos, GetDNP() ); + tempSymbol.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), m_pos, GetDNP() ); for( SCH_FIELD field : m_fields ) { field.ClearRenderCache(); - field.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), - m_pos, GetDNP() ); + field.Plot( aPlotter, local_background, aPlotOpts, GetUnit(), GetBodyStyle(), m_pos, GetDNP() ); if( IsSymbolLikePowerLocalLabel() && field.GetId() == FIELD_T::VALUE && ( field.IsVisible() || field.IsForceVisible() ) ) @@ -2917,20 +2964,18 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& for( const SCH_FIELD& field : GetFields() ) { - wxString text_field = field.GetShownText( sheet, false); + wxString text_field = field.GetShownText( sheet, false ); if( text_field.IsEmpty() ) continue; - properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), - field.GetName(), text_field ) ); + properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), field.GetName(), text_field ) ); } if( !m_part->GetKeyWords().IsEmpty() ) { - properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), - _( "Keywords" ), - m_part->GetKeyWords() ) ); + properties.emplace_back( + wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ), m_part->GetKeyWords() ) ); } aPlotter->HyperlinkMenu( GetBoundingBox(), properties ); @@ -2947,13 +2992,11 @@ void SCH_SYMBOL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const { - BOX2I bbox = GetBodyBoundingBox(); - BOX2I pins = GetBodyAndPinsBoundingBox(); - VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), - pins.GetEnd().x - bbox.GetEnd().x ), - std::max( bbox.GetY() - pins.GetY(), - pins.GetEnd().y - bbox.GetEnd().y ) ); - int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS ); + BOX2I bbox = GetBodyBoundingBox(); + BOX2I pins = GetBodyAndPinsBoundingBox(); + VECTOR2D margins( std::max( bbox.GetX() - pins.GetX(), pins.GetEnd().x - bbox.GetEnd().x ), + std::max( bbox.GetY() - pins.GetY(), pins.GetEnd().y - bbox.GetEnd().y ) ); + int strokeWidth = 3.0 * schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS ); margins.x = std::max( margins.x * 0.6, margins.y * 0.3 ); margins.y = std::max( margins.y * 0.6, margins.x * 0.3 ); @@ -2965,23 +3008,20 @@ void SCH_SYMBOL::PlotDNP( PLOTTER* aPlotter ) const aPlotter->ThickSegment( bbox.GetOrigin(), bbox.GetEnd(), strokeWidth, nullptr ); aPlotter->ThickSegment( bbox.GetOrigin() + VECTOR2I( bbox.GetWidth(), 0 ), - bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ), - strokeWidth, nullptr ); + bbox.GetOrigin() + VECTOR2I( 0, bbox.GetHeight() ), strokeWidth, nullptr ); } - /** * plot a local power pin indicator icon. */ -static void plotLocalPowerIcon( PLOTTER* aPlotter, - const VECTOR2D& aPos, double aSize, bool aRotate ) +static void plotLocalPowerIcon( PLOTTER* aPlotter, const VECTOR2D& aPos, double aSize, bool aRotate ) { double lineWidth = aSize / 10.0; std::vector shapeList; SCH_SYMBOL::BuildLocalPowerIconShape( shapeList, aPos, aSize, lineWidth, aRotate ); - int tolerance = 100; // approx error to approximate a Bezier curve by segments + int tolerance = 100; // approx error to approximate a Bezier curve by segments for( const SCH_SHAPE& shape : shapeList ) { @@ -2989,14 +3029,10 @@ static void plotLocalPowerIcon( PLOTTER* aPlotter, FILL_T filled = shape.GetFillMode() == FILL_T::NO_FILL ? FILL_T::NO_FILL : FILL_T::FILLED_SHAPE; if( shape.GetShape() == SHAPE_T::BEZIER ) - { - aPlotter->BezierCurve( shape.GetStart(), shape.GetBezierC1(), shape.GetBezierC2(), shape.GetEnd(), + aPlotter->BezierCurve( shape.GetStart(), shape.GetBezierC1(), shape.GetBezierC2(), shape.GetEnd(), tolerance, lineWidth ); - } else if( shape.GetShape() == SHAPE_T::CIRCLE ) - { aPlotter->Circle( shape.getCenter(), shape.GetRadius() * 2, filled, lineWidth ); - } } } @@ -3021,8 +3057,8 @@ void SCH_SYMBOL::PlotLocalPowerIconShape( PLOTTER* aPlotter ) const bool rotated = !orient.IsHorizontal(); - VECTOR2D pos; - double size = bbox.GetHeight() / 1.5; + VECTOR2D pos; + double size = bbox.GetHeight() / 1.5; if( rotated ) { @@ -3039,7 +3075,6 @@ void SCH_SYMBOL::PlotLocalPowerIconShape( PLOTTER* aPlotter ) const } - void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const { if( m_part ) @@ -3056,10 +3091,10 @@ void SCH_SYMBOL::PlotPins( PLOTTER* aPlotter ) const SCH_PLOT_OPTS plotOpts; // Copy the pin info from the symbol to the temp pins - for( unsigned i = 0; i < tempPins.size(); ++ i ) + for( unsigned i = 0; i < tempPins.size(); ++i ) { - SCH_PIN* symbolPin = GetPin( libPins[ i ] ); - SCH_PIN* tempPin = tempPins[ i ]; + SCH_PIN* symbolPin = GetPin( libPins[i] ); + SCH_PIN* tempPin = tempPins[i]; tempPin->SetName( symbolPin->GetShownName() ); tempPin->SetType( symbolPin->GetType() ); @@ -3126,10 +3161,8 @@ bool SCH_SYMBOL::IsPointClickableAnchor( const VECTOR2I& aPos ) const { for( const std::unique_ptr& pin : m_pins ) { - int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() - : GetUnit(); - int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() - : GetBodyStyle(); + int pin_unit = pin->GetLibPin() ? pin->GetLibPin()->GetUnit() : GetUnit(); + int pin_bodyStyle = pin->GetLibPin() ? pin->GetLibPin()->GetBodyStyle() : GetBodyStyle(); if( pin_unit > 0 && pin_unit != GetUnit() ) continue; @@ -3217,18 +3250,17 @@ std::unordered_set SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET { std::unordered_set componentClass; - auto getComponentClassFields = - [&]( const std::vector& fields ) + auto getComponentClassFields = [&]( const std::vector& fields ) + { + for( const SCH_FIELD& field : fields ) + { + if( field.GetCanonicalName() == wxT( "Component Class" ) ) { - for( const SCH_FIELD& field : fields ) - { - if( field.GetCanonicalName() == wxT( "Component Class" ) ) - { - if( field.GetShownText( aPath, false ) != wxEmptyString ) - componentClass.insert( field.GetShownText( aPath, false ) ); - } - } - }; + if( field.GetShownText( aPath, false ) != wxEmptyString ) + componentClass.insert( field.GetShownText( aPath, false ) ); + } + } + }; // First get component classes set on the symbol itself getComponentClassFields( m_fields ); @@ -3247,7 +3279,7 @@ std::unordered_set SCH_SYMBOL::GetComponentClassNames( const SCH_SHEET std::optional SCH_SYMBOL::GetVariant( const SCH_SHEET_PATH& aInstance, - const wxString& aVariantName ) const + const wxString& aVariantName ) const { SCH_SYMBOL_INSTANCE instance; @@ -3337,10 +3369,10 @@ double SCH_SYMBOL::Similarity( const SCH_ITEM& aOther ) const } -void SCH_SYMBOL::BuildLocalPowerIconShape( std::vector& aShapeList, const VECTOR2D& aPos, - double aSize, double aLineWidth, bool aHorizontal ) +void SCH_SYMBOL::BuildLocalPowerIconShape( std::vector& aShapeList, const VECTOR2D& aPos, double aSize, + double aLineWidth, bool aHorizontal ) { - SCH_LAYER_ID layer = LAYER_DEVICE; //dummy param + SCH_LAYER_ID layer = LAYER_DEVICE; //dummy param double x_right = aSize / 1.6180339887; double x_middle = x_right / 2.0; @@ -3380,8 +3412,8 @@ void SCH_SYMBOL::BuildLocalPowerIconShape( std::vector& aShapeList, c for( SCH_SHAPE& shape : aShapeList ) { - if( aHorizontal ) - shape.Rotate( VECTOR2I( 0, 0), true ); + if( aHorizontal ) + shape.Rotate( VECTOR2I( 0, 0 ), true ); shape.Move( aPos ); } @@ -3393,8 +3425,8 @@ static struct SCH_SYMBOL_DESC SCH_SYMBOL_DESC() { ENUM_MAP::Instance() - .Map( SYMBOL_ANGLE_0, wxS( "0" ) ) - .Map( SYMBOL_ANGLE_90, wxS( "90" ) ) + .Map( SYMBOL_ANGLE_0, wxS( "0" ) ) + .Map( SYMBOL_ANGLE_90, wxS( "90" ) ) .Map( SYMBOL_ANGLE_180, wxS( "180" ) ) .Map( SYMBOL_ANGLE_270, wxS( "270" ) ); @@ -3402,119 +3434,122 @@ static struct SCH_SYMBOL_DESC REGISTER_TYPE( SCH_SYMBOL ); propMgr.InheritsAfter( TYPE_HASH( SCH_SYMBOL ), TYPE_HASH( SYMBOL ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Position X" ), - &SCH_SYMBOL::SetX, &SCH_SYMBOL::GetX, PROPERTY_DISPLAY::PT_COORD, - ORIGIN_TRANSFORMS::ABS_X_COORD ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Position Y" ), - &SCH_SYMBOL::SetY, &SCH_SYMBOL::GetY, PROPERTY_DISPLAY::PT_COORD, - ORIGIN_TRANSFORMS::ABS_Y_COORD ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Position X" ), &SCH_SYMBOL::SetX, &SCH_SYMBOL::GetX, + PROPERTY_DISPLAY::PT_COORD, + ORIGIN_TRANSFORMS::ABS_X_COORD ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Position Y" ), &SCH_SYMBOL::SetY, &SCH_SYMBOL::GetY, + PROPERTY_DISPLAY::PT_COORD, + ORIGIN_TRANSFORMS::ABS_Y_COORD ) ); - propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Orientation" ), - &SCH_SYMBOL::SetOrientationProp, &SCH_SYMBOL::GetOrientationProp ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Mirror X" ), - &SCH_SYMBOL::SetMirrorX, &SCH_SYMBOL::GetMirrorX ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Mirror Y" ), - &SCH_SYMBOL::SetMirrorY, &SCH_SYMBOL::GetMirrorY ) ); + propMgr.AddProperty( new PROPERTY_ENUM( + _HKI( "Orientation" ), &SCH_SYMBOL::SetOrientationProp, &SCH_SYMBOL::GetOrientationProp ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Mirror X" ), &SCH_SYMBOL::SetMirrorX, + &SCH_SYMBOL::GetMirrorX ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Mirror Y" ), &SCH_SYMBOL::SetMirrorY, + &SCH_SYMBOL::GetMirrorY ) ); - auto hasLibPart = - []( INSPECTABLE* aItem ) -> bool - { - if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) - return symbol->GetLibSymbolRef() != nullptr; + auto hasLibPart = []( INSPECTABLE* aItem ) -> bool + { + if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) + return symbol->GetLibSymbolRef() != nullptr; - return false; - }; + return false; + }; - propMgr.AddProperty( new PROPERTY( _HKI( "Pin numbers" ), - &SYMBOL::SetShowPinNumbers, &SYMBOL::GetShowPinNumbers ) ) + propMgr.AddProperty( new PROPERTY( _HKI( "Pin numbers" ), &SYMBOL::SetShowPinNumbers, + &SYMBOL::GetShowPinNumbers ) ) .SetAvailableFunc( hasLibPart ); - propMgr.AddProperty( new PROPERTY( _HKI( "Pin names" ), - &SYMBOL::SetShowPinNames, &SYMBOL::GetShowPinNames ) ) + propMgr.AddProperty( new PROPERTY( _HKI( "Pin names" ), &SYMBOL::SetShowPinNames, + &SYMBOL::GetShowPinNames ) ) .SetAvailableFunc( hasLibPart ); const wxString groupFields = _HKI( "Fields" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Reference" ), - &SCH_SYMBOL::SetRefProp, &SCH_SYMBOL::GetRefProp ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Value" ), - &SCH_SYMBOL::SetValueProp, &SCH_SYMBOL::GetValueProp ), - groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Reference" ), &SCH_SYMBOL::SetRefProp, + &SCH_SYMBOL::GetRefProp ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Value" ), &SCH_SYMBOL::SetValueProp, + &SCH_SYMBOL::GetValueProp ), + groupFields ); propMgr.AddProperty( new PROPERTY( _HKI( "Library Link" ), - NO_SETTER( SCH_SYMBOL, wxString ), &SCH_SYMBOL::GetSymbolIDAsString ), - groupFields ); + NO_SETTER( SCH_SYMBOL, wxString ), + &SCH_SYMBOL::GetSymbolIDAsString ), + groupFields ); propMgr.AddProperty( new PROPERTY( _HKI( "Library Description" ), - NO_SETTER( SCH_SYMBOL, wxString ), &SCH_SYMBOL::GetDescription ), - groupFields ); - propMgr.AddProperty( new PROPERTY( _HKI( "Keywords" ), - NO_SETTER( SCH_SYMBOL, wxString ), &SCH_SYMBOL::GetKeyWords ), - groupFields ); + NO_SETTER( SCH_SYMBOL, wxString ), + &SCH_SYMBOL::GetDescription ), + groupFields ); + propMgr.AddProperty( new PROPERTY( _HKI( "Keywords" ), NO_SETTER( SCH_SYMBOL, wxString ), + &SCH_SYMBOL::GetKeyWords ), + groupFields ); - auto multiUnit = - [=]( INSPECTABLE* aItem ) -> bool - { - if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) - return symbol->IsMultiUnit(); + auto multiUnit = [=]( INSPECTABLE* aItem ) -> bool + { + if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) + return symbol->IsMultiUnit(); - return false; - }; + return false; + }; - auto multiBodyStyle = - [=]( INSPECTABLE* aItem ) -> bool - { - if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) - return symbol->IsMultiBodyStyle(); + auto multiBodyStyle = [=]( INSPECTABLE* aItem ) -> bool + { + if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) + return symbol->IsMultiBodyStyle(); - return false; - }; + return false; + }; - propMgr.AddProperty( new PROPERTY( _HKI( "Unit" ), - &SCH_SYMBOL::SetUnitProp, &SCH_SYMBOL::GetUnitProp ) ) + propMgr.AddProperty( new PROPERTY( _HKI( "Unit" ), &SCH_SYMBOL::SetUnitProp, + &SCH_SYMBOL::GetUnitProp ) ) .SetAvailableFunc( multiUnit ) - .SetChoicesFunc( []( INSPECTABLE* aItem ) - { - wxPGChoices choices; + .SetChoicesFunc( + []( INSPECTABLE* aItem ) + { + wxPGChoices choices; - if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) - { - for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ ) - choices.Add( symbol->GetUnitDisplayName( ii, false ), ii ); - } + if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) + { + for( int ii = 1; ii <= symbol->GetUnitCount(); ii++ ) + choices.Add( symbol->GetUnitDisplayName( ii, false ), ii ); + } - return choices; - } ); + return choices; + } ); - propMgr.AddProperty( new PROPERTY( _HKI( "Body Style" ), - &SCH_SYMBOL::SetBodyStyleProp, &SCH_SYMBOL::GetBodyStyleProp ) ) + propMgr.AddProperty( new PROPERTY( _HKI( "Body Style" ), &SCH_SYMBOL::SetBodyStyleProp, + &SCH_SYMBOL::GetBodyStyleProp ) ) .SetAvailableFunc( multiBodyStyle ) - .SetChoicesFunc( []( INSPECTABLE* aItem ) - { - wxPGChoices choices; + .SetChoicesFunc( + []( INSPECTABLE* aItem ) + { + wxPGChoices choices; - if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) - { - for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ ) - choices.Add( symbol->GetBodyStyleDescription( ii, false ) ); - } + if( SCH_SYMBOL* symbol = dynamic_cast( aItem ) ) + { + for( int ii = 1; ii <= symbol->GetBodyStyleCount(); ii++ ) + choices.Add( symbol->GetBodyStyleDescription( ii, false ) ); + } - return choices; - } ); + return choices; + } ); const wxString groupAttributes = _HKI( "Attributes" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Exclude From Board" ), - &SYMBOL::SetExcludedFromBoard, &SYMBOL::GetExcludedFromBoard ), - groupAttributes ); + propMgr.AddProperty( new PROPERTY( _HKI( "Exclude From Board" ), &SYMBOL::SetExcludedFromBoard, + &SYMBOL::GetExcludedFromBoard ), + groupAttributes ); propMgr.AddProperty( new PROPERTY( _HKI( "Exclude From Simulation" ), - &SCH_SYMBOL::SetExcludedFromSimProp, &SCH_SYMBOL::GetExcludedFromSimProp ), - groupAttributes ); + &SCH_SYMBOL::SetExcludedFromSimProp, + &SCH_SYMBOL::GetExcludedFromSimProp ), + groupAttributes ); propMgr.AddProperty( new PROPERTY( _HKI( "Exclude From Bill of Materials" ), - &SCH_SYMBOL::SetExcludedFromBOMProp, &SCH_SYMBOL::GetExcludedFromBOMProp ), - groupAttributes ); - propMgr.AddProperty( new PROPERTY( _HKI( "Do not Populate" ), - &SCH_SYMBOL::SetDNPProp, &SCH_SYMBOL::GetDNPProp ), - groupAttributes ); + &SCH_SYMBOL::SetExcludedFromBOMProp, + &SCH_SYMBOL::GetExcludedFromBOMProp ), + groupAttributes ); + propMgr.AddProperty( new PROPERTY( _HKI( "Do not Populate" ), &SCH_SYMBOL::SetDNPProp, + &SCH_SYMBOL::GetDNPProp ), + groupAttributes ); } } _SCH_SYMBOL_DESC; diff --git a/eeschema/sch_tablecell.cpp b/eeschema/sch_tablecell.cpp index 2b77c9e92e..01cd9dd79a 100644 --- a/eeschema/sch_tablecell.cpp +++ b/eeschema/sch_tablecell.cpp @@ -21,6 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include +#include #include #include #include @@ -89,9 +91,199 @@ int SCH_TABLECELL::GetColumn() const wxString SCH_TABLECELL::GetAddr() const { - return wxString::Format( wxT( "%c%d" ), - 'A' + GetColumn() % 26, - GetRow() + 1 ); + return wxString::Format( wxT( "%c%d" ), 'A' + GetColumn() % 26, GetRow() ); +} + + +/** + * Parse a cell address string like "A0" or "B12" into 0-based row and column indices. + * Supports single-letter columns (A-Z) and multi-letter columns (AA-ZZ). + * Both row and column numbers in the address are 0-based (A0 = first row, first column). + * + * @param aAddr The address string to parse (e.g., "A0", "B5", "AA10") + * @param aRow Output parameter for the 0-based row index + * @param aCol Output parameter for the 0-based column index + * @return true if parsing succeeded, false if format is invalid + */ +static bool parseCellAddress( const wxString& aAddr, int& aRow, int& aCol ) +{ + if( aAddr.IsEmpty() ) + return false; + + // Extract column part (letters) and row part (numbers) + size_t i = 0; + wxString colPart; + + // Read column letters (A-Z, AA-ZZ, etc.) + while( i < aAddr.Length() && wxIsalpha( aAddr[i] ) ) + { + colPart += wxToupper( aAddr[i] ); + i++; + } + + // Must have at least one letter + if( colPart.IsEmpty() ) + return false; + + // Convert column letters to 0-based index (A=0, B=1, ..., Z=25, AA=26, AB=27, etc.) + aCol = 0; + for( size_t j = 0; j < colPart.Length(); j++ ) + { + aCol = aCol * 26 + ( colPart[j] - 'A' + 1 ); + } + aCol -= 1; // Convert to 0-based + + // Read row number (0-based) + wxString rowPart = aAddr.Mid( i ); + if( rowPart.IsEmpty() ) + return false; + + // Convert row string to number (already 0-based in address string) + long rowNum; + if( !rowPart.ToLong( &rowNum ) || rowNum < 0 ) + return false; + + aRow = rowNum; // Already 0-based + + return true; +} + + +wxString SCH_TABLECELL::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath, + bool aAllowExtraText, int aDepth ) const +{ + SCH_SHEET* sheet = nullptr; + + if( aPath ) + sheet = aPath->Last(); + + std::function tableCellResolver = [&]( wxString* token ) -> bool + { + if( token->IsSameAs( wxT( "ROW" ) ) ) + { + *token = wxString::Format( wxT( "%d" ), GetRow() ); // 0-based + return true; + } + else if( token->IsSameAs( wxT( "COL" ) ) ) + { + *token = wxString::Format( wxT( "%d" ), GetColumn() ); // 0-based + return true; + } + else if( token->IsSameAs( wxT( "ADDR" ) ) ) + { + *token = GetAddr(); + return true; + } + else if( token->StartsWith( wxT( "CELL(" ) ) && token->EndsWith( wxT( ")" ) ) ) + { + // Handle CELL("A0") or CELL(0, 1) syntax + wxString args = token->Mid( 5, token->Length() - 6 ); // Extract arguments + args.Trim( true ).Trim( false ); // Remove whitespace + + SCH_TABLE* table = static_cast( GetParent() ); + if( !table ) + { + *token = wxT( "" ); + return true; + } + + int targetRow = -1; + int targetCol = -1; + + // Check if it's cell("A1") format (string argument with quotes) + if( args.StartsWith( wxT( "\"" ) ) && args.EndsWith( wxT( "\"" ) ) ) + { + wxString addr = args.Mid( 1, args.Length() - 2 ); // Remove quotes + if( !parseCellAddress( addr, targetRow, targetCol ) ) + { + *token = wxString::Format( wxT( "" ), addr ); + return true; + } + } + // Check if it's cell(row, col) format (two numeric arguments) + else if( args.Find( ',' ) != wxNOT_FOUND ) + { + wxString rowStr = args.BeforeFirst( ',' ).Trim( true ).Trim( false ); + wxString colStr = args.AfterFirst( ',' ).Trim( true ).Trim( false ); + + long rowNum, colNum; + if( !rowStr.ToLong( &rowNum ) || !colStr.ToLong( &colNum ) ) + { + *token = wxString::Format( wxT( "" ), args ); + return true; + } + + // Arguments are already 0-based + targetRow = rowNum; + targetCol = colNum; + } + else + { + *token = wxString::Format( wxT( "" ), args ); + return true; + } + + // Check bounds + if( targetRow < 0 || targetRow >= table->GetRowCount() || targetCol < 0 + || targetCol >= table->GetColCount() ) + { + wxString cellAddr; + if( targetRow >= 0 && targetCol >= 0 ) + { + char colLetter = 'A' + ( targetCol % 26 ); + cellAddr = wxString::Format( wxT( "%c%d" ), colLetter, targetRow ); + } + else + { + cellAddr = args; + } + *token = wxString::Format( wxT( "" ), cellAddr ); + return true; + } + + // Get the target cell and return its evaluated text + SCH_TABLECELL* targetCell = table->GetCell( targetRow, targetCol ); + if( targetCell ) + { + // Return the evaluated/displayed value, not raw text + // This ensures formulas in the target cell are evaluated + *token = targetCell->GetShownText( aSettings, aPath, false, aDepth + 1 ); + return true; + } + else + { + *token = wxT( "" ); + return true; + } + } + + // Fall back to sheet variables + if( sheet ) + { + if( sheet->ResolveTextVar( aPath, token, aDepth + 1 ) ) + return true; + } + + return false; + }; + + wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); + + if( HasTextVars() ) + text = ResolveTextVars( text, &tableCellResolver, aDepth ); + + VECTOR2I size = GetEnd() - GetStart(); + int colWidth; + + if( GetTextAngle().IsVertical() ) + colWidth = abs( size.y ) - ( GetMarginTop() + GetMarginBottom() ); + else + colWidth = abs( size.x ) - ( GetMarginLeft() + GetMarginRight() ); + + GetDrawFont( aSettings ) + ->LinebreakText( text, colWidth, GetTextSize(), GetEffectiveTextPenWidth(), IsBold(), IsItalic() ); + + return text; } @@ -125,10 +317,10 @@ void SCH_TABLECELL::SetRowHeight( int aHeight ) } -void SCH_TABLECELL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void SCH_TABLECELL::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, + int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) { - const int cell_body_style = -1; // flage to disable box ouline plotting + const int cell_body_style = -1; // flage to disable box ouline plotting if( m_colSpan >= 1 && m_rowSpan >= 1 ) SCH_TEXTBOX::Plot( aPlotter, aBackground, aPlotOpts, aUnit, cell_body_style, aOffset, aDimmed ); } @@ -141,15 +333,13 @@ void SCH_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorMessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); - aList.emplace_back( _( "Cell Height" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); + aList.emplace_back( _( "Cell Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); + aList.emplace_back( _( "Cell Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) ); wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) }; - int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; + int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; aList.emplace_back( _( "Style" ), textStyle[style] ); aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) ); @@ -236,26 +426,25 @@ static struct SCH_TABLECELL_DESC const wxString tableProps = _( "Table" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Column Width" ), - &SCH_TABLECELL::SetColumnWidth, &SCH_TABLECELL::GetColumnWidth, - PROPERTY_DISPLAY::PT_SIZE ), - tableProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Column Width" ), &SCH_TABLECELL::SetColumnWidth, + &SCH_TABLECELL::GetColumnWidth, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Row Height" ), - &SCH_TABLECELL::SetRowHeight, &SCH_TABLECELL::GetRowHeight, - PROPERTY_DISPLAY::PT_SIZE ), - tableProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Row Height" ), &SCH_TABLECELL::SetRowHeight, + &SCH_TABLECELL::GetRowHeight, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); const wxString cellProps = _( "Cell Properties" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Background Fill" ), - &EDA_SHAPE::SetFilled, &EDA_SHAPE::IsSolidFill ), - cellProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Background Fill" ), &EDA_SHAPE::SetFilled, + &EDA_SHAPE::IsSolidFill ), + cellProps ); propMgr.AddProperty( new PROPERTY( _HKI( "Background Fill Color" ), - &EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor ), - cellProps ) + &EDA_SHAPE::SetFillColor, &EDA_SHAPE::GetFillColor ), + cellProps ) .SetIsHiddenFromRulesEditor(); - } } _SCH_TABLECELL_DESC; diff --git a/eeschema/sch_tablecell.h b/eeschema/sch_tablecell.h index ad5f96714d..f5eeeb2692 100644 --- a/eeschema/sch_tablecell.h +++ b/eeschema/sch_tablecell.h @@ -33,27 +33,15 @@ class SCH_TABLECELL : public SCH_TEXTBOX public: SCH_TABLECELL( int aLineWidth = 0, FILL_T aFillType = FILL_T::NO_FILL ); - static inline bool ClassOf( const EDA_ITEM* aItem ) - { - return aItem && SCH_TABLECELL_T == aItem->Type(); - } + static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && SCH_TABLECELL_T == aItem->Type(); } - virtual wxString GetClass() const override - { - return wxT( "SCH_TABLECELL" ); - } + virtual wxString GetClass() const override { return wxT( "SCH_TABLECELL" ); } wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override; - EDA_ITEM* Clone() const override - { - return new SCH_TABLECELL( *this ); - } + EDA_ITEM* Clone() const override { return new SCH_TABLECELL( *this ); } - EDA_GROUP* GetParentGroup() const override - { - return GetParent()->GetParentGroup(); - } + EDA_GROUP* GetParentGroup() const override { return GetParent()->GetParentGroup(); } int GetRow() const; int GetColumn() const; @@ -61,25 +49,35 @@ public: /// @return the spreadsheet nomenclature for the cell (ie: B3 for 2nd column, 3rd row) wxString GetAddr() const; + wxString GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath, bool aAllowExtraText, + int aDepth = 0 ) const override; + + wxString GetShownText( bool aAllowExtraText, int aDepth = 0 ) const override + { + SCH_SHEET_PATH* sheetPath = nullptr; + + if( SCHEMATIC* schematic = Schematic() ) + sheetPath = &schematic->CurrentSheet(); + + return GetShownText( nullptr, sheetPath, aAllowExtraText, aDepth ); + } + int GetColSpan() const { return m_colSpan; } void SetColSpan( int aSpan ) { m_colSpan = aSpan; } int GetRowSpan() const { return m_rowSpan; } void SetRowSpan( int aSpan ) { m_rowSpan = aSpan; } - int GetRowHeight() const; + int GetRowHeight() const; void SetRowHeight( int aHeight ); - int GetColumnWidth() const; + int GetColumnWidth() const; void SetColumnWidth( int aWidth ); - bool IsFilledForHitTesting() const override - { - return true; - } + bool IsFilledForHitTesting() const override { return true; } - void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override; + void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index 004e4678bf..9bc59f2b4f 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -48,8 +48,7 @@ #include -SCH_TEXT::SCH_TEXT( const VECTOR2I& aPos, const wxString& aText, SCH_LAYER_ID aLayer, - KICAD_T aType ) : +SCH_TEXT::SCH_TEXT( const VECTOR2I& aPos, const wxString& aText, SCH_LAYER_ID aLayer, KICAD_T aType ) : SCH_ITEM( nullptr, aType ), EDA_TEXT( schIUScale, aText ) { @@ -90,10 +89,10 @@ void SCH_TEXT::NormalizeJustification( bool inverse ) if( GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT ) delta.x = bbox.GetWidth() / 2; else if( GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT ) - delta.x = - bbox.GetWidth() / 2; + delta.x = -bbox.GetWidth() / 2; if( GetVertJustify() == GR_TEXT_V_ALIGN_TOP ) - delta.y = - bbox.GetHeight() / 2; + delta.y = -bbox.GetHeight() / 2; else if( GetVertJustify() == GR_TEXT_V_ALIGN_BOTTOM ) delta.y = bbox.GetHeight() / 2; } @@ -102,12 +101,12 @@ void SCH_TEXT::NormalizeJustification( bool inverse ) if( GetHorizJustify() == GR_TEXT_H_ALIGN_LEFT ) delta.y = bbox.GetWidth() / 2; else if( GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT ) - delta.y = - bbox.GetWidth() / 2; + delta.y = -bbox.GetWidth() / 2; if( GetVertJustify() == GR_TEXT_V_ALIGN_TOP ) - delta.x = + bbox.GetHeight() / 2; + delta.x = +bbox.GetHeight() / 2; else if( GetVertJustify() == GR_TEXT_V_ALIGN_BOTTOM ) - delta.x = - bbox.GetHeight() / 2; + delta.x = -bbox.GetHeight() / 2; } if( inverse ) @@ -209,8 +208,7 @@ void SCH_TEXT::Rotate( const VECTOR2I& aCenter, bool aRotateCCW ) void SCH_TEXT::Rotate90( bool aClockwise ) { - if( ( GetTextAngle() == ANGLE_HORIZONTAL && aClockwise ) - || ( GetTextAngle() == ANGLE_VERTICAL && !aClockwise ) ) + if( ( GetTextAngle() == ANGLE_HORIZONTAL && aClockwise ) || ( GetTextAngle() == ANGLE_VERTICAL && !aClockwise ) ) { FlipHJustify(); } @@ -221,8 +219,7 @@ void SCH_TEXT::Rotate90( bool aClockwise ) void SCH_TEXT::MirrorSpinStyle( bool aLeftRight ) { - if( ( GetTextAngle() == ANGLE_HORIZONTAL && aLeftRight ) - || ( GetTextAngle() == ANGLE_VERTICAL && !aLeftRight ) ) + if( ( GetTextAngle() == ANGLE_HORIZONTAL && aLeftRight ) || ( GetTextAngle() == ANGLE_VERTICAL && !aLeftRight ) ) { FlipHJustify(); } @@ -270,7 +267,7 @@ int SCH_TEXT::GetTextOffset( const RENDER_SETTINGS* aSettings ) const else if( Schematic() ) ratio = Schematic()->Settings().m_TextOffsetRatio; else - ratio = DEFAULT_TEXT_OFFSET_RATIO; // For previews (such as in Preferences), etc. + ratio = DEFAULT_TEXT_OFFSET_RATIO; // For previews (such as in Preferences), etc. return KiROUND( ratio * GetTextSize().y ); } @@ -314,8 +311,7 @@ const BOX2I SCH_TEXT::GetBoundingBox() const } -wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, - int aDepth ) const +wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraText, int aDepth ) const { SCH_SHEET* sheet = nullptr; @@ -324,39 +320,32 @@ wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraTe else if( SCHEMATIC* schematic = Schematic() ) sheet = schematic->CurrentSheet().Last(); - std::function textResolver = - [&]( wxString* token ) -> bool - { - if( SCH_SYMBOL* sch_symbol = dynamic_cast( m_parent ) ) - { - if( sch_symbol->ResolveTextVar( aPath, token, aDepth + 1 ) ) - return true; - } - else if( LIB_SYMBOL* lib_symbol = dynamic_cast( m_parent ) ) - { - if( lib_symbol->ResolveTextVar( token, aDepth + 1 ) ) - return true; - } + std::function textResolver = [&]( wxString* token ) -> bool + { + if( SCH_SYMBOL* sch_symbol = dynamic_cast( m_parent ) ) + { + if( sch_symbol->ResolveTextVar( aPath, token, aDepth + 1 ) ) + return true; + } + else if( LIB_SYMBOL* lib_symbol = dynamic_cast( m_parent ) ) + { + if( lib_symbol->ResolveTextVar( token, aDepth + 1 ) ) + return true; + } - if( sheet ) - { - if( sheet->ResolveTextVar( aPath, token, aDepth + 1 ) ) - return true; - } + if( sheet ) + { + if( sheet->ResolveTextVar( aPath, token, aDepth + 1 ) ) + return true; + } - return false; - }; + return false; + }; wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); if( HasTextVars() ) - { - if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &textResolver ); - } - - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); + text = ResolveTextVars( text, &textResolver, aDepth ); return text; } @@ -364,8 +353,7 @@ wxString SCH_TEXT::GetShownText( const SCH_SHEET_PATH* aPath, bool aAllowExtraTe void SCH_TEXT::DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const { - wxCHECK_MSG( IsHypertext(), /* void */, - wxT( "Calling a hypertext menu on a SCH_TEXT with no hyperlink?" ) ); + wxCHECK_MSG( IsHypertext(), /* void */, wxT( "Calling a hypertext menu on a SCH_TEXT with no hyperlink?" ) ); SCH_NAVIGATE_TOOL* navTool = aFrame->GetToolManager()->GetTool(); navTool->HypertextCommand( m_hyperlink ); @@ -395,7 +383,7 @@ bool SCH_TEXT::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const bool SCH_TEXT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const { - if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) ) + if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) ) return false; BOX2I rect = aRect; @@ -412,7 +400,7 @@ bool SCH_TEXT::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) con bool SCH_TEXT::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const { - if( m_flags & (STRUCT_DELETED | SKIP_STRUCT ) ) + if( m_flags & ( STRUCT_DELETED | SKIP_STRUCT ) ) return false; return KIGEOM::BoxHitTest( aPoly, GetBoundingBox(), aContained ); @@ -440,8 +428,8 @@ std::vector SCH_TEXT::ViewGetLayers() const } -void SCH_TEXT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void SCH_TEXT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) { if( aBackground || IsPrivate() ) return; @@ -467,7 +455,7 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& a if( aDimmed ) { - color.Desaturate( ); + color.Desaturate(); color = color.Mix( bg, 0.5f ); } @@ -505,8 +493,8 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& a else attrs.m_Angle = ANGLE_VERTICAL; - aPlotter->PlotText( renderSettings->TransformCoordinate( txtpos ) + aOffset, color, - GetText(), attrs, font, GetFontMetrics() ); + aPlotter->PlotText( renderSettings->TransformCoordinate( txtpos ) + aOffset, color, GetText(), attrs, font, + GetFontMetrics() ); } else { @@ -520,14 +508,14 @@ void SCH_TEXT::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& a BOX2I firstLineBBox = GetTextBox( renderSettings, 0 ); int sizeDiff = firstLineBBox.GetHeight() - GetTextSize().y; int adjust = KiROUND( sizeDiff * 0.4 ); - VECTOR2I adjust_offset( 0, - adjust ); + VECTOR2I adjust_offset( 0, -adjust ); RotatePoint( adjust_offset, GetDrawRotation() ); text_offset += adjust_offset; } std::vector positions; - wxArrayString strings_list; + wxArrayString strings_list; wxStringSplit( GetShownText( sheet, true ), strings_list, '\n' ); positions.reserve( strings_list.Count() ); @@ -563,16 +551,16 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetName() : _( "Default" ) ); wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) }; - int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; + int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; aList.emplace_back( _( "Style" ), textStyle[style] ); aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) ); switch( GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: msg = _( "Align left" ); break; - case GR_TEXT_H_ALIGN_CENTER: msg = _( "Align center" ); break; - case GR_TEXT_H_ALIGN_RIGHT: msg = _( "Align right" ); break; + case GR_TEXT_H_ALIGN_LEFT: msg = _( "Align left" ); break; + case GR_TEXT_H_ALIGN_CENTER: msg = _( "Align center" ); break; + case GR_TEXT_H_ALIGN_RIGHT: msg = _( "Align right" ); break; case GR_TEXT_H_ALIGN_INDETERMINATE: msg = INDETERMINATE_STATE; break; } @@ -580,11 +568,11 @@ void SCH_TEXT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector' - << TO_UTF8( GetText() ) - << "\n"; + NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str() << " layer=\"" << m_layer << '"' << '>' + << TO_UTF8( GetText() ) << "\n"; } #endif @@ -703,9 +688,9 @@ static struct SCH_TEXT_DESC propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Height" ) ); propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Thickness" ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), - &SCH_TEXT::SetSchTextSize, &SCH_TEXT::GetSchTextSize, PROPERTY_DISPLAY::PT_SIZE ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), &SCH_TEXT::SetSchTextSize, + &SCH_TEXT::GetSchTextSize, PROPERTY_DISPLAY::PT_SIZE ), + _HKI( "Text Properties" ) ); // Orientation is exposed differently in schematic; mask the base for now propMgr.Mask( TYPE_HASH( SCH_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) ); diff --git a/eeschema/sch_text_help.md b/eeschema/sch_text_help.md index 3837d0fdf1..349706c8ab 100644 --- a/eeschema/sch_text_help.md +++ b/eeschema/sch_text_help.md @@ -64,6 +64,222 @@

+ +  
${ROW} (in tables) + +  
0, 1, 2... (0-based) + + +  
${COL} (in tables) + +  
0, 1, 2... (0-based) + + +  
${ADDR} (in tables) + +  
A0, B1, C2... (0-based) + + +
+ + +  
@{expression} + +  
evaluated_result + + +  
@{2 + 3} + +  
5 + + +  
@{${ROW} + 1} + +  
4 (when ROW=3) + + +
+ + + String Comparison & Conditional Text + + + + +  
@{"text" == "text"} + +  
1 + + +  
@{"text" != "other"} + +  
1 + + +  
@{if(condition, true_val, false_val)} + +  
Conditional text display + + +  
@{if("${LAYER}" == "F.Cu", "TOP", "BOTTOM")} + +  
TOP (on front layer) or BOTTOM + + +  
@{if(${ROW} > 5, "High", "Low")} + +  
Numeric comparisons work too + + +
+ + + Symbol Pin Functions + + + + +  
${refdes:UNIT(pin)} + +  
Unit designation for pin + + +  
${J1:UNIT(3)} + +  
J1B (for multi-unit symbol) + + +  
${refdes:NET_NAME(pin)} + +  
Net name connected to pin + + +  
${R1:NET_NAME(1)} + +  
VCC + + +  
${refdes:PIN_NAME(pin)} + +  
Pin name or selected alternate + + +  
${U1:PIN_NAME(5)} + +  
USART1_TX (alternate) or PA9 (base) + + +  
${refdes:PIN_BASE_NAME(pin)} + +  
Base pin name (ignoring alternates) + + +  
${U1:PIN_BASE_NAME(5)} + +  
PA9 + + +  
${refdes:PIN_ALT_LIST(pin)} + +  
All available pin functions (base name + alternates) + + +  
${U1:PIN_ALT_LIST(5)} + +  
PA9, USART1_TX, TIM1_CH2, I2C1_SCL + + +  
${refdes:SHORT_NET_NAME(pin)} + +  
Short net name or NC if unconnected + + +  
${J1:SHORT_NET_NAME(3)} + +  
GND or NC + + +  
${refdes:NET_CLASS(pin)} + +  
Net class for pin + + +  
${J1:NET_CLASS(1)} + +  
Power + + +
+ + + Escape Sequences + + + + +  
\${LITERAL} + +  
${LITERAL} (not expanded) + + +  
Price: \$25.00 + +  
Price: $25.00 + + +  
\@{x+y} + +  
@{x+y} (not evaluated) + + +
+ + + Nested Variables + + + + +  
${J1:UNIT(@{${ROW}+2})} + +  
J1B (when ROW=0, pin 2 in unit B) + + +  
${J1:NET_NAME(${COL})} + +  
Dynamic net lookup in tables + + +
+ + + Table Cell References + + + + +  
${CELL("A0")} + +  
Evaluated value from cell A0 + + +  
${CELL(0, 1)} + +  
Value from row 0, column 1 + + +  
${CELL(${ADDR})} + +  
Dynamic cell reference + + +  
${CELL(${ROW}-1, ${COL})} + +  
Value from cell above (if ROW > 0) + + +
+
@@ -128,4 +344,14 @@

Note that markup has precedence over bus definitions. +

+

Pin Functions: Automatically find the correct unit placement. For multi-unit symbols, functions like NET_NAME(pin) work even if the pin is in a different unit than the one on the current sheet.

+

Table Cell References: The CELL() function works only in table cells. Use ${CELL("A0")} or ${CELL(row, col)} to reference other cells in the same table. Row and column numbers are 0-based (A0 is the first row, first column). CELL returns the evaluated/displayed value, not the raw cell text.

+

Nested Variables: Variables can contain other variables. Inner variables are expanded first. Maximum nesting depth: 6 levels.

+

Error Messages:

+
    +
  • <UNRESOLVED: token> - Variable or function cannot be resolved
  • +
  • <Unit X not placed> - Pin is in a unit not placed on any sheet
  • +
  • <Unresolved: Cell X not found> - Cell address is out of table bounds
  • +
diff --git a/eeschema/sch_text_help_md.h b/eeschema/sch_text_help_md.h index cb0f9d13e0..0e342661ff 100644 --- a/eeschema/sch_text_help_md.h +++ b/eeschema/sch_text_help_md.h @@ -66,6 +66,222 @@ _HKI( "\n" " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -129,5 +345,15 @@ _HKI( "

 
${ROW} (in tables)
 
0, 1, 2... (0-based)
 
${COL} (in tables)
 
0, 1, 2... (0-based)
 
${ADDR} (in tables)
 
A0, B1, C2... (0-based)

 
@{expression}
 
evaluated_result
 
@{2 + 3}
 
5
 
@{${ROW} + 1}
 
4 (when ROW=3)

String Comparison & Conditional Text
 
@{\"text\" == \"text\"}
 
1
 
@{\"text\" != \"other\"}
 
1
 
@{if(condition, true_val, false_val)}
 
Conditional text display
 
@{if(\"${LAYER}\" == \"F.Cu\", \"TOP\", \"BOTTOM\")}
 
TOP (on front layer) or BOTTOM
 
@{if(${ROW} > 5, \"High\", \"Low\")}
 
Numeric comparisons work too

Symbol Pin Functions
 
${refdes:UNIT(pin)}
 
Unit designation for pin
 
${J1:UNIT(3)}
 
J1B (for multi-unit symbol)
 
${refdes:NET_NAME(pin)}
 
Net name connected to pin
 
${R1:NET_NAME(1)}
 
VCC
 
${refdes:PIN_NAME(pin)}
 
Pin name or selected alternate
 
${U1:PIN_NAME(5)}
 
USART1_TX (alternate) or PA9 (base)
 
${refdes:PIN_BASE_NAME(pin)}
 
Base pin name (ignoring alternates)
 
${U1:PIN_BASE_NAME(5)}
 
PA9
 
${refdes:PIN_ALT_LIST(pin)}
 
All available pin functions (base name + alternates)
 
${U1:PIN_ALT_LIST(5)}
 
PA9, USART1_TX, TIM1_CH2, I2C1_SCL
 
${refdes:SHORT_NET_NAME(pin)}
 
Short net name or NC if unconnected
 
${J1:SHORT_NET_NAME(3)}
 
GND or NC
 
${refdes:NET_CLASS(pin)}
 
Net class for pin
 
${J1:NET_CLASS(1)}
 
Power

Escape Sequences
 
\\${LITERAL}
 
${LITERAL} (not expanded)
 
Price: \\$25.00
 
Price: $25.00
 
\\@{x+y}
 
@{x+y} (not evaluated)

Nested Variables
 
${J1:UNIT(@{${ROW}+2})}
 
J1B (when ROW=0, pin 2 in unit B)
 
${J1:NET_NAME(${COL})}
 
Dynamic net lookup in tables

Table Cell References
 
${CELL(\"A0\")}
 
Evaluated value from cell A0
 
${CELL(0, 1)}
 
Value from row 0, column 1
 
${CELL(${ADDR})}
 
Dynamic cell reference
 
${CELL(${ROW}-1, ${COL})}
 
Value from cell above (if ROW > 0)


\n" "

\n" "

\n" "Note that markup has precedence over bus definitions.\n" +"

\n" +"

Pin Functions: Automatically find the correct unit placement. For multi-unit symbols, functions like NET_NAME(pin) work even if the pin is in a different unit than the one on the current sheet.

\n" +"

Table Cell References: The CELL() function works only in table cells. Use ${CELL(\"A0\")} or ${CELL(row, col)} to reference other cells in the same table. Row and column numbers are 0-based (A0 is the first row, first column). CELL returns the evaluated/displayed value, not the raw cell text.

\n" +"

Nested Variables: Variables can contain other variables. Inner variables are expanded first. Maximum nesting depth: 6 levels.

\n" +"

Error Messages:

\n" +"
    \n" +"
  • <UNRESOLVED: token> - Variable or function cannot be resolved
  • \n" +"
  • <Unit X not placed> - Pin is in a unit not placed on any sheet
  • \n" +"
  • <Unresolved: Cell X not found> - Cell address is out of table bounds
  • \n" +"
\n" "\n" "" ); diff --git a/eeschema/sch_textbox.cpp b/eeschema/sch_textbox.cpp index b39f134bd7..c47c0734df 100644 --- a/eeschema/sch_textbox.cpp +++ b/eeschema/sch_textbox.cpp @@ -41,8 +41,8 @@ #include -SCH_TEXTBOX::SCH_TEXTBOX( SCH_LAYER_ID aLayer, int aLineWidth, FILL_T aFillType, - const wxString& aText, KICAD_T aType ) : +SCH_TEXTBOX::SCH_TEXTBOX( SCH_LAYER_ID aLayer, int aLineWidth, FILL_T aFillType, const wxString& aText, + KICAD_T aType ) : SCH_SHAPE( SHAPE_T::RECTANGLE, aLayer, aLineWidth, aFillType, aType ), EDA_TEXT( schIUScale, aText ) { @@ -138,68 +138,36 @@ VECTOR2I SCH_TEXTBOX::GetDrawPos() const { switch( GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: - pos.y = bbox.GetBottom() - m_marginBottom; - break; - case GR_TEXT_H_ALIGN_CENTER: - pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2; - break; - case GR_TEXT_H_ALIGN_RIGHT: - pos.y = bbox.GetTop() + m_marginTop; - break; - case GR_TEXT_H_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_H_ALIGN_LEFT: pos.y = bbox.GetBottom() - m_marginBottom; break; + case GR_TEXT_H_ALIGN_CENTER: pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2; break; + case GR_TEXT_H_ALIGN_RIGHT: pos.y = bbox.GetTop() + m_marginTop; break; + case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } switch( GetVertJustify() ) { - case GR_TEXT_V_ALIGN_TOP: - pos.x = bbox.GetLeft() + m_marginLeft; - break; - case GR_TEXT_V_ALIGN_CENTER: - pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2; - break; - case GR_TEXT_V_ALIGN_BOTTOM: - pos.x = bbox.GetRight() - m_marginRight; - break; - case GR_TEXT_V_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_V_ALIGN_TOP: pos.x = bbox.GetLeft() + m_marginLeft; break; + case GR_TEXT_V_ALIGN_CENTER: pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2; break; + case GR_TEXT_V_ALIGN_BOTTOM: pos.x = bbox.GetRight() - m_marginRight; break; + case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } } else { switch( GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: - pos.x = bbox.GetLeft() + m_marginLeft; - break; - case GR_TEXT_H_ALIGN_CENTER: - pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2; - break; - case GR_TEXT_H_ALIGN_RIGHT: - pos.x = bbox.GetRight() - m_marginRight; - break; - case GR_TEXT_H_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_H_ALIGN_LEFT: pos.x = bbox.GetLeft() + m_marginLeft; break; + case GR_TEXT_H_ALIGN_CENTER: pos.x = ( bbox.GetLeft() + bbox.GetRight() ) / 2; break; + case GR_TEXT_H_ALIGN_RIGHT: pos.x = bbox.GetRight() - m_marginRight; break; + case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } switch( GetVertJustify() ) { - case GR_TEXT_V_ALIGN_TOP: - pos.y = bbox.GetTop() + m_marginTop; - break; - case GR_TEXT_V_ALIGN_CENTER: - pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2; - break; - case GR_TEXT_V_ALIGN_BOTTOM: - pos.y = bbox.GetBottom() - m_marginBottom; - break; - case GR_TEXT_V_ALIGN_INDETERMINATE: - wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); - break; + case GR_TEXT_V_ALIGN_TOP: pos.y = bbox.GetTop() + m_marginTop; break; + case GR_TEXT_V_ALIGN_CENTER: pos.y = ( bbox.GetTop() + bbox.GetBottom() ) / 2; break; + case GR_TEXT_V_ALIGN_BOTTOM: pos.y = bbox.GetBottom() - m_marginBottom; break; + case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break; } } @@ -269,36 +237,29 @@ KIFONT::FONT* SCH_TEXTBOX::GetDrawFont( const RENDER_SETTINGS* aSettings ) const } -wxString SCH_TEXTBOX::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath, - bool aAllowExtraText, int aDepth ) const +wxString SCH_TEXTBOX::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_SHEET_PATH* aPath, bool aAllowExtraText, + int aDepth ) const { SCH_SHEET* sheet = nullptr; if( aPath ) sheet = aPath->Last(); - std::function textResolver = - [&]( wxString* token ) -> bool - { - if( sheet ) - { - if( sheet->ResolveTextVar( aPath, token, aDepth + 1 ) ) - return true; - } + std::function textResolver = [&]( wxString* token ) -> bool + { + if( sheet ) + { + if( sheet->ResolveTextVar( aPath, token, aDepth + 1 ) ) + return true; + } - return false; - }; + return false; + }; wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); if( HasTextVars() ) - { - if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &textResolver ); - } - - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); + text = ResolveTextVars( text, &textResolver, aDepth ); VECTOR2I size = GetEnd() - GetStart(); int colWidth; @@ -308,8 +269,8 @@ wxString SCH_TEXTBOX::GetShownText( const RENDER_SETTINGS* aSettings, const SCH_ else colWidth = abs( size.x ) - ( GetMarginLeft() + GetMarginRight() ); - GetDrawFont( aSettings )->LinebreakText( text, colWidth, GetTextSize(), GetEffectiveTextPenWidth(), - IsBold(), IsItalic() ); + GetDrawFont( aSettings ) + ->LinebreakText( text, colWidth, GetTextSize(), GetEffectiveTextPenWidth(), IsBold(), IsItalic() ); return text; } @@ -355,8 +316,7 @@ bool SCH_TEXTBOX::IsHypertext() const void SCH_TEXTBOX::DoHypertextAction( EDA_DRAW_FRAME* aFrame ) const { - wxCHECK_MSG( IsHypertext(), /* void */, - wxT( "Calling a hypertext menu on a SCH_TEXTBOX with no hyperlink?" ) ); + wxCHECK_MSG( IsHypertext(), /* void */, wxT( "Calling a hypertext menu on a SCH_TEXTBOX with no hyperlink?" ) ); SCH_NAVIGATE_TOOL* navTool = aFrame->GetToolManager()->GetTool(); @@ -380,8 +340,8 @@ BITMAPS SCH_TEXTBOX::GetMenuImage() const } -void SCH_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, - int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) +void SCH_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, + const VECTOR2I& aOffset, bool aDimmed ) { if( IsPrivate() ) return; @@ -409,7 +369,7 @@ void SCH_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS if( aDimmed ) { - color.Desaturate( ); + color.Desaturate(); color = color.Mix( bg, 0.5f ); } @@ -430,8 +390,7 @@ void SCH_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS if( renderSettings->m_Transform.y1 ) { - temp.SetTextAngle( temp.GetTextAngle() == ANGLE_HORIZONTAL ? ANGLE_VERTICAL - : ANGLE_HORIZONTAL ); + temp.SetTextAngle( temp.GetTextAngle() == ANGLE_HORIZONTAL ? ANGLE_VERTICAL : ANGLE_HORIZONTAL ); } temp.SetStart( renderSettings->TransformCoordinate( m_start ) + aOffset ); @@ -451,8 +410,7 @@ void SCH_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS for( unsigned ii = 0; ii < strings_list.Count(); ii++ ) { - aPlotter->PlotText( positions[ii], color, strings_list.Item( ii ), attrs, font, - GetFontMetrics() ); + aPlotter->PlotText( positions[ii], color, strings_list.Item( ii ), attrs, font, GetFontMetrics() ); } if( HasHyperlink() ) @@ -473,16 +431,14 @@ void SCH_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorGetName() : _( "Default" ) ); wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) }; - int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; + int style = IsBold() && IsItalic() ? 3 : IsBold() ? 2 : IsItalic() ? 1 : 0; aList.emplace_back( _( "Style" ), textStyle[style] ); aList.emplace_back( _( "Text Size" ), aFrame->MessageTextFromValue( GetTextWidth() ) ); - aList.emplace_back( _( "Box Width" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); + aList.emplace_back( _( "Box Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); - aList.emplace_back( _( "Box Height" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); + aList.emplace_back( _( "Box Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); m_stroke.GetMsgPanelInfo( aFrame, aList ); } @@ -621,27 +577,22 @@ static struct SCH_TEXTBOX_DESC const wxString marginProps = _( "Margins" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Left" ), - &SCH_TEXTBOX::SetMarginLeft, &SCH_TEXTBOX::GetMarginLeft, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Top" ), - &SCH_TEXTBOX::SetMarginTop, &SCH_TEXTBOX::GetMarginTop, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Right" ), - &SCH_TEXTBOX::SetMarginRight, &SCH_TEXTBOX::GetMarginRight, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Bottom" ), - &SCH_TEXTBOX::SetMarginBottom, &SCH_TEXTBOX::GetMarginBottom, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Left" ), &SCH_TEXTBOX::SetMarginLeft, + &SCH_TEXTBOX::GetMarginLeft, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Top" ), &SCH_TEXTBOX::SetMarginTop, + &SCH_TEXTBOX::GetMarginTop, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Right" ), &SCH_TEXTBOX::SetMarginRight, + &SCH_TEXTBOX::GetMarginRight, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Bottom" ), &SCH_TEXTBOX::SetMarginBottom, + &SCH_TEXTBOX::GetMarginBottom, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), - &SCH_TEXTBOX::SetSchTextSize, &SCH_TEXTBOX::GetSchTextSize, - PROPERTY_DISPLAY::PT_SIZE ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Text Size" ), &SCH_TEXTBOX::SetSchTextSize, + &SCH_TEXTBOX::GetSchTextSize, PROPERTY_DISPLAY::PT_SIZE ), + _HKI( "Text Properties" ) ); propMgr.Mask( TYPE_HASH( SCH_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) ); } diff --git a/eeschema/schematic.cpp b/eeschema/schematic.cpp index f2fec3b30c..0ae6d0f06f 100644 --- a/eeschema/schematic.cpp +++ b/eeschema/schematic.cpp @@ -17,7 +17,9 @@ * with this program. If not, see . */ +#include #include +#include #include #include #include @@ -50,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -61,18 +64,19 @@ bool SCHEMATIC::m_IsSchematicExists = false; SCHEMATIC::SCHEMATIC( PROJECT* aPrj ) : - EDA_ITEM( nullptr, SCHEMATIC_T ), - m_project( nullptr ), - m_rootSheet( nullptr ), - m_schematicHolder( nullptr ) + EDA_ITEM( nullptr, SCHEMATIC_T ), + m_project( nullptr ), + m_rootSheet( nullptr ), + m_schematicHolder( nullptr ) { - m_currentSheet = new SCH_SHEET_PATH(); + m_currentSheet = new SCH_SHEET_PATH(); m_connectionGraph = new CONNECTION_GRAPH( this ); m_IsSchematicExists = true; SetProject( aPrj ); - PROPERTY_MANAGER::Instance().RegisterListener( TYPE_HASH( SCH_FIELD ), + PROPERTY_MANAGER::Instance().RegisterListener( + TYPE_HASH( SCH_FIELD ), [&]( INSPECTABLE* aItem, PROPERTY_BASE* aProperty, COMMIT* aCommit ) { // Special case: propagate value, footprint, and datasheet fields to other units @@ -128,8 +132,7 @@ SCHEMATIC::SCHEMATIC( PROJECT* aPrj ) : break; } - default: - break; + default: break; } } } @@ -181,8 +184,8 @@ void SCHEMATIC::SetProject( PROJECT* aPrj ) if( m_project ) { - PROJECT_FILE& project = m_project->GetProjectFile(); - project.m_ErcSettings = new ERC_SETTINGS( &project, "erc" ); + PROJECT_FILE& project = m_project->GetProjectFile(); + project.m_ErcSettings = new ERC_SETTINGS( &project, "erc" ); project.m_SchematicSettings = new SCHEMATIC_SETTINGS( &project, "schematic" ); project.m_SchematicSettings->LoadFromFile(); @@ -201,7 +204,7 @@ void SCHEMATIC::CacheExistingAnnotation() // Cache all existing annotations in the REFDES_TRACKER std::shared_ptr refdesTracker = m_project->GetProjectFile().m_SchematicSettings->m_refDesTracker; - SCH_SHEET_LIST sheets = Hierarchy(); + SCH_SHEET_LIST sheets = Hierarchy(); SCH_REFERENCE_LIST references; sheets.GetSymbols( references ); @@ -215,7 +218,7 @@ void SCHEMATIC::CacheExistingAnnotation() bool SCHEMATIC::Contains( const SCH_REFERENCE& aRef ) const { - SCH_SHEET_LIST sheets = Hierarchy(); + SCH_SHEET_LIST sheets = Hierarchy(); SCH_REFERENCE_LIST references; /// TODO(snh): This is horribly inefficient, we should be using refdesTracker for this. @@ -241,17 +244,12 @@ void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet ) wxLogTrace( traceSchSheetPaths, "SetRoot called: sheet='%s', UUID=%s, isVirtualRoot=%d, m_topLevelSheets.size()=%zu", - aRootSheet->GetName(), - aRootSheet->m_Uuid.AsString(), - isVirtualRoot ? 1 : 0, - m_topLevelSheets.size() ); + aRootSheet->GetName(), aRootSheet->m_Uuid.AsString(), isVirtualRoot ? 1 : 0, m_topLevelSheets.size() ); for( size_t i = 0; i < m_topLevelSheets.size(); ++i ) { SCH_SHEET* sheet = m_topLevelSheets[i]; - wxLogTrace( traceSchSheetPaths, - " m_topLevelSheets[%zu]: '%s' (UUID=%s, isVirtualRoot=%d)", - i, + wxLogTrace( traceSchSheetPaths, " m_topLevelSheets[%zu]: '%s' (UUID=%s, isVirtualRoot=%d)", i, sheet ? sheet->GetName() : wxString( "(null)" ), sheet ? sheet->m_Uuid.AsString() : wxString( "(null)" ), sheet && sheet->m_Uuid == niluuid ? 1 : 0 ); @@ -295,14 +293,11 @@ void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet ) m_currentSheet->push_back( m_topLevelSheets[0] ); wxLogTrace( traceSchCurrentSheet, "SetRoot: Set current sheet to first top-level sheet '%s', path='%s', size=%zu", - m_topLevelSheets[0]->GetName(), - m_currentSheet->Path().AsString(), - m_currentSheet->size() ); + m_topLevelSheets[0]->GetName(), m_currentSheet->Path().AsString(), m_currentSheet->size() ); } else { - wxLogTrace( traceSchCurrentSheet, - "SetRoot: No top-level sheets, current sheet left empty" ); + wxLogTrace( traceSchCurrentSheet, "SetRoot: No top-level sheets, current sheet left empty" ); } // If no top-level sheets, leave current sheet empty - it will be set when sheets are added } @@ -342,11 +337,8 @@ void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet ) m_currentSheet->clear(); m_currentSheet->push_back( aRootSheet ); - wxLogTrace( traceSchCurrentSheet, - "SetRoot: Set current sheet to root sheet '%s', path='%s', size=%zu", - aRootSheet->GetName(), - m_currentSheet->Path().AsString(), - m_currentSheet->size() ); + wxLogTrace( traceSchCurrentSheet, "SetRoot: Set current sheet to root sheet '%s', path='%s', size=%zu", + aRootSheet->GetName(), m_currentSheet->Path().AsString(), m_currentSheet->size() ); } if( m_project ) @@ -359,7 +351,7 @@ void SCHEMATIC::SetRoot( SCH_SHEET* aRootSheet ) if( m_rootSheet->GetScreen() ) { - SCH_SCREENS screens( m_rootSheet ); + SCH_SCREENS screens( m_rootSheet ); std::set variantNames = screens.GetVariantNames(); m_variantNames.insert( variantNames.begin(), variantNames.end() ); } @@ -394,12 +386,11 @@ void SCHEMATIC::RefreshHierarchy() void SCHEMATIC::GetContextualTextVars( wxArrayString* aVars ) const { - auto add = - [&]( const wxString& aVar ) - { - if( !alg::contains( *aVars, aVar ) ) - aVars->push_back( aVar ); - }; + auto add = [&]( const wxString& aVar ) + { + if( !alg::contains( *aVars, aVar ) ) + aVars->push_back( aVar ); + }; add( wxT( "#" ) ); add( wxT( "##" ) ); @@ -417,8 +408,7 @@ void SCHEMATIC::GetContextualTextVars( wxArrayString* aVars ) const } -bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token, - int aDepth ) const +bool SCHEMATIC::ResolveTextVar( const SCH_SHEET_PATH* aSheetPath, wxString* token, int aDepth ) const { wxCHECK( aSheetPath, false ); @@ -507,7 +497,7 @@ ERC_SETTINGS& SCHEMATIC::ErcSettings() const std::vector SCHEMATIC::ResolveERCExclusions() { SCH_SHEET_LIST sheetList = Hierarchy(); - ERC_SETTINGS& settings = ErcSettings(); + ERC_SETTINGS& settings = ErcSettings(); // Migrate legacy marker exclusions to new format to ensure exclusion matching functions across // file versions. Silently drops any legacy exclusions which can not be mapped to the new format @@ -530,8 +520,7 @@ std::vector SCHEMATIC::ResolveERCExclusions() { const wxString settingsKey = testMarker->GetRCItem()->GetSettingsKey(); - if( settingsKey != wxT( "pin_to_pin" ) - && settingsKey != wxT( "hier_label_mismatch" ) + if( settingsKey != wxT( "pin_to_pin" ) && settingsKey != wxT( "hier_label_mismatch" ) && settingsKey != wxT( "different_unit_net" ) ) { migratedExclusions.insert( testMarker->SerializeToString() ); @@ -605,8 +594,7 @@ void SCHEMATIC::AddBusAlias( std::shared_ptr aAlias ) auto sameDefinition = [&]( const std::shared_ptr& candidate ) -> bool { - return candidate && candidate->GetName() == aAlias->GetName() - && candidate->Members() == aAlias->Members(); + return candidate && candidate->GetName() == aAlias->GetName() && candidate->Members() == aAlias->Members(); }; auto it = std::find_if( m_busAliases.begin(), m_busAliases.end(), sameDefinition ); @@ -633,8 +621,7 @@ void SCHEMATIC::SetBusAliases( const std::vector>& aA auto sameDefinition = [&]( const std::shared_ptr& candidate ) -> bool { - return candidate && candidate->GetName() == clone->GetName() - && candidate->Members() == clone->Members(); + return candidate && candidate->GetName() == clone->GetName() && candidate->Members() == clone->Members(); }; if( std::find_if( m_busAliases.begin(), m_busAliases.end(), sameDefinition ) != m_busAliases.end() ) @@ -696,12 +683,12 @@ std::set SCHEMATIC::GetNetClassAssignmentCandidates() { std::set names; - for( const auto& [ key, subgraphList ] : m_connectionGraph->GetNetMap() ) + for( const auto& [key, subgraphList] : m_connectionGraph->GetNetMap() ) { CONNECTION_SUBGRAPH* firstSubgraph = subgraphList[0]; if( !firstSubgraph->GetDriverConnection()->IsBus() - && firstSubgraph->GetDriverPriority() >= CONNECTION_SUBGRAPH::PRIORITY::PIN ) + && firstSubgraph->GetDriverPriority() >= CONNECTION_SUBGRAPH::PRIORITY::PIN ) { names.insert( key.Name ); } @@ -726,16 +713,29 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const sheetPath = Hierarchy().GetSheetPathByKIIDPath( path ).value_or( sheetPath ); } + // Note: We don't expand nested variables or evaluate math expressions here. + // The multi-pass loop in GetShownText handles all variable and expression resolution + // before cross-references are resolved. This ensures table cell variables like ${ROW} + // are expanded correctly. + if( refItem && refItem->Type() == SCH_SYMBOL_T ) { SCH_SYMBOL* refSymbol = static_cast( refItem ); - if( refSymbol->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) ) - *token = std::move( remainder ); - else - *token = refSymbol->GetRef( &sheetPath, true ) + wxS( ":" ) + remainder; + bool resolved = refSymbol->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ); - return true; // Cross-reference is resolved whether or not the actual textvar was + if( resolved ) + { + *token = std::move( remainder ); + } + else + { + // Field/function not found on symbol + *token = + wxString::Format( wxT( "" ), refSymbol->GetRef( &sheetPath, false ), remainder ); + } + + return true; } else if( refItem && refItem->Type() == SCH_SHEET_T ) { @@ -743,10 +743,17 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const sheetPath.push_back( refSheet ); + wxString remainderBefore = remainder; + if( refSheet->ResolveTextVar( &sheetPath, &remainder, aDepth + 1 ) ) *token = std::move( remainder ); - return true; // Cross-reference is resolved whether or not the actual textvar was + // If the remainder still contains unresolved variables or expressions, + // return false so ExpandTextVars keeps the ${...} wrapper + if( remainderBefore.Contains( wxT( "${" ) ) || remainderBefore.Contains( wxT( "@{" ) ) ) + return false; + + return true; // Cross-reference is resolved } // If UUID resolution failed, try to resolve by reference designator @@ -787,16 +794,26 @@ bool SCHEMATIC::ResolveCrossReference( wxString* token, int aDepth ) const if( foundSymbol ) { - if( foundSymbol->ResolveTextVar( &foundPath, &remainder, aDepth + 1 ) ) + bool resolved = foundSymbol->ResolveTextVar( &foundPath, &remainder, aDepth + 1 ); + + if( resolved ) + { *token = std::move( remainder ); + } else - *token = foundSymbol->GetRef( &foundPath, true ) + wxS( ":" ) + remainder; + { + // Field/function not found on symbol + *token = wxString::Format( wxT( "" ), foundSymbol->GetRef( &foundPath, false ), + remainder ); + } return true; } } - return false; + // Reference not found - show error message + *token = wxString::Format( wxT( "" ), ref ); + return true; } @@ -834,7 +851,7 @@ wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const for( size_t i = 0; i < sourceLen; ++i ) { - if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' ) + if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' ) { wxString token; bool isCrossRef = false; @@ -842,8 +859,7 @@ wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const for( i = i + 2; i < sourceLen; ++i ) { - if( aSource[i] == '{' - && ( aSource[i-1] == '_' || aSource[i-1] == '^' || aSource[i-1] == '~' ) ) + if( aSource[i] == '{' && ( aSource[i - 1] == '_' || aSource[i - 1] == '^' || aSource[i - 1] == '~' ) ) { nesting++; } @@ -872,11 +888,11 @@ wxString SCHEMATIC::ConvertRefsToKIIDs( const wxString& aSource ) const for( size_t jj = 0; jj < references.GetCount(); jj++ ) { - SCH_SYMBOL* refSymbol = references[ jj ].GetSymbol(); + SCH_SYMBOL* refSymbol = references[jj].GetSymbol(); - if( ref == refSymbol->GetRef( &references[ jj ].GetSheetPath(), true ) ) + if( ref == refSymbol->GetRef( &references[jj].GetSheetPath(), true ) ) { - KIID_PATH path = references[ jj ].GetSheetPath().Path(); + KIID_PATH path = references[jj].GetSheetPath().Path(); path.push_back( refSymbol->m_Uuid ); token = path.AsString() + wxS( ":" ) + remainder; @@ -904,7 +920,7 @@ wxString SCHEMATIC::ConvertKIIDsToRefs( const wxString& aSource ) const for( size_t i = 0; i < sourceLen; ++i ) { - if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' ) + if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' ) { wxString token; bool isCrossRef = false; @@ -1048,7 +1064,7 @@ void SCHEMATIC::RecomputeIntersheetRefs() SCH_GLOBALLABEL* global = static_cast( item ); wxString resolvedLabel = global->GetShownText( &sheet, false ); - pageRefsMap[ resolvedLabel ].insert( sheet.GetVirtualPageNumber() ); + pageRefsMap[resolvedLabel].insert( sheet.GetVirtualPageNumber() ); } } @@ -1087,8 +1103,7 @@ void SCHEMATIC::RecomputeIntersheetRefs() } -wxString SCHEMATIC::GetOperatingPoint( const wxString& aNetName, int aPrecision, - const wxString& aRange ) +wxString SCHEMATIC::GetOperatingPoint( const wxString& aNetName, int aPrecision, const wxString& aRange ) { wxString spiceNetName( aNetName.Lower() ); NETLIST_EXPORTER_SPICE::ConvertToSpiceMarkup( &spiceNetName ); @@ -1203,7 +1218,7 @@ void SCHEMATIC::RecordERCExclusions() { wxString serialized = marker->SerializeToString(); ercSettings.m_ErcExclusions.insert( serialized ); - ercSettings.m_ErcExclusionComments[ serialized ] = marker->GetComment(); + ercSettings.m_ErcExclusionComments[serialized] = marker->GetComment(); } } } @@ -1314,7 +1329,7 @@ std::set SCHEMATIC::GetSchematicsSharedByMultipleProjects() c wxCHECK( m_rootSheet, retv ); SCH_SHEET_LIST hierarchy( m_rootSheet ); - SCH_SCREENS screens( m_rootSheet ); + SCH_SCREENS screens( m_rootSheet ); for( const SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() ) { @@ -1373,23 +1388,23 @@ void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen ) aScreen = GetCurrentScreen(); auto remove_item = [&]( SCH_ITEM* aItem ) -> void - { - changed = true; + { + changed = true; - if( !( aItem->GetFlags() & STRUCT_DELETED ) ) - { - aItem->SetFlags( STRUCT_DELETED ); + if( !( aItem->GetFlags() & STRUCT_DELETED ) ) + { + aItem->SetFlags( STRUCT_DELETED ); - if( aItem->IsSelected() && selectionTool ) - selectionTool->RemoveItemFromSel( aItem, true /*quiet mode*/ ); + if( aItem->IsSelected() && selectionTool ) + selectionTool->RemoveItemFromSel( aItem, true /*quiet mode*/ ); - if( m_schematicHolder ) - { - m_schematicHolder->RemoveFromScreen( aItem, aScreen ); - } - aCommit->Removed( aItem, aScreen ); - } - }; + if( m_schematicHolder ) + { + m_schematicHolder->RemoveFromScreen( aItem, aScreen ); + } + aCommit->Removed( aItem, aScreen ); + } + }; for( SCH_ITEM* item : aScreen->Items().OfType( SCH_JUNCTION_T ) ) @@ -1412,51 +1427,51 @@ void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen ) ncs.push_back( static_cast( item ) ); alg::for_all_pairs( junctions.begin(), junctions.end(), - [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond ) - { - if( ( aFirst->GetEditFlags() & STRUCT_DELETED ) - || ( aSecond->GetEditFlags() & STRUCT_DELETED ) ) - { - return; - } + [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond ) + { + if( ( aFirst->GetEditFlags() & STRUCT_DELETED ) + || ( aSecond->GetEditFlags() & STRUCT_DELETED ) ) + { + return; + } - if( aFirst->GetPosition() == aSecond->GetPosition() ) - remove_item( aSecond ); - } ); + if( aFirst->GetPosition() == aSecond->GetPosition() ) + remove_item( aSecond ); + } ); alg::for_all_pairs( ncs.begin(), ncs.end(), - [&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond ) - { - if( ( aFirst->GetEditFlags() & STRUCT_DELETED ) - || ( aSecond->GetEditFlags() & STRUCT_DELETED ) ) - { - return; - } + [&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond ) + { + if( ( aFirst->GetEditFlags() & STRUCT_DELETED ) + || ( aSecond->GetEditFlags() & STRUCT_DELETED ) ) + { + return; + } - if( aFirst->GetPosition() == aSecond->GetPosition() ) - remove_item( aSecond ); - } ); + if( aFirst->GetPosition() == aSecond->GetPosition() ) + remove_item( aSecond ); + } ); auto minX = []( const SCH_LINE* l ) - { - return std::min( l->GetStartPoint().x, l->GetEndPoint().x ); - }; + { + return std::min( l->GetStartPoint().x, l->GetEndPoint().x ); + }; auto maxX = []( const SCH_LINE* l ) - { - return std::max( l->GetStartPoint().x, l->GetEndPoint().x ); - }; + { + return std::max( l->GetStartPoint().x, l->GetEndPoint().x ); + }; auto minY = []( const SCH_LINE* l ) - { - return std::min( l->GetStartPoint().y, l->GetEndPoint().y ); - }; + { + return std::min( l->GetStartPoint().y, l->GetEndPoint().y ); + }; auto maxY = []( const SCH_LINE* l ) - { - return std::max( l->GetStartPoint().y, l->GetEndPoint().y ); - }; + { + return std::max( l->GetStartPoint().y, l->GetEndPoint().y ); + }; // Would be nice to put lines in a canonical form here by swapping // start <-> end as needed but I don't know what swapping breaks. @@ -1513,16 +1528,15 @@ void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen ) if( secondLine->GetFlags() & STRUCT_DELETED ) continue; - if( !secondLine->IsParallel( firstLine ) - || !secondLine->IsStrokeEquivalent( firstLine ) - || secondLine->GetLayer() != firstLine->GetLayer() ) + if( !secondLine->IsParallel( firstLine ) || !secondLine->IsStrokeEquivalent( firstLine ) + || secondLine->GetLayer() != firstLine->GetLayer() ) { continue; } // Remove identical lines if( firstLine->IsEndPoint( secondLine->GetStartPoint() ) - && firstLine->IsEndPoint( secondLine->GetEndPoint() ) ) + && firstLine->IsEndPoint( secondLine->GetEndPoint() ) ) { remove_item( secondLine ); continue; @@ -1556,16 +1570,15 @@ void SCHEMATIC::CleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen ) void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, - TOOL_MANAGER* aToolManager, - PROGRESS_REPORTER* aProgressReporter, - KIGFX::SCH_VIEW* aSchView, + TOOL_MANAGER* aToolManager, PROGRESS_REPORTER* aProgressReporter, + KIGFX::SCH_VIEW* aSchView, std::function* aChangedItemHandler, - PICKED_ITEMS_LIST* aLastChangeList ) + PICKED_ITEMS_LIST* aLastChangeList ) { SCHEMATIC_SETTINGS& settings = Settings(); RefreshHierarchy(); - SCH_SHEET_LIST list = Hierarchy(); - SCH_COMMIT localCommit( aToolManager ); + SCH_SHEET_LIST list = Hierarchy(); + SCH_COMMIT localCommit( aToolManager ); if( !aCommit ) aCommit = &localCommit; @@ -1589,10 +1602,8 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a if( settings.m_IntersheetRefsShow ) RecomputeIntersheetRefs(); - if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity - || aCleanupFlags == GLOBAL_CLEANUP - || aLastChangeList == nullptr - || ConnectionGraph()->IsMinor() ) + if( !ADVANCED_CFG::GetCfg().m_IncrementalConnectivity || aCleanupFlags == GLOBAL_CLEANUP + || aLastChangeList == nullptr || ConnectionGraph()->IsMinor() ) { // Clear all resolved netclass caches in case labels have changed m_project->GetProjectFile().NetSettings()->ClearAllCaches(); @@ -1667,11 +1678,9 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a // cases are not connectivity-related case UNDO_REDO::CHANGED: case UNDO_REDO::NEWITEM: - case UNDO_REDO::DELETED: - break; + case UNDO_REDO::DELETED: break; - default: - continue; + default: continue; } SCH_ITEM* item = dynamic_cast( aLastChangeList->GetPickedItem( ii ) ); @@ -1709,18 +1718,17 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a std::map itemMap; list.FillItemMap( itemMap ); - auto addPastAndPresentContainedItems = - [&]( SCH_RULE_AREA* changedRuleArea, SCH_SCREEN* screen ) - { - for( const KIID& pastItem : changedRuleArea->GetPastContainedItems() ) - { - if( itemMap.contains( pastItem ) ) - addItemToChangeSet( { static_cast( itemMap[pastItem] ), nullptr, screen } ); - } + auto addPastAndPresentContainedItems = [&]( SCH_RULE_AREA* changedRuleArea, SCH_SCREEN* screen ) + { + for( const KIID& pastItem : changedRuleArea->GetPastContainedItems() ) + { + if( itemMap.contains( pastItem ) ) + addItemToChangeSet( { static_cast( itemMap[pastItem] ), nullptr, screen } ); + } - for( SCH_ITEM* containedItem : changedRuleArea->GetContainedItems() ) - addItemToChangeSet( { containedItem, nullptr, screen } ); - }; + for( SCH_ITEM* containedItem : changedRuleArea->GetContainedItems() ) + addItemToChangeSet( { containedItem, nullptr, screen } ); + }; for( const auto& [changedRuleArea, screen] : changed_rule_areas ) addPastAndPresentContainedItems( changedRuleArea, screen ); @@ -1734,12 +1742,10 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a // to add the contained items to the change set to force update of their connectivity if( changed_item_data.item->Type() == SCH_DIRECTIVE_LABEL_T ) { - const std::vector labelConnectionPoints = - changed_item_data.item->GetConnectionPoints(); + const std::vector labelConnectionPoints = changed_item_data.item->GetConnectionPoints(); - auto candidateRuleAreas = - changed_item_data.screen->Items().Overlapping( SCH_RULE_AREA_T, - changed_item_data.item->GetBoundingBox() ); + auto candidateRuleAreas = changed_item_data.screen->Items().Overlapping( + SCH_RULE_AREA_T, changed_item_data.item->GetBoundingBox() ); for( SCH_ITEM* candidateRuleArea : candidateRuleAreas ) { @@ -1752,7 +1758,7 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a } } - for( const VECTOR2I& pt: pts ) + for( const VECTOR2I& pt : pts ) { for( SCH_ITEM* item : GetCurrentScreen()->Items().Overlapping( pt ) ) { @@ -1802,7 +1808,7 @@ void SCHEMATIC::RecalculateConnections( SCH_COMMIT* aCommit, SCH_CLEANUP_FLAGS a std::set affectedNets; - for( auto&[ path, item ] : all_items ) + for( auto& [path, item] : all_items ) { wxCHECK2( item, continue ); item->SetConnectivityDirty(); @@ -1832,15 +1838,15 @@ void SCHEMATIC::CreateDefaultScreens() // Create virtual root with niluuid and a screen to hold top-level sheets SCH_SHEET* virtualRoot = new SCH_SHEET( this ); const_cast( virtualRoot->m_Uuid ) = niluuid; - virtualRoot->SetScreen( new SCH_SCREEN( this ) ); // Virtual root has a screen + virtualRoot->SetScreen( new SCH_SCREEN( this ) ); // Virtual root has a screen // Create the actual first top-level sheet - SCH_SHEET* rootSheet = new SCH_SHEET( this ); + SCH_SHEET* rootSheet = new SCH_SHEET( this ); SCH_SCREEN* rootScreen = new SCH_SCREEN( this ); const_cast( rootSheet->m_Uuid ) = rootScreen->GetUuid(); rootSheet->SetScreen( rootScreen ); - rootScreen->SetFileName( "untitled.kicad_sch" ); // Set default filename to avoid conflicts + rootScreen->SetFileName( "untitled.kicad_sch" ); // Set default filename to avoid conflicts rootScreen->SetPageNumber( wxT( "1" ) ); // Set parent to virtual root @@ -1940,8 +1946,7 @@ bool SCHEMATIC::RemoveTopLevelSheet( SCH_SHEET* aSheet ) bool SCHEMATIC::IsTopLevelSheet( const SCH_SHEET* aSheet ) const { - return std::find( m_topLevelSheets.begin(), m_topLevelSheets.end(), aSheet ) - != m_topLevelSheets.end(); + return std::find( m_topLevelSheets.begin(), m_topLevelSheets.end(), aSheet ) != m_topLevelSheets.end(); } @@ -1949,9 +1954,8 @@ SCH_SHEET_LIST SCHEMATIC::BuildSheetListSortedByPageNumbers() const { SCH_SHEET_LIST hierarchy; - wxLogTrace( traceSchSheetPaths, - "BuildSheetListSortedByPageNumbers: %zu top-level sheets", - m_topLevelSheets.size() ); + wxLogTrace( traceSchSheetPaths, "BuildSheetListSortedByPageNumbers: %zu top-level sheets", + m_topLevelSheets.size() ); // Can't build hierarchy without top-level sheets if( m_topLevelSheets.empty() ) @@ -1962,11 +1966,8 @@ SCH_SHEET_LIST SCHEMATIC::BuildSheetListSortedByPageNumbers() const { if( sheet ) { - wxLogTrace( traceSchSheetPaths, - " Top-level sheet: '%s' (UUID=%s, isVirtualRoot=%d)", - sheet->GetName(), - sheet->m_Uuid.AsString(), - sheet->m_Uuid == niluuid ? 1 : 0 ); + wxLogTrace( traceSchSheetPaths, " Top-level sheet: '%s' (UUID=%s, isVirtualRoot=%d)", sheet->GetName(), + sheet->m_Uuid.AsString(), sheet->m_Uuid == niluuid ? 1 : 0 ); // Build the sheet list for this top-level sheet SCH_SHEET_LIST sheetList; @@ -2063,8 +2064,8 @@ void SCHEMATIC::SaveToHistory( const wxString& aProjectPath, std::vectorSaveSchematicFile( dst.GetFullPath(), sheet, this ); aFiles.push_back( dst.GetFullPath() ); - wxLogTrace( traceAutoSave, wxS("[history] sch saver exported sheet '%s' -> '%s'"), - absPath, dst.GetFullPath() ); + wxLogTrace( traceAutoSave, wxS( "[history] sch saver exported sheet '%s' -> '%s'" ), absPath, + dst.GetFullPath() ); } catch( const IO_ERROR& ioe ) { - wxLogTrace( traceAutoSave, wxS("[history] sch saver export failed for '%s': %s"), - absPath, wxString::FromUTF8( ioe.What() ) ); + wxLogTrace( traceAutoSave, wxS( "[history] sch saver export failed for '%s': %s" ), absPath, + wxString::FromUTF8( ioe.What() ) ); } } } diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp index 102ecca86c..5a6353a972 100644 --- a/eeschema/tools/sch_edit_tool.cpp +++ b/eeschema/tools/sch_edit_tool.cpp @@ -80,17 +80,14 @@ class SYMBOL_UNIT_MENU : public ACTION_MENU { public: SYMBOL_UNIT_MENU() : - ACTION_MENU( true ) + ACTION_MENU( true ) { SetIcon( BITMAPS::component_select_unit ); SetTitle( _( "Symbol Unit" ) ); } protected: - ACTION_MENU* create() const override - { - return new SYMBOL_UNIT_MENU(); - } + ACTION_MENU* create() const override { return new SYMBOL_UNIT_MENU(); } private: void update() override @@ -114,16 +111,15 @@ private: if( missingUnits.count( ii + 1 ) == 0 ) unit_text += _( " (already placed)" ); - wxMenuItem* item = Append( ID_POPUP_SCH_SELECT_UNIT1 + ii, unit_text, wxEmptyString, - wxITEM_CHECK ); + wxMenuItem* item = Append( ID_POPUP_SCH_SELECT_UNIT1 + ii, unit_text, wxEmptyString, wxITEM_CHECK ); if( unit == ii + 1 ) item->Check( true ); // The ID max for these submenus is ID_POPUP_SCH_SELECT_UNIT_END // See eeschema_id to modify this value. - if( ii >= ( ID_POPUP_SCH_SELECT_UNIT_END - ID_POPUP_SCH_SELECT_UNIT1) ) - break; // We have used all IDs for these submenus + if( ii >= ( ID_POPUP_SCH_SELECT_UNIT_END - ID_POPUP_SCH_SELECT_UNIT1 ) ) + break; // We have used all IDs for these submenus } if( !missingUnits.empty() ) @@ -132,8 +128,8 @@ private: for( int unitNumber : missingUnits ) { - wxString placeText = wxString::Format( _( "Place unit %s" ), - symbol->GetUnitDisplayName( unitNumber, false ) ); + wxString placeText = + wxString::Format( _( "Place unit %s" ), symbol->GetUnitDisplayName( unitNumber, false ) ); Append( ID_POPUP_SCH_PLACE_UNIT1 + unitNumber - 1, placeText ); } } @@ -145,17 +141,14 @@ class BODY_STYLE_MENU : public ACTION_MENU { public: BODY_STYLE_MENU() : - ACTION_MENU( true ) + ACTION_MENU( true ) { SetIcon( BITMAPS::body_style ); SetTitle( _( "Body Style" ) ); } protected: - ACTION_MENU* create() const override - { - return new BODY_STYLE_MENU(); - } + ACTION_MENU* create() const override { return new BODY_STYLE_MENU(); } private: void update() override @@ -194,17 +187,14 @@ class ALT_PIN_FUNCTION_MENU : public ACTION_MENU { public: ALT_PIN_FUNCTION_MENU() : - ACTION_MENU( true ) + ACTION_MENU( true ) { SetIcon( BITMAPS::component_select_unit ); SetTitle( _( "Pin Function" ) ); } protected: - ACTION_MENU* create() const override - { - return new ALT_PIN_FUNCTION_MENU(); - } + ACTION_MENU* create() const override { return new ALT_PIN_FUNCTION_MENU(); } private: void update() override @@ -218,15 +208,14 @@ private: wxCHECK( libPin, /* void */ ); - wxMenuItem* item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION, libPin->GetName(), wxEmptyString, - wxITEM_CHECK ); + wxMenuItem* item = Append( ID_POPUP_SCH_ALT_PIN_FUNCTION, libPin->GetName(), wxEmptyString, wxITEM_CHECK ); if( pin->GetAlt().IsEmpty() || ( pin->GetAlt() == libPin->GetName() ) ) item->Check( true ); int ii = 1; - for( const auto& [ name, definition ] : libPin->GetAlternates() ) + for( const auto& [name, definition] : libPin->GetAlternates() ) { // The default pin name is set above, avoid setting it again. if( name == libPin->GetName() ) @@ -240,7 +229,7 @@ private: // The ID max for these submenus is ID_POPUP_SCH_ALT_PIN_FUNCTION_END // See eeschema_id to modify this value. if( ++ii >= ( ID_POPUP_SCH_ALT_PIN_FUNCTION_END - ID_POPUP_SCH_SELECT_UNIT ) ) - break; // We have used all IDs for these submenus + break; // We have used all IDs for these submenus } } }; @@ -249,7 +238,8 @@ private: class PIN_TRICKS_MENU : public ACTION_MENU { public: - PIN_TRICKS_MENU() : ACTION_MENU( true ) + PIN_TRICKS_MENU() : + ACTION_MENU( true ) { SetIcon( BITMAPS::pin ); SetTitle( _( "Pin Helpers" ) ); @@ -271,11 +261,11 @@ private: if( !pin && !sheetPin ) return; - Add( _( "Wire" ), ID_POPUP_SCH_PIN_TRICKS_WIRE, BITMAPS::add_line ); - Add( _( "No Connect" ), ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT, BITMAPS::noconn ); - Add( _( "Net Label" ), ID_POPUP_SCH_PIN_TRICKS_NET_LABEL, BITMAPS::add_label ); - Add( _( "Hierarchical Label" ), ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL, BITMAPS::add_hierarchical_label ); - Add( _( "Global Label" ), ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL, BITMAPS::add_glabel ); + Add( _( "Wire" ), ID_POPUP_SCH_PIN_TRICKS_WIRE, BITMAPS::add_line ); + Add( _( "No Connect" ), ID_POPUP_SCH_PIN_TRICKS_NO_CONNECT, BITMAPS::noconn ); + Add( _( "Net Label" ), ID_POPUP_SCH_PIN_TRICKS_NET_LABEL, BITMAPS::add_label ); + Add( _( "Hierarchical Label" ), ID_POPUP_SCH_PIN_TRICKS_HIER_LABEL, BITMAPS::add_hierarchical_label ); + Add( _( "Global Label" ), ID_POPUP_SCH_PIN_TRICKS_GLOBAL_LABEL, BITMAPS::add_glabel ); } }; @@ -298,363 +288,325 @@ bool SCH_EDIT_TOOL::Init() wxASSERT_MSG( drawingTools, "eeshema.InteractiveDrawing tool is not available" ); - auto sheetHasUndefinedPins = - []( const SELECTION& aSel ) - { - if( aSel.Size() == 1 && aSel.Front()->Type() == SCH_SHEET_T ) - return static_cast( aSel.Front() )->HasUndefinedPins(); + auto hasElements = [this]( const SELECTION& aSel ) + { + return !m_frame->GetScreen()->Items().empty(); + }; - return false; - }; + auto sheetHasUndefinedPins = []( const SELECTION& aSel ) + { + if( aSel.Size() == 1 && aSel.Front()->Type() == SCH_SHEET_T ) + return static_cast( aSel.Front() )->HasUndefinedPins(); - auto attribDNPCond = - [] ( const SELECTION& aSel ) - { - return std::all_of( aSel.Items().begin(), aSel.Items().end(), - []( const EDA_ITEM* item ) - { - return !item->IsType( { SCH_SYMBOL_T } ) - || static_cast( item )->GetDNP(); - } ); - }; + return false; + }; - auto attribExcludeFromSimCond = - [] ( const SELECTION& aSel ) - { - return std::all_of( aSel.Items().begin(), aSel.Items().end(), - []( const EDA_ITEM* item ) - { - return !item->IsType( { SCH_SYMBOL_T } ) - || static_cast( item )->GetExcludedFromSim(); - } ); - }; + auto attribDNPCond = []( const SELECTION& aSel ) + { + return std::all_of( aSel.Items().begin(), aSel.Items().end(), + []( const EDA_ITEM* item ) + { + return !item->IsType( { SCH_SYMBOL_T } ) + || static_cast( item )->GetDNP(); + } ); + }; - auto attribExcludeFromBOMCond = - [] ( const SELECTION& aSel ) - { - return std::all_of( aSel.Items().begin(), aSel.Items().end(), - []( const EDA_ITEM* item ) - { - return !item->IsType( { SCH_SYMBOL_T } ) - || static_cast( item )->GetExcludedFromBOM(); - } ); - }; + auto attribExcludeFromSimCond = []( const SELECTION& aSel ) + { + return std::all_of( aSel.Items().begin(), aSel.Items().end(), + []( const EDA_ITEM* item ) + { + return !item->IsType( { SCH_SYMBOL_T } ) + || static_cast( item )->GetExcludedFromSim(); + } ); + }; + + auto attribExcludeFromBOMCond = []( const SELECTION& aSel ) + { + return std::all_of( aSel.Items().begin(), aSel.Items().end(), + []( const EDA_ITEM* item ) + { + return !item->IsType( { SCH_SYMBOL_T } ) + || static_cast( item )->GetExcludedFromBOM(); + } ); + }; - auto attribExcludeFromBoardCond = - [] ( const SELECTION& aSel ) - { - return std::all_of( aSel.Items().begin(), aSel.Items().end(), - []( const EDA_ITEM* item ) - { - return !item->IsType( { SCH_SYMBOL_T } ) - || static_cast( item )->GetExcludedFromBoard(); - } ); - }; + auto attribExcludeFromBoardCond = []( const SELECTION& aSel ) + { + return std::all_of( aSel.Items().begin(), aSel.Items().end(), + []( const EDA_ITEM* item ) + { + return !item->IsType( { SCH_SYMBOL_T } ) + || static_cast( item )->GetExcludedFromBoard(); + } ); + }; - static const std::vector attribTypes = { SCH_SYMBOL_T, SCH_SHEET_T }; static const std::vector sheetTypes = { SCH_SHEET_T }; auto sheetSelection = S_C::Count( 1 ) && S_C::OnlyTypes( sheetTypes ); - auto haveHighlight = - [this]( const SELECTION& sel ) - { - SCH_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); + auto haveHighlight = [this]( const SELECTION& sel ) + { + SCH_EDIT_FRAME* editFrame = dynamic_cast( m_frame ); - return editFrame && !editFrame->GetHighlightedConnection().IsEmpty(); - }; + return editFrame && !editFrame->GetHighlightedConnection().IsEmpty(); + }; - auto anyTextTool = - [this]( const SELECTION& aSel ) - { - return ( m_frame->IsCurrentTool( SCH_ACTIONS::placeLabel ) - || m_frame->IsCurrentTool( SCH_ACTIONS::placeClassLabel ) - || m_frame->IsCurrentTool( SCH_ACTIONS::placeGlobalLabel ) - || m_frame->IsCurrentTool( SCH_ACTIONS::placeHierLabel ) - || m_frame->IsCurrentTool( SCH_ACTIONS::placeSchematicText ) ); - }; + auto anyTextTool = [this]( const SELECTION& aSel ) + { + return ( m_frame->IsCurrentTool( SCH_ACTIONS::placeLabel ) + || m_frame->IsCurrentTool( SCH_ACTIONS::placeClassLabel ) + || m_frame->IsCurrentTool( SCH_ACTIONS::placeGlobalLabel ) + || m_frame->IsCurrentTool( SCH_ACTIONS::placeHierLabel ) + || m_frame->IsCurrentTool( SCH_ACTIONS::placeSchematicText ) ); + }; - auto duplicateCondition = - []( const SELECTION& aSel ) - { - if( SCH_LINE_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( aSel ) ) - return false; + auto duplicateCondition = []( const SELECTION& aSel ) + { + if( SCH_LINE_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( aSel ) ) + return false; - return true; - }; + return true; + }; - auto orientCondition = - []( const SELECTION& aSel ) - { - if( SCH_LINE_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( aSel ) ) - return false; + auto orientCondition = []( const SELECTION& aSel ) + { + if( SCH_LINE_WIRE_BUS_TOOL::IsDrawingLineWireOrBus( aSel ) ) + return false; - return SELECTION_CONDITIONS::HasTypes( SCH_EDIT_TOOL::RotatableItems )( aSel ); - }; + return SELECTION_CONDITIONS::HasTypes( SCH_EDIT_TOOL::RotatableItems )( aSel ); + }; const auto swapSelectionCondition = S_C::OnlyTypes( SwappableItems ) && SELECTION_CONDITIONS::MoreThan( 1 ); - auto propertiesCondition = - [this]( const SELECTION& aSel ) + auto propertiesCondition = [this]( const SELECTION& aSel ) + { + if( aSel.GetSize() == 0 ) + { + if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) ) { - if( aSel.GetSize() == 0 ) - { - if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) ) - { - DS_PROXY_VIEW_ITEM* ds = m_frame->GetCanvas()->GetView()->GetDrawingSheet(); - VECTOR2D cursor = getViewControls()->GetCursorPosition( false ); + DS_PROXY_VIEW_ITEM* ds = m_frame->GetCanvas()->GetView()->GetDrawingSheet(); + VECTOR2D cursor = getViewControls()->GetCursorPosition( false ); - if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) ) - return true; - } + if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) ) + return true; + } - return false; - } + return false; + } - SCH_ITEM* firstItem = dynamic_cast( aSel.Front() ); - const SCH_SELECTION* eeSelection = dynamic_cast( &aSel ); + SCH_ITEM* firstItem = dynamic_cast( aSel.Front() ); + const SCH_SELECTION* eeSelection = dynamic_cast( &aSel ); - if( !firstItem || !eeSelection ) - return false; + if( !firstItem || !eeSelection ) + return false; - switch( firstItem->Type() ) - { - case SCH_SYMBOL_T: - case SCH_SHEET_T: - case SCH_SHEET_PIN_T: - case SCH_TEXT_T: - case SCH_TEXTBOX_T: - case SCH_TABLE_T: - case SCH_TABLECELL_T: - case SCH_LABEL_T: - case SCH_GLOBAL_LABEL_T: - case SCH_HIER_LABEL_T: - case SCH_DIRECTIVE_LABEL_T: - case SCH_RULE_AREA_T: - case SCH_FIELD_T: - case SCH_SHAPE_T: - case SCH_BITMAP_T: - case SCH_GROUP_T: - return aSel.GetSize() == 1; + switch( firstItem->Type() ) + { + case SCH_SYMBOL_T: + case SCH_SHEET_T: + case SCH_SHEET_PIN_T: + case SCH_TEXT_T: + case SCH_TEXTBOX_T: + case SCH_TABLE_T: + case SCH_TABLECELL_T: + case SCH_LABEL_T: + case SCH_GLOBAL_LABEL_T: + case SCH_HIER_LABEL_T: + case SCH_DIRECTIVE_LABEL_T: + case SCH_RULE_AREA_T: + case SCH_FIELD_T: + case SCH_SHAPE_T: + case SCH_BITMAP_T: + case SCH_GROUP_T: return aSel.GetSize() == 1; - case SCH_LINE_T: - case SCH_BUS_WIRE_ENTRY_T: - case SCH_JUNCTION_T: - if( std::all_of( aSel.Items().begin(), aSel.Items().end(), - [&]( const EDA_ITEM* item ) - { - return item->Type() == SCH_LINE_T + case SCH_LINE_T: + case SCH_BUS_WIRE_ENTRY_T: + case SCH_JUNCTION_T: + if( std::all_of( aSel.Items().begin(), aSel.Items().end(), + [&]( const EDA_ITEM* item ) + { + return item->Type() == SCH_LINE_T && static_cast( item )->IsGraphicLine(); - } ) ) - { - return true; - } - else if( std::all_of( aSel.Items().begin(), aSel.Items().end(), - [&]( const EDA_ITEM* item ) - { - return item->Type() == SCH_JUNCTION_T; - } ) ) - { - return true; - } - else if( std::all_of( aSel.Items().begin(), aSel.Items().end(), - [&]( const EDA_ITEM* item ) - { - const SCH_ITEM* schItem = dynamic_cast( item ); - - wxCHECK( schItem, false ); - - return ( schItem->HasLineStroke() && schItem->IsConnectable() ) - || item->Type() == SCH_JUNCTION_T; - } ) ) - { - return true; - } - - return false; - - default: - return false; - } - }; - - auto autoplaceCondition = - []( const SELECTION& aSel ) + } ) ) { - for( const EDA_ITEM* item : aSel ) - { - if( item->IsType( SCH_COLLECTOR::FieldOwners ) ) - return true; - } + return true; + } + else if( std::all_of( aSel.Items().begin(), aSel.Items().end(), + [&]( const EDA_ITEM* item ) + { + return item->Type() == SCH_JUNCTION_T; + } ) ) + { + return true; + } + else if( std::all_of( aSel.Items().begin(), aSel.Items().end(), + [&]( const EDA_ITEM* item ) + { + const SCH_ITEM* schItem = dynamic_cast( item ); - return false; - }; + wxCHECK( schItem, false ); + + return ( schItem->HasLineStroke() && schItem->IsConnectable() ) + || item->Type() == SCH_JUNCTION_T; + } ) ) + { + return true; + } + + return false; + + default: return false; + } + }; + + auto autoplaceCondition = []( const SELECTION& aSel ) + { + for( const EDA_ITEM* item : aSel ) + { + if( item->IsType( SCH_COLLECTOR::FieldOwners ) ) + return true; + } + + return false; + }; // allTextTypes does not include SCH_SHEET_PIN_T because one cannot convert other // types to/from this type, living only in a SHEET - static const std::vector allTextTypes = { SCH_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_TEXT_T, - SCH_TEXTBOX_T }; + static const std::vector allTextTypes = { SCH_LABEL_T, SCH_DIRECTIVE_LABEL_T, + SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, + SCH_TEXT_T, SCH_TEXTBOX_T }; auto toChangeCondition = ( S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toLabelTypes = { SCH_DIRECTIVE_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_TEXT_T, - SCH_TEXTBOX_T }; + static const std::vector toLabelTypes = { SCH_DIRECTIVE_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, + SCH_TEXT_T, SCH_TEXTBOX_T }; auto toLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toLabelTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toCLabelTypes = { SCH_LABEL_T, - SCH_HIER_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_TEXT_T, + static const std::vector toCLabelTypes = { SCH_LABEL_T, SCH_HIER_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_TEXT_T, SCH_TEXTBOX_T }; auto toCLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toCLabelTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toHLabelTypes = { SCH_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_TEXT_T, - SCH_TEXTBOX_T }; + static const std::vector toHLabelTypes = { SCH_LABEL_T, SCH_DIRECTIVE_LABEL_T, SCH_GLOBAL_LABEL_T, + SCH_TEXT_T, SCH_TEXTBOX_T }; auto toHLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toHLabelTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toGLabelTypes = { SCH_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_HIER_LABEL_T, - SCH_TEXT_T, - SCH_TEXTBOX_T }; + static const std::vector toGLabelTypes = { SCH_LABEL_T, SCH_DIRECTIVE_LABEL_T, SCH_HIER_LABEL_T, + SCH_TEXT_T, SCH_TEXTBOX_T }; auto toGLabelCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toGLabelTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toTextTypes = { SCH_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_TEXTBOX_T }; + static const std::vector toTextTypes = { SCH_LABEL_T, SCH_DIRECTIVE_LABEL_T, SCH_GLOBAL_LABEL_T, + SCH_HIER_LABEL_T, SCH_TEXTBOX_T }; auto toTextCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toTextTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector toTextBoxTypes = { SCH_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_TEXT_T }; + static const std::vector toTextBoxTypes = { SCH_LABEL_T, SCH_DIRECTIVE_LABEL_T, SCH_GLOBAL_LABEL_T, + SCH_HIER_LABEL_T, SCH_TEXT_T }; auto toTextBoxCondition = ( S_C::Count( 1 ) && S_C::OnlyTypes( toTextBoxTypes ) ) - || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); + || ( S_C::MoreThan( 1 ) && S_C::OnlyTypes( allTextTypes ) ); - static const std::vector busEntryTypes = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T}; + static const std::vector busEntryTypes = { SCH_BUS_WIRE_ENTRY_T, SCH_BUS_BUS_ENTRY_T }; auto entryCondition = S_C::MoreThan( 0 ) && S_C::OnlyTypes( busEntryTypes ); - auto singleSheetCondition = S_C::Count( 1 ) && S_C::OnlyTypes( sheetTypes ); + auto singleSheetCondition = S_C::Count( 1 ) && S_C::OnlyTypes( sheetTypes ); - auto makeSymbolUnitMenu = - [&]( TOOL_INTERACTIVE* tool ) - { - std::shared_ptr menu = std::make_shared(); - menu->SetTool( tool ); - tool->GetToolMenu().RegisterSubMenu( menu ); - return menu.get(); - }; + auto makeSymbolUnitMenu = [&]( TOOL_INTERACTIVE* tool ) + { + std::shared_ptr menu = std::make_shared(); + menu->SetTool( tool ); + tool->GetToolMenu().RegisterSubMenu( menu ); + return menu.get(); + }; - auto makeBodyStyleMenu = - [&]( TOOL_INTERACTIVE* tool ) - { - std::shared_ptr menu = std::make_shared(); - menu->SetTool( tool ); - tool->GetToolMenu().RegisterSubMenu( menu ); - return menu.get(); - }; + auto makeBodyStyleMenu = [&]( TOOL_INTERACTIVE* tool ) + { + std::shared_ptr menu = std::make_shared(); + menu->SetTool( tool ); + tool->GetToolMenu().RegisterSubMenu( menu ); + return menu.get(); + }; - auto makePinFunctionMenu = - [&]( TOOL_INTERACTIVE* tool ) - { - std::shared_ptr menu = std::make_shared(); - menu->SetTool( tool ); - tool->GetToolMenu().RegisterSubMenu( menu ); - return menu.get(); - }; + auto makePinFunctionMenu = [&]( TOOL_INTERACTIVE* tool ) + { + std::shared_ptr menu = std::make_shared(); + menu->SetTool( tool ); + tool->GetToolMenu().RegisterSubMenu( menu ); + return menu.get(); + }; - auto makePinTricksMenu = - [&]( TOOL_INTERACTIVE* tool ) - { - std::shared_ptr menu = std::make_shared(); - menu->SetTool( tool ); - tool->GetToolMenu().RegisterSubMenu( menu ); - return menu.get(); - }; + auto makePinTricksMenu = [&]( TOOL_INTERACTIVE* tool ) + { + std::shared_ptr menu = std::make_shared(); + menu->SetTool( tool ); + tool->GetToolMenu().RegisterSubMenu( menu ); + return menu.get(); + }; - auto makeTransformMenu = - [&]() - { - CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool ); - menu->SetUntranslatedTitle( _HKI( "Transform Selection" ) ); + auto makeTransformMenu = [&]() + { + CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool ); + menu->SetUntranslatedTitle( _HKI( "Transform Selection" ) ); - menu->AddItem( SCH_ACTIONS::rotateCCW, orientCondition ); - menu->AddItem( SCH_ACTIONS::rotateCW, orientCondition ); - menu->AddItem( SCH_ACTIONS::mirrorV, orientCondition ); - menu->AddItem( SCH_ACTIONS::mirrorH, orientCondition ); + menu->AddItem( SCH_ACTIONS::rotateCCW, orientCondition ); + menu->AddItem( SCH_ACTIONS::rotateCW, orientCondition ); + menu->AddItem( SCH_ACTIONS::mirrorV, orientCondition ); + menu->AddItem( SCH_ACTIONS::mirrorH, orientCondition ); - return menu; - }; + return menu; + }; - auto makeAttributesMenu = - [&]() - { - CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool ); - menu->SetUntranslatedTitle( _HKI( "Attributes" ) ); + auto makeAttributesMenu = [&]() + { + CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( moveTool ); + menu->SetUntranslatedTitle( _HKI( "Attributes" ) ); - menu->AddCheckItem( SCH_ACTIONS::setExcludeFromSimulation, S_C::ShowAlways ); - menu->AddCheckItem( SCH_ACTIONS::setExcludeFromBOM, S_C::ShowAlways ); - menu->AddCheckItem( SCH_ACTIONS::setExcludeFromBoard, S_C::ShowAlways ); - menu->AddCheckItem( SCH_ACTIONS::setDNP, S_C::ShowAlways ); + menu->AddCheckItem( SCH_ACTIONS::setExcludeFromSimulation, S_C::ShowAlways ); + menu->AddCheckItem( SCH_ACTIONS::setExcludeFromBOM, S_C::ShowAlways ); + menu->AddCheckItem( SCH_ACTIONS::setExcludeFromBoard, S_C::ShowAlways ); + menu->AddCheckItem( SCH_ACTIONS::setDNP, S_C::ShowAlways ); - return menu; - }; + return menu; + }; - auto makeEditFieldsMenu = - [&]() - { - CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool ); - menu->SetUntranslatedTitle( _HKI( "Edit Main Fields" ) ); + auto makeEditFieldsMenu = [&]() + { + CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool ); + menu->SetUntranslatedTitle( _HKI( "Edit Main Fields" ) ); - menu->AddItem( SCH_ACTIONS::editReference, S_C::SingleSymbol, 200 ); - menu->AddItem( SCH_ACTIONS::editValue, S_C::SingleSymbol, 200 ); - menu->AddItem( SCH_ACTIONS::editFootprint, S_C::SingleSymbol, 200 ); + menu->AddItem( SCH_ACTIONS::editReference, S_C::SingleSymbol, 200 ); + menu->AddItem( SCH_ACTIONS::editValue, S_C::SingleSymbol, 200 ); + menu->AddItem( SCH_ACTIONS::editFootprint, S_C::SingleSymbol, 200 ); - return menu; - }; + return menu; + }; - auto makeConvertToMenu = - [&]() - { - CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool ); - menu->SetUntranslatedTitle( _HKI( "Change To" ) ); - menu->SetIcon( BITMAPS::right ); + auto makeConvertToMenu = [&]() + { + CONDITIONAL_MENU* menu = new CONDITIONAL_MENU( m_selectionTool ); + menu->SetUntranslatedTitle( _HKI( "Change To" ) ); + menu->SetIcon( BITMAPS::right ); - menu->AddItem( SCH_ACTIONS::toLabel, toLabelCondition ); - menu->AddItem(SCH_ACTIONS::toDLabel, toCLabelCondition ); - menu->AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition ); - menu->AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition ); - menu->AddItem( SCH_ACTIONS::toText, toTextCondition ); - menu->AddItem( SCH_ACTIONS::toTextBox, toTextBoxCondition ); + menu->AddItem( SCH_ACTIONS::toLabel, toLabelCondition ); + menu->AddItem( SCH_ACTIONS::toDLabel, toCLabelCondition ); + menu->AddItem( SCH_ACTIONS::toHLabel, toHLabelCondition ); + menu->AddItem( SCH_ACTIONS::toGLabel, toGLabelCondition ); + menu->AddItem( SCH_ACTIONS::toText, toTextCondition ); + menu->AddItem( SCH_ACTIONS::toTextBox, toTextBoxCondition ); - return menu; - }; + return menu; + }; const auto canCopyText = SCH_CONDITIONS::OnlyTypes( { SCH_TEXT_T, @@ -677,87 +629,87 @@ bool SCH_EDIT_TOOL::Init() moveMenu.AddSeparator(); moveMenu.AddMenu( makeSymbolUnitMenu( moveTool ), S_C::SingleMultiUnitSymbol, 1 ); - moveMenu.AddMenu( makeBodyStyleMenu( moveTool ), S_C::SingleMultiBodyStyleSymbol, 1 ); + moveMenu.AddMenu( makeBodyStyleMenu( moveTool ), S_C::SingleMultiBodyStyleSymbol, 1 ); - moveMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); - moveMenu.AddMenu( makeAttributesMenu(), S_C::HasTypes( attribTypes ), 200 ); - moveMenu.AddItem( SCH_ACTIONS::swap, swapSelectionCondition, 200 ); - moveMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); - moveMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); + moveMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); + moveMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 ); + moveMenu.AddItem( SCH_ACTIONS::swap, swapSelectionCondition, 200 ); + moveMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); + moveMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); moveMenu.AddSeparator(); - moveMenu.AddItem( ACTIONS::cut, S_C::IdleSelection ); - moveMenu.AddItem( ACTIONS::copy, S_C::IdleSelection ); - moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection ); - moveMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty ); - moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition ); + moveMenu.AddItem( ACTIONS::cut, S_C::IdleSelection ); + moveMenu.AddItem( ACTIONS::copy, S_C::IdleSelection ); + moveMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection ); + moveMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty ); + moveMenu.AddItem( ACTIONS::duplicate, duplicateCondition ); // // Add editing actions to the drawing tool menu // CONDITIONAL_MENU& drawMenu = drawingTools->GetToolMenu().GetMenu(); - drawMenu.AddItem( SCH_ACTIONS::clearHighlight, haveHighlight && S_C::Idle, 1 ); - drawMenu.AddSeparator( haveHighlight && S_C::Idle, 1 ); + drawMenu.AddItem( SCH_ACTIONS::clearHighlight, haveHighlight && SCH_CONDITIONS::Idle, 1 ); + drawMenu.AddSeparator( haveHighlight && SCH_CONDITIONS::Idle, 1 ); - drawMenu.AddItem( SCH_ACTIONS::enterSheet, sheetSelection && S_C::Idle, 1 ); - drawMenu.AddSeparator( sheetSelection && S_C::Idle, 1 ); + drawMenu.AddItem( SCH_ACTIONS::enterSheet, sheetSelection && SCH_CONDITIONS::Idle, 1 ); + drawMenu.AddSeparator( sheetSelection && SCH_CONDITIONS::Idle, 1 ); drawMenu.AddMenu( makeSymbolUnitMenu( drawingTools ), S_C::SingleMultiUnitSymbol, 1 ); - drawMenu.AddMenu( makeBodyStyleMenu( drawingTools ), S_C::SingleMultiBodyStyleSymbol, 1 ); + drawMenu.AddMenu( makeBodyStyleMenu( drawingTools ), S_C::SingleMultiBodyStyleSymbol, 1 ); - drawMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); - drawMenu.AddMenu( makeAttributesMenu(), S_C::HasTypes( attribTypes ), 200 ); - drawMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); - drawMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); - drawMenu.AddItem( SCH_ACTIONS::autoplaceFields, autoplaceCondition, 200 ); + drawMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); + drawMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 ); + drawMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); + drawMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); + drawMenu.AddItem( SCH_ACTIONS::autoplaceFields, autoplaceCondition, 200 ); - drawMenu.AddItem( SCH_ACTIONS::editWithLibEdit, S_C::SingleSymbolOrPower && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::editWithLibEdit, S_C::SingleSymbolOrPower && S_C::Idle, 200 ); - drawMenu.AddItem( SCH_ACTIONS::toLabel, anyTextTool && S_C::Idle, 200 ); - drawMenu.AddItem( SCH_ACTIONS::toHLabel, anyTextTool && S_C::Idle, 200 ); - drawMenu.AddItem( SCH_ACTIONS::toGLabel, anyTextTool && S_C::Idle, 200 ); - drawMenu.AddItem( SCH_ACTIONS::toText, anyTextTool && S_C::Idle, 200 ); - drawMenu.AddItem( SCH_ACTIONS::toTextBox, anyTextTool && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::toLabel, anyTextTool && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::toHLabel, anyTextTool && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::toGLabel, anyTextTool && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::toText, anyTextTool && S_C::Idle, 200 ); + drawMenu.AddItem( SCH_ACTIONS::toTextBox, anyTextTool && S_C::Idle, 200 ); // // Add editing actions to the selection tool menu // CONDITIONAL_MENU& selToolMenu = m_selectionTool->GetToolMenu().GetMenu(); - selToolMenu.AddMenu( makeSymbolUnitMenu( m_selectionTool ), S_C::SingleMultiUnitSymbol, 1 ); - selToolMenu.AddMenu( makeBodyStyleMenu( m_selectionTool ), S_C::SingleMultiBodyStyleSymbol, 1 ); + selToolMenu.AddMenu( makeSymbolUnitMenu( m_selectionTool ), S_C::SingleMultiUnitSymbol, 1 ); + selToolMenu.AddMenu( makeBodyStyleMenu( m_selectionTool ), S_C::SingleMultiBodyStyleSymbol, 1 ); selToolMenu.AddMenu( makePinFunctionMenu( m_selectionTool ), S_C::SingleMultiFunctionPin, 1 ); - selToolMenu.AddMenu( makePinTricksMenu( m_selectionTool ), S_C::AllPinsOrSheetPins, 1 ); + selToolMenu.AddMenu( makePinTricksMenu( m_selectionTool ), S_C::AllPinsOrSheetPins, 1 ); - selToolMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); - selToolMenu.AddMenu( makeAttributesMenu(), S_C::HasTypes( attribTypes ), 200 ); - selToolMenu.AddItem( SCH_ACTIONS::swap, swapSelectionCondition, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); - selToolMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); + selToolMenu.AddMenu( makeTransformMenu(), orientCondition, 200 ); + selToolMenu.AddMenu( makeAttributesMenu(), S_C::HasType( SCH_SYMBOL_T ), 200 ); + selToolMenu.AddItem( SCH_ACTIONS::swap, swapSelectionCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::properties, propertiesCondition, 200 ); + selToolMenu.AddMenu( makeEditFieldsMenu(), S_C::SingleSymbol, 200 ); selToolMenu.AddItem( SCH_ACTIONS::autoplaceFields, autoplaceCondition, 200 ); selToolMenu.AddItem( SCH_ACTIONS::editWithLibEdit, S_C::SingleSymbolOrPower && S_C::Idle, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::changeSymbol, S_C::SingleSymbolOrPower, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::updateSymbol, S_C::SingleSymbolOrPower, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::changeSymbols, S_C::MultipleSymbolsOrPower, 200 ); - selToolMenu.AddItem( SCH_ACTIONS::updateSymbols, S_C::MultipleSymbolsOrPower, 200 ); - selToolMenu.AddMenu( makeConvertToMenu(), toChangeCondition, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::changeSymbol, S_C::SingleSymbolOrPower, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::updateSymbol, S_C::SingleSymbolOrPower, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::changeSymbols, S_C::MultipleSymbolsOrPower, 200 ); + selToolMenu.AddItem( SCH_ACTIONS::updateSymbols, S_C::MultipleSymbolsOrPower, 200 ); + selToolMenu.AddMenu( makeConvertToMenu(), toChangeCondition, 200 ); selToolMenu.AddItem( SCH_ACTIONS::cleanupSheetPins, sheetHasUndefinedPins, 250 ); selToolMenu.AddSeparator( 300 ); - selToolMenu.AddItem( ACTIONS::cut, S_C::IdleSelection, 300 ); - selToolMenu.AddItem( ACTIONS::copy, S_C::IdleSelection, 300 ); - selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection, 300 ); - selToolMenu.AddItem( ACTIONS::paste, S_C::Idle, 300 ); - selToolMenu.AddItem( ACTIONS::pasteSpecial, S_C::Idle, 300 ); - selToolMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty, 300 ); - selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 ); + selToolMenu.AddItem( ACTIONS::cut, S_C::IdleSelection, 300 ); + selToolMenu.AddItem( ACTIONS::copy, S_C::IdleSelection, 300 ); + selToolMenu.AddItem( ACTIONS::copyAsText, canCopyText && S_C::IdleSelection, 300 ); + selToolMenu.AddItem( ACTIONS::paste, S_C::Idle, 300 ); + selToolMenu.AddItem( ACTIONS::pasteSpecial, S_C::Idle, 300 ); + selToolMenu.AddItem( ACTIONS::doDelete, S_C::NotEmpty, 300 ); + selToolMenu.AddItem( ACTIONS::duplicate, duplicateCondition, 300 ); selToolMenu.AddSeparator( 400 ); - selToolMenu.AddItem( ACTIONS::selectAll, S_C::ShowAlways, 400 ); - selToolMenu.AddItem( ACTIONS::unselectAll, S_C::ShowAlways, 400 ); + selToolMenu.AddItem( ACTIONS::selectAll, hasElements, 400 ); + selToolMenu.AddItem( ACTIONS::unselectAll, hasElements, 400 ); ACTION_MANAGER* mgr = m_toolMgr->GetActionManager(); // clang-format off @@ -772,46 +724,18 @@ bool SCH_EDIT_TOOL::Init() const std::vector SCH_EDIT_TOOL::RotatableItems = { - SCH_SHAPE_T, - SCH_RULE_AREA_T, - SCH_TEXT_T, - SCH_TEXTBOX_T, - SCH_TABLE_T, - SCH_TABLECELL_T, // will be promoted to parent table(s) - SCH_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_GROUP_T, - SCH_HIER_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_FIELD_T, - SCH_SYMBOL_T, - SCH_SHEET_PIN_T, - SCH_SHEET_T, - SCH_BITMAP_T, - SCH_BUS_BUS_ENTRY_T, - SCH_BUS_WIRE_ENTRY_T, - SCH_LINE_T, - SCH_JUNCTION_T, - SCH_NO_CONNECT_T + SCH_SHAPE_T, SCH_RULE_AREA_T, SCH_TEXT_T, SCH_TEXTBOX_T, SCH_TABLE_T, + SCH_TABLECELL_T, // will be promoted to parent table(s) + SCH_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_GROUP_T, SCH_HIER_LABEL_T, SCH_DIRECTIVE_LABEL_T, + SCH_FIELD_T, SCH_SYMBOL_T, SCH_SHEET_PIN_T, SCH_SHEET_T, SCH_BITMAP_T, + SCH_BUS_BUS_ENTRY_T, SCH_BUS_WIRE_ENTRY_T, SCH_LINE_T, SCH_JUNCTION_T, SCH_NO_CONNECT_T }; const std::vector SCH_EDIT_TOOL::SwappableItems = { - SCH_SHAPE_T, - SCH_RULE_AREA_T, - SCH_TEXT_T, - SCH_TEXTBOX_T, - SCH_LABEL_T, - SCH_SHEET_PIN_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_DIRECTIVE_LABEL_T, - SCH_FIELD_T, - SCH_SYMBOL_T, - SCH_SHEET_T, - SCH_BITMAP_T, - SCH_JUNCTION_T, - SCH_NO_CONNECT_T + SCH_SHAPE_T, SCH_RULE_AREA_T, SCH_TEXT_T, SCH_TEXTBOX_T, SCH_LABEL_T, + SCH_SHEET_PIN_T, SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_DIRECTIVE_LABEL_T, SCH_FIELD_T, + SCH_SYMBOL_T, SCH_SHEET_T, SCH_BITMAP_T, SCH_JUNCTION_T, SCH_NO_CONNECT_T }; @@ -820,14 +744,14 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) bool clockwise = ( aEvent.Matches( SCH_ACTIONS::rotateCW.MakeEvent() ) ); SCH_SELECTION& selection = m_selectionTool->RequestSelection( RotatableItems, true, false ); - wxLogTrace( "KICAD_SCH_MOVE", "SCH_EDIT_TOOL::Rotate: start, clockwise=%d, selection size=%u", - clockwise, selection.GetSize() ); + wxLogTrace( "KICAD_SCH_MOVE", "SCH_EDIT_TOOL::Rotate: start, clockwise=%d, selection size=%u", clockwise, + selection.GetSize() ); if( selection.GetSize() == 0 ) return 0; SCH_ITEM* head = nullptr; - int principalItemCount = 0; // User-selected items (as opposed to connected wires) + int principalItemCount = 0; // User-selected items (as opposed to connected wires) VECTOR2I rotPoint; bool moving = false; SCH_COMMIT localCommit( m_toolMgr ); @@ -897,7 +821,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) case SCH_SHEET_PIN_T: { // Rotate pin within parent sheet - SCH_SHEET_PIN* pin = static_cast( head ); + SCH_SHEET_PIN* pin = static_cast( head ); SCH_SHEET* sheet = pin->GetParent(); pin->Rotate( sheet->GetBoundingBox().GetCenter(), !clockwise ); @@ -932,10 +856,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) case SCH_JUNCTION_T: case SCH_NO_CONNECT_T: case SCH_BUS_BUS_ENTRY_T: - case SCH_BUS_WIRE_ENTRY_T: - head->Rotate( rotPoint, !clockwise ); - - break; + case SCH_BUS_WIRE_ENTRY_T: head->Rotate( rotPoint, !clockwise ); break; case SCH_FIELD_T: { @@ -954,10 +875,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) case SCH_RULE_AREA_T: case SCH_SHAPE_T: - case SCH_TEXTBOX_T: - head->Rotate( rotPoint, !clockwise ); - - break; + case SCH_TEXTBOX_T: head->Rotate( rotPoint, !clockwise ); break; case SCH_GROUP_T: { @@ -1003,8 +921,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) break; } - default: - UNIMPLEMENTED_FOR( head->GetClass() ); + default: UNIMPLEMENTED_FOR( head->GetClass() ); } m_frame->UpdateItem( head, false, true ); @@ -1323,9 +1240,8 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) * If a field is in only one list, it will simply be rotated by aFallbackRotation * (CW or CCW depending on which list it is in) */ -static void swapFieldPositionsWithMatching( std::vector& aAFields, - std::vector& aBFields, - unsigned aFallbackRotationsCCW ) +static void swapFieldPositionsWithMatching( std::vector& aAFields, std::vector& aBFields, + unsigned aFallbackRotationsCCW ) { std::set handledKeys; @@ -1491,7 +1407,7 @@ int SCH_EDIT_TOOL::Swap( const TOOL_EVENT& aEvent ) { SCH_SYMBOL* aSymbol = static_cast( a ); SCH_SYMBOL* bSymbol = static_cast( b ); - int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation(); + int aOrient = aSymbol->GetOrientation(), bOrient = bSymbol->GetOrientation(); std::swap( aOrient, bOrient ); aSymbol->SetOrientation( aOrient ); bSymbol->SetOrientation( bOrient ); @@ -1583,13 +1499,15 @@ int SCH_EDIT_TOOL::SwapPins( const TOOL_EVENT& aEvent ) if( projects.IsEmpty() ) { - m_frame->ShowInfoBarError( - _( "Pin swaps are disabled for symbols shared across other projects. Duplicate the sheet to edit pins independently." ) ); + m_frame->ShowInfoBarError( _( "Pin swaps are disabled for symbols shared across other projects. " + "Duplicate the sheet to edit pins independently." ) ); } else { m_frame->ShowInfoBarError( - wxString::Format( _( "Pin swaps are disabled for symbols shared across other projects (%s). Duplicate the sheet to edit pins independently." ), projects ) ); + wxString::Format( _( "Pin swaps are disabled for symbols shared across other projects (%s). " + "Duplicate the sheet to edit pins independently." ), + projects ) ); } } else if( !friendlySheets.empty() ) @@ -1597,7 +1515,9 @@ int SCH_EDIT_TOOL::SwapPins( const TOOL_EVENT& aEvent ) wxString sheets = AccumulateDescriptions( friendlySheets ); m_frame->ShowInfoBarError( - wxString::Format( _( "Pin swaps are disabled for symbols used by multiple sheet instances (%s). Duplicate the sheet to edit pins independently." ), sheets ) ); + wxString::Format( _( "Pin swaps are disabled for symbols used by multiple sheet instances (%s). " + "Duplicate the sheet to edit pins independently." ), + sheets ) ); } else { @@ -1811,13 +1731,14 @@ int SCH_EDIT_TOOL::SwapUnitLabels( const TOOL_EVENT& aEvent ) } // Sort labels by pin position (X, then Y) - std::sort( byPos.begin(), byPos.end(), []( const auto& a, const auto& b ) - { - if( a.first.x != b.first.x ) - return a.first.x < b.first.x; + std::sort( byPos.begin(), byPos.end(), + []( const auto& a, const auto& b ) + { + if( a.first.x != b.first.x ) + return a.first.x < b.first.x; - return a.first.y < b.first.y; - } ); + return a.first.y < b.first.y; + } ); // Discard position, just keep the order std::vector labels; @@ -1914,7 +1835,7 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent ) if( newItem->Type() == SCH_SHEET_T ) { SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet(); - SCH_SHEET* sheet = static_cast( newItem ); + SCH_SHEET* sheet = static_cast( newItem ); if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) ) { @@ -1941,19 +1862,17 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent ) if( newItem->Type() == SCH_SYMBOL_T ) { - SCHEMATIC_SETTINGS& projSettings = m_frame->Schematic().Settings(); - int annotateStartNum = projSettings.m_AnnotateStartNum; - ANNOTATE_ORDER_T annotateOrder = static_cast( projSettings.m_AnnotateSortOrder ); - ANNOTATE_ALGO_T annotateAlgo = static_cast( projSettings.m_AnnotateMethod ); + SCHEMATIC_SETTINGS& projSettings = m_frame->Schematic().Settings(); + int annotateStartNum = projSettings.m_AnnotateStartNum; + ANNOTATE_ORDER_T annotateOrder = static_cast( projSettings.m_AnnotateSortOrder ); + ANNOTATE_ALGO_T annotateAlgo = static_cast( projSettings.m_AnnotateMethod ); if( m_frame->eeconfig()->m_AnnotatePanel.automatic ) { static_cast( newItem )->ClearAnnotation( nullptr, false ); NULL_REPORTER reporter; - m_frame->AnnotateSymbols( &commit, ANNOTATE_SELECTION, - annotateOrder, - annotateAlgo, true /* recursive */, - annotateStartNum, false, false, reporter ); + m_frame->AnnotateSymbols( &commit, ANNOTATE_SELECTION, annotateOrder, annotateAlgo, + true /* recursive */, annotateStartNum, false, false, reporter ); } // Annotation clears the selection so re-add the item @@ -2100,7 +2019,7 @@ void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField ) SCH_COMMIT commit( m_toolMgr ); // Save old symbol in undo list if not already in edit, or moving. - if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved + if( aField->GetEditFlags() == 0 ) // i.e. not edited, or moved commit.Modify( aField, m_frame->GetScreen() ); if( parentType == SCH_SYMBOL_T && aField->GetId() == FIELD_T::REFERENCE ) @@ -2143,9 +2062,7 @@ void SCH_EDIT_TOOL::editFieldText( SCH_FIELD* aField ) int SCH_EDIT_TOOL::EditField( const TOOL_EVENT& aEvent ) { - SCH_SELECTION sel = m_selectionTool->RequestSelection( { SCH_FIELD_T, - SCH_SYMBOL_T, - SCH_PIN_T } ); + SCH_SELECTION sel = m_selectionTool->RequestSelection( { SCH_FIELD_T, SCH_SYMBOL_T, SCH_PIN_T } ); if( sel.Size() != 1 ) return 0; @@ -2158,8 +2075,8 @@ int SCH_EDIT_TOOL::EditField( const TOOL_EVENT& aEvent ) SCH_FIELD* field = static_cast( item ); if( ( aEvent.IsAction( &SCH_ACTIONS::editReference ) && field->GetId() != FIELD_T::REFERENCE ) - || ( aEvent.IsAction( &SCH_ACTIONS::editValue ) && field->GetId() != FIELD_T::VALUE ) - || ( aEvent.IsAction( &SCH_ACTIONS::editFootprint ) && field->GetId() != FIELD_T::FOOTPRINT ) ) + || ( aEvent.IsAction( &SCH_ACTIONS::editValue ) && field->GetId() != FIELD_T::VALUE ) + || ( aEvent.IsAction( &SCH_ACTIONS::editFootprint ) && field->GetId() != FIELD_T::FOOTPRINT ) ) { item = field->GetParentSymbol(); @@ -2393,9 +2310,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) dlg.ShowModal(); } - else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_ITEM_LOCATE_WIRE_T, - SCH_ITEM_LOCATE_BUS_T, - SCH_BUS_WIRE_ENTRY_T, + else if( SELECTION_CONDITIONS::OnlyTypes( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, SCH_BUS_WIRE_ENTRY_T, SCH_JUNCTION_T } )( selection ) ) { std::deque items; @@ -2420,7 +2335,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) SCH_INSPECTION_TOOL* inspectionTool = m_toolMgr->GetTool(); if( inspectionTool ) - inspectionTool->CrossProbe( static_cast ( selection.Front() ) ); + inspectionTool->CrossProbe( static_cast( selection.Front() ) ); } break; @@ -2434,7 +2349,8 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) DIALOG_TABLECELL_PROPERTIES dlg( m_frame, cells ); - dlg.ShowModal(); + // QuasiModal required for syntax help and Scintilla auto-complete + dlg.ShowQuasiModal(); if( dlg.GetReturnValue() == DIALOG_TABLECELL_PROPERTIES::TABLECELL_PROPS_EDIT_TABLE ) { @@ -2542,11 +2458,11 @@ void SCH_EDIT_TOOL::EditProperties( EDA_ITEM* aItem ) case SCH_SHEET_T: { - SCH_SHEET* sheet = static_cast( aItem ); - bool isUndoable = false; - bool doClearAnnotation = false; - bool okPressed = false; - bool updateHierarchyNavigator = false; + SCH_SHEET* sheet = static_cast( aItem ); + bool isUndoable = false; + bool doClearAnnotation = false; + bool okPressed = false; + bool updateHierarchyNavigator = false; // Keep track of existing sheet paths. EditSheet() can modify this list. // Note that we use the validity checking/repairing version here just to make sure @@ -2556,8 +2472,8 @@ void SCH_EDIT_TOOL::EditProperties( EDA_ITEM* aItem ) SCH_COMMIT commit( m_toolMgr ); commit.Modify( sheet, m_frame->GetScreen() ); - okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable, - &doClearAnnotation, &updateHierarchyNavigator ); + okPressed = m_frame->EditSheetProperties( sheet, &m_frame->GetCurrentSheet(), &isUndoable, &doClearAnnotation, + &updateHierarchyNavigator ); if( okPressed ) { @@ -2694,16 +2610,14 @@ void SCH_EDIT_TOOL::EditProperties( EDA_ITEM* aItem ) } case SCH_NO_CONNECT_T: - case SCH_PIN_T: - break; + case SCH_PIN_T: break; case SCH_GROUP_T: - m_toolMgr->RunAction( ACTIONS::groupProperties, - static_cast( static_cast( aItem ) ) ); + m_toolMgr->RunAction( ACTIONS::groupProperties, static_cast( static_cast( aItem ) ) ); break; - default: // Unexpected item + default: // Unexpected item wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + aItem->GetClass() ); } @@ -2714,11 +2628,10 @@ void SCH_EDIT_TOOL::EditProperties( EDA_ITEM* aItem ) int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) { KICAD_T convertTo = aEvent.Parameter(); - SCH_SELECTION selection = m_selectionTool->RequestSelection( { SCH_LABEL_LOCATE_ANY_T, - SCH_TEXT_T, - SCH_TEXTBOX_T } ); - SCH_COMMIT localCommit( m_toolMgr ); - SCH_COMMIT* commit = dynamic_cast( aEvent.Commit() ); + SCH_SELECTION selection = + m_selectionTool->RequestSelection( { SCH_LABEL_LOCATE_ANY_T, SCH_TEXT_T, SCH_TEXTBOX_T } ); + SCH_COMMIT localCommit( m_toolMgr ); + SCH_COMMIT* commit = dynamic_cast( aEvent.Commit() ); if( !commit ) commit = &localCommit; @@ -2729,14 +2642,14 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) if( item && item->Type() != convertTo ) { - EDA_TEXT* sourceText = dynamic_cast( item ); - bool selected = item->IsSelected(); - SCH_ITEM* newtext = nullptr; - VECTOR2I position = item->GetPosition(); + EDA_TEXT* sourceText = dynamic_cast( item ); + bool selected = item->IsSelected(); + SCH_ITEM* newtext = nullptr; + VECTOR2I position = item->GetPosition(); wxString txt; wxString href; - SPIN_STYLE spinStyle = SPIN_STYLE::SPIN::RIGHT; - LABEL_FLAG_SHAPE shape = LABEL_FLAG_SHAPE::L_UNSPECIFIED; + SPIN_STYLE spinStyle = SPIN_STYLE::SPIN::RIGHT; + LABEL_FLAG_SHAPE shape = LABEL_FLAG_SHAPE::L_UNSPECIFIED; wxCHECK2( sourceText, continue ); @@ -2781,14 +2694,11 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) SCH_TEXTBOX* textbox = static_cast( item ); BOX2I bbox = textbox->GetBoundingBox(); - bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(), - bbox.GetTop() + textbox->GetMarginTop() ); + bbox.SetOrigin( bbox.GetLeft() + textbox->GetMarginLeft(), bbox.GetTop() + textbox->GetMarginTop() ); bbox.SetEnd( bbox.GetRight() - textbox->GetMarginRight(), bbox.GetBottom() - textbox->GetMarginBottom() ); - if( convertTo == SCH_LABEL_T - || convertTo == SCH_HIER_LABEL_T - || convertTo == SCH_GLOBAL_LABEL_T ) + if( convertTo == SCH_LABEL_T || convertTo == SCH_HIER_LABEL_T || convertTo == SCH_GLOBAL_LABEL_T ) { EDA_TEXT* text = dynamic_cast( item ); wxCHECK( text, 0 ); @@ -2830,31 +2740,28 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) break; } - default: - UNIMPLEMENTED_FOR( item->GetClass() ); - break; + default: UNIMPLEMENTED_FOR( item->GetClass() ); break; } - auto getValidNetname = - []( const wxString& aText ) - { - wxString local_txt = aText; - local_txt.Replace( "\n", "_" ); - local_txt.Replace( "\r", "_" ); - local_txt.Replace( "\t", "_" ); + auto getValidNetname = []( const wxString& aText ) + { + wxString local_txt = aText; + local_txt.Replace( "\n", "_" ); + local_txt.Replace( "\r", "_" ); + local_txt.Replace( "\t", "_" ); - // Bus groups can have spaces; bus vectors and signal names cannot - if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) ) - local_txt.Replace( " ", "_" ); + // Bus groups can have spaces; bus vectors and signal names cannot + if( !NET_SETTINGS::ParseBusGroup( aText, nullptr, nullptr ) ) + local_txt.Replace( " ", "_" ); - // label strings are "escaped" i.e. a '/' is replaced by "{slash}" - local_txt = EscapeString( local_txt, CTX_NETNAME ); + // label strings are "escaped" i.e. a '/' is replaced by "{slash}" + local_txt = EscapeString( local_txt, CTX_NETNAME ); - if( local_txt.IsEmpty() ) - return _( "" ); - else - return local_txt; - }; + if( local_txt.IsEmpty() ) + return _( "" ); + else + return local_txt; + }; switch( convertTo ) { @@ -3011,9 +2918,7 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) break; } - default: - UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) ); - break; + default: UNIMPLEMENTED_FOR( wxString::Format( "%d.", convertTo ) ); break; } wxCHECK2( newtext, continue ); @@ -3049,11 +2954,11 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) // A SCH_GLOBALLABEL has a specific field for intersheet references that has // no meaning for other labels std::erase_if( new_label->GetFields(), - [&]( SCH_FIELD& field ) - { - return field.GetId() == FIELD_T::INTERSHEET_REFS - && new_label->Type() != SCH_GLOBAL_LABEL_T; - } ); + [&]( SCH_FIELD& field ) + { + return field.GetId() == FIELD_T::INTERSHEET_REFS + && new_label->Type() != SCH_GLOBAL_LABEL_T; + } ); } if( selected ) @@ -3086,12 +2991,7 @@ int SCH_EDIT_TOOL::ChangeTextType( const TOOL_EVENT& aEvent ) int SCH_EDIT_TOOL::JustifyText( const TOOL_EVENT& aEvent ) { - static std::vector justifiableItems = { - SCH_FIELD_T, - SCH_TEXT_T, - SCH_TEXTBOX_T, - SCH_LABEL_T - }; + static std::vector justifiableItems = { SCH_FIELD_T, SCH_TEXT_T, SCH_TEXTBOX_T, SCH_LABEL_T }; SCH_SELECTION& selection = m_selectionTool->RequestSelection( justifiableItems ); @@ -3106,16 +3006,15 @@ int SCH_EDIT_TOOL::JustifyText( const TOOL_EVENT& aEvent ) if( !commit ) commit = &localCommit; - auto setJustify = - [&]( EDA_TEXT* aTextItem ) - { - if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) ) - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); - else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) ) - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); - else - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); - }; + auto setJustify = [&]( EDA_TEXT* aTextItem ) + { + if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) ) + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) ) + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + else + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + }; for( EDA_ITEM* edaItem : selection ) { @@ -3255,7 +3154,7 @@ int SCH_EDIT_TOOL::EditPageNumber( const TOOL_EVENT& aEvent ) wxTextEntryDialog dlg( m_frame, msg, _( "Edit Sheet Page Number" ), pageNumber ); - dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space. + dlg.SetTextValidator( wxFILTER_ALPHANUMERIC ); // No white space. if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == instance.GetPageNumber() ) return 0; @@ -3307,7 +3206,7 @@ int SCH_EDIT_TOOL::DdAddImage( const TOOL_EVENT& aEvent ) } -void SCH_EDIT_TOOL::collectUnits( const SCH_SELECTION& aSelection, +void SCH_EDIT_TOOL::collectUnits( const SCH_SELECTION& aSelection, std::set>& aCollectedUnits ) { for( EDA_ITEM* item : aSelection ) @@ -3355,9 +3254,9 @@ int SCH_EDIT_TOOL::SetAttribute( const TOOL_EVENT& aEvent ) for( const auto& [symbol, _] : collectedUnits ) { if( ( aEvent.IsAction( &SCH_ACTIONS::setDNP ) && !symbol->GetDNP() ) - || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromSimulation ) && !symbol->GetExcludedFromSim() ) - || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBOM ) && !symbol->GetExcludedFromBOM() ) - || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBoard ) && !symbol->GetExcludedFromBoard() ) ) + || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromSimulation ) && !symbol->GetExcludedFromSim() ) + || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBOM ) && !symbol->GetExcludedFromBOM() ) + || ( aEvent.IsAction( &SCH_ACTIONS::setExcludeFromBoard ) && !symbol->GetExcludedFromBoard() ) ) { new_state = true; break; @@ -3393,9 +3292,8 @@ int SCH_EDIT_TOOL::SetAttribute( const TOOL_EVENT& aEvent ) wxString SCH_EDIT_TOOL::FixERCErrorMenuText( const std::shared_ptr& aERCItem ) { - if( aERCItem->GetErrorCode() == ERCE_SIMULATION_MODEL - || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_FILTERS - || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_LINK_ISSUES ) + if( aERCItem->GetErrorCode() == ERCE_SIMULATION_MODEL || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_FILTERS + || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_LINK_ISSUES ) { return _( "Edit Symbol Properties..." ); } @@ -3407,8 +3305,7 @@ wxString SCH_EDIT_TOOL::FixERCErrorMenuText( const std::shared_ptr& aER { return m_frame->GetRunMenuCommandDescription( SCH_ACTIONS::updateSymbol ); } - else if( aERCItem->GetErrorCode() == ERCE_UNANNOTATED - || aERCItem->GetErrorCode() == ERCE_DUPLICATE_REFERENCE ) + else if( aERCItem->GetErrorCode() == ERCE_UNANNOTATED || aERCItem->GetErrorCode() == ERCE_DUPLICATE_REFERENCE ) { return m_frame->GetRunMenuCommandDescription( SCH_ACTIONS::annotate ); } @@ -3427,9 +3324,8 @@ void SCH_EDIT_TOOL::FixERCError( const std::shared_ptr& aERCItem ) wxCHECK( frame, /* void */ ); - if( aERCItem->GetErrorCode() == ERCE_SIMULATION_MODEL - || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_FILTERS - || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_LINK_ISSUES ) + if( aERCItem->GetErrorCode() == ERCE_SIMULATION_MODEL || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_FILTERS + || aERCItem->GetErrorCode() == ERCE_FOOTPRINT_LINK_ISSUES ) { if( EDA_ITEM* item = frame->ResolveItem( aERCItem->GetMainItemID() ) ) EditProperties( item ); @@ -3448,8 +3344,7 @@ void SCH_EDIT_TOOL::FixERCError( const std::shared_ptr& aERCItem ) dlg.ShowQuasiModal(); } } - else if( aERCItem->GetErrorCode() == ERCE_UNANNOTATED - || aERCItem->GetErrorCode() == ERCE_DUPLICATE_REFERENCE ) + else if( aERCItem->GetErrorCode() == ERCE_UNANNOTATED || aERCItem->GetErrorCode() == ERCE_DUPLICATE_REFERENCE ) { m_toolMgr->RunAction( SCH_ACTIONS::annotate ); } diff --git a/include/common.h b/include/common.h index 3c3afed31d..b307b69547 100644 --- a/include/common.h +++ b/include/common.h @@ -67,9 +67,8 @@ KICOMMON_API wxString SearchHelpFileFullPath( const wxString& aBaseName ); * @param aReporter a point to a REPORTER object use to show messages (can be NULL) * @return true if \a aOutputDir already exists or was successfully created. */ -KICOMMON_API bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName, - const wxString& aBaseFilename, - REPORTER* aReporter = nullptr ); +KICOMMON_API bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName, const wxString& aBaseFilename, + REPORTER* aReporter = nullptr ); /** * It's annoying to throw up nag dialogs when the extension isn't right. Just fix it. @@ -89,20 +88,37 @@ KICOMMON_API wxString JoinExtensions( const std::vector& aExts ); * @param aString a string containing (perhaps) references to env var * @return the expanded environment variable. */ -KICOMMON_API const wxString ExpandEnvVarSubstitutions( const wxString& aString, - const PROJECT* aProject ); +KICOMMON_API const wxString ExpandEnvVarSubstitutions( const wxString& aString, const PROJECT* aProject ); /** * Expand '${var-name}' templates in text. */ #define FOR_ERC_DRC 1 -KICOMMON_API wxString ExpandTextVars( const wxString& aSource, - const std::function* aResolver, - int aFlags = 0 ); +KICOMMON_API wxString ExpandTextVars( const wxString& aSource, const std::function* aResolver, + int aFlags = 0, int aDepth = 0 ); -KICOMMON_API wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject, - int aFlags = 0 ); +KICOMMON_API wxString ExpandTextVars( const wxString& aSource, const PROJECT* aProject, int aFlags = 0 ); + +/** + * Multi-pass text variable expansion and math expression evaluation. + * + * Performs recursive resolution of both ${...} variable references and @{...} math expressions, + * then cleans up escape sequences (\${...} and \@{...}) to display literals. + * + * This helper encapsulates the common pattern used across schematic text components: + * - While text contains ${...} or @{...} and depth < max: + * - Expand variables via ExpandTextVars() + * - Evaluate math expressions via EXPRESSION_EVALUATOR + * - Convert escape markers back to literals + * + * @param aSource The source text containing variables and/or expressions + * @param aResolver Function to resolve variable references + * @param aDepth Current recursion depth (passed by reference, will be incremented) + * @return Fully expanded and evaluated text with escape sequences cleaned up + */ +KICOMMON_API wxString ResolveTextVars( const wxString& aSource, const std::function* aResolver, + int& aDepth ); /** * Returns any variables unexpanded, e.g. ${VAR} -> VAR @@ -136,4 +152,4 @@ KICOMMON_API long long TimestampDir( const wxString& aDirPath, const wxString& a KICOMMON_API bool WarnUserIfOperatingSystemUnsupported(); -#endif // INCLUDE__COMMON_H_ +#endif // INCLUDE__COMMON_H_ diff --git a/install-deps.sh b/install-deps.sh new file mode 100755 index 0000000000..bc3933208c --- /dev/null +++ b/install-deps.sh @@ -0,0 +1,53 @@ +#!/bin/bash +sudo apt-get update && sudo apt-get install -y \ + debhelper \ + cmake \ + cmake-curses-gui \ + build-essential \ + pkg-config \ + grep \ + doxygen \ + dblatex \ + po4a \ + asciidoc \ + source-highlight \ + libcairo2-dev \ + libglu1-mesa-dev \ + libgl1-mesa-dev \ + libglew-dev \ + libx11-dev \ + mesa-common-dev \ + libgtk-3-dev \ + libglm-dev \ + libwxgtk3.2-dev \ + libwxgtk-webview3.2-dev \ + python3-wxgtk4.0 \ + libbz2-dev \ + libssl-dev \ + libzstd-dev \ + zlib1g-dev \ + python3-dev \ + swig \ + python3-pytest \ + python3-cairosvg \ + python3-numpy \ + libocct-modeling-algorithms-dev \ + libocct-modeling-data-dev \ + libocct-data-exchange-dev \ + libocct-visualization-dev \ + libocct-foundation-dev \ + libocct-ocaf-dev \ + libgit2-dev \ + libsecret-1-dev \ + libboost-all-dev \ + libcurl4-openssl-dev \ + libngspice0-dev \ + unixodbc-dev \ + libspnav-dev \ + libnng-dev \ + libprotobuf-dev \ + protobuf-compiler \ + shared-mime-info \ + libzint-dev \ + libpoppler-dev \ + libpoppler-glib-dev diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 8f419c181d..19ad8c844b 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -689,6 +689,29 @@ foreach(file ${markdownFiles}) PROPERTIES OBJECT_DEPENDS "${existing_depends}${outputHeader}") endforeach() +# Generate pcb_text_help_md.h from pcb_text_help.md for text variable syntax help +add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h + COMMAND ${CMAKE_COMMAND} + -DinputFile=${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help.md + -DoutputFile=${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h + -P ${KICAD_CMAKE_MODULE_PATH}/BuildSteps/markdown2C.cmake + DEPENDS ${KICAD_CMAKE_MODULE_PATH}/BuildSteps/markdown2C.cmake ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help.md + COMMENT "creating pcb_text_help_md.h from pcb_text_help.md" +) + +# Add pcb_text_help_md.h as a dependency for source files that will include it +set_source_files_properties(pcb_text.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h) +set_source_files_properties(dialogs/dialog_text_properties.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h) +set_source_files_properties(dialogs/dialog_textbox_properties.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h) +set_source_files_properties(dialogs/dialog_table_properties.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h) +set_source_files_properties(dialogs/dialog_tablecell_properties.cpp + PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pcb_text_help_md.h) + if( APPLE ) # setup bundle set( PCBNEW_RESOURCES pcbnew.icns pcbnew_doc.icns fpedit.icns fpedit_doc.icns ) diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index cd1d0f52e8..104175b21c 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -140,8 +140,7 @@ BOARD::BOARD() : // Initialize default netclass. bds.m_NetSettings->SetDefaultNetclass( std::make_shared( NETCLASS::Default ) ); - bds.m_NetSettings->GetDefaultNetclass()->SetDescription( - _( "This is the default net class." ) ); + bds.m_NetSettings->GetDefaultNetclass()->SetDescription( _( "This is the default net class." ) ); bds.UseCustomTrackViaSize( false ); @@ -222,7 +221,7 @@ void BOARD::SetProject( PROJECT* aProject, bool aReferenceOnly ) // want to transfer it over to the project netclasses list. if( m_LegacyNetclassesLoaded ) { - std::shared_ptr legacySettings = GetDesignSettings().m_NetSettings; + std::shared_ptr legacySettings = GetDesignSettings().m_NetSettings; std::shared_ptr& projectSettings = project.NetSettings(); projectSettings->SetDefaultNetclass( legacySettings->GetDefaultNetclass() ); @@ -263,16 +262,10 @@ void BOARD::IncrementTimeStamp() m_timeStamp++; - if( !m_IntersectsAreaCache.empty() - || !m_EnclosedByAreaCache.empty() - || !m_IntersectsCourtyardCache.empty() - || !m_IntersectsFCourtyardCache.empty() - || !m_IntersectsBCourtyardCache.empty() - || !m_LayerExpressionCache.empty() - || !m_ZoneBBoxCache.empty() - || m_CopperItemRTreeCache - || m_maxClearanceValue.has_value() - || !m_itemByIdCache.empty() ) + if( !m_IntersectsAreaCache.empty() || !m_EnclosedByAreaCache.empty() || !m_IntersectsCourtyardCache.empty() + || !m_IntersectsFCourtyardCache.empty() || !m_IntersectsBCourtyardCache.empty() + || !m_LayerExpressionCache.empty() || !m_ZoneBBoxCache.empty() || m_CopperItemRTreeCache + || m_maxClearanceValue.has_value() || !m_itemByIdCache.empty() ) { m_IntersectsAreaCache.clear(); m_EnclosedByAreaCache.clear(); @@ -318,8 +311,8 @@ void BOARD::UpdateRatsnestExclusions() GetConnectivity()->RunOnUnconnectedEdges( [&]( CN_EDGE& aEdge ) { - if( aEdge.GetSourceNode() && aEdge.GetTargetNode() - && !aEdge.GetSourceNode()->Dirty() && !aEdge.GetTargetNode()->Dirty() ) + if( aEdge.GetSourceNode() && aEdge.GetTargetNode() && !aEdge.GetSourceNode()->Dirty() + && !aEdge.GetTargetNode()->Dirty() ) { std::pair ids = { aEdge.GetSourceNode()->Parent()->m_Uuid, aEdge.GetTargetNode()->Parent()->m_Uuid }; @@ -343,7 +336,7 @@ void BOARD::RecordDRCExclusions() { wxString serialized = marker->SerializeToString(); m_designSettings->m_DrcExclusions.insert( serialized ); - m_designSettings->m_DrcExclusionComments[ serialized ] = marker->GetComment(); + m_designSettings->m_DrcExclusionComments[serialized] = marker->GetComment(); } } @@ -463,12 +456,12 @@ std::vector BOARD::ResolveDRCExclusions( bool aCreateMarkers ) if( marker ) { - marker->SetExcluded( true, comments[ serialized ] ); + marker->SetExcluded( true, comments[serialized] ); newMarkers.push_back( marker ); // Exclusion still valid; store back to BOARD_DESIGN_SETTINGS m_designSettings->m_DrcExclusions.insert( serialized ); - m_designSettings->m_DrcExclusionComments[ serialized ] = comments[ serialized ]; + m_designSettings->m_DrcExclusionComments[serialized] = comments[serialized]; } } } @@ -479,12 +472,11 @@ std::vector BOARD::ResolveDRCExclusions( bool aCreateMarkers ) void BOARD::GetContextualTextVars( wxArrayString* aVars ) const { - auto add = - [&]( const wxString& aVar ) - { - if( !alg::contains( *aVars, aVar ) ) - aVars->push_back( aVar ); - }; + auto add = [&]( const wxString& aVar ) + { + if( !alg::contains( *aVars, aVar ) ) + aVars->push_back( aVar ); + }; add( wxT( "LAYER" ) ); add( wxT( "FILENAME" ) ); @@ -507,8 +499,8 @@ bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const { if( token->Contains( ':' ) ) { - wxString remainder; - wxString ref = token->BeforeFirst( ':', &remainder ); + wxString remainder; + wxString ref = token->BeforeFirst( ':', &remainder ); BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true ); if( refItem && refItem->Type() == PCB_FOOTPRINT_T ) @@ -521,6 +513,35 @@ bool BOARD::ResolveTextVar( wxString* token, int aDepth ) const return true; } } + + // If UUID resolution failed, try to resolve by reference designator + // This handles typing ${U1:VALUE} directly without save/reload + if( !refItem ) + { + for( const FOOTPRINT* footprint : Footprints() ) + { + if( footprint->GetReference().CmpNoCase( ref ) == 0 ) + { + wxString remainderCopy = remainder; + + if( footprint->ResolveTextVar( &remainderCopy, aDepth + 1 ) ) + { + *token = std::move( remainderCopy ); + } + else + { + // Field/function not found on footprint + *token = wxString::Format( wxT( "" ), footprint->GetReference(), remainder ); + } + + return true; + } + } + + // Reference not found - show error message + *token = wxString::Format( wxT( "" ), ref ); + return true; + } } if( token->IsSameAs( wxT( "FILENAME" ) ) ) @@ -574,27 +595,26 @@ VECTOR2I BOARD::GetPosition() const void BOARD::SetPosition( const VECTOR2I& aPos ) { - wxLogWarning( wxT( "This should not be called on the BOARD object") ); + wxLogWarning( wxT( "This should not be called on the BOARD object" ) ); } void BOARD::Move( const VECTOR2I& aMoveVector ) // overload { - INSPECTOR_FUNC inspector = - [&] ( EDA_ITEM* item, void* testData ) - { - if( item->IsBOARD_ITEM() ) - { - BOARD_ITEM* board_item = static_cast( item ); + INSPECTOR_FUNC inspector = [&]( EDA_ITEM* item, void* testData ) + { + if( item->IsBOARD_ITEM() ) + { + BOARD_ITEM* board_item = static_cast( item ); - // aMoveVector was snapshotted, don't need "data". - // Only move the top level group - if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() ) - board_item->Move( aMoveVector ); - } + // aMoveVector was snapshotted, don't need "data". + // Only move the top level group + if( !board_item->GetParentGroup() && !board_item->GetParentFootprint() ) + board_item->Move( aMoveVector ); + } - return INSPECT_RESULT::CONTINUE; - }; + return INSPECT_RESULT::CONTINUE; + }; Visit( inspector, nullptr, GENERAL_COLLECTOR::BoardLevelItems ); } @@ -647,14 +667,14 @@ TRACKS BOARD::TracksInNet( int aNetCode ) TRACKS ret; INSPECTOR_FUNC inspector = [aNetCode, &ret]( EDA_ITEM* item, void* testData ) - { - PCB_TRACK* t = static_cast( item ); + { + PCB_TRACK* t = static_cast( item ); - if( t->GetNetCode() == aNetCode ) - ret.push_back( t ); + if( t->GetNetCode() == aNetCode ) + ret.push_back( t ); - return INSPECT_RESULT::CONTINUE; - }; + return INSPECT_RESULT::CONTINUE; + }; // visit this BOARD's PCB_TRACKs and PCB_VIAs with above TRACK INSPECTOR which // appends all in aNetCode to ret. @@ -666,7 +686,7 @@ TRACKS BOARD::TracksInNet( int aNetCode ) bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer ) { - m_layers[ aIndex ] = aLayer; + m_layers[aIndex] = aLayer; recalcOpposites(); return true; } @@ -675,7 +695,7 @@ bool BOARD::SetLayerDescr( PCB_LAYER_ID aIndex, const LAYER& aLayer ) PCB_LAYER_ID BOARD::GetLayerID( const wxString& aLayerName ) const { // Check the BOARD physical layer names. - for( auto& [ layer_id, layer ] : m_layers ) + for( auto& [layer_id, layer] : m_layers ) { if( layer.m_name == aLayerName || layer.m_userName == aLayerName ) return ToLAYER_ID( layer_id ); @@ -785,26 +805,34 @@ const char* LAYER::ShowType( LAYER_T aType ) { default: case LT_SIGNAL: return "signal"; - case LT_POWER: return "power"; - case LT_MIXED: return "mixed"; + case LT_POWER: return "power"; + case LT_MIXED: return "mixed"; case LT_JUMPER: return "jumper"; - case LT_AUX: return "auxiliary"; - case LT_FRONT: return "front"; - case LT_BACK: return "back"; + case LT_AUX: return "auxiliary"; + case LT_FRONT: return "front"; + case LT_BACK: return "back"; } } LAYER_T LAYER::ParseType( const char* aType ) { - if( strcmp( aType, "signal" ) == 0 ) return LT_SIGNAL; - else if( strcmp( aType, "power" ) == 0 ) return LT_POWER; - else if( strcmp( aType, "mixed" ) == 0 ) return LT_MIXED; - else if( strcmp( aType, "jumper" ) == 0 ) return LT_JUMPER; - else if( strcmp( aType, "auxiliary" ) == 0 ) return LT_AUX; - else if( strcmp( aType, "front" ) == 0 ) return LT_FRONT; - else if( strcmp( aType, "back" ) == 0 ) return LT_BACK; - else return LT_UNDEFINED; + if( strcmp( aType, "signal" ) == 0 ) + return LT_SIGNAL; + else if( strcmp( aType, "power" ) == 0 ) + return LT_POWER; + else if( strcmp( aType, "mixed" ) == 0 ) + return LT_MIXED; + else if( strcmp( aType, "jumper" ) == 0 ) + return LT_JUMPER; + else if( strcmp( aType, "auxiliary" ) == 0 ) + return LT_AUX; + else if( strcmp( aType, "front" ) == 0 ) + return LT_FRONT; + else if( strcmp( aType, "back" ) == 0 ) + return LT_BACK; + else + return LT_UNDEFINED; } @@ -816,7 +844,7 @@ void BOARD::recalcOpposites() // Match up similary-named front/back user layers for( int layer = User_1; layer <= PCB_LAYER_ID_COUNT; layer += 2 ) { - if( m_layers[layer].m_opposite != layer ) // already paired + if( m_layers[layer].m_opposite != layer ) // already paired continue; if( m_layers[layer].m_type != LT_FRONT && m_layers[layer].m_type != LT_BACK ) @@ -826,7 +854,7 @@ void BOARD::recalcOpposites() for( int ii = layer + 2; ii <= PCB_LAYER_ID_COUNT; ii += 2 ) { - if( m_layers[ii].m_opposite != ii ) // already paired + if( m_layers[ii].m_opposite != ii ) // already paired continue; if( m_layers[ii].m_type != LT_FRONT && m_layers[ii].m_type != LT_BACK ) @@ -859,8 +887,7 @@ void BOARD::recalcOpposites() if( m_layers[layer].m_type != LT_FRONT || m_layers[next].m_type != LT_BACK ) continue; - if( m_layers[layer].m_userName != m_layers[layer].m_name - && m_layers[next].m_userName != m_layers[next].m_name ) + if( m_layers[layer].m_userName != m_layers[layer].m_name && m_layers[next].m_userName != m_layers[next].m_name ) { m_layers[layer].m_opposite = next; m_layers[next].m_opposite = layer; @@ -904,11 +931,11 @@ PCB_LAYER_ID BOARD::GetCopperLayerStackMaxId() const int imax = GetCopperLayerCount(); // layers IDs are F_Cu, B_Cu, and even IDs values (imax values) - if( imax <= 2 ) // at least 2 layers are expected + if( imax <= 2 ) // at least 2 layers are expected return B_Cu; // For a 4 layer, last ID is In2_Cu = 6 (IDs are 0, 2, 4, 6) - return static_cast( (imax-1) * 2 ); + return static_cast( ( imax - 1 ) * 2 ); } @@ -1023,8 +1050,7 @@ void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled ) break; } - default: - ; + default:; } } @@ -1035,12 +1061,11 @@ bool BOARD::IsFootprintLayerVisible( PCB_LAYER_ID aLayer ) const { case F_Cu: return IsElementVisible( LAYER_FOOTPRINTS_FR ); case B_Cu: return IsElementVisible( LAYER_FOOTPRINTS_BK ); - default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true; + default: wxFAIL_MSG( wxT( "BOARD::IsModuleLayerVisible(): bad layer" ) ); return true; } } - BOARD_DESIGN_SETTINGS& BOARD::GetDesignSettings() const { return *m_designSettings; @@ -1098,27 +1123,30 @@ void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector< if( aReporter ) aReporter->Report( _( "Tessellating copper zones..." ) ); - thread_pool& tp = GetKiCadThreadPool(); + thread_pool& tp = GetKiCadThreadPool(); std::vector> returns; returns.reserve( zones.size() ); - auto cache_zones = - [aReporter]( ZONE* aZone ) -> size_t - { - if( aReporter && aReporter->IsCancelled() ) - return 0; + auto cache_zones = [aReporter]( ZONE* aZone ) -> size_t + { + if( aReporter && aReporter->IsCancelled() ) + return 0; - aZone->CacheTriangulation(); + aZone->CacheTriangulation(); - if( aReporter ) - aReporter->AdvanceProgress(); + if( aReporter ) + aReporter->AdvanceProgress(); - return 1; - }; + return 1; + }; for( ZONE* zone : zones ) - returns.emplace_back( tp.submit_task( [cache_zones, zone] { return cache_zones( zone ); } ) ); + returns.emplace_back( tp.submit_task( + [cache_zones, zone] + { + return cache_zones( zone ); + } ) ); // Finalize the triangulation threads for( const std::future& ret : returns ) @@ -1176,29 +1204,19 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity switch( aBoardItem->Type() ) { - case PCB_NETINFO_T: - m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem ); - break; + case PCB_NETINFO_T: m_NetInfo.AppendNet( (NETINFO_ITEM*) aBoardItem ); break; // this one uses a vector - case PCB_MARKER_T: - m_markers.push_back( (PCB_MARKER*) aBoardItem ); - break; + case PCB_MARKER_T: m_markers.push_back( (PCB_MARKER*) aBoardItem ); break; // this one uses a vector - case PCB_GROUP_T: - m_groups.push_back( (PCB_GROUP*) aBoardItem ); - break; + case PCB_GROUP_T: m_groups.push_back( (PCB_GROUP*) aBoardItem ); break; // this one uses a vector - case PCB_GENERATOR_T: - m_generators.push_back( (PCB_GENERATOR*) aBoardItem ); - break; + case PCB_GENERATOR_T: m_generators.push_back( (PCB_GENERATOR*) aBoardItem ); break; // this one uses a vector - case PCB_ZONE_T: - m_zones.push_back( (ZONE*) aBoardItem ); - break; + case PCB_ZONE_T: m_zones.push_back( (ZONE*) aBoardItem ); break; case PCB_VIA_T: if( aMode == ADD_MODE::APPEND || aMode == ADD_MODE::BULK_APPEND ) @@ -1236,11 +1254,12 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity else m_footprints.push_front( footprint ); - footprint->RunOnChildren( [&]( BOARD_ITEM* aChild ) - { - m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); - }, - RECURSE_MODE::NO_RECURSE ); + footprint->RunOnChildren( + [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); + }, + RECURSE_MODE::NO_RECURSE ); break; } @@ -1267,11 +1286,12 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity { PCB_TABLE* table = static_cast( aBoardItem ); - table->RunOnChildren( [&]( BOARD_ITEM* aChild ) - { - m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); - }, - RECURSE_MODE::NO_RECURSE ); + table->RunOnChildren( + [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.insert( { aChild->m_Uuid, aChild } ); + }, + RECURSE_MODE::NO_RECURSE ); } break; @@ -1287,8 +1307,7 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode, bool aSkipConnectivity break; default: - wxFAIL_MSG( wxString::Format( wxT( "BOARD::Add() item type %s not handled" ), - aBoardItem->GetClass() ) ); + wxFAIL_MSG( wxString::Format( wxT( "BOARD::Add() item type %s not handled" ), aBoardItem->GetClass() ) ); return; } @@ -1356,45 +1375,34 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) break; } - case PCB_MARKER_T: - std::erase( m_markers, aBoardItem ); - break; + case PCB_MARKER_T: std::erase( m_markers, aBoardItem ); break; - case PCB_GROUP_T: - std::erase( m_groups, aBoardItem ); - break; + case PCB_GROUP_T: std::erase( m_groups, aBoardItem ); break; - case PCB_ZONE_T: - std::erase( m_zones, aBoardItem ); - break; + case PCB_ZONE_T: std::erase( m_zones, aBoardItem ); break; - case PCB_POINT_T: - std::erase( m_points, aBoardItem ); - break; + case PCB_POINT_T: std::erase( m_points, aBoardItem ); break; - case PCB_GENERATOR_T: - std::erase( m_generators, aBoardItem ); - break; + case PCB_GENERATOR_T: std::erase( m_generators, aBoardItem ); break; case PCB_FOOTPRINT_T: { std::erase( m_footprints, aBoardItem ); FOOTPRINT* footprint = static_cast( aBoardItem ); - footprint->RunOnChildren( [&]( BOARD_ITEM* aChild ) - { - m_itemByIdCache.erase( aChild->m_Uuid ); - }, - RECURSE_MODE::NO_RECURSE ); + footprint->RunOnChildren( + [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.erase( aChild->m_Uuid ); + }, + RECURSE_MODE::NO_RECURSE ); break; } case PCB_TRACE_T: case PCB_ARC_T: - case PCB_VIA_T: - std::erase( m_tracks, aBoardItem ); - break; + case PCB_VIA_T: std::erase( m_tracks, aBoardItem ); break; case PCB_BARCODE_T: case PCB_DIM_ALIGNED_T: @@ -1416,11 +1424,12 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) { PCB_TABLE* table = static_cast( aBoardItem ); - table->RunOnChildren( [&]( BOARD_ITEM* aChild ) - { - m_itemByIdCache.erase( aChild->m_Uuid ); - }, - RECURSE_MODE::NO_RECURSE ); + table->RunOnChildren( + [&]( BOARD_ITEM* aChild ) + { + m_itemByIdCache.erase( aChild->m_Uuid ); + }, + RECURSE_MODE::NO_RECURSE ); } break; @@ -1432,8 +1441,7 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aRemoveMode ) // other types may use linked list default: - wxFAIL_MSG( wxString::Format( wxT( "BOARD::Remove() item type %s not handled" ), - aBoardItem->GetClass() ) ); + wxFAIL_MSG( wxString::Format( wxT( "BOARD::Remove() item type %s not handled" ), aBoardItem->GetClass() ) ); } aBoardItem->SetFlags( STRUCT_DELETED ); @@ -1496,9 +1504,7 @@ void BOARD::RemoveAll( std::initializer_list aTypes ) break; case PCB_ARC_T: - case PCB_VIA_T: - wxFAIL_MSG( wxT( "Use PCB_TRACE_T to remove all tracks, arcs, and vias" ) ); - break; + case PCB_VIA_T: wxFAIL_MSG( wxT( "Use PCB_TRACE_T to remove all tracks, arcs, and vias" ) ); break; case PCB_SHAPE_T: std::copy( m_drawings.begin(), m_drawings.end(), std::back_inserter( removed ) ); @@ -1516,12 +1522,9 @@ void BOARD::RemoveAll( std::initializer_list aTypes ) case PCB_TEXTBOX_T: case PCB_TABLE_T: case PCB_TARGET_T: - case PCB_BARCODE_T: - wxFAIL_MSG( wxT( "Use PCB_SHAPE_T to remove all graphics and text" ) ); - break; + case PCB_BARCODE_T: wxFAIL_MSG( wxT( "Use PCB_SHAPE_T to remove all graphics and text" ) ); break; - default: - wxFAIL_MSG( wxT( "BOARD::RemoveAll() needs more ::Type() support" ) ); + default: wxFAIL_MSG( wxT( "BOARD::RemoveAll() needs more ::Type() support" ) ); } } @@ -1579,8 +1582,8 @@ bool BOARD::HasItemsOnLayer( PCB_LAYER_ID aLayer ) bool BOARD::RemoveAllItemsOnLayer( PCB_LAYER_ID aLayer ) { - bool modified = false; - bool removedItemLayers = false; + bool modified = false; + bool removedItemLayers = false; PCB_LAYER_COLLECTOR collector; collector.SetLayerId( aLayer ); @@ -1665,27 +1668,23 @@ wxString BOARD::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) void BOARD::UpdateUserUnits( BOARD_ITEM* aItem, KIGFX::VIEW* aView ) { - INSPECTOR_FUNC inspector = - [&]( EDA_ITEM* descendant, void* aTestData ) - { - PCB_DIMENSION_BASE* dimension = static_cast( descendant ); + INSPECTOR_FUNC inspector = [&]( EDA_ITEM* descendant, void* aTestData ) + { + PCB_DIMENSION_BASE* dimension = static_cast( descendant ); - if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC ) - { - dimension->UpdateUnits(); + if( dimension->GetUnitsMode() == DIM_UNITS_MODE::AUTOMATIC ) + { + dimension->UpdateUnits(); - if( aView ) - aView->Update( dimension ); - } + if( aView ) + aView->Update( dimension ); + } - return INSPECT_RESULT::CONTINUE; - }; + return INSPECT_RESULT::CONTINUE; + }; - aItem->Visit( inspector, nullptr, { PCB_DIM_ALIGNED_T, - PCB_DIM_LEADER_T, - PCB_DIM_ORTHOGONAL_T, - PCB_DIM_CENTER_T, - PCB_DIM_RADIAL_T } ); + aItem->Visit( inspector, nullptr, + { PCB_DIM_ALIGNED_T, PCB_DIM_LEADER_T, PCB_DIM_ORTHOGONAL_T, PCB_DIM_CENTER_T, PCB_DIM_RADIAL_T } ); } @@ -1707,7 +1706,7 @@ void BOARD::DeleteMARKERs( bool aWarningsAndErrors, bool aExclusions ) for( PCB_MARKER* marker : m_markers ) { if( ( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION && aExclusions ) - || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) ) + || ( marker->GetSeverity() != RPT_SEVERITY_EXCLUSION && aWarningsAndErrors ) ) { delete marker; } @@ -1861,42 +1860,42 @@ BOARD_ITEM* BOARD::ResolveItem( const KIID& aID, bool aAllowNullptrReturn ) cons void BOARD::FillItemMap( std::map& aMap ) { // the board itself - aMap[ m_Uuid ] = this; + aMap[m_Uuid] = this; for( PCB_TRACK* track : Tracks() ) - aMap[ track->m_Uuid ] = track; + aMap[track->m_Uuid] = track; for( FOOTPRINT* footprint : Footprints() ) { - aMap[ footprint->m_Uuid ] = footprint; + aMap[footprint->m_Uuid] = footprint; for( PAD* pad : footprint->Pads() ) - aMap[ pad->m_Uuid ] = pad; + aMap[pad->m_Uuid] = pad; - aMap[ footprint->Reference().m_Uuid ] = &footprint->Reference(); - aMap[ footprint->Value().m_Uuid ] = &footprint->Value(); + aMap[footprint->Reference().m_Uuid] = &footprint->Reference(); + aMap[footprint->Value().m_Uuid] = &footprint->Value(); for( BOARD_ITEM* drawing : footprint->GraphicalItems() ) - aMap[ drawing->m_Uuid ] = drawing; + aMap[drawing->m_Uuid] = drawing; } for( ZONE* zone : Zones() ) - aMap[ zone->m_Uuid ] = zone; + aMap[zone->m_Uuid] = zone; for( BOARD_ITEM* drawing : Drawings() ) - aMap[ drawing->m_Uuid ] = drawing; + aMap[drawing->m_Uuid] = drawing; for( PCB_MARKER* marker : m_markers ) - aMap[ marker->m_Uuid ] = marker; + aMap[marker->m_Uuid] = marker; for( PCB_GROUP* group : m_groups ) - aMap[ group->m_Uuid ] = group; + aMap[group->m_Uuid] = group; for( PCB_POINT* point : m_points ) - aMap[ point->m_Uuid ] = point; + aMap[point->m_Uuid] = point; for( PCB_GENERATOR* generator : m_generators ) - aMap[ generator->m_Uuid ] = generator; + aMap[generator->m_Uuid] = generator; } @@ -1907,7 +1906,7 @@ wxString BOARD::ConvertCrossReferencesToKIIDs( const wxString& aSource ) const for( size_t i = 0; i < sourceLen; ++i ) { - if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' ) + if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' ) { wxString token; bool isCrossRef = false; @@ -1961,7 +1960,7 @@ wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const for( size_t i = 0; i < sourceLen; ++i ) { - if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i+1] == '{' ) + if( aSource[i] == '$' && i + 1 < sourceLen && aSource[i + 1] == '{' ) { wxString token; bool isCrossRef = false; @@ -1979,14 +1978,13 @@ wxString BOARD::ConvertKIIDsToCrossReferences( const wxString& aSource ) const if( isCrossRef ) { - wxString remainder; - wxString ref = token.BeforeFirst( ':', &remainder ); - BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true ); + wxString remainder; + wxString ref = token.BeforeFirst( ':', &remainder ); + BOARD_ITEM* refItem = ResolveItem( KIID( ref ), true ); if( refItem && refItem->Type() == PCB_FOOTPRINT_T ) { - token = static_cast( refItem )->GetReference() + wxT( ":" ) - + remainder; + token = static_cast( refItem )->GetReference() + wxT( ":" ) + remainder; } } @@ -2123,10 +2121,9 @@ void BOARD::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector } -INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, - const std::vector& scanTypes ) +INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, const std::vector& scanTypes ) { -#if 0 && defined(DEBUG) +#if 0 && defined( DEBUG ) std::cout << GetClass().mb_str() << ' '; #endif @@ -2144,7 +2141,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, break; - /* + /* * Instances of the requested KICAD_T live in a list, either one that I manage, or one * that my footprints manage. If it's a type managed by class FOOTPRINT, then simply * pass it on to each footprint's Visit() function via IterateForward( m_footprints, ... ). @@ -2168,8 +2165,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, case PCB_BARCODE_T: if( !footprintsScanned ) { - if( IterateForward( m_footprints, inspector, testData, scanTypes ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } @@ -2179,8 +2175,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, if( !drawingsScanned ) { - if( IterateForward( m_drawings, inspector, testData, scanTypes ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_drawings, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } @@ -2195,8 +2190,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, case PCB_ARC_T: if( !tracksScanned ) { - if( IterateForward( m_tracks, inspector, testData, scanTypes ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_tracks, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } @@ -2227,8 +2221,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, case PCB_ZONE_T: if( !footprintsScanned ) { - if( IterateForward( m_footprints, inspector, testData, scanTypes ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } @@ -2236,7 +2229,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, footprintsScanned = true; } - for( ZONE* zone : m_zones) + for( ZONE* zone : m_zones ) { if( zone->Visit( inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT ) return INSPECT_RESULT::QUIT; @@ -2247,8 +2240,7 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, case PCB_GENERATOR_T: if( !footprintsScanned ) { - if( IterateForward( m_footprints, inspector, testData, scanTypes ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_footprints, inspector, testData, scanTypes ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } @@ -2265,16 +2257,14 @@ INSPECT_RESULT BOARD::Visit( INSPECTOR inspector, void* testData, break; case PCB_GROUP_T: - if( IterateForward( m_groups, inspector, testData, { scanType } ) - == INSPECT_RESULT::QUIT ) + if( IterateForward( m_groups, inspector, testData, { scanType } ) == INSPECT_RESULT::QUIT ) { return INSPECT_RESULT::QUIT; } break; - default: - break; + default: break; } } @@ -2329,7 +2319,7 @@ int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet ) aComplementNet = wxT( "P" ); rv = -1; } - else if ( ch == 'P' ) + else if( ch == 'P' ) { aComplementNet = wxT( "N" ); rv = 1; @@ -2342,9 +2332,7 @@ int BOARD::MatchDpSuffix( const wxString& aNetName, wxString& aComplementNet ) if( rv != 0 && count >= 1 ) { - aComplementNet = aNetName.Left( aNetName.length() - count ) - + aComplementNet - + aNetName.Right( count - 1 ); + aComplementNet = aNetName.Left( aNetName.length() - count ) + aComplementNet + aNetName.Right( count - 1 ); } return rv; @@ -2422,7 +2410,7 @@ void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes ) if( !m_project ) return; - BOARD_DESIGN_SETTINGS& bds = GetDesignSettings(); + BOARD_DESIGN_SETTINGS& bds = GetDesignSettings(); const std::shared_ptr& defaultNetClass = bds.m_NetSettings->GetDefaultNetclass(); bds.m_NetSettings->ClearAllCaches(); @@ -2449,12 +2437,10 @@ void BOARD::SynchronizeNetsAndNetClasses( bool aResetTrackAndViaSizes ) bool BOARD::SynchronizeComponentClasses( const std::unordered_set& aNewSheetPaths ) const { - std::shared_ptr settings = - GetProject()->GetProjectFile().ComponentClassSettings(); + std::shared_ptr settings = GetProject()->GetProjectFile().ComponentClassSettings(); return m_componentClassManager->SyncDynamicComponentClassAssignments( - settings->GetComponentClassAssignments(), settings->GetEnableSheetComponentClasses(), - aNewSheetPaths ); + settings->GetComponentClassAssignments(), settings->GetEnableSheetComponentClasses(), aNewSheetPaths ); } @@ -2470,7 +2456,7 @@ int BOARD::SetAreasNetCodesFromNetNames() continue; } - if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net + if( zone->GetNetCode() != 0 ) // i.e. if this zone is connected to a net { const NETINFO_ITEM* net = zone->GetNet(); @@ -2527,20 +2513,20 @@ PAD* BOARD::GetPad( std::vector& aPadList, const VECTOR2I& aPosition, cons int delta = aPadList.size(); - int idx = 0; // Starting index is the beginning of list + int idx = 0; // Starting index is the beginning of list while( delta ) { // Calculate half size of remaining interval to test. // Ensure the computed value is not truncated (too small) - if( (delta & 1) && ( delta > 1 ) ) + if( ( delta & 1 ) && ( delta > 1 ) ) delta++; delta /= 2; PAD* pad = aPadList[idx]; - if( pad->GetPosition() == aPosition ) // candidate found + if( pad->GetPosition() == aPosition ) // candidate found { // The pad must match the layer mask: if( ( aLayerSet & pad->GetLayerSet() ).any() ) @@ -2550,7 +2536,7 @@ PAD* BOARD::GetPad( std::vector& aPadList, const VECTOR2I& aPosition, cons // search for a pad at aPosition that matched this mask // search next - for( int ii = idx+1; ii <= idxmax; ii++ ) + for( int ii = idx + 1; ii <= idxmax; ii++ ) { pad = aPadList[ii]; @@ -2561,7 +2547,7 @@ PAD* BOARD::GetPad( std::vector& aPadList, const VECTOR2I& aPosition, cons return pad; } // search previous - for( int ii = idx - 1 ;ii >=0; ii-- ) + for( int ii = idx - 1; ii >= 0; ii-- ) { pad = aPadList[ii]; @@ -2576,9 +2562,9 @@ PAD* BOARD::GetPad( std::vector& aPadList, const VECTOR2I& aPosition, cons return nullptr; } - if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate + if( pad->GetPosition().x == aPosition.x ) // Must search considering Y coordinate { - if( pad->GetPosition().y < aPosition.y ) // Must search after this item + if( pad->GetPosition().y < aPosition.y ) // Must search after this item { idx += delta; @@ -2618,7 +2604,7 @@ PAD* BOARD::GetPad( std::vector& aPadList, const VECTOR2I& aPosition, cons * * This function is used to build ordered pads lists */ -bool sortPadsByXthenYCoord( PAD* const & aLH, PAD* const & aRH ) +bool sortPadsByXthenYCoord( PAD* const& aLH, PAD* const& aRH ) { if( aLH->GetPosition().x == aRH->GetPosition().x ) return aLH->GetPosition().y < aRH->GetPosition().y; @@ -2631,7 +2617,7 @@ void BOARD::GetSortedPadListByXthenYCoord( std::vector& aVector, int aNetC { for( FOOTPRINT* footprint : Footprints() ) { - for( PAD* pad : footprint->Pads( ) ) + for( PAD* pad : footprint->Pads() ) { if( aNetCode < 0 || pad->GetNetCode() == aNetCode ) aVector.push_back( pad ); @@ -2678,13 +2664,13 @@ std::tuple BOARD::GetTrackLength( const PCB } -FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer, - bool aVisibleOnly, bool aIgnoreLocked ) const +FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveLayer, bool aVisibleOnly, + bool aIgnoreLocked ) const { - FOOTPRINT* footprint = nullptr; + FOOTPRINT* footprint = nullptr; FOOTPRINT* alt_footprint = nullptr; - int min_dim = 0x7FFFFFFF; - int alt_min_dim = 0x7FFFFFFF; + int min_dim = 0x7FFFFFFF; + int alt_min_dim = 0x7FFFFFFF; bool current_layer_back = IsBackLayer( aActiveLayer ); for( FOOTPRINT* candidate : m_footprints ) @@ -2708,8 +2694,8 @@ FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveL int offy = bb.GetY() + bb.GetHeight() / 2; // off x & offy point to the middle of the box. - int dist = ( aPosition.x - offx ) * ( aPosition.x - offx ) + - ( aPosition.y - offy ) * ( aPosition.y - offy ); + int dist = + ( aPosition.x - offx ) * ( aPosition.x - offx ) + ( aPosition.y - offy ) * ( aPosition.y - offy ); if( current_layer_back == IsBackLayer( layer ) ) { @@ -2735,7 +2721,7 @@ FOOTPRINT* BOARD::GetFootprint( const VECTOR2I& aPosition, PCB_LAYER_ID aActiveL if( footprint ) return footprint; - if( alt_footprint) + if( alt_footprint ) return alt_footprint; return nullptr; @@ -2762,8 +2748,8 @@ std::list BOARD::GetZoneList( bool aIncludeZonesInFootprints ) const } -ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, - VECTOR2I aStartPointPosition, ZONE_BORDER_DISPLAY_STYLE aHatch ) +ZONE* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode, PCB_LAYER_ID aLayer, VECTOR2I aStartPointPosition, + ZONE_BORDER_DISPLAY_STYLE aHatch ) { ZONE* new_area = new ZONE( this ); @@ -2793,8 +2779,8 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, OUTLINE_ERROR_HA // max dist from one endPt to next startPt: use the current value int chainingEpsilon = GetOutlinesChainingEpsilon(); - bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError, - chainingEpsilon, aErrorHandler, aAllowUseArcsInPolygons ); + bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError, chainingEpsilon, + aErrorHandler, aAllowUseArcsInPolygons ); // Now add NPTH oval holes as holes in outlines if required if( aIncludeNPTHAsOutlines ) @@ -2803,19 +2789,19 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, OUTLINE_ERROR_HA { for( PAD* pad : fp->Pads() ) { - if( pad->GetAttribute () != PAD_ATTRIB::NPTH ) + if( pad->GetAttribute() != PAD_ATTRIB::NPTH ) continue; SHAPE_POLY_SET hole; pad->TransformHoleToPolygon( hole, 0, pad->GetMaxError(), ERROR_INSIDE ); - if( hole.OutlineCount() > 0 ) // can be not the case for malformed NPTH holes + if( hole.OutlineCount() > 0 ) // can be not the case for malformed NPTH holes { // Add this pad hole to the main outline // But we can have more than one main outline (i.e. more than one board), so // search the right main outline i.e. the outline that contains the pad hole SHAPE_LINE_CHAIN& pad_hole = hole.Outline( 0 ); - const VECTOR2I holePt = pad_hole.CPoint( 0 ); + const VECTOR2I holePt = pad_hole.CPoint( 0 ); for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj ) { @@ -2945,7 +2931,6 @@ void BOARD::MapNets( BOARD* aDestBoard ) NETINFO_ITEM* newNet = new NETINFO_ITEM( aDestBoard, item->GetNetname() ); aDestBoard->Add( newNet ); item->SetNet( newNet ); - } } } @@ -2953,7 +2938,7 @@ void BOARD::MapNets( BOARD* aDestBoard ) void BOARD::SanitizeNetcodes() { - for ( BOARD_CONNECTED_ITEM* item : AllConnectedItems() ) + for( BOARD_CONNECTED_ITEM* item : AllConnectedItems() ) { if( FindNet( item->GetNetCode() ) == nullptr ) item->SetNetCode( NETINFO_LIST::ORPHANED ); @@ -2998,12 +2983,10 @@ void BOARD::OnItemsChanged( std::vector& aItems ) } -void BOARD::OnItemsCompositeUpdate( std::vector& aAddedItems, - std::vector& aRemovedItems, +void BOARD::OnItemsCompositeUpdate( std::vector& aAddedItems, std::vector& aRemovedItems, std::vector& aChangedItems ) { - InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems, - aChangedItems ); + InvokeListeners( &BOARD_LISTENER::OnBoardCompositeUpdate, *this, aAddedItems, aRemovedItems, aChangedItems ); } @@ -3050,7 +3033,8 @@ wxString BOARD::GroupsSanityCheck( bool repair ) if( repair ) { while( GroupsSanityCheckInternal( repair ) != wxEmptyString ) - {}; + { + }; return wxEmptyString; } @@ -3127,7 +3111,7 @@ wxString BOARD::GroupsSanityCheckInternal( bool repair ) } -bool BOARD::cmp_items::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const +bool BOARD::cmp_items::operator()( const BOARD_ITEM* a, const BOARD_ITEM* b ) const { if( a->Type() != b->Type() ) return a->Type() < b->Type(); @@ -3141,15 +3125,14 @@ bool BOARD::cmp_items::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) c if( a->GetPosition().y != b->GetPosition().y ) return a->GetPosition().y < b->GetPosition().y; - if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards + if( a->m_Uuid != b->m_Uuid ) // shopuld be always the case foer valid boards return a->m_Uuid < b->m_Uuid; return a < b; } -bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, - const BOARD_ITEM* aSecond ) const +bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const { if( aFirst->Type() != aSecond->Type() ) return aFirst->Type() < aSecond->Type(); @@ -3195,8 +3178,7 @@ bool BOARD::cmp_drawings::operator()( const BOARD_ITEM* aFirst, } -void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, - SHAPE_POLY_SET& aOutlines, +void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aOutlines, KIGFX::RENDER_SETTINGS* aRenderSettings ) const { int maxError = GetDesignSettings().m_MaxError; @@ -3215,9 +3197,8 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, { footprint->TransformPadsToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); - footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE, - true, /* include text */ - true, /* include shapes */ + footprint->TransformFPShapesToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE, true, /* include text */ + true, /* include shapes */ false /* include private items */ ); for( const ZONE* zone : footprint->Zones() ) @@ -3293,8 +3274,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, break; } - default: - break; + default: break; } } } @@ -3441,8 +3421,8 @@ void BOARD::SaveToHistory( const wxString& aProjectPath, std::vector& // Verify we're saving for the correct project if( !projPath.IsSameAs( aProjectPath ) ) { - wxLogTrace( traceAutoSave, wxS("[history] pcb saver skipping - project path mismatch: %s vs %s"), - projPath, aProjectPath ); + wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - project path mismatch: %s vs %s" ), projPath, + aProjectPath ); return; } @@ -3454,8 +3434,7 @@ void BOARD::SaveToHistory( const wxString& aProjectPath, std::vector& // Derive relative path from project root. if( !boardPath.StartsWith( projPath ) ) { - wxLogTrace( traceAutoSave, wxS("[history] pcb saver skipping - board not under project: %s"), - boardPath ); + wxLogTrace( traceAutoSave, wxS( "[history] pcb saver skipping - board not under project: %s" ), boardPath ); return; // not under project } @@ -3479,11 +3458,10 @@ void BOARD::SaveToHistory( const wxString& aProjectPath, std::vector& // Save directly to history mirror path. pi->SaveBoard( dst.GetFullPath(), this, nullptr ); aFiles.push_back( dst.GetFullPath() ); - wxLogTrace( traceAutoSave, wxS("[history] pcb saver exported '%s'"), dst.GetFullPath() ); + wxLogTrace( traceAutoSave, wxS( "[history] pcb saver exported '%s'" ), dst.GetFullPath() ); } catch( const IO_ERROR& ioe ) { - wxLogTrace( traceAutoSave, wxS("[history] pcb saver export failed: %s"), - wxString::FromUTF8( ioe.What() ) ); + wxLogTrace( traceAutoSave, wxS( "[history] pcb saver export failed: %s" ), wxString::FromUTF8( ioe.What() ) ); } } diff --git a/pcbnew/dialogs/dialog_table_properties.cpp b/pcbnew/dialogs/dialog_table_properties.cpp index b1eea9785b..27c2127867 100644 --- a/pcbnew/dialogs/dialog_table_properties.cpp +++ b/pcbnew/dialogs/dialog_table_properties.cpp @@ -23,10 +23,13 @@ #include "dialog_table_properties.h" +#include + #include #include #include #include +#include #include #include #include @@ -56,20 +59,20 @@ DIALOG_TABLE_PROPERTIES::DIALOG_TABLE_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, P { m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); - m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() ); - m_grid->EnableEditing( true ); - m_grid->EnableGridLines( true ); - m_grid->EnableDragGridSize( false ); - m_grid->SetMargins( 0, 0 ); + m_grid->CreateGrid( m_table->GetRowCount(), m_table->GetColCount() ); + m_grid->EnableEditing( true ); + m_grid->EnableGridLines( true ); + m_grid->EnableDragGridSize( false ); + m_grid->SetMargins( 0, 0 ); m_grid->SetCellHighlightROPenWidth( 0 ); m_grid->EnableDragColMove( false ); - m_grid->EnableDragColSize( false ); - m_grid->SetColLabelSize( 0 ); + m_grid->EnableDragColSize( false ); + m_grid->SetColLabelSize( 0 ); m_grid->EnableDragRowMove( false ); - m_grid->EnableDragRowSize( false ); - m_grid->SetRowLabelSize( 0 ); - m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); + m_grid->EnableDragRowSize( false ); + m_grid->SetRowLabelSize( 0 ); + m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP ); m_gridSizer->Add( m_grid, 1, wxEXPAND, 5 ); m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) ); @@ -88,7 +91,8 @@ DIALOG_TABLE_PROPERTIES::DIALOG_TABLE_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, P } else { - attr->SetEditor( new GRID_CELL_STC_EDITOR( true, false, + attr->SetEditor( new GRID_CELL_STC_EDITOR( + true, false, [this, cell]( wxStyledTextEvent& aEvent, SCINTILLA_TRICKS* aScintillaTricks ) { aScintillaTricks->DoTextVarAutocomplete( @@ -128,6 +132,16 @@ DIALOG_TABLE_PROPERTIES::DIALOG_TABLE_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, P SetupStandardButtons(); Layout(); + // Add syntax help hyperlink + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _( "Syntax help" ), wxEmptyString, wxDefaultPosition, + wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _( "Show syntax help window" ) ); + m_gridSizer->Add( m_syntaxHelp, 0, wxTOP | wxBOTTOM | wxRIGHT | wxLEFT, 3 ); + + m_syntaxHelp->Bind( wxEVT_HYPERLINK, &DIALOG_TABLE_PROPERTIES::onSyntaxHelp, this ); + + m_helpWindow = nullptr; + // Now all widgets have the size fixed, call FinishDialogSettings finishDialogSettings(); } @@ -137,6 +151,9 @@ DIALOG_TABLE_PROPERTIES::~DIALOG_TABLE_PROPERTIES() { // Delete the GRID_TRICKS. m_grid->PopEventHandler( true ); + + if( m_helpWindow ) + m_helpWindow->Destroy(); } @@ -184,24 +201,25 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataToWindow() } } - CallAfter( [this]() - { - for( int row = 0; row < m_table->GetRowCount(); ++row ) - { - for( int col = 0; col < m_table->GetColCount(); ++col ) - { - PCB_TABLECELL* tableCell = m_table->GetCell( row, col ); + CallAfter( + [this]() + { + for( int row = 0; row < m_table->GetRowCount(); ++row ) + { + for( int col = 0; col < m_table->GetColCount(); ++col ) + { + PCB_TABLECELL* tableCell = m_table->GetCell( row, col ); - if( tableCell->IsSelected() ) - { - m_grid->SetGridCursor( row, col ); - m_grid->EnableCellEditControl(); - m_grid->ShowCellEditControl(); - return; - } - } - } - } ); + if( tableCell->IsSelected() ) + { + m_grid->SetGridCursor( row, col ); + m_grid->EnableCellEditControl(); + m_grid->ShowCellEditControl(); + return; + } + } + } + } ); sizeGridToTable(); @@ -417,7 +435,7 @@ bool DIALOG_TABLE_PROPERTIES::TransferDataFromWindow() void DIALOG_TABLE_PROPERTIES::sizeGridToTable() { - Layout(); // Make sure we get the current client size for the grid + Layout(); // Make sure we get the current client size for the grid wxSize availableGridSize = m_grid->GetClientSize(); @@ -443,3 +461,9 @@ void DIALOG_TABLE_PROPERTIES::onSize( wxSizeEvent& aEvent ) aEvent.Skip(); } + + +void DIALOG_TABLE_PROPERTIES::onSyntaxHelp( wxHyperlinkEvent& aEvent ) +{ + m_helpWindow = PCB_TEXT::ShowSyntaxHelp( this ); +} diff --git a/pcbnew/dialogs/dialog_table_properties.h b/pcbnew/dialogs/dialog_table_properties.h index dc2a4d0b4f..23ddbcd8b3 100644 --- a/pcbnew/dialogs/dialog_table_properties.h +++ b/pcbnew/dialogs/dialog_table_properties.h @@ -24,6 +24,8 @@ #ifndef DIALOG_TABLE_PROPERTIES_H #define DIALOG_TABLE_PROPERTIES_H +#include + #include #include @@ -31,6 +33,8 @@ class PCB_BASE_EDIT_FRAME; class PCB_TABLE; class WX_GRID; +class HTML_MESSAGE_BOX; +class wxHyperlinkCtrl; class DIALOG_TABLE_PROPERTIES : public DIALOG_TABLE_PROPERTIES_BASE @@ -49,14 +53,19 @@ private: void onHeaderChecked( wxCommandEvent& aEvent ) override; void onSize( wxSizeEvent& aEvent ) override; + void onSyntaxHelp( wxHyperlinkEvent& aEvent ); + private: PCB_BASE_EDIT_FRAME* m_frame; PCB_TABLE* m_table; - WX_GRID* m_grid; + WX_GRID* m_grid; - UNIT_BINDER m_borderWidth; - UNIT_BINDER m_separatorsWidth; + UNIT_BINDER m_borderWidth; + UNIT_BINDER m_separatorsWidth; + + wxHyperlinkCtrl* m_syntaxHelp; + HTML_MESSAGE_BOX* m_helpWindow; }; diff --git a/pcbnew/dialogs/dialog_tablecell_properties.cpp b/pcbnew/dialogs/dialog_tablecell_properties.cpp index fe289edb2e..ac4cfee8c9 100644 --- a/pcbnew/dialogs/dialog_tablecell_properties.cpp +++ b/pcbnew/dialogs/dialog_tablecell_properties.cpp @@ -21,8 +21,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include #include +#include #include #include #include @@ -39,7 +42,7 @@ #include #include "dialog_tablecell_properties.h" -DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, +DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aFrame, std::vector aCells ) : DIALOG_TABLECELL_PROPERTIES_BASE( aFrame ), m_frame( aFrame ), @@ -63,10 +66,11 @@ DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* a // Without this setting, on Windows, some esoteric unicode chars create display issue // in a wxStyledTextCtrl. // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY - m_cellText->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE); + m_cellText->SetTechnology( wxSTC_TECHNOLOGY_DIRECTWRITE ); #endif - m_scintillaTricks = new SCINTILLA_TRICKS( m_cellText, wxT( "{}" ), false, + m_scintillaTricks = new SCINTILLA_TRICKS( + m_cellText, wxT( "{}" ), false, // onAcceptFn [this]( wxKeyEvent& aEvent ) { @@ -121,8 +125,9 @@ DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* a SetupStandardButtons(); Layout(); - Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), - nullptr, this ); + m_helpWindow = nullptr; + + Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), nullptr, this ); m_hAlignLeft->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this ); m_hAlignCenter->Bind( wxEVT_BUTTON, &DIALOG_TABLECELL_PROPERTIES::onHAlignButton, this ); @@ -137,10 +142,12 @@ DIALOG_TABLECELL_PROPERTIES::DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* a DIALOG_TABLECELL_PROPERTIES::~DIALOG_TABLECELL_PROPERTIES() { - Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), - nullptr, this ); + Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TABLECELL_PROPERTIES::OnCharHook ), nullptr, this ); delete m_scintillaTricks; + + if( m_helpWindow ) + m_helpWindow->Destroy(); } @@ -224,18 +231,18 @@ bool DIALOG_TABLECELL_PROPERTIES::TransferDataToWindow() switch( hAlign ) { - case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break; - case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break; - case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break; - case GR_TEXT_H_ALIGN_INDETERMINATE: break; + case GR_TEXT_H_ALIGN_LEFT: m_hAlignLeft->Check(); break; + case GR_TEXT_H_ALIGN_CENTER: m_hAlignCenter->Check(); break; + case GR_TEXT_H_ALIGN_RIGHT: m_hAlignRight->Check(); break; + case GR_TEXT_H_ALIGN_INDETERMINATE: break; } switch( vAlign ) { - case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break; - case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break; - case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break; - case GR_TEXT_V_ALIGN_INDETERMINATE: break; + case GR_TEXT_V_ALIGN_TOP: m_vAlignTop->Check(); break; + case GR_TEXT_V_ALIGN_CENTER: m_vAlignCenter->Check(); break; + case GR_TEXT_V_ALIGN_BOTTOM: m_vAlignBottom->Check(); break; + case GR_TEXT_V_ALIGN_INDETERMINATE: break; } } @@ -424,4 +431,17 @@ void DIALOG_TABLECELL_PROPERTIES::onEditTable( wxCommandEvent& aEvent ) m_returnValue = TABLECELL_PROPS_EDIT_TABLE; Close(); } +} + + +void DIALOG_TABLECELL_PROPERTIES::onSyntaxHelp( wxHyperlinkEvent& aEvent ) +{ + if( m_helpWindow ) + { + m_helpWindow->Raise(); + m_helpWindow->Show( true ); + return; + } + + m_helpWindow = PCB_TEXT::ShowSyntaxHelp( this ); } \ No newline at end of file diff --git a/pcbnew/dialogs/dialog_tablecell_properties.h b/pcbnew/dialogs/dialog_tablecell_properties.h index 75d7f41dfe..1301d72a28 100644 --- a/pcbnew/dialogs/dialog_tablecell_properties.h +++ b/pcbnew/dialogs/dialog_tablecell_properties.h @@ -24,6 +24,7 @@ #ifndef DIALOG_TABLECELL_PROPERTIES_H #define DIALOG_TABLECELL_PROPERTIES_H +#include #include #include @@ -34,6 +35,8 @@ class PCB_BASE_EDIT_FRAME; class PCB_TABLE; class PCB_TABLECELL; class SCINTILLA_TRICKS; +class HTML_MESSAGE_BOX; +class wxHyperlinkCtrl; class DIALOG_TABLECELL_PROPERTIES : public DIALOG_TABLECELL_PROPERTIES_BASE { @@ -46,8 +49,7 @@ public: TABLECELL_PROPS_EDIT_TABLE }; - DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aParentFrame, - std::vector aCells ); + DIALOG_TABLECELL_PROPERTIES( PCB_BASE_EDIT_FRAME* aParentFrame, std::vector aCells ); ~DIALOG_TABLECELL_PROPERTIES(); ///< @return the value depending on the way the dialog was closed. enum TABLECELL_PROPS_RETVALUE GetReturnValue() { return m_returnValue; } @@ -58,8 +60,8 @@ private: void onHAlignButton( wxCommandEvent& aEvent ); void onVAlignButton( wxCommandEvent& aEvent ); - void onTextSize( wxCommandEvent &aEvent ) override; - void onAutoTextThickness( wxCommandEvent &aEvent ) override; + void onTextSize( wxCommandEvent& aEvent ) override; + void onAutoTextThickness( wxCommandEvent& aEvent ) override; void onBoldToggle( wxCommandEvent& aEvent ) override; void onEditTable( wxCommandEvent& aEvent ) override; @@ -68,21 +70,25 @@ private: void OnSystemColourChanged( wxSysColourChangedEvent& event ); void UpdateTheme( void ); -private: - PCB_BASE_EDIT_FRAME* m_frame; - PCB_TABLE* m_table; - std::vector m_cells; + void onSyntaxHelp( wxHyperlinkEvent& aEvent ) override; - UNIT_BINDER m_textHeight; - UNIT_BINDER m_textWidth; - UNIT_BINDER m_textThickness; - UNIT_BINDER m_marginLeft; - UNIT_BINDER m_marginTop; - UNIT_BINDER m_marginRight; - UNIT_BINDER m_marginBottom; - - wxStyledTextCtrl* m_cellText; - SCINTILLA_TRICKS* m_scintillaTricks; +private: + PCB_BASE_EDIT_FRAME* m_frame; + PCB_TABLE* m_table; + std::vector m_cells; + + UNIT_BINDER m_textHeight; + UNIT_BINDER m_textWidth; + UNIT_BINDER m_textThickness; + UNIT_BINDER m_marginLeft; + UNIT_BINDER m_marginTop; + UNIT_BINDER m_marginRight; + UNIT_BINDER m_marginBottom; + + wxStyledTextCtrl* m_cellText; + SCINTILLA_TRICKS* m_scintillaTricks; + + HTML_MESSAGE_BOX* m_helpWindow; enum TABLECELL_PROPS_RETVALUE m_returnValue; // the option that closed the dialog }; diff --git a/pcbnew/dialogs/dialog_tablecell_properties_base.cpp b/pcbnew/dialogs/dialog_tablecell_properties_base.cpp index 8312280622..950fcac5f2 100644 --- a/pcbnew/dialogs/dialog_tablecell_properties_base.cpp +++ b/pcbnew/dialogs/dialog_tablecell_properties_base.cpp @@ -13,299 +13,343 @@ /////////////////////////////////////////////////////////////////////////// -DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +DIALOG_TABLECELL_PROPERTIES_BASE::DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, + const wxString& title, const wxPoint& pos, + const wxSize& size, long style ) : + DIALOG_SHIM( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bMainSizer; - bMainSizer = new wxBoxSizer( wxVERTICAL ); - - m_infoBar = new WX_INFOBAR( this ); - m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); - m_infoBar->SetEffectDuration( 500 ); - m_infoBar->Hide(); - - bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 ); - - wxBoxSizer* bSizer7; - bSizer7 = new wxBoxSizer( wxHORIZONTAL ); + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxVERTICAL ); + + m_infoBar = new WX_INFOBAR( this ); + m_infoBar->SetShowHideEffects( wxSHOW_EFFECT_NONE, wxSHOW_EFFECT_NONE ); + m_infoBar->SetEffectDuration( 500 ); + m_infoBar->Hide(); + + bMainSizer->Add( m_infoBar, 0, wxEXPAND | wxBOTTOM, 5 ); + + wxBoxSizer* bSizer7; + bSizer7 = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer8; + bSizer8 = new wxBoxSizer( wxVERTICAL ); + + m_cellTextLabel = new wxStaticText( this, wxID_ANY, _( "Cell contents:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_cellTextLabel->Wrap( -1 ); + bSizer8->Add( m_cellTextLabel, 0, wxTOP | wxRIGHT | wxLEFT, 5 ); + + m_cellTextCtrl = + new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString ); + m_cellTextCtrl->SetUseTabs( false ); + m_cellTextCtrl->SetTabWidth( 4 ); + m_cellTextCtrl->SetIndent( 4 ); + m_cellTextCtrl->SetTabIndents( false ); + m_cellTextCtrl->SetBackSpaceUnIndents( false ); + m_cellTextCtrl->SetViewEOL( false ); + m_cellTextCtrl->SetViewWhiteSpace( false ); + m_cellTextCtrl->SetMarginWidth( 2, 0 ); + m_cellTextCtrl->SetIndentationGuides( false ); + m_cellTextCtrl->SetReadOnly( false ); + m_cellTextCtrl->SetMarginWidth( 1, 0 ); + m_cellTextCtrl->SetMarginWidth( 0, 0 ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS ); + m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT( "BLACK" ) ) ); + m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT( "WHITE" ) ) ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); + m_cellTextCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); + m_cellTextCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); + bSizer8->Add( m_cellTextCtrl, 1, wxEXPAND | wxALL, 2 ); - wxBoxSizer* bSizer8; - bSizer8 = new wxBoxSizer( wxVERTICAL ); - m_cellTextLabel = new wxStaticText( this, wxID_ANY, _("Cell contents:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_cellTextLabel->Wrap( -1 ); - bSizer8->Add( m_cellTextLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + bSizer7->Add( bSizer8, 1, wxEXPAND | wxTOP | wxRIGHT, 5 ); - m_cellTextCtrl = new wxStyledTextCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString ); - m_cellTextCtrl->SetUseTabs( false ); - m_cellTextCtrl->SetTabWidth( 4 ); - m_cellTextCtrl->SetIndent( 4 ); - m_cellTextCtrl->SetTabIndents( false ); - m_cellTextCtrl->SetBackSpaceUnIndents( false ); - m_cellTextCtrl->SetViewEOL( false ); - m_cellTextCtrl->SetViewWhiteSpace( false ); - m_cellTextCtrl->SetMarginWidth( 2, 0 ); - m_cellTextCtrl->SetIndentationGuides( false ); - m_cellTextCtrl->SetReadOnly( false ); - m_cellTextCtrl->SetMarginWidth( 1, 0 ); - m_cellTextCtrl->SetMarginWidth( 0, 0 ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDER, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPEN, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEREND, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUS ); - m_cellTextCtrl->MarkerSetBackground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("BLACK") ) ); - m_cellTextCtrl->MarkerSetForeground( wxSTC_MARKNUM_FOLDEROPENMID, wxColour( wxT("WHITE") ) ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->MarkerDefine( wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_EMPTY ); - m_cellTextCtrl->SetSelBackground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); - m_cellTextCtrl->SetSelForeground( true, wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ) ); - bSizer8->Add( m_cellTextCtrl, 1, wxEXPAND | wxALL, 2 ); + wxBoxSizer* bSizer9; + bSizer9 = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* bMargins; + bMargins = new wxBoxSizer( wxVERTICAL ); - bSizer7->Add( bSizer8, 1, wxEXPAND|wxTOP|wxRIGHT, 5 ); + wxGridBagSizer* gbFontSizer; + gbFontSizer = new wxGridBagSizer( 3, 5 ); + gbFontSizer->SetFlexibleDirection( wxBOTH ); + gbFontSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbFontSizer->SetEmptyCellSize( wxSize( -1, 5 ) ); - wxBoxSizer* bSizer9; - bSizer9 = new wxBoxSizer( wxVERTICAL ); + m_fontLabel = new wxStaticText( this, wxID_ANY, _( "Font:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_fontLabel->Wrap( -1 ); + gbFontSizer->Add( m_fontLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxLEFT, 1 ); - wxBoxSizer* bMargins; - bMargins = new wxBoxSizer( wxVERTICAL ); + wxString m_fontCtrlChoices[] = { _( "KiCad Font" ) }; + int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString ); + m_fontCtrl = new FONT_CHOICE( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, + m_fontCtrlChoices, 0 ); + m_fontCtrl->SetSelection( 0 ); + gbFontSizer->Add( m_fontCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 ); - wxGridBagSizer* gbFontSizer; - gbFontSizer = new wxGridBagSizer( 3, 5 ); - gbFontSizer->SetFlexibleDirection( wxBOTH ); - gbFontSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbFontSizer->SetEmptyCellSize( wxSize( -1,5 ) ); - m_fontLabel = new wxStaticText( this, wxID_ANY, _("Font:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_fontLabel->Wrap( -1 ); - gbFontSizer->Add( m_fontLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 1 ); + gbFontSizer->AddGrowableCol( 1 ); - wxString m_fontCtrlChoices[] = { _("KiCad Font") }; - int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString ); - m_fontCtrl = new FONT_CHOICE( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, m_fontCtrlChoices, 0 ); - m_fontCtrl->SetSelection( 0 ); - gbFontSizer->Add( m_fontCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 3 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + bMargins->Add( gbFontSizer, 0, wxEXPAND | wxBOTTOM, 5 ); + wxFlexGridSizer* fgTextStyleSizer; + fgTextStyleSizer = new wxFlexGridSizer( 0, 2, 5, 5 ); + fgTextStyleSizer->SetFlexibleDirection( wxBOTH ); + fgTextStyleSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbFontSizer->AddGrowableCol( 1 ); + wxBoxSizer* hAlignButtons; + hAlignButtons = new wxBoxSizer( wxHORIZONTAL ); - bMargins->Add( gbFontSizer, 0, wxEXPAND|wxBOTTOM, 5 ); + m_bold = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + hAlignButtons->Add( m_bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxFlexGridSizer* fgTextStyleSizer; - fgTextStyleSizer = new wxFlexGridSizer( 0, 2, 5, 5 ); - fgTextStyleSizer->SetFlexibleDirection( wxBOTH ); - fgTextStyleSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + m_italic = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + hAlignButtons->Add( m_italic, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxBoxSizer* hAlignButtons; - hAlignButtons = new wxBoxSizer( wxHORIZONTAL ); + m_separator0 = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_separator0->Enable( false ); - m_bold = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - hAlignButtons->Add( m_bold, 0, wxALIGN_CENTER_VERTICAL, 5 ); + hAlignButtons->Add( m_separator0, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_italic = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - hAlignButtons->Add( m_italic, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_hAlignLeft = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignLeft->SetToolTip( _( "Align left" ) ); - m_separator0 = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_separator0->Enable( false ); + hAlignButtons->Add( m_hAlignLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_separator0, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_hAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignCenter->SetToolTip( _( "Align horizontal center" ) ); - m_hAlignLeft = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignLeft->SetToolTip( _("Align left") ); + hAlignButtons->Add( m_hAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_hAlignLeft, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_hAlignRight = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_hAlignRight->SetToolTip( _( "Align right" ) ); - m_hAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignCenter->SetToolTip( _("Align horizontal center") ); + hAlignButtons->Add( m_hAlignRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_hAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_separator1 = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_separator1->Enable( false ); - m_hAlignRight = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_hAlignRight->SetToolTip( _("Align right") ); + hAlignButtons->Add( m_separator1, 0, wxALL, 5 ); - hAlignButtons->Add( m_hAlignRight, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_vAlignTop = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignTop->SetToolTip( _( "Align top" ) ); - m_separator1 = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_separator1->Enable( false ); + hAlignButtons->Add( m_vAlignTop, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_separator1, 0, wxALL, 5 ); + m_vAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignCenter->SetToolTip( _( "Align vertical center" ) ); - m_vAlignTop = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignTop->SetToolTip( _("Align top") ); + hAlignButtons->Add( m_vAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_vAlignTop, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_vAlignBottom = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_vAlignBottom->SetToolTip( _( "Align bottom" ) ); - m_vAlignCenter = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignCenter->SetToolTip( _("Align vertical center") ); + hAlignButtons->Add( m_vAlignBottom, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_vAlignCenter, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_vAlignBottom = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_vAlignBottom->SetToolTip( _("Align bottom") ); + fgTextStyleSizer->Add( hAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); - hAlignButtons->Add( m_vAlignBottom, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bMargins->Add( fgTextStyleSizer, 1, wxEXPAND, 5 ); - fgTextStyleSizer->Add( hAlignButtons, 0, wxALIGN_CENTER_VERTICAL, 5 ); + wxGridBagSizer* gbSizer1; + gbSizer1 = new wxGridBagSizer( 3, 5 ); + gbSizer1->SetFlexibleDirection( wxBOTH ); + gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + gbSizer1->SetEmptyCellSize( wxSize( -1, 8 ) ); + m_SizeXLabel = new wxStaticText( this, wxID_ANY, _( "Text width:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeXLabel->Wrap( -1 ); + m_SizeXLabel->SetToolTip( _( "Text width" ) ); - bMargins->Add( fgTextStyleSizer, 1, wxEXPAND, 5 ); + gbSizer1->Add( m_SizeXLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); - wxGridBagSizer* gbSizer1; - gbSizer1 = new wxGridBagSizer( 3, 5 ); - gbSizer1->SetFlexibleDirection( wxBOTH ); - gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - gbSizer1->SetEmptyCellSize( wxSize( -1,8 ) ); + m_SizeXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_SizeXCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 ); - m_SizeXLabel = new wxStaticText( this, wxID_ANY, _("Text width:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_SizeXLabel->Wrap( -1 ); - m_SizeXLabel->SetToolTip( _("Text width") ); + m_SizeXUnits = new wxStaticText( this, wxID_ANY, _( "unit" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeXUnits->Wrap( -1 ); + gbSizer1->Add( m_SizeXUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); - gbSizer1->Add( m_SizeXLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + m_SizeYLabel = new wxStaticText( this, wxID_ANY, _( "Text height:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeYLabel->Wrap( -1 ); + m_SizeYLabel->SetToolTip( _( "Text height" ) ); - m_SizeXCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - gbSizer1->Add( m_SizeXCtrl, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + gbSizer1->Add( m_SizeYLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); - m_SizeXUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); - m_SizeXUnits->Wrap( -1 ); - gbSizer1->Add( m_SizeXUnits, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + m_SizeYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_SizeYCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 ); - m_SizeYLabel = new wxStaticText( this, wxID_ANY, _("Text height:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_SizeYLabel->Wrap( -1 ); - m_SizeYLabel->SetToolTip( _("Text height") ); + m_SizeYUnits = new wxStaticText( this, wxID_ANY, _( "unit" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_SizeYUnits->Wrap( -1 ); + gbSizer1->Add( m_SizeYUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); - gbSizer1->Add( m_SizeYLabel, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + m_ThicknessLabel = new wxStaticText( this, wxID_ANY, _( "Thickness:" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessLabel->Wrap( -1 ); + m_ThicknessLabel->SetToolTip( _( "Text thickness" ) ); - m_SizeYCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - gbSizer1->Add( m_SizeYCtrl, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + gbSizer1->Add( m_ThicknessLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); - m_SizeYUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); - m_SizeYUnits->Wrap( -1 ); - gbSizer1->Add( m_SizeYUnits, wxGBPosition( 1, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + m_ThicknessCtrl = + new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + gbSizer1->Add( m_ThicknessCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 ); - m_ThicknessLabel = new wxStaticText( this, wxID_ANY, _("Thickness:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_ThicknessLabel->Wrap( -1 ); - m_ThicknessLabel->SetToolTip( _("Text thickness") ); + m_ThicknessUnits = new wxStaticText( this, wxID_ANY, _( "unit" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_ThicknessUnits->Wrap( -1 ); + gbSizer1->Add( m_ThicknessUnits, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); - gbSizer1->Add( m_ThicknessLabel, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 4 ); + m_autoTextThickness = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, + wxBU_AUTODRAW | wxBORDER_NONE ); + m_autoTextThickness->SetToolTip( _( "Adjust the text thickness" ) ); - m_ThicknessCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); - gbSizer1->Add( m_ThicknessCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxEXPAND, 5 ); + gbSizer1->Add( m_autoTextThickness, wxGBPosition( 2, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); - m_ThicknessUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 ); - m_ThicknessUnits->Wrap( -1 ); - gbSizer1->Add( m_ThicknessUnits, wxGBPosition( 2, 2 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); - m_autoTextThickness = new BITMAP_BUTTON( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|wxBORDER_NONE ); - m_autoTextThickness->SetToolTip( _("Adjust the text thickness") ); + bMargins->Add( gbSizer1, 0, wxEXPAND | wxTOP, 5 ); - gbSizer1->Add( m_autoTextThickness, wxGBPosition( 2, 3 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL, 5 ); + bMargins->Add( 0, 20, 0, wxEXPAND, 5 ); - bMargins->Add( gbSizer1, 0, wxEXPAND|wxTOP, 5 ); + wxGridSizer* gMarginsSizer; + gMarginsSizer = new wxGridSizer( 0, 3, 4, 2 ); + wxStaticText* marginsLabel; + marginsLabel = new wxStaticText( this, wxID_ANY, _( "Cell margins:" ), wxDefaultPosition, wxDefaultSize, 0 ); + marginsLabel->Wrap( -1 ); + gMarginsSizer->Add( marginsLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); - bMargins->Add( 0, 20, 0, wxEXPAND, 5 ); + m_marginTopCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginTopCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - wxGridSizer* gMarginsSizer; - gMarginsSizer = new wxGridSizer( 0, 3, 4, 2 ); + m_marginTopUnits = new wxStaticText( this, wxID_ANY, _( "mm" ), wxDefaultPosition, wxDefaultSize, 0 ); + m_marginTopUnits->Wrap( -1 ); + gMarginsSizer->Add( m_marginTopUnits, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 2 ); - wxStaticText* marginsLabel; - marginsLabel = new wxStaticText( this, wxID_ANY, _("Cell margins:"), wxDefaultPosition, wxDefaultSize, 0 ); - marginsLabel->Wrap( -1 ); - gMarginsSizer->Add( marginsLabel, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_marginLeftCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginLeftCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_marginTopCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginTopCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - m_marginTopUnits = new wxStaticText( this, wxID_ANY, _("mm"), wxDefaultPosition, wxDefaultSize, 0 ); - m_marginTopUnits->Wrap( -1 ); - gMarginsSizer->Add( m_marginTopUnits, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 2 ); + gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); - m_marginLeftCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginLeftCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_marginRightCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginRightCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); - m_marginRightCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginRightCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + m_marginBottomCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + gMarginsSizer->Add( m_marginBottomCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); - gMarginsSizer->Add( 0, 0, 1, wxEXPAND, 5 ); + bMargins->Add( gMarginsSizer, 0, wxEXPAND, 5 ); - m_marginBottomCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - gMarginsSizer->Add( m_marginBottomCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 ); + bSizer9->Add( bMargins, 1, wxEXPAND | wxALL, 10 ); - bMargins->Add( gMarginsSizer, 0, wxEXPAND, 5 ); + bSizer7->Add( bSizer9, 1, wxEXPAND, 5 ); - bSizer9->Add( bMargins, 1, wxEXPAND|wxALL, 10 ); + bMainSizer->Add( bSizer7, 1, wxEXPAND | wxLEFT, 5 ); - bSizer7->Add( bSizer9, 1, wxEXPAND, 5 ); + wxBoxSizer* bButtons; + bButtons = new wxBoxSizer( wxHORIZONTAL ); + m_editTable = new wxButton( this, wxID_ANY, _( "Edit Table..." ), wxDefaultPosition, wxDefaultSize, 0 ); + m_editTable->SetToolTip( _( "Edit table properties and cell contents" ) ); - bMainSizer->Add( bSizer7, 1, wxEXPAND|wxLEFT, 5 ); + bButtons->Add( m_editTable, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10 ); - wxBoxSizer* bButtons; - bButtons = new wxBoxSizer( wxHORIZONTAL ); + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _( "Syntax help" ), wxEmptyString, wxDefaultPosition, + wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _( "Show syntax help window" ) ); - m_editTable = new wxButton( this, wxID_ANY, _("Edit Table..."), wxDefaultPosition, wxDefaultSize, 0 ); - m_editTable->SetToolTip( _("Edit table properties and cell contents") ); + bButtons->Add( m_syntaxHelp, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10 ); - bButtons->Add( m_editTable, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 10 ); + bButtons->Add( 0, 0, 1, wxEXPAND, 5 ); - bButtons->Add( 0, 0, 1, wxEXPAND, 5 ); + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); - m_sdbSizer1 = new wxStdDialogButtonSizer(); - m_sdbSizer1OK = new wxButton( this, wxID_OK ); - m_sdbSizer1->AddButton( m_sdbSizer1OK ); - m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); - m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); - m_sdbSizer1->Realize(); + bButtons->Add( m_sdbSizer1, 0, wxEXPAND | wxALL, 5 ); - bButtons->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 ); + bMainSizer->Add( bButtons, 0, wxEXPAND, 5 ); - bMainSizer->Add( bButtons, 0, wxEXPAND, 5 ); + this->SetSizer( bMainSizer ); + this->Layout(); + bMainSizer->Fit( this ); - this->SetSizer( bMainSizer ); - this->Layout(); - bMainSizer->Fit( this ); - - // Connect Events - m_bold->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBoldToggle ), NULL, this ); - m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); - m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); - m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); - m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); - m_ThicknessCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); - m_autoTextThickness->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onAutoTextThickness ), NULL, this ); - m_editTable->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); + // Connect Events + m_bold->Connect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBoldToggle ), NULL, this ); + m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); + m_SizeXCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); + m_SizeYCtrl->Connect( wxEVT_COMMAND_TEXT_ENTER, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_ThicknessCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); + m_autoTextThickness->Connect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onAutoTextThickness ), NULL, + this ); + m_editTable->Connect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); + m_syntaxHelp->Connect( wxEVT_COMMAND_HYPERLINK, + wxHyperlinkEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onSyntaxHelp ), NULL, this ); } DIALOG_TABLECELL_PROPERTIES_BASE::~DIALOG_TABLECELL_PROPERTIES_BASE() { - // Disconnect Events - m_bold->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBoldToggle ), NULL, this ); - m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); - m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); - m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); - m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); - m_ThicknessCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); - m_autoTextThickness->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onAutoTextThickness ), NULL, this ); - m_editTable->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); - + // Disconnect Events + m_bold->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onBoldToggle ), NULL, this ); + m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); + m_SizeXCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onTextSize ), NULL, this ); + m_SizeYCtrl->Disconnect( wxEVT_COMMAND_TEXT_ENTER, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::OnOkClick ), NULL, this ); + m_ThicknessCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onThickness ), NULL, this ); + m_autoTextThickness->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onAutoTextThickness ), + NULL, this ); + m_editTable->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onEditTable ), NULL, this ); + m_syntaxHelp->Disconnect( wxEVT_COMMAND_HYPERLINK, + wxHyperlinkEventHandler( DIALOG_TABLECELL_PROPERTIES_BASE::onSyntaxHelp ), NULL, this ); } diff --git a/pcbnew/dialogs/dialog_tablecell_properties_base.h b/pcbnew/dialogs/dialog_tablecell_properties_base.h index c24944aa8a..7d4d63d507 100644 --- a/pcbnew/dialogs/dialog_tablecell_properties_base.h +++ b/pcbnew/dialogs/dialog_tablecell_properties_base.h @@ -31,6 +31,7 @@ class WX_INFOBAR; #include #include #include +#include #include #include @@ -41,58 +42,59 @@ class WX_INFOBAR; /////////////////////////////////////////////////////////////////////////////// class DIALOG_TABLECELL_PROPERTIES_BASE : public DIALOG_SHIM { - private: +private: +protected: + WX_INFOBAR* m_infoBar; + wxStaticText* m_cellTextLabel; + wxStyledTextCtrl* m_cellTextCtrl; + wxStaticText* m_fontLabel; + FONT_CHOICE* m_fontCtrl; + BITMAP_BUTTON* m_bold; + BITMAP_BUTTON* m_italic; + BITMAP_BUTTON* m_separator0; + BITMAP_BUTTON* m_hAlignLeft; + BITMAP_BUTTON* m_hAlignCenter; + BITMAP_BUTTON* m_hAlignRight; + BITMAP_BUTTON* m_separator1; + BITMAP_BUTTON* m_vAlignTop; + BITMAP_BUTTON* m_vAlignCenter; + BITMAP_BUTTON* m_vAlignBottom; + wxStaticText* m_SizeXLabel; + wxTextCtrl* m_SizeXCtrl; + wxStaticText* m_SizeXUnits; + wxStaticText* m_SizeYLabel; + wxTextCtrl* m_SizeYCtrl; + wxStaticText* m_SizeYUnits; + wxStaticText* m_ThicknessLabel; + wxTextCtrl* m_ThicknessCtrl; + wxStaticText* m_ThicknessUnits; + BITMAP_BUTTON* m_autoTextThickness; + wxTextCtrl* m_marginTopCtrl; + wxStaticText* m_marginTopUnits; + wxTextCtrl* m_marginLeftCtrl; + wxTextCtrl* m_marginRightCtrl; + wxTextCtrl* m_marginBottomCtrl; + wxButton* m_editTable; + wxHyperlinkCtrl* m_syntaxHelp; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; - protected: - WX_INFOBAR* m_infoBar; - wxStaticText* m_cellTextLabel; - wxStyledTextCtrl* m_cellTextCtrl; - wxStaticText* m_fontLabel; - FONT_CHOICE* m_fontCtrl; - BITMAP_BUTTON* m_bold; - BITMAP_BUTTON* m_italic; - BITMAP_BUTTON* m_separator0; - BITMAP_BUTTON* m_hAlignLeft; - BITMAP_BUTTON* m_hAlignCenter; - BITMAP_BUTTON* m_hAlignRight; - BITMAP_BUTTON* m_separator1; - BITMAP_BUTTON* m_vAlignTop; - BITMAP_BUTTON* m_vAlignCenter; - BITMAP_BUTTON* m_vAlignBottom; - wxStaticText* m_SizeXLabel; - wxTextCtrl* m_SizeXCtrl; - wxStaticText* m_SizeXUnits; - wxStaticText* m_SizeYLabel; - wxTextCtrl* m_SizeYCtrl; - wxStaticText* m_SizeYUnits; - wxStaticText* m_ThicknessLabel; - wxTextCtrl* m_ThicknessCtrl; - wxStaticText* m_ThicknessUnits; - BITMAP_BUTTON* m_autoTextThickness; - wxTextCtrl* m_marginTopCtrl; - wxStaticText* m_marginTopUnits; - wxTextCtrl* m_marginLeftCtrl; - wxTextCtrl* m_marginRightCtrl; - wxTextCtrl* m_marginBottomCtrl; - wxButton* m_editTable; - wxStdDialogButtonSizer* m_sdbSizer1; - wxButton* m_sdbSizer1OK; - wxButton* m_sdbSizer1Cancel; - - // Virtual event handlers, override them in your derived class - virtual void onBoldToggle( wxCommandEvent& event ) { event.Skip(); } - virtual void onTextSize( wxCommandEvent& event ) { event.Skip(); } - virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } - virtual void onThickness( wxCommandEvent& event ) { event.Skip(); } - virtual void onAutoTextThickness( wxCommandEvent& event ) { event.Skip(); } - virtual void onEditTable( wxCommandEvent& event ) { event.Skip(); } + // Virtual event handlers, override them in your derived class + virtual void onBoldToggle( wxCommandEvent& event ) { event.Skip(); } + virtual void onTextSize( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onThickness( wxCommandEvent& event ) { event.Skip(); } + virtual void onAutoTextThickness( wxCommandEvent& event ) { event.Skip(); } + virtual void onEditTable( wxCommandEvent& event ) { event.Skip(); } + virtual void onSyntaxHelp( wxHyperlinkEvent& event ) { event.Skip(); } - public: - - DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Table Cell Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - - ~DIALOG_TABLECELL_PROPERTIES_BASE(); +public: + DIALOG_TABLECELL_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, + const wxString& title = _( "Table Cell Properties" ), + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), + long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ); + ~DIALOG_TABLECELL_PROPERTIES_BASE(); }; - diff --git a/pcbnew/dialogs/dialog_text_properties.cpp b/pcbnew/dialogs/dialog_text_properties.cpp index 20d3537cb2..3052f12aad 100644 --- a/pcbnew/dialogs/dialog_text_properties.cpp +++ b/pcbnew/dialogs/dialog_text_properties.cpp @@ -25,9 +25,11 @@ #include "dialog_text_properties.h" #include +#include #include #include +#include #include #include #include @@ -72,10 +74,11 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC // Without this setting, on Windows, some esoteric unicode chars create display issue // in a wxStyledTextCtrl. // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY - m_MultiLineText->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE); + m_MultiLineText->SetTechnology( wxSTC_TECHNOLOGY_DIRECTWRITE ); #endif - m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false, + m_scintillaTricks = new SCINTILLA_TRICKS( + m_MultiLineText, wxT( "{}" ), false, // onAcceptFn [this]( wxKeyEvent& aEvent ) { @@ -97,6 +100,16 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC m_MultiLineText->SetScrollWidth( 1 ); m_MultiLineText->SetScrollWidthTracking( true ); + // Add syntax help hyperlink + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _( "Syntax help" ), wxEmptyString, wxDefaultPosition, + wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _( "Show syntax help window" ) ); + m_MultiLineSizer->Add( m_syntaxHelp, 0, wxBOTTOM | wxRIGHT | wxLEFT, 3 ); + + m_syntaxHelp->Bind( wxEVT_HYPERLINK, &DIALOG_TEXT_PROPERTIES::onSyntaxHelp, this ); + + m_helpWindow = nullptr; + if( m_item->GetParentFootprint() ) { m_PositionXLabel->SetLabel( _( "Offset X:" ) ); @@ -135,21 +148,9 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC // Do not allow locking items in the footprint editor m_cbLocked->Show( false ); - m_tabOrder = { - m_SingleLineText, - m_LayerSelectionCtrl, - m_SizeXCtrl, - m_SizeYCtrl, - m_ThicknessCtrl, - m_Visible, - m_cbKnockout, - m_KeepUpright, - m_PositionXCtrl, - m_PositionYCtrl, - m_OrientCtrl, - m_sdbSizerOK, - m_sdbSizerCancel - }; + m_tabOrder = { m_SingleLineText, m_LayerSelectionCtrl, m_SizeXCtrl, m_SizeYCtrl, m_ThicknessCtrl, + m_Visible, m_cbKnockout, m_KeepUpright, m_PositionXCtrl, m_PositionYCtrl, + m_OrientCtrl, m_sdbSizerOK, m_sdbSizerCancel }; } else { @@ -162,20 +163,9 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC m_KeepUpright->Show( false ); m_statusLine->Show( false ); - m_tabOrder = { - m_MultiLineText, - m_cbLocked, - m_LayerSelectionCtrl, - m_SizeXCtrl, - m_SizeYCtrl, - m_ThicknessCtrl, - m_cbKnockout, - m_PositionXCtrl, - m_PositionYCtrl, - m_OrientCtrl, - m_sdbSizerOK, - m_sdbSizerCancel - }; + m_tabOrder = { m_MultiLineText, m_cbLocked, m_LayerSelectionCtrl, m_SizeXCtrl, + m_SizeYCtrl, m_ThicknessCtrl, m_cbKnockout, m_PositionXCtrl, + m_PositionYCtrl, m_OrientCtrl, m_sdbSizerOK, m_sdbSizerCancel }; } m_bold->SetIsCheckButton(); @@ -238,8 +228,7 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set, // so we have to listen to wxEVT_CHAR_HOOK events instead. - Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ), - nullptr, this ); + Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ), nullptr, this ); finishDialogSettings(); } @@ -247,10 +236,12 @@ DIALOG_TEXT_PROPERTIES::DIALOG_TEXT_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PC DIALOG_TEXT_PROPERTIES::~DIALOG_TEXT_PROPERTIES() { - Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ), - nullptr, this ); + Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXT_PROPERTIES::OnCharHook ), nullptr, this ); delete m_scintillaTricks; + + if( m_helpWindow ) + m_helpWindow->Destroy(); } @@ -312,12 +303,10 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow() if( parentFP ) { - m_statusLine->SetLabel( wxString::Format( _( "Footprint %s (%s), %s, rotated %.1f deg"), - parentFP->GetReference(), - parentFP->GetValue(), - parentFP->IsFlipped() ? _( "back side (mirrored)" ) - : _( "front side" ), - parentFP->GetOrientation().AsDegrees() ) ); + m_statusLine->SetLabel( wxString::Format( + _( "Footprint %s (%s), %s, rotated %.1f deg" ), parentFP->GetReference(), parentFP->GetValue(), + parentFP->IsFlipped() ? _( "back side (mirrored)" ) : _( "front side" ), + parentFP->GetOrientation().AsDegrees() ) ); } else { @@ -357,20 +346,20 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow() m_bold->Check( m_item->IsBold() ); m_italic->Check( m_item->IsItalic() ); - switch ( m_item->GetHorizJustify() ) + switch( m_item->GetHorizJustify() ) { - case GR_TEXT_H_ALIGN_LEFT: m_alignLeft->Check( true ); break; - case GR_TEXT_H_ALIGN_CENTER: m_alignCenter->Check( true ); break; - case GR_TEXT_H_ALIGN_RIGHT: m_alignRight->Check( true ); break; - case GR_TEXT_H_ALIGN_INDETERMINATE: break; + case GR_TEXT_H_ALIGN_LEFT: m_alignLeft->Check( true ); break; + case GR_TEXT_H_ALIGN_CENTER: m_alignCenter->Check( true ); break; + case GR_TEXT_H_ALIGN_RIGHT: m_alignRight->Check( true ); break; + case GR_TEXT_H_ALIGN_INDETERMINATE: break; } - switch ( m_item->GetVertJustify() ) + switch( m_item->GetVertJustify() ) { - case GR_TEXT_V_ALIGN_BOTTOM: m_valignBottom->Check( true ); break; - case GR_TEXT_V_ALIGN_CENTER: m_valignCenter->Check( true ); break; - case GR_TEXT_V_ALIGN_TOP: m_valignTop->Check( true ); break; - case GR_TEXT_V_ALIGN_INDETERMINATE: break; + case GR_TEXT_V_ALIGN_BOTTOM: m_valignBottom->Check( true ); break; + case GR_TEXT_V_ALIGN_CENTER: m_valignCenter->Check( true ); break; + case GR_TEXT_V_ALIGN_TOP: m_valignTop->Check( true ); break; + case GR_TEXT_V_ALIGN_INDETERMINATE: break; } m_mirrored->Check( m_item->IsMirrored() ); @@ -382,7 +371,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow() } -void DIALOG_TEXT_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) +void DIALOG_TEXT_PROPERTIES::onFontSelected( wxCommandEvent& aEvent ) { if( KIFONT::FONT::IsStroke( aEvent.GetString() ) ) { @@ -393,7 +382,7 @@ void DIALOG_TEXT_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) int thickness = m_thickness.GetValue(); m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) ) - < abs( thickness - GetPenSizeForNormal( textSize ) ) ); + < abs( thickness - GetPenSizeForNormal( textSize ) ) ); } else { @@ -403,7 +392,7 @@ void DIALOG_TEXT_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) } -void DIALOG_TEXT_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent ) +void DIALOG_TEXT_PROPERTIES::onBoldToggle( wxCommandEvent& aEvent ) { int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() ); @@ -442,7 +431,7 @@ void DIALOG_TEXT_PROPERTIES::onThickness( wxCommandEvent& event ) int thickness = m_thickness.GetValue(); m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) ) - < abs( thickness - GetPenSizeForNormal( textSize ) ) ); + < abs( thickness - GetPenSizeForNormal( textSize ) ) ); } @@ -544,8 +533,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow() if( m_fontCtrl->HaveFontSelection() ) { - m_item->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), - m_italic->IsChecked() ) ); + m_item->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), m_italic->IsChecked() ) ); } m_item->SetTextSize( VECTOR2I( m_textWidth.GetValue(), m_textHeight.GetValue() ) ); @@ -589,7 +577,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow() m_item->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); if( m_valignBottom->IsChecked() ) - m_item->SetVertJustify ( GR_TEXT_V_ALIGN_BOTTOM ); + m_item->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); else if( m_valignCenter->IsChecked() ) m_item->SetVertJustify( GR_TEXT_V_ALIGN_CENTER ); else @@ -611,3 +599,9 @@ void DIALOG_TEXT_PROPERTIES::onMultiLineTCLostFocus( wxFocusEvent& event ) event.Skip(); } + + +void DIALOG_TEXT_PROPERTIES::onSyntaxHelp( wxHyperlinkEvent& aEvent ) +{ + m_helpWindow = PCB_TEXT::ShowSyntaxHelp( this ); +} diff --git a/pcbnew/dialogs/dialog_text_properties.h b/pcbnew/dialogs/dialog_text_properties.h index 61a9fd1dee..ff23150e87 100644 --- a/pcbnew/dialogs/dialog_text_properties.h +++ b/pcbnew/dialogs/dialog_text_properties.h @@ -24,6 +24,7 @@ #ifndef DIALOG_TEXT_PROPERTIES_H #define DIALOG_TEXT_PROPERTIES_H +#include #include #include @@ -35,6 +36,8 @@ class BOARD_ITEM; class EDA_TEXT; class PCB_TEXT; class SCINTILLA_TRICKS; +class HTML_MESSAGE_BOX; +class wxHyperlinkCtrl; class DIALOG_TEXT_PROPERTIES : public DIALOG_TEXT_PROPERTIES_BASE @@ -51,30 +54,34 @@ public: virtual void OnSetFocusText( wxFocusEvent& event ) override; private: - void onFontSelected( wxCommandEvent &aEvent ) override; - void onBoldToggle( wxCommandEvent &aEvent ) override; - void onAlignButton( wxCommandEvent &aEvent ) override; - void onValignButton( wxCommandEvent &aEvent ) override; - void onThickness( wxCommandEvent &aEvent ) override; - void onTextSize( wxCommandEvent &aEvent ) override; - void onAutoTextThickness( wxCommandEvent &aEvent ) override; + void onFontSelected( wxCommandEvent& aEvent ) override; + void onBoldToggle( wxCommandEvent& aEvent ) override; + void onAlignButton( wxCommandEvent& aEvent ) override; + void onValignButton( wxCommandEvent& aEvent ) override; + void onThickness( wxCommandEvent& aEvent ) override; + void onTextSize( wxCommandEvent& aEvent ) override; + void onAutoTextThickness( wxCommandEvent& aEvent ) override; bool TransferDataToWindow() override; bool TransferDataFromWindow() override; void onMultiLineTCLostFocus( wxFocusEvent& event ) override; + void onSyntaxHelp( wxHyperlinkEvent& aEvent ); + private: PCB_BASE_EDIT_FRAME* m_frame; PCB_TEXT* m_item; - UNIT_BINDER m_textWidth; - UNIT_BINDER m_textHeight; - UNIT_BINDER m_thickness; - UNIT_BINDER m_posX; - UNIT_BINDER m_posY; - UNIT_BINDER m_orientation; // rotation in degrees + UNIT_BINDER m_textWidth; + UNIT_BINDER m_textHeight; + UNIT_BINDER m_thickness; + UNIT_BINDER m_posX; + UNIT_BINDER m_posY; + UNIT_BINDER m_orientation; // rotation in degrees - SCINTILLA_TRICKS* m_scintillaTricks; + SCINTILLA_TRICKS* m_scintillaTricks; + wxHyperlinkCtrl* m_syntaxHelp; + HTML_MESSAGE_BOX* m_helpWindow; }; diff --git a/pcbnew/dialogs/dialog_textbox_properties.cpp b/pcbnew/dialogs/dialog_textbox_properties.cpp index c50e6b189c..e8c7cbe9ae 100644 --- a/pcbnew/dialogs/dialog_textbox_properties.cpp +++ b/pcbnew/dialogs/dialog_textbox_properties.cpp @@ -23,8 +23,11 @@ #include "dialog_textbox_properties.h" +#include + #include #include +#include #include #include #include @@ -38,8 +41,7 @@ #include -DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, - PCB_TEXTBOX* aTextBox ) : +DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aParent, PCB_TEXTBOX* aTextBox ) : DIALOG_TEXTBOX_PROPERTIES_BASE( aParent ), m_frame( aParent ), m_textBox( aTextBox ), @@ -55,10 +57,11 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare // Without this setting, on Windows, some esoteric unicode chars create display issue // in a wxStyledTextCtrl. // for SetTechnology() info, see https://www.scintilla.org/ScintillaDoc.html#SCI_SETTECHNOLOGY - m_MultiLineText->SetTechnology(wxSTC_TECHNOLOGY_DIRECTWRITE); + m_MultiLineText->SetTechnology( wxSTC_TECHNOLOGY_DIRECTWRITE ); #endif - m_scintillaTricks = new SCINTILLA_TRICKS( m_MultiLineText, wxT( "{}" ), false, + m_scintillaTricks = new SCINTILLA_TRICKS( + m_MultiLineText, wxT( "{}" ), false, // onAcceptFn [this]( wxKeyEvent& aEvent ) { @@ -71,7 +74,7 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare // getTokensFn [this]( const wxString& xRef, wxArrayString* tokens ) { - m_frame->GetContextualTextVars( m_textBox, xRef, tokens ); + m_frame->GetContextualTextVars( m_textBox, xRef, tokens ); } ); } ); @@ -80,6 +83,16 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare m_MultiLineText->SetScrollWidth( 1 ); m_MultiLineText->SetScrollWidthTracking( true ); + // Add syntax help hyperlink + m_syntaxHelp = new wxHyperlinkCtrl( this, wxID_ANY, _( "Syntax help" ), wxEmptyString, wxDefaultPosition, + wxDefaultSize, wxHL_DEFAULT_STYLE ); + m_syntaxHelp->SetToolTip( _( "Show syntax help window" ) ); + m_MultiLineSizer->Add( m_syntaxHelp, 0, wxBOTTOM | wxRIGHT | wxLEFT, 3 ); + + m_syntaxHelp->Bind( wxEVT_HYPERLINK, &DIALOG_TEXTBOX_PROPERTIES::onSyntaxHelp, this ); + + m_helpWindow = nullptr; + if( m_textBox->GetParentFootprint() ) { // Do not allow locking items in the footprint editor @@ -142,28 +155,29 @@ DIALOG_TEXTBOX_PROPERTIES::DIALOG_TEXTBOX_PROPERTIES( PCB_BASE_EDIT_FRAME* aPare for( size_t ii = 0; ii < m_OrientCtrl->GetCount() && ii < 4; ++ii ) m_OrientCtrl->SetString( ii, wxString::Format( "%.1f", rot_list[ii] ) ); - for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames ) + for( const auto& [lineStyle, lineStyleDesc] : lineTypeNames ) m_borderStyleCombo->Append( lineStyleDesc.name, KiBitmapBundle( lineStyleDesc.bitmap ) ); SetupStandardButtons(); // wxTextCtrls fail to generate wxEVT_CHAR events when the wxTE_MULTILINE flag is set, // so we have to listen to wxEVT_CHAR_HOOK events instead. - Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ), - nullptr, this ); + Connect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ), nullptr, this ); finishDialogSettings(); - Layout(); - bMainSizer->Fit( this ); + Layout(); + bMainSizer->Fit( this ); } DIALOG_TEXTBOX_PROPERTIES::~DIALOG_TEXTBOX_PROPERTIES() { - Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ), - nullptr, this ); + Disconnect( wxEVT_CHAR_HOOK, wxKeyEventHandler( DIALOG_TEXTBOX_PROPERTIES::OnCharHook ), nullptr, this ); delete m_scintillaTricks; + + if( m_helpWindow ) + m_helpWindow->Destroy(); } @@ -259,7 +273,7 @@ void DIALOG_TEXTBOX_PROPERTIES::onValignButton( wxCommandEvent& aEvent ) } } -void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) +void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent& aEvent ) { if( KIFONT::FONT::IsStroke( aEvent.GetString() ) ) { @@ -269,7 +283,7 @@ void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) int thickness = m_thickness.GetValue(); m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) ) - < abs( thickness - GetPenSizeForNormal( textSize ) ) ); + < abs( thickness - GetPenSizeForNormal( textSize ) ) ); } else { @@ -278,7 +292,7 @@ void DIALOG_TEXTBOX_PROPERTIES::onFontSelected( wxCommandEvent & aEvent ) } -void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent & aEvent ) +void DIALOG_TEXTBOX_PROPERTIES::onBoldToggle( wxCommandEvent& aEvent ) { int textSize = std::min( m_textWidth.GetValue(), m_textHeight.GetValue() ); @@ -307,7 +321,7 @@ void DIALOG_TEXTBOX_PROPERTIES::onThickness( wxCommandEvent& event ) int thickness = m_thickness.GetValue(); m_bold->Check( abs( thickness - GetPenSizeForBold( textSize ) ) - < abs( thickness - GetPenSizeForNormal( textSize ) ) ); + < abs( thickness - GetPenSizeForNormal( textSize ) ) ); } @@ -405,8 +419,7 @@ bool DIALOG_TEXTBOX_PROPERTIES::TransferDataFromWindow() if( m_fontCtrl->HaveFontSelection() ) { - m_textBox->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), - m_italic->IsChecked() ) ); + m_textBox->SetFont( m_fontCtrl->GetFontSelection( m_bold->IsChecked(), m_italic->IsChecked() ) ); } m_textBox->SetTextSize( VECTOR2I( m_textWidth.GetValue(), m_textHeight.GetValue() ) ); @@ -483,3 +496,9 @@ void DIALOG_TEXTBOX_PROPERTIES::onMultiLineTCLostFocus( wxFocusEvent& event ) event.Skip(); } + + +void DIALOG_TEXTBOX_PROPERTIES::onSyntaxHelp( wxHyperlinkEvent& aEvent ) +{ + m_helpWindow = PCB_TEXT::ShowSyntaxHelp( this ); +} diff --git a/pcbnew/dialogs/dialog_textbox_properties.h b/pcbnew/dialogs/dialog_textbox_properties.h index c7d396c483..03d68427dc 100644 --- a/pcbnew/dialogs/dialog_textbox_properties.h +++ b/pcbnew/dialogs/dialog_textbox_properties.h @@ -24,6 +24,7 @@ #ifndef DIALOG_TEXTBOX_PROPERTIES_H #define DIALOG_TEXTBOX_PROPERTIES_H +#include #include #include @@ -33,6 +34,8 @@ class PCB_BASE_EDIT_FRAME; class PCB_TEXTBOX; class SCINTILLA_TRICKS; +class HTML_MESSAGE_BOX; +class wxHyperlinkCtrl; class DIALOG_TEXTBOX_PROPERTIES : public DIALOG_TEXTBOX_PROPERTIES_BASE @@ -48,24 +51,28 @@ private: void onValignButton( wxCommandEvent& aEvent ) override; void onThickness( wxCommandEvent& aEvent ) override; void onBorderChecked( wxCommandEvent& event ) override; - void onTextSize( wxCommandEvent &aEvent ) override; - void onAutoTextThickness( wxCommandEvent &aEvent ) override; + void onTextSize( wxCommandEvent& aEvent ) override; + void onAutoTextThickness( wxCommandEvent& aEvent ) override; bool TransferDataToWindow() override; bool TransferDataFromWindow() override; void onMultiLineTCLostFocus( wxFocusEvent& event ) override; + void onSyntaxHelp( wxHyperlinkEvent& aEvent ); + private: PCB_BASE_EDIT_FRAME* m_frame; PCB_TEXTBOX* m_textBox; - UNIT_BINDER m_textWidth; - UNIT_BINDER m_textHeight; - UNIT_BINDER m_thickness; - UNIT_BINDER m_orientation; // rotation in degrees - UNIT_BINDER m_borderWidth; + UNIT_BINDER m_textWidth; + UNIT_BINDER m_textHeight; + UNIT_BINDER m_thickness; + UNIT_BINDER m_orientation; // rotation in degrees + UNIT_BINDER m_borderWidth; - SCINTILLA_TRICKS* m_scintillaTricks; + SCINTILLA_TRICKS* m_scintillaTricks; + wxHyperlinkCtrl* m_syntaxHelp; + HTML_MESSAGE_BOX* m_helpWindow; }; diff --git a/pcbnew/pcb_tablecell.cpp b/pcbnew/pcb_tablecell.cpp index c3f4f5defc..acd304f97b 100644 --- a/pcbnew/pcb_tablecell.cpp +++ b/pcbnew/pcb_tablecell.cpp @@ -21,6 +21,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include +#include #include #include #include @@ -49,7 +51,7 @@ void PCB_TABLECELL::swapData( BOARD_ITEM* aImage ) { wxASSERT( aImage->Type() == PCB_TABLECELL_T ); - std::swap( *((PCB_TABLECELL*) this), *((PCB_TABLECELL*) aImage) ); + std::swap( *( (PCB_TABLECELL*) this ), *( (PCB_TABLECELL*) aImage ) ); } @@ -95,9 +97,65 @@ int PCB_TABLECELL::GetColumn() const wxString PCB_TABLECELL::GetAddr() const { - return wxString::Format( wxT( "%c%d" ), - 'A' + GetColumn() % 26, - GetRow() + 1 ); + return wxString::Format( wxT( "%c%d" ), 'A' + GetColumn() % 26, GetRow() + 1 ); +} + + +wxString PCB_TABLECELL::GetShownText( bool aAllowExtraText, int aDepth ) const +{ + const FOOTPRINT* parentFootprint = GetParentFootprint(); + const BOARD* board = GetBoard(); + + std::function tableCellResolver = [&]( wxString* token ) -> bool + { + if( token->IsSameAs( wxT( "ROW" ) ) ) + { + *token = wxString::Format( wxT( "%d" ), GetRow() + 1 ); // 1-based + return true; + } + else if( token->IsSameAs( wxT( "COL" ) ) ) + { + *token = wxString::Format( wxT( "%d" ), GetColumn() + 1 ); // 1-based + return true; + } + else if( token->IsSameAs( wxT( "ADDR" ) ) ) + { + *token = GetAddr(); + return true; + } + else if( token->IsSameAs( wxT( "LAYER" ) ) ) + { + *token = GetLayerName(); + return true; + } + + if( parentFootprint && parentFootprint->ResolveTextVar( token, aDepth + 1 ) ) + return true; + + if( board->ResolveTextVar( token, aDepth + 1 ) ) + return true; + + return false; + }; + + wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); + + if( HasTextVars() ) + text = ResolveTextVars( text, &tableCellResolver, aDepth ); + + KIFONT::FONT* font = GetDrawFont( nullptr ); + EDA_ANGLE drawAngle = GetDrawRotation(); + std::vector corners = GetCornersInSequence( drawAngle ); + int colWidth = ( corners[1] - corners[0] ).EuclideanNorm(); + + if( GetTextAngle().IsHorizontal() ) + colWidth -= ( GetMarginLeft() + GetMarginRight() ); + else + colWidth -= ( GetMarginTop() + GetMarginBottom() ); + + font->LinebreakText( text, colWidth, GetTextSize(), GetEffectiveTextPenWidth(), IsBold(), IsItalic() ); + + return text; } @@ -144,10 +202,8 @@ void PCB_TABLECELL::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorMessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); - aList.emplace_back( _( "Cell Height" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); + aList.emplace_back( _( "Cell Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); + aList.emplace_back( _( "Cell Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) ); @@ -193,13 +249,10 @@ bool PCB_TABLECELL::operator==( const BOARD_ITEM& aBoardItem ) const bool PCB_TABLECELL::operator==( const PCB_TABLECELL& aOther ) const { - return m_colSpan == aOther.m_colSpan - && m_rowSpan == aOther.m_rowSpan - && PCB_TEXTBOX::operator==( aOther ); + return m_colSpan == aOther.m_colSpan && m_rowSpan == aOther.m_rowSpan && PCB_TEXTBOX::operator==( aOther ); } - static struct PCB_TABLECELL_DESC { PCB_TABLECELL_DESC() @@ -250,14 +303,14 @@ static struct PCB_TABLECELL_DESC const wxString tableProps = _( "Table" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Column Width" ), - &PCB_TABLECELL::SetColumnWidth, &PCB_TABLECELL::GetColumnWidth, - PROPERTY_DISPLAY::PT_SIZE ), - tableProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Column Width" ), &PCB_TABLECELL::SetColumnWidth, + &PCB_TABLECELL::GetColumnWidth, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Row Height" ), - &PCB_TABLECELL::SetRowHeight, &PCB_TABLECELL::GetRowHeight, - PROPERTY_DISPLAY::PT_SIZE ), - tableProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Row Height" ), &PCB_TABLECELL::SetRowHeight, + &PCB_TABLECELL::GetRowHeight, + PROPERTY_DISPLAY::PT_SIZE ), + tableProps ); } } _PCB_TABLECELL_DESC; diff --git a/pcbnew/pcb_tablecell.h b/pcbnew/pcb_tablecell.h index a1f91891c5..5e10caa23b 100644 --- a/pcbnew/pcb_tablecell.h +++ b/pcbnew/pcb_tablecell.h @@ -34,30 +34,15 @@ class PCB_TABLECELL : public PCB_TEXTBOX public: PCB_TABLECELL( BOARD_ITEM* parent ); - static inline bool ClassOf( const EDA_ITEM* aItem ) - { - return aItem && PCB_TABLECELL_T == aItem->Type(); - } + static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && PCB_TABLECELL_T == aItem->Type(); } - wxString GetClass() const override - { - return wxT( "PCB_TABLECELL" ); - } + wxString GetClass() const override { return wxT( "PCB_TABLECELL" ); } - virtual wxString GetFriendlyName() const override - { - return _( "Table Cell" ); - } + virtual wxString GetFriendlyName() const override { return _( "Table Cell" ); } - EDA_ITEM* Clone() const override - { - return new PCB_TABLECELL( *this ); - } + EDA_ITEM* Clone() const override { return new PCB_TABLECELL( *this ); } - EDA_GROUP* GetParentGroup() const override - { - return GetParent()->GetParentGroup(); - } + EDA_GROUP* GetParentGroup() const override { return GetParent()->GetParentGroup(); } int GetRow() const; int GetColumn() const; @@ -65,22 +50,21 @@ public: // @return the spreadsheet nomenclature for the cell (ie: B3 for 2nd column, 3rd row) wxString GetAddr() const; + wxString GetShownText( bool aAllowExtraText, int aDepth = 0 ) const override; + int GetColSpan() const { return m_colSpan; } void SetColSpan( int aSpan ) { m_colSpan = aSpan; } int GetRowSpan() const { return m_rowSpan; } void SetRowSpan( int aSpan ) { m_rowSpan = aSpan; } - int GetRowHeight() const; + int GetRowHeight() const; void SetRowHeight( int aHeight ); - int GetColumnWidth() const; + int GetColumnWidth() const; void SetColumnWidth( int aWidth ); - bool IsFilledForHitTesting() const override - { - return true; - } + bool IsFilledForHitTesting() const override { return true; } wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override; diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp index 627b24e657..4d4c191f6a 100644 --- a/pcbnew/pcb_text.cpp +++ b/pcbnew/pcb_text.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,7 @@ PCB_TEXT::PCB_TEXT( BOARD_ITEM* parent, KICAD_T idtype ) : } -PCB_TEXT::PCB_TEXT( FOOTPRINT* aParent, KICAD_T idtype) : +PCB_TEXT::PCB_TEXT( FOOTPRINT* aParent, KICAD_T idtype ) : BOARD_ITEM( aParent, idtype ), EDA_TEXT( pcbIUScale ) { @@ -87,7 +88,7 @@ void PCB_TEXT::CopyFrom( const BOARD_ITEM* aOther ) } -void PCB_TEXT::Serialize( google::protobuf::Any &aContainer ) const +void PCB_TEXT::Serialize( google::protobuf::Any& aContainer ) const { using namespace kiapi::common; kiapi::board::types::BoardText boardText; @@ -95,8 +96,7 @@ void PCB_TEXT::Serialize( google::protobuf::Any &aContainer ) const boardText.mutable_id()->set_value( m_Uuid.AsStdString() ); boardText.set_layer( ToProtoEnum( GetLayer() ) ); boardText.set_knockout( IsKnockout() ); - boardText.set_locked( IsLocked() ? types::LockedState::LS_LOCKED - : types::LockedState::LS_UNLOCKED ); + boardText.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED ); google::protobuf::Any any; EDA_TEXT::Serialize( any ); @@ -111,7 +111,7 @@ void PCB_TEXT::Serialize( google::protobuf::Any &aContainer ) const } -bool PCB_TEXT::Deserialize( const google::protobuf::Any &aContainer ) +bool PCB_TEXT::Deserialize( const google::protobuf::Any& aContainer ) { using namespace kiapi::common; kiapi::board::types::BoardText boardText; @@ -141,35 +141,28 @@ wxString PCB_TEXT::GetShownText( bool aAllowExtraText, int aDepth ) const const FOOTPRINT* parentFootprint = GetParentFootprint(); const BOARD* board = GetBoard(); - std::function resolver = - [&]( wxString* token ) -> bool - { - if( token->IsSameAs( wxT( "LAYER" ) ) ) - { - *token = GetLayerName(); - return true; - } + std::function resolver = [&]( wxString* token ) -> bool + { + if( token->IsSameAs( wxT( "LAYER" ) ) ) + { + *token = GetLayerName(); + return true; + } - if( parentFootprint && parentFootprint->ResolveTextVar( token, aDepth + 1 ) ) - return true; + if( parentFootprint && parentFootprint->ResolveTextVar( token, aDepth + 1 ) ) + return true; - // board can be null in some cases when saving a footprint in FP editor - if( board && board->ResolveTextVar( token, aDepth + 1 ) ) - return true; + // board can be null in some cases when saving a footprint in FP editor + if( board && board->ResolveTextVar( token, aDepth + 1 ) ) + return true; - return false; - }; + return false; + }; wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); if( HasTextVars() ) - { - if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &resolver ); - } - - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); + text = ResolveTextVars( text, &resolver, aDepth ); return text; } @@ -490,7 +483,7 @@ void PCB_TEXT::swapData( BOARD_ITEM* aImage ) { assert( aImage->Type() == PCB_TEXT_T ); - std::swap( *((PCB_TEXT*) this), *((PCB_TEXT*) aImage) ); + std::swap( *( (PCB_TEXT*) this ), *( (PCB_TEXT*) aImage ) ); } @@ -516,10 +509,8 @@ SHAPE_POLY_SET PCB_TEXT::GetKnockoutCache( const KIFONT::FONT* aFont, const wxSt EDA_ANGLE drawAngle = GetDrawRotation(); VECTOR2I drawPos = GetDrawPos(); - if( m_knockout_cache.IsEmpty() - || m_knockout_cache_text_attrs != attrs - || m_knockout_cache_text != forResolvedText - || m_knockout_cache_angle != drawAngle ) + if( m_knockout_cache.IsEmpty() || m_knockout_cache_text_attrs != attrs || m_knockout_cache_text != forResolvedText + || m_knockout_cache_angle != drawAngle ) { m_knockout_cache.RemoveAllContours(); @@ -541,8 +532,7 @@ SHAPE_POLY_SET PCB_TEXT::GetKnockoutCache( const KIFONT::FONT* aFont, const wxSt } -void PCB_TEXT::buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, - int aClearance ) const +void PCB_TEXT::buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, int aClearance ) const { SHAPE_POLY_SET poly( aRenderedText ); @@ -586,7 +576,8 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, // Simplify shapes is not usually always efficient, but in this case it is. SHAPE_POLY_SET textShape; - CALLBACK_GAL callback_gal( empty_opts, + CALLBACK_GAL callback_gal( + empty_opts, // Stroke callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) { @@ -633,9 +624,8 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, } -void PCB_TEXT::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, - int aClearance, int aMaxError, ERROR_LOC aErrorLoc, - bool aIgnoreLineWidth ) const +void PCB_TEXT::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, + ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const { SHAPE_POLY_SET poly; @@ -673,6 +663,27 @@ double PCB_TEXT::Similarity( const BOARD_ITEM& aOther ) const } +HTML_MESSAGE_BOX* PCB_TEXT::ShowSyntaxHelp( wxWindow* aParentWindow ) +{ + wxString msg = +#include "pcb_text_help_md.h" + ; + + HTML_MESSAGE_BOX* dlg = new HTML_MESSAGE_BOX( aParentWindow, _( "Syntax Help" ) ); + wxSize sz( 320, 320 ); + + dlg->SetMinSize( dlg->ConvertDialogToPixels( sz ) ); + dlg->SetDialogSizeInDU( sz.x, sz.y ); + + wxString html_txt; + ConvertMarkdown2Html( wxGetTranslation( msg ), html_txt ); + dlg->AddHTML_Text( html_txt ); + dlg->ShowModeless(); + + return dlg; +} + + static struct PCB_TEXT_DESC { PCB_TEXT_DESC() @@ -686,25 +697,24 @@ static struct PCB_TEXT_DESC propMgr.Mask( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Knockout" ), - &BOARD_ITEM::SetIsKnockout, &BOARD_ITEM::IsKnockout ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Knockout" ), &BOARD_ITEM::SetIsKnockout, + &BOARD_ITEM::IsKnockout ), + _HKI( "Text Properties" ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Keep Upright" ), - &PCB_TEXT::SetKeepUpright, &PCB_TEXT::IsKeepUpright ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( _HKI( "Keep Upright" ), &PCB_TEXT::SetKeepUpright, + &PCB_TEXT::IsKeepUpright ), + _HKI( "Text Properties" ) ); - auto isFootprintText = - []( INSPECTABLE* aItem ) -> bool - { - if( PCB_TEXT* text = dynamic_cast( aItem ) ) - return text->GetParentFootprint(); + auto isFootprintText = []( INSPECTABLE* aItem ) -> bool + { + if( PCB_TEXT* text = dynamic_cast( aItem ) ) + return text->GetParentFootprint(); - return false; - }; + return false; + }; - propMgr.OverrideAvailability( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), - _HKI( "Keep Upright" ), isFootprintText ); + propMgr.OverrideAvailability( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Keep Upright" ), + isFootprintText ); propMgr.Mask( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); } diff --git a/pcbnew/pcb_text.h b/pcbnew/pcb_text.h index e5ad09c77c..a3b1cf6163 100644 --- a/pcbnew/pcb_text.h +++ b/pcbnew/pcb_text.h @@ -32,6 +32,7 @@ class LINE_READER; class MSG_PANEL_ITEM; class FOOTPRINT; +class HTML_MESSAGE_BOX; class PCB_TEXT : public BOARD_ITEM, public EDA_TEXT @@ -48,10 +49,7 @@ public: void CopyFrom( const BOARD_ITEM* aOther ) override; - static inline bool ClassOf( const EDA_ITEM* aItem ) - { - return aItem && PCB_TEXT_T == aItem->Type(); - } + static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && PCB_TEXT_T == aItem->Type(); } bool IsType( const std::vector& aScanTypes ) const override { @@ -67,8 +65,8 @@ public: return false; } - void Serialize( google::protobuf::Any &aContainer ) const override; - bool Deserialize( const google::protobuf::Any &aContainer ) override; + void Serialize( google::protobuf::Any& aContainer ) const override; + bool Deserialize( const google::protobuf::Any& aContainer ) override; void StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide ) override; @@ -81,20 +79,11 @@ public: bool Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const override; - virtual VECTOR2I GetPosition() const override - { - return EDA_TEXT::GetTextPos(); - } + virtual VECTOR2I GetPosition() const override { return EDA_TEXT::GetTextPos(); } - virtual void SetPosition( const VECTOR2I& aPos ) override - { - EDA_TEXT::SetTextPos( aPos ); - } + virtual void SetPosition( const VECTOR2I& aPos ) override { EDA_TEXT::SetTextPos( aPos ); } - void Move( const VECTOR2I& aMoveVector ) override - { - EDA_TEXT::Offset( aMoveVector ); - } + void Move( const VECTOR2I& aMoveVector ) override { EDA_TEXT::Offset( aMoveVector ); } void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override; @@ -123,10 +112,7 @@ public: return TextHitTest( aPoly, aContained ); } - wxString GetClass() const override - { - return wxT( "PCB_TEXT" ); - } + wxString GetClass() const override { return wxT( "PCB_TEXT" ); } /** * Function TransformTextToPolySet @@ -136,20 +122,16 @@ public: * @param aClearance the clearance around the text * @param aMaxError the maximum error to allow when approximating curves */ - void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aMaxError, - ERROR_LOC aErrorLoc ) const; + void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc ) const; - void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, - int aMaxError, ERROR_LOC aErrorLoc, - bool aIgnoreLineWidth = false ) const override; + void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, + ERROR_LOC aErrorLoc, bool aIgnoreLineWidth = false ) const override; // @copydoc BOARD_ITEM::GetEffectiveShape - virtual std::shared_ptr - GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER, - FLASHING aFlash = FLASHING::DEFAULT ) const override; + virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER, + FLASHING aFlash = FLASHING::DEFAULT ) const override; - SHAPE_POLY_SET GetKnockoutCache( const KIFONT::FONT* aFont, const wxString& forResolvedText, - int aMaxError ) const; + SHAPE_POLY_SET GetKnockoutCache( const KIFONT::FONT* aFont, const wxString& forResolvedText, int aMaxError ) const; virtual wxString GetTextTypeDescription() const; @@ -157,6 +139,13 @@ public: BITMAPS GetMenuImage() const override; + /** + * Display a syntax help window for text variables and expressions. + * @param aParentWindow Parent window for the help dialog + * @return Pointer to the modeless help dialog + */ + static HTML_MESSAGE_BOX* ShowSyntaxHelp( wxWindow* aParentWindow ); + /** * @return the text rotation for drawings and plotting the footprint rotation is taken * in account. @@ -180,7 +169,7 @@ public: bool operator==( const PCB_TEXT& aOther ) const; bool operator==( const BOARD_ITEM& aBoardItem ) const override; -#if defined(DEBUG) +#if defined( DEBUG ) virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } #endif @@ -189,8 +178,7 @@ protected: * Build a nominally rectangular bounding box for the rendered text. (It's not a BOX2I * because it will be a diamond shape for non-cardinally rotated text.) */ - void buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, - int aClearance ) const; + void buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, int aClearance ) const; virtual void swapData( BOARD_ITEM* aImage ) override; @@ -199,11 +187,11 @@ protected: const KIFONT::METRICS& getFontMetrics() const override { return GetFontMetrics(); } private: - mutable wxString m_knockout_cache_text; - mutable TEXT_ATTRIBUTES m_knockout_cache_text_attrs; - mutable EDA_ANGLE m_knockout_cache_angle; - mutable VECTOR2I m_knockout_cache_pos; - mutable SHAPE_POLY_SET m_knockout_cache; + mutable wxString m_knockout_cache_text; + mutable TEXT_ATTRIBUTES m_knockout_cache_text_attrs; + mutable EDA_ANGLE m_knockout_cache_angle; + mutable VECTOR2I m_knockout_cache_pos; + mutable SHAPE_POLY_SET m_knockout_cache; }; -#endif // #define PCB_TEXT_H +#endif // #define PCB_TEXT_H diff --git a/pcbnew/pcb_text_help.md b/pcbnew/pcb_text_help.md new file mode 100644 index 0000000000..d5df7a0a1e --- /dev/null +++ b/pcbnew/pcb_text_help.md @@ -0,0 +1,290 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MarkupResult
 
^{superscript}
 
superscript 
 
Driver Board^{Rev A}
 
Driver BoardRev A

 
_{subscript}
 
subscript 
 
D_{0} - D_{15}
 
D0 - D15
 
~{overbar}
 
~{CLK}
       
overbar
   
CLK
 
${variable}
 
variable_value
 
${PROJECTNAME}
 
MyBoard

PCB Variables
 
${FILENAME}
 
board.kicad_pcb
 
${FILEPATH}
 
/path/to/board.kicad_pcb
 
${LAYER} (in text/tables)
 
F.Cu, B.Cu, F.SilkS...

Footprint Cross-References
 
${refdes:field}
 
field_value of footprint refdes
 
${U1:REFERENCE}
 
U1
 
${U1:VALUE}
 
STM32F407VGT6
 
${U1:FOOTPRINT_LIBRARY}
 
Package_QFP
 
${U1:FOOTPRINT_NAME}
 
LQFP-100_14x14mm_P0.5mm

Pad/Pin Functions
 
${refdes:NET_NAME(pad)}
 
Net name connected to pad
 
${U1:NET_NAME(5)}
 
VCC
 
${refdes:SHORT_NET_NAME(pad)}
 
Short net name or NC
 
${J1:SHORT_NET_NAME(3)}
 
GND or NC
 
${refdes:NET_CLASS(pad)}
 
Net class for pad
 
${J1:NET_CLASS(1)}
 
Power
 
${refdes:PIN_NAME(pad)}
 
Pin function/name
 
${U1:PIN_NAME(5)}
 
USART1_TX

Table Variables
 
${ROW} (in tables)
 
1, 2, 3...
 
${COL} (in tables)
 
1, 2, 3...
 
${ADDR} (in tables)
 
A1, B2, C3...

Math Expressions
 
@{expression}
 
evaluated_result
 
@{2 + 3}
 
5
 
@{${ROW} - 1}
 
3 (when ROW=4)

String Comparison & Conditional Text
 
@{"text" == "text"}
 
1
 
@{"text" != "other"}
 
1
 
@{if(condition, true_val, false_val)}
 
Conditional text display
 
@{if("${LAYER}" == "F.Cu", "TOP", "BOTTOM")}
 
TOP (on front layer) or BOTTOM
 
@{if(${ROW} > 5, "High", "Low")}
 
Numeric comparisons work too

Escape Sequences
 
\${LITERAL}
 
${LITERAL} (not expanded)
 
Price: \$25.00
 
Price: $25.00
 
\@{x+y}
 
@{x+y} (not evaluated)

Nested Variables
 
${U1:NET_NAME(@{${ROW}-2})}
 
Dynamic net lookup in tables
 
${U${ROW}:VALUE}
 
Dynamic footprint reference

+

+

+Note that markup has precedence over variable expansion. +

+

Footprint Cross-References: Reference fields and pads on other footprints using ${refdes:field} or ${refdes:function(pad)} syntax.

+

Nested Variables: Variables can contain other variables. Inner variables are expanded first. Maximum nesting depth: 10 levels.

+

Error Messages:

+
    +
  • <UNRESOLVED: token> - Variable or function cannot be resolved
  • +
  • <Unknown reference: U1> - Footprint not found
  • +
+ diff --git a/pcbnew/pcb_text_help_md.h b/pcbnew/pcb_text_help_md.h new file mode 100644 index 0000000000..62a2f4cb9d --- /dev/null +++ b/pcbnew/pcb_text_help_md.h @@ -0,0 +1,292 @@ +// Do not edit this file, it is autogenerated by CMake from the .md file +_HKI( "\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"
MarkupResult
 
^{superscript}
 
superscript 
 
Driver Board^{Rev A}
 
Driver BoardRev A

 
_{subscript}
 
subscript 
 
D_{0} - D_{15}
 
D0 - D15
 
~{overbar}
 
~{CLK}
       
overbar
   
CLK
 
${variable}
 
variable_value
 
${PROJECTNAME}
 
MyBoard

PCB Variables
 
${FILENAME}
 
board.kicad_pcb
 
${FILEPATH}
 
/path/to/board.kicad_pcb
 
${LAYER} (in text/tables)
 
F.Cu, B.Cu, F.SilkS...

Footprint Cross-References
 
${refdes:field}
 
field_value of footprint refdes
 
${U1:REFERENCE}
 
U1
 
${U1:VALUE}
 
STM32F407VGT6
 
${U1:FOOTPRINT_LIBRARY}
 
Package_QFP
 
${U1:FOOTPRINT_NAME}
 
LQFP-100_14x14mm_P0.5mm

Pad/Pin Functions
 
${refdes:NET_NAME(pad)}
 
Net name connected to pad
 
${U1:NET_NAME(5)}
 
VCC
 
${refdes:SHORT_NET_NAME(pad)}
 
Short net name or NC
 
${J1:SHORT_NET_NAME(3)}
 
GND or NC
 
${refdes:NET_CLASS(pad)}
 
Net class for pad
 
${J1:NET_CLASS(1)}
 
Power
 
${refdes:PIN_NAME(pad)}
 
Pin function/name
 
${U1:PIN_NAME(5)}
 
USART1_TX

Table Variables
 
${ROW} (in tables)
 
1, 2, 3...
 
${COL} (in tables)
 
1, 2, 3...
 
${ADDR} (in tables)
 
A1, B2, C3...

Math Expressions
 
@{expression}
 
evaluated_result
 
@{2 + 3}
 
5
 
@{${ROW} - 1}
 
3 (when ROW=4)

String Comparison & Conditional Text
 
@{\"text\" == \"text\"}
 
1
 
@{\"text\" != \"other\"}
 
1
 
@{if(condition, true_val, false_val)}
 
Conditional text display
 
@{if(\"${LAYER}\" == \"F.Cu\", \"TOP\", \"BOTTOM\")}
 
TOP (on front layer) or BOTTOM
 
@{if(${ROW} > 5, \"High\", \"Low\")}
 
Numeric comparisons work too

Escape Sequences
 
\\${LITERAL}
 
${LITERAL} (not expanded)
 
Price: \\$25.00
 
Price: $25.00
 
\\@{x+y}
 
@{x+y} (not evaluated)

Nested Variables
 
${U1:NET_NAME(@{${ROW}-2})}
 
Dynamic net lookup in tables
 
${U${ROW}:VALUE}
 
Dynamic footprint reference

\n" +"

\n" +"

\n" +"Note that markup has precedence over variable expansion.\n" +"

\n" +"

Footprint Cross-References: Reference fields and pads on other footprints using ${refdes:field} or ${refdes:function(pad)} syntax.

\n" +"

Nested Variables: Variables can contain other variables. Inner variables are expanded first. Maximum nesting depth: 10 levels.

\n" +"

Error Messages:

\n" +"
    \n" +"
  • <UNRESOLVED: token> - Variable or function cannot be resolved
  • \n" +"
  • <Unknown reference: U1> - Footprint not found
  • \n" +"
\n" +"\n" +"" ); diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp index 5910c6d391..8c85cbdc65 100644 --- a/pcbnew/pcb_textbox.cpp +++ b/pcbnew/pcb_textbox.cpp @@ -73,7 +73,7 @@ void PCB_TEXTBOX::CopyFrom( const BOARD_ITEM* aOther ) } -void PCB_TEXTBOX::Serialize( google::protobuf::Any &aContainer ) const +void PCB_TEXTBOX::Serialize( google::protobuf::Any& aContainer ) const { using namespace kiapi::common::types; using namespace kiapi::board; @@ -94,11 +94,9 @@ void PCB_TEXTBOX::Serialize( google::protobuf::Any &aContainer ) const if( GetFont() ) attrs->set_font_name( GetFont()->GetName().ToStdString() ); - attrs->set_horizontal_alignment( - ToProtoEnum( GetHorizJustify() ) ); + attrs->set_horizontal_alignment( ToProtoEnum( GetHorizJustify() ) ); - attrs->set_vertical_alignment( - ToProtoEnum( GetVertJustify() ) ); + attrs->set_vertical_alignment( ToProtoEnum( GetVertJustify() ) ); attrs->mutable_angle()->set_value_degrees( GetTextAngleDegrees() ); attrs->set_line_spacing( GetLineSpacing() ); @@ -115,7 +113,7 @@ void PCB_TEXTBOX::Serialize( google::protobuf::Any &aContainer ) const } -bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any &aContainer ) +bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any& aContainer ) { using namespace kiapi::board; types::BoardTextBox boardText; @@ -148,17 +146,15 @@ bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any &aContainer ) if( !text.attributes().font_name().empty() ) { - attrs.m_Font = KIFONT::FONT::GetFont( - wxString( text.attributes().font_name().c_str(), wxConvUTF8 ), attrs.m_Bold, - attrs.m_Italic ); + attrs.m_Font = KIFONT::FONT::GetFont( wxString( text.attributes().font_name().c_str(), wxConvUTF8 ), + attrs.m_Bold, attrs.m_Italic ); } attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T ); attrs.m_LineSpacing = text.attributes().line_spacing(); attrs.m_StrokeWidth = text.attributes().stroke_width().value_nm(); - attrs.m_Halign = - FromProtoEnum( - text.attributes().horizontal_alignment() ); + attrs.m_Halign = FromProtoEnum( + text.attributes().horizontal_alignment() ); attrs.m_Valign = FromProtoEnum( text.attributes().vertical_alignment() ); @@ -307,20 +303,16 @@ VECTOR2I PCB_TEXTBOX::GetDrawPos( bool aIsFlipped ) const case GR_TEXT_H_ALIGN_LEFT: horizontalAlignment = GR_TEXT_H_ALIGN_RIGHT; break; case GR_TEXT_H_ALIGN_CENTER: horizontalAlignment = GR_TEXT_H_ALIGN_CENTER; break; case GR_TEXT_H_ALIGN_RIGHT: horizontalAlignment = GR_TEXT_H_ALIGN_LEFT; break; - case GR_TEXT_H_ALIGN_INDETERMINATE: - horizontalAlignment = GR_TEXT_H_ALIGN_INDETERMINATE; - break; + case GR_TEXT_H_ALIGN_INDETERMINATE: horizontalAlignment = GR_TEXT_H_ALIGN_INDETERMINATE; break; } } - wxASSERT_MSG( - horizontalAlignment != GR_TEXT_H_ALIGN_INDETERMINATE - && verticalAlignment != GR_TEXT_V_ALIGN_INDETERMINATE, - wxS( "Indeterminate state legal only in dialogs. Horizontal and vertical alignment " - "must be set before calling PCB_TEXTBOX::GetDrawPos." ) ); + wxASSERT_MSG( horizontalAlignment != GR_TEXT_H_ALIGN_INDETERMINATE + && verticalAlignment != GR_TEXT_V_ALIGN_INDETERMINATE, + wxS( "Indeterminate state legal only in dialogs. Horizontal and vertical alignment " + "must be set before calling PCB_TEXTBOX::GetDrawPos." ) ); - if( horizontalAlignment == GR_TEXT_H_ALIGN_INDETERMINATE - || verticalAlignment == GR_TEXT_V_ALIGN_INDETERMINATE ) + if( horizontalAlignment == GR_TEXT_H_ALIGN_INDETERMINATE || verticalAlignment == GR_TEXT_V_ALIGN_INDETERMINATE ) { return center; } @@ -329,43 +321,35 @@ VECTOR2I PCB_TEXTBOX::GetDrawPos( bool aIsFlipped ) const { textAnchor = corners[0]; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER - && verticalAlignment == GR_TEXT_V_ALIGN_TOP ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_TOP ) { textAnchor = midTop; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT - && verticalAlignment == GR_TEXT_V_ALIGN_TOP ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_TOP ) { textAnchor = corners[1]; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT - && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) { textAnchor = midLeft; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER - && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) { textAnchor = center; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT - && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER ) { textAnchor = midRight; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT - && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) { textAnchor = corners[3]; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER - && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) { textAnchor = midBottom; } - else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT - && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) + else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM ) { textAnchor = corners[2]; } @@ -447,13 +431,7 @@ wxString PCB_TEXTBOX::GetShownText( bool aAllowExtraText, int aDepth ) const wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth ); if( HasTextVars() ) - { - if( aDepth < ADVANCED_CFG::GetCfg().m_ResolveTextRecursionDepth ) - text = ExpandTextVars( text, &resolver ); - } - - if( text.Contains( wxT( "@{" ) ) ) - text = EvaluateText( text ); + text = ResolveTextVars( text, &resolver, aDepth ); KIFONT::FONT* font = GetDrawFont( nullptr ); EDA_ANGLE drawAngle = GetDrawRotation(); @@ -499,11 +477,9 @@ void PCB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vectorMessageTextFromValue( GetTextWidth() ) ); aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) ); - aList.emplace_back( _( "Box Width" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); + aList.emplace_back( _( "Box Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) ); - aList.emplace_back( _( "Box Height" ), - aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) )); + aList.emplace_back( _( "Box Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) ); m_stroke.GetMsgPanelInfo( aFrame, aList ); } @@ -531,8 +507,8 @@ void PCB_TEXTBOX::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) EDA_ANGLE drawAngle = GetDrawRotation(); std::vector corners = GetCornersInSequence( drawAngle ); SetWidth( lineWidth ); - VECTOR2I diag = corners[2] - corners[0]; - EDA_ANGLE angle = GetTextAngle(); + VECTOR2I diag = corners[2] - corners[0]; + EDA_ANGLE angle = GetTextAngle(); SetShape( SHAPE_T::RECTANGLE ); SetStart( corners[0] ); @@ -607,8 +583,7 @@ bool PCB_TEXTBOX::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) cons wxString PCB_TEXTBOX::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const { return wxString::Format( _( "PCB text box '%s' on %s" ), - aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ), - GetLayerName() ); + aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ), GetLayerName() ); } @@ -628,7 +603,7 @@ void PCB_TEXTBOX::swapData( BOARD_ITEM* aImage ) { wxASSERT( aImage->Type() == PCB_TEXTBOX_T ); - std::swap( *((PCB_TEXTBOX*) this), *((PCB_TEXTBOX*) aImage) ); + std::swap( *( (PCB_TEXTBOX*) this ), *( (PCB_TEXTBOX*) aImage ) ); } @@ -657,7 +632,8 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearanc // Simplify shapes is not usually always efficient, but in this case it is. SHAPE_POLY_SET textShape; - CALLBACK_GAL callback_gal( empty_opts, + CALLBACK_GAL callback_gal( + empty_opts, // Stroke callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) { @@ -703,9 +679,8 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearanc } -void PCB_TEXTBOX::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, - int aClearance, int aMaxError, ERROR_LOC aErrorLoc, - bool aIgnoreLineWidth ) const +void PCB_TEXTBOX::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, + ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const { // Don't use PCB_SHAPE::TransformShapeToPolygon. We want to treat the textbox as filled even // if there's no background colour. @@ -730,7 +705,7 @@ void PCB_TEXTBOX::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID TransformOvalToPolygon( aBuffer, pts[3], pts[0], width, aMaxError, aErrorLoc ); } } - else if( GetShape() == SHAPE_T::POLY ) // Non-cardinally-rotated rect + else if( GetShape() == SHAPE_T::POLY ) // Non-cardinally-rotated rect { aBuffer.NewOutline(); @@ -782,8 +757,7 @@ bool PCB_TEXTBOX::operator==( const BOARD_ITEM& aBoardItem ) const bool PCB_TEXTBOX::operator==( const PCB_TEXTBOX& aOther ) const { - return m_borderEnabled == aOther.m_borderEnabled - && EDA_TEXT::operator==( aOther ); + return m_borderEnabled == aOther.m_borderEnabled && EDA_TEXT::operator==( aOther ); } @@ -825,11 +799,11 @@ static struct PCB_TEXTBOX_DESC if( lineStyleEnum.Choices().GetCount() == 0 ) { - lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) ) - .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) ) - .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) ) - .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) ) - .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) ); + lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) ) + .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) ) + .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) ) + .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) ) + .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) ); } PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); @@ -856,46 +830,41 @@ static struct PCB_TEXTBOX_DESC propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask" ) ); propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask Margin Override" ) ); - propMgr.AddProperty( new PROPERTY( _HKI( "Knockout" ), - &BOARD_ITEM::SetIsKnockout, &BOARD_ITEM::IsKnockout ), - _HKI( "Text Properties" ) ); + propMgr.AddProperty( new PROPERTY( + _HKI( "Knockout" ), &BOARD_ITEM::SetIsKnockout, &BOARD_ITEM::IsKnockout ), + _HKI( "Text Properties" ) ); const wxString borderProps = _( "Border Properties" ); void ( PCB_TEXTBOX::*lineStyleSetter )( LINE_STYLE ) = &PCB_TEXTBOX::SetLineStyle; LINE_STYLE ( PCB_TEXTBOX::*lineStyleGetter )() const = &PCB_TEXTBOX::GetLineStyle; - propMgr.AddProperty( new PROPERTY( _HKI( "Border" ), - &PCB_TEXTBOX::SetBorderEnabled, &PCB_TEXTBOX::IsBorderEnabled ), + propMgr.AddProperty( new PROPERTY( _HKI( "Border" ), &PCB_TEXTBOX::SetBorderEnabled, + &PCB_TEXTBOX::IsBorderEnabled ), + borderProps ); + + propMgr.AddProperty( + new PROPERTY_ENUM( _HKI( "Border Style" ), lineStyleSetter, lineStyleGetter ), borderProps ); - propMgr.AddProperty( new PROPERTY_ENUM( _HKI( "Border Style" ), - lineStyleSetter, lineStyleGetter ), - borderProps ); - - propMgr.AddProperty( new PROPERTY( _HKI( "Border Width" ), - &PCB_TEXTBOX::SetBorderWidth, &PCB_TEXTBOX::GetBorderWidth, - PROPERTY_DISPLAY::PT_SIZE ), - borderProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Border Width" ), &PCB_TEXTBOX::SetBorderWidth, + &PCB_TEXTBOX::GetBorderWidth, PROPERTY_DISPLAY::PT_SIZE ), + borderProps ); const wxString marginProps = _( "Margins" ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Left" ), - &PCB_TEXTBOX::SetMarginLeft, &PCB_TEXTBOX::GetMarginLeft, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Top" ), - &PCB_TEXTBOX::SetMarginTop, &PCB_TEXTBOX::GetMarginTop, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Right" ), - &PCB_TEXTBOX::SetMarginRight, &PCB_TEXTBOX::GetMarginRight, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); - propMgr.AddProperty( new PROPERTY( _HKI( "Margin Bottom" ), - &PCB_TEXTBOX::SetMarginBottom, &PCB_TEXTBOX::GetMarginBottom, - PROPERTY_DISPLAY::PT_SIZE ), - marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Left" ), &PCB_TEXTBOX::SetMarginLeft, + &PCB_TEXTBOX::GetMarginLeft, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Top" ), &PCB_TEXTBOX::SetMarginTop, + &PCB_TEXTBOX::GetMarginTop, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Right" ), &PCB_TEXTBOX::SetMarginRight, + &PCB_TEXTBOX::GetMarginRight, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); + propMgr.AddProperty( new PROPERTY( _HKI( "Margin Bottom" ), &PCB_TEXTBOX::SetMarginBottom, + &PCB_TEXTBOX::GetMarginBottom, PROPERTY_DISPLAY::PT_SIZE ), + marginProps ); propMgr.Mask( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) ); } diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index 4472f9d068..92530cf27d 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -118,26 +118,13 @@ static const std::vector footprintTypes = { PCB_FOOTPRINT_T }; static const std::vector groupTypes = { PCB_GROUP_T }; -static const std::vector trackTypes = { PCB_TRACE_T, - PCB_ARC_T, - PCB_VIA_T }; +static const std::vector trackTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }; -static const std::vector baseConnectedTypes = { PCB_PAD_T, - PCB_VIA_T, - PCB_TRACE_T, - PCB_ARC_T }; +static const std::vector baseConnectedTypes = { PCB_PAD_T, PCB_VIA_T, PCB_TRACE_T, PCB_ARC_T }; -static const std::vector connectedTypes = { PCB_TRACE_T, - PCB_ARC_T, - PCB_VIA_T, - PCB_PAD_T, - PCB_ZONE_T }; +static const std::vector connectedTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T }; -static const std::vector routableTypes = { PCB_TRACE_T, - PCB_ARC_T, - PCB_VIA_T, - PCB_PAD_T, - PCB_FOOTPRINT_T }; +static const std::vector routableTypes = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_FOOTPRINT_T }; EDIT_TOOL::EDIT_TOOL() : @@ -168,8 +155,8 @@ static std::shared_ptr makePositioningToolsMenu( TOOL_INTERACT return aSelection.Empty() || !aSelection.Front()->IsMoving(); }; - menu->AddItem( PCB_ACTIONS::moveExact, SELECTION_CONDITIONS::NotEmpty && notMovingCondition ); - menu->AddItem( PCB_ACTIONS::positionRelative, SELECTION_CONDITIONS::NotEmpty && notMovingCondition ); + menu->AddItem( PCB_ACTIONS::moveExact, SELECTION_CONDITIONS::NotEmpty && notMovingCondition ); + menu->AddItem( PCB_ACTIONS::positionRelative, SELECTION_CONDITIONS::NotEmpty && notMovingCondition ); menu->AddItem( PCB_ACTIONS::interactiveOffsetTool, SELECTION_CONDITIONS::NotEmpty && notMovingCondition ); return menu; }; @@ -181,38 +168,32 @@ static std::shared_ptr makeShapeModificationMenu( TOOL_INTERAC menu->SetUntranslatedTitle( _HKI( "Shape Modification" ) ); - static const std::vector filletChamferTypes = { PCB_SHAPE_LOCATE_POLY_T, - PCB_SHAPE_LOCATE_RECT_T, + static const std::vector filletChamferTypes = { PCB_SHAPE_LOCATE_POLY_T, PCB_SHAPE_LOCATE_RECT_T, PCB_SHAPE_LOCATE_SEGMENT_T }; - static const std::vector healShapesTypes = { PCB_SHAPE_LOCATE_SEGMENT_T, - PCB_SHAPE_LOCATE_ARC_T, + static const std::vector healShapesTypes = { PCB_SHAPE_LOCATE_SEGMENT_T, PCB_SHAPE_LOCATE_ARC_T, PCB_SHAPE_LOCATE_BEZIER_T }; static const std::vector lineExtendTypes = { PCB_SHAPE_LOCATE_SEGMENT_T }; - static const std::vector polygonBooleanTypes = { PCB_SHAPE_LOCATE_RECT_T, - PCB_SHAPE_LOCATE_POLY_T, + static const std::vector polygonBooleanTypes = { PCB_SHAPE_LOCATE_RECT_T, PCB_SHAPE_LOCATE_POLY_T, PCB_SHAPE_LOCATE_CIRCLE_T }; - static const std::vector polygonSimplifyTypes = { PCB_SHAPE_LOCATE_POLY_T, - PCB_ZONE_T }; + static const std::vector polygonSimplifyTypes = { PCB_SHAPE_LOCATE_POLY_T, PCB_ZONE_T }; - auto hasCornerCondition = - [aTool]( const SELECTION& aSelection ) - { - PCB_POINT_EDITOR *pt_tool = aTool->GetManager()->GetTool(); + auto hasCornerCondition = [aTool]( const SELECTION& aSelection ) + { + PCB_POINT_EDITOR* pt_tool = aTool->GetManager()->GetTool(); - return pt_tool && pt_tool->HasCorner(); - }; + return pt_tool && pt_tool->HasCorner(); + }; - auto hasMidpointCondition = - [aTool]( const SELECTION& aSelection ) - { - PCB_POINT_EDITOR *pt_tool = aTool->GetManager()->GetTool(); + auto hasMidpointCondition = [aTool]( const SELECTION& aSelection ) + { + PCB_POINT_EDITOR* pt_tool = aTool->GetManager()->GetTool(); - return pt_tool && pt_tool->HasMidpoint(); - }; + return pt_tool && pt_tool->HasMidpoint(); + }; // clang-format off menu->AddItem( PCB_ACTIONS::healShapes, SELECTION_CONDITIONS::HasTypes( healShapesTypes ) ); @@ -489,175 +470,161 @@ bool EDIT_TOOL::Init() std::shared_ptr gateSwapSubMenu = makeGateSwapMenu( this ); m_selectionTool->GetToolMenu().RegisterSubMenu( gateSwapSubMenu ); - auto positioningToolsCondition = - [this]( const SELECTION& aSel ) - { - std::shared_ptr subMenu = makePositioningToolsMenu( this ); - subMenu->Evaluate( aSel ); - return subMenu->GetMenuItemCount() > 0; - }; + auto positioningToolsCondition = [this]( const SELECTION& aSel ) + { + std::shared_ptr subMenu = makePositioningToolsMenu( this ); + subMenu->Evaluate( aSel ); + return subMenu->GetMenuItemCount() > 0; + }; - auto shapeModificationCondition = - [this]( const SELECTION& aSel ) - { - std::shared_ptr subMenu = makeShapeModificationMenu( this ); - subMenu->Evaluate( aSel ); - return subMenu->GetMenuItemCount() > 0; - }; + auto shapeModificationCondition = [this]( const SELECTION& aSel ) + { + std::shared_ptr subMenu = makeShapeModificationMenu( this ); + subMenu->Evaluate( aSel ); + return subMenu->GetMenuItemCount() > 0; + }; // Does selection map to a single eligible footprint and exactly one unit? - auto gateSwapSingleUnitOnOneFootprint = - []( const SELECTION& aSelection ) - { - const FOOTPRINT* fp = GATE_SWAP_MENU::GetSingleEligibleFootprint( aSelection ); + auto gateSwapSingleUnitOnOneFootprint = []( const SELECTION& aSelection ) + { + const FOOTPRINT* fp = GATE_SWAP_MENU::GetSingleEligibleFootprint( aSelection ); - if( !fp ) - return false; + if( !fp ) + return false; - std::unordered_set selPadNums = GATE_SWAP_MENU::CollectSelectedPadNumbers( aSelection, fp ); + std::unordered_set selPadNums = GATE_SWAP_MENU::CollectSelectedPadNumbers( aSelection, fp ); - std::vector unitsHit = GATE_SWAP_MENU::GetUnitsHitIndices( fp, selPadNums ); + std::vector unitsHit = GATE_SWAP_MENU::GetUnitsHitIndices( fp, selPadNums ); - if( unitsHit.size() != 1 ) - return false; + if( unitsHit.size() != 1 ) + return false; - const int sourceIdx = unitsHit.front(); - std::vector targets = GATE_SWAP_MENU::GetCompatibleTargets( fp, sourceIdx ); - return !targets.empty(); - }; + const int sourceIdx = unitsHit.front(); + std::vector targets = GATE_SWAP_MENU::GetCompatibleTargets( fp, sourceIdx ); + return !targets.empty(); + }; // Does selection map to a single eligible footprint and more than one unit with equal pin counts? - auto gateSwapMultipleUnitsOnOneFootprint = - []( const SELECTION& aSelection ) + auto gateSwapMultipleUnitsOnOneFootprint = []( const SELECTION& aSelection ) + { + const FOOTPRINT* fp = GATE_SWAP_MENU::GetSingleEligibleFootprint( aSelection ); + + if( !fp ) + return false; + + std::unordered_set selPadNums = GATE_SWAP_MENU::CollectSelectedPadNumbers( aSelection, fp ); + + std::vector unitsHit = GATE_SWAP_MENU::GetUnitsHitIndices( fp, selPadNums ); + + if( unitsHit.size() < 2 ) + return false; + + return GATE_SWAP_MENU::EqualPinCounts( fp, unitsHit ); + }; + + auto propertiesCondition = [this]( const SELECTION& aSel ) + { + if( aSel.GetSize() == 0 ) + { + if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) ) { - const FOOTPRINT* fp = GATE_SWAP_MENU::GetSingleEligibleFootprint( aSelection ); + DS_PROXY_VIEW_ITEM* ds = canvas()->GetDrawingSheet(); + VECTOR2D cursor = getViewControls()->GetCursorPosition( false ); - if( !fp ) - return false; - - std::unordered_set selPadNums = GATE_SWAP_MENU::CollectSelectedPadNumbers( aSelection, fp ); - - std::vector unitsHit = GATE_SWAP_MENU::GetUnitsHitIndices( fp, selPadNums ); - - if( unitsHit.size() < 2 ) - return false; - - return GATE_SWAP_MENU::EqualPinCounts( fp, unitsHit ); - }; - - auto propertiesCondition = - [this]( const SELECTION& aSel ) - { - if( aSel.GetSize() == 0 ) - { - if( getView()->IsLayerVisible( LAYER_SCHEMATIC_DRAWINGSHEET ) ) - { - DS_PROXY_VIEW_ITEM* ds = canvas()->GetDrawingSheet(); - VECTOR2D cursor = getViewControls()->GetCursorPosition( false ); - - if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) ) - return true; - } - - return false; - } - - if( aSel.GetSize() == 1 ) + if( ds && ds->HitTestDrawingSheetItems( getView(), cursor ) ) return true; + } - for( EDA_ITEM* item : aSel ) - { - if( !dynamic_cast( item ) ) - return false; - } + return false; + } - return true; - }; - - auto inFootprintEditor = - [this]( const SELECTION& aSelection ) - { - return m_isFootprintEditor; - }; - - auto canMirror = - [this]( const SELECTION& aSelection ) - { - if( !m_isFootprintEditor - && SELECTION_CONDITIONS::OnlyTypes( padTypes )( aSelection ) ) - { - return false; - } - - if( SELECTION_CONDITIONS::HasTypes( groupTypes )( aSelection ) ) - return true; - - return SELECTION_CONDITIONS::HasTypes( EDIT_TOOL::MirrorableItems )( aSelection ); - }; - - auto singleFootprintCondition = SELECTION_CONDITIONS::OnlyTypes( footprintTypes ) - && SELECTION_CONDITIONS::Count( 1 ); - - auto multipleFootprintsCondition = - []( const SELECTION& aSelection ) - { - bool foundFirst = false; - - for( EDA_ITEM* item : aSelection ) - { - if( item->Type() == PCB_FOOTPRINT_T ) - { - if( foundFirst ) - return true; - else - foundFirst = true; - } - } + if( aSel.GetSize() == 1 ) + return true; + for( EDA_ITEM* item : aSel ) + { + if( !dynamic_cast( item ) ) return false; - }; + } - auto noActiveToolCondition = - [this]( const SELECTION& aSelection ) + return true; + }; + + auto inFootprintEditor = [this]( const SELECTION& aSelection ) + { + return m_isFootprintEditor; + }; + + auto canMirror = [this]( const SELECTION& aSelection ) + { + if( !m_isFootprintEditor && SELECTION_CONDITIONS::OnlyTypes( padTypes )( aSelection ) ) + { + return false; + } + + if( SELECTION_CONDITIONS::HasTypes( groupTypes )( aSelection ) ) + return true; + + return SELECTION_CONDITIONS::HasTypes( EDIT_TOOL::MirrorableItems )( aSelection ); + }; + + auto singleFootprintCondition = + SELECTION_CONDITIONS::OnlyTypes( footprintTypes ) && SELECTION_CONDITIONS::Count( 1 ); + + auto multipleFootprintsCondition = []( const SELECTION& aSelection ) + { + bool foundFirst = false; + + for( EDA_ITEM* item : aSelection ) + { + if( item->Type() == PCB_FOOTPRINT_T ) { - return frame()->ToolStackIsEmpty(); - }; + if( foundFirst ) + return true; + else + foundFirst = true; + } + } - auto notMovingCondition = - []( const SELECTION& aSelection ) - { - return aSelection.Empty() || !aSelection.Front()->IsMoving(); - }; + return false; + }; - auto noItemsCondition = - [this]( const SELECTION& aSelections ) -> bool - { - return frame()->GetBoard() && !frame()->GetBoard()->IsEmpty(); - }; + auto noActiveToolCondition = [this]( const SELECTION& aSelection ) + { + return frame()->ToolStackIsEmpty(); + }; - auto isSkippable = - [this]( const SELECTION& aSelection ) - { - return frame()->IsCurrentTool( PCB_ACTIONS::moveIndividually ); - }; + auto notMovingCondition = []( const SELECTION& aSelection ) + { + return aSelection.Empty() || !aSelection.Front()->IsMoving(); + }; - SELECTION_CONDITION isRoutable = SELECTION_CONDITIONS::NotEmpty - && SELECTION_CONDITIONS::HasTypes( routableTypes ) - && notMovingCondition - && !inFootprintEditor; + auto noItemsCondition = [this]( const SELECTION& aSelections ) -> bool + { + return frame()->GetBoard() && !frame()->GetBoard()->IsEmpty(); + }; + + auto isSkippable = [this]( const SELECTION& aSelection ) + { + return frame()->IsCurrentTool( PCB_ACTIONS::moveIndividually ); + }; + + SELECTION_CONDITION isRoutable = SELECTION_CONDITIONS::NotEmpty && SELECTION_CONDITIONS::HasTypes( routableTypes ) + && notMovingCondition && !inFootprintEditor; const auto canCopyAsText = SELECTION_CONDITIONS::NotEmpty - && SELECTION_CONDITIONS::OnlyTypes( { PCB_FIELD_T, - PCB_TEXT_T, - PCB_TEXTBOX_T, - PCB_DIM_ALIGNED_T, - PCB_DIM_LEADER_T, - PCB_DIM_CENTER_T, - PCB_DIM_RADIAL_T, - PCB_DIM_ORTHOGONAL_T, - PCB_TABLE_T, - PCB_TABLECELL_T, - } ); + && SELECTION_CONDITIONS::OnlyTypes( { + PCB_FIELD_T, + PCB_TEXT_T, + PCB_TEXTBOX_T, + PCB_DIM_ALIGNED_T, + PCB_DIM_LEADER_T, + PCB_DIM_CENTER_T, + PCB_DIM_RADIAL_T, + PCB_DIM_ORTHOGONAL_T, + PCB_TABLE_T, + PCB_TABLECELL_T, + } ); // Add context menu entries that are displayed when selection tool is active CONDITIONAL_MENU& menu = m_selectionTool->GetToolMenu().GetMenu(); @@ -873,24 +840,23 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent ) std::vector footprints; // Gather items from the collector into per-type vectors - const auto gatherItemsByType = - [&]() + const auto gatherItemsByType = [&]() + { + for( EDA_ITEM* item : aCollector ) + { + if( PCB_TRACK* track = dynamic_cast( item ) ) { - for( EDA_ITEM* item : aCollector ) - { - if( PCB_TRACK* track = dynamic_cast( item ) ) - { - if( track->Type() == PCB_VIA_T ) - vias.push_back( track ); - else - tracks.push_back( track ); - } - else if( FOOTPRINT* footprint = dynamic_cast( item ) ) - { - footprints.push_back( footprint ); - } - } - }; + if( track->Type() == PCB_VIA_T ) + vias.push_back( track ); + else + tracks.push_back( track ); + } + else if( FOOTPRINT* footprint = dynamic_cast( item ) ) + { + footprints.push_back( footprint ); + } + } + }; // Initial gathering of items gatherItemsByType(); @@ -927,14 +893,14 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent ) * disambiguation menu when it doesn't matter which items is picked. */ auto connected = []( PCB_TRACK* track, const VECTOR2I& pt ) - { - return track->GetStart() == pt || track->GetEnd() == pt; - }; + { + return track->GetStart() == pt || track->GetEnd() == pt; + }; if( tracks.size() == 2 && vias.size() == 0 ) { if( connected( tracks[0], tracks[1]->GetStart() ) - || connected( tracks[0], tracks[1]->GetEnd() ) ) + || connected( tracks[0], tracks[1]->GetEnd() ) ) { aCollector.Remove( tracks[1] ); } @@ -942,7 +908,7 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent ) else if( tracks.size() == 2 && vias.size() == 1 ) { if( connected( tracks[0], vias[0]->GetPosition() ) - && connected( tracks[1], vias[0]->GetPosition() ) ) + && connected( tracks[1], vias[0]->GetPosition() ) ) { aCollector.Remove( tracks[0] ); aCollector.Remove( tracks[1] ); @@ -997,8 +963,8 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) controls->ShowCursor( true ); controls->SetAutoPan( true ); - BOARD_COMMIT commit( this ); - bool restore_state = false; + BOARD_COMMIT commit( this ); + bool restore_state = false; commit.Modify( theArc ); @@ -1019,61 +985,58 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) std::set addedTracks; - auto getUniqueTrackAtAnchorCollinear = - [&]( const VECTOR2I& aAnchor, const SEG& aCollinearSeg ) -> PCB_TRACK* - { - std::shared_ptr conn = board()->GetConnectivity(); + auto getUniqueTrackAtAnchorCollinear = [&]( const VECTOR2I& aAnchor, const SEG& aCollinearSeg ) -> PCB_TRACK* + { + std::shared_ptr conn = board()->GetConnectivity(); - // Allow items at a distance within the width of the arc track - int allowedDeviation = theArc->GetWidth(); + // Allow items at a distance within the width of the arc track + int allowedDeviation = theArc->GetWidth(); - std::vector itemsOnAnchor; + std::vector itemsOnAnchor; - for( int i = 0; i < 3; i++ ) - { - itemsOnAnchor = conn->GetConnectedItemsAtAnchor( theArc, aAnchor, - baseConnectedTypes, - allowedDeviation ); - allowedDeviation /= 2; + for( int i = 0; i < 3; i++ ) + { + itemsOnAnchor = conn->GetConnectedItemsAtAnchor( theArc, aAnchor, baseConnectedTypes, allowedDeviation ); + allowedDeviation /= 2; - if( itemsOnAnchor.size() == 1 ) - break; - } + if( itemsOnAnchor.size() == 1 ) + break; + } - PCB_TRACK* track = nullptr; + PCB_TRACK* track = nullptr; - if( itemsOnAnchor.size() == 1 && itemsOnAnchor.front()->Type() == PCB_TRACE_T ) - { - track = static_cast( itemsOnAnchor.front() ); - commit.Modify( track ); + if( itemsOnAnchor.size() == 1 && itemsOnAnchor.front()->Type() == PCB_TRACE_T ) + { + track = static_cast( itemsOnAnchor.front() ); + commit.Modify( track ); - SEG trackSeg( track->GetStart(), track->GetEnd() ); + SEG trackSeg( track->GetStart(), track->GetEnd() ); - // Allow deviations in colinearity as defined in ADVANCED_CFG - if( trackSeg.Angle( aCollinearSeg ) > maxTangentDeviation ) - track = nullptr; - } + // Allow deviations in colinearity as defined in ADVANCED_CFG + if( trackSeg.Angle( aCollinearSeg ) > maxTangentDeviation ) + track = nullptr; + } - if( !track ) - { - track = new PCB_TRACK( theArc->GetParent() ); - track->SetStart( aAnchor ); - track->SetEnd( aAnchor ); - track->SetNet( theArc->GetNet() ); - track->SetLayer( theArc->GetLayer() ); - track->SetWidth( theArc->GetWidth() ); - track->SetLocked( theArc->IsLocked() ); - track->SetHasSolderMask( theArc->HasSolderMask() ); - track->SetLocalSolderMaskMargin( theArc->GetLocalSolderMaskMargin() ); - track->SetFlags( IS_NEW ); - getView()->Add( track ); - addedTracks.insert( track ); - } + if( !track ) + { + track = new PCB_TRACK( theArc->GetParent() ); + track->SetStart( aAnchor ); + track->SetEnd( aAnchor ); + track->SetNet( theArc->GetNet() ); + track->SetLayer( theArc->GetLayer() ); + track->SetWidth( theArc->GetWidth() ); + track->SetLocked( theArc->IsLocked() ); + track->SetHasSolderMask( theArc->HasSolderMask() ); + track->SetLocalSolderMaskMargin( theArc->GetLocalSolderMaskMargin() ); + track->SetFlags( IS_NEW ); + getView()->Add( track ); + addedTracks.insert( track ); + } - return track; - }; + return track; + }; - PCB_TRACK* trackOnStart = getUniqueTrackAtAnchorCollinear( theArc->GetStart(), tanStart); + PCB_TRACK* trackOnStart = getUniqueTrackAtAnchorCollinear( theArc->GetStart(), tanStart ); PCB_TRACK* trackOnEnd = getUniqueTrackAtAnchorCollinear( theArc->GetEnd(), tanEnd ); if( trackOnStart->GetLength() != 0 ) @@ -1092,14 +1055,13 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) if( tanIntersect = tanStart.IntersectLines( tanEnd ); !tanIntersect ) return 0; - auto isTrackStartClosestToArcStart = - [&]( PCB_TRACK* aTrack ) -> bool - { - double trackStartToArcStart = aTrack->GetStart().Distance( theArc->GetStart() ); - double trackEndToArcStart = aTrack->GetEnd().Distance( theArc->GetStart() ); + auto isTrackStartClosestToArcStart = [&]( PCB_TRACK* aTrack ) -> bool + { + double trackStartToArcStart = aTrack->GetStart().Distance( theArc->GetStart() ); + double trackEndToArcStart = aTrack->GetEnd().Distance( theArc->GetStart() ); - return trackStartToArcStart < trackEndToArcStart; - }; + return trackStartToArcStart < trackEndToArcStart; + }; bool isStartTrackOnStartPt = isTrackStartClosestToArcStart( trackOnStart ); bool isEndTrackOnStartPt = isTrackStartClosestToArcStart( trackOnEnd ); @@ -1131,19 +1093,17 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) // * * // - auto getFurthestPointToTanInterstect = - [&]( VECTOR2I& aPointA, VECTOR2I& aPointB ) -> VECTOR2I - { - if( ( aPointA - *tanIntersect ).EuclideanNorm() - > ( aPointB - *tanIntersect ).EuclideanNorm() ) - { - return aPointA; - } - else - { - return aPointB; - } - }; + auto getFurthestPointToTanInterstect = [&]( VECTOR2I& aPointA, VECTOR2I& aPointB ) -> VECTOR2I + { + if( ( aPointA - *tanIntersect ).EuclideanNorm() > ( aPointB - *tanIntersect ).EuclideanNorm() ) + { + return aPointA; + } + else + { + return aPointB; + } + }; CIRCLE maxTanCircle; VECTOR2I tanStartPoint = getFurthestPointToTanInterstect( tanStart.A, tanStart.B ); @@ -1173,8 +1133,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) m_cursor = controls->GetMousePosition(); // Constrain cursor within the isosceles triangle - if( cSegTanStartSide != cSegTanStart.Side( m_cursor ) - || cSegTanEndSide != cSegTanEnd.Side( m_cursor ) + if( cSegTanStartSide != cSegTanStart.Side( m_cursor ) || cSegTanEndSide != cSegTanEnd.Side( m_cursor ) || cSegChordSide != cSegChord.Side( m_cursor ) ) { std::vector possiblePoints; @@ -1186,8 +1145,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) for( const VECTOR2I& candidate : possiblePoints ) { - if( ( candidate - m_cursor ).SquaredEuclideanNorm() - < ( closest - m_cursor ).SquaredEuclideanNorm() ) + if( ( candidate - m_cursor ).SquaredEuclideanNorm() < ( closest - m_cursor ).SquaredEuclideanNorm() ) { closest = candidate; } @@ -1246,8 +1204,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) restore_state = true; // Perform undo locally break; // Finish } - else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) - || evt->IsDblClick( BUT_LEFT ) ) + else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) { // Eat mouse-up/-click events that leaked through from the lock dialog if( eatFirstMouseUp && !evt->IsAction( &ACTIONS::cursorClick ) ) @@ -1270,8 +1227,7 @@ int EDIT_TOOL::DragArcTrack( const TOOL_EVENT& aEvent ) if( isEndTrackOnStartPt ) newEnd = trackOnEnd->GetEnd(); - int maxLengthIU = - KiROUND( ADVANCED_CFG::GetCfg().m_MaxTrackLengthToKeep * pcbIUScale.IU_PER_MM ); + int maxLengthIU = KiROUND( ADVANCED_CFG::GetCfg().m_MaxTrackLengthToKeep * pcbIUScale.IU_PER_MM ); if( trackOnStart->GetLength() <= maxLengthIU ) { @@ -1332,7 +1288,7 @@ int EDIT_TOOL::ChangeTrackWidth( const TOOL_EVENT& aEvent ) // Iterate from the back so we don't have to worry about removals. for( int i = aCollector.GetCount() - 1; i >= 0; --i ) { - BOARD_ITEM* item = aCollector[ i ]; + BOARD_ITEM* item = aCollector[i]; if( !dynamic_cast( item ) ) aCollector.Remove( item ); @@ -1500,51 +1456,49 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent ) PCB_TRACK* t1; PCB_TRACK* t2; // Start point of track is modified after PCB_ARC is added, otherwise the end point: - bool t1Start = true; - bool t2Start = true; + bool t1Start = true; + bool t2Start = true; }; std::vector filletOperations; bool operationPerformedOnAtLeastOne = false; - bool didOneAttemptFail = false; + bool didOneAttemptFail = false; std::set processedTracks; - auto processFilletOp = - [&]( PCB_TRACK* aTrack, bool aStartPoint ) + auto processFilletOp = [&]( PCB_TRACK* aTrack, bool aStartPoint ) + { + std::shared_ptr c = board()->GetConnectivity(); + VECTOR2I anchor = aStartPoint ? aTrack->GetStart() : aTrack->GetEnd(); + std::vector itemsOnAnchor; + + itemsOnAnchor = c->GetConnectedItemsAtAnchor( aTrack, anchor, baseConnectedTypes ); + + if( itemsOnAnchor.size() > 0 && selection.Contains( itemsOnAnchor.at( 0 ) ) + && itemsOnAnchor.at( 0 )->Type() == PCB_TRACE_T ) + { + PCB_TRACK* trackOther = static_cast( itemsOnAnchor.at( 0 ) ); + + // Make sure we don't fillet the same pair of tracks twice + if( processedTracks.find( trackOther ) == processedTracks.end() ) { - std::shared_ptr c = board()->GetConnectivity(); - VECTOR2I anchor = aStartPoint ? aTrack->GetStart() : aTrack->GetEnd(); - std::vector itemsOnAnchor; - - itemsOnAnchor = c->GetConnectedItemsAtAnchor( aTrack, anchor, baseConnectedTypes ); - - if( itemsOnAnchor.size() > 0 - && selection.Contains( itemsOnAnchor.at( 0 ) ) - && itemsOnAnchor.at( 0 )->Type() == PCB_TRACE_T ) + if( itemsOnAnchor.size() == 1 ) { - PCB_TRACK* trackOther = static_cast( itemsOnAnchor.at( 0 ) ); - - // Make sure we don't fillet the same pair of tracks twice - if( processedTracks.find( trackOther ) == processedTracks.end() ) - { - if( itemsOnAnchor.size() == 1 ) - { - FILLET_OP filletOp; - filletOp.t1 = aTrack; - filletOp.t2 = trackOther; - filletOp.t1Start = aStartPoint; - filletOp.t2Start = aTrack->IsPointOnEnds( filletOp.t2->GetStart() ); - filletOperations.push_back( filletOp ); - } - else - { - // User requested to fillet these two tracks but not possible as - // there are other elements connected at that point - didOneAttemptFail = true; - } - } + FILLET_OP filletOp; + filletOp.t1 = aTrack; + filletOp.t2 = trackOther; + filletOp.t1Start = aStartPoint; + filletOp.t2Start = aTrack->IsPointOnEnds( filletOp.t2->GetStart() ); + filletOperations.push_back( filletOp ); } - }; + else + { + // User requested to fillet these two tracks but not possible as + // there are other elements connected at that point + didOneAttemptFail = true; + } + } + } + }; for( EDA_ITEM* item : selection ) { @@ -1554,7 +1508,7 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent ) if( track->GetLength() > 0 ) { - processFilletOp( track, true ); // on the start point of track + processFilletOp( track, true ); // on the start point of track processFilletOp( track, false ); // on the end point of track processedTracks.insert( track ); @@ -1571,7 +1525,7 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent ) PCB_TRACK* track2 = filletOp.t2; bool trackOnStart = track1->IsPointOnEnds( track2->GetStart() ); - bool trackOnEnd = track1->IsPointOnEnds( track2->GetEnd() ); + bool trackOnEnd = track1->IsPointOnEnds( track2->GetEnd() ); if( trackOnStart && trackOnEnd ) continue; // Ignore duplicate tracks @@ -1587,32 +1541,31 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent ) SHAPE_ARC sArc( t1Seg, t2Seg, filletRadius ); VECTOR2I t1newPoint, t2newPoint; - auto setIfPointOnSeg = - []( VECTOR2I& aPointToSet, const SEG& aSegment, const VECTOR2I& aVecToTest ) - { - VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest; + auto setIfPointOnSeg = []( VECTOR2I& aPointToSet, const SEG& aSegment, const VECTOR2I& aVecToTest ) + { + VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest; - // Find out if we are on the segment (minimum precision) - if( segToVec.EuclideanNorm() < SHAPE_ARC::MIN_PRECISION_IU ) - { - aPointToSet.x = aVecToTest.x; - aPointToSet.y = aVecToTest.y; - return true; - } + // Find out if we are on the segment (minimum precision) + if( segToVec.EuclideanNorm() < SHAPE_ARC::MIN_PRECISION_IU ) + { + aPointToSet.x = aVecToTest.x; + aPointToSet.y = aVecToTest.y; + return true; + } - return false; - }; + return false; + }; //Do not draw a fillet if the end points of the arc are not within the track segments if( !setIfPointOnSeg( t1newPoint, t1Seg, sArc.GetP0() ) - && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP0() ) ) + && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP0() ) ) { didOneAttemptFail = true; continue; } if( !setIfPointOnSeg( t1newPoint, t1Seg, sArc.GetP1() ) - && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP1() ) ) + && !setIfPointOnSeg( t2newPoint, t2Seg, sArc.GetP1() ) ) { didOneAttemptFail = true; continue; @@ -1669,8 +1622,7 @@ int EDIT_TOOL::FilletTracks( const TOOL_EVENT& aEvent ) * @return std::optional the radius or std::nullopt if no * valid radius specified */ -static std::optional GetRadiusParams( PCB_BASE_EDIT_FRAME& aFrame, const wxString& aTitle, - int& aPersitentRadius ) +static std::optional GetRadiusParams( PCB_BASE_EDIT_FRAME& aFrame, const wxString& aTitle, int& aPersitentRadius ) { WX_UNIT_ENTRY_DIALOG dlg( &aFrame, aTitle, _( "Radius:" ), aPersitentRadius ); @@ -1683,8 +1635,7 @@ static std::optional GetRadiusParams( PCB_BASE_EDIT_FRAME& aFrame, const wx } -static std::optional -GetDogboneParams( PCB_BASE_EDIT_FRAME& aFrame ) +static std::optional GetDogboneParams( PCB_BASE_EDIT_FRAME& aFrame ) { // Persistent parameters static DOGBONE_CORNER_ROUTINE::PARAMETERS s_dogBoneParams{ @@ -1742,8 +1693,7 @@ static std::optional GetChamferParams( PCB_BASE_EDIT_FRAME& aFra // Store last used setback to allow pressing "enter" if repeat chamfer is required static CHAMFER_PARAMS params{ default_setback, default_setback }; - WX_UNIT_ENTRY_DIALOG dlg( &aFrame, _( "Chamfer Lines" ), _( "Chamfer setback:" ), - params.m_chamfer_setback_a ); + WX_UNIT_ENTRY_DIALOG dlg( &aFrame, _( "Chamfer Lines" ), _( "Chamfer setback:" ), params.m_chamfer_setback_a ); if( dlg.ShowModal() == wxID_CANCEL || dlg.GetValue() == 0 ) return std::nullopt; @@ -1771,9 +1721,8 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) // We've converted the polygon and rectangle to segments, so drop everything // that isn't a segment at this point - if( !item->IsType( { PCB_SHAPE_LOCATE_SEGMENT_T, - PCB_SHAPE_LOCATE_POLY_T, - PCB_SHAPE_LOCATE_RECT_T } ) ) + if( !item->IsType( + { PCB_SHAPE_LOCATE_SEGMENT_T, PCB_SHAPE_LOCATE_POLY_T, PCB_SHAPE_LOCATE_RECT_T } ) ) { aCollector.Remove( item ); } @@ -1788,9 +1737,9 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) for( EDA_ITEM* item : selection ) { std::vector pts; - PCB_SHAPE *graphic = static_cast( item ); - PCB_LAYER_ID layer = graphic->GetLayer(); - int width = graphic->GetWidth(); + PCB_SHAPE* graphic = static_cast( item ); + PCB_LAYER_ID layer = graphic->GetLayer(); + int width = graphic->GetWidth(); if( graphic->GetShape() == SHAPE_T::RECTANGLE ) { @@ -1813,7 +1762,7 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) for( size_t jj = 1; jj < pts.size(); ++jj ) { - PCB_SHAPE *line = new PCB_SHAPE( frame()->GetModel(), SHAPE_T::SEGMENT ); + PCB_SHAPE* line = new PCB_SHAPE( frame()->GetModel(), SHAPE_T::SEGMENT ); line->SetStart( pts[jj - 1] ); line->SetEnd( pts[jj] ); @@ -1824,7 +1773,7 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) if( pts.size() > 1 ) { - PCB_SHAPE *line = new PCB_SHAPE( frame()->GetModel(), SHAPE_T::SEGMENT ); + PCB_SHAPE* line = new PCB_SHAPE( frame()->GetModel(), SHAPE_T::SEGMENT ); line->SetStart( pts.back() ); line->SetEnd( pts.front() ); @@ -1884,39 +1833,36 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) // Handle modifications to existing items by the routine // How to deal with this depends on whether we're in the footprint editor or not // and whether the item was conjured up by decomposing a polygon or rectangle - auto item_modification_handler = - [&]( BOARD_ITEM& aItem ) - { - // If the item was "conjured up" it will be added later separately - if( !alg::contains( lines_to_add, &aItem ) ) - { - commit.Modify( &aItem ); - items_to_select_on_success.push_back( &aItem ); - } - }; + auto item_modification_handler = [&]( BOARD_ITEM& aItem ) + { + // If the item was "conjured up" it will be added later separately + if( !alg::contains( lines_to_add, &aItem ) ) + { + commit.Modify( &aItem ); + items_to_select_on_success.push_back( &aItem ); + } + }; bool any_items_created = !lines_to_add.empty(); - auto item_creation_handler = - [&]( std::unique_ptr aItem ) - { - any_items_created = true; - items_to_select_on_success.push_back( aItem.get() ); - commit.Add( aItem.release() ); - }; + auto item_creation_handler = [&]( std::unique_ptr aItem ) + { + any_items_created = true; + items_to_select_on_success.push_back( aItem.get() ); + commit.Add( aItem.release() ); + }; bool any_items_removed = !items_to_remove.empty(); - auto item_removal_handler = - [&]( BOARD_ITEM& aItem ) - { - aItem.SetFlags( STRUCT_DELETED ); - any_items_removed = true; - items_to_deselect_on_success.push_back( &aItem ); - commit.Remove( &aItem ); - }; + auto item_removal_handler = [&]( BOARD_ITEM& aItem ) + { + aItem.SetFlags( STRUCT_DELETED ); + any_items_removed = true; + items_to_deselect_on_success.push_back( &aItem ); + commit.Remove( &aItem ); + }; // Combine these callbacks into a CHANGE_HANDLER to inject in the ROUTINE - ITEM_MODIFICATION_ROUTINE::CALLABLE_BASED_HANDLER change_handler( - item_creation_handler, item_modification_handler, item_removal_handler ); + ITEM_MODIFICATION_ROUTINE::CALLABLE_BASED_HANDLER change_handler( item_creation_handler, item_modification_handler, + item_removal_handler ); // Construct an appropriate tool std::unique_ptr pairwise_line_routine; @@ -1924,24 +1870,22 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) if( aEvent.IsAction( &PCB_ACTIONS::filletLines ) ) { static int s_filletRadius = pcbIUScale.mmToIU( 1 ); - std::optional filletRadiusIU = - GetRadiusParams( *frame(), _( "Fillet Lines" ), s_filletRadius ); + std::optional filletRadiusIU = GetRadiusParams( *frame(), _( "Fillet Lines" ), s_filletRadius ); if( filletRadiusIU.has_value() ) { - pairwise_line_routine = std::make_unique( - frame()->GetModel(), change_handler, *filletRadiusIU ); + pairwise_line_routine = + std::make_unique( frame()->GetModel(), change_handler, *filletRadiusIU ); } } else if( aEvent.IsAction( &PCB_ACTIONS::dogboneCorners ) ) { - std::optional dogboneParams = - GetDogboneParams( *frame() ); + std::optional dogboneParams = GetDogboneParams( *frame() ); if( dogboneParams.has_value() ) { - pairwise_line_routine = std::make_unique( - frame()->GetModel(), change_handler, *dogboneParams ); + pairwise_line_routine = + std::make_unique( frame()->GetModel(), change_handler, *dogboneParams ); } } else if( aEvent.IsAction( &PCB_ACTIONS::chamferLines ) ) @@ -1950,15 +1894,13 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) if( chamfer_params.has_value() ) { - pairwise_line_routine = std::make_unique( frame()->GetModel(), - change_handler, - *chamfer_params ); + pairwise_line_routine = + std::make_unique( frame()->GetModel(), change_handler, *chamfer_params ); } } else if( aEvent.IsAction( &PCB_ACTIONS::extendLines ) ) { - pairwise_line_routine = std::make_unique( frame()->GetModel(), - change_handler ); + pairwise_line_routine = std::make_unique( frame()->GetModel(), change_handler ); } if( !pairwise_line_routine ) @@ -1972,8 +1914,7 @@ int EDIT_TOOL::ModifyLines( const TOOL_EVENT& aEvent ) alg::for_all_pairs( selection.begin(), selection.end(), [&]( EDA_ITEM* a, EDA_ITEM* b ) { - if( ( a->GetFlags() & STRUCT_DELETED ) == 0 - && ( b->GetFlags() & STRUCT_DELETED ) == 0 ) + if( ( a->GetFlags() & STRUCT_DELETED ) == 0 && ( b->GetFlags() & STRUCT_DELETED ) == 0 ) { PCB_SHAPE* line_a = static_cast( a ); PCB_SHAPE* line_b = static_cast( b ); @@ -2036,8 +1977,7 @@ int EDIT_TOOL::SimplifyPolygons( const TOOL_EVENT& aEvent ) // Store last used value static int s_toleranceValue = pcbIUScale.mmToIU( 3 ); - WX_UNIT_ENTRY_DIALOG dlg( frame(), _( "Simplify Shapes" ), _( "Tolerance value:" ), - s_toleranceValue ); + WX_UNIT_ENTRY_DIALOG dlg( frame(), _( "Simplify Shapes" ), _( "Tolerance value:" ), s_toleranceValue ); if( dlg.ShowModal() == wxID_CANCEL ) return 0; @@ -2049,7 +1989,7 @@ int EDIT_TOOL::SimplifyPolygons( const TOOL_EVENT& aEvent ) BOARD_COMMIT commit{ this }; - std::vector shapeList; + std::vector shapeList; for( EDA_ITEM* item : selection ) { @@ -2093,8 +2033,8 @@ int EDIT_TOOL::HealShapes( const TOOL_EVENT& aEvent ) // We've converted the polygon and rectangle to segments, so drop everything // that isn't a segment at this point - if( !item->IsType( { PCB_SHAPE_LOCATE_SEGMENT_T, PCB_SHAPE_LOCATE_ARC_T, - PCB_SHAPE_LOCATE_BEZIER_T } ) ) + if( !item->IsType( + { PCB_SHAPE_LOCATE_SEGMENT_T, PCB_SHAPE_LOCATE_ARC_T, PCB_SHAPE_LOCATE_BEZIER_T } ) ) { aCollector.Remove( item ); } @@ -2106,8 +2046,7 @@ int EDIT_TOOL::HealShapes( const TOOL_EVENT& aEvent ) // Store last used value static int s_toleranceValue = pcbIUScale.mmToIU( 3 ); - WX_UNIT_ENTRY_DIALOG dlg( frame(), _( "Heal Shapes" ), _( "Tolerance value:" ), - s_toleranceValue ); + WX_UNIT_ENTRY_DIALOG dlg( frame(), _( "Heal Shapes" ), _( "Tolerance value:" ), s_toleranceValue ); if( dlg.ShowModal() == wxID_CANCEL ) return 0; @@ -2183,30 +2122,26 @@ int EDIT_TOOL::BooleanPolygons( const TOOL_EVENT& aEvent ) BOARD_COMMIT commit{ this }; // Handle modifications to existing items by the routine - auto item_modification_handler = - [&]( BOARD_ITEM& aItem ) - { - commit.Modify( &aItem ); - }; + auto item_modification_handler = [&]( BOARD_ITEM& aItem ) + { + commit.Modify( &aItem ); + }; std::vector items_to_select_on_success; - auto item_creation_handler = - [&]( std::unique_ptr aItem ) - { - items_to_select_on_success.push_back( aItem.get() ); - commit.Add( aItem.release() ); - }; + auto item_creation_handler = [&]( std::unique_ptr aItem ) + { + items_to_select_on_success.push_back( aItem.get() ); + commit.Add( aItem.release() ); + }; - auto item_removal_handler = - [&]( BOARD_ITEM& aItem ) - { - commit.Remove( &aItem ); - }; + auto item_removal_handler = [&]( BOARD_ITEM& aItem ) + { + commit.Remove( &aItem ); + }; // Combine these callbacks into a CHANGE_HANDLER to inject in the ROUTINE - ITEM_MODIFICATION_ROUTINE::CALLABLE_BASED_HANDLER change_handler( item_creation_handler, - item_modification_handler, + ITEM_MODIFICATION_ROUTINE::CALLABLE_BASED_HANDLER change_handler( item_creation_handler, item_modification_handler, item_removal_handler ); // Construct an appropriate routine @@ -2313,7 +2248,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) if( ( SELECTION_CONDITIONS::OnlyTypes( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } ) )( selection ) ) { DIALOG_TRACK_VIA_PROPERTIES dlg( editFrame, selection ); - dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR + dlg.ShowQuasiModal(); // QuasiModal required for NET_SELECTOR } else if( ( SELECTION_CONDITIONS::OnlyTypes( { PCB_TABLECELL_T } ) )( selection ) ) { @@ -2324,14 +2259,15 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) DIALOG_TABLECELL_PROPERTIES dlg( editFrame, cells ); - dlg.ShowModal(); + // QuasiModal required for syntax help and Scintilla auto-complete + dlg.ShowQuasiModal(); if( dlg.GetReturnValue() == DIALOG_TABLECELL_PROPERTIES::TABLECELL_PROPS_EDIT_TABLE ) { PCB_TABLE* table = static_cast( cells[0]->GetParent() ); DIALOG_TABLE_PROPERTIES tableDlg( frame(), table ); - tableDlg.ShowQuasiModal(); // Scintilla's auto-complete requires quasiModal + tableDlg.ShowQuasiModal(); // Scintilla's auto-complete requires quasiModal } } else if( selection.Size() == 1 && selection.Front()->IsBOARD_ITEM() ) @@ -2451,8 +2387,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) return 0; std::optional oldRefPt; - bool is_hover = selection.IsHover(); // N.B. This must be saved before the second - // call to RequestSelection() below + bool is_hover = selection.IsHover(); // N.B. This must be saved before the second + // call to RequestSelection() below if( selection.HasReferencePoint() ) oldRefPt = selection.GetReferencePoint(); @@ -2529,8 +2465,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) int max = coord_limits::max() - COORDS_PADDING; int min = -max; - bool outOfBounds = rotPos.x < min || rotPos.x > max || rotPos.y < min || rotPos.y > max - || rotEnd.x < min || rotEnd.x > max || rotEnd.y < min || rotEnd.y > max; + bool outOfBounds = rotPos.x < min || rotPos.x > max || rotPos.y < min || rotPos.y > max || rotEnd.x < min + || rotEnd.x > max || rotEnd.y < min || rotEnd.y > max; if( !outOfBounds ) { @@ -2602,18 +2538,8 @@ static void mirrorPad( PAD& aPad, const VECTOR2I& aMirrorPoint, FLIP_DIRECTION a const std::vector EDIT_TOOL::MirrorableItems = { - PCB_SHAPE_T, - PCB_FIELD_T, - PCB_TEXT_T, - PCB_TEXTBOX_T, - PCB_ZONE_T, - PCB_PAD_T, - PCB_TRACE_T, - PCB_ARC_T, - PCB_VIA_T, - PCB_GROUP_T, - PCB_GENERATOR_T, - PCB_POINT_T, + PCB_SHAPE_T, PCB_FIELD_T, PCB_TEXT_T, PCB_TEXTBOX_T, PCB_ZONE_T, PCB_PAD_T, + PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_GROUP_T, PCB_GENERATOR_T, PCB_POINT_T, }; @@ -2646,8 +2572,8 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) updateModificationPoint( selection ); VECTOR2I mirrorPoint = selection.GetReferencePoint(); - FLIP_DIRECTION flipDirection = aEvent.IsAction( &PCB_ACTIONS::mirrorV ) ? FLIP_DIRECTION::TOP_BOTTOM - : FLIP_DIRECTION::LEFT_RIGHT; + FLIP_DIRECTION flipDirection = + aEvent.IsAction( &PCB_ACTIONS::mirrorV ) ? FLIP_DIRECTION::TOP_BOTTOM : FLIP_DIRECTION::LEFT_RIGHT; for( EDA_ITEM* item : selection ) { @@ -2659,48 +2585,30 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent ) // modify each object as necessary switch( item->Type() ) { - case PCB_SHAPE_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_SHAPE_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; - case PCB_ZONE_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_ZONE_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; case PCB_FIELD_T: - case PCB_TEXT_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_TEXT_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; - case PCB_TEXTBOX_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_TEXTBOX_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; case PCB_TABLE_T: // JEY TODO: tables break; - case PCB_PAD_T: - mirrorPad( *static_cast( item ), mirrorPoint, flipDirection ); - break; + case PCB_PAD_T: mirrorPad( *static_cast( item ), mirrorPoint, flipDirection ); break; case PCB_TRACE_T: case PCB_ARC_T: - case PCB_VIA_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_VIA_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; - case PCB_GROUP_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_GROUP_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; - case PCB_GENERATOR_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_GENERATOR_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; - case PCB_POINT_T: - static_cast( item )->Mirror( mirrorPoint, flipDirection ); - break; + case PCB_POINT_T: static_cast( item )->Mirror( mirrorPoint, flipDirection ); break; default: // it's likely the commit object is wrong if you get here @@ -2750,16 +2658,15 @@ int EDIT_TOOL::JustifyText( const TOOL_EVENT& aEvent ) if( selection.Empty() ) return 0; - auto setJustify = - [&]( EDA_TEXT* aTextItem ) - { - if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) ) - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); - else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) ) - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); - else - aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); - }; + auto setJustify = [&]( EDA_TEXT* aTextItem ) + { + if( aEvent.Matches( ACTIONS::leftJustify.MakeEvent() ) ) + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); + else if( aEvent.Matches( ACTIONS::centerJustify.MakeEvent() ) ) + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_CENTER ); + else + aTextItem->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); + }; for( EDA_ITEM* item : selection ) { @@ -2965,11 +2872,11 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) case PCB_GROUP_T: board_item->RunOnChildren( - [&commit]( BOARD_ITEM* aItem ) - { - commit.Remove( aItem ); - }, - RECURSE_MODE::RECURSE ); + [&commit]( BOARD_ITEM* aItem ) + { + commit.Remove( aItem ); + }, + RECURSE_MODE::RECURSE ); commit.Remove( board_item ); itemsDeleted++; @@ -2991,7 +2898,7 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) if( !aIsCut && aItems.GetSize() == 1 ) { VECTOR2I curPos = getViewControls()->GetCursorPosition(); - ZONE* zone = static_cast( board_item ); + ZONE* zone = static_cast( board_item ); int outlineIdx, holeIdx; @@ -3075,7 +2982,7 @@ void EDIT_TOOL::DeleteItems( const PCB_SELECTION& aItems, bool aIsCut ) int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) { - PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); editFrame->PushTool( aEvent ); @@ -3084,8 +2991,8 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) // get a copy instead of reference (as we're going to clear the selection before removing items) PCB_SELECTION selectionCopy; - bool isCut = aEvent.Parameter() == PCB_ACTIONS::REMOVE_FLAGS::CUT; - bool isAlt = aEvent.Parameter() == PCB_ACTIONS::REMOVE_FLAGS::ALT; + bool isCut = aEvent.Parameter() == PCB_ACTIONS::REMOVE_FLAGS::CUT; + bool isAlt = aEvent.Parameter() == PCB_ACTIONS::REMOVE_FLAGS::ALT; // If we are in a "Cut" operation, then the copied selection exists already and we want to // delete exactly that; no more, no fewer. Any filtering for locked items must be done in @@ -3117,8 +3024,7 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) sTool->FilterCollectorForLockedItems( aCollector ); } ); - if( !selectionCopy.IsHover() - && m_selectionTool->GetSelection().CountType( PCB_FOOTPRINT_T ) > beforeFPCount ) + if( !selectionCopy.IsHover() && m_selectionTool->GetSelection().CountType( PCB_FOOTPRINT_T ) > beforeFPCount ) { wxBell(); canvas()->Refresh(); @@ -3162,14 +3068,13 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) VECTOR2I translation; EDA_ANGLE rotation; - ROTATION_ANCHOR rotationAnchor = selection.Size() > 1 ? ROTATE_AROUND_SEL_CENTER - : ROTATE_AROUND_ITEM_ANCHOR; + ROTATION_ANCHOR rotationAnchor = selection.Size() > 1 ? ROTATE_AROUND_SEL_CENTER : ROTATE_AROUND_ITEM_ANCHOR; // TODO: Implement a visible bounding border at the edge BOX2I sel_box = selection.GetBoundingBox(); DIALOG_MOVE_EXACT dialog( frame(), translation, rotation, rotationAnchor, sel_box ); - int ret = dialog.ShowModal(); + int ret = dialog.ShowModal(); if( ret == wxID_OK ) { @@ -3198,15 +3103,9 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) switch( rotationAnchor ) { - case ROTATE_AROUND_ITEM_ANCHOR: - boardItem->Rotate( boardItem->GetPosition(), angle ); - break; - case ROTATE_AROUND_SEL_CENTER: - boardItem->Rotate( selCenter, angle ); - break; - case ROTATE_AROUND_USER_ORIGIN: - boardItem->Rotate( frame()->GetScreen()->m_LocalOrigin, angle ); - break; + case ROTATE_AROUND_ITEM_ANCHOR: boardItem->Rotate( boardItem->GetPosition(), angle ); break; + case ROTATE_AROUND_SEL_CENTER: boardItem->Rotate( selCenter, angle ); break; + case ROTATE_AROUND_USER_ORIGIN: boardItem->Rotate( frame()->GetScreen()->m_LocalOrigin, angle ); break; case ROTATE_AROUND_AUX_ORIGIN: boardItem->Rotate( board()->GetDesignSettings().GetAuxOrigin(), angle ); break; @@ -3246,13 +3145,13 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) // Be sure that there is at least one item that we can modify const PCB_SELECTION& selection = m_selectionTool->RequestSelection( - []( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) - { - sTool->FilterCollectorForMarkers( aCollector ); - sTool->FilterCollectorForHierarchy( aCollector, true ); - sTool->FilterCollectorForFreePads( aCollector, true ); - sTool->FilterCollectorForTableCells( aCollector ); - } ); + []( const VECTOR2I&, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool ) + { + sTool->FilterCollectorForMarkers( aCollector ); + sTool->FilterCollectorForHierarchy( aCollector, true ); + sTool->FilterCollectorForFreePads( aCollector, true ); + sTool->FilterCollectorForTableCells( aCollector ); + } ); if( selection.Empty() ) return 0; @@ -3335,7 +3234,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) if( increment && static_cast( dupe_item )->CanHaveNumber() ) { PAD_TOOL* padTool = m_toolMgr->GetTool(); - wxString padNumber = padTool->GetLastPadNumber(); + wxString padNumber = padTool->GetLastPadNumber(); padNumber = parentFootprint->GetNextPadNumber( padNumber ); padTool->SetLastPadNumber( padNumber ); static_cast( dupe_item )->SetNumber( padNumber ); @@ -3371,9 +3270,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) commit.Add( dupe_item ); break; - default: - UNIMPLEMENTED_FOR( orig_item->GetClass() ); - break; + default: UNIMPLEMENTED_FOR( orig_item->GetClass() ); break; } } } @@ -3415,11 +3312,8 @@ int EDIT_TOOL::Increment( const TOOL_EVENT& aEvent ) switch( aCollector[i]->Type() ) { case PCB_PAD_T: - case PCB_TEXT_T: - break; - default: - aCollector.Remove( i ); - break; + case PCB_TEXT_T: break; + default: aCollector.Remove( i ); break; } } @@ -3484,8 +3378,7 @@ int EDIT_TOOL::Increment( const TOOL_EVENT& aEvent ) break; } - default: - break; + default: break; } } @@ -3549,7 +3442,7 @@ bool EDIT_TOOL::updateModificationPoint( PCB_SELECTION& aSelection ) for( EDA_ITEM* item : aSelection.Items() ) { - if( !item->IsType( { PCB_TEXT_T, PCB_FIELD_T } ) ) + if( !item->IsType( { PCB_TEXT_T, PCB_FIELD_T } ) ) nonFieldsBBox.Merge( item->GetBoundingBox() ); } @@ -3579,19 +3472,18 @@ bool EDIT_TOOL::pickReferencePoint( const wxString& aTooltip, const wxString& aS picker->SetCursor( KICURSOR::PLACE ); picker->ClearHandlers(); - const auto setPickerLayerSet = - [&]() - { - MAGNETIC_SETTINGS* magSettings = editFrame->GetMagneticItemsSettings(); - LSET layerFilter; + const auto setPickerLayerSet = [&]() + { + MAGNETIC_SETTINGS* magSettings = editFrame->GetMagneticItemsSettings(); + LSET layerFilter; - if( !magSettings->allLayers ) - layerFilter = LSET( { editFrame->GetActiveLayer() } ); - else - layerFilter = LSET::AllLayersMask(); + if( !magSettings->allLayers ) + layerFilter = LSET( { editFrame->GetActiveLayer() } ); + else + layerFilter = LSET::AllLayersMask(); - picker->SetLayerSet( layerFilter ); - }; + picker->SetLayerSet( layerFilter ); + }; // Initial set setPickerLayerSet(); @@ -3680,11 +3572,10 @@ bool EDIT_TOOL::pickReferencePoint( const wxString& aTooltip, const wxString& aS int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent ) { - CLIPBOARD_IO io; + CLIPBOARD_IO io; PCB_GRID_HELPER grid( m_toolMgr, getEditFrame()->GetMagneticItemsSettings() ); - TOOL_EVENT selectReferencePoint( aEvent.Category(), aEvent.Action(), - "pcbnew.InteractiveEdit.selectReferencePoint", - TOOL_ACTION_SCOPE::AS_GLOBAL ); + TOOL_EVENT selectReferencePoint( aEvent.Category(), aEvent.Action(), "pcbnew.InteractiveEdit.selectReferencePoint", + TOOL_ACTION_SCOPE::AS_GLOBAL ); frame()->PushTool( selectReferencePoint ); Activate(); @@ -3705,7 +3596,7 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent ) for( EDA_ITEM* item : selection ) { - if( item->IsBOARD_ITEM() ) + if( item->IsBOARD_ITEM() ) items.push_back( static_cast( item ) ); } @@ -3713,8 +3604,8 @@ int EDIT_TOOL::copyToClipboard( const TOOL_EVENT& aEvent ) if( aEvent.IsAction( &PCB_ACTIONS::copyWithReference ) ) { - if( !pickReferencePoint( _( "Select reference point for the copy..." ), - _( "Selection copied" ), _( "Copy canceled" ), refPoint ) ) + if( !pickReferencePoint( _( "Select reference point for the copy..." ), _( "Selection copied" ), + _( "Copy canceled" ), refPoint ) ) { frame()->PopTool( selectReferencePoint ); return 0; diff --git a/setup-env.sh b/setup-env.sh new file mode 100644 index 0000000000..af1fcadb50 --- /dev/null +++ b/setup-env.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Source this file to set up the environment for running KiCad from ~/bin/kicad +# Usage: source setup-env.sh + +export LD_LIBRARY_PATH="$HOME/bin/kicad/lib:$LD_LIBRARY_PATH" +export PATH="$HOME/bin/kicad/bin:$PATH" + +echo "KiCad environment configured:" +echo " LD_LIBRARY_PATH: $LD_LIBRARY_PATH" +echo " PATH: $PATH"