codeallyadvanced 2.6.0__tar.gz → 3.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. {codeallyadvanced-2.6.0/src/codeallyadvanced.egg-info → codeallyadvanced-3.1.0}/PKG-INFO +36 -20
  2. codeallyadvanced-3.1.0/README.md +70 -0
  3. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/pyproject.toml +6 -6
  4. codeallyadvanced-3.1.0/src/codeallyadvanced/_version.py +1 -0
  5. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/DimensionsControl.py +63 -0
  6. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/DirectorySelector.py +141 -0
  7. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/DualSpinnerControl.py +196 -0
  8. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/MinMaxControl.py +57 -0
  9. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/NamedSpinCtrl.py +156 -0
  10. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/PositionControl.py +63 -0
  11. codeallyadvanced-3.1.0/src/codeallyadvanced/ui/widgets/TitledPanel.py +82 -0
  12. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0/src/codeallyadvanced.egg-info}/PKG-INFO +36 -20
  13. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced.egg-info/SOURCES.txt +2 -1
  14. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced.egg-info/requires.txt +5 -5
  15. codeallyadvanced-2.6.0/README.md +0 -54
  16. codeallyadvanced-2.6.0/src/codeallyadvanced/_version.py +0 -1
  17. codeallyadvanced-2.6.0/src/codeallyadvanced/resources/images/folder.py +0 -21
  18. codeallyadvanced-2.6.0/src/codeallyadvanced/ui/widgets/DimensionsControl.py +0 -58
  19. codeallyadvanced-2.6.0/src/codeallyadvanced/ui/widgets/DirectorySelector.py +0 -83
  20. codeallyadvanced-2.6.0/src/codeallyadvanced/ui/widgets/DualSpinnerControl.py +0 -132
  21. codeallyadvanced-2.6.0/src/codeallyadvanced/ui/widgets/MinMaxControl.py +0 -40
  22. codeallyadvanced-2.6.0/src/codeallyadvanced/ui/widgets/PositionControl.py +0 -58
  23. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/LICENSE +0 -0
  24. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/setup.cfg +0 -0
  25. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/__init__.py +0 -0
  26. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/py.typed +0 -0
  27. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/__init__.py +0 -0
  28. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/DefaultPreferences.py +0 -0
  29. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/__init__.py +0 -0
  30. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/__init__.py +0 -0
  31. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxActor.py +0 -0
  32. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxArrow.py +0 -0
  33. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxClass.py +0 -0
  34. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxNewClassDiagram.py +0 -0
  35. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxNewProject.py +0 -0
  36. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxNewSequenceDiagram.py +0 -0
  37. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxNewUseCaseDiagram.py +0 -0
  38. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxNote.py +0 -0
  39. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxOpenFile.py +0 -0
  40. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRedo.py +0 -0
  41. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipAggregation.py +0 -0
  42. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipAssociation.py +0 -0
  43. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipComposition.py +0 -0
  44. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipInheritance.py +0 -0
  45. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipNote.py +0 -0
  46. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxRelationshipRealization.py +0 -0
  47. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxSaveDiagram.py +0 -0
  48. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxSequenceDiagramInstance.py +0 -0
  49. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxSequenceDiagramMessage.py +0 -0
  50. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxText.py +0 -0
  51. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxUndo.py +0 -0
  52. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxUseCase.py +0 -0
  53. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxZoomIn.py +0 -0
  54. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/ImgToolboxZoomOut.py +0 -0
  55. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/UmlLollipop.py +0 -0
  56. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/UmlNote.py +0 -0
  57. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/UmlText.py +0 -0
  58. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/__init__.py +0 -0
  59. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded16/py.typed +0 -0
  60. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxActor.py +0 -0
  61. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxArrow.py +0 -0
  62. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxClass.py +0 -0
  63. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxNewClassDiagram.py +0 -0
  64. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxNewProject.py +0 -0
  65. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxNewSequenceDiagram.py +0 -0
  66. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxNewUseCaseDiagram.py +0 -0
  67. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxNote.py +0 -0
  68. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxOpenFile.py +0 -0
  69. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRedo.py +0 -0
  70. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipAggregation.py +0 -0
  71. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipAssociation.py +0 -0
  72. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipComposition.py +0 -0
  73. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipInheritance.py +0 -0
  74. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipNote.py +0 -0
  75. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxRelationshipRealization.py +0 -0
  76. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxSaveDiagram.py +0 -0
  77. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxSequenceDiagramInstance.py +0 -0
  78. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxSequenceDiagramMessage.py +0 -0
  79. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxText.py +0 -0
  80. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxUndo.py +0 -0
  81. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxUseCase.py +0 -0
  82. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxZoomIn.py +0 -0
  83. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/ImgToolboxZoomOut.py +0 -0
  84. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/UmlLollipop.py +0 -0
  85. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/UmlNote.py +0 -0
  86. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/UmlText.py +0 -0
  87. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/__init__.py +0 -0
  88. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/embedded32/py.typed +0 -0
  89. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/icons/sourceimages/__init__.py +0 -0
  90. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/images/py.typed +0 -0
  91. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/Embedded16.py +0 -0
  92. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/Embedded24.py +0 -0
  93. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/Embedded32.py +0 -0
  94. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/Embedded48.py +0 -0
  95. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/Embedded64.py +0 -0
  96. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/__init__.py +0 -0
  97. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/minimalistglyph/py.typed +0 -0
  98. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/MageBitMap.py +0 -0
  99. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/__init__.py +0 -0
  100. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/back16.py +0 -0
  101. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/back64.py +0 -0
  102. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/cancel16.py +0 -0
  103. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/cancel64.py +0 -0
  104. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/next16.py +0 -0
  105. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/next64.py +0 -0
  106. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/mystic/py.typed +0 -0
  107. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/Embedded16.py +0 -0
  108. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/Embedded24.py +0 -0
  109. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/Embedded32.py +0 -0
  110. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/Embedded48.py +0 -0
  111. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/Embedded64.py +0 -0
  112. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/__init__.py +0 -0
  113. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neoindustrialminimalist/py.typed +0 -0
  114. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/Embedded16.py +0 -0
  115. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/Embedded24.py +0 -0
  116. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/Embedded32.py +0 -0
  117. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/Embedded48.py +0 -0
  118. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/Embedded64.py +0 -0
  119. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/__init__.py +0 -0
  120. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/neumorphic/py.typed +0 -0
  121. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/resources/py.typed +0 -0
  122. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/AttachmentSide.py +0 -0
  123. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/Common.py +0 -0
  124. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/UnitTestBaseW.py +0 -0
  125. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/__init__.py +0 -0
  126. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/mystic/Mystic.py +0 -0
  127. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/mystic/MysticPanel.py +0 -0
  128. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/mystic/MysticStepBase.py +0 -0
  129. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/mystic/__init__.py +0 -0
  130. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/mystic/py.typed +0 -0
  131. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/py.typed +0 -0
  132. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/DialControl.py +0 -0
  133. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/DialSelector.py +0 -0
  134. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/DirectionEnum.py +0 -0
  135. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/MacDialSelector.py +0 -0
  136. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/__init__.py +0 -0
  137. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced/ui/widgets/py.typed +0 -0
  138. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced.egg-info/dependency_links.txt +0 -0
  139. {codeallyadvanced-2.6.0 → codeallyadvanced-3.1.0}/src/codeallyadvanced.egg-info/top_level.txt +0 -0
@@ -1,27 +1,27 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeallyadvanced
3
- Version: 2.6.0
3
+ Version: 3.1.0
4
4
  Summary: Humberto`s Common wxPython UI Stuff
5
5
  Author-email: "Humberto A. Sanchez II" <Humberto.A.Sanchez.II@gmail.com>
6
6
  Maintainer-email: "Humberto A. Sanchez II" <Humberto.A.Sanchez.II@gmail.com>
7
7
  License-Expression: AGPL-1.0-or-later
8
8
  Project-URL: Repository, https://github.com/hasii2011/code-ally-advanced
9
- Keywords: pyut,python,wxPython,UI,umldiagrammer
9
+ Keywords: uml,python,wxPython,UI,umldiagrammer
10
10
  Classifier: Programming Language :: Python
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Operating System :: MacOS :: MacOS X
13
13
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
14
  Description-Content-Type: text/markdown
15
15
  License-File: LICENSE
16
- Requires-Dist: buildlackey>=2.0.0
17
- Requires-Dist: wxPython>=4.2.4
16
+ Requires-Dist: buildlackey>=2.1.0
17
+ Requires-Dist: wxPython>=4.3.1
18
18
  Provides-Extra: test
19
- Requires-Dist: mypy==1.18.2; extra == "test"
20
- Requires-Dist: codeallybasic==1.30.0; extra == "test"
19
+ Requires-Dist: mypy==2.3.1; extra == "test"
20
+ Requires-Dist: codeallybasic==1.40.0; extra == "test"
21
21
  Requires-Dist: mypy-extensions==1.1.0; extra == "test"
22
22
  Requires-Dist: types-Deprecated==1.3.1.20251101; extra == "test"
23
23
  Requires-Dist: html-testRunner~=1.2.1; extra == "test"
24
- Requires-Dist: click==8.3.3; extra == "test"
24
+ Requires-Dist: click==8.5.0; extra == "test"
25
25
  Provides-Extra: docs
26
26
  Requires-Dist: sphinx>=7.0.0; extra == "docs"
27
27
  Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == "docs"
@@ -33,39 +33,54 @@ Requires-Dist: twine==6.2.0; extra == "deploy"
33
33
  Requires-Dist: build==1.3.0; extra == "deploy"
34
34
  Dynamic: license-file
35
35
 
36
- ![](https://github.com/hasii2011/code-ally-basic/blob/master/developer/agpl-license-web-badge-version-2-256x48.png "AGPL")
37
-
36
+ [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/hasii2011/code-ally-advanced/graphs/commit-activity)
38
37
  [![CI](https://github.com/hasii2011/code-ally-advanced/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/hasii2011/code-ally-advanced/actions/workflows/ci.yml)
39
38
  [![PyPI version](https://badge.fury.io/py/codeallyadvanced.svg)](https://badge.fury.io/py/codeallyadvanced)
40
- [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/hasii2011/code-ally-advanced/graphs/commit-activity)
39
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)
40
+ [![Made with Python](https://img.shields.io/badge/Made%20with-Python-3776AB?logo=python&logoColor=white)](https://www.python.org/)
41
+ [![Documentation Status](https://readthedocs.org/projects/code-ally-advanced/badge/?version=latest)](https://code-ally-advanced.readthedocs.io/en/latest/?badge=latest)
42
+ [![GitHub Copilot: No](https://img.shields.io/badge/GitHub_Copilot-No-red?logo=github&style=flat-square)](https://github.com/hasii2011/code-ally-basic/wiki/GitHub-Copilot)
41
43
 
42
- [![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)
44
+ This repository hosts common UI artifacts for various projects I develop.
43
45
 
44
- Host common UI artifacts for various projects I am developing
46
+ The documentation is on [Read the Docs](https://code-ally-advanced.readthedocs.io/en/latest/).
45
47
 
46
48
  ___
47
- Common wxPython UI artifacts for various projects I am developing
49
+ Available wxPython UI components:
48
50
 
49
51
  * Dimensions Control
50
52
  * Position Control
51
53
  * MinMax Control
54
+ * Named Spin Control
52
55
  * Directory Selector
56
+ * Dial Selector
57
+ * Titled Panels
53
58
 
54
- ![SpinnerWidgets](./developer/SpinnerWidgets.png)
59
+ ### Component Previews
55
60
 
56
- * DialSelector
61
+ * Spinner Widgets
62
+
63
+ ![SpinnerWidgets](./developer/SpinnerWidgets.png)
64
+
65
+ * Directory Selector
66
+
67
+ ![DirectorySelector](./developer/DirectorySelector.png)
68
+
69
+ * Dial Selector
57
70
 
58
71
  ![DialSelector](./developer/DialSelector.png)
59
72
 
60
- Written by <a href="mailto:email@humberto.a.sanchez.ii@gmail.com?subject=Hello Humberto">Humberto A. Sanchez II</a> (C) 2025
73
+ * Titled Panels
74
+
75
+ ![TitledPanels](./developer/TitledPanels.png)
76
+
77
+ Written by <a href="mailto:humberto.a.sanchez.ii@gmail.com?subject=Hello Humberto">Humberto A. Sanchez II</a> (C) 2026
61
78
 
62
79
  ## Note
63
80
  For all kinds of problems, requests, enhancements, bug reports, etc., drop me an e-mail.
64
81
 
65
82
  ## Developer Notes
66
- This project uses [buildlackey](https://github.com/hasii2011/buildlackey) for day-to-day development builds
67
-
68
- Also notice that this project does not include a `requirements.txt` file. All dependencies are listed in the `pyproject.toml` file.
83
+ This project uses [buildlackey](https://github.com/hasii2011/buildlackey) for day-to-day development builds.
69
84
 
70
85
  #### Install the main project dependencies
71
86
 
@@ -86,4 +101,5 @@ pip install .[deploy]
86
101
  ```
87
102
 
88
103
  ---
89
- [Copilot Statement](https://github.com/hasii2011/code-ally-basic/wiki/GitHub-Copilot).
104
+ > [!NOTE]
105
+ > **I do not consent to GitHub's use of this project's code in Copilot.** See our [GitHub Copilot Statement](https://github.com/hasii2011/code-ally-basic/wiki/GitHub-Copilot) for details.
@@ -0,0 +1,70 @@
1
+ [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/hasii2011/code-ally-advanced/graphs/commit-activity)
2
+ [![CI](https://github.com/hasii2011/code-ally-advanced/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/hasii2011/code-ally-advanced/actions/workflows/ci.yml)
3
+ [![PyPI version](https://badge.fury.io/py/codeallyadvanced.svg)](https://badge.fury.io/py/codeallyadvanced)
4
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)
5
+ [![Made with Python](https://img.shields.io/badge/Made%20with-Python-3776AB?logo=python&logoColor=white)](https://www.python.org/)
6
+ [![Documentation Status](https://readthedocs.org/projects/code-ally-advanced/badge/?version=latest)](https://code-ally-advanced.readthedocs.io/en/latest/?badge=latest)
7
+ [![GitHub Copilot: No](https://img.shields.io/badge/GitHub_Copilot-No-red?logo=github&style=flat-square)](https://github.com/hasii2011/code-ally-basic/wiki/GitHub-Copilot)
8
+
9
+ This repository hosts common UI artifacts for various projects I develop.
10
+
11
+ The documentation is on [Read the Docs](https://code-ally-advanced.readthedocs.io/en/latest/).
12
+
13
+ ___
14
+ Available wxPython UI components:
15
+
16
+ * Dimensions Control
17
+ * Position Control
18
+ * MinMax Control
19
+ * Named Spin Control
20
+ * Directory Selector
21
+ * Dial Selector
22
+ * Titled Panels
23
+
24
+ ### Component Previews
25
+
26
+ * Spinner Widgets
27
+
28
+ ![SpinnerWidgets](./developer/SpinnerWidgets.png)
29
+
30
+ * Directory Selector
31
+
32
+ ![DirectorySelector](./developer/DirectorySelector.png)
33
+
34
+ * Dial Selector
35
+
36
+ ![DialSelector](./developer/DialSelector.png)
37
+
38
+ * Titled Panels
39
+
40
+ ![TitledPanels](./developer/TitledPanels.png)
41
+
42
+ Written by <a href="mailto:humberto.a.sanchez.ii@gmail.com?subject=Hello Humberto">Humberto A. Sanchez II</a> (C) 2026
43
+
44
+ ## Note
45
+ For all kinds of problems, requests, enhancements, bug reports, etc., drop me an e-mail.
46
+
47
+ ## Developer Notes
48
+ This project uses [buildlackey](https://github.com/hasii2011/buildlackey) for day-to-day development builds.
49
+
50
+ #### Install the main project dependencies
51
+
52
+ ```bash
53
+ pip install .
54
+ ```
55
+
56
+ #### Install the test dependencies
57
+
58
+ ```bash
59
+ pip install .[test]
60
+ ```
61
+
62
+ #### Install the deploy dependencies
63
+
64
+ ```bash
65
+ pip install .[deploy]
66
+ ```
67
+
68
+ ---
69
+ > [!NOTE]
70
+ > **I do not consent to GitHub's use of this project's code in Copilot.** See our [GitHub Copilot Statement](https://github.com/hasii2011/code-ally-basic/wiki/GitHub-Copilot) for details.
@@ -9,7 +9,7 @@ description = 'Humberto`s Common wxPython UI Stuff'
9
9
  readme = "README.md"
10
10
  authors = [{name = 'Humberto A. Sanchez II', email = 'Humberto.A.Sanchez.II@gmail.com'}]
11
11
  maintainers = [{name = 'Humberto A. Sanchez II', email = 'Humberto.A.Sanchez.II@gmail.com'}]
12
- keywords = ['pyut', 'python', 'wxPython', 'UI', 'umldiagrammer']
12
+ keywords = ['uml', 'python', 'wxPython', 'UI', 'umldiagrammer']
13
13
  license = 'AGPL-1.0-or-later'
14
14
  license-files = ['LICENSE']
15
15
  classifiers = [
@@ -20,18 +20,18 @@ classifiers = [
20
20
  ]
21
21
 
22
22
  dependencies = [
23
- 'buildlackey>=2.0.0',
24
- 'wxPython>=4.2.4'
23
+ 'buildlackey>=2.1.0',
24
+ 'wxPython>=4.3.1'
25
25
  ]
26
26
 
27
27
  [project.optional-dependencies]
28
28
  test = [
29
- 'mypy==1.18.2',
30
- 'codeallybasic==1.30.0',
29
+ 'mypy==2.3.1',
30
+ 'codeallybasic==1.40.0',
31
31
  'mypy-extensions==1.1.0',
32
32
  'types-Deprecated==1.3.1.20251101',
33
33
  'html-testRunner~=1.2.1',
34
- 'click==8.3.3'
34
+ 'click==8.5.0'
35
35
 
36
36
  ]
37
37
 
@@ -0,0 +1 @@
1
+ __version__: str = '3.1.0'
@@ -0,0 +1,63 @@
1
+
2
+ from logging import Logger
3
+ from logging import getLogger
4
+
5
+ from dataclasses import dataclass
6
+
7
+ from wx.lib.sized_controls import SizedPanel
8
+
9
+ from codeallybasic.Dimensions import Dimensions
10
+
11
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import DualSpinnerControl
12
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import DualSpinnerParameters
13
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import SpinnerValues
14
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import ValueChangeCallback
15
+
16
+
17
+ @dataclass
18
+ class DimensionsParameters(DualSpinnerParameters):
19
+ minValue: int = 50
20
+ maxValue: int = 300
21
+ firstSpinnerLabel: str = 'W:'
22
+ secondSpinnerLabel: str = 'H:'
23
+
24
+
25
+ class DimensionsControl(DualSpinnerControl):
26
+ """
27
+ A facade around the basic dual spinner control; Essentially
28
+ * Converts the spinner values to and from the Dimension type;
29
+ * Handles the spinner callback
30
+ * Forwards the spinner values as Dimension values
31
+ """
32
+ DIMENSION_MIN_VALUE: int = 50
33
+ DIMENSION_MAX_VALUE: int = 300
34
+
35
+ def __init__(self, parent: SizedPanel, parameters: DimensionsParameters):
36
+ """
37
+
38
+ Args:
39
+ parent: The parent window
40
+ parameters: Configuration parameters for the dimensions control
41
+ """
42
+ self.logger: Logger = getLogger(__name__)
43
+ self._dimensionsChangedCallback: ValueChangeCallback = parameters.valueChangedCallback
44
+ self._dimensions: Dimensions = Dimensions()
45
+
46
+ super().__init__(parent=parent, parameters=parameters)
47
+
48
+ def _setDimensions(self, newValue: Dimensions):
49
+ self._dimensions = newValue
50
+ self.spinnerValues = SpinnerValues(value0=newValue.width, value1=newValue.height)
51
+
52
+ # noinspection PyPropertyDefinition
53
+ # noinspection PyTypeChecker
54
+ dimensions = property(fget=None, fset=_setDimensions, fdel=None, doc='Write only property to set dimensions on control')
55
+
56
+ def _notifyValueChanged(self, spinnerValues: SpinnerValues):
57
+ self.logger.info(f'{spinnerValues}')
58
+
59
+ self._dimensions.width = spinnerValues.value0
60
+ self._dimensions.height = spinnerValues.value1
61
+
62
+ if self._dimensionsChangedCallback is not None:
63
+ self._dimensionsChangedCallback(self._dimensions)
@@ -0,0 +1,141 @@
1
+
2
+ from dataclasses import dataclass
3
+ from logging import Logger
4
+ from logging import getLogger
5
+
6
+ from pathlib import Path
7
+ from typing import Callable
8
+ from typing import Optional
9
+ from typing import cast
10
+
11
+ from wx import BORDER_THEME
12
+ from wx import ID_ANY
13
+ from wx import ID_OK
14
+ from wx import DD_DEFAULT_STYLE
15
+ from wx import EVT_BUTTON
16
+ from wx import ART_BUTTON
17
+ from wx import ART_FOLDER
18
+
19
+ from wx import ArtProvider
20
+ from wx import BitmapBundle
21
+ from wx import BitmapButton
22
+ from wx import DirDialog
23
+ from wx import CommandEvent
24
+ from wx import Size
25
+ from wx import TextCtrl
26
+
27
+ from wx.lib.sized_controls import SizedPanel
28
+ from wx.lib.sized_controls import SizedStaticBox
29
+
30
+ DEFAULT_MIN_WIDTH: int = 280
31
+ DEFAULT_MAX_WIDTH: int = 600
32
+ DEFAULT_CONTROL_HEIGHT: int = 58
33
+ FOLDER_BITMAP_SIZE: Size = Size(16, 16)
34
+
35
+ DirectoryPathChangedCallback = Callable[[Path], None]
36
+ NO_PATH_CALLBACK: DirectoryPathChangedCallback = cast(DirectoryPathChangedCallback, None)
37
+
38
+
39
+ @dataclass
40
+ class DirectorySelectorParameters:
41
+ caption: str = ''
42
+ pathChangedCallback: DirectoryPathChangedCallback = NO_PATH_CALLBACK
43
+ expand: bool = True
44
+ proportion: int = 0
45
+
46
+
47
+ class DirectorySelector(SizedStaticBox):
48
+ """
49
+ A horizontal row container used for selecting and displaying a filesystem directory.
50
+
51
+ Combines a non-editable TextCtrl showing the current directory path with a
52
+ BitmapButton featuring a folder icon. Clicking the button
53
+ invokes a DirDialog allowing the user to browse for a directory.
54
+
55
+ Features:
56
+ * Responsive layout: Horizontally expands (proportion=1) to fill available
57
+ width in parent sizers, bounded by DEFAULT_MIN_WIDTH and
58
+ DEFAULT_MAX_WIDTH.
59
+ * Vertical alignment: Maintains a compact, single-line height
60
+ (DEFAULT_CONTROL_HEIGHT) with centered controls.
61
+ * Callback notification: Dispatches directory change events to an optional
62
+ callback (`pathChangedCallback`) whenever a new directory is selected.
63
+ * Two-way path binding: Provides a `directoryPath` property (getter/setter)
64
+ to read or programmatically update the selected Path.
65
+ """
66
+ DEFAULT_MIN_WIDTH: int = DEFAULT_MIN_WIDTH
67
+ DEFAULT_MAX_WIDTH: int = DEFAULT_MAX_WIDTH
68
+ DEFAULT_CONTROL_HEIGHT: int = DEFAULT_CONTROL_HEIGHT
69
+ FOLDER_BITMAP_SIZE: Size = FOLDER_BITMAP_SIZE
70
+
71
+ def __init__(
72
+ self,
73
+ parent: SizedPanel,
74
+ parameters: Optional[DirectorySelectorParameters] = None,
75
+ caption: str = '',
76
+ ):
77
+ """
78
+ Initialize the DirectorySelector static box and child controls.
79
+
80
+ Args:
81
+ parent: The parent sized panel
82
+ parameters: Configuration parameters for the directory selector
83
+ caption: Optional caption string used if parameters is not provided
84
+ """
85
+
86
+ self.logger: Logger = getLogger(__name__)
87
+
88
+ params: DirectorySelectorParameters = parameters if parameters is not None else DirectorySelectorParameters(caption=caption)
89
+
90
+ super().__init__(parent, ID_ANY, params.caption, style=BORDER_THEME)
91
+
92
+ self.SetSizerType('horizontal')
93
+ # noinspection PyUnresolvedReferences
94
+ self.SetSizerProps(expand=params.expand, proportion=params.proportion)
95
+
96
+ self._directorPathChangedCallback: DirectoryPathChangedCallback = params.pathChangedCallback
97
+
98
+ textCtrl: TextCtrl = TextCtrl(self)
99
+ textCtrl.SetSizerProps(valign='centre', proportion=1, border=(('right',), 5))
100
+
101
+ folderBitmapBundle: BitmapBundle = ArtProvider.GetBitmapBundle(ART_FOLDER, ART_BUTTON, FOLDER_BITMAP_SIZE)
102
+ selectButton: BitmapButton = BitmapButton(self, ID_ANY, folderBitmapBundle)
103
+ selectButton.SetSizerProps(valign='centre')
104
+
105
+ textCtrl.SetValue('')
106
+ textCtrl.SetEditable(False)
107
+
108
+ self._textDiagramsDirectory: TextCtrl = textCtrl
109
+ self._directoryPath: Path = Path('')
110
+
111
+ self.Bind(EVT_BUTTON, self._onSelectDiagramsDirectory, selectButton)
112
+
113
+ self.SetMinSize(Size(DEFAULT_MIN_WIDTH, DEFAULT_CONTROL_HEIGHT))
114
+ self.SetMaxSize(Size(DEFAULT_MAX_WIDTH, DEFAULT_CONTROL_HEIGHT))
115
+
116
+ def DoGetBestSize(self) -> Size:
117
+ """
118
+ Calculate the best size for this directory selector static box.
119
+ """
120
+ return Size(400, DEFAULT_CONTROL_HEIGHT)
121
+
122
+ @property
123
+ def directoryPath(self) -> Path:
124
+ return self._directoryPath
125
+
126
+ @directoryPath.setter
127
+ def directoryPath(self, value: Path):
128
+
129
+ self._directoryPath = value
130
+ self._textDiagramsDirectory.SetValue(str(value))
131
+
132
+ # noinspection PyUnusedLocal
133
+ def _onSelectDiagramsDirectory(self, _event: CommandEvent):
134
+
135
+ with DirDialog(None, 'Choose the Diagrams Directory', defaultPath=str(self._directoryPath), style=DD_DEFAULT_STYLE) as dlg:
136
+
137
+ if dlg.ShowModal() == ID_OK:
138
+ self._directoryPath = Path(dlg.GetPath())
139
+ self._textDiagramsDirectory.SetValue(str(self._directoryPath))
140
+ if self._directorPathChangedCallback is not None:
141
+ self._directorPathChangedCallback(self._directoryPath)
@@ -0,0 +1,196 @@
1
+
2
+ from typing import Any
3
+ from typing import Callable
4
+ from typing import cast
5
+ from typing import Optional
6
+
7
+ from logging import Logger
8
+ from logging import getLogger
9
+
10
+ from dataclasses import dataclass
11
+
12
+ from wx import Size
13
+ from wx import ID_ANY
14
+ from wx import EVT_TEXT
15
+ from wx import EVT_SPINCTRL
16
+ from wx import BORDER_THEME
17
+
18
+ from wx import SpinCtrl
19
+ from wx import StaticText
20
+ from wx import CommandEvent
21
+
22
+ from wx import NewIdRef as wxNewIdRef
23
+
24
+ from wx.lib.sized_controls import SizedPanel
25
+ from wx.lib.sized_controls import SizedStaticBox
26
+
27
+ SPINNER_WIDTH: int = 80
28
+ SPINNER_HEIGHT: int = -1 # In wxWidgets, passing -1 for height uses native platform control height
29
+ DEFAULT_CONTROL_HEIGHT: int = 58
30
+
31
+ ValueChangeCallback = Callable[[Any], None]
32
+ NO_VALUE_CALLBACK: ValueChangeCallback = cast(ValueChangeCallback, None)
33
+
34
+
35
+ @dataclass
36
+ class DualSpinnerParameters:
37
+ caption: str = ''
38
+ valueChangedCallback: ValueChangeCallback = NO_VALUE_CALLBACK
39
+ minValue: int = 100
40
+ maxValue: int = 300
41
+ firstSpinnerLabel: str = ''
42
+ secondSpinnerLabel: str = ''
43
+ proportion: int = 0
44
+ expand: bool = True
45
+
46
+
47
+ @dataclass
48
+ class SpinnerValues:
49
+ value0: int = 0
50
+ value1: int = 0
51
+
52
+
53
+ class DualSpinnerControl(SizedStaticBox):
54
+ """
55
+ A component that pairs two spinners in a horizontal panel; Callers set
56
+ the title to display and optionally the minimum and maximum spinner values
57
+ Ideal for subclassing to use as a way to get x,y coordinates or width, height
58
+ sizes
59
+ """
60
+
61
+ DEFAULT_MIN_VALUE: int = 100
62
+ DEFAULT_MAX_VALUE: int = 300
63
+
64
+ dscLogger: Logger = getLogger(__name__) # Used as base class; So needs unique logger
65
+
66
+ def __init__(self, parent: SizedPanel, parameters: DualSpinnerParameters):
67
+ """
68
+
69
+ Args:
70
+ parent: The parent panel
71
+ parameters: Configuration parameters for the dual spinner control
72
+ """
73
+
74
+ super().__init__(parent, ID_ANY, parameters.caption, style=BORDER_THEME)
75
+
76
+ self.SetSizerType('horizontal')
77
+ # noinspection PyUnresolvedReferences
78
+ self.SetSizerProps(expand=parameters.expand, proportion=parameters.proportion)
79
+
80
+ self._callback: ValueChangeCallback = parameters.valueChangedCallback
81
+
82
+ self._wxSpinner0Id: int = wxNewIdRef()
83
+ self._wxSpinner1Id: int = wxNewIdRef()
84
+
85
+ self._firstSpinnerLabel: Optional[StaticText] = None
86
+ self._secondSpinnerLabel: Optional[StaticText] = None
87
+
88
+ self._spinner0: SpinCtrl = cast(SpinCtrl, None)
89
+ self._spinner1: SpinCtrl = cast(SpinCtrl, None)
90
+
91
+ self._createControls(parameters)
92
+ self._bindEventHandlers()
93
+
94
+ self.SetMinSize(Size(-1, DEFAULT_CONTROL_HEIGHT))
95
+ self.SetMaxSize(Size(-1, DEFAULT_CONTROL_HEIGHT))
96
+
97
+ def _createControls(self, parameters: DualSpinnerParameters):
98
+ """
99
+ Instantiate labels, spin controls, and configure ranges and initial values
100
+
101
+ Args:
102
+ parameters: Configuration parameters for the dual spinner control
103
+ """
104
+ if len(parameters.firstSpinnerLabel) > 0:
105
+ self._firstSpinnerLabel = StaticText(self, ID_ANY, parameters.firstSpinnerLabel)
106
+ self._firstSpinnerLabel.SetSizerProps(valign='centre', border=(('right',), 5))
107
+
108
+ self._spinner0 = SpinCtrl(self, self._wxSpinner0Id, '', size=Size(SPINNER_WIDTH, SPINNER_HEIGHT))
109
+ self._spinner0.SetSizerProps(valign='centre', border=(('right',), 10))
110
+
111
+ if len(parameters.secondSpinnerLabel) > 0:
112
+ self._secondSpinnerLabel = StaticText(self, ID_ANY, parameters.secondSpinnerLabel)
113
+ self._secondSpinnerLabel.SetSizerProps(valign='centre', border=(('right',), 5))
114
+
115
+ self._spinner1 = SpinCtrl(self, self._wxSpinner1Id, '', size=Size(SPINNER_WIDTH, SPINNER_HEIGHT))
116
+ self._spinner1.SetSizerProps(valign='centre')
117
+
118
+ self._spinner0.SetRange(parameters.minValue, parameters.maxValue)
119
+ self._spinner1.SetRange(parameters.minValue, parameters.maxValue)
120
+
121
+ self._spinnerValues: SpinnerValues = SpinnerValues(parameters.minValue, parameters.maxValue)
122
+
123
+ def _bindEventHandlers(self):
124
+ """
125
+ Bind to both text and spin events for typing and arrow clicks
126
+
127
+ """
128
+ self.Bind(EVT_TEXT, self._onSpinnerValueChanged, self._spinner0)
129
+ self.Bind(EVT_TEXT, self._onSpinnerValueChanged, self._spinner1)
130
+ self.Bind(EVT_SPINCTRL, self._onSpinnerValueChanged, self._spinner0)
131
+ self.Bind(EVT_SPINCTRL, self._onSpinnerValueChanged, self._spinner1)
132
+
133
+ def DoGetBestSize(self) -> Size:
134
+ """
135
+ Calculate the best size for this static box container, keeping
136
+ a compact vertical height suitable for spinner controls.
137
+ """
138
+ sizerBest: Size = self.GetSizer().GetMinSize()
139
+ borders: tuple[int, int] = self.GetBordersForSizer()
140
+ totalWidth: int = sizerBest.width + (borders[1] * 2) + 10
141
+
142
+ return Size(totalWidth, DEFAULT_CONTROL_HEIGHT)
143
+
144
+ def _setSpinnerValues(self, spinnerValues: SpinnerValues):
145
+ """
146
+ Write only; The appropriate way to retrieve the values is via the change callback
147
+ Args:
148
+ spinnerValues:
149
+ """
150
+ self._spinnerValues = spinnerValues
151
+ self._spinner0.SetValue(spinnerValues.value0)
152
+ self._spinner1.SetValue(spinnerValues.value1)
153
+ self.dscLogger.info(f'range: {self._spinner0.GetRange()} - {self._spinner0.GetValue()=} {self._spinner1.GetValue()=}')
154
+
155
+ # noinspection PyPropertyDefinition
156
+ # noinspection PyTypeChecker
157
+ spinnerValues = property(fget=None, fset=_setSpinnerValues, fdel=None, doc='Write only property to initialize spinner values')
158
+
159
+ def enableControls(self, value: bool):
160
+ """
161
+ Enable or disable the spinner controls
162
+
163
+ Args:
164
+ value: `True` to enable, else `False`
165
+ """
166
+ if value is True:
167
+ self._spinner0.Enable()
168
+ self._spinner1.Enable()
169
+ if self._firstSpinnerLabel is not None:
170
+ self._firstSpinnerLabel.Enable()
171
+ if self._secondSpinnerLabel is not None:
172
+ self._secondSpinnerLabel.Enable()
173
+ else:
174
+ self._spinner0.Disable()
175
+ self._spinner1.Disable()
176
+ if self._firstSpinnerLabel is not None:
177
+ self._firstSpinnerLabel.Disable()
178
+ if self._secondSpinnerLabel is not None:
179
+ self._secondSpinnerLabel.Disable()
180
+
181
+ def _onSpinnerValueChanged(self, event: CommandEvent):
182
+
183
+ eventId: int = event.GetId()
184
+
185
+ if eventId == self._wxSpinner0Id:
186
+ self._spinnerValues.value0 = self._spinner0.GetValue()
187
+ elif eventId == self._wxSpinner1Id:
188
+ self._spinnerValues.value1 = self._spinner1.GetValue()
189
+ else:
190
+ self.dscLogger.error(f'Unknown spinner event id: {eventId}')
191
+
192
+ self._notifyValueChanged(self._spinnerValues)
193
+
194
+ def _notifyValueChanged(self, spinnerValues: SpinnerValues):
195
+ if self._callback is not None:
196
+ self._callback(spinnerValues)
@@ -0,0 +1,57 @@
1
+
2
+ from logging import Logger
3
+ from logging import getLogger
4
+
5
+ from dataclasses import dataclass
6
+
7
+ from wx.lib.sized_controls import SizedPanel
8
+
9
+ from codeallybasic.MinMax import MinMax
10
+
11
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import DualSpinnerControl
12
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import DualSpinnerParameters
13
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import SpinnerValues
14
+ from codeallyadvanced.ui.widgets.DualSpinnerControl import ValueChangeCallback
15
+
16
+
17
+ @dataclass
18
+ class MinMaxParameters(DualSpinnerParameters):
19
+ minValue: int = -1024
20
+ maxValue: int = 1024
21
+ firstSpinnerLabel: str = 'Min:'
22
+ secondSpinnerLabel: str = 'Max:'
23
+
24
+
25
+ class MinMaxControl(DualSpinnerControl):
26
+ """
27
+ A facade around the basic dual spinner control for MinMax values.
28
+ """
29
+ def __init__(self, parent: SizedPanel, parameters: MinMaxParameters):
30
+ """
31
+
32
+ Args:
33
+ parent: The parent window
34
+ parameters: Configuration parameters for the min/max control
35
+ """
36
+ self.logger: Logger = getLogger(__name__)
37
+ self._valuesChangedCallback: ValueChangeCallback = parameters.valueChangedCallback
38
+ self._minMax: MinMax = MinMax()
39
+
40
+ super().__init__(parent=parent, parameters=parameters)
41
+
42
+ def _setMinMax(self, newValue: MinMax):
43
+ self._minMax = newValue
44
+ self.spinnerValues = SpinnerValues(value0=newValue.minValue, value1=newValue.maxValue)
45
+
46
+ # noinspection PyPropertyDefinition
47
+ # noinspection PyTypeChecker
48
+ minMax = property(fget=None, fset=_setMinMax, fdel=None, doc='Write only property to set values')
49
+
50
+ def _notifyValueChanged(self, spinnerValues: SpinnerValues):
51
+
52
+ self.logger.info(f'{spinnerValues}')
53
+ self._minMax.minValue = spinnerValues.value0
54
+ self._minMax.maxValue = spinnerValues.value1
55
+
56
+ if self._valuesChangedCallback is not None:
57
+ self._valuesChangedCallback(self._minMax)