From d9018cdb444fbdfc53854e4d58da49c28d1cd26a Mon Sep 17 00:00:00 2001 From: Blake-Madden <66873089+Blake-Madden@users.noreply.github.com> Date: Sat, 28 Feb 2026 04:02:48 -0500 Subject: [PATCH] Add wxRibbonMSWFlatArtProvider, a (Fluent UI like) flat theme Also add some previously missing checks to other art providers and improve their documentation. Closes #26253. --- Makefile.in | 16 + build/bakefiles/files.bkl | 1 + build/cmake/files.cmake | 1 + build/files | 1 + build/msw/makefile.gcc | 16 + build/msw/makefile.vc | 16 + build/msw/wx_ribbon.vcxproj | 1 + build/msw/wx_ribbon.vcxproj.filters | 3 + build/osx/wxcocoa.xcodeproj/project.pbxproj | 8 + build/osx/wxiphone.xcodeproj/project.pbxproj | 4 + include/wx/ribbon/art.h | 102 ++ interface/wx/ribbon/art.h | 47 + samples/ribbon/ribbondemo.cpp | 10 + src/ribbon/art_aui.cpp | 6 +- src/ribbon/art_msw.cpp | 7 +- src/ribbon/art_msw_flat.cpp | 1178 ++++++++++++++++++ src/ribbon/descrip.mms | 5 +- 17 files changed, 1416 insertions(+), 6 deletions(-) create mode 100644 src/ribbon/art_msw_flat.cpp diff --git a/Makefile.in b/Makefile.in index ff78f39f6d..44cfcabc1e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2289,6 +2289,7 @@ RIBBONDLL_OBJECTS = \ ribbondll_art_internal.o \ ribbondll_art_msw.o \ ribbondll_art_aui.o \ + ribbondll_art_msw_flat.o \ ribbondll_bar.o \ ribbondll_buttonbar.o \ ribbondll_control.o \ @@ -2308,6 +2309,7 @@ RIBBONLIB_OBJECTS = \ ribbonlib_art_internal.o \ ribbonlib_art_msw.o \ ribbonlib_art_aui.o \ + ribbonlib_art_msw_flat.o \ ribbonlib_bar.o \ ribbonlib_buttonbar.o \ ribbonlib_control.o \ @@ -4338,6 +4340,7 @@ COND_USE_GUI_1___MONOLIB_GUI_SRC_OBJECTS = \ monodll_art_internal.o \ monodll_art_msw.o \ monodll_art_aui.o \ + monodll_art_msw_flat.o \ monodll_bar.o \ monodll_ribbon_buttonbar.o \ monodll_ribbon_control.o \ @@ -6123,6 +6126,7 @@ COND_USE_GUI_1___MONOLIB_GUI_SRC_OBJECTS_1 = \ monolib_art_internal.o \ monolib_art_msw.o \ monolib_art_aui.o \ + monolib_art_msw_flat.o \ monolib_bar.o \ monolib_ribbon_buttonbar.o \ monolib_ribbon_control.o \ @@ -16941,6 +16945,9 @@ monodll_art_msw.o: $(srcdir)/src/ribbon/art_msw.cpp $(MONODLL_ODEP) monodll_art_aui.o: $(srcdir)/src/ribbon/art_aui.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/ribbon/art_aui.cpp +monodll_art_msw_flat.o: $(srcdir)/src/ribbon/art_msw_flat.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/ribbon/art_msw_flat.cpp + monodll_bar.o: $(srcdir)/src/ribbon/bar.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/ribbon/bar.cpp @@ -21729,6 +21736,9 @@ monolib_art_msw.o: $(srcdir)/src/ribbon/art_msw.cpp $(MONOLIB_ODEP) monolib_art_aui.o: $(srcdir)/src/ribbon/art_aui.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/ribbon/art_aui.cpp +monolib_art_msw_flat.o: $(srcdir)/src/ribbon/art_msw_flat.cpp $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/ribbon/art_msw_flat.cpp + monolib_bar.o: $(srcdir)/src/ribbon/bar.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/ribbon/bar.cpp @@ -34302,6 +34312,9 @@ ribbondll_art_msw.o: $(srcdir)/src/ribbon/art_msw.cpp $(RIBBONDLL_ODEP) ribbondll_art_aui.o: $(srcdir)/src/ribbon/art_aui.cpp $(RIBBONDLL_ODEP) $(CXXC) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(srcdir)/src/ribbon/art_aui.cpp +ribbondll_art_msw_flat.o: $(srcdir)/src/ribbon/art_msw_flat.cpp $(RIBBONDLL_ODEP) + $(CXXC) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(srcdir)/src/ribbon/art_msw_flat.cpp + ribbondll_bar.o: $(srcdir)/src/ribbon/bar.cpp $(RIBBONDLL_ODEP) $(CXXC) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(srcdir)/src/ribbon/bar.cpp @@ -34335,6 +34348,9 @@ ribbonlib_art_msw.o: $(srcdir)/src/ribbon/art_msw.cpp $(RIBBONLIB_ODEP) ribbonlib_art_aui.o: $(srcdir)/src/ribbon/art_aui.cpp $(RIBBONLIB_ODEP) $(CXXC) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(srcdir)/src/ribbon/art_aui.cpp +ribbonlib_art_msw_flat.o: $(srcdir)/src/ribbon/art_msw_flat.cpp $(RIBBONLIB_ODEP) + $(CXXC) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(srcdir)/src/ribbon/art_msw_flat.cpp + ribbonlib_bar.o: $(srcdir)/src/ribbon/bar.cpp $(RIBBONLIB_ODEP) $(CXXC) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(srcdir)/src/ribbon/bar.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 9df77fa7a4..97c17c98d3 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -3067,6 +3067,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/ribbon/art_internal.cpp src/ribbon/art_msw.cpp src/ribbon/art_aui.cpp + src/ribbon/art_msw_flat.cpp src/ribbon/bar.cpp src/ribbon/buttonbar.cpp src/ribbon/control.cpp diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index c163c8752a..5be2db93e2 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -2798,6 +2798,7 @@ set(RIBBON_SRC src/ribbon/art_internal.cpp src/ribbon/art_msw.cpp src/ribbon/art_aui.cpp + src/ribbon/art_msw_flat.cpp src/ribbon/bar.cpp src/ribbon/buttonbar.cpp src/ribbon/control.cpp diff --git a/build/files b/build/files index 12357c3cdb..04b6561a60 100644 --- a/build/files +++ b/build/files @@ -2758,6 +2758,7 @@ RIBBON_SRC = src/ribbon/art_internal.cpp src/ribbon/art_msw.cpp src/ribbon/art_aui.cpp + src/ribbon/art_msw_flat.cpp src/ribbon/bar.cpp src/ribbon/buttonbar.cpp src/ribbon/control.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 64e511aafa..9a6b527414 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -1662,6 +1662,7 @@ RIBBONDLL_OBJECTS = \ $(OBJS)\ribbondll_art_internal.o \ $(OBJS)\ribbondll_art_msw.o \ $(OBJS)\ribbondll_art_aui.o \ + $(OBJS)\ribbondll_art_msw_flat.o \ $(OBJS)\ribbondll_bar.o \ $(OBJS)\ribbondll_buttonbar.o \ $(OBJS)\ribbondll_control.o \ @@ -1683,6 +1684,7 @@ RIBBONLIB_OBJECTS = \ $(OBJS)\ribbonlib_art_internal.o \ $(OBJS)\ribbonlib_art_msw.o \ $(OBJS)\ribbonlib_art_aui.o \ + $(OBJS)\ribbonlib_art_msw_flat.o \ $(OBJS)\ribbonlib_bar.o \ $(OBJS)\ribbonlib_buttonbar.o \ $(OBJS)\ribbonlib_control.o \ @@ -2048,6 +2050,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_art_internal.o \ $(OBJS)\monodll_art_msw.o \ $(OBJS)\monodll_art_aui.o \ + $(OBJS)\monodll_art_msw_flat.o \ $(OBJS)\monodll_bar.o \ $(OBJS)\monodll_ribbon_buttonbar.o \ $(OBJS)\monodll_ribbon_control.o \ @@ -2915,6 +2918,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_art_internal.o \ $(OBJS)\monolib_art_msw.o \ $(OBJS)\monolib_art_aui.o \ + $(OBJS)\monolib_art_msw_flat.o \ $(OBJS)\monolib_bar.o \ $(OBJS)\monolib_ribbon_buttonbar.o \ $(OBJS)\monolib_ribbon_control.o \ @@ -8854,6 +8858,9 @@ $(OBJS)\monodll_art_msw.o: ../../src/ribbon/art_msw.cpp $(OBJS)\monodll_art_aui.o: ../../src/ribbon/art_aui.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monodll_art_msw_flat.o: ../../src/ribbon/art_msw_flat.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monodll_bar.o: ../../src/ribbon/bar.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -11474,6 +11481,9 @@ $(OBJS)\monolib_art_msw.o: ../../src/ribbon/art_msw.cpp $(OBJS)\monolib_art_aui.o: ../../src/ribbon/art_aui.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monolib_art_msw_flat.o: ../../src/ribbon/art_msw_flat.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monolib_bar.o: ../../src/ribbon/bar.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -18134,6 +18144,9 @@ $(OBJS)\ribbondll_art_msw.o: ../../src/ribbon/art_msw.cpp $(OBJS)\ribbondll_art_aui.o: ../../src/ribbon/art_aui.cpp $(CXX) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\ribbondll_art_msw_flat.o: ../../src/ribbon/art_msw_flat.cpp + $(CXX) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\ribbondll_bar.o: ../../src/ribbon/bar.cpp $(CXX) -c -o $@ $(RIBBONDLL_CXXFLAGS) $(CPPDEPS) $< @@ -18170,6 +18183,9 @@ $(OBJS)\ribbonlib_art_msw.o: ../../src/ribbon/art_msw.cpp $(OBJS)\ribbonlib_art_aui.o: ../../src/ribbon/art_aui.cpp $(CXX) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\ribbonlib_art_msw_flat.o: ../../src/ribbon/art_msw_flat.cpp + $(CXX) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\ribbonlib_bar.o: ../../src/ribbon/bar.cpp $(CXX) -c -o $@ $(RIBBONLIB_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 7ddd306739..8303f0fbc2 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -1853,6 +1853,7 @@ RIBBONDLL_OBJECTS = \ $(OBJS)\ribbondll_art_internal.obj \ $(OBJS)\ribbondll_art_msw.obj \ $(OBJS)\ribbondll_art_aui.obj \ + $(OBJS)\ribbondll_art_msw_flat.obj \ $(OBJS)\ribbondll_bar.obj \ $(OBJS)\ribbondll_buttonbar.obj \ $(OBJS)\ribbondll_control.obj \ @@ -1881,6 +1882,7 @@ RIBBONLIB_OBJECTS = \ $(OBJS)\ribbonlib_art_internal.obj \ $(OBJS)\ribbonlib_art_msw.obj \ $(OBJS)\ribbonlib_art_aui.obj \ + $(OBJS)\ribbonlib_art_msw_flat.obj \ $(OBJS)\ribbonlib_bar.obj \ $(OBJS)\ribbonlib_buttonbar.obj \ $(OBJS)\ribbonlib_control.obj \ @@ -2435,6 +2437,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_art_internal.obj \ $(OBJS)\monodll_art_msw.obj \ $(OBJS)\monodll_art_aui.obj \ + $(OBJS)\monodll_art_msw_flat.obj \ $(OBJS)\monodll_bar.obj \ $(OBJS)\monodll_ribbon_buttonbar.obj \ $(OBJS)\monodll_ribbon_control.obj \ @@ -3302,6 +3305,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_art_internal.obj \ $(OBJS)\monolib_art_msw.obj \ $(OBJS)\monolib_art_aui.obj \ + $(OBJS)\monolib_art_msw_flat.obj \ $(OBJS)\monolib_bar.obj \ $(OBJS)\monolib_ribbon_buttonbar.obj \ $(OBJS)\monolib_ribbon_control.obj \ @@ -9356,6 +9360,9 @@ $(OBJS)\monodll_art_msw.obj: ..\..\src\ribbon\art_msw.cpp $(OBJS)\monodll_art_aui.obj: ..\..\src\ribbon\art_aui.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\ribbon\art_aui.cpp +$(OBJS)\monodll_art_msw_flat.obj: ..\..\src\ribbon\art_msw_flat.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\ribbon\art_msw_flat.cpp + $(OBJS)\monodll_bar.obj: ..\..\src\ribbon\bar.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\ribbon\bar.cpp @@ -11976,6 +11983,9 @@ $(OBJS)\monolib_art_msw.obj: ..\..\src\ribbon\art_msw.cpp $(OBJS)\monolib_art_aui.obj: ..\..\src\ribbon\art_aui.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\ribbon\art_aui.cpp +$(OBJS)\monolib_art_msw_flat.obj: ..\..\src\ribbon\art_msw_flat.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\ribbon\art_msw_flat.cpp + $(OBJS)\monolib_bar.obj: ..\..\src\ribbon\bar.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\ribbon\bar.cpp @@ -18636,6 +18646,9 @@ $(OBJS)\ribbondll_art_msw.obj: ..\..\src\ribbon\art_msw.cpp $(OBJS)\ribbondll_art_aui.obj: ..\..\src\ribbon\art_aui.cpp $(CXX) /c /nologo /TP /Fo$@ $(RIBBONDLL_CXXFLAGS) ..\..\src\ribbon\art_aui.cpp +$(OBJS)\ribbondll_art_msw_flat.obj: ..\..\src\ribbon\art_msw_flat.cpp + $(CXX) /c /nologo /TP /Fo$@ $(RIBBONDLL_CXXFLAGS) ..\..\src\ribbon\art_msw_flat.cpp + $(OBJS)\ribbondll_bar.obj: ..\..\src\ribbon\bar.cpp $(CXX) /c /nologo /TP /Fo$@ $(RIBBONDLL_CXXFLAGS) ..\..\src\ribbon\bar.cpp @@ -18672,6 +18685,9 @@ $(OBJS)\ribbonlib_art_msw.obj: ..\..\src\ribbon\art_msw.cpp $(OBJS)\ribbonlib_art_aui.obj: ..\..\src\ribbon\art_aui.cpp $(CXX) /c /nologo /TP /Fo$@ $(RIBBONLIB_CXXFLAGS) ..\..\src\ribbon\art_aui.cpp +$(OBJS)\ribbonlib_art_msw_flat.obj: ..\..\src\ribbon\art_msw_flat.cpp + $(CXX) /c /nologo /TP /Fo$@ $(RIBBONLIB_CXXFLAGS) ..\..\src\ribbon\art_msw_flat.cpp + $(OBJS)\ribbonlib_bar.obj: ..\..\src\ribbon\bar.cpp $(CXX) /c /nologo /TP /Fo$@ $(RIBBONLIB_CXXFLAGS) ..\..\src\ribbon\bar.cpp diff --git a/build/msw/wx_ribbon.vcxproj b/build/msw/wx_ribbon.vcxproj index a797505c2e..73f6867d72 100644 --- a/build/msw/wx_ribbon.vcxproj +++ b/build/msw/wx_ribbon.vcxproj @@ -859,6 +859,7 @@ Create + diff --git a/build/msw/wx_ribbon.vcxproj.filters b/build/msw/wx_ribbon.vcxproj.filters index 046fb494c9..36fadd1410 100644 --- a/build/msw/wx_ribbon.vcxproj.filters +++ b/build/msw/wx_ribbon.vcxproj.filters @@ -28,6 +28,9 @@ Source Files + + Source Files + Source Files diff --git a/build/osx/wxcocoa.xcodeproj/project.pbxproj b/build/osx/wxcocoa.xcodeproj/project.pbxproj index 5c94bc69b0..68971c5274 100644 --- a/build/osx/wxcocoa.xcodeproj/project.pbxproj +++ b/build/osx/wxcocoa.xcodeproj/project.pbxproj @@ -282,6 +282,7 @@ AAABEE399008310A8BC9BE43 /* imagtga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7029BB5751398AA02D8C24 /* imagtga.cpp */; }; 3C0EB1DDA5243E31B2D92CE2 /* jquant2.c in Sources */ = {isa = PBXBuildFile; fileRef = 02D9332D5C5632E981936E29 /* jquant2.c */; }; A0BA01A85C303C78A3130711 /* art_aui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */; }; + F1A2B3C4D5E63C78A3130711 /* art_msw_flat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */; }; EBDEBA86AA7930EB86A02E67 /* ssim.c in Sources */ = {isa = PBXBuildFile; fileRef = 5CECF4A5F2D839E397B3143F /* ssim.c */; }; 246B4FF96BA135258FE45F50 /* encconv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C269E9CA99DF3AE5B1BD6AFA /* encconv.cpp */; }; 699D88EE2DAA3594B6606890 /* ViewStyle.cxx in Sources */ = {isa = PBXBuildFile; fileRef = C133B838193A35ABBB803151 /* ViewStyle.cxx */; }; @@ -1402,6 +1403,7 @@ 95826E8528CC32D8934C36ED /* xh_frame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5A9B63746753EDFB2EC48D3 /* xh_frame.cpp */; }; EDD92822EBD93E86AE5A2ED2 /* slidercmn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E8072CA67D19346ABF4D465F /* slidercmn.cpp */; }; A0BA01A85C303C78A3130712 /* art_aui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */; }; + F1A2B3C4D5E63C78A3130712 /* art_msw_flat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */; }; CF3082BA1ED232F4B904BD15 /* stdpbase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 75BF90BEF2F83BF28EC0458D /* stdpbase.cpp */; }; D9EE059D3C3C3C13AE4419F2 /* stattextcmn.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54BD19211DBD388AA0DEC7A1 /* stattextcmn.cpp */; }; FE5B7C7A84B83C17A38E8405 /* LexSML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 912B2982C9413F2FB40CA2D9 /* LexSML.cxx */; }; @@ -3100,6 +3102,7 @@ DC928C38CA8331F18FF00BCD /* tif_lzma.c in Sources */ = {isa = PBXBuildFile; fileRef = 3088384F07C63A5DB3581656 /* tif_lzma.c */; }; 8AA341CCFB8E3F6AB3523597 /* splash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8836E29C5A370E80CE070E /* splash.cpp */; }; A0BA01A85C303C78A3130713 /* art_aui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */; }; + F1A2B3C4D5E63C78A3130713 /* art_msw_flat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */; }; CB078622E90F33BE9D131135 /* buttonbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5612DBC4125B379DA2B28824 /* buttonbar.cpp */; }; 1BCC944F5E0936F5830F03EA /* windowid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E9B9B85572D0312BBF2878DB /* windowid.cpp */; }; 0FDDE8E193743F3A8CBDC67D /* richtextprint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C4C45D3C63AA37CEBCE83321 /* richtextprint.cpp */; }; @@ -5604,6 +5607,7 @@ A298576700C33F018616E7BD /* auibook.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = auibook.cpp; path = ../../src/aui/auibook.cpp; sourceTree = SOURCE_ROOT; }; 5F555177554E398286DBC6FB /* xh_stlin.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = xh_stlin.cpp; path = ../../src/xrc/xh_stlin.cpp; sourceTree = SOURCE_ROOT; }; DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = art_aui.cpp; path = ../../src/ribbon/art_aui.cpp; sourceTree = SOURCE_ROOT; }; + F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = art_msw_flat.cpp; path = ../../src/ribbon/art_msw_flat.cpp; sourceTree = SOURCE_ROOT; }; 42040492AAA43A60BA8DE111 /* filter_enc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = filter_enc.c; path = ../../3rdparty/libwebp/src/enc/filter_enc.c; sourceTree = SOURCE_ROOT; }; 23FC98E2305230E2990471E3 /* wxcrt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = wxcrt.cpp; path = ../../src/common/wxcrt.cpp; sourceTree = SOURCE_ROOT; }; BACAA6CE4A0934459F26B27C /* graphicc.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = graphicc.cpp; path = ../../src/generic/graphicc.cpp; sourceTree = SOURCE_ROOT; }; @@ -6140,6 +6144,7 @@ 4C4649974D8B3A109D1BF145 /* art_internal.cpp */, B540E18F9C91381CA175BABB /* art_msw.cpp */, DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */, + F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */, 9FDDE855D9F83E4891362EB4 /* bar.cpp */, 5612DBC4125B379DA2B28824 /* buttonbar.cpp */, 12363D1F50FE301DAEE7F04B /* control.cpp */, @@ -9451,6 +9456,7 @@ DE43350F6C9D3148A64F0AFB /* art_internal.cpp in Sources */, 7DC4A542372437ECA0790F89 /* art_msw.cpp in Sources */, A0BA01A85C303C78A3130713 /* art_aui.cpp in Sources */, + F1A2B3C4D5E63C78A3130713 /* art_msw_flat.cpp in Sources */, 056CA84179433AA48D55DA67 /* bar.cpp in Sources */, CB078622E90F33BE9D131134 /* buttonbar.cpp in Sources */, EB52C6A91594381393294502 /* control.cpp in Sources */, @@ -10108,6 +10114,7 @@ DE43350F6C9D3148A64F0AF9 /* art_internal.cpp in Sources */, 7DC4A542372437ECA0790F87 /* art_msw.cpp in Sources */, A0BA01A85C303C78A3130711 /* art_aui.cpp in Sources */, + F1A2B3C4D5E63C78A3130711 /* art_msw_flat.cpp in Sources */, 056CA84179433AA48D55DA65 /* bar.cpp in Sources */, CB078622E90F33BE9D131135 /* buttonbar.cpp in Sources */, EB52C6A91594381393294500 /* control.cpp in Sources */, @@ -11584,6 +11591,7 @@ DE43350F6C9D3148A64F0AFA /* art_internal.cpp in Sources */, 7DC4A542372437ECA0790F88 /* art_msw.cpp in Sources */, A0BA01A85C303C78A3130712 /* art_aui.cpp in Sources */, + F1A2B3C4D5E63C78A3130712 /* art_msw_flat.cpp in Sources */, 056CA84179433AA48D55DA66 /* bar.cpp in Sources */, CB078622E90F33BE9D131133 /* buttonbar.cpp in Sources */, EB52C6A915943813932944FE /* control.cpp in Sources */, diff --git a/build/osx/wxiphone.xcodeproj/project.pbxproj b/build/osx/wxiphone.xcodeproj/project.pbxproj index 32787c97a3..d0ee1975c0 100644 --- a/build/osx/wxiphone.xcodeproj/project.pbxproj +++ b/build/osx/wxiphone.xcodeproj/project.pbxproj @@ -729,6 +729,7 @@ 7F77E347E1243D77A666FB43 /* clipbrd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12453E271F2A3AC9969E62A4 /* clipbrd.cpp */; }; 159E4248CB1333AD841D9F03 /* LexYAML.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 9CC7C6FFD67233788EEDFC5E /* LexYAML.cxx */; }; A0BA01A85C303C78A3130711 /* art_aui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */; }; + F1A2B3C4D5E63C78A3130714 /* art_msw_flat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */; }; 0BB3BF0909A134BA93CF5620 /* xh_richtext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 88C2B895570936A3B4FAF3CF /* xh_richtext.cpp */; }; FBA19C939E1E33EDB05043FE /* cairo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5DBE56B153AA3AC8A4BBE77C /* cairo.cpp */; }; 8E674574343A3C009B1BCD00 /* tif_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = 88FF67EB6E7D302A9CDEF660 /* tif_codec.c */; }; @@ -1448,6 +1449,7 @@ 3720038D64CF3C0B8F642A90 /* tokenzr.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = tokenzr.cpp; path = ../../src/common/tokenzr.cpp; sourceTree = SOURCE_ROOT; }; 5EB5FAE81851390D80798E73 /* rescaler_mips32.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = rescaler_mips32.c; path = ../../3rdparty/libwebp/src/dsp/rescaler_mips32.c; sourceTree = SOURCE_ROOT; }; DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = art_aui.cpp; path = ../../src/ribbon/art_aui.cpp; sourceTree = SOURCE_ROOT; }; + F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = art_msw_flat.cpp; path = ../../src/ribbon/art_msw_flat.cpp; sourceTree = SOURCE_ROOT; }; 4BA14FFC0F4B3AE0B4D6B185 /* jquant1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jquant1.c; path = ../../src/jpeg/jquant1.c; sourceTree = SOURCE_ROOT; }; 8EB76F786D7F3FF286948D22 /* jcomapi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = jcomapi.c; path = ../../src/jpeg/jcomapi.c; sourceTree = SOURCE_ROOT; }; 082CA018FB883999839C1DCE /* m_tables.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = m_tables.cpp; path = ../../src/html/m_tables.cpp; sourceTree = SOURCE_ROOT; }; @@ -2636,6 +2638,7 @@ 4C4649974D8B3A109D1BF145 /* art_internal.cpp */, B540E18F9C91381CA175BABB /* art_msw.cpp */, DD5E8709C3BC3727BBC7B97A /* art_aui.cpp */, + F1A2B3C4D5E63727BBC7B97A /* art_msw_flat.cpp */, 9FDDE855D9F83E4891362EB4 /* bar.cpp */, 5612DBC4125B379DA2B28824 /* buttonbar.cpp */, 12363D1F50FE301DAEE7F04B /* control.cpp */, @@ -4072,6 +4075,7 @@ DE43350F6C9D3148A64F0AF9 /* art_internal.cpp in Sources */, 7DC4A542372437ECA0790F87 /* art_msw.cpp in Sources */, A0BA01A85C303C78A3130711 /* art_aui.cpp in Sources */, + F1A2B3C4D5E63C78A3130714 /* art_msw_flat.cpp in Sources */, 056CA84179433AA48D55DA65 /* bar.cpp in Sources */, CB078622E90F33BE9D131131 /* buttonbar.cpp in Sources */, EB52C6A915943813932944FF /* control.cpp in Sources */, diff --git a/include/wx/ribbon/art.h b/include/wx/ribbon/art.h index 305c543fe6..034a48e36c 100644 --- a/include/wx/ribbon/art.h +++ b/include/wx/ribbon/art.h @@ -790,6 +790,108 @@ protected: int m_help_button_offset; }; +class WXDLLIMPEXP_RIBBON wxRibbonMSWFlatArtProvider : public wxRibbonMSWArtProvider +{ +public: + wxRibbonMSWFlatArtProvider(); + virtual ~wxRibbonMSWFlatArtProvider(); + + wxNODISCARD wxRibbonArtProvider* Clone() const override; + + void DrawTab(wxDC& dc, + wxWindow* wnd, + const wxRibbonPageTabInfo& tab) override; + + void DrawTabSeparator( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + double visibility) override; + + void DrawPageBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) override; + + void DrawScrollButton( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + long style) override; + + void DrawPanelBackground( + wxDC& dc, + wxRibbonPanel* wnd, + const wxRect& rect) override; + + void DrawGalleryBackground( + wxDC& dc, + wxRibbonGallery* wnd, + const wxRect& rect) override; + + void DrawGalleryItemBackground( + wxDC& dc, + wxRibbonGallery* wnd, + const wxRect& rect, + wxRibbonGalleryItem* item) override; + + void DrawMinimisedPanel( + wxDC& dc, + wxRibbonPanel* wnd, + const wxRect& rect, + wxBitmap& bitmap) override; + + void DrawButtonBarBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) override; + + void DrawButtonBarButton( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + wxRibbonButtonKind kind, + long state, + const wxString& label, + const wxBitmap& bitmap_large, + const wxBitmap& bitmap_small) override; + + void DrawToolBarBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) override; + + void DrawTool( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + const wxBitmap& bitmap, + wxRibbonButtonKind kind, + long state) override; + + void DrawToggleButton( + wxDC& dc, + wxRibbonBar* wnd, + const wxRect& rect, + wxRibbonDisplayMode mode) override; + + void DrawHelpButton(wxDC& dc, + wxRibbonBar* wnd, + const wxRect& rect) override; + +protected: + void DrawPartialPageBackground(wxDC& dc, wxWindow* wnd, const wxRect& r, + wxRibbonPage* page, wxPoint offset, bool hovered = false); + void DrawPartialPageBackground(wxDC& dc, wxWindow* wnd, + const wxRect& rect, bool allow_hovered = true); + void DrawGalleryButton(wxDC& dc, wxRect rect, + wxRibbonGalleryButtonState state, wxBitmap* bitmaps) override; + void DrawPanelBorder(wxDC& dc, const wxRect& rect, wxPen& primary_colour, + wxPen& secondary_colour); + void ReallyDrawTabSeparator(wxWindow* wnd, const wxRect& rect, + double visibility); +}; + class WXDLLIMPEXP_RIBBON wxRibbonAUIArtProvider : public wxRibbonMSWArtProvider { public: diff --git a/interface/wx/ribbon/art.h b/interface/wx/ribbon/art.h index e3e8324fb8..d99dbb6ea0 100644 --- a/interface/wx/ribbon/art.h +++ b/interface/wx/ribbon/art.h @@ -1071,6 +1071,19 @@ public: +/** + @class wxRibbonMSWArtProvider + + An art provider which draws a ribbon using gradients to mimic the + appearance of Microsoft Office 2007 and the Windows Vista / Aero + visual style. Tabs, panels, button bars, and toolbars all use + gradient fills to create a glossy, three-dimensional look. + + @library{wxribbon} + @category{ribbon} + + @see wxRibbonMSWFlatArtProvider, wxRibbonAUIArtProvider +*/ class wxRibbonMSWArtProvider : public wxRibbonArtProvider { public: @@ -1078,6 +1091,40 @@ public: }; +/** + @class wxRibbonMSWFlatArtProvider + + A flat variant of wxRibbonMSWArtProvider that uses solid colour fills + instead of gradients, providing a modern appearance consistent with + the Windows Metro / Fluent design language. + + @since 3.3.3 + + @library{wxribbon} + @category{ribbon} + + @see wxRibbonMSWArtProvider, wxRibbonAUIArtProvider +*/ +class wxRibbonMSWFlatArtProvider : public wxRibbonMSWArtProvider +{ +public: + wxRibbonMSWFlatArtProvider(); +}; + + +/** + @class wxRibbonAUIArtProvider + + An art provider styled after the wxAUI docking framework. Like + wxRibbonMSWArtProvider it uses gradient fills, but differs in its + layout of panel labels (placed at the top rather than the bottom) + and general styling. + + @library{wxribbon} + @category{ribbon} + + @see wxRibbonMSWArtProvider, wxRibbonMSWFlatArtProvider +*/ class wxRibbonAUIArtProvider : public wxRibbonMSWArtProvider { public: diff --git a/samples/ribbon/ribbondemo.cpp b/samples/ribbon/ribbondemo.cpp index 0cb1886951..3c685aa7f1 100644 --- a/samples/ribbon/ribbondemo.cpp +++ b/samples/ribbon/ribbondemo.cpp @@ -63,6 +63,7 @@ public: ID_DEFAULT_PROVIDER, ID_AUI_PROVIDER, ID_MSW_PROVIDER, + ID_MSW_FLAT_PROVIDER, ID_MAIN_TOOLBAR, ID_POSITION_TOP, ID_POSITION_TOP_ICONS, @@ -119,6 +120,7 @@ public: void OnDefaultProvider(wxRibbonButtonBarEvent& evt); void OnAUIProvider(wxRibbonButtonBarEvent& evt); void OnMSWProvider(wxRibbonButtonBarEvent& evt); + void OnMSWFlatProvider(wxRibbonButtonBarEvent& evt); void OnJustify(wxRibbonToolBarEvent& evt); void OnJustifyUpdateUI(wxUpdateUIEvent& evt); void OnNew(wxRibbonToolBarEvent& evt); @@ -210,6 +212,7 @@ EVT_UPDATE_UI(ID_UI_CHANGE_TEXT_UPDATED, MyFrame::OnChangeTextUpdateUI) EVT_RIBBONBUTTONBAR_CLICKED(ID_DEFAULT_PROVIDER, MyFrame::OnDefaultProvider) EVT_RIBBONBUTTONBAR_CLICKED(ID_AUI_PROVIDER, MyFrame::OnAUIProvider) EVT_RIBBONBUTTONBAR_CLICKED(ID_MSW_PROVIDER, MyFrame::OnMSWProvider) +EVT_RIBBONBUTTONBAR_CLICKED(ID_MSW_FLAT_PROVIDER, MyFrame::OnMSWFlatProvider) EVT_RIBBONBUTTONBAR_CLICKED(ID_SELECTION_EXPAND_H, MyFrame::OnSelectionExpandHButton) EVT_RIBBONBUTTONBAR_CLICKED(ID_SELECTION_EXPAND_V, MyFrame::OnSelectionExpandVButton) EVT_RIBBONBUTTONBAR_CLICKED(ID_SELECTION_CONTRACT, MyFrame::OnSelectionContractButton) @@ -406,6 +409,7 @@ MyFrame::MyFrame() wxArtProvider::GetBitmap(wxART_QUESTION, wxART_OTHER, wxSize(32, 32))); provider_bar->AddButton(ID_AUI_PROVIDER, "AUI Provider", aui_style_xpm); provider_bar->AddButton(ID_MSW_PROVIDER, "MSW Provider", msw_style_xpm); + provider_bar->AddButton(ID_MSW_FLAT_PROVIDER, "MSW Flat Provider", msw_style_xpm); wxRibbonPanel *primary_panel = new wxRibbonPanel(scheme, wxID_ANY, "Primary Colour", colours_xpm); m_primary_gallery = PopulateColoursPanel(primary_panel, @@ -1075,6 +1079,12 @@ void MyFrame::OnMSWProvider(wxRibbonButtonBarEvent& WXUNUSED(evt)) SetArtProvider(new wxRibbonMSWArtProvider); } +void MyFrame::OnMSWFlatProvider(wxRibbonButtonBarEvent& WXUNUSED(evt)) +{ + m_ribbon->DismissExpandedPanel(); + SetArtProvider(new wxRibbonMSWFlatArtProvider); +} + void MyFrame::SetArtProvider(wxRibbonArtProvider *prov) { m_ribbon->Freeze(); diff --git a/src/ribbon/art_aui.cpp b/src/ribbon/art_aui.cpp index e7102023db..0fdd724f8b 100644 --- a/src/ribbon/art_aui.cpp +++ b/src/ribbon/art_aui.cpp @@ -501,8 +501,10 @@ void wxRibbonAUIArtProvider::DrawTab(wxDC& dc, dc.DrawBitmap(icon, x - offset, tab.rect.y + (tab.rect.height - icon.GetLogicalHeight()) / 2, true); } - dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height); - dc.DrawText(label, x, y); + { + wxDCClipper clip(dc, x, tab.rect.y, width, tab.rect.height); + dc.DrawText(label, x, y); + } } } diff --git a/src/ribbon/art_msw.cpp b/src/ribbon/art_msw.cpp index 748c45a28c..00c4a4e91d 100644 --- a/src/ribbon/art_msw.cpp +++ b/src/ribbon/art_msw.cpp @@ -1449,6 +1449,9 @@ void wxRibbonMSWArtProvider::DrawTab( } } + if ( tab.page == nullptr ) + return; + if(m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS) { wxBitmap icon = tab.page->GetIcon(); @@ -1502,7 +1505,7 @@ void wxRibbonMSWArtProvider::DrawTab( if(width <= text_width) { - dc.SetClippingRegion(x, tab.rect.y, width, tab.rect.height); + wxDCClipper clip(dc, x, tab.rect.y, width, tab.rect.height); dc.DrawText(label, x, y); } else @@ -1948,7 +1951,7 @@ void wxRibbonMSWArtProvider::DrawPanelBackground( { // Room for some characters and ... // Display as many characters as possible and append ... - for(size_t len = label.Len() - 1; len >= 3; --len) + for( int len = wxSsize(label) - 1; len >= 3; --len ) { new_label = label.Mid(0, len) + "..."; label_size = dc.GetTextExtent(new_label); diff --git a/src/ribbon/art_msw_flat.cpp b/src/ribbon/art_msw_flat.cpp new file mode 100644 index 0000000000..ee19b4a701 --- /dev/null +++ b/src/ribbon/art_msw_flat.cpp @@ -0,0 +1,1178 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/ribbon/art_msw_flat.cpp +// Purpose: Flat MSW style art provider for ribbon interface +// Author: wxWidgets team +// Created: 2026-02-27 +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + + +#if wxUSE_RIBBON + +#include "wx/ribbon/art.h" +#include "wx/ribbon/art_internal.h" +#include "wx/ribbon/bar.h" +#include "wx/ribbon/buttonbar.h" +#include "wx/ribbon/gallery.h" +#include "wx/ribbon/toolbar.h" + +#ifndef WX_PRECOMP +#include "wx/dcmemory.h" +#endif + +#ifdef __WXMSW__ +#include "wx/msw/private.h" +#endif + +wxRibbonMSWFlatArtProvider::wxRibbonMSWFlatArtProvider() + : wxRibbonMSWArtProvider() +{ +} + +wxRibbonMSWFlatArtProvider::~wxRibbonMSWFlatArtProvider() +{ +} + +wxRibbonArtProvider* wxRibbonMSWFlatArtProvider::Clone() const +{ + wxRibbonMSWFlatArtProvider *copy = new wxRibbonMSWFlatArtProvider; + CloneTo(copy); + return copy; +} + +void wxRibbonMSWFlatArtProvider::DrawTab( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRibbonPageTabInfo& tab) +{ + if ( tab.rect.height <= 2 ) + return; + + if ( tab.active || tab.hovered || tab.highlight ) + { + if ( tab.active ) + { + wxRect background(tab.rect); + + background.x += 2; + background.y += 2; + background.width -= 4; + background.height -= 2; + + if ( background.width > 0 && background.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_tab_active_background_colour)); + dc.DrawRectangle(background.x, background.y, + background.width, background.height); + } + } + else if ( tab.hovered ) + { + wxRect background(tab.rect); + + background.x += 2; + background.y += 2; + background.width -= 4; + background.height -= 3; + + if ( background.width > 0 && background.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_tab_hover_background_colour)); + dc.DrawRectangle(background.x, background.y, + background.width, background.height); + } + } + else if ( tab.highlight ) + { + wxRect background(tab.rect); + + background.x += 2; + background.y += 2; + background.width -= 4; + background.height -= 3; + + if ( background.width > 0 && background.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_tab_highlight_colour)); + dc.DrawRectangle(background.x, background.y, + background.width, background.height); + } + } + + wxPoint border_points[6]; + border_points[0] = wxPoint(1, tab.rect.height - 2); + border_points[1] = wxPoint(1, 3); + border_points[2] = wxPoint(3, 1); + border_points[3] = wxPoint(tab.rect.width - 4, 1); + border_points[4] = wxPoint(tab.rect.width - 2, 3); + border_points[5] = wxPoint(tab.rect.width - 2, tab.rect.height - 1); + + dc.SetPen(m_tab_border_pen); + dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, + tab.rect.x, tab.rect.y); + + if ( tab.active ) + { + // Give the tab a curved outward border at the bottom + dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 2); + dc.DrawPoint(tab.rect.x + tab.rect.width - 1, + tab.rect.y + tab.rect.height - 2); + + dc.SetPen(wxPen(m_tab_active_background_colour)); + + dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 2); + dc.DrawPoint(tab.rect.x + tab.rect.width - 2, + tab.rect.y + tab.rect.height - 2); + dc.DrawPoint(tab.rect.x + 1, tab.rect.y + tab.rect.height - 1); + dc.DrawPoint(tab.rect.x, tab.rect.y + tab.rect.height - 1); + dc.DrawPoint(tab.rect.x + tab.rect.width - 2, + tab.rect.y + tab.rect.height - 1); + dc.DrawPoint(tab.rect.x + tab.rect.width - 1, + tab.rect.y + tab.rect.height - 1); + } + } + + if ( tab.page == nullptr ) + return; + + if ( m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS ) + { + wxBitmap icon = tab.page->GetIcon(); + if ( icon.IsOk() ) + { + int x = tab.rect.x + 4; + if ( (m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS) == 0 ) + x = tab.rect.x + (tab.rect.width - icon.GetLogicalWidth()) / 2; + dc.DrawBitmap(icon, x, tab.rect.y + 1 + (tab.rect.height - 1 - + icon.GetLogicalHeight()) / 2, true); + } + } + if ( m_flags & wxRIBBON_BAR_SHOW_PAGE_LABELS ) + { + wxString label = tab.page->GetLabel(); + if ( !label.empty() ) + { + dc.SetFont(m_tab_label_font); + + if ( tab.active ) + { + dc.SetTextForeground(m_tab_active_label_colour); + } + else if ( tab.hovered ) + { + dc.SetTextForeground(m_tab_hover_label_colour); + } + else + { + dc.SetTextForeground(m_tab_label_colour); + } + + dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); + + int text_height; + int text_width; + dc.GetTextExtent(label, &text_width, &text_height); + int width = tab.rect.width - 5; + int x = tab.rect.x + 3; + if ( m_flags & wxRIBBON_BAR_SHOW_PAGE_ICONS ) + { + const wxBitmap& icon = tab.page->GetIcon(); + if ( icon.IsOk() ) + { + const int iconWidth = icon.GetLogicalWidth(); + x += 3 + iconWidth; + width -= 3 + iconWidth; + } + } + int y = tab.rect.y + (tab.rect.height - text_height) / 2; + + if ( width <= text_width ) + { + wxDCClipper clip(dc, x, tab.rect.y, width, tab.rect.height); + dc.DrawText(label, x, y); + } + else + { + dc.DrawText(label, x + (width - text_width) / 2 + 1, y); + } + } + } +} + +void wxRibbonMSWFlatArtProvider::ReallyDrawTabSeparator(wxWindow* wnd, + const wxRect& rect, double visibility) +{ + if ( !m_cached_tab_separator.IsOk() + || m_cached_tab_separator.GetLogicalSize() != rect.GetSize() ) + { + m_cached_tab_separator = wxBitmap(rect.GetSize()); + } + + wxMemoryDC dc(m_cached_tab_separator); + DrawTabCtrlBackground(dc, wnd, rect); + + wxCoord x = rect.x + rect.width / 2; + + unsigned char r = (unsigned char)(m_tab_separator_colour.Red() * visibility + + m_tab_ctrl_background_brush.GetColour().Red() * (1.0 - visibility) + + 0.5); + unsigned char g = (unsigned char)(m_tab_separator_colour.Green() * visibility + + m_tab_ctrl_background_brush.GetColour().Green() * (1.0 - visibility) + + 0.5); + unsigned char b = (unsigned char)(m_tab_separator_colour.Blue() * visibility + + m_tab_ctrl_background_brush.GetColour().Blue() * (1.0 - visibility) + + 0.5); + + dc.SetPen(wxPen(wxColour(r, g, b))); + dc.DrawLine(x, rect.y, x, rect.y + rect.height - 1); + + m_cached_tab_separator_visibility = visibility; +} + +void wxRibbonMSWFlatArtProvider::DrawPartialPageBackground(wxDC& dc, + wxWindow* wnd, const wxRect& r, wxRibbonPage* page, + wxPoint offset, bool hovered) +{ + wxRect background; + + if ( wnd->GetSizer() && wnd->GetParent() != page ) + { + background = wnd->GetParent()->GetSize(); + offset = wxPoint(0, 0); + } + else + { + background = page->GetSize(); + page->AdjustRectToIncludeScrollButtons(&background); + background.height -= 2; + } + wxRect paint_rect(r); + paint_rect.x += offset.x; + paint_rect.y += offset.y; + + // Clamp vertically to the background but allow full width, as expanded + // panels can be wider than the page. + wxRect rect(paint_rect); + if ( rect.y < background.y ) + { + rect.height -= (background.y - rect.y); + rect.y = background.y; + } + if ( rect.GetBottom() > background.GetBottom() ) + rect.SetBottom(background.GetBottom()); + rect.x -= offset.x; + rect.y -= offset.y; + + if ( rect.width > 0 && rect.height > 0 ) + { + wxColour bg_colour; + if ( hovered ) + bg_colour = m_page_hover_background_colour; + else + bg_colour = m_page_background_colour; + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(bg_colour)); + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + } +} + +void wxRibbonMSWFlatArtProvider::DrawPageBackground( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& rect) +{ + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(m_tab_ctrl_background_brush); + + { + wxRect edge(rect); + + edge.width = 2; + dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height); + + edge.x += rect.width - 2; + dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height); + + edge = rect; + edge.height = 2; + edge.y += (rect.height - edge.height); + dc.DrawRectangle(edge.x, edge.y, edge.width, edge.height); + } + + { + wxRect background(rect); + background.x += 2; + background.width -= 4; + background.height -= 2; + + if ( background.width > 0 && background.height > 0 ) + { + dc.SetBrush(wxBrush(m_page_background_colour)); + dc.DrawRectangle(background.x, background.y, + background.width, background.height); + } + } + + { + wxPoint border_points[8]; + border_points[0] = wxPoint(2, 0); + border_points[1] = wxPoint(1, 1); + border_points[2] = wxPoint(1, rect.height - 4); + border_points[3] = wxPoint(3, rect.height - 2); + border_points[4] = wxPoint(rect.width - 4, rect.height - 2); + border_points[5] = wxPoint(rect.width - 2, rect.height - 4); + border_points[6] = wxPoint(rect.width - 2, 1); + border_points[7] = wxPoint(rect.width - 4, -1); + + dc.SetPen(m_page_border_pen); + dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, + rect.x, rect.y); + } +} + +void wxRibbonMSWFlatArtProvider::DrawScrollButton( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& rect_, + long style) +{ + wxRect rect(rect_); + + if ( (style & wxRIBBON_SCROLL_BTN_FOR_MASK) == wxRIBBON_SCROLL_BTN_FOR_PAGE ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(m_tab_ctrl_background_brush); + dc.DrawRectangle(rect); + dc.SetClippingRegion(rect); + switch ( style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK ) + { + case wxRIBBON_SCROLL_BTN_LEFT: + rect.x++; + wxFALLTHROUGH; + case wxRIBBON_SCROLL_BTN_RIGHT: + rect.y--; + rect.width--; + break; + case wxRIBBON_SCROLL_BTN_UP: + rect.x++; + rect.y--; + rect.width -= 2; + rect.height++; + break; + case wxRIBBON_SCROLL_BTN_DOWN: + rect.x++; + rect.width -= 2; + rect.height--; + break; + } + } + + { + wxRect background(rect); + background.x++; + background.y++; + background.width -= 2; + background.height -= 2; + + if ( background.width > 0 && background.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_page_background_colour)); + dc.DrawRectangle(background.x, background.y, + background.width, background.height); + } + } + + { + wxPoint border_points[7]; + switch ( style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK ) + { + case wxRIBBON_SCROLL_BTN_LEFT: + border_points[0] = wxPoint(2, 0); + border_points[1] = wxPoint(rect.width - 1, 0); + border_points[2] = wxPoint(rect.width - 1, rect.height - 1); + border_points[3] = wxPoint(2, rect.height - 1); + border_points[4] = wxPoint(0, rect.height - 3); + border_points[5] = wxPoint(0, 2); + break; + case wxRIBBON_SCROLL_BTN_RIGHT: + border_points[0] = wxPoint(0, 0); + border_points[1] = wxPoint(rect.width - 3, 0); + border_points[2] = wxPoint(rect.width - 1, 2); + border_points[3] = wxPoint(rect.width - 1, rect.height - 3); + border_points[4] = wxPoint(rect.width - 3, rect.height - 1); + border_points[5] = wxPoint(0, rect.height - 1); + break; + case wxRIBBON_SCROLL_BTN_UP: + border_points[0] = wxPoint(2, 0); + border_points[1] = wxPoint(rect.width - 3, 0); + border_points[2] = wxPoint(rect.width - 1, 2); + border_points[3] = wxPoint(rect.width - 1, rect.height - 1); + border_points[4] = wxPoint(0, rect.height - 1); + border_points[5] = wxPoint(0, 2); + break; + case wxRIBBON_SCROLL_BTN_DOWN: + border_points[0] = wxPoint(0, 0); + border_points[1] = wxPoint(rect.width - 1, 0); + border_points[2] = wxPoint(rect.width - 1, rect.height - 3); + border_points[3] = wxPoint(rect.width - 3, rect.height - 1); + border_points[4] = wxPoint(2, rect.height - 1); + border_points[5] = wxPoint(0, rect.height - 3); + break; + } + border_points[6] = border_points[0]; + + dc.SetPen(m_page_border_pen); + dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, + rect.x, rect.y); + } + + { + // NB: Code for handling hovered/active state is temporary + wxPoint arrow_points[3]; + switch ( style & wxRIBBON_SCROLL_BTN_DIRECTION_MASK ) + { + case wxRIBBON_SCROLL_BTN_LEFT: + arrow_points[0] = wxPoint(rect.width / 2 - 2, rect.height / 2); + if ( style & wxRIBBON_SCROLL_BTN_ACTIVE ) + arrow_points[0].y += 1; + arrow_points[1] = arrow_points[0] + wxPoint(3, -3); + arrow_points[2] = arrow_points[0] + wxPoint(3, 3); + break; + case wxRIBBON_SCROLL_BTN_RIGHT: + arrow_points[0] = wxPoint(rect.width / 2 + 2, rect.height / 2); + if ( style & wxRIBBON_SCROLL_BTN_ACTIVE ) + arrow_points[0].y += 1; + arrow_points[1] = arrow_points[0] - wxPoint(3, 3); + arrow_points[2] = arrow_points[0] - wxPoint(3, -3); + break; + case wxRIBBON_SCROLL_BTN_UP: + arrow_points[0] = wxPoint(rect.width / 2, rect.height / 2 - 2); + if ( style & wxRIBBON_SCROLL_BTN_ACTIVE ) + arrow_points[0].y += 1; + arrow_points[1] = arrow_points[0] + wxPoint( 3, 3); + arrow_points[2] = arrow_points[0] + wxPoint(-3, 3); + break; + case wxRIBBON_SCROLL_BTN_DOWN: + arrow_points[0] = wxPoint(rect.width / 2, rect.height / 2 + 2); + if ( style & wxRIBBON_SCROLL_BTN_ACTIVE ) + arrow_points[0].y += 1; + arrow_points[1] = arrow_points[0] - wxPoint( 3, 3); + arrow_points[2] = arrow_points[0] - wxPoint(-3, 3); + break; + } + + dc.SetPen(*wxTRANSPARENT_PEN); + wxBrush brush(style & wxRIBBON_SCROLL_BTN_HOVERED + ? m_tab_active_background_colour : m_tab_label_colour); + dc.SetBrush(brush); + dc.DrawPolygon(sizeof(arrow_points)/sizeof(wxPoint), arrow_points, + rect.x, rect.y); + } +} + +void wxRibbonMSWFlatArtProvider::DrawGalleryButton(wxDC& dc, + wxRect rect, + wxRibbonGalleryButtonState state, + wxBitmap* bitmaps) +{ + wxBitmap btn_bitmap; + wxColour btn_colour; + switch ( state ) + { + case wxRIBBON_GALLERY_BUTTON_NORMAL: + btn_colour = m_gallery_button_background_colour; + btn_bitmap = bitmaps[0]; + break; + case wxRIBBON_GALLERY_BUTTON_HOVERED: + btn_colour = m_gallery_button_hover_background_colour; + btn_bitmap = bitmaps[1]; + break; + case wxRIBBON_GALLERY_BUTTON_ACTIVE: + btn_colour = m_gallery_button_active_background_colour; + btn_bitmap = bitmaps[2]; + break; + case wxRIBBON_GALLERY_BUTTON_DISABLED: + btn_colour = m_gallery_button_disabled_background_colour; + btn_bitmap = bitmaps[3]; + break; + } + + rect.x++; + rect.y++; + if ( m_flags & wxRIBBON_BAR_FLOW_VERTICAL ) + { + rect.width--; + rect.height -= 2; + } + else + { + rect.width -= 2; + rect.height--; + } + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(btn_colour)); + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + + dc.DrawBitmap(btn_bitmap, rect.x + rect.width / 2 - 2, + rect.y + (rect.height / 2) - 2, true); +} + +void wxRibbonMSWFlatArtProvider::DrawGalleryItemBackground( + wxDC& dc, + wxRibbonGallery* wnd, + const wxRect& rect, + wxRibbonGalleryItem* item) +{ + if ( wnd->GetHoveredItem() != item && wnd->GetActiveItem() != item && + wnd->GetSelection() != item ) + return; + + dc.SetPen(m_gallery_item_border_pen); + dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y); + dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1); + dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, + rect.y + rect.height - 1); + dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, + rect.y + rect.height - 1); + + wxColour bg_colour; + + if ( wnd->GetActiveItem() == item || wnd->GetSelection() == item ) + bg_colour = m_gallery_button_active_background_colour; + else + bg_colour = m_gallery_button_hover_background_colour; + + wxRect inner(rect); + inner.x += 1; + inner.width -= 2; + inner.y += 1; + inner.height -= 2; + if ( inner.width > 0 && inner.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(bg_colour)); + dc.DrawRectangle(inner.x, inner.y, inner.width, inner.height); + } +} + +void wxRibbonMSWFlatArtProvider::DrawPanelBorder(wxDC& dc, const wxRect& rect, + wxPen& primary_colour, + wxPen& secondary_colour) +{ + wxUnusedVar(secondary_colour); + + const wxPoint border_points[] = { + {2, 0}, + {rect.width - 3, 0}, + {rect.width - 1, 2}, + {rect.width - 1, rect.height - 3}, + {rect.width - 3, rect.height - 1}, + {2, rect.height - 1}, + {0, rect.height - 3}, + {0, 2}, + {2, 0}, + }; + + dc.SetPen(primary_colour); + dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, + rect.x, rect.y); +} + +void wxRibbonMSWFlatArtProvider::DrawMinimisedPanel( + wxDC& dc, + wxRibbonPanel* wnd, + const wxRect& rect, + wxBitmap& bitmap) +{ + DrawPartialPageBackground(dc, wnd, rect, false); + + wxRect true_rect(rect); + RemovePanelPadding(&true_rect); + + if ( wnd->GetExpandedPanel() != nullptr ) + { + wxRect client_rect(true_rect); + client_rect.x++; + client_rect.width -= 2; + client_rect.y++; + client_rect.height = (true_rect.y + true_rect.height) - client_rect.y; + + if ( client_rect.width > 0 && client_rect.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_panel_active_background_colour)); + dc.DrawRectangle(client_rect.x, client_rect.y, + client_rect.width, client_rect.height); + } + } + else if ( wnd->IsHovered() ) + { + wxRect client_rect(true_rect); + client_rect.x++; + client_rect.width -= 2; + client_rect.y++; + client_rect.height -= 2; + if ( client_rect.width > 0 && client_rect.height > 0 ) + DrawPartialPageBackground(dc, wnd, client_rect, true); + } + + wxRect preview; + DrawMinimisedPanelCommon(dc, wnd, true_rect, &preview); + + dc.SetBrush(m_panel_hover_label_background_brush); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(preview.x + 1, preview.y + preview.height - 8, + preview.width - 2, 7); + + { + wxRect full_rect(preview); + full_rect.x += 1; + full_rect.y += 1; + full_rect.width -= 2; + full_rect.height -= 9; + + if ( full_rect.width > 0 && full_rect.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(m_page_hover_background_colour)); + dc.DrawRectangle(full_rect.x, full_rect.y, + full_rect.width, full_rect.height); + } + } + + if ( bitmap.IsOk() ) + { + dc.DrawBitmap(bitmap, preview.x + (preview.width - + bitmap.GetLogicalWidth()) / 2, + preview.y + (preview.height - 7 - + bitmap.GetLogicalHeight()) / 2, true); + } + + if ( !wnd->IsHovered() ) + DrawPanelBorder(dc, preview, m_panel_border_pen, + m_panel_border_gradient_pen); + else + DrawPanelBorder(dc, preview, m_panel_hover_border_pen, + m_panel_hover_border_gradient_pen); + + DrawPanelBorder(dc, true_rect, m_panel_minimised_border_pen, + m_panel_minimised_border_gradient_pen); +} + +void wxRibbonMSWFlatArtProvider::DrawButtonBarButton( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& rect, + wxRibbonButtonKind kind, + long state, + const wxString& label, + const wxBitmap& bitmap_large, + const wxBitmap& bitmap_small) +{ + if ( kind == wxRIBBON_BUTTON_TOGGLE ) + { + kind = wxRIBBON_BUTTON_NORMAL; + if ( state & wxRIBBON_BUTTONBAR_BUTTON_TOGGLED ) + state ^= wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK; + } + + if ( state & (wxRIBBON_BUTTONBAR_BUTTON_HOVER_MASK | + wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK) ) + { + if ( state & wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK ) + dc.SetPen(m_button_bar_active_border_pen); + else + dc.SetPen(m_button_bar_hover_border_pen); + + wxRect bg_rect(rect); + bg_rect.x++; + bg_rect.y++; + bg_rect.width -= 2; + bg_rect.height -= 2; + + if ( kind == wxRIBBON_BUTTON_HYBRID ) + { + switch ( state & wxRIBBON_BUTTONBAR_BUTTON_SIZE_MASK ) + { + case wxRIBBON_BUTTONBAR_BUTTON_LARGE: + { + int iYBorder = rect.y + bitmap_large.GetLogicalHeight() + 4; + wxRect partial_bg(rect); + if ( state & wxRIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED ) + { + partial_bg.SetBottom(iYBorder - 1); + } + else + { + partial_bg.height -= (iYBorder - partial_bg.y + 1); + partial_bg.y = iYBorder + 1; + } + dc.DrawLine(rect.x, iYBorder, rect.x + rect.width, + iYBorder); + bg_rect.Intersect(partial_bg); + } + break; + case wxRIBBON_BUTTONBAR_BUTTON_MEDIUM: + { + int iArrowWidth = 9; + if ( state & wxRIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED ) + { + bg_rect.width -= iArrowWidth; + dc.DrawLine(bg_rect.x + bg_rect.width, + rect.y, bg_rect.x + bg_rect.width, + rect.y + rect.height); + } + else + { + --iArrowWidth; + bg_rect.x += bg_rect.width - iArrowWidth; + bg_rect.width = iArrowWidth; + dc.DrawLine(bg_rect.x - 1, rect.y, + bg_rect.x - 1, rect.y + rect.height); + } + } + break; + case wxRIBBON_BUTTONBAR_BUTTON_SMALL: + break; + } + } + + wxColour bg_colour; + if ( state & wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK ) + bg_colour = m_button_bar_active_background_colour; + else + bg_colour = m_button_bar_hover_background_colour; + + if ( bg_rect.width > 0 && bg_rect.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(bg_colour)); + dc.DrawRectangle(bg_rect.x, bg_rect.y, + bg_rect.width, bg_rect.height); + } + + const wxPoint border_points[] = { + {2, 0}, + {rect.width - 3, 0}, + {rect.width - 1, 2}, + {rect.width - 1, rect.height - 3}, + {rect.width - 3, rect.height - 1}, + {2, rect.height - 1}, + {0, rect.height - 3}, + {0, 2}, + {2, 0}, + }; + + if ( state & wxRIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK ) + dc.SetPen(m_button_bar_active_border_pen); + else + dc.SetPen(m_button_bar_hover_border_pen); + + dc.DrawLines(sizeof(border_points)/sizeof(wxPoint), border_points, + rect.x, rect.y); + } + + dc.SetFont(m_button_bar_label_font); + dc.SetTextForeground(state & wxRIBBON_BUTTONBAR_BUTTON_DISABLED + ? m_button_bar_label_disabled_colour + : m_button_bar_label_colour); + DrawButtonBarButtonForeground(dc, rect, kind, state, label, bitmap_large, + bitmap_small); +} + +void wxRibbonMSWFlatArtProvider::DrawTabSeparator( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + double visibility) +{ + if ( visibility <= 0.0 ) + { + return; + } + if ( visibility > 1.0 ) + { + visibility = 1.0; + } + + if ( !m_cached_tab_separator.IsOk() || m_cached_tab_separator.GetLogicalSize() != rect.GetSize() || visibility != m_cached_tab_separator_visibility ) + { + wxRect size(rect.GetSize()); + ReallyDrawTabSeparator(wnd, size, visibility); + } + dc.DrawBitmap(m_cached_tab_separator, rect.x, rect.y, false); +} + +void wxRibbonMSWFlatArtProvider::DrawPartialPageBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + bool allow_hovered) +{ + // Assume the window is a child of a ribbon page, and also check for a + // hovered panel somewhere between the window and the page, as it causes + // the background to change. + wxPoint offset(wnd->GetPosition()); + wxRibbonPage* page = nullptr; + wxWindow* parent = wnd->GetParent(); + wxRibbonPanel* panel = wxDynamicCast(wnd, wxRibbonPanel); + bool hovered = false; + + if ( panel != nullptr ) + { + hovered = allow_hovered && panel->IsHovered(); + if ( panel->GetExpandedDummy() != nullptr ) + { + offset = panel->GetExpandedDummy()->GetPosition(); + parent = panel->GetExpandedDummy()->GetParent(); + } + } + for ( ; parent; parent = parent->GetParent() ) + { + if ( panel == nullptr ) + { + panel = wxDynamicCast(parent, wxRibbonPanel); + if ( panel != nullptr ) + { + hovered = allow_hovered && panel->IsHovered(); + if ( panel->GetExpandedDummy() != nullptr ) + { + parent = panel->GetExpandedDummy(); + } + } + } + page = wxDynamicCast(parent, wxRibbonPage); + if ( page != nullptr ) + { + break; + } + offset += parent->GetPosition(); + } + if ( page != nullptr ) + { + DrawPartialPageBackground(dc, wnd, rect, page, offset, hovered); + return; + } + + // No page found - fallback to painting with a stock brush + dc.SetBrush(*wxWHITE_BRUSH); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); +} + +void wxRibbonMSWFlatArtProvider::DrawPanelBackground( + wxDC& dc, + wxRibbonPanel* wnd, + const wxRect& rect) +{ + DrawPartialPageBackground(dc, wnd, rect, false); + + wxRect true_rect(rect); + RemovePanelPadding(&true_rect); + bool has_ext_button = wnd->HasExtButton(); + + int label_height; + { + dc.SetFont(m_panel_label_font); + dc.SetPen(*wxTRANSPARENT_PEN); + if ( wnd->IsHovered() ) + { + dc.SetBrush(m_panel_hover_label_background_brush); + dc.SetTextForeground(m_panel_hover_label_colour); + } + else + { + dc.SetBrush(m_panel_label_background_brush); + dc.SetTextForeground(m_panel_label_colour); + } + + wxRect label_rect(true_rect); + wxString label = wnd->GetLabel(); + bool clip_label = false; + wxSize label_size(dc.GetTextExtent(label)); + + label_rect.SetX(label_rect.GetX() + 1); + label_rect.SetWidth(label_rect.GetWidth() - 2); + label_rect.SetHeight(label_size.GetHeight() + 2); + label_rect.SetY(true_rect.GetBottom() - label_rect.GetHeight()); + label_height = label_rect.GetHeight(); + + wxRect label_bg_rect = label_rect; + + if ( has_ext_button ) + label_rect.SetWidth(label_rect.GetWidth() - 13); + + if ( label_size.GetWidth() > label_rect.GetWidth() ) + { + // Test if there is enough length for 3 letters and ... + wxString new_label = label.Mid(0, 3) + "..."; + label_size = dc.GetTextExtent(new_label); + if ( label_size.GetWidth() > label_rect.GetWidth() ) + { + // Not enough room for three characters and ... + // Display the entire label and just crop it + clip_label = true; + } + else + { + // Room for some characters and ... + // Display as many characters as possible and append ... + for ( int len = static_cast(label.Len()) - 1; len >= 3; --len ) + { + new_label = label.Mid(0, len) + "..."; + label_size = dc.GetTextExtent(new_label); + if ( label_size.GetWidth() <= label_rect.GetWidth() ) + { + label = new_label; + break; + } + } + } + } + + dc.DrawRectangle(label_bg_rect); + if ( clip_label ) + { + wxDCClipper clip(dc, label_rect); + dc.DrawText(label, label_rect.x, label_rect.y + + (label_rect.GetHeight() - label_size.GetHeight()) / 2); + } + else + { + dc.DrawText(label, label_rect.x + + (label_rect.GetWidth() - label_size.GetWidth()) / 2, + label_rect.y + + (label_rect.GetHeight() - label_size.GetHeight()) / 2); + } + + if ( has_ext_button ) + { + if ( wnd->IsExtButtonHovered() ) + { + dc.SetPen(m_panel_hover_button_border_pen); + dc.SetBrush(m_panel_hover_button_background_brush); + dc.DrawRoundedRectangle(label_rect.GetRight(), label_rect.GetBottom() - 13, 13, 13, 1.0); + dc.DrawBitmap(m_panel_extension_bitmap[1], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, true); + } + else + dc.DrawBitmap(m_panel_extension_bitmap[0], label_rect.GetRight() + 3, label_rect.GetBottom() - 10, true); + } + } + + if ( wnd->IsHovered() ) + { + wxRect client_rect(true_rect); + client_rect.x++; + client_rect.width -= 2; + client_rect.y++; + client_rect.height -= 2 + label_height; + if ( client_rect.width > 0 && client_rect.height > 0 ) + DrawPartialPageBackground(dc, wnd, client_rect, true); + } + + if ( !wnd->IsHovered() ) + DrawPanelBorder(dc, true_rect, m_panel_border_pen, m_panel_border_gradient_pen); + else + DrawPanelBorder(dc, true_rect, m_panel_hover_border_pen, m_panel_hover_border_gradient_pen); +} + +void wxRibbonMSWFlatArtProvider::DrawGalleryBackground( + wxDC& dc, + wxRibbonGallery* wnd, + const wxRect& rect) +{ + DrawPartialPageBackground(dc, wnd, rect); + + if ( wnd->IsHovered() ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(m_gallery_hover_background_brush); + if ( m_flags & wxRIBBON_BAR_FLOW_VERTICAL ) + { + dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, + rect.height - 16); + } + else + { + dc.DrawRectangle(rect.x + 1, rect.y + 1, rect.width - 16, + rect.height - 2); + } + } + + dc.SetPen(m_gallery_border_pen); + // Outline + dc.DrawLine(rect.x + 1, rect.y, rect.x + rect.width - 1, rect.y); + dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1); + dc.DrawLine(rect.x + 1, rect.y + rect.height - 1, rect.x + rect.width - 1, + rect.y + rect.height - 1); + dc.DrawLine(rect.x + rect.width - 1, rect.y + 1, rect.x + rect.width - 1, + rect.y + rect.height - 1); + + DrawGalleryBackgroundCommon(dc, wnd, rect); +} + +void wxRibbonMSWFlatArtProvider::DrawButtonBarBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) +{ + DrawPartialPageBackground(dc, wnd, rect, true); +} + +void wxRibbonMSWFlatArtProvider::DrawToolBarBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) +{ + DrawPartialPageBackground(dc, wnd, rect); +} + +void +wxRibbonMSWFlatArtProvider::DrawToggleButton(wxDC& dc, + wxRibbonBar* wnd, + const wxRect& rect, + wxRibbonDisplayMode mode) +{ + int bindex = 0; + DrawPartialPageBackground(dc, wnd, rect, false); + + dc.DestroyClippingRegion(); + dc.SetClippingRegion(rect); + + if ( wnd->IsToggleButtonHovered() ) + { + dc.SetPen(m_ribbon_toggle_pen); + dc.SetBrush(m_ribbon_toggle_brush); + dc.DrawRoundedRectangle(rect.GetX(), rect.GetY(), 20, 20, 1.0); + bindex = 1; + } + switch ( mode ) + { + case wxRIBBON_BAR_PINNED: + dc.DrawBitmap(m_ribbon_toggle_up_bitmap[bindex], rect.GetX()+7, rect.GetY()+6, true); + break; + case wxRIBBON_BAR_MINIMIZED: + dc.DrawBitmap(m_ribbon_toggle_down_bitmap[bindex], rect.GetX()+7, rect.GetY()+6, true); + break; + case wxRIBBON_BAR_EXPANDED: + dc.DrawBitmap(m_ribbon_toggle_pin_bitmap[bindex], rect.GetX()+4, rect.GetY()+5, true); + break; + } +} + +void wxRibbonMSWFlatArtProvider::DrawHelpButton(wxDC& dc, + wxRibbonBar* wnd, + const wxRect& rect) +{ + DrawPartialPageBackground(dc, wnd, rect, false); + + dc.DestroyClippingRegion(); + dc.SetClippingRegion(rect); + + if ( wnd->IsHelpButtonHovered() ) + { + dc.SetPen(m_ribbon_toggle_pen); + dc.SetBrush(m_ribbon_toggle_brush); + dc.DrawRoundedRectangle(rect.GetX(), rect.GetY(), 20, 20, 1.0); + dc.DrawBitmap(m_ribbon_bar_help_button_bitmap[1], rect.GetX()+4, rect.GetY()+5, true); + } + else + { + dc.DrawBitmap(m_ribbon_bar_help_button_bitmap[0], rect.GetX()+4, rect.GetY()+5, true); + } +} + +void wxRibbonMSWFlatArtProvider::DrawTool( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& rect, + const wxBitmap& bitmap, + wxRibbonButtonKind kind, + long state) +{ + if ( kind == wxRIBBON_BUTTON_TOGGLE ) + { + if ( state & wxRIBBON_TOOLBAR_TOOL_TOGGLED ) + state ^= wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK; + } + + wxRect bg_rect(rect); + bg_rect.Deflate(1); + if ( (state & wxRIBBON_TOOLBAR_TOOL_LAST) == 0 ) + bg_rect.width++; + bool is_split_hybrid = (kind == wxRIBBON_BUTTON_HYBRID && (state & + (wxRIBBON_TOOLBAR_TOOL_HOVER_MASK | wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK))); + + // Background - single solid fill + wxColour bg_colour = m_tool_background_colour; + if ( state & wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK ) + bg_colour = m_tool_active_background_colour; + else if ( state & wxRIBBON_TOOLBAR_TOOL_HOVER_MASK ) + bg_colour = m_tool_hover_background_colour; + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(bg_colour)); + dc.DrawRectangle(bg_rect.x, bg_rect.y, bg_rect.width, bg_rect.height); + + if ( is_split_hybrid ) + { + wxRect nonrect(bg_rect); + if ( state & (wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED | + wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE) ) + { + nonrect.width -= 8; + } + else + { + nonrect.x += nonrect.width - 8; + nonrect.width = 8; + } + wxBrush B(m_tool_hover_background_top_colour); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(B); + dc.DrawRectangle(nonrect.x, nonrect.y, nonrect.width, nonrect.height); + } + + // Border + dc.SetPen(m_toolbar_border_pen); + if ( state & wxRIBBON_TOOLBAR_TOOL_FIRST ) + { + dc.DrawPoint(rect.x + 1, rect.y + 1); + dc.DrawPoint(rect.x + 1, rect.y + rect.height - 2); + } + else + dc.DrawLine(rect.x, rect.y + 1, rect.x, rect.y + rect.height - 1); + + if ( state & wxRIBBON_TOOLBAR_TOOL_LAST ) + { + dc.DrawPoint(rect.x + rect.width - 2, rect.y + 1); + dc.DrawPoint(rect.x + rect.width - 2, rect.y + rect.height - 2); + } + + // Foreground + int avail_width = bg_rect.GetWidth(); + if ( kind & wxRIBBON_BUTTON_DROPDOWN ) + { + avail_width -= 8; + if ( is_split_hybrid ) + { + dc.DrawLine(rect.x + avail_width + 1, rect.y, + rect.x + avail_width + 1, rect.y + rect.height); + } + dc.DrawBitmap(m_toolbar_drop_bitmap, bg_rect.x + avail_width + 2, + bg_rect.y + (bg_rect.height / 2) - 2, true); + } + dc.DrawBitmap(bitmap, bg_rect.x + (avail_width - bitmap.GetLogicalWidth()) / 2, + bg_rect.y + (bg_rect.height - bitmap.GetLogicalHeight()) / 2, true); +} + +#endif // wxUSE_RIBBON diff --git a/src/ribbon/descrip.mms b/src/ribbon/descrip.mms index 3d5f93f7a7..31ee4118b0 100644 --- a/src/ribbon/descrip.mms +++ b/src/ribbon/descrip.mms @@ -43,11 +43,11 @@ CC_DEFINE = .c.obj : cc $(CFLAGS)$(CC_DEFINE) $(MMS$TARGET_NAME).c -OBJECTS=art_aui.obj,art_internal.obj,art_msw.obj,bar.obj,buttonbar.obj,\ +OBJECTS=art_aui.obj,art_internal.obj,art_msw.obj,art_msw_flat.obj,bar.obj,buttonbar.obj,\ control_ribbon.obj,gallery.obj,page.obj,panel.obj,\ toolbar_ribbon.obj -SOURCES=art_aui.cpp art_internal.cpp art_msw.cpp bar.cpp buttonbar.cpp\ +SOURCES=art_aui.cpp art_internal.cpp art_msw.cpp art_msw_flat.cpp bar.cpp buttonbar.cpp\ control.cpp gallery.cpp page.cpp panel.cpp toolbar.cpp all : $(SOURCES) @@ -73,6 +73,7 @@ $(OBJECTS) : [--.include.wx]setup.h art_aui.obj : art_aui.cpp art_internal.obj : art_internal.cpp art_msw.obj : art_msw.cpp +art_msw_flat.obj : art_msw_flat.cpp bar.obj : bar.cpp buttonbar.obj : buttonbar.cpp control_ribbon.obj : control.cpp