Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets
Commits:
5b3e213f by Vadim Zeitlin at 2025-06-10T02:44:30+02:00
Fix reference to an old Sun C++ compiler issue
This is almost surely not relevant any more, but keep this for now, just
at least make the link point to the correct issue.
- - - - -
622c2c70 by Vadim Zeitlin at 2025-06-10T02:51:20+02:00
Use ar and ranlib in deterministic mode for reproducible builds
Enable deterministic mode for binutils tools when --enable-repro-build
is used to ensure that static libraries don't contain current timestamp.
Closes #25502.
- - - - -
ebd7c646 by Vadim Zeitlin at 2025-06-12T22:38:29+02:00
Avoid repainting wxNotebook when it is being destroyed
This is unnecessary and may result in a crash if a WM_PAINT event comes
after wxNotebook itself has been already destroyed (e.g. from the base
class dtor when it destroys the notebook children which triggers
invalidating the parent) because our OnPaint() depends on the object
being in a well-defined state.
Closes #25499.
- - - - -
3e32a9ab by Vadim Zeitlin at 2025-06-12T22:40:28+02:00
Don't bother resetting wxStaticBitmap image when destroying it
This results in sending a WM_PAINT to the control parent which may be
rather unexpected if it happens while it is itself being destroyed, see
the fix for #25499 in the parent commit, so don't do it when Free() is
called from dtor.
And it is also unnecessary to do it when Free() is called from
DoUpdateImage(), as it calls MSWReplaceImageHandle() with another,
valid, handle right next anyhow.
- - - - -
84c88756 by Vadim Zeitlin at 2025-06-13T16:08:57+02:00
Reset wxStaticBitmap::m_currentHandle to 0 too for consistency
It doesn't really matter, but it seems tidier to reset it to 0 instead
of keeping (even unused) handle to a destroyed object.
- - - - -
60eb8d06 by Vadim Zeitlin at 2025-06-13T18:14:34+02:00
Operate on both controls in "Hyperlink" page of widgets sample
This ensures that operations such as disabling the control affect both
hyperlink controls on this page.
- - - - -
0637670e by Vadim Zeitlin at 2025-06-14T21:51:17+02:00
Drop support for using generic wxHyperlinkCtrl in wxMSW
We require the use of comctl32.dll v6 now, so we can always use the
native version, remove the code falling back to the generic one.
Note that wxHyperlinkCtrl still inherits from wxGenericHyperlinkCtrl
because it uses many of its member variables and its support for popup
menu, which is not available in the native control.
- - - - -
401fd3aa by Vadim Zeitlin at 2025-06-14T21:59:50+02:00
Fix wxHyperlinkCtrl::GetLabel() in wxMSW native version
We wrongly returned the full HTML fragment used by the native control as
the label instead of returning just the actual label part after creating
the control.
This fixes the problem which could be easily seen by switching from the
native to the generic control in the widgets sample: the label changed
to HTML markup instead of staying the same.
- - - - -
0f5d251b by Vadim Zeitlin at 2025-06-14T22:05:34+02:00
Use foreground window colour as link colour in wxMSW
Make wxHyperlinkCtrl behaviour in wxMSW the same as in the generic
version and change the (normal) link colour if the foregound window
colour is changed.
Note that the control still doesn't inherit the default foreground
colour from its parent and keeps using the default link colour by
default. But it changes it if SetForegroundColour() is explicitly
called.
- - - - -
2151ac97 by Vadim Zeitlin at 2025-06-14T22:16:59+02:00
Grey out wxHyperlinkCtrl in wxMSW when it is disabled
It doesn't seem right to keep showing the link in its normal colour when
it is disabled and doesn't react to mouse events, so grey it out.
- - - - -
e934d811 by Vadim Zeitlin at 2025-06-14T22:18:51+02:00
Grey out wxGenericHyperlinkCtrl when it is disabled too
This makes the behaviour consistent across all 3 (native MSW, native GTK
and this one) wxHyperlinkCtrl implementations.
- - - - -
8713b52a by Vadim Zeitlin at 2025-06-14T23:36:20+02:00
Add support for wxGenericHyperlinkCtrl to XRC too
Allow to create the generic version of wxHyperlinkCtrl in addition to
the native one.
- - - - -
44765dd4 by Vadim Zeitlin at 2025-06-15T02:26:30+02:00
Fix wxRendererNative::GetCollapseButtonSize() documentation
Use the correct type for the DC parameter which was changed to
wxReadOnlyDC.
Closes #25516.
- - - - -
146b9f32 by Vadim Zeitlin at 2025-06-15T02:39:45+02:00
Fix wxNotebook::GetThemeBackgroundColour() for dark mode in wxMSW
Return the actual background colour instead of returning the colour used
by the system which is irrelevant, as we draw the notebook ourselves in
dark mode.
Closes #25527.
- - - - -
53eb2420 by Blake-Madden at 2025-06-16T19:13:19+02:00
Document wxPoint2DDouble and wxOutCode
Closes #25520.
- - - - -
2f91f82f by Blake-Madden at 2025-06-16T19:14:13+02:00
Fix a couple of misspellings in comments in ZIP streams code
Closes #25524.
- - - - -
21938d61 by Vadim Zeitlin at 2025-06-16T19:18:11+02:00
Merge branch 'repro-ar'
Use ar and ranlib in deterministic mode for reproducible builds.
See #25508.
- - - - -
7d0023df by Alexander Koshelev at 2025-06-16T19:19:10+02:00
Add persistence support for wxCheckBox
Allow to easily save and restore wxCheckBox state too.
Closes #25515.
Co-authored-by: Vadim Zeitlin <
va...@wxwidgets.org>
- - - - -
cae57d46 by Vadim Zeitlin at 2025-06-16T19:20:23+02:00
Merge branch 'msw-avoid-repaint-in-dtor'
Avoid repainting when windows are being destroyed in wxMSW.
See #25518.
- - - - -
0eaf0980 by Vadim Zeitlin at 2025-06-16T19:21:15+02:00
Merge branch 'hyperlink-improvements'
wxHyperlinkCtrl improvements.
See #25528.
- - - - -
18da5b82 by Vadim Zeitlin at 2025-06-16T19:21:42+02:00
Add persistence support for groups of wxRadioButton controls
Allow to easily save and restore the selected radio button.
Closes #25530.
- - - - -
26 changed files:
- Makefile.in
- build/aclocal/bakefile.m4
- build/bakefiles/files.bkl
- build/cmake/files.cmake
- build/files
- build/msw/wx_core.vcxproj
- build/msw/wx_core.vcxproj.filters
- configure
-
configure.ac
- docs/doxygen/overviews/xrc_format.h
- include/wx/msw/hyperlink.h
- + include/wx/persist/checkbox.h
- + include/wx/persist/radiobut.h
- interface/wx/geometry.h
- + interface/wx/persist/checkbox.h
- + interface/wx/persist/radiobut.h
- interface/wx/renderer.h
- misc/schema/xrc_schema.rnc
- samples/widgets/hyperlnk.cpp
- src/common/zipstrm.cpp
- src/generic/hyperlinkg.cpp
- src/msw/hyperlink.cpp
- src/msw/notebook.cpp
- src/msw/statbmp.cpp
- src/xrc/xh_hyperlink.cpp
- tests/allheaders.h
Changes:
=====================================
Makefile.in
=====================================
@@ -3955,6 +3955,7 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \
wx/persist.h \
wx/persist/bookctrl.h \
wx/persist/dataview.h \
+ wx/persist/radiobut.h \
wx/persist/splitter.h \
wx/persist/toplevel.h \
wx/persist/treebook.h \
@@ -4059,6 +4060,7 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \
wx/power.h \
wx/imagwebp.h \
wx/webpdecoder.h \
+ wx/persist/checkbox.h \
$(LOWLEVEL_HDR) \
$(GUI_CORE_HEADERS) \
wx/mediactrl.h \
=====================================
build/aclocal/bakefile.m4
=====================================
@@ -519,7 +519,7 @@ AC_DEFUN([AC_BAKEFILE_CHECK_BASIC_STUFF],
if test "x$SUNCXX" = "xyes"; then
dnl Sun C++ compiler requires special way of creating static libs;
dnl see here for more details:
- dnl
https://github.com/wxWidgets/wxWidgets/issues/2639
+ dnl
https://github.com/wxWidgets/wxWidgets/issues/22004
AR=$CXX
AROPTIONS="-xar -o"
AC_SUBST(AR)
=====================================
build/bakefiles/files.bkl
=====================================
@@ -1229,6 +1229,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/persist.h
wx/persist/bookctrl.h
wx/persist/dataview.h
+ wx/persist/radiobut.h
wx/persist/splitter.h
wx/persist/toplevel.h
wx/persist/treebook.h
@@ -1333,6 +1334,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/power.h
wx/imagwebp.h
wx/webpdecoder.h
+ wx/persist/checkbox.h
</set>
<!-- ====================================================================== -->
=====================================
build/cmake/files.cmake
=====================================
@@ -1130,6 +1130,7 @@ set(GUI_CMN_HDR
wx/persist.h
wx/persist/bookctrl.h
wx/persist/dataview.h
+ wx/persist/radiobut.h
wx/persist/splitter.h
wx/persist/toplevel.h
wx/persist/treebook.h
@@ -1229,6 +1230,7 @@ set(GUI_CMN_HDR
wx/power.h
wx/webpdecoder.h
wx/imagwebp.h
+ wx/persist/checkbox.h
)
set(UNIX_SRC
=====================================
build/files
=====================================
@@ -1155,8 +1155,10 @@ GUI_CMN_HDR =
wx/peninfobase.h
wx/persist.h
wx/persist/bookctrl.h
+ wx/persist/checkbox.h
wx/persist/combobox.h
wx/persist/dataview.h
+ wx/persist/radiobut.h
wx/persist/splitter.h
wx/persist/toplevel.h
wx/persist/treebook.h
=====================================
build/msw/wx_core.vcxproj
=====================================
@@ -2049,6 +2049,7 @@
<ClInclude Include="..\..\include\wx\progdlg.h" />
<ClInclude Include="..\..\include\wx\quantize.h" />
<ClInclude Include="..\..\include\wx\radiobox.h" />
+ <ClInclude Include="..\..\include\wx\persist\radiobut.h" />
<ClInclude Include="..\..\include\wx\radiobut.h" />
<ClInclude Include="..\..\include\wx\range.h" />
<ClInclude Include="..\..\include\wx\rawbmp.h" />
@@ -2194,6 +2195,7 @@
<ClInclude Include="..\..\include\wx\webpdecoder.h" />
<ClInclude Include="..\..\include\wx\imagwebp.h" />
<ClInclude Include="..\..\include\wx\msw\mfc.h" />
+ <ClInclude Include="..\..\include\wx\persist\checkbox.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
=====================================
build/msw/wx_core.vcxproj.filters
=====================================
@@ -2077,12 +2077,18 @@
<ClInclude Include="..\..\include\wx\persist\bookctrl.h">
<Filter>Common Headers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\wx\persist\checkbox.h">
+ <Filter>Common Headers</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\wx\persist\combobox.h">
<Filter>Common Headers</Filter>
</ClInclude>
<ClInclude Include="..\..\include\wx\persist\dataview.h">
<Filter>Common Headers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\wx\persist\radiobut.h">
+ <Filter>Common Headers</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\wx\persist\splitter.h">
<Filter>Common Headers</Filter>
</ClInclude>
=====================================
configure
=====================================
@@ -35643,11 +35643,6 @@ else
fi
fi
-if test "x$wxUSE_REPRODUCIBLE_BUILD" = "xyes"; then
- $as_echo "#define wxUSE_REPRODUCIBLE_BUILD 1" >>confdefs.h
-
-fi
-
if test "x$WXWIN_COMPATIBILITY_3_0" = "xyes"; then
$as_echo "#define WXWIN_COMPATIBILITY_3_0 1" >>confdefs.h
@@ -43650,6 +43645,13 @@ EOF
fi
+if test "x$wxUSE_REPRODUCIBLE_BUILD" = "xyes"; then
+ $as_echo "#define wxUSE_REPRODUCIBLE_BUILD 1" >>confdefs.h
+
+ AROPTIONS="rcD"
+ RANLIB="$RANLIB -D"
+fi
+
case ${INSTALL} in
/* ) # Absolute
;;
=====================================
configure.ac
=====================================
@@ -4911,10 +4911,6 @@ else
fi
fi
-if test "x$wxUSE_REPRODUCIBLE_BUILD" = "xyes"; then
- AC_DEFINE(wxUSE_REPRODUCIBLE_BUILD)
-fi
-
dnl ---------------------------------------------------------------------------
dnl compatibility level
dnl ---------------------------------------------------------------------------
@@ -8017,6 +8013,16 @@ fi
AC_BAKEFILE([m4_include(autoconf_inc.m4)])
+dnl Override some options set by AC_BAKEFILE() above.
+if test "x$wxUSE_REPRODUCIBLE_BUILD" = "xyes"; then
+ AC_DEFINE(wxUSE_REPRODUCIBLE_BUILD)
+ dnl We consider that when --enable-repro-build is used, ar and ranlib
+ dnl support deterministic mode (if they don't, we wouldn't be able to
+ dnl honour this option anyhow).
+ AROPTIONS="rcD"
+ RANLIB="$RANLIB -D"
+fi
+
dnl make install path absolute (if not already);
dnl will fail with (some) MSDOS paths
case ${INSTALL} in
=====================================
docs/doxygen/overviews/xrc_format.h
=====================================
@@ -1378,6 +1378,14 @@ page.
@endTable
+@subsubsection xrc_wxgenerichyperlinkctrl wxGenericHyperlinkCtrl
+
+This handler is identical to the one for @ref xrc_wxhyperlinkctrl
+"wxHyperlinkCtrl", please see it for more information. The only difference is
+that, for the platforms with a native wxHyperlinkCtrl implementation, using
+this handler creates a generic control rather than a native one.
+
+
@subsubsection xrc_wxinfobar wxInfoBar
@beginTable
=====================================
include/wx/msw/hyperlink.h
=====================================
@@ -63,6 +63,9 @@ public:
virtual void SetVisitedColour(const wxColour &colour) override;
// overridden/inherited wxWindow methods
+ virtual bool Enable(bool enable = true) override;
+ virtual bool SetForegroundColour(const wxColour& colour) override;
+
virtual wxVisualAttributes GetDefaultAttributes() const override;
static wxVisualAttributes
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
@@ -77,6 +80,10 @@ private:
bool MSWAreCustomColoursEnabled() const;
void MSWEnableCustomColours();
+ // This is set to the previously used colour when the control is disabled,
+ // to be able to restore it later when the control is enabled again.
+ wxColour m_savedEnabledColour;
+
wxDECLARE_DYNAMIC_CLASS( wxHyperlinkCtrl );
};
=====================================
include/wx/persist/checkbox.h
=====================================
@@ -0,0 +1,89 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/persist/checkbox.h
+// Purpose: Persistence support for wxCheckBox.
+// Author: Alexander Koshelev, Vadim Zeitlin
+// Created: 2025-06-11
+// Copyright: (c) 2025 wxWidgets team
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PERSIST_CHECKBOX_H_
+#define _WX_PERSIST_CHECKBOX_H_
+
+#include "wx/persist/window.h"
+
+#include "wx/checkbox.h"
+
+// ----------------------------------------------------------------------------
+// string constants used by wxPersistentCheckBox
+// ----------------------------------------------------------------------------
+
+#define wxPERSIST_CHECKBOX_KIND wxASCII_STR("Checkbox")
+
+#define wxPERSIST_CHECKBOX_VALUE wxASCII_STR("Value")
+
+// ----------------------------------------------------------------------------
+// wxPersistentCheckBox: supports saving/restoring checkbox state
+// ----------------------------------------------------------------------------
+
+// Implementation note: we depend on the values of wxCheckBoxState enum not
+// changing, as we save them directly as numbers, but this seems a safe bet as
+// it's hard to imagine adding any more values to it.
+
+class wxPersistentCheckBox : public wxPersistentWindow<wxCheckBox>
+{
+public:
+ explicit wxPersistentCheckBox(wxCheckBox* checkbox)
+ : wxPersistentWindow<wxCheckBox>(checkbox)
+ {
+ }
+
+ virtual void Save() const override
+ {
+ const wxCheckBox* const checkbox = Get();
+ const auto value = checkbox->Get3StateValue();
+ SaveValue(wxPERSIST_CHECKBOX_VALUE, static_cast<int>(value));
+ }
+
+ virtual bool Restore() override
+ {
+ int value;
+ if ( !RestoreValue(wxPERSIST_CHECKBOX_VALUE, &value) )
+ return false;
+
+ switch ( value )
+ {
+ case wxCHK_UNCHECKED:
+ case wxCHK_CHECKED:
+ // These values are always valid.
+ break;
+
+ case wxCHK_UNDETERMINED:
+ if ( Get()->Is3State() )
+ {
+ // This value is valid for this checkbox.
+ break;
+ }
+
+ wxFALLTHROUGH;
+
+ default:
+ // Silently ignore invalid values, as it's not really clear
+ // what else can we do about them.
+ return false;
+ }
+
+ Get()->Set3StateValue(static_cast<wxCheckBoxState>(value));
+
+ return true;
+ }
+
+ virtual wxString GetKind() const override { return wxPERSIST_CHECKBOX_KIND; }
+};
+
+inline wxPersistentObject *wxCreatePersistentObject(wxCheckBox* checkbox)
+{
+ return new wxPersistentCheckBox(checkbox);
+}
+
+#endif // _WX_PERSIST_CHECKBOX_H_
=====================================
include/wx/persist/radiobut.h
=====================================
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/persist/radiobut.h
+// Purpose: Persistence support for wxRadioButton.
+// Author: Vadim Zeitlin
+// Created: 2025-06-12
+// Copyright: (c) 2025 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PERSIST_RADIOBUT_H_
+#define _WX_PERSIST_RADIOBUT_H_
+
+#include "wx/persist/window.h"
+
+#include "wx/radiobut.h"
+
+#if wxUSE_RADIOBTN
+
+// ----------------------------------------------------------------------------
+// string constants used by wxPersistentRadioButton
+// ----------------------------------------------------------------------------
+
+#define wxPERSIST_RADIOBUTTON_KIND wxASCII_STR("RadioButton")
+
+#define wxPERSIST_RADIOBUTTON_VALUE wxASCII_STR("Value")
+
+// ----------------------------------------------------------------------------
+// wxPersistentRadioButton: supports saving/restoring radio buttons state
+// ----------------------------------------------------------------------------
+
+// This class should be always used with the first button in a group of radio
+// buttons and it saves its state as an integer indicating the offset of the
+// selected radio button in this group.
+//
+// Currently radio buttons with wxRB_SINGLE style are not supported. While it
+// wouldn't be very difficult to add support for them if anybody really needs
+// it, it seems relatively unlikely, so for now we don't bother to do it.
+
+class wxPersistentRadioButton : public wxPersistentWindow<wxRadioButton>
+{
+public:
+ explicit wxPersistentRadioButton(wxRadioButton* radiobutton)
+ : wxPersistentWindow<wxRadioButton>(radiobutton)
+ {
+ wxASSERT_MSG( !radiobutton->HasFlag(wxRB_SINGLE),
+ "wxPersistentRadioButton doesn't support wxRB_SINGLE" );
+
+ wxASSERT_MSG( radiobutton->HasFlag(wxRB_GROUP),
+ "wxPersistentRadioButton should be used with the first "
+ "radio button in a group" );
+ }
+
+ virtual void Save() const override
+ {
+ const wxRadioButton* button = Get();
+ for ( int n = 0;; ++n )
+ {
+ if ( button->GetValue() )
+ {
+ // We found the selected button, save its index.
+ SaveValue(wxPERSIST_RADIOBUTTON_VALUE, n);
+ break;
+ }
+
+ button = button->GetNextInGroup();
+ if ( !button )
+ {
+ wxFAIL_MSG("Didn't find a selected radio button in the group?");
+ break;
+ }
+ }
+ }
+
+ virtual bool Restore() override
+ {
+ int value;
+ if ( !RestoreValue(wxPERSIST_RADIOBUTTON_VALUE, &value) )
+ return false;
+
+ wxRadioButton* button = Get();
+ for ( int n = 0;; ++n )
+ {
+ if ( n == value )
+ {
+ // We found the button with the saved index, set its value.
+ button->SetValue(true);
+ break;
+ }
+
+ button = button->GetNextInGroup();
+
+ if ( !button )
+ {
+ // The saved value is invalid, silently ignore it because there
+ // doesn't seem to be much else that we can do in this case.
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ virtual wxString GetKind() const override { return wxPERSIST_RADIOBUTTON_KIND; }
+};
+
+inline wxPersistentObject *wxCreatePersistentObject(wxRadioButton* radiobutton)
+{
+ return new wxPersistentRadioButton(radiobutton);
+}
+
+#endif // wxUSE_RADIOBTN
+
+#endif // _WX_PERSIST_RADIOBUT_H_
=====================================
interface/wx/geometry.h
=====================================
@@ -6,16 +6,23 @@
/////////////////////////////////////////////////////////////////////////////
+/**
+ Represents where a point is in relation to a rectangle.
+ */
enum wxOutCode
{
+ /// The point is inside the rectangle.
wxInside = 0x00 ,
+ /// The point is outside of the rectangle, to its left.
wxOutLeft = 0x01 ,
+ /// The point is outside of the rectangle, to its right.
wxOutRight = 0x02 ,
+ /// The point is outside of the rectangle, above it.
wxOutTop = 0x08 ,
+ /// The point is outside of the rectangle, below it.
wxOutBottom = 0x04
};
-
class wxPoint2DInt
{
public :
@@ -69,36 +76,119 @@ wxPoint2DInt operator/(const wxPoint2DInt& pt , wxInt32 n);
/**
- wxPoint2Ds represent a point or a vector in a 2D coordinate system.
+ wxPoint2DDouble represents a point in a 2D (Cartesian) coordinate system,
+ with additional vector operations available.
*/
class wxPoint2DDouble
{
public :
+ /**
+ Initializes to zero the x and y members.
+ */
wxPoint2DDouble();
+ /**
+ Initializes the point with the given coordinates.
+ */
wxPoint2DDouble( wxDouble x , wxDouble y );
+ /**
+ Initializes the point from another point.
+ */
wxPoint2DDouble( const wxPoint2DDouble &pt );
+ /**
+ Initializes the point from another point.
+ */
wxPoint2DDouble( const wxPoint2DInt &pt );
+ /**
+ Initializes the point from another point.
+ */
wxPoint2DDouble( const wxPoint &pt );
- // two different conversions to integers, floor and rounding
- void GetFloor( wxInt32 *x , wxInt32 *y ) const;
- void GetRounded( wxInt32 *x , wxInt32 *y ) const;
+ /**
+ Returns the floored value of the point's coordinates.
+
+ @param[out] x The value to write the floored X coordinate to.
+ @param[out] y The value to write the floored Y coordinate to.
+ */
+ void GetFloor(wxInt32* x, wxInt32* y) const;
+ /**
+ @overload
+ */
wxPoint GetFloor() const;
+ /**
+ Returns the rounded value of the point's coordinates.
+
+ @param[out] x The value to write the rounded X coordinate to.
+ @param[out] y The value to write the rounded Y coordinate to.
+ */
+ void GetRounded(wxInt32* x, wxInt32* y) const;
+ /**
+ @overload
+ */
wxPoint GetRounded() const;
+ /**
+ Returns the hypotenuse, where the X and Y coordinates of the point
+ represent the lengths of the base and height sides of a right triangle.
+ */
wxDouble GetVectorLength() const;
- wxDouble GetVectorAngle() const ;
- void SetVectorLength( wxDouble length );
+ /**
+ Sets the vector length to @c length, preserving the right angle and altering
+ the X and Y values (which represent the base and height sides
+ of a right triangle).
+ */
+ void SetVectorLength(wxDouble length);
+
+ /**
+ Returns the principal value of the arc tangent of the Y and X values,
+ expressed in degrees.
+ */
+ wxDouble GetVectorAngle() const ;
+
+ /**
+ Repositions the X and Y coordinates based on the provided angle's degrees.
+ */
void SetVectorAngle( wxDouble degrees );
- // set the vector length to 1.0, preserving the angle
+
+ /**
+ Sets the vector length to 1.0, preserving the right angle and altering
+ the X and Y values (which represent the base and height sides
+ of a right triangle).
+ */
void Normalize();
+ /**
+ Returns the distance between this point and @c pt.
+ */
wxDouble GetDistance( const wxPoint2DDouble &pt ) const;
+ /**
+ Returns the squared distance between this point and @c pt.
+ */
wxDouble GetDistanceSquare( const wxPoint2DDouble &pt ) const;
+
+ /**
+ Returns the dot (i.e., scalar) product, where the products of the
+ X and Y values of this point and @c are added.
+ */
wxDouble GetDotProduct( const wxPoint2DDouble &vec ) const;
+ /**
+ Returns the cross product, where the products of the Y
+ values of this point and @c are subtracted from the X products.
+ This represents another vector that is at right angles to both points.
+ */
wxDouble GetCrossProduct( const wxPoint2DDouble &vec ) const;
- // the reflection of this point
+ /**
+ @name Miscellaneous operators
+
+ Note that binary operators are defined as friend functions inside this
+ class, making them accessible via argument-dependent lookup, but hidden
+ otherwise.
+ */
+ ///@{
+ /**
+ Returns the reflection (i.e., negation) of this point.
+ For example, (2, 4) on a Cartesian coordinate system will become (-2, -4).
+ */
wxPoint2DDouble operator-() const;
wxPoint2DDouble& operator=(const wxPoint2DDouble& pt);
@@ -112,21 +202,26 @@ public :
bool operator==(const wxPoint2DDouble& pt) const;
bool operator!=(const wxPoint2DDouble& pt) const;
+ friend wxPoint2DDouble operator+(const wxPoint2DDouble& pt1, const wxPoint2DDouble& pt2);
+ friend wxPoint2DDouble operator-(const wxPoint2DDouble& pt1, const wxPoint2DDouble& pt2);
+ friend wxPoint2DDouble operator*(wxDouble n, const wxPoint2DDouble& pt);
+ friend wxPoint2DDouble operator*(wxInt32 n, const wxPoint2DDouble& pt);
+ friend wxPoint2DDouble operator*(const wxPoint2DDouble& pt, wxDouble n);
+ friend wxPoint2DDouble operator*(const wxPoint2DDouble& pt, wxInt32 n);
+ friend wxPoint2DDouble operator/(const wxPoint2DDouble& pt, wxDouble n);
+ friend wxPoint2DDouble operator/(const wxPoint2DDouble& pt, wxInt32 n);
+ ///@}
+
+ /**
+ X coordinate of this point.
+ */
wxDouble m_x;
+ /**
+ Y coordinate of this point.
+ */
wxDouble m_y;
};
-wxPoint2DDouble operator+(const wxPoint2DDouble& pt1 , const wxPoint2DDouble& pt2);
-wxPoint2DDouble operator-(const wxPoint2DDouble& pt1 , const wxPoint2DDouble& pt2);
-wxPoint2DDouble operator*(wxDouble n , const wxPoint2DDouble& pt);
-wxPoint2DDouble operator*(wxInt32 n , const wxPoint2DDouble& pt);
-wxPoint2DDouble operator*(const wxPoint2DDouble& pt , wxDouble n);
-wxPoint2DDouble operator*(const wxPoint2DDouble& pt , wxInt32 n);
-wxPoint2DDouble operator/(const wxPoint2DDouble& pt , wxDouble n);
-wxPoint2DDouble operator/(const wxPoint2DDouble& pt , wxInt32 n);
-
-
-
/**
wxRect2DDouble is an axis-aligned rectangle;
each side of the rect is parallel to the X or Y axis.
=====================================
interface/wx/persist/checkbox.h
=====================================
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/persist/checkbox.h
+// Purpose: Interface of wxPersistentCheckBox
+// Author: Vadim Zeitlin
+// Created: 2025-06-15
+// Copyright: (c) 2025 Vadim Zeitlin <
va...@wxwidgets.org>
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ Persistence adapter for wxCheckBox controls.
+
+ This adapter saves and restores the state of a wxCheckBox control,
+
+ Example of using it:
+ @code
+ auto* checkbox = new wxCheckBox(this, wxID_ANY, "&Remember me");
+
+ wxPersistentRegisterAndRestore(checkbox);
+ @endcode
+
+ If the checkbox is checked, it will be checked again after the application
+ restart.
+
+ @since 3.3.0
+ */
+class wxPersistentCheckBox : public wxPersistentWindow<wxCheckBox>
+{
+public:
+ /**
+ Constructor.
+
+ Note that 3-state checkboxes are also supported.
+
+ @param checkbox
+ The associated checkbox.
+ */
+ explicit wxPersistentCheckBox(wxCheckBox *checkbox);
+
+ /**
+ Save the current checkbox state.
+
+ The state is saved as an integer value corresponding to the numeric
+ value returned by wxCheckBox::Get3StateValue(). For unchecked and
+ checked checkboxes this value is 0 and 1 respectively, as is customary.
+ */
+ virtual void Save() const;
+
+ /**
+ Restore the previously saved checkbox state.
+
+ If the saved index is valid, i.e. is ::wxCHK_UNCHECKED, ::wxCHK_CHECKED
+ or ::wxCHK_UNDETERMINED if checkbox supports 3rd state, the checkbox
+ state is set to the previously saved value (otherwise it is ignored).
+ */
+ virtual bool Restore();
+};
+
+/// Overload allowing persistence adapter creation for wxCheckBox objects.
+wxPersistentObject *wxCreatePersistentObject(wxCheckBox *checkbox);
=====================================
interface/wx/persist/radiobut.h
=====================================
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/persist/radiobutton.h
+// Purpose: Interface of wxPersistentRadioButton
+// Author: Vadim Zeitlin
+// Created: 2025-06-15
+// Copyright: (c) 2025 Vadim Zeitlin <
va...@wxwidgets.org>
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ Persistence adapter for wxRadioButton controls.
+
+ This adapter saves and restores the index of the selected wxRadioButton in
+ a group of radio buttons, to allow to retain the selection across program
+ executions.
+
+ Example of using it:
+ @code
+ // Assume that all these controls are added to some sizer elsewhere.
+ auto* label = new wxStaticText(this, wxID_ANY, "Play with:");
+
+ auto* black = new wxRadioButton(this, wxID_ANY, "&Black",
+ wxDefaultPosition,
+ wxDefaultSize,
+ wxRB_GROUP);
+ auto* white = new wxRadioButton(this, wxID_ANY, "&White");
+
+ // We register the first radio button here, but all radio buttons in the
+ // same group are potentially affected by this call.
+ wxPersistentRegisterAndRestore(black);
+ @endcode
+
+ During the first program execution, black colour will be selected, but if
+ the user selects white pieces, this selection will be restored during the
+ subsequent run.
+
+ @since 3.3.0
+ */
+class wxPersistentRadioButton : public wxPersistentWindow<wxRadioButton>
+{
+public:
+ /**
+ Constructor.
+
+ Please note that the radio button must be the first one in the group,
+ i.e. have ::wxRB_GROUP style set, otherwise an assertion will be
+ triggered.
+
+ Also note that currently ::wxRB_SINGLE style is not supported.
+
+ @param radiobutton
+ The associated radiobutton.
+ */
+ explicit wxPersistentRadioButton(wxRadioButton *radiobutton);
+
+ /**
+ Save the currently selected button index.
+
+ The 0-based index of the selected radio button in the group is saved as
+ radio button value.
+ */
+ virtual void Save() const;
+
+ /**
+ Restore the previously saved selection.
+
+ If the saved index is valid, i.e. is positive and less than the number
+ of radio buttons in the group, the radio button with the corresponding
+ index will be selected.
+ */
+ virtual bool Restore();
+};
+
+/// Overload allowing persistence adapter creation for wxRadioButton objects.
+wxPersistentObject *wxCreatePersistentObject(wxRadioButton *radiobutton);
=====================================
interface/wx/renderer.h
=====================================
@@ -469,9 +469,12 @@ public:
/**
Returns the size of a collapse button.
+ @a dc parameter was of type wxDC until wxWidgets 3.3.0, which changed
+ it to wxReadOnlyDC as this function doesn't modify the DC contents.
+
@since 3.1.0
*/
- virtual wxSize GetCollapseButtonSize(wxWindow *win, wxDC& dc) = 0;
+ virtual wxSize GetCollapseButtonSize(wxWindow *win, wxReadOnlyDC& dc) = 0;
/**
Draw the border for sash window: this border must be such that the sash
=====================================
misc/schema/xrc_schema.rnc
=====================================
@@ -191,6 +191,7 @@ builtinWindowClasses =
| wxGauge
| wxGenericAnimationCtrl
| wxGenericDirCtrl
+ | wxGenericHyperlinkCtrl
| wxGrid
| wxHtmlWindow
| wxHyperlinkCtrl
@@ -297,6 +298,7 @@ builtinClassesNames =
| "wxGauge"
| "wxGenericAnimationCtrl"
| "wxGenericDirCtrl"
+ | "wxGenericHyperlinkCtrl"
| "wxGrid"
| "wxHtmlWindow"
| "wxHyperlinkCtrl"
@@ -1043,6 +1045,14 @@ wxGenericDirCtrl =
[xrc:p="o"] element defaultfilter {_, t_integer }*
}
+wxGenericHyperlinkCtrl =
+ element object {
+ attribute class { "wxGenericHyperlinkCtrl" } &
+ stdObjectNodeAttributes &
+ stdWindowProperties &
+ [xrc:p="important"] element label {_, t_text }* &
+ [xrc:p="important"] element url {_, t_url }*
+ }
wxGrid =
element object {
=====================================
samples/widgets/hyperlnk.cpp
=====================================
@@ -77,6 +77,13 @@ public:
virtual ~HyperlinkWidgetsPage() {}
virtual wxWindow *GetWidget() const override { return m_hyperlink; }
+ virtual Widgets GetWidgets() const override
+ {
+ Widgets widgets(WidgetsPage::GetWidgets());
+ widgets.push_back(m_hyperlinkLong);
+ return widgets;
+ }
+
virtual void RecreateWidget() override { CreateHyperlink(); }
// lazy creation of the content
=====================================
src/common/zipstrm.cpp
=====================================
@@ -346,9 +346,9 @@ size_t wxStoredOutputStream::OnSysWrite(const void *buffer, size_t size)
/////////////////////////////////////////////////////////////////////////////
// wxRawInputStream
//
-// Used to handle the unusal case of raw copying an entry of unknown
+// Used to handle the unusual case of raw copying an entry of unknown
// length. This can only happen when the zip being copied from is being
-// read from a non-seekable stream, and also was original written to a
+// read from a non-seekable stream, and also was originally written to a
// non-seekable stream.
//
// In this case there's no option but to decompress the stream to find
@@ -364,7 +364,7 @@ size_t wxStoredOutputStream::OnSysWrite(const void *buffer, size_t size)
// allows the data read to be read a second time via an extra method 'GetData'.
//
// The wxRawInputStream then draws data through the tee using a decompressor
-// then instead of returning the decompressed data, retuns the raw data
+// then instead of returning the decompressed data, returns the raw data
// from wxTeeInputStream::GetData().
class wxTeeInputStream : public wxFilterInputStream
=====================================
src/generic/hyperlinkg.cpp
=====================================
@@ -200,6 +200,12 @@ void wxGenericHyperlinkCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
+ if ( !IsThisEnabled() )
+ {
+ // Grey out the control when it is disabled.
+ dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
+ }
+
dc.DrawText(GetLabel(), GetLabelRect().GetTopLeft());
if (HasFocus())
{
=====================================
src/msw/hyperlink.cpp
=====================================
@@ -51,14 +51,6 @@
namespace
{
- bool HasNativeHyperlinkCtrl()
- {
- // Notice that we really must test comctl32.dll version and not the OS
- // version here as even under Vista/7 we could be not using the v6 e.g.
- // if the program doesn't have the correct manifest for some reason.
- return wxApp::GetComCtl32Version() >= 600;
- }
-
wxString GetLabelForSysLink(const wxString& text, const wxString& url)
{
// Any "&"s in the text should appear on the screen and not be (mis)
@@ -84,12 +76,6 @@ bool wxHyperlinkCtrl::Create(wxWindow *parent,
long style,
const wxString& name)
{
- if ( !HasNativeHyperlinkCtrl() )
- {
- return wxGenericHyperlinkCtrl::Create( parent, id, label, url, pos,
- size, style, name );
- }
-
if ( !CreateControl(parent, id, pos, size, style,
wxDefaultValidator, name) )
{
@@ -110,6 +96,10 @@ bool wxHyperlinkCtrl::Create(wxWindow *parent,
return false;
}
+ // Make sure our GetLabel() returns the label that was specified and not
+ // the HTML fragment used as the label by the native control.
+ m_labelOrig = label;
+
if ( wxSystemSettings::GetAppearance().IsDark() )
{
// Override the colour used by default by the native control with the
@@ -147,31 +137,40 @@ WXDWORD wxHyperlinkCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
void wxHyperlinkCtrl::SetURL(const wxString &url)
{
- if ( !HasNativeHyperlinkCtrl() )
- {
- wxGenericHyperlinkCtrl::SetURL( url );
- return;
- }
-
if ( GetURL() != url )
SetVisited( false );
wxGenericHyperlinkCtrl::SetURL( url );
- wxWindow::SetLabel( GetLabelForSysLink(m_labelOrig, url) );
+ SetLabel(m_labelOrig);
}
void wxHyperlinkCtrl::SetLabel(const wxString &label)
{
- if ( !HasNativeHyperlinkCtrl() )
- {
- wxGenericHyperlinkCtrl::SetLabel( label );
- return;
- }
-
m_labelOrig = label;
wxWindow::SetLabel( GetLabelForSysLink(label, GetURL()) );
InvalidateBestSize();
}
+bool wxHyperlinkCtrl::Enable(bool enable)
+{
+ if ( !wxGenericHyperlinkCtrl::Enable(enable) )
+ return false;
+
+ wxColour colour;
+ if ( enable )
+ {
+ colour = m_savedEnabledColour;
+ }
+ else
+ {
+ m_savedEnabledColour = GetNormalColour();
+ colour = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
+ }
+
+ SetForegroundColour(colour);
+
+ return true;
+}
+
bool wxHyperlinkCtrl::MSWAreCustomColoursEnabled() const
{
LITEM litem = { };
@@ -203,16 +202,23 @@ void wxHyperlinkCtrl::MSWEnableCustomColours()
wxColour wxHyperlinkCtrl::GetHoverColour() const
{
- if ( !HasNativeHyperlinkCtrl() )
- return wxGenericHyperlinkCtrl::GetHoverColour();
-
// Native control doesn't use special colour on hover.
return GetNormalColour();
}
+bool wxHyperlinkCtrl::SetForegroundColour(const wxColour& colour)
+{
+ if ( !wxGenericHyperlinkCtrl::SetForegroundColour(colour) )
+ return false;
+
+ SetNormalColour(colour);
+
+ return true;
+}
+
wxColour wxHyperlinkCtrl::GetNormalColour() const
{
- if ( !HasNativeHyperlinkCtrl() || MSWAreCustomColoursEnabled() )
+ if ( MSWAreCustomColoursEnabled() )
return wxGenericHyperlinkCtrl::GetNormalColour();
return GetClassDefaultAttributes().colFg;
@@ -220,15 +226,14 @@ wxColour wxHyperlinkCtrl::GetNormalColour() const
void wxHyperlinkCtrl::SetNormalColour(const wxColour &colour)
{
- if ( HasNativeHyperlinkCtrl() )
- MSWEnableCustomColours();
+ MSWEnableCustomColours();
wxGenericHyperlinkCtrl::SetNormalColour(colour);
}
wxColour wxHyperlinkCtrl::GetVisitedColour() const
{
- if ( !HasNativeHyperlinkCtrl() || MSWAreCustomColoursEnabled() )
+ if ( MSWAreCustomColoursEnabled() )
return wxGenericHyperlinkCtrl::GetVisitedColour();
// Native control doesn't show visited links differently.
@@ -237,8 +242,7 @@ wxColour wxHyperlinkCtrl::GetVisitedColour() const
void wxHyperlinkCtrl::SetVisitedColour(const wxColour &colour)
{
- if ( HasNativeHyperlinkCtrl() )
- MSWEnableCustomColours();
+ MSWEnableCustomColours();
wxGenericHyperlinkCtrl::SetVisitedColour(colour);
}
@@ -254,7 +258,7 @@ wxHyperlinkCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
{
auto attrs = wxGenericHyperlinkCtrl::GetClassDefaultAttributes(variant);
- if ( HasNativeHyperlinkCtrl() && !wxSystemSettings::GetAppearance().IsDark() )
+ if ( !wxSystemSettings::GetAppearance().IsDark() )
attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_HOTLIGHT);
return attrs;
@@ -262,9 +266,6 @@ wxHyperlinkCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
wxSize wxHyperlinkCtrl::DoGetBestClientSize() const
{
- if ( !HasNativeHyperlinkCtrl() )
- return wxGenericHyperlinkCtrl::DoGetBestClientSize();
-
// Windows allows to pass 0 as maximum width here, but Wine interprets 0 as
// meaning "minimum possible width", so use something that works for both.
const WPARAM UNLIMITED_WIDTH = 10000;
@@ -277,21 +278,18 @@ wxSize wxHyperlinkCtrl::DoGetBestClientSize() const
bool wxHyperlinkCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
{
- if ( HasNativeHyperlinkCtrl() )
+ switch ( ((LPNMHDR) lParam)->code )
{
- switch ( ((LPNMHDR) lParam)->code )
- {
- case NM_CLICK:
- case NM_RETURN:
- SetVisited();
- SendEvent();
-
- // SendEvent() launches the browser by default, so we consider
- // that the event was processed in any case, either by user
- // code or by wx itself, hence we always return true to
- // indicate that the default processing shouldn't take place.
- return true;
- }
+ case NM_CLICK:
+ case NM_RETURN:
+ SetVisited();
+ SendEvent();
+
+ // SendEvent() launches the browser by default, so we consider
+ // that the event was processed in any case, either by user
+ // code or by wx itself, hence we always return true to
+ // indicate that the default processing shouldn't take place.
+ return true;
}
return wxGenericHyperlinkCtrl::MSWOnNotify(idCtrl, lParam, result);
=====================================
src/msw/notebook.cpp
=====================================
@@ -311,6 +311,11 @@ int wxNotebook::MSWGetToolTipMessage() const
wxNotebook::~wxNotebook()
{
+ // Make sure we don't try to repaint the notebook any more: not only is
+ // this useless, it can also crash when calling member functions of a
+ // half-destroyed object.
+ Unbind(wxEVT_PAINT, &wxNotebook::OnPaint, this);
+
#if wxUSE_UXTHEME
if ( m_hbrBackground )
::DeleteObject((HBRUSH)m_hbrBackground);
@@ -1808,6 +1813,14 @@ bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child)
// Windows only: attempts to get colour for UX theme page background
wxColour wxNotebook::GetThemeBackgroundColour() const
{
+ if ( wxMSWDarkMode::IsActive() )
+ {
+ // We know the colour used in dark mode as we draw the notebook
+ // ourselves, so just return it (especially because the code below
+ // would return totally inappropriate light mode colour).
+ return GetBackgroundColour();
+ }
+
#if wxUSE_UXTHEME
if (wxUxThemeIsActive())
{
=====================================
src/msw/statbmp.cpp
=====================================
@@ -161,11 +161,10 @@ void wxStaticBitmap::Free()
{
m_bitmap.UnRef();
- MSWReplaceImageHandle(0);
-
if ( m_ownsCurrentHandle )
{
::DeleteObject(m_currentHandle);
+ m_currentHandle = 0;
m_ownsCurrentHandle = false;
}
}
=====================================
src/xrc/xh_hyperlink.cpp
=====================================
@@ -57,18 +57,42 @@ wxHyperlinkCtrlXmlHandler::wxHyperlinkCtrlXmlHandler()
wxObject *wxHyperlinkCtrlXmlHandler::DoCreateResource()
{
- XRC_MAKE_INSTANCE(control, wxHyperlinkCtrl)
-
- control->Create
- (
- m_parentAsWindow,
- GetID(),
- GetText(wxT("label")),
- GetParamValue(wxT("url")),
- GetPosition(), GetSize(),
- GetStyle(wxT("style"), wxHL_DEFAULT_STYLE),
- GetName()
- );
+ wxHyperlinkCtrlBase* control = nullptr;
+ if ( m_instance )
+ control = wxStaticCast(m_instance, wxHyperlinkCtrlBase);
+
+ if ( !control )
+ {
+ if ( m_class == "wxHyperlinkCtrl" )
+ {
+ control = new wxHyperlinkCtrl
+ (
+ m_parentAsWindow,
+ GetID(),
+ GetText(wxT("label")),
+ GetParamValue(wxT("url")),
+ GetPosition(), GetSize(),
+ GetStyle(wxT("style"), wxHL_DEFAULT_STYLE),
+ GetName()
+ );
+ }
+ else // m_class must be "wxGenericHyperlinkCtrl"
+ {
+ control = new wxGenericHyperlinkCtrl
+ (
+ m_parentAsWindow,
+ GetID(),
+ GetText(wxT("label")),
+ GetParamValue(wxT("url")),
+ GetPosition(), GetSize(),
+ GetStyle(wxT("style"), wxHL_DEFAULT_STYLE),
+ GetName()
+ );
+ }
+ }
+
+ if ( GetBool("hidden", 0) == 1 )
+ control->Hide();
SetupWindow(control);
@@ -77,7 +101,8 @@ wxObject *wxHyperlinkCtrlXmlHandler::DoCreateResource()
bool wxHyperlinkCtrlXmlHandler::CanHandle(wxXmlNode *node)
{
- return IsOfClass(node, wxT("wxHyperlinkCtrl"));
+ return IsOfClass(node, wxT("wxHyperlinkCtrl")) ||
+ IsOfClass(node, wxT("wxGenericHyperlinkCtrl"));
}
#endif // wxUSE_XRC && wxUSE_HYPERLINKCTRL
=====================================
tests/allheaders.h
=====================================
@@ -265,8 +265,10 @@
#include <wx/peninfobase.h>
#include <wx/persist.h>
#include <wx/persist/bookctrl.h>
+#include <wx/persist/checkbox.h>
#include <wx/persist/combobox.h>
#include <wx/persist/dataview.h>
+#include <wx/persist/radiobut.h>
#include <wx/persist/splitter.h>
#include <wx/persist/toplevel.h>
#include <wx/persist/treebook.h>
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/66bd59a958705398ad22536a8d301596b1951cb8...18da5b8269706472f6c0fa09dcbae605a477da19
--
View it on GitLab:
https://gitlab.com/wxwidgets/wxwidgets/-/compare/66bd59a958705398ad22536a8d301596b1951cb8...18da5b8269706472f6c0fa09dcbae605a477da19
You're receiving this email because of your account on
gitlab.com.