From 0fa541e8706f74887efeba9e475eae618873da2a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 30 Jan 2009 21:38:29 +0000 Subject: [PATCH] add support for persistent controls git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58529 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- Makefile.in | 25 +++ build/bakefiles/files.bkl | 6 + build/msw/makefile.bcc | 28 +++ build/msw/makefile.gcc | 28 +++ build/msw/makefile.vc | 28 +++ build/msw/makefile.wat | 28 +++ build/msw/wx_core.dsp | 24 +++ build/msw/wx_vc7_core.vcproj | 18 ++ build/msw/wx_vc8_core.vcproj | 24 +++ build/msw/wx_vc9_core.vcproj | 24 +++ docs/changes.txt | 3 + docs/doxygen/mainpages/topics.h | 1 + docs/doxygen/overviews/persistence.h | 115 +++++++++++ include/wx/persist.h | 222 ++++++++++++++++++++++ include/wx/persist/bookctrl.h | 67 +++++++ include/wx/persist/toplevel.h | 129 +++++++++++++ include/wx/persist/treebook.h | 97 ++++++++++ include/wx/persist/window.h | 85 +++++++++ interface/wx/persist.h | 273 +++++++++++++++++++++++++++ interface/wx/persist/bookctrl.h | 47 +++++ interface/wx/persist/toplevel.h | 43 +++++ interface/wx/persist/treebook.h | 43 +++++ interface/wx/persist/window.h | 51 +++++ samples/widgets/widgets.cpp | 50 +++-- src/common/persist.cpp | 109 +++++++++++ 25 files changed, 1548 insertions(+), 20 deletions(-) create mode 100644 docs/doxygen/overviews/persistence.h create mode 100644 include/wx/persist.h create mode 100644 include/wx/persist/bookctrl.h create mode 100644 include/wx/persist/toplevel.h create mode 100644 include/wx/persist/treebook.h create mode 100644 include/wx/persist/window.h create mode 100644 interface/wx/persist.h create mode 100644 interface/wx/persist/bookctrl.h create mode 100644 interface/wx/persist/toplevel.h create mode 100644 interface/wx/persist/treebook.h create mode 100644 interface/wx/persist/window.h create mode 100644 src/common/persist.cpp diff --git a/Makefile.in b/Makefile.in index fd4fa5affb..c5c79ff9f8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -3625,6 +3625,11 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \ wx/notebook.h \ wx/ownerdrw.h \ wx/paper.h \ + wx/persist.h \ + wx/persist/bookctrl.h \ + wx/persist/toplevel.h \ + wx/persist/treebook.h \ + wx/persist/window.h \ wx/pickerbase.h \ wx/popupwin.h \ wx/print.h \ @@ -4104,6 +4109,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS = \ monodll_nbkbase.o \ monodll_overlaycmn.o \ monodll_paper.o \ + monodll_persist.o \ monodll_pickerbase.o \ monodll_popupcmn.o \ monodll_prntbase.o \ @@ -4295,6 +4301,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS = \ monodll_nbkbase.o \ monodll_overlaycmn.o \ monodll_paper.o \ + monodll_persist.o \ monodll_pickerbase.o \ monodll_popupcmn.o \ monodll_prntbase.o \ @@ -5915,6 +5922,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_1 = \ monolib_nbkbase.o \ monolib_overlaycmn.o \ monolib_paper.o \ + monolib_persist.o \ monolib_pickerbase.o \ monolib_popupcmn.o \ monolib_prntbase.o \ @@ -6106,6 +6114,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_1 = \ monolib_nbkbase.o \ monolib_overlaycmn.o \ monolib_paper.o \ + monolib_persist.o \ monolib_pickerbase.o \ monolib_popupcmn.o \ monolib_prntbase.o \ @@ -7872,6 +7881,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_2 = \ coredll_nbkbase.o \ coredll_overlaycmn.o \ coredll_paper.o \ + coredll_persist.o \ coredll_pickerbase.o \ coredll_popupcmn.o \ coredll_prntbase.o \ @@ -8063,6 +8073,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_2 = \ coredll_nbkbase.o \ coredll_overlaycmn.o \ coredll_paper.o \ + coredll_persist.o \ coredll_pickerbase.o \ coredll_popupcmn.o \ coredll_prntbase.o \ @@ -9381,6 +9392,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_3 = \ corelib_nbkbase.o \ corelib_overlaycmn.o \ corelib_paper.o \ + corelib_persist.o \ corelib_pickerbase.o \ corelib_popupcmn.o \ corelib_prntbase.o \ @@ -9572,6 +9584,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_3 = \ corelib_nbkbase.o \ corelib_overlaycmn.o \ corelib_paper.o \ + corelib_persist.o \ corelib_pickerbase.o \ corelib_popupcmn.o \ corelib_prntbase.o \ @@ -18139,6 +18152,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@monodll_paper.o: $(srcdir)/src/common/paper.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/paper.cpp +@COND_USE_GUI_1@monodll_persist.o: $(srcdir)/src/common/persist.cpp $(MONODLL_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/persist.cpp + @COND_USE_GUI_1@monodll_pickerbase.o: $(srcdir)/src/common/pickerbase.cpp $(MONODLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/pickerbase.cpp @@ -22807,6 +22823,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@monolib_paper.o: $(srcdir)/src/common/paper.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/paper.cpp +@COND_USE_GUI_1@monolib_persist.o: $(srcdir)/src/common/persist.cpp $(MONOLIB_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/persist.cpp + @COND_USE_GUI_1@monolib_pickerbase.o: $(srcdir)/src/common/pickerbase.cpp $(MONOLIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/pickerbase.cpp @@ -27658,6 +27677,9 @@ coredll_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(COREDLL_ODEP) @COND_USE_GUI_1@coredll_paper.o: $(srcdir)/src/common/paper.cpp $(COREDLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/paper.cpp +@COND_USE_GUI_1@coredll_persist.o: $(srcdir)/src/common/persist.cpp $(COREDLL_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/persist.cpp + @COND_USE_GUI_1@coredll_pickerbase.o: $(srcdir)/src/common/pickerbase.cpp $(COREDLL_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/pickerbase.cpp @@ -31156,6 +31178,9 @@ corelib_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(CORELIB_ODEP) @COND_USE_GUI_1@corelib_paper.o: $(srcdir)/src/common/paper.cpp $(CORELIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/paper.cpp +@COND_USE_GUI_1@corelib_persist.o: $(srcdir)/src/common/persist.cpp $(CORELIB_ODEP) +@COND_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/persist.cpp + @COND_USE_GUI_1@corelib_pickerbase.o: $(srcdir)/src/common/pickerbase.cpp $(CORELIB_ODEP) @COND_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/pickerbase.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 9db7573006..ce89734eec 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -678,6 +678,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/common/nbkbase.cpp src/common/overlaycmn.cpp src/common/paper.cpp + src/common/persist.cpp src/common/pickerbase.cpp src/common/popupcmn.cpp src/common/prntbase.cpp @@ -906,6 +907,11 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/notebook.h wx/ownerdrw.h wx/paper.h + wx/persist.h + wx/persist/bookctrl.h + wx/persist/toplevel.h + wx/persist/treebook.h + wx/persist/window.h wx/pickerbase.h wx/popupwin.h wx/print.h diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index ebda828d89..51e1c44a7c 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -1704,6 +1704,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.obj \ $(OBJS)\monodll_overlaycmn.obj \ $(OBJS)\monodll_paper.obj \ + $(OBJS)\monodll_persist.obj \ $(OBJS)\monodll_pickerbase.obj \ $(OBJS)\monodll_popupcmn.obj \ $(OBJS)\monodll_prntbase.obj \ @@ -1942,6 +1943,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.obj \ $(OBJS)\monodll_overlaycmn.obj \ $(OBJS)\monodll_paper.obj \ + $(OBJS)\monodll_persist.obj \ $(OBJS)\monodll_pickerbase.obj \ $(OBJS)\monodll_popupcmn.obj \ $(OBJS)\monodll_prntbase.obj \ @@ -2384,6 +2386,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.obj \ $(OBJS)\monolib_overlaycmn.obj \ $(OBJS)\monolib_paper.obj \ + $(OBJS)\monolib_persist.obj \ $(OBJS)\monolib_pickerbase.obj \ $(OBJS)\monolib_popupcmn.obj \ $(OBJS)\monolib_prntbase.obj \ @@ -2622,6 +2625,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.obj \ $(OBJS)\monolib_overlaycmn.obj \ $(OBJS)\monolib_paper.obj \ + $(OBJS)\monolib_persist.obj \ $(OBJS)\monolib_pickerbase.obj \ $(OBJS)\monolib_popupcmn.obj \ $(OBJS)\monolib_prntbase.obj \ @@ -2969,6 +2973,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.obj \ $(OBJS)\coredll_overlaycmn.obj \ $(OBJS)\coredll_paper.obj \ + $(OBJS)\coredll_persist.obj \ $(OBJS)\coredll_pickerbase.obj \ $(OBJS)\coredll_popupcmn.obj \ $(OBJS)\coredll_prntbase.obj \ @@ -3207,6 +3212,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.obj \ $(OBJS)\coredll_overlaycmn.obj \ $(OBJS)\coredll_paper.obj \ + $(OBJS)\coredll_persist.obj \ $(OBJS)\coredll_pickerbase.obj \ $(OBJS)\coredll_popupcmn.obj \ $(OBJS)\coredll_prntbase.obj \ @@ -3451,6 +3457,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.obj \ $(OBJS)\corelib_overlaycmn.obj \ $(OBJS)\corelib_paper.obj \ + $(OBJS)\corelib_persist.obj \ $(OBJS)\corelib_pickerbase.obj \ $(OBJS)\corelib_popupcmn.obj \ $(OBJS)\corelib_prntbase.obj \ @@ -3689,6 +3696,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.obj \ $(OBJS)\corelib_overlaycmn.obj \ $(OBJS)\corelib_paper.obj \ + $(OBJS)\corelib_persist.obj \ $(OBJS)\corelib_pickerbase.obj \ $(OBJS)\corelib_popupcmn.obj \ $(OBJS)\corelib_prntbase.obj \ @@ -7146,6 +7154,11 @@ $(OBJS)\monodll_paper.obj: ..\..\src\common\paper.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_persist.obj: ..\..\src\common\persist.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monodll_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -9364,6 +9377,11 @@ $(OBJS)\monolib_paper.obj: ..\..\src\common\paper.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_persist.obj: ..\..\src\common\persist.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monolib_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -11603,6 +11621,11 @@ $(OBJS)\coredll_paper.obj: ..\..\src\common\paper.cpp $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\coredll_persist.obj: ..\..\src\common\persist.cpp + $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\coredll_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -12972,6 +12995,11 @@ $(OBJS)\corelib_paper.obj: ..\..\src\common\paper.cpp $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\corelib_persist.obj: ..\..\src\common\persist.cpp + $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\corelib_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\common\pickerbase.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index e23b144a54..e13fc07a71 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -1722,6 +1722,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.o \ $(OBJS)\monodll_overlaycmn.o \ $(OBJS)\monodll_paper.o \ + $(OBJS)\monodll_persist.o \ $(OBJS)\monodll_pickerbase.o \ $(OBJS)\monodll_popupcmn.o \ $(OBJS)\monodll_prntbase.o \ @@ -1962,6 +1963,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.o \ $(OBJS)\monodll_overlaycmn.o \ $(OBJS)\monodll_paper.o \ + $(OBJS)\monodll_persist.o \ $(OBJS)\monodll_pickerbase.o \ $(OBJS)\monodll_popupcmn.o \ $(OBJS)\monodll_prntbase.o \ @@ -2408,6 +2410,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.o \ $(OBJS)\monolib_overlaycmn.o \ $(OBJS)\monolib_paper.o \ + $(OBJS)\monolib_persist.o \ $(OBJS)\monolib_pickerbase.o \ $(OBJS)\monolib_popupcmn.o \ $(OBJS)\monolib_prntbase.o \ @@ -2648,6 +2651,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.o \ $(OBJS)\monolib_overlaycmn.o \ $(OBJS)\monolib_paper.o \ + $(OBJS)\monolib_persist.o \ $(OBJS)\monolib_pickerbase.o \ $(OBJS)\monolib_popupcmn.o \ $(OBJS)\monolib_prntbase.o \ @@ -3009,6 +3013,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.o \ $(OBJS)\coredll_overlaycmn.o \ $(OBJS)\coredll_paper.o \ + $(OBJS)\coredll_persist.o \ $(OBJS)\coredll_pickerbase.o \ $(OBJS)\coredll_popupcmn.o \ $(OBJS)\coredll_prntbase.o \ @@ -3249,6 +3254,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.o \ $(OBJS)\coredll_overlaycmn.o \ $(OBJS)\coredll_paper.o \ + $(OBJS)\coredll_persist.o \ $(OBJS)\coredll_pickerbase.o \ $(OBJS)\coredll_popupcmn.o \ $(OBJS)\coredll_prntbase.o \ @@ -3499,6 +3505,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.o \ $(OBJS)\corelib_overlaycmn.o \ $(OBJS)\corelib_paper.o \ + $(OBJS)\corelib_persist.o \ $(OBJS)\corelib_pickerbase.o \ $(OBJS)\corelib_popupcmn.o \ $(OBJS)\corelib_prntbase.o \ @@ -3739,6 +3746,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.o \ $(OBJS)\corelib_overlaycmn.o \ $(OBJS)\corelib_paper.o \ + $(OBJS)\corelib_persist.o \ $(OBJS)\corelib_pickerbase.o \ $(OBJS)\corelib_popupcmn.o \ $(OBJS)\corelib_prntbase.o \ @@ -7410,6 +7418,11 @@ $(OBJS)\monodll_paper.o: ../../src/common/paper.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monodll_persist.o: ../../src/common/persist.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monodll_pickerbase.o: ../../src/common/pickerbase.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -9742,6 +9755,11 @@ $(OBJS)\monolib_paper.o: ../../src/common/paper.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monolib_persist.o: ../../src/common/persist.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monolib_pickerbase.o: ../../src/common/pickerbase.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -12095,6 +12113,11 @@ $(OBJS)\coredll_paper.o: ../../src/common/paper.cpp $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\coredll_persist.o: ../../src/common/persist.cpp + $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\coredll_pickerbase.o: ../../src/common/pickerbase.cpp $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< @@ -13576,6 +13599,11 @@ $(OBJS)\corelib_paper.o: ../../src/common/paper.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\corelib_persist.o: ../../src/common/persist.cpp + $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\corelib_pickerbase.o: ../../src/common/pickerbase.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 4da5672d5c..d51a4fbd0c 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -1884,6 +1884,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.obj \ $(OBJS)\monodll_overlaycmn.obj \ $(OBJS)\monodll_paper.obj \ + $(OBJS)\monodll_persist.obj \ $(OBJS)\monodll_pickerbase.obj \ $(OBJS)\monodll_popupcmn.obj \ $(OBJS)\monodll_prntbase.obj \ @@ -2122,6 +2123,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_nbkbase.obj \ $(OBJS)\monodll_overlaycmn.obj \ $(OBJS)\monodll_paper.obj \ + $(OBJS)\monodll_persist.obj \ $(OBJS)\monodll_pickerbase.obj \ $(OBJS)\monodll_popupcmn.obj \ $(OBJS)\monodll_prntbase.obj \ @@ -2570,6 +2572,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.obj \ $(OBJS)\monolib_overlaycmn.obj \ $(OBJS)\monolib_paper.obj \ + $(OBJS)\monolib_persist.obj \ $(OBJS)\monolib_pickerbase.obj \ $(OBJS)\monolib_popupcmn.obj \ $(OBJS)\monolib_prntbase.obj \ @@ -2808,6 +2811,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_nbkbase.obj \ $(OBJS)\monolib_overlaycmn.obj \ $(OBJS)\monolib_paper.obj \ + $(OBJS)\monolib_persist.obj \ $(OBJS)\monolib_pickerbase.obj \ $(OBJS)\monolib_popupcmn.obj \ $(OBJS)\monolib_prntbase.obj \ @@ -3185,6 +3189,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.obj \ $(OBJS)\coredll_overlaycmn.obj \ $(OBJS)\coredll_paper.obj \ + $(OBJS)\coredll_persist.obj \ $(OBJS)\coredll_pickerbase.obj \ $(OBJS)\coredll_popupcmn.obj \ $(OBJS)\coredll_prntbase.obj \ @@ -3423,6 +3428,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_nbkbase.obj \ $(OBJS)\coredll_overlaycmn.obj \ $(OBJS)\coredll_paper.obj \ + $(OBJS)\coredll_persist.obj \ $(OBJS)\coredll_pickerbase.obj \ $(OBJS)\coredll_popupcmn.obj \ $(OBJS)\coredll_prntbase.obj \ @@ -3673,6 +3679,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.obj \ $(OBJS)\corelib_overlaycmn.obj \ $(OBJS)\corelib_paper.obj \ + $(OBJS)\corelib_persist.obj \ $(OBJS)\corelib_pickerbase.obj \ $(OBJS)\corelib_popupcmn.obj \ $(OBJS)\corelib_prntbase.obj \ @@ -3911,6 +3918,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_nbkbase.obj \ $(OBJS)\corelib_overlaycmn.obj \ $(OBJS)\corelib_paper.obj \ + $(OBJS)\corelib_persist.obj \ $(OBJS)\corelib_pickerbase.obj \ $(OBJS)\corelib_popupcmn.obj \ $(OBJS)\corelib_prntbase.obj \ @@ -7492,6 +7500,11 @@ $(OBJS)\monodll_paper.obj: ..\..\src\common\paper.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_persist.obj: ..\..\src\common\persist.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monodll_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -9710,6 +9723,11 @@ $(OBJS)\monolib_paper.obj: ..\..\src\common\paper.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_persist.obj: ..\..\src\common\persist.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monolib_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -11949,6 +11967,11 @@ $(OBJS)\coredll_paper.obj: ..\..\src\common\paper.cpp $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\coredll_persist.obj: ..\..\src\common\persist.cpp + $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\coredll_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\common\pickerbase.cpp @@ -13318,6 +13341,11 @@ $(OBJS)\corelib_paper.obj: ..\..\src\common\paper.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\common\paper.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\corelib_persist.obj: ..\..\src\common\persist.cpp + $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\common\persist.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\corelib_pickerbase.obj: ..\..\src\common\pickerbase.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\common\pickerbase.cpp diff --git a/build/msw/makefile.wat b/build/msw/makefile.wat index 082784a063..6527a430d9 100644 --- a/build/msw/makefile.wat +++ b/build/msw/makefile.wat @@ -399,6 +399,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = & $(OBJS)\monodll_nbkbase.obj & $(OBJS)\monodll_overlaycmn.obj & $(OBJS)\monodll_paper.obj & + $(OBJS)\monodll_persist.obj & $(OBJS)\monodll_pickerbase.obj & $(OBJS)\monodll_popupcmn.obj & $(OBJS)\monodll_prntbase.obj & @@ -639,6 +640,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = & $(OBJS)\monodll_nbkbase.obj & $(OBJS)\monodll_overlaycmn.obj & $(OBJS)\monodll_paper.obj & + $(OBJS)\monodll_persist.obj & $(OBJS)\monodll_pickerbase.obj & $(OBJS)\monodll_popupcmn.obj & $(OBJS)\monodll_prntbase.obj & @@ -1090,6 +1092,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = & $(OBJS)\monolib_nbkbase.obj & $(OBJS)\monolib_overlaycmn.obj & $(OBJS)\monolib_paper.obj & + $(OBJS)\monolib_persist.obj & $(OBJS)\monolib_pickerbase.obj & $(OBJS)\monolib_popupcmn.obj & $(OBJS)\monolib_prntbase.obj & @@ -1330,6 +1333,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = & $(OBJS)\monolib_nbkbase.obj & $(OBJS)\monolib_overlaycmn.obj & $(OBJS)\monolib_paper.obj & + $(OBJS)\monolib_persist.obj & $(OBJS)\monolib_pickerbase.obj & $(OBJS)\monolib_popupcmn.obj & $(OBJS)\monolib_prntbase.obj & @@ -1702,6 +1706,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = & $(OBJS)\coredll_nbkbase.obj & $(OBJS)\coredll_overlaycmn.obj & $(OBJS)\coredll_paper.obj & + $(OBJS)\coredll_persist.obj & $(OBJS)\coredll_pickerbase.obj & $(OBJS)\coredll_popupcmn.obj & $(OBJS)\coredll_prntbase.obj & @@ -1942,6 +1947,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = & $(OBJS)\coredll_nbkbase.obj & $(OBJS)\coredll_overlaycmn.obj & $(OBJS)\coredll_paper.obj & + $(OBJS)\coredll_persist.obj & $(OBJS)\coredll_pickerbase.obj & $(OBJS)\coredll_popupcmn.obj & $(OBJS)\coredll_prntbase.obj & @@ -2194,6 +2200,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = & $(OBJS)\corelib_nbkbase.obj & $(OBJS)\corelib_overlaycmn.obj & $(OBJS)\corelib_paper.obj & + $(OBJS)\corelib_persist.obj & $(OBJS)\corelib_pickerbase.obj & $(OBJS)\corelib_popupcmn.obj & $(OBJS)\corelib_prntbase.obj & @@ -2434,6 +2441,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = & $(OBJS)\corelib_nbkbase.obj & $(OBJS)\corelib_overlaycmn.obj & $(OBJS)\corelib_paper.obj & + $(OBJS)\corelib_persist.obj & $(OBJS)\corelib_pickerbase.obj & $(OBJS)\corelib_popupcmn.obj & $(OBJS)\corelib_prntbase.obj & @@ -7655,6 +7663,11 @@ $(OBJS)\monodll_paper.obj : .AUTODEPEND ..\..\src\common\paper.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< !endif +!ifeq USE_GUI 1 +$(OBJS)\monodll_persist.obj : .AUTODEPEND ..\..\src\common\persist.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< +!endif + !ifeq USE_GUI 1 $(OBJS)\monodll_pickerbase.obj : .AUTODEPEND ..\..\src\common\pickerbase.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< @@ -9987,6 +10000,11 @@ $(OBJS)\monolib_paper.obj : .AUTODEPEND ..\..\src\common\paper.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< !endif +!ifeq USE_GUI 1 +$(OBJS)\monolib_persist.obj : .AUTODEPEND ..\..\src\common\persist.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< +!endif + !ifeq USE_GUI 1 $(OBJS)\monolib_pickerbase.obj : .AUTODEPEND ..\..\src\common\pickerbase.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< @@ -12340,6 +12358,11 @@ $(OBJS)\coredll_paper.obj : .AUTODEPEND ..\..\src\common\paper.cpp $(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $< !endif +!ifeq USE_GUI 1 +$(OBJS)\coredll_persist.obj : .AUTODEPEND ..\..\src\common\persist.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $< +!endif + !ifeq USE_GUI 1 $(OBJS)\coredll_pickerbase.obj : .AUTODEPEND ..\..\src\common\pickerbase.cpp $(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $< @@ -13821,6 +13844,11 @@ $(OBJS)\corelib_paper.obj : .AUTODEPEND ..\..\src\common\paper.cpp $(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $< !endif +!ifeq USE_GUI 1 +$(OBJS)\corelib_persist.obj : .AUTODEPEND ..\..\src\common\persist.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $< +!endif + !ifeq USE_GUI 1 $(OBJS)\corelib_pickerbase.obj : .AUTODEPEND ..\..\src\common\pickerbase.cpp $(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $< diff --git a/build/msw/wx_core.dsp b/build/msw/wx_core.dsp index 3701568184..245918092e 100644 --- a/build/msw/wx_core.dsp +++ b/build/msw/wx_core.dsp @@ -562,6 +562,10 @@ SOURCE=..\..\src\common\paper.cpp # End Source File # Begin Source File +SOURCE=..\..\src\common\persist.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\common\pickerbase.cpp # End Source File # Begin Source File @@ -5742,6 +5746,10 @@ SOURCE=..\..\include\wx\bmpcbox.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\persist\bookctrl.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\bookctrl.h # End Source File # Begin Source File @@ -6254,6 +6262,10 @@ SOURCE=..\..\include\wx\pen.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\persist.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\pickerbase.h # End Source File # Begin Source File @@ -6506,6 +6518,10 @@ SOURCE=..\..\include\wx\toplevel.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\persist\toplevel.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\treebase.h # End Source File # Begin Source File @@ -6514,6 +6530,10 @@ SOURCE=..\..\include\wx\treebook.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\persist\treebook.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\treectrl.h # End Source File # Begin Source File @@ -6550,6 +6570,10 @@ SOURCE=..\..\include\wx\window.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\persist\window.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\windowid.h # End Source File # Begin Source File diff --git a/build/msw/wx_vc7_core.vcproj b/build/msw/wx_vc7_core.vcproj index 6c145c93b0..786f4ec1e5 100644 --- a/build/msw/wx_vc7_core.vcproj +++ b/build/msw/wx_vc7_core.vcproj @@ -801,6 +801,9 @@ + + @@ -3556,6 +3559,9 @@ + + @@ -3940,6 +3946,9 @@ + + @@ -4129,12 +4138,18 @@ + + + + @@ -4162,6 +4177,9 @@ + + diff --git a/build/msw/wx_vc8_core.vcproj b/build/msw/wx_vc8_core.vcproj index 1ce1d73732..9d142e47de 100644 --- a/build/msw/wx_vc8_core.vcproj +++ b/build/msw/wx_vc8_core.vcproj @@ -1106,6 +1106,10 @@ RelativePath="..\..\src\common\paper.cpp" > + + @@ -4763,6 +4767,10 @@ RelativePath="..\..\include\wx\bmpcbox.h" > + + @@ -5275,6 +5283,10 @@ RelativePath="..\..\include\wx\pen.h" > + + @@ -5527,6 +5539,10 @@ RelativePath="..\..\include\wx\toplevel.h" > + + @@ -5535,6 +5551,10 @@ RelativePath="..\..\include\wx\treebook.h" > + + @@ -5571,6 +5591,10 @@ RelativePath="..\..\include\wx\window.h" > + + diff --git a/build/msw/wx_vc9_core.vcproj b/build/msw/wx_vc9_core.vcproj index 37fbe587a3..d8b4318214 100644 --- a/build/msw/wx_vc9_core.vcproj +++ b/build/msw/wx_vc9_core.vcproj @@ -1102,6 +1102,10 @@ RelativePath="..\..\src\common\paper.cpp" > + + @@ -4759,6 +4763,10 @@ RelativePath="..\..\include\wx\bmpcbox.h" > + + @@ -5271,6 +5279,10 @@ RelativePath="..\..\include\wx\pen.h" > + + @@ -5523,6 +5535,10 @@ RelativePath="..\..\include\wx\toplevel.h" > + + @@ -5531,6 +5547,10 @@ RelativePath="..\..\include\wx\treebook.h" > + + @@ -5567,6 +5587,10 @@ RelativePath="..\..\include\wx\window.h" > + + diff --git a/docs/changes.txt b/docs/changes.txt index 9bfdfdc586..62aa60f58c 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -280,6 +280,9 @@ Major new features in this release welcome (and due to using the simple Doxygen syntax it is now easier than ever to submit patches correcting them! :-) +- Support for persistent objects automatically saving and restoring their state + was added. + 2.9.0 ----- diff --git a/docs/doxygen/mainpages/topics.h b/docs/doxygen/mainpages/topics.h index 4fc700a58a..f4b83b22a1 100644 --- a/docs/doxygen/mainpages/topics.h +++ b/docs/doxygen/mainpages/topics.h @@ -63,6 +63,7 @@ The following is a basic categorization of them: @li @subpage overview_stream @li @subpage overview_thread @li @subpage overview_config +@li @subpage overview_persistence @li @subpage overview_fs @li @subpage overview_resyntax @li @subpage overview_archive diff --git a/docs/doxygen/overviews/persistence.h b/docs/doxygen/overviews/persistence.h new file mode 100644 index 0000000000..3b018a59eb --- /dev/null +++ b/docs/doxygen/overviews/persistence.h @@ -0,0 +1,115 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: docs/doxygen/overviews/persistence.h +// Purpose: overview of persistent objects +// Author: Vadim Zeitlin +// Created: 2009-01-23 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + +@page overview_persistence Persistent Objects Overview + +Persistent objects are simply the objects which automatically save their state +when they are destroyed and restore it when they are recreated, even during +another program invocation. + +Most often, persistent objects are, in fact, persistent windows as it is +especially convenient to automatically restore the UI state when the program is +restarted but an object of any class can be made persistent. Moreover, +persistence is implemented in a non-intrusive way so that the original object +class doesn't need to be modified at all in order to add support for saving and +restoring its properties. + +The persistence framework involves + - wxPersistenceManager which all persistent objects register themselves with. + This class handles actual saving and restoring of persistent data as well as + various global aspects of persistence, e.g. it can be used to disable + restoring the saved data. + - wxPersistentObject is the base class for all persistent objects or, rather, + adaptors for the persistent objects as this class main purpose is to provide + the bridge between the original class -- which has no special persistence + support -- and wxPersistenceManager, + - wxPersistentWindow<> which derives from wxPersistentObject and implements some + of its methods using wxWindow-specific functionality. Notably, + wxPersistenceManager handles the destruction of persistent windows + automatically implicitly while it has to be done explicitly for the + arbitrary persistent objects. + - wxCreatePersistentObject() function which is used to create the + appropriate persistence adapter for the object. + + +@section persistence_using Using Persistent Windows + +wxWidgets has built-in support for a (constantly growing) number of controls. +Currently the following classes are supported: + - wxTopLevelWindow (and hence wxFrame and wxDialog) + - wxBookCtrlBase, i.e. wxNotebook, wxListbook, wxToolbook and wxChoicebook + - wxTreebook + +To automatically save and restore the properties of the windows of classes +listed above you need to + + -# Set a unique name for the window using wxWindow::SetName(): this step is + important as the name is used in the configuration file and so must be + unique among all windows of the same class. + + -# Call wxPersistenceManager::Register() at any moment after creating the + window and then wxPersistenceManager::Restore() when the settings may be + restored (which can't be always done immediately, e.g. often the window + needs to be populated first). If settings can be restored immediately after + the window creation, as is often the case for wxTopLevelWindow, for + example, then wxPersistenceManager::RegisterAndRestore() can be used to do + both at once. + + -# If you do not want the settings for the window to be saved (for example + the changes to the dialog size are usually not saved if the dialog was + cancelled), you need to call wxPersistenceManager::Unregister() manually. + Otherwise the settings will be automatically saved when the control itself + is destroyed. + +Example of using a notebook control which automatically remembers the last open +page: +@code + wxNotebook *book = new wxNotebook(parent, wxID_ANY); + book->SetName("MyBook"); // do not use the default name + book->AddPage(...); + book->AddPage(...); + book->AddPage(...); + if ( !wxPersistenceManager::RegisterAndRestore(book) ) + { + // nothing was restored, so choose the default page ourselves + book->SetSelection(0); + } +@endcode + + +@section persistence_defining Defining Custom Persistent Windows + +User-defined classes can be easily integrated with wxPersistenceManager. To add +support for your custom class @c MyWidget you just need to: + + -# Define a new @c MyPersistentWidget class inheriting from + wxPersistentWindow. + + -# Implement its pure virtual GetKind() method returning a unique string + identifying all @c MyWidget objects, typically something like @c "widget" + + -# Implement its pure virtual Save() and Restore() methods to actually save + and restore the widget settings using wxPersistentObject::SaveValue() and + wxPersistentObject::RestoreValue() methods. + + -# Define wxCreatePersistentObject() overload taking @c MyWidget * and + returning a new @c MyPersistentWidget object. + +If you want to add persistence support for a class not deriving from wxWindow, +you need to derive @c MyPersistentWidget directly from wxPersistentObject and +so implement its pure virtual wxPersistentObject::GetName() method too. +Additionally, you must ensure that wxPersistenceManager::SaveAndUnregister() is +called when your object is destroyed as this can be only done automatically for +windows. + + */ + diff --git a/include/wx/persist.h b/include/wx/persist.h new file mode 100644 index 0000000000..7e331b6480 --- /dev/null +++ b/include/wx/persist.h @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist.h +// Purpose: common classes for persistence support +// Author: Vadim Zeitlin +// Created: 2009-01-18 +// RCS-ID: $Id: wxhead.h,v 1.10 2008-04-15 23:34:19 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_H_ +#define _WX_PERSIST_H_ + +#include "wx/string.h" +#include "wx/hashmap.h" +#include "wx/confbase.h" + +class wxPersistentObject; + +WX_DECLARE_VOIDPTR_HASH_MAP(wxPersistentObject *, wxPersistentObjectsMap); + +// ---------------------------------------------------------------------------- +// global functions +// ---------------------------------------------------------------------------- + +/* + We do _not_ declare this function as doing this would force us to specialize + it for the user classes deriving from the standard persistent classes. + However we do define overloads of wxCreatePersistentObject() for all the wx + classes which means that template wxPersistentObject::Restore() picks up the + right overload to use provided that the header defining the correct overload + is included before calling it. And a compilation error happens if this is + not done. + +template +wxPersistentObject *wxCreatePersistentObject(T *obj); + + */ + +// ---------------------------------------------------------------------------- +// wxPersistenceManager: global aspects of persistent windows +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxPersistenceManager +{ +public: + // accessor to the unique persistence manager object + static wxPersistenceManager& Get(); + + + // globally disable restoring or saving the persistent properties (both are + // enabled by default) + bool DisableSaving() { m_doSave = false; } + bool DisableRestoring() { m_doRestore = false; } + + + // register an object with the manager: when using the first overload, + // wxCreatePersistentObject() must be specialized for this object class; + // with the second one the persistent adapter is created by the caller + // + // the object shouldn't be already registered with us + template + wxPersistentObject *Register(T *obj) + { + return Register(obj, wxCreatePersistentObject(obj)); + } + + wxPersistentObject *Register(void *obj, wxPersistentObject *po); + + // check if the object is registered and return the associated + // wxPersistentObject if it is or NULL otherwise + wxPersistentObject *Find(void *obj) const; + + // unregister the object, this is called by wxPersistentObject itself so + // there is usually no need to do it explicitly + // + // deletes the associated wxPersistentObject + void Unregister(void *obj); + + + // save/restore the state of an object + // + // these methods do nothing if DisableSaving/Restoring() was called + // + // Restore() returns true if the object state was really restored + void Save(void *obj); + bool Restore(void *obj); + + // combines both Save() and Unregister() calls + void SaveAndUnregister(void *obj) + { + Save(obj); + Unregister(obj); + } + + // combines both Register() and Restore() calls + template + bool RegisterAndRestore(T *obj) + { + return Register(obj) && Restore(obj); + } + + bool RegisterAndRestore(void *obj, wxPersistentObject *po) + { + return Register(obj, po) && Restore(obj); + } + + + // methods used by the persistent objects to save and restore the data + // + // currently these methods simply use wxConfig::Get() + // + // TODO: make this customizable by allowing + // (a) specifying custom wxConfig object to use + // (b) allowing to use something else entirely + template + bool + SaveValue(const wxPersistentObject& who, const wxString& name, T value) + { + wxConfigBase * const conf = GetConfig(); + if ( !conf ) + return false; + + return conf->Write(GetKey(who, name), value); + } + + template + bool + RestoreValue(const wxPersistentObject& who, const wxString& name, T *value) + { + wxConfigBase * const conf = GetConfig(); + if ( !conf ) + return false; + + return conf->Read(GetKey(who, name), value); + } + +private: + // ctor is private, use Get() + wxPersistenceManager() + { + m_doSave = + m_doRestore = true; + } + + // helpers of Save/Restore(), will be customized later + wxConfigBase *GetConfig() const { return wxConfigBase::Get(); } + wxString GetKey(const wxPersistentObject& who, const wxString& name) const; + + + // map with the registered objects as keys and associated + // wxPersistentObjects as values + wxPersistentObjectsMap m_persistentObjects; + + // true if we should restore/save the settings (it doesn't make much sense + // to use this class when both of them are false but setting one of them to + // false may make sense in some situations) + bool m_doSave, + m_doRestore; + + DECLARE_NO_COPY_CLASS(wxPersistenceManager); +}; + +// ---------------------------------------------------------------------------- +// wxPersistentObject: ABC for anything persistent +// ---------------------------------------------------------------------------- + +class wxPersistentObject +{ +public: + // ctor associates us with the object whose options we save/restore + wxPersistentObject(void *obj) : m_obj(obj) { } + + // trivial but virtual dtor + virtual ~wxPersistentObject() { } + + + // methods used by wxPersistenceManager + // ------------------------------------ + + // save/restore the corresponding objects settings + // + // these methods shouldn't be used directly as they don't respect the + // global wxPersistenceManager::DisableSaving/Restoring() settings, use + // wxPersistenceManager methods with the same name instead + virtual void Save() const = 0; + virtual bool Restore() = 0; + + + // get the kind of the objects we correspond to, e.g. "Frame" + virtual wxString GetKind() const = 0; + + // get the name of the object we correspond to, e.g. "Main" + virtual wxString GetName() const = 0; + + + // return the associated object + void *GetObject() const { return m_obj; } + +protected: + // wrappers for wxPersistenceManager methods which don't require passing + // "this" as the first parameter all the time + template + bool SaveValue(const wxString& name, T value) const + { + return wxPersistenceManager::Get().SaveValue(*this, name, value); + } + + template + bool RestoreValue(const wxString& name, T *value) + { + return wxPersistenceManager::Get().RestoreValue(*this, name, value); + } + +private: + void * const m_obj; + + DECLARE_NO_COPY_CLASS(wxPersistentObject) +}; + +#endif // _WX_PERSIST_H_ + diff --git a/include/wx/persist/bookctrl.h b/include/wx/persist/bookctrl.h new file mode 100644 index 0000000000..a7930486a8 --- /dev/null +++ b/include/wx/persist/bookctrl.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/bookctrl.h +// Purpose: persistence support for wxBookCtrl +// Author: Vadim Zeitlin +// Created: 2009-01-19 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_BOOKCTRL_H_ +#define _WX_PERSIST_BOOKCTRL_H_ + +#include "wx/persist/window.h" + +#include "wx/bookctrl.h" + +// ---------------------------------------------------------------------------- +// string constants used by wxPersistentBookCtrl +// ---------------------------------------------------------------------------- + +#define wxPERSIST_BOOK_KIND "Book" + +#define wxPERSIST_BOOK_SELECTION "Selection" + +// ---------------------------------------------------------------------------- +// wxPersistentBookCtrl: supports saving/restoring book control selection +// ---------------------------------------------------------------------------- + +class wxPersistentBookCtrl : public wxPersistentWindow +{ +public: + wxPersistentBookCtrl(wxBookCtrlBase *book) + : wxPersistentWindow(book) + { + } + + virtual void Save() const + { + SaveValue(wxPERSIST_BOOK_SELECTION, Get()->GetSelection()); + } + + virtual bool Restore() + { + long sel; + if ( RestoreValue(wxPERSIST_BOOK_SELECTION, &sel) ) + { + wxBookCtrlBase * const book = Get(); + if ( sel >= 0 && (unsigned)sel < book->GetPageCount() ) + { + book->SetSelection(sel); + return true; + } + } + + return false; + } + + virtual wxString GetKind() const { return wxPERSIST_BOOK_KIND; } +}; + +inline wxPersistentObject *wxCreatePersistentObject(wxBookCtrlBase *book) +{ + return new wxPersistentBookCtrl(book); +} + +#endif // _WX_PERSIST_BOOKCTRL_H_ diff --git a/include/wx/persist/toplevel.h b/include/wx/persist/toplevel.h new file mode 100644 index 0000000000..9d6edda5d0 --- /dev/null +++ b/include/wx/persist/toplevel.h @@ -0,0 +1,129 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/toplevel.h +// Purpose: persistence support for wxTLW +// Author: Vadim Zeitlin +// Created: 2009-01-19 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_TOPLEVEL_H_ +#define _WX_PERSIST_TOPLEVEL_H_ + +#include "wx/persist/window.h" + +#include "wx/toplevel.h" +#include "wx/display.h" + +// ---------------------------------------------------------------------------- +// string constants used by wxPersistentTLW +// ---------------------------------------------------------------------------- + +// we use just "Window" to keep configuration files and such short, there +// should be no confusion with wxWindow itself as we don't have persistent +// windows, just persistent controls which have their own specific kind strings +#define wxPERSIST_TLW_KIND "Window" + +// names for various persistent options +#define wxPERSIST_TLW_X "x" +#define wxPERSIST_TLW_Y "y" +#define wxPERSIST_TLW_W "w" +#define wxPERSIST_TLW_H "h" + +#define wxPERSIST_TLW_MAXIMIZED "Maximized" +#define wxPERSIST_TLW_ICONIZED "Iconized" + +// ---------------------------------------------------------------------------- +// wxPersistentTLW: supports saving/restoring window position and size as well +// as maximized/iconized/restore state +// ---------------------------------------------------------------------------- + +class wxPersistentTLW : public wxPersistentWindow +{ +public: + wxPersistentTLW(wxTopLevelWindow *tlw) + : wxPersistentWindow(tlw) + { + } + + virtual void Save() const + { + const wxTopLevelWindow * const tlw = Get(); + + const wxPoint pos = tlw->GetScreenPosition(); + SaveValue(wxPERSIST_TLW_X, pos.x); + SaveValue(wxPERSIST_TLW_Y, pos.y); + + // notice that we use GetSize() here and not GetClientSize() because + // the latter doesn't return correct results for the minimized windows + // (at least not under Windows) + // + // of course, it shouldn't matter anyhow usually, the client size + // should be preserved as well unless the size of the decorations + // changed between the runs + const wxSize size = tlw->GetSize(); + SaveValue(wxPERSIST_TLW_W, size.x); + SaveValue(wxPERSIST_TLW_H, size.y); + + SaveValue(wxPERSIST_TLW_MAXIMIZED, tlw->IsMaximized()); + SaveValue(wxPERSIST_TLW_ICONIZED, tlw->IsIconized()); + } + + virtual bool Restore() + { + wxTopLevelWindow * const tlw = Get(); + + long x wxDUMMY_INITIALIZE(-1), + y wxDUMMY_INITIALIZE(-1), + w wxDUMMY_INITIALIZE(-1), + h wxDUMMY_INITIALIZE(-1); + const bool hasPos = RestoreValue(wxPERSIST_TLW_X, &x) && + RestoreValue(wxPERSIST_TLW_Y, &y); + const bool hasSize = RestoreValue(wxPERSIST_TLW_W, &w) && + RestoreValue(wxPERSIST_TLW_H, &h); + + if ( hasPos ) + { + // to avoid making the window completely invisible if it had been + // shown on a monitor which was disconnected since the last run + // (this is pretty common for notebook with external displays) + // + // NB: we should allow window position to be (slightly) off screen, + // it's not uncommon to position the window so that its upper + // left corner has slightly negative coordinate + if ( wxDisplay::GetFromPoint(wxPoint(x, y)) != wxNOT_FOUND || + (hasSize && wxDisplay::GetFromPoint( + wxPoint(x + w, y + h)) != wxNOT_FOUND) ) + { + tlw->Move(x, y, wxSIZE_ALLOW_MINUS_ONE); + } + //else: should we try to adjust position/size somehow? + } + + if ( hasSize ) + tlw->SetSize(w, h); + + // note that the window can be both maximized and iconized + bool maximized; + if ( RestoreValue(wxPERSIST_TLW_MAXIMIZED, &maximized) && maximized ) + tlw->Maximize(); + + bool iconized; + if ( RestoreValue(wxPERSIST_TLW_ICONIZED, &iconized) && iconized ) + tlw->Iconize(); + + // the most important property of the window that we restore is its + // size, so disregard the value of hasPos here + return hasSize; + } + + virtual wxString GetKind() const { return wxPERSIST_TLW_KIND; } +}; + +inline wxPersistentObject *wxCreatePersistentObject(wxTopLevelWindow *tlw) +{ + return new wxPersistentTLW(tlw); +} + +#endif // _WX_PERSIST_TOPLEVEL_H_ diff --git a/include/wx/persist/treebook.h b/include/wx/persist/treebook.h new file mode 100644 index 0000000000..0d2fddb3a1 --- /dev/null +++ b/include/wx/persist/treebook.h @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/treebook.h +// Purpose: persistence support for wxBookCtrl +// Author: Vadim Zeitlin +// Created: 2009-01-19 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_TREEBOOK_H_ +#define _WX_PERSIST_TREEBOOK_H_ + +#include "wx/persist/bookctrl.h" + +#include "wx/arrstr.h" +#include "wx/treebook.h" + +// ---------------------------------------------------------------------------- +// string constants used by wxPersistentTreeBookCtrl +// ---------------------------------------------------------------------------- + +#define wxPERSIST_TREEBOOK_KIND "TreeBook" + +// this key contains the indices of all expanded nodes in the tree book +// separated by wxPERSIST_TREEBOOK_EXPANDED_SEP +#define wxPERSIST_TREEBOOK_EXPANDED_BRANCHES "Expanded" +#define wxPERSIST_TREEBOOK_EXPANDED_SEP ',' + +// ---------------------------------------------------------------------------- +// wxPersistentTreeBookCtrl: supports saving/restoring open tree branches +// ---------------------------------------------------------------------------- + +class wxPersistentTreeBookCtrl : public wxPersistentBookCtrl +{ +public: + wxPersistentTreeBookCtrl(wxTreebook *book) + : wxPersistentBookCtrl(book) + { + } + + virtual void Save() const + { + const wxTreebook * const book = GetTreeBook(); + + wxString expanded; + const size_t count = book->GetPageCount(); + for ( size_t n = 0; n < count; n++ ) + { + if ( book->IsNodeExpanded(n) ) + { + if ( !expanded.empty() ) + expanded += wxPERSIST_TREEBOOK_EXPANDED_SEP; + + expanded += wxString::Format("%u", static_cast(n)); + } + } + + SaveValue(wxPERSIST_TREEBOOK_EXPANDED_BRANCHES, expanded); + + wxPersistentBookCtrl::Save(); + } + + virtual bool Restore() + { + wxTreebook * const book = GetTreeBook(); + + wxString expanded; + if ( RestoreValue(wxPERSIST_TREEBOOK_EXPANDED_BRANCHES, &expanded) ) + { + const wxArrayString + indices(wxSplit(expanded, wxPERSIST_TREEBOOK_EXPANDED_SEP)); + + const size_t pageCount = book->GetPageCount(); + const size_t count = indices.size(); + for ( size_t n = 0; n < count; n++ ) + { + unsigned long idx; + if ( indices[n].ToULong(&idx) && idx < pageCount ) + book->ExpandNode(idx); + } + } + + return wxPersistentBookCtrl::Restore(); + } + + virtual wxString GetKind() const { return wxPERSIST_TREEBOOK_KIND; } + + wxTreebook *GetTreeBook() const { return static_cast(Get()); } +}; + +inline wxPersistentObject *wxCreatePersistentObject(wxTreebook *book) +{ + return new wxPersistentTreeBookCtrl(book); +} + +#endif // _WX_PERSIST_TREEBOOK_H_ diff --git a/include/wx/persist/window.h b/include/wx/persist/window.h new file mode 100644 index 0000000000..692e143a13 --- /dev/null +++ b/include/wx/persist/window.h @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/window.h +// Purpose: wxPersistentWindow declaration +// Author: Vadim Zeitlin +// Created: 2009-01-23 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_WINDOW_H_ +#define _WX_PERSIST_WINDOW_H_ + +#include "wx/persist.h" + +#include "wx/window.h" + +// ---------------------------------------------------------------------------- +// wxPersistentWindow: base class for persistent windows, uses the window name +// as persistent name by default and automatically reacts +// to the window destruction +// ---------------------------------------------------------------------------- + +// type-independent part of wxPersistentWindow +class wxPersistentWindowBase : +#if wxEVENTS_COMPATIBILITY_2_8 + // in compatibility mode we need to derive from wxEvtHandler to be able to + // handle events + public wxEvtHandler , +#endif + public wxPersistentObject +{ +public: + wxPersistentWindowBase(wxWindow *win) + : wxPersistentObject(win) + { + win->Connect + ( + wxEVT_DESTROY, + wxWindowDestroyEventHandler( + wxPersistentWindowBase::HandleDestroy), + NULL, + this + ); + } + + virtual wxString GetName() const + { + const wxString name = GetWindow()->GetName(); + wxASSERT_MSG( !name.empty(), "persistent windows should be named!" ); + + return name; + } + +protected: + wxWindow *GetWindow() const { return static_cast(GetObject()); } + +private: + void HandleDestroy(wxWindowDestroyEvent& event) + { + event.Skip(); + + // this will delete this object itself + wxPersistenceManager::Get().SaveAndUnregister(GetWindow()); + } + + DECLARE_NO_COPY_CLASS(wxPersistentWindowBase) +}; + +template +class wxPersistentWindow : public wxPersistentWindowBase +{ +public: + typedef T WindowType; + + wxPersistentWindow(WindowType *win) + : wxPersistentWindowBase(win) + { + } + + WindowType *Get() const { return static_cast(GetWindow()); } +}; + +#endif // _WX_PERSIST_WINDOW_H_ + diff --git a/interface/wx/persist.h b/interface/wx/persist.h new file mode 100644 index 0000000000..beae4c785f --- /dev/null +++ b/interface/wx/persist.h @@ -0,0 +1,273 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/persist.h +// Purpose: interface of wxPersistenceManager and related classes +// Author: Vadim Zeitlin +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + Provides support for automatically saving and restoring object properties + to persistent storage. + + This class is the central element of wxWidgets persistence framework, see + @ref overview_persistence for its overview. + + This is a singleton class and its unique instance can be retrieved using + Get() method. + + @library{wxcore} + */ +class wxPersistenceManager +{ +public: + /** + Returns the unique persistence manager object. + */ + static wxPersistenceManager& Get(); + + /** + Globally disable saving the persistence object properties. + + By default, saving properties in Save() is enabled but the program may + wish to disable if, for example, it detects that it is running on a + system which shouldn't be modified in any way and so configuration + file (or Windows registry) shouldn't be written to. + + @see DisableRestoring() + */ + bool DisableSaving(); + + /** + Globally disable restoring the persistence object properties. + + By default, restoring properties in Restore() is enabled but this + function allows to disable it. This is mostly useful for testing. + + @see DisableSaving() + */ + bool DisableRestoring(); + + + /** + Register an object with the manager automatically creating a + persistence adapter for it. + + This is equivalent to calling Register(void *, wxPersistentObject *) + with wxCreatePersistentObject(obj) as the second argument. + + @param obj + The object to register. wxCreatePersistentObject() overload must be + defined for the objects of this class. + */ + template + wxPersistentObject *Register(T *obj) + { + return Register(obj, wxCreatePersistentObject(obj)); + } + + /** + Register an object with the manager. + + Note that registering the object doesn't do anything except allowing to + call Restore() for it later. If you want to register the object and + restore its properties, use RegisterAndRestore(). + + The manager takes ownership of @a po and will delete it when it is + unregistered. + + @param obj + The object to register. + @param po + The wxPersistentObject to use for saving and restoring this object + properties. + */ + wxPersistentObject *Register(void *obj, wxPersistentObject *po); + + /** + Check if the object is registered and return the associated + wxPersistentObject if it is or @NULL otherwise. + */ + wxPersistentObject *Find(void *obj) const; + + /** + Unregister the object and delete the associated wxPersistentObject. + + For the persistent windows this is done automatically (via + SaveAndUnregister()) when the window is destroyed so you only need to + call this function explicitly if you are using custom persistent + objects or if you want to prevent the object properties from being + saved. + + @param obj + An object previously registered with Register(). + */ + void Unregister(void *obj); + + + /** + Save the object properties to persistent storage. + + This method does nothing if DisableSaving() had been called. + + @param obj + An object previously registered with Register(). + + @see SaveAndUnregister() + */ + void Save(void *obj); + + /** + Restore the object properties previously saved by Save(). + + This method does nothing if DisableRestoring() had been called. + + @param obj + An object previously registered with Register(). + @return + @true if the object properties were restored or @false if nothing + was found to restore or the saved settings were invalid. + + @see RegisterAndRestore() + */ + bool Restore(void *obj); + + /// Combines both Save() and Unregister() calls. + void SaveAndUnregister(void *obj); + + /// Combines both Register() and Restore() calls. + //@{ + template + bool RegisterAndRestore(T *obj); + + bool RegisterAndRestore(void *obj, wxPersistentObject *po); + //@} +}; + +/** + Base class for persistent object adapters. + + wxWidgets persistence framework is non-intrusive, i.e. can work with the + classes which have no relationship to nor knowledge of it. To allow this, + an intermediate persistence adapter is used: this is just a simple object + which provides the methods used by wxPersistenceManager to save and restore + the object properties and implements them using the concrete class methods. + + You may derive your own classes from wxPersistentObject to implement + persistence support for your common classes, see @ref persistence_defining. + + @see wxPersistentWindow<> + */ +class wxPersistentObject +{ +public: + /** + Constructor takes the object which we're associated with. + + This object must have life-time greater than ours as we keep a pointer + to it. + */ + wxPersistentObject(void *obj); + + /// Trivial but virtual destructor. + virtual ~wxPersistentObject(); + + + /** + @name Methods to be implemented in the derived classes. + + Notice that these methods are only used by wxPersistenceManager + normally and shouldn't be called directly. + */ + //@{ + + /** + Save the object properties. + + The implementation of this method should use SaveValue(). + */ + virtual void Save() const = 0; + + /** + Restore the object properties. + + The implementation of this method should use RestoreValue(). + */ + virtual bool Restore() = 0; + + + /** + Returns the string uniquely identifying the objects supported by this + adapter. + + This method is called from SaveValue() and RestoreValue() and normally + returns some short (but not too cryptic) strings, e.g. @c "Checkbox". + */ + virtual wxString GetKind() const = 0; + + /** + Returns the string uniquely identifying the object we're associated + with among all the other objects of the same type. + + This method is used together with GetKind() to construct the unique + full name of the object in e.g. a configuration file. + */ + virtual wxString GetName() const = 0; + + //@} + + + /// Return the associated object. + void *GetObject() const; + +protected: + /** + Save the specified value using the given name. + + @param name + The name of the value in the configuration file. + @param value + The value to save, currently must be a type supported by wxConfig. + @return + @true if the value was saved or @false if an error occurred. + */ + template + bool SaveValue(const wxString& name, T value) const + { + return wxPersistenceManager::Get().SaveValue(*this, name, value); + } + + /** + Restore the value saved by Save(). + + @param name + The same name as was used by Save(). + @param value + Non-@NULL pointer which will be filled with the value if it was + read successfully or not modified if it wasn't. + @return + @true if the value was successfully read or @false if it was not + found or an error occurred. + */ + template + bool RestoreValue(const wxString& name, T *value) + { + return wxPersistenceManager::Get().RestoreValue(*this, name, value); + } +}; + +/** + Function used to create the correct persistent adapter for the given type + of objects. + + To be precise, there is no such template function definition but there are + overloads of wxCreatePersistentObject() taking different object types for + all wxWidgets classes supporting persistence. And you may also define your + own overloads to integrate your custom classes with wxWidgets persistence + framework. + + @see @ref persistence_defining + */ +template +wxPersistentObject *wxCreatePersistentObject(T *obj); diff --git a/interface/wx/persist/bookctrl.h b/interface/wx/persist/bookctrl.h new file mode 100644 index 0000000000..b6fe21268c --- /dev/null +++ b/interface/wx/persist/bookctrl.h @@ -0,0 +1,47 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/bookctrl.h +// Purpose: interface of wxPersistentBookCtrl +// Author: Vadim Zeitlin +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + Persistence adapter for wxBookCtrlBase. + + This adapter handles the selected page of wxBookCtrlBase, i.e. it saves its + value when the associated book control is destroyed and restores it when it + is recreated. + + @see wxPersistentTreeBookCtrl + */ +class wxPersistentBookCtrl : public wxPersistentWindow +{ +public: + /** + Constructor. + + @param book + The associated book control. + */ + wxPersistentBookCtrl(wxBookCtrlBase *book); + + /** + Save the currently selected page index. + */ + virtual void Save() const; + + /** + Restore the selected page index. + + The book control must be initialized before calling this function, i.e. + all of its pages should be already added to it -- otherwise restoring + the selection has no effect. + */ + virtual bool Restore(); +}; + +/// Overload allowing persistence adapter creation for wxBookCtrlBase-derived +/// objects. +wxPersistentObject *wxCreatePersistentObject(wxBookCtrlBase *book); diff --git a/interface/wx/persist/toplevel.h b/interface/wx/persist/toplevel.h new file mode 100644 index 0000000000..eaffd2470e --- /dev/null +++ b/interface/wx/persist/toplevel.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/toplevel.h +// Purpose: interface of wxPersistentTLW +// Author: Vadim Zeitlin +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + Persistence adapter for wxTopLevelWindow. + + This adapter saves and restores the geometry (i.e. position and size) and + the state (iconized, maximized or normal) of top level windows. It can be + used with both wxFrame and wxDialog. + + Note that it does @em not save nor restore the window visibility. + */ +class wxPersistentTLW : public wxPersistentWindow +{ +public: + /** + Constructor. + + @param book + The associated window. + */ + wxPersistentTLW(wxTopLevelWindow *book); + + /** + Save the current window geometry. + */ + virtual void Save() const; + + /** + Restore the window geometry. + */ + virtual bool Restore(); +}; + +/// Overload allowing persistence adapter creation for wxTopLevelWindow-derived +/// objects. +wxPersistentObject *wxCreatePersistentObject(wxTopLevelWindow *book); diff --git a/interface/wx/persist/treebook.h b/interface/wx/persist/treebook.h new file mode 100644 index 0000000000..28be96024e --- /dev/null +++ b/interface/wx/persist/treebook.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/treebook.h +// Purpose: interface of wxPersistentTreeBook +// Author: Vadim Zeitlin +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + Persistence adapter for wxTreebook. + + This adapter saves and restores the expanded branches of the wxTreeCtrl + used by wxTreebook, in addition to saving and restoring the selection as + implemented by the base wxPersistentBookCtrl class. + */ +class wxPersistentTreeBook : public wxPersistentBookCtrl +{ +public: + /** + Constructor. + + @param book + The associated tree book control. + */ + wxPersistentTreeBook(wxTreebook *book); + + /** + Save the currently opened branches. + */ + virtual void Save() const; + + /** + Restore the opened branches. + + The book control must be initialized before calling this function, i.e. + all of its pages should be already added to it. + */ + virtual bool Restore(); +}; + +/// Overload allowing persistence adapter creation for wxTreebook objects. +wxPersistentObject *wxCreatePersistentObject(wxTreebook *book); diff --git a/interface/wx/persist/window.h b/interface/wx/persist/window.h new file mode 100644 index 0000000000..6219c59d4f --- /dev/null +++ b/interface/wx/persist/window.h @@ -0,0 +1,51 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/window.h +// Purpose: interface of wxPersistentWindow<> +// Author: Vadim Zeitlin +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +/** + Base class for persistent windows. + + Compared to wxPersistentObject this class does three things: + - Most importantly, wxPersistentWindow catches wxWindowDestroyEvent + generated when the window is destroyed and saves its properties + automatically when it happens. + - It implements GetName() using wxWindow::GetName() so that the derived + classes don't need to do it. + - It adds a convenient wxPersistentWindow::Get() accessor returning the + window object of the correct type. + */ +template +class wxPersistentWindow : public wxPersistentObject +{ +public: + /// The type of the associated window. + typedef T WindowType; + + /** + Constructor for a persistent window object. + + The constructor uses wxEvtHandler::Connect() to catch + wxWindowDestroyEvent generated when the window is destroyed and call + wxPersistenceManager::SaveAndUnregister() when this happens. This + ensures that the window properties are saved and that this object + itself is deleted when the window is. + */ + wxPersistentWindow(WindowType *win); + + WindowType *Get() const { return static_cast(GetWindow()); } + /** + Implements the base class pure virtual method using wxWindow::GetName(). + + Notice that window names are usually not unique while this function + must return a unique (at least among the objects of this type) string. + Because of this you need to specify a non-default window name in its + constructor when creating it or explicitly call wxWindow::SetName() + before saving or restoring persistent properties. + */ + virtual wxString GetName() const; +}; diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index 71b3fb8872..a808a3a87f 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -51,6 +51,9 @@ #include "wx/imaglist.h" #include "wx/wupdlock.h" +#include "wx/persist/toplevel.h" +#include "wx/persist/treebook.h" + #include "widgets.h" #include "../sample.xpm" @@ -325,6 +328,8 @@ bool WidgetsApp::OnInit() if ( !wxApp::OnInit() ) return false; + SetVendorName("wxWidgets_Samples"); + // the reason for having these ifdef's is that I often run two copies of // this sample side by side and it is useful to see which one is which wxString title; @@ -351,10 +356,6 @@ bool WidgetsApp::OnInit() wxFrame *frame = new WidgetsFrame(title + _T(" widgets demo")); frame->Show(); - //wxLog::AddTraceMask(_T("listbox")); - //wxLog::AddTraceMask(_T("scrollbar")); - //wxLog::AddTraceMask(_T("focus")); - return true; } @@ -365,15 +366,18 @@ bool WidgetsApp::OnInit() WidgetsFrame::WidgetsFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title) { + SetName("Main"); + const bool sizeSet = wxPersistenceManager::Get().RegisterAndRestore(this); + // set the frame icon SetIcon(wxICON(sample)); // init everything #if USE_LOG - m_lboxLog = (wxListBox *)NULL; - m_logTarget = (wxLog *)NULL; + m_lboxLog = NULL; + m_logTarget = NULL; #endif // USE_LOG - m_book = (WidgetsBookCtrl *)NULL; + m_book = NULL; #if wxUSE_MENUS // create the menubar @@ -435,13 +439,10 @@ WidgetsFrame::WidgetsFrame(const wxString& title) // Uncomment to suppress page theme (draw in solid colour) //style |= wxNB_NOPAGETHEME; - m_book = new WidgetsBookCtrl(m_panel, Widgets_BookCtrl, wxDefaultPosition, -#ifdef __WXMOTIF__ - wxSize(500, wxDefaultCoord), // under Motif, height is a function of the width... -#else - wxDefaultSize, -#endif - style); + m_book = new WidgetsBookCtrl(m_panel, Widgets_BookCtrl, + wxDefaultPosition, wxDefaultSize, + style, "Widgets"); + InitBook(); #ifndef __WXHANDHELD__ @@ -482,7 +483,10 @@ WidgetsFrame::WidgetsFrame(const wxString& title) m_panel->SetSizer(sizerTop); - sizerTop->SetSizeHints(this); + const wxSize sizeMin = m_panel->GetBestSize(); + if ( !sizeSet ) + SetClientSize(sizeMin); + SetMinClientSize(sizeMin); #if USE_LOG && !defined(__WXCOCOA__) // wxCocoa's listbox is too flakey to use for logging right now @@ -613,10 +617,13 @@ void WidgetsFrame::InitBook() wxEVT_COMMAND_WIDGETS_PAGE_CHANGED, wxWidgetsbookEventHandler(WidgetsFrame::OnPageChanged) ); + const bool pageSet = wxPersistenceManager::Get().RegisterAndRestore(m_book); + #if USE_TREEBOOK // for treebook page #0 is empty parent page only so select the first page // with some contents - m_book->SetSelection(1); + if ( !pageSet ) + m_book->SetSelection(1); // but ensure that the top of the tree is shown nevertheless wxTreeCtrl * const tree = m_book->GetTreeCtrl(); @@ -624,10 +631,13 @@ void WidgetsFrame::InitBook() wxTreeItemIdValue cookie; tree->EnsureVisible(tree->GetFirstChild(tree->GetRootItem(), cookie)); #else - // for other books set selection twice to force connected event handler - // to force lazy creation of initial visible content - m_book->SetSelection(1); - m_book->SetSelection(0); + if ( !pageSet ) + { + // for other books set selection twice to force connected event handler + // to force lazy creation of initial visible content + m_book->SetSelection(1); + m_book->SetSelection(0); + } #endif // USE_TREEBOOK } diff --git a/src/common/persist.cpp b/src/common/persist.cpp new file mode 100644 index 0000000000..80df492e5e --- /dev/null +++ b/src/common/persist.cpp @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/common/persist.cpp +// Purpose: common persistence support classes +// Author: Vadim Zeitlin +// Created: 2009-01-20 +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// 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/persist.h" + +// ============================================================================ +// wxPersistenceManager implementation +// ============================================================================ + +/* static */ +wxPersistenceManager& wxPersistenceManager::Get() +{ + static wxPersistenceManager s_manager; + + return s_manager; +} + +wxString +wxPersistenceManager::GetKey(const wxPersistentObject& who, + const wxString& name) const +{ + wxString key("Persistent_Options"); // TODO: make this configurable + key << wxCONFIG_PATH_SEPARATOR << who.GetKind() + << wxCONFIG_PATH_SEPARATOR << who.GetName() + << wxCONFIG_PATH_SEPARATOR << name; + + return key; +} + +wxPersistentObject *wxPersistenceManager::Find(void *obj) const +{ + const wxPersistentObjectsMap::const_iterator + it = m_persistentObjects.find(obj); + return it == m_persistentObjects.end() ? NULL : it->second; +} + +wxPersistentObject * +wxPersistenceManager::Register(void *obj, wxPersistentObject *po) +{ + if ( wxPersistentObject *old = Find(obj) ) + { + wxFAIL_MSG( "object is already registered" ); + + delete po; // still avoid the memory leaks + return old; + } + + m_persistentObjects[obj] = po; + + return po; +} + +void wxPersistenceManager::Unregister(void *obj) +{ + wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); + wxCHECK_RET( it != m_persistentObjects.end(), "not registered" ); + + wxPersistentObject * const po = it->second; + m_persistentObjects.erase(it); + delete po; +} + +void wxPersistenceManager::Save(void *obj) +{ + if ( !m_doSave ) + return; + + wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); + wxCHECK_RET( it != m_persistentObjects.end(), "not registered" ); + + it->second->Save(); +} + +bool wxPersistenceManager::Restore(void *obj) +{ + if ( !m_doRestore ) + return false; + + wxPersistentObjectsMap::iterator it = m_persistentObjects.find(obj); + wxCHECK_MSG( it != m_persistentObjects.end(), false, "not registered" ); + + return it->second->Restore(); +} + -- 2.45.2