diff --git a/Makefile.in b/Makefile.in index a996c31157..b72e564934 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4581,7 +4581,8 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS = \ monodll_datavgen.o \ monodll_editlbox.o \ monodll_laywin.o \ - monodll_calctrlg.o + monodll_calctrlg.o \ + monodll_rowheightcache.o @COND_USE_GUI_1_WXUNIV_0@__CORE_SRC_OBJECTS = $(COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS) COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS = \ $(__LOWLEVEL_SRC_OBJECTS_1) \ @@ -4841,7 +4842,8 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS = \ monodll_datavgen.o \ monodll_editlbox.o \ monodll_laywin.o \ - monodll_calctrlg.o + monodll_calctrlg.o \ + monodll_rowheightcache.o @COND_USE_GUI_1_WXUNIV_1@__CORE_SRC_OBJECTS = $(COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS) COND_TOOLKIT_DFB___LOWLEVEL_SRC_OBJECTS = \ monodll_fontmgrcmn.o \ @@ -6557,7 +6559,8 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_1 = \ monolib_datavgen.o \ monolib_editlbox.o \ monolib_laywin.o \ - monolib_calctrlg.o + monolib_calctrlg.o \ + monolib_rowheightcache.o @COND_USE_GUI_1_WXUNIV_0@__CORE_SRC_OBJECTS_1 = $(COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_1) COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_1 = \ $(__LOWLEVEL_SRC_OBJECTS_3) \ @@ -6817,7 +6820,8 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_1 = \ monolib_datavgen.o \ monolib_editlbox.o \ monolib_laywin.o \ - monolib_calctrlg.o + monolib_calctrlg.o \ + monolib_rowheightcache.o @COND_USE_GUI_1_WXUNIV_1@__CORE_SRC_OBJECTS_1 = $(COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_1) COND_TOOLKIT_DFB___LOWLEVEL_SRC_OBJECTS_2 = \ monolib_fontmgrcmn.o \ @@ -8680,7 +8684,8 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_2 = \ coredll_datavgen.o \ coredll_editlbox.o \ coredll_laywin.o \ - coredll_calctrlg.o + coredll_calctrlg.o \ + coredll_rowheightcache.o @COND_USE_GUI_1_WXUNIV_0@__CORE_SRC_OBJECTS_2 = $(COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_2) COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_2 = \ $(__LOWLEVEL_SRC_OBJECTS_5) \ @@ -8940,7 +8945,8 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_2 = \ coredll_datavgen.o \ coredll_editlbox.o \ coredll_laywin.o \ - coredll_calctrlg.o + coredll_calctrlg.o \ + coredll_rowheightcache.o @COND_USE_GUI_1_WXUNIV_1@__CORE_SRC_OBJECTS_2 = $(COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_2) COND_TOOLKIT_DFB___LOWLEVEL_SRC_OBJECTS_4 = \ coredll_fontmgrcmn.o \ @@ -10398,7 +10404,8 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_3 = \ corelib_datavgen.o \ corelib_editlbox.o \ corelib_laywin.o \ - corelib_calctrlg.o + corelib_calctrlg.o \ + corelib_rowheightcache.o @COND_USE_GUI_1_WXUNIV_0@__CORE_SRC_OBJECTS_3 = $(COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_3) COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_3 = \ $(__LOWLEVEL_SRC_OBJECTS_7) \ @@ -10658,7 +10665,8 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_3 = \ corelib_datavgen.o \ corelib_editlbox.o \ corelib_laywin.o \ - corelib_calctrlg.o + corelib_calctrlg.o \ + corelib_rowheightcache.o @COND_USE_GUI_1_WXUNIV_1@__CORE_SRC_OBJECTS_3 = $(COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_3) COND_TOOLKIT_DFB___LOWLEVEL_SRC_OBJECTS_6 = \ corelib_fontmgrcmn.o \ @@ -20700,6 +20708,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@monodll_calctrlg.o: $(srcdir)/src/generic/calctrlg.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/generic/calctrlg.cpp +@COND_USE_GUI_1@monodll_rowheightcache.o: $(srcdir)/src/generic/rowheightcache.cpp $(MONODLL_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/generic/rowheightcache.cpp + @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monodll_osx_cocoa_mediactrl.o: $(srcdir)/src/osx/cocoa/mediactrl.mm $(MONODLL_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/mediactrl.mm @@ -25953,6 +25964,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@monolib_calctrlg.o: $(srcdir)/src/generic/calctrlg.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/generic/calctrlg.cpp +@COND_USE_GUI_1@monolib_rowheightcache.o: $(srcdir)/src/generic/rowheightcache.cpp $(MONOLIB_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/generic/rowheightcache.cpp + @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@monolib_osx_cocoa_mediactrl.o: $(srcdir)/src/osx/cocoa/mediactrl.mm $(MONOLIB_ODEP) @COND_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/mediactrl.mm @@ -31299,6 +31313,9 @@ coredll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(COREDLL_ODEP) @COND_USE_GUI_1@coredll_calctrlg.o: $(srcdir)/src/generic/calctrlg.cpp $(COREDLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/generic/calctrlg.cpp +@COND_USE_GUI_1@coredll_rowheightcache.o: $(srcdir)/src/generic/rowheightcache.cpp $(COREDLL_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/generic/rowheightcache.cpp + corelib_event.o: $(srcdir)/src/common/event.cpp $(CORELIB_ODEP) $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/event.cpp @@ -35547,6 +35564,9 @@ corelib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(CORELIB_ODEP) @COND_USE_GUI_1@corelib_calctrlg.o: $(srcdir)/src/generic/calctrlg.cpp $(CORELIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/generic/calctrlg.cpp +@COND_USE_GUI_1@corelib_rowheightcache.o: $(srcdir)/src/generic/rowheightcache.cpp $(CORELIB_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/generic/rowheightcache.cpp + advdll_version_rc.o: $(srcdir)/src/msw/version.rc $(ADVDLL_ODEP) $(WINDRES) -i$< -o$@ --define __WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p_67) $(__DEBUG_DEFINE_p_66) $(__EXCEPTIONS_DEFINE_p_65) $(__RTTI_DEFINE_p_65) $(__THREAD_DEFINE_p_65) --define WXBUILDING --define WXDLLNAME=$(WXDLLNAMEPREFIXGUI)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_adv$(WXCOMPILER)$(VENDORTAG)$(WXDLLVERSIONTAG) $(__RCDEFDIR_p) --include-dir $(top_srcdir)/include $(__INC_TIFF_BUILD_p_66) $(__INC_TIFF_p_66) $(__INC_JPEG_p_66) $(__INC_PNG_p_65) $(__INC_ZLIB_p_67) $(__INC_REGEX_p_65) $(__INC_EXPAT_p_65) --define WXUSINGDLL --define WXMAKINGDLL_ADV diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 3f84e21ae5..6001ccbd34 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -1005,6 +1005,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/generic/editlbox.cpp src/generic/laywin.cpp src/generic/calctrlg.cpp + src/generic/rowheightcache.cpp wx/affinematrix2dbase.h diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index 3111a384c2..c126d0f237 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -908,6 +908,7 @@ set(GUI_CMN_SRC src/generic/wizard.cpp src/generic/editlbox.cpp src/generic/datavgen.cpp + src/generic/rowheightcache.cpp ) set(GUI_CMN_HDR diff --git a/build/files b/build/files index d774633b94..13a542b9c9 100644 --- a/build/files +++ b/build/files @@ -899,6 +899,7 @@ GUI_CMN_SRC = src/generic/renderg.cpp src/generic/richmsgdlgg.cpp src/generic/richtooltipg.cpp + src/generic/rowheightcache.cpp src/generic/sashwin.cpp src/generic/scrlwing.cpp src/generic/selstore.cpp diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index 61a863bb2b..4b00f027de 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -2126,7 +2126,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.obj \ $(OBJS)\monodll_editlbox.obj \ $(OBJS)\monodll_laywin.obj \ - $(OBJS)\monodll_calctrlg.obj + $(OBJS)\monodll_calctrlg.obj \ + $(OBJS)\monodll_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_OBJECTS = \ @@ -2451,7 +2452,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.obj \ $(OBJS)\monodll_editlbox.obj \ $(OBJS)\monodll_laywin.obj \ - $(OBJS)\monodll_calctrlg.obj + $(OBJS)\monodll_calctrlg.obj \ + $(OBJS)\monodll_rowheightcache.obj !endif !if "$(USE_STC)" == "1" ____MONOLIB_STC_SRC_FILENAMES_OBJECTS = \ @@ -2955,7 +2957,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.obj \ $(OBJS)\monolib_editlbox.obj \ $(OBJS)\monolib_laywin.obj \ - $(OBJS)\monolib_calctrlg.obj + $(OBJS)\monolib_calctrlg.obj \ + $(OBJS)\monolib_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_1_OBJECTS = \ @@ -3280,7 +3283,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.obj \ $(OBJS)\monolib_editlbox.obj \ $(OBJS)\monolib_laywin.obj \ - $(OBJS)\monolib_calctrlg.obj + $(OBJS)\monolib_calctrlg.obj \ + $(OBJS)\monolib_rowheightcache.obj !endif !if "$(USE_STC)" == "1" ____MONOLIB_STC_SRC_FILENAMES_1_OBJECTS = \ @@ -3659,7 +3663,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.obj \ $(OBJS)\coredll_editlbox.obj \ $(OBJS)\coredll_laywin.obj \ - $(OBJS)\coredll_calctrlg.obj + $(OBJS)\coredll_calctrlg.obj \ + $(OBJS)\coredll_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_2_OBJECTS = \ @@ -3984,7 +3989,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.obj \ $(OBJS)\coredll_editlbox.obj \ $(OBJS)\coredll_laywin.obj \ - $(OBJS)\coredll_calctrlg.obj + $(OBJS)\coredll_calctrlg.obj \ + $(OBJS)\coredll_rowheightcache.obj !endif !if "$(MONOLITHIC)" == "0" && "$(SHARED)" == "0" && "$(USE_GUI)" == "1" __corelib___depname = \ @@ -4329,7 +4335,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.obj \ $(OBJS)\corelib_editlbox.obj \ $(OBJS)\corelib_laywin.obj \ - $(OBJS)\corelib_calctrlg.obj + $(OBJS)\corelib_calctrlg.obj \ + $(OBJS)\corelib_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_3_OBJECTS = \ @@ -4654,7 +4661,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.obj \ $(OBJS)\corelib_editlbox.obj \ $(OBJS)\corelib_laywin.obj \ - $(OBJS)\corelib_calctrlg.obj + $(OBJS)\corelib_calctrlg.obj \ + $(OBJS)\corelib_rowheightcache.obj !endif !if "$(SHARED)" == "1" ____wxcore_namedll_DEP = $(__coredll___depname) @@ -8937,6 +8945,11 @@ $(OBJS)\monodll_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\monodll_version.res: ..\..\src\msw\version.rc brcc32 -32 -r -fo$@ -i$(BCCDIR)\include -d__WXMSW__ $(__WXUNIV_DEFINE_p_67) $(__DEBUG_DEFINE_p_66) $(__NDEBUG_DEFINE_p_65) $(__EXCEPTIONS_DEFINE_p_65) $(__RTTI_DEFINE_p_65) $(__THREAD_DEFINE_p_65) $(__UNICODE_DEFINE_p_67) -i$(SETUPHDIR) -i..\..\include $(____CAIRO_INCLUDEDIR_FILENAMES_4) -dWXBUILDING -dWXDLLNAME=wx$(PORTNAME)$(WXUNIVNAME)$(WX_VERSION_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)$(WXCOMPILER)$(VENDORTAG) -i$(BCCDIR)\include\windows\sdk -i..\..\src\tiff\libtiff -i..\..\src\jpeg -i..\..\src\png -i..\..\src\zlib -i..\..\src\regex -i..\..\src\expat\expat\lib -i..\..\src\stc\scintilla\include -i..\..\src\stc\scintilla\lexlib -i..\..\src\stc\scintilla\src -d__WX__ -dSCI_LEXER -dNO_CXX11_REGEX -dLINK_LEXERS -dwxUSE_BASE=1 -dWXMAKINGDLL ..\..\src\msw\version.rc @@ -11478,6 +11491,11 @@ $(OBJS)\monolib_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\basedll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) -q -c -P -o$@ $(BASEDLL_CXXFLAGS) -H ..\..\src\common\dummy.cpp @@ -13983,6 +14001,11 @@ $(OBJS)\coredll_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\coredll_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\corelib_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) -H ..\..\src\common\dummy.cpp @@ -15711,6 +15734,11 @@ $(OBJS)\corelib_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\corelib_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\advdll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) -q -c -P -o$@ $(ADVDLL_CXXFLAGS) -H ..\..\src\common\dummy.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 792e88f599..e96d680d75 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -2152,7 +2152,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.o \ $(OBJS)\monodll_editlbox.o \ $(OBJS)\monodll_laywin.o \ - $(OBJS)\monodll_calctrlg.o + $(OBJS)\monodll_calctrlg.o \ + $(OBJS)\monodll_rowheightcache.o endif endif ifeq ($(USE_GUI),1) @@ -2479,7 +2480,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.o \ $(OBJS)\monodll_editlbox.o \ $(OBJS)\monodll_laywin.o \ - $(OBJS)\monodll_calctrlg.o + $(OBJS)\monodll_calctrlg.o \ + $(OBJS)\monodll_rowheightcache.o endif endif ifeq ($(USE_STC),1) @@ -2987,7 +2989,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.o \ $(OBJS)\monolib_editlbox.o \ $(OBJS)\monolib_laywin.o \ - $(OBJS)\monolib_calctrlg.o + $(OBJS)\monolib_calctrlg.o \ + $(OBJS)\monolib_rowheightcache.o endif endif ifeq ($(USE_GUI),1) @@ -3314,7 +3317,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.o \ $(OBJS)\monolib_editlbox.o \ $(OBJS)\monolib_laywin.o \ - $(OBJS)\monolib_calctrlg.o + $(OBJS)\monolib_calctrlg.o \ + $(OBJS)\monolib_rowheightcache.o endif endif ifeq ($(USE_STC),1) @@ -3707,7 +3711,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.o \ $(OBJS)\coredll_editlbox.o \ $(OBJS)\coredll_laywin.o \ - $(OBJS)\coredll_calctrlg.o + $(OBJS)\coredll_calctrlg.o \ + $(OBJS)\coredll_rowheightcache.o endif endif ifeq ($(USE_GUI),1) @@ -4034,7 +4039,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.o \ $(OBJS)\coredll_editlbox.o \ $(OBJS)\coredll_laywin.o \ - $(OBJS)\coredll_calctrlg.o + $(OBJS)\coredll_calctrlg.o \ + $(OBJS)\coredll_rowheightcache.o endif endif ifeq ($(MONOLITHIC),0) @@ -4385,7 +4391,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.o \ $(OBJS)\corelib_editlbox.o \ $(OBJS)\corelib_laywin.o \ - $(OBJS)\corelib_calctrlg.o + $(OBJS)\corelib_calctrlg.o \ + $(OBJS)\corelib_rowheightcache.o endif endif ifeq ($(USE_GUI),1) @@ -4712,7 +4719,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.o \ $(OBJS)\corelib_editlbox.o \ $(OBJS)\corelib_laywin.o \ - $(OBJS)\corelib_calctrlg.o + $(OBJS)\corelib_calctrlg.o \ + $(OBJS)\corelib_rowheightcache.o endif endif ifeq ($(SHARED),1) @@ -9119,6 +9127,11 @@ $(OBJS)\monodll_calctrlg.o: ../../src/generic/calctrlg.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monodll_rowheightcache.o: ../../src/generic/rowheightcache.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +endif + $(OBJS)\monodll_version_rc.o: ../../src/msw/version.rc $(WINDRES) -i$< -o$@ --define __WXMSW__ $(__WXUNIV_DEFINE_p_67) $(__DEBUG_DEFINE_p_66) $(__NDEBUG_DEFINE_p_65) $(__EXCEPTIONS_DEFINE_p_65) $(__RTTI_DEFINE_p_65) $(__THREAD_DEFINE_p_65) $(__UNICODE_DEFINE_p_67) --include-dir $(SETUPHDIR) --include-dir ../../include $(__CAIRO_INCLUDEDIR_p) --define WXBUILDING --define WXDLLNAME=wx$(PORTNAME)$(WXUNIVNAME)$(WX_VERSION_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)$(WXCOMPILER)$(VENDORTAG) --include-dir ../../src/tiff/libtiff --include-dir ../../src/jpeg --include-dir ../../src/png --include-dir ../../src/zlib --include-dir ../../src/regex --include-dir ../../src/expat/expat/lib --include-dir ../../src/stc/scintilla/include --include-dir ../../src/stc/scintilla/lexlib --include-dir ../../src/stc/scintilla/src --define __WX__ --define SCI_LEXER --define NO_CXX11_REGEX --define LINK_LEXERS --define wxUSE_BASE=1 --define WXMAKINGDLL @@ -11660,6 +11673,11 @@ $(OBJS)\monolib_calctrlg.o: ../../src/generic/calctrlg.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monolib_rowheightcache.o: ../../src/generic/rowheightcache.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +endif + $(OBJS)\basedll_dummy.o: ../../src/common/dummy.cpp $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $< @@ -14165,6 +14183,11 @@ $(OBJS)\coredll_calctrlg.o: ../../src/generic/calctrlg.cpp $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\coredll_rowheightcache.o: ../../src/generic/rowheightcache.cpp + $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< +endif + $(OBJS)\corelib_dummy.o: ../../src/common/dummy.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< @@ -15893,6 +15916,11 @@ $(OBJS)\corelib_calctrlg.o: ../../src/generic/calctrlg.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\corelib_rowheightcache.o: ../../src/generic/rowheightcache.cpp + $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< +endif + $(OBJS)\advdll_dummy.o: ../../src/common/dummy.cpp $(CXX) -c -o $@ $(ADVDLL_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 6b918dd50d..b526facee5 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -2443,7 +2443,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.obj \ $(OBJS)\monodll_editlbox.obj \ $(OBJS)\monodll_laywin.obj \ - $(OBJS)\monodll_calctrlg.obj + $(OBJS)\monodll_calctrlg.obj \ + $(OBJS)\monodll_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_OBJECTS = \ @@ -2768,7 +2769,8 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_datavgen.obj \ $(OBJS)\monodll_editlbox.obj \ $(OBJS)\monodll_laywin.obj \ - $(OBJS)\monodll_calctrlg.obj + $(OBJS)\monodll_calctrlg.obj \ + $(OBJS)\monodll_rowheightcache.obj !endif !if "$(USE_STC)" == "1" ____MONOLIB_STC_SRC_FILENAMES_OBJECTS = \ @@ -3278,7 +3280,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.obj \ $(OBJS)\monolib_editlbox.obj \ $(OBJS)\monolib_laywin.obj \ - $(OBJS)\monolib_calctrlg.obj + $(OBJS)\monolib_calctrlg.obj \ + $(OBJS)\monolib_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_1_OBJECTS = \ @@ -3603,7 +3606,8 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_datavgen.obj \ $(OBJS)\monolib_editlbox.obj \ $(OBJS)\monolib_laywin.obj \ - $(OBJS)\monolib_calctrlg.obj + $(OBJS)\monolib_calctrlg.obj \ + $(OBJS)\monolib_rowheightcache.obj !endif !if "$(USE_STC)" == "1" ____MONOLIB_STC_SRC_FILENAMES_1_OBJECTS = \ @@ -4048,7 +4052,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.obj \ $(OBJS)\coredll_editlbox.obj \ $(OBJS)\coredll_laywin.obj \ - $(OBJS)\coredll_calctrlg.obj + $(OBJS)\coredll_calctrlg.obj \ + $(OBJS)\coredll_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_2_OBJECTS = \ @@ -4373,7 +4378,8 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_datavgen.obj \ $(OBJS)\coredll_editlbox.obj \ $(OBJS)\coredll_laywin.obj \ - $(OBJS)\coredll_calctrlg.obj + $(OBJS)\coredll_calctrlg.obj \ + $(OBJS)\coredll_rowheightcache.obj !endif !if "$(MONOLITHIC)" == "0" && "$(SHARED)" == "0" && "$(USE_GUI)" == "1" __corelib___depname = \ @@ -4724,7 +4730,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.obj \ $(OBJS)\corelib_editlbox.obj \ $(OBJS)\corelib_laywin.obj \ - $(OBJS)\corelib_calctrlg.obj + $(OBJS)\corelib_calctrlg.obj \ + $(OBJS)\corelib_rowheightcache.obj !endif !if "$(USE_GUI)" == "1" && "$(WXUNIV)" == "1" ____CORE_SRC_FILENAMES_3_OBJECTS = \ @@ -5049,7 +5056,8 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_datavgen.obj \ $(OBJS)\corelib_editlbox.obj \ $(OBJS)\corelib_laywin.obj \ - $(OBJS)\corelib_calctrlg.obj + $(OBJS)\corelib_calctrlg.obj \ + $(OBJS)\corelib_rowheightcache.obj !endif !if "$(SHARED)" == "1" ____wxcore_namedll_DEP = $(__coredll___depname) @@ -9646,6 +9654,11 @@ $(OBJS)\monodll_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\monodll_version.res: ..\..\src\msw\version.rc rc /fo$@ /d WIN32 $(____DEBUGRUNTIME_6) /d _CRT_SECURE_NO_DEPRECATE=1 /d _CRT_NON_CONFORMING_SWPRINTFS=1 /d _SCL_SECURE_NO_WARNINGS=1 $(__NO_VC_CRTDBG_p_72) /d __WXMSW__ $(__WXUNIV_DEFINE_p_67) $(__DEBUG_DEFINE_p_66) $(__NDEBUG_DEFINE_p_65) $(__EXCEPTIONS_DEFINE_p_65) $(__RTTI_DEFINE_p_65) $(__THREAD_DEFINE_p_65) $(__UNICODE_DEFINE_p_67) /i $(SETUPHDIR) /i ..\..\include $(____CAIRO_INCLUDEDIR_FILENAMES_4) /d WXBUILDING /d WXDLLNAME=wx$(PORTNAME)$(WXUNIVNAME)$(WX_VERSION_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)$(WXCOMPILER)$(VENDORTAG) /i ..\..\src\tiff\libtiff /i ..\..\src\jpeg /i ..\..\src\png /i ..\..\src\zlib /i ..\..\src\regex /i ..\..\src\expat\expat\lib /i ..\..\src\stc\scintilla\include /i ..\..\src\stc\scintilla\lexlib /i ..\..\src\stc\scintilla\src /d __WX__ /d SCI_LEXER /d NO_CXX11_REGEX /d LINK_LEXERS /d wxUSE_BASE=1 /d WXMAKINGDLL ..\..\src\msw\version.rc @@ -12187,6 +12200,11 @@ $(OBJS)\monolib_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\basedll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) /Ycwx/wxprec.h ..\..\src\common\dummy.cpp @@ -14692,6 +14710,11 @@ $(OBJS)\coredll_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\coredll_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\corelib_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) /Ycwx/wxprec.h ..\..\src\common\dummy.cpp @@ -16420,6 +16443,11 @@ $(OBJS)\corelib_calctrlg.obj: ..\..\src\generic\calctrlg.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\generic\calctrlg.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\corelib_rowheightcache.obj: ..\..\src\generic\rowheightcache.cpp + $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\generic\rowheightcache.cpp +!endif + $(OBJS)\advdll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) /c /nologo /TP /Fo$@ $(ADVDLL_CXXFLAGS) /Ycwx/wxprec.h ..\..\src\common\dummy.cpp diff --git a/build/msw/wx_core.vcxproj b/build/msw/wx_core.vcxproj index bf3ea86b5a..87c60a35e1 100644 --- a/build/msw/wx_core.vcxproj +++ b/build/msw/wx_core.vcxproj @@ -1061,6 +1061,7 @@ + diff --git a/build/msw/wx_core.vcxproj.filters b/build/msw/wx_core.vcxproj.filters index 7e17bd7ad0..83c265118a 100644 --- a/build/msw/wx_core.vcxproj.filters +++ b/build/msw/wx_core.vcxproj.filters @@ -603,6 +603,9 @@ Generic Sources + + Generic Sources + Generic Sources diff --git a/build/msw/wx_vc7_core.vcproj b/build/msw/wx_vc7_core.vcproj index a161fe794c..03c0a9c23e 100644 --- a/build/msw/wx_vc7_core.vcproj +++ b/build/msw/wx_vc7_core.vcproj @@ -1286,6 +1286,9 @@ + + diff --git a/build/msw/wx_vc8_core.vcproj b/build/msw/wx_vc8_core.vcproj index 701ec8da4e..6bd3bb2e76 100644 --- a/build/msw/wx_vc8_core.vcproj +++ b/build/msw/wx_vc8_core.vcproj @@ -2127,6 +2127,10 @@ RelativePath="..\..\src\generic\richtooltipg.cpp" > + + diff --git a/build/msw/wx_vc9_core.vcproj b/build/msw/wx_vc9_core.vcproj index c235625f90..6211764ce1 100644 --- a/build/msw/wx_vc9_core.vcproj +++ b/build/msw/wx_vc9_core.vcproj @@ -2123,6 +2123,10 @@ RelativePath="..\..\src\generic\richtooltipg.cpp" > + + diff --git a/docs/changes.txt b/docs/changes.txt index 44657da85c..ff9a427e8e 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -137,6 +137,7 @@ wxGTK: wxMSW: - Fix passing Unicode strings via wxIPC when using DDE. +- Improve wxDataViewCtrl performance with variable line heights (Jens Goepfert). 3.1.2: (released 2018-12-10) diff --git a/include/wx/generic/private/rowheightcache.h b/include/wx/generic/private/rowheightcache.h new file mode 100644 index 0000000000..9136a3863c --- /dev/null +++ b/include/wx/generic/private/rowheightcache.h @@ -0,0 +1,155 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/rowheightcache.h +// Purpose: height cache of rows in a dataview +// Author: Jens Goepfert (mail@jensgoepfert.de) +// Created: 2018-03-06 +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_ROWHEIGHTCACHE_H_ +#define _WX_PRIVATE_ROWHEIGHTCACHE_H_ + +#include "wx/hashmap.h" +#include "wx/vector.h" + +// struct describing a range of rows which contains rows .. +struct RowRange +{ + unsigned int from; + unsigned int to; +}; + +/** + A helper class that manages a set of RowRange objects. + + It stores the indices that are members of a group in a memory + efficient way. +*/ +class WXDLLIMPEXP_CORE RowRanges +{ +public: + /** + Adds a row index to this group by adding it to an existing RowRange + or by creating a new one. + */ + void Add(unsigned int row); + + /** + Removes a row index and all indices after idx from this group. + */ + void Remove(unsigned int row); + + /** + Checks whether a row index is contained in this group. + */ + bool Has(unsigned int row) const; + + /** + Returns the number of row indices that are contained in this group. + */ + unsigned int CountAll() const; + + /** + Returns the number of rows that are in this group before the given row + index. + + Not that this doesn't include the given row. + */ + unsigned int CountTo(unsigned int row) const; + + /** + Returns the size of the range. + + This is only used for testing and debugging. + */ + unsigned int GetSize() const { return m_ranges.size(); } + +private: + wxVector m_ranges; + + /** + If a new row index was inserted, Cleanup() checks if the neighbour + ranges of idx can includes the same row indices and discards + unnecessary RowRange objects. + */ + void CleanUp(unsigned int idx); +}; + +WX_DECLARE_HASH_MAP(unsigned int, RowRanges*, wxIntegerHash, wxIntegerEqual, + HeightToRowRangesMap); + +/** + HeightCache implements a cache mechanism for wxDataViewCtrl. + + It gives fast access to: + * the height of one line (GetLineHeight) + * the y-coordinate where a row starts (GetLineStart) + * and vice versa (GetLineAt) + + The layout of the cache is a hashmap where the keys are all existing row + heights in pixels. The values are RowRange objects that represent all rows + having the specified height. + + An example: + @code + { + 22: RowRange([0..10], [15..17], [20..2000]), + 42: RowRange([11..12], [18..18]), + 62: RowRange([13..14], [19..19]) + } + @endcode + + Examples + ======== + + GetLineStart + ------------ + To retrieve the y-coordinate of item 1000 it is necessary to look into + each key of the hashmap *m_heightToRowRange*. Get the row count of + indices lower than 1000 (RowRange::CountTo) and multiplies it which the + according height. + + RowRange([0..10], [15..17], [20..2000]).CountTo(1000) + --> 0..10 are 11 items, 15..17 are 3 items and 20..1000 are 980 items (1000-20) + = 11 + 3 + 980 = 994 items + + GetLineStart(1000) --> (22 * 994) + (42 * 3) + (62 * 3) = 22180 + + GetLineHeight + ------------- + To retrieve the line height look into each key and check if row is + contained in RowRange (RowRange::Has) + + GetLineAt + --------- + To retrieve the row that starts at a specific y-coordinate. + Look into each key and count all rows. + Use bisect algorithm in combination with GetLineStart() to + find the appropriate item +*/ +class WXDLLIMPEXP_CORE HeightCache +{ +public: + ~HeightCache(); + bool GetLineStart(unsigned int row, int& start); + bool GetLineHeight(unsigned int row, int& height); + bool GetLineAt(int y, unsigned int& row); + bool GetLineInfo(unsigned int row, int &start, int &height); + + void Put(unsigned int row, int height); + + /** + Removes the stored height of the given row from the cache and + invalidates all cached rows (including the given one). + */ + void Remove(unsigned int row); + + void Clear(); + +private: + HeightToRowRangesMap m_heightToRowRange; +}; + + +#endif // _WX_PRIVATE_ROWHEIGHTCACHE_H_ diff --git a/samples/dataview/dataview.cpp b/samples/dataview/dataview.cpp index 9d654828d6..10d613e618 100644 --- a/samples/dataview/dataview.cpp +++ b/samples/dataview/dataview.cpp @@ -165,11 +165,12 @@ private: // the controls stored in the various tabs of the main notebook: - wxDataViewCtrl* m_ctrl[4]; + wxDataViewCtrl* m_ctrl[5]; // the models associated with the first two DVC: wxObjectDataPtr m_music_model; + wxObjectDataPtr m_long_music_model; wxObjectDataPtr m_list_model; // other data: @@ -287,6 +288,53 @@ private: }; +// ---------------------------------------------------------------------------- +// MultiLineCustomRenderer +// ---------------------------------------------------------------------------- + +class MultiLineCustomRenderer : public wxDataViewCustomRenderer +{ +public: + // a simple renderer that wraps each word on a new line + explicit MultiLineCustomRenderer() + : wxDataViewCustomRenderer("string", wxDATAVIEW_CELL_INERT, 0) + { } + + virtual bool Render(wxRect rect, wxDC *dc, int state) wxOVERRIDE + { + RenderText(m_value, 0, rect, dc, state); + return true; + } + + virtual wxSize GetSize() const wxOVERRIDE + { + wxSize txtSize = GetTextExtent(m_value); + int lines = m_value.Freq('\n') + 1; + txtSize.SetHeight(txtSize.GetHeight() * lines); + return txtSize; + } + + virtual bool SetValue(const wxVariant &value) wxOVERRIDE + { + m_value = value.GetString(); + m_value.Replace(" ", "\n"); + return true; + } + + virtual bool GetValue(wxVariant &WXUNUSED(value)) const wxOVERRIDE { return true; } + +#if wxUSE_ACCESSIBILITY + virtual wxString GetAccessibleDescription() const wxOVERRIDE + { + return m_value; + } +#endif // wxUSE_ACCESSIBILITY + +private: + wxString m_value; +}; + + // ============================================================================ // implementation // ============================================================================ @@ -459,6 +507,7 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int m_ctrl[1] = NULL; m_ctrl[2] = NULL; m_ctrl[3] = NULL; + m_ctrl[4] = NULL; m_eventFromProgram = false; @@ -606,6 +655,16 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int fourthPanelSz->Add(button_sizer4); fourthPanel->SetSizerAndFit(fourthPanelSz); + // fifth page of the notebook + // --------------------------- + + wxPanel *fifthPanel = new wxPanel(m_notebook, wxID_ANY); + + BuildDataViewCtrl(fifthPanel, 4); // sets m_ctrl[4] + + wxSizer *fifthPanelSz = new wxBoxSizer(wxVERTICAL); + fifthPanelSz->Add(m_ctrl[4], 1, wxGROW | wxALL, 5); + fifthPanel->SetSizerAndFit(fifthPanelSz); // complete GUI @@ -615,6 +674,7 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int m_notebook->AddPage(secondPanel, "MyListModel"); m_notebook->AddPage(thirdPanel, "wxDataViewListCtrl"); m_notebook->AddPage(fourthPanel, "wxDataViewTreeCtrl"); + m_notebook->AddPage(fifthPanel, "wxDataViewTreeCtrl Variable line height"); wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL); @@ -837,6 +897,35 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l tc->Expand(cont); } break; + + case 4: + { + wxASSERT(!m_ctrl[4] && !m_long_music_model); + m_ctrl[4] = + new wxDataViewCtrl( parent, wxID_ANY, wxDefaultPosition, + wxDefaultSize, style | wxDV_VARIABLE_LINE_HEIGHT ); + + m_long_music_model = new MyLongMusicTreeModel; + m_ctrl[4]->AssociateModel(m_long_music_model.get()); + + // column 0 of the view control: + MultiLineCustomRenderer *tr = + new MultiLineCustomRenderer(); + wxDataViewColumn *column0 = + new wxDataViewColumn("title", tr, 0, 200, wxALIGN_LEFT, + wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE); + m_ctrl[4]->AppendColumn(column0); + + // column 1 of the view control: + tr = new MultiLineCustomRenderer(); + wxDataViewColumn *column1 = + new wxDataViewColumn("artist", tr, 1, 150, wxALIGN_LEFT, + wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE | + wxDATAVIEW_COL_RESIZABLE); + column1->SetMinWidth(150); // this column can't be resized to be smaller + m_ctrl[4]->AppendColumn(column1); + } + break; } } @@ -1013,6 +1102,8 @@ void MyFrame::OnStyleChange( wxCommandEvent& WXUNUSED(event) ) m_music_model.reset(NULL); else if (nPanel == 1) m_list_model.reset(NULL); + else if (nPanel == 4) + m_long_music_model.reset(NULL); // rebuild the DVC for the selected panel: BuildDataViewCtrl((wxPanel*)m_notebook->GetPage(nPanel), nPanel, style); diff --git a/samples/dataview/mymodels.cpp b/samples/dataview/mymodels.cpp index fcffc59d69..e00ba68099 100644 --- a/samples/dataview/mymodels.cpp +++ b/samples/dataview/mymodels.cpp @@ -312,6 +312,19 @@ unsigned int MyMusicTreeModel::GetChildren( const wxDataViewItem &parent, } +// ---------------------------------------------------------------------------- +// MyLongMusicTreeModel +// ---------------------------------------------------------------------------- + +MyLongMusicTreeModel::MyLongMusicTreeModel() : MyMusicTreeModel() +{ + for (int i = 0; i < 50; i++) + { + AddToClassical("The Four Seasons", "Antonio Vivaldi", 1721); + AddToClassical("La costanza trionfante degl'amori e de gl'odii", "Antonio Vivaldi", 1716); + } +} + // ---------------------------------------------------------------------------- // MyListModel diff --git a/samples/dataview/mymodels.h b/samples/dataview/mymodels.h index 59d3c984a7..db089197a9 100644 --- a/samples/dataview/mymodels.h +++ b/samples/dataview/mymodels.h @@ -188,6 +188,17 @@ private: }; +// ---------------------------------------------------------------------------- +// MyLongMusicTreeModel +// ---------------------------------------------------------------------------- + +class MyLongMusicTreeModel : public MyMusicTreeModel +{ +public: + MyLongMusicTreeModel(); +}; + + // ---------------------------------------------------------------------------- // MyListModel // ---------------------------------------------------------------------------- diff --git a/src/generic/datavgen.cpp b/src/generic/datavgen.cpp index 8f3ebf7cd8..38ab4f7a60 100644 --- a/src/generic/datavgen.cpp +++ b/src/generic/datavgen.cpp @@ -53,6 +53,7 @@ #include "wx/stopwatch.h" #include "wx/weakref.h" #include "wx/generic/private/markuptext.h" +#include "wx/generic/private/rowheightcache.h" #include "wx/generic/private/widthcalc.h" #if wxUSE_ACCESSIBILITY #include "wx/private/markupparser.h" @@ -710,6 +711,9 @@ public: bool Cleared(); void Resort() { + if ( m_rowHeightCache ) + m_rowHeightCache->Clear(); + if (!IsVirtualList()) { m_root->Resort(this); @@ -822,6 +826,7 @@ public: int GetLineStart( unsigned int row ) const; // row * m_lineHeight in fixed mode int GetLineHeight( unsigned int row ) const; // m_lineHeight in fixed mode int GetLineAt( unsigned int y ) const; // y / m_lineHeight in fixed mode + int QueryAndCacheLineHeight(unsigned int row, wxDataViewItem item) const; void SetRowHeight( int lineHeight ) { m_lineHeight = lineHeight; } int GetRowHeight() const { return m_lineHeight; } @@ -911,6 +916,7 @@ private: bool m_hasFocus; bool m_useCellFocus; bool m_currentColSetByKeyboard; + HeightCache *m_rowHeightCache; #if wxUSE_DRAG_AND_DROP int m_dragCount; @@ -1947,6 +1953,14 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i m_useCellFocus = false; m_currentRow = (unsigned)-1; m_lineHeight = GetDefaultRowHeight(); + if (GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT)) + { + m_rowHeightCache = new HeightCache(); + } + else + { + m_rowHeightCache = NULL; + } #if wxUSE_DRAG_AND_DROP m_dragCount = 0; @@ -1983,6 +1997,7 @@ wxDataViewMainWindow::~wxDataViewMainWindow() { DestroyTree(); delete m_renameTimer; + delete m_rowHeightCache; } @@ -2740,6 +2755,12 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData } else { + if ( m_rowHeightCache ) + { + // specific position (row) is unclear, so clear whole height cache + m_rowHeightCache->Clear(); + } + wxDataViewTreeNode *parentNode = FindNode(parent); if ( !parentNode ) @@ -2881,6 +2902,9 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, return true; } + if ( m_rowHeightCache ) + m_rowHeightCache->Remove(GetRowByItem(parent) + itemPosInNode); + // Delete the item from wxDataViewTreeNode representation: const int itemsDeleted = 1 + itemNode->GetSubTreeCount(); @@ -2945,6 +2969,9 @@ bool wxDataViewMainWindow::DoItemChanged(const wxDataViewItem & item, int view_c { if ( !IsVirtualList() ) { + if ( m_rowHeightCache ) + m_rowHeightCache->Remove(GetRowByItem(item)); + // Move this node to its new correct place after it was updated. // // In principle, we could skip the call to PutInSortOrder() if the modified @@ -2995,6 +3022,9 @@ bool wxDataViewMainWindow::Cleared() m_selection.Clear(); m_currentRow = (unsigned)-1; + if ( m_rowHeightCache ) + m_rowHeightCache->Clear(); + if (GetModel()) { BuildTree( GetModel() ); @@ -3322,147 +3352,132 @@ wxRect wxDataViewMainWindow::GetLinesRect( unsigned int rowFrom, unsigned int ro int wxDataViewMainWindow::GetLineStart( unsigned int row ) const { - const wxDataViewModel *model = GetModel(); + // check for the easy case first + if ( !m_rowHeightCache || !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT) ) + return row * m_lineHeight; - if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) + int start = 0; + if ( m_rowHeightCache->GetLineStart(row, start) ) + return start; + + unsigned int r; + for (r = 0; r < row; r++) { - // TODO make more efficient - - int start = 0; - - unsigned int r; - for (r = 0; r < row; r++) + int height = 0; + if ( !m_rowHeightCache->GetLineHeight(r, height) ) { - const wxDataViewTreeNode* node = GetTreeNodeByRow(r); - if (!node) return start; + // row height not in cache -> get it from the renderer... + wxDataViewItem item = GetItemByRow(r); + if (!item) + break; - wxDataViewItem item = node->GetItem(); - - unsigned int cols = GetOwner()->GetColumnCount(); - unsigned int col; - int height = m_lineHeight; - for (col = 0; col < cols; col++) - { - const wxDataViewColumn *column = GetOwner()->GetColumn(col); - if (column->IsHidden()) - continue; // skip it! - - if ((col != 0) && - model->IsContainer(item) && - !model->HasContainerColumns(item)) - continue; // skip it! - - wxDataViewRenderer *renderer = - const_cast(column->GetRenderer()); - renderer->PrepareForItem(model, item, column->GetModelColumn()); - - height = wxMax( height, renderer->GetSize().y ); - } - - start += height; + height = QueryAndCacheLineHeight(r, item); } - return start; - } - else - { - return row * m_lineHeight; + start += height; } + + return start; } int wxDataViewMainWindow::GetLineAt( unsigned int y ) const { - const wxDataViewModel *model = GetModel(); - // check for the easy case first - if ( !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT) ) + if ( !m_rowHeightCache || !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT) ) return y / m_lineHeight; - // TODO make more efficient unsigned int row = 0; + if ( m_rowHeightCache->GetLineAt(y, row) ) + return row; + + // OnPaint asks GetLineAt for the very last y position and this is always + // below the last item (--> an invalid item). To prevent iterating over all + // items, check if y is below the last row. + // Because this is done very often (for each repaint) its worth to handle + // this special case separately. + int height = 0; + int start = 0; + unsigned int rowCount = GetRowCount(); + if (rowCount == 0 || + (m_rowHeightCache->GetLineInfo(rowCount - 1, start, height) && + y >= static_cast(start + height))) + { + return rowCount; + } + + // sum all item heights until y is reached unsigned int yy = 0; for (;;) { - const wxDataViewTreeNode* node = GetTreeNodeByRow(row); - if (!node) + height = 0; + if ( !m_rowHeightCache->GetLineHeight(row, height) ) { - // not really correct... - return row + ((y-yy) / m_lineHeight); - } + // row height not in cache -> get it from the renderer... + wxDataViewItem item = GetItemByRow(row); + if ( !item ) + { + wxASSERT(row >= GetRowCount()); + break; + } - wxDataViewItem item = node->GetItem(); - - unsigned int cols = GetOwner()->GetColumnCount(); - unsigned int col; - int height = m_lineHeight; - for (col = 0; col < cols; col++) - { - const wxDataViewColumn *column = GetOwner()->GetColumn(col); - if (column->IsHidden()) - continue; // skip it! - - if ((col != 0) && - model->IsContainer(item) && - !model->HasContainerColumns(item)) - continue; // skip it! - - wxDataViewRenderer *renderer = - const_cast(column->GetRenderer()); - renderer->PrepareForItem(model, item, column->GetModelColumn()); - - height = wxMax( height, renderer->GetSize().y ); + height = QueryAndCacheLineHeight(row, item); } yy += height; if (y < yy) - return row; + break; row++; } + return row; } int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const { - const wxDataViewModel *model = GetModel(); - - if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT) - { - wxASSERT( !IsVirtualList() ); - - const wxDataViewTreeNode* node = GetTreeNodeByRow(row); - // wxASSERT( node ); - if (!node) return m_lineHeight; - - wxDataViewItem item = node->GetItem(); - - int height = m_lineHeight; - - unsigned int cols = GetOwner()->GetColumnCount(); - unsigned int col; - for (col = 0; col < cols; col++) - { - const wxDataViewColumn *column = GetOwner()->GetColumn(col); - if (column->IsHidden()) - continue; // skip it! - - if ((col != 0) && - model->IsContainer(item) && - !model->HasContainerColumns(item)) - continue; // skip it! - - wxDataViewRenderer *renderer = - const_cast(column->GetRenderer()); - renderer->PrepareForItem(model, item, column->GetModelColumn()); - - height = wxMax( height, renderer->GetSize().y ); - } - - return height; - } - else - { + // check for the easy case first + if ( !m_rowHeightCache || !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT) ) return m_lineHeight; + + int height = 0; + if ( m_rowHeightCache->GetLineHeight(row, height) ) + return height; + + wxDataViewItem item = GetItemByRow(row); + if ( !item ) + return m_lineHeight; + + height = QueryAndCacheLineHeight(row, item); + return height; +} + +int wxDataViewMainWindow::QueryAndCacheLineHeight(unsigned int row, wxDataViewItem item) const +{ + const wxDataViewModel *model = GetModel(); + int height = m_lineHeight; + unsigned int cols = GetOwner()->GetColumnCount(); + unsigned int col; + for (col = 0; col < cols; col++) + { + const wxDataViewColumn *column = GetOwner()->GetColumn(col); + if (column->IsHidden()) + continue; // skip it! + + if ((col != 0) && + model->IsContainer(item) && + !model->HasContainerColumns(item)) + continue; // skip it! + + wxDataViewRenderer *renderer = + const_cast(column->GetRenderer()); + renderer->PrepareForItem(model, item, column->GetModelColumn()); + + height = wxMax(height, renderer->GetSize().y); } + + // ... and store the height in the cache + m_rowHeightCache->Put(row, height); + + return height; } @@ -3603,6 +3618,13 @@ void wxDataViewMainWindow::Expand( unsigned int row ) if (!node->HasChildren()) return; + if ( m_rowHeightCache ) + { + // Expand makes new rows visible thus we invalidates all following + // rows in the height cache + m_rowHeightCache->Remove(row); + } + if (!node->IsOpen()) { if ( !SendExpanderEvent(wxEVT_DATAVIEW_ITEM_EXPANDING, node->GetItem()) ) @@ -3652,6 +3674,13 @@ void wxDataViewMainWindow::Collapse(unsigned int row) if (!node->HasChildren()) return; + if ( m_rowHeightCache ) + { + // Collapse hides rows thus we invalidates all following + // rows in the height cache + m_rowHeightCache->Remove(row); + } + if (node->IsOpen()) { if ( !SendExpanderEvent(wxEVT_DATAVIEW_ITEM_COLLAPSING,node->GetItem()) ) diff --git a/src/generic/rowheightcache.cpp b/src/generic/rowheightcache.cpp new file mode 100644 index 0000000000..3eb0e68a24 --- /dev/null +++ b/src/generic/rowheightcache.cpp @@ -0,0 +1,332 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: generic/rowheightcache.cpp +// Purpose: height cache of rows in a dataview +// Author: Jens Goepfert (mail@jensgoepfert.de) +// Created: 2018-03-06 +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#endif // WX_PRECOMP + +#include "wx/generic/private/rowheightcache.h" + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// RowRanges +// ---------------------------------------------------------------------------- + +void RowRanges::Add(unsigned int row) +{ + size_t count = m_ranges.size(); + size_t rngIdx = 0; + for (rngIdx = 0; rngIdx < count; ++rngIdx) + { + RowRange &rng = m_ranges[rngIdx]; + + if (row >= rng.from && rng.to > row) + { + // index already in range + return; + } + + if (row == rng.from - 1) + { + // extend range at the beginning (to the left) + rng.from = row; + // no cleanup necessary + return; + } + if (row == rng.to) + { + // extend range at the end (set to row+1 because 'to' is not + // including) + rng.to = row + 1; + CleanUp(rngIdx); + return; + } + + if (rng.from > row + 1) + { + // this range is already behind row index, so break here and insert + // a new range before + break; + } + } + + RowRange newRange; + newRange.from = row; + newRange.to = row + 1; + m_ranges.insert(m_ranges.begin() + rngIdx, newRange); +} + +void RowRanges::Remove(unsigned int row) +{ + size_t count = m_ranges.size(); + size_t rngIdx = 0; + while (rngIdx < count) + { + RowRange &rng = m_ranges[rngIdx]; + if (rng.from >= row) + { + // this range starts behind row index, so remove it + m_ranges.erase(m_ranges.begin() + rngIdx); + count--; + continue; + } + if (rng.to > row) + { + // this ranges includes row, so cut off at row index to exclude row + rng.to = row; + } + + rngIdx += 1; + } +} + + +void RowRanges::CleanUp(unsigned int idx) +{ + size_t count = m_ranges.size(); + + wxCHECK_RET( idx < count, "Wrong index" ); + + size_t rngIdx = 0; + if (idx > 0) + { + // start one RowRange before + rngIdx = idx - 1; + } + + RowRange *prevRng = &m_ranges[rngIdx]; + rngIdx++; + while (rngIdx <= idx + 1 && rngIdx < count) + { + RowRange &rng = m_ranges[rngIdx]; + + if (prevRng->to == rng.from) + { + // this range starts where the previous range began, so remove this + // and set the to-value of the previous range to the to-value of + // this range + prevRng->to = rng.to; + m_ranges.erase(m_ranges.begin() + rngIdx); + count--; + continue; + } + + prevRng = &rng; + rngIdx += 1; + } +} + +bool RowRanges::Has(unsigned int row) const +{ + size_t count = m_ranges.size(); + for (size_t rngIdx = 0; rngIdx < count; rngIdx++) + { + const RowRange &rng = m_ranges[rngIdx]; + if (rng.from <= row && row < rng.to) + { + return true; + } + } + return false; +} + +unsigned int RowRanges::CountAll() const +{ + unsigned int ctr = 0; + size_t count = m_ranges.size(); + for (size_t rngIdx = 0; rngIdx < count; rngIdx++) + { + const RowRange &rng = m_ranges[rngIdx]; + ctr += rng.to - rng.from; + } + return ctr; +} + +unsigned int RowRanges::CountTo(unsigned int row) const +{ + unsigned int ctr = 0; + size_t count = m_ranges.size(); + for (size_t rngIdx = 0; rngIdx < count; rngIdx++) + { + const RowRange &rng = m_ranges[rngIdx]; + if (rng.from > row) + { + break; + } + else if (rng.to < row) + { + ctr += rng.to - rng.from; + } + else + { + ctr += row - rng.from; + break; + } + } + return ctr; +} + +// ---------------------------------------------------------------------------- +// HeightCache +// ---------------------------------------------------------------------------- + +bool HeightCache::GetLineInfo(unsigned int row, int &start, int &height) +{ + int y = 0; + bool found = false; + HeightToRowRangesMap::iterator it; + for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + { + int rowHeight = it->first; + RowRanges* rowRanges = it->second; + if (rowRanges->Has(row)) + { + height = rowHeight; + found = true; + } + y += rowHeight * (rowRanges->CountTo(row)); + } + if (found) + { + start = y; + } + return found; +} + +bool HeightCache::GetLineStart(unsigned int row, int &start) +{ + int height = 0; + return GetLineInfo(row, start, height); +} + +bool HeightCache::GetLineHeight(unsigned int row, int &height) +{ + HeightToRowRangesMap::iterator it; + for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + { + int rowHeight = it->first; + RowRanges* rowRanges = it->second; + if (rowRanges->Has(row)) + { + height = rowHeight; + return true; + } + } + return false; +} + +bool HeightCache::GetLineAt(int y, unsigned int &row) +{ + unsigned int total = 0; + HeightToRowRangesMap::iterator it; + for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + { + RowRanges* rowRanges = it->second; + total += rowRanges->CountAll(); + } + + if (total == 0) + { + return false; + } + + int lo = 0; + int hi = total; + int start, height; + while (lo < hi) + { + int mid = (lo + hi) / 2; + if (GetLineInfo(mid, start, height)) + { + if (start + height <= y) + { + lo = mid + 1; + } + else + { + hi = mid; + } + } + else + { + // should never happen, except the HeightCache has gaps which is an + // invalid state + return false; + } + } + if (GetLineInfo(lo, start, height)) + { + if (y < start) + { + // given y point is before the first row + return false; + } + row = lo; + return true; + } + else + { + // given y point is after the last row + return false; + } +} + +void HeightCache::Put(unsigned int row, int height) +{ + RowRanges *rowRanges = m_heightToRowRange[height]; + if (rowRanges == NULL) + { + rowRanges = new RowRanges(); + m_heightToRowRange[height] = rowRanges; + } + rowRanges->Add(row); +} + +void HeightCache::Remove(unsigned int row) +{ + HeightToRowRangesMap::iterator it; + for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + { + RowRanges* rowRanges = it->second; + rowRanges->Remove(row); + } +} + +void HeightCache::Clear() +{ + HeightToRowRangesMap::iterator it; + for (it = m_heightToRowRange.begin(); it != m_heightToRowRange.end(); ++it) + { + RowRanges* rowRanges = it->second; + delete rowRanges; + } + m_heightToRowRange.clear(); +} + +HeightCache::~HeightCache() +{ + Clear(); +} diff --git a/tests/Makefile.in b/tests/Makefile.in index 14e4f749e9..626269dfd7 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -255,6 +255,7 @@ TEST_GUI_OBJECTS = \ test_gui_socket.o \ test_gui_tlw.o \ test_gui_dataview.o \ + test_gui_rowheightcachetest.o \ test_gui_boxsizer.o \ test_gui_gridsizer.o \ test_gui_wrapsizer.o \ @@ -1038,6 +1039,9 @@ test_gui_tlw.o: $(srcdir)/persistence/tlw.cpp $(TEST_GUI_ODEP) test_gui_dataview.o: $(srcdir)/persistence/dataview.cpp $(TEST_GUI_ODEP) $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/persistence/dataview.cpp +test_gui_rowheightcachetest.o: $(srcdir)/rowheightcache/rowheightcachetest.cpp $(TEST_GUI_ODEP) + $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/rowheightcache/rowheightcachetest.cpp + test_gui_boxsizer.o: $(srcdir)/sizers/boxsizer.cpp $(TEST_GUI_ODEP) $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/sizers/boxsizer.cpp diff --git a/tests/makefile.bcc b/tests/makefile.bcc index 51c88f2ddd..51192463b0 100644 --- a/tests/makefile.bcc +++ b/tests/makefile.bcc @@ -242,6 +242,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_socket.obj \ $(OBJS)\test_gui_tlw.obj \ $(OBJS)\test_gui_dataview.obj \ + $(OBJS)\test_gui_rowheightcachetest.obj \ $(OBJS)\test_gui_boxsizer.obj \ $(OBJS)\test_gui_gridsizer.obj \ $(OBJS)\test_gui_wrapsizer.obj \ @@ -1093,6 +1094,9 @@ $(OBJS)\test_gui_tlw.obj: .\persistence\tlw.cpp $(OBJS)\test_gui_dataview.obj: .\persistence\dataview.cpp $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\persistence\dataview.cpp +$(OBJS)\test_gui_rowheightcachetest.obj: .\rowheightcache\rowheightcachetest.cpp + $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\rowheightcache\rowheightcachetest.cpp + $(OBJS)\test_gui_boxsizer.obj: .\sizers\boxsizer.cpp $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\sizers\boxsizer.cpp diff --git a/tests/makefile.gcc b/tests/makefile.gcc index c7894bdeb1..94d034dd80 100644 --- a/tests/makefile.gcc +++ b/tests/makefile.gcc @@ -237,6 +237,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_socket.o \ $(OBJS)\test_gui_tlw.o \ $(OBJS)\test_gui_dataview.o \ + $(OBJS)\test_gui_rowheightcachetest.o \ $(OBJS)\test_gui_boxsizer.o \ $(OBJS)\test_gui_gridsizer.o \ $(OBJS)\test_gui_wrapsizer.o \ @@ -1070,6 +1071,9 @@ $(OBJS)\test_gui_tlw.o: ./persistence/tlw.cpp $(OBJS)\test_gui_dataview.o: ./persistence/dataview.cpp $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\test_gui_rowheightcachetest.o: ./rowheightcache/rowheightcachetest.cpp + $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\test_gui_boxsizer.o: ./sizers/boxsizer.cpp $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $< diff --git a/tests/makefile.vc b/tests/makefile.vc index 5e104bd30e..95861401c6 100644 --- a/tests/makefile.vc +++ b/tests/makefile.vc @@ -248,6 +248,7 @@ TEST_GUI_OBJECTS = \ $(OBJS)\test_gui_socket.obj \ $(OBJS)\test_gui_tlw.obj \ $(OBJS)\test_gui_dataview.obj \ + $(OBJS)\test_gui_rowheightcachetest.obj \ $(OBJS)\test_gui_boxsizer.obj \ $(OBJS)\test_gui_gridsizer.obj \ $(OBJS)\test_gui_wrapsizer.obj \ @@ -1284,6 +1285,9 @@ $(OBJS)\test_gui_tlw.obj: .\persistence\tlw.cpp $(OBJS)\test_gui_dataview.obj: .\persistence\dataview.cpp $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\persistence\dataview.cpp +$(OBJS)\test_gui_rowheightcachetest.obj: .\rowheightcache\rowheightcachetest.cpp + $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\rowheightcache\rowheightcachetest.cpp + $(OBJS)\test_gui_boxsizer.obj: .\sizers\boxsizer.cpp $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\sizers\boxsizer.cpp diff --git a/tests/rowheightcache/rowheightcachetest.cpp b/tests/rowheightcache/rowheightcachetest.cpp new file mode 100644 index 0000000000..04085cc745 --- /dev/null +++ b/tests/rowheightcache/rowheightcachetest.cpp @@ -0,0 +1,275 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: tests/rowheightcache/rowheightcachetest.cpp +// Purpose: unit tests for the row height cache of a dataview +// Author: Jens Goepfert (mail@jensgoepfert.de) +// Created: 2018-03-06 +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "testprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#endif + +#include "wx/generic/private/rowheightcache.h" + +// ---------------------------------------------------------------------------- +// TestRowRangesAdd +// ---------------------------------------------------------------------------- +TEST_CASE("RowHeightCacheTestCase::TestRowRangesSimple", "[dataview][heightcache]") +{ + RowRanges rr; + + CHECK(rr.CountAll() == 0); + + for (unsigned int i = 0; i <= 10; i++) + { + CHECK(rr.Has(i) == false); + + rr.Add(i); + + CHECK(rr.CountAll() == i+1); + CHECK(rr.CountTo(i) == i); + CHECK(rr.Has(i) == true); + } + + CHECK(rr.GetSize() == 1); // every row is sorted in the same range, so count == 1 + CHECK(rr.CountAll() == 11); // 11 rows collected + CHECK(rr.CountTo(10) == 10); + + rr.Add(5); // row 5 already contained -> does nothing + + CHECK(rr.GetSize() == 1); // every row is sorted in the same range, so count == 1 + CHECK(rr.CountAll() == 11); // 11 rows collected + CHECK(rr.CountTo(10) == 10); + + for (int i = 10; i >= 0; i--) + { + CHECK(rr.CountAll() == (unsigned)i+1); + CHECK(rr.CountTo((unsigned)i) == (unsigned)i); + + rr.Remove(i); + + CHECK(rr.CountAll() == (unsigned)i); + CHECK(rr.CountTo((unsigned)i) == (unsigned)i); + } + + CHECK(rr.CountAll() == 0); // everything removed, no row range is left behind + for (int i = 10; i > 0; i--) + { + CHECK(rr.CountTo(i) == 0); + } + CHECK(rr.GetSize() == 0); +} + +// ---------------------------------------------------------------------------- +// TestRowRangesRemove +// ---------------------------------------------------------------------------- +TEST_CASE("RowHeightCacheTestCase::TestRowRangesGapsMod2", "[dataview][heightcache]") +{ + RowRanges rr; + for (int i = 0; i < 100; i++) + { + CHECK(rr.Has(i) == false); + + if (i % 2 == 0) + { + rr.Add(i); + } + } + CHECK(rr.CountAll() == 50); + CHECK(rr.CountTo(100) == 50); + + for (unsigned int i = 99; i > 0; i--) + { + if (i % 2 == 0) + { + CHECK(rr.Has(i) == true); + rr.Remove(i); + CHECK(rr.Has(i) == false); + } + else + { + CHECK(rr.Has(i) == false); + } + } + + // only row 0 is in the RowRanges, so remove 1 does nothing + rr.Remove(1); + + CHECK(rr.CountAll() == 1); + CHECK(rr.CountTo(0) == 0); + CHECK(rr.CountTo(1) == 1); + CHECK(rr.CountTo(100) == 1); + CHECK(rr.GetSize() == 1); + + rr.Remove(0); // last row is beeing removed + + CHECK(rr.CountAll() == 0); + CHECK(rr.CountTo(0) == 0); + CHECK(rr.CountTo(1) == 0); + CHECK(rr.CountTo(100) == 0); + CHECK(rr.GetSize() == 0); + + rr.Add(10); + CHECK(rr.GetSize() == 1); + CHECK(rr.CountTo(1) == 0); // tests CountTo first break + rr.Add(5); // inserts a range at the beginning + CHECK(rr.GetSize() == 2); + rr.Remove(10); + rr.Remove(5); + CHECK(rr.GetSize() == 0); +} + +// ---------------------------------------------------------------------------- +// TestRowRangesCleanUp1 +// ---------------------------------------------------------------------------- +TEST_CASE("RowHeightCacheTestCase::TestRowRangesCleanUp1", "[dataview][heightcache]") +{ + RowRanges rr; + for (unsigned int i = 0; i < 100; i++) + { + CHECK(rr.Has(i) == false); + + if (i % 2 == 0) + { + rr.Add(i); + } + } + CHECK(rr.GetSize() == 50); // adding 50 rows (only even) results in 50 range objects + CHECK(rr.CountAll() == 50); + CHECK(rr.CountTo(100) == 50); + + for (unsigned int i = 0; i < 100; i++) + { + if (i % 2 == 1) + { + rr.Add(i); + } + } + + CHECK(rr.GetSize() == 1); // adding 50 rows (only odd) should combined to 1 range object + CHECK(rr.CountAll() == 100); + CHECK(rr.CountTo(100) == 100); +} + +// ---------------------------------------------------------------------------- +// TestRowRangesCleanUp2 +// ---------------------------------------------------------------------------- +TEST_CASE("RowHeightCacheTestCase::TestRowRangesCleanUp2", "[dataview][heightcache]") +{ + RowRanges rr; + for (unsigned int i = 0; i < 10; i++) + { + rr.Add(i); + } + CHECK(rr.GetSize() == 1); // adding 10 sequent rows results in 1 range objects + CHECK(rr.CountAll() == 10); + CHECK(rr.CountTo(100) == 10); + + for (unsigned int i = 12; i < 20; i++) + { + rr.Add(i); + } + + CHECK(rr.GetSize() == 2); + rr.Add(11); // tests extending a range at the beginning (to the left) + CHECK(rr.GetSize() == 2); + rr.Add(10); // extends a range and reduces them + CHECK(rr.GetSize() == 1); +} + +// ---------------------------------------------------------------------------- +// TestHeightCache +// ---------------------------------------------------------------------------- +TEST_CASE("RowHeightCacheTestCase::TestHeightCache", "[dataview][heightcache]") +{ + HeightCache hc; + + for (unsigned int i = 0; i <= 10; i++) + { + hc.Put(i, 22); + } + for (unsigned int i = 15; i <= 17; i++) + { + hc.Put(i, 22); + } + for (unsigned int i = 20; i <= 2000; i++) + { + hc.Put(i, 22); + } + + hc.Put(11, 42); + hc.Put(12, 42); + hc.Put(18, 42); + + hc.Put(13, 62); + hc.Put(14, 62); + hc.Put(19, 62); + + int start = 0; + int height = 0; + unsigned int row = 666; + + CHECK(hc.GetLineStart(1000, start) == true); + CHECK(start == 22180); + + CHECK(hc.GetLineHeight(1000, height) == true); + CHECK(height == 22); + + CHECK(hc.GetLineHeight(5000, start) == false); + + // test invalid y + CHECK(hc.GetLineAt(-1, row) == false); + CHECK(row == 666); + + // test start of first row + CHECK(hc.GetLineAt(0, row) == true); + CHECK(row == 0); + + // test end of first row + CHECK(hc.GetLineAt(21, row) == true); + CHECK(row == 0); + + // test start of second row + CHECK(hc.GetLineAt(22, row) == true); + CHECK(row == 1); + + hc.Remove(1000); // Delete row 1000 and everything behind + + CHECK(hc.GetLineAt(22179, row) == true); + CHECK(row == 999); + CHECK(hc.GetLineHeight(999, height) == true); + CHECK(height == 22); + + row = 666; + height = 666; + CHECK(hc.GetLineAt(22180, row) == false); + CHECK(row == 666); + CHECK(hc.GetLineHeight(1000, height) == false); + CHECK(height == 666); + + hc.Clear(); // Clear all items + for (int i = 20; i <= 2000; i++) + { + height = 666; + CHECK(hc.GetLineHeight(i, height) == false); + CHECK(height == 666); + } + + hc.Clear(); // Clear twice should not crash + + row = 666; + height = 666; + CHECK(hc.GetLineAt(22180, row) == false); + CHECK(row == 666); +} diff --git a/tests/test.bkl b/tests/test.bkl index 8acc4145ff..52bf6e0e98 100644 --- a/tests/test.bkl +++ b/tests/test.bkl @@ -267,6 +267,7 @@ net/socket.cpp persistence/tlw.cpp persistence/dataview.cpp + rowheightcache/rowheightcachetest.cpp sizers/boxsizer.cpp sizers/gridsizer.cpp sizers/wrapsizer.cpp diff --git a/tests/test_vc7_test_gui.vcproj b/tests/test_vc7_test_gui.vcproj index 7f908ef8e5..5854a3b1a2 100644 --- a/tests/test_vc7_test_gui.vcproj +++ b/tests/test_vc7_test_gui.vcproj @@ -526,6 +526,9 @@ + + diff --git a/tests/test_vc8_test_gui.vcproj b/tests/test_vc8_test_gui.vcproj index 86ddb5dea7..6c61aa1c74 100644 --- a/tests/test_vc8_test_gui.vcproj +++ b/tests/test_vc8_test_gui.vcproj @@ -1170,6 +1170,10 @@ RelativePath=".\controls\richtextctrltest.cpp" > + + diff --git a/tests/test_vc9_test_gui.vcproj b/tests/test_vc9_test_gui.vcproj index 25d5167c03..85e5038f99 100644 --- a/tests/test_vc9_test_gui.vcproj +++ b/tests/test_vc9_test_gui.vcproj @@ -1142,6 +1142,10 @@ RelativePath=".\controls\richtextctrltest.cpp" > + +