]> git.saurik.com Git - wxWidgets.git/commitdiff
Add wxIntegerValidator and wxFloatingPointValidator classes.
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 19 Jan 2011 10:48:28 +0000 (10:48 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 19 Jan 2011 10:48:28 +0000 (10:48 +0000)
Add validators for integer and floating point numbers.

Add an example of their use to the validate sample as well as a new unit test
and documentation for them.

Use the new classes instead of wxTextValidator in wxGrid code.

Closes #12166.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66714 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

34 files changed:
Makefile.in
build/bakefiles/files.bkl
build/msw/makefile.bcc
build/msw/makefile.gcc
build/msw/makefile.vc
build/msw/makefile.wat
build/msw/wx_core.dsp
build/msw/wx_vc7_core.vcproj
build/msw/wx_vc8_core.vcproj
build/msw/wx_vc9_core.vcproj
docs/changes.txt
docs/doxygen/mainpages/cat_classes.h
docs/doxygen/overviews/validator.h
include/wx/valnum.h [new file with mode: 0644]
interface/wx/valgen.h
interface/wx/validate.h
interface/wx/valnum.h [new file with mode: 0644]
interface/wx/valtext.h
samples/validate/validate.cpp
samples/validate/validate.h
src/common/valnum.cpp [new file with mode: 0644]
src/generic/grideditors.cpp
tests/Makefile.in
tests/makefile.bcc
tests/makefile.gcc
tests/makefile.vc
tests/makefile.wat
tests/strings/numformatter.cpp
tests/test.bkl
tests/test_test_gui.dsp
tests/test_vc7_test_gui.vcproj
tests/test_vc8_test_gui.vcproj
tests/test_vc9_test_gui.vcproj
tests/validators/valnum.cpp [new file with mode: 0644]

index 74c5e06f2bbf5282350ee83d4bba45370cbdb4cb..b1acf426895e7c534d817ffb70816035bf2874b5 100644 (file)
@@ -3933,6 +3933,7 @@ COND_USE_GUI_1_ALL_GUI_HEADERS =  \
        wx/toolbar.h \
        wx/validate.h \
        wx/valtext.h \
+       wx/valnum.h \
        wx/window.h \
        wx/windowid.h \
        wx/wrapsizer.h \
@@ -4592,6 +4593,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS =  \
        monodll_valgen.o \
        monodll_validate.o \
        monodll_valtext.o \
+       monodll_valnum.o \
        monodll_wincmn.o \
        monodll_windowid.o \
        monodll_wrapsizer.o \
@@ -4805,6 +4807,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS =  \
        monodll_valgen.o \
        monodll_validate.o \
        monodll_valtext.o \
+       monodll_valnum.o \
        monodll_wincmn.o \
        monodll_windowid.o \
        monodll_wrapsizer.o \
@@ -6502,6 +6505,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_1 =  \
        monolib_valgen.o \
        monolib_validate.o \
        monolib_valtext.o \
+       monolib_valnum.o \
        monolib_wincmn.o \
        monolib_windowid.o \
        monolib_wrapsizer.o \
@@ -6715,6 +6719,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_1 =  \
        monolib_valgen.o \
        monolib_validate.o \
        monolib_valtext.o \
+       monolib_valnum.o \
        monolib_wincmn.o \
        monolib_windowid.o \
        monolib_wrapsizer.o \
@@ -8596,6 +8601,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_2 =  \
        coredll_valgen.o \
        coredll_validate.o \
        coredll_valtext.o \
+       coredll_valnum.o \
        coredll_wincmn.o \
        coredll_windowid.o \
        coredll_wrapsizer.o \
@@ -8809,6 +8815,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_2 =  \
        coredll_valgen.o \
        coredll_validate.o \
        coredll_valtext.o \
+       coredll_valnum.o \
        coredll_wincmn.o \
        coredll_windowid.o \
        coredll_wrapsizer.o \
@@ -10168,6 +10175,7 @@ COND_USE_GUI_1_WXUNIV_0___CORE_SRC_OBJECTS_3 =  \
        corelib_valgen.o \
        corelib_validate.o \
        corelib_valtext.o \
+       corelib_valnum.o \
        corelib_wincmn.o \
        corelib_windowid.o \
        corelib_wrapsizer.o \
@@ -10381,6 +10389,7 @@ COND_USE_GUI_1_WXUNIV_1___CORE_SRC_OBJECTS_3 =  \
        corelib_valgen.o \
        corelib_validate.o \
        corelib_valtext.o \
+       corelib_valnum.o \
        corelib_wincmn.o \
        corelib_windowid.o \
        corelib_wrapsizer.o \
@@ -20059,6 +20068,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP)
 @COND_USE_GUI_1@monodll_valtext.o: $(srcdir)/src/common/valtext.cpp $(MONODLL_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/valtext.cpp
 
+@COND_USE_GUI_1@monodll_valnum.o: $(srcdir)/src/common/valnum.cpp $(MONODLL_ODEP)
+@COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/valnum.cpp
+
 @COND_USE_GUI_1@monodll_wincmn.o: $(srcdir)/src/common/wincmn.cpp $(MONODLL_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/wincmn.cpp
 
@@ -25339,6 +25351,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP)
 @COND_USE_GUI_1@monolib_valtext.o: $(srcdir)/src/common/valtext.cpp $(MONOLIB_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/valtext.cpp
 
+@COND_USE_GUI_1@monolib_valnum.o: $(srcdir)/src/common/valnum.cpp $(MONOLIB_ODEP)
+@COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/valnum.cpp
+
 @COND_USE_GUI_1@monolib_wincmn.o: $(srcdir)/src/common/wincmn.cpp $(MONOLIB_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/wincmn.cpp
 
@@ -30799,6 +30814,9 @@ coredll_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(COREDLL_ODEP)
 @COND_USE_GUI_1@coredll_valtext.o: $(srcdir)/src/common/valtext.cpp $(COREDLL_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/valtext.cpp
 
+@COND_USE_GUI_1@coredll_valnum.o: $(srcdir)/src/common/valnum.cpp $(COREDLL_ODEP)
+@COND_USE_GUI_1@       $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/valnum.cpp
+
 @COND_USE_GUI_1@coredll_wincmn.o: $(srcdir)/src/common/wincmn.cpp $(COREDLL_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/common/wincmn.cpp
 
@@ -34762,6 +34780,9 @@ corelib_win32.o: $(srcdir)/src/univ/themes/win32.cpp $(CORELIB_ODEP)
 @COND_USE_GUI_1@corelib_valtext.o: $(srcdir)/src/common/valtext.cpp $(CORELIB_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/valtext.cpp
 
+@COND_USE_GUI_1@corelib_valnum.o: $(srcdir)/src/common/valnum.cpp $(CORELIB_ODEP)
+@COND_USE_GUI_1@       $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/valnum.cpp
+
 @COND_USE_GUI_1@corelib_wincmn.o: $(srcdir)/src/common/wincmn.cpp $(CORELIB_ODEP)
 @COND_USE_GUI_1@       $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/common/wincmn.cpp
 
index 9d59f444d913a62ccf23a853e8d71dafcb8de6ac..9c029fc6cb222a6e1832deed07d86760fc0c1df9 100644 (file)
@@ -766,6 +766,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     src/common/valgen.cpp
     src/common/validate.cpp
     src/common/valtext.cpp
+    src/common/valnum.cpp
     src/common/wincmn.cpp
     src/common/windowid.cpp
     src/common/wrapsizer.cpp
@@ -909,6 +910,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     wx/toolbar.h
     wx/validate.h
     wx/valtext.h
+    wx/valnum.h
     wx/window.h
     wx/windowid.h
     wx/wrapsizer.h
index ca01770400dc6f56f29df61d1b661c2c1525d928..7f3d2ad4db3c8303dace1b37b27444f6a5d0e738 100644 (file)
@@ -1905,6 +1905,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.obj \\r
        $(OBJS)\monodll_validate.obj \\r
        $(OBJS)\monodll_valtext.obj \\r
+       $(OBJS)\monodll_valnum.obj \
        $(OBJS)\monodll_wincmn.obj \\r
        $(OBJS)\monodll_windowid.obj \\r
        $(OBJS)\monodll_wrapsizer.obj \\r
@@ -2166,6 +2167,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.obj \\r
        $(OBJS)\monodll_validate.obj \\r
        $(OBJS)\monodll_valtext.obj \\r
+       $(OBJS)\monodll_valnum.obj \
        $(OBJS)\monodll_wincmn.obj \\r
        $(OBJS)\monodll_windowid.obj \\r
        $(OBJS)\monodll_wrapsizer.obj \\r
@@ -2659,6 +2661,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.obj \\r
        $(OBJS)\monolib_validate.obj \\r
        $(OBJS)\monolib_valtext.obj \\r
+       $(OBJS)\monolib_valnum.obj \
        $(OBJS)\monolib_wincmn.obj \\r
        $(OBJS)\monolib_windowid.obj \\r
        $(OBJS)\monolib_wrapsizer.obj \\r
@@ -2920,6 +2923,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.obj \\r
        $(OBJS)\monolib_validate.obj \\r
        $(OBJS)\monolib_valtext.obj \\r
+       $(OBJS)\monolib_valnum.obj \
        $(OBJS)\monolib_wincmn.obj \\r
        $(OBJS)\monolib_windowid.obj \\r
        $(OBJS)\monolib_wrapsizer.obj \\r
@@ -3301,6 +3305,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.obj \\r
        $(OBJS)\coredll_validate.obj \\r
        $(OBJS)\coredll_valtext.obj \\r
+       $(OBJS)\coredll_valnum.obj \
        $(OBJS)\coredll_wincmn.obj \\r
        $(OBJS)\coredll_windowid.obj \\r
        $(OBJS)\coredll_wrapsizer.obj \\r
@@ -3562,6 +3567,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.obj \\r
        $(OBJS)\coredll_validate.obj \\r
        $(OBJS)\coredll_valtext.obj \\r
+       $(OBJS)\coredll_valnum.obj \
        $(OBJS)\coredll_wincmn.obj \\r
        $(OBJS)\coredll_windowid.obj \\r
        $(OBJS)\coredll_wrapsizer.obj \\r
@@ -3832,6 +3838,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.obj \\r
        $(OBJS)\corelib_validate.obj \\r
        $(OBJS)\corelib_valtext.obj \\r
+       $(OBJS)\corelib_valnum.obj \
        $(OBJS)\corelib_wincmn.obj \\r
        $(OBJS)\corelib_windowid.obj \\r
        $(OBJS)\corelib_wrapsizer.obj \\r
@@ -4093,6 +4100,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.obj \\r
        $(OBJS)\corelib_validate.obj \\r
        $(OBJS)\corelib_valtext.obj \\r
+       $(OBJS)\corelib_valnum.obj \
        $(OBJS)\corelib_wincmn.obj \\r
        $(OBJS)\corelib_windowid.obj \\r
        $(OBJS)\corelib_wrapsizer.obj \\r
@@ -7816,6 +7824,11 @@ $(OBJS)\monodll_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\monodll_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\monodll_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -10141,6 +10154,11 @@ $(OBJS)\monolib_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\monolib_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\monolib_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -12460,6 +12478,11 @@ $(OBJS)\coredll_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\coredll_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\coredll_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) -q -c -P -o$@ $(COREDLL_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -13840,6 +13863,11 @@ $(OBJS)\corelib_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\corelib_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\corelib_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) -q -c -P -o$@ $(CORELIB_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
index f9d1a5467106db7948db82fbd8996d87085b1743..0506d9d1f71cfb4e71d9cfcdc23d90a1f3d4a492 100644 (file)
@@ -1916,6 +1916,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.o \\r
        $(OBJS)\monodll_validate.o \\r
        $(OBJS)\monodll_valtext.o \\r
+       $(OBJS)\monodll_valnum.o \
        $(OBJS)\monodll_wincmn.o \\r
        $(OBJS)\monodll_windowid.o \\r
        $(OBJS)\monodll_wrapsizer.o \\r
@@ -2179,6 +2180,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.o \\r
        $(OBJS)\monodll_validate.o \\r
        $(OBJS)\monodll_valtext.o \\r
+       $(OBJS)\monodll_valnum.o \
        $(OBJS)\monodll_wincmn.o \\r
        $(OBJS)\monodll_windowid.o \\r
        $(OBJS)\monodll_wrapsizer.o \\r
@@ -2676,6 +2678,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.o \\r
        $(OBJS)\monolib_validate.o \\r
        $(OBJS)\monolib_valtext.o \\r
+       $(OBJS)\monolib_valnum.o \
        $(OBJS)\monolib_wincmn.o \\r
        $(OBJS)\monolib_windowid.o \\r
        $(OBJS)\monolib_wrapsizer.o \\r
@@ -2939,6 +2942,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.o \\r
        $(OBJS)\monolib_validate.o \\r
        $(OBJS)\monolib_valtext.o \\r
+       $(OBJS)\monolib_valnum.o \
        $(OBJS)\monolib_wincmn.o \\r
        $(OBJS)\monolib_windowid.o \\r
        $(OBJS)\monolib_wrapsizer.o \\r
@@ -3334,6 +3338,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.o \\r
        $(OBJS)\coredll_validate.o \\r
        $(OBJS)\coredll_valtext.o \\r
+       $(OBJS)\coredll_valnum.o \
        $(OBJS)\coredll_wincmn.o \\r
        $(OBJS)\coredll_windowid.o \\r
        $(OBJS)\coredll_wrapsizer.o \\r
@@ -3597,6 +3602,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.o \\r
        $(OBJS)\coredll_validate.o \\r
        $(OBJS)\coredll_valtext.o \\r
+       $(OBJS)\coredll_valnum.o \
        $(OBJS)\coredll_wincmn.o \\r
        $(OBJS)\coredll_windowid.o \\r
        $(OBJS)\coredll_wrapsizer.o \\r
@@ -3873,6 +3879,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.o \\r
        $(OBJS)\corelib_validate.o \\r
        $(OBJS)\corelib_valtext.o \\r
+       $(OBJS)\corelib_valnum.o \
        $(OBJS)\corelib_wincmn.o \\r
        $(OBJS)\corelib_windowid.o \\r
        $(OBJS)\corelib_wrapsizer.o \\r
@@ -4136,6 +4143,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.o \\r
        $(OBJS)\corelib_validate.o \\r
        $(OBJS)\corelib_valtext.o \\r
+       $(OBJS)\corelib_valnum.o \
        $(OBJS)\corelib_wincmn.o \\r
        $(OBJS)\corelib_windowid.o \\r
        $(OBJS)\corelib_wrapsizer.o \\r
@@ -7966,6 +7974,11 @@ $(OBJS)\monodll_valtext.o: ../../src/common/valtext.cpp
 endif\r
 \r
 ifeq ($(USE_GUI),1)\r
+$(OBJS)\monodll_valnum.o: ../../src/common/valnum.cpp
+       $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
+endif
+
+ifeq ($(USE_GUI),1)
 $(OBJS)\monodll_wincmn.o: ../../src/common/wincmn.cpp\r
        $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<\r
 endif\r
@@ -10291,6 +10304,11 @@ $(OBJS)\monolib_valtext.o: ../../src/common/valtext.cpp
 endif\r
 \r
 ifeq ($(USE_GUI),1)\r
+$(OBJS)\monolib_valnum.o: ../../src/common/valnum.cpp
+       $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
+endif
+
+ifeq ($(USE_GUI),1)
 $(OBJS)\monolib_wincmn.o: ../../src/common/wincmn.cpp\r
        $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<\r
 endif\r
@@ -12610,6 +12628,11 @@ $(OBJS)\coredll_valtext.o: ../../src/common/valtext.cpp
 endif\r
 \r
 ifeq ($(USE_GUI),1)\r
+$(OBJS)\coredll_valnum.o: ../../src/common/valnum.cpp
+       $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $<
+endif
+
+ifeq ($(USE_GUI),1)
 $(OBJS)\coredll_wincmn.o: ../../src/common/wincmn.cpp\r
        $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $<\r
 endif\r
@@ -13990,6 +14013,11 @@ $(OBJS)\corelib_valtext.o: ../../src/common/valtext.cpp
 endif\r
 \r
 ifeq ($(USE_GUI),1)\r
+$(OBJS)\corelib_valnum.o: ../../src/common/valnum.cpp
+       $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $<
+endif
+
+ifeq ($(USE_GUI),1)
 $(OBJS)\corelib_wincmn.o: ../../src/common/wincmn.cpp\r
        $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $<\r
 endif\r
index 322a1bfe3b61a99c4a1f271bc3e229a77668961f..395efdab18e4835ac4861ef97188def77a033b69 100644 (file)
@@ -2113,6 +2113,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.obj \\r
        $(OBJS)\monodll_validate.obj \\r
        $(OBJS)\monodll_valtext.obj \\r
+       $(OBJS)\monodll_valnum.obj \
        $(OBJS)\monodll_wincmn.obj \\r
        $(OBJS)\monodll_windowid.obj \\r
        $(OBJS)\monodll_wrapsizer.obj \\r
@@ -2374,6 +2375,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  \
        $(OBJS)\monodll_valgen.obj \\r
        $(OBJS)\monodll_validate.obj \\r
        $(OBJS)\monodll_valtext.obj \\r
+       $(OBJS)\monodll_valnum.obj \
        $(OBJS)\monodll_wincmn.obj \\r
        $(OBJS)\monodll_windowid.obj \\r
        $(OBJS)\monodll_wrapsizer.obj \\r
@@ -2873,6 +2875,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.obj \\r
        $(OBJS)\monolib_validate.obj \\r
        $(OBJS)\monolib_valtext.obj \\r
+       $(OBJS)\monolib_valnum.obj \
        $(OBJS)\monolib_wincmn.obj \\r
        $(OBJS)\monolib_windowid.obj \\r
        $(OBJS)\monolib_wrapsizer.obj \\r
@@ -3134,6 +3137,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  \
        $(OBJS)\monolib_valgen.obj \\r
        $(OBJS)\monolib_validate.obj \\r
        $(OBJS)\monolib_valtext.obj \\r
+       $(OBJS)\monolib_valnum.obj \
        $(OBJS)\monolib_wincmn.obj \\r
        $(OBJS)\monolib_windowid.obj \\r
        $(OBJS)\monolib_wrapsizer.obj \\r
@@ -3581,6 +3585,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.obj \\r
        $(OBJS)\coredll_validate.obj \\r
        $(OBJS)\coredll_valtext.obj \\r
+       $(OBJS)\coredll_valnum.obj \
        $(OBJS)\coredll_wincmn.obj \\r
        $(OBJS)\coredll_windowid.obj \\r
        $(OBJS)\coredll_wrapsizer.obj \\r
@@ -3842,6 +3847,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  \
        $(OBJS)\coredll_valgen.obj \\r
        $(OBJS)\coredll_validate.obj \\r
        $(OBJS)\coredll_valtext.obj \\r
+       $(OBJS)\coredll_valnum.obj \
        $(OBJS)\coredll_wincmn.obj \\r
        $(OBJS)\coredll_windowid.obj \\r
        $(OBJS)\coredll_wrapsizer.obj \\r
@@ -4118,6 +4124,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.obj \\r
        $(OBJS)\corelib_validate.obj \\r
        $(OBJS)\corelib_valtext.obj \\r
+       $(OBJS)\corelib_valnum.obj \
        $(OBJS)\corelib_wincmn.obj \\r
        $(OBJS)\corelib_windowid.obj \\r
        $(OBJS)\corelib_wrapsizer.obj \\r
@@ -4379,6 +4386,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  \
        $(OBJS)\corelib_valgen.obj \\r
        $(OBJS)\corelib_validate.obj \\r
        $(OBJS)\corelib_valtext.obj \\r
+       $(OBJS)\corelib_valnum.obj \
        $(OBJS)\corelib_wincmn.obj \\r
        $(OBJS)\corelib_windowid.obj \\r
        $(OBJS)\corelib_wrapsizer.obj \\r
@@ -8396,6 +8404,11 @@ $(OBJS)\monodll_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\monodll_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\monodll_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -10721,6 +10734,11 @@ $(OBJS)\monolib_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\monolib_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\monolib_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -13040,6 +13058,11 @@ $(OBJS)\coredll_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\coredll_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\coredll_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
@@ -14420,6 +14443,11 @@ $(OBJS)\corelib_valtext.obj: ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !if "$(USE_GUI)" == "1"\r
+$(OBJS)\corelib_valnum.obj: ..\..\src\common\valnum.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\common\valnum.cpp
+!endif
+
+!if "$(USE_GUI)" == "1"
 $(OBJS)\corelib_wincmn.obj: ..\..\src\common\wincmn.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\common\wincmn.cpp\r
 !endif\r
index 86cd7fdcf92e56d829224c2c79757ef917c47439..0b32d6b439b8098876f10757d5f2dfce897bea94 100644 (file)
@@ -467,6 +467,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  &
        $(OBJS)\monodll_valgen.obj &\r
        $(OBJS)\monodll_validate.obj &\r
        $(OBJS)\monodll_valtext.obj &\r
+       $(OBJS)\monodll_valnum.obj &
        $(OBJS)\monodll_wincmn.obj &\r
        $(OBJS)\monodll_windowid.obj &\r
        $(OBJS)\monodll_wrapsizer.obj &\r
@@ -730,6 +731,7 @@ ____CORE_SRC_FILENAMES_OBJECTS =  &
        $(OBJS)\monodll_valgen.obj &\r
        $(OBJS)\monodll_validate.obj &\r
        $(OBJS)\monodll_valtext.obj &\r
+       $(OBJS)\monodll_valnum.obj &
        $(OBJS)\monodll_wincmn.obj &\r
        $(OBJS)\monodll_windowid.obj &\r
        $(OBJS)\monodll_wrapsizer.obj &\r
@@ -1232,6 +1234,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  &
        $(OBJS)\monolib_valgen.obj &\r
        $(OBJS)\monolib_validate.obj &\r
        $(OBJS)\monolib_valtext.obj &\r
+       $(OBJS)\monolib_valnum.obj &
        $(OBJS)\monolib_wincmn.obj &\r
        $(OBJS)\monolib_windowid.obj &\r
        $(OBJS)\monolib_wrapsizer.obj &\r
@@ -1495,6 +1498,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS =  &
        $(OBJS)\monolib_valgen.obj &\r
        $(OBJS)\monolib_validate.obj &\r
        $(OBJS)\monolib_valtext.obj &\r
+       $(OBJS)\monolib_valnum.obj &
        $(OBJS)\monolib_wincmn.obj &\r
        $(OBJS)\monolib_windowid.obj &\r
        $(OBJS)\monolib_wrapsizer.obj &\r
@@ -1901,6 +1905,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  &
        $(OBJS)\coredll_valgen.obj &\r
        $(OBJS)\coredll_validate.obj &\r
        $(OBJS)\coredll_valtext.obj &\r
+       $(OBJS)\coredll_valnum.obj &
        $(OBJS)\coredll_wincmn.obj &\r
        $(OBJS)\coredll_windowid.obj &\r
        $(OBJS)\coredll_wrapsizer.obj &\r
@@ -2164,6 +2169,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS =  &
        $(OBJS)\coredll_valgen.obj &\r
        $(OBJS)\coredll_validate.obj &\r
        $(OBJS)\coredll_valtext.obj &\r
+       $(OBJS)\coredll_valnum.obj &
        $(OBJS)\coredll_wincmn.obj &\r
        $(OBJS)\coredll_windowid.obj &\r
        $(OBJS)\coredll_wrapsizer.obj &\r
@@ -2442,6 +2448,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  &
        $(OBJS)\corelib_valgen.obj &\r
        $(OBJS)\corelib_validate.obj &\r
        $(OBJS)\corelib_valtext.obj &\r
+       $(OBJS)\corelib_valnum.obj &
        $(OBJS)\corelib_wincmn.obj &\r
        $(OBJS)\corelib_windowid.obj &\r
        $(OBJS)\corelib_wrapsizer.obj &\r
@@ -2705,6 +2712,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS =  &
        $(OBJS)\corelib_valgen.obj &\r
        $(OBJS)\corelib_validate.obj &\r
        $(OBJS)\corelib_valtext.obj &\r
+       $(OBJS)\corelib_valnum.obj &
        $(OBJS)\corelib_wincmn.obj &\r
        $(OBJS)\corelib_windowid.obj &\r
        $(OBJS)\corelib_wrapsizer.obj &\r
@@ -8225,6 +8233,11 @@ $(OBJS)\monodll_valtext.obj :  .AUTODEPEND ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !ifeq USE_GUI 1\r
+$(OBJS)\monodll_valnum.obj :  .AUTODEPEND ..\..\src\common\valnum.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $<
+!endif
+
+!ifeq USE_GUI 1
 $(OBJS)\monodll_wincmn.obj :  .AUTODEPEND ..\..\src\common\wincmn.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $<\r
 !endif\r
@@ -10550,6 +10563,11 @@ $(OBJS)\monolib_valtext.obj :  .AUTODEPEND ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !ifeq USE_GUI 1\r
+$(OBJS)\monolib_valnum.obj :  .AUTODEPEND ..\..\src\common\valnum.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $<
+!endif
+
+!ifeq USE_GUI 1
 $(OBJS)\monolib_wincmn.obj :  .AUTODEPEND ..\..\src\common\wincmn.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $<\r
 !endif\r
@@ -12869,6 +12887,11 @@ $(OBJS)\coredll_valtext.obj :  .AUTODEPEND ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !ifeq USE_GUI 1\r
+$(OBJS)\coredll_valnum.obj :  .AUTODEPEND ..\..\src\common\valnum.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $<
+!endif
+
+!ifeq USE_GUI 1
 $(OBJS)\coredll_wincmn.obj :  .AUTODEPEND ..\..\src\common\wincmn.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(COREDLL_CXXFLAGS) $<\r
 !endif\r
@@ -14249,6 +14272,11 @@ $(OBJS)\corelib_valtext.obj :  .AUTODEPEND ..\..\src\common\valtext.cpp
 !endif\r
 \r
 !ifeq USE_GUI 1\r
+$(OBJS)\corelib_valnum.obj :  .AUTODEPEND ..\..\src\common\valnum.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $<
+!endif
+
+!ifeq USE_GUI 1
 $(OBJS)\corelib_wincmn.obj :  .AUTODEPEND ..\..\src\common\wincmn.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(CORELIB_CXXFLAGS) $<\r
 !endif\r
index 233278896eb59dbb82436dd56eafa5b2c681f0e2..8fafe9801938c700854b575097704b38bb7f2fdf 100644 (file)
@@ -730,6 +730,10 @@ SOURCE=..\..\src\common\validate.cpp
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\src\common\valnum.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\src\common\valtext.cpp\r
 # End Source File\r
 # Begin Source File\r
@@ -6797,6 +6801,10 @@ SOURCE=..\..\include\wx\validate.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\include\wx\valnum.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\include\wx\valtext.h\r
 # End Source File\r
 # Begin Source File\r
index 1af35ea21e17c30d3c34cb3e3961bc0388b347e4..f06e630c335fe339afff023e032c087b8f2545a7 100644 (file)
                                RelativePath="..\..\src\common\validate.cpp">\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\src\common\valnum.cpp">
+                       </File>
+                       <File
                                RelativePath="..\..\src\common\valtext.cpp">\r
                        </File>\r
                        <File\r
                                RelativePath="..\..\include\wx\validate.h">\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\include\wx\valnum.h">
+                       </File>
+                       <File
                                RelativePath="..\..\include\wx\valtext.h">\r
                        </File>\r
                        <File\r
index c84aa41ddcf3507e56780bb9c94bead1c1115c0a..4f9adc4de2b186bb43ce40ed012ad91391b54be2 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\src\common\valnum.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\src\common\valtext.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\include\wx\valnum.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\include\wx\valtext.h"\r
                                >\r
                        </File>\r
index d007bd54f5e50137a4e3ffdb5a9ded80642693f7..8113db4af9a16e9402f35da73591a9b4a6fa4a1d 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\src\common\valnum.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\src\common\valtext.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\..\include\wx\valnum.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\include\wx\valtext.h"\r
                                >\r
                        </File>\r
index b1efe24315eb35edde419e9e1bc17034821b5046..0e564f755a12fa9d614857f31f83f2076993e408 100644 (file)
@@ -423,6 +423,7 @@ All:
 - Added negatable command line switches (Armel Asselin).
 - Added wxVersionInfo and various GetLibraryVersionInfo() functions (troelsk).
 - Added wxNumberFormatter for dealing with thousands separators.
+- Added wxIntegerValidator<> and wxFloatingPointValidator<> validators.
 
 Unix:
 
index 282cbdadc5537995d2cb87e2edb282e9194ccf6c..c1a895e05786f7fbcceb4ed2021b85d2e5152608 100644 (file)
@@ -208,6 +208,8 @@ Related Overviews: @ref overview_validator
 @li wxValidator: Base validator class
 @li wxTextValidator: Text control validator class
 @li wxGenericValidator: Generic control validator class
+@li wxIntegerValidator: Text control validator class for integer numbers
+@li wxFloatingPointValidator: Text control validator class for floating point numbers
 
 
 
index 42038a6d1f2533767b6f83ea37f685b4de02ffc0..81010b915fadcadad11a1318edd06647c080273a 100644 (file)
@@ -10,7 +10,8 @@
 
 @page overview_validator wxValidator Overview
 
-Classes: wxValidator, wxTextValidator, wxGenericValidator
+Classes: wxValidator, wxTextValidator, wxGenericValidator, wxIntegerValidator,
+wxFloatingPointValidator
 
 @li @ref overview_validator_intro
 @li @ref overview_validator_anatomy
diff --git a/include/wx/valnum.h b/include/wx/valnum.h
new file mode 100644 (file)
index 0000000..428fe7f
--- /dev/null
@@ -0,0 +1,457 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/valnum.h
+// Purpose:     Numeric validator classes.
+// Author:      Vadim Zeitlin based on the submission of Fulvio Senore
+// Created:     2010-11-06
+// Copyright:   (c) 2010 wxWidgets team
+//              (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_VALNUM_H_
+#define _WX_VALNUM_H_
+
+#include "wx/defs.h"
+
+#if wxUSE_VALIDATORS
+
+#include "wx/validate.h"
+
+#include <limits>
+
+// Bit masks used for numeric validator styles.
+enum wxNumValidatorStyle
+{
+    wxNUM_VAL_DEFAULT               = 0x0,
+    wxNUM_VAL_THOUSANDS_SEPARATOR   = 0x1,
+    wxNUM_VAL_ZERO_AS_BLANK         = 0x2,
+    wxNUM_VAL_NO_TRAILING_ZEROES    = 0x4
+};
+
+// ----------------------------------------------------------------------------
+// Base class for all numeric validators.
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_CORE wxNumValidatorBase : public wxValidator
+{
+public:
+    // Change the validator style. Usually it's specified during construction.
+    void SetStyle(int style) { m_style = style; }
+
+
+    // Override base class method to not do anything but always return success:
+    // we don't need this as we do our validation on the fly here.
+    virtual bool Validate(wxWindow * WXUNUSED(parent)) { return true; }
+
+protected:
+    wxNumValidatorBase(int style)
+    {
+        m_style = style;
+    }
+
+    wxNumValidatorBase(const wxNumValidatorBase& other)
+    {
+        m_style = other.m_style;
+    }
+
+    bool HasFlag(wxNumValidatorStyle style) const
+    {
+        return (m_style & style) != 0;
+    }
+
+    // Get the text entry of the associated control. Normally shouldn't ever
+    // return NULL (and will assert if it does return it) but the caller should
+    // still test the return value for safety.
+    wxTextEntry *GetTextEntry() const;
+
+    // Convert wxNUM_VAL_THOUSANDS_SEPARATOR and wxNUM_VAL_NO_TRAILING_ZEROES
+    // bits of our style to the corresponding wxNumberFormatter::Style values.
+    int GetFormatFlags() const;
+
+    // Return true if pressing a '-' key is acceptable for the current control
+    // contents and insertion point. This is meant to be called from the
+    // derived class IsCharOk() implementation.
+    bool IsMinusOk(const wxString& val, int pos) const;
+
+    // Return the string which would result from inserting the given character
+    // at the specified position.
+    wxString GetValueAfterInsertingChar(wxString val, int pos, wxChar ch) const
+    {
+        val.insert(pos, ch);
+        return val;
+    }
+
+private:
+    // Check whether the specified character can be inserted in the control at
+    // the given position in the string representing the current controls
+    // contents.
+    //
+    // Notice that the base class checks for '-' itself so it's never passed to
+    // this function.
+    virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const = 0;
+
+    // NormalizeString the contents of the string if it's a valid number, return
+    // empty string otherwise.
+    virtual wxString NormalizeString(const wxString& s) const = 0;
+
+
+    // Event handlers.
+    void OnChar(wxKeyEvent& event);
+    void OnKillFocus(wxFocusEvent& event);
+
+
+    // Determine the current insertion point and text in the associated control.
+    void GetCurrentValueAndInsertionPoint(wxString& val, int& pos) const;
+
+
+    // Combination of wxVAL_NUM_XXX values.
+    int m_style;
+
+
+    wxDECLARE_EVENT_TABLE();
+
+    wxDECLARE_NO_ASSIGN_CLASS(wxNumValidatorBase);
+};
+
+namespace wxPrivate
+{
+
+// This is a helper class used by wxIntegerValidator and wxFloatingPointValidator
+// below that implements Transfer{To,From}Window() adapted to the type of the
+// variable.
+//
+// The template argument B is the name of the base class which must derive from
+// wxNumValidatorBase and define LongestValueType type and {To,As}String()
+// methods i.e. basically be one of wx{Integer,Number}ValidatorBase classes.
+//
+// The template argument T is just the type handled by the validator that will
+// inherit from this one.
+template <class B, typename T>
+class wxNumValidator : public B
+{
+public:
+    typedef B BaseValidator;
+    typedef T ValueType;
+
+    typedef typename BaseValidator::LongestValueType LongestValueType;
+
+    wxCOMPILE_TIME_ASSERT
+    (
+        sizeof(ValueType) <= sizeof(LongestValueType),
+        UnsupportedType
+    );
+
+    void SetMin(ValueType min)
+    {
+        this->DoSetMin(min);
+    }
+
+    void SetMax(ValueType max)
+    {
+        this->DoSetMax(max);
+    }
+
+    void SetRange(ValueType min, ValueType max)
+    {
+        SetMin(min);
+        SetMax(max);
+    }
+
+    virtual bool TransferToWindow()
+    {
+        if ( m_value )
+        {
+            wxTextEntry * const control = BaseValidator::GetTextEntry();
+            if ( !control )
+                return false;
+
+            control->SetValue(NormalizeValue(*m_value));
+        }
+
+        return true;
+    }
+
+    virtual bool TransferFromWindow()
+    {
+        if ( m_value )
+        {
+            wxTextEntry * const control = BaseValidator::GetTextEntry();
+            if ( !control )
+                return false;
+
+            const wxString s(control->GetValue());
+            LongestValueType value;
+            if ( s.empty() && BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
+                value = 0;
+            else if ( !BaseValidator::FromString(s, &value) )
+                return false;
+
+            if ( !IsInRange(value) )
+                return false;
+
+            *m_value = static_cast<ValueType>(value);
+        }
+
+        return true;
+    }
+
+protected:
+    wxNumValidator(ValueType *value, int style)
+        : BaseValidator(style),
+          m_value(value)
+    {
+    }
+
+    // Implement wxNumValidatorBase virtual method which is the same for
+    // both integer and floating point numbers.
+    virtual wxString NormalizeString(const wxString& s) const
+    {
+        LongestValueType value;
+        return BaseValidator::FromString(s, &value) ? NormalizeValue(value)
+                                                    : wxString();
+    }
+
+private:
+    // Just a helper which is a common part of TransferToWindow() and
+    // NormalizeString(): returns string representation of a number honouring
+    // wxNUM_VAL_ZERO_AS_BLANK flag.
+    wxString NormalizeValue(LongestValueType value) const
+    {
+        wxString s;
+        if ( value != 0 || !BaseValidator::HasFlag(wxNUM_VAL_ZERO_AS_BLANK) )
+            s = ToString(value);
+
+        return s;
+    }
+
+
+    ValueType * const m_value;
+
+    wxDECLARE_NO_ASSIGN_CLASS(wxNumValidator);
+};
+
+} // namespace wxPrivate
+
+// ----------------------------------------------------------------------------
+// Validators for integer numbers.
+// ----------------------------------------------------------------------------
+
+// Base class for integer numbers validator. This class contains all non
+// type-dependent code of wxIntegerValidator<> and always works with values of
+// type LongestValueType. It is not meant to be used directly, please use
+// wxIntegerValidator<> only instead.
+class WXDLLIMPEXP_CORE wxIntegerValidatorBase : public wxNumValidatorBase
+{
+protected:
+    // Define the type we use here, it should be the maximal-sized integer type
+    // we support to make it possible to base wxIntegerValidator<> for any type
+    // on it.
+#ifdef wxLongLong_t
+    typedef wxLongLong_t LongestValueType;
+#else
+    typedef long LongestValueType;
+#endif
+
+    wxIntegerValidatorBase(int style)
+        : wxNumValidatorBase(style)
+    {
+        wxASSERT_MSG( !(style & wxNUM_VAL_NO_TRAILING_ZEROES),
+                      "This style doesn't make sense for integers." );
+    }
+
+    wxIntegerValidatorBase(const wxIntegerValidatorBase& other)
+        : wxNumValidatorBase(other)
+    {
+        m_min = other.m_min;
+        m_max = other.m_max;
+    }
+
+    // Provide methods for wxNumValidator use.
+    wxString ToString(LongestValueType value) const;
+    static bool FromString(const wxString& s, LongestValueType *value);
+
+    void DoSetMin(LongestValueType min) { m_min = min; }
+    void DoSetMax(LongestValueType max) { m_max = max; }
+
+    bool IsInRange(LongestValueType value) const
+    {
+        return m_min <= value && value <= m_max;
+    }
+
+    // Implement wxNumValidatorBase pure virtual method.
+    virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
+
+private:
+    // Minimal and maximal values accepted (inclusive).
+    LongestValueType m_min, m_max;
+
+    wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidatorBase);
+};
+
+// Validator for integer numbers. It can actually work with any integer type
+// (short, int or long and long long if supported) and their unsigned versions
+// as well.
+template <typename T>
+class wxIntegerValidator
+    : public wxPrivate::wxNumValidator<wxIntegerValidatorBase, T>
+{
+public:
+    typedef T ValueType;
+
+    typedef
+        wxPrivate::wxNumValidator<wxIntegerValidatorBase, T> Base;
+
+    // Ctor for an integer validator.
+    //
+    // Sets the range appropriately for the type, including setting 0 as the
+    // minimal value for the unsigned types.
+    wxIntegerValidator(ValueType *value = NULL, int style = wxNUM_VAL_DEFAULT)
+        : Base(value, style)
+    {
+        DoSetMin(std::numeric_limits<ValueType>::min());
+        DoSetMax(std::numeric_limits<ValueType>::max());
+    }
+
+    virtual wxObject *Clone() const { return new wxIntegerValidator(*this); }
+
+private:
+    wxDECLARE_NO_ASSIGN_CLASS(wxIntegerValidator);
+};
+
+// Helper function for creating integer validators which allows to avoid
+// explicitly specifying the type as it deduces it from its parameter.
+template <typename T>
+inline wxIntegerValidator<T>
+wxMakeIntegerValidator(T *value, int style = wxNUM_VAL_DEFAULT)
+{
+    return wxIntegerValidator<T>(value, style);
+}
+
+// ----------------------------------------------------------------------------
+// Validators for floating point numbers.
+// ----------------------------------------------------------------------------
+
+// Similar to wxIntegerValidatorBase, this class is not meant to be used
+// directly, only wxFloatingPointValidator<> should be used in the user code.
+class WXDLLIMPEXP_CORE wxFloatingPointValidatorBase : public wxNumValidatorBase
+{
+public:
+    // Set precision i.e. the number of digits shown (and accepted on input)
+    // after the decimal point. By default this is set to the maximal precision
+    // supported by the type handled by the validator.
+    void SetPrecision(unsigned precision) { m_precision = precision; }
+
+protected:
+    // Notice that we can't use "long double" here because it's not supported
+    // by wxNumberFormatter yet, so restrict ourselves to just double (and
+    // float).
+    typedef double LongestValueType;
+
+    wxFloatingPointValidatorBase(int style)
+        : wxNumValidatorBase(style)
+    {
+    }
+
+    wxFloatingPointValidatorBase(const wxFloatingPointValidatorBase& other)
+        : wxNumValidatorBase(other)
+    {
+        m_precision = other.m_precision;
+
+        m_min = other.m_min;
+        m_max = other.m_max;
+    }
+
+    // Provide methods for wxNumValidator use.
+    wxString ToString(LongestValueType value) const;
+    static bool FromString(const wxString& s, LongestValueType *value);
+
+    void DoSetMin(LongestValueType min) { m_min = min; }
+    void DoSetMax(LongestValueType max) { m_max = max; }
+
+    bool IsInRange(LongestValueType value) const
+    {
+        return m_min <= value && value <= m_max;
+    }
+
+    // Implement wxNumValidatorBase pure virtual method.
+    virtual bool IsCharOk(const wxString& val, int pos, wxChar ch) const;
+
+private:
+    // Maximum number of decimals digits after the decimal separator.
+    unsigned m_precision;
+
+    // Minimal and maximal values accepted (inclusive).
+    LongestValueType m_min, m_max;
+
+    wxDECLARE_NO_ASSIGN_CLASS(wxFloatingPointValidatorBase);
+};
+
+// Validator for floating point numbers. It can be used with float, double or
+// long double values.
+template <typename T>
+class wxFloatingPointValidator
+    : public wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T>
+{
+public:
+    typedef T ValueType;
+    typedef wxPrivate::wxNumValidator<wxFloatingPointValidatorBase, T> Base;
+
+    // Ctor using implicit (maximal) precision for this type.
+    wxFloatingPointValidator(ValueType *value = NULL,
+                             int style = wxNUM_VAL_DEFAULT)
+        : Base(value, style)
+    {
+        DoSetMinMax();
+
+        SetPrecision(std::numeric_limits<ValueType>::digits10);
+    }
+
+    // Ctor specifying an explicit precision.
+    wxFloatingPointValidator(int precision,
+                      ValueType *value = NULL,
+                      int style = wxNUM_VAL_DEFAULT)
+        : Base(value, style)
+    {
+        DoSetMinMax();
+
+        this->SetPrecision(precision);
+    }
+
+    virtual wxObject *Clone() const
+    {
+        return new wxFloatingPointValidator(*this);
+    }
+
+private:
+    void DoSetMinMax()
+    {
+        // NB: Do not use min(), it's not the smallest representable value for
+        //     the floating point types but rather the smallest representable
+        //     positive value.
+        DoSetMin(-std::numeric_limits<ValueType>::max());
+        DoSetMax( std::numeric_limits<ValueType>::max());
+    }
+};
+
+// Helper similar to wxMakeIntValidator().
+//
+// NB: Unfortunately we can't just have a wxMakeNumericValidator() which would
+//     return either wxIntegerValidator<> or wxFloatingPointValidator<> so we
+//     do need two different functions.
+template <typename T>
+inline wxFloatingPointValidator<T>
+wxMakeFloatingPointValidator(T *value, int style = wxNUM_VAL_DEFAULT)
+{
+    return wxFloatingPointValidator<T>(value, style);
+}
+
+template <typename T>
+inline wxFloatingPointValidator<T>
+wxMakeFloatingPointValidator(int precision, T *value, int style = wxNUM_VAL_DEFAULT)
+{
+    return wxFloatingPointValidator<T>(precision, value, style);
+}
+
+#endif // wxUSE_VALIDATORS
+
+#endif // _WX_VALNUM_H_
index cc2a6962a59a26d34f6e56c70f67a0fac651ee4b..9a4dc6b45b4204285be5ccf8be833eac2c68a68f 100644 (file)
@@ -27,7 +27,8 @@
     @library{wxcore}
     @category{validator}
 
-    @see @ref overview_validator, wxValidator, wxTextValidator
+    @see @ref overview_validator, wxValidator, wxTextValidator,
+        wxIntegerValidator, wxFloatingPointValidator
 */
 class wxGenericValidator : public wxValidator
 {
index bdbe3aeea4f1a97fde40394899c9e5aea2c599e7..fcaa6a76cb8cc83144436e5f21429f87a11e3acd 100644 (file)
@@ -38,7 +38,8 @@
     @stdobjects
     ::wxDefaultValidator
 
-    @see @ref overview_validator, wxTextValidator, wxGenericValidator
+    @see @ref overview_validator, wxTextValidator, wxGenericValidator,
+        wxIntegerValidator, wxFloatingPointValidator
 */
 class wxValidator : public wxEvtHandler
 {
diff --git a/interface/wx/valnum.h b/interface/wx/valnum.h
new file mode 100644 (file)
index 0000000..56268d3
--- /dev/null
@@ -0,0 +1,346 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/valnum.h
+// Purpose:     Documentation of numeric validator classes.
+// Author:      Vadim Zeitlin based on the submission of Fulvio Senore
+// Created:     2010-11-06
+// Copyright:   (c) 2010 wxWidgets team
+//              (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+/**
+    Bit masks used for numeric validator styles.
+
+    A combination of these flags can be used when creating wxIntegerValidator
+    and wxFloatingPointValidator objects and with their SetStyle() methods.
+
+    @since 2.9.2
+    @category{validator}
+ */
+enum wxNumValidatorStyle
+{
+    /**
+        Indicates absence of any other flags.
+
+        This value corresponds to the default behaviour.
+     */
+    wxNUM_VAL_DEFAULT = 0,
+
+    /**
+        Use thousands separators in the numbers.
+
+        When this style is used, numbers are formatted using the thousands
+        separators after validating the user entry (if the current locale uses
+        the thousands separators character).
+     */
+    wxNUM_VAL_THOUSANDS_SEPARATOR = 1,
+
+    /**
+        Show a value of zero as an empty string.
+
+        With this style a value of zero in the associated variable is
+        translated to an empty string and an empty value of the control is
+        translated to a value of zero.
+     */
+    wxNUM_VAL_ZERO_AS_BLANK = 2,
+
+    /**
+        Remove trailing zeroes from the fractional part of the number.
+
+        This style can only be used with wxFloatingPointValidator and indicates
+        that trailing zeroes should be removed from the control text when it is
+        validated. By default, as many zeroes as needed to satisfy the
+        precision used when creating the validator will be appended.
+
+        For example, without this style a wxFloatingPointValidator with a
+        precision 3 will show the value of 1.5 as "1.500" after validation.
+        With this style, the value will be shown as just "1.5" (while a value
+        of e.g. 1.567 will still be shown with all the three significant
+        digits, of course).
+     */
+    wxNUM_VAL_NO_TRAILING_ZEROES
+
+};
+
+/**
+    wxNumValidator is the common base class for numeric validator classes.
+
+    This class is never used directly, but only as a base class for
+    wxIntegerValidator and wxFloatingPointValidator.
+
+    @tparam T
+        Type of the values used with this validator.
+
+    @category{validator}
+
+    @since 2.9.2
+ */
+template <typename T>
+class wxNumValidator : public wxValidator
+{
+public:
+    /// Type of the values this validator is used with.
+    typedef T ValueType;
+
+    /**
+        Sets the minimal value accepted by the validator.
+
+        This value is inclusive, i.e. the value equal to @a min is accepted.
+     */
+    void SetMin(ValueType min);
+
+    /**
+        Sets the maximal value accepted by the validator.
+
+        This value is inclusive, i.e. the value equal to @a max is accepted.
+     */
+    void SetMax(ValueType max);
+
+    /**
+        Sets both minimal and maximal values accepted by the validator.
+
+        Calling this is equivalent to calling both SetMin() and SetMax().
+     */
+    void SetRange(ValueType min, ValueType max)
+
+
+    /**
+        Change the validator style.
+
+        Can be used to change the style of the validator after its creation.
+        The @a style parameter must be a combination of the values from
+        wxNumValidatorStyle enum.
+     */
+    void SetStyle(int style);
+
+
+    /**
+        Override base class method to format the control contents.
+
+        This method is called when the associated window is shown and it fills
+        it with the contents of the associated variable, if any, formatted
+        according to the validator style.
+
+        It does nothing if there is no associated variable.
+     */
+    virtual bool TransferToWindow();
+
+    /**
+        Override base class method to validate the control contents.
+
+        This method is called to check the correctness of user input and fill
+        the associated variable with the controls numeric value. It returns
+        false if it is not a number in the configured range or if the control
+        contents is empty for a validator without wxNUM_VAL_ZERO_AS_BLANK
+        style.
+
+        It does nothing if there is no associated variable.
+     */
+    virtual bool TransferFromWindow();
+};
+
+/**
+    Validator for text entries used for integer entry.
+
+    This validator can be used with wxTextCtrl or wxComboBox (and potentially
+    any other class implementing wxTextEntry interface) to check that only
+    valid integer values can be entered into them.
+
+    This is a template class which can be instantiated for all the integer types
+    (i.e. @c short, @c int, @c long and <code>long long</code> if available) as
+    well as their unsigned versions.
+
+    By default this validator accepts any integer values in the range
+    appropriate for its type, e.g. <code>INT_MIN..INT_MAX</code> for @c int or
+    <code>0..USHRT_MAX</code> for <code>unsigned short</code>. This range can
+    be restricted further by calling SetMin() and SetMax() or SetRange()
+    methods inherited from the base class.
+
+    A simple example of using this class:
+    @code
+        class MyDialog : public wxDialog
+        {
+        public:
+            MyDialog()
+            {
+                ...
+                // Allow positive integers and display them with thousands
+                // separators.
+                wxIntegerValidator<unsigned long>
+                    val(&m_value, wxNUM_VAL_THOUSANDS_SEPARATOR);
+
+                // If the variable were of type "long" and not "unsigned long"
+                // we would have needed to call val.SetMin(0) but as it is,
+                // this is not needed.
+
+                // Associate it with the text control:
+                new wxTextCtrl(this, ..., val);
+            }
+
+        private:
+            unsigned long m_value;
+        };
+    @endcode
+    For more information, please see @ref overview_validator.
+
+    @library{wxcore}
+    @category{validator}
+
+    @see @ref overview_validator, wxValidator, wxGenericValidator,
+    wxTextValidator, wxMakeIntegerValidator()
+
+    @since 2.9.2
+*/
+template <typename T>
+class wxIntegerValidator : public wxNumValidator<T>
+{
+public:
+    /// Type of the values this validator is used with.
+    typedef T ValueType;
+
+    /**
+        Validator constructor.
+
+        @param value
+            A pointer to the variable associated with the validator. If non
+            @NULL, this variable should have a lifetime equal to or longer than
+            the validator lifetime (which is usually determined by the lifetime
+            of the window).
+        @param style
+            A combination of wxNumValidatorStyle enum values with the exception
+            of wxNUM_VAL_NO_TRAILING_ZEROES which can't be used here.
+    */
+    wxIntegerValidator(ValueType *value = NULL, int style = wxNUM_VAL_DEFAULT);
+};
+
+/**
+    Creates a wxIntegerValidator object with automatic type deduction.
+
+    This function can be used to create wxIntegerValidator object without
+    explicitly specifying its type, e.g. write just:
+    @code
+        new wxTextCtrl(..., wxMakeIntegerValidator(&m_var));
+    @endcode
+    instead of more verbose
+    @code
+        new wxTextCtrl(..., wxIntegerValidator<unsigned long>(&m_var));
+    @endcode
+
+    @since 2.9.2
+ */
+template <typename T>
+wxIntegerValidator<T>
+wxMakeIntegerValidator(T *value, int style = wxNUM_VAL_DEFAULT);
+
+/**
+    Validator for text entries used for floating point numbers entry.
+
+    This validator can be used with wxTextCtrl or wxComboBox (and potentially
+    any other class implementing wxTextEntry interface) to check that only
+    valid floating point values can be entered into them. Currently only fixed
+    format is supported on input, i.e. scientific format with mantissa and
+    exponent is not supported.
+
+    This template class can be instantiated for either @c float or @c double,
+    <code>long double</code> values are not currently supported.
+
+    Similarly to wxIntegerValidator<>, the range for the accepted values is by
+    default set appropriately for the type. Additionally, this validator allows
+    to specify the maximum number of digits that can be entered after the
+    decimal separator. By default this is also set appropriately for the type
+    used, e.g. 6 for @c float and 15 for @c double on a typical IEEE-754-based
+    implementation. As with the range, the precision can be restricted after
+    the validator creation if necessary.
+
+    A simple example of using this class:
+    @code
+        class MyDialog : public wxDialog
+        {
+        public:
+            MyDialog()
+            {
+                ...
+                // Allow floating point numbers from 0 to 100 with 2 decimal
+                // digits only and handle empty string as 0 by default.
+                wxFloatingPointValidator<float>
+                    val(2, &m_value, wxNUM_VAL_ZERO_AS_BLANK);
+                val.SetRange(0, 100);
+
+                // Associate it with the text control:
+                new wxTextCtrl(this, ..., val);
+            }
+
+        private:
+            float m_value;
+        };
+    @endcode
+
+    For more information, please see @ref overview_validator.
+
+    @library{wxcore}
+    @category{validator}
+
+    @see @ref overview_validator, wxValidator, wxGenericValidator,
+    wxTextValidator, wxMakeIntegerValidator()
+
+    @since 2.9.2
+*/
+template <typename T>
+class wxFloatingPointValidator : public wxNumValidator<T>
+{
+public:
+    /// Type of the values this validator is used with.
+    typedef T ValueType;
+
+    /**
+        Validator constructor.
+
+        @param value
+            A pointer to the variable associated with the validator. If non
+            @NULL, this variable should have a lifetime equal to or longer than
+            the validator lifetime (which is usually determined by the lifetime
+            of the window).
+        @param style
+            A combination of wxNumValidatorStyle enum values.
+        @param precision
+            The number of decimal digits after the decimal separator to show
+            and accept.
+    */
+    //@{
+    wxFloatingPointValidator(ValueType *value = NULL,
+                             int style = wxNUM_VAL_DEFAULT);
+    wxFloatingPointValidator(int precision,
+                             ValueType *value = NULL,
+                             int style = wxNUM_VAL_DEFAULT);
+    //@}
+
+
+    /**
+        Set precision.
+
+        Precision is the number of digits shown (and accepted on input)
+        after the decimal point. By default this is set to the maximal
+        precision supported by the type handled by the validator in its
+        constructor.
+     */
+    void SetPrecision(unsigned precision);
+};
+
+/**
+    Creates a wxFloatingPointValidator object with automatic type deduction.
+
+    Similarly to wxMakeIntegerValidator(), this function allows to avoid
+    explicitly specifying the validator type.
+
+    @since 2.9.2
+ */
+//@{
+template <typename T>
+inline wxFloatingPointValidator<T>
+wxMakeFloatingPointValidator(T *value, int style = wxNUM_VAL_DEFAULT);
+
+template <typename T>
+inline wxFloatingPointValidator<T>
+wxMakeFloatingPointValidator(int precision,
+                             T *value, int style = wxNUM_VAL_DEFAULT);
+//@}
index b4f9e0491297804e8607c6eefd7983c238c7cead..f0d03f5f97a2d18739ddaf171e73da5acd9b6be6 100644 (file)
@@ -77,7 +77,8 @@ enum wxTextValidatorStyle
     @library{wxcore}
     @category{validator}
 
-    @see @ref overview_validator, wxValidator, wxGenericValidator
+    @see @ref overview_validator, wxValidator, wxGenericValidator,
+        wxIntegerValidator, wxFloatingPointValidator
 */
 class wxTextValidator : public wxValidator
 {
index 344f719d148070f123a5ae74d38be2d72df19b91..59c9d95036d5a92e711558dc97360579df4b354b 100644 (file)
@@ -31,6 +31,7 @@
 #include "wx/sizer.h"
 #include "wx/valgen.h"
 #include "wx/valtext.h"
+#include "wx/valnum.h"
 
 #ifndef __WXMSW__
     #include "../sample.xpm"
@@ -63,6 +64,8 @@ MyData::MyData()
     m_string = wxT("Spaces are invalid here");
     m_string2 = "Valid text";
     m_listbox_choices.Add(0);
+    m_intValue = 0;
+    m_doubleValue = 12354.31;
 }
 
 // ----------------------------------------------------------------------------
@@ -215,6 +218,9 @@ void MyFrame::OnTestDialog(wxCommandEvent& WXUNUSED(event))
         m_listbox->Append(wxString(wxT("checkbox: ")) + checkbox_state);
         m_listbox->Append(wxString(wxT("combobox: ")) + g_data.m_combobox_choice);
         m_listbox->Append(wxString(wxT("radiobox: ")) + g_radiobox_choices[g_data.m_radiobox_choice]);
+
+        m_listbox->Append(wxString::Format("integer value: %d", g_data.m_intValue));
+        m_listbox->Append(wxString::Format("double value: %.3f", g_data.m_doubleValue));
     }
 }
 
@@ -296,6 +302,49 @@ MyDialog::MyDialog( wxWindow *parent, const wxString& title,
     btn->AddButton(new wxButton(this, wxID_CANCEL));
     btn->Realize();
 
+    // setup a sizer with the controls for numeric validators
+    // ------------------------------------------------------
+
+    wxIntegerValidator<int> valInt(&g_data.m_intValue,
+                                   wxNUM_VAL_THOUSANDS_SEPARATOR |
+                                   wxNUM_VAL_ZERO_AS_BLANK);
+    valInt.SetMin(0); // Only allow positive numbers
+
+    m_numericTextInt = new wxTextCtrl
+                           (
+                                this,
+                                wxID_ANY,
+                                "",
+                                wxDefaultPosition,
+                                wxDefaultSize,
+                                wxTE_RIGHT,
+                                valInt
+                            );
+    m_numericTextInt->SetToolTip("uses wxIntegerValidator to accept positive "
+                                 "integers only");
+
+    m_numericTextDouble = new wxTextCtrl
+                              (
+                                this,
+                                wxID_ANY,
+                                "",
+                                wxDefaultPosition,
+                                wxDefaultSize,
+                                wxTE_RIGHT,
+                                wxMakeFloatingPointValidator
+                                (
+                                    3,
+                                    &g_data.m_doubleValue,
+                                    wxNUM_VAL_THOUSANDS_SEPARATOR |
+                                    wxNUM_VAL_NO_TRAILING_ZEROES
+                                )
+                              );
+    m_numericTextDouble->SetToolTip("uses wxFloatingPointValidator with 3 decimals");
+    wxBoxSizer *numSizer = new wxBoxSizer( wxHORIZONTAL );
+    numSizer->Add( m_numericTextInt, 1, wxALL, 10 );
+    numSizer->Add( m_numericTextDouble, 1, wxALL, 10 );
+
+
 
     // setup the main sizer
     // --------------------
@@ -310,6 +359,8 @@ MyDialog::MyDialog( wxWindow *parent, const wxString& title,
                                     wxGenericValidator(&g_data.m_radiobox_choice)),
                    0, wxGROW | wxLEFT|wxBOTTOM|wxRIGHT, 10);
 
+    mainsizer->Add( numSizer, 0, wxGROW | wxALL );
+
     mainsizer->Add(btn, 0, wxGROW | wxALL, 10);
 
     SetSizer(mainsizer);
index dfef4c78afcaddc1c0e9aa0d16b856f34a5cc6f9..beb50de15db807cbd8f7c6489962fb1d902bf087 100644 (file)
@@ -52,6 +52,9 @@ public:
     bool TransferDataToWindow();
     wxTextCtrl *m_text;
     wxComboBox *m_combobox;
+
+    wxTextCtrl *m_numericTextInt;
+    wxTextCtrl *m_numericTextDouble;
 };
 
 class MyData
@@ -72,6 +75,10 @@ public:
     // the string entered in the combobox's text-edit field.
     wxString m_combobox_choice;
 
+    // variables handled by wxNumericTextValidator
+    int m_intValue;
+    double m_doubleValue;
+
     bool m_checkbox_state;
     int m_radiobox_choice;
 };
diff --git a/src/common/valnum.cpp b/src/common/valnum.cpp
new file mode 100644 (file)
index 0000000..8a84e4f
--- /dev/null
@@ -0,0 +1,299 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/common/valnumtext.cpp
+// Purpose:     Numeric validator classes implementation
+// Author:      Vadim Zeitlin based on the submission of Fulvio Senore
+// Created:     2010-11-06
+// Copyright:   (c) 2010 wxWidgets team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// Declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#if wxUSE_VALIDATORS && wxUSE_TEXTCTRL
+
+#ifndef WX_PRECOMP
+    #include "wx/textctrl.h"
+    #include "wx/combobox.h"
+#endif
+
+#include "wx/valnum.h"
+#include "wx/numformatter.h"
+
+// ============================================================================
+// wxNumValidatorBase implementation
+// ============================================================================
+
+BEGIN_EVENT_TABLE(wxNumValidatorBase, wxValidator)
+    EVT_CHAR(wxNumValidatorBase::OnChar)
+    EVT_KILL_FOCUS(wxNumValidatorBase::OnKillFocus)
+END_EVENT_TABLE()
+
+int wxNumValidatorBase::GetFormatFlags() const
+{
+    int flags = wxNumberFormatter::Style_None;
+    if ( m_style & wxNUM_VAL_THOUSANDS_SEPARATOR )
+        flags |= wxNumberFormatter::Style_WithThousandsSep;
+    if ( m_style & wxNUM_VAL_NO_TRAILING_ZEROES )
+        flags |= wxNumberFormatter::Style_NoTrailingZeroes;
+
+    return flags;
+}
+
+wxTextEntry *wxNumValidatorBase::GetTextEntry() const
+{
+#if wxUSE_TEXTCTRL
+    if ( wxTextCtrl *text = wxDynamicCast(m_validatorWindow, wxTextCtrl) )
+        return text;
+#endif // wxUSE_TEXTCTRL
+
+#if wxUSE_COMBOBOX
+    if ( wxComboBox *combo = wxDynamicCast(m_validatorWindow, wxComboBox) )
+        return combo;
+#endif // wxUSE_COMBOBOX
+
+    wxFAIL_MSG("Can only be used with wxTextCtrl or wxComboBox");
+
+    return NULL;
+}
+
+void
+wxNumValidatorBase::GetCurrentValueAndInsertionPoint(wxString& val,
+                                                             int& pos) const
+{
+    wxTextEntry * const control = GetTextEntry();
+    if ( !control )
+        return;
+
+    val = control->GetValue();
+    pos = control->GetInsertionPoint();
+
+    long selFrom, selTo;
+    control->GetSelection(&selFrom, &selTo);
+
+    const long selLen = selTo - selFrom;
+    if ( selLen )
+    {
+        // Remove selected text because pressing a key would make it disappear.
+        val.erase(selFrom, selLen);
+
+        // And adjust the insertion point to have correct position in the new
+        // string.
+        if ( pos > selFrom )
+        {
+            if ( pos >= selTo )
+                pos -= selLen;
+            else
+                pos = selFrom;
+        }
+    }
+}
+
+bool wxNumValidatorBase::IsMinusOk(const wxString& val, int pos) const
+{
+    // Minus is only ever accepted in the beginning of the string.
+    if ( pos != 0 )
+        return false;
+
+    // And then only if there is no existing minus sign there.
+    if ( !val.empty() && val[0] == '-' )
+        return false;
+
+    return true;
+}
+
+void wxNumValidatorBase::OnChar(wxKeyEvent& event)
+{
+    // By default we just validate this key so don't prevent the normal
+    // handling from taking place.
+    event.Skip();
+
+    if ( !m_validatorWindow )
+        return;
+
+#if wxUSE_UNICODE
+    const int ch = event.GetUnicodeKey();
+    if ( ch == WXK_NONE )
+    {
+        // It's a character without any Unicode equivalent at all, e.g. cursor
+        // arrow or function key, we never filter those.
+        return;
+    }
+#else // !wxUSE_UNICODE
+    const int ch = event.GetKeyCode();
+    if ( ch > WXK_DELETE )
+    {
+        // Not a character neither.
+        return;
+    }
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+    if ( ch < WXK_SPACE || ch == WXK_DELETE )
+    {
+        // Allow ASCII control characters and Delete.
+        return;
+    }
+
+    // Check if this character is allowed in the current state.
+    wxString val;
+    int pos;
+    GetCurrentValueAndInsertionPoint(val, pos);
+
+    if ( !IsCharOk(val, pos, ch) )
+    {
+        if ( !wxValidator::IsSilent() )
+            wxBell();
+
+        // Do not skip the event in this case, stop handling it here.
+        event.Skip(false);
+    }
+}
+
+void wxNumValidatorBase::OnKillFocus(wxFocusEvent& event)
+{
+    wxTextEntry * const control = GetTextEntry();
+    if ( !control )
+        return;
+
+    // When we change the control value below, its "modified" status is reset
+    // so we need to explicitly keep it marked as modified if it was so in the
+    // first place.
+    //
+    // Notice that only wxTextCtrl (and not wxTextEntry) has
+    // IsModified()/MarkDirty() methods hence the need for dynamic cast.
+    wxTextCtrl * const text = wxDynamicCast(m_validatorWindow, wxTextCtrl);
+    const bool wasModified = text ? text->IsModified() : false;
+
+    control->ChangeValue(NormalizeString(control->GetValue()));
+
+    if ( wasModified )
+        text->MarkDirty();
+
+    event.Skip();
+}
+
+// ============================================================================
+// wxIntegerValidatorBase implementation
+// ============================================================================
+
+wxString wxIntegerValidatorBase::ToString(LongestValueType value) const
+{
+    return wxNumberFormatter::ToString(value, GetFormatFlags());
+}
+
+bool
+wxIntegerValidatorBase::FromString(const wxString& s, LongestValueType *value)
+{
+    return wxNumberFormatter::FromString(s, value);
+}
+
+bool
+wxIntegerValidatorBase::IsCharOk(const wxString& val, int pos, wxChar ch) const
+{
+    // We may accept minus sign if we can represent negative numbers at all.
+    if ( ch == '-' )
+    {
+        // Notice that entering '-' can make our value invalid, for example if
+        // we're limited to -5..15 range and the current value is 12, then the
+        // new value would be (invalid) -12. We consider it better to let the
+        // user do this because perhaps he is going to press Delete key next to
+        // make it -2 and forcing him to delete 1 first would be unnatural.
+        //
+        // TODO: It would be nice to indicate that the current control contents
+        //       is invalid (if it's indeed going to be the case) once
+        //       wxValidator supports doing this non-intrusively.
+        return m_min < 0 && IsMinusOk(val, pos);
+    }
+
+    // We only accept digits here (remember that '-' is taken care of by the
+    // base class already).
+    if ( ch < '0' || ch > '9' )
+        return false;
+
+    // And the value after insertion needs to be in the defined range.
+    LongestValueType value;
+    if ( !FromString(GetValueAfterInsertingChar(val, pos, ch), &value) )
+        return false;
+
+    return IsInRange(value);
+}
+
+// ============================================================================
+// wxFloatingPointValidatorBase implementation
+// ============================================================================
+
+wxString wxFloatingPointValidatorBase::ToString(LongestValueType value) const
+{
+    return wxNumberFormatter::ToString(value, m_precision, GetFormatFlags());
+}
+
+bool
+wxFloatingPointValidatorBase::FromString(const wxString& s,
+                                         LongestValueType *value)
+{
+    return wxNumberFormatter::FromString(s, value);
+}
+
+bool
+wxFloatingPointValidatorBase::IsCharOk(const wxString& val,
+                                       int pos,
+                                       wxChar ch) const
+{
+    // We may accept minus sign if we can represent negative numbers at all.
+    if ( ch == '-' )
+        return m_min < 0 && IsMinusOk(val, pos);
+
+    const wxChar separator = wxNumberFormatter::GetDecimalSeparator();
+    if ( ch == separator )
+    {
+        if ( val.find(separator) != wxString::npos )
+        {
+            // There is already a decimal separator, can't insert another one.
+            return false;
+        }
+
+        // Prepending a separator before the minus sign isn't allowed.
+        if ( pos == 0 && !val.empty() && val[0] == '-' )
+            return false;
+
+        // Otherwise always accept it, adding a decimal separator doesn't
+        // change the number value and, in particular, can't make it invalid.
+        // OTOH the checks below might not pass because strings like "." or
+        // "-." are not valid numbers so parsing them would fail, hence we need
+        // to treat it specially here.
+        return true;
+    }
+
+    // Must be a digit then.
+    if ( ch < '0' || ch > '9' )
+        return false;
+
+    // Check whether the value we'd obtain if we accepted this key is correct.
+    const wxString newval(GetValueAfterInsertingChar(val, pos, ch));
+
+    LongestValueType value;
+    if ( !FromString(newval, &value) )
+        return false;
+
+    // Also check that it doesn't have too many decimal digits.
+    const size_t posSep = newval.find(separator);
+    if ( posSep != wxString::npos && newval.length() - posSep - 1 > m_precision )
+        return false;
+
+    // Finally check whether it is in the range.
+    return IsInRange(value);
+}
+
+#endif // wxUSE_VALIDATORS && wxUSE_TEXTCTRL
index 57f01972b3471cac7304f289832989143d307532..6574ed6cb839ff6842abef644b9173d652041b99 100644 (file)
     #include "wx/textctrl.h"
     #include "wx/checkbox.h"
     #include "wx/combobox.h"
-    #include "wx/valtext.h"
     #include "wx/intl.h"
     #include "wx/math.h"
     #include "wx/listbox.h"
 #endif
 
+#include "wx/valnum.h"
 #include "wx/textfile.h"
 #include "wx/spinctrl.h"
 #include "wx/tokenzr.h"
@@ -660,7 +660,7 @@ void wxGridCellNumberEditor::Create(wxWindow* parent,
         wxGridCellTextEditor::Create(parent, id, evtHandler);
 
 #if wxUSE_VALIDATORS
-        Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
+        Text()->SetValidator(wxIntegerValidator<int>());
 #endif
     }
 }
@@ -875,7 +875,7 @@ void wxGridCellFloatEditor::Create(wxWindow* parent,
     wxGridCellTextEditor::Create(parent, id, evtHandler);
 
 #if wxUSE_VALIDATORS
-    Text()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
+    Text()->SetValidator(wxFloatingPointValidator<double>(m_precision));
 #endif
 }
 
index 53b6e4dcc15bcfa8635d3d6ae48fc2de584f281d..9c5c25bff829225b74a3e68717d03d80898b4c15 100644 (file)
@@ -213,6 +213,7 @@ TEST_GUI_OBJECTS =  \
        test_gui_settings.o \
        test_gui_socket.o \
        test_gui_boxsizer.o \
+       test_gui_valnum.o \
        test_gui_clientsize.o \
        test_gui_setsize.o \
        test_gui_xrctest.o
@@ -866,6 +867,9 @@ test_gui_socket.o: $(srcdir)/net/socket.cpp $(TEST_GUI_ODEP)
 test_gui_boxsizer.o: $(srcdir)/sizers/boxsizer.cpp $(TEST_GUI_ODEP)
        $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/sizers/boxsizer.cpp
 
+test_gui_valnum.o: $(srcdir)/validators/valnum.cpp $(TEST_GUI_ODEP)
+       $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/validators/valnum.cpp
+
 test_gui_clientsize.o: $(srcdir)/window/clientsize.cpp $(TEST_GUI_ODEP)
        $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/window/clientsize.cpp
 
index 53a429011fad94105babae471f25fd3ca6168609..15598e5f189ff02c6620aeaa353c27a5cf0f5c66 100644 (file)
@@ -198,6 +198,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_settings.obj \\r
        $(OBJS)\test_gui_socket.obj \\r
        $(OBJS)\test_gui_boxsizer.obj \\r
+       $(OBJS)\test_gui_valnum.obj \
        $(OBJS)\test_gui_clientsize.obj \\r
        $(OBJS)\test_gui_setsize.obj \\r
        $(OBJS)\test_gui_xrctest.obj\r
@@ -912,6 +913,9 @@ $(OBJS)\test_gui_socket.obj: .\net\socket.cpp
 $(OBJS)\test_gui_boxsizer.obj: .\sizers\boxsizer.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\sizers\boxsizer.cpp\r
 \r
+$(OBJS)\test_gui_valnum.obj: .\validators\valnum.cpp
+       $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\validators\valnum.cpp
+
 $(OBJS)\test_gui_clientsize.obj: .\window\clientsize.cpp\r
        $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\window\clientsize.cpp\r
 \r
index 505525af1485479085140644eea1af3a161a9384..8146997c8b5b4733032ba62f9ea406f5c12be4a9 100644 (file)
@@ -191,6 +191,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_settings.o \\r
        $(OBJS)\test_gui_socket.o \\r
        $(OBJS)\test_gui_boxsizer.o \\r
+       $(OBJS)\test_gui_valnum.o \
        $(OBJS)\test_gui_clientsize.o \\r
        $(OBJS)\test_gui_setsize.o \\r
        $(OBJS)\test_gui_xrctest.o\r
@@ -893,6 +894,9 @@ $(OBJS)\test_gui_socket.o: ./net/socket.cpp
 $(OBJS)\test_gui_boxsizer.o: ./sizers/boxsizer.cpp\r
        $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<\r
 \r
+$(OBJS)\test_gui_valnum.o: ./validators/valnum.cpp
+       $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\test_gui_clientsize.o: ./window/clientsize.cpp\r
        $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<\r
 \r
index 233b854b2f1caf3401032602e353cd7fdceba436..a18a3dec1adfef0594a761479dac141d66fed244 100644 (file)
@@ -193,6 +193,7 @@ TEST_GUI_OBJECTS =  \
        $(OBJS)\test_gui_settings.obj \\r
        $(OBJS)\test_gui_socket.obj \\r
        $(OBJS)\test_gui_boxsizer.obj \\r
+       $(OBJS)\test_gui_valnum.obj \
        $(OBJS)\test_gui_clientsize.obj \\r
        $(OBJS)\test_gui_setsize.obj \\r
        $(OBJS)\test_gui_xrctest.obj\r
@@ -1038,6 +1039,9 @@ $(OBJS)\test_gui_socket.obj: .\net\socket.cpp
 $(OBJS)\test_gui_boxsizer.obj: .\sizers\boxsizer.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\sizers\boxsizer.cpp\r
 \r
+$(OBJS)\test_gui_valnum.obj: .\validators\valnum.cpp
+       $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\validators\valnum.cpp
+
 $(OBJS)\test_gui_clientsize.obj: .\window\clientsize.cpp\r
        $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\window\clientsize.cpp\r
 \r
index e35199ad196d6f16c2a1c676728a65f63bd43f72..e542ea03b95479a6c3653fcd4fbe625458fea845 100644 (file)
@@ -433,6 +433,7 @@ TEST_GUI_OBJECTS =  &
        $(OBJS)\test_gui_settings.obj &\r
        $(OBJS)\test_gui_socket.obj &\r
        $(OBJS)\test_gui_boxsizer.obj &\r
+       $(OBJS)\test_gui_valnum.obj &
        $(OBJS)\test_gui_clientsize.obj &\r
        $(OBJS)\test_gui_setsize.obj &\r
        $(OBJS)\test_gui_xrctest.obj\r
@@ -951,6 +952,9 @@ $(OBJS)\test_gui_socket.obj :  .AUTODEPEND .\net\socket.cpp
 $(OBJS)\test_gui_boxsizer.obj :  .AUTODEPEND .\sizers\boxsizer.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<\r
 \r
+$(OBJS)\test_gui_valnum.obj :  .AUTODEPEND .\validators\valnum.cpp
+       $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<
+
 $(OBJS)\test_gui_clientsize.obj :  .AUTODEPEND .\window\clientsize.cpp\r
        $(CXX) -bt=nt -zq -fo=$^@ $(TEST_GUI_CXXFLAGS) $<\r
 \r
index 7d5971901e17597ab750885d53929d87a24a9d0f..7ab235bc8188761cd79348689e374f21376a84d9 100644 (file)
@@ -31,18 +31,13 @@ public:
     {
         // We need to use a locale with known decimal point and which uses the
         // thousands separator for the tests to make sense.
-        wxLanguage lang;
-        if ( wxLocale::IsAvailable(wxLANGUAGE_ENGLISH_US) )
-            lang = wxLANGUAGE_ENGLISH_US;
-        else if ( wxLocale::IsAvailable(wxLANGUAGE_ENGLISH_UK) )
-            lang = wxLANGUAGE_ENGLISH_UK;
-        else
+        m_locale = new wxLocale(wxLANGUAGE_ENGLISH_UK,
+                                wxLOCALE_DONT_LOAD_DEFAULT);
+        if ( !m_locale->IsOk() )
         {
+            delete m_locale;
             m_locale = NULL;
-            return;
         }
-
-        m_locale = new wxLocale(lang, wxLOCALE_DONT_LOAD_DEFAULT);
     }
 
     virtual ~NumFormatterTestCase()
index e11e1360547ef4c4b8f917748d15fb888e61db67..33d577ece25e0368d78794a035d4298a77d6efa6 100644 (file)
              -->
             net/socket.cpp
             sizers/boxsizer.cpp
+            validators/valnum.cpp
             window/clientsize.cpp
             window/setsize.cpp
             xml/xrctest.cpp
index 2ed004defb4f5c1526248519248055debad0b5b7..6020cf61b44b91267bb282278363f5c5678b0897 100644 (file)
@@ -517,6 +517,10 @@ SOURCE=.\controls\treectrltest.cpp
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\validators\valnum.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\controls\virtlistctrltest.cpp\r
 # End Source File\r
 # Begin Source File\r
index 377614d36f42cd673dac00b1247156a25ec8bc53..c4790f5855af6c6c280b597eba897b4904944bfe 100644 (file)
                                RelativePath=".\controls\treectrltest.cpp">\r
                        </File>\r
                        <File\r
+                               RelativePath=".\validators\valnum.cpp">
+                       </File>
+                       <File
                                RelativePath=".\controls\virtlistctrltest.cpp">\r
                        </File>\r
                        <File\r
index 278380561204128e704198a6ddd83e44c6989d67..a6c9a9b31c74a12990c77a4df8e167509cc0b672 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\validators\valnum.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath=".\controls\virtlistctrltest.cpp"\r
                                >\r
                        </File>\r
index 958ea5d401b41911a334b9837853f35b7e1ee50a..24e9b62a2e4e393ee56e3154236f7b5ffcd9727e 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath=".\validators\valnum.cpp"
+                               >
+                       </File>
+                       <File
                                RelativePath=".\controls\virtlistctrltest.cpp"\r
                                >\r
                        </File>\r
diff --git a/tests/validators/valnum.cpp b/tests/validators/valnum.cpp
new file mode 100644 (file)
index 0000000..2711629
--- /dev/null
@@ -0,0 +1,286 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        tests/validators/valnum.cpp
+// Purpose:     Unit tests for numeric validators.
+// Author:      Vadim Zeitlin
+// Created:     2011-01-18
+// RCS-ID:      $Id$
+// Copyright:   (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
+///////////////////////////////////////////////////////////////////////////////
+
+#include "testprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/app.h"
+    #include "wx/intl.h"
+    #include "wx/textctrl.h"
+    #include "wx/validate.h"
+#endif // WX_PRECOMP
+
+#include "wx/valnum.h"
+
+#include "asserthelper.h"
+#include "testableframe.h"
+#include "wx/uiaction.h"
+
+class NumValidatorTestCase : public CppUnit::TestCase
+{
+public:
+    NumValidatorTestCase() { }
+
+    void setUp();
+    void tearDown();
+
+private:
+    CPPUNIT_TEST_SUITE( NumValidatorTestCase );
+        CPPUNIT_TEST( TransferInt );
+        CPPUNIT_TEST( TransferUnsigned );
+        CPPUNIT_TEST( TransferFloat );
+        CPPUNIT_TEST( ZeroAsBlank );
+        CPPUNIT_TEST( NoTrailingZeroes );
+        WXUISIM_TEST( Interactive );
+    CPPUNIT_TEST_SUITE_END();
+
+    void TransferInt();
+    void TransferUnsigned();
+    void TransferFloat();
+    void ZeroAsBlank();
+    void NoTrailingZeroes();
+#if wxUSE_UIACTIONSIMULATOR
+    void Interactive();
+#endif // wxUSE_UIACTIONSIMULATOR
+
+    wxTextCtrl *m_text;
+
+    wxDECLARE_NO_COPY_CLASS(NumValidatorTestCase);
+};
+
+// register in the unnamed registry so that these tests are run by default
+CPPUNIT_TEST_SUITE_REGISTRATION( NumValidatorTestCase );
+
+// also include in it's own registry so that these tests can be run alone
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( NumValidatorTestCase, "NumValidatorTestCase" );
+
+void NumValidatorTestCase::setUp()
+{
+    m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
+}
+
+void NumValidatorTestCase::tearDown()
+{
+    wxTheApp->GetTopWindow()->DestroyChildren();
+}
+
+void NumValidatorTestCase::TransferInt()
+{
+    int value = 0;
+    wxIntegerValidator<int> valInt(&value);
+    valInt.SetWindow(m_text);
+
+    CPPUNIT_ASSERT( valInt.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "0", m_text->GetValue() );
+
+    value = 17;
+    CPPUNIT_ASSERT( valInt.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "17", m_text->GetValue() );
+
+
+    m_text->ChangeValue("foobar");
+    CPPUNIT_ASSERT( !valInt.TransferFromWindow() );
+
+    m_text->ChangeValue("-234");
+    CPPUNIT_ASSERT( valInt.TransferFromWindow() );
+    CPPUNIT_ASSERT_EQUAL( -234, value );
+
+    m_text->ChangeValue("9223372036854775808"); // == LLONG_MAX + 1
+    CPPUNIT_ASSERT( !valInt.TransferFromWindow() );
+
+    m_text->Clear();
+    CPPUNIT_ASSERT( !valInt.TransferFromWindow() );
+}
+
+void NumValidatorTestCase::TransferUnsigned()
+{
+    unsigned value = 0;
+    wxIntegerValidator<unsigned> valUnsigned(&value);
+    valUnsigned.SetWindow(m_text);
+
+    CPPUNIT_ASSERT( valUnsigned.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "0", m_text->GetValue() );
+
+    value = 17;
+    CPPUNIT_ASSERT( valUnsigned.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "17", m_text->GetValue() );
+
+
+    m_text->ChangeValue("foobar");
+    CPPUNIT_ASSERT( !valUnsigned.TransferFromWindow() );
+
+    m_text->ChangeValue("-234");
+    CPPUNIT_ASSERT( !valUnsigned.TransferFromWindow() );
+
+    m_text->ChangeValue("234");
+    CPPUNIT_ASSERT( valUnsigned.TransferFromWindow() );
+    CPPUNIT_ASSERT_EQUAL( 234, value );
+
+    m_text->ChangeValue("18446744073709551616"); // == ULLONG_MAX + 1
+    CPPUNIT_ASSERT( !valUnsigned.TransferFromWindow() );
+
+    m_text->Clear();
+    CPPUNIT_ASSERT( !valUnsigned.TransferFromWindow() );
+}
+
+void NumValidatorTestCase::TransferFloat()
+{
+    float value = 0;
+    wxFloatingPointValidator<float> valFloat(3, &value);
+    valFloat.SetWindow(m_text);
+
+    CPPUNIT_ASSERT( valFloat.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "0.000", m_text->GetValue() );
+
+    value = 1.234f;
+    CPPUNIT_ASSERT( valFloat.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "1.234", m_text->GetValue() );
+
+    value = 1.2345678f;
+    CPPUNIT_ASSERT( valFloat.TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "1.235", m_text->GetValue() );
+
+
+    m_text->ChangeValue("foobar");
+    CPPUNIT_ASSERT( !valFloat.TransferFromWindow() );
+
+    m_text->ChangeValue("-234.567");
+    CPPUNIT_ASSERT( valFloat.TransferFromWindow() );
+    CPPUNIT_ASSERT_EQUAL( -234.567f, value );
+
+    m_text->Clear();
+    CPPUNIT_ASSERT( !valFloat.TransferFromWindow() );
+}
+
+void NumValidatorTestCase::ZeroAsBlank()
+{
+    long value = 0;
+    m_text->SetValidator(
+        wxMakeIntegerValidator(&value, wxNUM_VAL_ZERO_AS_BLANK));
+
+    wxValidator * const val = m_text->GetValidator();
+
+    CPPUNIT_ASSERT( val->TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "", m_text->GetValue() );
+
+    value++;
+    CPPUNIT_ASSERT( val->TransferFromWindow() );
+    CPPUNIT_ASSERT_EQUAL( 0, value );
+}
+
+void NumValidatorTestCase::NoTrailingZeroes()
+{
+    double value = 1.2;
+    m_text->SetValidator(
+        wxMakeFloatingPointValidator(3, &value, wxNUM_VAL_NO_TRAILING_ZEROES));
+
+    wxValidator * const val = m_text->GetValidator();
+
+    CPPUNIT_ASSERT( val->TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "1.2", m_text->GetValue() );
+
+    value = 1.234;
+    CPPUNIT_ASSERT( val->TransferToWindow() );
+    CPPUNIT_ASSERT_EQUAL( "1.234", m_text->GetValue() );
+}
+
+#if wxUSE_UIACTIONSIMULATOR
+
+void NumValidatorTestCase::Interactive()
+{
+    // Set a locale using comma as thousands separator character.
+    wxLocale loc(wxLANGUAGE_ENGLISH_UK, wxLOCALE_DONT_LOAD_DEFAULT);
+
+    m_text->SetValidator(
+        wxIntegerValidator<unsigned>(NULL, wxNUM_VAL_THOUSANDS_SEPARATOR));
+
+    // Create a sibling text control to be able to switch focus and thus
+    // trigger the control validation/normalization.
+    wxTextCtrl * const text2 = new wxTextCtrl(m_text->GetParent(), wxID_ANY);
+    text2->Move(10, 80); // Just to see it better while debugging...
+    wxFloatingPointValidator<float> valFloat(3);
+    valFloat.SetRange(-10., 10.);
+    text2->SetValidator(valFloat);
+
+    wxUIActionSimulator sim;
+
+    // Entering '-' in a control with positive range is not allowed.
+    m_text->SetFocus();
+    sim.Char('-');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "", m_text->GetValue() );
+
+    // Neither is entering '.' or any non-digit character.
+    sim.Text(".a+/");
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "", m_text->GetValue() );
+
+    // Entering digits should work though and after leaving the control the
+    // contents should be normalized.
+    sim.Text("1234567");
+    wxYield();
+    text2->SetFocus();
+    wxYield();
+    if ( loc.IsOk() )
+        CPPUNIT_ASSERT_EQUAL( "1,234,567", m_text->GetValue() );
+    else
+        CPPUNIT_ASSERT_EQUAL( "1234567", m_text->GetValue() );
+
+
+    // Entering both '-' and '.' in this control should work but only in the
+    // correct order.
+    sim.Char('-');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-", text2->GetValue() );
+
+    text2->SetInsertionPoint(0);
+    sim.Char('.');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-", text2->GetValue() );
+
+    text2->SetInsertionPointEnd();
+    sim.Char('.');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-.", text2->GetValue() );
+
+    // Adding up to three digits after the point should work.
+    sim.Text("987");
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-.987", text2->GetValue() );
+
+    // But no more.
+    sim.Text("654");
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-.987", text2->GetValue() );
+
+    // We can remove one digit and another one though.
+    sim.Char(WXK_BACK);
+    sim.Char(WXK_BACK);
+    sim.Char('6');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "-.96", text2->GetValue() );
+
+
+    // Also test the range constraint.
+    text2->Clear();
+
+    sim.Char('9');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "9", text2->GetValue() );
+
+    sim.Char('9');
+    wxYield();
+    CPPUNIT_ASSERT_EQUAL( "9", text2->GetValue() );
+}
+
+#endif // wxUSE_UIACTIONSIMULATOR