Compare commits

...

233 Commits

Author SHA1 Message Date
Wayne Stambaugh 3f5d3fa0c6 Tag release version 7.0.1. 2023-03-09 16:59:45 -05:00
Seth Hillbrand 51dc2b109e Handle fully-nested zones
The logic to handle divots needs to account for fully nested, same net
zones.  The process of subtracting led to us considering the inner zone
to be a zone knock-out (negative polygon).  To avoid this, we need to
check if the inner, higher priority zone has any connection to the outer
zone.  If it does not, then we can treat it as an isolated zone without
worrying about divots to the outer zone.

(cherry picked from commit 9146e38af4)
2023-03-09 09:25:20 -08:00
mitxela 2358ff6f07 Helper function to allow net.GetNetClassName()
(cherry picked from commit 734d3667a8)
2023-03-09 14:03:02 +00:00
mitxela 11788d2f39 Expose shared_ptr to swig
Possibly not the right way to go about it but technically works


(cherry picked from commit 182abd4652)
2023-03-09 14:02:48 +00:00
mitxela 541f7467c6 Fix python GetAllNetClasses
(cherry picked from commit 716328e511)
2023-03-09 14:02:34 +00:00
jean-pierre charras 411c9707ee specctra export: fix handling of multi-layer zones.
(from master branch)
2023-03-07 15:45:28 +01:00
Jon Evans ee0ba17c03 Improve HiDPI handling of appearance/layer controls
(cherry picked from commit 43d3a18b86)
2023-03-07 08:49:06 -05:00
Jon Evans 64bc850d8f Fix layer widget in HiDPI situations
(cherry picked from commit 89ef6b36f4)
2023-03-07 08:49:06 -05:00
Jeff Young 154f64dae3 Edge connectors shouldn't trigger edge clearance violations.
Fixes https://gitlab.com/kicad/code/kicad/issues/14199

(cherry picked from commit 33e7c78533)
2023-03-07 12:23:56 +00:00
Johannes Maibaum 7fa758358f Don't bracket KICAD_VERSION when using git describe
(Cherry-picked from 75424cb246)
2023-03-07 10:40:28 +00:00
Salvador E. Tropea f135881bd6 Use constants for the names of the built-in colors
- Avoid repetition and errors from typos
- Allow simple changes
- Simpler data type handling, the constants are wxString
2023-03-07 10:32:18 +00:00
Seth Hillbrand 839301f81e Revert "Consolidated ERC fixes"
This reverts commit 2127712115.

Version uses functions only available in the master branch.  Will revert
for 7.0.2 to allow targeted update
2023-03-06 21:22:55 -08:00
Seth Hillbrand 04f4ca9772 Update translations 2023-03-06 16:55:17 -08:00
Rigo Ligo 525328fba1 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-03-07 01:50:07 +01:00
boonchai k 471c125c1a Translated using Weblate (Thai)
Currently translated at 89.2% (7148 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/th/
2023-03-07 01:50:07 +01:00
Tokita, Hiroshi 8ef99137c6 Translated using Weblate (Japanese)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ja/
2023-03-07 01:50:07 +01:00
boonchai k 404cad062a Translated using Weblate (Thai)
Currently translated at 88.6% (7104 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/th/
2023-03-07 01:50:07 +01:00
dsa-t d4be813f2e Translated using Weblate (Russian)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ru/
2023-03-07 01:50:06 +01:00
Jonathan Haas ab3c0b2f03 Translated using Weblate (German)
Currently translated at 99.9% (8009 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-03-07 01:50:06 +01:00
CloverGit defcfc2962 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/zh_Hans/
2023-03-07 01:50:06 +01:00
Jan Straka 267cfdf54b Translated using Weblate (Czech)
Currently translated at 90.1% (7218 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/cs/
2023-03-07 01:50:06 +01:00
turkce a7b0231b3c Translated using Weblate (Turkish)
Currently translated at 42.1% (3375 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/tr/
2023-03-07 01:50:06 +01:00
turkce 7c19958840 Translated using Weblate (Turkish)
Currently translated at 41.3% (3310 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/tr/
2023-03-07 01:50:06 +01:00
ssantos 34c3bb7d2c Translated using Weblate (Portuguese)
Currently translated at 99.8% (8001 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pt/
2023-03-07 01:50:06 +01:00
Toni Laiho b37545ee6c Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:05 +01:00
Henrik Kauhanen c1e924c894 Translated using Weblate (Swedish)
Currently translated at 99.9% (8007 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:05 +01:00
Tom Niesse 200e9e28ea Translated using Weblate (Dutch)
Currently translated at 82.8% (6638 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/nl/
2023-03-07 01:50:05 +01:00
Henrik Kauhanen b95f958890 Translated using Weblate (Swedish)
Currently translated at 99.9% (8007 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:05 +01:00
김랑기 fe9666bdaf Translated using Weblate (Korean)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-03-07 01:50:05 +01:00
Henrik Kauhanen 948de5dc79 Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:05 +01:00
Toni Laiho 8800fd8250 Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:05 +01:00
Henrik Kauhanen b1e5d8c915 Translated using Weblate (German)
Currently translated at 99.9% (8009 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-03-07 01:50:05 +01:00
Henrik Kauhanen 02aec8b091 Translated using Weblate (Swedish)
Currently translated at 99.9% (8005 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:04 +01:00
김랑기 50517f6aa6 Translated using Weblate (Korean)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/ko/
2023-03-07 01:50:04 +01:00
Henrik Kauhanen a752473280 Translated using Weblate (Finnish)
Currently translated at 99.9% (8010 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:04 +01:00
Henrik Kauhanen 7e1972d483 Translated using Weblate (German)
Currently translated at 99.9% (8009 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-03-07 01:50:04 +01:00
Henrik Kauhanen de48bf04bc Translated using Weblate (Swedish)
Currently translated at 99.9% (8006 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:04 +01:00
Henrik Kauhanen 228bf66cac Translated using Weblate (Finnish)
Currently translated at 99.9% (8010 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:04 +01:00
Jan Straka c986c1d26a Translated using Weblate (Czech)
Currently translated at 89.7% (7188 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/cs/
2023-03-07 01:50:04 +01:00
Henrik Kauhanen b0f7ea5b16 Translated using Weblate (Swedish)
Currently translated at 99.9% (8006 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:04 +01:00
Jan Sobków 8b2e2ff1f8 Translated using Weblate (Polish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pl/
2023-03-07 01:50:03 +01:00
Toni Laiho d00166223f Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:03 +01:00
Toni Laiho 4701b4bfc2 Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:03 +01:00
Ivan Chuba e4c74c727f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/uk/
2023-03-07 01:50:03 +01:00
Henrik Kauhanen f626ce29c4 Translated using Weblate (Swedish)
Currently translated at 99.9% (8006 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/sv/
2023-03-07 01:50:03 +01:00
Wellington Terumi Uemura 768d8e5811 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pt_BR/
2023-03-07 01:50:03 +01:00
ZbeeGin 2ac3a4a103 Translated using Weblate (Polish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/pl/
2023-03-07 01:50:03 +01:00
Toni Laiho bb512f3fc0 Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:03 +01:00
Henrik Kauhanen d6e7a89c97 Translated using Weblate (Finnish)
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/fi/
2023-03-07 01:50:03 +01:00
Ulices a5455da909 Translated using Weblate (Spanish (Mexico))
Currently translated at 100.0% (8011 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/es_MX/
2023-03-07 01:50:02 +01:00
Henrik Kauhanen 8dadc698cc Translated using Weblate (German)
Currently translated at 99.9% (8010 of 8011 strings)

Translation: KiCad EDA/v7
Translate-URL: https://hosted.weblate.org/projects/kicad/v7/de/
2023-03-07 01:50:02 +01:00
James J 2127712115 Consolidated ERC fixes
- Consistent calculation of IsStacked() for pins across ERC checks
 - Correct placement of ERC marker for unresolved field variables
 - Add sheet-specific paths to two ERC check results

(cherry picked from commit 39e56485fc)
2023-03-06 16:38:11 -08:00
Mario Luzeiro d5b635027e 3D-Viewer: sort models and material models when rendering in transparent
Also enables transparency on model preview and small optimizations fixes

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14005

(cherry picked from commit 7bc976f3f4)
2023-03-06 16:24:24 -08:00
Graham Keeth 9b2aeda51e Fix column offset in BOM script
Debugged by @svk28

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14128

(cherry picked from commit cc110399ea)
2023-03-06 16:23:31 -08:00
Seth Hillbrand 5aba9b539f Revert font spacing/tabs to the v6 model
While convoluted, this model matches as best we have found so far, the
alignment with scintilla.  The spacing is character size for N-1 of the
characters in the 4-space tab stops.  The final character is sized for
the actual space character in the stroke font (0.761905)

Fixes https://gitlab.com/kicad/code/kicad/issues/13791

(cherry picked from commit bce402a01c)
2023-03-06 16:23:06 -08:00
JamesJCode b82020722b Eeschema netlist output: Propagate NC across hierarchical schematics
Fixes #12580

Additionally does not export no_connect netlist annotation on pins
which are both connected to another pin and a NC item, unless all
connected pins are stacked at the symbol level.

Adds testing of pin types to netlist QA unit tests.

(cherry picked from commit 9dca70a773)
2023-03-06 16:22:25 -08:00
Seth Hillbrand b62a8fe65a Handle excessively large values when hatching
While unusual, ensure that hatched zones don't break KiCad if they are
close to the integer limit

Fixes https://gitlab.com/kicad/code/kicad/issues/14066

(cherry picked from commit ffcc0e50b7)
2023-03-06 16:21:13 -08:00
Seth Hillbrand a5d85e3281 Bitmaps are not actually copper
We report bitmaps as being 'on' a copper layer because they are
associated with it but they are not actually physical parts so should
not be included in the DRC checks

Additionally, Bitmaps effective shape starts are the top left corner
rather than the center (unclear why that was there in the first place)

Fixes https://gitlab.com/kicad/code/kicad/issues/14065

(cherry picked from commit 1b8b216ac8)
2023-03-06 16:20:44 -08:00
Seth Hillbrand e699bcf5a3 Use Chamfer lines when deflating
Rounded line ends when deflating leads to microscopic jags in the
outline that are not visible but add substantial computation time and
minor error when computing polygon offsets.

Instead, the chamfer deflate method prevents these jagged lines by
clipping angles < 90° by the error level.  This does not impact deflate
calls where we explicitly require the angles to be maintained

(cherry picked from commit af10878954)
2023-03-06 16:18:51 -08:00
Seth Hillbrand 7ef5e079fd Smarten connection width checker looking for splits
Fractured polygons are always fractured along the x-axis, so when
checking to see if a segment is a fracture point, we check if the y
coordinate is equal.  This avoids situations where there are multiple
fracture points between two inflection points

Additionally, we add a second check to ensure we don't hit spurious
blobs (all kinks should be symmetric and therefore be substantial in
each direction)

Fixes https://gitlab.com/kicad/code/kicad/issues/14130

(cherry picked from commit 7653a2bf99)
2023-03-06 16:14:56 -08:00
Jeff Young 4076461347 Make SPICE netlist title explicit.
Fixes https://gitlab.com/kicad/code/kicad/issues/14183

(cherry picked from commit 6838de962b)
2023-03-06 23:09:51 +00:00
qu1ck d610486c1e Add vector3 to swig
Fixes regression in 7.0 making fp 3d model offsets not accessible in
python

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14179

(cherry picked from commit 88062c5fc3)
2023-03-06 11:23:09 -08:00
Christoph Moench-Tegeder 1891e2ad68 CMakeLists.txt: do not use -ffloat-store on clang
According to it's User Manual, clang does not know about -ffloat-store.
This is corrobated by the FreeBSD i386 build (using LLVM 13 and 15,
depending on the base system version) failing early with an error
message complaining about this parameter being unknown.

See
https://pkg-status.freebsd.org/beefy17/data/main-i386-default/pb27279cba1ca_sed03776ca7/logs/kicad-7.0.0,2.log
for an example of the failure, and
https://clang.llvm.org/docs/UsersManual.html#controlling-floating-point-behavior
for the available floating point options on clang.

(Cherry-picked from 46a59aa2c3)
2023-03-06 16:01:55 +00:00
aris-kimi f1e060902b Simulator: Fix RLGC c unit
(Cherry-picked from db2780090c)
2023-03-06 15:59:54 +00:00
Jeff Young 7dbd920912 Don't allow footprint editor pad tools to run outside footprint editor.
(They can get called if a user re-assigns hotkeys to them.)

Fixes https://gitlab.com/kicad/code/kicad/issues/14166
2023-03-06 14:43:20 +00:00
aris-kimi 05ab9e3836 Simulator: Fix diode ibv unit
(Cherry-picked from 5b43dc4e7b)
2023-03-06 14:20:33 +00:00
Jeff Young a4e0f1f7aa Support both wxWidgets APIs for excluded characters.
(Sadly they're mutually incompatible.)

Fixes https://gitlab.com/kicad/code/kicad/issues/14153

(cherry picked from commit b5060d2951)
2023-03-06 14:17:11 +00:00
Jeff Young a8f27d13e6 Use name (even for fallback models) *if* it's specified in dropdown.
Fixes https://gitlab.com/kicad/code/kicad/issues/12425

(cherry picked from commit 7547e550aa)
2023-03-06 11:18:14 +00:00
Jeff Young 05d425ea88 Add 12505 to the regression test suite.
Fixes https://gitlab.com/kicad/code/kicad/issues/12505

(cherry picked from commit d96598c87c)
2023-03-06 10:27:46 +00:00
Jeff Young 3cb12b5a60 Allow others to also process units changed event.
Fixes https://gitlab.com/kicad/code/kicad/issues/14156

(cherry picked from commit 6a5f305684)
2023-03-05 16:07:00 +00:00
Alex 8f1237e629 bom_csv_grouped_extra: use field-specific methods for data.
Fixes https://gitlab.com/kicad/code/kicad/issues/14129


(cherry picked from commit c1f4911d7e)
2023-03-05 00:26:46 +00:00
Wayne Stambaugh 2c7f44f78d Coverity fixes and code cleaning.
(cherry picked from commit 789bf6455a)
2023-03-04 13:14:59 -05:00
Jeff Young a9447aa8c7 Add UNITS_CHANGED handling to 3D preview controls.
Fixes https://gitlab.com/kicad/code/kicad/issues/14156

(cherry picked from commit 915b352d9b)
2023-03-04 12:12:34 +00:00
Jeff Young 9b61b350fe Don't commit changes on paint events or updateUI events.
Also use std::numeric_limits::epsilon for comparing doubles.

Fixes https://gitlab.com/kicad/code/kicad/issues/13851

(cherry picked from commit d714ff8549)
2023-03-04 00:10:39 +00:00
Alex e3cf65fbdf Fix bitmap scaling when reading legacy schematic as well.
(cherry picked from commit bfc3e2d29b)
2023-03-03 22:39:38 +00:00
Jeff Young e51d43568e Prefer Clamp() to std::min( std::max() ).
(cherry picked from commit d545216432)
2023-03-03 21:32:19 +00:00
Jeff Young 1bb6b7acdd Overflow safety.
Potential fix for some or all of
https://gitlab.com/kicad/code/kicad/-/issues/13969

(cherry picked from commit 2f2a00c307)
2023-03-03 21:32:12 +00:00
Seth Hillbrand adc7a3ba4a Correct parent symbol for lib_text
The edited symbol should be pulled from the parent window when there is
not an existing text object

(cherry picked from commit 59fc62e898)
2023-03-03 12:40:56 -08:00
Jeff Young 94ec6cc362 Convert inline models in Sim.Params fields to SPICE syntax.
Fixes https://gitlab.com/kicad/code/kicad/issues/14157

(cherry picked from commit 14f1f3ec79)
2023-03-03 18:18:32 +00:00
Jeff Young bbdb5eb6e3 Use resolved fields when generating LIB_TREE info.
Fixes https://gitlab.com/kicad/code/kicad/issues/13737

(cherry picked from commit 2fb24347ad)
2023-03-03 17:23:13 +00:00
Jeff Young e487ca8bd8 Handle alternate pin definitions when printing.
Fixes https://gitlab.com/kicad/code/kicad/issues/14122

(cherry picked from commit 2973d292d9)
2023-03-03 12:57:03 +00:00
Jeff Young f5b0e20f78 The screen for undo is the screen that *owns* the SCH_SHEET...
... not the screen the SCH_SHEET owns.

Fixes https://gitlab.com/kicad/code/kicad/issues/14099

(cherry picked from commit 5849458476)
2023-03-03 00:23:41 +00:00
Seth Hillbrand 6116eebbad Prevent inf when presented with 0 errormax
acos(1) returns 0, so this implies infinite segements to get to 0 error.
This is not reasonable but might be encountered in bad arcs or circles
that have 0 radius.  Instead of returning infinite or std::max segments,
we limit the error to be at least 1 IU

(cherry picked from commit 1fda68099f)
2023-03-02 10:21:25 -08:00
Jeff Young 8619705e44 Hook up AddField handler to GRID_TRICKS for SCH dialogs.
Fixes https://gitlab.com/kicad/code/kicad/issues/git/14153
2023-03-02 18:16:02 +00:00
Jeff Young c216ed2d1f Make SME prop-grid hack Mac-only.
Fixes https://gitlab.com/kicad/code/kicad/issues/13852

(cherry picked from commit dcba555d44)
2023-03-02 14:59:57 +00:00
Jeff Young e17dc25bba Add support for non-cardianlly-rotated text boxes.
Also fixes a couple of bugs in text boxes in flipped footprints.

Fixes https://gitlab.com/kicad/code/kicad/issues/14112

(cherry picked from commit 7638e23ff1)
2023-03-02 14:58:44 +00:00
Salvador E. Tropea d311915f9d Fix the CONNECTIVITY_DATA::GetNetItems Python API
- The C++ member now uses std::vector<KICAD_T>
- The Python side can use a single value or a list,
  like in v6.

The std::vector translation is based on the v6 KICAD_T[]
translation.
2023-03-01 18:49:12 +00:00
Jeff Young 3a95826b42 Move only-write-model-if-it-contains-overrides up to base class.
It's necessary to keep us from writing out model lines for included
models and fall-backs of included models.

(cherry picked from commit f5edcf82f2)
2023-03-01 13:44:26 +00:00
jean-pierre charras dcc1009162 plotters rework: add plot fct to use TEXT_ATTRIBUTES class to pass text settings
Old PLOTTER::Text is not (yet) removed, but it use negative text size
to mirrored text, which is not really compatible with some plotters (especially PDF).
Using TEXT_ATTRIBUTES is much easy and much better,
so PLOTTER::PlotText() is added.
Note: "old" PLOTTER::Text() is not removed yet.
From master, commit 51d46c0e73
2023-03-01 10:45:23 +01:00
jean-pierre charras d61e01ff4f Plot Gerber format: ensure all attributes are added to polygon items.
Especially, TA.AperFunction,EtchedComponent for net tie footprints using polygons.
From master, commit ece34e1a0c
2023-03-01 09:39:15 +01:00
Seth Hillbrand 51b9d8e7ad Allow for rounding error in connection width checker
We perform checks using squared distance but this loses the integer
rounding in the standard norm.  To correct for this, we allow a single
IU in the restriction, allowing fractionally smaller connection widths
before calculating the squared limit

Fixes https://gitlab.com/kicad/code/kicad/issues/14130

Fixes https://gitlab.com/kicad/code/kicad/issues/14131

(cherry picked from commit a0f99ea8ba)
2023-02-28 15:26:49 -08:00
qu1ck 90eb5e9c31 PCM: auto reload global libs after dialog is run
This adds Reset() method to KIFACE to reload global libs stored in
global static vars.
Also refactors some lib reload code in various frames to have
common MAIL_RELOAD_LIB handler.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/12500

(cherry picked from commit 2975f53647)
2023-02-28 16:48:28 -05:00
Seth Hillbrand 17c34c88dc Avoid forcing all units
When the enduser is not allowed to change the status of "common to all
units", then it should be disabled

Fixes https://gitlab.com/kicad/code/kicad/issues/14084

(cherry picked from commit 3207d1386e)
2023-02-28 13:42:51 -08:00
aris-kimi ff6f658f9d Simulator: Fix some cases with initial conditions
(cherry picked from commit 4a761179d0)
2023-02-28 21:31:45 +00:00
Seth Hillbrand fb798a4150 Export footprint pad holes to STEP regardless
Footprint pad holes form a part of the board outline regardless of
whether the footprint is in the BOM or not

Fixes https://gitlab.com/kicad/code/kicad/issues/14013

(cherry picked from commit daf70f9b6a)
2023-02-28 12:02:40 -08:00
Salvador E. Tropea 4213bb3a62 Fix rounding errors in gerber files
The userToDeviceCoordinates helper returns a VECTOR2D
Converting it to VECTOR2I back and forth generates rounding errors
Also is a waste of time
2023-02-28 19:23:26 +00:00
Jeff Young 8a34f91172 Fix for overwriting non-specified constraints.
Fixes https://gitlab.com/kicad/code/kicad/issues/14070
2023-02-28 18:29:43 +00:00
jean-pierre charras 764ddd4773 Fix compil warnings. 2023-02-28 18:00:22 +01:00
jean-pierre charras ea0dcc8ebd Fixes in build board outlines as polygon and convert_shape_list_to_polygon:
- Ensure Bezier curves have their polygon build before use it.
- When building board outlines as polygon the same chaining epsilon value
for DRC, export step and 3D view (default 0.01mm).
Fixes #14115
https://gitlab.com/kicad/code/kicad/issues/14115
Fixes #14009
https://gitlab.com/kicad/code/kicad/issues/14009
2023-02-28 17:26:28 +01:00
jean-pierre charras 3f5db9f7f9 EXPORTER_STEP: handle sub-layers in dielectric layer.
A dielectric layer (between 2 copper layers) can be made by more than one
layer (composite dielectric).  Not frequent, but possible.
sub-layers where previously ignored.
2023-02-28 17:25:40 +01:00
Jeff Young a6a0bba1b7 Stage group children when staging group.
Many operations such as move, rotate, etc. are applied directly to the
group's children, so it's the children that need staging.

Fixes https://gitlab.com/kicad/code/kicad/issues/13999
2023-02-28 14:21:12 +00:00
Jeff Young 5ec785e2f7 Spacing & font-size issues in 3D model preview dialog.
Fixes https://gitlab.com/kicad/code/kicad/issues/13880

(cherry picked from commit 7bb006c91d)
2023-02-28 14:21:12 +00:00
Graham Keeth f7d9f1f69d Fix SPICE pins for BJTs and MESFETs
- MESFETs don't have a substrate/bulk pin
- BJTs have a substrate pin, and HICUM/VBIC have TJ

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/13848

(cherry picked from commit 6af3dadaee)
2023-02-28 14:21:12 +00:00
Jeff Young 42efd2d005 Make substrate and thermal junction nodes optional.
Fixes https://gitlab.com/kicad/code/kicad/issues/14083

(cherry picked from commit 1fdc81e68d)
2023-02-28 14:21:12 +00:00
Jeff Young d32e13daee Clear model name when switching to internal model.
Also fixes a bug to ensure that a modelLine gets written when using
an internal model.

Fixes https://gitlab.com/kicad/code/kicad/issues/14083

(cherry picked from commit 2e5bf0210a)
2023-02-28 14:21:12 +00:00
Jeff Young e82c21e944 Get rid of m_sortedSymbolPinList in favour of a properly scoped variable.
Fixes https://gitlab.com/kicad/code/kicad/issues/14083

(cherry picked from commit 2a79a453ec)
2023-02-28 14:21:12 +00:00
Johannes Pfister 33f835a437 When importing legacy PCB dimension: Use automatic dimension when Unit couldn't be determined
(cherry picked from commit a87550a2c6)
2023-02-28 14:21:12 +00:00
Jeff Young 59d8110801 Always highlight children when they're selected on their own.
Fixes https://gitlab.com/kicad/code/kicad/issues/13876

(cherry picked from commit a1ceb585c7)
2023-02-28 14:21:11 +00:00
Jeff Young d028b381fa Make SIM_MODEL_SPICE_FALLBACK act more like the model it's a fallback for.
In particular, install/show the parameters, and keep the existing name
field.

Fixes https://gitlab.com/kicad/code/kicad/issues/14102

(cherry picked from commit 281fde71b9)
2023-02-28 14:21:11 +00:00
Roberto Fernandez Bautista a1a3f810f0 Add missing line from commit b03366c9e8
(cherry picked from commit bb8a3a7fdc)
2023-02-27 23:13:44 +00:00
Roberto Fernandez Bautista c96f0f2396 Fix CADSTAR importer memory leaks
We were leaking the xml tree when throwing exceptions


(cherry picked from commit b03366c9e8)
2023-02-27 22:58:41 +00:00
Fabien Corona 46c8985661 sim - switches: open <-> closed in description 2023-02-27 19:04:48 +01:00
jean-pierre charras c588639503 PANEL_COLOR_SETTINGS: swap swatches and texts to avoid annoying truncation.
In some languages, the texts can be long, and create truncation of the left
column. So if the left column shows swatches they are truncated, or not visible
Truncating long texts is less annoying.
Fixes #14052
https://gitlab.com/kicad/code/kicad/issues/14052
2023-02-27 08:37:13 +01:00
Jeff Young b3c6f559b2 Don't eval empty string.
Fixes https://gitlab.com/kicad/code/kicad/issues/13756

(cherry picked from commit 79f13ea9c7)
2023-02-26 23:14:40 +00:00
Marek Roszko 85544d109c Don't destroy the DIALOG_PCM_PROGRESS until after the threads actually terminated
(cherry picked from commit 47cf26f047)
2023-02-26 22:47:14 +00:00
Jeff Young 4aba595b2b Add second instance of "don't mess up user formatting" fix.
Fixes https://gitlab.com/kicad/code/kicad/issues/13989

(cherry picked from commit 4b427b2d0c)
2023-02-26 22:00:20 +00:00
Jeff Young b2241dca72 Adjust stroke font baseline offset to better match 6.0.
Fixes https://gitlab.com/kicad/code/kicad/issues/13886

(cherry picked from commit 4bb508eacf)
2023-02-26 21:59:43 +00:00
Jeff Young 4ffe742b69 Log new undo record at the start of Change Symbols.
Also fixes a bug where the "screen" variable was used with stale
data.

Fixes https://gitlab.com/kicad/code/kicad/issues/14061

(cherry picked from commit 2b96161d0e)
2023-02-26 21:58:57 +00:00
Jeff Young 5979b8e385 Don't allocate all of memory when the coord system turns inside out.
Fixes https://gitlab.com/kicad/code/kicad/issues/14088

(cherry picked from commit fe9370ceea)
2023-02-26 21:58:08 +00:00
Roberto Fernandez Bautista 955bd5a6d1 CADSTAR Sch: Fix loading of graphical arc shapes
Correctly load arc shapes as real arcs instead of approximating now that
v7 supports graphical arcs in the schematic.

Also fix calculation of arc geometry for ccw arcs.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14101


(cherry picked from commit 698d0b7e92)
2023-02-26 18:47:39 +00:00
qu1ck 1eb8191519 Treat dimensions in fp as text for bbox calculations
(cherry picked from commit 1ff021bb927e9a146f57277554f370f97c07041c)
2023-02-26 17:59:22 +00:00
qu1ck 396bda5611 Sync pcbnew selection with selected items after plugin is run
(cherry picked from commit 9f10c142c4)
2023-02-26 17:58:57 +00:00
Jon Evans cb334be8c4 PNS: Diff pairs can have different hole-to-hole size
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13993


(cherry picked from commit f12f2b8420)
2023-02-26 17:57:47 +00:00
Jon Evans 8845cc0556 PNS: Safety for evaluating item nets for rules
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13993


(cherry picked from commit 459473ccc3)
2023-02-26 17:57:33 +00:00
Jon Evans e34800ad49 Allow shorting copper zones through negative clearance
This brings the zone filler in line with other places where
we use negative clearance rules to disable constraints.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14069


(cherry picked from commit b176881d49)
2023-02-26 17:45:46 +00:00
qu1ck 5b574901b3 Fix swig mappings for PCB_BITMAP
From Master branch.
2023-02-26 10:28:59 +01:00
Alex 59b68154e1 Reduce some flickering in PCM.
(cherry picked from commit b592017495)
2023-02-26 08:34:49 +00:00
jean-pierre charras 5a501c8e48 kicad manager, OnOpenFileInTextEditor(): do not quote the filename.
It will be quoted later.
Fixes #14086
https://gitlab.com/kicad/code/kicad/issues/14086
2023-02-26 08:36:58 +01:00
Seth Hillbrand f927c15adf Prevent mutex deadlock
The overbar function in outline fonts recursively calls the text
function which already owns the lock.  To avoid this, we have an
unlocked variant that is wrapped by the exposed text function

Fixes https://gitlab.com/kicad/code/kicad/issues/14015


(cherry picked from commit 81256c0fa4)
2023-02-25 13:44:18 +00:00
Jon Evans d08157f7db Re-disable validator for VALUE and add comment explaining it 2023-02-25 08:05:42 -05:00
jean-pierre charras 8a9ac4f01f Pcbnew: optimize netname and num text size and position display on pad.
Sizes where a bit too big. Fix also a difference between Cairo and OpenGL.
Fixes #13872
https://gitlab.com/kicad/code/kicad/issues/13872
2023-02-25 11:08:29 +01:00
Jon Evans 39df5f3b15 Do not invalidate board caches during DRC
Footprints now modify their parent container when destroyed due to
26542796, and a temporary footprint is created during DRC
in some situations.  This can lead to board caches being messed
with during DRC which can cause unpredictable bad effects due to
multithreading.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/13844


(cherry picked from commit 8440d7258b)
2023-02-25 03:56:27 +00:00
Jon Evans 981bf328ae Value field needs to use the normal text control
Fixes https://gitlab.com/kicad/code/kicad/-/issues/14056
2023-02-24 22:18:31 -05:00
Jon Evans 1f8e9727b0 Set copper edge clearance to a more reasonable default
(cherry picked from commit 1215a967e2)
2023-02-25 01:43:55 +00:00
Jeff Young f604bcb557 Only write included models if they have overridden parameters.
Fixes https://gitlab.com/kicad/code/kicad/issues/13953

(cherry picked from commit 5a12e5ee76)
2023-02-24 20:47:22 +00:00
Jeff Young eccf9eb4a4 Change strategy for committing values from SIM_MODEL propGrid.
Note that the PCB editor's propGrid doesn't seem to need this workaround,
but I haven't yet figured out what's different between it and the sim model
propGrid.

Fixes https://gitlab.com/kicad/code/kicad/issues/13852

(cherry picked from commit c188318174)
2023-02-24 20:47:22 +00:00
Jeff Young 39403fa885 Cleanup some dead code, and add a potentially needed fix for non-Mac.
(The Mac bug is fixed in 4e5b1da81fce7cd9ffedaec878ed07bfcfff4fe2 in
our wxWidgets fork.)

(cherry picked from commit 200a06a677)
2023-02-24 20:47:22 +00:00
Jeff Young 5e7cc30564 Don't mess up user formatting if eval'ing didn't actually change value.
Fixes https://gitlab.com/kicad/code/kicad/issues/13989

(cherry picked from commit 8059edff0e)
2023-02-24 20:47:22 +00:00
Jeff Young f942b4c657 Don't allow extra text in Sim.* fields.
(In particular, the field name.)

Fixes https://gitlab.com/kicad/code/kicad/issues/13996

(cherry picked from commit 71df3f9edb)
2023-02-24 20:47:22 +00:00
Jeff Young f5aeb5b068 More dead code removal and a bit of formatting and const& for strings.
(cherry picked from commit a126d961d8)
2023-02-24 20:47:22 +00:00
Jeff Young 7f6cb9b07b Remove most of SIM_VALUE in favour of good old wxString.
This allows us to save the user's intent, including units, formatting,
and crucially variable references.

(cherry picked from commit 68fe146861)
2023-02-24 20:47:22 +00:00
Jeff Young db3657d411 Terminology and more dead code.
(cherry picked from commit 29f21cdde6)
2023-02-24 20:47:22 +00:00
Jeff Young 38e5da724d Remove dead and redundant code.
(cherry picked from commit 90adc26b73)
2023-02-24 20:47:22 +00:00
Marco Ciampa 24a63eb304 Updated Italian translation 2023-02-24 14:12:48 +01:00
jean-pierre charras c1f5ae1c5a Plot footprint texts: add code to plot Knockout texts.
Fixes #14068
https://gitlab.com/kicad/code/kicad/issues/14068
2023-02-24 08:49:56 +01:00
Jon Evans 009211c740 Fix some PCB_SHAPE properties
Hide irrelevant position/start/end properties
for shape classes that don't use them.


(cherry picked from commit 1651b44ab1)
2023-02-24 01:24:41 +00:00
Alex 1a208a1612 Print original netnames properly when reconnecting zones/vias.
Using GetNetname() after SetNet() isn't a good idea to get the original
name when updating PCB from Schematic.


(cherry picked from commit 9d96edc44f)
2023-02-23 20:30:39 +00:00
Alex b867e51c6c pcbnew: Fix pads losing nets after Undo.
Wasn't fixed in all places after being broken in
13f5c78e89


(cherry picked from commit f31e5ea783)
2023-02-23 20:30:20 +00:00
qu1ck 7693b93c50 Fix plugins in pcbnew breaking by opening fp editor
From master branch.
2023-02-23 15:31:00 +01:00
jean-pierre charras c3d7158669 Eeschema plot: honor B&W plot option for bitmap images.
Fixes #14013
https://gitlab.com/kicad/code/kicad/issues/14013
2023-02-23 09:53:35 +01:00
Marek Roszko 9f5e50f25e Fix typo in appearance_controls.cpp
(cherry picked from commit c2a4dd93e8)
2023-02-23 01:36:52 +00:00
Jon Evans a091ab76d7 Disable auto-refill zones
We need a more advanced dirtying system for this to work out for
many users, it turns out.  Right now too many changes cause full
zone refills which interrupt workflow.


(cherry picked from commit d8f4d04093)
2023-02-23 01:16:21 +00:00
jean-pierre charras d5eb242295 Fix incorrect tilt of italic texts when plotting them.
Fixes #14023
https://gitlab.com/kicad/code/kicad/issues/14023
2023-02-22 20:25:25 +01:00
Salvador E. Tropea b21e65fc5f Fix compatibility with wxWidgets 3.0.x
- Use CanonicalName when GetCanonicalWithRegion() isn't available
2023-02-22 19:23:55 +00:00
Jeff Young 1b07e81936 Fix compile error on OSX. 2023-02-22 18:06:32 +00:00
Jeff Young 962b2d45ef Implement default levels for JFETs, MOSFETs and MESFETs.
(cherry picked from commit fe2679d965)
2023-02-22 18:04:23 +00:00
Jeff Young 7894b41277 Don't allow 0 field text size.
Fixes https://gitlab.com/kicad/code/kicad/issues/13987

(cherry picked from commit cb71ea872b)
2023-02-22 18:04:23 +00:00
Jeff Young 51d0b8d2b5 Don't allow SCH_LABEL_LOCATE_ANY_T to steal SCH_LABEL_LOCATE_WIRE_T's items.
Fixes https://gitlab.com/kicad/code/kicad/issues/13936

(cherry picked from commit 5967ab9a4d)
2023-02-22 18:04:23 +00:00
Jeff Young 7b992a1dc4 Correctly netlist a voltage source with both AC and DC values.
Fixes https://gitlab.com/kicad/code/kicad/issues/13912

(cherry picked from commit c618bb7046)
2023-02-22 18:04:21 +00:00
Jeff Young 2f8615c6c4 Don't use the just-in-time model resolver when updating the dialog.
If it changes in the middle it will leave you in a world of hurt.

Also don't update the library after a loss-of-focus unless the path
really changed.

Fixes https://gitlab.com/kicad/code/kicad/issues/13869

Fixes https://gitlab.com/kicad/code/kicad/issues/13854

(cherry picked from commit 64f1808d60)
2023-02-22 17:53:10 +00:00
Salvador E. Tropea aee6d9d01c Create the built-in colors in the constructor
This is needed so Python scripts can get built-in colors using the
SETTINGS_MANAGER.GetColorSettings() member.
Otherwise calling it with a built-in name crashes.
2023-02-22 09:12:22 -03:00
Marek Roszko fd4a0dbedf Fix up handling of font names available in multiple names
ttf fonts can declare multiple language names. Many by default opt to just declare one and not tag it any particular language.
However, there are CJK languages that typically leverage this function the most. They'll tag both a "en" and a cjk lang family name in CJK characters.

To be as user friendly as possible, we need to display said fonts in the CJK languages if KiCad to set to such a locale.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14011


(cherry picked from commit 39e69a3d29)
2023-02-22 01:27:09 +00:00
Marek Roszko 14381ac68a Catch parsing exceptions of the local repository.json
Fixes KICAD-B9


(cherry picked from commit 6029fae30b)
2023-02-21 12:15:09 +00:00
Fabien Corona c00a98fed4 Revert "sim - Remember the option to save powers"
This reverts commit 74dcc1b9d5.
2023-02-20 20:59:52 +01:00
Mark Roszko aab7581909 Fix symbol contributor link
(cherry picked from commit 365c7be4ed)
2023-02-20 19:44:59 +00:00
Fabien Corona 74dcc1b9d5 sim - Remember the option to save powers
Fixes #13978


(cherry picked from commit 2a3b70b7eb)
2023-02-20 19:38:19 +00:00
Fabien Corona 17241b3543 sim - missing assignment 2023-02-20 18:15:37 +01:00
Fabien Corona a4a859f47b sim - Check FindParam() results before using them 2023-02-20 18:14:48 +01:00
Fabien Corona b66ed8bc41 sim - don't write dc parameter twice 2023-02-20 18:13:44 +01:00
Fabien Corona 754feff5e7 sim - allow sources that are both AC and TRAN 2023-02-20 18:12:36 +01:00
Fabien Corona cd1b425a80 sim: VSIN - allow user to specify a phase
TD is not the same as PHASE.
TD is the delay before the source turns on.
PHASE is ... the phase

If only TD is set, the signal starts later, but the phase is still 0 when compared to the t=0 of the simulation.

(cherry picked from commit 39a1b14a0f)
2023-02-20 08:45:09 +00:00
Marek Roszko 187947e8d8 Fix crash deleting project tree items
Fixes sentry KICAD-C2


(cherry picked from commit 7d25b6de87)
2023-02-19 15:12:07 +00:00
Marek Roszko 6b38927123 Fix crash parsing cadstar
Fixes sentry KICAD-B2
2023-02-19 08:11:33 -05:00
Marek Roszko f46e4049b6 Try to prevent a crash in mpFXY::Plot
Fixes sentry kicad-c0
2023-02-19 08:11:27 -05:00
Marek Roszko 0ea8299fa7 Fix copypasta typo in export pos
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13991


(cherry picked from commit 9b708ce6d1)
2023-02-19 05:24:36 +00:00
Marek Roszko 5d793193e0 Fix crash by using a shared_mutex to read/write lock the nickIndex
Fixes sentry kicad-ax
2023-02-18 13:02:25 -05:00
Mark Roszko 62337f75b8 FT_Face is also not thread, protect getTextAsGlyphs
(cherry picked from commit 7b4abb1f7b)
2023-02-17 15:17:11 +00:00
Marek Roszko 4d4fdfff70 freetype is not thread safe, zone filler can trigger multi-thread access
sentry KICAD-B1

https://freetype.org/freetype2/docs/reference/ft2-base_interface.html
[Since 2.5.6] In multi-threaded applications it is easiest to use one FT_Library object per thread.
In case this is too cumbersome, a single FT_Library object across threads is possible also, as long as a mutex lock is used around FT_New_Face and FT_Done_Face.


(cherry picked from commit 65d5b34da3)
2023-02-17 15:17:02 +00:00
Alex b63d0a3138 Keep image sizes when loading/saving 7.0- schematic file formats.
Previously, images were assumed to have 300 PPI density when loading from
schematic, but not after initial placement.


(cherry picked from commit bd4758e4df)
2023-02-17 01:50:01 +00:00
Alex 7949c09183 Prevent ghost image after canceling bitmap placement.
(cherry picked from commit ecb28ddf1c)
2023-02-17 01:49:47 +00:00
Seth Hillbrand 3f535aca8c Fix Ukrainian language name
Should refer to the language not to a Ukrainian person

(cherry picked from commit 576bef4ba0)
2023-02-16 15:11:14 -08:00
Jon Evans 9f44809164 Revert "Handle another case where schematic view was being cleared"
This reverts commit 245ce7259c.
2023-02-16 16:44:30 -05:00
Jon Evans f7ccb18af5 Revert "Symbol editor: stop removing overlay from view"
This reverts commit f36cd60fdb.
2023-02-16 16:44:20 -05:00
Jon Evans cca9945867 Revert "Fix handling of selection overlay in schematic editor"
This reverts commit e2711a6121.

This ended up being too complex for 7.0
2023-02-16 16:43:57 -05:00
Jeff Young f23c6b0c2f Clear dirty flags after a move.
Fixes https://gitlab.com/kicad/code/kicad/issues/11362

(cherry picked from commit 40e1296a8b)
2023-02-16 18:10:26 +00:00
Jeff Young 6d22b8c6ed Negative clearance means test won't run, not rule won't match.
Fixes https://gitlab.com/kicad/code/kicad/issues/13947
2023-02-16 18:10:26 +00:00
Jon Evans 245ce7259c Handle another case where schematic view was being cleared
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13944


(cherry picked from commit ec2fc161e1)
2023-02-16 13:25:44 +00:00
Jon Evans f36cd60fdb Symbol editor: stop removing overlay from view
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13944


(cherry picked from commit 955a5a13eb)
2023-02-16 13:17:34 +00:00
jean-pierre charras 8467e2d376 Pcbnew: Do not change visibility objects when changing Visibility layers
Fixes #13836
https://gitlab.com/kicad/code/kicad/issues/13836
2023-02-16 12:42:25 +01:00
jean-pierre charras 2529918d5f Pcbnew: fix incorrect rotation of thermal spoke for rotated footprints.
If the footprint rotation is not a multiple of 90°, the thermal spokes
were not correctly rotated.
Fixes #13919
https://gitlab.com/kicad/code/kicad/issues/13919
2023-02-16 12:41:35 +01:00
Jon Evans e2711a6121 Fix handling of selection overlay in schematic editor
We weren't actually using the overlay group at all

Fixes https://gitlab.com/kicad/code/kicad/-/issues/11142


(cherry picked from commit 0f18a36f8f)
2023-02-16 02:17:36 +00:00
Marek Roszko 89d22e5f94 update sentry-native to 0.6.0
primarily interested in windows bug fix to stack unwinding


(cherry picked from commit 041b7b196d)
2023-02-16 02:10:05 +00:00
jean-pierre charras f13fda9be5 Fix a QA test for bitmaps, to work with latest changes in bitmap code.
cherry pick from 05b68413f7
2023-02-15 15:56:12 +01:00
Ian McInerney 49f6a63a06 Fix compatibility with older wx versions
ToInt was only added in wx 3.1.6 apparently, so for now make them long
types. Fixes bug introduced in 1e8cc6855d

(Cherry-picked from 2b1040ae67)
2023-02-15 11:49:38 +00:00
Ian McInerney e078fea846 Relax wxPython version mismatch check to major.minor
The previous version check failed when the version was even slightly
different, including on the revision field. Theoretically the ABI of the
wx minor versions in use should be the same, so this might work. On the
other hand, with wxPython it could break as well. YOLO.

(Cherry-picked from 1e8cc6855d)
2023-02-15 11:49:15 +00:00
Ian McInerney 048c8b1670 Support subrelease field in wxWidgets cmake detection
Sometimes wxWidgets increments the subrelease to a non-zero value, and
since wxPython will report a subrelease, we must ensure we can get the
subrelease from the wx library properly, otherwise configure will fail
thinking the library isn't the same version as that used by wxPython.

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/13887

(Cherry-picked from b536580119)
2023-02-15 11:48:53 +00:00
Marek Roszko 3b5c38d861 CURLINFO_SIZE_DOWNLOAD_T is a enum entry, use the version check instead
(cherry picked from commit c189053ee5)
2023-02-15 04:45:22 +00:00
Marek Roszko 90fb075e34 CURLOPT_XFERINFOFUNCTION is an enum entry not a define, the check is invalid
(cherry picked from commit 94b5ddbb50)
2023-02-15 04:26:51 +00:00
Jon Evans 08c6d9ce96 Set PPI properly in schematic bitmaps, too
(cherry picked from commit e8a88411ea)
2023-02-15 02:37:22 +00:00
Marek Roszko 76ccb8c31f Try and avoid crashing on gl context creation failure in the 3d viewer
Sentry event id 0ad4afa6b86a4a03ad7f8fdbcdb72f86


(cherry picked from commit 5ccf205788)
2023-02-15 02:20:14 +00:00
Jon Evans 3dfc502814 Router: Do not collide items within a net tie footprint
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13909

(cherry picked from commit 2d7c5c5c0f)
2023-02-14 21:10:42 -05:00
Jon Evans df0f626283 Properties: remove assertion that no longer makes sense
(cherry picked from commit e5b376721d)
2023-02-14 21:10:42 -05:00
Jon Evans 1909ce9220 Properties: fix rebuilding when availability changes
(cherry picked from commit 61dd4b7043)
2023-02-14 21:10:42 -05:00
Jon Evans 15bef82e1e Properties: add some validators for PAD
(cherry picked from commit 0b3928d38f)
2023-02-14 21:10:42 -05:00
Jon Evans 60a45241e6 Properties: introduce validators; re-enable zone hatch settings
(cherry picked from commit eb240fda9a)
2023-02-14 21:10:42 -05:00
Jon Evans d403e92315 Properties: introduce method chaining for initialization
(cherry picked from commit 254168c788)
2023-02-14 21:10:42 -05:00
Marek Roszko eed7ede376 Fix step colors some more
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13611

I need to refactor the overall structure and know what to do, but ugh lazy


(cherry picked from commit c6540575b5)
2023-02-15 00:45:17 +00:00
Jon Evans d20f49b58b Fix handling of PPI when loading embedded images
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13884


(cherry picked from commit 473979d686)
2023-02-15 00:42:30 +00:00
Jon Evans 37091df142 Symbol chooser: save UI settings even when canceled
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13903

(cherry picked from commit 29c4482bc8)
2023-02-14 18:27:31 -05:00
Jon Evans 21081cf80f Handle custom columns in symbol tree synchronizing adapter
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13907

(cherry picked from commit 0913552f84)
2023-02-14 18:27:21 -05:00
Mark Roszko c213b37e96 Update 2 files
- /vcpkg-configuration.json
- /vcpkg.json
2023-02-14 23:12:05 +00:00
Seth Hillbrand d1ca84aa43 Don't desaturate the selection shadow
Selection shadows are helpful when showing which elements are selected
and there is no benefit (and some downside) to having their color
removed.

Fixes https://gitlab.com/kicad/code/kicad/issues/13878

(cherry picked from commit 9f8b25a0b0)
2023-02-14 10:22:49 -08:00
Wayne Stambaugh 0f7fbc411a Allow plotting of multiple board layers per plot in Python.
Since the always plot the edge cuts layer  option was deprecate,
the ability to plot multiple board layers was exposed through the
PLOT_CONTROLLER object.

Added the interactive plot information which was overlooked during
version 7 development.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/13841

(cherry picked from commit eb83f76bff)
2023-02-14 09:53:16 -05:00
Jeff Young f4b2b1b03f Workaround wxWidgets enforced min pen width by using transparent pen.
Also fixes some bugs in our shape printing code when a border is not
specified but a fill is.

Fixes https://gitlab.com/kicad/code/kicad/issues/13891

(cherry picked from commit 03484aedbc)
2023-02-14 14:45:24 +00:00
Marek Roszko 0ecc36c4a5 Fix step model colors again
Fixes https://gitlab.com/kicad/code/kicad/-/issues/13882


(cherry picked from commit df022acc11)
2023-02-14 03:23:06 +00:00
Marek Roszko a48eace90a It's not impossible for the font face to fail loading
LoadFont()'s only usage already checked for nullptr to fallback, let's actually return nullptr on a failed load

Fixes sentry KICAD-8Z
Make the cause of sentry KICAD-95


(cherry picked from commit e8e407dfba)
2023-02-14 01:09:56 +00:00
Marek Roszko 7a2a51ad44 Prevent another GAL crash on init due to psuedo-race
Fixes Sentry KICAD-98


(cherry picked from commit 9647a22e50)
2023-02-14 00:11:15 +00:00
Seth Hillbrand f56fcb0a14 Better handling of vertex sorting
Nominally, the zcode of a vertex is unique.  This is not 100% true,
however, as we must interlace two 32-bit numbers into a single 32-bit
number.  Sorting needs to account for the possibility that the zcode
will be the same while other elements of the vertex are different.  This
commit fixes the broken boolean logic to more clearly handle these cases

Fixes https://gitlab.com/kicad/code/kicad/issues/13867

(cherry picked from commit e7fe69b97f)
2023-02-13 11:23:14 -08:00
Jeff Young 7816652078 Account for border when calculating text margin for text boxes.
Also fixes some unnoticed issues with the textbox dialogs (probably
dating from the move to wxWidgets 3.2).

Fixes https://gitlab.com/kicad/code/kicad/issues/13877
2023-02-13 17:07:42 +00:00
Jeff Young 20aacc7026 Don't confuse .OP with .OPTIONS.
Fixes https://gitlab.com/kicad/code/kicad/issues/13849

(cherry picked from commit d6bef19811)
2023-02-13 13:34:40 +00:00
Jeff Young 49938cfd09 Fix layout issue in IBIS fields. 2023-02-13 12:42:42 +00:00
Jeff Young 53a4ed6b24 ReadDataFields must be a separate step from Create.
Create() is done without execption processing, while ReadDataFields
should have exception processing.

(This also fixes a case where exception processing on ReadDataFields
was missing.)

Also fixes a bug where the pinSelect menu wasn't checked for -1 before
fetching.

Fixes https://gitlab.com/kicad/code/kicad/issues/13856
2023-02-13 12:42:42 +00:00
Marek Roszko 534000b49d Ensure gal is initialized before letting DoRepaint blowup spectacularly.
Maybe a fix for KICAD-6B


(cherry picked from commit 58350b4521)
2023-02-13 12:21:44 +00:00
Jeff Young 7e2ccbf909 Prepend correct SPICE prefix when necessary for plotting currents.
Fixes https://gitlab.com/kicad/code/kicad/issues/13850

(cherry picked from commit a22964a977)
2023-02-13 10:59:32 +00:00
Jeff Young b0b6968185 Fix too-narrow text edit control on Mac.
Also makes the yellow error highlight in CvPCB a bit less jarring.

Fixes https://gitlab.com/kicad/code/kicad/issues/13866

(cherry picked from commit 77421c8fb6)
2023-02-13 10:56:55 +00:00
Jeff Young 94963b5b3a Remove DRC exclusions that no longer have items.
Fixes https://gitlab.com/kicad/code/kicad/issues/13802

(cherry picked from commit 13391176ae)
2023-02-13 10:55:07 +00:00
Jeff Young 77fa61e6fc Make sure screen RTrees are updated when changing bounding boxes.
(cherry picked from commit 7bc79c17d4)
2023-02-13 10:54:59 +00:00
Jeff Young 94c450ad16 Bug fixes for LIB_PIN boundbox generation.
(cherry picked from commit 9ce5978c3d)
2023-02-13 10:54:55 +00:00
Jeff Young a292bf7c83 Don't dirty connectivity when moving non-reference SCH_FIELD.
(cherry picked from commit 2e9ed67e05)
2023-02-13 10:54:49 +00:00
Marek Roszko b24ee1c44f Prevent a crash when a spice SW_I lacks two pin net names
Fixes KICAD-5D


(cherry picked from commit 2cc3d8e9bc)
2023-02-13 03:32:07 +00:00
Jon Evans 981b22ba49 Add initial sections to bare template
(cherry picked from commit 12a9ed0208)
2023-02-11 12:04:45 -05:00
Jon Evans e1eedd3bba Attempt to fix GitLab template duplication
(cherry picked from commit 609ef96e42)
2023-02-11 12:04:39 -05:00
Wayne Stambaugh b949fd4d43 Begin 7.0.1 development. 2023-02-11 11:36:50 -05:00
492 changed files with 64979 additions and 51047 deletions
+20
View File
@@ -0,0 +1,20 @@
<!-- --------Before Creating a New Issue-----------
* Limit report to a single issue.
* Search the issue tracker to verify the issue has not already been reported.
* Complete all instructions between `template comment markers <>.
* Keep report contents limited to the necessary information required to fix the issue.
* When creating an issue against the stable version of KiCad, make sure the latest available stable version is installed as issues may have already been resolved in later stable versions. -->
# Description
<!-- What is the current behavior and what is the expected behavior? -->
<!-- If the issue is visual/graphical, please attach screenshots of the problem. -->
<!-- Add the issue details below this line and before the "Steps to reproduce" heading. -->
# Steps to reproduce
<!-- If there are multiple steps to reproduce it or it is a visual issue, then providing a screen recording as an attachment to this report is recommended. -->
<!-- If this issue is specific to a project, please attach the necessary files to this issue. -->
<!-- Add the steps to reproduce using the numbers below -->
<!-- Add new step numbers before the "KiCad Version" heading. -->
1.
# KiCad Version
+3 -2
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015-2022 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -671,7 +671,8 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
return false;
}
int chainingEpsilon = pcbIUScale.mmToIU( 0.02 ); // max dist from one endPt to next startPt
// max dist from one endPt to next startPt
int chainingEpsilon = m_board->GetOutlinesChainingEpsilon();
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
m_board->GetDesignSettings().m_MaxError,
+9
View File
@@ -383,6 +383,15 @@ void EDA_3D_CANVAS::DoRePaint()
if( m_glRC == nullptr )
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
// CreateCtx could and does fail per sentry crash events, lets be graceful
if( m_glRC == nullptr )
{
warningReporter.Report( _( "OpenGL context creation error" ), RPT_SEVERITY_ERROR );
warningReporter.Finalize();
m_is_currently_painting.clear();
return;
}
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
// Set the OpenGL viewport according to the client size of this canvas.
@@ -257,6 +257,13 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
if( m_glRC == nullptr )
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
// CreateCtx could and does fail per sentry crash events, lets be graceful
if( m_glRC == nullptr )
{
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint creating gl context failed" ) );
return;
}
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
// Set the OpenGL viewport according to the client size of this canvas.
@@ -323,8 +330,16 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
m_ogl_3dmodel->BeginDrawMulti( true );
m_ogl_3dmodel->DrawOpaque( false );
glDepthMask( GL_FALSE );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
m_ogl_3dmodel->DrawTransparent( 1.0f, false );
glDisable( GL_BLEND );
glDepthMask( GL_TRUE );
m_ogl_3dmodel->EndDrawMulti();
glPopMatrix();
+98 -15
View File
@@ -27,13 +27,14 @@
* @file c_ogl_3dmodel.cpp
* @brief
*/
#include <algorithm>
#include <stdexcept>
#include <gal/opengl/kiglew.h> // Must be included first
#include "3d_model.h"
#include "opengl_utils.h"
#include "../common_ogl/ogl_utils.h"
#include "../3d_math.h"
#include <utility>
#include <wx/debug.h>
#include <wx/log.h>
#include <chrono>
@@ -177,9 +178,11 @@ MODEL_3D::MODEL_3D( const S3DMODEL& a3DModel, MATERIAL_MODE aMaterialMode )
// use material color for mesh bounding box or some sort of average vertex color.
glm::vec3 avg_color = material.m_Diffuse;
BBOX_3D &mesh_bbox = m_meshes_bbox[mesh_i];
for( unsigned int vtx_i = 0; vtx_i < mesh.m_VertexSize; ++vtx_i )
{
m_meshes_bbox[mesh_i].Union( mesh.m_Positions[vtx_i] );
mesh_bbox.Union( mesh.m_Positions[vtx_i] );
VERTEX& vtx_out = mesh_group.m_vertices[vtx_offset + vtx_i];
@@ -222,16 +225,19 @@ MODEL_3D::MODEL_3D( const S3DMODEL& a3DModel, MATERIAL_MODE aMaterialMode )
}
}
if( m_meshes_bbox[mesh_i].IsInitialized() )
if( mesh_bbox.IsInitialized() )
{
// generate geometry for the bounding box
MakeBbox( m_meshes_bbox[mesh_i], ( mesh_i + 1 ) * bbox_vtx_count,
MakeBbox( mesh_bbox, ( mesh_i + 1 ) * bbox_vtx_count,
&bbox_tmp_vertices[( mesh_i + 1 ) * bbox_vtx_count],
&bbox_tmp_indices[( mesh_i + 1 ) * bbox_idx_count],
{ avg_color, 1.0f } );
// bump the outer bounding box
m_model_bbox.Union( m_meshes_bbox[mesh_i] );
m_model_bbox.Union( mesh_bbox );
// add to the material group
material.m_bbox.Union( mesh_bbox );
}
@@ -410,7 +416,9 @@ void MODEL_3D::EndDrawMulti()
void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
SFVEC3F& aSelectionColor ) const
const SFVEC3F& aSelectionColor,
const glm::mat4 *aModelWorldMatrix,
const SFVEC3F *aCameraWorldPos ) const
{
if( aOpacity <= FLT_EPSILON )
return;
@@ -439,27 +447,102 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const float*)&param.x );
for( const MODEL_3D::MATERIAL& mat : m_materials )
std::vector<const MODEL_3D::MATERIAL *> materialsToRender;
materialsToRender.reserve( m_materials.size() );
if( aModelWorldMatrix && aCameraWorldPos )
{
if( ( mat.IsTransparent() != aTransparent )
// Sort Material groups
std::vector<std::pair<const MODEL_3D::MATERIAL*, float>> materialsSorted;
// Calculate the distance to the camera for each material group
for( const MODEL_3D::MATERIAL& mat : m_materials )
{
if( mat.m_render_idx_count == 0 )
{
continue;
}
if( ( mat.IsTransparent() != aTransparent )
&& ( aOpacity >= 1.0f )
&& m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
{
continue;
{
continue;
}
const BBOX_3D& bBox = mat.m_bbox;
const SFVEC3F& bBoxCenter = bBox.GetCenter();
const SFVEC3F bBoxWorld = *aModelWorldMatrix * glm::vec4( bBoxCenter, 1.0f );
const float distanceToCamera = glm::length( *aCameraWorldPos - bBoxWorld );
materialsSorted.emplace_back( &mat, distanceToCamera );
}
// Sort from back to front
std::sort( materialsSorted.begin(), materialsSorted.end(),
[&]( std::pair<const MODEL_3D::MATERIAL*, float>& a,
std::pair<const MODEL_3D::MATERIAL*, float>& b ) {
// If A is inside B, then A is rendered first
if( b.first->m_bbox.Inside( a.first->m_bbox ) )
{
return true;
}
else
{
if( a.first->m_bbox.Inside( b.first->m_bbox ) )
{
return false;
}
}
return a.second > b.second;
} );
for( const std::pair<const MODEL_3D::MATERIAL*, float>& mat : materialsSorted )
{
materialsToRender.push_back( mat.first );
}
}
else
{
for( const MODEL_3D::MATERIAL& mat : m_materials )
{
// There is at least one default material created in case a mesh has no declared materials.
// Most meshes have a material, so usually the first material will have nothing to render and is skip.
// See S3D::GetModel for more details.
if( mat.m_render_idx_count == 0 )
{
continue;
}
if( ( mat.IsTransparent() != aTransparent )
&& ( aOpacity >= 1.0f )
&& m_materialMode != MATERIAL_MODE::DIFFUSE_ONLY )
{
continue;
}
materialsToRender.push_back( &mat );
}
}
for( const MODEL_3D::MATERIAL* mat : materialsToRender )
{
switch( m_materialMode )
{
case MATERIAL_MODE::NORMAL:
OglSetMaterial( mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
OglSetMaterial( *mat, aOpacity, aUseSelectedMaterial, aSelectionColor );
break;
case MATERIAL_MODE::DIFFUSE_ONLY:
OglSetDiffuseMaterial( mat.m_Diffuse, aOpacity, aUseSelectedMaterial, aSelectionColor );
OglSetDiffuseMaterial( mat->m_Diffuse, aOpacity, aUseSelectedMaterial, aSelectionColor );
break;
case MATERIAL_MODE::CAD_MODE:
OglSetDiffuseMaterial( MaterialDiffuseToColorCAD( mat.m_Diffuse ), aOpacity,
OglSetDiffuseMaterial( MaterialDiffuseToColorCAD( mat->m_Diffuse ), aOpacity,
aUseSelectedMaterial, aSelectionColor );
break;
@@ -467,9 +550,9 @@ void MODEL_3D::Draw( bool aTransparent, float aOpacity, bool aUseSelectedMateria
break;
}
glDrawElements( GL_TRIANGLES, mat.m_render_idx_count, m_index_buffer_type,
glDrawElements( GL_TRIANGLES, mat->m_render_idx_count, m_index_buffer_type,
reinterpret_cast<const void*>(
static_cast<uintptr_t>( mat.m_render_idx_buffer_offset ) ) );
static_cast<uintptr_t>( mat->m_render_idx_buffer_offset ) ) );
}
}
+14 -5
View File
@@ -54,7 +54,7 @@ public:
*/
void DrawOpaque( bool aUseSelectedMaterial, SFVEC3F aSelectionColor = SFVEC3F( 0.0f ) ) const
{
Draw( false, 1.0f, aUseSelectedMaterial, aSelectionColor );
Draw( false, 1.0f, aUseSelectedMaterial, aSelectionColor, nullptr, nullptr );
}
/**
@@ -63,9 +63,19 @@ public:
void DrawTransparent( float aOpacity, bool aUseSelectedMaterial,
SFVEC3F aSelectionColor = SFVEC3F( 0.0f ) ) const
{
Draw( true, aOpacity, aUseSelectedMaterial, aSelectionColor );
Draw( true, aOpacity, aUseSelectedMaterial, aSelectionColor, nullptr, nullptr );
}
/**
* Render the model into the current context.
* if aModelWorldMatrix and aCameraWorldPos is provided,
* it renders the material groups sorted.
*/
void Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
const SFVEC3F& aSelectionColor,
const glm::mat4 *aModelWorldMatrix,
const SFVEC3F *aCameraWorldPos ) const;
/**
* Return true if have opaque meshes to render.
*/
@@ -136,6 +146,8 @@ private:
unsigned int m_render_idx_buffer_offset = 0;
unsigned int m_render_idx_count = 0;
BBOX_3D m_bbox; ///< bounding box for this material group, used for transparent material ordering
MATERIAL( const SMATERIAL& aOther ) : SMATERIAL( aOther ) { }
bool IsTransparent() const { return m_Transparency > FLT_EPSILON; }
};
@@ -159,9 +171,6 @@ private:
static void MakeBbox( const BBOX_3D& aBox, unsigned int aIdxOffset, VERTEX* aVtxOut,
GLuint* aIdxOut, const glm::vec4& aColor );
void Draw( bool aTransparent, float aOpacity, bool aUseSelectedMaterial,
SFVEC3F& aSelectionColor ) const;
};
#endif // _MODEL_3D_H_
@@ -22,14 +22,19 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cstdint>
#include <gal/opengl/kiglew.h> // Must be included first
#include "plugins/3dapi/xv3d_types.h"
#include "render_3d_opengl.h"
#include "opengl_utils.h"
#include "common_ogl/ogl_utils.h"
#include <footprint.h>
#include <3d_math.h>
#include <glm/geometric.hpp>
#include <math/util.h> // for KiROUND
#include <utility>
#include <vector>
#include <wx/log.h>
#include <base_units.h>
@@ -858,9 +863,12 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
glPopMatrix();
}
glm::mat4 cameraViewMatrix;
glGetFloatv( GL_MODELVIEW_MATRIX, glm::value_ptr( cameraViewMatrix ) );
// Render 3D Models (Non-transparent)
render3dModels( false, false );
render3dModels( true, false );
renderOpaqueModels( cameraViewMatrix );
// Display board body
if( m_boardAdapter.m_Cfg->m_Render.show_board_body )
@@ -922,8 +930,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
glTexEnvi( GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT );
glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA );
render3dModels( false, true );
render3dModels( true, true );
renderTransparentModels( cameraViewMatrix );
glDisable( GL_BLEND );
OglResetTextureState();
@@ -1143,14 +1150,15 @@ void RENDER_3D_OPENGL::renderSolderMaskLayer( PCB_LAYER_ID aLayerID, float aZPos
}
void RENDER_3D_OPENGL::render3dModelsSelected( bool aRenderTopOrBot, bool aRenderTransparentOnly,
bool aRenderSelectedOnly )
void RENDER_3D_OPENGL::get3dModelsSelected( std::list<MODELTORENDER> &aDstRenderList,
bool aGetTop, bool aGetBot, bool aRenderTransparentOnly,
bool aRenderSelectedOnly )
{
wxASSERT( ( aGetTop == true ) || ( aGetBot == true ) );
if( !m_boardAdapter.GetBoard() )
return;
MODEL_3D::BeginDrawMulti( !aRenderSelectedOnly );
// Go for all footprints
for( FOOTPRINT* fp : m_boardAdapter.GetBoard()->Footprints() )
{
@@ -1175,54 +1183,52 @@ void RENDER_3D_OPENGL::render3dModelsSelected( bool aRenderTopOrBot, bool aRende
{
if( m_boardAdapter.IsFootprintShown( (FOOTPRINT_ATTR_T) fp->GetAttributes() ) )
{
if( aRenderTopOrBot == !fp->IsFlipped() )
renderFootprint( fp, aRenderTransparentOnly, highlight );
const bool isFlipped = fp->IsFlipped();
if( ( aGetTop == !isFlipped ) ||
( aGetBot == isFlipped ) )
get3dModelsFromFootprint( aDstRenderList, fp, aRenderTransparentOnly, highlight );
}
}
}
MODEL_3D::EndDrawMulti();
}
void RENDER_3D_OPENGL::render3dModels( bool aRenderTopOrBot, bool aRenderTransparentOnly )
{
if( m_boardAdapter.m_IsBoardView )
render3dModelsSelected( aRenderTopOrBot, aRenderTransparentOnly, true );
render3dModelsSelected( aRenderTopOrBot, aRenderTransparentOnly, false );
}
void RENDER_3D_OPENGL::renderFootprint( const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
bool aIsSelected )
void RENDER_3D_OPENGL::get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstRenderList,
const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
bool aIsSelected )
{
if( !aFootprint->Models().empty() )
{
const double zpos = m_boardAdapter.GetFootprintZPos( aFootprint->IsFlipped() );
SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
glPushMatrix();
VECTOR2I pos = aFootprint->GetPosition();
glTranslatef( pos.x * m_boardAdapter.BiuTo3dUnits(), -pos.y * m_boardAdapter.BiuTo3dUnits(),
zpos );
glm::mat4 fpMatrix( 1.0f );
fpMatrix = glm::translate( fpMatrix,
SFVEC3F( pos.x * m_boardAdapter.BiuTo3dUnits(),
-pos.y * m_boardAdapter.BiuTo3dUnits(),
zpos ) );
if( !aFootprint->GetOrientation().IsZero() )
glRotated( aFootprint->GetOrientation().AsDegrees(), 0.0, 0.0, 1.0 );
{
fpMatrix = glm::rotate( fpMatrix,
(float) aFootprint->GetOrientation().AsRadians(),
SFVEC3F( 0.0f, 0.0f, 1.0f ) );
}
if( aFootprint->IsFlipped() )
{
glRotatef( 180.0f, 0.0f, 1.0f, 0.0f );
glRotatef( 180.0f, 0.0f, 0.0f, 1.0f );
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 1.0f, 0.0f ) );
fpMatrix = glm::rotate( fpMatrix, glm::pi<float>(), SFVEC3F( 0.0f, 0.0f, 1.0f ) );
}
double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3dUnits() * UNITS3D_TO_UNITSPCB;
const double modelunit_to_3d_units_factor = m_boardAdapter.BiuTo3dUnits() *
UNITS3D_TO_UNITSPCB;
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
modelunit_to_3d_units_factor );
fpMatrix = glm::scale( fpMatrix,
SFVEC3F( modelunit_to_3d_units_factor ) );
// Get the list of model files for this model
for( const FP_3DMODEL& sM : aFootprint->Models() )
@@ -1243,66 +1249,232 @@ void RENDER_3D_OPENGL::renderFootprint( const FOOTPRINT* aFootprint, bool aRende
if( ( !aRenderTransparentOnly && modelPtr->HasOpaqueMeshes() && opaque ) ||
( aRenderTransparentOnly && ( modelPtr->HasTransparentMeshes() || !opaque ) ) )
{
glPushMatrix();
glm::mat4 modelworldMatrix = fpMatrix;
std::vector<double> key = { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z,
sM.m_Rotation.x, sM.m_Rotation.y, sM.m_Rotation.z,
sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z };
const SFVEC3F offset = SFVEC3F( sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z );
const SFVEC3F rotation = SFVEC3F( sM.m_Rotation.x, sM.m_Rotation.y, sM.m_Rotation.z );
const SFVEC3F scale = SFVEC3F( sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z );
std::vector<float> key = { offset.x, offset.y, offset.z,
rotation.x, rotation.y, rotation.z,
scale.x, scale.y, scale.z };
auto it = m_3dModelMatrixMap.find( key );
if( it != m_3dModelMatrixMap.end() )
{
glMultMatrixf( glm::value_ptr( it->second ) );
modelworldMatrix *= it->second;
}
else
{
glm::mat4 mtx( 1 );
mtx = glm::translate( mtx, { sM.m_Offset.x, sM.m_Offset.y, sM.m_Offset.z } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.z ), { 0.0f, 0.0f, 1.0f } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.y ), { 0.0f, 1.0f, 0.0f } );
mtx = glm::rotate( mtx, glm::radians( (float) -sM.m_Rotation.x ), { 1.0f, 0.0f, 0.0f } );
mtx = glm::scale( mtx, { sM.m_Scale.x, sM.m_Scale.y, sM.m_Scale.z } );
glm::mat4 mtx( 1.0f );
mtx = glm::translate( mtx, offset );
mtx = glm::rotate( mtx, glm::radians( -rotation.z ), { 0.0f, 0.0f, 1.0f } );
mtx = glm::rotate( mtx, glm::radians( -rotation.y ), { 0.0f, 1.0f, 0.0f } );
mtx = glm::rotate( mtx, glm::radians( -rotation.x ), { 1.0f, 0.0f, 0.0f } );
mtx = glm::scale( mtx, scale );
m_3dModelMatrixMap[ key ] = mtx;
glMultMatrixf( glm::value_ptr( mtx ) );
modelworldMatrix *= mtx;
}
if( aRenderTransparentOnly )
{
modelPtr->DrawTransparent( sM.m_Opacity,
aFootprint->IsSelected() || aIsSelected,
selColor );
aDstRenderList.emplace_back( modelworldMatrix,
modelPtr,
sM.m_Opacity,
true,
aFootprint->IsSelected() || aIsSelected );
}
else
{
modelPtr->DrawOpaque( aFootprint->IsSelected() || aIsSelected, selColor );
aDstRenderList.emplace_back( modelworldMatrix,
modelPtr,
1.0f,
false,
aFootprint->IsSelected() || aIsSelected );
}
}
}
}
}
}
if( m_boardAdapter.m_Cfg->m_Render.opengl_show_model_bbox )
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glDisable( GL_LIGHTING );
void RENDER_3D_OPENGL::renderOpaqueModels( const glm::mat4 &aCameraViewMatrix )
{
const SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
glLineWidth( 1 );
modelPtr->DrawBboxes();
glPushMatrix();
glLineWidth( 4 );
modelPtr->DrawBbox();
std::list<MODELTORENDER> renderList;
glEnable( GL_LIGHTING );
glDisable( GL_BLEND );
}
if( m_boardAdapter.m_IsBoardView )
{
renderList.clear();
glPopMatrix();
get3dModelsSelected( renderList, true, true, false, true );
if( !renderList.empty() )
{
MODEL_3D::BeginDrawMulti( false );
for( const MODELTORENDER& mtr : renderList )
{
renderModel( aCameraViewMatrix, mtr, selColor, nullptr );
}
MODEL_3D::EndDrawMulti();
}
}
renderList.clear();
get3dModelsSelected( renderList, true, true, false, false );
if( !renderList.empty() )
{
MODEL_3D::BeginDrawMulti( true );
for( const MODELTORENDER& mtr : renderList )
{
renderModel( aCameraViewMatrix, mtr, selColor, nullptr );
}
MODEL_3D::EndDrawMulti();
}
glPopMatrix();
}
void RENDER_3D_OPENGL::renderTransparentModels( const glm::mat4 &aCameraViewMatrix )
{
const SFVEC3F selColor = m_boardAdapter.GetColor( m_boardAdapter.m_Cfg->m_Render.opengl_selection_color );
std::list<MODELTORENDER> renderListModels; // do not clear it until this function returns
if( m_boardAdapter.m_IsBoardView )
{
// Get Transparent Selected
get3dModelsSelected( renderListModels, true, true, true, true );
}
// Get Transparent Not Selected
get3dModelsSelected( renderListModels, true, true, true, false );
if( renderListModels.empty() )
return;
std::vector<std::pair<const MODELTORENDER *, float>> transparentModelList;
transparentModelList.reserve( renderListModels.size() );
// Calculate the distance to the camera for each model
const SFVEC3F &cameraPos = m_camera.GetPos();
for( const MODELTORENDER& mtr : renderListModels )
{
const BBOX_3D& bBox = mtr.m_model->GetBBox();
const SFVEC3F& bBoxCenter = bBox.GetCenter();
const SFVEC3F bBoxWorld = mtr.m_modelWorldMat * glm::vec4( bBoxCenter, 1.0f );
const float distanceToCamera = glm::length( cameraPos - bBoxWorld );
transparentModelList.emplace_back( &mtr, distanceToCamera );
}
// Sort from back to front
std::sort( transparentModelList.begin(), transparentModelList.end(),
[&]( std::pair<const MODELTORENDER *, float>& a,
std::pair<const MODELTORENDER *, float>& b ) {
return a.second > b.second;
} );
// Start rendering calls
glPushMatrix();
bool isUsingColorInformation = !( transparentModelList.begin()->first->m_isSelected &&
m_boardAdapter.m_IsBoardView );
MODEL_3D::BeginDrawMulti( isUsingColorInformation );
for( const std::pair<const MODELTORENDER *, float>& mtr : transparentModelList )
{
if( m_boardAdapter.m_IsBoardView )
{
// Toggle between using model color or the select color
if( !isUsingColorInformation && !mtr.first->m_isSelected )
{
isUsingColorInformation = true;
glEnableClientState( GL_COLOR_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glEnable( GL_COLOR_MATERIAL );
}
else
{
if( isUsingColorInformation && mtr.first->m_isSelected )
{
isUsingColorInformation = false;
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisable( GL_COLOR_MATERIAL );
}
}
}
glPopMatrix();
// Render model, sort each individuall material group
// by passing cameraPos
renderModel( aCameraViewMatrix, *mtr.first, selColor, &cameraPos );
}
MODEL_3D::EndDrawMulti();
glPopMatrix();
}
void RENDER_3D_OPENGL::renderModel( const glm::mat4 &aCameraViewMatrix,
const MODELTORENDER &aModelToRender,
const SFVEC3F &aSelColor,
const SFVEC3F *aCameraWorldPos )
{
const glm::mat4 modelviewMatrix = aCameraViewMatrix * aModelToRender.m_modelWorldMat;
glLoadMatrixf( glm::value_ptr( modelviewMatrix ) );
aModelToRender.m_model->Draw( aModelToRender.m_isTransparent,
aModelToRender.m_opacity,
aModelToRender.m_isSelected,
aSelColor,
&aModelToRender.m_modelWorldMat,
aCameraWorldPos );
if( m_boardAdapter.m_Cfg->m_Render.opengl_show_model_bbox )
{
const bool wasBlendEnabled = glIsEnabled( GL_BLEND );
if( !wasBlendEnabled )
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
glDisable( GL_LIGHTING );
glLineWidth( 1 );
aModelToRender.m_model->DrawBboxes();
glLineWidth( 4 );
aModelToRender.m_model->DrawBbox();
glEnable( GL_LIGHTING );
if( !wasBlendEnabled )
{
glDisable( GL_BLEND );
}
}
}
@@ -129,18 +129,44 @@ private:
*/
void load3dModels( REPORTER* aStatusReporter );
/**
* @param aRenderTopOrBot true will render Top, false will render bottom
* @param aRenderTransparentOnly true will render only the transparent objects, false will
* render opaque
*/
void render3dModels( bool aRenderTopOrBot, bool aRenderTransparentOnly );
struct MODELTORENDER
{
glm::mat4 m_modelWorldMat;
const MODEL_3D* m_model;
float m_opacity;
bool m_isTransparent;
bool m_isSelected;
void render3dModelsSelected( bool aRenderTopOrBot, bool aRenderTransparentOnly,
bool aRenderSelectedOnly );
MODELTORENDER( glm::mat4 aModelWorldMat,
const MODEL_3D* aNodel,
float aOpacity,
bool aIsTransparent,
bool aIsSelected ) :
m_modelWorldMat( std::move( aModelWorldMat ) ),
m_model( aNodel ),
m_opacity( aOpacity ),
m_isTransparent( aIsTransparent ),
m_isSelected( aIsSelected )
{
}
};
void renderFootprint( const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
bool aIsSelected );
void renderOpaqueModels( const glm::mat4 &aCameraViewMatrix );
void renderTransparentModels( const glm::mat4 &aCameraViewMatrix );
void renderModel( const glm::mat4 &aCameraViewMatrix,
const MODELTORENDER &aModelToRender,
const SFVEC3F &aSelColor,
const SFVEC3F *aCameraWorldPos );
void get3dModelsSelected( std::list<MODELTORENDER> &aDstRenderList,
bool aGetTop, bool aGetBot, bool aRenderTransparentOnly,
bool aRenderSelectedOnly );
void get3dModelsFromFootprint( std::list<MODELTORENDER> &aDstRenderList,
const FOOTPRINT* aFootprint, bool aRenderTransparentOnly,
bool aIsSelected );
void setLightFront( bool enabled );
void setLightTop( bool enabled );
@@ -210,7 +236,7 @@ private:
// Caches
std::map< wxString, MODEL_3D* > m_3dModelMap;
std::map< std::vector<double>, glm::mat4 > m_3dModelMatrixMap;
std::map< std::vector<float>, glm::mat4 > m_3dModelMatrixMap;
BOARD_ITEM* m_currentRollOverItem;
@@ -229,6 +229,16 @@ bool BBOX_2D::Inside( const SFVEC2F& aPoint ) const
}
bool BBOX_2D::Inside( const BBOX_2D& aBBox ) const
{
wxASSERT( IsInitialized() );
wxASSERT( aBBox.IsInitialized() );
return Inside( aBBox.Min() ) &&
Inside( aBBox.Max() );
}
float BBOX_2D::Area() const
{
SFVEC2F extent = GetExtent();
@@ -132,6 +132,14 @@ public:
*/
bool Inside( const SFVEC2F& aPoint ) const;
/**
* Check if a bounding box is inside this bounding box.
*
* @param aBBox the bounding box to test if it is inside
* @return true if aBBox is smaller and all points are inside
*/
bool Inside( const BBOX_2D& aBBox ) const;
/**
* Calculate the area of a bounding box.
*
@@ -238,6 +238,16 @@ bool BBOX_3D::Inside( const SFVEC3F& aPoint ) const
}
bool BBOX_3D::Inside( const BBOX_3D& aBBox ) const
{
wxASSERT( IsInitialized() );
wxASSERT( aBBox.IsInitialized() );
return Inside( aBBox.Min() ) &&
Inside( aBBox.Max() );
}
float BBOX_3D::Volume() const
{
wxASSERT( IsInitialized() );
@@ -125,6 +125,14 @@ public:
*/
bool Inside( const SFVEC3F& aPoint ) const;
/**
* Check if a bounding box is inside this bounding box.
*
* @param aBBox the bounding box to test if it is inside
* @return true if aBBox is smaller and all points are inside
*/
bool Inside( const BBOX_3D& aBBox ) const;
/**
* Apply a transformation matrix to the box points.
*
@@ -70,6 +70,8 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
m_selected = -1;
m_previewLabel->SetFont( KIUI::GetStatusFont( this ) );
// Set the bitmap of 3D view buttons:
m_bpvTop->SetBitmap( KiBitmap( BITMAPS::axis3d_top ) );
m_bpvFront->SetBitmap( KiBitmap( BITMAPS::axis3d_front ) );
@@ -140,6 +142,9 @@ PANEL_PREVIEW_3D_MODEL::PANEL_PREVIEW_3D_MODEL( wxWindow* aParent, PCB_BASE_FRAM
this );
}
aFrame->Connect( UNITS_CHANGED, wxCommandEventHandler( PANEL_PREVIEW_3D_MODEL::onUnitsChanged ),
nullptr, this );
#ifdef __WXOSX__
// Call layout once to get the proper button sizes after the bitmaps have been set
Layout();
@@ -538,6 +543,29 @@ void PANEL_PREVIEW_3D_MODEL::onMouseWheelOffset( wxMouseEvent& event )
}
void PANEL_PREVIEW_3D_MODEL::onUnitsChanged( wxCommandEvent& aEvent )
{
double xoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
xoff->GetValue() )
/ pcbIUScale.IU_PER_MM;
double yoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
yoff->GetValue() )
/ pcbIUScale.IU_PER_MM;
double zoff_mm = EDA_UNIT_UTILS::UI::DoubleValueFromString( pcbIUScale, m_userUnits,
zoff->GetValue() )
/ pcbIUScale.IU_PER_MM;
PCB_BASE_FRAME* frame = static_cast<PCB_BASE_FRAME*>( aEvent.GetClientData() );
m_userUnits = frame->GetUserUnits();
xoff->SetValue( formatOffsetValue( xoff_mm ) );
yoff->SetValue( formatOffsetValue( yoff_mm ) );
zoff->SetValue( formatOffsetValue( zoff_mm ) );
aEvent.Skip();
}
void PANEL_PREVIEW_3D_MODEL::UpdateDummyFootprint( bool aReloadRequired )
{
m_dummyFootprint->Models().clear();
@@ -141,6 +141,8 @@ private:
void doIncrementRotation( wxSpinEvent& aEvent, double aSign );
void doIncrementOffset( wxSpinEvent& aEvent, double aSign );
void onUnitsChanged( wxCommandEvent& aEvent );
wxString formatScaleValue( double aValue );
wxString formatRotationValue( double aValue );
wxString formatOffsetValue( double aValue );
@@ -183,12 +183,11 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
wxBoxSizer* bSizer6;
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
wxStaticText* staticPreviewLabel;
staticPreviewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
staticPreviewLabel->Wrap( -1 );
staticPreviewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
m_previewLabel = new wxStaticText( this, wxID_ANY, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 );
m_previewLabel->Wrap( -1 );
m_previewLabel->SetFont( wxFont( 11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) );
bSizer6->Add( staticPreviewLabel, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
bSizer6->Add( m_previewLabel, 1, wxEXPAND|wxLEFT|wxRIGHT, 10 );
bSizerRight->Add( bSizer6, 0, wxEXPAND, 5 );
@@ -207,7 +206,7 @@ PANEL_PREVIEW_3D_MODEL_BASE::PANEL_PREVIEW_3D_MODEL_BASE( wxWindow* parent, wxWi
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), wxBU_AUTODRAW|0 );
m_bpvISO->SetToolTip( _("Enable/disable orthographic projection") );
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP|wxBOTTOM, 5 );
bSizer3DButtons->Add( m_bpvISO, 0, wxTOP, 14 );
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
@@ -2089,7 +2089,7 @@
<object class="sizeritem" expanded="1">
<property name="border">10</property>
<property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<property name="proportion">1</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
@@ -2127,11 +2127,11 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">staticPreviewLabel</property>
<property name="name">m_previewLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">none</property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
@@ -2172,8 +2172,8 @@
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxTOP|wxBOTTOM</property>
<property name="border">14</property>
<property name="flag">wxTOP</property>
<property name="proportion">0</property>
<object class="wxBitmapButton" expanded="1">
<property name="BottomDockable">1</property>
@@ -68,6 +68,7 @@ class PANEL_PREVIEW_3D_MODEL_BASE : public wxPanel
wxSlider* m_opacity;
wxTextCtrl* m_boardThicknessCtrl;
wxStaticText* m_boardThicknessUnits;
wxStaticText* m_previewLabel;
wxBoxSizer* m_SizerPanelView;
wxBitmapButton* m_bpvISO;
wxBitmapButton* m_bpvLeft;
+6 -2
View File
@@ -350,12 +350,16 @@ endif(USE_DISTCC)
# Set flags for GCC, or treat llvm as GCC
#================================================
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
if( CMAKE_COMPILER_IS_GNUCXX )
# Set 32-bit flag for GCC to prevent excess precision
# clang des not know this flag, so keep this separate
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
set( CMAKE_CXX_FLAGS "-ffloat-store ${CMAKE_CXX_FLAGS}" )
endif()
endif( CMAKE_COMPILER_IS_GNUCXX )
if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
# Link flags in Debug: -g1 and -ggdb1 or -g1 and -ggdb3 can be used.
# Level 1 produces minimal information, enough for making basic backtraces.
+1 -1
View File
@@ -66,7 +66,7 @@ macro( create_git_version_header _git_src_path )
# Check to make sure 'git' command did not fail. Otherwise fallback
# to KiCadVersion.cmake as the revision level.
if( _git_describe_result EQUAL 0 )
set( KICAD_VERSION "(${_git_DESCRIBE})" )
set( KICAD_VERSION "${_git_DESCRIBE}" )
endif()
if( _git_rev_parse_head_result EQUAL 0 )
+11 -2
View File
@@ -926,8 +926,17 @@ if(wxWidgets_FOUND)
"\\2" wxWidgets_VERSION_MINOR "${_wx_version_h}" )
string(REGEX REPLACE "^(.*\n)?#define +wxRELEASE_NUMBER +([0-9]+).*"
"\\2" wxWidgets_VERSION_PATCH "${_wx_version_h}" )
set(wxWidgets_VERSION_STRING
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" )
string(REGEX REPLACE "^(.*\n)?#define +wxSUBRELEASE_NUMBER +([0-9]+).*"
"\\2" wxWidgets_VERSION_SUBRELEASE "${_wx_version_h}" )
if( ${wxWidgets_VERSION_SUBRELEASE} GREATER 0 )
set(wxWidgets_VERSION_STRING
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}.${wxWidgets_VERSION_SUBRELEASE}" )
else()
set(wxWidgets_VERSION_STRING
"${wxWidgets_VERSION_MAJOR}.${wxWidgets_VERSION_MINOR}.${wxWidgets_VERSION_PATCH}" )
endif()
DBG_MSG("wxWidgets_VERSION_STRING: ${wxWidgets_VERSION_STRING}")
endif()
+1 -1
View File
@@ -37,7 +37,7 @@
# KiCad.
#
# Note: This version string should follow the semantic versioning system
set( KICAD_SEMANTIC_VERSION "7.0.0" )
set( KICAD_SEMANTIC_VERSION "7.0.1" )
# Default the version to the semantic version.
# This is overridden by the git repository tag though (if using git)
+1
View File
@@ -45,6 +45,7 @@
#include <eda_base_frame.h>
#include <eda_draw_frame.h>
#include <paths.h>
#include <kiplatform/ui.h>
static std::unique_ptr<BITMAP_STORE> s_BitmapStore;
+18 -11
View File
@@ -75,6 +75,7 @@ void BITMAP_BASE::SetImage( wxImage* aImage )
delete m_originalImage;
m_originalImage = new wxImage( *aImage );
rebuildBitmap();
updatePPI();
}
@@ -90,6 +91,21 @@ void BITMAP_BASE::rebuildBitmap( bool aResetID )
}
void BITMAP_BASE::updatePPI()
{
// Todo: eventually we need to support dpi / scaling in both dimensions
int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
if( dpiX > 1 )
{
if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
m_ppi = KiROUND( dpiX * 2.54 );
else
m_ppi = dpiX;
}
}
void BITMAP_BASE::ImportData( BITMAP_BASE* aItem )
{
*m_image = *aItem->m_image;
@@ -116,6 +132,7 @@ bool BITMAP_BASE::ReadImageFile( wxInputStream& aInStream )
delete m_originalImage;
m_originalImage = new wxImage( *m_image );
rebuildBitmap();
updatePPI();
return true;
}
@@ -136,17 +153,7 @@ bool BITMAP_BASE::ReadImageFile( const wxString& aFullFilename )
delete m_originalImage;
m_originalImage = new wxImage( *m_image );
rebuildBitmap();
// Todo: eventually we need to support dpi / scaling in both dimensions
int dpiX = m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
if( dpiX > 1 )
{
if( m_originalImage->GetOptionInt( wxIMAGE_OPTION_RESOLUTIONUNIT ) == wxIMAGE_RESOLUTION_CM )
m_ppi = KiROUND( dpiX * 2.54 );
else
m_ppi = dpiX;
}
updatePPI();
return true;
}
+10 -2
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 Jon Evans <jon@craftyjon.com>
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -178,7 +178,15 @@ bool DATABASE_CONNECTION::Disconnect()
return false;
}
m_conn->disconnect();
try
{
m_conn->disconnect();
}
catch( boost::locale::conv::conversion_error& exc )
{
wxLogTrace( traceDatabase, wxT( "Disconnect() error \"%s\" occured." ), exc.what() );
return false;
}
return !m_conn->connected();
}
+1 -1
View File
@@ -1129,7 +1129,7 @@ static void buildKicadAboutBanner( EDA_BASE_FRAME* aParent, ABOUT_APP_INFO& aInf
#define SYMBOL_LIB_CONTRIBUTION _( "Symbols by" )
aInfo.AddLibrarian( new CONTRIBUTOR( wxS( "GitLab contributors" ),
wxEmptyString,
wxS( "https://gitlab.com/kicad/libraries/kicad-symbols/-/graphs/v7" ),
wxS( "https://gitlab.com/kicad/libraries/kicad-symbols/-/graphs/master" ),
SYMBOL_LIB_CONTRIBUTION,
aInfo.CreateKiBitmap( BITMAPS::add_component ) ) );
+4 -1
View File
@@ -262,8 +262,11 @@ void PANEL_COLOR_SETTINGS::createSwatch( int aLayer, const wxString& aName )
defaultColor, SWATCH_MEDIUM );
swatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
m_colorsGridSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxLEFT, 5 );
// Display the swatches in the left column and the layer name in the right column
// The right column is sometimes (depending on the translation) truncated for long texts.
// We cannot allow swatches to be truncated or not shown
m_colorsGridSizer->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3 );
m_colorsGridSizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxLEFT, 5 );
m_labels[aLayer] = label;
m_swatches[aLayer] = swatch;
+9 -10
View File
@@ -58,7 +58,13 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
const wxPoint& aPosition, const wxSize& aSize,
KIGFX::GAL_DISPLAY_OPTIONS& aOptions, GAL_TYPE aGalType ) :
wxScrolledCanvas( aParentWindow, aWindowId, aPosition, aSize ),
m_MouseCapturedLost( false ),
m_parent( aParentWindow ),
m_edaFrame( nullptr ),
m_lastRefresh( 0 ),
m_pendingRefresh( false ),
m_drawing( false ),
m_drawingEnabled( false ),
m_gal( nullptr ),
m_view( nullptr ),
m_painter( nullptr ),
@@ -70,11 +76,10 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
m_stealsFocus( true ),
m_statusPopup( nullptr )
{
m_parent = aParentWindow;
m_MouseCapturedLost = false;
m_PaintEventCounter = std::make_unique<PROF_COUNTER>( "Draw panel paint events" );
m_minRefreshPeriod = 13; // 77 FPS (minus render time) by default
SetLayoutDirection( wxLayout_LeftToRight );
m_edaFrame = dynamic_cast<EDA_DRAW_FRAME*>( m_parent );
@@ -146,12 +151,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
Connect( eventType, wxEventHandler( EDA_DRAW_PANEL_GAL::OnEvent ), nullptr,
m_eventDispatcher );
m_pendingRefresh = false;
m_drawing = false;
m_drawingEnabled = false;
m_minRefreshPeriod = 13; // 77 FPS (minus render time) by default
// Set up timer that prevents too frequent redraw commands
m_refreshTimer.SetOwner( this );
Connect( m_refreshTimer.GetId(), wxEVT_TIMER,
@@ -212,7 +211,7 @@ void EDA_DRAW_PANEL_GAL::DoRePaint()
if( !m_drawingEnabled )
return;
if( !m_gal->IsVisible() )
if( !m_gal->IsInitialized() || !m_gal->IsVisible() )
return;
m_pendingRefresh = false;
+11 -6
View File
@@ -3,7 +3,7 @@
*
* Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2004-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -78,12 +78,16 @@ BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER )
EVT_ACTIVATE( EDA_DRAW_FRAME::onActivate )
END_EVENT_TABLE()
bool EDA_DRAW_FRAME::m_openGLFailureOccured = false;
EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
long aStyle, const wxString& aFrameName, const EDA_IU_SCALE& aIuScale ) :
KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, aIuScale )
long aStyle, const wxString& aFrameName,
const EDA_IU_SCALE& aIuScale ) :
KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName, aIuScale ),
m_socketServer( nullptr )
{
m_socketServer = nullptr;
m_mainToolBar = nullptr;
@@ -171,8 +175,8 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
OnMove( dummy );
// we need to kludge the msg panel to the correct size again
// especially important even for first launches as the constructor of the window here usually doesn't
// have the correct dpi awareness yet
// especially important even for first launches as the constructor of the window
// here usually doesn't have the correct dpi awareness yet
m_frameSize.y += m_msgFrameHeight;
m_msgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight( this );
m_frameSize.y -= m_msgFrameHeight;
@@ -609,7 +613,8 @@ void EDA_DRAW_FRAME::DisplayGridMsg()
{
wxString msg;
msg.Printf( wxS( "grid %s" ), MessageTextFromValue( GetCanvas()->GetGAL()->GetGridSize().x, false ) );
msg.Printf( wxS( "grid %s" ), MessageTextFromValue( GetCanvas()->GetGAL()->GetGridSize().x,
false ) );
SetStatusText( msg, 4 );
}
+3 -4
View File
@@ -392,10 +392,9 @@ static struct EDA_ITEM_DESC
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
REGISTER_TYPE( EDA_ITEM );
auto typeProp = new PROPERTY_ENUM<EDA_ITEM, KICAD_T>( wxS( "Type" ),
NO_SETTER( EDA_ITEM, KICAD_T ), &EDA_ITEM::Type );
typeProp->SetIsInternal( true );
propMgr.AddProperty( typeProp );
propMgr.AddProperty( new PROPERTY_ENUM<EDA_ITEM, KICAD_T>( wxS( "Type" ),
NO_SETTER( EDA_ITEM, KICAD_T ), &EDA_ITEM::Type ) )
.SetIsInternal();
}
} _EDA_ITEM_DESC;
+19 -4
View File
@@ -1687,21 +1687,36 @@ static struct EDA_SHAPE_DESC
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
REGISTER_TYPE( EDA_SHAPE );
auto isNotPolygon =
[]( INSPECTABLE* aItem ) -> bool
{
// Polygons, unlike other shapes, have no meaningful start or end coordinates
if( EDA_SHAPE* shape = dynamic_cast<EDA_SHAPE*>( aItem ) )
return shape->GetShape() != SHAPE_T::POLY;
return false;
};
auto shape = new PROPERTY_ENUM<EDA_SHAPE, SHAPE_T>( _HKI( "Shape" ),
NO_SETTER( EDA_SHAPE, SHAPE_T ), &EDA_SHAPE::GetShape );
propMgr.AddProperty( shape );
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start X" ),
&EDA_SHAPE::SetStartX, &EDA_SHAPE::GetStartX, PROPERTY_DISPLAY::PT_COORD,
ORIGIN_TRANSFORMS::ABS_X_COORD ) );
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
.SetAvailableFunc( isNotPolygon );
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Start Y" ),
&EDA_SHAPE::SetStartY, &EDA_SHAPE::GetStartY, PROPERTY_DISPLAY::PT_COORD,
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
.SetAvailableFunc( isNotPolygon );
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End X" ),
&EDA_SHAPE::SetEndX, &EDA_SHAPE::GetEndX, PROPERTY_DISPLAY::PT_COORD,
ORIGIN_TRANSFORMS::ABS_X_COORD ) );
ORIGIN_TRANSFORMS::ABS_X_COORD ) )
.SetAvailableFunc( isNotPolygon );
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "End Y" ),
&EDA_SHAPE::SetEndY, &EDA_SHAPE::GetEndY, PROPERTY_DISPLAY::PT_COORD,
ORIGIN_TRANSFORMS::ABS_Y_COORD ) );
ORIGIN_TRANSFORMS::ABS_Y_COORD ) )
.SetAvailableFunc( isNotPolygon );
// TODO: m_arcCenter, m_bezierC1, m_bezierC2, m_poly
propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Line Width" ),
&EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::PT_SIZE ) );
+4 -1
View File
@@ -65,7 +65,7 @@ int EDA_UNIT_UTILS::Mils2mm( double aVal )
}
void EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS& aUnits )
bool EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS& aUnits )
{
wxString buf( aTextValue.Strip( wxString::both ) );
unsigned brk_point = 0;
@@ -92,6 +92,9 @@ void EDA_UNIT_UTILS::FetchUnitsFromString( const wxString& aTextValue, EDA_UNITS
aUnits = EDA_UNITS::INCHES;
else if( unit == wxT( "de" ) || unit == wxT( "ra" ) ) // "deg" or "rad"
aUnits = EDA_UNITS::DEGREES;
else
return false;
return true;
}
+143 -32
View File
@@ -18,23 +18,25 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fontconfig/fontconfig.h>
#include <font/fontconfig.h>
#include <pgm_base.h>
#include <wx/log.h>
#include <trace_helpers.h>
#include <string_utils.h>
#include <macros.h>
#include <font/fontconfig.h>
using namespace fontconfig;
static FONTCONFIG* g_config = nullptr;
inline static FcChar8* wxStringToFcChar8( const wxString& str )
/**
* A simple wrapper to avoid exporing fontconfig in the header
*/
struct fontconfig::FONTCONFIG_PAT
{
wxScopedCharBuffer const fcBuffer = str.ToUTF8();
return (FcChar8*) fcBuffer.data();
}
FcPattern* pat;
};
wxString FONTCONFIG::Version()
@@ -61,19 +63,112 @@ FONTCONFIG* Fontconfig()
}
bool FONTCONFIG::isLanguageMatch( const wxString& aSearchLang, const wxString& aSupportedLang )
{
if( aSearchLang.Lower() == aSupportedLang.Lower() )
return true;
if( aSupportedLang.empty() )
return false;
if( aSearchLang.empty() )
return false;
wxArrayString supportedLangBits;
wxStringSplit( aSupportedLang.Lower(), supportedLangBits, wxS( '-' ) );
wxArrayString searhcLangBits;
wxStringSplit( aSearchLang.Lower(), searhcLangBits, wxS( '-' ) );
// if either side of the comparison have only one section, then its a broad match but fine
// i.e. the haystack is declaring broad support or the search language is broad
if( searhcLangBits.size() == 1 || supportedLangBits.size() == 1 )
{
return searhcLangBits[0] == supportedLangBits[0];
}
// the full two part comparison should have passed the initial shortcut
return false;
}
std::string FONTCONFIG::getFcString( FONTCONFIG_PAT& aPat, const char* aObj, int aIdx )
{
FcChar8* str;
std::string res;
if( FcPatternGetString( aPat.pat, aObj, aIdx, &str ) == FcResultMatch )
res = std::string( reinterpret_cast<char*>( str ) );
return res;
}
void FONTCONFIG::getAllFamilyStrings( FONTCONFIG_PAT& aPat,
std::unordered_map<std::string, std::string>& aFamStringMap )
{
std::string famLang;
std::string fam;
int langIdx = 0;
do
{
famLang = getFcString( aPat, FC_FAMILYLANG, langIdx );
if( famLang.empty() && langIdx != 0 )
break;
else
{
fam = getFcString( aPat, FC_FAMILY, langIdx );
aFamStringMap.insert_or_assign( famLang, fam );
}
} while( langIdx++ < std::numeric_limits<
int8_t>::max() ); //arbitrary to avoid getting stuck for any reason
}
std::string FONTCONFIG::getFamilyStringByLang( FONTCONFIG_PAT& aPat, const wxString& aDesiredLang )
{
std::unordered_map<std::string, std::string> famStrings;
getAllFamilyStrings( aPat, famStrings );
if( famStrings.empty() )
return "";
for( auto const& [key, val] : famStrings )
{
if( isLanguageMatch( aDesiredLang, FROM_UTF8( key.c_str() ) ) )
{
return val;
}
}
// fall back to the first and maybe only available name
// most fonts by review don't even bother declaring more than one font family name
// and they don't even bother declare the language tag either, they just leave it blank
return famStrings.begin()->second;
}
FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString &aFontFile,
bool aBold, bool aItalic )
{
FF_RESULT retval = FF_RESULT::FF_ERROR;
wxString qualifiedFontName = aFontName;
wxScopedCharBuffer const fcBuffer = qualifiedFontName.ToUTF8();
FcPattern* pat = FcPatternCreate();
if( aBold )
qualifiedFontName << wxS( ":Bold" );
FcPatternAddString( pat, FC_STYLE, (const FcChar8*) "Bold" );
if( aItalic )
qualifiedFontName << wxS( ":Italic" );
FcPatternAddString( pat, FC_STYLE, (const FcChar8*) "Italic" );
FcPatternAddString( pat, FC_FAMILY, (FcChar8*) fcBuffer.data() );
FcPattern* pat = FcNameParse( wxStringToFcChar8( qualifiedFontName ) );
FcConfigSubstitute( nullptr, pat, FcMatchPattern );
FcDefaultSubstitute( pat );
@@ -95,6 +190,9 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
retval = FF_RESULT::FF_SUBSTITUTE;
std::unordered_map<std::string, std::string> famStrings;
FONTCONFIG_PAT patHolder{ font };
getAllFamilyStrings( patHolder, famStrings );
if( FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch )
{
fontName = wxString::FromUTF8( (char*) family );
@@ -129,19 +227,29 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
has_ital = true;
}
if( fontName.Lower().StartsWith( aFontName.Lower() ) )
for( auto const& [key, val] : famStrings )
{
if( ( aBold && !has_bold ) && ( aItalic && !has_ital ) )
retval = FF_RESULT::FF_MISSING_BOLD_ITAL;
else if( aBold && !has_bold )
retval = FF_RESULT::FF_MISSING_BOLD;
else if( aItalic && !has_ital )
retval = FF_RESULT::FF_MISSING_ITAL;
else if( ( aBold != has_bold ) || ( aItalic != has_ital ) )
retval = FF_RESULT::FF_SUBSTITUTE;
else
retval = FF_RESULT::FF_OK;
wxString searchFont;
searchFont = wxString::FromUTF8( (char*) val.data() );
if( searchFont.Lower().StartsWith( aFontName.Lower() ) )
{
if( ( aBold && !has_bold ) && ( aItalic && !has_ital ) )
retval = FF_RESULT::FF_MISSING_BOLD_ITAL;
else if( aBold && !has_bold )
retval = FF_RESULT::FF_MISSING_BOLD;
else if( aItalic && !has_ital )
retval = FF_RESULT::FF_MISSING_ITAL;
else if( ( aBold != has_bold ) || ( aItalic != has_ital ) )
retval = FF_RESULT::FF_SUBSTITUTE;
else
retval = FF_RESULT::FF_OK;
break;
}
}
}
}
@@ -158,13 +266,14 @@ FONTCONFIG::FF_RESULT FONTCONFIG::FindFont( const wxString &aFontName, wxString
}
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts, const std::string& aDesiredLang )
{
if( m_fonts.empty() )
// be sure to cache bust if the language changed
if( m_fontInfoCache.empty() || m_fontCacheLastLang != aDesiredLang )
{
FcPattern* pat = FcPatternCreate();
FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, FC_OUTLINE,
nullptr );
FcObjectSet* os = FcObjectSetBuild( FC_FAMILY, FC_FAMILYLANG, FC_STYLE, FC_LANG, FC_FILE,
FC_OUTLINE, nullptr );
FcFontSet* fs = FcFontList( nullptr, pat, os );
for( int i = 0; fs && i < fs->nfont; ++i )
@@ -172,12 +281,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
FcPattern* font = fs->fonts[i];
FcChar8* file;
FcChar8* style;
FcChar8* family;
FcLangSet* langSet;
FcBool outline;
if( FcPatternGetString( font, FC_FILE, 0, &file ) == FcResultMatch
&& FcPatternGetString( font, FC_FAMILY, 0, &family ) == FcResultMatch
&& FcPatternGetString( font, FC_STYLE, 0, &style ) == FcResultMatch
&& FcPatternGetLangSet( font, FC_LANG, 0, &langSet ) == FcResultMatch
&& FcPatternGetBool( font, FC_OUTLINE, 0, &outline ) == FcResultMatch )
@@ -185,7 +292,9 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
if( !outline )
continue;
std::string theFamily( reinterpret_cast<char *>( family ) );
FONTCONFIG_PAT patHolder{ font };
std::string theFamily =
getFamilyStringByLang( patHolder, FROM_UTF8( aDesiredLang.c_str() ) );
#ifdef __WXMAC__
// On Mac (at least) some of the font names are in their own language. If
@@ -238,10 +347,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
if( theFamily.length() > 0 && theFamily.front() == '.' )
continue;
std::map<std::string, FONTINFO>::iterator it = m_fonts.find( theFamily );
std::map<std::string, FONTINFO>::iterator it = m_fontInfoCache.find( theFamily );
if( it == m_fonts.end() )
m_fonts.emplace( theFamily, fontInfo );
if( it == m_fontInfoCache.end() )
m_fontInfoCache.emplace( theFamily, fontInfo );
else
it->second.Children().push_back( fontInfo );
}
@@ -249,8 +358,10 @@ void FONTCONFIG::ListFonts( std::vector<std::string>& aFonts )
if( fs )
FcFontSetDestroy( fs );
m_fontCacheLastLang = aDesiredLang;
}
for( const std::pair<const std::string, FONTINFO>& entry : m_fonts )
for( const std::pair<const std::string, FONTINFO>& entry : m_fontInfoCache )
aFonts.push_back( entry.second.Family() );
}
+31 -6
View File
@@ -44,6 +44,7 @@ using namespace KIFONT;
FT_Library OUTLINE_FONT::m_freeType = nullptr;
std::mutex OUTLINE_FONT::m_freeTypeMutex;
OUTLINE_FONT::OUTLINE_FONT() :
m_face(NULL),
@@ -51,6 +52,8 @@ OUTLINE_FONT::OUTLINE_FONT() :
m_fakeBold( false ),
m_fakeItal( false )
{
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
if( !m_freeType )
FT_Init_FreeType( &m_freeType );
}
@@ -58,6 +61,8 @@ OUTLINE_FONT::OUTLINE_FONT() :
wxString OUTLINE_FONT::FreeTypeVersion()
{
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
if( !m_freeType )
FT_Init_FreeType( &m_freeType );
@@ -90,31 +95,36 @@ wxString OUTLINE_FONT::FontLibraryVersion()
OUTLINE_FONT* OUTLINE_FONT::LoadFont( const wxString& aFontName, bool aBold, bool aItalic )
{
OUTLINE_FONT* font = new OUTLINE_FONT();
std::unique_ptr<OUTLINE_FONT> font = std::make_unique<OUTLINE_FONT>();
wxString fontFile;
using fc = fontconfig::FONTCONFIG;
fc::FF_RESULT retval = Fontconfig()->FindFont( aFontName, fontFile, aBold, aItalic );
if( retval == fc::FF_RESULT::FF_ERROR )
return nullptr;
if( retval == fc::FF_RESULT::FF_MISSING_BOLD || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
font->SetFakeBold();
if( retval == fc::FF_RESULT::FF_MISSING_ITAL || retval == fc::FF_RESULT::FF_MISSING_BOLD_ITAL )
font->SetFakeItal();
if( retval != fc::FF_RESULT::FF_ERROR )
(void) font->loadFace( fontFile );
if( font->loadFace( fontFile ) != 0 )
return nullptr;
font->m_fontName = aFontName; // Keep asked-for name, even if we substituted.
font->m_fontFileName = fontFile;
return font;
return font.release();
}
FT_Error OUTLINE_FONT::loadFace( const wxString& aFontFileName )
{
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
// TODO: check that going from wxString to char* with UTF-8
// conversion for filename makes sense on any/all platforms
FT_Error e = FT_New_Face( m_freeType, aFontFileName.mb_str( wxConvUTF8 ), 0, &m_face );
@@ -323,6 +333,18 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const
{
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
return getTextAsGlyphsUnlocked( aBBox, aGlyphs, aText, aSize, aPosition, aAngle, aMirror,
aOrigin, aTextStyle );
}
VECTOR2I OUTLINE_FONT::getTextAsGlyphsUnlocked( BOX2I* aBBox, std::vector<std::unique_ptr<GLYPH>>* aGlyphs,
const wxString& aText, const VECTOR2I& aSize,
const VECTOR2I& aPosition, const EDA_ANGLE& aAngle,
bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const
{
VECTOR2D glyphSize = aSize;
FT_Face face = m_face;
@@ -366,7 +388,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
{
FT_Matrix matrix;
// Create a 12 degree slant
const float angle = ( -M_PI * 12 ) / 180.0f;
const float angle = (float)( -M_PI * 12.0f ) / 180.0f;
matrix.xx = (FT_Fixed) ( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed) ( -sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed) ( 0 * 0x10000L ); // Don't rotate in the y direction
@@ -466,7 +488,7 @@ VECTOR2I OUTLINE_FONT::getTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_pt
{
std::vector<std::unique_ptr<GLYPH>> underscoreGlyphs;
getTextAsGlyphs( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
getTextAsGlyphsUnlocked( nullptr, &underscoreGlyphs, wxT( "_" ), aSize, { 0, 0 }, ANGLE_0, false,
{ 0, 0 }, aTextStyle & ~TEXT_STYLE::OVERBAR );
OUTLINE_GLYPH* underscoreGlyph = static_cast<OUTLINE_GLYPH*>( underscoreGlyphs[0].get() );
@@ -552,6 +574,9 @@ void OUTLINE_FONT::RenderToOpenGLCanvas( KIGFX::OPENGL_GAL& aGal, const wxString
unsigned int glyphCount;
hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( buf, &glyphCount );
hb_glyph_position_t* glyphPos = hb_buffer_get_glyph_positions( buf, &glyphCount );
std::lock_guard<std::mutex> guard( m_freeTypeMutex );
hb_font_t* referencedFont = hb_ft_font_create_referenced( m_face );
hb_ft_font_set_funcs( referencedFont );
+20 -10
View File
@@ -52,7 +52,8 @@ static constexpr double UNDERLINE_POSITION_FACTOR = -0.16;
///< Scale factor for a glyph
static constexpr double STROKE_FONT_SCALE = 1.0 / 21.0;
static constexpr int FONT_OFFSET = -10;
///< Offset (in stroke font units) to move the origin to the baseline.
static constexpr int FONT_OFFSET = -8;
bool g_defaultFontInitialized = false;
@@ -225,11 +226,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
bool aMirror, const VECTOR2I& aOrigin,
TEXT_STYLE_FLAGS aTextStyle ) const
{
constexpr double SPACE_WIDTH = 0.6;
constexpr int TAB_WIDTH = 4;
constexpr double INTER_CHAR = 0.2;
constexpr double TAB_WIDTH = 4 * 0.82; // Not quite as wide as 5.1/6.0 tab formatting, but
// a better match for Scintilla, and closer to the
// nominal SPACE_WIDTH + INTER_CHAR
constexpr double SUPER_SUB_SIZE_MULTIPLIER = 0.7;
constexpr double SUPER_HEIGHT_OFFSET = 0.5;
constexpr double SUB_HEIGHT_OFFSET = 0.3;
@@ -237,6 +235,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
VECTOR2I cursor( aPosition );
VECTOR2D glyphSize( aSize );
double tilt = ( aTextStyle & TEXT_STYLE::ITALIC ) ? ITALIC_TILT : 0.0;
double space_width = m_glyphBoundingBoxes->front().GetWidth(); // First char is space
int char_count = 0;
if( aTextStyle & TEXT_STYLE::SUBSCRIPT || aTextStyle & TEXT_STYLE::SUPERSCRIPT )
{
@@ -250,18 +250,26 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
for( wxUniChar c : aText )
{
// Handle tabs as locked to the nearest 4th column (in space-widths).
// Handle tabs as locked to the next 4th column (in base-widths).
if( c == '\t' )
{
int tabWidth = KiROUND( glyphSize.x * TAB_WIDTH );
int currentIntrusion = ( cursor.x - aOrigin.x ) % tabWidth;
char_count = ( char_count / TAB_WIDTH + 1 ) * TAB_WIDTH - 1;
cursor.x += tabWidth - currentIntrusion;
int new_cursor = aPosition.x + aSize.x * char_count
+ aSize.x * space_width;
while( new_cursor <= cursor.x )
{
char_count += TAB_WIDTH;
new_cursor += aSize.x * TAB_WIDTH;
}
cursor.x = new_cursor;
}
else if( c == ' ' )
{
// 'space' character - draw nothing, advance cursor position
cursor.x += KiROUND( glyphSize.x * SPACE_WIDTH );
cursor.x += KiROUND( glyphSize.x * space_width );
}
else
{
@@ -292,6 +300,8 @@ VECTOR2I STROKE_FONT::GetTextAsGlyphs( BOX2I* aBBox, std::vector<std::unique_ptr
cursor.x += KiROUND( glyphExtents.x );
}
++char_count;
}
VECTOR2D barOffset( 0.0, 0.0 );
+1
View File
@@ -596,6 +596,7 @@ bool FP_LIB_TABLE::LoadGlobalTable( FP_LIB_TABLE& aTable )
}
}
aTable.Clear();
aTable.Load( fn.GetFullPath() );
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
+47 -13
View File
@@ -57,11 +57,6 @@ static std::optional<double> getKiCadConfiguredScale( const COMMON_SETTINGS& aCo
scale = canvas_scale;
}
if( scale )
{
wxLogTrace( traceHiDpi, wxS( "Scale factor (configured): %f" ), *scale );
}
return scale;
}
@@ -83,11 +78,6 @@ static std::optional<double> getEnvironmentScale()
scale = ENV_VAR::GetEnvVar<double>( wxS( "GDK_SCALE" ) );
}
if( scale )
{
wxLogTrace( traceHiDpi, wxS( "Scale factor (environment): %f" ), *scale );
}
return scale;
}
@@ -101,15 +91,18 @@ DPI_SCALING::DPI_SCALING( COMMON_SETTINGS* aConfig, const wxWindow* aWindow )
double DPI_SCALING::GetScaleFactor() const
{
std::optional<double> val;
wxString src;
if( m_config )
{
val = getKiCadConfiguredScale( *m_config );
src = wxS( "config" );
}
if( !val )
{
val = getEnvironmentScale();
src = wxS( "env" );
}
if( !val && m_window )
@@ -117,17 +110,58 @@ double DPI_SCALING::GetScaleFactor() const
// Use the native WX reporting.
// On Linux, this will not work until WX 3.2 and GTK >= 3.10
// Otherwise it returns 1.0
val = KIPLATFORM::UI::GetSystemScaleFactor( m_window );
wxLogTrace( traceHiDpi, wxS( "Scale factor (WX): %f" ), *val );
val = KIPLATFORM::UI::GetPixelScaleFactor( m_window );
src = wxS( "platform" );
}
if( !val )
{
// Nothing else we can do, give it a default value
val = GetDefaultScaleFactor();
wxLogTrace( traceHiDpi, wxS( "Scale factor (default): %f" ), *val );
src = wxS( "default" );
}
wxLogTrace( traceHiDpi, wxS( "Scale factor (%s): %f" ), src, *val );
return *val;
}
double DPI_SCALING::GetContentScaleFactor() const
{
std::optional<double> val;
wxString src;
if( m_config )
{
val = getKiCadConfiguredScale( *m_config );
src = wxS( "config" );
}
if( !val )
{
val = getEnvironmentScale();
src = wxS( "env" );
}
if( !val && m_window )
{
// Use the native WX reporting.
// On Linux, this will not work until WX 3.2 and GTK >= 3.10
// Otherwise it returns 1.0
val = KIPLATFORM::UI::GetContentScaleFactor( m_window );
src = wxS( "platform" );
}
if( !val )
{
// Nothing else we can do, give it a default value
val = GetDefaultScaleFactor();
src = wxS( "default" );
}
wxLogTrace( traceHiDpi, wxS( "Content scale factor (%s): %f" ), src, *val );
return *val;
}
+5
View File
@@ -91,6 +91,11 @@ void GRSetColorPen( wxDC* DC, const COLOR4D& Color, int width, wxPenStyle style
if( s_ForceBlackPen )
color = COLOR4D::BLACK;
// wxWidgets will enforce a minimum pen width when printing, so we have to make the pen
// transparent when we don't want the object stroked.
if( width == 0 )
color = COLOR4D::UNSPECIFIED;
const wxPen& curr_pen = DC->GetPen();
if( !curr_pen.IsOk() || curr_pen.GetColour() != color.ToColour()
+1
View File
@@ -424,6 +424,7 @@ void GRID_TRICKS::onCharHook( wxKeyEvent& ev )
{
wxCommandEvent dummy;
m_addHandler( dummy );
handled = true;
}
}
else if( ev.GetModifiers() == wxMOD_CONTROL && ev.GetKeyCode() == 'V' )
+2 -2
View File
@@ -264,7 +264,7 @@ bool KICAD_CURL_EASY::SetTransferCallback( const TRANSFER_CALLBACK& aCallback, s
{
progress = std::make_unique<CURL_PROGRESS>( this, aCallback,
static_cast<curl_off_t>( aInterval ) );
#ifdef CURLOPT_XFERINFOFUNCTION
#if LIBCURL_VERSION_NUM >= 0x072000 // 7.32.0
setOption( CURLOPT_XFERINFOFUNCTION, xferinfo );
setOption( CURLOPT_XFERINFODATA, progress.get() );
#else
@@ -286,7 +286,7 @@ bool KICAD_CURL_EASY::SetOutputStream( const std::ostream* aOutput )
int KICAD_CURL_EASY::GetTransferTotal( uint64_t& aDownloadedBytes ) const
{
#ifdef CURLINFO_SIZE_DOWNLOAD_T
#if LIBCURL_VERSION_NUM >= 0x073700 // 7.55.0
curl_off_t dl;
int result = curl_easy_getinfo( m_CURL, CURLINFO_SIZE_DOWNLOAD_T, &dl );
aDownloadedBytes = static_cast<uint64_t>( dl );
+3 -1
View File
@@ -193,6 +193,8 @@ LIB_TABLE_ROW* LIB_TABLE::findRow( const wxString& aNickName, bool aCheckIfEnabl
{
cur->ensureIndex();
std::shared_lock<std::shared_mutex> lock( cur->m_nickIndexMutex );
for( const std::pair<const wxString, int>& entry : cur->m_nickIndex )
{
if( entry.first == aNickName )
@@ -303,7 +305,7 @@ bool LIB_TABLE::InsertRow( LIB_TABLE_ROW* aRow, bool doReplace )
{
ensureIndex();
std::lock_guard<std::mutex> lock( m_nickIndexMutex );
std::lock_guard<std::shared_mutex> lock( m_nickIndexMutex );
INDEX_CITER it = m_nickIndex.find( aRow->GetNickName() );
+21 -1
View File
@@ -110,7 +110,7 @@ LANGUAGE_DESCR LanguagesList[] =
{ wxLANGUAGE_SWEDISH, ID_LANGUAGE_SWEDISH, wxT( "Svenska" ), true },
// { wxLANGUAGE_VIETNAMESE, ID_LANGUAGE_VIETNAMESE, wxT( "Tiếng Việt" ), true },
// { wxLANGUAGE_TURKISH, ID_LANGUAGE_TURKISH, wxT( "Türkçe" ), true },
{ wxLANGUAGE_UKRAINIAN, ID_LANGUAGE_UKRANIAN, wxT( "Українець" ), true },
{ wxLANGUAGE_UKRAINIAN, ID_LANGUAGE_UKRANIAN, wxT( "Українська" ), true },
{ wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED,
wxT( "简体中文" ), true },
{ wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL,
@@ -775,6 +775,26 @@ void PGM_BASE::SetLanguageIdentifier( int menu_id )
}
wxString PGM_BASE::GetLanguageTag()
{
const wxLanguageInfo* langInfo = wxLocale::GetLanguageInfo( m_language_id );
if( !langInfo )
return "";
else
{
#if wxCHECK_VERSION( 3, 1, 6 )
wxString str = langInfo->GetCanonicalWithRegion();
#else
wxString str = langInfo->CanonicalName;
#endif
str.Replace( "_", "-" );
return str;
}
}
void PGM_BASE::SetLanguagePath()
{
wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
+180 -139
View File
@@ -861,145 +861,186 @@ void DXF_PLOTTER::Text( const VECTOR2I& aPos,
}
else
{
/* Emit text as a text entity. This loses formatting and shape but it's
more useful as a CAD object */
VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
SetColor( aColor );
wxString cname = getDXFColorName( m_currentColor );
VECTOR2D size_dev = userToDeviceSize( aSize );
int h_code = 0, v_code = 0;
switch( aH_justify )
{
case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
}
switch( aV_justify )
{
case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
}
// Position, size, rotation and alignment
// The two alignment point usages is somewhat idiot (see the DXF ref)
// Anyway since we don't use the fit/aligned options, they're the same
fprintf( m_outputFile,
" 0\n"
"TEXT\n"
" 7\n"
"%s\n" // Text style
" 8\n"
"%s\n" // Layer name
" 10\n"
"%g\n" // First point X
" 11\n"
"%g\n" // Second point X
" 20\n"
"%g\n" // First point Y
" 21\n"
"%g\n" // Second point Y
" 40\n"
"%g\n" // Text height
" 41\n"
"%g\n" // Width factor
" 50\n"
"%g\n" // Rotation
" 51\n"
"%g\n" // Oblique angle
" 71\n"
"%d\n" // Mirror flags
" 72\n"
"%d\n" // H alignment
" 73\n"
"%d\n", // V alignment
aBold ? (aItalic ? "KICADBI" : "KICADB") : (aItalic ? "KICADI" : "KICAD"),
TO_UTF8( cname ),
origin_dev.x, origin_dev.x,
origin_dev.y, origin_dev.y,
size_dev.y, fabs( size_dev.x / size_dev.y ),
aOrient.AsDegrees(),
aItalic ? DXF_OBLIQUE_ANGLE : 0,
size_dev.x < 0 ? 2 : 0, // X mirror flag
h_code, v_code );
/* There are two issue in emitting the text:
- Our overline character (~) must be converted to the appropriate
control sequence %%O or %%o
- Text encoding in DXF is more or less unspecified since depends on
the DXF declared version, the acad version reading it *and* some
system variables to be put in the header handled only by newer acads
Also before R15 unicode simply is not supported (you need to use
bigfonts which are a massive PITA). Common denominator solution:
use Latin1 (and however someone could choke on it, anyway). Sorry
for the extended latin people. If somewant want to try fixing this
recent version seems to use UTF-8 (and not UCS2 like the rest of
Windows)
XXX Actually there is a *third* issue: older DXF formats are limited
to 255 bytes records (it was later raised to 2048); since I'm lazy
and text so long is not probable I just don't implement this rule.
If someone is interested in fixing this, you have to emit the first
partial lines with group code 3 (max 250 bytes each) and then finish
with a group code 1 (less than 250 bytes). The DXF refs explains it
in no more details...
*/
int braceNesting = 0;
int overbarDepth = -1;
fputs( " 1\n", m_outputFile );
for( unsigned int i = 0; i < aText.length(); i++ )
{
/* Here I do a bad thing: writing the output one byte at a time!
but today I'm lazy and I have no idea on how to coerce a Unicode
wxString to spit out latin1 encoded text ...
At least stdio is *supposed* to do output buffering, so there is
hope is not too slow */
wchar_t ch = aText[i];
if( ch > 255 )
{
// I can't encode this...
putc( '?', m_outputFile );
}
else
{
if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
{
fputs( "%%o", m_outputFile );
overbarDepth = braceNesting;
// Skip the '{'
i++;
continue;
}
else if( aText[i] == '{' )
{
braceNesting++;
}
else if( aText[i] == '}' )
{
if( braceNesting > 0 )
braceNesting--;
if( braceNesting == overbarDepth )
{
fputs( "%%O", m_outputFile );
overbarDepth = -1;
continue;
}
}
putc( ch, m_outputFile );
}
}
putc( '\n', m_outputFile );
TEXT_ATTRIBUTES attrs;
attrs.m_Halign = aH_justify;
attrs.m_Valign =aV_justify;
attrs.m_StrokeWidth = aWidth;
attrs.m_Angle = aOrient;
attrs.m_Italic = aItalic;
attrs.m_Bold = aBold;
attrs.m_Mirrored = aSize.x < 0;
attrs.m_Multiline = false;
plotOneLineOfText( aPos, aColor, aText, attrs );
}
}
void DXF_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
TEXT_ATTRIBUTES attrs = aAttributes;
// Fix me: see how to use DXF text mode for multiline texts
if( attrs.m_Multiline && !aText.Contains( wxT( "\n" ) ) )
attrs.m_Multiline = false; // the text has only one line.
bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
if( m_textAsLines || containsNonAsciiChars( aText ) || attrs.m_Multiline || processSuperSub )
{
// output text as graphics.
// Perhaps multiline texts could be handled as DXF text entity
// but I do not want spend time about that (JPC)
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
}
else
plotOneLineOfText( aPos, aColor, aText, attrs );
}
void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes )
{
/* Emit text as a text entity. This loses formatting and shape but it's
more useful as a CAD object */
VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
SetColor( aColor );
wxString cname = getDXFColorName( m_currentColor );
VECTOR2D size_dev = userToDeviceSize( aAttributes.m_Size );
int h_code = 0, v_code = 0;
switch( aAttributes.m_Halign )
{
case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
}
switch( aAttributes.m_Valign )
{
case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
}
// Position, size, rotation and alignment
// The two alignment point usages is somewhat idiot (see the DXF ref)
// Anyway since we don't use the fit/aligned options, they're the same
fprintf( m_outputFile,
" 0\n"
"TEXT\n"
" 7\n"
"%s\n" // Text style
" 8\n"
"%s\n" // Layer name
" 10\n"
"%g\n" // First point X
" 11\n"
"%g\n" // Second point X
" 20\n"
"%g\n" // First point Y
" 21\n"
"%g\n" // Second point Y
" 40\n"
"%g\n" // Text height
" 41\n"
"%g\n" // Width factor
" 50\n"
"%g\n" // Rotation
" 51\n"
"%g\n" // Oblique angle
" 71\n"
"%d\n" // Mirror flags
" 72\n"
"%d\n" // H alignment
" 73\n"
"%d\n", // V alignment
aAttributes.m_Bold ?
(aAttributes.m_Italic ? "KICADBI" : "KICADB")
: (aAttributes.m_Italic ? "KICADI" : "KICAD"), TO_UTF8( cname ),
origin_dev.x, origin_dev.x,
origin_dev.y, origin_dev.y,
size_dev.y, fabs( size_dev.x / size_dev.y ),
aAttributes.m_Angle.AsDegrees(),
aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
h_code, v_code );
/* There are two issue in emitting the text:
- Our overline character (~) must be converted to the appropriate
control sequence %%O or %%o
- Text encoding in DXF is more or less unspecified since depends on
the DXF declared version, the acad version reading it *and* some
system variables to be put in the header handled only by newer acads
Also before R15 unicode simply is not supported (you need to use
bigfonts which are a massive PITA). Common denominator solution:
use Latin1 (and however someone could choke on it, anyway). Sorry
for the extended latin people. If somewant want to try fixing this
recent version seems to use UTF-8 (and not UCS2 like the rest of
Windows)
XXX Actually there is a *third* issue: older DXF formats are limited
to 255 bytes records (it was later raised to 2048); since I'm lazy
and text so long is not probable I just don't implement this rule.
If someone is interested in fixing this, you have to emit the first
partial lines with group code 3 (max 250 bytes each) and then finish
with a group code 1 (less than 250 bytes). The DXF refs explains it
in no more details...
*/
int braceNesting = 0;
int overbarDepth = -1;
fputs( " 1\n", m_outputFile );
for( unsigned int i = 0; i < aText.length(); i++ )
{
/* Here I do a bad thing: writing the output one byte at a time!
but today I'm lazy and I have no idea on how to coerce a Unicode
wxString to spit out latin1 encoded text ...
At least stdio is *supposed* to do output buffering, so there is
hope is not too slow */
wchar_t ch = aText[i];
if( ch > 255 )
{
// I can't encode this...
putc( '?', m_outputFile );
}
else
{
if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
{
fputs( "%%o", m_outputFile );
overbarDepth = braceNesting;
// Skip the '{'
i++;
continue;
}
else if( aText[i] == '{' )
{
braceNesting++;
}
else if( aText[i] == '}' )
{
if( braceNesting > 0 )
braceNesting--;
if( braceNesting == overbarDepth )
{
fputs( "%%O", m_outputFile );
overbarDepth = -1;
continue;
}
}
putc( ch, m_outputFile );
}
}
putc( '\n', m_outputFile );
}
+41 -18
View File
@@ -154,7 +154,6 @@ void GERBER_PLOTTER::SetGerberCoordinatesFormat( int aResolution, bool aUseInche
void GERBER_PLOTTER::emitDcode( const VECTOR2D& pt, int dcode )
{
fprintf( m_outputFile, "X%dY%dD%02d*\n", KiROUND( pt.x ), KiROUND( pt.y ), dcode );
}
@@ -902,18 +901,16 @@ void GERBER_PLOTTER::plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAn
}
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aData )
void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, GBR_METADATA* aGbrMetadata )
{
if( aPoly.PointCount() <= 2 )
return;
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
if( gbr_metadata )
if( aGbrMetadata )
{
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
std::string attrib = aGbrMetadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
if( !attrib.empty() )
{
@@ -922,7 +919,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aDat
}
}
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0 , gbr_metadata );
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0 , aGbrMetadata );
// Clear the TA attribute, to avoid the next item to inherit it:
if( clearTA_AperFunction )
@@ -939,18 +936,17 @@ void GERBER_PLOTTER::PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, void* aDat
}
void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList, void* aData )
void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
GBR_METADATA* aGbrMetadata )
{
if( aCornerList.size() <= 2 )
return;
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
if( gbr_metadata )
if( aGbrMetadata )
{
std::string attrib = gbr_metadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
std::string attrib = aGbrMetadata->m_ApertureMetadata.FormatAttribute( !m_useX2format );
if( !attrib.empty() )
{
@@ -959,7 +955,7 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
}
}
PlotPoly( aCornerList, FILL_T::FILLED_SHAPE, 0, gbr_metadata );
PlotPoly( aCornerList, FILL_T::FILLED_SHAPE, 0, aGbrMetadata );
// Clear the TA attribute, to avoid the next item to inherit it:
if( clearTA_AperFunction )
@@ -976,6 +972,19 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList,
}
void GERBER_PLOTTER::PlotPolyAsRegion( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill,
int aWidth, GBR_METADATA* aGbrMetadata )
{
// plot a filled polygon using Gerber region, therefore adding X2 attributes
// to the solid polygon
if( aWidth )
PlotPoly( aPoly, FILL_T::NO_FILL, aWidth, aGbrMetadata );
if( aFill != FILL_T::NO_FILL )
PlotGerberRegion( aPoly, aGbrMetadata );
}
void GERBER_PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill, int aWidth,
void* aData )
{
@@ -1322,7 +1331,7 @@ void GERBER_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
if( orient.IsCardinal90() )
std::swap( size.x, size.y );
VECTOR2I pos_device = userToDeviceCoordinates( aPos );
VECTOR2D pos_device = userToDeviceCoordinates( aPos );
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
selectAperture( size, 0, ANGLE_0, APERTURE::AT_OVAL, aperture_attrib );
@@ -1353,7 +1362,7 @@ void GERBER_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
orient -= ANGLE_180;
}
VECTOR2I pos_device = userToDeviceCoordinates( aPos );
VECTOR2D pos_device = userToDeviceCoordinates( aPos );
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
selectAperture( size, 0, orient, APERTURE::AM_ROTATED_OVAL, aperture_attrib );
@@ -1416,7 +1425,7 @@ void GERBER_PLOTTER::FlashPadRect( const VECTOR2I& pos, const VECTOR2I& aSize,
}
else
{
VECTOR2I pos_device = userToDeviceCoordinates( pos );
VECTOR2D pos_device = userToDeviceCoordinates( pos );
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
selectAperture( size, 0, ANGLE_0, APERTURE::AT_RECT, aperture_attrib );
@@ -1433,7 +1442,7 @@ void GERBER_PLOTTER::FlashPadRect( const VECTOR2I& pos, const VECTOR2I& aSize,
{
m_hasApertureRotRect = true;
VECTOR2I pos_device = userToDeviceCoordinates( pos );
VECTOR2D pos_device = userToDeviceCoordinates( pos );
int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0;
selectAperture( size, 0, aOrient, APERTURE::AM_ROT_RECT, aperture_attrib );
@@ -1755,7 +1764,7 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const VECTOR2I& aShapePos, const
if( aData )
gbr_metadata = *static_cast<GBR_METADATA*>( aData );
VECTOR2I pos_device = userToDeviceCoordinates( aShapePos );
VECTOR2D pos_device = userToDeviceCoordinates( aShapePos );
SHAPE_POLY_SET outline;
std::vector<VECTOR2I> cornerList;
@@ -1994,6 +2003,20 @@ void GERBER_PLOTTER::Text( const VECTOR2I& aPos,
}
void GERBER_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
GBR_METADATA* gbr_metadata = static_cast<GBR_METADATA*>( aData );
if( gbr_metadata )
formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
}
void GERBER_PLOTTER::SetLayerPolarity( bool aPositive )
{
if( aPositive )
+30 -4
View File
@@ -1376,7 +1376,9 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
double ctm_a, ctm_b, ctm_c, ctm_d, ctm_e, ctm_f;
double wideningFactor, heightFactor;
computeTextParameters( aPos, aText, aOrient, aSize, m_plotMirror, aH_justify,
VECTOR2I t_size( std::abs( aSize.x ), std::abs( aSize.y ) );
computeTextParameters( aPos, aText, aOrient, t_size, m_plotMirror, aH_justify,
aV_justify, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
@@ -1389,7 +1391,7 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
if( !aFont )
aFont = KIFONT::FONT::GetFont();
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, aSize, aWidth, aBold, aItalic ) );
VECTOR2I full_box( aFont->StringBoundaryLimits( aText, t_size, aWidth, aBold, aItalic ) );
VECTOR2I box_x( full_box.x, 0 );
VECTOR2I box_y( 0, full_box.y );
@@ -1410,13 +1412,13 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
{
wxString word = str_tok.GetNextToken();
computeTextParameters( pos, word, aOrient, aSize, m_plotMirror, GR_TEXT_H_ALIGN_LEFT,
computeTextParameters( pos, word, aOrient, t_size, m_plotMirror, GR_TEXT_H_ALIGN_LEFT,
GR_TEXT_V_ALIGN_BOTTOM, aWidth, aItalic, aBold, &wideningFactor, &ctm_a,
&ctm_b, &ctm_c, &ctm_d, &ctm_e, &ctm_f, &heightFactor );
// Extract the changed width and rotate by the orientation to get the offset for the
// next word
VECTOR2I bbox( aFont->StringBoundaryLimits( word, aSize, aWidth, aBold, aItalic ).x, 0 );
VECTOR2I bbox( aFont->StringBoundaryLimits( word, t_size, aWidth, aBold, aItalic ).x, 0 );
RotatePoint( bbox, aOrient );
pos += bbox;
@@ -1444,6 +1446,30 @@ void PDF_PLOTTER::Text( const VECTOR2I& aPos,
}
void PDF_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
VECTOR2I size = aAttributes.m_Size;
// PDF files do not like 0 sized texts which create broken files.
if( size.x == 0 || size.y == 0 )
return;
if( aAttributes.m_Mirrored )
size.x = -size.x;
PDF_PLOTTER::Text( aPos, aColor, aText, aAttributes.m_Angle, size,
aAttributes.m_Halign, aAttributes.m_Valign,
aAttributes.m_StrokeWidth,
aAttributes.m_Italic, aAttributes.m_Bold,
aAttributes.m_Multiline,
aFont, aData );
}
void PDF_PLOTTER::HyperlinkBox( const BOX2I& aBox, const wxString& aDestinationURL )
{
m_hyperlinksInPage.push_back( std::make_pair( aBox, aDestinationURL ) );
+22
View File
@@ -967,6 +967,28 @@ void PS_PLOTTER::Text( const VECTOR2I& aPos,
}
void PS_PLOTTER::PlotText( const VECTOR2I& aPos,
const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
SetCurrentLineWidth( aAttributes.m_StrokeWidth );
SetColor( aColor );
// Draw the hidden postscript text (if requested)
if( m_textMode == PLOT_TEXT_MODE::PHANTOM )
{
std::string ps_test = encodeStringForPlotter( aText );
VECTOR2D pos_dev = userToDeviceCoordinates( aPos );
fprintf( m_outputFile, "%s %g %g phantomshow\n", ps_test.c_str(), pos_dev.x, pos_dev.y );
}
PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aData );
}
/**
* Character widths for Helvetica
*/
+27 -1
View File
@@ -633,7 +633,13 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
{
wxMemoryOutputStream img_stream;
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
if( m_colorMode )
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
else // Plot in B&W
{
wxImage image = aImage.ConvertToGreyscale();
image.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
}
size_t input_len = img_stream.GetOutputStreamBuffer()->GetBufferSize();
std::vector<uint8_t> buffer( input_len );
std::vector<uint8_t> encoded;
@@ -847,3 +853,23 @@ void SVG_PLOTTER::Text( const VECTOR2I& aPos,
fputs( "</g>", m_outputFile );
}
void SVG_PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
VECTOR2I size = aAttributes.m_Size;
if( aAttributes.m_Mirrored )
size.x = -size.x;
SVG_PLOTTER::Text( aPos, aColor, aText, aAttributes.m_Angle, size,
aAttributes.m_Halign, aAttributes.m_Valign,
aAttributes.m_StrokeWidth,
aAttributes.m_Italic, aAttributes.m_Bold,
aAttributes.m_Multiline,
aFont, aData );
}
+50 -18
View File
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2017-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -694,23 +694,6 @@ void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, int a
}
/**
* Same as GRText, but plot graphic text instead of draw it.
*
* @param aPos is the text position (according to aH_justify, aV_justify).
* @param aColor is the text color.
* @param aText is the text to draw.
* @param aOrient is the angle.
* @param aSize is the text size (size.x or size.y can be < 0 for mirrored texts).
* @param aH_justify is the horizontal justification (Left, center, right).
* @param aV_justify is the vertical justification (bottom, center, top).
* @param aPenWidth is the line width (if = 0, use plot default line width).
* @param aItalic is the true to simulate an italic font.
* @param aBold use true to use a bold font Useful only with default width value (aPenWidth = 0).
* @param aMultilineAllowed use true to plot text as multiline, otherwise single line.
* @param aData is a parameter used by some plotters in SetCurrentLineWidth(),
* not directly used here.
*/
void PLOTTER::Text( const VECTOR2I& aPos,
const COLOR4D& aColor,
const wxString& aText,
@@ -759,6 +742,55 @@ void PLOTTER::Text( const VECTOR2I& aPos,
attributes.m_Valign = aV_justify;
attributes.m_Size = aSize;
// if Size.x is < 0, the text is mirrored (we have no other param to know a text is mirrored)
if( attributes.m_Size.x < 0 )
{
attributes.m_Size.x = -attributes.m_Size.x;
attributes.m_Mirrored = true;
}
if( !aFont )
aFont = KIFONT::FONT::GetFont();
aFont->Draw( &callback_gal, aText, aPos, attributes );
}
void PLOTTER::PlotText( const VECTOR2I& aPos, const COLOR4D& aColor,
const wxString& aText,
const TEXT_ATTRIBUTES& aAttributes,
KIFONT::FONT* aFont,
void* aData )
{
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
TEXT_ATTRIBUTES attributes = aAttributes;
int penWidth = attributes.m_StrokeWidth;
SetColor( aColor );
SetCurrentLineWidth( penWidth, aData );
if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
penWidth = GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
if( penWidth < 0 )
penWidth = -penWidth;
attributes.m_StrokeWidth = penWidth;
CALLBACK_GAL callback_gal( empty_opts,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
MoveTo( aPt1 );
LineTo( aPt2 );
PenFinish();
},
// Polygon callback
[&]( const SHAPE_LINE_CHAIN& aPoly )
{
PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, aData );
} );
if( !aFont )
aFont = KIFONT::FONT::GetFont();
@@ -193,7 +193,7 @@ void CADSTAR_ARCHIVE_PARSER::LINECODE::Parse( XNODE* aNode, PARSER_CONTEXT* aCon
XNODE* cNode = aNode->GetChildren();
if( cNode->GetName() != wxT( "STYLE" ) )
if( !cNode || cNode->GetName() != wxT( "STYLE" ) )
THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
@@ -486,18 +486,28 @@ void CADSTAR_ARCHIVE_PARSER::VERTEX::AppendToChain( SHAPE_LINE_CHAIN* aChainToAp
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
double aAccuracy ) const
{
VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
if( Type == VERTEX_TYPE::POINT )
{
aChainToAppendTo->Append( endPoint );
aChainToAppendTo->Append( aCadstarToKicadPointCallback( End ) );
return;
}
wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
"Can't append an arc to vertex to an empty chain" );
VECTOR2I startPoint = aChainToAppendTo->GetPoint( -1 );
aChainToAppendTo->Append( BuildArc( aChainToAppendTo->GetPoint( -1 ), aCadstarToKicadPointCallback),
aAccuracy );
}
SHAPE_ARC CADSTAR_ARCHIVE_PARSER::VERTEX::BuildArc( const VECTOR2I& aPrevPoint,
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
{
wxCHECK_MSG( Type != VERTEX_TYPE::POINT, SHAPE_ARC(),
"Can't build an arc for a straight segment!" );
VECTOR2I startPoint = aPrevPoint;
VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
VECTOR2I centerPoint;
if( Type == VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE || Type == VERTEX_TYPE::CLOCKWISE_SEMICIRCLE )
@@ -516,9 +526,8 @@ void CADSTAR_ARCHIVE_PARSER::VERTEX::AppendToChain( SHAPE_LINE_CHAIN* aChainToAp
clockwise = !clockwise;
SHAPE_ARC arc;
arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
aChainToAppendTo->Append( arc, aAccuracy );
return arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
}
@@ -2419,7 +2428,9 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
const wxString& aFileTypeIdentifier, PROGRESS_REPORTER* aProgressReporter )
{
KEYWORD emptyKeywords[1] = {};
XNODE * iNode = nullptr, *cNode = nullptr;
XNODE* rootNode = nullptr;
XNODE* cNode = nullptr;
XNODE* iNode = nullptr;
int tok;
bool cadstarFileCheckDone = false;
wxString str;
@@ -2451,7 +2462,10 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
{
if( !aProgressReporter->KeepRefreshing() )
{
delete rootNode;
THROW_IO_ERROR( _( "File import cancelled by user." ) );
}
aProgressReporter->SetCurrentProgress( currentProgress() );
previousReportedProgress = currentProgress();
@@ -2467,6 +2481,7 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
else
{
//too many closing brackets
delete rootNode;
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
}
@@ -2476,6 +2491,9 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
str = wxString( lexer.CurText(), *conv );
cNode = new XNODE( wxXML_ELEMENT_NODE, str );
if( !rootNode )
rootNode = cNode;
if( iNode )
{
//we will add it as attribute as well as child node
@@ -2485,7 +2503,10 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
else if( !cadstarFileCheckDone )
{
if( cNode->GetName() != aFileTypeIdentifier )
{
delete rootNode;
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
cadstarFileCheckDone = true;
}
@@ -2501,19 +2522,28 @@ XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
else
{
//not enough closing brackets
delete rootNode;
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
}
// Not enough closing brackets
if( iNode != nullptr )
{
delete rootNode;
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
// Throw if no data was parsed
if( cNode )
return cNode;
if( rootNode )
{
return rootNode;
}
else
{
delete rootNode;
THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
}
return nullptr;
}
@@ -83,6 +83,7 @@ class wxXmlAttribute;
class PROGRESS_REPORTER;
class SHAPE_LINE_CHAIN;
class SHAPE_POLY_SET;
class SHAPE_ARC;
/**
* @brief Helper functions and common structures for CADSTAR PCB and Schematic archive files.
@@ -92,6 +93,8 @@ class CADSTAR_ARCHIVE_PARSER
public:
CADSTAR_ARCHIVE_PARSER() { m_progressReporter = nullptr; }
virtual ~CADSTAR_ARCHIVE_PARSER() {}
typedef wxString LINECODE_ID;
typedef wxString HATCHCODE_ID;
@@ -451,6 +454,10 @@ public:
void AppendToChain( SHAPE_LINE_CHAIN* aChainToAppendTo,
const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
double aAccuracy ) const;
SHAPE_ARC BuildArc( const VECTOR2I& aPrevPoint,
const std::function<VECTOR2I( const VECTOR2I& )>
aCadstarToKicadPointCallback ) const;
};
/**
+5 -4
View File
@@ -130,7 +130,7 @@ const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE
}
void PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
PROPERTY_BASE& PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aGroup )
{
const wxString& name = aProperty->Name();
TYPE_ID hash = aProperty->OwnerHash();
@@ -147,15 +147,16 @@ void PROPERTY_MANAGER::AddProperty( PROPERTY_BASE* aProperty, const wxString& aG
}
m_dirty = true;
return *aProperty;
}
void PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew,
const wxString& aGroup )
PROPERTY_BASE& PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName,
PROPERTY_BASE* aNew, const wxString& aGroup )
{
CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
AddProperty( aNew, aGroup );
return AddProperty( aNew, aGroup );
}
+2 -1
View File
@@ -25,6 +25,7 @@
#include <pgm_base.h>
#include <settings/app_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/color_settings.h>
#include <settings/common_settings.h>
#include <settings/parameters.h>
@@ -147,7 +148,7 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
&m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
&m_ColorTheme, wxS( "_builtin_default" ) ) );
&m_ColorTheme, COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT ) );
addParamsForWindow( &m_Window, "window" );
+4 -2
View File
@@ -31,6 +31,8 @@
///! Update the schema version whenever a migration is required
const int colorsSchemaVersion = 5;
const wxString COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT = "_builtin_default";
const wxString COLOR_SETTINGS::COLOR_BUILTIN_CLASSIC = "_builtin_classic";
COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath ) :
@@ -378,12 +380,12 @@ void COLOR_SETTINGS::SetColor( int aLayer, const COLOR4D& aColor )
std::vector<COLOR_SETTINGS*> COLOR_SETTINGS::CreateBuiltinColorSettings()
{
COLOR_SETTINGS* defaultTheme = new COLOR_SETTINGS( wxT( "_builtin_default" ) );
COLOR_SETTINGS* defaultTheme = new COLOR_SETTINGS( COLOR_BUILTIN_DEFAULT );
defaultTheme->SetName( _( "KiCad Default" ) );
defaultTheme->m_writeFile = false;
defaultTheme->Load(); // We can just get the colors out of the param defaults for this one
COLOR_SETTINGS* classicTheme = new COLOR_SETTINGS( wxT( "_builtin_classic" ) );
COLOR_SETTINGS* classicTheme = new COLOR_SETTINGS( COLOR_BUILTIN_CLASSIC );
classicTheme->SetName( _( "KiCad Classic" ) );
classicTheme->m_writeFile = false;
+14 -4
View File
@@ -66,6 +66,10 @@ SETTINGS_MANAGER::SETTINGS_MANAGER( bool aHeadless ) :
// create the common settings shared by all applications. Not loaded immediately
m_common_settings = RegisterSettings( new COMMON_SETTINGS, false );
// Create the built-in color settings
// Here to allow the Python API to access the built-in colors
registerBuiltinColorSettings();
}
SETTINGS_MANAGER::~SETTINGS_MANAGER()
@@ -203,7 +207,7 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetColorSettings( const wxString& aName )
if( !ret )
{
ret = registerColorSettings( aName );
*ret = *m_color_settings.at( "_builtin_default" );
*ret = *m_color_settings.at( COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
ret->SetFilename( wxT( "user" ) );
ret->SetReadOnly( false );
}
@@ -212,7 +216,7 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetColorSettings( const wxString& aName )
}
// This had better work
return m_color_settings.at( "_builtin_default" );
return m_color_settings.at( COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
}
@@ -305,11 +309,17 @@ COLOR_SETTINGS* SETTINGS_MANAGER::GetMigratedColorSettings()
}
void SETTINGS_MANAGER::registerBuiltinColorSettings()
{
for( COLOR_SETTINGS* settings : COLOR_SETTINGS::CreateBuiltinColorSettings() )
m_color_settings[settings->GetFilename()] = RegisterSettings( settings, false );
}
void SETTINGS_MANAGER::loadAllColorSettings()
{
// Create the built-in color settings
for( COLOR_SETTINGS* settings : COLOR_SETTINGS::CreateBuiltinColorSettings() )
m_color_settings[settings->GetFilename()] = RegisterSettings( settings, false );
registerBuiltinColorSettings();
wxFileName third_party_path;
const ENV_VAR_MAP& env = Pgm().GetLocalEnvVariables();
+41 -1
View File
@@ -34,13 +34,18 @@
%rename(getWxPoint) operator wxPoint;
%rename(getWxSize) operator wxSize;
%{
#include <math/vector2d.h>
%include <math/vector2d.h>
#include <math/vector3.h>
#include <math/box2.h>
%}
%include <math/vector2d.h>
%include <math/vector3.h>
%include <math/box2.h>
%template(VECTOR2I) VECTOR2<int>;
%template(VECTOR2I_EXTENDED_TYPE) VECTOR2_TRAITS<int>;
%template(VECTOR3D) VECTOR3<double>;
%template(BOX2I) BOX2<VECTOR2I>;
%extend VECTOR2<int>
@@ -74,3 +79,38 @@
%}
}
%extend VECTOR3<double>
{
void Set(double x, double y, double z) { self->x = x; self->y = y; self->z = z; }
PyObject* Get()
{
PyObject* tup = PyTuple_New(3);
PyTuple_SET_ITEM(tup, 0, PyFloat_FromDouble(self->x));
PyTuple_SET_ITEM(tup, 1, PyFloat_FromDouble(self->y));
PyTuple_SET_ITEM(tup, 2, PyFloat_FromDouble(self->z));
return tup;
}
%pythoncode
%{
def __eq__(self,other): return (self.x==other.x and self.y==other.y and self.z==other.z)
def __ne__(self,other): return not (self==other)
def __str__(self): return str(self.Get())
def __repr__(self): return 'VECTOR3D'+str(self.Get())
def __len__(self): return len(self.Get())
def __getitem__(self, index): return self.Get()[index]
def __setitem__(self, index, val):
if index == 0:
self.x = val
elif index == 1:
self.y = val
elif index == 2:
self.z = val
else:
raise IndexError
def __nonzero__(self): return self.Get() != (0, 0, 0)
%}
}
+1 -1
View File
@@ -50,7 +50,7 @@
/// URL to launch a new issue with pre-populated description
wxString COMMON_CONTROL::m_bugReportUrl =
wxS( "https://gitlab.com/kicad/code/kicad/issues/new?issue[description]=%s" );
wxS( "https://gitlab.com/kicad/code/kicad/issues/new?issuable_template=bare&issue[description]=%s" );
/// Issue template to use for reporting bugs (this should not be translated)
+12 -1
View File
@@ -24,6 +24,7 @@
#include <widgets/color_swatch.h>
#include <wx/dcmemory.h>
#include <gal/dpi_scaling.h>
#include <dialogs/dialog_color_picker.h>
#include <memory>
@@ -133,6 +134,16 @@ COLOR_SWATCH::COLOR_SWATCH( wxWindow* aParent, const COLOR4D& aColor, int aID,
m_checkerboardSize = ConvertDialogToPixels( CHECKERBOARD_SIZE_DU );
m_checkerboardBg = aParent->GetBackgroundColour();
#ifdef __WXMSW__
// These need additional scaling on Windows because of some discrepancy between pixel and
// content scaling that only affects certain widgets on Windows HiDPI. On other platforms, the
// value returned by ConvertDialogToPixels appears to be correct.
DPI_SCALING dpi( nullptr, aParent );
m_size /= dpi.GetContentScaleFactor();
m_checkerboardSize /= dpi.GetContentScaleFactor();
#endif
auto sizer = new wxBoxSizer( wxHORIZONTAL );
SetSizer( sizer );
@@ -300,4 +311,4 @@ void COLOR_SWATCH::OnDarkModeToggle()
m_checkerboardBg = m_parent->GetBackgroundColour();
wxBitmap bm = MakeBitmap( m_color, m_background, m_size, m_checkerboardSize, m_checkerboardBg );
m_swatch->SetBitmap( bm );
}
}
+2 -1
View File
@@ -20,6 +20,7 @@
#include <widgets/font_choice.h>
#include <wx/fontenum.h>
#include <font/fontconfig.h>
#include <pgm_base.h>
// The "official" name of the building Kicad stroke font (always existing)
#include <font/kicad_font_name.h>
@@ -32,7 +33,7 @@ FONT_CHOICE::FONT_CHOICE( wxWindow* aParent, int aId, wxPoint aPosition, wxSize
m_systemFontCount = wxChoice::GetCount();
std::vector<std::string> fontNames;
Fontconfig()->ListFonts( fontNames );
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
wxArrayString menuList;
+5 -1
View File
@@ -27,6 +27,7 @@
#include <wx/odcombo.h>
#include <wx/menuitem.h>
#include <gal/dpi_scaling.h>
#include <layer_ids.h>
#include <widgets/layer_box_selector.h>
@@ -140,9 +141,12 @@ int LAYER_BOX_SELECTOR::SetLayerSelection( int layer )
void LAYER_BOX_SELECTOR::ResyncBitmapOnly()
{
DPI_SCALING dpi( nullptr, this );
int size = static_cast<int>( dpi.GetScaleFactor() * 14 );
for( int i = 0; i < (int) GetCount(); ++i )
{
wxBitmap layerbmp( 14, 14 );
wxBitmap layerbmp( size, size );
DrawColorSwatch( layerbmp, getLayerColor( LAYER_PCB_BACKGROUND ), getLayerColor( i ) );
}
}
+197 -186
View File
@@ -327,7 +327,7 @@ void mpInfoLegend::Plot( wxDC& dc, mpWindow& w )
int plotCount = 0;
int posY = 0;
int tmpX = 0, tmpY = 0;
mpLayer* ly = NULL;
mpLayer* ly = nullptr;
wxPen lpen;
wxString label;
@@ -541,8 +541,8 @@ mpFXY::mpFXY( const wxString& name, int flags )
SetName( name );
m_flags = flags;
m_type = mpLAYER_PLOT;
m_scaleX = NULL;
m_scaleY = NULL;
m_scaleX = nullptr;
m_scaleY = nullptr;
// Avoid not initialized members:
maxDrawX = minDrawX = maxDrawY = minDrawY = 0;
@@ -562,207 +562,218 @@ void mpFXY::UpdateViewBoundary( wxCoord xnew, wxCoord ynew )
void mpFXY::Plot( wxDC& dc, mpWindow& w )
{
if( m_visible )
wxCHECK_RET( m_scaleX, wxS( "X scale was not set" ) );
wxCHECK_RET( m_scaleY, wxS( "Y scale was not set" ) );
if( !m_visible )
return;
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
// Check for a collapsed window before we try to allocate a negative number of points
if( endPx <= startPx || minYpx >= maxYpx )
return;
dc.SetPen( m_pen );
double x, y;
// Do this to reset the counters to evaluate bounding box for label positioning
Rewind();
GetNextXY( x, y );
maxDrawX = x;
minDrawX = x;
maxDrawY = y;
minDrawY = y;
// drawnPoints = 0;
Rewind();
dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
if( !m_continuous )
{
dc.SetPen( m_pen );
bool first = true;
wxCoord ix = 0;
std::set<wxCoord> ys;
double x, y;
// Do this to reset the counters to evaluate bounding box for label positioning
Rewind(); GetNextXY( x, y );
maxDrawX = x; minDrawX = x; maxDrawY = y; minDrawY = y;
// drawnPoints = 0;
Rewind();
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
if( !m_continuous )
while( GetNextXY( x, y ) )
{
bool first = true;
wxCoord ix = 0;
std::set<wxCoord> ys;
double px = m_scaleX->TransformToPlot( x );
double py = m_scaleY->TransformToPlot( y );
wxCoord newX = w.x2p( px );
while( GetNextXY( x, y ) )
if( first )
{
double px = m_scaleX->TransformToPlot( x );
double py = m_scaleY->TransformToPlot( y );
wxCoord newX = w.x2p( px );
if( first )
{
ix = newX;
first = false;
}
if( newX == ix ) // continue until a new X coordinate is reached
{
// collect all unique points
ys.insert( w.y2p( py ) );
continue;
}
for( auto& iy: ys )
{
if( m_drawOutsideMargins
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx)
&& (iy <= maxYpx) ) )
{
// for some reason DrawPoint does not use the current pen,
// so we use DrawLine for fat pens
if( m_pen.GetWidth() <= 1 )
{
dc.DrawPoint( ix, iy );
}
else
{
dc.DrawLine( ix, iy, ix, iy );
}
UpdateViewBoundary( ix, iy );
}
}
ys.clear();
ix = newX;
first = false;
}
if( newX == ix ) // continue until a new X coordinate is reached
{
// collect all unique points
ys.insert( w.y2p( py ) );
continue;
}
}
else
{
int count = 0;
int x0=0; // X position of merged current vertical line
int ymin0=0; // y min coord of merged current vertical line
int ymax0=0; // y max coord of merged current vertical line
int dupx0 = 0; // count of currently merged vertical lines
wxPoint line_start; // starting point of the current line to draw
// A buffer to store coordinates of lines to draw
std::vector<wxPoint>pointList;
pointList.reserve( endPx - startPx + 1 );
// Note: we can use dc.DrawLines() only for a reasonable number or points (<10000),
// because at least on Windows dc.DrawLines() can hang for a lot of points.
// (> 10000 points) (can happens when a lot of points is calculated)
// To avoid long draw time (and perhaps hanging) one plot only not redundant lines.
// To avoid artifacts when skipping points to the same x coordinate, for each
// group of points at a give, x coordinate we also draw a vertical line at this coord,
// from the ymin to the ymax vertical coordinates of skipped points
while( GetNextXY( x, y ) )
for( auto& iy: ys )
{
double px = m_scaleX->TransformToPlot( x );
double py = m_scaleY->TransformToPlot( y );
wxCoord x1 = w.x2p( px );
wxCoord y1 = w.y2p( py );
// Store only points on the drawing area, to speed up the drawing time
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the
// first point is drawn, the x1 low limit is startPx-1 in plot coordinates
if( x1 >= startPx-1 && x1 <= endPx )
if( m_drawOutsideMargins
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx) ) )
{
if( !count || line_start.x != x1 )
{
if( count && dupx0 > 1 && ymin0 != ymax0 )
{
// Vertical points are merged, draw the pending vertical line
// However, if the line is one pixel length, it is not drawn,
// because the main trace show this point
dc.DrawLine( x0, ymin0, x0, ymax0 );
}
x0 = x1;
ymin0 = ymax0 = y1;
dupx0 = 0;
pointList.emplace_back( wxPoint( x1, y1 ) );
line_start.x = x1;
line_start.y = y1;
count++;
}
// for some reason DrawPoint does not use the current pen, so we use
// DrawLine for fat pens
if( m_pen.GetWidth() <= 1 )
dc.DrawPoint( ix, iy );
else
{
ymin0 = std::min( ymin0, y1 );
ymax0 = std::max( ymax0, y1 );
x0 = x1;
dupx0++;
}
dc.DrawLine( ix, iy, ix, iy );
UpdateViewBoundary( ix, iy );
}
}
if( pointList.size() > 1 )
{
// For a better look (when using dashed lines) and more optimization,
// try to merge horizontal segments, in order to plot longer lines
// we are merging horizontal segments because this is easy,
// and horizontal segments are a frequent cases
std::vector<wxPoint> drawPoints;
drawPoints.reserve( endPx - startPx + 1 );
drawPoints.push_back( pointList[0] ); // push the first point in list
for( size_t ii = 1; ii < pointList.size()-1; ii++ )
{
// Skip intermediate points between the first point and the last
// point of the segment candidate
if( drawPoints.back().y == pointList[ii].y &&
drawPoints.back().y == pointList[ii+1].y )
continue;
else
drawPoints.push_back( pointList[ii] );
}
// push the last point to draw in list
if( drawPoints.back() != pointList.back() )
drawPoints.push_back( pointList.back() );
dc.DrawLines( drawPoints.size(), &drawPoints[0] );
}
ys.clear();
ix = newX;
ys.insert( w.y2p( py ) );
}
}
else
{
int count = 0;
int x0=0; // X position of merged current vertical line
int ymin0=0; // y min coord of merged current vertical line
int ymax0=0; // y max coord of merged current vertical line
int dupx0 = 0; // count of currently merged vertical lines
wxPoint line_start; // starting point of the current line to draw
if( !m_name.IsEmpty() && m_showName )
// A buffer to store coordinates of lines to draw
std::vector<wxPoint>pointList;
pointList.reserve( endPx - startPx + 1 );
// Note: we can use dc.DrawLines() only for a reasonable number or points (<10000),
// because at least on Windows dc.DrawLines() can hang for a lot of points.
// (> 10000 points) (can happens when a lot of points is calculated)
// To avoid long draw time (and perhaps hanging) one plot only not redundant lines.
// To avoid artifacts when skipping points to the same x coordinate, for each group of
// points at a give, x coordinate we also draw a vertical line at this coord, from the
// ymin to the ymax vertical coordinates of skipped points
while( GetNextXY( x, y ) )
{
dc.SetFont( m_font );
double px = m_scaleX->TransformToPlot( x );
double py = m_scaleY->TransformToPlot( y );
wxCoord tx, ty;
dc.GetTextExtent( m_name, &tx, &ty );
wxCoord x1 = w.x2p( px );
wxCoord y1 = w.y2p( py );
// xxx implement else ... if (!HasBBox())
// Store only points on the drawing area, to speed up the drawing time
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the first point
// is drawn, the x1 low limit is startPx-1 in plot coordinates
if( x1 >= startPx-1 && x1 <= endPx )
{
// const int sx = w.GetScrX();
// const int sy = w.GetScrY();
if( !count || line_start.x != x1 )
{
if( count && dupx0 > 1 && ymin0 != ymax0 )
{
// Vertical points are merged, draw the pending vertical line
// However, if the line is one pixel length, it is not drawn, because
// the main trace show this point
dc.DrawLine( x0, ymin0, x0, ymax0 );
}
if( (m_flags & mpALIGNMASK) == mpALIGN_NW )
{
tx = minDrawX + 8;
ty = maxDrawY + 8;
}
else if( (m_flags & mpALIGNMASK) == mpALIGN_NE )
{
tx = maxDrawX - tx - 8;
ty = maxDrawY + 8;
}
else if( (m_flags & mpALIGNMASK) == mpALIGN_SE )
{
tx = maxDrawX - tx - 8;
ty = minDrawY - ty - 8;
x0 = x1;
ymin0 = ymax0 = y1;
dupx0 = 0;
pointList.emplace_back( wxPoint( x1, y1 ) );
line_start.x = x1;
line_start.y = y1;
count++;
}
else
{
// mpALIGN_SW
tx = minDrawX + 8;
ty = minDrawY - ty - 8;
ymin0 = std::min( ymin0, y1 );
ymax0 = std::max( ymax0, y1 );
x0 = x1;
dupx0++;
}
}
}
if( pointList.size() > 1 )
{
// For a better look (when using dashed lines) and more optimization, try to merge
// horizontal segments, in order to plot longer lines
// We are merging horizontal segments because this is easy, and horizontal segments
// are a frequent cases
std::vector<wxPoint> drawPoints;
drawPoints.reserve( endPx - startPx + 1 );
drawPoints.push_back( pointList[0] ); // push the first point in list
for( size_t ii = 1; ii < pointList.size()-1; ii++ )
{
// Skip intermediate points between the first point and the last point of the
// segment candidate
if( drawPoints.back().y == pointList[ii].y &&
drawPoints.back().y == pointList[ii+1].y )
{
continue;
}
else
{
drawPoints.push_back( pointList[ii] );
}
}
dc.DrawText( m_name, tx, ty );
// push the last point to draw in list
if( drawPoints.back() != pointList.back() )
drawPoints.push_back( pointList.back() );
dc.DrawLines( drawPoints.size(), &drawPoints[0] );
}
}
if( !m_name.IsEmpty() && m_showName )
{
dc.SetFont( m_font );
wxCoord tx, ty;
dc.GetTextExtent( m_name, &tx, &ty );
// xxx implement else ... if (!HasBBox())
{
// const int sx = w.GetScrX();
// const int sy = w.GetScrY();
if( (m_flags & mpALIGNMASK) == mpALIGN_NW )
{
tx = minDrawX + 8;
ty = maxDrawY + 8;
}
else if( (m_flags & mpALIGNMASK) == mpALIGN_NE )
{
tx = maxDrawX - tx - 8;
ty = maxDrawY + 8;
}
else if( (m_flags & mpALIGNMASK) == mpALIGN_SE )
{
tx = maxDrawX - tx - 8;
ty = minDrawY - ty - 8;
}
else
{
// mpALIGN_SW
tx = minDrawX + 8;
ty = minDrawY - ty - 8;
}
}
dc.DrawText( m_name, tx, ty );
}
dc.DestroyClippingRegion();
}
@@ -1395,7 +1406,7 @@ mpScaleY::mpScaleY( const wxString& name, int flags, bool ticks )
m_flags = flags;
m_ticks = ticks;
m_type = mpLAYER_AXIS;
m_masterScale = NULL;
m_masterScale = nullptr;
m_nameFlags = mpALIGN_BORDER_LEFT;
}
@@ -1662,11 +1673,11 @@ mpWindow::mpWindow( wxWindow* parent,
m_minX = m_minY = 0;
m_maxX = m_maxY = 0;
m_last_lx = m_last_ly = 0;
m_buff_bmp = NULL;
m_buff_bmp = nullptr;
m_enableDoubleBuffer = false;
m_enableMouseNavigation = true;
m_enableLimitedView = false;
m_movingInfoLayer = NULL;
m_movingInfoLayer = nullptr;
// Set margins to 0
m_marginTop = 0; m_marginRight = 0; m_marginBottom = 0; m_marginLeft = 0;
@@ -1914,10 +1925,10 @@ void mpWindow::OnMouseLeftRelease( wxMouseEvent& event )
m_zooming = false;
if( m_movingInfoLayer != NULL )
if( m_movingInfoLayer != nullptr )
{
m_movingInfoLayer->UpdateReference();
m_movingInfoLayer = NULL;
m_movingInfoLayer = nullptr;
}
else
{
@@ -1953,7 +1964,7 @@ void mpWindow::Fit( double xMin, double xMax, double yMin, double yMax,
yMin -= yExtra;
yMax += yExtra;
if( printSizeX != NULL && printSizeY != NULL )
if( printSizeX != nullptr && printSizeY != nullptr )
{
// Printer:
m_scrX = *printSizeX;
@@ -1994,7 +2005,7 @@ void mpWindow::Fit( double xMin, double xMax, double yMin, double yMax,
// It is VERY IMPORTANT to DO NOT call Refresh if we are drawing to the printer!!
// Otherwise, the DC dimensions will be those of the window instead of the printer device
if( printSizeX == NULL || printSizeY == NULL )
if( printSizeX == nullptr || printSizeY == nullptr )
UpdateAll();
}
@@ -2634,7 +2645,7 @@ unsigned int mpWindow::CountLayers() const
mpLayer* mpWindow::GetLayer( int position ) const
{
if( ( position >= (int) m_layers.size() ) || position < 0 )
return NULL;
return nullptr;
return m_layers[position];
}
@@ -2648,7 +2659,7 @@ const mpLayer* mpWindow::GetLayerByName( const wxString& name ) const
return layer;
}
return NULL; // Not found
return nullptr; // Not found
}
@@ -2735,7 +2746,7 @@ mpInfoLayer* mpWindow::IsInsideInfoLayer( wxPoint& point )
}
}
return NULL;
return nullptr;
}
@@ -3078,9 +3089,9 @@ bool mpPrintout::OnPrintPage( int page )
// Restore colours
plotWindow->SetColourTheme( oldBgColour, oldFgColour, oldAxColour );
// Restore drawing
plotWindow->Fit( plotWindow->GetDesiredXmin(),
plotWindow->GetDesiredXmax(), plotWindow->GetDesiredYmin(),
plotWindow->GetDesiredYmax(), NULL, NULL );
plotWindow->Fit( plotWindow->GetDesiredXmin(), plotWindow->GetDesiredXmax(),
plotWindow->GetDesiredYmin(), plotWindow->GetDesiredYmax(), nullptr,
nullptr );
plotWindow->UpdateAll();
}
+66 -43
View File
@@ -65,8 +65,6 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
delete wxPGGlobalVars->m_defaultRenderer;
wxPGGlobalVars->m_defaultRenderer = new PG_CELL_RENDERER();
m_cachedSelection = std::make_unique<SELECTION>();
m_caption = new wxStaticText( this, wxID_ANY, _( "No objects selected" ) );
mainSizer->Add( m_caption, 0, wxALL | wxEXPAND, 5 );
@@ -74,6 +72,7 @@ PROPERTIES_PANEL::PROPERTIES_PANEL( wxWindow* aParent, EDA_BASE_FRAME* aFrame )
wxPG_DEFAULT_STYLE );
m_grid->SetUnspecifiedValueAppearance( wxPGCell( wxT( "<...>" ) ) );
m_grid->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS );
m_grid->SetValidationFailureBehavior( wxPG_VFB_MARK_CELL );
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RETURN );
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_NUMPAD_ENTER );
m_grid->AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_DOWN );
@@ -131,23 +130,20 @@ void PROPERTIES_PANEL::OnLanguageChanged()
void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
{
if( *m_cachedSelection == aSelection )
{
updatePropertyValues( aSelection );
return;
}
auto reset =
[&]()
{
if( m_grid->IsEditorFocused() )
m_grid->CommitChangesFromEditor();
*m_cachedSelection = aSelection;
if( m_grid->IsEditorFocused() )
m_grid->CommitChangesFromEditor();
m_grid->Clear();
m_displayed.clear();
m_grid->Clear();
m_displayed.clear();
};
if( aSelection.Empty() )
{
m_caption->SetLabel( _( "No objects selected" ) );
reset();
return;
}
@@ -159,15 +155,6 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
wxCHECK( !types.empty(), /* void */ );
if( aSelection.Size() > 1 )
{
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
}
else
{
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
}
PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance();
propMgr.SetUnits( m_frame->GetUserUnits() );
propMgr.SetTransforms( &m_frame->GetOriginTransforms() );
@@ -181,8 +168,7 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
std::vector<wxString> groupDisplayOrder = propMgr.GetGroupDisplayOrder( *types.begin() );
std::set<wxString> groups( groupDisplayOrder.begin(), groupDisplayOrder.end() );
std::map<wxPGProperty*, int> pgPropOrders;
std::map<wxString, std::vector<wxPGProperty*>> pgPropGroups;
std::set<PROPERTY_BASE*> availableProps;
// Get all possible properties
for( const TYPE_ID& type : types )
@@ -214,40 +200,77 @@ void PROPERTIES_PANEL::rebuildProperties( const SELECTION& aSelection )
}
}
EDA_ITEM* firstItem = aSelection.Front();
// Find a set of properties that is common to all selected items
for( PROPERTY_BASE* property : commonProps )
{
if( property->IsInternal() )
continue;
if( !propMgr.IsAvailableFor( TYPE_HASH( *aSelection.Front() ), property,
aSelection.Front() ) )
if( propMgr.IsAvailableFor( TYPE_HASH( *firstItem ), property, firstItem ) )
availableProps.insert( property );
}
bool writeable = true;
std::set<PROPERTY_BASE*> existingProps;
for( wxPropertyGridIterator it = m_grid->GetIterator(); !it.AtEnd(); it.Next() )
{
wxPGProperty* pgProp = it.GetProperty();
PROPERTY_BASE* property = propMgr.GetProperty( TYPE_HASH( *firstItem ), pgProp->GetName() );
// Switching item types? Property may no longer be valid
if( !property )
continue;
// Either determine the common value for a property or "<...>" to indicate multiple values
bool available;
bool writeable;
wxVariant commonVal;
available = extractValueAndWritability( aSelection, property, commonVal, writeable );
extractValueAndWritability( aSelection, property, commonVal, writeable );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
if( available )
existingProps.insert( property );
}
if( existingProps == availableProps )
return;
// Some difference exists: start from scratch
reset();
std::map<wxPGProperty*, int> pgPropOrders;
std::map<wxString, std::vector<wxPGProperty*>> pgPropGroups;
for( PROPERTY_BASE* property : availableProps )
{
wxPGProperty* pgProp = createPGProperty( property );
wxVariant commonVal;
if( !extractValueAndWritability( aSelection, property, commonVal, writeable ) )
continue;
if( pgProp )
{
wxPGProperty* pgProp = createPGProperty( property );
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
m_displayed.push_back( property );
if( pgProp )
{
pgProp->SetValue( commonVal );
pgProp->Enable( writeable );
m_displayed.push_back( property );
wxASSERT( displayOrder.count( property ) );
pgPropOrders[pgProp] = displayOrder[property];
pgPropGroups[property->Group()].emplace_back( pgProp );
}
wxASSERT( displayOrder.count( property ) );
pgPropOrders[pgProp] = displayOrder[property];
pgPropGroups[property->Group()].emplace_back( pgProp );
}
}
if( aSelection.Size() > 1 )
{
m_caption->SetLabel( wxString::Format( _( "%d objects selected" ), aSelection.Size() ) );
}
else
{
m_caption->SetLabel( aSelection.Front()->GetFriendlyName() );
}
const wxString unspecifiedGroupCaption = _( "Basic Properties" );
for( const wxString& groupName : groupDisplayOrder )
-17
View File
@@ -75,24 +75,10 @@ protected:
/**
* Generates the property grid for a given selection of items.
*
* Calling this will remove any existing properties shown, causing visible flicker on some
* platforms and canceling any pending edits. Make sure to only call this when the group of
* selected items has actually changed.
*
* @param aSelection is a set of items to show properties for.
*/
virtual void rebuildProperties( const SELECTION& aSelection );
/**
* Updates the values shown in the property grid for the current selection.
*
* Does not add or remove properties from the display (@see rebuildProperties)
* This implies that aSelection must have the same contents as m_cachedSelection.
*
* @param aSelection is the set of selected items.
*/
virtual void updatePropertyValues( const SELECTION& aSelection ) {}
virtual wxPGProperty* createPGProperty( const PROPERTY_BASE* aProperty ) const = 0;
// Event handlers
@@ -128,9 +114,6 @@ protected:
/// Proportion of the grid column splitter that is used for the key column (0.0 - 1.0)
float m_splitter_key_proportion;
/// A copy of the most recent selection passed to rebuildProperties
std::unique_ptr<SELECTION> m_cachedSelection;
};
#endif /* PROPERTIES_PANEL_H */
+4 -2
View File
@@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -42,6 +42,8 @@ void SEARCH_PANE::OnLanguageChange()
wxWindow* page = m_notebook->GetPage( i );
SEARCH_PANE_TAB* tab = dynamic_cast<SEARCH_PANE_TAB*>( page );
wxCHECK( tab, /* void */ );
tab->RefreshColumnNames();
m_notebook->SetPageText( i, wxGetTranslation( tab->GetSearchHandler()->GetName() ) );
}
@@ -103,4 +105,4 @@ void SEARCH_PANE::OnNotebookPageChanged( wxBookCtrlEvent& aEvent )
SEARCH_PANE_TAB* SEARCH_PANE::GetCurrentTab() const
{
return dynamic_cast<SEARCH_PANE_TAB*>( m_notebook->GetCurrentPage() );
}
}
+2 -3
View File
@@ -38,9 +38,8 @@ SYMBOLS_LISTBOX::SYMBOLS_LISTBOX( CVPCB_MAINFRAME* parent, wxWindowID id ) :
ITEMS_LISTBOX_BASE( parent, id ),
m_warningAttr( std::make_unique<wxListItemAttr>() )
{
m_warningAttr->SetBackgroundColour( KIPLATFORM::UI::IsDarkTheme()
? wxColour( 112, 96, 32 )
: *wxYELLOW );
m_warningAttr->SetBackgroundColour( KIPLATFORM::UI::IsDarkTheme() ? wxColour( 112, 96, 32 )
: wxColour( 255, 248, 212 ) );
}
+3
View File
@@ -84,6 +84,9 @@ void CVPCB_MAINFRAME::ReCreateHToolbar()
m_tcFilterString = new wxTextCtrl( m_mainToolBar, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxDefaultSize, wxTE_PROCESS_ENTER );
// Min size on Mac is (a not very useful) single character
m_tcFilterString->SetMinSize( wxSize( 150, -1 ) );
m_tcFilterString->Bind( wxEVT_TEXT_ENTER, &CVPCB_MAINFRAME::onTextFilterChanged, this );
m_mainToolBar->AddControl( m_tcFilterString );
+4
View File
@@ -947,6 +947,10 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
m_toolManager->RunAction( ACTIONS::updateSchematicFromPcb, true );
break;
case MAIL_RELOAD_LIB:
SyncView();
break;
default:;
}
+12 -12
View File
@@ -512,21 +512,18 @@ int DIALOG_CHANGE_SYMBOLS::processMatchingSymbols()
int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
SYMBOL_CHANGE_INFO>& aSymbols )
SYMBOL_CHANGE_INFO>& aSymbols )
{
wxCHECK( !aSymbols.empty(), 0 );
int matchesProcessed = 0;
SCH_EDIT_FRAME* frame = dynamic_cast<SCH_EDIT_FRAME*>( GetParent() );
SCH_SCREEN* screen = nullptr;
LIB_SYMBOL* libSymbol = nullptr;
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
wxString msg;
wxCHECK( frame, 0 );
wxString msg;
auto it = symbols.begin();
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO> symbols = aSymbols;
std::map<SCH_SYMBOL*, SYMBOL_CHANGE_INFO>::iterator it = symbols.begin();
// Remove all symbols that don't have a valid library symbol link or enough units to
// satify the library symbol update.
@@ -536,7 +533,7 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
wxCHECK2( symbol && it->second.m_LibId.IsValid(), continue );
libSymbol = frame->GetLibSymbol( it->second.m_LibId );
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( it->second.m_LibId );
if( !libSymbol )
{
@@ -562,18 +559,21 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
}
}
bool appendUndo = false;
// Removing the symbol needs to be done before the LIB_SYMBOL is changed to prevent stale
// library symbols in the schematic file.
for( const auto& [ symbol, symbol_change_info ] : symbols )
{
wxCHECK( symbol && !symbol_change_info.m_Instances.empty(), 0 );
screen = symbol_change_info.m_Instances[0].LastScreen();
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
wxCHECK( screen, 0 );
screen->Remove( symbol );
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, true );
frame->SaveCopyInUndoList( screen, symbol, UNDO_REDO::CHANGED, appendUndo );
appendUndo = true;
}
for( const auto& [ symbol, symbol_change_info ] : symbols )
@@ -581,8 +581,9 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
if( symbol_change_info.m_LibId != symbol->GetLibId() )
symbol->SetLibId( symbol_change_info.m_LibId );
libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
LIB_SYMBOL* libSymbol = frame->GetLibSymbol( symbol_change_info.m_LibId );
std::unique_ptr<LIB_SYMBOL> flattenedSymbol = libSymbol->Flatten();
SCH_SCREEN* screen = symbol_change_info.m_Instances[0].LastScreen();
symbol->SetLibSymbol( flattenedSymbol.release() );
@@ -696,7 +697,6 @@ int DIALOG_CHANGE_SYMBOLS::processSymbols( const std::map<SCH_SYMBOL*,
}
symbol->SetSchSymbolLibraryName( wxEmptyString );
screen = symbol_change_info.m_Instances[0].LastScreen();
screen->Append( symbol );
frame->GetCanvas()->GetView()->Update( symbol );
@@ -157,6 +157,8 @@ void DIALOG_FIELD_PROPERTIES::init()
// Predefined fields cannot contain some chars, or cannot be empty,
// and need a SCH_FIELD_VALIDATOR (m_StyledTextCtrl cannot use a SCH_FIELD_VALIDATOR).
// VALUE_FIELD does not use the validator so that it uses the Scintilla text control, since we
// allow text replacement for this field (but not the other predefined fields)
bool use_validator = m_fieldId == REFERENCE_FIELD
|| m_fieldId == FOOTPRINT_FIELD
|| m_fieldId == DATASHEET_FIELD
@@ -189,10 +191,12 @@ void DIALOG_FIELD_PROPERTIES::init()
"cannot be changed." ) ) );
m_note->Show( true );
m_TextCtrl->Enable( false );
m_StyledTextCtrl->Enable( false );
}
else
{
m_TextCtrl->Enable( true );
m_StyledTextCtrl->Enable( true );
}
GetSizer()->SetSizeHints( this );
@@ -489,6 +489,16 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
processItem( aSheetPath, pin );
}
}
else if( m_wires->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_WIRE_T,
SCH_LABEL_LOCATE_WIRE_T } ) )
{
processItem( aSheetPath, aItem );
}
else if( m_buses->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_BUS_T,
SCH_LABEL_LOCATE_BUS_T } ) )
{
processItem( aSheetPath, aItem );
}
else if( aItem->IsType( { SCH_LABEL_LOCATE_ANY_T } ) )
{
if( m_globalLabels->GetValue() && aItem->Type() == SCH_GLOBAL_LABEL_T )
@@ -529,16 +539,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
}
}
}
else if( m_wires->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_WIRE_T,
SCH_LABEL_LOCATE_WIRE_T } ) )
{
processItem( aSheetPath, aItem );
}
else if( m_buses->GetValue() && aItem->IsType( { SCH_ITEM_LOCATE_BUS_T,
SCH_LABEL_LOCATE_BUS_T } ) )
{
processItem( aSheetPath, aItem );
}
else if( m_schTextAndGraphics->GetValue() && aItem->IsType( { SCH_TEXT_T, SCH_TEXTBOX_T,
SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
SCH_SHAPE_T } ) )
+8 -4
View File
@@ -110,7 +110,11 @@ DIALOG_LABEL_PROPERTIES::DIALOG_LABEL_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_L
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
m_grid->SetTable( m_fields );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
[&]( wxCommandEvent& aEvent )
{
OnAddField( aEvent );
} ) );
m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
// Show/hide columns according to user's preference
@@ -603,7 +607,7 @@ void DIALOG_LABEL_PROPERTIES::OnAddField( wxCommandEvent& event )
if( !m_grid->CommitPendingChanges() )
return;
int fieldID = m_fields->size();
int fieldID = (int) m_fields->size();
wxString fieldName;
if( (int) fieldID == m_currentLabel->GetMandatoryFieldCount()
@@ -637,8 +641,8 @@ void DIALOG_LABEL_PROPERTIES::OnAddField( wxCommandEvent& event )
wxGridTableMessage msg( m_fields, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1 );
m_grid->ProcessTableMessage( msg );
m_grid->MakeCellVisible( m_fields->size() - 1, 0 );
m_grid->SetGridCursor( m_fields->size() - 1, fieldName == wxT( "Netclass" ) ? 1 : 0 );
m_grid->MakeCellVisible( (int) m_fields->size() - 1, 0 );
m_grid->SetGridCursor( (int) m_fields->size() - 1, 0 );
m_grid->EnableCellEditControl();
m_grid->ShowCellEditControl();
@@ -119,7 +119,8 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow()
wxFAIL_MSG( "Line type not found in the type lookup map" );
m_privateCheckbox->SetValue( m_shape->IsPrivate() );
m_checkApplyToAllUnits->SetValue( m_shape->GetUnit() == 0 );
m_checkApplyToAllUnits->SetValue(
symbol && symbol->GetUnitCount() > 1 && m_shape->GetUnit() == 0 );
m_checkApplyToAllUnits->Enable( symbol && symbol->GetUnitCount() > 1 );
m_checkApplyToAllConversions->SetValue( m_shape->GetConvert() == 0 );
@@ -65,7 +65,11 @@ DIALOG_LIB_SYMBOL_PROPERTIES::DIALOG_LIB_SYMBOL_PROPERTIES( SYMBOL_EDIT_FRAME* a
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
m_fields = new FIELDS_GRID_TABLE<LIB_FIELD>( this, aParent, m_grid, m_libEntry );
m_grid->SetTable( m_fields );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
[&]( wxCommandEvent& aEvent )
{
OnAddField( aEvent );
} ) );
m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
// Show/hide columns according to the user's preference
@@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2001 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 2004-2022 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2023 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -122,8 +122,14 @@ DIALOG_LIB_TEXT_PROPERTIES::~DIALOG_LIB_TEXT_PROPERTIES()
bool DIALOG_LIB_TEXT_PROPERTIES::TransferDataToWindow()
{
LIB_SYMBOL* symbol = nullptr;
if( m_graphicText )
{
symbol = m_graphicText->GetParent();
wxCHECK( symbol, false );
m_textSize.SetValue( m_graphicText->GetTextWidth() );
m_StyledTextCtrl->SetValue( m_graphicText->GetText() );
m_StyledTextCtrl->EmptyUndoBuffer();
@@ -135,7 +141,8 @@ bool DIALOG_LIB_TEXT_PROPERTIES::TransferDataToWindow()
m_bold->Check( m_graphicText->IsBold() );
m_privateCheckbox->SetValue( m_graphicText->IsPrivate() );
m_CommonUnit->SetValue( m_graphicText->GetUnit() == 0 );
m_CommonUnit->SetValue(
symbol && symbol->GetUnitCount() > 1 && m_graphicText->GetUnit() == 0 );
m_CommonConvert->SetValue( m_graphicText->GetConvert() == 0 );
if( m_graphicText->GetTextAngle().IsHorizontal() )
@@ -161,10 +168,12 @@ bool DIALOG_LIB_TEXT_PROPERTIES::TransferDataToWindow()
{
SYMBOL_EDITOR_SETTINGS* cfg = m_parent->GetSettings();
auto* tools = m_parent->GetToolManager()->GetTool<SYMBOL_EDITOR_DRAWING_TOOLS>();
symbol = m_parent->GetCurSymbol();
m_textSize.SetValue( schIUScale.MilsToIU( cfg->m_Defaults.text_size ) );
m_CommonUnit->SetValue( !tools->GetDrawSpecificUnit() );
m_CommonUnit->SetValue(
symbol && symbol->GetUnitCount() > 1 && !tools->GetDrawSpecificUnit() );
m_CommonConvert->SetValue( !tools->GetDrawSpecificConvert() );
if( tools->GetLastTextAngle().IsHorizontal() )
@@ -173,6 +182,8 @@ bool DIALOG_LIB_TEXT_PROPERTIES::TransferDataToWindow()
m_vertical->Check();
}
m_CommonUnit->Enable( symbol && symbol->GetUnitCount() > 1 );
return true;
}
@@ -141,6 +141,8 @@ bool DIALOG_LIB_TEXTBOX_PROPERTIES::TransferDataToWindow()
if( !wxDialog::TransferDataToWindow() )
return false;
LIB_SYMBOL* symbol = m_currentText->GetParent();
m_textCtrl->SetValue( m_currentText->GetText() );
m_textCtrl->EmptyUndoBuffer();
@@ -204,7 +206,9 @@ bool DIALOG_LIB_TEXTBOX_PROPERTIES::TransferDataToWindow()
m_fillColorSwatch->Enable( m_currentText->IsFilled() );
m_privateCheckbox->SetValue( m_currentText->IsPrivate() );
m_CommonUnit->SetValue( m_currentText->GetUnit() == 0 );
m_CommonUnit->SetValue(
symbol && symbol->GetUnitCount() > 1 && m_currentText->GetUnit() == 0 );
m_CommonUnit->Enable( symbol && symbol->GetUnitCount() > 1 );
m_CommonConvert->SetValue( m_currentText->GetConvert() == 0 );
return true;
+1 -1
View File
@@ -266,7 +266,7 @@ bool DIALOG_PIN_PROPERTIES::TransferDataToWindow()
m_numberSize.SetValue( m_pin->GetNumberTextSize() );
m_pinLength.SetValue( m_pin->GetLength() );
m_checkApplyToAllParts->Enable( m_pin->GetParent()->IsMulti() );
m_checkApplyToAllParts->SetValue( m_pin->GetUnit() == 0 );
m_checkApplyToAllParts->SetValue( m_pin->GetParent()->IsMulti() && m_pin->GetUnit() == 0 );
m_checkApplyToAllConversions->SetValue( m_pin->GetConvert() == 0 );
m_checkShow->SetValue( m_pin->IsVisible() );
+4 -1
View File
@@ -338,7 +338,10 @@ COLOR_SETTINGS* DIALOG_PLOT_SCHEMATIC::getColorSettings()
int selection = m_colorTheme->GetSelection();
if( selection < 0 )
return m_parent->GetSettingsManager()->GetColorSettings( "_builtin_default" );
{
return m_parent->GetSettingsManager()->GetColorSettings(
COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
}
return static_cast<COLOR_SETTINGS*>( m_colorTheme->GetClientData( selection ) );
}
+5 -1
View File
@@ -61,7 +61,11 @@ DIALOG_SHEET_PROPERTIES::DIALOG_SHEET_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_S
m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
m_grid->SetTable( m_fields );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this,
[&]( wxCommandEvent& aEvent )
{
OnAddField( aEvent );
} ) );
m_grid->SetSelectionMode( wxGrid::wxGridSelectRows );
// Show/hide columns according to user's preference
+151 -135
View File
@@ -74,26 +74,19 @@ DIALOG_SIM_MODEL<T_symbol, T_field>::DIALOG_SIM_MODEL( wxWindow* aParent, T_symb
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} );
m_typeChoice->Clear();
m_scintillaTricks = new SCINTILLA_TRICKS( m_codePreview, wxT( "{}" ), false );
m_paramGridMgr->Bind( wxEVT_PG_SELECTED, &DIALOG_SIM_MODEL::onParamGridSelectionChange, this );
m_paramGrid->SetValidationFailureBehavior( wxPG_VFB_STAY_IN_PROPERTY
| wxPG_VFB_BEEP
| wxPG_VFB_MARK_CELL );
wxPropertyGrid* grid = m_paramGrid->GetGrid();
//grid->SetCellBackgroundColour( grid->GetPropertyDefaultCell().GetBgCol() );
//grid->SetCellTextColour( grid->GetPropertyDefaultCell().GetFgCol();
// In wx 3.0 the color will be wrong sometimes.
grid->SetCellDisabledTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ) );
grid->Bind( wxEVT_SET_FOCUS, &DIALOG_SIM_MODEL::onParamGridSetFocus, this );
grid->Bind( wxEVT_UPDATE_UI, &DIALOG_SIM_MODEL::onUpdateUI, this );
grid->AddActionTrigger( wxPG_ACTION_EDIT, WXK_RETURN );
grid->DedicateKey( WXK_RETURN );
@@ -169,6 +162,14 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
m_fields[ VALUE_FIELD ].SetText( wxT( "${SIM.PARAMS}" ) );
}
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
std::sort( sourcePins.begin(), sourcePins.end(),
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
{
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} );
std::string libraryFilename = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::LIBRARY_FIELD );
if( libraryFilename != "" )
@@ -179,8 +180,11 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
if( !loadLibrary( libraryFilename ) )
{
m_libraryPathText->ChangeValue( libraryFilename );
m_modelNameChoice->SetSelection( -1 );
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
m_libraryModelsMgr.CreateModel( nullptr, sourcePins, m_fields );
m_modelNameChoice->Append( _( "<unknown>" ) );
m_modelNameChoice->SetSelection( 0 );
}
else
{
@@ -255,14 +259,6 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataToWindow()
m_curModelType = SIM_MODEL::ReadTypeFromFields( m_fields );
}
std::vector<LIB_PIN*> sourcePins = m_symbol.GetAllLibPins();
std::sort( sourcePins.begin(), sourcePins.end(),
[]( const LIB_PIN* lhs, const LIB_PIN* rhs )
{
return StrNumCmp( lhs->GetNumber(), rhs->GetNumber(), true ) < 0;
} );
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{
wxString msg;
@@ -302,33 +298,28 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
{
m_pinAssignmentsGrid->CommitPendingChanges();
// This should have been done in wxPGTextCtrlEditor::OnTextCtrlEvent(), but something must
// be clearing it before we get here, resulting in CommitChangesFromEditor() doing nothing
m_paramGrid->GetGrid()->EditorsValueWasModified();
m_paramGrid->GetGrid()->CommitChangesFromEditor();
if( !DIALOG_SIM_MODEL_BASE::TransferDataFromWindow() )
return false;
if( !m_modelNameChoice->IsEmpty() )
{
std::string modelName = m_modelNameChoice->GetStringSelection().ToStdString();
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::NAME_FIELD, modelName );
}
std::string path;
std::string name;
if( m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() )
if( m_useLibraryModelRadioButton->GetValue() )
{
path = m_libraryPathText->GetValue();
wxFileName fn( path );
if( fn.MakeRelativeTo( Prj().GetProjectPath() ) && !fn.GetFullPath().StartsWith( ".." ) )
path = fn.GetFullPath();
if( !m_modelNameChoice->IsEmpty() )
name = m_modelNameChoice->GetStringSelection().ToStdString();
else if( dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( &curModel() ) )
name = SIM_MODEL::GetFieldValue( &m_fields, SIM_LIBRARY::NAME_FIELD, false );
}
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::LIBRARY_FIELD, path );
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY::NAME_FIELD, name );
if( isIbisLoaded() )
{
@@ -337,17 +328,19 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
if( ibismodel )
{
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD,
ibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first );
std::string pins;
std::string modelName = std::string( m_ibisModelCombobox->GetValue().c_str() );
std::string differential;
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD,
std::string( m_ibisModelCombobox->GetValue().c_str() ) );
if( m_ibisPinCombobox->GetSelection() >= 0 )
pins = ibismodel->GetIbisPins().at( m_ibisPinCombobox->GetSelection() ).first;
SIM_MODEL::SetFieldValue(
m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD,
ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() ? "1" : "" );
if( ibismodel->CanDifferential() && m_differentialCheckbox->GetValue() )
differential = "1";
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::PIN_FIELD, pins );
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::MODEL_FIELD, modelName );
SIM_MODEL::SetFieldValue( m_fields, SIM_LIBRARY_KIBIS::DIFF_FIELD, differential );
}
}
@@ -368,11 +361,13 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::TransferDataFromWindow()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateWidgets()
{
updateIbisWidgets();
updateInstanceWidgets();
updateModelParamsTab();
updateModelCodeTab();
updatePinAssignments();
SIM_MODEL* model = &curModel();
updateIbisWidgets( model );
updateInstanceWidgets( model );
updateModelParamsTab( model );
updateModelCodeTab( model );
updatePinAssignments( model );
std::string ref = SIM_MODEL::GetFieldValue( &m_fields, SIM_REFERENCE_FIELD );
@@ -388,9 +383,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateWidgets()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateIbisWidgets()
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateIbisWidgets( SIM_MODEL* aModel )
{
SIM_MODEL_KIBIS* modelkibis = isIbisLoaded() ? dynamic_cast<SIM_MODEL_KIBIS*>( &curModel() )
SIM_MODEL_KIBIS* modelkibis = isIbisLoaded() ? dynamic_cast<SIM_MODEL_KIBIS*>( aModel )
: nullptr;
m_ibisModelCombobox->Show( isIbisLoaded() );
@@ -404,16 +399,16 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateIbisWidgets()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets( SIM_MODEL* aModel )
{
// Change the Type choice to match the current device type.
if( &curModel() != m_prevModel )
if( aModel != m_prevModel )
{
m_deviceTypeChoice->Clear();
if( m_useLibraryModelRadioButton->GetValue() )
{
m_deviceTypeChoice->Append( curModel().GetDeviceInfo().description );
m_deviceTypeChoice->Append( aModel->GetDeviceInfo().description );
m_deviceTypeChoice->SetSelection( 0 );
}
else
@@ -425,7 +420,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
m_deviceTypeChoice->Append( SIM_MODEL::DeviceInfo( deviceType ).description );
if( deviceType == curModel().GetDeviceType() )
if( deviceType == aModel->GetDeviceType() )
m_deviceTypeChoice->SetSelection( m_deviceTypeChoice->GetCount() - 1 );
}
}
@@ -434,11 +429,11 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
for( SIM_MODEL::TYPE type : SIM_MODEL::TYPE_ITERATOR() )
{
if( SIM_MODEL::TypeInfo( type ).deviceType == curModel().GetDeviceType() )
if( SIM_MODEL::TypeInfo( type ).deviceType == aModel->GetDeviceType() )
{
m_typeChoice->Append( SIM_MODEL::TypeInfo( type ).description );
if( type == curModel().GetType() )
if( type == aModel->GetType() )
m_typeChoice->SetSelection( m_typeChoice->GetCount() - 1 );
}
}
@@ -446,19 +441,14 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
m_typeChoice->Enable( !m_useLibraryModelRadioButton->GetValue() || isIbisLoaded() );
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( &curModel() )
|| dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( &curModel() ) )
{
if( dynamic_cast<SIM_MODEL_RAW_SPICE*>( aModel ) )
m_modelNotebook->SetSelection( 1 );
}
else
{
m_modelNotebook->SetSelection( 0 );
}
if( curModel().HasPrimaryValue() )
if( aModel->HasPrimaryValue() )
{
const SIM_MODEL::PARAM& primary = curModel().GetParam( 0 );
const SIM_MODEL::PARAM& primary = aModel->GetParam( 0 );
m_saveInValueCheckbox->SetLabel( wxString::Format( _( "Save parameter '%s (%s)' in Value "
"field" ),
@@ -476,9 +466,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateInstanceWidgets()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab()
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab( SIM_MODEL* aModel )
{
if( &curModel() != m_prevModel )
if( aModel != m_prevModel )
{
// This wxPropertyGridManager column and header stuff has to be here because it segfaults in
// the constructor.
@@ -530,8 +520,8 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab()
m_paramGrid->CollapseAll();
for( int i = 0; i < curModel().GetParamCount(); ++i )
addParamPropertyIfRelevant( i );
for( int i = 0; i < aModel->GetParamCount(); ++i )
addParamPropertyIfRelevant( aModel, i );
m_paramGrid->CollapseAll();
m_paramGrid->Expand( "AC" );
@@ -563,15 +553,18 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelParamsTab()
// Model values other than the currently edited value may have changed. Update them.
// This feature is called "autofill" and present only in certain models. Don't do it for
// models that don't have it for performance reasons.
if( curModel().HasAutofill() )
( *it )->SetValueFromString( param.value->ToString() );
if( aModel->HasAutofill() )
( *it )->SetValueFromString( param.value );
}
}
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab()
void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab( SIM_MODEL* aModel )
{
if( dynamic_cast<SIM_MODEL_SPICE_FALLBACK*>( aModel ) )
return;
wxString text;
SPICE_ITEM item;
@@ -580,7 +573,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab()
if( m_useInstanceModelRadioButton->GetValue() || item.modelName == "" )
item.modelName = m_fields.at( REFERENCE_FIELD ).GetText();
text << curModel().SpiceGenerator().Preview( item );
text << aModel->SpiceGenerator().Preview( item );
m_codePreview->SetText( text );
m_codePreview->SelectNone();
@@ -588,9 +581,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updateModelCodeTab()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments( SIM_MODEL* aModel )
{
removeOrphanedPinAssignments();
removeOrphanedPinAssignments( aModel );
// Reset the grid.
@@ -601,9 +594,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
m_pinAssignmentsGrid->SetCellValue( row, PIN_COLUMN::MODEL, _( "Not Connected" ) );
// Now set up the grid values in the Model column.
for( int modelPinIndex = 0; modelPinIndex < curModel().GetPinCount(); ++modelPinIndex )
for( int modelPinIndex = 0; modelPinIndex < aModel->GetPinCount(); ++modelPinIndex )
{
wxString symbolPinNumber = curModel().GetPin( modelPinIndex ).symbolPinNumber;
wxString symbolPinNumber = aModel->GetPin( modelPinIndex ).symbolPinNumber;
if( symbolPinNumber == "" )
continue;
@@ -613,7 +606,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
if( symbolPinRow == -1 )
continue;
wxString modelPinString = getModelPinString( modelPinIndex );
wxString modelPinString = getModelPinString( aModel, modelPinIndex );
m_pinAssignmentsGrid->SetCellValue( symbolPinRow, PIN_COLUMN::MODEL, modelPinString );
}
@@ -630,14 +623,14 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
std::vector<BITMAPS> modelPinIcons;
wxArrayString modelPinChoices;
for( int jj = 0; jj < curModel().GetPinCount(); ++jj )
for( int jj = 0; jj < aModel->GetPinCount(); ++jj )
{
if( curModel().GetPin( jj ).symbolPinNumber != "" )
if( aModel->GetPin( jj ).symbolPinNumber != "" )
modelPinIcons.push_back( PinShapeGetBitmap( GRAPHIC_PINSHAPE::LINE ) );
else
modelPinIcons.push_back( BITMAPS::INVALID_BITMAP );
modelPinChoices.Add( getModelPinString( jj ) );
modelPinChoices.Add( getModelPinString( aModel, jj ) );
}
modelPinIcons.push_back( BITMAPS::INVALID_BITMAP );
@@ -652,11 +645,9 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
// TODO: Show a preview of the symbol with the pin numbers shown.
SIM_MODEL* model = &curModel();
if( model->GetType() == SIM_MODEL::TYPE::SUBCKT )
if( aModel->GetType() == SIM_MODEL::TYPE::SUBCKT )
{
SIM_MODEL_SUBCKT* subckt = static_cast<SIM_MODEL_SUBCKT*>( model );
SIM_MODEL_SUBCKT* subckt = static_cast<SIM_MODEL_SUBCKT*>( aModel );
m_subckt->SetText( subckt->GetSpiceCode() );
}
else
@@ -668,12 +659,12 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::updatePinAssignments()
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::removeOrphanedPinAssignments()
void DIALOG_SIM_MODEL<T_symbol, T_field>::removeOrphanedPinAssignments( SIM_MODEL* aModel )
{
for( int i = 0; i < curModel().GetPinCount(); ++i )
for( int i = 0; i < aModel->GetPinCount(); ++i )
{
if( !m_symbol.GetPin( curModel().GetPin( i ).symbolPinNumber ) )
curModel().SetPinSymbolPinNumber( i, "" );
if( !m_symbol.GetPin( aModel->GetPin( i ).symbolPinNumber ) )
aModel->SetPinSymbolPinNumber( i, "" );
}
}
@@ -682,6 +673,9 @@ template <typename T_symbol, typename T_field>
bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryPath,
bool aForceReload )
{
if( m_prevLibrary == aLibraryPath && !aForceReload )
return true;
wxString msg;
WX_STRING_REPORTER reporter( &msg );
@@ -735,75 +729,77 @@ bool DIALOG_SIM_MODEL<T_symbol, T_field>::loadLibrary( const wxString& aLibraryP
m_ibisPinCombobox->SetSelection( -1 );
}
m_prevLibrary = aLibraryPath;
return true;
}
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::addParamPropertyIfRelevant( int aParamIndex )
void DIALOG_SIM_MODEL<T_symbol, T_field>::addParamPropertyIfRelevant( SIM_MODEL* aModel,
int aParamIndex )
{
if( curModel().GetParam( aParamIndex ).info.dir == SIM_MODEL::PARAM::DIR_OUT )
if( aModel->GetParam( aParamIndex ).info.dir == SIM_MODEL::PARAM::DIR_OUT )
return;
switch( curModel().GetParam( aParamIndex ).info.category )
switch( aModel->GetParam( aParamIndex ).info.category )
{
case CATEGORY::AC:
m_paramGrid->HideProperty( "AC", false );
m_paramGrid->AppendIn( "AC", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "AC", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::DC:
m_paramGrid->HideProperty( "DC", false );
m_paramGrid->AppendIn( "DC", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "DC", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::CAPACITANCE:
m_paramGrid->HideProperty( "Capacitance", false );
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Capacitance", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::TEMPERATURE:
m_paramGrid->HideProperty( "Temperature", false );
m_paramGrid->AppendIn( "Temperature", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Temperature", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::NOISE:
m_paramGrid->HideProperty( "Noise", false );
m_paramGrid->AppendIn( "Noise", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Noise", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::DISTRIBUTED_QUANTITIES:
m_paramGrid->HideProperty( "Distributed Quantities", false );
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Distributed Quantities", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::WAVEFORM:
m_paramGrid->HideProperty( "Waveform", false );
m_paramGrid->AppendIn( "Waveform", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Waveform", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::GEOMETRY:
m_paramGrid->HideProperty( "Geometry", false );
m_paramGrid->AppendIn( "Geometry", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Geometry", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::LIMITING_VALUES:
m_paramGrid->HideProperty( "Limiting Values", false );
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Limiting Values", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::ADVANCED:
m_paramGrid->HideProperty( "Advanced", false );
m_paramGrid->AppendIn( "Advanced", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Advanced", newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::FLAGS:
m_paramGrid->HideProperty( "Flags", false );
m_paramGrid->AppendIn( "Flags", newParamProperty( aParamIndex ) );
m_paramGrid->AppendIn( "Flags", newParamProperty( aModel, aParamIndex ) );
break;
default:
m_paramGrid->Insert( m_firstCategory, newParamProperty( aParamIndex ) );
m_paramGrid->Insert( m_firstCategory, newParamProperty( aModel, aParamIndex ) );
break;
case CATEGORY::INITIAL_CONDITIONS:
@@ -814,9 +810,10 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::addParamPropertyIfRelevant( int aParam
template <typename T_symbol, typename T_field>
wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( int aParamIndex ) const
wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( SIM_MODEL* aModel ,
int aParamIndex ) const
{
const SIM_MODEL::PARAM& param = curModel().GetParam( aParamIndex );
const SIM_MODEL::PARAM& param = aModel->GetParam( aParamIndex );
wxString paramDescription;
if( param.info.description == "" )
@@ -830,18 +827,18 @@ wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( int aParamI
{
case SIM_VALUE::TYPE_BOOL:
// TODO.
prop = new SIM_BOOL_PROPERTY( paramDescription, param.info.name, curModel(), aParamIndex );
prop = new SIM_BOOL_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex );
prop->SetAttribute( wxPG_BOOL_USE_CHECKBOX, true );
break;
case SIM_VALUE::TYPE_INT:
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, curModel(),
aParamIndex, SIM_VALUE::TYPE_INT );
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex,
SIM_VALUE::TYPE_INT );
break;
case SIM_VALUE::TYPE_FLOAT:
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, curModel(),
aParamIndex, SIM_VALUE::TYPE_FLOAT );
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex,
SIM_VALUE::TYPE_FLOAT );
break;
//case TYPE_COMPLEX:
@@ -850,13 +847,12 @@ wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( int aParamI
case SIM_VALUE::TYPE_STRING:
if( param.info.enumValues.empty() )
{
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, curModel(),
prop = new SIM_STRING_PROPERTY( paramDescription, param.info.name, *aModel,
aParamIndex, SIM_VALUE::TYPE_STRING );
}
else
{
prop = new SIM_ENUM_PROPERTY( paramDescription, param.info.name, curModel(),
aParamIndex );
prop = new SIM_ENUM_PROPERTY( paramDescription, param.info.name, *aModel, aParamIndex );
}
break;
@@ -869,15 +865,9 @@ wxPGProperty* DIALOG_SIM_MODEL<T_symbol, T_field>::newParamProperty( int aParamI
// Legacy due to the way we extracted the parameters from Ngspice.
#if wxCHECK_VERSION( 3, 1, 0 )
if( param.isOtherVariant )
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValueOfOtherVariant ) );
else
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue ) );
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue ) );
#else
if( param.isOtherVariant )
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValueOfOtherVariant.c_str() ) );
else
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue.c_str() ) );
prop->SetCell( 3, wxString::FromUTF8( param.info.defaultValue.c_str() ) );
#endif
wxString typeStr;
@@ -967,9 +957,10 @@ wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getSymbolPinString( int symbolPinI
template <typename T_symbol, typename T_field>
wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getModelPinString( int aModelPinIndex ) const
wxString DIALOG_SIM_MODEL<T_symbol, T_field>::getModelPinString( SIM_MODEL* aModel,
int aModelPinIndex ) const
{
const wxString& pinName = curModel().GetPin( aModelPinIndex ).name;
const wxString& pinName = aModel->GetPin( aModelPinIndex ).name;
LOCALE_IO toggle;
@@ -1219,10 +1210,18 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onTypeChoice( wxCommandEvent& aEvent )
{
int idx = m_modelNameChoice->GetSelection();
auto& kibisModel = static_cast<SIM_MODEL_KIBIS&>( m_libraryModelsMgr.GetModels().at( idx ).get() );
auto& baseModel = static_cast<SIM_MODEL_KIBIS&>( m_libraryModelsMgr.GetModels().at( idx ).get() );
m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_KIBIS>( type, kibisModel,
m_fields, sourcePins ) );
m_libraryModelsMgr.SetModel( idx, std::make_unique<SIM_MODEL_KIBIS>( type, baseModel ) );
try
{
m_libraryModelsMgr.GetModels().at( idx ).get().ReadDataFields( &m_fields, sourcePins );
}
catch( IO_ERROR& err )
{
DisplayErrorMessage( this, err.What() );
}
}
m_curModelType = type;
@@ -1238,12 +1237,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onTypeChoice( wxCommandEvent& aEvent )
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::onPageChanging( wxBookCtrlEvent& event )
{
// This should have been done in wxPGTextCtrlEditor::OnTextCtrlEvent(), but something must
// be clearing it before we get here, resulting in CommitChangesFromEditor() doing nothing
m_paramGrid->GetGrid()->EditorsValueWasModified();
m_paramGrid->GetGrid()->CommitChangesFromEditor();
updateModelCodeTab();
updateModelCodeTab( &curModel() );
}
@@ -1266,7 +1260,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onPinAssignmentsGridCellChange( wxGrid
std::string( m_sortedPartPins.at( symbolPinIndex )->GetShownNumber().ToUTF8() ) );
}
updatePinAssignments();
updatePinAssignments( &curModel() );
aEvent.Skip();
}
@@ -1292,10 +1286,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSetFocus( wxFocusEvent& aEv
// Tab key is pressed. This is inconvenient, so we fix that here.
wxPropertyGrid* grid = m_paramGrid->GetGrid();
grid->CommitChangesFromEditor();
wxPGProperty* selected = grid->GetSelection();
wxPGProperty* selected = grid->GetSelection();
if( !selected )
selected = grid->wxPropertyGridInterface::GetFirst();
@@ -1312,8 +1303,6 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSelectionChange( wxProperty
{
wxPropertyGrid* grid = m_paramGrid->GetGrid();
grid->CommitChangesFromEditor();
// Jump over categories.
if( grid->GetSelection() && grid->GetSelection()->IsCategory() )
{
@@ -1359,6 +1348,7 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSelectionChange( wxProperty
}
wxWindow* editorControl = grid->GetEditorControl();
if( !editorControl )
{
m_prevParamGridSelection = grid->GetSelection();
@@ -1371,6 +1361,32 @@ void DIALOG_SIM_MODEL<T_symbol, T_field>::onParamGridSelectionChange( wxProperty
}
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::onUpdateUI( wxUpdateUIEvent& aEvent )
{
// This is currently patched in wxPropertyGrid::ScrollWindow() in the Mac wxWidgets fork.
// However, we may need this version if it turns out to be an issue on other platforms and
// we can't get it upstreamed.
#if 0
// It's a shame to do this on the UpdateUI event, but neither the wxPropertyGridManager,
// wxPropertyGridPage, wxPropertyGrid, nor the wxPropertyGrid's GetCanvas() window appear
// to get scroll events.
wxPropertyGrid* grid = m_paramGrid->GetGrid();
wxTextCtrl* ctrl = grid->GetEditorTextCtrl();
if( ctrl )
{
wxRect ctrlRect = ctrl->GetScreenRect();
wxRect gridRect = grid->GetScreenRect();
if( ctrlRect.GetTop() < gridRect.GetTop() || ctrlRect.GetBottom() > gridRect.GetBottom() )
grid->ClearSelection();
}
#endif
}
template <typename T_symbol, typename T_field>
void DIALOG_SIM_MODEL<T_symbol, T_field>::adjustParamGridColumns( int aWidth, bool aForce )
{
+11 -9
View File
@@ -70,18 +70,18 @@ private:
bool TransferDataFromWindow() override;
void updateWidgets();
void updateIbisWidgets();
void updateInstanceWidgets();
void updateModelParamsTab();
void updateModelCodeTab();
void updatePinAssignments();
void updateIbisWidgets( SIM_MODEL* aModel );
void updateInstanceWidgets( SIM_MODEL* aModel );
void updateModelParamsTab( SIM_MODEL* aModel );
void updateModelCodeTab( SIM_MODEL* aModel );
void updatePinAssignments( SIM_MODEL* aModel );
void removeOrphanedPinAssignments();
void removeOrphanedPinAssignments( SIM_MODEL* aModel );
bool loadLibrary( const wxString& aLibraryPath, bool aForceReload = false );
void addParamPropertyIfRelevant( int aParamIndex );
wxPGProperty* newParamProperty( int aParamIndex ) const;
void addParamPropertyIfRelevant( SIM_MODEL* aModel, int aParamIndex );
wxPGProperty* newParamProperty( SIM_MODEL* aModel, int aParamIndex ) const;
int findSymbolPinRow( const wxString& aSymbolPinNumber ) const;
@@ -89,7 +89,7 @@ private:
const SIM_LIBRARY* library() const;
wxString getSymbolPinString( int aSymbolPinNumber ) const;
wxString getModelPinString( int aModelPinIndex ) const;
wxString getModelPinString( SIM_MODEL* aModel, int aModelPinIndex ) const;
int getModelPinIndex( const wxString& aModelPinString ) const;
void onRadioButton( wxCommandEvent& aEvent ) override;
@@ -111,6 +111,7 @@ private:
void onParamGridSetFocus( wxFocusEvent& aEvent );
void onParamGridSelectionChange( wxPropertyGridEvent& aEvent );
void onUpdateUI( wxUpdateUIEvent& aEvent );
void adjustParamGridColumns( int aWidth, bool aForce );
@@ -122,6 +123,7 @@ private:
SIM_LIB_MGR m_libraryModelsMgr;
SIM_LIB_MGR m_builtinModelsMgr;
wxString m_prevLibrary;
const SIM_MODEL* m_prevModel;
std::vector<LIB_PIN*> m_sortedPartPins; //< Pins of the current part.
+2 -2
View File
@@ -72,7 +72,7 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
m_ibisPinCombobox = new wxComboBox( m_modelPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_ibisPinCombobox->Hide();
gbSizer1->Add( m_ibisPinCombobox, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_ibisPinCombobox, wxGBPosition( 2, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxTOP|wxBOTTOM, 2 );
m_differentialCheckbox = new wxCheckBox( m_modelPanel, wxID_ANY, _("Differential"), wxDefaultPosition, wxDefaultSize, 0 );
m_differentialCheckbox->Hide();
@@ -88,7 +88,7 @@ DIALOG_SIM_MODEL_BASE::DIALOG_SIM_MODEL_BASE( wxWindow* parent, wxWindowID id, c
m_ibisModelCombobox = new wxComboBox( m_modelPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxTE_PROCESS_ENTER );
m_ibisModelCombobox->Hide();
gbSizer1->Add( m_ibisModelCombobox, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
gbSizer1->Add( m_ibisModelCombobox, wxGBPosition( 3, 1 ), wxGBSpan( 1, 1 ), wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 1 );
gbSizer1->AddGrowableCol( 1 );
+4 -4
View File
@@ -699,10 +699,10 @@
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="border">2</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxComboBox" expanded="1">
@@ -905,10 +905,10 @@
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="border">1</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxEXPAND</property>
<property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxComboBox" expanded="1">
@@ -880,9 +880,9 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent )
int maxWidth = defaultDlgSize.x / 3;
if( col == m_grid->GetNumberCols() - 1 )
m_grid->SetColSize( col, std::min( std::max( 50, textWidth ), maxWidth ) );
m_grid->SetColSize( col, Clamp( 50, textWidth, maxWidth ) );
else
m_grid->SetColSize( col, std::min( std::max( 100, textWidth ), maxWidth ) );
m_grid->SetColSize( col, Clamp( 100, textWidth, maxWidth ) );
}
}
}
@@ -325,7 +325,11 @@ DIALOG_SYMBOL_PROPERTIES::DIALOG_SYMBOL_PROPERTIES( SCH_EDIT_FRAME* aParent,
m_pinGrid->SetDefaultRowSize( m_pinGrid->GetDefaultRowSize() + 4 );
m_fieldsGrid->SetTable( m_fields );
m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this ) );
m_fieldsGrid->PushEventHandler( new FIELDS_GRID_TRICKS( m_fieldsGrid, this,
[&]( wxCommandEvent& aEvent )
{
OnAddField( aEvent );
} ) );
m_fieldsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
// Show/hide columns according to user's preference
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@@ -29,10 +29,10 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
bMainSizer->Add( m_infoBar, 0, wxEXPAND|wxBOTTOM, 5 );
m_textEntrySizer = new wxGridBagSizer( 3, 3 );
m_textEntrySizer = new wxGridBagSizer( 2, 3 );
m_textEntrySizer->SetFlexibleDirection( wxBOTH );
m_textEntrySizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_textEntrySizer->SetEmptyCellSize( wxSize( 0,0 ) );
m_textEntrySizer->SetEmptyCellSize( wxSize( 0,10 ) );
m_textLabel = new wxStaticText( this, wxID_ANY, _("Text:"), wxDefaultPosition, wxDefaultSize, 0 );
m_textLabel->Wrap( -1 );
@@ -126,7 +126,7 @@
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxGridBagSizer" expanded="1">
<property name="empty_cell_size">0,0</property>
<property name="empty_cell_size">0,10</property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">3</property>
<property name="growablerows"></property>
@@ -135,7 +135,7 @@
<property name="name">m_textEntrySizer</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">protected</property>
<property name="vgap">3</property>
<property name="vgap">2</property>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
+6 -18
View File
@@ -891,7 +891,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow()
m_globalTable->Clear();
m_globalTable->m_rows.transfer( m_globalTable->m_rows.end(), global_model()->m_rows.begin(),
global_model()->m_rows.end(), global_model()->m_rows );
m_globalTable->reindex();
m_globalTable->reindex( true );
}
if( project_model() && *project_model() != *m_projectTable )
@@ -901,7 +901,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow()
m_projectTable->Clear();
m_projectTable->m_rows.transfer( m_projectTable->m_rows.end(), project_model()->m_rows.begin(),
project_model()->m_rows.end(), project_model()->m_rows );
m_projectTable->reindex();
m_projectTable->reindex( true );
}
return true;
@@ -1014,9 +1014,7 @@ size_t PANEL_SYM_LIB_TABLE::m_pageNdx = 0;
void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
{
auto* schEditor = (SCH_EDIT_FRAME*) aKiway->Player( FRAME_SCH, false );
auto* symbolEditor = (SYMBOL_EDIT_FRAME*) aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
auto* symbolViewer = (SYMBOL_VIEWER_FRAME*) aKiway->Player( FRAME_SCH_VIEWER, false );
SYMBOL_LIB_TABLE* globalTable = &SYMBOL_LIB_TABLE::GetGlobalLibTable();
wxString globalTablePath = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
@@ -1093,23 +1091,13 @@ void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent )
}
}
if( schEditor )
schEditor->SyncView();
if( symbolEditor )
{
// Check if the currently selected symbol library been removed or disabled.
if( !currentLib.empty() && projectTable && !projectTable->HasLibrary( currentLib, true ) )
{
symbolEditor->SetCurLib( wxEmptyString );
symbolEditor->emptyScreen();
}
symbolEditor->SyncLibraries( true );
symbolEditor->ThawLibraryTree();
symbolEditor->RefreshLibraryTree();
}
if( symbolViewer )
symbolViewer->ReCreateLibList();
std::string payload = "";
aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
aKiway->ExpressMail( FRAME_SCH_SYMBOL_EDITOR, MAIL_RELOAD_LIB, payload );
aKiway->ExpressMail( FRAME_SCH_VIEWER, MAIL_RELOAD_LIB, payload );
}
+22 -3
View File
@@ -135,6 +135,8 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override;
void Reset() override;
void OnKifaceEnd() override;
wxWindow* CreateKiWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway,
@@ -286,6 +288,8 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
int HandleJob( JOB* aJob ) override;
private:
bool loadGlobalLibTable();
std::unique_ptr<EESCHEMA_JOBS_HANDLER> m_jobHandler;
} kiface( "eeschema", KIWAY::FACE_SCH );
@@ -332,11 +336,28 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
start_common( aCtlBits );
if( !loadGlobalLibTable() )
return false;
m_jobHandler = std::make_unique<EESCHEMA_JOBS_HANDLER>();
return true;
}
void IFACE::Reset()
{
loadGlobalLibTable();
}
bool IFACE::loadGlobalLibTable()
{
wxFileName fn = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
if( !fn.FileExists() )
{
if( !( aCtlBits & KFCTL_CLI ) )
if( !( m_start_flags & KFCTL_CLI ) )
{
DIALOG_GLOBAL_SYM_LIB_TABLE_CONFIG fpDialog( nullptr );
@@ -366,8 +387,6 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
}
}
m_jobHandler = std::make_unique<EESCHEMA_JOBS_HANDLER>();
return true;
}
+2 -1
View File
@@ -46,6 +46,7 @@
#include <wx/settings.h>
#include <string_utils.h>
#include <widgets/grid_combobox.h>
#include <pgm_base.h>
enum
@@ -275,7 +276,7 @@ void FIELDS_GRID_TABLE<T>::initGrid( WX_GRID* aGrid )
wxArrayString fonts;
std::vector<std::string> fontNames;
Fontconfig()->ListFonts( fontNames );
Fontconfig()->ListFonts( fontNames, std::string( Pgm().GetLanguageTag().utf8_str() ) );
for( const std::string& name : fontNames )
fonts.Add( wxString( name ) );
+3 -2
View File
@@ -38,8 +38,9 @@ class SCH_LABEL_BASE;
class FIELDS_GRID_TRICKS : public GRID_TRICKS
{
public:
FIELDS_GRID_TRICKS( WX_GRID* aGrid, DIALOG_SHIM* aDialog ) :
GRID_TRICKS( aGrid ),
FIELDS_GRID_TRICKS( WX_GRID* aGrid, DIALOG_SHIM* aDialog,
std::function<void( wxCommandEvent& )> aAddHandler ) :
GRID_TRICKS( aGrid, std::move( aAddHandler ) ),
m_dlg( aDialog )
{}
+8 -2
View File
@@ -158,7 +158,7 @@ protected:
wxString GetHtmlFieldRow( const LIB_FIELD& aField ) const
{
wxString name = aField.GetCanonicalName();
wxString text = aField.GetFullText( m_unit > 0 ? m_unit : 1 );
wxString text;
wxString fieldhtml = FieldFormat;
fieldhtml.Replace( wxS( "__NAME__" ), EscapeHTML( name ) );
@@ -166,7 +166,7 @@ protected:
switch( aField.GetId() )
{
case DATASHEET_FIELD:
text = m_symbol->GetDatasheetField().GetText();
text = m_symbol->GetDatasheetField().GetShownText( 0, false );
if( text.IsEmpty() || text == wxT( "~" ) )
{
@@ -191,7 +191,13 @@ protected:
// showing the value just repeats the name, so that's not much use...
return wxEmptyString;
case REFERENCE_FIELD:
text = aField.GetFullText( m_unit > 0 ? m_unit : 1 );
fieldhtml.Replace( wxS( "__VALUE__" ), EscapeHTML( text ) );
break;
default:
text = aField.GetShownText( 0, false );
fieldhtml.Replace( wxS( "__VALUE__" ), EscapeHTML( text ) );
}
+8 -2
View File
@@ -383,8 +383,14 @@ void LIB_FIELD::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffs
if( !font )
font = KIFONT::FONT::GetFont( renderSettings->GetDefaultFont(), IsBold(), IsItalic() );
aPlotter->Text( textpos, color, GetShownText(), orient, GetTextSize(), hjustify, vjustify,
penWidth, IsItalic(), IsBold(), false, font );
TEXT_ATTRIBUTES attrs = GetAttributes();
attrs.m_StrokeWidth = penWidth;
attrs.m_Halign = hjustify;
attrs.m_Valign = vjustify;
attrs.m_Angle = orient;
attrs.m_Multiline = false;
aPlotter->PlotText( textpos, color, GetShownText(), attrs, font );
}
+49 -24
View File
@@ -812,8 +812,15 @@ void LIB_PIN::PlotPinTexts( PLOTTER *aPlotter, const VECTOR2I &aPinPos, int aPin
int size, GR_TEXT_H_ALIGN_T hJustify, GR_TEXT_V_ALIGN_T vJustify, int penWidth )
{
aPlotter->Text( VECTOR2I( px, py ), color, text, angle, VECTOR2I( size, size ),
hJustify, vJustify, penWidth, false, false, false, font );
TEXT_ATTRIBUTES attrs;
attrs.m_StrokeWidth = std::min( penWidth, size / 5 ); // Keep text readable
attrs.m_Angle = angle;
attrs.m_Size = VECTOR2I( size, size );
attrs.m_Halign = hJustify;
attrs.m_Valign = vJustify;
attrs.m_Multiline = false;
aPlotter->PlotText( VECTOR2I( px, py ), color, text, attrs, font );
};
/* Draw the text inside, but the pin numbers outside. */
@@ -1205,7 +1212,7 @@ const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNa
BOX2I bbox;
VECTOR2I begin;
VECTOR2I end;
int nameTextOffset = 0;
int pinNameOffset = 0;
int nameTextLength = 0;
int nameTextHeight = 0;
int numberTextLength = 0;
@@ -1228,7 +1235,7 @@ const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNa
if( GetParent() )
{
if( GetParent()->ShowPinNames() )
nameTextOffset = GetParent()->GetPinNameOffset();
pinNameOffset = GetParent()->GetPinNameOffset();
else
includeName = false;
@@ -1236,30 +1243,42 @@ const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNa
includeNumber = false;
}
// Get maximum height including ascenders and descenders
wxString test = wxT( "Xg" );
if( includeNumber )
{
VECTOR2D fontSize( m_numTextSize, m_numTextSize );
VECTOR2I numSize = font->StringBoundaryLimits( number, fontSize, penWidth, false, false );
numberTextLength = numSize.x;
numberTextHeight = numSize.y;
numberTextLength = font->StringBoundaryLimits( number, fontSize, penWidth, false, false ).x;
numberTextHeight = font->StringBoundaryLimits( test, fontSize, penWidth, false, false ).y;
}
if( includeName )
{
VECTOR2D fontSize( m_nameTextSize, m_nameTextSize );
VECTOR2I nameSize = font->StringBoundaryLimits( name, fontSize, penWidth, false, false );
nameTextLength = nameSize.x + nameTextOffset;
nameTextHeight = nameSize.y + schIUScale.MilsToIU( PIN_TEXT_MARGIN );
nameTextLength = font->StringBoundaryLimits( name, fontSize, penWidth, false, false ).x
+ pinNameOffset;
nameTextHeight = font->StringBoundaryLimits( test, fontSize, penWidth, false, false ).y
+ schIUScale.MilsToIU( PIN_TEXT_MARGIN );
}
// KIFONT has to be rather tight on boundary limits for knockout text in PCBNew, but in truth
// the stroke font returns a vertically under-sized bounding box (even though it *does* in fact
// attempt to account for the font size being stroke centre-point to stroke centre-point).
if( font->IsStroke() )
{
numberTextHeight += 2 * penWidth;
nameTextHeight += 2 * penWidth;
}
if( includeType )
{
double fontSize = std::max( m_nameTextSize * 3 / 4, schIUScale.mmToIU( 0.7 ) );
double stroke = fontSize / 8.0;
VECTOR2I typeTextSize = font->StringBoundaryLimits( GetElectricalTypeName(),
VECTOR2D( fontSize, fontSize ),
fontSize / 8.0, false, false );
KiROUND( stroke ), false, false );
typeTextLength = typeTextSize.x + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS;
minsizeV = std::max( minsizeV, typeTextSize.y / 2 );
@@ -1269,24 +1288,30 @@ const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNa
if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, *this ) );
// calculate top left corner position
// for the default pin orientation (PIN_RIGHT)
begin.y = std::max( minsizeV, numberTextHeight + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) );
begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
// Attempt to mimic SCH_PAINTER's algorithm without actually knowing the schematic text
// offset ratio.
int PIN_TEXT_OFFSET = schIUScale.MilsToIU( 24 ) + 2 * penWidth;
// calculate bottom right corner position and adjust top left corner position
if( nameTextOffset ) // for values > 0, pin name is inside the body
// Calculate topLeft & bottomRight corner positions for the default pin orientation (PIN_RIGHT)
if( pinNameOffset || !includeName )
{
// pin name is inside the body (or invisible)
// pin number is above the line
begin.y = std::max( minsizeV, numberTextHeight + PIN_TEXT_OFFSET );
begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
end.x = m_length + nameTextLength;
end.y = std::min( -minsizeV, -nameTextHeight / 2 );
}
else // if value == 0:
// pin name is outside the body, and above the pin line
// pin num is below the pin line
else
{
end.x = std::max( m_length, nameTextLength );
end.y = -begin.y;
begin.y = std::max( minsizeV, nameTextHeight );
// pin name is above pin line
// pin number is below line
begin.y = std::max( minsizeV, nameTextHeight + PIN_TEXT_OFFSET );
begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
end.x = std::max( m_length, nameTextLength );
end.y = std::min( -minsizeV, -numberTextHeight - PIN_TEXT_OFFSET );
}
// Now, calculate boundary box corners position for the actual pin orientation
+48 -43
View File
@@ -389,54 +389,59 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
}
}
penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID )
{
switch( GetShape() )
{
case SHAPE_T::ARC:
GRArc( DC, pt1, pt2, c, penWidth, color );
break;
case SHAPE_T::CIRCLE:
GRCircle( DC, pt1, GetRadius(), penWidth, color );
break;
case SHAPE_T::RECT:
GRRect( DC, pt1, pt2, penWidth, color );
break;
case SHAPE_T::POLY:
GRPoly( DC, ptCount, buffer, false, penWidth, color, color );
break;
case SHAPE_T::BEZIER:
GRPoly( DC, ptCount, buffer, false, penWidth, color, color );
break;
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
}
}
else
{
std::vector<SHAPE*> shapes = MakeEffectiveShapes( true );
penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
}
for( SHAPE* shape : shapes )
if( penWidth > 0 )
{
if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID )
{
STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings,
[&]( const VECTOR2I& a, const VECTOR2I& b )
{
VECTOR2I pts = aTransform.TransformCoordinate( a ) + aOffset;
VECTOR2I pte = aTransform.TransformCoordinate( b ) + aOffset;
GRLine( DC, pts.x, pts.y, pte.x, pte.y, penWidth, color );
} );
}
switch( GetShape() )
{
case SHAPE_T::ARC:
GRArc( DC, pt1, pt2, c, penWidth, color );
break;
for( SHAPE* shape : shapes )
delete shape;
case SHAPE_T::CIRCLE:
GRCircle( DC, pt1, GetRadius(), penWidth, color );
break;
case SHAPE_T::RECT:
GRRect( DC, pt1, pt2, penWidth, color );
break;
case SHAPE_T::POLY:
GRPoly( DC, ptCount, buffer, false, penWidth, color, color );
break;
case SHAPE_T::BEZIER:
GRPoly( DC, ptCount, buffer, false, penWidth, color, color );
break;
default:
UNIMPLEMENTED_FOR( SHAPE_T_asString() );
}
}
else
{
std::vector<SHAPE*> shapes = MakeEffectiveShapes( true );
for( SHAPE* shape : shapes )
{
STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings,
[&]( const VECTOR2I& a, const VECTOR2I& b )
{
VECTOR2I pts = aTransform.TransformCoordinate( a ) + aOffset;
VECTOR2I pte = aTransform.TransformCoordinate( b ) + aOffset;
GRLine( DC, pts.x, pts.y, pte.x, pte.y, penWidth, color );
} );
}
for( SHAPE* shape : shapes )
delete shape;
}
}
delete[] buffer;
+4 -3
View File
@@ -326,9 +326,10 @@ void LIB_TEXT::Plot( PLOTTER* plotter, bool aBackground, const VECTOR2I& offset,
if( !font )
font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), IsBold(), IsItalic() );
plotter->Text( pos, color, GetText(), t1 ? ANGLE_HORIZONTAL : ANGLE_VERTICAL, GetTextSize(),
GetHorizJustify(), GetVertJustify(), penWidth, IsItalic(), IsBold(),
true, font );
attrs.m_StrokeWidth = penWidth;
attrs.m_Angle = t1 ? ANGLE_HORIZONTAL : ANGLE_VERTICAL;
plotter->PlotText( pos, color, GetText(), attrs, font );
}
+5 -3
View File
@@ -465,11 +465,13 @@ void LIB_TEXTBOX::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOf
text.GetLinePositions( positions, (int) strings_list.Count() );
TEXT_ATTRIBUTES attrs = GetAttributes();
attrs.m_StrokeWidth = penWidth;
attrs.m_Multiline = false;
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
aPlotter->Text( positions[ii], color, strings_list.Item( ii ), text.GetTextAngle(),
text.GetTextSize(), text.GetHorizJustify(), text.GetVertJustify(),
penWidth, text.IsItalic(), text.IsBold(), false, font );
aPlotter->PlotText( positions[ii], color, strings_list.Item( ii ), attrs, font );
}
}
@@ -113,16 +113,18 @@ SCH_SYMBOL* NETLIST_EXPORTER_BASE::findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PA
}
void NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins )
std::vector<PIN_INFO> NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol,
SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins )
{
wxString ref( aSymbol->GetRef( aSheetPath ) );
wxString ref( aSymbol->GetRef( aSheetPath ) );
std::vector<PIN_INFO> pins;
// Power symbols and other symbols which have the reference starting with "#" are not
// included in netlist (pseudo or virtual symbols)
if( ref[0] == wxChar( '#' ) )
return;
return pins;
// if( aSymbol->m_FlagControlMulti == 1 )
// continue; /* yes */
@@ -130,9 +132,7 @@ void NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH*
// 1 screen), this will be erroneously be toggled.
if( !aSymbol->GetLibSymbolRef() )
return;
m_sortedSymbolPinList.clear();
return pins;
// If symbol is a "multi parts per package" type
if( aSymbol->GetLibSymbolRef()->GetUnitCount() > 1 )
@@ -140,7 +140,7 @@ void NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH*
// Collect all pins for this reference designator by searching the entire design for
// other parts with the same reference designator.
// This is only done once, it would be too expensive otherwise.
findAllUnitsOfSymbol( aSymbol, aSheetPath, aKeepUnconnectedPins );
findAllUnitsOfSymbol( aSymbol, aSheetPath, pins, aKeepUnconnectedPins );
}
else // GetUnitCount() <= 1 means one part per package
@@ -161,31 +161,33 @@ void NETLIST_EXPORTER_BASE::CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH*
continue;
}
m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
pins.emplace_back( pin->GetShownNumber(), netName );
}
}
}
// Sort pins in m_SortedSymbolPinList by pin number
std::sort( m_sortedSymbolPinList.begin(), m_sortedSymbolPinList.end(),
std::sort( pins.begin(), pins.end(),
[]( const PIN_INFO& lhs, const PIN_INFO& rhs )
{
return StrNumCmp( lhs.num, rhs.num, true ) < 0;
} );
// Remove duplicate Pins in m_SortedSymbolPinList
eraseDuplicatePins();
eraseDuplicatePins( pins );
// record the usage of this library symbol
m_libParts.insert( aSymbol->GetLibSymbolRef().get() ); // rejects non-unique pointers
return pins;
}
void NETLIST_EXPORTER_BASE::eraseDuplicatePins()
void NETLIST_EXPORTER_BASE::eraseDuplicatePins( std::vector<PIN_INFO>& aPins )
{
for( unsigned ii = 0; ii < m_sortedSymbolPinList.size(); ii++ )
for( unsigned ii = 0; ii < aPins.size(); ii++ )
{
if( m_sortedSymbolPinList[ii].num.empty() ) /* already deleted */
if( aPins[ii].num.empty() ) /* already deleted */
continue;
/* Search for duplicated pins
@@ -198,17 +200,17 @@ void NETLIST_EXPORTER_BASE::eraseDuplicatePins()
*/
int idxref = ii;
for( unsigned jj = ii + 1; jj < m_sortedSymbolPinList.size(); jj++ )
for( unsigned jj = ii + 1; jj < aPins.size(); jj++ )
{
if( m_sortedSymbolPinList[jj].num.empty() ) // Already removed
if( aPins[jj].num.empty() ) // Already removed
continue;
// if other pin num, stop search,
// because all pins having the same number are consecutive in list.
if( m_sortedSymbolPinList[idxref].num != m_sortedSymbolPinList[jj].num )
if( aPins[idxref].num != aPins[jj].num )
break;
m_sortedSymbolPinList[jj].num.clear();
aPins[jj].num.clear();
}
}
}
@@ -216,6 +218,7 @@ void NETLIST_EXPORTER_BASE::eraseDuplicatePins()
void NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol( SCH_SYMBOL* aSchSymbol,
SCH_SHEET_PATH* aSheetPath,
std::vector<PIN_INFO>& aPins,
bool aKeepUnconnectedPins )
{
wxString ref = aSchSymbol->GetRef( aSheetPath );
@@ -251,7 +254,7 @@ void NETLIST_EXPORTER_BASE::findAllUnitsOfSymbol( SCH_SYMBOL* aSchSymbol,
continue;
}
m_sortedSymbolPinList.emplace_back( pin->GetShownNumber(), netName );
aPins.emplace_back( pin->GetShownNumber(), netName );
}
}
}
@@ -147,7 +147,7 @@ public:
protected:
/**
* Find a symbol from the DrawList and builds its pin list in m_sortedSymbolPinList.
* Find a symbol from the DrawList and builds its pin list.
*
* This list is sorted by pin number. The symbol is the next actual symbol after \a aSymbol.
* Power symbols and virtual symbols that have their reference designators starting with
@@ -155,8 +155,8 @@ protected:
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins );
std::vector<PIN_INFO> CreatePinList( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins );
/**
* Check if the given symbol should be processed for netlisting.
@@ -170,7 +170,7 @@ protected:
SCH_SYMBOL* findNextSymbol( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath );
/**
* Erase duplicate pins from m_sortedSymbolPinList (i.e. set pointer in this list to NULL).
* Erase duplicate pins.
*
* (This is a list of pins found in the whole schematic, for a single symbol.) These
* duplicate pins were put in list because some pins (power pins...) are found more than
@@ -179,24 +179,18 @@ protected:
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
* Also set the m_Flag member of "removed" NETLIST_OBJECT pin item to 1
*/
void eraseDuplicatePins();
void eraseDuplicatePins( std::vector<PIN_INFO>& pins );
/**
* Find all units for symbols with multiple symbols per package.
*
* Search the entire design for all units of \a aSymbol based on matching reference
* designator, and for each unit, add all its pins to the temporary sorted pin list,
* m_sortedSymbolPinList.
* designator, and for each unit, add all its pins to the sorted pin list.
* if aKeepUnconnectedPins = false, unconnected pins will be removed from list
* but usually we need all pins in netlists.
*/
void findAllUnitsOfSymbol( SCH_SYMBOL* aSchSymbol, SCH_SHEET_PATH* aSheetPath,
bool aKeepUnconnectedPins );
/// Used to temporarily store and filter the list of pins of a schematic symbol when
/// generating schematic symbol data in netlist (comp section). No ownership of members.
/// TODO(snh): Descope this object
std::vector<PIN_INFO> m_sortedSymbolPinList;
std::vector<PIN_INFO>& aPins, bool aKeepUnconnectedPins );
/// Used for "multiple symbols per package" symbols to avoid processing a lib symbol more than
/// once
@@ -79,7 +79,7 @@ bool NETLIST_EXPORTER_ORCADPCB2::WriteNetlist( const wxString& aOutFileName,
if( !symbol->GetIncludeOnBoard() )
continue;
CreatePinList( symbol, &sheet, true );
std::vector<PIN_INFO> pins = CreatePinList( symbol, &sheet, true );
if( symbol->GetLibSymbolRef()
&& symbol->GetLibSymbolRef()->GetFPFilters().GetCount() != 0 )
@@ -110,7 +110,7 @@ bool NETLIST_EXPORTER_ORCADPCB2::WriteNetlist( const wxString& aOutFileName,
ret |= fprintf( f, "\n" );
// Write pin list:
for( const PIN_INFO& pin : m_sortedSymbolPinList )
for( const PIN_INFO& pin : pins )
{
if( pin.num.IsEmpty() ) // Erased pin in list
continue;
@@ -148,7 +148,7 @@ bool NETLIST_EXPORTER_SPICE::DoWriteNetlist( OUTPUTFORMATTER& aFormatter, unsign
void NETLIST_EXPORTER_SPICE::WriteHead( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions )
{
aFormatter.Print( 0, "KiCad schematic\n" );
aFormatter.Print( 0, ".title KiCad schematic\n" );
}
@@ -220,7 +220,7 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
if( !symbol || symbol->GetFieldText( SIM_ENABLE_FIELD ) == wxT( "0" ) )
continue;
CreatePinList( symbol, &sheet, true );
std::vector<PIN_INFO> pins = CreatePinList( symbol, &sheet, true );
SPICE_ITEM spiceItem;
@@ -267,8 +267,8 @@ bool NETLIST_EXPORTER_SPICE::ReadSchematicAndLibraries( unsigned aNetlistOptions
{
readRefName( sheet, *symbol, spiceItem, refNames );
readModel( sheet, *symbol, spiceItem );
readPinNumbers( *symbol, spiceItem );
readPinNetNames( *symbol, spiceItem, ncCounter );
readPinNumbers( *symbol, spiceItem, pins );
readPinNetNames( *symbol, spiceItem, pins, ncCounter );
// TODO: transmission line handling?
@@ -387,49 +387,55 @@ void NETLIST_EXPORTER_SPICE::ReadDirectives( unsigned aNetlistOptions )
wxStringTokenizer tokenizer( text, wxT( "\r\n" ), wxTOKEN_STRTOK );
bool foundDirective = false;
auto isDirective =
[]( const wxString& line, const wxString& dir )
{
return line == dir || line.StartsWith( dir + wxS( " " ) );
};
while( tokenizer.HasMoreTokens() )
{
wxString line = tokenizer.GetNextToken().Upper();
if( line.StartsWith( wxT( "." ) ) )
{
if( line.StartsWith( wxT( ".AC" ) )
|| line.StartsWith( wxT( ".CONTROL" ) )
|| line.StartsWith( wxT( ".CSPARAM" ) )
|| line.StartsWith( wxT( ".DISTO" ) )
|| line.StartsWith( wxT( ".ELSE" ) )
|| line.StartsWith( wxT( ".ELSEIF" ) )
|| line.StartsWith( wxT( ".END" ) )
|| line.StartsWith( wxT( ".ENDC" ) )
|| line.StartsWith( wxT( ".ENDIF" ) )
|| line.StartsWith( wxT( ".ENDS" ) )
|| line.StartsWith( wxT( ".FOUR" ) )
|| line.StartsWith( wxT( ".FUNC" ) )
|| line.StartsWith( wxT( ".GLOBAL" ) )
|| line.StartsWith( wxT( ".IC" ) )
|| line.StartsWith( wxT( ".IF" ) )
|| line.StartsWith( wxT( ".INCLUDE" ) )
|| line.StartsWith( wxT( ".LIB" ) )
|| line.StartsWith( wxT( ".MEAS" ) )
|| line.StartsWith( wxT( ".MODEL" ) )
|| line.StartsWith( wxT( ".NODESET" ) )
|| line.StartsWith( wxT( ".NOISE" ) )
|| line.StartsWith( wxT( ".OP" ) )
|| line.StartsWith( wxT( ".OPTIONS" ) )
|| line.StartsWith( wxT( ".PARAM" ) )
|| line.StartsWith( wxT( ".PLOT" ) )
|| line.StartsWith( wxT( ".PRINT" ) )
|| line.StartsWith( wxT( ".PROBE" ) )
|| line.StartsWith( wxT( ".PZ" ) )
|| line.StartsWith( wxT( ".SAVE" ) )
|| line.StartsWith( wxT( ".SENS" ) )
|| line.StartsWith( wxT( ".SP" ) )
|| line.StartsWith( wxT( ".SUBCKT" ) )
|| line.StartsWith( wxT( ".TEMP" ) )
|| line.StartsWith( wxT( ".TF" ) )
|| line.StartsWith( wxT( ".TITLE" ) )
|| line.StartsWith( wxT( ".TRAN" ) )
|| line.StartsWith( wxT( ".WIDTH" ) ) )
if( isDirective( line, wxS( ".AC" ) )
|| isDirective( line, wxS( ".CONTROL" ) )
|| isDirective( line, wxS( ".CSPARAM" ) )
|| isDirective( line, wxS( ".DISTO" ) )
|| isDirective( line, wxS( ".ELSE" ) )
|| isDirective( line, wxS( ".ELSEIF" ) )
|| isDirective( line, wxS( ".END" ) )
|| isDirective( line, wxS( ".ENDC" ) )
|| isDirective( line, wxS( ".ENDIF" ) )
|| isDirective( line, wxS( ".ENDS" ) )
|| isDirective( line, wxS( ".FOUR" ) )
|| isDirective( line, wxS( ".FUNC" ) )
|| isDirective( line, wxS( ".GLOBAL" ) )
|| isDirective( line, wxS( ".IC" ) )
|| isDirective( line, wxS( ".IF" ) )
|| isDirective( line, wxS( ".INCLUDE" ) )
|| isDirective( line, wxS( ".LIB" ) )
|| isDirective( line, wxS( ".MEAS" ) )
|| isDirective( line, wxS( ".MODEL" ) )
|| isDirective( line, wxS( ".NODESET" ) )
|| isDirective( line, wxS( ".NOISE" ) )
|| isDirective( line, wxS( ".OP" ) )
|| isDirective( line, wxS( ".OPTIONS" ) )
|| isDirective( line, wxS( ".PARAM" ) )
|| isDirective( line, wxS( ".PLOT" ) )
|| isDirective( line, wxS( ".PRINT" ) )
|| isDirective( line, wxS( ".PROBE" ) )
|| isDirective( line, wxS( ".PZ" ) )
|| isDirective( line, wxS( ".SAVE" ) )
|| isDirective( line, wxS( ".SENS" ) )
|| isDirective( line, wxS( ".SP" ) )
|| isDirective( line, wxS( ".SUBCKT" ) )
|| isDirective( line, wxS( ".TEMP" ) )
|| isDirective( line, wxS( ".TF" ) )
|| isDirective( line, wxS( ".TITLE" ) )
|| isDirective( line, wxS( ".TRAN" ) )
|| isDirective( line, wxS( ".WIDTH" ) ) )
{
foundDirective = true;
break;
@@ -495,7 +501,7 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
if( auto rawSpiceModel = dynamic_cast<const SIM_MODEL_RAW_SPICE*>( aItem.model ) )
{
int libParamIndex = static_cast<int>( SIM_MODEL_RAW_SPICE::SPICE_PARAM::LIB );
wxString path = rawSpiceModel->GetParam( libParamIndex ).value->ToString();
wxString path = rawSpiceModel->GetParam( libParamIndex ).value;
if( !path.IsEmpty() )
m_rawIncludes.insert( path );
@@ -527,20 +533,20 @@ void NETLIST_EXPORTER_SPICE::readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSym
}
void NETLIST_EXPORTER_SPICE::readPinNumbers( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem )
void NETLIST_EXPORTER_SPICE::readPinNumbers( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
const std::vector<PIN_INFO>& aPins )
{
for( const PIN_INFO& pin : m_sortedSymbolPinList )
aItem.pinNumbers.emplace_back( std::string( pin.num.ToUTF8() ) );
for( const PIN_INFO& pin : aPins )
aItem.pinNumbers.emplace_back( pin.num.ToStdString() );
}
void NETLIST_EXPORTER_SPICE::readPinNetNames( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
int& aNcCounter )
const std::vector<PIN_INFO>& aPins, int& aNcCounter )
{
for( const PIN_INFO& pinInfo : m_sortedSymbolPinList )
for( const PIN_INFO& pinInfo : aPins )
{
std::string netName = GenerateItemPinNetName( std::string( pinInfo.netName.ToUTF8() ),
aNcCounter );
std::string netName = GenerateItemPinNetName( pinInfo.netName.ToStdString(), aNcCounter );
aItem.pinNetNames.push_back( netName );
m_nets.insert( netName );
@@ -632,6 +638,12 @@ void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter,
if( aNetlistOptions & OPTION_SAVE_ALL_CURRENTS )
aFormatter.Print( 0, ".probe alli\n" );
auto isSimCommand =
[]( const wxString& candidate, const wxString& dir )
{
return candidate == dir || candidate.StartsWith( dir + wxS( " " ) );
};
for( const wxString& directive : m_directives )
{
bool simCommand = false;
@@ -640,15 +652,15 @@ void NETLIST_EXPORTER_SPICE::WriteDirectives( OUTPUTFORMATTER& aFormatter,
{
wxString candidate = directive.Upper();
simCommand = ( candidate.StartsWith( wxT( ".AC" ) )
|| candidate.StartsWith( wxT( ".DC" ) )
|| candidate.StartsWith( wxT( ".TRAN" ) )
|| candidate.StartsWith( wxT( ".OP" ) )
|| candidate.StartsWith( wxT( ".DISTO" ) )
|| candidate.StartsWith( wxT( ".NOISE" ) )
|| candidate.StartsWith( wxT( ".PZ" ) )
|| candidate.StartsWith( wxT( ".SENS" ) )
|| candidate.StartsWith( wxT( ".TF" ) ) );
simCommand = ( isSimCommand( candidate, wxS( ".AC" ) )
|| isSimCommand( candidate, wxS( ".DC" ) )
|| isSimCommand( candidate, wxS( ".TRAN" ) )
|| isSimCommand( candidate, wxS( ".OP" ) )
|| isSimCommand( candidate, wxS( ".DISTO" ) )
|| isSimCommand( candidate, wxS( ".NOISE" ) )
|| isSimCommand( candidate, wxS( ".PZ" ) )
|| isSimCommand( candidate, wxS( ".SENS" ) )
|| isSimCommand( candidate, wxS( ".TF" ) ) );
}
if( !simCommand || ( aNetlistOptions & OPTION_SIM_COMMAND ) )
@@ -130,7 +130,7 @@ public:
protected:
void ReadDirectives( unsigned aNetlistOptions );
virtual void WriteDirectives( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions ) const;
virtual void WriteDirectives( OUTPUTFORMATTER& candidate, unsigned aNetlistOptions ) const;
virtual std::string GenerateItemPinNetName( const std::string& aNetName,
int& aNcCounter ) const;
@@ -144,8 +144,10 @@ private:
void readRefName( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
std::set<std::string>& aRefNames );
void readModel( SCH_SHEET_PATH& aSheet, SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem );
void readPinNumbers( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem );
void readPinNetNames( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem, int& aNcCounter );
void readPinNumbers( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
const std::vector<PIN_INFO>& aPins );
void readPinNetNames( SCH_SYMBOL& aSymbol, SPICE_ITEM& aItem,
const std::vector<PIN_INFO>& aPins, int& aNcCounter );
void writeInclude( OUTPUTFORMATTER& aFormatter, unsigned aNetlistOptions,
const wxString& aPath );

Some files were not shown because too many files have changed in this diff Show More