diff --git a/assdraw/Makefile.am b/assdraw/Makefile.am new file mode 100644 index 000000000..5942bf5a6 --- /dev/null +++ b/assdraw/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libpropgrid src diff --git a/assdraw/Makefile.in b/assdraw/Makefile.in new file mode 100644 index 000000000..69a34a7e6 --- /dev/null +++ b/assdraw/Makefile.in @@ -0,0 +1,630 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure config.guess config.sub depcomp \ + install-sh ltmain.sh missing +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno configure.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SUBDIRS = libpropgrid src +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ + cd $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_srcdir) && $(AUTOHEADER) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ + check-am clean clean-generic clean-libtool clean-recursive \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-shar dist-tarZ dist-zip distcheck distclean \ + distclean-generic distclean-hdr distclean-libtool \ + distclean-recursive distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/assdraw/autogen.sh b/assdraw/autogen.sh new file mode 100755 index 000000000..e5cb78973 --- /dev/null +++ b/assdraw/autogen.sh @@ -0,0 +1,248 @@ +#!/bin/sh + +# This script does all the magic calls to automake/autoconf and friends +# that are needed to configure a Subversion checkout. As described in +# the file HACKING you need a couple of extra tools to run this script +# successfully. +# +# If you are compiling from a released tarball you don't need these +# tools and you shouldn't use this script. Just call ./configure +# directly. + +ACLOCAL=${ACLOCAL-aclocal-1.9} +AUTOCONF=${AUTOCONF-autoconf} +AUTOHEADER=${AUTOHEADER-autoheader} +AUTOMAKE=${AUTOMAKE-automake-1.9} +LIBTOOLIZE=${LIBTOOLIZE-libtoolize} + +GLIB_REQUIRED_VERSION=2.10.0 +AUTOCONF_REQUIRED_VERSION=2.54 +AUTOMAKE_REQUIRED_VERSION=1.9 +LIBTOOL_REQUIRED_VERSION=1.5 + +REQUIRED_M4="pkg.m4" +REQUIRED_M4_WX="wxwin.m4 wxwin28.m4" + +PROJECT="assdraw" + +srcdir=`pwd` +test -z "$srcdir" && srcdir=. +ORIGDIR=`pwd` +cd $srcdir + +test -d src || { + echo + echo "You must run this script in the top-level $PROJECT directory." + echo + exit 1 +} + +check_version () +{ + VERSION_A=$1 + VERSION_B=$2 + + save_ifs="$IFS" + IFS=. + set dummy $VERSION_A 0 0 0 + MAJOR_A=$2 + MINOR_A=$3 + MICRO_A=$4 + set dummy $VERSION_B 0 0 0 + MAJOR_B=$2 + MINOR_B=$3 + MICRO_B=$4 + IFS="$save_ifs" + + if expr "$MAJOR_A" = "$MAJOR_B" > /dev/null; then + if expr "$MINOR_A" \> "$MINOR_B" > /dev/null; then + echo "yes (version $VERSION_A)" + elif expr "$MINOR_A" = "$MINOR_B" > /dev/null; then + if expr "$MICRO_A" \>= "$MICRO_B" > /dev/null; then + echo "yes (version $VERSION_A)" + else + echo "Too old (version $VERSION_A)" + DIE=1 + fi + else + echo "Too old (version $VERSION_A)" + DIE=1 + fi + elif expr "$MAJOR_A" \> "$MAJOR_B" > /dev/null; then + echo "Major version might be too new ($VERSION_A)" + else + echo "Too old (version $VERSION_A)" + DIE=1 + fi +} + +DIE=0 + + +echo -n "checking for libtool >= $LIBTOOL_REQUIRED_VERSION ... " +if ($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1; then + LIBTOOLIZE=$LIBTOOLIZE +elif (glibtoolize --version) < /dev/null > /dev/null 2>&1; then + LIBTOOLIZE=glibtoolize +else + echo + echo " You must have libtool installed to compile $PROJECT." + echo " Install the appropriate package for your distribution," + echo " or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + echo + DIE=1 +fi + +if test x$LIBTOOLIZE != x; then + VER=`$LIBTOOLIZE --version \ + | grep libtool | sed "s/.* \([0-9.]*\)[-a-z0-9]*$/\1/"` + check_version $VER $LIBTOOL_REQUIRED_VERSION +fi + +echo -n "checking for autoconf >= $AUTOCONF_REQUIRED_VERSION ... " +if ($AUTOCONF --version) < /dev/null > /dev/null 2>&1; then + VER=`$AUTOCONF --version | head -n 1 \ + | grep -iw autoconf | sed "s/.* \([0-9.]*\)[-a-z0-9]*$/\1/"` + check_version $VER $AUTOCONF_REQUIRED_VERSION +else + echo + echo " You must have autoconf installed to compile $PROJECT." + echo " Download the appropriate package for your distribution," + echo " or get the source tarball at ftp://ftp.gnu.org/pub/gnu/autoconf/" + echo + DIE=1; +fi + + +echo -n "checking for automake >= $AUTOMAKE_REQUIRED_VERSION ... " +if ($AUTOMAKE --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=$AUTOMAKE + ACLOCAL=$ACLOCAL +elif (automake-1.10 --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake-1.10 + ACLOCAL=aclocal-1.10 +elif (automake-1.9 --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake-1.9 + ACLOCAL=aclocal-1.9 +else + echo + echo " You must have automake $AUTOMAKE_REQUIRED_VERSION or newer installed to compile $PROJECT." + echo " Download the appropriate package for your distribution," + echo " or get the source tarball at ftp://ftp.gnu.org/pub/gnu/automake/" + echo + DIE=1 +fi + +if test x$AUTOMAKE != x; then + VER=`$AUTOMAKE --version \ + | grep automake | sed "s/.* \([0-9.]*\)[-a-z0-9]*$/\1/"` + check_version $VER $AUTOMAKE_REQUIRED_VERSION +fi + + +if test "$DIE" -eq 1; then + echo + echo "Please install/upgrade the missing tools and call me again." + echo + exit 1 +fi + + +echo +echo "I am going to run ./configure with the following arguments:" +echo +echo " --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS $@" +echo + +if test -z "$*"; then + echo "If you wish to pass additional arguments, please specify them " + echo "on the $0 command line or set the AUTOGEN_CONFIGURE_ARGS " + echo "environment variable." + echo +fi + + + +echo "--- Checking for required M4 files ---" + +if test -z "$ACLOCAL_FLAGS"; then + acdir=`$ACLOCAL --print-ac-dir` + + for file in $REQUIRED_M4; do + if [ ! -f "$acdir/$file" ]; then + echo + echo "WARNING: aclocal's directory is $acdir, but..." + echo " no file $acdir/$file" + echo " You may see fatal macro warnings below." + echo " If these files are installed in /some/dir, set the " + echo " ACLOCAL_FLAGS environment variable to \"-I /some/dir\"" + echo " or install $acdir/$file." + echo + fi + done + + + for file in $REQUIRED_M4_WX; do + if [ -f "$acdir/$file" ]; then + FOUND_M4_WX="yes" + fi + done + + if test -z "$FOUND_M4_WX"; then + echo + echo "WARNING: aclocal's directory is $acdir, but..." + echo " none of: \"$REQUIRED_M4_WX\" were found." + echo " You may see fatal macro warnings below." + echo " If these files are installed in /some/dir, set the " + echo " ACLOCAL_FLAGS environment variable to \"-I /some/dir\"" + echo " or install ONE OF: \"$REQUIRED_M4_WX\" in $acdir." + echo "NOTE: These are the same files under different names." + echo + fi +fi + + + +echo "--- $ACLOCAL ---" +$ACLOCAL $ACLOCAL_FLAGS +RC=$? +if test $RC -ne 0; then + echo "$ACLOCAL gave errors. Please fix the error conditions and try again." + exit $RC +fi + +echo "--- $LIBTOOLIZE ---" +$LIBTOOLIZE --force || exit $? + +echo "--- $AUTOHEADER ---" +$AUTOHEADER || exit $? + +echo "--- $AUTOMAKE ---" +$AUTOMAKE --add-missing || exit $? + +echo "--- $AUTOCONF ---" +$AUTOCONF || exit $? + +cd $ORIGDIR + +echo "--- $srcdir/configure ---" +$srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@" +RC=$? + +echo +echo +echo "***********************************************************************" +echo "*" +echo "* Please do not ask for support when using the SVN verison of aegisub," +echo "* download an official distfile in order to receive support." +echo "*" +echo "***********************************************************************" +echo + +if test $RC -ne 0; then + echo + echo "Configure failed or did not finish!" + exit $RC +fi + +echo "Now type 'make' to compile the $PROJECT." diff --git a/assdraw/configure.in b/assdraw/configure.in new file mode 100644 index 000000000..612a6a3b2 --- /dev/null +++ b/assdraw/configure.in @@ -0,0 +1,82 @@ +AC_PREREQ(2.61) + + +####### +# Setup +####### +AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) +AC_CONFIG_SRCDIR([src/engine.cpp]) +AC_CONFIG_HEADER([config.h]) +AM_INIT_AUTOMAKE([foreign]) +AC_CANONICAL_HOST + + +#################### +# Check for programs +#################### +AC_PROG_CC +AC_PROG_CXX +AC_LANG(C++) +AC_PROG_LIBTOOL +AC_PROG_INSTALL +#PKG_PROG_PKG_CONFIG([0.20]) + + +################# +# Developers only +################# +AM_MAINTAINER_MODE + +AC_ARG_VAR([DEBUG_FLAGS], [Debug flag to use with --enable debug (default: -g)]) +if test -z "$DEBUG_FLAGS"; then + DEBUG_FLAGS="-g"; +fi + +AC_MSG_CHECKING([whether to turn on debugging]) +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging (default=no)]) +if test "$enable_debug" = "yes"; then + AC_MSG_RESULT([yes ($DEBUG_FLAGS)]) + CPPFLAGS="$DEBUG_FLAGS $CPPFLAGS" +else + AC_MSG_RESULT([no]) +fi + +AC_ARG_ENABLE(build-dist) +if test "$enable_build_dist" = "yes"; then + SVN_VERSION=`svnversion .` + PACKAGE_STRING="${PACKAGE_STRING}-r$SVN_VERSION" + PACKAGE_VERSION="${PACKAGE_VERSION}-r$SVN_VERSION" + VERSION="${VERSION}-r$SVN_VERSION" +fi + +# Checks for header files. + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T + +AM_OPTIONS_WXCONFIG +AM_PATH_WXCONFIG(2.8.1, [have_wxconfig=1], [have_wxconfig=0], [std,gl,stc]) + +if test "$have_wxconfig" != 1; then + AC_MSG_FAILURE([ +wxWidgets detection failed, please set --with-wx* or add +the libraries to your LDFLAGS, CXX/CFLAGS. + ]) +fi + +PKG_CHECK_MODULES(LIBAGG, libagg >= 2.5.0, [with_libagg=yes], [with_libagg=no]) + +if test "$with_libagg" != "yes"; then + AC_MSG_FAILURE([You must have AGG installed: http://vector-agg.sourceforge.net/]) +fi + +AC_OUTPUT([ +Makefile +libpropgrid/Makefile +src/wxAGG/Makefile +src/xpm/Makefile +src/Makefile +]) diff --git a/assdraw/libpropgrid/Makefile.am b/assdraw/libpropgrid/Makefile.am new file mode 100644 index 000000000..59aa8d0f0 --- /dev/null +++ b/assdraw/libpropgrid/Makefile.am @@ -0,0 +1,23 @@ +noinst_LIBRARIES = libpropgrid.a + +AM_CPPFLAGS = -Iinclude @WX_CPPFLAGS@ + +libpropgrid_a_SOURCES = \ + advprops.cpp \ + extras.cpp \ + manager.cpp \ + odcombo.cpp \ + propgrid.cpp \ + props.cpp + +libpropgrid_a_SOURCES += \ + include/wx/propgrid/advprops.h \ + include/wx/propgrid/Doxyfile \ + include/wx/propgrid/extras.h \ + include/wx/propgrid/manager.h \ + include/wx/propgrid/odcombo.h \ + include/wx/propgrid/pg_dox_mainpage.h \ + include/wx/propgrid/propdev.h \ + include/wx/propgrid/propgrid.h + + diff --git a/assdraw/libpropgrid/Makefile.in b/assdraw/libpropgrid/Makefile.in new file mode 100644 index 000000000..30939d2ad --- /dev/null +++ b/assdraw/libpropgrid/Makefile.in @@ -0,0 +1,461 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = libpropgrid +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libpropgrid_a_AR = $(AR) $(ARFLAGS) +libpropgrid_a_LIBADD = +am_libpropgrid_a_OBJECTS = advprops.$(OBJEXT) extras.$(OBJEXT) \ + manager.$(OBJEXT) odcombo.$(OBJEXT) propgrid.$(OBJEXT) \ + props.$(OBJEXT) +libpropgrid_a_OBJECTS = $(am_libpropgrid_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libpropgrid_a_SOURCES) +DIST_SOURCES = $(libpropgrid_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +noinst_LIBRARIES = libpropgrid.a +AM_CPPFLAGS = -Iinclude @WX_CPPFLAGS@ +libpropgrid_a_SOURCES = advprops.cpp extras.cpp manager.cpp \ + odcombo.cpp propgrid.cpp props.cpp \ + include/wx/propgrid/advprops.h include/wx/propgrid/Doxyfile \ + include/wx/propgrid/extras.h include/wx/propgrid/manager.h \ + include/wx/propgrid/odcombo.h \ + include/wx/propgrid/pg_dox_mainpage.h \ + include/wx/propgrid/propdev.h include/wx/propgrid/propgrid.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libpropgrid/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign libpropgrid/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libpropgrid.a: $(libpropgrid_a_OBJECTS) $(libpropgrid_a_DEPENDENCIES) + -rm -f libpropgrid.a + $(libpropgrid_a_AR) libpropgrid.a $(libpropgrid_a_OBJECTS) $(libpropgrid_a_LIBADD) + $(RANLIB) libpropgrid.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/advprops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extras.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odcombo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/propgrid.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/props.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/assdraw/libpropgrid/advprops.cpp b/assdraw/libpropgrid/advprops.cpp new file mode 100644 index 000000000..4d04f012d --- /dev/null +++ b/assdraw/libpropgrid/advprops.cpp @@ -0,0 +1,1882 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: advprops.cpp +// Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.) +// Author: Jaakko Salli +// Modified by: +// Created: Sep-25-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "advprops.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" + #include "wx/object.h" + #include "wx/hash.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/event.h" + #include "wx/window.h" + #include "wx/panel.h" + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/button.h" + #include "wx/pen.h" + #include "wx/brush.h" + #include "wx/cursor.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/msgdlg.h" + #include "wx/choice.h" + #include "wx/stattext.h" + #include "wx/textctrl.h" + #include "wx/scrolwin.h" + #include "wx/dirdlg.h" + #include "wx/combobox.h" + #include "wx/layout.h" + #include "wx/sizer.h" + #include "wx/textdlg.h" + #include "wx/filedlg.h" + #include "wx/intl.h" +#endif + +#define __wxPG_SOURCE_FILE__ + +#include + +#if wxPG_INCLUDE_ADVPROPS + +#include + +#include + +#ifdef __WXMSW__ + #include +#endif + +// ----------------------------------------------------------------------- + +#if defined(__WXMSW__) + #define wxPG_CAN_DRAW_CURSOR 1 +#elif defined(__WXGTK__) + #define wxPG_CAN_DRAW_CURSOR 0 +#elif defined(__WXMAC__) + #define wxPG_CAN_DRAW_CURSOR 0 +#else + #define wxPG_CAN_DRAW_CURSOR 0 +#endif + + +#if !defined(wxPG_ALLOW_WXADV) + #undef wxUSE_DATEPICKCTRL + #define wxUSE_DATEPICKCTRL 0 +#endif + +// ----------------------------------------------------------------------- +// Value type related +// ----------------------------------------------------------------------- + + +bool operator == (const wxFont&, const wxFont&) +{ + return false; +} + +WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxFont,wxFontProperty,(const wxFont*)NULL) + +// Implement dynamic class for type value. +IMPLEMENT_DYNAMIC_CLASS(wxColourPropertyValue,wxObject) + +bool operator == (const wxColourPropertyValue& a, const wxColourPropertyValue& b) +{ + return ( ( a.m_colour == b.m_colour ) && (a.m_type == b.m_type) ); +} + +WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxColourPropertyValue,wxSystemColourProperty, + (const wxColourPropertyValue*)NULL) + +WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(wxColour,wxColourProperty, + (const wxColour*)wxBLACK) + +bool operator == (const wxArrayInt& array1, const wxArrayInt& array2) +{ + if ( array1.GetCount() != array2.GetCount() ) + return false; + size_t i; + for ( i=0; i + + +// NOTE: Regardless that this class inherits from a working editor, it has +// all necessary methods to work independently. wxTextCtrl stuff is only +// used for event handling here. +class wxPGSpinCtrlEditor : public wxPGTextCtrlEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + virtual ~wxPGSpinCtrlEditor(); + + // See below for short explanations of what these are suppposed to do. + wxPG_DECLARE_CREATECONTROLS + + virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, + wxWindow* wnd, wxEvent& event ) const; +}; + + +// This macro also defines global wxPGEditor_SpinCtrl for storing +// the singleton class instance. +WX_PG_IMPLEMENT_EDITOR_CLASS(SpinCtrl,wxPGSpinCtrlEditor,wxPGEditor) + + +// Trivial destructor. +wxPGSpinCtrlEditor::~wxPGSpinCtrlEditor() +{ +} + + +// Create controls and initialize event handling. +#ifndef __WXPYTHON__ +wxWindow* wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz, wxWindow** pSecondary ) const +#else +wxPGWindowPair wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz ) const +#endif +{ + const int margin = 1; + wxSize butSz(18, sz.y); + wxSize tcSz(sz.x - butSz.x - margin, sz.y); + wxPoint butPos(pos.x + tcSz.x + margin, pos.y); + + wxSpinButton* wnd2 = new wxSpinButton(); +#ifdef __WXMSW__ + wnd2->Hide(); +#endif + wnd2->Create( propgrid, wxPG_SUBID2, butPos, butSz, wxSP_VERTICAL ); + wnd2->SetRange( INT_MIN, INT_MAX ); + //wnd2->SetRange( 5, 12 ); + wnd2->SetValue( 0 ); + + propgrid->Connect( wxPG_SUBID2, wxEVT_SCROLL_LINEUP, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid ); + propgrid->Connect( wxPG_SUBID2, wxEVT_SCROLL_LINEDOWN, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent, NULL, propgrid ); + + // Let's add validator to make sure only numbers can be entered + wxString temps; + wxTextValidator validator(wxFILTER_NUMERIC, &temps); + +#ifndef __WXPYTHON__ + wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz, NULL ); + wnd1->SetValidator(validator); + + *pSecondary = wnd2; + return wnd1; +#else + wxTextCtrl* wnd1 = (wxTextCtrl*) wxPGTextCtrlEditor::CreateControls( propgrid, property, pos, tcSz ).m_primary; + wnd1->SetValidator(validator); + + return wxPGWindowPair(wnd1, wnd2); +#endif +} + +// Control's events are redirected here +bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, + wxWindow* wnd, wxEvent& event ) const +{ + int evtType = event.GetEventType(); + + if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN ) + { + wxString s; + // Can't use wnd since it might be clipper window + wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl); + + if ( tc ) + s = tc->GetValue(); + else + s = property->GetValueAsString(wxPG_FULL_VALUE); + + wxSpinButton* spinButton = (wxSpinButton*) propgrid->GetEditorControlSecondary(); + int spinMin = spinButton->GetMin(); + int spinMax = spinButton->GetMax(); + + if ( property->GetValueType() == wxPG_VALUETYPE(double) ) + { + double v_d; + + // Try double + if ( s.ToDouble(&v_d) ) + { + if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += 1.0; + else v_d -= 1.0; + + // Min/Max + double dSpinMin = (double) spinMin; + double dSpinMax = (double) spinMax; + if ( v_d > dSpinMax ) v_d = dSpinMax; + else if ( v_d < dSpinMin ) v_d = dSpinMin; + + wxPropertyGrid::DoubleToString(s, v_d, 6, true, NULL); + } + else + { + return false; + } + } + else + { + long v_l; + + // Try long + if ( s.ToLong(&v_l, 0) ) + { + if ( evtType == wxEVT_SCROLL_LINEUP ) v_l++; + else v_l--; + + // Min/Max + if ( v_l > spinMax ) v_l = spinMax; + else if ( v_l < spinMin ) v_l = spinMin; + + s = wxString::Format(wxT("%i"),(int)v_l); + } + else + { + return false; + } + } + + if ( tc ) + tc->SetValue(s); + + return true; + } + + return wxPGTextCtrlEditor::OnEvent(propgrid,property,wnd,event); +} + +#endif // wxUSE_SPINBTN + + +// ----------------------------------------------------------------------- +// wxDatePickerCtrl-based property editor +// ----------------------------------------------------------------------- + +#if wxUSE_DATEPICKCTRL + + +#include +#include + +class wxPGDatePickerCtrlEditor : public wxPGEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + virtual ~wxPGDatePickerCtrlEditor(); + + wxPG_DECLARE_CREATECONTROLS + + virtual void UpdateControl( wxPGProperty* property, wxWindow* wnd ) const; + virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, + wxWindow* wnd, wxEvent& event ) const; + virtual bool CopyValueFromControl( wxPGProperty* property, wxWindow* wnd ) const; + virtual void SetValueToUnspecified( wxWindow* wnd ) const; +}; + + +WX_PG_IMPLEMENT_EDITOR_CLASS(DatePickerCtrl,wxPGDatePickerCtrlEditor,wxPGEditor) + + +wxPGDatePickerCtrlEditor::~wxPGDatePickerCtrlEditor() +{ +} + +#ifndef __WXPYTHON__ +wxWindow* wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + wxWindow** ) const +#else +wxPGWindowPair wxPGDatePickerCtrlEditor::CreateControls( wxPropertyGrid* propgrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz ) const +#endif +{ + wxCHECK_MSG( property->IsKindOf(WX_PG_CLASSINFO(wxDateProperty)), + NULL, + wxT("DatePickerCtrl editor can only be used with wxDateProperty or derivative.") ); + + wxDatePropertyClass* prop = (wxDatePropertyClass*) property; + + // Use two stage creation to allow cleaner display on wxMSW + wxDatePickerCtrl* ctrl = new wxDatePickerCtrl(); +#ifdef __WXMSW__ + ctrl->Hide(); + wxSize useSz = wxDefaultSize; + useSz.x = sz.x; +#else + wxSize useSz = sz; +#endif + ctrl->Create(propgrid, + wxPG_SUBID1, + prop->GetDateValue(), + pos, + useSz, + prop->GetDatePickerStyle() | wxNO_BORDER); + + // Connect all required events to grid's OnCustomEditorEvent + // (all relevenat wxTextCtrl, wxComboBox and wxButton events are + // already connected) + propgrid->Connect( wxPG_SUBID1, wxEVT_DATE_CHANGED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent ); + +#ifdef __WXMSW__ + ctrl->Show(); +#endif + + return ctrl; +} + +// Copies value from property to control +void wxPGDatePickerCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* wnd ) const +{ + wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd; + wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) ); + + // We assume that property's data type is 'int' (or something similar), + // thus allowing us to get raw, unchecked value via DoGetValue. + ctrl->SetValue( *((const wxDateTime*)property->DoGetValue().GetVoidPtr()) ); +} + +// Control's events are redirected here +bool wxPGDatePickerCtrlEditor::OnEvent( wxPropertyGrid* WXUNUSED(propgrid), + wxPGProperty* WXUNUSED(property), + wxWindow* WXUNUSED(wnd), + wxEvent& event ) const +{ + if ( event.GetEventType() == wxEVT_DATE_CHANGED ) + return true; + + return false; +} + +bool wxPGDatePickerCtrlEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* wnd ) const +{ + wxDatePickerCtrl* ctrl = (wxDatePickerCtrl*) wnd; + wxASSERT( ctrl && ctrl->IsKindOf(CLASSINFO(wxDatePickerCtrl)) ); + + wxDatePropertyClass* prop = (wxDatePropertyClass*) property; + prop->SetDateValue( ctrl->GetValue() ); + + return true; +} + +void wxPGDatePickerCtrlEditor::SetValueToUnspecified( wxWindow* WXUNUSED(wnd) ) const +{ + // TODO? + //wxDateProperty* prop = (wxDateProperty*) property; + //ctrl->SetValue(?); +} + +#endif // wxUSE_DATEPICKCTRL + + +// ----------------------------------------------------------------------- +// wxFontProperty +// ----------------------------------------------------------------------- + +#include +#include + +static const wxChar* gs_fp_es_family_labels[] = { + wxT("Default"), wxT("Decorative"), + wxT("Roman"), wxT("Script"), + wxT("Swiss"), wxT("Modern"), + wxT("Teletype"), + (const wxChar*) NULL +}; + +static long gs_fp_es_family_values[] = { + wxFONTFAMILY_DEFAULT, wxFONTFAMILY_DECORATIVE, + wxFONTFAMILY_ROMAN, wxFONTFAMILY_SCRIPT, + wxFONTFAMILY_SWISS, wxFONTFAMILY_MODERN, + wxFONTFAMILY_TELETYPE +}; + +static const wxChar* gs_fp_es_style_labels[] = { + wxT("Normal"), + wxT("Slant"), + wxT("Italic"), + (const wxChar*) NULL +}; + +static long gs_fp_es_style_values[] = { + wxNORMAL, + wxSLANT, + wxITALIC +}; + +static const wxChar* gs_fp_es_weight_labels[] = { + wxT("Normal"), + wxT("Light"), + wxT("Bold"), + (const wxChar*) NULL +}; + +static long gs_fp_es_weight_values[] = { + wxNORMAL, + wxLIGHT, + wxBOLD +}; + +// Class body is in advprops.h + + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFontProperty,wxBaseParentProperty, + wxFont,const wxFont&,TextCtrlAndButton) + + +wxFontPropertyClass::wxFontPropertyClass( const wxString& label, const wxString& name, + const wxFont& value ) + : wxPGPropertyWithChildren(label,name) +{ + wxPG_INIT_REQUIRED_TYPE(wxFont) + DoSetValue( wxPGVariantCreator(value) ); + + // Initialize font family choices list + if ( !wxPGGlobalVars->m_fontFamilyChoices ) + { + WX_PG_GLOBALS_LOCKER() + + wxFontEnumerator enumerator; + enumerator.EnumerateFacenames(); + +#if wxMINOR_VERSION > 6 + wxArrayString faceNames = enumerator.GetFacenames(); +#else + wxArrayString& faceNames = *enumerator.GetFacenames(); +#endif + + faceNames.Sort(); + + wxPGGlobalVars->m_fontFamilyChoices = new wxPGChoices(faceNames); + } + + wxString emptyString(wxEmptyString); + + AddChild( wxIntProperty( _("Point Size"),emptyString,m_value_wxFont.GetPointSize() ) ); + + AddChild( wxEnumProperty(_("Family"), emptyString, + gs_fp_es_family_labels,gs_fp_es_family_values, + m_value_wxFont.GetFamily()) ); + + wxString faceName = m_value_wxFont.GetFaceName(); + // If font was not in there, add it now + if ( faceName.length() && + wxPGGlobalVars->m_fontFamilyChoices->Index(faceName) == wxNOT_FOUND ) + wxPGGlobalVars->m_fontFamilyChoices->AddAsSorted(faceName); + + wxPGProperty* p = wxEnumProperty(_("Face Name"),emptyString, + *wxPGGlobalVars->m_fontFamilyChoices); + + p->SetValueFromString(faceName,wxPG_FULL_VALUE); + + AddChild( p ); + + AddChild( wxEnumProperty(_("Style"),emptyString, + gs_fp_es_style_labels,gs_fp_es_style_values,m_value_wxFont.GetStyle()) ); + + AddChild( wxEnumProperty(_("Weight"),emptyString, + gs_fp_es_weight_labels,gs_fp_es_weight_values,m_value_wxFont.GetWeight()) ); + + AddChild( wxBoolProperty(_("Underlined"),emptyString, + m_value_wxFont.GetUnderlined()) ); + +} + +wxFontPropertyClass::~wxFontPropertyClass () { } + +void wxFontPropertyClass::DoSetValue( wxPGVariant value ) +{ + const wxFont* font = wxPGVariantToWxObjectPtr(value,wxFont); + + if ( font && font->Ok() ) + m_value_wxFont = *font; + else + m_value_wxFont = wxFont(10,wxSWISS,wxNORMAL,wxNORMAL); + + RefreshChildren(); +} + +wxPGVariant wxFontPropertyClass::DoGetValue() const +{ + return wxPGVariantCreator(m_value_wxFont); +} + +wxString wxFontPropertyClass::GetValueAsString( int argFlags ) const +{ + return wxPGPropertyWithChildren::GetValueAsString(argFlags); +} + +bool wxFontPropertyClass::OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, + wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + // Update value from last minute changes + PrepareValueForDialogEditing(propgrid); + + wxFontData data; + data.SetInitialFont(m_value_wxFont); + data.SetColour(*wxBLACK); + + wxFontDialog dlg(propgrid, data); + if ( dlg.ShowModal() == wxID_OK ) + { + propgrid->EditorsValueWasModified(); + + wxFontData retData = dlg.GetFontData(); + wxFont font = retData.GetChosenFont(); + + DoSetValue(wxPGVariantCreator(font)); + UpdateControl(primary); + + return true; + } + } + return false; +} + +void wxFontPropertyClass::RefreshChildren() +{ + if ( !GetCount() ) return; + Item(0)->DoSetValue( (long)m_value_wxFont.GetPointSize() ); + Item(1)->DoSetValue( (long)m_value_wxFont.GetFamily() ); + Item(2)->SetValueFromString( m_value_wxFont.GetFaceName(), wxPG_FULL_VALUE ); + Item(3)->DoSetValue( (long)m_value_wxFont.GetStyle() ); + Item(4)->DoSetValue( (long)m_value_wxFont.GetWeight() ); + Item(5)->DoSetValue( m_value_wxFont.GetUnderlined() ); +} + +void wxFontPropertyClass::ChildChanged( wxPGProperty* p ) +{ + wxASSERT( this == p->GetParent() ); + + int ind = p->GetIndexInParent(); + + if ( ind == 0 ) + { + m_value_wxFont.SetPointSize( wxPGVariantToLong(p->DoGetValue()) ); + } + else if ( ind == 1 ) + { + int fam = p->DoGetValue().GetLong(); + if ( fam < wxDEFAULT || + fam > wxTELETYPE ) + fam = wxDEFAULT; + m_value_wxFont.SetFamily( fam ); + } + else if ( ind == 2 ) + { + m_value_wxFont.SetFaceName( p->GetValueAsString(wxPG_FULL_VALUE) ); + } + else if ( ind == 3 ) + { + int st = wxPGVariantToLong(p->DoGetValue()); + if ( st != wxFONTSTYLE_NORMAL && + st != wxFONTSTYLE_SLANT && + st != wxFONTSTYLE_ITALIC ) + st = wxFONTWEIGHT_NORMAL; + m_value_wxFont.SetStyle( st ); + } + else if ( ind == 4 ) + { + int wt = wxPGVariantToLong(p->DoGetValue()); + if ( wt != wxFONTWEIGHT_NORMAL && + wt != wxFONTWEIGHT_LIGHT && + wt != wxFONTWEIGHT_BOLD ) + wt = wxFONTWEIGHT_NORMAL; + m_value_wxFont.SetWeight( wt ); + } + else if ( ind == 5 ) + { + m_value_wxFont.SetUnderlined( wxPGVariantToBool(p->DoGetValue())?true:false ); + } +} + +/* +wxSize wxFontPropertyClass::GetImageSize() const +{ + return wxSize(-1,-1); +} + +void wxFontPropertyClass::OnCustomPaint(wxDC& dc, + const wxRect& rect, + wxPGPaintData& paintData) +{ + wxString drawFace; + if ( paintData.m_choiceItem >= 0 ) + drawFace = wxPGGlobalVars->m_fontFamilyChoices->GetLabel(paintData.m_choiceItem); + else + drawFace = m_value_wxFont.GetFaceName(); + + if ( drawFace.length() ) + { + // Draw the background + dc.SetBrush( wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)) ); + //dc.SetBrush( *wxWHITE_BRUSH ); + //dc.SetPen( *wxMEDIUM_GREY_PEN ); + dc.DrawRectangle( rect ); + + wxFont oldFont = dc.GetFont(); + wxFont drawFont(oldFont.GetPointSize(), + wxDEFAULT,wxNORMAL,wxBOLD,false,drawFace); + dc.SetFont(drawFont); + + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT) ); + dc.DrawText( wxT("Aa"), rect.x+2, rect.y+1 ); + + dc.SetFont(oldFont); + } + else + { + // No file - just draw a white box + dc.SetBrush ( *wxWHITE_BRUSH ); + dc.DrawRectangle ( rect ); + } +} +*/ + + +// ----------------------------------------------------------------------- +// wxSystemColourProperty +// ----------------------------------------------------------------------- + +// wxEnumProperty based classes cannot use wxPG_PROP_CLASS_SPECIFIC_1 +#define wxPG_PROP_HIDE_CUSTOM_COLOUR wxPG_PROP_CLASS_SPECIFIC_2 + +#include + +//#define wx_cp_es_syscolours_len 25 +static const wxChar* gs_cp_es_syscolour_labels[] = { + wxT("AppWorkspace"), + wxT("ActiveBorder"), + wxT("ActiveCaption"), + wxT("ButtonFace"), + wxT("ButtonHighlight"), + wxT("ButtonShadow"), + wxT("ButtonText"), + wxT("CaptionText"), + wxT("ControlDark"), + wxT("ControlLight"), + wxT("Desktop"), + wxT("GrayText"), + wxT("Highlight"), + wxT("HighlightText"), + wxT("InactiveBorder"), + wxT("InactiveCaption"), + wxT("InactiveCaptionText"), + wxT("Menu"), + wxT("Scrollbar"), + wxT("Tooltip"), + wxT("TooltipText"), + wxT("Window"), + wxT("WindowFrame"), + wxT("WindowText"), + wxT("Custom"), + (const wxChar*) NULL +}; + +static long gs_cp_es_syscolour_values[] = { + wxSYS_COLOUR_APPWORKSPACE, + wxSYS_COLOUR_ACTIVEBORDER, + wxSYS_COLOUR_ACTIVECAPTION, + wxSYS_COLOUR_BTNFACE, + wxSYS_COLOUR_BTNHIGHLIGHT, + wxSYS_COLOUR_BTNSHADOW, + wxSYS_COLOUR_BTNTEXT , + wxSYS_COLOUR_CAPTIONTEXT, + wxSYS_COLOUR_3DDKSHADOW, + wxSYS_COLOUR_3DLIGHT, + wxSYS_COLOUR_BACKGROUND, + wxSYS_COLOUR_GRAYTEXT, + wxSYS_COLOUR_HIGHLIGHT, + wxSYS_COLOUR_HIGHLIGHTTEXT, + wxSYS_COLOUR_INACTIVEBORDER, + wxSYS_COLOUR_INACTIVECAPTION, + wxSYS_COLOUR_INACTIVECAPTIONTEXT, + wxSYS_COLOUR_MENU, + wxSYS_COLOUR_SCROLLBAR, + wxSYS_COLOUR_INFOBK, + wxSYS_COLOUR_INFOTEXT, + wxSYS_COLOUR_WINDOW, + wxSYS_COLOUR_WINDOWFRAME, + wxSYS_COLOUR_WINDOWTEXT, + wxPG_COLOUR_CUSTOM +}; + + +// Class body is in advprops.h + + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxSystemColourProperty,wxEnumProperty, + wxColourPropertyValue,const wxColourPropertyValue&,Choice) + + +void wxSystemColourPropertyClass::Init( int type, const wxColour& colour ) +{ + + m_value.m_type = type; + if ( colour.Ok() ) + m_value.m_colour = colour; + else + m_value.m_colour = *wxWHITE; + + m_flags |= wxPG_PROP_STATIC_CHOICES; // Colour selection cannot be changed. +} + + +static wxPGChoices gs_wxSystemColourProperty_choicesCache; + + +wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxColourPropertyValue& value ) + : wxEnumPropertyClass( label, + name, + gs_cp_es_syscolour_labels, + gs_cp_es_syscolour_values, + &gs_wxSystemColourProperty_choicesCache ) +{ + wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue) + + if ( &value ) + Init(value.m_type,value.m_colour); + else + Init(0,*wxBLACK); + + DoSetValue( &m_value ); +} + + +wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxColourPropertyValue& value ) + : wxEnumPropertyClass( label, name, labels, values, choicesCache ) +{ + if ( &value ) + Init(value.m_type,value.m_colour); + else + Init(wxPG_COLOUR_CUSTOM,*wxBLACK); +} + + +wxSystemColourPropertyClass::wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxColour& value ) + : wxEnumPropertyClass( label, name, labels, values, choicesCache ) +{ + Init(wxPG_COLOUR_CUSTOM,value); +} + + +wxSystemColourPropertyClass::~wxSystemColourPropertyClass() { } + + +int wxSystemColourPropertyClass::ColToInd( const wxColour& colour ) +{ + size_t i; + size_t i_max = m_choices.GetCount() - 1; + + if ( !colour.Ok() ) + return wxNOT_FOUND; + + long pixval = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); + const wxArrayInt& arrValues = m_choices.GetValues(); + + for ( i=0; i>8)&0xFF),((col>>16)&0xFF)); +} + + +void wxSystemColourPropertyClass::DoSetValue( wxPGVariant value ) +{ + wxColourPropertyValue* pval = wxPGVariantToWxObjectPtr(value,wxColourPropertyValue); + + m_flags &= ~(wxPG_PROP_UNSPECIFIED); + + if ( pval != (wxColourPropertyValue*) NULL ) + { + if ( !pval->m_colour.Ok() ) + { + m_flags |= wxPG_PROP_UNSPECIFIED; + m_index = wxNOT_FOUND; + + m_value.Init( wxPG_COLOUR_CUSTOM, *wxWHITE ); + return; + } + else if ( pval != &m_value ) + { + m_value = *pval; + } + } + else + { + m_value.Init( wxPG_COLOUR_CUSTOM, *wxWHITE ); + } + + if ( m_value.m_type < wxPG_COLOUR_WEB_BASE ) + { + m_value.m_colour = GetColour( m_value.m_type ); + wxEnumPropertyClass::DoSetValue( (long)m_value.m_type ); + } + else + { + m_index = m_choices.GetCount()-1; + } +} + + +long wxSystemColourPropertyClass::GetColour( int index ) +{ + wxColour colour = wxSystemSettings::GetColour ( (wxSystemColour)index ); + return wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); +} + + +wxPGVariant wxSystemColourPropertyClass::DoGetValue() const +{ + return wxPGVariantCreator(&m_value); +} + + +wxString wxSystemColourPropertyClass::GetValueAsString( int argFlags ) const +{ + // Always show custom colour for non-choice editor + // Assumes changed editor means its textctrl based... + if ( m_value.m_type == wxPG_COLOUR_CUSTOM || + (argFlags & wxPG_PROPERTY_SPECIFIC) ) + { + +/*#ifdef __WXDEBUG__ + // Sanity check + if ( m_value.m_type != wxPG_COLOUR_CUSTOM && + (GetEditorClass() == wxPG_EDITOR(Choice) || + GetEditorClass() == wxPG_EDITOR(ChoiceAndButton)) ) + { + wxLogDebug(wxT("wxSystemColourPropertyClass: Assumed wrong editor type!!!")); + } +#endif*/ + + return wxString::Format(wxT("(%i,%i,%i)"), + (int)m_value.m_colour.Red(), + (int)m_value.m_colour.Green(), + (int)m_value.m_colour.Blue()); + } + return m_choices.GetLabel(m_index); +} + + +wxSize wxSystemColourPropertyClass::GetImageSize() const +{ + return wxSize(-1,-1); +} + + +bool wxSystemColourPropertyClass::QueryColourFromUser( wxPropertyGrid* propgrid, wxWindow* primary ) +{ + bool res = false; + + m_value.m_type = wxPG_COLOUR_CUSTOM; + + wxColourData data; + data.SetChooseFull(true); + data.SetColour(m_value.m_colour); + int i; + for ( i = 0; i < 16; i++) + { + wxColour colour(i*16, i*16, i*16); + data.SetCustomColour(i, colour); + } + + wxColourDialog dialog(propgrid, &data); + if ( dialog.ShowModal() == wxID_OK ) + { + wxColourData retData = dialog.GetColourData(); + m_value.m_colour = retData.GetColour(); + wxSystemColourPropertyClass::DoSetValue(&m_value); + + res = true; + } + + // Update text in combo box (so it is "(R,G,B)" not "Custom"). + if ( primary ) + GetEditorClass()->SetControlStringValue(primary,GetValueAsString(0)); + + return res; +} + + +// Need to do some extra event handling. +bool wxSystemColourPropertyClass::OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) + { + int index = m_index; // m_index has already been updated. + int type = wxEnumPropertyClass::DoGetValue().GetLong(); + + const wxArrayInt& arrValues = m_choices.GetValues(); + + if ( ( arrValues.GetCount() && type == wxPG_COLOUR_CUSTOM ) || + ( !arrValues.GetCount() && (index == (int)(m_choices.GetCount()-1) && + !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR)) + ) + ) + { + QueryColourFromUser(propgrid,primary); + + return true; + } + else + { + m_value.m_type = type; + m_value.m_colour = GetColour( type ); + } + } + else if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + // We need to handle button click in case editor has been + // switched to one that has wxButton as well. + return QueryColourFromUser(propgrid,primary); + } + return false; +} + + +void wxSystemColourPropertyClass::OnCustomPaint( wxDC& dc, const wxRect& rect, + wxPGPaintData& paintdata ) +{ + if ( paintdata.m_choiceItem >= 0 && + ( paintdata.m_choiceItem < (int)(GetItemCount()-1) || (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR)) + ) + { + int colInd; + const wxArrayInt& values = m_choices.GetValues(); + if ( values.GetCount() ) + colInd = values[paintdata.m_choiceItem]; + else + colInd = paintdata.m_choiceItem; + dc.SetBrush ( wxColour ( GetColour ( colInd ) ) ); + } + else if ( !(m_flags & wxPG_PROP_UNSPECIFIED) ) + dc.SetBrush ( m_value.m_colour ); + else + dc.SetBrush ( *wxWHITE ); + + dc.DrawRectangle ( rect ); +} + + +bool wxSystemColourPropertyClass::SetValueFromString( const wxString& text, int flags ) +{ + wxColourPropertyValue val; + if ( text[0] == wxT('(') ) + { + // Custom colour. + val.m_type = wxPG_COLOUR_CUSTOM; + + int r, g, b; + wxSscanf(text.c_str(),wxT("(%i,%i,%i)"),&r,&g,&b); + val.m_colour.Set(r,g,b); + + wxSystemColourPropertyClass::DoSetValue( &val ); + + return true; + } + else + { + // Predefined colour. + bool res = wxEnumPropertyClass::SetValueFromString(text,flags); + if ( res ) + { + val.m_type = m_index; + const wxArrayInt& values = GetValues(); + if ( values.GetCount() ) + val.m_type = values[m_index]; + + // Get proper colour for type. + val.m_colour = wxColourFromPGLong(GetColour(val.m_type)); + + wxSystemColourPropertyClass::DoSetValue( &val ); + return true; + } + } + return false; +} + + +void wxSystemColourPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_COLOUR_ALLOW_CUSTOM ) + { + int ival = value.GetLong(); + + SetChoicesExclusive(); // Make sure we don't corrupt colour lists of other properties + + if ( ival && (m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) + { + // Show custom choice + m_choices.Add(wxT("Custom"),wxPG_COLOUR_CUSTOM); + m_flags &= ~(wxPG_PROP_HIDE_CUSTOM_COLOUR); + } + else if ( !ival && !(m_flags & wxPG_PROP_HIDE_CUSTOM_COLOUR) ) + { + // Hide custom choice + m_choices.RemoveAt(m_choices.GetCount()-1); + m_flags |= wxPG_PROP_HIDE_CUSTOM_COLOUR; + } + } +} + + +// ----------------------------------------------------------------------- +// wxColourProperty +// ----------------------------------------------------------------------- + +static const wxChar* gs_cp_es_normcolour_labels[] = { + wxT("Black"), + wxT("Maroon"), + wxT("Navy"), + wxT("Purple"), + wxT("Teal"), + wxT("Gray"), + wxT("Green"), + wxT("Olive"), + wxT("Brown"), + wxT("Blue"), + wxT("Fuchsia"), + wxT("Red"), + wxT("Orange"), + wxT("Silver"), + wxT("Lime"), + wxT("Aqua"), + wxT("Yellow"), + wxT("White"), + wxT("Custom"), + (const wxChar*) NULL +}; + +static unsigned long gs_cp_es_normcolour_colours[] = { + wxPG_COLOUR(0,0,0), + wxPG_COLOUR(128,0,0), + wxPG_COLOUR(0,0,128), + wxPG_COLOUR(128,0,128), + wxPG_COLOUR(0,128,128), + wxPG_COLOUR(128,128,128), + wxPG_COLOUR(0,128,0), + wxPG_COLOUR(128,128,0), + wxPG_COLOUR(166,124,81), + wxPG_COLOUR(0,0,255), + wxPG_COLOUR(255,0,255), + wxPG_COLOUR(255,0,0), + wxPG_COLOUR(247,148,28), + wxPG_COLOUR(192,192,192), + wxPG_COLOUR(0,255,0), + wxPG_COLOUR(0,255,255), + wxPG_COLOUR(255,255,0), + wxPG_COLOUR(255,255,255), + wxPG_COLOUR(0,0,0) +}; + +WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(wxColourProperty, + wxColourPropertyClass, + gs_cp_es_normcolour_labels, + (const long*)NULL, + gs_cp_es_normcolour_colours, + TextCtrlAndButton) + +// ----------------------------------------------------------------------- +// wxCursorProperty +// ----------------------------------------------------------------------- + +#define wxPG_CURSOR_IMAGE_WIDTH 32 + +//#define wx_cp_es_syscursors_len 28 +static const wxChar* gs_cp_es_syscursors_labels[] = { + wxT("Default"), + wxT("Arrow"), + wxT("Right Arrow"), + wxT("Blank"), + wxT("Bullseye"), + wxT("Character"), + wxT("Cross"), + wxT("Hand"), + wxT("I-Beam"), + wxT("Left Button"), + wxT("Magnifier"), + wxT("Middle Button"), + wxT("No Entry"), + wxT("Paint Brush"), + wxT("Pencil"), + wxT("Point Left"), + wxT("Point Right"), + wxT("Question Arrow"), + wxT("Right Button"), + wxT("Sizing NE-SW"), + wxT("Sizing N-S"), + wxT("Sizing NW-SE"), + wxT("Sizing W-E"), + wxT("Sizing"), + wxT("Spraycan"), + wxT("Wait"), + wxT("Watch"), + wxT("Wait Arrow"), + (const wxChar*) NULL +}; + +static long gs_cp_es_syscursors_values[] = { + wxCURSOR_NONE, + wxCURSOR_ARROW, + wxCURSOR_RIGHT_ARROW, + wxCURSOR_BLANK, + wxCURSOR_BULLSEYE, + wxCURSOR_CHAR, + wxCURSOR_CROSS, + wxCURSOR_HAND, + wxCURSOR_IBEAM, + wxCURSOR_LEFT_BUTTON, + wxCURSOR_MAGNIFIER, + wxCURSOR_MIDDLE_BUTTON, + wxCURSOR_NO_ENTRY, + wxCURSOR_PAINT_BRUSH, + wxCURSOR_PENCIL, + wxCURSOR_POINT_LEFT, + wxCURSOR_POINT_RIGHT, + wxCURSOR_QUESTION_ARROW, + wxCURSOR_RIGHT_BUTTON, + wxCURSOR_SIZENESW, + wxCURSOR_SIZENS, + wxCURSOR_SIZENWSE, + wxCURSOR_SIZEWE, + wxCURSOR_SIZING, + wxCURSOR_SPRAYCAN, + wxCURSOR_WAIT, + wxCURSOR_WATCH, + wxCURSOR_ARROWWAIT +}; + +WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxCursorProperty,wxEnumProperty,int) + +wxCursorPropertyClass::wxCursorPropertyClass( const wxString& label, const wxString& name, + int value ) + : wxEnumPropertyClass( label, + name, + gs_cp_es_syscursors_labels, + gs_cp_es_syscursors_values, + value ) +{ + m_flags |= wxPG_PROP_STATIC_CHOICES; // Cursor selection cannot be changed. + //wxEnumPropertyClass::DoSetValue ( (void*)&value, NULL ); +} + +wxCursorPropertyClass::~wxCursorPropertyClass() +{ +} + +wxSize wxCursorPropertyClass::GetImageSize() const +{ +#if wxPG_CAN_DRAW_CURSOR + return wxSize(wxPG_CURSOR_IMAGE_WIDTH,wxPG_CURSOR_IMAGE_WIDTH); +#else + return wxSize(0,0); +#endif +} + +#if wxPG_CAN_DRAW_CURSOR + +void wxCursorPropertyClass::OnCustomPaint( wxDC& dc, + const wxRect& rect, + wxPGPaintData& paintdata ) +{ + + // Background brush + dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) ); + + if ( paintdata.m_choiceItem >= 0 ) + { + dc.DrawRectangle( rect ); + + int cursorindex = gs_cp_es_syscursors_values[paintdata.m_choiceItem]; + + /* + if ( cursorindex == wxPG_CURSOR_FROM_FILE ) + { + wxFAIL_MSG(wxT("not implemented")); + } + else if ( cursorindex == wxPG_CURSOR_FROM_RESOURCE ) + { + wxFAIL_MSG(wxT("not implemented")); + } + else + */ + { + if ( cursorindex == wxCURSOR_NONE ) + cursorindex = wxCURSOR_ARROW; + + wxCursor cursor( cursorindex ); + + #ifdef __WXMSW__ + ::DrawIconEx( (HDC)dc.GetHDC(), + rect.x, + rect.y, + (HICON)cursor.GetHandle(), + 0, + 0, + 0, + NULL, + DI_COMPAT | DI_DEFAULTSIZE | DI_NORMAL + ); + #endif + } + } +} +#else +void wxCursorPropertyClass::OnCustomPaint( wxDC&, const wxRect&, wxPGPaintData& ) { } +#endif + +// ----------------------------------------------------------------------- +// wxImageFileProperty +// ----------------------------------------------------------------------- + +#if wxUSE_IMAGE + +const wxString& wxPGGetDefaultImageWildcard() +{ + WX_PG_GLOBALS_LOCKER() + + // Form the wildcard, if not done yet + if ( !wxPGGlobalVars->m_pDefaultImageWildcard.length() ) + { + + wxString str; + + // TODO: This section may require locking (using global). + + wxList& handlers = wxImage::GetHandlers(); + + wxList::iterator node; + + // Let's iterate over the image handler list. + //for ( wxList::Node *node = handlers.GetFirst(); node; node = node->GetNext() ) + for ( node = handlers.begin(); node != handlers.end(); node++ ) + { + wxImageHandler *handler = (wxImageHandler*)*node; + + wxString ext_lo = handler->GetExtension(); + wxString ext_up = ext_lo.Upper(); + + str.append( ext_up ); + str.append( wxT(" files (*.") ); + str.append( ext_up ); + str.append( wxT(")|*.") ); + str.append( ext_lo ); + str.append( wxT("|") ); + } + + str.append ( wxT("All files (*.*)|*.*") ); + + wxPGGlobalVars->m_pDefaultImageWildcard = str; + } + + return wxPGGlobalVars->m_pDefaultImageWildcard; +} + +WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxImageFileProperty, + wxFileProperty, + const wxString&) + +wxImageFilePropertyClass::wxImageFilePropertyClass( const wxString& label, const wxString& name, + const wxString& value ) + : wxFilePropertyClass(label,name,value) +{ + + m_wildcard = wxPGGetDefaultImageWildcard(); + + m_pImage = (wxImage*) NULL; + m_pBitmap = (wxBitmap*) NULL; +} + +wxImageFilePropertyClass::~wxImageFilePropertyClass() +{ + if ( m_pBitmap ) + delete m_pBitmap; + if ( m_pImage ) + delete m_pImage; +} + +void wxImageFilePropertyClass::DoSetValue( wxPGVariant value ) +{ + wxFilePropertyClass::DoSetValue(value); + + // Delete old image + if ( m_pImage ) + { + delete m_pImage; + m_pImage = NULL; + } + if ( m_pBitmap ) + { + delete m_pBitmap; + m_pBitmap = NULL; + } + + // Create the image thumbnail + if ( m_filename.FileExists() ) + { + m_pImage = new wxImage ( m_filename.GetFullPath() ); + } +} + +wxSize wxImageFilePropertyClass::GetImageSize() const +{ + return wxSize(-1,-1); +} + +void wxImageFilePropertyClass::OnCustomPaint( wxDC& dc, + const wxRect& rect, + wxPGPaintData& ) +{ + if ( m_pBitmap || (m_pImage && m_pImage->Ok() ) ) + { + // Draw the thumbnail + + // Create the bitmap here because required size is not known in DoSetValue(). + if ( !m_pBitmap ) + { + m_pImage->Rescale( rect.width, rect.height ); + m_pBitmap = new wxBitmap( *m_pImage ); + delete m_pImage; + m_pImage = NULL; + } + + dc.DrawBitmap( *m_pBitmap, rect.x, rect.y, false ); + } + else + { + // No file - just draw a white box + dc.SetBrush( *wxWHITE_BRUSH ); + dc.DrawRectangle ( rect ); + } +} + +#endif // wxUSE_IMAGE + +// ----------------------------------------------------------------------- +// wxMultiChoiceProperty +// ----------------------------------------------------------------------- + +#if wxUSE_CHOICEDLG + +#include + +#ifndef __WXPYTHON__ +wxPGProperty* wxPG_CONSTFUNC(wxMultiChoiceProperty)(const wxString& label, + const wxString& name, + const wxPGChoices& choices, + const wxArrayInt& value) +{ + return new wxPG_PROPCLASS(wxMultiChoiceProperty)(label,name,choices,value); +} +#endif + +wxPGProperty* wxPG_CONSTFUNC(wxMultiChoiceProperty)(const wxString& label, + const wxString& name, + const wxArrayString& strings, + const wxArrayInt& value) +{ + return new wxPG_PROPCLASS(wxMultiChoiceProperty)(label,name,strings,value); +} + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxMultiChoiceProperty,wxBaseProperty, + wxArrayInt,const wxArrayInt&,TextCtrlAndButton) + +wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label, + const wxString& name, + const wxPGChoices& choices, + const wxArrayInt& value) + : wxPGProperty(label,name) +{ + wxPG_INIT_REQUIRED_TYPE(wxArrayInt) + + m_choices.Assign(choices); + SetValueI(value); +} + + +wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label, + const wxString& name, + const wxArrayString& strings, + const wxArrayInt& value) + : wxPGProperty(label,name) +{ + wxPG_INIT_REQUIRED_TYPE(wxArrayInt) + + m_choices.Set(strings); + SetValueI(value); +} + +wxMultiChoicePropertyClass::wxMultiChoicePropertyClass(const wxString& label, + const wxString& name, + const wxArrayInt& WXUNUSED(value)) + : wxPGProperty(label,name) +{ +} + +wxMultiChoicePropertyClass::~wxMultiChoicePropertyClass() +{ +} + +void wxMultiChoicePropertyClass::SetValueI( const wxArrayInt& arr ) +{ + if ( &arr ) + { + m_value_wxArrayInt = arr; + GenerateValueAsString(); + } + else + { + m_display = wxEmptyString; + } +} + +void wxMultiChoicePropertyClass::DoSetValue( wxPGVariant value ) +{ +#if !wxPG_PGVARIANT_IS_VARIANT + wxArrayInt* pObj = (wxArrayInt*)wxPGVariantToVoidPtr(value); + SetValueI(*pObj); +#else + wxArrayInt arr = wxPGVariantToArrayInt(value); + SetValueI(arr); +#endif +} + +wxPGVariant wxMultiChoicePropertyClass::DoGetValue() const +{ + return wxPGVariantCreator(m_value_wxArrayInt); +} + +wxString wxMultiChoicePropertyClass::GetValueAsString( int ) const +{ + return m_display; +} + +void wxMultiChoicePropertyClass::GenerateValueAsString() +{ + // Allow zero-length strings list + if ( !m_choices.IsOk() || !m_choices.GetCount() ) + { + m_display = wxEmptyString; + return; + } + + wxString& tempStr = m_display; + wxArrayInt indices = GetValueAsIndices(); + unsigned int i; + unsigned int itemCount = indices.GetCount(); + + tempStr.Empty(); + + if ( itemCount ) + tempStr.append( wxT("\"") ); + + for ( i = 0; i < itemCount; i++ ) + { + int ind = indices.Item(i); + wxCHECK_RET( ind >= 0 && ind < (int)m_choices.GetCount(), + wxT("value out of range") ); + tempStr.append( m_choices.GetLabel(ind) ); + tempStr.append( wxT("\"") ); + if ( i < (itemCount-1) ) + tempStr.append ( wxT(" \"") ); + } +} + +wxArrayInt wxMultiChoicePropertyClass::GetValueAsIndices() const +{ + const wxArrayInt& choiceValues = m_choices.GetValues(); + if ( choiceValues.GetCount() ) + { + // Translate values to string indices. + wxArrayInt selections; + + unsigned int i; + for ( i=0; i= 0 ) + selections.Add(sIndex); + } + + return selections; + } + + return m_value_wxArrayInt; +} + +bool wxMultiChoicePropertyClass::OnEvent( wxPropertyGrid* propgrid, + wxWindow* primary, + wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + // Update the value + PrepareValueForDialogEditing(propgrid); + + // launch editor dialog + wxMultiChoiceDialog dlg( propgrid, + _("Make a selection:"), + m_label, + m_choices.GetCount(), + &m_choices.GetLabels()[0], + wxCHOICEDLG_STYLE ); + + dlg.Move( propgrid->GetGoodEditorDialogPosition(this,dlg.GetSize()) ); + + dlg.SetSelections(GetValueAsIndices()); + + if ( dlg.ShowModal() == wxID_OK ) + { + wxArrayInt arrInt = dlg.GetSelections(); + + const wxArrayInt& choiceValues = m_choices.GetValues(); + if ( choiceValues.GetCount() ) + { + // Translate string indices to values. + wxArrayInt values; + + unsigned int i; + for ( i=0; im_itemCount = m_choices.GetCount(); + + choiceinfo->m_choices = &m_choices; + } + return -1; +} + +bool wxMultiChoicePropertyClass::SetValueFromString( const wxString& text, int ) +{ + m_value_wxArrayInt.Empty(); + const wxArrayString& strings = m_choices.GetLabels(); + const wxArrayInt& values = m_choices.GetValues(); + + WX_PG_TOKENIZER2_BEGIN(text,wxT('"')) + int ind = strings.Index( token ); + if ( ind != wxNOT_FOUND ) + { + if ( values.GetCount() ) + ind = values.Item(ind); + + m_value_wxArrayInt.Add(ind); + } + WX_PG_TOKENIZER2_END() + + GenerateValueAsString(); + + return true; +} + +#endif // wxUSE_CHOICEDLG + + +// ----------------------------------------------------------------------- +// wxDateProperty +// ----------------------------------------------------------------------- + +#if wxUSE_DATETIME + + +#if wxUSE_DATEPICKCTRL + #define dtCtrl DatePickerCtrl +#else + #define dtCtrl TextCtrl +#endif + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxDateProperty, + wxBaseProperty, + wxDateTime, + const wxDateTime&, + dtCtrl) + + +wxString wxDatePropertyClass::ms_defaultDateFormat; + + +wxDatePropertyClass::wxDatePropertyClass( const wxString& label, + const wxString& name, + const wxDateTime& value ) + : wxPGProperty(label,name) +{ + wxPGRegisterDefaultValueType(wxDateTime) + +#if wxUSE_DATEPICKCTRL + wxPGRegisterEditorClass(DatePickerCtrl); + + m_dpStyle = wxDP_DEFAULT | wxDP_SHOWCENTURY; +#else + m_dpStyle = 0; +#endif + + DoSetValue( value ); +} + +wxDatePropertyClass::~wxDatePropertyClass() +{ +} + +void wxDatePropertyClass::DoSetValue( wxPGVariant value ) +{ + m_valueDateTime = wxPGVariantToDateTime(value); +} + +wxPGVariant wxDatePropertyClass::DoGetValue() const +{ + return wxPGVariantCreator(m_valueDateTime); +} + +bool wxDatePropertyClass::SetValueFromString( const wxString& text, + int WXUNUSED(argFlags) ) +{ + const wxChar* c = m_valueDateTime.ParseFormat(text.c_str(),wxDefaultDateTimeFormat); + + return c ? true : false; +} + +wxString wxDatePropertyClass::GetValueAsString( int argFlags ) const +{ + const wxChar* format = (const wxChar*) NULL; + + if ( !m_valueDateTime.IsValid() ) + return wxT("Invalid"); + + if ( !ms_defaultDateFormat.length() ) + { +#if wxUSE_DATEPICKCTRL + bool showCentury = m_dpStyle & wxDP_SHOWCENTURY ? true : false; +#else + bool showCentury = true; +#endif + ms_defaultDateFormat = DetermineDefaultDateFormat( showCentury ); + } + + if ( m_format.length() && + !(argFlags & wxPG_FULL_VALUE) ) + format = m_format.c_str(); + + // Determine default from locale + // NB: This is really simple stuff, but can't figure anything + // better without proper support in wxLocale + if ( !format ) + format = ms_defaultDateFormat.c_str(); + + return m_valueDateTime.Format(format); +} + +wxString wxDatePropertyClass::DetermineDefaultDateFormat( bool showCentury ) +{ + // This code is basicly copied from datectlg.cpp's SetFormat + // + wxString format; + + wxDateTime dt; + dt.ParseFormat(wxT("2003-10-13"), wxT("%Y-%m-%d")); + wxString str(dt.Format(wxT("%x"))); + + const wxChar *p = str.c_str(); + while ( *p ) + { + int n=wxAtoi(p); + if (n == dt.GetDay()) + { + format.Append(wxT("%d")); + p += 2; + } + else if (n == (int)dt.GetMonth()+1) + { + format.Append(wxT("%m")); + p += 2; + } + else if (n == dt.GetYear()) + { + format.Append(wxT("%Y")); + p += 4; + } + else if (n == (dt.GetYear() % 100)) + { + if (showCentury) + format.Append(wxT("%Y")); + else + format.Append(wxT("%y")); + p += 2; + } + else + format.Append(*p++); + } + + return format; +} + +void wxDatePropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_DATE_FORMAT ) + { + m_format = value.GetString(); + } + else if ( id == wxPG_DATE_PICKER_STYLE ) + { + m_dpStyle = value.GetLong(); + ms_defaultDateFormat.clear(); // This may need recalculation + } +} + +#endif // wxUSE_DATETIME + + +// ----------------------------------------------------------------------- +// wxPropertyContainerMethods +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::InitAllTypeHandlers() +{ + wxPG_INIT_REQUIRED_TYPE(wxColour) + wxPG_INIT_REQUIRED_TYPE(wxFont) + wxPG_INIT_REQUIRED_TYPE(wxArrayInt) + wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue) +#if wxUSE_DATETIME + wxPGRegisterDefaultValueType(wxDateTime) +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::RegisterAdditionalEditors() +{ +#if wxUSE_SPINBTN + wxPGRegisterEditorClass(SpinCtrl); +#endif +#if wxUSE_DATEPICKCTRL + wxPGRegisterEditorClass(DatePickerCtrl); +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::RegisterAdvancedPropertyClasses() +{ + wxPGRegisterPropertyClass(wxMultiChoiceProperty); + wxPGRegisterPropertyClass(wxImageFileProperty); + wxPGRegisterPropertyClass(wxColourProperty); + wxPGRegisterPropertyClass(wxFontProperty); + wxPGRegisterPropertyClass(wxSystemColourProperty); + wxPGRegisterPropertyClass(wxCursorProperty); +#if wxUSE_DATETIME + wxPGRegisterPropertyClass(wxDateProperty); +#endif +} + +// ----------------------------------------------------------------------- + +#endif // wxPG_INCLUDE_ADVPROPS diff --git a/assdraw/libpropgrid/extras.cpp b/assdraw/libpropgrid/extras.cpp new file mode 100644 index 000000000..5c582120b --- /dev/null +++ b/assdraw/libpropgrid/extras.cpp @@ -0,0 +1,23 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: extras.cpp +// Purpose: wxPropertyGrid Extras +// Author: Jaakko Salli +// Modified by: +// Created: Mar-05-2006 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// +// In wxPython version this file will have additional property and +// editor control source code. +// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + diff --git a/assdraw/libpropgrid/include/wx/propgrid/Doxyfile b/assdraw/libpropgrid/include/wx/propgrid/Doxyfile new file mode 100644 index 000000000..4007200bd --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/Doxyfile @@ -0,0 +1,210 @@ +# Doxyfile 1.3.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = wxPropertyGrid +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = YES +BRIEF_MEMBER_DESC = NO +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = YES +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = YES +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = YES +SORT_BY_SCOPE_NAME = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = doxygen.log +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +#INPUT = ../../include/wx/propgrid/ +INPUT = +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = ../../../docs/html/propgrid +HTML_FILE_EXTENSION = .htm +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = propgrid.chm +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = ../../../include +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = YES diff --git a/assdraw/libpropgrid/include/wx/propgrid/advprops.h b/assdraw/libpropgrid/include/wx/propgrid/advprops.h new file mode 100644 index 000000000..4d724db77 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/advprops.h @@ -0,0 +1,432 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: advprops.h +// Purpose: wxPropertyGrid Advanced Properties (font, colour, etc.) +// Author: Jaakko Salli +// Modified by: +// Created: Sep-25-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PROPGRID_ADVPROPS_H_ +#define _WX_PROPGRID_ADVPROPS_H_ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma interface "advprops.cpp" +#endif + +// ----------------------------------------------------------------------- + + +// +// Additional Value Type Handlers +// +#ifndef SWIG + +WX_PG_DECLARE_VALUE_TYPE_WITH_DECL(wxFont,WXDLLIMPEXP_PG) + +WX_PG_DECLARE_VALUE_TYPE_WITH_DECL(wxColour,WXDLLIMPEXP_PG) + +WX_PG_DECLARE_VALUE_TYPE_VOIDP_WITH_DECL(wxArrayInt,WXDLLIMPEXP_PG) + + +#if wxUSE_DATETIME +#include +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(wxDateTime,WXDLLIMPEXP_PG) +#endif + +bool WXDLLIMPEXP_PG operator == (const wxFont&, const wxFont&); + +bool WXDLLIMPEXP_PG operator == (const wxArrayInt& array1, const wxArrayInt& array2); + +#endif + + +// +// Additional Property Editors +// +#if wxUSE_SPINBTN +WX_PG_DECLARE_EDITOR_WITH_DECL(SpinCtrl,WXDLLIMPEXP_PG) +#endif + +#if wxUSE_DATEPICKCTRL && defined(wxPG_ALLOW_WXADV) +WX_PG_DECLARE_EDITOR_WITH_DECL(DatePickerCtrl,WXDLLIMPEXP_PG) +#endif + +// ----------------------------------------------------------------------- + + +// Web colour is currently unsupported +#define wxPG_COLOUR_WEB_BASE 0x10000 +//#define wxPG_TO_WEB_COLOUR(A) ((wxUint32)(A+wxPG_COLOUR_WEB_BASE)) + + +#define wxPG_COLOUR_CUSTOM 0xFFFFFF + +/** \class wxColourPropertyValue + \ingroup classes + \brief Because text, background and other colours tend to differ between + platforms, wxSystemColourProperty must be able to select between system + colour and, when necessary, to pick a custom one. wxSystemColourProperty + value makes this possible. +*/ +class WXDLLIMPEXP_PG wxColourPropertyValue : public wxObject +{ +public: + /** An integer value relating to the colour, and which exact + meaning depends on the property with which it is used. + + For wxSystemColourProperty: + + Any of wxSYS_COLOUR_XXX, or any web-colour ( use wxPG_TO_WEB_COLOUR + macro - (currently unsupported) ), or wxPG_COLOUR_CUSTOM. + + For custom colour properties without values array specified: + + index or wxPG_COLOUR_CUSTOM + + For custom colour properties with values array specified: + + m_arrValues[index] or wxPG_COLOUR_CUSTOM + */ + wxUint32 m_type; + + /** Resulting colour. Should be correct regardless of type. */ + wxColour m_colour; + + wxColourPropertyValue() { } + + inline void Init( wxUint32 type, const wxColour& colour ) + { + m_type = type; + m_colour = colour; + } + + inline wxColourPropertyValue( const wxColour& colour ) + { + m_type = wxPG_COLOUR_CUSTOM; + m_colour = colour; + } + + inline wxColourPropertyValue( wxUint32 type ) + { + m_type = type; + } + + inline wxColourPropertyValue( wxUint32 type, const wxColour& colour ) + { + Init( type, colour ); + } + +#ifndef SWIG +private: + DECLARE_DYNAMIC_CLASS(wxColourPropertyValue) +#endif +}; + +#ifndef SWIG +bool WXDLLIMPEXP_PG operator == (const wxColourPropertyValue&, const wxColourPropertyValue&); + +WX_PG_DECLARE_VALUE_TYPE_WITH_DECL(wxColourPropertyValue,WXDLLIMPEXP_PG) +#endif + +#ifndef SWIG + #define wxPG_EMPTY_CPV (*((wxColourPropertyValue*)NULL)) + #define wxPG_NORMAL_FONT (*wxNORMAL_FONT) +#else + #define wxPG_EMPTY_CPV wxCPV_wxPG_EMPTY + #define wxPG_NORMAL_FONT wxFONT_wxPG_NORMAL_FONT +#endif + + +// ----------------------------------------------------------------------- +// Declare part of custom colour property macro pairs. + +#define WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY_WITH_DECL(NAME,DECL) \ +extern DECL wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxColourPropertyValue& value = wxPG_EMPTY_CPV ); \ +extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY(NAME) \ +extern wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxColourPropertyValue& value = wxPG_EMPTY_CPV ); \ +extern wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR_WITH_DECL(NAME,DECL) \ +extern DECL wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxColour& value = wxPG_COLOUR_BLACK ); \ +extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR(NAME) \ +extern wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxColour& value = wxPG_COLOUR_BLACK ); \ +extern wxPGPropertyClassInfo NAME##ClassInfo; + +// Declare advanced properties. +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxFontProperty,const wxFont&,wxPG_NORMAL_FONT,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxSystemColourProperty,const wxColourPropertyValue&,wxPG_EMPTY_CPV,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxCursorProperty,int,wxCURSOR_NONE,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxDateProperty,const wxDateTime&,wxDateTime(),WXDLLIMPEXP_PG) + +#if wxUSE_IMAGE || defined(SWIG) +#include +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxImageFileProperty,const wxString&,wxEmptyString,WXDLLIMPEXP_PG) +#endif + +WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR_WITH_DECL(wxColourProperty,WXDLLIMPEXP_PG) + +// MultiChoice is trickier. + +#ifndef __WXPYTHON__ + +extern WXDLLIMPEXP_PG wxPGProperty* wxMultiChoiceProperty(const wxString& label, + const wxString& name, + const wxArrayString& choices = wxArrayString(), + const wxArrayInt& value = wxPG_EMPTY_ARRAYINT); + +extern WXDLLIMPEXP_PG wxPGProperty* wxMultiChoiceProperty(const wxString& label, + const wxString& name, + const wxPGChoices& choices, + const wxArrayInt& value = wxPG_EMPTY_ARRAYINT); + +extern WXDLLIMPEXP_PG wxPGProperty* wxMultiChoiceProperty(const wxString& label, + const wxString& name, + const wxArrayInt& value); + +#else + +extern WXDLLIMPEXP_PG wxPGProperty* wxMultiChoiceProperty(const wxString& label, + const wxString& name = wxPG_LABEL, + const wxArrayString& choices = wxArrayString(), + // This crazyness is needed for Python 2.3 (which uses + // VC6) compatibility. + #ifndef SWIG + const wxArrayInt& value = (*((wxArrayInt*)NULL))); + #else + const wxArrayInt& value = wxArrayInt()); + #endif + +#endif + +// ----------------------------------------------------------------------- + +// +// Define property classes *only* if propdev.h was included +// +#if defined(_WX_PROPGRID_PROPDEV_H_) + +//#ifndef SWIG + +// ----------------------------------------------------------------------- + +class WXDLLIMPEXP_PG wxFontPropertyClass : public wxPGPropertyWithChildren +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxFontPropertyClass( const wxString& label, const wxString& name, const wxFont& value ); + virtual ~wxFontPropertyClass(); + + WX_PG_DECLARE_PARENTAL_TYPE_METHODS() + virtual wxString GetValueAsString( int argFlags = 0 ) const; + + WX_PG_DECLARE_EVENT_METHODS() + WX_PG_DECLARE_PARENTAL_METHODS() + //WX_PG_DECLARE_CUSTOM_PAINT_METHODS() + +protected: + wxFont m_value_wxFont; +}; + +// ----------------------------------------------------------------------- + + +/** If set, then match from list is searched for a custom colour. */ +#define wxPG_PROP_TRANSLATE_CUSTOM wxPG_PROP_CLASS_SPECIFIC_1 + + +class WXDLLIMPEXP_PG wxSystemColourPropertyClass : public wxEnumPropertyClass +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxColourPropertyValue& value ); + ~wxSystemColourPropertyClass(); + + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_EVENT_METHODS() + WX_PG_DECLARE_CUSTOM_PAINT_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() + + // Helper function to show the colour dialog + bool QueryColourFromUser( wxPropertyGrid* propgrid, wxWindow* primary ); + + // Default is to use wxSystemSettings::GetColour(index). Override to use + // custom colour tables etc. + virtual long GetColour( int index ); + +protected: + + // Special constructors to be used by derived classes. + wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxColourPropertyValue& value ); + wxSystemColourPropertyClass( const wxString& label, const wxString& name, + const wxChar** labels, const long* values, wxPGChoices* choicesCache, + const wxColour& value ); + + void Init ( int type, const wxColour& colour ); + + // Translates colour to a int value, return wxNOT_FOUND if no match. + int ColToInd ( const wxColour& colour ); + + wxColourPropertyValue m_value; +}; + +// ----------------------------------------------------------------------- + +#ifndef SWIG + +class WXDLLIMPEXP_PG wxCursorPropertyClass : public wxEnumPropertyClass +{ + WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() +public: + + wxCursorPropertyClass( const wxString& label, const wxString& name, int value ); + virtual ~wxCursorPropertyClass(); + + WX_PG_DECLARE_CUSTOM_PAINT_METHODS() +}; + +#endif + +// ----------------------------------------------------------------------- + +#if wxUSE_IMAGE || defined(SWIG) + +WXDLLIMPEXP_PG const wxString& wxPGGetDefaultImageWildcard(); + +class WXDLLIMPEXP_PG wxImageFilePropertyClass : public wxFilePropertyClass +{ + WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() +public: + + wxImageFilePropertyClass( const wxString& label, const wxString& name, const wxString& value ); + virtual ~wxImageFilePropertyClass (); + + virtual void DoSetValue ( wxPGVariant value ); + WX_PG_DECLARE_CUSTOM_PAINT_METHODS() + +protected: + wxBitmap* m_pBitmap; // final thumbnail area + wxImage* m_pImage; // intermediate thumbnail area + +}; + +#endif + +#if wxUSE_CHOICEDLG && !defined(SWIG) //|| defined(SWIG) + +class WXDLLIMPEXP_PG wxMultiChoicePropertyClass : public wxPGProperty +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxMultiChoicePropertyClass( const wxString& label, + const wxString& name, + const wxArrayString& strings, + const wxArrayInt& value ); + wxMultiChoicePropertyClass( const wxString& label, + const wxString& name = wxPG_LABEL, + const wxArrayInt& value = wxArrayInt() ); + wxMultiChoicePropertyClass( const wxString& label, + const wxString& name, + const wxPGChoices& choices, + const wxArrayInt& value = wxArrayInt() ); + virtual ~wxMultiChoicePropertyClass(); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int flags = 0 ) const; + virtual bool SetValueFromString( const wxString& text, int flags ); + WX_PG_DECLARE_EVENT_METHODS() + + virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + +protected: + + void SetValueI( const wxArrayInt& arr ); // I stands for internal + void GenerateValueAsString(); + + // Returns translation of values into string indices. + wxArrayInt GetValueAsIndices() const; + + wxPGChoices m_choices; // Holds strings (any values given are ignored). + wxArrayInt m_value_wxArrayInt; // Actual value. + + wxString m_display; // Cache displayed text since generating it is relatively complicated. +}; + +#endif // wxUSE_CHOICEDLG + +// ----------------------------------------------------------------------- + +#if wxUSE_DATETIME && !defined(SWIG) + +class WXDLLIMPEXP_PG wxDatePropertyClass : public wxPGProperty +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxDatePropertyClass( const wxString& label, const wxString& name, const wxDateTime& value ); + virtual ~wxDatePropertyClass(); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int flags = 0 ) const; + virtual bool SetValueFromString( const wxString& text, int flags ); + + //WX_PG_DECLARE_EVENT_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() + + inline void SetFormat( const wxString& format ) + { + m_format = format; + } + + inline const wxString& GetFormat() const + { + return m_format; + } + + inline void SetDateValue( const wxDateTime& dt ) + { + m_valueDateTime = dt; + } + + inline const wxDateTime& GetDateValue() const + { + return m_valueDateTime; + } + + inline long GetDatePickerStyle() const + { + return m_dpStyle; + } + +protected: + wxDateTime m_valueDateTime; + wxString m_format; + long m_dpStyle; // DatePicker style + + static wxString ms_defaultDateFormat; + static wxString DetermineDefaultDateFormat( bool showCentury ); +}; + +#endif + +// ----------------------------------------------------------------------- + +//#endif // #ifndef SWIG + +#endif // _WX_PROPGRID_PROPDEV_H_ + +#endif // _WX_PROPGRID_ADVPROPS_H_ diff --git a/assdraw/libpropgrid/include/wx/propgrid/extras.h b/assdraw/libpropgrid/include/wx/propgrid/extras.h new file mode 100644 index 000000000..055628c39 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/extras.h @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: extras.h +// Purpose: wxPropertyGrid Extras Header +// Author: Jaakko Salli +// Modified by: +// Created: Mar-05-2006 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef WX_PROPGRID_EXTRAS_H +#define WX_PROPGRID_EXTRAS_H + +// +// In wxPython version this file will have additional property and +// editor control headers. +// + +#endif // WX_PROPGRID_EXTRAS_H diff --git a/assdraw/libpropgrid/include/wx/propgrid/manager.h b/assdraw/libpropgrid/include/wx/propgrid/manager.h new file mode 100644 index 000000000..154a54350 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/manager.h @@ -0,0 +1,1253 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: manager.h +// Purpose: wxPropertyGridManager +// Author: Jaakko Salli +// Modified by: +// Created: Jan-14-2005 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PROPGRID_MANAGER_H_ +#define _WX_PROPGRID_MANAGER_H_ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma interface "manager.cpp" +#endif + +#include + +// ----------------------------------------------------------------------- + +#ifndef SWIG +extern WXDLLIMPEXP_PG const wxChar *wxPropertyGridManagerNameStr; +#endif + +/** \class wxPropertyGridPage + \ingroup classes + \brief + Holder of property grid page information. You can subclass this and + give instance in wxPropertyGridManager::AddPage. It inherits from + wxEvtHandler and can be used to process events specific to this + page (id of events will still be same as manager's). If you don't + want to use it to process all events of the page, you need to + return false in the derived wxPropertyGridPage::IsHandlingAllEvents. + + Please note that wxPropertyGridPage lacks many non-const property + manipulation functions found in wxPropertyGridManager. Please use + parent manager (m_manager member variable) when needed. + +

Derived from

+ + wxPropertyGridState\n + wxPropertyContainerMethods\n + wxEvtHandler\n + wxObject\n + +

Include files

+ + + +

Event handling

+ + wxPropertyGridPage receives events emitted by its wxPropertyGridManager, but + only those events that are specific to that page. If wxPropertyGridPage::IsHandlingAllEvents + returns false, then unhandled events are sent to the manager's parent, as usual. +*/ +class WXDLLIMPEXP_PG wxPropertyGridPage : public wxEvtHandler, + public wxPropertyContainerMethods, + public wxPropertyGridState +{ + friend class wxPropertyGridManager; +#ifndef SWIG + DECLARE_CLASS(wxPropertyGridPage) +#endif +public: + + wxPropertyGridPage(); + virtual ~wxPropertyGridPage(); + + /** See wxPropertyGrid::AppendIn. */ + inline wxPGId AppendIn( wxPGId id, wxPGProperty* property ) + { + return DoInsert((wxPGPropertyWithChildren*)(wxPGProperty*)id,-1,property); + } + + /** See wxPropertyGrid::AppendIn. */ + inline wxPGId AppendIn( wxPGPropNameStr name, wxPGProperty* property ) + { + return DoInsert((wxPGPropertyWithChildren*)(wxPGProperty*)BaseGetPropertyByName(name),-1,property); + } + + /** Return pointer to contained property grid state. + */ + inline wxPropertyGridState* GetStatePtr() + { + return this; + } + + /** See wxPropertyGrid::Insert. */ + wxPGId Insert( wxPGId id, int index, wxPGProperty* property ); + + /** See wxPropertyGrid::Insert. */ + wxPGId Insert( wxPGPropNameStr name, int index, wxPGProperty* property ); + + /** Do any member initialization in this method. + \remarks + - Called every time the page is added into a manager. + - You can add properties to the page here. + */ + virtual void Init() {}; + + /** Return false here to indicate unhandled events should be + propagated to manager's parent, as normal. + */ + virtual bool IsHandlingAllEvents() const { return true; } + +#ifndef SWIG +protected: + + virtual void RefreshProperty( wxPGProperty* p ); + + //virtual bool ProcessEvent( wxEvent& event ); + + wxPropertyGridManager* m_manager; + wxString m_label; + int m_id; // toolbar index + +private: + bool m_isDefault; // is this base page object? + +private: + DECLARE_EVENT_TABLE() +#endif +}; + +// ----------------------------------------------------------------------- + + +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_BODY(NAME,AT1) \ +{ \ + wxPGProperty* p = wxPGIdToPtr(id); \ + wxASSERT_MSG(p,wxT("invalid property id")); \ + if ( p ) \ + { \ + wxPropertyGridState* pState = p->GetParentState(); \ + wxASSERT( pState != (wxPropertyGridState*) NULL ); \ + if ( pState == m_pPropGrid->m_pState ) m_pPropGrid->NAME(id,_av1_); \ + else pState->NAME(p,_av1_); \ + } \ +} + +// _P1 version doesn't have overloaded version that accepts name instead of id. +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1(NAME,AT1) \ +wxPG_IPAM_DECL void wxPropertyGridManager::NAME( wxPGId id, AT1 _av1_ ) \ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_BODY(NAME,AT1) + +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_INBODY(NAME,AT1) \ +wxPG_IPAM_DECL void NAME( wxPGId id, AT1 _av1_ ) \ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_BODY(NAME,AT1) + + +// This is for mirroring wxPropertyGrid methods with ease. +// Needs to be in here because of inlines. +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(NAME,AT1) \ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1(NAME,AT1) \ +wxPG_IPAM_DECL void wxPropertyGridManager::NAME( wxPGPropNameStr name, AT1 _av1_ ) \ +{ \ + wxPGId id = GetPropertyByNameI(name); \ + if ( !wxPGIdIsOk(id) ) return; \ + NAME(id,_av1_); \ +} + + +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(NAME,AT1) \ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_INBODY(NAME,AT1) \ +wxPG_IPAM_DECL void NAME( wxPGPropNameStr name, AT1 _av1_ ) \ +{ \ + NAME(GetPropertyByNameI(name),_av1_); \ +} + + +//class wxPropertyGridPageData; + +#define wxPG_IPAM_DECL inline + +/** \class wxPropertyGridManager + \ingroup classes + \brief + wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid, + which can optionally have toolbar for mode and page selection, help text box, + and a compactor button. + Use window flags to select which ones to include. + +

Derived from

+ + wxPropertyContainerMethods\n + wxWindow\n + wxEvtHandler\n + wxObject\n + +

Include files

+ + + +

Window styles

+ + @link wndflags Additional Window Styles@endlink + +

Event handling

+ + To process input from a propertygrid control, use these event handler macros to + direct input to member functions that take a wxPropertyGridEvent argument. + + + + + + + + + + + + + +
EVT_PG_SELECTED (id, func)Property is selected.
EVT_PG_CHANGED (id, func)Property value is modified.
EVT_PG_HIGHLIGHTED (id, func)Mouse moves over property. Event's property is NULL if hovered on area that is not a property.
EVT_PG_PAGE_CHANGED (id, func)User changed page in manager.
EVT_PG_ITEM_COLLAPSED (id, func)User collapses a property or category.
EVT_PG_ITEM_EXPANDED (id, func)User expands a property or category.
EVT_PG_COMPACT_MODE_ENTERED (id, func)User presses the compactor button, compact mode is entered.
EVT_PG_EXPANDED_MODE_ENTERED (id, func)User presses the compactor button, expanded mode is entered.
EVT_BUTTON (id, func)Button in a property editor was clicked. Only occurs if the property doesn't handle button clicks itself.
EVT_TEXT (id, func)wxTextCtrl based editor was updated (but property value was not yet modified)
+ + \sa @link wxPropertyGridEvent wxPropertyGridEvent@endlink + +*/ +// BM_MANAGER +class WXDLLIMPEXP_PG wxPropertyGridManager : public wxPanel, public wxPropertyContainerMethods +{ +#ifndef SWIG + DECLARE_CLASS(wxPropertyGridManager) +#endif + friend class wxPropertyGridPage; +public: + +#ifdef SWIG + %pythonAppend wxPropertyGridManager { + self._setOORInfo(self) + self.DoDefaultTypeMappings() + self.edited_objects = {} + self.DoDefaultValueTypeMappings() + if not hasattr(self.__class__,'_vt2setter'): + self.__class__._vt2setter = {} + } + %pythonAppend wxPropertyGridManager() "" + + wxPropertyGridManager( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPGMAN_DEFAULT_STYLE, + const wxChar* name = wxPyPropertyGridManagerNameStr ); + %RenameCtor(PrePropertyGridManager, wxPropertyGridManager()); + +#else + + /** Two step constructor. Call Create when this constructor is called to build up the + wxPropertyGridManager. + */ + wxPropertyGridManager(); + + /** The default constructor. The styles to be used are styles valid for + the wxWindow. + \sa @link wndflags Additional Window Styles@endlink + */ + wxPropertyGridManager( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPGMAN_DEFAULT_STYLE, + const wxChar* name = wxPropertyGridManagerNameStr ); + + /** Destructor */ + virtual ~wxPropertyGridManager(); + +#endif + + /** Creates new property page. Note that the first page is not created + automatically. + \param label + A label for the page. This may be shown as a toolbar tooltip etc. + \param bmp + Bitmap image for toolbar. If wxNullBitmap is used, then a built-in + default image is used. + \param pageObj + wxPropertyGridPage instance. Manager will take ownership of this object. + NULL indicates that a default page instance should be created. + \retval + Returns index to the page created. + \remarks + If toolbar is used, it is highly recommended that the pages are + added when the toolbar is not turned off using window style flag + switching. + */ + inline int AddPage( const wxString& label = wxEmptyString, + const wxBitmap& bmp = wxPG_NULL_BITMAP, + wxPropertyGridPage* pageObj = (wxPropertyGridPage*) NULL ) + { + return InsertPage(-1,label,bmp,pageObj); + } + + /** See wxPropertyGrid::Append. */ + inline wxPGId AppendCategory( const wxString& label, const wxString& name = wxPG_LABEL ) + { + wxCHECK( m_targetState, wxNullProperty ); + return m_targetState->Append( new wxPropertyCategoryClass(label,name) ); + } + + /** See wxPropertyGrid::Append. */ + inline wxPGId Append( wxPGProperty* property ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->Append(property); + } + + inline wxPGId Append( const wxString& label, const wxString& name, const wxString& value = wxEmptyString ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->Append( wxStringProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name, int value ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->Append( wxIntProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name, double value ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->Append( wxFloatProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name, bool value ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->Append( wxBoolProperty(label,name,value) ); + } + + /** See wxPropertyGrid::AppendIn. */ + inline wxPGId AppendIn( wxPGId id, wxPGProperty* property ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->DoInsert((wxPGPropertyWithChildren*)(wxPGProperty*)id,-1,property); + } + + /** See wxPropertyGrid::AppendIn. */ + inline wxPGId AppendIn( wxPGPropNameStr name, wxPGProperty* property ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxCHECK_MSG( m_selPage >= 0, wxNullProperty, wxT("You need to add a page before adding properties") ); + return m_targetState->DoInsert((wxPGPropertyWithChildren*)(wxPGProperty*)m_targetState->BaseGetPropertyByName(name),-1,property); + } + + /** Returns true if all property grid data changes have been committed. Usually + only returns false if value in active editor has been invalidated by a + wxValidator. + */ + inline bool CanClose() + { + return m_pPropGrid->CanClose(); + } + + void ClearModifiedStatus ( wxPGId id ); + + inline void ClearModifiedStatus () + { + m_pPropGrid->ClearModifiedStatus(); + } + + /** Clears the target page. + */ + /*inline void ClearTargetPage() + { + ClearPage(m_targetPage); + }*/ + + /** Deletes all properties on given page. + */ + void ClearPage( int page ); + + bool ClearPropertyValue( wxPGId id ); + bool ClearPropertyValue( wxPGPropNameStr name ); + + /** Collapses given item. Returns true if it was collapsable and previously expanded. */ + bool Collapse( wxPGId id ); + bool Collapse( wxPGPropNameStr name ); + + /** Collapses all items that can be collapsed. + \retval + Return false if failed (may fail if editor value cannot be validated). + */ + inline bool CollapseAll() + { + return m_targetState->ExpandAll(0); + } + + /** Compacts (arg is true) or expands the propertygrid (i.e. low priority + items are already hidden or shown). + */ + bool Compact( bool compact ); + + /** Two step creation. Whenever the control is created without any parameters, + use Create to actually create it. Don't access the control's public methods + before this is called. + \sa @link wndflags Additional Window Styles@endlink + */ + bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPGMAN_DEFAULT_STYLE, + const wxChar* name = wxPropertyGridManagerNameStr ); + + /** Disables a property. */ + inline bool DisableProperty( wxPGId id ) { return EnableProperty (id,false); } + + /** Disables a property. */ + inline bool DisableProperty( wxPGPropNameStr name ) { return EnableProperty (name,false); } + + /** Enables or disables (shows/hides) categories according to parameter enable. + WARNING: Not tested properly, use at your own risk. + */ + inline bool EnableCategories( bool enable ) + { + long fl = m_windowStyle | wxPG_HIDE_CATEGORIES; + if ( enable ) fl = m_windowStyle & ~(wxPG_HIDE_CATEGORIES); + SetWindowStyleFlag(m_windowStyle); + return true; + } + + /** Enables or disables a property on target page. */ + bool EnableProperty( wxPGId id, bool enable = true ); + bool EnableProperty( wxPGPropNameStr name, bool enable = true ); + + /** Selects page, scrolls and/or expands items to ensure that the + given item is visible. Returns true if something was actually done. + */ + bool EnsureVisible( wxPGId id ); + + /** Selects page, scrolls and/or expands items to ensure that the + given item is visible. Returns true if something was actually done. + */ + inline bool EnsureVisible( wxPGPropNameStr name ) + { + return EnsureVisible(GetPropertyByNameI(name)); + } + + /** Expands given item. Returns true if it was expandable and previously collapsed. */ + bool Expand( wxPGId id ); + bool Expand( wxPGPropNameStr name ); + + /** Expands all parents on target page. + \retval + Return false if failed (may fail if editor value cannot be validated). + */ + bool ExpandAll() + { + return m_targetState->ExpandAll(1); + } + + /** Returns number of children of the root property of the selected page. */ + inline size_t GetChildrenCount() + { + return GetChildrenCount( wxPGIdGen(m_pPropGrid->m_pState->m_properties) ); + } + + /** Returns number of children of the root property of given page. */ + size_t GetChildrenCount( int pageIndex ); + + /** Returns number of children for the property. + + NB: Cannot be in container methods class due to name hiding. + */ + inline size_t GetChildrenCount( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(0) + return p->GetChildCount(); + } + + /** Returns number of children for the property. */ + inline size_t GetChildrenCount( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(0) + return p->GetChildCount(); + } + + /** Returns height of the description text box. */ + int GetDescBoxHeight() const; + + /** Returns id of first item (in target page), whether it is a category or a property. */ + inline wxPGId GetFirst() const + { + return m_targetState->GetFirst(); + } + + /** Returns id of first category (in target page). */ + inline wxPGId GetFirstCategory() const + { + return m_targetState->GetFirstCategory (); + } + + /** Returns id of first property that is not a category (from target page). */ + inline wxPGId GetFirstProperty() const + { + return m_targetState->GetFirstProperty(); + } + + /** Returns pointer to the contained wxPropertyGrid. This does not change + after wxPropertyGridManager has been created, so you can safely obtain + pointer once and use it for the entire lifetime of the instance. + */ + inline wxPropertyGrid* GetGrid() + { + wxASSERT(m_pPropGrid); + return m_pPropGrid; + }; + + /** Returns id of last child of given property. + \remarks + Returns even sub-properties. + */ + inline wxPGId GetLastChild( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) p; + if ( !pwc->GetParentingType() || !pwc->GetCount() ) return wxNullProperty; + return wxPGIdGen(pwc->Last()); + } + inline wxPGId GetLastChild( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return GetLastChild( wxPGIdGen(p) ); + } + + /** Returns id of next category after a given property (which does not have to be category). */ + inline wxPGId GetNextCategory( wxPGId id ) const + { + wxCHECK( m_targetState, wxNullProperty ); + return m_targetState->GetNextCategory(id); + } + + /** Returns id of next property (from target page). This does not iterate + to sub-properties or categories. + */ + inline wxPGId GetNextProperty( wxPGId id ) const + { + wxCHECK( m_targetState, wxNullProperty ); + return m_targetState->GetNextProperty(id); + } + + /** Returns page object for given page index. + */ + inline wxPropertyGridPage* GetPage( unsigned int ind ) const + { + return (wxPropertyGridPage*)m_arrPages.Item(ind); + } + + /** Returns index for a page name. If no match is found, wxNOT_FOUND is returned. */ + int GetPageByName( const wxChar* name ) const; + + /** Returns index for a relevant propertygrid state. If no match is found, + wxNOT_FOUND is returned. + */ + int GetPageByState( wxPropertyGridState* pstate ) const; + + /** Returns number of managed pages. */ + size_t GetPageCount() const; + + /** Returns name of given page. */ + const wxString& GetPageName( int index ) const; + + /** Returns "root property" of the given page. It does not have name, etc. + and it is not visible. It is only useful for accessing its children. + */ + wxPGId GetPageRoot( int index ) const; + + /** Returns id of previous property (in target page). */ + inline wxPGId GetPrevProperty( wxPGId id ) const + { + return m_targetState->GetPrevProperty(id); + } + + /** Returns id of previous item under the same parent. */ + inline wxPGId GetPrevSibling( wxPGId id ) + { + return wxPropertyGridState::GetPrevSibling(id); + } + inline wxPGId GetPrevSibling( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return wxPropertyGridState::GetPrevSibling(wxPGIdGen(p)); + } + + /** Returns id of property with given label (case-sensitive). If there is no + property with such label, returned property id is invalid ( i.e. it will return + false with IsOk method). If there are multiple properties with identical name, + most recent added is returned. + */ + wxPGId GetPropertyByLabel( const wxString& name, + wxPropertyGridState** ppState = (wxPropertyGridState**)NULL ) const; + + /** Returns id of property's nearest parent category. If no category + found, returns invalid wxPGId. + */ + inline wxPGId GetPropertyCategory( wxPGId id ) const + { + return m_pPropGrid->GetPropertyCategory(id); + } + wxPGId GetPropertyCategory( wxPGPropNameStr name ) const + { + return m_pPropGrid->GetPropertyCategory(name); + } + + /** Returns cell background colour of a property. */ + inline wxColour GetPropertyColour( wxPGId id ) const + { + return m_pPropGrid->GetPropertyColour(id); + } + inline wxColour GetPropertyColour( wxPGPropNameStr name ) const + { + return m_pPropGrid->GetPropertyColour(name); + } + + /** Returns cell text colour of a property. */ + inline wxColour GetPropertyTextColour( wxPGId id ) const + { + return m_pPropGrid->GetPropertyTextColour(id); + } + inline wxColour GetPropertyTextColour( wxPGPropNameStr name ) const + { + return m_pPropGrid->GetPropertyTextColour(name); + } + + /** Returns a wxVariant list containing wxVariant versions of all + property values. Order is not guaranteed, but generally it should + match the visible order in the grid. + \param flags + Use wxKEEP_STRUCTURE to retain category structure; each sub + category will be its own wxVariantList of wxVariant. + \remarks + This works on the target page (*not* the selected page). + */ +#ifndef SWIG + wxVariant GetPropertyValues( const wxString& listname = wxEmptyString, + wxPGId baseparent = wxNullProperty, long flags = 0 ) const + { + return m_targetState->GetPropertyValues(listname,baseparent,flags); + } +#endif + + /** Returns "root property" of the target page. It does not have name, etc. + and it is not visible. It is only useful for accessing its children. + */ + wxPGId GetRoot() const { return wxPGIdGen(m_targetState->m_properties); } + + /** Returns index to currently selected page. */ + inline int GetSelectedPage() const { return m_selPage; } + + /** Shortcut for GetGrid()->GetSelection(). */ + inline wxPGId GetSelectedProperty() const + { + return m_pPropGrid->GetSelection(); + } + + /** Synonyme for GetSelectedPage. */ + inline int GetSelection() const { return m_selPage; } + + /** Returns index of page that is target for insert operations etc. */ + inline int GetTargetPage() const { return m_targetPage; } + + /** Returns a pointer to the toolbar currently associated with the + wxPropertyGridManager (if any). */ + inline wxToolBar* GetToolBar() const { return m_pToolbar; } + + inline void InitAllTypeHandlers() + { + wxPropertyGrid::InitAllTypeHandlers(); + } + + /** See wxPropertyGrid::Insert. */ + inline wxPGId Insert( wxPGId id, int index, wxPGProperty* property ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxPGId res_id = m_targetState->DoInsert((wxPGPropertyWithChildren*)wxPGIdToPtr(id),index,property); + if ( m_targetState == m_pPropGrid->m_pState ) + m_pPropGrid->DrawItems ( property, (wxPGProperty*) NULL ); + return res_id; + } + + /** See wxPropertyGrid::Insert. */ + inline wxPGId Insert( wxPGPropNameStr name, int index, wxPGProperty* property ) + { + wxCHECK( m_targetState, wxNullProperty ); + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + wxPGId res_id = m_targetState->DoInsert((wxPGPropertyWithChildren*)p,index,property); + if ( m_targetState == m_pPropGrid->m_pState ) + m_pPropGrid->DrawItems( property, (wxPGProperty*) NULL ); + return res_id; + } + + /** Creates new property page. Note that the first page is not created + automatically. + \param index + Add to this position. -1 will add as the last item. + \param label + A label for the page. This may be shown as a toolbar tooltip etc. + \param bmp + Bitmap image for toolbar. If wxNullBitmap is used, then a built-in + default image is used. + \param pageObj + wxPropertyGridPage instance. Manager will take ownership of this object. + If NULL, default page object is constructed. + \retval + Returns index to the page created. + */ + virtual int InsertPage( int index, const wxString& label, const wxBitmap& bmp = wxNullBitmap, + wxPropertyGridPage* pageObj = (wxPropertyGridPage*) NULL ); + + /** Returns true if any property on any page has been modified by the user. */ + bool IsAnyModified() const; + + /** Returns true if updating is frozen (ie. Freeze() called but not yet Thaw() ). */ + inline bool IsFrozen() const { return (m_pPropGrid->m_frozen>0)?true:false; } + + /** Returns true if any property on given page has been modified by the user. */ + bool IsPageModified( size_t index ) const; + + /** Returns true if property is a category. + NB: SHOULD BE IN METHODS CLASS. + */ +/* + inline bool IsPropertyCategory( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return (p->GetParentingType()>0)?true:false; + } + inline bool IsPropertyCategory( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return (p->GetParentingType()>0)?true:false; + } +*/ + + /** Disables item's textctrl if other way of editing is available. */ + void LimitPropertyEditing( wxPGId id, bool limit = true ); + void LimitPropertyEditing( wxPGPropNameStr name, bool limit = true ); + + virtual void Refresh( bool eraseBackground = true, + const wxRect* rect = (const wxRect*) NULL ); + + /** Removes a page. + \retval + Returns false if it was not possible to remove page in question. + */ + virtual bool RemovePage( int page ); + + /** Select and displays a given page. Also makes it target page for + insert operations etc. + \param index + Index of page being seleced. Can be -1 to select nothing. + */ + void SelectPage( int index ); + + /** Select and displays a given page. */ + inline void SelectPage( const wxChar* name ) + { + SelectPage( GetPageByName(name) ); + } + + /** Select a property. */ + inline bool SelectProperty( wxPGId id, bool focus = false ) + { + return wxPGIdToPtr(id)->GetParentState()->DoSelectProperty(id,focus); + } + inline bool SelectProperty( wxPGPropNameStr name, bool focus = false ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return p->GetParentState()->DoSelectProperty(p,focus); + } + + /** Sets label and text in description box. + */ + void SetDescription( const wxString& label, const wxString& content ); + + /** Sets text colour of a category caption (but not it's children). + */ + inline void SetCaptionTextColour( wxPGId id, const wxColour& col ) + { + m_pPropGrid->SetCaptionTextColour( id, col ); + } + inline void SetCaptionTextColour( wxPGPropNameStr name, const wxColour& col ) + { + m_pPropGrid->SetCaptionTextColour( name, col ); + } + + /** Sets the current category - Append will add non-categories under this one. + */ + inline void SetCurrentCategory( wxPGId id ) + { + wxPropertyCategoryClass* pc = (wxPropertyCategoryClass*)wxPGIdToPtr(id); +#ifdef __WXDEBUG__ + if ( pc ) wxASSERT( pc->GetParentingType() > 0 ); +#endif + m_targetState->m_currentCategory = pc; + } + + /** Sets the current category - Append will add non-categories under this one. + */ + inline void SetCurrentCategory( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetCurrentCategory(wxPGIdGen(p)); + } + + /** Sets y coordinate of the description box splitter. */ + void SetDescBoxHeight( int ht, bool refresh = true ); + + /** All properties added/inserted will have given priority by default. + \param + priority can be wxPG_HIGH (default) or wxPG_LOW. + */ + inline void SetDefaultPriority( int priority ) + { + m_pPropGrid->SetDefaultPriority(priority); + } + + /** Same as SetDefaultPriority(wxPG_HIGH). */ + inline void ResetDefaultPriority() + { + m_pPropGrid->ResetDefaultPriority(); + } + + /** Sets property attribute for all applicapple properties. + Be sure to use this method after all properties have been + added to the grid. + */ + void SetPropertyAttributeAll( int attrid, wxVariant value ); + + /** Sets label of a property. + */ + void SetPropertyLabel( wxPGId id, const wxString& newlabel ); + void SetPropertyLabel( wxPGPropNameStr name, const wxString& newlabel ); + + /** Sets background colour of property and all its children. Colours of + captions are not affected. Background brush cache is optimized for often + set colours to be set last. + + NOTE: This function is deprecated. Use SetPropertyBackgroundColour. + */ + inline void SetPropertyColour( wxPGId id, const wxColour& col ) + { + m_pPropGrid->SetPropertyBackgroundColour( id, col ); + } + inline void SetPropertyColour( wxPGPropNameStr name, const wxColour& col ) + { + m_pPropGrid->SetPropertyBackgroundColour( name, col ); + } + + /** Sets background colour of property and all its children. Colours of + captions are not affected. Background brush cache is optimized for often + set colours to be set last. + */ + inline void SetPropertyBackgroundColour( wxPGId id, const wxColour& col ) + { + m_pPropGrid->SetPropertyBackgroundColour( id, col ); + } + inline void SetPropertyBackgroundColour( wxPGPropNameStr name, const wxColour& col ) + { + m_pPropGrid->SetPropertyBackgroundColour( name, col ); + } + + /** Sets text colour of property and all its children. + */ + inline void SetPropertyTextColour( wxPGId id, const wxColour& col ) + { + m_pPropGrid->SetPropertyTextColour( id, col ); + } + inline void SetPropertyTextColour( wxPGPropNameStr name, const wxColour& col ) + { + m_pPropGrid->SetPropertyTextColour( name, col ); + } + + /** Sets background and text colour of property and all its children to the default. */ + inline void SetPropertyColourToDefault( wxPGId id ) + { + m_pPropGrid->SetPropertyColourToDefault(id); + } + inline void SetPropertyColourToDefault ( wxPGPropNameStr name ) + { + m_pPropGrid->SetPropertyColourToDefault(name); + } + + /** Sets property value. + \remarks + Actual name of this method is SetPropertyValue. It may be shown incorrectly + due to limitations in Doxygen C preprocessor. */ + void SetPropertyValueLong( wxPGId id, long value ); +#ifndef __WXPYTHON__ + void SetPropertyValue( wxPGId id, int value ); +#endif + void SetPropertyValueDouble( wxPGId id, double value ); + void SetPropertyValueBool( wxPGId id, bool value ); + void SetPropertyValueString( wxPGId id, const wxString& value ); + void SetPropertyValueArrstr2( wxPGId id, const wxArrayString& value ); + void SetPropertyValueWxObjectPtr( wxPGId id, wxObject* value ); +#ifndef __WXPYTHON__ + void SetPropertyValue( wxPGId id, void* value ); + void SetPropertyValue( wxPGId id, wxVariant& value ); +#endif + + void SetPropertyValueLong( wxPGPropNameStr name, long value ); +#ifndef __WXPYTHON__ + void SetPropertyValue( wxPGPropNameStr name, int value ); +#endif + void SetPropertyValueDouble( wxPGPropNameStr name, double value ); + void SetPropertyValueBool( wxPGPropNameStr name, bool value ); + void SetPropertyValueString( wxPGPropNameStr name, const wxString& value ); + void SetPropertyValueWxObjectPtr( wxPGPropNameStr name, wxObject* value ); +#ifndef __WXPYTHON__ + void SetPropertyValue( wxPGPropNameStr name, void* value ); + void SetPropertyValue( wxPGPropNameStr name, wxVariant& value ); + void SetPropertyValueArrstr2( wxPGPropNameStr name, const wxArrayString& value ); + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValueArrint2,const wxArrayInt&) +#else + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1_INBODY(SetPropertyValueArrint2,const wxArrayInt&) +#endif +#if wxUSE_DATETIME + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValueDatetime,wxDateTime) +#endif + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValuePoint,const wxPoint&) + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValueSize,const wxSize&) + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValueLongLong,const wxLongLong&) + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValueULongLong,const wxULongLong&) +#ifdef __WXPYTHON__ + wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_INBODY(SetPropertyValuePyObject,PyObject*) +#endif + +#ifndef __WXPYTHON__ + inline void SetPropertyValue( wxPGId id, wxObject& value ) + { + SetPropertyValue(id,&value); + } + + inline void SetPropertyValue( wxPGPropNameStr name, wxObject& value ) + { + SetPropertyValue(name,&value); + } + + inline void SetPropertyValue( wxPGId id, const wxChar* value ) + { + SetPropertyValue(id,wxString(value)); + } + inline void SetPropertyValue( wxPGPropNameStr name, const wxChar* value ) + { + SetPropertyValue(name,wxString(value)); + } + + /** Sets various property values from a list of wxVariants. If property with + name is missing from the grid, new property is created under given default + category (or root if omitted). Works on target page. + */ + void SetPropertyValues( const wxVariantList& list, wxPGId defaultCategory ) + { + m_targetState->SetPropertyValues(list,defaultCategory); + } + + inline void SetPropertyValues( const wxVariant& list, wxPGId defaultCategory ) + { + SetPropertyValues(list.GetList(),defaultCategory); + } + inline void SetPropertyValues( const wxVariantList& list, const wxString& defaultCategory = wxEmptyString ) + { + SetPropertyValues(list,GetPropertyByName(defaultCategory)); + } + inline void SetPropertyValues( const wxVariant& list, const wxString& defaultCategory = wxEmptyString ) + { + SetPropertyValues(list.GetList(),GetPropertyByName(defaultCategory)); + } +#endif + + /** Sets property's value to unspecified. If it has children (it may be category), + then the same thing is done to them. + */ +#ifdef wxPG_COMPATIBILITY_1_0_0 + void SetPropertyValueUnspecified( wxPGId id ); + void SetPropertyValueUnspecified( wxPGPropNameStr name ); +#else + void SetPropertyUnspecified( wxPGId id ); + void SetPropertyUnspecified( wxPGPropNameStr name ); +#endif + + /** Moves splitter as left as possible, while still allowing all + labels to be shown in full. + \param subProps + If false, will still allow sub-properties (ie. properties which + parent is not root or category) to be cropped. + \param allPages + If true, takes labels on all pages into account. + */ + void SetSplitterLeft( bool subProps = false, bool allPages = true ); + + inline void SetSplitterPosition( int newx, bool refresh = true ) + { + m_pPropGrid->SetSplitterPosition(newx,refresh); + } + + /** Synonyme for SelectPage(name). */ + inline void SetStringSelection( const wxChar* name ) + { + SelectPage( GetPageByName(name) ); + } + + /** Sets page to which append, insert, etc. will add items. + Every time a page is changed, target page is automatically + switched to that. + */ + void SetTargetPage( int index ); + + /** Sets page to which append, insert, etc. will add items. + Every time a page is changed, target page is automatically + switched to that. + */ + inline void SetTargetPage( const wxChar* name ) + { + SetTargetPage( GetPageByName(name) ); + } + + /** Sorts all items at all levels of the target page (except sub-properties). */ + inline void Sort() + { + m_pPropGrid->Sort(wxPGIdGen(m_targetState->m_properties)); + } + + /** Sorts children of a category. + */ + inline void Sort( wxPGId id ) + { + m_pPropGrid->Sort(id); + } + + /** Sorts children of a category. + */ + inline void Sort( wxPGPropNameStr name ) + { + m_pPropGrid->Sort( GetPropertyByNameI(name) ); + } + + /** Deselect current selection, if any (from current page). + \retval + false if editor could not be closed. + */ + inline bool ClearSelection() + { + return m_pPropGrid->ClearSelection(); + } + +#ifdef SWIG + %pythoncode { + def GetValuesFromPage(self,page,dict_=None,as_strings=False): + "Same as GetValues, but returns values from specific page only." + "" + "For argument descriptions, see GetValues." + + if dict_ is None: + dict_ = {} + elif hasattr(dict_,'__dict__'): + dict_ = dict_.__dict__ + + if not as_strings: + getter = self.GetPropertyValue + else: + getter = self.GetPropertyValueAsString + + root = self.GetPageRoot(page) + self._GetValues(root,self.GetFirstChild(root),dict_,getter) + + return dict_ + + + def GetValues(self,dict_=None,as_strings=False): + "Returns values in the grid." + "" + "dict_: if not given, then a new one is created. dict_ can be" + " object as well, in which case it's __dict__ is used." + "as_strings: if True, then string representations of values" + " are fetched instead of native types. Useful for config and such." + "" + "Return value: dictionary with values. It is always a dictionary," + "so if dict_ was object with __dict__ attribute, then that attribute" + "is returned." + + if dict_ is None: + dict_ = {} + elif hasattr(dict_,'__dict__'): + dict_ = dict_.__dict__ + + if not as_strings: + getter = self.GetPropertyValue + else: + getter = self.GetPropertyValueAsString + + for page in range(0,self.GetPageCount()): + root = self.GetPageRoot(page) + self._GetValues(root,self.GetFirstChild(root),dict_,getter) + + return dict_ + + GetPropertyValues = GetValues + + } +#endif + +protected: + + // + // Subclassing helpers + // + + /** Creates property grid for the manager. Override to use subclassed + wxPropertyGrid. + */ + virtual wxPropertyGrid* CreatePropertyGrid() const; + +public: + +#ifndef DOXYGEN + + // + // Overridden functions - no documentation required. + // + + virtual wxSize DoGetBestSize() const; + void SetId( wxWindowID winid ); + + virtual void Freeze(); + virtual void Thaw(); + virtual void SetExtraStyle ( long exStyle ); + virtual bool SetFont ( const wxFont& font ); + virtual void SetWindowStyleFlag ( long style ); + +#ifndef SWIG + + // + // Event handlers + // + void OnMouseMove( wxMouseEvent &event ); + void OnMouseClick( wxMouseEvent &event ); + void OnMouseUp( wxMouseEvent &event ); + void OnMouseEntry( wxMouseEvent &event ); + + void OnPaint( wxPaintEvent &event ); + + void OnToolbarClick( wxCommandEvent &event ); + void OnResize( wxSizeEvent& event ); + void OnCompactorClick( wxCommandEvent& event ); + void OnPropertyGridSelect( wxPropertyGridEvent& event ); + +protected: + + wxPropertyGrid* m_pPropGrid; + + wxArrayPtrVoid m_arrPages; + +#if wxUSE_TOOLBAR + wxToolBar* m_pToolbar; +#endif + wxStaticText* m_pTxtHelpCaption; + wxStaticText* m_pTxtHelpContent; + wxButton* m_pButCompactor; + + wxPropertyGridState* m_targetState; + + wxPropertyGridPage* m_emptyPage; + + long m_iFlags; + + // Selected page index. + int m_selPage; + + int m_width; + + int m_height; + + int m_extraHeight; + + int m_splitterY; + + int m_splitterHeight; + + int m_nextTbInd; + + int m_dragOffset; + + wxCursor m_cursorSizeNS; + + int m_nextDescBoxSize; + + int m_targetPage; + + unsigned char m_dragStatus; + + unsigned char m_onSplitter; + + + + virtual wxPGId DoGetPropertyByName( wxPGPropNameStr name ) const; + + /** Select and displays a given page. */ + virtual bool DoSelectPage( int index ); + + virtual void RefreshProperty( wxPGProperty* p ); + + // Sets some members to defaults. + void Init1(); + + // Initializes some members. + void Init2( int style ); + +/*#ifdef __WXMSW__ + virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; +#endif*/ + + /** Recalculates new positions for components, according to the + given size. + */ + void RecalculatePositions( int width, int height ); + + /** (Re)creates/destroys controls, according to the window style bits. */ + void RecreateControls(); + + void RefreshHelpBox( int new_splittery, int new_width, int new_height ); + + void RepaintSplitter( wxDC& dc, int new_splittery, int new_width, int new_height, bool desc_too ); + + void SetDescribedProperty( wxPGProperty* p ); + + virtual bool ProcessEvent( wxEvent& event ); + +private: + DECLARE_EVENT_TABLE() +#endif // #ifndef SWIG +#endif // #ifndef DOXYGEN +}; + +// ----------------------------------------------------------------------- + +#ifndef __wxPG_SOURCE_FILE__ + #undef wxPG_IPAM_DECL + #undef wxPG_IMPLEMENT_PGMAN_METHOD_NORET1 +#endif + +// ----------------------------------------------------------------------- + +#endif // _WX_PROPGRID_MANAGER_H_ diff --git a/assdraw/libpropgrid/include/wx/propgrid/odcombo.h b/assdraw/libpropgrid/include/wx/propgrid/odcombo.h new file mode 100644 index 000000000..98af218aa --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/odcombo.h @@ -0,0 +1,1100 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: odcombo.h +// Purpose: wxPGOwnerDrawnComboBox and related classes interface +// Author: Jaakko Salli +// Modified by: +// Created: Jan-25-2005 +// RCS-ID: $Id: +// Copyright: (c) 2005 Jaakko Salli +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PROPGRID_ODCOMBO_H_ +#define _WX_PROPGRID_ODCOMBO_H_ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma interface "odcombo.h" +#endif + + +#include "wx/renderer.h" + + +// Item counts in GUI components were changed in 2.7.0 +#if wxCHECK_VERSION(2,7,0) + #define wxODCCount unsigned int + #define wxODCIndex unsigned int +#else + #define wxODCCount int + #define wxODCIndex int +#endif + + +// wxRect: Inside(<=2.7.0) or Contains(>2.7.0)? +#if !wxCHECK_VERSION(2,7,1) + #define wxPGRectContains Inside +#else + #define wxPGRectContains Contains +#endif + +class WXDLLEXPORT wxTextCtrl; +class WXDLLEXPORT wxButton; + +#ifdef WXMAKINGLIB_PROPGRID + #define WXDLLEXPORT_PGODC +#elif defined(WXMAKINGDLL_PROPGRID) + #define WXDLLEXPORT_PGODC WXEXPORT +#elif defined(WXUSINGDLL) + #define WXDLLEXPORT_PGODC WXIMPORT +#else // not making nor using DLL + #define WXDLLEXPORT_PGODC +#endif + +class WXDLLEXPORT_PGODC wxPGComboPopup; +class WXDLLEXPORT_PGODC wxPGComboControlBase; +class WXDLLEXPORT_PGODC wxPGOwnerDrawnComboBox; + + +// ---------------------------------------------------------------------------- + + +// New window styles for wxPGComboControlBase + +enum +{ + // Double-clicking causes value to cycle (ie. call to popup's CycleValue method). + wxPGCC_DCLICK_CYCLES = 0x0100, + + // Use keyboard behaviour alternate to platform default: + // Up an down keys will show popup instead of cycling value. + wxPGCC_ALT_KEYS = 0x0200, +}; + +#define wxPGCC_PROCESS_ENTER 0 + +// ---------------------------------------------------------------------------- +// wxPGComboControlBase: a base class for generic control that looks like +// a wxComboBox but allows completely custom popup (in addition to other +// customizations). +// ---------------------------------------------------------------------------- + +// wxComboControl internal flags +enum +{ + // First those that can be passed to Customize. + // It is Windows style for all flags to be clear. + + // Button is preferred outside the border (GTK style) + wxPGCC_BUTTON_OUTSIDE_BORDER = 0x0001, + // Show popup on mouse up instead of mouse down (which is the Windows style) + wxPGCC_POPUP_ON_MOUSE_UP = 0x0002, + // All text is not automatically selected on click + wxPGCC_NO_TEXT_AUTO_SELECT = 0x0004, + // Drop-button stays depressed while the popup is open + wxPGCC_BUTTON_STAYS_DOWN = 0x0008, + // Button covers the entire control + wxPGCC_FULL_BUTTON = 0x0010, + + // Internal use: signals creation is complete + wxPGCC_IFLAG_CREATED = 0x0100, + // Internal use: really put button outside + wxPGCC_IFLAG_BUTTON_OUTSIDE = 0x0200, + // Internal use: SetTextIndent has been called + wxPGCC_IFLAG_INDENT_SET = 0x0400, + // Internal use: Set wxTAB_TRAVERSAL to parent when popup is dismissed + wxPGCC_IFLAG_PARENT_TAB_TRAVERSAL = 0x0800, + // Button has bitmap or has non-standard size + wxPGCC_IFLAG_HAS_NONSTANDARD_BUTTON = 0x1000 +}; + + +// Flags used by PreprocessMouseEvent and HandleButtonMouseEvent +enum +{ + wxPGCC_MF_ON_BUTTON = 0x0001, // cursor is on dropbutton area +}; + + +// Namespace for wxComboControl feature flags +struct wxPGComboControlFeatures +{ + enum + { + MovableButton = 0x0001, // Button can be on either side of control + BitmapButton = 0x0002, // Button may be replace with bitmap + ButtonSpacing = 0x0004, // Non-bitmap button can have spacing from + // the edge of the control + TextIndent = 0x0008, // SetTextIndent can be used + PaintControl = 0x0010, // Combo control itself can be custom painted + PaintWritable = 0x0020, // A variable-width area in front of writable + // combo control's textctrl can be custom + // painted + Borderless = 0x0040, // wxNO_BORDER window style works + + // There is no feature flags for... + // PushButtonBitmapBackground - if its in renderer native, then it should be + // not an issue to have it automatically under the bitmap. + + All = MovableButton|BitmapButton| + ButtonSpacing|TextIndent| + PaintControl|PaintWritable| + Borderless, + }; +}; + + +class wxPGComboPopupWindow; + + +class WXDLLEXPORT_PGODC wxPGComboControlBase : public wxControl +{ + friend class wxPGComboPopup; + friend class wxPGComboPopupWindow; +public: + // ctors and such + wxPGComboControlBase() : wxControl() { Init(); } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name); + + virtual ~wxPGComboControlBase(); + + virtual bool Destroy(); + + // show/hide popup window + virtual void ShowPopup(); + virtual void HidePopup(); + + // Override for totally custom combo action + virtual void OnButtonClick(); + + // return true if the popup is currently shown + inline bool IsPopupShown() const { return m_isPopupShown; } + + // set interface class instance derived from wxPGComboPopup + void SetPopup( wxPGComboPopup* iface ); + + // get interface class instance derived from wxPGComboPopup + wxPGComboPopup* GetPopup() const { return m_popupInterface; } + + // get the popup window containing the popup control + wxWindow *GetPopupWindow() const { return m_winPopup; } + + // get the popup control/panel in window + wxWindow *GetPopupControl() const { return m_popup; } + + // Get the text control which is part of the combobox. + inline wxTextCtrl *GetTextCtrl() const { return m_text; } + + // get the dropdown button which is part of the combobox + // note: its not necessarily a wxButton or wxBitmapButton + inline wxWindow *GetButton() const { return m_btn; } + + // forward these methods to all subcontrols + virtual bool Enable(bool enable = true); + virtual bool Show(bool show = true); + virtual bool SetFont(const wxFont& font); +#if wxUSE_TOOLTIPS + virtual void DoSetToolTip( wxToolTip *tip ); +#endif + + // wxTextCtrl methods - for readonly combo they should return + // without errors. + virtual wxString GetValue() const; + virtual void SetValue(const wxString& value); + virtual void Copy(); + virtual void Cut(); + virtual void Paste(); + virtual void SetInsertionPoint(long pos); + virtual void SetInsertionPointEnd(); + virtual long GetInsertionPoint() const; + virtual long GetLastPosition() const; + virtual void Replace(long from, long to, const wxString& value); + virtual void Remove(long from, long to); + virtual void SetSelection(long from, long to); + virtual void Undo(); + + // Returns the text field rectangle, including any image that is painted with it. + inline const wxRect& GetTextRect() const + { + return m_tcArea; + } + + // + // Popup customization methods + // + + // Sets minimum width of the popup. If wider than combo control, it will extend to the left. + // Remarks: + // * Value -1 indicates the default. + // * Custom popup may choose to ignore this (wxPGOwnerDrawnComboBox does not). + inline void SetPopupMinWidth( int width ) + { + m_widthMinPopup = width; + } + + // Sets preferred maximum height of the popup. + // Remarks: + // * Value -1 indicates the default. + // * Custom popup may choose to ignore this (wxPGOwnerDrawnComboBox does not). + inline void SetPopupMaxHeight( int height ) + { + m_heightPopup = height; + } + + // Extends popup size horizontally, relative to the edges of the combo control. + // Remarks: + // * Popup minimum width may override extLeft (ie. it has higher precedence). + // * Values 0 indicate default. + // * Custom popup may not take this fully into account (wxPGOwnerDrawnComboBox takes). + inline void SetPopupExtents( int extLeft, int extRight ) + { + m_extLeft = extLeft; + m_extRight = extRight; + } + + // Set width, in pixels, of custom paint area in writable combo. + // In read-only, used to indicate area that is not covered by the + // focus rectangle (which may or may not be drawn, depending on the + // popup type). + void SetCustomPaintWidth( int width ); + inline int GetCustomPaintWidth() const { return m_widthCustomPaint; } + + // Set position of dropdown button. + // width: 0 > for specific custom width, negative to adjust to smaller than default + // height: 0 > for specific custom height, negative to adjust to smaller than default + // side: wxLEFT or wxRIGHT, indicates on which side the button will be placed. + // spacingX: empty space on sides of the button. Default is 0. + // Remarks: + // There is no spacingY - the button will be centered vertically. + void SetButtonPosition( int width = 0, int height = 0, int side = wxRIGHT, + int spacingX = 0 /*, int spacingY = 0*/ ); + + + // + // Sets dropbutton to be drawn with custom bitmaps. + // + // bmpNormal: drawn when cursor is not on button + // blankButtonBg: Draw blank button background below the image. + // NOTE! This is only properly supported on platforms with appropriate + // method in wxRendererNative. + // bmpPressed: drawn when button is depressed + // bmpHover: drawn when cursor hovers on button. This is ignored on platforms + // that do not generally display hover differently. + // bmpDisabled: drawn when combobox is disabled. + void SetButtonBitmaps( const wxBitmap& bmpNormal, + bool blankButtonBg = false, + const wxBitmap& bmpPressed = wxNullBitmap, + const wxBitmap& bmpHover = wxNullBitmap, + const wxBitmap& bmpDisabled = wxNullBitmap ); + + // + // This will set the space in pixels between left edge of the control and the + // text, regardless whether control is read-only (ie. no wxTextCtrl) or not. + // Platform-specific default can be set with value-1. + // Remarks + // * This method may do nothing on some native implementations. + void SetTextIndent( int indent ); + + // Returns actual indentation in pixels. + inline wxCoord GetTextIndent() const + { + return m_absIndent; + } + + // + // Utilies needed by the popups or native implementations + // + + // Draws focus background (on combo control) in a way typical on platform. + // Unless you plan to paint your own focus indicator, you should always call this + // in your wxPGComboPopup::PaintComboControl implementation. + // In addition, it sets pen and text colour to what looks good and proper + // against the background. + // flags: wxRendererNative flags: wxCONTROL_ISSUBMENU: is drawing a list item instead of combo control + // wxCONTROL_SELECTED: list item is selected + // wxCONTROL_DISABLED: control/item is disabled + virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ); + + // Returns true if focused. Differs from FindFocus in that takes + // child controls into account. + bool IsFocused() const + { + const wxWindow* curFocus = FindFocus(); + if ( curFocus == this || (m_text && curFocus == m_text) ) + return true; + + return false; + } + + // Returns true if focus indicator should be drawn. + inline bool ShouldDrawFocus() const + { + const wxWindow* curFocus = FindFocus(); + return ( !m_isPopupShown && + (curFocus == this || (m_btn && curFocus == m_btn)) && + (m_windowStyle & wxCB_READONLY) ); + } + + // These methods return references to appropriate dropbutton bitmaps + inline const wxBitmap& GetBitmapNormal() const { return m_bmpNormal; } + inline const wxBitmap& GetBitmapPressed() const { return m_bmpPressed; } + inline const wxBitmap& GetBitmapHover() const { return m_bmpHover; } + inline const wxBitmap& GetBitmapDisabled() const { return m_bmpDisabled; } + + // Return internal flags + inline wxUint32 GetInternalFlags() const { return m_iFlags; } + + // Return true if Create has finished + inline bool IsCreated() const { return m_iFlags & wxPGCC_IFLAG_CREATED ? true : false; } + + // Popup may use these as callbacks to measure and draw list items. + // (wxPGOwnerDrawnComboBox uses these, obviously) + // item: -1 means item is the combo control itself + // flags: wxPGCC_PAINTING_CONTROL is set if painting to combo control instead of list + // return value: OnDrawListItem must return true if it did anything + virtual bool OnDrawListItem( wxDC& dc, const wxRect& rect, int item, int flags ); + + // Return item height, or -1 for text height (default) + virtual wxCoord OnMeasureListItem( int item ); + + // Return item width, or -1 for calculating from text extent (default) + virtual wxCoord OnMeasureListItemWidth( int item ); + + // Returns true if can and should send focus event to the main control from + // textctrl input handler. + inline bool ConsumingTextCtrlFocusEvent() + { + if ( m_skipTextCtrlFocusEvents == 0 ) + return true; + + m_skipTextCtrlFocusEvents--; + return false; + } + + // NOTE: + // I basicly needed to add callback methods into wxComboControlBase - otherwise it + // will not be easily possible to use wxPGVListBoxComboPopup from simultaneously existing + // wxComboControl and wxPGGenericComboControl (since some native implementations + // might not have all the features, I really would like to have this options). + +protected: + + // + // Override these for customization purposes + // + + // called from wxSizeEvent handler + virtual void OnResize() = 0; + + // Return native text identation (for pure text, not textctrl) + virtual wxCoord GetNativeTextIndent() const; + + // Called in syscolourchanged handler and base create + virtual void OnThemeChange(); + + // Creates wxTextCtrl. + // extraStyle: Extra style parameters + void CreateTextCtrl( int extraStyle, const wxValidator& validator ); + + // Installs standard input handler to combo + void InstallInputHandlers(); + + // Flags for DrawButton. + enum + { + Button_PaintBackground = 0x0001, // Paints control background below the button + Button_BitmapOnly = 0x0002 // Only paints the bitmap + }; + + // Draws dropbutton. Using wxRenderer or bitmaps, as appropriate. + // Flags are defined above. + void DrawButton( wxDC& dc, const wxRect& rect, int flags = Button_PaintBackground ); + + // Call if cursor is on button area or mouse is captured for the button. + //bool HandleButtonMouseEvent( wxMouseEvent& event, bool isInside ); + bool HandleButtonMouseEvent( wxMouseEvent& event, int flags ); + + // Conversion to double-clicks and some basic filtering + // returns true if event was consumed or filtered (event type is also set to 0 in this case) + //bool PreprocessMouseEvent( wxMouseEvent& event, bool isOnButtonArea ); + bool PreprocessMouseEvent( wxMouseEvent& event, int flags ); + + // + // This will handle left_down and left_dclick events outside button in a Windows-like manner. + // If you need alternate behaviour, it is recommended you manipulate and filter events to it + // instead of building your own handling routine (for reference, on wxEVT_LEFT_DOWN it will + // toggle popup and on wxEVT_LEFT_DCLICK it will do the same or run the popup's dclick method, + // if defined - you should pass events of other types of it for common processing). + void HandleNormalMouseEvent( wxMouseEvent& event ); + + // Creates popup window, calls interface->Create(), etc + void CreatePopup(); + + // common code to be called on popup hide/dismiss + void OnPopupDismiss(); + + // Dispatches command event from the control + //void SendEvent( int evtType = wxEVT_COMMAND_COMBOBOX_SELECTED, int selection, ); + + // override the base class virtuals involved in geometry calculations + virtual void DoMoveWindow(int x, int y, int width, int height); + virtual wxSize DoGetBestSize() const; + + // Recalculates button and textctrl areas. Called when size or button setup change. + // btnWidth: default/calculated width of the dropbutton. 0 means unchanged, + // just recalculate. + void CalculateAreas( int btnWidth = 0 ); + + // Standard textctrl positioning routine. Just give it platform-dependant + // textctrl coordinate adjustment. + void PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust ); + + // event handlers + void OnSizeEvent(wxSizeEvent& event); + void OnFocusEvent(wxFocusEvent& event); + void OnKeyEvent(wxKeyEvent& event); + void OnTextCtrlEvent(wxCommandEvent& event); + void OnSysColourChanged(wxSysColourChangedEvent& event); + + // Set customization flags (directs how wxComboControlBase helpers behave) + void Customize( wxUint32 flags ) { m_iFlags |= flags; } + + // Dispatches size event and refreshes + void RecalcAndRefresh(); + + + // This is used when m_text is hidden (readonly). + wxString m_valueString; + + // the text control and button we show all the time + wxTextCtrl* m_text; + wxWindow* m_btn; + + // wxPopupWindow or similar containing the window managed by the interface. + wxWindow* m_winPopup; + + // the popup control/panel + wxWindow* m_popup; + + // popup interface + wxPGComboPopup* m_popupInterface; + + // this is input etc. handler the text control + wxEvtHandler* m_textEvtHandler; + + // this is for the top level window + wxEvtHandler* m_toplevEvtHandler; + + // this is for the control in popup + wxEvtHandler* m_popupExtraHandler; + + // needed for "instant" double-click handling + //wxLongLong m_timeLastMouseUp; + + // used to prevent immediate re-popupping incase closed popup + // by clicking on the combo control (needed because of inconsistent + // transient implementation across platforms). + wxLongLong m_timeCanAcceptClick; + + // how much popup should expand to the left/right of the control + wxCoord m_extLeft; + wxCoord m_extRight; + + // minimum popup width + wxCoord m_widthMinPopup; + + // preferred popup height + wxCoord m_heightPopup; + + // how much of writable combo is custom-paint by callback? + // also used to indicate area that is not covered by "blue" + // selection indicator. + wxCoord m_widthCustomPaint; + + // absolute text indentation, in pixels + wxCoord m_absIndent; + + // Width of the "fake" border + wxCoord m_widthCustomBorder; + + // The button and textctrl click/paint areas + wxRect m_tcArea; + wxRect m_btnArea; + + // current button state (uses renderer flags) + int m_btnState; + + // button position + int m_btnWid; + int m_btnHei; + int m_btnSide; + int m_btnSpacingX; + + // last default button width + int m_btnWidDefault; + + // custom dropbutton bitmaps + wxBitmap m_bmpNormal; + wxBitmap m_bmpPressed; + wxBitmap m_bmpHover; + wxBitmap m_bmpDisabled; + + // area used by the button + wxSize m_btnSize; + + // platform-dependant customization and other flags + wxUint32 m_iFlags; + + // draw blank button background under bitmap? + bool m_blankButtonBg; + + // is the popup window currenty shown? + bool m_isPopupShown; + + // TODO: Remove after real popup works ok. + unsigned char m_fakePopupUsage; + + wxByte m_skipTextCtrlFocusEvents; + +private: + void Init(); + + DECLARE_EVENT_TABLE() + + DECLARE_ABSTRACT_CLASS(wxPGComboControlBase) +}; + + + +class WXDLLEXPORT_PGODC wxPGGenericComboControl : public wxPGComboControlBase +{ +public: + // ctors and such + wxPGGenericComboControl() : wxPGComboControlBase() { Init(); } + + wxPGGenericComboControl(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + : wxPGComboControlBase() + { + Init(); + + (void)Create(parent, id, value, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + virtual ~wxPGGenericComboControl(); + + static int GetFeatures() { return wxPGComboControlFeatures::All; } + +protected: + + virtual void OnResize(); + + // event handlers + //void OnSizeEvent( wxSizeEvent& event ); + void OnPaintEvent( wxPaintEvent& event ); + void OnMouseEvent( wxMouseEvent& event ); + +private: + void Init(); + + DECLARE_EVENT_TABLE() + + DECLARE_DYNAMIC_CLASS(wxPGGenericComboControl) +}; + + + +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) + +class WXDLLEXPORT_PGODC wxPGComboControl : public wxPGComboControlBase +{ +public: + // ctors and such + wxPGComboControl() : wxPGComboControlBase() { Init(); } + + wxPGComboControl(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + : wxPGComboControlBase() + { + Init(); + + (void)Create(parent, id, value, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + virtual ~wxPGComboControl(); + + //virtual void DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ); + + static int GetFeatures() { return wxPGComboControlFeatures::All; } + +protected: + + // customization + virtual void OnResize(); + virtual wxCoord GetNativeTextIndent() const; + virtual void OnThemeChange(); + + // event handlers + //void OnSizeEvent( wxSizeEvent& event ); + void OnPaintEvent( wxPaintEvent& event ); + void OnMouseEvent( wxMouseEvent& event ); + +private: + void Init(); + + DECLARE_EVENT_TABLE() + + DECLARE_DYNAMIC_CLASS(wxPGComboControl) +}; + +#else + +class WXDLLEXPORT_PGODC wxPGComboControl : public wxPGGenericComboControl +{ +public: + // ctors and such + wxPGComboControl() : wxPGGenericComboControl() {} + + wxPGComboControl(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + : wxPGGenericComboControl() + { + (void)Create(parent, id, value, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + { + return wxPGGenericComboControl::Create(parent,id,value,pos,size,style,validator,name); + } + + virtual ~wxPGComboControl() {} + +protected: + +private: + DECLARE_DYNAMIC_CLASS(wxPGComboControl) +}; + + +#endif + + + +// ---------------------------------------------------------------------------- +// wxComboPopupInterface is the interface class that lies between +// the wxPGOwnerDrawnComboBox and its popup window. +// ---------------------------------------------------------------------------- + +// wxComboPopup internal flags +enum +{ + wxPGCP_IFLAG_CREATED = 0x0001, // Set by wxComboControlBase after Create is called +}; + +class WXDLLEXPORT_PGODC wxPGComboPopup +{ + friend class wxPGComboControlBase; +public: + wxPGComboPopup(wxPGComboControl *combo) + { + m_combo = combo; + m_iFlags = 0; + } + + virtual ~wxPGComboPopup(); + + // Create the popup child control. + // Return true for success. + virtual bool Create(wxWindow* parent) = 0; + + // We must have an associated control which is subclassed by the combobox. + virtual wxWindow *GetControl() = 0; + + // Called immediately after the popup is shown + virtual void OnPopup(); + + // Called when popup is dismissed + virtual void OnDismiss(); + + // Called just prior to displaying popup. + // Default implementation does nothing. + virtual void SetStringValue( const wxString& value ); + + // Gets displayed string representation of the value. + virtual wxString GetStringValue() const = 0; + + // This is called to custom paint in the combo control itself (ie. not the popup). + // Default implementation draws value as string. + virtual void PaintComboControl( wxDC& dc, const wxRect& rect ); + + // Receives key events from the parent wxComboControl. + // Events not handled should be skipped, as usual. + virtual void OnComboKeyEvent( wxKeyEvent& event ); + + // Implement if you need to support special action when user + // double-clicks on the parent wxComboControl. + virtual void OnComboDoubleClick(); + + // Return final size of popup. Called on every popup, just prior to OnShow. + // minWidth = preferred minimum width for window + // prefHeight = preferred height. Only applies if > 0, + // maxHeight = max height for window, as limited by screen size + // and should only be rounded down, if necessary. + virtual wxSize GetAdjustedSize( int minWidth, int prefHeight, int maxHeight ); + + // Return true if you want delay call to Create until the popup is shown + // for the first time. It is more efficient, but note that it is often + // more convenient to have the control created immediately. + // Default returns false. + virtual bool LazyCreate(); + + // + // Utilies + // + + // Hides the popup + void Dismiss(); + + // Returns true if Create has been called. + inline bool IsCreated() const + { + return (m_iFlags & wxPGCP_IFLAG_CREATED) ? true : false; + } + +protected: + wxPGComboControl* m_combo; + wxUint32 m_iFlags; +}; + + + + +// New window styles for wxPGOwnerDrawnComboBox + +enum +{ + // Causes double-clicking to cycle the item instead of showing + // the popup. Shift-pressed causes cycling direction to reverse. + //wxODCB_DOUBLE_CLICK_CYCLES = wxPGCC_SPECIAL_DOUBLE_CLICK, + + // if used, control itself is not custom paint using callback + // even if this is not used, writable combo is never custom paint + // until SetCustomPaintWidth is called + wxODCB_STD_CONTROL_PAINT = 0x0400 +}; + + +// +// Callback flags +// + +enum +{ + // when set, we are painting the selected item in control, + // not in the popup + wxPGCC_PAINTING_CONTROL = 0x0001 +}; + +// +// Callback arguments: +// pCb: combo box in question +// item: index of item drawn or measured +// dc: device context to draw on. NULL reference when measuring. +// rect: draw call: rectangle in device context to limit the drawing on. Use rect.x and rect.y +// as the origin. +// measure call: initially width and height are -1. You need to set rect.height to whatever +// is the height of the given item. +// flags: see above +/* +typedef void (wxEvtHandler::* wxComboPaintCallback)( wxPGComboControl* pCb, + int item, + wxDC& dc, + wxRect& rect, + int flags ); +*/ + + + +#include "wx/vlbox.h" + +// ---------------------------------------------------------------------------- +// wxPGVListBoxComboPopup is a wxVListBox customized to act as a popup control. +// +// Notes: +// wxOwnerDrawnComboBox uses this as its popup. However, it always derives +// from native wxComboControl. If you need to use this popup with +// wxPGGenericComboControl, then remember that vast majority of item manipulation +// functionality is implemented in the wxPGVListBoxComboPopup class itself. +// +// ---------------------------------------------------------------------------- + + +class wxPGVListBoxComboPopup : public wxVListBox, public wxPGComboPopup +{ + friend class wxPGOwnerDrawnComboBox; +public: + + // ctor and dtor + wxPGVListBoxComboPopup(wxPGComboControl* combo/*, wxComboPaintCallback callback*/); + virtual ~wxPGVListBoxComboPopup(); + + // required virtuals + virtual bool Create(wxWindow* parent); + virtual wxWindow *GetControl() { return this; } + virtual void SetStringValue( const wxString& value ); + virtual wxString GetStringValue() const; + + // more customization + virtual void OnPopup(); + virtual wxSize GetAdjustedSize( int minWidth, int prefHeight, int maxHeight ); + virtual void PaintComboControl( wxDC& dc, const wxRect& rect ); + virtual void OnComboKeyEvent( wxKeyEvent& event ); + virtual void OnComboDoubleClick(); + //virtual bool CycleValue( bool forward ); + //virtual bool OnComboDoubleClick(); + virtual bool LazyCreate(); + + // Item management + void SetSelection( int item ); + void Insert( const wxString& item, int pos ); + int Append(const wxString& item); + void Clear(); + void Delete( wxODCIndex item ); + void SetItemClientData(wxODCIndex n, void* clientData, wxClientDataType clientDataItemsType); + void *GetItemClientData(wxODCIndex n) const; + void SetString( int item, const wxString& str ); + wxString GetString( int item ) const; + wxODCCount GetCount() const; + int FindString(const wxString& s) const; + int GetSelection() const; + + void Populate( int n, const wxString choices[] ); + void ClearClientDatas(); + + // helpers + inline int GetItemAtPosition( const wxPoint& pos ) { return HitTest(pos); } + inline wxCoord GetTotalHeight() const { return EstimateTotalHeight(); } + inline wxCoord GetLineHeight(int line) const { return OnMeasureItem(line); } + +protected: + + // Called by OnComboDoubleClick and OnComboKeyEvent + bool HandleKey( int keycode, bool saturate ); + + // sends combobox select event from the parent combo control + void SendComboBoxEvent( int selection ); + void DismissWithEvent(); + + // Re-calculates width for given item + void CheckWidth( int pos ); + + virtual wxCoord OnGetRowHeight(size_t n) const { return OnMeasureItem(n); } + + // wxVListBox implementation + virtual void OnDrawItem(wxDC& dc, const wxRect& rect, size_t n) const; + virtual wxCoord OnMeasureItem(size_t n) const; + void OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const; + + // filter mouse move events happening outside the list box + // move selection with cursor + void OnMouseMove(wxMouseEvent& event); + void OnMouseWheel(wxMouseEvent& event); + void OnKey(wxKeyEvent& event); + void OnLeftClick(wxMouseEvent& event); + + wxArrayString m_strings; + wxArrayPtrVoid m_clientDatas; + wxArrayInt m_widths; // cached line widths + + wxString m_stringValue; + + wxFont m_font; + + int m_value; // selection + int m_itemHover; // on which item the cursor is + int m_widestWidth; // width of widest item thus far + int m_avgCharWidth; + int m_baseImageWidth; // how much per item drawn in addition to text + int m_itemHeight; // default item height (calculate from font size + // and used in the absence of callback) + wxClientDataType m_clientDataItemsType; + +private: + + // has the mouse been released on this control? + bool m_clicked; + + DECLARE_EVENT_TABLE() +}; + + +// ---------------------------------------------------------------------------- +// wxPGOwnerDrawnComboBox: a generic wxComboBox that allows custom paint items. +// +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT_PGODC wxPGOwnerDrawnComboBox : public wxPGComboControl, public wxItemContainer +{ + friend class wxPGComboPopupWindow; + friend class wxPGComboControlBase; +public: + + // ctors and such + wxPGOwnerDrawnComboBox() : wxPGComboControl() { Init(); } + + wxPGOwnerDrawnComboBox(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + int n, + const wxString choices[], + //wxComboPaintCallback callback, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + : wxPGComboControl() + { + Init(); + + (void)Create(parent, id, value, pos, size, n, choices, + /*callback,*/ style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + wxPGOwnerDrawnComboBox(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, + const wxString choices[] = (const wxString *) NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr); + + virtual ~wxPGOwnerDrawnComboBox(); + + // wxControlWithItems methods + virtual void Clear(); + virtual void Delete(wxODCIndex n); + virtual wxODCCount GetCount() const; + virtual wxString GetString(wxODCIndex n) const; + virtual void SetString(wxODCIndex n, const wxString& s); + virtual int FindString(const wxString& s) const; + virtual void Select(int n); + virtual int GetSelection() const; + void SetSelection(int n) { Select(n); } + + wxCONTROL_ITEMCONTAINER_CLIENTDATAOBJECT_RECAST + +protected: + + // clears all allocated client datas + void ClearClientDatas(); + + virtual int DoAppend(const wxString& item); + virtual int DoInsert(const wxString& item, wxODCIndex pos); + virtual void DoSetItemClientData(wxODCIndex n, void* clientData); + virtual void* DoGetItemClientData(wxODCIndex n) const; + virtual void DoSetItemClientObject(wxODCIndex n, wxClientData* clientData); + virtual wxClientData* DoGetItemClientObject(wxODCIndex n) const; +#if wxCHECK_VERSION(2,9,0) + virtual int DoInsertItems(const wxArrayStringsAdapter& items, + unsigned int pos, + void **clientData, + wxClientDataType type); + virtual void DoClear() { Clear(); } + virtual void DoDeleteOneItem(unsigned int pos) { Delete(pos); } +#endif + + // overload m_popupInterface member so we can access specific popup interface easier + wxPGVListBoxComboPopup* m_popupInterface; + +private: + void Init(); + + DECLARE_EVENT_TABLE() + + DECLARE_DYNAMIC_CLASS(wxPGOwnerDrawnComboBox) +}; + +#endif // _WX_PROPGRID_ODCOMBO_H_ diff --git a/assdraw/libpropgrid/include/wx/propgrid/pg_dox_mainpage.h b/assdraw/libpropgrid/include/wx/propgrid/pg_dox_mainpage.h new file mode 100644 index 000000000..cd90909d0 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/pg_dox_mainpage.h @@ -0,0 +1,1897 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: pg_dox_mainpage.h +// Purpose: wxPropertyGrid Doxygen Documentation +// Author: Jaakko Salli +// Modified by: +// Created: Oct-08-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef __WX_PG_DOX_MAINPAGE_H__ +#define __WX_PG_DOX_MAINPAGE_H__ + +/** + \mainpage wxPropertyGrid 1.2.11 Overview + + wxPropertyGrid is a specialized two-column grid for editing properties + such as strings, numbers, flagsets, fonts, and colours. It allows hierarchial, + collapsible properties ( via so-called categories that can hold child + properties), sub-properties, and has strong wxVariant support (for example, + allows populating from near-arbitrary list of wxVariants). + + Documentation for wxPython bindings: For a tutorial see the accompanied + wxPython readme file and the test_propgrid.py sample. Otherwise, individual + member functions should work very much the same as with the C++ wxWidgets, + so you'll probably find wxPropertyGrid and wxPropertyGridManager class references handy. + + Classes:\n + wxPropertyGrid\n + wxPropertyGridManager\n + wxPropertyGridEvent\n + + Header files:\n + wx/propgrid/propgrid.h: Mandatory when using wxPropertyGrid.\n + wx/propgrid/advprops.h: For less often used property classes.\n + wx/propgrid/manager.h: Mandatory when using wxPropertyGridManager.\n + wx/propgrid/propdev.h: Mandatory when implementing custom property classes.\n + + \ref featurelist\n + \ref basics\n + \ref categories\n + \ref parentprops + \ref enumandflags\n + \ref advprops\n + \ref operations\n + \ref events\n + \ref populating\n + \ref customizing\n + \ref custprop\n + \ref usage2\n + \ref subclassing\n + \ref misc\n + \ref proplist\n + \ref userhelp\n + \ref bugs\n + \ref issues\n + \ref todo\n + \ref notes\n + \ref newprops\n + \ref neweditors\n + + \section featurelist wxPropertyGrid Features + + Following is a non-exhaustive list of various wxPropertyGrid features and classes or methods necessary + to use them. + + - Hiding property editor: You can either use limited editing mode (wxPG_LIMITED_EDITING + window style, wxPropertyGrid::LimitPropertyEditing), which hides wxTextCtrl based + editor when other methods (dialog or sub-properties) are available, or you + can disable the property, which effectively hides the editor and makes the property + label to be drawn in grey colour. + - Unspecified, empty values (wxPropertyGrid::SetPropertyUnspecified, + wxPropertyGrid::IsPropertyUnspecified). + - Client data (void*) (wxPropertyGrid::SetPropertyClientData, + wxPropertyGrid::GetPropertyClientData). + - Multi-page management (\ref usage2). + - Setting wxValidator for editor (wxPropertyGrid::SetPropertyValidator). + - Changing editor of property (wxPropertyGrid::SetPropertyEditor). + - Property's value bitmap - small image shown in front of the value text + (wxPropertyGrid::SetPropertyImage). + - Help text shown in parent frame's status bar or in manager's description + text box (wxPropertyGrid::SetPropertyHelpString, wxPropertyGrid::GetPropertyHelpString). + - Changing set of choices used by wxEnumProperty, wxEditEnumProperty or wxMultiChoiceProperty + (wxPropertyGrid::SetPropertyChoices). + - Changing background colour of property's cell (wxPropertyGrid::SetPropertyColour). + - Setting property text max length (wxPropertyGrid::SetPropertyMaxLength) + - Hiding a property (wxPropertyGrid::HideProperty) + - Setting property attributes (\ref attributes) + - Populating wxPropertyGrid (\ref populating). + + \section basics Creating and Populating wxPropertyGrid (updated!) + + As seen here, wxPropertyGrid is constructed in the same way as + other wxWidgets controls: + + \code + + // Necessary header file + #include + + ... + + // Assumes code is in frame/dialog constructor + + // Construct wxPropertyGrid control + wxPropertyGrid* pg = new wxPropertyGrid( + this, // parent + PGID, // id + wxDefaultPosition, // position + wxDefaultSize, // size + // Some specific window styles - for all additional styles, + // see Modules->PropertyGrid Window Styles + wxPG_AUTO_SORT | // Automatic sorting after items added + wxPG_SPLITTER_AUTO_CENTER | // Automatically center splitter until user manually adjusts it + // Default style + wxPG_DEFAULT_STYLE ); + + // Window style flags are at premium, so some less often needed ones are + // available as extra window styles (wxPG_EX_xxx) which must be set using + // SetExtraStyle member function. wxPG_EX_HELP_AS_TOOLTIPS, for instance, + // allows displaying help strings as tooltips. + pg->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS ); + + \endcode + + (for complete list of new window styles: @link wndflags Additional Window Styles@endlink) + + wxPropertyGrid is usually populated with lines like this: + + \code + pg->Append( wxStringProperty(wxT("Label"),wxT("Name"),wxT("Initial Value")) ); + \endcode + + wxStringProperty is a factory function that creates a property instance of + a property class "wxStringProperty". Only the first function argument (label) + is mandatory. When necessary, name defaults to label and initial value to + default value. If wxPG_LABEL is used as the name argument, then the label is + automatically used as a name as well (this is more efficient than manually + defining both as the same). Empty name is also allowed, but in this case the + property cannot be accessed by its name. + + To demonstrate other common property classes, here's another code snippet: + + \code + + // Add int property + pg->Append( wxIntProperty(wxT("IntProperty"), wxPG_LABEL, 12345678) ); + + // Add float property (value type is actually double) + pg->Append( wxFloatProperty(wxT("FloatProperty"), wxPG_LABEL, 12345.678) ); + + // Add a bool property + pg->Append( wxBoolProperty(wxT("BoolProperty"), wxPG_LABEL, false) ); + + // A string property that can be edited in a separate editor dialog. + pg->Append( wxLongStringProperty(wxT("LongStringProperty"), + wxPG_LABEL, + wxT("This is much longer string than the ") + wxT("first one. Edit it by clicking the button."))); + + // String editor with dir selector button. + pg->Append( wxDirProperty(wxT("DirProperty"), wxPG_LABEL, ::wxGetUserHome()) ); + + // A file selector property. + pg->Append( wxFileProperty(wxT("FileProperty"), wxPG_LABEL, wxEmptyString) ); + + // Extra: set wildcard for file property (format same as in wxFileDialog). + pg->SetPropertyAttribute(wxT("FileProperty"), + wxPG_FILE_WILDCARD, + wxT("All files (*.*)|*.*")); + + \endcode + + All operations on properties should be done via wxPropertyGrid's + (or wxPropertyGridManager's) methods. Class reference of the base property + class should only be interesting for those creating custom property classes. + + Property operations, such as SetPropertyValue or DisableProperty, + all have two versions: one which accepts property id (of type wxPGId) and + another that accepts property name. Id is faster since it doesn't require + hash map lookup, but name is often much more convenient. + + You can get property id as Append/Insert return value, or by calling + GetPropertyByName. + + Below are samples for using some of the more commong operations. See + wxPropertyContainerMethods and wxPropertyGrid class references for complete list. + + \code + + wxPGId MyPropertyId = pg->GetPropertyByName( wxT("MyProperty") ); + + // There are many overloaded versions of this method, of which each accept + // different type of value. + // NOTE: If type of MyProperty is not "long", then this will yield a + // run-time error message. + pg->SetPropertyValue( wxT("MyProperty"), 200 ); + + // Setting a string works for all properties - conversion is done + // automatically. + pg->SetPropertyValue( MyPropertyId, wxT("400") ); + + // Getting property value as wxVariant. + wxVariant value = pg->GetPropertyValue( wxT("MyProperty") ); + + // Getting property value as String (again, works for all typs). + wxString value = pg->GetPropertyValueAsString( MyPropertyId ); + + // Getting property value as int. Provokes a run-time error + // if used with property which value type is not "long". + long value = pg->GetPropertyValueAsLong( wxT("MyProperty") ); + + // Set new name. + pg->SetPropertyName( wxT("MyProperty"), wxT("X") ); + + // Set new label - we need to use the new name. + pg->SetPropertyLabel( wxT("X"), wxT("New Label") ); + + // Disable the property. + pg->DisableProperty( MyPropertyId ); + + // Set property as read-only. + pg->SetPropertyReadOnly( MyPropertyId ); + + \endcode + + + \section categories Categories + + wxPropertyGrid has a hierarchial property storage and display model, which + allows property categories to hold child properties and even other + categories. Other than that, from the programmer's point of view, categories + can be treated exactly the same as "other" properties. For example, despite + its name, GetPropertyByName also returns a category by name, and SetPropertyLabel + also sets label of a category. Note however that sometimes the label of a + property category may be referred as caption (for example, there is + SetCaptionForegroundColour method that sets text colour of a property category's label). + + When category is added at the top (i.e. root) level of the hierarchy, + it becomes a *current category*. This means that all other (non-category) + properties after it are automatically added to it. You may add + properties to specific categories by using wxPropertyGrid::Insert or wxPropertyGrid::AppendIn. + + Category code sample: + + \code + + // One way to add category (similar to how other properties are added) + pg->Append( wxPropertyCategory(wxT("Main")) ); + + // All these are added to "Main" category + pg->Append( wxStringProperty(wxT("Name")) ); + pg->Append( wxIntProperty(wxT("Age"),wxPG_LABEL,25) ); + pg->Append( wxIntProperty(wxT("Height"),wxPG_LABEL,180) ); + pg->Append( wxIntProperty(wxT("Weight")) ); + + // Another way + pg->AppendCategory( wxT("Attributes") ); + + // All these are added to "Attributes" category + pg->Append( wxIntProperty(wxT("Intelligence")) ); + pg->Append( wxIntProperty(wxT("Agility")) ); + pg->Append( wxIntProperty(wxT("Strength")) ); + + \endcode + + + \section parentprops Parent Properties + + If you want to combine number of properties under single parent (just + like wxFontProperty combines font attributes), then the easiest way to + proceed is to use wxParentProperty. + + \remarks + - wxParentProperty's value type is string, in which + a child property that has children of its own will be embedded in + braces ([]). + - Children of wxParentProperty cannot be accessed globally by their name. + Instead, use "Parent.Child" format. + - However, events occur for the children, not the parent. In addition + to GetPropertyParent, You can use wxPropertyGridEvent::GetMainParent() + to find out property's highest wxParentProperty or wxCustomProperty. + + Sample: + + \code + wxPGId pid = pg->Append( wxParentProperty(wxT("Car"),wxPG_LABEL) ); + + pg->AppendIn( pid, wxStringProperty(wxT("Model")), + wxPG_LABEL, + wxT("Lamborghini Diablo SV")) ); + + pg->AppendIn( pid, wxIntProperty(wxT("Engine Size (cc)"), + wxPG_LABEL, + 5707) ); + + wxPGId speedId = pg->AppendIn( pid, wxParentProperty(wxT("Speeds"),wxPG_LABEL) ); + pg->AppendIn( speedId, wxIntProperty(wxT("Max. Speed (mph)"),wxPG_LABEL,300) ); + pg->AppendIn( speedId, wxFloatProperty(wxT("0-100 mph (sec)"),wxPG_LABEL,3.9) ); + pg->AppendIn( speedId, wxFloatProperty(wxT("1/4 mile (sec)"),wxPG_LABEL,8.6) ); + + pg->AppendIn( pid, wxIntProperty(wxT("Price ($)"), + wxPG_LABEL, + 300000) ); + + // Displayed value of "Car" property is now: + // "Lamborghini Diablo SV; [300; 3.9; 8.6]; 300000" + + \endcode + + \section enumandflags wxEnumProperty and wxFlagsProperty + + wxEnumProperty is used when you want property's (integer) value + to be selected from a popup list of choices. + + Creating wxEnumProperty is more complex than those described earlier. + You have to provide list of constant labels, and optionally relevant values + (if label indexes are not sufficient). + + \remarks + + - Value wxPG_INVALID_VALUE (equals 2147483647 which usually equals INT_MAX) is not + allowed as value. + + A very simple example: + + \code + + // + // Using wxArrayString + // + wxArrayString arrDiet; + arr.Add(wxT("Herbivore")); + arr.Add(wxT("Carnivore")); + arr.Add(wxT("Omnivore")); + + pg->Append( wxEnumProperty(wxT("Diet"), + wxPG_LABEL, + arrDiet) ); + + + + // + // Using wxChar* array + // + const wxChar* arrayDiet[] = + { wxT("Herbivore"), wxT("Carnivore"), wxT("Omnivore"), NULL }; + + pg->Append( wxEnumProperty(wxT("Diet"), + wxPG_LABEL, + arrayDiet) ); + + + \endcode + + Here's extended example using values as well: + + \code + + // + // Using wxArrayString and wxArrayInt + // + wxArrayString arrDiet; + arr.Add(wxT("Herbivore")); + arr.Add(wxT("Carnivore")); + arr.Add(wxT("Omnivore")); + + wxArrayInt arrIds; + arrIds.Add(40); + arrIds.Add(45); + arrIds.Add(50); + + // Note that the initial value (the last argument) is the actual value, + // not index or anything like that. Thus, our value selects "Omnivore". + pg->Append( wxEnumProperty(wxT("Diet"), + wxPG_LABEL, + arrDiet, + arrIds, + 50) ); + + + // + // Using wxChar* and long arrays + // + const wxChar* array_diet[] = + { wxT("Herbivore"), wxT("Carnivore"), wxT("Omnivore"), NULL }; + + long array_diet_ids[] = + { 40, 45, 50 }; + + pg->Append( wxEnumProperty(wxT("Diet"), + wxPG_LABEL, + array_diet, + array_diet_ids) ); + + \endcode + + wxPGChoices is a class where wxEnumProperty, and other properties which + require label storage, actually stores strings and values. It is used + to facilitiate reference counting, and therefore recommended way of + adding items when multiple properties share the same set. + + You can use it directly as well, filling it and then passing it to the + factory function. + + \code + + wxPGChoices chs; + chs.Add(wxT("Herbivore"),40); + chs.Add(wxT("Carnivore"),45); + chs.Add(wxT("Omnivore"),50); + + // Note: you can add even whole arrays to wxPGChoices + + pg->Append( wxEnumProperty(wxT("Diet"), + wxPG_LABEL, + chs) ); + + // Add same choices to another property as well - this is efficient due + // to reference counting + pg->Append( wxEnumProperty(wxT("Diet 2"), + wxPG_LABEL, + chs) ); + + \endcode + + If you later need to change choices used by a property, there is function + for that as well. + + \code + + // + // Example 1: Add one extra item + wxPGChoices& choices = pg->GetPropertyChoices(wxT("Diet")); + choices.Add(wxT("Custom"),55); + + // + // Example 2: Replace all the choices + wxPGChoices chs; + chs.Add(wxT(""),0); + pg->SetPropertyChoices(wxT("Diet"),chs); + + \endcode + + If you want to create your enum properties with simple (label,name,value) + constructor, then you need to create a new property class using one of the + supplied macro pairs. See \ref newprops for details. + + wxEditEnumProperty is works exactly like wxEnumProperty, except + is uses non-readonly combobox as default editor, and has string values. + + wxFlagsProperty is similar: + + \code + + const wxChar* flags_prop_labels[] = { wxT("wxICONIZE"), + wxT("wxCAPTION"), wxT("wxMINIMIZE_BOX"), wxT("wxMAXIMIZE_BOX"), NULL }; + + // this value array would be optional if values matched string indexes + long flags_prop_values[] = { wxICONIZE, wxCAPTION, wxMINIMIZE_BOX, + wxMAXIMIZE_BOX }; + + pg->Append( wxFlagsProperty(wxT("Window Style"), + wxPG_LABEL, + flags_prop_labels, + flags_prop_values, + wxDEFAULT_FRAME_STYLE) ); + + \endcode + + wxFlagsProperty can use wxPGChoices just the same way as wxEnumProperty + (and also custom property classes can be created with similar macro pairs). + Note: When changing "choices" (ie. flag labels) of wxFlagsProperty, + you will need to use SetPropertyChoices - otherwise they will not get updated + properly. + + \section advprops Advanced Properties + + This section describes the use of less often needed property classes. + To use them, you have to include . + + \code + + // Necessary extra header file + #include + + ... + + // wxArrayStringProperty embeds a wxArrayString. + pg->Append( wxArrayStringProperty(wxT("Label of ArrayStringProperty"), + wxT("NameOfArrayStringProp"))); + + // Date property. + // NB: This will use wxDatePickerCtrl only if wxPG_ALLOW_WXADV is defined + // in propgrid.h or in the library project settings. + pg->Append( wxDateProperty(wxT("MyDateProperty"), + wxPG_LABEL, + wxDateTime::Now()) ); + + // Image file property. Wildcard is auto-generated from available + // image handlers, so it is not set this time. + pg->Append( wxImageFileProperty(wxT("Label of ImageFileProperty"), + wxT("NameOfImageFileProp"))); + + // Font property has sub-properties. Note that we give window's font as + // initial value. + pg->Append( wxFontProperty(wxT("Font"), + wxPG_LABEL, + GetFont()) ); + + // Colour property with arbitrary colour. + pg->Append( wxColourProperty(wxT("My Colour 1"), + wxPG_LABEL, + wxColour(242,109,0) ) ); + + // System colour property. + pg->Append( wxSystemColourProperty (wxT("My SysColour 1"), + wxPG_LABEL, + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)) ); + + // System colour property with custom colour. + pg->Append( wxSystemColourProperty (wxT("My SysColour 2"), + wxPG_LABEL, + wxColour(0,200,160) ) ); + + // Cursor property + pg->Append( wxCursorProperty (wxT("My Cursor"), + wxPG_LABEL, + wxCURSOR_ARROW)); + + \endcode + + + \section operations More About Operating with Properties + + Example of iterating through all properties (that are not category captions or + sub-property items): + + \code + + wxPGId id = pg->GetFirstProperty(); + + while ( id.IsOk() ) + { + // Do something with property id + + ... + + // Get next + pg->GetNextProperty( id ); + } + + \endcode + + Getting value of selected wxSystemColourProperty (which value type is derived + from wxObject): + + \code + + wxPGId id = pg->GetSelection(); + + if ( id.IsOk() ) + { + + // Get name of property + const wxString& name = pg->GetPropertyName( id ); + + // If type is not correct, GetColour() method will produce run-time error + if ( pg->IsPropertyValueType( id, CLASSINFO(wxColourPropertyValue) ) ) + { + wxColourPropertyValue* pcolval = + wxDynamicCast(pg->GetPropertyValueAsWxObjectPtr(id), + wxColourPropertyValue); + + // Report value + wxString text; + if ( pcolval->m_type == wxPG_CUSTOM_COLOUR ) + text.Printf( wxT("It is custom colour: (%i,%i,%i)"), + (int)pcolval->m_colour.Red(), + (int)pcolval->m_colour.Green(), + (int)pcolval->m_colour.Blue()); + else + text.Printf( wxT("It is wx system colour (number=%i): (%i,%i,%i)"), + (int)pcolval->m_type, + (int)pcolval->m_colour.Red(), + (int)pcolval->m_colour.Green(), + (int)pcolval->m_colour.Blue()); + + wxMessageBox( text ); + } + + } + + + \endcode + + \section populating Populating wxPropertyGrid Automatically + + \subsection fromvariants Populating from List of wxVariants + + Example of populating an empty wxPropertyGrid from a values stored + in an arbitrary list of wxVariants. + + \code + + // This is a static method that initializes *all* builtin type handlers + // available, including those for wxColour and wxFont. Refers to *all* + // included properties, so when compiling with static library, this + // method may increase the executable size significantly. + pg->InitAllTypeHandlers (); + + // Get contents of the grid as a wxVariant list + wxVariant all_values = pg->GetPropertyValues(); + + // Populate the list with values. If a property with appropriate + // name is not found, it is created according to the type of variant. + pg->SetPropertyValues ( my_list_variant ); + + // In order to get wxObject ptr from a variant value, + // wxGetVariantCast(VARIANT,CLASSNAME) macro has to be called. + // Like this: + wxVariant v_txcol = pg->GetPropertyValue(wxT("Text Colour")); + const wxColour& txcol = wxGetVariantCast(v_txcol,wxColour); + + \endcode + + + \section events Event Handling + + Probably the most important event is the Changed event which occurs when + value of any property is changed by the user. Use EVT_PG_CHANGED(id,func) + in your event table to use it. + For complete list of event types, see wxPropertyGrid class reference. + + The custom event class, wxPropertyGridEvent, has methods to directly + access the property that triggered the event. + + Here's a small sample: + + \code + + // Portion of an imaginary event table + BEGIN_EVENT_TABLE(MyForm, wxFrame) + + ... + + // This occurs when a property value changes + EVT_PG_CHANGED( PGID, MyForm::OnPropertyGridChange ) + + ... + + END_EVENT_TABLE() + + void MyForm::OnPropertyGridChange( wxPropertyGridEvent& event ) + { + + // Get name of changed property + const wxString& name = event.GetPropertyName(); + + // Get resulting value - wxVariant is convenient here. + wxVariant value = event.GetPropertyValue(); + + } + + \endcode + + \remarks On Sub-property Event Handling + - For wxParentProperty and wxCustomProperty, events will occur for + sub-property. For those properties that inherit directly from + wxPGPropertyWithChildren/wxBaseParentPropertyClass (wxFontProperty, + wxFlagsProperty, etc), events occur for the main parent property + only (actually, this has to do whether the children are "private" or not + - see the attributes). + - When wxParentProperty or wxCustomProperty's child gets changed, you can + use wxPropertyGridEvent::GetMainParent to obtain its top non-category + parent (useful, if you have wxParentProperty as child of another + wxParentProperty, for example). + + + \subsection tofile Saving Population to a Text-based Storage + + \code + + static void WritePropertiesToMyStorage( wxPropertyGrid* pg, wxPGId id, wxMyStorage& f, int depth ) + { + wxString s; + wxString s2; + + while ( id.IsOk() ) + { + + // TODO: Save property into text storage using: + // wxPropertyGrid::GetPropertyClassName + // wxPropertyGrid::GetPropertyName + // wxPropertyGrid::GetPropertyLabel + // wxPropertyGrid::GetPropertyValueAsString + // wxPropertyGrid::GetPropertyChoices + // wxPropertyGrid::GetPropertyAttributes + + // Example for adding choices: + wxPGChoices& choices = pg->GetPropertyChoices(id); + if ( choices.IsOk() ) + { + // First add id of the choices list inorder to optimize + s2.Printf(wxT("\"%X\""),(unsigned int)choices.GetId()); + s.Append(s2); + f.AddToken(s2); + + size_t i; + wxArrayString& labels = choices.GetLabels(); + wxArrayInt& values = choices.GetValues(); + if ( values.GetCount() ) + for ( i=0; iGetFirstChild(id); + if ( firstChild.IsOk() ) + { + WritePropertiesToMyStorage( pg, firstChild, f, depth+1 ); + + // TODO: Add parent's terminator + } + + id = pg->GetNextSibling(id); + } + } + + ... + + // Then you can use this to store the entire hierarchy + wxPGId firstChild = pg->GetFirstChild(pg->GetRoot()); + if ( firstChild.IsOk() ) + WritePropertiesToFile(pg,first_child,InstanceOfMyStorage,0); + + \endcode + + For more practical'ish example, see FormMain::OnSaveToFileClick in + propgridsample.cpp. + + \subsection fromfile Loading Population from a Text-based Storage + + \code + + // Recommended when modifying the grid a lot at once + pg->Freeze(); + + // Necessary if you want a full-page loading + pg->Clear(); + + wxPropertyGridPopulator populator(pg); + + // Store strings from the source here + wxString s_class; + wxString s_name; + wxString s_value; + wxString s_attr; + + // Each set of choices loaded must have id + wxPGChoicesId choicesId; + + wxArrayString choiceLabels; + wxArrayInt choiceValues; + + // Pseudo-code loop to parse the source one "line" at a time + while ( !source.IsAtEnd() ) + { + + // Clear stuff that doesn't exist at every "line" + choicesId = (wxPGChoicesId) 0; + choiceLabels.Empty(); + choiceValues.Empty(); + + // TODO: Load "line" to variables + + // TODO: When a sequence of sibling properties is terminated, call this: + // populator.EndChildren(); + + // TODO: If had choices, use following code: + // if ( choicesId && !populator.HasChoices(choicesId) ) + // { + // populator.AddChoices(choicesId,choiceLabels,choiceValues); + // } + + // TODO: Add the property. + // (for sake of simplicity we use here default name for properties) + // populator.AppendByClass(s_class, + // s_name, + // wxPG_LABEL, + // s_value, + // s_attr, + // choicesId); + + // TODO: When a sequence of sibling properties begins, call this: + // populator.BeginChildren(); + + } + + pg->Thaw(); + + \endcode + + For more practical'ish example, see FormMain::OnLoadFromFileClick in + propgridsample.cpp. + + + \section customizing Customizing Properties (without sub-classing) + + In this section are presented various ways to have custom appearance + and behaviour for your properties without all the necessary hassle + of sub-classing a property class etc. + + \subsection customimage Setting Value Image + + Every property can have a small value image placed in front of the + actual value text. Built-in example of this can be seen with + wxColourProperty and wxImageFileProperty, but for others it can + be set using wxPropertyGrid::SetPropertyImage method. + + \subsection customvalidator Setting Validator + + You can set wxValidator for a property using wxPropertyGrid::SetPropertyValidator. + + \subsection customeditor Setting Property's Editor Control(s) + + You can set editor control (or controls, in case of a control and button), + of any property using wxPropertyGrid::SetPropertyEditor. Editors are passed + using wxPG_EDITOR(EditorName) macro, and valid built-in EditorNames are + TextCtrl, Choice, ComboBox, CheckBox, TextCtrlAndButton, ChoiceAndButton, + SpinCtrl, and DatePickerCtrl. Two last mentioned ones require call to + static member function wxPropertyGrid::RegisterAdditionalEditors(). + + Following example changes wxColourProperty's editor from default Choice + to TextCtrlAndButton. wxColourProperty has its internal event handling set + up so that button click events of the button will be used to trigger + colour selection dialog. + + \code + + wxPGId colProp = pg->Append(wxColourProperty(wxT("Text Colour"))); + + pg->SetPropertyEditor(colProp,wxPG_EDITOR(TextCtrlAndButton)); + + \endcode + + Naturally, creating and setting custom editor classes is a possibility as + well. For more information, see wxPGEditor class reference. + + \subsection customeventhandling Handling Events Passed from Properties + + wxEVT_COMMAND_BUTTON_CLICKED (corresponds to event table macro EVT_BUTTON): + Occurs when editor button click is not handled by the property itself + (as is the case, for example, if you set property's editor to TextCtrlAndButton + from the original TextCtrl). + + \subsection attributes Property Attributes + + Miscellaneous values, often specific to a property type, can be set + using wxPropertyGrid::SetPropertyAttribute and wxPropertyGrid::SetPropertyAttributeAll + methods. + + For complete list of attributes, see @link attrids Property Attributes@endlink. + + \subsection boolcheckbox Setting wxBoolProperties to Use Check Box + + To have all wxBoolProperties to use CheckBox editor instead of Choice, use + following (call after bool properties have been added): + + \code + pg->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX,(long)1); + \endcode + + + + \section custprop wxCustomProperty + + wxCustomProperty allows extra customizing. + + - May have children. + + For more info on attributes, see \ref attrids. In sample application, + there is a CustomProperty property that has children that can be + used to modify the property itself. + + \remarks + - Children of wxParentProperty cannot be accessed globally by their name. + Instead, use "Parent.Child" format. + - However, events occur for the children, not the parent. In addition + to GetPropertyParent, You can use wxPropertyGridEvent::GetMainParent() + to find out property's highest wxParentProperty or wxCustomProperty. + + Limitations: + - Currently wxCustomProperty is limited to wxString value type. + - As in wxParentProperty: names of child properties are not visible + globally. You need to use "Parent.SubProperty" name format to access + them. + + + \section usage2 Using wxPropertyGridManager (Updated!) + + wxPropertyGridManager is an efficient multi-page version of wxPropertyGrid, + which can optionally have toolbar for mode and page selection, help text box, + and a compactor button. + + wxPropertyGridManager mirrors most non-visual methods of wxPropertyGrid, some + identically, some so that they can affect a property on any page, and some + so that they can only affect selected target page. + + Generally, methods that operate on a property ( such as + GetPropertyValue, SetPropertyValue, EnableProperty, LimitPropertyEditing, Delete, etc. ), + work globally (so the given property can exist on any managed page). + + Methods that add properties ( Append, Insert, etc.) or operate on multiple properties + (such as GetPropertyValues or SetPropertyValues), will work in target page only. + Use SetTargetPage(index) method to set current target page. Changing a displayed page + (using SelectPage(index), for example) will automatically set the target page + to the one displayed. + + Global methods such as ExpandAll generally work on the target page only. + + Visual methods, such as SetCellBackgroundColour and GetNextVisible are only + available in wxPropertyGrid. Use wxPropertyGridManager::GetGrid() to obtain + pointer to it. + + wxPropertyGridManager constructor has exact same format as wxPropertyGrid + constructor, and basicly accepts same extra window style flags (albeit also + has some extra ones). + + Here's some example code for creating and populating a wxPropertyGridManager: + + \code + + wxPropertyGridManager* pgMan = new wxPropertyGridManager(this, PGID, + wxDefaultPosition, wxDefaultSize, + // These and other similar styles are automatically + // passed to the embedded wxPropertyGrid. + wxPG_BOLD_MODIFIED|wxPG_SPLITTER_AUTO_CENTER| + // Include toolbar. + wxPG_TOOLBAR | + // Include description box. + wxPG_DESCRIPTION | + // Include compactor. + wxPG_COMPACTOR | + // Plus defaults. + wxPGMAN_DEFAULT_STYLE + ); + + // Adding a page sets target page to the one added, so + // we don't have to call SetTargetPage if we are filling + // it right after adding. + pgMan->AddPage(wxT("First Page")); + + pgMan->AppendCategory(wxT("Category A1")); + + // Remember, the next line equals pgman->Append( wxIntProperty(wxT("Number"),wxPG_LABEL,1) ); + pgMan->Append( wxT("Number"),wxPG_LABEL,1 ); + + pgMan->Append( wxColourProperty(wxT("Colour"),wxPG_LABEL,*wxWHITE) ); + + pgMan->AddPage(wxT("Second Page")); + + pgMan->Append( wxT("Text"),wxPG_LABEL,wxT("(no text)") ); + + pgMan->Append( wxFontProperty(wxT("Font"),wxPG_LABEL) ); + + // For total safety, finally reset the target page. + pgMan->SetTargetPage(0); + + \endcode + + \subsection propgridpage wxPropertyGridPage (New!) + + wxPropertyGridPage is holder of properties for one page in manager. It is derived from + wxEvtHandler, so you can subclass it to process page-specific property grid events. Hand + over your page instance in wxPropertyGridManager::AddPage. + + Please note that the wxPropertyGridPage itself only sports subset of wxPropertyGrid API. + Naturally it inherits from wxPropertyGridMethods and wxPropertyGridState, but, for instance, setting property values is + not yet supported. Use parent manager (m_manager member) instead when needed. Basic property + appending and insertion is supported, however. + + + \section subclassing Subclassing wxPropertyGrid and wxPropertyGridManager (New!) + + Few things to note: + + - Only a small percentage of member functions are virtual. If you need more, + just let me know. + + - Data manipulation is done in wxPropertyGridState class. So, instead of + overriding wxPropertyGrid::Insert, you'll probably want to override wxPropertyGridState::DoInsert. + + - Override wxPropertyGrid::CreateState to instantiate your derivative wxPropertyGridState. + For wxPropertyGridManager, you'll need to subclass wxPropertyGridPage instead (since it + is derived from wxPropertyGridState), and hand over instances in wxPropertyGridManager::AddPage + calls. + + - You can use a derivate wxPropertyGrid with manager by overriding wxPropertyGridManager::CreatePropertyGrid + member function. + + + \section misc Miscellaneous Topics (Updated!) + + \subsection namescope Property Name Scope + + - All properties which parent is category or root have their names + globally accessible. + + - Sub-properties (i.e. properties which have parent that is not category or + root) can not be accessed globally by their name. Instead, use + "." in place of "". + + \subsection boolproperty wxBoolProperty + + There are few points about wxBoolProperty that require futher discussion: + - wxBoolProperty can be shown as either normal combobox or as a checkbox. + Property attribute wxPG_BOOL_USE_CHECKBOX is used to change this. + For example, if you have a wxFlagsProperty, you can + set its all items to use check box using the following: + \code + pg->SetPropertyAttribute(wxT("MyFlagsProperty"),wxPG_BOOL_USE_CHECKBOX,(long)1,wxPG_RECURSE); + \endcode + + - Default item names for wxBoolProperty are [wxT("False"),wxT("True")]. This can be + changed using wxPropertyGrid::SetBoolChoices(trueChoice,falseChoice). + + \subsection textctrlupdates Updates from wxTextCtrl Based Editor + + Changes from wxTextCtrl based property editors are committed (ie. + wxEVT_PG_CHANGED is sent etc.) *only* when (1) user presser enter, (2) + user moves to edit another property, or (3) when focus or mouse leaves + the grid. + + Because of this, you may find it useful, in some apps, to monitor + wxEVT_COMMAND_TEXT_UPDATED (EVT_TEXT macro) for non-committed changes + in editor. However, the current problem is that pressing Esc in editor + cancels any changes made, thus possibly rendering your knowledge of + changed state incomplete. There is no current, perfect solution for + this problem. + + \subsection splittercentering Centering the Splitter (New!) + + If you need to center the splitter, but only once when the program starts, + then do not use the wxPG_SPLITTER_AUTO_CENTER window style, but the + wxPropertyGrid::CenterSplitter() method. However, be sure to call it after + the sizer setup and SetSize calls! (ie. usually at the end of the + frame/dialog constructor) + + \subsection compilerdefines Supported Preprocessor Defines + + Here is list of supported preprocessor defines (other than those that relate with + wxWidgets core library): + + wxPG_USE_WXMODULE: Define as 0 to not use wxModule to manage global variables. + This may be needed in cases where wxPropertyGrid is linked as a plugin DLL, or when + wxPropertyGrid is linked statically in a DLL. + + WXMAKINGLIB_PROPGRID: Define if you are linking wxPropertyGrid statically + but wxWidgets itself is DLL. + + WXMAKINGDLL_PROPGRID: Define when building wxPropertyGrid as a DLL. This + should be automatically defined correctly by the Bakefile-generated makefiles. + + wxPG_COMPATIBILITY_1_0_0: Define to make wxPropertyGrid more compatible with the + old 1.0.x releases. + + + \section proplist Property Type Descriptions (Updated!) + + Here are descriptions of built-in properties, with attributes + (see wxPropertyGrid::SetPropertyAttribute) that apply to them. + Note that not all attributes are necessarily here. For complete + list, see @link attrids Property Attributes@endlink. + + \subsection wxPropertyCategory + + Inheritable Class: wxPropertyCategoryClass. + + Not an actual property per se, but a header for a group of properties. + + \subsection wxParentProperty + + Pseudo-property that can have sub-properties inserted under itself. + Has textctrl editor that allows editing values of all sub-properties + in a one string. In essence, it is a category that has look and feel + of a property, and which children can be edited via the textctrl. + + \subsection wxStringProperty + + Inheritable Class: wxStringProperty + + Simple string property. wxPG_STRING_PASSWORD attribute may be used + to echo value as asterisks and use wxTE_PASSWORD for wxTextCtrl. + + \subsection wxIntProperty + + Like wxStringProperty, but converts text to a signed long integer. + + \subsection wxUIntProperty + + Like wxIntProperty, but displays value as unsigned int. To set + the prefix used globally, manipulate wxPG_UINT_PREFIX string attribute. + To set the globally used base, manipulate wxPG_UINT_BASE int + attribute. Regardless of current prefix, understands (hex) values starting + with both "0x" and "$". + + \subsection wxFloatProperty + + Like wxStringProperty, but converts text to a double-precision floating point. + Default float-to-text precision is 6 decimals, but this can be changed + by modifying wxPG_FLOAT_PRECISION attribute. + + \subsection wxBoolProperty + + Represents a boolean value. wxChoice is used as editor control, by the + default. wxPG_BOOL_USE_CHECKBOX attribute can be set to 1 inorder to use + check box instead. + + \subsection wxLongStringProperty + + Inheritable Class: wxLongStringPropertyClass + + Like wxStringProperty, but has a button that triggers a small text editor + dialog. + + \subsection wxDirProperty + + Like wxLongStringProperty, but the button triggers dir selector instead. + + \subsection wxFileProperty + + Inheritable Class: wxFilePropertyClass + + Like wxLongStringProperty, but the button triggers file selector instead. + Default wildcard is "All files..." but this can be changed by setting + wxPG_FILE_WILDCARD attribute (see wxFileDialog for format details). + Attribute wxPG_FILE_SHOW_FULL_PATH can be set to 0 inorder to show + only the filename, not the entire path. + + \subsection wxEnumProperty + + Inheritable Class: wxEnumPropertyClass + + Represents a single selection from a list of choices - + custom combobox control is used to edit the value. + + \subsection wxFlagsProperty + + Inheritable Class: wxFlagsPropertyClass + + Represents a bit set that fits in a long integer. wxBoolProperty sub-properties + are created for editing individual bits. Textctrl is created to manually edit + the flags as a text; a continous sequence of spaces, commas and semicolons + is considered as a flag id separator. + Note: When changing "choices" (ie. flag labels) of wxFlagsProperty, you + will need to use SetPropertyChoices - otherwise they will not get updated properly. + + \subsection wxArrayStringProperty + + Inheritable Class: wxArrayStringPropertyClass + + Allows editing of a list of strings in wxTextCtrl and in a separate dialog. + + \subsection wxDateProperty + + Inheritable Class: wxDatePropertyClass + + wxDateTime property. Default editor is DatePickerCtrl, altough TextCtrl + should work as well. wxPG_DATE_FORMAT attribute can be used to change + string wxDateTime::Format uses (altough default is recommended as it is + locale-dependant), and wxPG_DATE_PICKER_STYLE allows changing window + style given to DatePickerCtrl (default is wxDP_DEFAULT|wxDP_SHOWCENTURY). + + + Note that DatePickerCtrl editor depends on wxAdv library, and will only + be used if wxPG_ALLOW_WXADV is defined in propgrid.h or in the library + project settings. + + + \subsection wxEditEnumProperty + + Represents a string that can be freely edited or selected from list of choices - + custom combobox control is used to edit the value. + + \subsection wxMultiChoiceProperty + + Inheritable Class: wxMultiChoicePropertyClass + + Allows editing a multiple selection from a list of strings. This is + property is pretty much built around concept of wxMultiChoiceDialog. + + \subsection wxImageFileProperty + + Inheritable Class: wxImageFilePropertyClass + + Like wxFileProperty, but has thumbnail of the image in front of + the filename and autogenerates wildcard from available image handlers. + + \subsection wxColourProperty + + Inheritable Class: None - instead, see \ref custcolprop. + + Useful alternate editor: Choice. + + Represents wxColour. wxButton is used to trigger a colour picker dialog. + + \subsection wxFontProperty + + Inheritable Class: wxFontPropertyClass + + Represents wxFont. Various sub-properties are used to edit individual + subvalues. + + \subsection wxSystemColourProperty + + Inheritable Class: wxSystemColourPropertyClass + + Represents wxColour and a system colour index. wxChoice is used to edit + the value. Drop-down list has color images. + + \subsection wxCursorProperty + + Inheritable Class: wxCursorPropertyPropertyClass + + Represents a wxCursor. wxChoice is used to edit the value. + Drop-down list has cursor images under some (wxMSW) platforms. + + \subsection wxCustomProperty + + Inheritable Class: wxCustomPropertyClass + + A customizable property class with string data type. Value image, Editor class, + and children can be modified. + + \subsection Additional Sample Properties + + Sample application has following additional examples of custom properties: + - wxFontDataProperty ( edits wxFontData ) + - wxPointProperty ( edits wxPoint ) + - wxSizeProperty ( edits wxSize ) + - wxAdvImageFileProperty ( like wxImageFileProperty, but also has a drop-down for recent image selection) + - wxDirsProperty ( edits a wxArrayString consisting of directory strings) + - wxArrayDoubleProperty ( edits wxArrayDouble ) + + \section userhelp Using wxPropertyGrid (Updated!) + + This is a short summary of how a wxPropertyGrid is used (not how it is programmed), + or, rather, how it should behave in practice. + + - Basic mouse usage is as follows:\n + - Clicking property label selects it. + - Clicking property value selects it and focuses to editor control. + - Clicking category label selects the category. + - Double-clicking category label selects the category and expands/collapses it. + - Double-clicking labels of a property with children expands/collapses it. + + - Keyboard usage is as follows:\n + - alt + down (or right) - displays editor dialog (if any) for a property. Note + that this shortcut can be changed using wxPropertyGrid::SetButtonShortcut.\n + Only when editor control is not focused:\n + - cursor up - moves to previous visible property\n + - cursor down - moves to next visible property\n + - cursor left - if collapsible, collapses, otherwise moves to previous property\n + - cursor right - if expandable, expands, otherwise moves to next property\n + - tab (if enabled) - focuses keyboard to the editor control of selected property\n + Only when editor control is focused:\n + - return/enter - confirms changes made to a wxTextCtrl based editor\n + - tab - moves to next visible property (or, if in last one, moves out of grid)\n + - shift-tab - moves to previous visible property (or, if in first one, moves out of grid)\n + - escape - unfocuses from editor control and cancels any changes made + (latter for wxTextCtrl based editor only)\n + + - In long strings tabs are represented by "\t" and line break by "\n". + + \section bugs Known Bugs + NOTE! This section is severely out of date. TODO section in propgrid.cpp has a lot + more of these. + Any insight on these is more than welcome. + - wxGTK: Pressing ESC to unfocus an editor control will screw the focusing + (either focuses back to the editor or moves focus to limbo; works perfectly + on wxMSW though). + - I have experienced a complete freeze when toying with the popup of + wxAdvImageProperty. Visiting another window will end it. + - wxGTK: in sample application, property text colour is not set correct from + wxSystemColourProperty. Value is correct, but the resulting text colour + is sometimes a bit skewed if it is not a shade of gray. This may be GTK's + attempt to auto-adjust it. + - wxGTK: Sometimes '...' text on editor button may disappear (maybe + "invisible font" related thingie). wxAdvImageProperty never seem to get + the text, while other controls do. + Following are wxWidgets or platform bugs: + - wxMSW: After (real) popup window is shown in wxPropertyGrid, grid's scrollbar + won't get hilight until another window is visited. This is probably a Windows + bug. + - wxGTK+ w/ unicode: image handlers return only the first character of an extension + - wxGTK+ 1.2: Controls sometimes disappear. They reappear when cursor is moved + over them. + - wxGTK+ 1.2: Cannot set (multiple) items for wxListBox (affects + wxMultiChoiceProperty). + + \section issues Issues + These are not bugs per se, but miscellaneous cross-platform issues that have been + resolved in a less-than-satisfactory manner. + - wxGTK: When selecting wxCursorProperty in sample, there may be + warning: Invalid UTF8 string passed to pango_layout_set_text(). + This is probably specific to older versions of GTK. + - Win2K: Pressing Alt+non-registered key combo resulted in app hanging when + wxTAB_TRAVERSAL was used directly. Current solution is not to use it, but + to use wxWANTS_CHARS alone. Strangely enough, this works on wxMSW (but + not wxGTK - precompiler conditional are used to sort things out). + - wxMSW: Toolbar's ToggleTool doesn't disable last item in the same radiogroup. AFAIK, + there is no way to do that (though I didn't do extensive research). + - Atleast with wxGTK2+Unicode+Debug Mode File Selector dialog may trigger an assertion + failure (line 1060 in string.cpp with 2.5.3) that can be cancelled + probably without any ill-effect. + - Under GTK, EVT_MOTION does not trigger for child control. Causes cursor change + inconsistencies. Permanent mouse capture is not practical since it causes wxWindow:: + SetCursor to fail (and events cannot be relayed to native controls anyway). + Easy solution used: Splitter drag detect margin and control do not overlap. + - When splitter is being dragged, active editor control (button as well under wxGTK) + is hidden to prevent flickering. This may go unnoticed with some + controls (wxTextCtrl) but is very noticeable with others (wxChoice). + - Under MSW, when resizing, editor controls flicker. No easy fix here + (wxEVT_ONIDLE might be employed). + - Under GTK 1.2, font may show invisible if it is not bold (so it is forced). + - Under wxGTK, controls may flicker a bit (actually, a lot) when being shown. + + \section todo Todo + For a detailed TODO, see propertygrid.cpp (just search for "todo" and you'll find it). + + \section notes Design Notes + - Currently wxPropertyGridManager uses "easy" way to relay events from embedded + wxPropertyGrid. That is, the exact same id is used for both. + + - wxHashMap used to access properties by name uses 'const wxChar*' instead of 'wxString'. + Altough this has somewhat lower performance if used mostly with wxStrings, it is much + faster if a lot of non-wxString strings are used, since they don't have to be + recreated as wxString before using with the hashmap. + If you want to change this behaviour, see propertygrid.h. Comment current version + (including wxPGNameStr), and uncomment version that uses wxString. + Note that with unicode, wxString is always used (due to some weird issues). + + - If wxPG_DOUBLE_BUFFER is 1 (default for MSW, GTK and MAC), wxPropertyGrid::OnDrawItems + composes the image on a wxMemoryDC. This effectively eliminates flicker caused by drawing + itself (property editor controls are another matter). + + - Under wxMSW, flicker freedom when creating native editor controls is achieved by using + following undocumented scheme: + \code + wxControl* ctrl = new wxControl(); + #ifdef __WXMSW__ + ctrl->Hide(); + #endif + ctrl->Create(parent,id,...); + + ...further initialize, move, resize, etc... + + #ifdef __WXMSW__ + ctrl->Show(); + #endif + \endcode + + \section crossplatform Crossplatform Notes (not necessarily wxPropertyGrid specific) + + - GTK1: When showing a dialog you may encounter invisible font! + Solution: Set parent's font using SetOwnFont instead of SetFont. + + - GTK: Your own control can overdraw wxGTK wxWindow border! + + - wxWindow::SetSizeHints may be necessary to shrink controls below certain treshold, + but only on some platforms. For example wxMSW might allow any shrinking without + SetSizeHints call where wxGTK might not. + + - GTK Choice (atleast, maybe other controls as well) likes its items set + in constructor. Appending them seems to be slower (Freeze+Thaw won't help). + Even using Append that gets wxArrayString argument may not be good, since it + may just append every string one at a time. + + + \section newprops Creating New Properties (Updated!) + + Easiest solution for creating an arbitrary property is to subclass an existing, + inheritable property that has the desired value type and editor. Property class + to derive from is always property name + Class, for instance wxStringPropertyClass in + case of wxStringProperty. You need to include header file wx/propgrid/propdev.h, + specify a mandatory constructor, and override some virtual member functions (see + wxPGProperty and wxPGPropertyWithChildren). + + For instance: + + \code + + #include + + // wxLongStringProperty has wxString as value type and TextCtrlAndButton as editor. + class MyStringPropertyClass : public wxLongStringPropertyClass + { + public: + + // Normal property constructor. + MyStringPropertyClass(const wxString& name, + const wxString& label = wxPG_LABEL, + const wxString& value = wxEmptyString) + : wxLongStringPropertyClass(name,label,value) + { + } + + // Do something special when button is clicked. + virtual bool OnButtonClick(wxPropertyGrid* propGrid, + wxWindow* primaryCtrl) + { + // Update value in case last minute changes were made. + PrepareValueForDialogEditing(propGrid); + + // TODO: Create dialog (m_value has current string, if needed) + + int res = dlg.ShowModal(); + if ( res == wxID_OK && dlg.IsModified() ) + { + DoSetValue(dlg.GetString()); + UpdateControl(primaryCtrl); + return true; + } + + return false; + } + + protected: + }; + + \endcode + + You can then create a property instance with new keyword (as factory function + is absent since macros are not used), for instance: + + \code + + pg->Append( new MyStringPropertyClass(name,label,value) ); + + \endcode + + If you want to change editor used, use code like below (continues our sample above). + + Note that built-in editors include: TextCtrl, Choice, ComboBox, TextCtrlAndButton, + ChoiceAndButton, CheckBox, SpinCtrl, and DatePickerCtrl. + + \code + + // In class body: + virtual const wxPGEditor* DoGetEditorClass() const + { + return wxPG_EDITOR(TextCtrl); + } + + \endcode + + If you want to change value type used, use code like below. + + However, first a word on value types: They are essentially wxPGValueType instances holding + reimplemented member functions for handling specific type of data. Use wxPG_VALUETYPE(ValueType) + to get pointer, altought this should usually not be necessary outside GetValueType. Lightweight + wxPGVariant is used to convey value to (DoSetValue) and from (DoGetValue) property. For common + and small types such as long and bool, the entire value is stored in wxPGVariant. For large + types (even double!), only a pointer is stored. This is sufficient since property instance + is responsible for storing its value. + + Built-in value types include: wxString, long, bool, double, void, + wxArrayString. advprops.h also has: wxFont, wxColour, wxArrayInt. See below + for more information about implementing your own value types. + + \code + + // In class body: + public: + + // Minimal constructor must set the new value. + MyPropertyClass(const wxString& name, + const wxString& label = wxPG_LABEL, + UsedDataType value = DefaultValue) + : wxInheritedPropertyClass(name,label,OtherDefaultValue) + { + m_value2 = value; + } + + virtual const wxPGValueType* GetValueType() const + { + return wxPG_VALUETYPE(UsedDataType); + } + + virtual void DoSetValue(wxPGVariant value) + { + // TODO: Retrieve value from wxPGVariant. For simple types, + // you can use: + // + // UsedDataType val = value.GetFoo(); // Like GetString, or GetLong, similar to wxVariant + // + // For complex types, use: + // + // UsedDataType* pVal = (UsedDataType*) wxPGVariantToVoidPtr(value); + // + // - OR - + // + // UsedDataType* pVal = wxPGVariantToWxObjectPtr(value,UsedDataType); + // wxASSERT(ptr); // Since its NULL if type-checking failed + // + + // TODO: Store value to m_value2; + } + + virtual wxPGVariant DoGetValue() const + { + // TODO: Return value as wxPGVariant. + // + // For simple types, return the entire value. For example: + // + // return wxPGVariant(m_value2); + // + // For complex types, return pointer. For example: + // + // return wxPGVariant((void*)&m_value2); + } + + virtual wxString GetValueAsString(int argFlags) const + { + // TODO: If (argFlags & wxPG_FULL_VALUE), then return storable + // (to config, database, etc) string. Otherwise return + // shown string. + } + + virtual bool SetValueFromString(const wxString& text, + int WXUNUSED(argFlags)) + { + // TODO: Set value from given string (which is same as previously + // returned from GetValueAsString(wxPG_FULL_VALUE)). Return + // true if value was actually changed. + } + + protected: + UsedDataType m_value2; + + \endcode + + If you want to add support for the internal RTTI scheme, use code like this: + + \code + + // In private portion of class body: + WX_PG_DECLARE_CLASSINFO() + + // In source file: + WX_PG_IMPLEMENT_CLASSINFO(MyStringProperty,wxLongStringProperty) + wxPG_GETCLASSNAME_IMPLEMENTATION(MyStringProperty) + + \endcode + + + \remarks + - For practical examples of arbitrary properties, please take a look + at the sample properties in contrib/samples/propgrid/sampleprops.cpp. + - Read wxPGProperty and wxPGPropertyWithChildren class documentation to + find out what each virtual member function should do. + - Value for property is usually stored in a member named m_value. + - Documentation below may be helpful (altough you'd probably do better + by looking at the sample properties first). + + \subsection methoda Macro Pairs + + These are quick methods for creating customized properties. + + \subsubsection custstringprop String Property with Button + + This custom property will be exactly the same as wxLongStringProperty, + except that you can specify a custom code to handle what happens + when the button is pressed. + + In header: + \code + WX_PG_DECLARE_STRING_PROPERTY(PROPNAME) + \endcode + + In source: + \code + + #include + + // FLAGS can be wxPG_NO_ESCAPE if escape sequences shall not be expanded. + WX_PG_IMPLEMENT_STRING_PROPERTY(PROPNAME, FLAGS) + + bool PROPNAMEClass::OnButtonClick( wxPropertyGrid* propgrid, wxString& value ) + { + // + // TODO: Show dialog, read initial string from value. If changed, + // store new string to value and return TRUE. + // + } + \endcode + + FLAGS is either wxPG_NO_ESCAPE (newlines and tabs are not translated to and + from escape sequences) or wxPG_ESCAPE (newlines and tabs are transformed + into C-string escapes). + + There is also WX_PG_IMPLEMENT_STRING_PROPERTY_WITH_VALIDATOR variant which + also allows setting up a validator for the property. Like this: + + \code + + #include + + WX_PG_IMPLEMENT_STRING_PROPERTY_WITH_VALIDATOR(PROPNAME, FLAGS) + + bool PROPNAMEClass::OnButtonClick( wxPropertyGrid* propgrid, wxString& value ) + { + // + // TODO: Show dialog, read initial string from value. If changed, + // store new string to value and return TRUE. + // + } + + wxValidator* PROPNAMEClass::DoGetValidator() const + { + // + // TODO: Return pointer to a new wxValidator instance. In most situations, + // code like this should work well: + // + // WX_PG_DOGETVALIDATOR_ENTRY() + // + // wxMyValidator* validator = new wxMyValidator(...); + // + // ... prepare validator... + // + // WX_PG_DOGETVALIDATOR_EXIT(validator) + // + // Macros are used to maintain only one actual validator instance + // (ie. on a second call, function exits within the first macro). + // + // For real examples, search props.cpp for ::DoGetValidator, it should + // have several. + // + } + \endcode + + \subsubsection custflagsprop Custom Flags Property + Flags property with custom default value and built-in labels/values. + + In header: + \code + WX_PG_DECLARE_CUSTOM_FLAGS_PROPERTY(PROPNAME) + \endcode + + In source: + \code + + #include + + // LABELS are VALUES are as in the arguments to wxFlagsProperty + // constructor. DEFVAL is the new default value (normally it is 0). + WX_PG_IMPLEMENT_CUSTOM_FLAGS_PROPERTY(PROPNAME,LABELS,VALUES,DEFAULT_FLAGS) + \endcode + + The new property class will have simple (label,name,value) constructor. + + \subsubsection custenumprop Custom EnumProperty + + Exactly the same as custom FlagsProperty. Simply replace FLAGS with ENUM in + macro names to create wxEnumProperty based class instead. + + \subsubsection custarraystringprop Custom ArrayString property + + This type of custom property allows selecting different string delimiter + (default is '"' on both sides of the string - as in C code), and allows + adding custom button into the editor dialog. + + In header: + \code + WX_PG_DECLARE_ARRAYSTRING_PROPERTY(wxMyArrayStringProperty) + \endcode + + In source: + + \code + + #include + + // second argument = string delimiter. '"' for C string style (default), + // and anything else for str1 str2 str3 style + // (so for example, using ';' would result to str1; str2; str3). + // third argument = const wxChar* text for the custom button. If NULL + // then no button is added. + WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY(wxMyArrayStringProperty,',',wxT("Browse")) + + bool wxMyArrayStringPropertyClass::OnCustomStringEdit (wxWindow* parent, + wxString& value) + { + // + // TODO: Show custom editor dialog, read initial string from value. + // If changed, store new string to value and return TRUE. + // + } + + \endcode + + \subsubsection custcolprop Custom ColourProperty + + wxColourProperty/wxSystemColourProperty that can have custom list of colours + in dropdown. + + Use version that doesn't have _USES_WXCOLOUR in macro names to have + wxColourPropertyValue as value type instead of plain wxColour (in this case + values array might also make sense). + + In header: + \code + #include + WX_PG_DECLARE_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR(wxMyColourProperty) + \endcode + + In source: + + \code + + #include + + // Colour labels. Last (before NULL, if any) must be Custom. + static const wxChar* mycolprop_labels[] = { + wxT("Black"), + wxT("Blue"), + wxT("Brown"), + wxT("Custom"), + (const wxChar*) NULL + }; + + // Relevant colour values as unsigned longs. + static unsigned long mycolprop_colours[] = { + wxPG_COLOUR(0,0,0), + wxPG_COLOUR(0,0,255), + wxPG_COLOUR(166,124,81), + wxPG_COLOUR(0,0,0) + }; + + // Implement property class. Third argument is optional values array, + // but in this example we are only interested in creating a shortcut + // for user to access the colour values. + WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR(wxMyColourProperty, + mycolprop_labels, + (long*)NULL, + mycolprop_colours) + \endcode + + \subsection declaring Declaring an Arbitrary Property + + To make your property available globally, you need to declare it in a + header file. Usually you would want to use WX_PG_DECLARE_PROPERTY + macro to do that (it is defined in propgrid.h). It has three arguments: PROPNAME, + T_AS_ARG and DEFVAL. PROPNAME is property NAME (eg. wxStringProperty), + T_AS_ARG is type input in function argument list (eg. "int" for int value type, + "const wxString&" for wxString value type, etc.), and DEFVAL is default value for that. + + For example: + + \code + + // Declare wxRealPoint Property in the header + WX_PG_DECLARE_PROPERTY(wxRealPointProperty,const wxRealPoint&,wxRealPoint(0.0,0.0)) + + \endcode + + There is also WX_PG_DECLARE_PROPERTY_WITH_DECL which takes an additional declaration + argument (export, for example, when exporting from a dll). + + If you want that your property could be inherited from, then you would also + have to define the class body in the header file. In most cases this is probably not + necessary and the class can be defined and implemented completely in the source. + In the case of wxPropertyGrid library, most property classes are defined in + propdev.h to allow them to be inherited from, but . + + \subsection implementing Implementing a Property + + First there is class body with WX_PG_DECLARE_PROPERTY_CLASS macro, + constructor, virtual destructor, and declarations for other overridden + methods. Then comes WX_PG_IMPLEMENT_PROPERTY_CLASS macro, and + after that class method implementations. + + \subsection Tips + + - To get property's parent grid, call GetGrid(). + + \subsection valuetypes Creating New Value Types + + If you want to a property to use a value type that is not among the + builtin types, then you need to create a new property value type. It is + quite straightforward, using two macros. + + In header, use WX_PG_DECLARE_VALUE_TYPE(DATATYPE), like this: + + \code + // Example: Declare value type for wxRealPoint. + WX_PG_DECLARE_VALUE_TYPE(wxRealPoint) + \endcode + + If, however, class of your value type does not inherit from + wxObject, and you need to use it in wxVariant list used as a + persistent storage (for example, see wxPropertyGrid::GetPropertyValues), + then use this instead, as it also declares a necessary wxVariantData_DATATYPE + class. + + \code + // Example: Declare value type and wxVariantData class for wxRealPoint. + WX_PG_DECLARE_VALUE_TYPE_VOIDP(wxRealPoint) + \endcode + + There are also _WITH_DECL versions of both. + + However, there are a few different implement macros to place in + a source file. Pick one according to the type of type. + + \code + + // For implementing value type for a wxObject based class. + WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(TYPE,DEFPROPERTY,DEFVAL) + + // Same as above, except that an instance of TYPE is + // stored in class. Thus, DEFVAL can be any expression + // that can be assigned to the type. + WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ_OWNDEFAULT(TYPE,DEFPROPERTY,DEFVAL) + + // For implementing value type for a non-wxObject based class. + // Like with ...WXOBJ_OWNDEFAULT macro above, instance of TYPE + // is stored and DEFVAL can be any expression. + WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_SIMPLE(TYPE,DEFPROPERTY,DEFVAL) + + // Like above, but also implement the wxVariantData class + // declared with the second kind of value type declare macro. + WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP(TYPE,DEFPROPERTY,DEFVAL) + + // Like above, but accepts a custom wxVariantData class. + // You need to use WX_PG_DECLARE_VALUE_TYPE with this instead + // of _VOIDP version. + WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_CVD(TYPE,DEFPROPERTY,DEFVAL,VARIANTDATACLASS) + + // For implementing value type with different default value. + // NOTE: With this type you need to use wxPG_INIT_REQUIRED_TYPE2 + // instead of wxPG_INIT_REQUIRED_TYPE. + WX_PG_IMPLEMENT_DERIVED_TYPE(TYPENAME,PARENTVT,DEFVAL) + + // For implementing value type for a POD (plain 'ol data) value. + // Generally should not be used since it is meant for + // wxString, int, double etc. which are already implemented. + WX_PG_IMPLEMENT_VALUE_TYPE(TYPE,DEFPROPERTY,TYPESTRING,GETTER,DEFVAL) + + \endcode + + Argument descriptions: + + TYPE - Actual data type represented by the value type, or if + derived type, any custom name. + + DEFPROPERY - Name of the property that will edit this + value type by default. + + DEFVAL - Default value for the property. + + TYPENAME - An arbitraty typename for this value type. Applies + only to the derived type. + + PARENTVT - Name of parent value type, from which this derived + type inherits from. + + \remarks + - Your class, which you create value type for, must have a + copy constructor. + + \section neweditors Creating Custom Property Editor + + - See the sources of built-in editors in contrib/src/propgrid/propgrid.cpp + (search for wxPGTextCtrlEditor). + + - For additional information, see wxPGEditor class reference + + \subsection wxpythoneditors In wxPython + + - See README-propgrid-wxPython.txt + +*/ + +#endif // __WX_PG_DOX_MAINPAGE_H__ + diff --git a/assdraw/libpropgrid/include/wx/propgrid/propdev.h b/assdraw/libpropgrid/include/wx/propgrid/propdev.h new file mode 100644 index 000000000..8db14757f --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/propdev.h @@ -0,0 +1,1694 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: propdev.h +// Purpose: wxPropertyGrid Internal/Property Developer Header +// Author: Jaakko Salli +// Modified by: +// Created: Nov-23-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PROPGRID_PROPDEV_H_ +#define _WX_PROPGRID_PROPDEV_H_ + +// ----------------------------------------------------------------------- + +#ifdef _WX_PROPGRID_ADVPROPS_H_ + #error "propdev.h must be included *before* advprops.h" +#endif + + +class WXDLLIMPEXP_PG wxArrayEditorDialog; + +// ----------------------------------------------------------------------- + +// These are intuitive substitutes for base property classes. +typedef wxPGProperty wxBasePropertyClass; +typedef wxPGPropertyWithChildren wxBaseParentPropertyClass; + +// ----------------------------------------------------------------------- + +#ifndef SWIG + +// This is required for sharing common global variables. +// TODO: Automatic locking mechanism? +class WXDLLIMPEXP_PG wxPGGlobalVarsClass +{ +public: + + wxPGGlobalVarsClass(); + ~wxPGGlobalVarsClass(); + + wxString m_pDefaultImageWildcard; // Used by advprops, but here to make things easier. + + //wxArrayPtrVoid m_arrEditorClasses; // List of editor class instances. + wxPGHashMapS2P m_mapEditorClasses; // Map of editor class instances (keys are name string). + +#if wxUSE_VALIDATORS + wxArrayPtrVoid m_arrValidators; // These wxValidators need to be freed +#endif + + wxPGHashMapS2P m_dictValueType; // Valuename -> Value type object instance. + +#if wxPG_VALUETYPE_IS_STRING + wxPGHashMapS2P m_dictValueTypeByClass; // VTClassname -> Value type object instance. +#endif + + wxPGHashMapS2P m_dictPropertyClassInfo; // PropertyName -> ClassInfo + + wxPGChoices* m_fontFamilyChoices; + + int m_numBoolChoices; // 2 or 3 + + wxString m_boolChoices[3]; // default is ["False", "True"]. Extra space is for "Unspecified". + + bool m_autoGetTranslation; // If true then some things are automatically translated + + int m_offline; // > 0 if errors cannot or should not be shown in statusbar etc. + +/*#if wxUSE_THREADS + wxCriticalSection m_critSect; // To allow different property grids to be addressed from different threads +#endif*/ +}; + +extern WXDLLIMPEXP_PG wxPGGlobalVarsClass* wxPGGlobalVars; + +#endif + + +/* +#define wxPGUnRefChoices(PCHOICESDATA) \ + PCHOICESDATA->UnRef() +*/ + +// TODO: This locks on Linux, fix it! +/*#if wxUSE_THREADS + #define WX_PG_GLOBALS_LOCKER() \ + wxCriticalSectionLocker _globalVarsLocker_(wxPGGlobalVars->m_critSect); +#else*/ + #define WX_PG_GLOBALS_LOCKER() +//#endif + +// ----------------------------------------------------------------------- +// wxPGEditor class. + + +// Needed for wxPython bindings +class wxPGWindowPair +{ +public: + wxPGWindowPair() + { + m_primary = m_secondary = NULL; + } + + wxWindow* m_primary; + wxWindow* m_secondary; + +#ifndef SWIG + wxPGWindowPair( wxWindow* a ) + { + m_primary = a; + m_secondary = NULL; + }; + wxPGWindowPair( wxWindow* a, wxWindow* b ) + { + m_primary = a; + m_secondary = b; + }; +#endif +}; + + +/** \class wxPGEditor + \ingroup classes + \brief Base for property editor classes. + \remarks + - Event handling: + wxPGEditor::CreateControls should Connect all necessary events to the + wxPropertyGrid::OnCustomEditorEvent. For Example: + \code + // Relays wxEVT_COMMAND_TEXT_UPDATED events of primary editor + // control to the OnEvent. + // NOTE: This event in particular is actually automatically conveyed, but + // it is just used as an example. + propgrid->Connect( wxPG_SUBID1, wxEVT_COMMAND_TEXT_UPDATED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent ); + \endcode + OnCustomEditorEvent will then forward events, first to wxPGEditor::OnEvent + and then to wxPGProperty::OnEvent. + - You need to call macro wxPGRegisterEditorClass(EditorName) before using a custom editor class. + - See propgrid.cpp for how builtin editors works (starting from wxPGTextCtrlEditor). +*/ +class WXDLLIMPEXP_PG wxPGEditor +{ +public: + + /** Constructor. */ + wxPGEditor() + { + #if defined(__WXPYTHON__) + m_scriptObject = NULL; + #endif + } + + /** Destructor. */ + virtual ~wxPGEditor(); + + /** Returns pointer to the name of the editor. For example, wxPG_EDITOR(TextCtrl) + has name "TextCtrl". This method is autogenerated for custom editors. + */ + virtual wxPG_CONST_WXCHAR_PTR GetName() const = 0; + + /** Instantiates editor controls. + \remarks + - Primary control shall use id wxPG_SUBID1, and secondary (button) control + shall use wxPG_SUBID2. + \param propgrid + wxPropertyGrid to which the property belongs (use as parent for control). + \param propert + Property for which this method is called. + \param pos + Position, inside wxPropertyGrid, to create control(s) to. + \param size + Initial size for control(s). + \param psecondary + If method generates a secondary (button) control, pointer to it must + be stored here. + */ +#ifndef __WXPYTHON__ + virtual wxWindow* CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz, wxWindow** psecondary ) const = 0; + #define wxPG_DECLARE_CREATECONTROLS \ + virtual wxWindow* CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, \ + const wxPoint& pos, const wxSize& sz, wxWindow** psecondary ) const; +#else + virtual wxPGWindowPair CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz ) const = 0; + #define wxPG_DECLARE_CREATECONTROLS \ + virtual wxPGWindowPair CreateControls( wxPropertyGrid* propgrid, wxPGProperty* property, \ + const wxPoint& pos, const wxSize& sz ) const; +#endif + + /** Loads value from property to the control. */ + virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const = 0; + + /** Used to draw the value when control is hidden. Default is to draw a string. + Note that some margin above and below has been taken into account, to make + drawing text easier without giving loads parameters. If Pen is changed, + it must be returned to *wxTRANSPARENT_PEN. + */ + virtual void DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const; + + /** Handles events. Returns true if value in control was modified + (see wxPGProperty::OnEvent for more information). + */ + virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, + wxWindow* wnd_primary, wxEvent& event ) const = 0; + + /** Copies value from ctrl to property's internal storage. + Returns true if value was different. + */ + virtual bool CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const = 0; + + /** Sets value in control to unspecified. */ + virtual void SetValueToUnspecified( wxWindow* ctrl ) const = 0; + + /** Sets control's value specifically from string. */ + virtual void SetControlStringValue( wxWindow* ctrl, const wxString& txt ) const; + + /** Sets control's value specifically from int (applies to choice etc.). */ + virtual void SetControlIntValue( wxWindow* ctrl, int value ) const; + + /** Inserts item to existing control. Index -1 means appending. + Default implementation does nothing. Returns index of item added. + */ + virtual int InsertItem( wxWindow* ctrl, const wxString& label, int index ) const; + + /** Deletes item from existing control. + Default implementation does nothing. + */ + virtual void DeleteItem( wxWindow* ctrl, int index ) const; + + /** Extra processing when control gains focus. For example, wxTextCtrl + based controls should select all text. + */ + virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const; + + /** Returns true if control itself can contain the custom image. Default is + to return false. + */ + virtual bool CanContainCustomImage() const; + +#if defined(__WXPYTHON__) && !defined(SWIG) + // This is the python object that contains and owns the C++ representation. + PyObject* m_scriptObject; +#endif + +protected: +}; + + +//#ifndef SWIG +#if 1 + + +#define WX_PG_DECLARE_EDITOR_CLASS() \ +public: \ + virtual wxPG_CONST_WXCHAR_PTR GetName() const; \ +private: + + +#define WX_PG_IMPLEMENT_EDITOR_CLASS(EDITOR,CLASSNAME,BASECLASS) \ +wxPG_CONST_WXCHAR_PTR CLASSNAME::GetName() const \ +{ \ + return wxT(#EDITOR); \ +} \ +wxPGEditor* wxPGEditor_##EDITOR = (wxPGEditor*) NULL; \ +wxPGEditor* wxPGConstruct##EDITOR##EditorClass() \ +{ \ + wxASSERT( !wxPGEditor_##EDITOR ); \ + return new CLASSNAME(); \ +} + + +#define WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS() \ +wxPG_DECLARE_CREATECONTROLS \ +virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const; \ +virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, \ + wxWindow* primary, wxEvent& event ) const; \ +virtual bool CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const; \ +virtual void SetValueToUnspecified( wxWindow* ctrl ) const; + + +// +// Following are the built-in editor classes. +// + +class WXDLLIMPEXP_PG wxPGTextCtrlEditor : public wxPGEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGTextCtrlEditor() {} + virtual ~wxPGTextCtrlEditor(); + + WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS() + + virtual void DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const; + virtual void SetControlStringValue( wxWindow* ctrl, const wxString& txt ) const; + virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const; + + // Provided so that, for example, ComboBox editor can use the same code + // (multiple inheritance would get way too messy). + static bool OnTextCtrlEvent( wxPropertyGrid* propgrid, + wxPGProperty* property, + wxWindow* ctrl, + wxEvent& event ); + + static bool CopyTextCtrlValueFromControl( wxPGProperty* property, wxWindow* ctrl ); + +}; + + +class WXDLLIMPEXP_PG wxPGChoiceEditor : public wxPGEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGChoiceEditor() {} + virtual ~wxPGChoiceEditor(); + + WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS() + + virtual void SetControlIntValue( wxWindow* ctrl, int value ) const; + virtual void SetControlStringValue( wxWindow* ctrl, const wxString& txt ) const; + + virtual int InsertItem( wxWindow* ctrl, const wxString& label, int index ) const; + virtual void DeleteItem( wxWindow* ctrl, int index ) const; + virtual bool CanContainCustomImage() const; + + // CreateControls calls this with CB_READONLY in extraStyle + wxWindow* CreateControlsBase( wxPropertyGrid* propgrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + long extraStyle ) const; + +}; + + +class WXDLLIMPEXP_PG wxPGComboBoxEditor : public wxPGChoiceEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGComboBoxEditor() {} + virtual ~wxPGComboBoxEditor(); + + wxPG_DECLARE_CREATECONTROLS // Macro is used for conviency due to different signature with wxPython + + virtual void UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const; + + virtual bool OnEvent( wxPropertyGrid* propgrid, wxPGProperty* property, + wxWindow* ctrl, wxEvent& event ) const; + + virtual bool CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const; + + virtual void OnFocus( wxPGProperty* property, wxWindow* wnd ) const; + +}; + + +class WXDLLIMPEXP_PG wxPGChoiceAndButtonEditor : public wxPGChoiceEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGChoiceAndButtonEditor() {} + virtual ~wxPGChoiceAndButtonEditor(); + wxPG_DECLARE_CREATECONTROLS // Macro is used for conviency due to different signature with wxPython +}; + + +class WXDLLIMPEXP_PG wxPGTextCtrlAndButtonEditor : public wxPGTextCtrlEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGTextCtrlAndButtonEditor() {} + virtual ~wxPGTextCtrlAndButtonEditor(); + wxPG_DECLARE_CREATECONTROLS +}; + + +#if wxPG_INCLUDE_CHECKBOX + +// +// Use custom check box code instead of native control +// for cleaner (ie. more integrated) look. +// +class WXDLLIMPEXP_PG wxPGCheckBoxEditor : public wxPGEditor +{ + WX_PG_DECLARE_EDITOR_CLASS() +public: + wxPGCheckBoxEditor() {} + virtual ~wxPGCheckBoxEditor(); + + WX_PG_IMPLEMENT_EDITOR_CLASS_STD_METHODS() + + virtual void DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const; + + virtual void SetControlIntValue( wxWindow* ctrl, int value ) const; +}; + +#endif + +#endif // SWIG + + +// ----------------------------------------------------------------------- +// Value type registeration macros + +#define wxPGRegisterValueType(TYPENAME) \ + if ( wxPGValueType_##TYPENAME == (wxPGValueType*) NULL ) \ + { \ + wxPGValueType_##TYPENAME = wxPropertyGrid::RegisterValueType( wxPGNewVT##TYPENAME(), false, wxT(#TYPENAME) ); \ + } + +// Use this in RegisterDefaultValues. +#define wxPGRegisterDefaultValueType(TYPENAME) \ + if ( wxPGValueType_##TYPENAME == (wxPGValueType*) NULL ) \ + { \ + wxPGValueType_##TYPENAME = wxPropertyGrid::RegisterValueType( new wxPGValueType##TYPENAME##Class, true, wxT(#TYPENAME) ); \ + } + +#define wxPG_INIT_REQUIRED_TYPE(T) \ + wxPGRegisterValueType(T) + +// Use this with 'simple' value types (derived) +#define wxPG_INIT_REQUIRED_TYPE2(T) \ + if ( wxPGValueType_##T == (wxPGValueType*) NULL ) \ + { \ + wxPGValueType_##T = wxPropertyGrid::RegisterValueType( new wxPGValueType##T##Class, false, wxT(#T) ); \ + } + +// ----------------------------------------------------------------------- +// Editor class registeration macros + +#define wxPGRegisterEditorClass(EDITOR) \ + if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \ + { \ + wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( wxPGConstruct##EDITOR##EditorClass(), wxT(#EDITOR) ); \ + } + +// Use this in RegisterDefaultEditors. +#define wxPGRegisterDefaultEditorClass(EDITOR) \ +if ( wxPGEditor_##EDITOR == (wxPGEditor*) NULL ) \ + { \ + wxPGEditor_##EDITOR = wxPropertyGrid::RegisterEditorClass( wxPGConstruct##EDITOR##EditorClass(), wxT(#EDITOR), true ); \ + } + +#define wxPG_INIT_REQUIRED_EDITOR(T) \ + wxPGRegisterEditorClass(T) + +// ----------------------------------------------------------------------- + +#define WX_PG_IMPLEMENT_SUBTYPE(VALUETYPE,CVALUETYPE,DEFPROPERTY,TYPESTRING,GETTER,DEFVAL) \ +const wxPGValueType *wxPGValueType_##VALUETYPE = (wxPGValueType*) NULL; \ +class wxPGValueType##VALUETYPE##Class : public wxPGValueType \ +{ \ +public: \ + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return TYPESTRING; } \ + virtual wxPGVariant GetDefaultValue() const { return wxPGVariantCreator(m_default); } \ + virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const \ + { return wxVariant( value.GETTER(), name ); } \ + virtual wxPGProperty* GenerateProperty( const wxString& label, const wxString& name ) const \ + { \ + return wxPG_CONSTFUNC(DEFPROPERTY)(label,name); \ + } \ + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const \ + { \ + wxPG_CHECK_RET_DBG( wxStrcmp(GetTypeName(),value.GetType().c_str()) == 0, \ + wxT("SetValueFromVariant: wxVariant type mismatch.") ); \ + property->DoSetValue(value.GETTER()); \ + } \ + wxPGValueType##VALUETYPE##Class(); \ + virtual ~wxPGValueType##VALUETYPE##Class(); \ +protected: \ + CVALUETYPE m_default; \ +}; \ +wxPGValueType##VALUETYPE##Class::wxPGValueType##VALUETYPE##Class() { m_default = DEFVAL; } \ +wxPGValueType##VALUETYPE##Class::~wxPGValueType##VALUETYPE##Class() { } + +#define WX_PG_IMPLEMENT_VALUE_TYPE(VALUETYPE,DEFPROPERTY,TYPESTRING,GETTER,DEFVAL) \ +WX_PG_IMPLEMENT_SUBTYPE(VALUETYPE,VALUETYPE,DEFPROPERTY,TYPESTRING,GETTER,DEFVAL) + +// +// Implements wxVariantData for the type. +// +#define WX_PG_IMPLEMENT_VALUE_TYPE_VDC(VDCLASS,VALUETYPE) \ +WX_PG_IMPLEMENT_DYNAMIC_CLASS_VARIANTDATA(VDCLASS,wxVariantData) \ +VDCLASS::VDCLASS() { } \ +VDCLASS::VDCLASS(const VALUETYPE& value) \ +{ \ + m_value = value; \ +} \ +void VDCLASS::Copy(wxVariantData& data) \ +{ \ + wxPG_CHECK_RET_DBG( data.GetType() == GetType(), wxT(#VDCLASS) wxT("::Copy: Can't copy to this type of data") ); \ + VDCLASS& otherData = (VDCLASS&) data; \ + otherData.m_value = m_value; \ +} \ +wxString VDCLASS::GetType() const \ +{ \ + return wxString(wxT(#VALUETYPE)); \ +} \ +bool VDCLASS::Eq(wxVariantData& data) const \ +{ \ + wxPG_CHECK_MSG_DBG( data.GetType() == GetType(), false, wxT(#VDCLASS) wxT("::Eq: argument mismatch") ); \ + VDCLASS& otherData = (VDCLASS&) data; \ + return otherData.m_value == m_value; \ +} \ +void* VDCLASS::GetValuePtr() { return (void*)&m_value; } + + +#define WX_PG_GENVARIANT_WXOBJ_BASE(VALUETYPE) \ +virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const \ +{ return wxVariant( new wxVariantData_##VALUETYPE( (*(VALUETYPE*)wxPGVariantGetWxObjectPtr(value)) ), name ); } + +#define WX_PG_GENVARIANT_VOIDP_SIMPLE() \ +virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const \ +{ \ + void* ptr = (void*)wxPGVariantToVoidPtr(value); \ + wxASSERT( ptr ); \ + if ( !ptr ) return wxVariant(); \ + return wxVariant( ptr, name ); \ +} + +#define WX_PG_GENVARIANT_VOIDP_CVD(VDCLASS, VALUETYPE) \ +virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const \ +{ \ + void* ptr = (void*)wxPGVariantToVoidPtr(value); \ + wxASSERT( ptr ); \ + if ( !ptr ) return wxVariant(); \ + return wxVariant( new VDCLASS(*((VALUETYPE*)ptr)), name ); \ +} + + +// TODO: When ready, remove GetValueClassInfo +#define WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ_BASE(VALUETYPE,DEFPROPERTY,DEFVAL) \ +class WX_PG_DECLARE_VALUE_TYPE_VDC(VALUETYPE) \ + virtual wxClassInfo* GetValueClassInfo(); \ +}; \ +WX_PG_IMPLEMENT_VALUE_TYPE_VDC(wxVariantData_##VALUETYPE,VALUETYPE) \ +wxClassInfo* wxVariantData_##VALUETYPE::GetValueClassInfo() \ +{ \ + return m_value.GetClassInfo(); \ +} \ +const wxPGValueType *wxPGValueType_##VALUETYPE = (wxPGValueType*) NULL; \ +class wxPGValueType##VALUETYPE##Class : public wxPGValueType \ +{ \ +public: \ + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return CLASSINFO(VALUETYPE)->GetClassName(); } \ + WX_PG_GENVARIANT_WXOBJ_BASE(VALUETYPE) \ + virtual wxPGProperty* GenerateProperty( const wxString& label, const wxString& name ) const \ + { \ + return wxPG_CONSTFUNC(DEFPROPERTY)(label,name); \ + } \ + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const \ + { \ + const VALUETYPE* real_value; \ + wxPG_CHECK_RET_DBG( wxStrcmp(GetTypeName(),value.GetType().c_str()) == 0, \ + wxT("GetPtrFromVariant: wxVariant type mismatch.") ); \ + wxVariantData_##VALUETYPE* vd = wxDynamicCastVariantData(value.GetData(), wxVariantData_##VALUETYPE); \ + if ( vd ) \ + real_value = &vd->GetValue(); \ + else \ + real_value = ((const VALUETYPE*)value.GetWxObjectPtr()); \ + property->DoSetValue( (wxObject*) real_value ); \ + } + +// This should not be used by built-in types (advprops.cpp types should use it though) +#define WX_PG_IMPLEMENT_VALUE_TYPE_CREATOR(VALUETYPE) \ +wxPGValueType* wxPGNewVT##VALUETYPE() { return new wxPGValueType##VALUETYPE##Class; } + +#define WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ(VALUETYPE,DEFPROPERTY,DEFVAL) \ +WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ_BASE(VALUETYPE,DEFPROPERTY,DEFVAL) \ + virtual wxPGVariant GetDefaultValue() const { return wxPGVariantCreator(DEFVAL); } \ +}; \ +WX_PG_IMPLEMENT_VALUE_TYPE_CREATOR(VALUETYPE) + +#define WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ_OWNDEFAULT(VALUETYPE,DEFPROPERTY,DEFVAL) \ +WX_PG_IMPLEMENT_VALUE_TYPE_WXOBJ_BASE(VALUETYPE,DEFPROPERTY,DEFVAL) \ + wxPGValueType##VALUETYPE##Class() { m_default = DEFVAL; } \ + virtual ~wxPGValueType##VALUETYPE##Class() { } \ + virtual wxPGVariant GetDefaultValue() const { return wxPGVariantCreator((wxObject*)&m_default); } \ +protected: \ + VALUETYPE m_default; \ +}; \ +WX_PG_IMPLEMENT_VALUE_TYPE_CREATOR(VALUETYPE) + + +#define WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_BASE(VALUETYPE,DEFPROPERTY,DEFVAL,VDCLASS) \ +const wxPGValueType *wxPGValueType_##VALUETYPE = (wxPGValueType*)NULL; \ +class wxPGValueType##VALUETYPE##Class : public wxPGValueType \ +{ \ +protected: \ + VALUETYPE m_default; \ +public: \ + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return wxT(#VALUETYPE); } \ + virtual wxPG_CONST_WXCHAR_PTR GetCustomTypeName() const { return wxT(#VALUETYPE); } \ + virtual wxPGVariant GetDefaultValue() const { return wxPGVariantCreator((void*)&m_default); } \ + virtual wxPGProperty* GenerateProperty( const wxString& label, const wxString& name ) const \ + { \ + return wxPG_CONSTFUNC(DEFPROPERTY)(label,name); \ + } \ + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const \ + { \ + wxPG_CHECK_RET_DBG( wxStrcmp(GetTypeName(),value.GetType().c_str()) == 0, \ + wxT("SetValueFromVariant: wxVariant type mismatch.") ); \ + VDCLASS* vd = (VDCLASS*)value.GetData(); \ + wxPG_CHECK_RET_DBG( wxDynamicCastVariantData(vd, VDCLASS), \ + wxT("SetValueFromVariant: wxVariantData mismatch.")); \ + property->DoSetValue((void*)&vd->GetValue() ); \ + } \ + wxPGValueType##VALUETYPE##Class() { m_default = DEFVAL; } \ + virtual ~wxPGValueType##VALUETYPE##Class() { } + + +#define WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_SIMPLE(VALUETYPE,DEFPROPERTY,DEFVAL) \ +WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_BASE(VALUETYPE,DEFPROPERTY,DEFVAL,wxVariantData_##VALUETYPE) \ +WX_PG_GENVARIANT_VOIDP_SIMPLE() \ +}; \ +WX_PG_IMPLEMENT_VALUE_TYPE_CREATOR(VALUETYPE) + + +// If you use this macro in application code, you need to pair it with +// WX_PG_DECLARE_VALUE_TYPE with this instead of _VOIDP version. +#define WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_CVD(VALUETYPE,DEFPROPERTY,DEFVAL,VDCLASS) \ +WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_BASE(VALUETYPE,DEFPROPERTY,DEFVAL,VDCLASS) \ +WX_PG_GENVARIANT_VOIDP_CVD(VDCLASS, VALUETYPE) \ +}; \ +WX_PG_IMPLEMENT_VALUE_TYPE_CREATOR(VALUETYPE) + +#define WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP2(VALUETYPE,DEFPROPERTY,DEFVAL,VDCLASS) \ +WX_PG_IMPLEMENT_VALUE_TYPE_VDC(VDCLASS,VALUETYPE) \ +WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP_CVD(VALUETYPE,DEFPROPERTY,DEFVAL,VDCLASS) + +#define WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP(VALUETYPE,DEFPROPERTY,DEFVAL) \ +WX_PG_IMPLEMENT_VALUE_TYPE_VOIDP2(VALUETYPE,DEFPROPERTY,DEFVAL,wxVariantData_##VALUETYPE) + +// +// Use this to create a new type with a different default value. +// NOTE: With this type you need to use wxPG_INIT_REQUIRED_TYPE2 +// instead of wxPG_INIT_REQUIRED_TYPE. +#define WX_PG_IMPLEMENT_DERIVED_TYPE(VALUETYPE,PARENTVT,DEFVAL) \ +const wxPGValueType *wxPGValueType_##VALUETYPE = (wxPGValueType*) NULL; \ +class wxPGValueType##VALUETYPE##Class : public wxPGValueType \ +{ \ +protected: \ + const wxPGValueType* m_parentClass; \ + PARENTVT m_default; \ +public: \ + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return m_parentClass->GetTypeName(); } \ + virtual wxPG_CONST_WXCHAR_PTR GetCustomTypeName() const { return wxT(#VALUETYPE); } \ + virtual wxPGVariant GetDefaultValue() const { return wxPGVariantCreator(m_default); } \ + virtual wxVariant GenerateVariant ( wxPGVariant value, const wxString& name ) const \ + { return m_parentClass->GenerateVariant(value,name); } \ + virtual wxPGProperty* GenerateProperty ( const wxString& label, const wxString& name ) const \ + { return m_parentClass->GenerateProperty(label,name); } \ + virtual void SetValueFromVariant ( wxPGProperty* property, wxVariant& value ) const \ + { m_parentClass->SetValueFromVariant(property,value); } \ + wxPGValueType##VALUETYPE##Class(); \ + virtual ~wxPGValueType##VALUETYPE##Class(); \ +}; \ +wxPGValueType##VALUETYPE##Class::wxPGValueType##VALUETYPE##Class() \ +{ \ + m_default = DEFVAL; \ + m_parentClass = wxPGValueType_##PARENTVT; \ + wxASSERT( m_parentClass != (wxPGValueType*) NULL); \ +} \ +wxPGValueType##VALUETYPE##Class::~wxPGValueType##VALUETYPE##Class() { } + +// ----------------------------------------------------------------------- + +// +// Additional property class declaration helper macros +// + +#define WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() \ +public: \ + WX_PG_DECLARE_GETCLASSNAME \ + WX_PG_DECLARE_GETCLASSINFO \ +private: + +// ----------------------------------------------------------------------- + +// +// Property class implementation helper macros. +// + +#define WX_PG_DECLARE_PARENTAL_TYPE_METHODS() \ + virtual void DoSetValue ( wxPGVariant value ); \ + virtual wxPGVariant DoGetValue () const; + +#define WX_PG_DECLARE_BASIC_TYPE_METHODS() \ + virtual void DoSetValue ( wxPGVariant value ); \ + virtual wxPGVariant DoGetValue () const; \ + virtual wxString GetValueAsString ( int argFlags = 0 ) const; \ + virtual bool SetValueFromString ( const wxString& text, int flags = 0 ); + +// class WXDLLIMPEXP_PG +#define wxPG_BEGIN_PROPERTY_CLASS_BODY2(CLASSNAME,UPCLASS,T,INTERNAL_T,T_AS_ARG,DECL) \ +DECL CLASSNAME : public UPCLASS \ +{ \ + WX_PG_DECLARE_PROPERTY_CLASS_NOPARENS \ +protected: \ + INTERNAL_T m_value; \ +public: \ + CLASSNAME( const wxString& label, const wxString& name, T_AS_ARG value ); \ + virtual ~CLASSNAME(); + +#define wxPG_BEGIN_PROPERTY_CLASS_BODY(NAME,UPCLASS,T,T_AS_ARG) \ +wxPG_BEGIN_PROPERTY_CLASS_BODY2(wxPG_PROPCLASS(NAME),UPCLASS,T,T,T_AS_ARG,class) + +#define wxPG_BEGIN_PROPERTY_CLASS_BODY_WITH_DECL(NAME,UPCLASS,T,T_AS_ARG,DECL) \ +wxPG_BEGIN_PROPERTY_CLASS_BODY2(wxPG_PROPCLASS(NAME),UPCLASS,T,T,T_AS_ARG,class DECL) + +#define wxPG_END_PROPERTY_CLASS_BODY() \ +}; + +#define WX_PG_DECLARE_CHOICE_METHODS() \ + virtual bool SetValueFromInt( long value, int flags = 0 ); \ + virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + +#define WX_PG_DECLARE_EVENT_METHODS() \ + virtual bool OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event ); + +#define WX_PG_DECLARE_PARENTAL_METHODS() \ + virtual void ChildChanged( wxPGProperty* p ); \ + virtual void RefreshChildren(); + +#define WX_PG_DECLARE_CUSTOM_PAINT_METHODS() \ + virtual wxSize GetImageSize() const; \ + virtual void OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata ); + +#define WX_PG_DECLARE_ATTRIBUTE_METHODS() \ + virtual void SetAttribute( int id, wxVariant& value ); + +#if wxUSE_VALIDATORS + #define WX_PG_DECLARE_VALIDATOR_METHODS() \ + virtual wxValidator* DoGetValidator() const; +#else + #define WX_PG_DECLARE_VALIDATOR_METHODS() +#endif + +#if wxPG_INCLUDE_WXOBJECT + #define wxPG_GETCLASSNAME_IMPLEMENTATION(PROPNAME) +#else + #define wxPG_GETCLASSNAME_IMPLEMENTATION(PROPNAME) \ + static const wxChar* PROPNAME##_ClassName = wxT(#PROPNAME); \ + wxPG_CONST_WXCHAR_PTR PROPNAME##Class::GetClassName() const { return PROPNAME##_ClassName; } +#endif + +// Implements sans constructor function. Also, first arg is class name, not property name. +#define WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(PROPNAME,T,EDITOR) \ +wxPG_GETCLASSNAME_IMPLEMENTATION(PROPNAME) \ +wxPG_VALUETYPE_MSGVAL PROPNAME##Class::GetValueType() const \ +{ \ + return wxPG_VALUETYPE(T); \ +} \ +const wxPGEditor* PROPNAME##Class::DoGetEditorClass() const \ +{ \ + return wxPGEditor_##EDITOR; \ +} + + +#define WX_PG_IMPLEMENT_CLASSINFO(NAME,UPCLASS) \ +static wxPGProperty* NAME##Class2(const wxString& label, const wxString& name) \ +{ \ + return wxPG_CONSTFUNC(NAME)(label,name); \ +} \ +wxPGPropertyClassInfo NAME##ClassInfo = {wxT(#NAME),&UPCLASS##Info,&NAME##Class2}; \ +const wxPGPropertyClassInfo* NAME##Class::GetClassInfo() const \ +{ \ + return &NAME##ClassInfo; \ +} + + +// second constfunc and classinfo is for creating properties w/o value from text +// (should be changed to simpler scheme in 1.2) +#define WX_PG_IMPLEMENT_CONSTFUNC(NAME,T_AS_ARG) \ +wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name, T_AS_ARG value ) \ +{ \ + return new wxPG_PROPCLASS(NAME)(label,name,value); \ +} + +// Adds constructor function as well. +#define WX_PG_IMPLEMENT_PROPERTY_CLASS2(NAME,CLASSNAME,UPCLASS,T,T_AS_ARG,EDITOR) \ +WX_PG_IMPLEMENT_CONSTFUNC(NAME,T_AS_ARG) \ +WX_PG_IMPLEMENT_CLASSINFO(NAME,UPCLASS) \ +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(NAME,T,EDITOR) + +// A regular property +#define WX_PG_IMPLEMENT_PROPERTY_CLASS(NAME,UPNAME,T,T_AS_ARG,EDITOR) \ +WX_PG_IMPLEMENT_PROPERTY_CLASS2(NAME,wxPG_PROPCLASS(NAME),wxPG_PROPCLASS(UPNAME),T,T_AS_ARG,EDITOR) + +// Derived property class is one that inherits from an existing working property +// class, but assumes same value and editor type. +#define WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(NAME,UPNAME,T_AS_ARG) \ +WX_PG_IMPLEMENT_CONSTFUNC(NAME,T_AS_ARG) \ +WX_PG_IMPLEMENT_CLASSINFO(NAME,UPNAME##Class) \ +wxPG_GETCLASSNAME_IMPLEMENTATION(NAME) + +// ----------------------------------------------------------------------- + +#define wxPG_NO_ESCAPE wxPG_PROP_NO_ESCAPE // No escape sequences +#define wxPG_ESCAPE 0 // Escape sequences + +#define WX_PG_IMPLEMENT_STRING_PROPERTY_WITH_VALIDATOR(NAME,FLAGS) \ +class NAME##Class : public wxLongStringPropertyClass \ +{ \ + WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() \ +public: \ + NAME##Class( const wxString& name, const wxString& label, const wxString& value ); \ + virtual ~NAME##Class(); \ + virtual bool OnButtonClick( wxPropertyGrid* propgrid, wxString& value ); \ + WX_PG_DECLARE_VALIDATOR_METHODS() \ +}; \ +WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(NAME,wxLongStringProperty,const wxString&) \ +NAME##Class::NAME##Class( const wxString& name, const wxString& label, const wxString& value ) \ + : wxLongStringPropertyClass(name,label,value) \ +{ \ + m_flags |= FLAGS; \ +} \ +NAME##Class::~NAME##Class() { } + +#if wxUSE_VALIDATORS + +#define WX_PG_IMPLEMENT_STRING_PROPERTY(NAME,FLAGS) \ +WX_PG_IMPLEMENT_STRING_PROPERTY_WITH_VALIDATOR(NAME,FLAGS) \ +wxValidator* wxPG_PROPCLASS(NAME)::DoGetValidator () const \ +{ return (wxValidator*) NULL; } + +#else + +#define WX_PG_IMPLEMENT_STRING_PROPERTY WX_PG_IMPLEMENT_STRING_PROPERTY_WITH_VALIDATOR + +#endif + +// ----------------------------------------------------------------------- + +// This will create interface for wxFlagsProperty derived class +// named CLASSNAME. +#define WX_PG_IMPLEMENT_CUSTOM_FLAGS_PROPERTY2(NAME,CLASSNAME,LABELS,VALUES,DEFVAL) \ +class CLASSNAME : public wxFlagsPropertyClass \ +{ \ + WX_PG_DECLARE_PROPERTY_CLASS() \ +public: \ + CLASSNAME( const wxString& label, const wxString& name, long value ); \ + virtual ~CLASSNAME(); \ +}; \ +WX_PG_IMPLEMENT_DERIVED_TYPE(long_##NAME,long,DEFVAL) \ +WX_PG_IMPLEMENT_PROPERTY_CLASS(NAME,wxFlagsProperty,long_##NAME,long,TextCtrl) \ +CLASSNAME::CLASSNAME( const wxString& label, const wxString& name, long value ) \ + : wxFlagsPropertyClass(label,name,LABELS,VALUES,value!=-1?value:DEFVAL) \ +{ \ + wxPG_INIT_REQUIRED_TYPE2(long_##NAME) \ + m_flags |= wxPG_PROP_STATIC_CHOICES; \ +} \ +CLASSNAME::~CLASSNAME() { } + +#define WX_PG_IMPLEMENT_CUSTOM_FLAGS_PROPERTY(NAME,LABELS,VALUES,DEFVAL) \ +WX_PG_IMPLEMENT_CUSTOM_FLAGS_PROPERTY2(NAME,wxPG_PROPCLASS(NAME),LABELS,VALUES,DEFVAL) + +// ----------------------------------------------------------------------- + +// This will create interface for Enum property derived class +// named CLASSNAME. +#define WX_PG_IMPLEMENT_CUSTOM_ENUM_PROPERTY2(NAME,CLASSNAME,LABELS,VALUES,DEFVAL) \ +class CLASSNAME : public wxEnumPropertyClass \ +{ \ + WX_PG_DECLARE_PROPERTY_CLASS() \ +public: \ + CLASSNAME ( const wxString& label, const wxString& name, int value ); \ + virtual ~CLASSNAME(); \ +}; \ +WX_PG_IMPLEMENT_DERIVED_TYPE(long_##NAME,long,DEFVAL) \ +WX_PG_IMPLEMENT_PROPERTY_CLASS(NAME,wxEnumProperty,long_##NAME,int,Choice) \ +CLASSNAME::CLASSNAME ( const wxString& label, const wxString& name, int value ) \ + : wxEnumPropertyClass(label,name,LABELS,VALUES,value!=-1?value:DEFVAL) \ +{ \ + wxPG_INIT_REQUIRED_TYPE2(long_##NAME) \ + m_flags |= wxPG_PROP_STATIC_CHOICES; \ +} \ +CLASSNAME::~CLASSNAME() { } + +#define WX_PG_IMPLEMENT_CUSTOM_ENUM_PROPERTY(NAME,LABELS,VALUES,DEFVAL) \ +WX_PG_IMPLEMENT_CUSTOM_ENUM_PROPERTY2(NAME,wxPG_PROPCLASS(NAME),LABELS,VALUES,DEFVAL) + +// ----------------------------------------------------------------------- + +// Implementation for user wxColour editor property + +#define WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY2(NAME,CLASSNAME,LABELS,VALUES,COLOURS) \ +class CLASSNAME : public wxPG_PROPCLASS(wxSystemColourProperty) \ +{ \ + WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() \ +public: \ + CLASSNAME( const wxString& label, const wxString& name, \ + const wxColourPropertyValue& value ); \ + virtual ~CLASSNAME (); \ + virtual long GetColour ( int index ); \ +}; \ +static wxPGChoices gs_##NAME##_choicesCache; \ +WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(NAME,wxSystemColourProperty,const wxColourPropertyValue&) \ +CLASSNAME::CLASSNAME( const wxString& label, const wxString& name, \ + const wxColourPropertyValue& value ) \ + : wxPG_PROPCLASS(wxSystemColourProperty)(label,name,LABELS,VALUES,&gs_##NAME##_choicesCache,value ) \ +{ \ + wxPG_INIT_REQUIRED_TYPE(wxColourPropertyValue) \ + m_flags |= wxPG_PROP_TRANSLATE_CUSTOM; \ + DoSetValue ( &m_value ); \ +} \ +CLASSNAME::~CLASSNAME () { } \ +long CLASSNAME::GetColour ( int index ) \ +{ \ + const wxArrayInt& values = GetValues(); \ + if ( !values.GetCount() ) \ + { \ + wxASSERT( index < (int)m_choices.GetCount() ); \ + return COLOURS[index]; \ + } \ + return COLOURS[values[index]]; \ +} + +#define WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY(NAME,LABELS,VALUES,COLOURS) \ + WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY2(NAME,wxPG_PROPCLASS(NAME),LABELS,VALUES,COLOURS) + +// ----------------------------------------------------------------------- + +#define WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(NAME,CLASSNAME,LABELS,VALUES,COLOURS,EDITOR) \ +class CLASSNAME : public wxPG_PROPCLASS(wxSystemColourProperty) \ +{ \ + WX_PG_DECLARE_PROPERTY_CLASS() \ +public: \ + CLASSNAME( const wxString& label, const wxString& name, \ + const wxColour& value ); \ + virtual ~CLASSNAME (); \ + virtual void DoSetValue ( wxPGVariant value ); \ + virtual wxPGVariant DoGetValue() const; \ + virtual wxString GetValueAsString ( int argFlags ) const; \ + virtual long GetColour ( int index ); \ +}; \ +static wxPGChoices gs_##NAME##_choicesCache; \ +WX_PG_IMPLEMENT_PROPERTY_CLASS(NAME,wxSystemColourProperty,wxColour,const wxColour&,EDITOR) \ +CLASSNAME::CLASSNAME( const wxString& label, const wxString& name, const wxColour& value ) \ + : wxPG_PROPCLASS(wxSystemColourProperty)(label,name,LABELS,VALUES,&gs_##NAME##_choicesCache,value ) \ +{ \ + wxPG_INIT_REQUIRED_TYPE(wxColour) \ + m_flags |= wxPG_PROP_TRANSLATE_CUSTOM; \ + DoSetValue(&m_value.m_colour); \ +} \ +CLASSNAME::~CLASSNAME () { } \ +void CLASSNAME::DoSetValue( wxPGVariant value ) \ +{ \ + wxColour* pval = wxPGVariantToWxObjectPtr(value, wxColour); \ + wxCHECK_RET(pval, wxT("NULL wxColour pointer")); \ + m_value.m_type = wxPG_COLOUR_CUSTOM; \ + if ( m_flags & wxPG_PROP_TRANSLATE_CUSTOM ) \ + { \ + int found_ind = ColToInd(*pval); \ + if ( found_ind != wxNOT_FOUND ) m_value.m_type = found_ind; \ + } \ + m_value.m_colour = *pval; \ + if ( m_value.m_type < wxPG_COLOUR_WEB_BASE ) \ + wxPG_PROPCLASS(wxEnumProperty)::DoSetValue ( (long)m_value.m_type ); \ + else \ + m_index = GetItemCount()-1; \ +} \ +wxPGVariant CLASSNAME::DoGetValue() const \ +{ \ + return wxPGVariantCreator(m_value.m_colour); \ +} \ +wxString CLASSNAME::GetValueAsString( int argFlags ) const \ +{ \ + const wxPGEditor* editor = GetEditorClass(); \ + if ( editor != wxPG_EDITOR(Choice) && \ + editor != wxPG_EDITOR(ChoiceAndButton) ) \ + argFlags |= wxPG_PROPERTY_SPECIFIC; \ + return wxSystemColourPropertyClass::GetValueAsString(argFlags); \ +} \ +long CLASSNAME::GetColour( int index ) \ +{ \ + const wxArrayInt& values = GetValues(); \ + if ( !values.GetCount() ) \ + { \ + wxASSERT( index < (int)GetItemCount() ); \ + return COLOURS[index]; \ + } \ + return COLOURS[values[index]]; \ +} + +#define WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR(NAME,LABELS,VALUES,COLOURS) \ + WX_PG_IMPLEMENT_CUSTOM_COLOUR_PROPERTY_USES_WXCOLOUR2(NAME,wxPG_PROPCLASS(NAME),LABELS,VALUES,COLOURS,Choice) + +// ----------------------------------------------------------------------- + +// +// These macros helps creating DoGetValidator +#define WX_PG_DOGETVALIDATOR_ENTRY() \ + WX_PG_GLOBALS_LOCKER() \ + static wxValidator* s_ptr = (wxValidator*) NULL; \ + if ( s_ptr ) return s_ptr; + +// Common function exit +#define WX_PG_DOGETVALIDATOR_EXIT(VALIDATOR) \ + s_ptr = VALIDATOR; \ + wxPGGlobalVars->m_arrValidators.Add( (void*) VALIDATOR ); \ + return VALIDATOR; + +// ----------------------------------------------------------------------- + +// +// Ids for sub-controls +// NB: It should not matter what these are. +#define wxPG_SUBID1 11485 +#define wxPG_SUBID2 11486 +#define wxPG_SUBID_TEMP1 11487 + +// ----------------------------------------------------------------------- + +/** \class wxPGPaintData + \ingroup classes + \brief Contains information relayed to property's OnCustomPaint. +*/ +struct wxPGPaintData +{ + /** wxPropertyGrid. */ + const wxPropertyGrid* m_parent; + + /** Normally -1, otherwise index to drop-down list item that has to be drawn. */ + int m_choiceItem; + + /** Set to drawn width in OnCustomPaint (optional). */ + int m_drawnWidth; + + /** In a measure item call, set this to the height of item at m_choiceItem index. */ + int m_drawnHeight; + + +}; + + +// ----------------------------------------------------------------------- + +#ifndef SWIG + +/** \class wxPGInDialogValidator + \ingroup classes + \brief Creates and manages a temporary wxTextCtrl for validation purposes. + Uses wxPropertyGrid's current editor, if available. +*/ +class WXDLLIMPEXP_PG wxPGInDialogValidator +{ +public: + wxPGInDialogValidator() + { + m_textCtrl = NULL; + } + + ~wxPGInDialogValidator() + { + if ( m_textCtrl ) + m_textCtrl->Destroy(); + } + + bool DoValidate( wxPropertyGrid* propGrid, wxValidator* validator, const wxString& value ); + +private: + wxTextCtrl* m_textCtrl; +}; + +#endif + + +#ifndef DOXYGEN + + +// ----------------------------------------------------------------------- +// Some property class definitions (these should be useful to inherit from). +// ----------------------------------------------------------------------- + +//#ifndef SWIG +#if 1 + +#define wxPG_PROP_PASSWORD wxPG_PROP_CLASS_SPECIFIC_2 + +class WXDLLIMPEXP_PG wxStringPropertyClass : public wxPGProperty +{ + WX_PG_DECLARE_PROPERTY_CLASS_NOPARENS +public: + wxStringPropertyClass( const wxString& label, const wxString& name, const wxString& value ); + virtual ~wxStringPropertyClass(); + + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() + +protected: + wxString m_value; +}; + +// ----------------------------------------------------------------------- + +// This provides base for wxEnumPropertyClass and any custom +// "dynamic" enum property classes. +class WXDLLIMPEXP_PG wxBaseEnumPropertyClass : public wxPGProperty +{ +public: + wxBaseEnumPropertyClass( const wxString& label, const wxString& name ); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int argFlags ) const; + virtual bool SetValueFromString( const wxString& text, int argFlags ); + virtual bool SetValueFromInt( long value, int argFlags ); + + // + // Additional virtuals + + // This must be overridden to have non-index based value + virtual int GetIndexForValue( int value ) const; + + // This returns string and value for index + // Returns NULL if beyond last item + // pvalue is never NULL - always set it. + virtual const wxString* GetEntry( size_t index, int* pvalue ) const = 0; + +protected: + + int m_index; +}; + +// ----------------------------------------------------------------------- + +// If set, then selection of choices is static and should not be +// changed (i.e. returns NULL in GetPropertyChoices). +#define wxPG_PROP_STATIC_CHOICES wxPG_PROP_CLASS_SPECIFIC_1 + +class WXDLLIMPEXP_PG wxEnumPropertyClass : public wxBaseEnumPropertyClass +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + +#ifndef SWIG + wxEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values = NULL, int value = 0 ); + wxEnumPropertyClass( const wxString& label, const wxString& name, + wxPGChoices& choices, int value = 0 ); + + // Special constructor for caching choices (used by derived class) + wxEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, wxPGChoices* choicesCache, int value = 0 ); +#endif + wxEnumPropertyClass( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values = wxArrayInt(), int value = 0 ); + + virtual ~wxEnumPropertyClass(); + + virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + virtual int GetIndexForValue( int value ) const; + virtual const wxString* GetEntry( size_t index, int* pvalue ) const; + + inline size_t GetItemCount() const { return m_choices.GetCount(); } + inline const wxArrayInt& GetValues() const { return m_choices.GetValues(); } + +protected: + wxPGChoices m_choices; +}; + +// ----------------------------------------------------------------------- + +class WXDLLIMPEXP_PG wxFlagsPropertyClass : public wxPGPropertyWithChildren +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + +#ifndef SWIG + wxFlagsPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values = NULL, long value = 0 ); + wxFlagsPropertyClass( const wxString& label, const wxString& name, + wxPGChoices& choices, long value = 0 ); +#endif + wxFlagsPropertyClass( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, int value = 0 ); + virtual ~wxFlagsPropertyClass (); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int argFlags ) const; + virtual bool SetValueFromString( const wxString& text, int flags ); + virtual void ChildChanged( wxPGProperty* p ); + virtual void RefreshChildren(); + + // this is necessary for conveying m_choices + virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + + // helpers + inline size_t GetItemCount() const { return m_choices.GetCount(); } + inline const wxArrayInt& GetValues() const { return m_choices.GetValues(); } + inline const wxString& GetLabel( size_t ind ) const { return m_choices.GetLabel(ind); } + +protected: + wxPGChoices m_choices; + + // Used to detect if choices have been changed + wxPGChoicesData* m_oldChoicesData; + + long m_value; + + // Converts string id to a relevant bit. + long IdToBit( const wxString& id ) const; + + // Creates children and sets value. + void Init(); +}; + +// ----------------------------------------------------------------------- + +#include + +// Indicates first bit useable by derived properties. +#define wxPG_PROP_SHOW_FULL_FILENAME wxPG_PROP_CLASS_SPECIFIC_1 + +class WXDLLIMPEXP_PG wxFilePropertyClass : public wxPGProperty +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxFilePropertyClass( const wxString& label, const wxString& name = wxPG_LABEL, + const wxString& value = wxEmptyString ); + virtual ~wxFilePropertyClass (); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int argFlags ) const; + virtual bool SetValueFromString( const wxString& text, int flags ); + virtual bool OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event ); + + virtual void SetAttribute( int id, wxVariant& value ); + +#if wxUSE_VALIDATORS + static wxValidator* GetClassValidator(); + virtual wxValidator* DoGetValidator() const; +#endif + +protected: + wxString m_wildcard; + wxString m_fnstr; // needed for return value + wxString m_basePath; // If set, then show path relative to it + wxString m_initialPath; // If set, start the file dialog here + wxString m_dlgTitle; // If set, used as title for file dialog + wxFileName m_filename; // used as primary storage + int m_indFilter; // index to the selected filter +}; + +// ----------------------------------------------------------------------- + +#define wxPG_PROP_NO_ESCAPE wxPG_PROP_CLASS_SPECIFIC_1 + +// +// In wxTextCtrl, strings a space delimited C-like strings. For example: +// "String 1" "String 2" "String 3" +// +// To have " in a string, use \". +// To have \ in a string, use \\. +// +class WXDLLIMPEXP_PG wxLongStringPropertyClass : public wxBasePropertyClass +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxLongStringPropertyClass( const wxString& label, const wxString& name = wxPG_LABEL, const wxString& value = wxEmptyString ); + virtual ~wxLongStringPropertyClass(); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual wxString GetValueAsString( int argFlags = 0 ) const; + virtual bool SetValueFromString( const wxString& text, int flags ); + + WX_PG_DECLARE_EVENT_METHODS() + + // Shows string editor dialog. Value to be edited should be read from value, and + // if dialog is not cancelled, it should be stored back and true should be returned + // if that was the case. + virtual bool OnButtonClick( wxPropertyGrid* propgrid, wxString& value ); + +protected: + wxString m_value; +}; + +// ----------------------------------------------------------------------- + +// wxBoolProperty specific flags +#define wxPG_PROP_USE_CHECKBOX wxPG_PROP_CLASS_SPECIFIC_1 +// DCC = Double Click Cycles +#define wxPG_PROP_USE_DCC wxPG_PROP_CLASS_SPECIFIC_2 + + +// ----------------------------------------------------------------------- + +class WXDLLIMPEXP_PG wxArrayStringPropertyClass : public wxPGProperty +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxArrayStringPropertyClass( const wxString& label, + const wxString& name, + const wxArrayString& value ); + virtual ~wxArrayStringPropertyClass(); + + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_EVENT_METHODS() + + virtual void GenerateValueAsString(); + + // Shows string editor dialog. Value to be edited should be read from value, and + // if dialog is not cancelled, it should be stored back and true should be returned + // if that was the case. + virtual bool OnCustomStringEdit( wxWindow* parent, wxString& value ); + + // Helper. + virtual bool OnButtonClick( wxPropertyGrid* propgrid, + wxWindow* primary, + const wxChar* cbt ); + + // Creates wxArrayEditorDialog for string editing. Called in OnButtonClick. + virtual wxArrayEditorDialog* CreateEditorDialog(); + +protected: + wxArrayString m_value; + wxString m_display; // Cache for displayed text. +}; + +#define WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR(PROPNAME,DELIMCHAR,CUSTBUTTXT) \ +class wxPG_PROPCLASS(PROPNAME) : public wxPG_PROPCLASS(wxArrayStringProperty) \ +{ \ + WX_PG_DECLARE_PROPERTY_CLASS() \ +public: \ + wxPG_PROPCLASS(PROPNAME)( const wxString& label, const wxString& name, const wxArrayString& value ); \ + ~wxPG_PROPCLASS(PROPNAME)(); \ + virtual void GenerateValueAsString(); \ + virtual bool SetValueFromString( const wxString& text, int ); \ + virtual bool OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event ); \ + virtual bool OnCustomStringEdit( wxWindow* parent, wxString& value ); \ + WX_PG_DECLARE_VALIDATOR_METHODS() \ +}; \ +WX_PG_IMPLEMENT_PROPERTY_CLASS(PROPNAME,wxArrayStringProperty,wxArrayString,const wxArrayString&,TextCtrlAndButton) \ +wxPG_PROPCLASS(PROPNAME)::wxPG_PROPCLASS(PROPNAME) ( const wxString& label, const wxString& name, const wxArrayString& value ) \ + : wxPG_PROPCLASS(wxArrayStringProperty)(label,name,value) \ +{ \ + wxPG_PROPCLASS(PROPNAME)::GenerateValueAsString(); \ +} \ +wxPG_PROPCLASS(PROPNAME)::~wxPG_PROPCLASS(PROPNAME)() { } \ +void wxPG_PROPCLASS(PROPNAME)::GenerateValueAsString() \ +{ \ + wxChar delimChar = DELIMCHAR; \ + if ( delimChar == wxT('"') ) \ + wxPG_PROPCLASS(wxArrayStringProperty)::GenerateValueAsString(); \ + else \ + wxPropertyGrid::ArrayStringToString(m_display,m_value,0,DELIMCHAR,0); \ +} \ +bool wxPG_PROPCLASS(PROPNAME)::SetValueFromString( const wxString& text, int ) \ +{ \ + wxChar delimChar = DELIMCHAR; \ + if ( delimChar == wxT('"') ) \ + return wxPG_PROPCLASS(wxArrayStringProperty)::SetValueFromString(text,0); \ + \ + m_value.Empty(); \ + WX_PG_TOKENIZER1_BEGIN(text,DELIMCHAR) \ + m_value.Add( token ); \ + WX_PG_TOKENIZER1_END() \ + GenerateValueAsString(); \ + return true; \ +} \ +bool wxPG_PROPCLASS(PROPNAME)::OnEvent( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event ) \ +{ \ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) \ + return OnButtonClick(propgrid,primary,(const wxChar*) CUSTBUTTXT); \ + return false; \ +} + +#if wxUSE_VALIDATORS + +#define WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY(PROPNAME,DELIMCHAR,CUSTBUTTXT) \ +WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR(PROPNAME,DELIMCHAR,CUSTBUTTXT) \ +wxValidator* wxPG_PROPCLASS(PROPNAME)::DoGetValidator () const \ +{ return (wxValidator*) NULL; } + +#else + +#define WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY_WITH_VALIDATOR WX_PG_IMPLEMENT_ARRAYSTRING_PROPERTY + +#endif + + +// ----------------------------------------------------------------------- +// wxPGEditorDialog +// TODO: To be enabled for 1.3. +// ----------------------------------------------------------------------- + +#if 0 +class wxPGEditorDialog : public wxDialog +{ +public: + + wxPGEditorDialog() : wxDialog() + { + m_modified = false; + } + + /** Called instead non-virtual Create. Must call wxDialog::Create internally. + Note that wxPropertyGrid is always dialog's parent. + + \params + custBtText: Allow setting single custom button action. Text is + button title. Event must be intercepted in property's OnEvent() + member function. Not all dialogs are expected to support this. + */ + virtual bool VCreate( wxPropertyGrid* pg, + wxPGProperty* p, + const wxString& caption, + const wxString& message, + wxVariant value, + const wxChar* custBtText = NULL ) = 0; + + virtual wxVariant GetValue() const = 0; + + // Returns true if value was actually modified + inline bool IsModified() const { return m_modified; } + +protected: + + bool m_modified; + +private: +}; +#endif + +// ----------------------------------------------------------------------- +// wxArrayEditorDialog +// ----------------------------------------------------------------------- + +#include +#include +#include + +#define wxAEDIALOG_STYLE \ + (wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxOK | wxCANCEL | wxCENTRE) + +class WXDLLIMPEXP_PG wxArrayEditorDialog : public wxDialog +{ +public: + wxArrayEditorDialog(); + + void Init(); + + wxArrayEditorDialog( wxWindow *parent, + const wxString& message, + const wxString& caption, + long style = wxAEDIALOG_STYLE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& sz = wxDefaultSize ); + + bool Create( wxWindow *parent, + const wxString& message, + const wxString& caption, + long style = wxAEDIALOG_STYLE, + const wxPoint& pos = wxDefaultPosition, + const wxSize& sz = wxDefaultSize ); + + /** Set value modified by dialog. + */ + virtual void SetDialogValue( const wxVariant& WXUNUSED(value) ) + { + wxFAIL_MSG(wxT("re-implement this member function in derived class")); + } + + /** Return value modified by dialog. + */ + virtual wxVariant GetDialogValue() const + { + wxFAIL_MSG(wxT("re-implement this member function in derived class")); + return wxVariant(); + } + + /** Override to return wxValidator to be used with the wxTextCtrl + in dialog. Note that the validator is used in the standard + wx way, ie. it immediately prevents user from entering invalid + input. + + \remarks + Dialog frees the validator. + */ + virtual wxValidator* GetTextCtrlValidator() const + { + return (wxValidator*) NULL; + } + + // Returns true if array was actually modified + bool IsModified() const { return m_modified; } + + //const wxArrayString& GetStrings() const { return m_array; } + + // implementation from now on + void OnUpdateClick(wxCommandEvent& event); + void OnAddClick(wxCommandEvent& event); + void OnDeleteClick(wxCommandEvent& event); + void OnListBoxClick(wxCommandEvent& event); + void OnUpClick(wxCommandEvent& event); + void OnDownClick(wxCommandEvent& event); + //void OnCustomEditClick(wxCommandEvent& event); + void OnIdle(wxIdleEvent& event); + +protected: + wxTextCtrl* m_edValue; + wxListBox* m_lbStrings; + + wxButton* m_butAdd; // Button pointers + wxButton* m_butCustom; // required for disabling/enabling changing. + wxButton* m_butUpdate; + wxButton* m_butRemove; + wxButton* m_butUp; + wxButton* m_butDown; + + //wxArrayString m_array; + + const wxChar* m_custBtText; + //wxArrayStringPropertyClass* m_pCallingClass; + + bool m_modified; + + unsigned char m_curFocus; + + // These must be overridden - must return true on success. + virtual wxString ArrayGet( size_t index ) = 0; + virtual size_t ArrayGetCount() = 0; + virtual bool ArrayInsert( const wxString& str, int index ) = 0; + virtual bool ArraySet( size_t index, const wxString& str ) = 0; + virtual void ArrayRemoveAt( int index ) = 0; + virtual void ArraySwap( size_t first, size_t second ) = 0; + +private: +#ifndef SWIG + DECLARE_DYNAMIC_CLASS_NO_COPY(wxArrayEditorDialog) + DECLARE_EVENT_TABLE() +#endif +}; + +// ----------------------------------------------------------------------- + + +/** This is a simple property which holds sub-properties. Has default editing + textctrl based editing capability. In essence, it is a category that has + look and feel of a property, and which children can be edited via the textctrl. +*/ +class WXDLLIMPEXP_PG wxParentPropertyClass : public wxPGPropertyWithChildren +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxParentPropertyClass( const wxString& label, const wxString& name = wxPG_LABEL ); + virtual ~wxParentPropertyClass(); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual void ChildChanged( wxPGProperty* p ); + virtual wxString GetValueAsString( int argFlags = 0 ) const; + +protected: + wxString m_string; +}; + + +// ----------------------------------------------------------------------- + +#endif // #ifndef SWIG + +/** \class wxCustomPropertyClass + \ingroup classes + \brief This is a rather inefficient but very versatile property class. + + Base class offers the following: + - Add any properties as children (i.e. like wxParentProperty) + - Editor control can be set at run-time. + - By default has string value type. + - Has capacity to have choices. + - Can have custom-paint bitmap. + + Also note: + - Has m_parentingType of -2 (technical detail). +*/ +class WXDLLIMPEXP_PG wxCustomPropertyClass : public wxPGPropertyWithChildren +{ +#ifndef SWIG + WX_PG_DECLARE_PROPERTY_CLASS() +#endif +public: + + wxCustomPropertyClass( const wxString& label, const wxString& name = wxPG_LABEL ); + virtual ~wxCustomPropertyClass(); + + virtual void DoSetValue( wxPGVariant value ); + virtual wxPGVariant DoGetValue() const; + virtual bool SetValueFromString( const wxString& text, int flags ); + virtual wxString GetValueAsString( int argFlags ) const; + +#ifdef wxPG_COMPATIBILITY_1_0_0 + virtual bool OnEvent ( wxPropertyGrid* propgrid, wxWindow* primary, wxEvent& event ); +#endif + WX_PG_DECLARE_CUSTOM_PAINT_METHODS() + + virtual bool SetValueFromInt ( long value, int arg_flags ); + virtual int GetChoiceInfo ( wxPGChoiceInfo* choiceinfo ); + + virtual void SetAttribute ( int id, wxVariant& value ); + +protected: + //wxPGChoicesData* m_choices; + wxPGChoices m_choices; +#ifdef wxPG_COMPATIBILITY_1_0_0 + wxPropertyGridCallback m_callback; +#endif + wxPGPaintCallback m_paintCallback; + + wxString m_value; +}; + +// ----------------------------------------------------------------------- + +#ifndef SWIG + +// +// Tokenizer macros. +// NOTE: I have made two versions - worse ones (performance and consistency +// wise) use wxStringTokenizer and better ones (may have unfound bugs) +// use custom code. +// + +#include + +// TOKENIZER1 can be done with wxStringTokenizer +#define WX_PG_TOKENIZER1_BEGIN(WXSTRING,DELIMITER) \ + wxStringTokenizer tkz(WXSTRING,DELIMITER,wxTOKEN_RET_EMPTY); \ + while ( tkz.HasMoreTokens() ) \ + { \ + wxString token = tkz.GetNextToken(); \ + token.Trim(true); \ + token.Trim(false); + +#define WX_PG_TOKENIZER1_END() \ + } + + +// +// 2nd version: tokens are surrounded by DELIMITERs (for example, C-style strings). +// TOKENIZER2 must use custom code (a class) for full compliancy +// with " surrounded strings with \" inside. +// +// class implementation is in propgrid.cpp +// + +class WXDLLIMPEXP_PG wxPGStringTokenizer +{ +public: + wxPGStringTokenizer( const wxString& str, wxChar delimeter ); + ~wxPGStringTokenizer(); + + bool HasMoreTokens(); // not const so we can do some stuff in it + wxString GetNextToken(); + +protected: +#ifndef SWIG + + const wxString* m_str; + wxString::const_iterator m_curPos; + wxString m_readyToken; + wxUniChar m_delimeter; +#endif +}; + +#define WX_PG_TOKENIZER2_BEGIN(WXSTRING,DELIMITER) \ + wxPGStringTokenizer tkz(WXSTRING,DELIMITER); \ + while ( tkz.HasMoreTokens() ) \ + { \ + wxString token = tkz.GetNextToken(); + +#define WX_PG_TOKENIZER2_END() \ + } + +#endif + +// ----------------------------------------------------------------------- + +#endif // !DOXYGEN + +#endif // _WX_PROPGRID_PROPDEV_H_ diff --git a/assdraw/libpropgrid/include/wx/propgrid/propgrid.doxygen b/assdraw/libpropgrid/include/wx/propgrid/propgrid.doxygen new file mode 100644 index 000000000..7e26ca321 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/propgrid.doxygen @@ -0,0 +1 @@ +# THIS FILE IS NO LONGER USED (use Doxyfile instead) diff --git a/assdraw/libpropgrid/include/wx/propgrid/propgrid.h b/assdraw/libpropgrid/include/wx/propgrid/propgrid.h new file mode 100644 index 000000000..c575dfd16 --- /dev/null +++ b/assdraw/libpropgrid/include/wx/propgrid/propgrid.h @@ -0,0 +1,7276 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: propgrid.h +// Purpose: wxPropertyGrid +// Author: Jaakko Salli +// Modified by: +// Created: Sep-25-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef __WX_PROPGRID_PROPGRID_H__ +#define __WX_PROPGRID_PROPGRID_H__ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma interface "propgrid.cpp" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NB: Do *NOT * remove this. +#if defined(SWIG) || defined(SWIG_TYPE_TABLE) + #ifndef __WXPYTHON__ + #define __WXPYTHON__ + #endif +#endif + +// +// In case DOXYGEN was not specified... +#if !defined(DOXYGEN) && !defined(_WX_WINDOW_H_BASE_) && !defined(SWIG) + // I've tried to get this auto-defined in Doxygen config, but have not + // succeeded thus far... so using a hack here. + #define DOXYGEN +#endif + + +// Doxygen special includes +#ifdef DOXYGEN + #include "pg_dox_mainpage.h" + #include "propdev.h" +#endif + + +// +// Need to define some things for DOXYGEN +#ifdef DOXYGEN + #define wxUSE_VALIDATORS 1 + #define wxUSE_DATETIME 1 + #define wxUSE_TOOLTIPS 1 + #define wxUSE_SPINBTN 1 + #define wxUSE_DATEPICKCTRL 1 +#endif + + +// +// Check some wxUSE_FOOs +#ifndef wxUSE_VALIDATORS + #error "wxUSE_VALIDATORS not defined" +#endif + +#ifndef wxUSE_DATETIME + #error "wxUSE_DATETIME not defined" +#endif + +#ifndef wxUSE_DATEPICKCTRL + #error "wxUSE_DATEPICKCTRL not defined" +#endif + + +// Uncomment next line to allow wxAdv linkage (required for DatePickerCtrl editor) +// #define wxPG_ALLOW_WXADV + +#if defined(__WXPYTHON__) + #include + + #undef wxPG_ALLOW_WXADV + #define wxPG_ALLOW_WXADV +#endif + +// Defines for component version. +// The following symbols should be updated for each new component release +// since some kind of tests, like those of AM_WXCODE_CHECKFOR_COMPONENT_VERSION() +// for "configure" scripts under unix, use them. +#define wxPROPGRID_MAJOR 1 +#define wxPROPGRID_MINOR 2 +#define wxPROPGRID_RELEASE 11 + +// For non-Unix systems (i.e. when building without a configure script), +// users of this component can use the following macro to check if the +// current version is at least major.minor.release +#define wxCHECK_PROPGRID_VERSION(major,minor,release) \ + (wxPROPGRID_MAJOR > (major) || \ + (wxPROPGRID_MAJOR == (major) && wxPROPGRID_MINOR > (minor)) || \ + (wxPROPGRID_MAJOR == (major) && wxPROPGRID_MINOR == (minor) && wxPROPGRID_RELEASE >= (release))) + + +// Legacy version number +#define wxPG_VERSION ((wxPROPGRID_MAJOR*1000)+(wxPROPGRID_MINOR*100)+(wxPROPGRID_RELEASE*10)) + + +// ----------------------------------------------------------------------- + + +// +// Here are some platform dependent defines +// NOTE: More in propertygrid.cpp +// + +#ifndef SWIG + +#if defined(__WXMSW__) + // tested + + #define wxPG_XBEFORETEXT 5 // space between vertical line and value text + #define wxPG_XBEFOREWIDGET 1 // space between vertical line and value editor control + + #define wxPG_TEXTCTRLXADJUST 3 // x position adjustment for wxTextCtrl (and like) + + #define wxPG_ICON_WIDTH 9 // comment to use bitmap buttons + #define wxPG_USE_RENDERER_NATIVE 0 // 1 if wxRendererNative should be employed + + #define wxPG_DOUBLE_BUFFER 1 // 1 to use double-buffer that guarantees flicker-free painting + + #define wxPG_HEAVY_GFX 1 // 1 for prettier appearance + + #define wxPG_SUPPORT_TOOLTIPS 1 // Enable tooltips + +#elif defined(__WXGTK__) + // tested + + #define wxPG_XBEFORETEXT 6 // space between vertical line and value text + #define wxPG_XBEFOREWIDGET 1 // space between vertical line and value editor control + + #define wxPG_TEXTCTRLXADJUST 3 // x position adjustment for wxTextCtrl (and like) + + #define wxPG_ICON_WIDTH 9 // comment to use bitmap buttons + #define wxPG_USE_RENDERER_NATIVE 0 // 1 if wxRendererNative should be employed + + #define wxPG_DOUBLE_BUFFER 1 // 1 to use double-buffer that guarantees flicker-free painting + + #define wxPG_HEAVY_GFX 1 // 1 for prettier appearance + + #define wxPG_SUPPORT_TOOLTIPS 1 // Enable tooltips + +#elif defined(__WXMAC__) + // *not* tested + + #define wxPG_XBEFORETEXT 5 // space between vertical line and value text + #define wxPG_XBEFOREWIDGET 1 // space between vertical line and value editor widget + + #define wxPG_TEXTCTRLXADJUST 3 // x position adjustment for wxTextCtrl (and like) + + #define wxPG_ICON_WIDTH 11 // comment to use bitmap buttons + #define wxPG_USE_RENDERER_NATIVE 1 // 1 if wxRendererNative should be employed + + #define wxPG_DOUBLE_BUFFER 0 // 1 to use double-buffer that guarantees flicker-free painting + + #define wxPG_HEAVY_GFX 1 // 1 for prettier appearance + + #define wxPG_SUPPORT_TOOLTIPS 1 // Enable tooltips + +#else + // defaults + // tested on: none. + + #define wxPG_XBEFORETEXT 6 // space between vertical line and value text + #define wxPG_XBEFOREWIDGET 1 // space between vertical line and value editor widget + + #define wxPG_TEXTCTRLXADJUST 3 // x position adjustment for wxTextCtrl (and like) + + #define wxPG_ICON_WIDTH 9 // comment to use bitmap buttons + #define wxPG_USE_RENDERER_NATIVE 0 // 1 if wxRendererNative should be employed + + #define wxPG_DOUBLE_BUFFER 0 // 1 to use double-buffer that guarantees flicker-free painting + + #define wxPG_HEAVY_GFX 0 // 1 for prettier appearance + + #define wxPG_SUPPORT_TOOLTIPS 0 // Enable tooltips + +#endif // #if defined(__WXMSW__) + + +#if defined(__WXWINCE__) + #define wxPG_SMALL_SCREEN 1 + #undef wxPG_DOUBLE_BUFFER + #define wxPG_DOUBLE_BUFFER 0 +#else + #define wxPG_SMALL_SCREEN 0 +#endif + +#endif // #ifndef SWIG + +// Undefine wxPG_ICON_WIDTH to use supplied xpm bitmaps instead +// (for tree buttons) +//#undef wxPG_ICON_WIDTH + +// Need to force disable tooltips? +#if !wxUSE_TOOLTIPS + #undef wxPG_SUPPORT_TOOLTIPS + #define wxPG_SUPPORT_TOOLTIPS 0 +#endif + + +// Set 1 to include basic properties ( ~48k in 0.9.9.2 ) +#define wxPG_INCLUDE_BASICPROPS 1 + +// Set 1 to include advanced properties (wxFontProperty, wxColourProperty, etc.) ( ~32k in 0.9.9.2 ) +#define wxPG_INCLUDE_ADVPROPS 1 + +// Set 1 include wxPropertyGridManager ( ~36k in 0.9.9.1 ) +//#define wxPG_INCLUDE_MANAGER 1 + +// Set 1 to include checkbox editor class ( ~4k in 0.9.9.1 ) +#define wxPG_INCLUDE_CHECKBOX 1 + +// 1 to allow user data for each property +#define wxPG_USE_CLIENT_DATA 1 + +// NOTE: This is not supported as 1. +#define wxPG_INCLUDE_WXOBJECT 0 + +// ----------------------------------------------------------------------- + +#ifdef wxPG_COMPATIBILITY_1_0_0 + + #define wxRECURSE wxPG_RECURSE + #define wxKEEP_STRUCTURE wxPG_KEEP_STRUCTURE + #define wxPGConstants wxPGChoices + #define wxPG_EX_CLASSIC_SPACING 0 + + #define wxPGCtrlClass wxWindow + #define wxCCustomTextCtrl wxTextCtrl + #define wxCCustomComboBox wxPGOwnerDrawnComboBox + #define wxCCustomButton wxButton + +#endif // #ifdef wxPG_COMPATIBILITY_1_0_0 + +#ifdef __WXPYTHON__ + #define wxPG_PGVARIANT_IS_VARIANT 1 // 1 + #define wxPG_VALUETYPE_IS_STRING 0 // 1 +#else + #define wxPG_PGVARIANT_IS_VARIANT 0 + #define wxPG_VALUETYPE_IS_STRING 0 +#endif + + +#ifndef SWIG + #if !wxCHECK_VERSION(2,9,0) + #if !defined(wxUniChar) + #define wxUniChar wxChar + #endif + //#define wxPGGetIterChar(str, i) str[i] + #define wxPGGetIterChar(str, i) *i + #else + #define wxPGGetIterChar(str, i) *i + #endif +#endif + + +// ----------------------------------------------------------------------- + +// +// wxPython special considerations +// +// TODO: Using wxPG_GETVALUE_CONST yields some ugly function +// names, so might as well make those GetPropertyValueAsXXX non-static +// for regular C++ build as well.s +// + +#if !wxPG_VALUETYPE_IS_STRING + #define wxPG_VALUETYPE_MSGVAL const wxPGValueType* +#else + #define wxPG_VALUETYPE_MSGVAL wxString +#endif + + +#ifndef __WXPYTHON__ + +// Some Strings are returned as const wxChar* in C++, and as wxString in wxPython +// (using just wxString for everything would've been better, but the current scheme +// is necessary for better backwards compatibility). +#define wxPG_CONST_WXCHAR_PTR const wxChar* +#define wxPG_CONST_WXCHAR_DEFVAL ((const wxChar*)NULL) +#define wxPG_TO_WXCHAR_PTR(A) A + +#define wxPG_PYTHON_STATIC static +#define wxPG_GETVALUE_CONST + +// In C++ we can stick with overloaded methods +#define SetPropertyValueLong SetPropertyValue +#define SetPropertyValueDouble SetPropertyValue +#define SetPropertyValueBool SetPropertyValue +#define SetPropertyValueString SetPropertyValue +#define SetPropertyValueWxObjectPtr SetPropertyValue +#define SetPropertyValuePoint SetPropertyValue +#define SetPropertyValueSize SetPropertyValue +#define SetPropertyValueArrint2 SetPropertyValue +#define SetPropertyValueArrstr2 SetPropertyValue +#define SetPropertyValueDatetime SetPropertyValue +#define SetPropertyValueLongLong SetPropertyValue +#define SetPropertyValueULongLong SetPropertyValue + +#else + +// Some Strings are returned as const wxChar* in C++, and as wxString in wxPython +// (using just wxString for everything would've been better, but the current scheme +// is necessary for better backwards compatibility). +#define wxPG_CONST_WXCHAR_PTR wxString +#define wxPG_CONST_WXCHAR_DEFVAL wxEmptyString +#define wxPG_TO_WXCHAR_PTR(A) (A.c_str()) + +// Declaring GetValues as static will yield problems +#define wxPG_PYTHON_STATIC +#define wxPG_GETVALUE_CONST const + +// Because SWIG has problems combining overloaded functions and +// Python object-to-wxXXX conversion, we need to use Python proxy +// functions for these value setters. +#define SetPropertyValueArrstr2 _SetPropertyValueArrstr +#define SetPropertyValueArrint2 _SetPropertyValueArrint + +#endif + + +// wxPG_CHECK_FOO_DBG - on Release and wxPython builds, show wxLogWarning instead +// (so that the program flow is not interrupted, but the message can still be seen). +#if !defined(__WXDEBUG__) || defined(__WXPYTHON__) + #define wxPG_CHECK_RET_DBG(A,B) \ + if ( !(A) ) { wxLogWarning(B); return; } + #define wxPG_CHECK_MSG_DBG(A,B,C) \ + if ( !(A) ) { wxLogWarning(C); return B; } +#else + #define wxPG_CHECK_RET_DBG(A,B) wxCHECK_RET(A,B) + #define wxPG_CHECK_MSG_DBG(A,B,C) wxCHECK_MSG(A,B,C) +#endif + + +// ----------------------------------------------------------------------- + +// Our very custom dynamic object macros. Should only be used +// directly in an abstract (typeless etc.) base property classes. +#if wxPG_INCLUDE_WXOBJECT + #error "wxPG_INCLUDE_WXOBJECT is not currently supported (as of 1.0.0b)." + #define WX_PG_DECLARE_GETCLASSNAME + #define WX_PG_DECLARE_GETCLASSINFO +#else + #define WX_PG_DECLARE_GETCLASSNAME virtual wxPG_CONST_WXCHAR_PTR GetClassName() const; + #define WX_PG_DECLARE_GETCLASSINFO virtual const wxPGPropertyClassInfo* GetClassInfo() const; +#endif + +// ----------------------------------------------------------------------- + +#ifdef WXMAKINGLIB_PROPGRID + #define WXDLLIMPEXP_PG +#elif defined(WXMAKINGDLL_PROPGRID) + #define WXDLLIMPEXP_PG WXEXPORT +#elif defined(WXUSINGDLL) + #define WXDLLIMPEXP_PG WXIMPORT +#else // not making nor using DLL + #define WXDLLIMPEXP_PG +#endif + +// ----------------------------------------------------------------------- + +#if wxPG_PGVARIANT_IS_VARIANT + #define wxPGVariant wxVariant +#else + class WXDLLIMPEXP_PG wxPGVariant; +#endif + +#ifndef SWIG +class WXDLLIMPEXP_PG wxPGValueType; +class WXDLLIMPEXP_PG wxPGEditor; +class WXDLLIMPEXP_PG wxPGProperty; +class WXDLLIMPEXP_PG wxPGPropertyWithChildren; +class WXDLLIMPEXP_PG wxPropertyCategoryClass; +class WXDLLIMPEXP_PG wxPGChoices; +class WXDLLIMPEXP_PG wxPropertyGridState; +class WXDLLIMPEXP_PG wxPropertyContainerMethods; +class WXDLLIMPEXP_PG wxPropertyGrid; +class WXDLLIMPEXP_PG wxPropertyGridEvent; +class WXDLLIMPEXP_PG wxPropertyGridManager; +class WXDLLIMPEXP_PG wxPGOwnerDrawnComboBox; +class WXDLLIMPEXP_PG wxPGCustomComboControl; + +struct wxPGPaintData; + +extern WXDLLIMPEXP_PG const wxChar *wxPropertyGridNameStr; + +#endif // #ifndef SWIG + + +#ifdef __WXPYTHON__ + class wxPGPyEditor; +#endif // #ifndef __WXPYTHON__ + + +/** @defgroup miscellaneous wxPropertyGrid Miscellanous + This section describes some miscellanous values, types and macros. + @{ +*/ + +#if wxPG_PGVARIANT_IS_VARIANT + #define wxPG_EMPTY_ARRAYINT wxArrayInt() + #define wxPG_EMPTY_ARRAYSTRING wxArrayString() +#elif !defined(SWIG) + #define wxPG_EMPTY_ARRAYINT (*((wxArrayInt*)NULL)) + #define wxPG_EMPTY_ARRAYSTRING (*((wxArrayString*)NULL)) +#else + #define wxPG_EMPTY_ARRAYINT wxArrayInt_wxPG_EMPTY + #define wxPG_EMPTY_ARRAYSTRING wxArrayString_wxPG_EMPTY +#endif + +#if !defined(SWIG) + #define wxPG_LABEL (*((wxString*)NULL)) // Used to tell wxPGProperty to use label as name as well. + #define wxPG_NULL_BITMAP wxNullBitmap + #define wxPG_COLOUR_BLACK (*wxBLACK) +#else + #define wxPG_LABEL wxString_wxPG_LABEL + #define wxPG_NULL_BITMAP wxBitmap_NULL + #define wxPG_COLOUR_BLACK wxColour_BLACK +#endif // #ifndef SWIG + + +// Used to indicate wxPGChoices::Add etc that the value is actually not given +// by the caller. +#define wxPG_INVALID_VALUE INT_MAX + + +/** Convert Red, Green and Blue to a single 32-bit value. +*/ +#define wxPG_COLOUR(R,G,B) ((wxUint32)(R+(G<<8)+(B<<16))) + +/** Return this in GetImageSize() to indicate that the custom painted + property image is flexible. That is, it will paint (dropdown) + list item images with PREFWID,PREFHEI size. +*/ +#define wxPG_FLEXIBLE_SIZE(PREFWID,PREFHEI) wxSize(-(PREFWID),-(PREFHEI)) + +#define wxPG_FULL_CUSTOM_PAINT_WIDTH -99999 + +/** Return this in GetImageSize() to indicate that the property is + custom painted completely (ie. the text as well). +*/ +#define wxPG_FULL_CUSTOM_PAINT_SIZE(HEI) \ + wxSize(wxPG_FULL_CUSTOM_PAINT_WIDTH,HEI) + +/** Return this in GetImageSize() to indicate that the property is + custom painted completely (ie. the text as well), and with flexible + height. +*/ +#define wxPG_FULL_CUSTOM_PAINT_FLEXIBLE_SIZE(PREFHEI) \ + wxSize(wxPG_FULL_CUSTOM_PAINT_WIDTH,-(PREFHEI)) + + +/** This callback function is used by atleast wxCustomProperty + to facilitiate easy custom action on button press. + \param propGrid + related wxPropertyGrid + \param property + related wxPGProperty + \param ctrl + If not NULL (for example, not selected), a wxWindow* or equivalent + \param data + Value depends on the context. + \retval + True if changed value of the property. +*/ +typedef bool (*wxPropertyGridCallback)(wxPropertyGrid* propGrid, + wxPGProperty* property, + wxWindow* ctrl, + int data); + +/** This callback function is used by atleast wxCustomProperty + to facilitiate drawing items in drop down list. + + Works very much like wxPGProperty::OnCustomPaint. +*/ +typedef void (*wxPGPaintCallback)(wxPGProperty* property, + wxDC& dc, + const wxRect& rect, + wxPGPaintData& paintdata); + +/** Use this with wxPropertyGrid::IsPropertyKindOf. For example, as in + \code + pg->IsPropertyKindOf(WX_PG_CLASSINFO(wxStringProperty)) + \endcode +*/ +#define WX_PG_CLASSINFO(NAME) NAME##ClassInfo + +/** @} +*/ + +// ----------------------------------------------------------------------- + +/** @defgroup wndflags wxPropertyGrid Window Styles + SetWindowStyleFlag method can be used to modify some of these at run-time. + @{ +*/ +/** This will cause Sort() automatically after an item is added. + When inserting a lot of items in this mode, it may make sense to + use Freeze() before operations and Thaw() afterwards to increase + performance. +*/ +#define wxPG_AUTO_SORT 0x00000010 + +/** Categories are not initially shown (even if added). + IMPORTANT NOTE: If you do not plan to use categories, then this + style will waste resources. + This flag can also be changed using wxPropertyGrid::EnableCategories method. +*/ +#define wxPG_HIDE_CATEGORIES 0x00000020 + +/* This style combines non-categoric mode and automatic sorting. +*/ +#define wxPG_ALPHABETIC_MODE (wxPG_HIDE_CATEGORIES|wxPG_AUTO_SORT) + +/** Modified values are shown in bold font. Changing this requires Refresh() + to show changes. +*/ +#define wxPG_BOLD_MODIFIED 0x00000040 + +/** When wxPropertyGrid is resized, splitter moves to the center. This + behaviour stops once the user manually moves the splitter. +*/ +#define wxPG_SPLITTER_AUTO_CENTER 0x00000080 + +/** Display tooltips for cell text that cannot be shown completely. If + wxUSE_TOOLTIPS is 0, then this doesn't have any effect. +*/ +#define wxPG_TOOLTIPS 0x00000100 + +/** Disables margin and hides all expand/collapse buttons that would appear + outside the margin (for sub-properties). Toggling this style automatically + expands all collapsed items. +*/ +#define wxPG_HIDE_MARGIN 0x00000200 + +/** This style prevents user from moving the splitter. +*/ +#define wxPG_STATIC_SPLITTER 0x00000400 + +/** Combination of other styles that make it impossible for user to modify + the layout. +*/ +#define wxPG_STATIC_LAYOUT (wxPG_HIDE_MARGIN|wxPG_STATIC_SPLITTER) + +/** Disables wxTextCtrl based editors for properties which + can be edited in another way. Equals calling wxPropertyGrid::LimitPropertyEditing + for all added properties. +*/ +#define wxPG_LIMITED_EDITING 0x00000800 + +#ifdef DOXYGEN + +/** wxTAB_TRAVERSAL allows using Tab/Shift-Tab to travel between properties + in grid. Travelling forwards from last property will navigate to the + next control, and backwards from first will navigate to the previous one. +*/ + #define wxTAB_TRAVERSAL 0x00080000 + +#endif + +/** wxPropertyGridManager only: Show toolbar for mode and page selection. */ +#define wxPG_TOOLBAR 0x00001000 + +/** wxPropertyGridManager only: Show adjustable text box showing description + or help text, if available, for currently selected property. +*/ +#define wxPG_DESCRIPTION 0x00002000 + +/** wxPropertyGridManager only: Show compactor button that toggles hidden + state of low-priority properties. +*/ +#define wxPG_COMPACTOR 0x00004000 + +/** + NOTE: wxPG_EX_xxx are extra window styles and must be set using SetExtraStyle() + member function. + + Speeds up switching to wxPG_HIDE_CATEGORIES mode. Initially, if wxPG_HIDE_CATEGORIES + is not defined, the non-categorized data storage is not activated, and switching + the mode first time becomes somewhat slower. wxPG_EX_INIT_NOCAT activates the + non-categorized data storage right away. IMPORTANT NOTE: If you do plan not + switching to non-categoric mode, or if you don't plan to use categories at + all, then using this style will result in waste of resources. + +*/ +#define wxPG_EX_INIT_NOCAT 0x00001000 + +/** Extended window style that sets wxPropertyGridManager toolbar to not + use flat style. +*/ +#define wxPG_EX_NO_FLAT_TOOLBAR 0x00002000 + +/** This extra style allows editing more similar to some Microsoft/Mono + provided property sheet controls. Currently this includes (but more may be + added later, incase I missed something): + * Pressing ENTER in control, in addition to confirming changes, will + unfocus it. + * Pressing ESC doesn't cancel edit (but still unfocuses the editor). + + Note that ESC and ENTER events in editor controls are relayed to the + wxPropertyGrid itself, so that they can be detected by the application. +*/ +//#define wxPG_EX_ALTERNATE_KEYS 0x00004000 + +/** Shows alphabetic/categoric mode buttons from toolbar. +*/ +#define wxPG_EX_MODE_BUTTONS 0x00008000 + +/** Show property help strings as tool tips instead as text on the status bar. + You can set the help strings using SetPropertyHelpString member function. +*/ +#define wxPG_EX_HELP_AS_TOOLTIPS 0x00010000 + +/** Prevent TAB from focusing to wxButtons. This behaviour was default + in version 1.2.0 and earlier. + NOTE! Tabbing to button doesn't work yet. Problem seems to be that on wxMSW + atleast the button doesn't properly propagate key events (yes, I'm using + wxWANTS_CHARS). +*/ +//#define wxPG_EX_NO_TAB_TO_BUTTON 0x00020000 + +/** Set this style to have labels of disabled properties become greyed + along with the values. +*/ +#define wxPG_EX_GREY_LABEL_WHEN_DISABLED 0x00040000 + + +/** Allows relying on native double-buffering. +*/ +#define wxPG_EX_NATIVE_DOUBLE_BUFFERING 0x00080000 + + +/** Process all events immediately, if possible. That is, ProcessEvent is + called instead of AddPendingEvent. +*/ +#define wxPG_EX_PROCESS_EVENTS_IMMEDIATELY 0x00100000 + + +/** Set this style to let user have ability to set values of properties to + unspecified state. Currently, this applies to following properties: + - wxIntProperty, wxUIntProperty, and wxFloatProperty: Clear the + text field. +*/ +#define wxPG_EX_AUTO_UNSPECIFIED_VALUES 0x00200000 + + +/** Combines various styles. +*/ +#define wxPG_DEFAULT_STYLE (0) + +/** Combines various styles. +*/ +#define wxPGMAN_DEFAULT_STYLE (0) + +/** @} +*/ + +/** Flags for wxPropertyGrid::GetPropertyValues and wxPropertyGridManager::GetPropertyValues. */ +#define wxPG_KEEP_STRUCTURE 0x00000010 + +/** Flags for wxPropertyGrid::SetPropertyAttribute etc */ +#define wxPG_RECURSE 0x00000020 +#define wxPG_RECURSE_STARTS 0x00000040 +#define wxPG_FORCE 0x00000080 + +// ----------------------------------------------------------------------- + +// Property priorities +#define wxPG_LOW 1 +#define wxPG_HIGH 2 + +// ----------------------------------------------------------------------- + +// Misc argument flags. +#define wxPG_FULL_VALUE 0x00000001 // Get/Store full value instead of displayed value. +#define wxPG_REPORT_ERROR 0x00000002 +#define wxPG_PROPERTY_SPECIFIC 0x00000004 +#define wxPG_EDITABLE_VALUE 0x00000008 // Get/Store value that must be editable in wxTextCtrl + +// ----------------------------------------------------------------------- + + +#if defined(__WXPYTHON__) + #define wxPG_ID_IS_PTR 1 +#else + #define wxPG_ID_IS_PTR 0 +#endif + + +#if wxPG_ID_IS_PTR + +#define wxNullProperty ((wxPGProperty*)NULL) +#define wxPGId wxPGProperty* +#define wxPGIdGen(PTR) PTR +#define wxPGIdToPtr(ID) ((wxPGProperty*)ID) +#define wxPGIdIsOk(ID) ( ID != ((wxPGProperty*)NULL) ) + +#else + +#define wxNullProperty wxPGId(NULL) + + +/** \class wxPGId + \ingroup classes + \brief + Simple wrapper for the wxPGProperty pointer. + + NB: This class exists because: + - Abstract wxPGId would allow both flexibility and speed + (for possible native'ish implementations, altough this doesn't make + sense anymore). + - wxPG methods should be mostly used for property manipulation + (or such vision I had at first), and since wxPGId id = pg->Append(...) + is faster tow write, it seemed useful. + + *However* in future I may just start using wxPG_ID_IS_PTR by the default. + It might even result into slightly smaller code (altough I have checked out + some MSVC generated assembly, and it seems to optimize out the wrapper in + usual scenarios). +*/ +class WXDLLIMPEXP_PG wxPGId +{ +public: + inline wxPGId() { m_ptr = (wxPGProperty*) NULL; } + ~wxPGId() {} + + bool IsOk() const { return ( m_ptr != NULL ); } + + bool operator == (const wxPGId& other) + { + return m_ptr == other.m_ptr; + } + + inline const wxString& GetName() const; + +#ifndef SWIG + inline wxPGId( wxPGProperty* ptr ) { m_ptr = ptr; } + inline wxPGId( wxPGProperty& ref ) { m_ptr = &ref; } + + operator wxPGProperty* () + { + return m_ptr; + } + wxPGProperty* GetPropertyPtr() const { return m_ptr; } +#endif // #ifndef SWIG + + wxPGProperty& GetProperty() const { return *m_ptr; } +private: + wxPGProperty* m_ptr; +}; + +#define wxPGIdGen(PTR) wxPGId(PTR) +#define wxPGIdToPtr(ID) ID.GetPropertyPtr() +#define wxPGIdIsOk(ID) ID.IsOk() + +#endif // wxPG_ID_IS_PTR + + +// ----------------------------------------------------------------------- + +WXDLLIMPEXP_PG void wxPGTypeOperationFailed ( const wxPGProperty* p, const wxChar* typestr, const wxChar* op ); +WXDLLIMPEXP_PG void wxPGGetFailed ( const wxPGProperty* p, const wxChar* typestr ); + +// ----------------------------------------------------------------------- + +/** @defgroup propflags wxPGProperty Flags + @{ +*/ + +// NOTE: Do not change order of these, and if you add +// any, remember also to update gs_property_flag_to_string +// in propgrid.cpp. + +/** Indicates bold font. +*/ +#define wxPG_PROP_MODIFIED 0x0001 + +/** Disables ('greyed' text and editor does not activate) property. +*/ +#define wxPG_PROP_DISABLED 0x0002 + +/** Hider button will hide this property. +*/ +#define wxPG_PROP_HIDEABLE 0x0004 + +/** This property has custom paint image just in front of its value. + If property only draws custom images into a popup list, then this + flag should not be set. +*/ +#define wxPG_PROP_CUSTOMIMAGE 0x0008 + +/** Do not create text based editor for this property (but button-triggered + dialog and choice are ok). +*/ +#define wxPG_PROP_NOEDITOR 0x0010 + +/** Value is unspecified. +*/ +#define wxPG_PROP_UNSPECIFIED 0x0020 + +/** Indicates the bit useable by derived properties. +*/ +#define wxPG_PROP_CLASS_SPECIFIC_1 0x0040 + +/** Indicates the bit useable by derived properties. +*/ +#define wxPG_PROP_CLASS_SPECIFIC_2 0x0080 + +/** Property value cannot be modified. However, editor may be created + so that the value can be easily copied. +*/ +#define wxPG_PROP_READONLY 0x0100 + +/** @} +*/ + +// Amalgam of flags that should be inherited by sub-properties +#define wxPG_INHERITED_PROPFLAGS (wxPG_PROP_HIDEABLE|wxPG_PROP_NOEDITOR) + + +// ----------------------------------------------------------------------- + +/** @defgroup attrids wxPropertyGrid Property Attribute Identifiers + wxPropertyGrid::SetPropertyAttribute accepts one of these as + attrid argument when used with one of the built-in property classes. + @{ +*/ + +/** wxBoolProperty specific, int, default 0. When 1 sets bool property to + use checkbox instead of choice. +*/ +#define wxPG_BOOL_USE_CHECKBOX 64 + +/** wxBoolProperty specific, int, default 0. When 1 sets bool property value + to cycle on double click (instead of showing the popup listbox). +*/ +#define wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING 65 + +/** wxFloatProperty (and similar) specific, int, default -1. Sets the (max) precision + used when floating point value is rendered as text. The default -1 means infinite + precision. +*/ +#define wxPG_FLOAT_PRECISION 66 + +/** The text will be echoed as asterisks (wxTE_PASSWORD will be passed to textctrl etc). +*/ +#define wxPG_STRING_PASSWORD 67 + +/** Define base used by a wxUIntProperty. Valid constants are + wxPG_BASE_OCT, wxPG_BASE_DEC, wxPG_BASE_HEX and wxPG_BASE_HEXL + (lowercase characters). +*/ +#define wxPG_UINT_BASE 68 + +/** Define prefix rendered to wxUIntProperty. Accepted constants + wxPG_PREFIX_NONE, wxPG_PREFIX_0x, and wxPG_PREFIX_DOLLAR_SIGN. + Note: Only wxPG_PREFIX_NONE works with Decimal and Octal + numbers. +*/ +#define wxPG_UINT_PREFIX 69 + +/** wxFileProperty/wxImageFileProperty specific, wxChar*, default is detected/varies. + Sets the wildcard used in the triggered wxFileDialog. Format is the + same. +*/ +#define wxPG_FILE_WILDCARD 70 + +/** wxFileProperty/wxImageFileProperty specific, int, default 1. + When 0, only the file name is shown (i.e. drive and directory are hidden). +*/ +#define wxPG_FILE_SHOW_FULL_PATH 71 + +/** Specific to wxFileProperty and derived properties, wxString, default empty. + If set, then the filename is shown relative to the given path string. +*/ +#define wxPG_FILE_SHOW_RELATIVE_PATH 72 + +/** Specific to wxFileProperty and derived properties, wxString, default is empty. + Sets the initial path of where to look for files. +*/ +#define wxPG_FILE_INITIAL_PATH 73 + +/** Specific to wxFileProperty and derivatives, wxString, default is empty. + Sets a specific title for the dir dialog. +*/ +#define wxPG_FILE_DIALOG_TITLE 74 + +/** Specific to wxDirProperty, wxString, default is empty. + Sets a specific message for the dir dialog. +*/ +#define wxPG_DIR_DIALOG_MESSAGE 75 + +/** Sets displayed date format for wxDateProperty. +*/ +#define wxPG_DATE_FORMAT 76 + +/** Sets wxDatePickerCtrl window style used with wxDateProperty. Default + is wxDP_DEFAULT | wxDP_SHOWCENTURY. +*/ +#define wxPG_DATE_PICKER_STYLE 77 + + +#ifdef wxPG_COMPATIBILITY_1_0_0 + +/** wxCustomProperty specific, wxPGEditor*. Set editor control. Editor pointer is stored + in variable named wxPGEditor_EDITORNAME. So the basic built-in editors are at + wxPGEditor_TextCtrl, wxPGEditor_Choice, wxPGEditor_ComboBox, wxPGEditor_CheckBox, + wxPGEditor_TextCtrlAndButton, and wxPGEditor_ChoiceAndButton. +*/ +#define wxPG_CUSTOM_EDITOR 128 + +/** wxCustomProperty specific, wxBitmap*. Sets a small bitmap. Value must be given as + pointer and it is then copied. If you give it wxNullBitmap, then the current + image (if any) is deleted. +*/ +#define wxPG_CUSTOM_IMAGE 129 + +/** wxCustomProperty specific, void*. Sets callback function (of type wxPropertyGridCallback) + that is called whenever button is pressed. +*/ +#define wxPG_CUSTOM_CALLBACK 130 + +#endif // wxPG_COMPATIBILITY_1_0_0 + +/** wxCustomProperty specific, void*. Sets callback function (of type wxPGPaintCallback) + that is called whenever image in front of property needs to be repainted. This attribute + takes precedence over bitmap set with wxPG_CUSTOM_IMAGE, and it is only proper way + to draw images to wxCustomProperty's drop down choices list. + \remarks + Callback must handle measure calls (i.e. when rect.x < 0, set paintdata.m_drawnHeight to + height of item in question). +*/ +#define wxPG_CUSTOM_PAINT_CALLBACK 131 + + +/** wxCustomProperty specific, int, default 0. Setting to 1 makes children private, similar to other + properties with children. + \remarks + - Children must be added when this attribute has value 0. Otherwise + there will be an assertion failure. + - Changed event occurs on the parent only. +*/ +#define wxPG_CUSTOM_PRIVATE_CHILDREN 132 + + +/** wxColourProperty and its kind, int, default 1. Setting this attribute to 0 hides custom + colour from property's list of choices. +*/ +#define wxPG_COLOUR_ALLOW_CUSTOM 151 + + +/** First attribute id that is guaranteed not to be used built-in + properties. +*/ +#define wxPG_USER_ATTRIBUTE 192 + +/** @} +*/ + +// +// Valid constants for wxPG_UINT_BASE attribute +// (long because of wxVariant constructor) +#define wxPG_BASE_OCT (long)8 +#define wxPG_BASE_DEC (long)10 +#define wxPG_BASE_HEX (long)16 +#define wxPG_BASE_HEXL (long)32 + +// +// Valid constants for wxPG_UINT_PREFIX attribute +#define wxPG_PREFIX_NONE (long)0 +#define wxPG_PREFIX_0x (long)1 +#define wxPG_PREFIX_DOLLAR_SIGN (long)2 + + +// ----------------------------------------------------------------------- +// Value type. + +// Value type declarer, with optional declaration part (with creator function). +#define WX_PG_DECLARE_VALUE_TYPE_WITH_DECL(VALUETYPE,DECL) \ + extern DECL const wxPGValueType *wxPGValueType_##VALUETYPE; \ + extern DECL wxPGValueType* wxPGNewVT##VALUETYPE(); + +// Value type declarer (with creator function). +#define WX_PG_DECLARE_VALUE_TYPE(VALUETYPE) \ + extern const wxPGValueType *wxPGValueType_##VALUETYPE; \ + wxPGValueType* wxPGNewVT##VALUETYPE(); + +// Value type declarer, with optional declaration part. +#define WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(VALUETYPE,DECL) \ + extern DECL const wxPGValueType *wxPGValueType_##VALUETYPE; + +// Value type accessor. +#if !wxPG_VALUETYPE_IS_STRING + #define wxPG_VALUETYPE(T) wxPGValueType_##T + #define wxPG_VALUETYPE_PTR(T) wxPGValueType_##T +#else + #define wxPG_VALUETYPE(T) wxT(#T) + #define wxPG_VALUETYPE_PTR(T) wxPropertyContainerMethods::GetValueType(wxT(#T)) +#endif + +// Like wxPG_VALUETYPE, but casts pointer to exact class. +#define wxPG_VALUETYPE_EXACT(T) ((wxPGValueType##VALUETYPE##Class)wxPGValueType##T) + +// Declare builtin value types. +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(none,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(wxString,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(long,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(bool,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(double,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(void,WXDLLIMPEXP_PG) +WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(wxArrayString,WXDLLIMPEXP_PG) +#ifdef __WXPYTHON__ + WX_PG_DECLARE_VALUE_TYPE_BUILTIN_WITH_DECL(PyObject,WXDLLIMPEXP_PG) +#endif + +// +// With wxWidgets 2.9 and later we demand native C++ RTTI support +#if wxCHECK_VERSION(2,9,0) + #ifdef wxNO_RTTI + #error "You need to enable compiler RTTI support when using wxWidgets 2.9.0 or later" + #endif + #define WX_PG_DECLARE_DYNAMIC_CLASS_VARIANTDATA(A) + #define WX_PG_IMPLEMENT_DYNAMIC_CLASS_VARIANTDATA(A, B) +#else + #define WX_PG_DECLARE_DYNAMIC_CLASS_VARIANTDATA DECLARE_DYNAMIC_CLASS + #define WX_PG_IMPLEMENT_DYNAMIC_CLASS_VARIANTDATA IMPLEMENT_DYNAMIC_CLASS +#endif + +// VDC = wxVariantData Class +#define WX_PG_DECLARE_VALUE_TYPE_VDC(VALUETYPE) \ +wxVariantData_##VALUETYPE : public wxPGVariantDataWxObj \ +{ \ + WX_PG_DECLARE_DYNAMIC_CLASS_VARIANTDATA(wxVariantData_##VALUETYPE) \ +protected: \ + VALUETYPE m_value; \ +public: \ + wxVariantData_##VALUETYPE(); \ + wxVariantData_##VALUETYPE(const VALUETYPE& value); \ + virtual void Copy(wxVariantData& data); \ + virtual bool Eq(wxVariantData& data) const; \ + virtual wxString GetType() const; \ + virtual void* GetValuePtr(); \ + inline const VALUETYPE& GetValue () const { return m_value; } + +// Value type declarer for void* that need auto-generated . +#define WX_PG_DECLARE_VALUE_TYPE_VOIDP_WITH_DECL(VALUETYPE,DECL) \ +class DECL WX_PG_DECLARE_VALUE_TYPE_VDC(VALUETYPE) \ +}; \ +extern DECL const wxPGValueType *wxPGValueType_##VALUETYPE; + +#define WX_PG_DECLARE_VALUE_TYPE_VOIDP(VALUETYPE) \ +class WX_PG_DECLARE_VALUE_TYPE_VDC(VALUETYPE) \ +}; \ +WX_PG_DECLARE_VALUE_TYPE(VALUETYPE) + +#ifndef SWIG + +/** \class wxPGVariantDataWxObj + \ingroup classes + \brief Identical to wxVariantDataWxObjectPtr except that it deletes the + ptr on destruction. +*/ +class WXDLLIMPEXP_PG wxPGVariantDataWxObj : public wxVariantData +{ +public: + wxPGVariantDataWxObj(); + virtual ~wxPGVariantDataWxObj(); + +#if wxUSE_STD_IOSTREAM + virtual bool Write(wxSTD ostream& str) const; +#endif + virtual bool Write(wxString& str) const; +#if wxUSE_STD_IOSTREAM + virtual bool Read(wxSTD istream& str); +#endif + virtual bool Read(wxString& str); + + virtual void* GetValuePtr() = 0; +}; + +#endif // #ifndef SWIG + +#if !wxCHECK_VERSION(2,9,0) +typedef wxList wxVariantList; +#endif + +// ----------------------------------------------------------------------- +// Editor class. + +// Editor accessor. +#define wxPG_EDITOR(T) wxPGEditor_##T + +// Declare editor class, with optional part. +#define WX_PG_DECLARE_EDITOR_WITH_DECL(EDITOR,DECL) \ +extern DECL wxPGEditor* wxPGEditor_##EDITOR; \ +extern DECL wxPGEditor* wxPGConstruct##EDITOR##EditorClass(); + +// Declare editor class. +#define WX_PG_DECLARE_EDITOR(EDITOR) \ +extern wxPGEditor* wxPGEditor_##EDITOR; \ +extern wxPGEditor* wxPGConstruct##EDITOR##EditorClass(); + +// Declare builtin editor classes. +WX_PG_DECLARE_EDITOR_WITH_DECL(TextCtrl,WXDLLIMPEXP_PG) +WX_PG_DECLARE_EDITOR_WITH_DECL(Choice,WXDLLIMPEXP_PG) +WX_PG_DECLARE_EDITOR_WITH_DECL(ComboBox,WXDLLIMPEXP_PG) +WX_PG_DECLARE_EDITOR_WITH_DECL(TextCtrlAndButton,WXDLLIMPEXP_PG) +#if wxPG_INCLUDE_CHECKBOX +WX_PG_DECLARE_EDITOR_WITH_DECL(CheckBox,WXDLLIMPEXP_PG) +#endif +WX_PG_DECLARE_EDITOR_WITH_DECL(ChoiceAndButton,WXDLLIMPEXP_PG) + +// ----------------------------------------------------------------------- + +/** \class wxPGValueType + \ingroup classes + \brief wxPGValueType is base class for property value types. +*/ + +class WXDLLIMPEXP_PG wxPGValueType +{ +public: + + virtual ~wxPGValueType() = 0; + + /** Returns type name. If there is wxVariantData for this type, then name should + be the same that the class uses (otherwise wxT("void*")). */ + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const = 0; + + /** Returns custom type name. If this is base for a type, should not be overridden, + as the default implementation already does good thing and calls GetTypeName. + Otherwise, should be an unique string, such as the class name etc. + */ + virtual wxPG_CONST_WXCHAR_PTR GetCustomTypeName() const; + + /** Returns default value. + */ + virtual wxPGVariant GetDefaultValue() const = 0; + + /** Creates wxVariant with supplied value and name. + */ + virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const = 0; + + /** Creates new property instance with "proper" class. Initial value is set + to default. + */ + virtual wxPGProperty* GenerateProperty( const wxString& label, const wxString& name ) const = 0; + + /** Sets property value from wxVariant. + */ + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const = 0; + + /** Returns type that can be passed to CreatePropertyByType. + */ + inline wxPG_CONST_WXCHAR_PTR GetType() const + { + return GetCustomTypeName(); + } + +protected: +}; + + +// ----------------------------------------------------------------------- + +// wxVariant definition macro (sans functional eq-operator) +#define WX_PG_DECLARE_VARIANT_DATA(CLASSNAME, DATATYPE, DECL) \ +class DECL CLASSNAME : public wxVariantData \ +{ \ + DECLARE_DYNAMIC_CLASS(CLASSNAME) \ +public: \ + CLASSNAME() { } \ + CLASSNAME(const DATATYPE& value) { m_value = value; } \ + inline DATATYPE GetValue() const { return m_value; } \ + inline const DATATYPE& GetValueRef() const { return m_value; } \ + inline void SetValue(const DATATYPE& value) { m_value = value; } \ + virtual bool Eq(wxVariantData&) const { return false; } \ + virtual wxString GetType() const { return wxT(#DATATYPE); } \ + virtual wxVariantData* Clone() { return new CLASSNAME; } \ + virtual void Copy(wxVariantData &data) { ((CLASSNAME&)data).SetValue(m_value); } \ + virtual bool Read(wxString &) { return false; } \ + virtual bool Write(wxString &) const { return true; } \ +protected: \ + DATATYPE m_value; \ +}; + + +#define WX_PG_DECLARE_VARIANT_DATA_PTR(CLASSNAME, DATATYPE, DECL) \ +class DECL CLASSNAME : public wxVariantData \ +{ \ + DECLARE_DYNAMIC_CLASS(CLASSNAME) \ +public: \ + CLASSNAME() { } \ + CLASSNAME(DATATYPE* value) { m_value = value; } \ + inline void SetValue(DATATYPE* value) { m_value = value; } \ + inline DATATYPE* GetValue() const { return m_value; } \ + virtual bool Eq(wxVariantData&) const { return false; } \ + virtual wxString GetType() const { return wxT(#DATATYPE); } \ + virtual wxVariantData* Clone() { return new CLASSNAME; } \ + virtual void Copy(wxVariantData &data) { ((CLASSNAME&)data).SetValue(m_value); } \ + virtual bool Read(wxString &) { return false; } \ + virtual bool Write(wxString &) const { return true; } \ +protected: \ + DATATYPE* m_value; \ +}; + + +#if wxPG_PGVARIANT_IS_VARIANT + + #define wxPGVariantToWxObjectPtr(A,B) wxDynamicCast(A.GetWxObjectPtr(),B); + #define wxPGVariantGetWxObjectPtr(A) A.GetWxObjectPtr() + #define wxPGVariantToWxObject(A) (*A.GetWxObjectPtr()) + #define wxPGVariantToDateTime(A) A.GetDateTime() + #define wxPGVariantToWxPoint(A) ((wxPGVariantDataPoint*)(A.GetData()))->GetValueRef() + #define wxPGVariantToWxSize(A) ((wxPGVariantDataSize*)(A.GetData()))->GetValueRef() + #define wxPGVariantToWxLongLong(A) ((wxPGVariantDataLongLong*)(A.GetData()))->GetValueRef() + #define wxPGVariantToWxULongLong(A) ((wxPGVariantDataULongLong*)(A.GetData()))->GetValueRef() + #define wxPGVariantToArrayInt(A) ((wxPGVariantDataArrayInt*)(A.GetData()))->GetValueRef() + #define wxPGVariantToPyObject(A) ((wxPGVariantDataPyObject*)(A.GetData()))->GetValue() + #define wxPGVariantFromWxObject(A) wxVariant((wxObject*)A) + #define wxPGVariantFromLong(A) wxVariant(((long)A)) + + #if !defined(SWIG) + + WX_PG_DECLARE_VARIANT_DATA(wxPGVariantDataPoint, wxPoint, WXDLLIMPEXP_PG) + WX_PG_DECLARE_VARIANT_DATA(wxPGVariantDataSize, wxSize, WXDLLIMPEXP_PG) + WX_PG_DECLARE_VARIANT_DATA(wxPGVariantDataArrayInt, wxArrayInt, WXDLLIMPEXP_PG) + WX_PG_DECLARE_VARIANT_DATA(wxPGVariantDataLongLong, wxLongLong, WXDLLIMPEXP_PG) + WX_PG_DECLARE_VARIANT_DATA(wxPGVariantDataULongLong, wxULongLong, WXDLLIMPEXP_PG) + #ifdef __WXPYTHON__ + WX_PG_DECLARE_VARIANT_DATA_PTR(wxPGVariantDataPyObject, PyObject, WXDLLIMPEXP_PG) + #endif + + // We need this because wxVariant lacks all necessary constructors + inline wxVariant wxPGVariantCreator(long a) { return wxVariant((long)a); } + inline wxVariant wxPGVariantCreator(int a) { return wxVariant((long)a); } + inline wxVariant wxPGVariantCreator(bool a) { return wxVariant(a); } + inline wxVariant wxPGVariantCreator(const double& a) { return wxVariant(a); } + inline wxVariant wxPGVariantCreator(const wxString& a) { return wxVariant(a); } + + // NB: This may look dangerous. However, the wxVariant lives only a very short + // time, so it is very unlikely they value will be modified by some + // "third party". + inline wxVariant wxPGVariantCreator(const wxObject* a) { return wxVariant((wxObject*)a); } + inline wxVariant wxPGVariantCreator(const wxObject& a) { return wxVariant((wxObject*)(&a)); } + + inline wxVariant wxPGVariantCreator(wxObject* a) { return wxVariant(a); } + inline wxVariant wxPGVariantCreator(wxObject& a) { return wxVariant(&a); } + inline wxVariant wxPGVariantCreator(void* a) { return wxVariant(a); } + inline wxVariant wxPGVariantCreator(const wxArrayString& a) { return wxVariant((wxArrayString&)a); } + inline wxVariant wxPGVariantCreator(const wxArrayInt& a) { return wxVariant(new wxPGVariantDataArrayInt(a)); } + inline wxVariant wxPGVariantCreator(const wxPoint& a) { return wxVariant(new wxPGVariantDataPoint(a)); } + inline wxVariant wxPGVariantCreator(const wxSize& a) { return wxVariant(new wxPGVariantDataSize(a)); } + inline wxVariant wxPGVariantCreator(const wxLongLong& a) { return wxVariant(new wxPGVariantDataLongLong(a)); } + inline wxVariant wxPGVariantCreator(const wxULongLong& a) { return wxVariant(new wxPGVariantDataULongLong(a)); } + #ifdef __WXPYTHON__ + inline wxVariant wxPGVariantCreator(PyObject* a) { return wxVariant(new wxPGVariantDataPyObject(a)); } + #endif + #if wxUSE_DATETIME + inline wxVariant wxPGVariantCreator(const wxDateTime& a) { return wxVariant(a); } + #endif + #endif // !defined(SWIG) + +#else // !wxPG_PGVARIANT_IS_VARIANT + +union wxPGVariantUnion +{ + long m_long; + void* m_ptr; + bool m_bool; +}; + +// +// Very simple value wrapper class +// +// NB: It only holds the pointers for a short period, so don't +// worry about it not making copies. +class WXDLLIMPEXP_PG wxPGVariant +{ +public: + + /** Constructor for none. */ + wxPGVariant() + { + m_v.m_ptr = (void*)NULL; + } +#ifndef SWIG + /** Constructor for long integer. */ + wxPGVariant( long v_long ) + { + m_v.m_long = v_long; + } + /** Constructor for integer. */ + wxPGVariant( int v_long ) + { + m_v.m_long = v_long; + } + /** Constructor for bool. */ + wxPGVariant( bool value ) + { + m_v.m_bool = value; + } + /** Constructor for float. */ + wxPGVariant( const double& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxString*. */ + wxPGVariant( const wxString& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxArrayString*. */ + wxPGVariant( const wxArrayString& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxArrayInt. */ + wxPGVariant( const wxArrayInt& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxPoint. */ + wxPGVariant( const wxPoint& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxSize. */ + wxPGVariant( const wxSize& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxLongLong. */ + wxPGVariant( const wxLongLong& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxULongLong. */ + wxPGVariant( const wxULongLong& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxObject&. */ + wxPGVariant( const wxObject& v_ptr ) + { + m_v.m_ptr = (void*)&v_ptr; + } + /** Constructor for wxObject*. */ + wxPGVariant( const wxObject* v_ptr ) + { + m_v.m_ptr = (void*)v_ptr; + } + /** Constructor for void*. */ + wxPGVariant( void* v_ptr ) + { + m_v.m_ptr = v_ptr; + } +#if wxUSE_DATETIME + /** Constructor for wxDateTime ptr. */ + wxPGVariant( const wxDateTime& dt ) + { + m_v.m_ptr = (void*) &dt; + } +#endif + + /** Returns value as long integer. */ + inline long GetLong() const + { + return m_v.m_long; + } + /** Returns value as boolean integer. */ + inline bool GetBool() const + { + return m_v.m_bool; + } + /** Returns value as floating point number. */ + inline double GetDouble() const + { + return *((double*)m_v.m_ptr); + } + /** Returns value as floating point number ptr. */ + inline double* GetDoublePtr() const + { + return (double*) m_v.m_ptr; + } + /** Returns value as a wxString. */ + inline const wxString& GetString() const + { + return *((const wxString*)m_v.m_ptr); + } + /** Returns value as a reference to a wxArrayString. */ + inline wxArrayString& GetArrayString() const + { + wxArrayString* temp = (wxArrayString*)m_v.m_ptr; + return *temp; + } + + inline const wxObject& GetWxObject() const + { + return *((const wxObject*)m_v.m_ptr); + } + + inline wxObject* GetWxObjectPtr() const + { + return (wxObject*)m_v.m_ptr; + } + + /** Returns value as void*. */ + inline void* GetVoidPtr() const + { + return m_v.m_ptr; + } +#if wxUSE_DATETIME + /** Returns value as const wxDateTime&. */ + inline const wxDateTime& GetDateTime() const + { + return *((const wxDateTime*)m_v.m_ptr); + } +#endif + +#endif // #ifndef SWIG + + /** Returns value as long integer without type checking. */ + inline long GetRawLong() const { return m_v.m_long; } + + /** Returns value as void* without type checking. */ + inline void* GetRawPtr() const { return m_v.m_ptr; } + +#undef wxPG_ASSERT_VARIANT_GET + + /** Value in portable format. */ + wxPGVariantUnion m_v; +}; + + #define wxPGVariantGetWxObjectPtr(A) ((wxObject*)A.GetRawPtr()) + #define wxPGVariantToWxObjectPtr(A,B) wxDynamicCast((wxObject*)A.GetRawPtr(),B); + #define wxPGVariantToWxObject(A) A.GetWxObject() + #define wxPGVariantToDateTime(A) *((wxDateTime*)A.GetVoidPtr()) + #define wxPGVariantToWxPoint(A) *((wxPoint*)wxPGVariantToVoidPtr(A)) + #define wxPGVariantToWxSize(A) *((wxSize*)wxPGVariantToVoidPtr(A)) + #define wxPGVariantToWxLongLong(A) *((wxLongLong*)wxPGVariantToVoidPtr(A)) + #define wxPGVariantToWxULongLong(A) *((wxULongLong*)wxPGVariantToVoidPtr(A)) + #define wxPGVariantToArrayInt(A) *((wxArrayInt*)A.GetVoidPtr()) + #define wxPGVariantFromWxObject(A) *((const wxObject*)A) + #define wxPGVariantFromLong(A) wxPGVariant(A) + #define wxPGVariantCreator wxPGVariant + +#endif // !wxPG_PGVARIANT_IS_VARIANT + +// Helper macros +#define wxPGVariantToString(A) A.GetString() +#define wxPGVariantToLong(A) A.GetLong() +#define wxPGVariantToBool(A) A.GetBool() +#define wxPGVariantToDouble(A) A.GetDouble() +#define wxPGVariantToArrayString(A) A.GetArrayString() +#define wxPGVariantToVoidPtr(A) A.GetVoidPtr() + +#define wxPGVariantFromString(A) A +#define wxPGVariantFromDouble(A) A +#define wxPGVariantFromArrayString(A) A +#define wxPGVariantFromBool(A) A + + +// ----------------------------------------------------------------------- + +// +// Property class declaration helper macros +// (wxPGRootPropertyClass and wxPropertyCategory require this). +// + +#define WX_PG_DECLARE_CLASSINFO() \ + WX_PG_DECLARE_GETCLASSNAME \ + WX_PG_DECLARE_GETCLASSINFO + +// We don't want to create SWIG interface for DoGetEditorClass (we'll use GetEditor instead) +#ifndef SWIG + #define WX_PG_DECLARE_DOGETEDITORCLASS virtual const wxPGEditor* DoGetEditorClass() const; +#else + #define WX_PG_DECLARE_DOGETEDITORCLASS +#endif + +#define WX_PG_DECLARE_PROPERTY_CLASS() \ +public: \ + virtual wxPG_VALUETYPE_MSGVAL GetValueType() const; \ + WX_PG_DECLARE_DOGETEDITORCLASS \ + WX_PG_DECLARE_CLASSINFO() \ +private: + + +// Added for SWIG (which apparently doesn't support 0-argument macros) +// NB: Othwise, this is *identical* to WX_PG_DECLARE_PROPERTY_CLASS() +#define WX_PG_DECLARE_PROPERTY_CLASS_NOPARENS \ +public: \ + virtual wxPG_VALUETYPE_MSGVAL GetValueType() const; \ + WX_PG_DECLARE_DOGETEDITORCLASS \ + WX_PG_DECLARE_CLASSINFO() \ +private: + + + +#ifndef SWIG + +// ----------------------------------------------------------------------- +// wxPGPropertyClassInfo + + +typedef wxPGProperty* (*wxPGPropertyConstructor) (const wxString&,const wxString&); + +/** \class wxPGPropertyClassInfo + \ingroup classes + \brief Class info structure for wxPGProperty derivatives (may be deprecated + in a future release). +*/ +struct wxPGPropertyClassInfo +{ + /** One returned by GetPropertyClassName */ + const wxChar* m_name; + + /** Classinfo of the base property class. */ + const wxPGPropertyClassInfo* m_baseInfo; + + /** Simple property constructor function. */ + wxPGPropertyConstructor m_constructor; +}; + + +// Use this macro to register your custom property classes. +#define wxPGRegisterPropertyClass(NAME) \ + wxPropertyGrid::RegisterPropertyClass(wxT(#NAME),&NAME##ClassInfo) + + +// ----------------------------------------------------------------------- + + +// Structure for relaying choice/list info. +struct wxPGChoiceInfo +{ + const wxChar** m_arrWxChars; + wxString* m_arrWxString; + wxPGChoices* m_choices; + int m_itemCount; +}; + + +// ----------------------------------------------------------------------- + + +/** \class wxPGPropertyDataExt + \ingroup classes + \brief wxPGPropertyDataExt is data extension class for wxPGProperty. +*/ +class WXDLLIMPEXP_PG wxPGPropertyDataExt +{ +public: + + wxPGPropertyDataExt() + { +#if wxUSE_VALIDATORS + m_validator = (wxValidator*) NULL; +#endif + m_customEditor = (wxPGEditor*) NULL; + m_valueBitmap = (wxBitmap*) NULL; + } + + ~wxPGPropertyDataExt() + { + // Do not delete m_customEditor +#if wxUSE_VALIDATORS + delete m_validator; +#endif + delete m_valueBitmap; + } + + // For conviency, declare all members public. + + wxString m_helpString; // Help shown in statusbar or help box. + const wxPGEditor* m_customEditor; // Overrides editor returned by property class + +#if wxUSE_VALIDATORS + // NOTE: This is candidate for hash mapping. + wxValidator* m_validator; // Editor is going to get this validator +#endif + + wxBitmap* m_valueBitmap; // Show this in front of the value +}; + +#endif + +// ----------------------------------------------------------------------- + +/** \class wxPGProperty + \ingroup classes + \brief wxPGProperty, alias wxBasePropertyClass, is base class for properties. + Information here is provided primarily for anyone who creates new properties, + since all operations on properties should be done via wxPropertyGrid's or + wxPropertyGridManager's methods. + + \remarks + - When changing name of a property, it is essential to use wxPropertyGrid::SetPropertyName + (that's why there is no SetName method). +*/ +class WXDLLIMPEXP_PG wxPGProperty +{ +#ifndef SWIG + friend class wxPGPropertyWithChildren; + friend class wxPropertyGrid; + friend class wxPropertyContainerMethods; + friend class wxPropertyGridState; +#endif +public: + +// PYSWIG is a special symbol used by my custom scripts. Code to remove it +// automatically should be added in future. +#ifndef PYSWIG + /** Basic constructor. Should not be necessary to override. + */ + wxPGProperty(); +#endif + + /** Constructor. + Real used property classes should have constructor of this style: + + \code + + // If MyValueType is a class, then it should be a constant reference + // (e.g. const MyValueType& ) instead. + wxMyProperty( const wxString& label, const wxString& name, + MyValueType value ) : wxPGProperty + { + // Only required if MyValueType is not built-in default + // (wxString, long, double, bool, and wxArrayString are; + // wxFont, wxColour, etc. are not). + wxPG_INIT_REQUIRED_TYPE(MyValueType) + DoSetValue(value); // Generally recommended way to set the initial value. + + // If has child properties (i.e. wxPGPropertyWithChildren is used + // as the parent class), then create children here. For example: + // AddChild( new wxStringProperty( wxT("Subprop 1"), wxPG_LABEL, value.GetSubProp1() ) ); + } + + \endcode + + Of course, in this example, wxPGProperty could also be wxPGPropertyWithChildren + (if it has sub-properties) or actually any other property class. + */ + wxPGProperty( const wxString& label, const wxString& name ); + + /** Virtual destructor. It is customary for derived properties to override this. */ + virtual ~wxPGProperty(); + + /** Sets property's internal value. + \param value + Simple container with GetString(), GetLong() etc. methods. Currently recommended + means to extract value is to use wxPGVariantToXXX(value) macro. + \remarks + Example pseudo-implementation with comments: + \code + + void wxMyProperty::DoSetValue ( wxPGVariant value ) + { + // A) Get value. For example + const wxMyValueType* pvalue = wxPGVariantToWxObjectPtr(value,wxMyValueType); + // or: + const wxString& str = wxPGVariantToString(value); + // or: + long val = wxPGVariantToLong(value); + + // B) If value is wxObject or void based with NULL default, then handle that: + if ( pvalue ) + m_value = *pvalue; + else + pmyvalue->SetToDefault(); + + // Otherwise + // m_value = *pvalue; + // is sufficient. + + // C) If has children, this should be here (before displaying in control). + RefreshChildren(); + + } + + \endcode + */ + virtual void DoSetValue( wxPGVariant value ); + + /** Returns properly constructed wxPGVariant. + */ + virtual wxPGVariant DoGetValue() const; + + /** Returns text representation of property's value. + \param argFlags + If wxPG_FULL_VALUE is set, returns complete, storable value instead of displayable + one (they may be different). + */ + virtual wxString GetValueAsString( int argFlags = 0 ) const; + + /** Converts string to a value, and if succesfull, calls DoSetValue() on it. + Default behaviour is to do nothing. + \param text + String to get the value from. + \param report_error + If true, invalid string will be reported (prefer to use wxLogError). + \retval + true if value was changed. + */ + virtual bool SetValueFromString( const wxString& text, int flags = 0 ); + + /** Converts integer to a value, and if succesfull, calls DoSetValue() on it. + Default behaviour is to do nothing. + \param value + Int to get the value from. + \param flags + If has wxPG_FULL_VALUE, then the value given is a actual value and not an index. + \retval + true if value was changed. + */ + virtual bool SetValueFromInt( long value, int flags = 0 ); + + /** Returns size of the custom painted image in front of property. This method + must be overridden to return non-default value if OnCustomPaint is to be + called. + \remarks + - If flexible image size is desired, return wxPG_FLEXIBLE_SIZE(wid,hei). + OnCustomPaint is then called to measure items as well (see for + wxPGProperty::OnCustomPaint for measure call specs). + - If entire property, including text, is to be custom painted, then + wxPG_FULL_CUSTOM_PAINT_SIZE(hei) or wxPG_FULL_CUSTOM_PAINT_FLEXIBLE_SIZE(hei) + is to be returned. + - Default behaviour is to return wxSize(0,0), which means no image. + - Default image width or height is indicated with dimension -1. + */ + virtual wxSize GetImageSize() const; + + /** Events received by editor widgets are processed here. Note that editor class + usually processes most events. Some, such as button press events of + TextCtrlAndButton class, should be handled here. Also, if custom handling + for regular events is desired, then that can also be done (for example, + wxSystemColourProperty custom handles wxEVT_COMMAND_CHOICE_SELECTED). + \param event + Associated wxEvent. + \retval + Should return true if any changes in value should be reported. This is case, + for example, when enter is pressed in wxTextCtrl. + */ + virtual bool OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event ); + +#if wxPG_INCLUDE_WXOBJECT + inline wxPG_CONST_WXCHAR_PTR GetClassName() const + { + return GetClassInfo()->GetClassName(); + } +#else + /** Returns classname (for example, "wxStringProperty" for wxStringProperty) + of a property class. + */ + virtual wxPG_CONST_WXCHAR_PTR GetClassName() const = 0; +#endif + + /** Returns pointer to the object that has methods related to + the value type of this property. Keep atleast this method + abstract so the class is kept abstract. + */ +#ifndef __WXPYTHON__ + virtual const wxPGValueType* GetValueType() const = 0; +#else + #ifndef SWIG + virtual const wxPGValueType* GetValueType() const; + #endif + + // Implement this in Python + virtual wxString GetType() const; +#endif + +#if !wxPG_VALUETYPE_IS_STRING + const wxPGValueType* GetValueTypePtr() const { return GetValueType(); } +#else + const wxPGValueType* GetValueTypePtr() const; +#endif + +#ifndef SWIG + /** Returns pointer to an instance of editor class. + */ + virtual const wxPGEditor* DoGetEditorClass() const; +#endif + +#ifdef __WXPYTHON__ + /** Returns name of editor used. Takes precendence in the wxPython bindings. + */ + virtual wxString GetEditor() const; +#endif + +#if wxUSE_VALIDATORS + /** Returns pointer to the wxValidator that should be used + with the editor of this property (NULL for no validator). + Setting validator explicitly via SetPropertyValidator + will override this. + + In most situations, code like this should work well + (macros are used to maintain one actual validator instance, + so on the second call the function exits within the first + macro): + + \code + + wxValidator* wxMyPropertyClass::DoGetValidator () const + { + WX_PG_DOGETVALIDATOR_ENTRY() + + wxMyValidator* validator = new wxMyValidator(...); + + ... prepare validator... + + WX_PG_DOGETVALIDATOR_EXIT(validator) + } + + \endcode + + \remarks + You can get common filename validator by returning + wxFilePropertyClass::GetClassValidator(). wxDirProperty, + for example, uses it. + */ + virtual wxValidator* DoGetValidator () const; +#endif // #if wxUSE_VALIDATORS + + /** Returns 0 for normal items. 1 for categories, -1 for other properties with children, + -2 for wxCustomProperty (mostly like -1 ones but with few expections). + \remarks + Should not be overridden by new custom properties. Usually only used internally. + */ + inline signed char GetParentingType() const { return m_parentingType; } + + /** Returns current value's index to the choice control. May also return, + through pointer arguments, strings that should be inserted to that control. + Irrelevant to classes which do not employ wxPG_EDITOR(Choice) or similar. + \remarks + - If returns -1 in choiceinfo->m_itemCount, then in that case this + class be derived from wxBaseEnumPropertyClass (see propdev.h) and + GetEntry is used to fill an array (slower, but handier if you don't + store your labels as arrays of strings). + - Must not crash even if property's set of choices is uninitialized + (i.e. it points to wxPGGlobalVars->m_emptyConstants). + */ + virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + + /** Override to paint an image in front of the property value text or drop-down + list item (but only if wxPGProperty::GetImageSize is overridden as well). + + If property's GetImageSize() returns size that has height != 0 but less than + row height ( < 0 has special meanings), wxPropertyGrid calls this method to + draw a custom image in a limited area in front of the editor control or + value text/graphics, and if control has drop-down list, then the image is + drawn there as well (even in the case GetImageSize() returned higher height + than row height). + + NOTE: Following applies when GetImageSize() returns a "flexible" height ( + using wxPG_FLEXIBLE_SIZE(W,H) macro), which implies variable height items: + If rect.x is < 0, then this is a measure item call, which means that + dc is invalid and only thing that should be done is to set paintdata.m_drawnHeight + to the height of the image of item at index paintdata.m_choiceItem. This call + may be done even as often as once every drop-down popup show. + + \param dc + wxDC to paint on. + \param rect + Box reserved for custom graphics. Includes surrounding rectangle, if any. + If x is < 0, then this is a measure item call (see above). + \param paintdata + wxPGPaintData structure with much useful data. + + \remarks + - You can actually exceed rect width, but if you do so then paintdata.m_drawnWidth + must be set to the full width drawn in pixels. + - Due to technical reasons, rect's height will be default even if custom height + was reported during measure call. + - Changing font and text colour affects the text drawn next to the painted image + (which is done immediately after the OnCustomPaint call finishes). + - Brush is guaranteed to be default background colour. It has been already used to + clear the background of area being painted. It can be modified. + - Pen is guaranteed to be 1-wide 'black' (or whatever is the proper colour) pen for + drawing framing rectangle. It can be changed as well. + \sa @link GetValueAsString @endlink + */ + virtual void OnCustomPaint( wxDC& dc, + const wxRect& rect, wxPGPaintData& paintdata ); + + /** Sets an attribute of this property. This is quite property class specific, + and there are no common attributes. Note that attribute may be specific + to a property instance, or it may affect all properties of its class. + \param id + Identifier of attribute + \param value + Value for that attribute. + */ + virtual void SetAttribute( int id, wxVariant& value ); + + + /** Adds entry to property's wxPGChoices and editor control (if it is active). + Returns index of item added. + */ + inline int AppendChoice( const wxString& label, int value = wxPG_INVALID_VALUE ) + { + return InsertChoice(label,-1,value); + } + + /** Removes entry from property's wxPGChoices and editor control (if it is active). + + If selected item is deleted, then the value is set to unspecified. + */ + void DeleteChoice( int index ); + + /** Returns comma-delimited string of property attributes. + */ + wxString GetAttributes( unsigned int flagmask = 0xFFFF ); + +#if !wxPG_INCLUDE_WXOBJECT + /** Returns classinfo of the property class. + */ + virtual const wxPGPropertyClassInfo* GetClassInfo() const = 0; +#endif + + /** Returns property's label. */ + inline const wxString& GetLabel() const { return m_label; } + +#ifndef SWIG + /** Returns wxPropertyGridState to which this property belongs. */ + wxPropertyGridState* GetParentState() const; +#endif + + /** Returns property's name (alternate way to access property). */ + inline const wxString& GetName() const { return m_name; } + inline void DoSetName(const wxString& str) { m_name = str; } + + /** If property did not have data extension, one is created now + (returns true in that case). + */ + bool EnsureDataExt(); + + /** Gets pre-calculated top y coordinate of property graphics. + This cannot be relied on all times (wxPropertyGrid knows when :) ), + and value is -1 if property is not visible. + */ + inline int GetY() const { return m_y; } + + void UpdateControl( wxWindow* primary ); + + inline wxString GetDisplayedString() const + { + return GetValueAsString(0); + } + + /** Returns property id. */ + inline wxPGId GetId() { return wxPGIdGen(this); } + + /** Returns property grid where property lies. */ + wxPropertyGrid* GetGrid() const; + + /** Returns highest level non-category, non-root parent. Useful when you + have nested wxCustomProperties/wxParentProperties. + \remarks + Thus, if immediate parent is root or category, this will return the + property itself. + */ + wxPGProperty* GetMainParent() const; + + /** Return parent of property */ + inline wxPGPropertyWithChildren* GetParent() const { return m_parent; } + + /** Returns true if property is valid and wxPropertyGrid methods + can operate on it safely. + */ + inline bool IsOk() const + { + return (( m_y >= -1 )?true:false); + } + + typedef short FlagType; +#ifndef __WXPYTHON__ + typedef void* ClientDataType; +#else + typedef PyObject* ClientDataType; +#endif + + inline bool IsFlagSet( FlagType flag ) const + { + return ( m_flags & flag ) ? true : false; + } + + inline bool IsValueUnspecified() const + { + return ( m_flags & wxPG_PROP_UNSPECIFIED ) ? true : false; + } + + bool HasFlag( FlagType flag ) const + { + return ( m_flags & flag ) ? true : false; + } + + /** Initializes the property. Usually only called in the constructor. + */ + void Init( const wxString& label, const wxString& name ); + + /** Returns true if extra children can be added for this property + (i.e. it is wxPropertyCategory or wxCustomProperty) + */ + inline bool CanHaveExtraChildren() const + { + return ( m_parentingType == 1 || m_parentingType == -2 ); + } + + /** Returns property's data extension (NULL if none). */ + inline wxPGPropertyDataExt* GetDataExt() { return m_dataExt; } + + unsigned int GetFlags() const + { + return (unsigned int)m_flags; + } + + const wxPGEditor* GetEditorClass() const; + +#ifndef __WXPYTHON__ + /** Returns type name of property that is compatible with CreatePropertyByType. + and wxVariant::GetType. + */ + inline const wxChar* GetType() const + { + return GetValueTypePtr()->GetType(); + } +#endif + + /** Adds entry to property's wxPGChoices and editor control (if it is active). + Returns index of item added. + */ + int InsertChoice( const wxString& label, int index, int value = wxPG_INVALID_VALUE ); + + bool IsKindOf( wxPGPropertyClassInfo& info ); + + /** Returns true if this is a sub-property. */ + inline bool IsSubProperty() const + { + wxPGProperty* parent = (wxPGProperty*)m_parent; + if ( parent && parent->GetParentingType() < 0 && parent->m_y > -2 ) + return true; + return false; + } + + /** Returns last visible sub-property, recursively. + */ + const wxPGProperty* GetLastVisibleSubItem() const; + + inline int GetMaxLength() const + { + return (int) m_maxLen; + } + +#ifdef SWIG + %pythoncode { + def GetValue(self): + return self.GetGrid().GetPropertyValue(self) + } +#else + /** Returns value as wxVariant. + */ + wxVariant GetValueAsVariant() const; +#endif + + /** Returns true if containing grid uses wxPG_EX_AUTO_UNSPECIFIED_VALUES. + */ + bool UsesAutoUnspecified() const; + + inline wxBitmap* GetValueImage() const + { + if ( m_dataExt ) + return m_dataExt->m_valueBitmap; + return (wxBitmap*) NULL; + } + + /** Returns number of children (always 0 for normal properties). */ + size_t GetChildCount() const; + + inline unsigned int GetArrIndex() const { return m_arrIndex; } + + inline unsigned int GetDepth() const { return (unsigned int)m_depth; } + + /** Returns position in parent's array. */ + inline unsigned int GetIndexInParent() const + { + return (unsigned int)m_arrIndex; + } + + /** Hides or reveals the property. + \param hide + true for hide, false for reveal. + */ + inline bool Hide( bool hide ); + + inline bool IsEnabled() const + { + return ( m_flags & wxPG_PROP_DISABLED ) ? false : true; + } + + /** If property's editor is created this forces its recreation. Useful + in SetAttribute etc. Returns true if actually did anything. + */ + bool RecreateEditor(); + + inline void SetAttrib( int id, wxVariant value ) + { + SetAttribute(id,value); + } + + /** Sets attributes from a comma-delimited string. + */ + void SetAttributes( const wxString& attributes ); + + /** Sets editor for a property. */ +#ifndef SWIG + inline void SetEditor( const wxPGEditor* editor ) + { + EnsureDataExt(); + m_dataExt->m_customEditor = editor; + } +#endif + + /** Sets editor for a property. */ + inline void SetEditor( const wxString& editorName ); + + /** Changes value of a property with choices, but only + works if the value type is long or string. */ + void SetChoiceSelection( int newValue, const wxPGChoiceInfo& choiceInfo ); + + /** Set wxBitmap in front of the value. This bitmap will be ignored if + property class has implemented OnCustomPaint. + */ + void SetValueImage( wxBitmap& bmp ); + + /** If property has choices and they are not yet exclusive, new such copy + of them will be created. + */ + void SetChoicesExclusive(); + + void SetFlag( FlagType flag ) { m_flags |= flag; } + + inline void SetHelpString( const wxString& helpString ) + { + EnsureDataExt(); + m_dataExt->m_helpString = helpString; + } + + inline void SetLabel( const wxString& label ) { m_label = label; } + + inline void SetValueToUnspecified() + { + m_flags |= wxPG_PROP_UNSPECIFIED; + } + +#if wxUSE_VALIDATORS + /** Sets wxValidator for a property*/ + inline void SetValidator( const wxValidator& validator ) + { + EnsureDataExt(); + m_dataExt->m_validator = wxDynamicCast(validator.Clone(),wxValidator); + } + + /** Gets assignable version of property's validator. */ + inline wxValidator* GetValidator() const + { + if ( m_dataExt ) + return m_dataExt->m_validator; + return DoGetValidator(); + } +#endif // #if wxUSE_VALIDATORS + + inline bool StdValidationProcedure( wxPGVariant value ) + { + DoSetValue( value ); + return true; + } + + /** Updates property value in case there were last minute + changes. If value was unspecified, it will be set to default. + Use only for properties that have TextCtrl-based editor. + \remarks + If you have code similar to + \code + // Update the value in case of last minute changes + if ( primary && propgrid->IsEditorsValueModified() ) + GetEditorClass()->CopyValueFromControl( this, primary ); + \endcode + in wxPGProperty::OnEvent wxEVT_COMMAND_BUTTON_CLICKED handler, + then replace it with call to this method. + \retval + True if value changed. + */ + bool PrepareValueForDialogEditing( wxPropertyGrid* propgrid ); + +#if wxPG_USE_CLIENT_DATA + inline ClientDataType GetClientData() const { return m_clientData; } + + /** Sets client data (void*) of a property. + \remarks + This untyped client data has to be deleted manually. + */ + inline void SetClientData( ClientDataType clientData ) + { +#ifdef __WXPYTHON__ + if ( m_clientData ) + Py_DECREF( m_clientData ); + Py_INCREF( clientData ); +#endif + m_clientData = clientData; + } +#endif + + /** Sets new set of choices for property. + */ + bool SetChoices( wxPGChoices& choices ); + + /** Sets new set of choices for property. + */ + inline bool SetChoices( const wxArrayString& labels, + const wxArrayInt& values = wxPG_EMPTY_ARRAYINT ); + + /** Set max length of text editor. + */ + inline bool SetMaxLength( int maxLen ); + + inline wxString GetHelpString() const + { + if (m_dataExt) + return m_dataExt->m_helpString; + return wxEmptyString; + } + + void ClearFlag( FlagType flag ) { m_flags &= ~(flag); } + + // Use, for example, to detect if item is inside collapsed section. + bool IsSomeParent( wxPGProperty* candidate_parent ) const; + + // Shows error as a tooltip or something similar (depends on platform). + void ShowError( const wxString& msg ); + +#if defined(__WXPYTHON__) && !defined(SWIG) + // This is the python object that contains and owns the C++ representation. + PyObject* m_scriptObject; +#endif + +#ifndef SWIG +protected: + + // Called in constructors. + void Init(); + + wxString m_label; + wxString m_name; + wxPGPropertyWithChildren* m_parent; +#if wxPG_USE_CLIENT_DATA + ClientDataType m_clientData; +#endif + wxPGPropertyDataExt* m_dataExt; // Optional data extension. + unsigned int m_arrIndex; // Index in parent's property array. + int m_y; // This could be short int. + + short m_maxLen; // Maximum length (mainly for string properties). + // Could be in some sort of wxBaseStringProperty, but currently, + // for maximum flexibility and compatibility, we'll stick it here. + // Anyway, we had 3 excess bytes to use so short int will fit in + // just fine. + + FlagType m_flags; + + // 1 = category + // 0 = no children + // -1 = has fixed-set of sub-properties + // -2 = this is wxCustomProperty (sub-properties can be added) + signed char m_parentingType; + + unsigned char m_depth; // Root has 0, categories etc. at that level 1, etc. + + // m_depthBgCol indicates width of background colour between margin and item + // (essentially this is category's depth, if none then equals m_depth). + unsigned char m_depthBgCol; + + unsigned char m_bgColIndex; // Background brush index. + unsigned char m_fgColIndex; // Foreground colour index. + +#endif // #ifndef SWIG +}; + +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxBasePropertyClassInfo; + + +// +// wxPGId comparison operators. +// TODO: Are these really used? +// + +#if !defined(__WXPYTHON__) + +inline bool operator==(const wxPGId& id, const wxString& b) +{ + wxASSERT(wxPGIdIsOk(id)); + const wxString& a = wxPGIdToPtr(id)->GetName(); + return (a.Len() == b.Len()) && (a.Cmp(b) == 0); +} + +inline bool operator==(const wxPGId& id, const wxChar* b) +{ + wxASSERT(wxPGIdIsOk(id)); + return wxPGIdToPtr(id)->GetName().Cmp(b) == 0; +} + +#endif // !defined(__WXPYTHON__) + + +// For dual-pointer-usage reasons, we need to use this trickery +// instead of wxObjArray. wxPGValueType hash map is declared +// in propdev.h. +typedef wxArrayPtrVoid wxPGArrayProperty; + + +// Always use wxString based hashmap with unicode, stl, swig and GCC 4.0+ +#if !defined(SWIG) +WX_DECLARE_STRING_HASH_MAP_WITH_DECL(void*, + wxPGHashMapS2P, + class WXDLLIMPEXP_PG); +#else +class WXDLLIMPEXP_PG wxPGHashMapS2P; +#endif + +#define wxPGPropNameStr const wxString& +#define wxPGNameConv(STR) STR + + +// ----------------------------------------------------------------------- + + +#ifndef SWIG + +WX_DECLARE_VOIDPTR_HASH_MAP_WITH_DECL(void*, + wxPGHashMapP2P, + class WXDLLIMPEXP_PG); + +#else +class WXDLLIMPEXP_PG wxPGHashMapP2P; +#endif // #ifndef SWIG + +// ----------------------------------------------------------------------- + +/** \class wxPGPropertyWithChildren + \ingroup classes + \brief wxPGPropertyWithChildren, alias wxParentPropertyClass, is a base + class for new properties that have sub-properties. For example, + wxFontProperty and wxFlagsProperty descend from this class. +*/ +class WXDLLIMPEXP_PG wxPGPropertyWithChildren : public wxPGProperty +{ +#ifndef SWIG + friend class wxPGProperty; + friend class wxPropertyGridState; + friend class wxPropertyGrid; +#endif + //_WX_PG_DECLARE_PROPERTY_CLASS(wxPGPropertyWithChildren) +public: + + /** Special constructor only used in special cases. */ + wxPGPropertyWithChildren(); + + /** When new class is derived, call this constructor. + \param label + Label for the property. + */ + wxPGPropertyWithChildren( const wxString& label, const wxString& name ); + + /** Destructor. */ + virtual ~wxPGPropertyWithChildren(); + + //virtual int GetParentingType() const; + + /** Advanced variant of GetValueAsString() that forms a string that + contains sequence of text representations of sub-properties. + */ + // Advanced version that gives property list and index to this item + virtual wxString GetValueAsString( int argFlags = 0 ) const; + + /** This overridden version converts comma or semicolon separated + tokens into child values. + */ + virtual bool SetValueFromString( const wxString& text, int flags ); + + /** Refresh values of child properties. + */ + virtual void RefreshChildren(); + + /** Called after child property p has been altered. + The value of this parent property should now be updated accordingly. + */ + virtual void ChildChanged( wxPGProperty* p ); + + /** This is used by properties that have fixed sub-properties. */ + void AddChild( wxPGProperty* prop ); + + /** This is used by Insert etc. */ + void AddChild2( wxPGProperty* prop, int index = -1, bool correct_mode = true ); + + /** Returns number of sub-properties. */ + inline size_t GetCount() const { return m_children.GetCount(); } + + /** Returns sub-property at index i. */ + inline wxPGProperty* Item( size_t i ) const { return (wxPGProperty*)m_children.Item(i); } + + /** Returns last sub-property. + */ + wxPGProperty* Last() const { return (wxPGProperty*)m_children.Last(); } + + /** Returns index of given sub-property. */ + inline int Index( const wxPGProperty* p ) const { return m_children.Index((void*)p); } + + /** Deletes all sub-properties. */ + void Empty(); + + inline bool IsExpanded() const + { + return ( m_expanded > 0 ) ? true : false; + } + + // Puts correct indexes to children + void FixIndexesOfChildren( size_t starthere = 0 ); + +#ifndef SWIG + // Returns wxPropertyGridState in which this property resides. + wxPropertyGridState* GetParentState() const { return m_parentState; } +#endif + + wxPGProperty* GetItemAtY( unsigned int y, unsigned int lh ); + + /** Returns (direct) child property with given name (or NULL if not found). + */ + wxPGProperty* GetPropertyByName( const wxString& name ) const; + +#ifndef SWIG + // Call for after sub-properties added with AddChild + void PrepareSubProperties(); + + inline void SetParentState( wxPropertyGridState* pstate ) { m_parentState = pstate; } + + // Call after fixed sub-properties added/removed after creation. + // if oldSelInd >= 0 and < new max items, then selection is + // moved to it. + void SubPropsChanged( int oldSelInd = -1 ); + +protected: + + wxPropertyGridState* m_parentState; + + wxPGArrayProperty m_children; + unsigned char m_expanded; +#endif // SWIG +}; + +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxBaseParentPropertyClassInfo; + +// ----------------------------------------------------------------------- + +/** \class wxPGRootPropertyClass + \ingroup classes + \brief Root parent property. +*/ +class WXDLLIMPEXP_PG wxPGRootPropertyClass : public wxPGPropertyWithChildren +{ +public: + WX_PG_DECLARE_PROPERTY_CLASS_NOPARENS +public: + + /** Constructor. */ + wxPGRootPropertyClass(); + virtual ~wxPGRootPropertyClass(); + +protected: +}; + +// ----------------------------------------------------------------------- + +/** \class wxPropertyCategoryClass + \ingroup classes + \brief Category (caption) property. +*/ +class WXDLLIMPEXP_PG wxPropertyCategoryClass : public wxPGPropertyWithChildren +{ + WX_PG_DECLARE_PROPERTY_CLASS_NOPARENS +public: + + /** Special constructor only used in special cases. */ + wxPropertyCategoryClass(); + + /** Construct. + \param label + Label for the category. + \remarks + All non-category properties appended will have most recently + added category. + */ + wxPropertyCategoryClass( const wxString& label, const wxString& name = wxPG_LABEL ); + ~wxPropertyCategoryClass(); + + /** Must be overridden with function that doesn't do anything. */ + virtual wxString GetValueAsString( int argFlags ) const; + + inline int GetTextExtent() const { return m_textExtent; } + + void CalculateTextExtent( wxWindow* wnd, wxFont& font ); + + void SetTextColIndex( unsigned int colInd ) { m_capFgColIndex = (wxByte) colInd; } + unsigned int GetTextColIndex() const { return (unsigned int) m_capFgColIndex; } + +protected: + int m_textExtent; // pre-calculated length of text + wxByte m_capFgColIndex; // caption text colour index +}; + +// ----------------------------------------------------------------------- + + +#ifndef SWIG + +typedef void* wxPGChoicesId; + +class WXDLLIMPEXP_PG wxPGChoicesData +{ +public: + + // Constructor sets m_refCount to 1. + wxPGChoicesData(); + + ~wxPGChoicesData(); + + wxArrayString m_arrLabels; + wxArrayInt m_arrValues; + + // So that multiple properties can use the same set + int m_refCount; + +}; + +#define wxPGChoicesEmptyData ((wxPGChoicesData*)NULL) + +#endif // SWIG + + +/** \class wxPGChoices + \ingroup classes + \brief Helper class for managing constant (key=value) sequences. +*/ +class WXDLLIMPEXP_PG wxPGChoices +{ +public: + + /** Basic constructor. */ + wxPGChoices() + { + Init(); + } + + /** Copy constructor. */ + wxPGChoices( wxPGChoices& a ) + { + wxASSERT(a.m_data); + m_data = a.m_data; + a.m_data->m_refCount++; + } + + /** Constructor. */ + wxPGChoices( const wxChar** labels, const long* values = NULL ) + { + Init(); + Set(labels,values); + } + + /** Constructor. */ + wxPGChoices( const wxArrayString& labels, const wxArrayInt& values = wxPG_EMPTY_ARRAYINT ) + { + Init(); + Set(labels,values); + } + + /** Simple interface constructor. */ + inline wxPGChoices( wxPGChoicesData* data ) + { + wxASSERT(data); + m_data = data; + data->m_refCount++; + } + + /** Destructor. */ + ~wxPGChoices() + { + Free (); + } + + void AssignData( wxPGChoicesData* data ); + + inline void Assign( const wxPGChoices& a ) + { + AssignData(a.m_data); + } + + /** Adds to current. If did not have own copies, creates them now. If was empty, + identical to set except that creates copies. + */ + void Add( const wxChar** labels, const long* values = NULL ); + + /** Version that works with wxArrayString. */ + void Add( const wxArrayString& arr, const long* values = NULL ); + + /** Version that works with wxArrayString and wxArrayInt. */ + void Add( const wxArrayString& arr, const wxArrayInt& arrint ); + + /** Adds single item. */ + void Add( const wxChar* label, int value = wxPG_INVALID_VALUE ); + + /** Adds single item. */ + void AddAsSorted( const wxString& label, int value = wxPG_INVALID_VALUE ); + + inline void EnsureData() + { + if ( m_data == wxPGChoicesEmptyData ) + m_data = new wxPGChoicesData(); + } + + /** Returns reference to wxArrayString of labels for you to modify. + */ + inline wxArrayString& GetLabels() + { + wxASSERT( m_data->m_refCount != 0xFFFFFFF ); + return m_data->m_arrLabels; + } + + /** Returns reference to wxArrayInt of values for you to modify. + */ + inline wxArrayInt& GetValues() + { + wxASSERT( m_data->m_refCount != 0xFFFFFFF ); + return m_data->m_arrValues; + } + + /** Returns false if this is a constant empty set of choices, + which should not be modified. + */ + bool IsOk () const + { + return ( m_data != wxPGChoicesEmptyData ); + } + + /** Gets a unsigned number identifying this list. */ + wxPGChoicesId GetId() const { return (wxPGChoicesId) m_data; }; + + /** Removes count items starting at position nIndex. */ + inline void RemoveAt(size_t nIndex, size_t count = 1) + { + wxASSERT( m_data->m_refCount != 0xFFFFFFF ); + wxPGChoicesData* data = m_data; + data->m_arrLabels.RemoveAt(nIndex,count); + if ( data->m_arrValues.GetCount() ) + data->m_arrValues.RemoveAt(nIndex,count); + } + +#ifndef SWIG + /** Does not create copies for itself. */ + void Set( const wxChar** labels, const long* values = NULL ) + { + Free(); + Add(labels,values); + } + + /** Version that works with wxArrayString. + TODO: Deprecate this. + */ + void Set( wxArrayString& arr, const long* values = (const long*) NULL ) + { + Free(); + Add(arr,values); + } +#endif // SWIG + + /** Version that works with wxArrayString and wxArrayInt. */ + void Set( const wxArrayString& labels, const wxArrayInt& values = wxPG_EMPTY_ARRAYINT ) + { + Free(); + if ( &values ) + Add(labels,values); + else + Add(labels); + } + + // Creates exclusive copy of current choices + inline void SetExclusive() + { + if ( m_data->m_refCount != 1 ) + { + wxPGChoicesData* data = new wxPGChoicesData; + data->m_arrLabels = m_data->m_arrLabels; + data->m_arrValues = m_data->m_arrValues; + Free(); + m_data = data; + } + } + + inline const wxString& GetLabel( size_t ind ) const + { + return m_data->m_arrLabels[ind]; + } + + inline const wxArrayString& GetLabels() const { return m_data->m_arrLabels; } + + inline size_t GetCount () const + { + wxASSERT_MSG( m_data, + wxT("When checking if wxPGChoices is valid, use IsOk() instead of GetCount()") ); + return m_data->m_arrLabels.GetCount(); + } + + inline int GetValue( size_t ind ) const { return m_data->m_arrValues[ind]; } + inline const wxArrayInt& GetValues() const { return m_data->m_arrValues; } + + inline int Index( const wxString& str ) const { return m_data->m_arrLabels.Index(str); } + + /** Inserts single item. */ +#if wxCHECK_VERSION(2,9,0) + void Insert( const wxString& label, int index, int value = wxPG_INVALID_VALUE ); +#else + void Insert( const wxChar* label, int index, int value = wxPG_INVALID_VALUE ); +#endif + + // Returns data, increases refcount. + inline wxPGChoicesData* GetData() + { + wxASSERT( m_data->m_refCount != 0xFFFFFFF ); + m_data->m_refCount++; + return m_data; + } + + // Returns plain data ptr - no refcounting stuff is done. + inline wxPGChoicesData* GetDataPtr() const { return m_data; } + + // Changes ownership of data to you. + inline wxPGChoicesData* ExtractData() + { + wxPGChoicesData* data = m_data; + m_data = wxPGChoicesEmptyData; + return data; + } + + inline void AddString( const wxString& str ) { m_data->m_arrLabels.Add(str); } + inline void AddInt( int val ) { m_data->m_arrValues.Add(val); } + + inline void SetLabels( wxArrayString& arr ) { m_data->m_arrLabels = arr; } + inline void SetValues( wxArrayInt& arr ) { m_data->m_arrValues = arr; } +#ifndef SWIG + inline void SetLabels( const wxArrayString& arr ) { m_data->m_arrLabels = arr; } + inline void SetValues( const wxArrayInt& arr ) { m_data->m_arrValues = arr; } + +protected: + + wxPGChoicesData* m_data; + + void Init(); + void Free(); +#endif +}; + + +// ----------------------------------------------------------------------- +// Property declaration. + +// Doxygen will only generate warnings here +#ifndef DOXYGEN + + +#define wxPG_CONSTFUNC(PROP) PROP +#define wxPG_PROPCLASS(PROP) PROP##Class + +// Macro based constructor. +#define wxPG_NEWPROPERTY(PROP,LABEL,NAME,VALUE) wx##PROP##Property(LABEL,NAME,VALUE) + +#define wxPG_DECLARE_PROPERTY_CLASSINFO(NAME) \ + extern wxPGPropertyClassInfo NAME##ClassInfo; + +#define wxPG_DECLARE_PROPERTY_CLASSINFO_WITH_DECL(NAME,DECL) \ + extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_PROPERTY_WITH_DECL(NAME,VALARG,DEFVAL,DECL) \ + extern DECL wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, VALARG value = DEFVAL ); \ + extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_PROPERTY(NAME,VALARG,DEFVAL) \ + extern wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, VALARG value = DEFVAL ); \ + wxPG_DECLARE_PROPERTY_CLASSINFO(NAME) + +// +// Specific macro-based declarations. +// + +#define WX_PG_DECLARE_STRING_PROPERTY_WITH_DECL(NAME,DECL) \ +extern DECL wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name= wxPG_LABEL, const wxString& value = wxEmptyString ); \ +extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_STRING_PROPERTY(NAME) \ +extern wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name= wxPG_LABEL, const wxString& value = wxEmptyString ); \ +wxPG_DECLARE_PROPERTY_CLASSINFO(NAME) + +#define WX_PG_DECLARE_CUSTOM_FLAGS_PROPERTY_WITH_DECL(NAME,DECL) \ +WX_PG_DECLARE_PROPERTY_WITH_DECL(NAME,long,-1,DECL) + +#define WX_PG_DECLARE_CUSTOM_FLAGS_PROPERTY(NAME) \ +WX_PG_DECLARE_PROPERTY(NAME,long,-1) + +#define WX_PG_DECLARE_CUSTOM_ENUM_PROPERTY_WITH_DECL(NAME,DECL) \ +WX_PG_DECLARE_PROPERTY_WITH_DECL(NAME,int,-1,DECL) + +#define WX_PG_DECLARE_CUSTOM_ENUM_PROPERTY(NAME) \ +WX_PG_DECLARE_PROPERTY(NAME,int,-1) + +#define WX_PG_DECLARE_ARRAYSTRING_PROPERTY_WITH_DECL(NAME,DECL) \ +extern DECL wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxArrayString& value = wxArrayString() ); \ +extern DECL wxPGPropertyClassInfo NAME##ClassInfo; + +#define WX_PG_DECLARE_ARRAYSTRING_PROPERTY(NAME) \ +extern wxPGProperty* wxPG_CONSTFUNC(NAME)( const wxString& label, const wxString& name = wxPG_LABEL, const wxArrayString& value = wxArrayString() ); \ +wxPG_DECLARE_PROPERTY_CLASSINFO(NAME) + +// Declare basic property classes. +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxStringProperty,const wxString&,wxEmptyString,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxIntProperty,long,0,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxUIntProperty,unsigned long,0,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxFloatProperty,double,0.0,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxBoolProperty,bool,false,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxLongStringProperty,const wxString&,wxEmptyString,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxFileProperty,const wxString&,wxEmptyString,WXDLLIMPEXP_PG) +WX_PG_DECLARE_PROPERTY_WITH_DECL(wxArrayStringProperty,const wxArrayString&,wxArrayString(),WXDLLIMPEXP_PG) + +WX_PG_DECLARE_STRING_PROPERTY_WITH_DECL(wxDirProperty,WXDLLIMPEXP_PG) + +// Enum and Flags Properties require special attention. +#ifndef SWIG + +extern WXDLLIMPEXP_PG wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + const wxChar** labels = (const wxChar**) NULL, + const long* values = NULL, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + wxPGChoices& constants, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& choices, const wxArrayInt& values, int value = 0 ); + +#else + +// Separate for SWIG inorder to have more default arguments +extern WXDLLIMPEXP_PG wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name = wxPG_LABEL, + const wxArrayString& choices = wxArrayString(), const wxArrayInt& values = wxArrayInt(), int value = 0 ); + +#endif // SWIG + +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxEnumPropertyClassInfo; + + +#ifndef SWIG + +extern WXDLLIMPEXP_PG wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + const wxChar** labels = (const wxChar**) NULL, + const long* values = NULL, const wxString& value = wxEmptyString ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxString& value = wxEmptyString ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + wxPGChoices& constants, const wxString& value = wxEmptyString ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& choices, const wxArrayInt& values, const wxString& value = wxEmptyString ); + +#else + +// Separate for SWIG inorder to have more default arguments +extern WXDLLIMPEXP_PG wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name = wxPG_LABEL, + const wxArrayString& choices = wxArrayString(), const wxArrayInt& values = wxArrayInt(), const wxString& value = wxEmptyString ); + +#endif // SWIG + +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxEditEnumPropertyClassInfo; + + +#ifndef SWIG + +extern WXDLLIMPEXP_PG wxPGProperty* wxFlagsProperty( const wxString& label, const wxString& name, const wxChar** labels = (const wxChar**) NULL, + const long* values = NULL, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxFlagsProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxFlagsProperty( const wxString& label, const wxString& name, + wxPGChoices& constants, int value = 0 ); + +extern WXDLLIMPEXP_PG wxPGProperty* wxFlagsProperty( const wxString& label, const wxString& name, + const wxArrayString& flag_labels, const wxArrayInt& values, int value = 0 ); + +#else + +// Separate for SWIG inorder to have more default arguments +extern WXDLLIMPEXP_PG wxPGProperty* wxFlagsProperty( const wxString& label, const wxString& name = wxPG_LABEL, + const wxArrayString& flag_labels = wxArrayString(), const wxArrayInt& values = wxArrayInt(), int value = 0 ); + +#endif // SWIG + + +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxFlagsPropertyClassInfo; + + +// wxCustomProperty doesn't have value argument. +extern WXDLLIMPEXP_PG wxPGProperty* wxCustomProperty( const wxString& label, const wxString& name = wxPG_LABEL ); +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxCustomPropertyClassInfo; + +// wxParentProperty doesn't have value argument. +extern WXDLLIMPEXP_PG wxPGProperty* wxParentProperty( const wxString& label, const wxString& name ); +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxParentPropertyClassInfo; + +// wxPropertyCategory doesn't have value argument. +extern WXDLLIMPEXP_PG wxPGProperty* wxPropertyCategory ( const wxString& label, const wxString& name = wxPG_LABEL ); +extern WXDLLIMPEXP_PG wxPGPropertyClassInfo wxPropertyCategoryClassInfo; + +#endif // DOXYGEN + + +#ifndef wxDynamicCastVariantData + #define wxDynamicCastVariantData wxDynamicCast +#endif + +// FIXME: Should this be out-of-inline? +inline wxObject* wxPG_VariantToWxObject( wxVariant& variant, wxClassInfo* classInfo ) +{ + if ( !variant.IsValueKindOf(classInfo) ) + return (wxObject*) NULL; + wxVariantData* vdata = variant.GetData(); + + wxPGVariantDataWxObj* vdataWxObj = wxDynamicCastVariantData(vdata, wxPGVariantDataWxObj); + if ( vdataWxObj ) + return (wxObject*) vdataWxObj->GetValuePtr(); + + return variant.GetWxObjectPtr(); +} + +// +// Redefine wxGetVariantCast to also take propertygrid variantdata +// classes into account. +// TODO: Remove after persistent wxObject classes added (i.e. +// GetWxObjectPtr works for all). +// +#undef wxGetVariantCast +#define wxGetVariantCast(var,classname) (classname*)wxPG_VariantToWxObject(var,&classname::ms_classInfo) + +// TODO: After a while, remove this. +#define WX_PG_VARIANT_TO_WXOBJECT(VARIANT,CLASSNAME) (CLASSNAME*)wxPG_VariantToWxObject(VARIANT,&CLASSNAME::ms_classInfo) +//#define WX_PG_VARIANT_TO_WXOBJECT(VARIANT,CLASSNAME) wxGetVariantCast(VARIANT,CLASSNAME) + +// ----------------------------------------------------------------------- + +#ifndef SWIG +// We won't need this class from wxPython + +/** \class wxPropertyGridState + \ingroup classes + \brief + Contains information of a single wxPropertyGrid page. +*/ +// BM_STATE +class WXDLLIMPEXP_PG wxPropertyGridState +{ + friend class wxPGProperty; + friend class wxPropertyGrid; + friend class wxPropertyGridManager; +public: + + /** Constructor. */ + wxPropertyGridState(); + + /** Destructor. */ + virtual ~wxPropertyGridState(); + + /** Base append. */ + wxPGId Append( wxPGProperty* property ); + + wxPGId AppendIn( wxPGPropertyWithChildren* pwc, const wxString& label, const wxString& propname, wxVariant& value ); + + /** Returns property by its name. */ + wxPGId BaseGetPropertyByName( wxPGPropNameStr name ) const; + + /** Called in, for example, wxPropertyGrid::Clear. */ + void Clear(); + + void ClearModifiedStatus( wxPGProperty* p ); + + static void ClearPropertyAndChildrenFlags( wxPGProperty* p, long flags ); + static void SetPropertyAndChildrenFlags( wxPGProperty* p, long flags ); + + bool ClearPropertyValue( wxPGProperty* p ); + + inline bool ClearSelection() + { + return DoSelectProperty(wxPGIdGen((wxPGProperty*)NULL)); + } + + bool Collapse( wxPGProperty* p ); + + /** Override this member function to add custom behaviour on property deletion. + */ + virtual void DoDelete( wxPGProperty* item ); + + /** Override this member function to add custom behaviour on property insertion. + */ + virtual wxPGId DoInsert( wxPGPropertyWithChildren* parent, int index, wxPGProperty* property ); + + bool EnableCategories( bool enable ); + + /** Enables or disables given property and its subproperties. */ + bool EnableProperty( wxPGProperty* p, bool enable ); + + bool Expand( wxPGProperty* p ); + + bool ExpandAll( unsigned char do_expand ); + + /** Returns id of first item, whether it is a category or property. */ + inline wxPGId GetFirst() const + { + wxPGProperty* p = (wxPGProperty*) NULL; + if ( m_properties->GetCount() ) + p = m_properties->Item(0); + return wxPGIdGen(p); + } + + wxPGId GetFirstCategory() const; + + wxPGId GetFirstProperty() const; + + wxPropertyGrid* GetGrid() const { return m_pPropGrid; } + + wxPGId GetNextCategory( wxPGId id ) const; + + wxPGId GetNextProperty( wxPGId id ) const; + + static wxPGId GetNextSibling( wxPGId id ); + + static wxPGId GetPrevSibling( wxPGId id ); + + wxPGId GetPrevProperty( wxPGId id ) const; + + wxPGId GetPropertyByLabel( const wxString& name, wxPGPropertyWithChildren* parent = (wxPGPropertyWithChildren*) NULL ) const; + + wxVariant GetPropertyValues( const wxString& listname, wxPGId baseparent, long flags ) const; + + inline wxPGProperty* GetSelection() const { return m_selected; } + + /** Used by SetSplitterLeft. */ + int GetLeftSplitterPos( wxClientDC& dc, wxPGPropertyWithChildren* pwc, bool subProps ); + + inline bool IsDisplayed() const; + + inline bool IsInNonCatMode() const { return (bool)(m_properties == m_abcArray); } + + /** Only inits arrays, doesn't migrate things or such. */ + void InitNonCatMode (); + + void LimitPropertyEditing ( wxPGProperty* p, bool limit = true ); + + bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 ); + + void SetPropertyLabel( wxPGProperty* p, const wxString& newlabel ); + + bool SetPropertyPriority( wxPGProperty* p, int priority ); + + void SetPropVal( wxPGProperty* p, const wxPGVariant& value ); + + bool SetPropertyValue( wxPGProperty* p, const wxPGValueType* typeclass, const wxPGVariant& value ); + + bool SetPropertyValue( wxPGProperty* p, const wxChar* typestring, const wxPGVariant& value ); + + bool SetPropertyValueString( wxPGProperty* p, const wxString& value ); + + bool SetPropertyValue( wxPGProperty* p, wxVariant& value ); + + bool SetPropertyValueWxObjectPtr( wxPGProperty* p, wxObject* value ); + + /** Sets value (long integer) of a property. */ + inline void SetPropertyValueLong( wxPGProperty* p, long value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(long), wxPGVariantFromLong(value) ); + } + /** Sets value (integer) of a property. */ + inline void SetPropertyValue( wxPGProperty* p, int value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(long), wxPGVariantFromLong((long)value) ); + } + /** Sets value (floating point) of a property. */ + inline void SetPropertyValueDouble( wxPGProperty* p, double value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(double), wxPGVariantFromDouble(value) ); + } + /** Sets value (bool) of a property. */ + inline void SetPropertyValueBool( wxPGProperty* p, bool value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(bool), wxPGVariantFromLong(value?(long)1:(long)0) ); + } + /** Sets value (wxArrayString) of a property. */ + inline void SetPropertyValueArrstr2( wxPGProperty* p, const wxArrayString& value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(wxArrayString), wxPGVariantFromArrayString(value) ); + } + /** Sets value (void*) of a property. */ + inline void SetPropertyValue( wxPGProperty* p, void* value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(void), value ); + } + /** Sets value (wxPoint&) of a property. */ + inline void SetPropertyValuePoint( wxPGProperty* p, const wxPoint& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("wxPoint"), wxPGVariantCreator(value) ); + } + /** Sets value (wxSize&) of a property. */ + inline void SetPropertyValueSize( wxPGProperty* p, const wxSize& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("wxSize"), wxPGVariantCreator(value) ); + } + /** Sets value (wxArrayInt&) of a property. */ + inline void SetPropertyValueArrint2( wxPGProperty* p, const wxArrayInt& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("wxArrayInt"), wxPGVariantCreator(value)); + } +#if wxUSE_DATETIME + /** Sets value (wxDateTime&) of a property. */ + inline void SetPropertyValueDatetime( wxPGProperty* p, const wxDateTime& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("datetime"), wxPGVariantCreator(value) ); + } +#endif +#ifdef __WXPYTHON__ + inline void SetPropertyValuePyObject( wxPGProperty* p, PyObject* value ) + { + SetPropertyValue( p, wxPG_VALUETYPE(PyObject), wxPGVariantCreator(value) ); + } +#endif + /** Sets value (wxLongLong&) of a property. */ + inline void SetPropertyValueLongLong( wxPGProperty* p, const wxLongLong& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("wxLongLong"), wxPGVariantCreator(value) ); + } + /** Sets value (wxULongLong&) of a property. */ + inline void SetPropertyValueULongLong( wxPGProperty* p, const wxULongLong& value ) + { + wxASSERT(p); + SetPropertyValue( p, wxT("wxULongLong"), wxPGVariantCreator(value) ); + } + + void SetPropertyValues( const wxVariantList& list, wxPGId default_category ); + + void SetPropertyUnspecified( wxPGProperty* p ); + +#ifdef wxPG_COMPATIBILITY_1_0_0 + #define SetPropertyValueUnspecified SetPropertyUnspecified +#endif + + void Sort( wxPGProperty* p ); + void Sort(); + +protected: + +#ifndef DOXYGEN + int PrepareToAddItem ( wxPGProperty* property, wxPGPropertyWithChildren* scheduledParent ); + + /** If visible, then this is pointer to wxPropertyGrid. + This shall *never* be NULL to indicate that this state is not visible. + */ + wxPropertyGrid* m_pPropGrid; + + /** Pointer to currently used array. */ + wxPGPropertyWithChildren* m_properties; + + /** Array for categoric mode. */ + wxPGRootPropertyClass m_regularArray; + + /** Array for root of non-categoric mode. */ + wxPGRootPropertyClass* m_abcArray; + + /** Dictionary for name-based access. */ + wxPGHashMapS2P m_dictName; + + /** Most recently added category. */ + wxPropertyCategoryClass* m_currentCategory; + + /** Pointer to selected property. */ + wxPGProperty* m_selected; + + /** 1 if m_lastCaption is also the bottommost caption. */ + unsigned char m_lastCaptionBottomnest; + /** 1 items appended/inserted, so stuff needs to be done before drawing; + If m_bottomy == 0, then calcylatey's must be done. + Otherwise just sort. + */ + unsigned char m_itemsAdded; + + /** 1 if any value is modified. */ + unsigned char m_anyModified; + +#endif // #ifndef DOXYGEN + +}; + +#endif // #ifndef SWIG + +inline bool wxPGProperty::SetChoices( const wxArrayString& labels, + const wxArrayInt& values ) +{ + wxPGChoices chs(labels,values); + return SetChoices(chs); +} + +// ----------------------------------------------------------------------- + +/* + + wxASSERT_MSG( wxPGIdIsOk(id), \ + wxT("invalid property id") ); \ + +*/ + + +// Helper macro that does necessary preparations when calling +// some wxPGProperty's member function. +#define wxPG_PROP_ID_CALL_PROLOG() \ + wxPGProperty *p = wxPGIdToPtr(id); \ + wxCHECK_RET( p, wxT("invalid property id") ); + +#define wxPG_PROP_NAME_CALL_PROLOG() \ + wxPGProperty *p = wxPGIdToPtr(GetPropertyByNameI(name)); \ + if ( !p ) return; + +#define wxPG_PROP_ID_CALL_PROLOG_RETVAL(RVAL) \ + wxPGProperty *p = wxPGIdToPtr(id); \ + wxCHECK_MSG( p, RVAL, wxT("invalid property id") ); + +#define wxPG_PROP_NAME_CALL_PROLOG_RETVAL(RVAL) \ + wxPGProperty *p = wxPGIdToPtr(GetPropertyByNameI(name)); \ + if ( !p ) return RVAL; + +// GetPropertyName version used internally. Use GetPropertyName for slight speed advantage, +// or GetPropertyNameA for nice assertion (essential for wxPython bindings). +#define GetPropertyByNameI GetPropertyByNameA + +// FOR BACKWARDS COMPATIBILITY +#define GetPropertyByNameWithAssert GetPropertyByNameA + + +/** \class wxPropertyContainerMethods + \ingroup classes + \brief In order to have most same base methods, both wxPropertyGrid and + wxPropertyGridManager must derive from this. +*/ +class WXDLLIMPEXP_PG wxPropertyContainerMethods +// BM_METHODS +{ +public: + + /** Destructor */ + virtual ~wxPropertyContainerMethods() { }; + + /** Adds choice to a property that can accept one. + \remarks + - If you need to make sure that you modify only the set of choices of + a single property (and not also choices of other properties with initially + identical set), call wxPropertyGrid::SetPropertyChoicesPrivate. + - This usually only works for wxEnumProperty and derivatives (wxFlagsProperty + can get accept new items but its items may not get updated). + */ + void AddPropertyChoice( wxPGId id, const wxString& label, int value = wxPG_INVALID_VALUE ); + inline void AddPropertyChoice( wxPGPropNameStr name, const wxString& label, int value = wxPG_INVALID_VALUE ) + { + wxPG_PROP_NAME_CALL_PROLOG() + AddPropertyChoice(wxPGIdGen(p),label,value); + } + + /** Inorder to add new items into a property with fixed children (for instance, wxFlagsProperty), + you need to call this method. After populating has been finished, you need to call EndAddChildren. + */ + void BeginAddChildren( wxPGId id ); + inline void BeginAddChildren( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + BeginAddChildren(wxPGIdGen(p)); + } + + /** Called after population of property with fixed children has finished. + */ + void EndAddChildren( wxPGId id ); + inline void EndAddChildren( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + EndAddChildren(wxPGIdGen(p)); + } + + /** Inserts choice to a property that can accept one. + + See AddPropertyChoice for more details. + */ + void InsertPropertyChoice( wxPGId id, const wxString& label, int index, int value = wxPG_INVALID_VALUE ); + inline void InsertPropertyChoice( wxPGPropNameStr name, const wxString& label, int index, int value = wxPG_INVALID_VALUE ) + { + wxPG_PROP_NAME_CALL_PROLOG() + InsertPropertyChoice(wxPGIdGen(p),label,index,value); + } + + /** Deletes choice from a property. + + If selected item is deleted, then the value is set to unspecified. + + See AddPropertyChoice for more details. + */ + void DeletePropertyChoice( wxPGId id, int index ); + inline void DeletePropertyChoice( wxPGPropNameStr name, int index ) + { + wxPG_PROP_NAME_CALL_PROLOG() + DeletePropertyChoice(wxPGIdGen(p),index); + } + + /** Constructs a property. Class used is given as the first + string argument. It may be either normal property class + name, such as "wxIntProperty" or a short one such as + "Int". + */ + static wxPGProperty* CreatePropertyByClass(const wxString &classname, + const wxString &label, + const wxString &name); + + /** Constructs a property. Value type name used is given as the first + string argument. It may be "string", "long", etc. Any value returned + by wxVariant::GetType fits there. + + Otherwise, this is similar as CreatePropertyByClass. + \remarks + Cannot generate property category. + */ + static wxPGProperty* CreatePropertyByType(const wxString &valuetype, + const wxString &label, + const wxString &name); + + /** Deletes a property by id. If category is deleted, all children are automatically deleted as well. */ + void Delete( wxPGId id ); + + /** Deletes a property by name. */ + inline void Delete( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + Delete( wxPGIdGen(p) ); + } + + /** Returns id of first child of given property. + \remarks + Does not return sub-properties! + */ + inline wxPGId GetFirstChild( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) p; + if ( pwc->GetParentingType()==0 || pwc->GetParentingType()==-1 || !pwc->GetCount() ) + return wxNullProperty; + return wxPGIdGen(pwc->Item(0)); + } + inline wxPGId GetFirstChild( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return GetFirstChild( wxPGIdGen(p) ); + } + + /** Returns next item under the same parent. */ + inline wxPGId GetNextSibling( wxPGId id ) + { + return wxPropertyGridState::GetNextSibling(id); + } + inline wxPGId GetNextSibling( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return wxPropertyGridState::GetNextSibling(wxPGIdGen(p)); + } + + /** Returns comma-delimited string with property's attributes (both + pseudo-attributes such as "Disabled" and "Modified" and real + attributes such as "BoolUseCheckbox" - actual names may vary). + \param flagmask + Combination of property flags that should be included (in addition + to any other attributes). For example, to avoid adding Modified + attribute use ~(wxPG_PROP_MODIFIED). + \remarks + Atleast in 1.2.x and earlier this does not return complete list of attributes + (for example, no floating point precision) and some attributes have + generic names (such as "Special1" instead of "UseCheckbox" etc) + */ + inline wxString GetPropertyAttributes( wxPGId id, unsigned int flagmask = 0xFFFF ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetAttributes(flagmask); + } + + /** Sets attributes from a string generated by GetPropertyAttributes. + \remarks + Performance may not be top-notch. + */ + inline static void SetPropertyAttributes( wxPGId id, const wxString& attributes ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetAttributes(attributes); + } + + inline void SetPropertyAttributes( wxPGPropNameStr name, const wxString& attributes ) const + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetAttributes(attributes); + } + + /** Returns id of property with given name (case-sensitive). If there is no + property with such name, returned property id is invalid ( i.e. it will return + false with IsOk method). + \remarks + - Sub-properties (i.e. properties which have parent that is not category or + root) can not be accessed globally by their name. Instead, use + "." in place of "". + */ + wxPGId GetPropertyByName( wxPGPropNameStr name ) const; + + /** Returns id of a sub-property 'subname' of property 'name'. Same as + calling GetPropertyByNameI(wxT("name.subname")), albeit slightly faster. + */ + wxPGId GetPropertyByName( wxPGPropNameStr name, wxPGPropNameStr subname ) const; + + /** Returns writable reference to property's list of choices (and relevant + values). If property does not have any choices, will return reference + to an invalid set of choices that will return false on IsOk call. + */ + wxPGChoices& GetPropertyChoices( wxPGId id ); + wxPGChoices& GetPropertyChoices( wxPGPropNameStr name ); + + /** Gets name of property's constructor function. */ + inline wxPG_CONST_WXCHAR_PTR GetPropertyClassName( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxPG_CONST_WXCHAR_DEFVAL) + return p->GetClassName(); + } + + /** Gets name of property's constructor function. */ + inline wxPG_CONST_WXCHAR_PTR GetPropertyClassName( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxPG_CONST_WXCHAR_DEFVAL) + return p->GetClassName(); + } + +#if wxPG_USE_CLIENT_DATA + /** Returns client data (void*) of a property. */ + inline wxPGProperty::ClientDataType GetPropertyClientData( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(NULL) + return p->GetClientData(); + } + /** Returns client data (void*) of a property. */ + inline wxPGProperty::ClientDataType GetPropertyClientData( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(NULL) + return p->GetClientData(); + } +#endif + + /** Returns property's editor. */ + inline const wxPGEditor* GetPropertyEditor( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(NULL) + return p->GetEditorClass(); + } + + inline const wxPGEditor* GetPropertyEditor( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(NULL) + return p->GetEditorClass(); + } + + /** Returns property's custom value image (NULL of none). */ + inline wxBitmap* GetPropertyImage( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(NULL) + if ( p->GetDataExt() ) + return p->GetDataExt()->m_valueBitmap; + return (wxBitmap*) NULL; + } + + inline wxBitmap* GetPropertyImage( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(NULL) + return GetPropertyImage(wxPGIdGen(p)); + } + + /** Returns property's position under its parent. */ + inline unsigned int GetPropertyIndex( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(INT_MAX) + return p->GetIndexInParent(); + } + + /** Returns property's position under its parent. */ + inline unsigned int GetPropertyIndex( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(INT_MAX) + return p->GetIndexInParent(); + } + + /** Returns label of a property. */ + inline const wxString& GetPropertyLabel( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetLabel(); + } + inline const wxString& GetPropertyLabel( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetLabel(); + } + + /** Returns name of a property. Note that obviously there is no name-version + of this member function. */ + inline const wxString& GetPropertyName( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetName(); + } + + /** Returns parent item of a property. */ + inline wxPGId GetPropertyParent( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + return p->GetParent(); + } + + /** Returns parent item of a property. */ + inline wxPGId GetPropertyParent( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return p->GetParent(); + } + + /** Returns priority of a property (wxPG_HIGH or wxPG_LOW). */ + inline int GetPropertyPriority( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxPG_HIGH) + if ( p && p->IsFlagSet(wxPG_PROP_HIDEABLE) ) + return wxPG_LOW; + return wxPG_HIGH; + } + + /** Returns priority of a property (wxPG_HIGH or wxPG_LOW). */ + inline int GetPropertyPriority( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxPG_HIGH) + return GetPropertyPriority(wxPGIdGen(p)); + } + + /** Returns pointer to a property. + */ + inline wxPGProperty* GetPropertyPtr( wxPGId id ) const { return wxPGIdToPtr(id); } + + /** Returns pointer to a property. + */ + inline wxPGProperty* GetPropertyPtr( wxPGPropNameStr name ) const + { + return wxPGIdToPtr(GetPropertyByName(name)); + } + + /** Returns help string associated with a property. */ + inline wxString GetPropertyHelpString( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetHelpString(); + } + + /** Returns help string associated with a property. */ + inline wxString GetPropertyHelpString( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(m_emptyString) + return p->GetHelpString(); + } + + /** Returns short name for property's class. For example, + "wxPropertyCategory" translates to "Category" and "wxIntProperty" + to "Int". + */ + wxPG_PYTHON_STATIC wxString GetPropertyShortClassName( wxPGId id ); + +#if wxUSE_VALIDATORS + /** Returns validator of a property as a reference, which you + can pass to any number of SetPropertyValidator. + */ + inline wxValidator* GetPropertyValidator( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(NULL) + return p->GetValidator(); + } + inline wxValidator* GetPropertyValidator( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(NULL) + return p->GetValidator(); + } +#endif + +#ifndef SWIG + /** Returns value as wxVariant. To get wxObject pointer from it, + you will have to use WX_PG_VARIANT_TO_WXOBJECT(VARIANT,CLASSNAME) macro. + + If property value is unspecified, Null variant is returned. + */ + inline wxVariant GetPropertyValue( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxVariant()) + return p->GetValueAsVariant(); + } + + /** Returns value as wxVariant. To get wxObject pointer from it, + you will have to use WX_PG_VARIANT_TO_WXOBJECT(VARIANT,CLASSNAME) macro. + + If property value is unspecified, Null variant is returned. + */ + inline wxVariant GetPropertyValue( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxVariant()) + return p->GetValueAsVariant(); + } +#endif + + wxPG_PYTHON_STATIC wxString GetPropertyValueAsString( wxPGId id ) wxPG_GETVALUE_CONST; + wxPG_PYTHON_STATIC long GetPropertyValueAsLong( wxPGId id ) wxPG_GETVALUE_CONST; +#ifndef SWIG + wxPG_PYTHON_STATIC inline int GetPropertyValueAsInt( wxPGId id ) wxPG_GETVALUE_CONST { return (int)GetPropertyValueAsLong(id); } +#endif + wxPG_PYTHON_STATIC bool GetPropertyValueAsBool( wxPGId id ) wxPG_GETVALUE_CONST; + wxPG_PYTHON_STATIC double GetPropertyValueAsDouble( wxPGId id ) wxPG_GETVALUE_CONST; + wxPG_PYTHON_STATIC const wxObject* GetPropertyValueAsWxObjectPtr( wxPGId id ) wxPG_GETVALUE_CONST; + wxPG_PYTHON_STATIC void* GetPropertyValueAsVoidPtr( wxPGId id ) wxPG_GETVALUE_CONST; + +#define wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(TYPENAME, DEFVAL) \ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(DEFVAL) \ + if ( wxStrcmp(p->GetValueTypePtr()->GetCustomTypeName(),TYPENAME) != 0 ) \ + { \ + wxPGGetFailed(p,TYPENAME); \ + return DEFVAL; \ + } + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC const wxArrayString& GetPropertyValueAsArrayString( wxPGId id ) wxPG_GETVALUE_CONST; +#else + wxPG_PYTHON_STATIC inline wxArrayString GetPropertyValueAsArrayString( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("arrstring"), wxArrayString()) + return wxPGVariantToArrayString(p->DoGetValue()); + } +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC inline const wxPoint& GetPropertyValueAsPoint( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxPoint"), *((const wxPoint*)NULL)) + return wxPGVariantToWxPoint(p->DoGetValue()); + } +#else + wxPG_PYTHON_STATIC inline wxPoint GetPropertyValueAsPoint( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxPoint"), wxPoint()) + return wxPGVariantToWxPoint(p->DoGetValue()); + } +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC inline const wxSize& GetPropertyValueAsSize( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxSize"), *((const wxSize*)NULL)) + return wxPGVariantToWxSize(p->DoGetValue()); + } +#else + wxPG_PYTHON_STATIC inline wxSize GetPropertyValueAsSize( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxSize"), wxSize()) + return wxPGVariantToWxSize(p->DoGetValue()); + } +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC inline const wxLongLong& GetPropertyValueAsLongLong( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxLongLong"), *((const wxLongLong*)NULL)) + return wxPGVariantToWxLongLong(p->DoGetValue()); + } +#else + wxPG_PYTHON_STATIC inline wxLongLong GetPropertyValueAsLongLong( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxLongLong"), wxLongLong()) + return wxPGVariantToWxLongLong(p->DoGetValue()); + } +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC inline const wxULongLong& GetPropertyValueAsULongLong( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxULongLong"), *((const wxULongLong*)NULL)) + return wxPGVariantToWxULongLong(p->DoGetValue()); + } +#else + wxPG_PYTHON_STATIC inline wxULongLong GetPropertyValueAsULongLong( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxULongLong"), wxULongLong()) + return wxPGVariantToWxULongLong(p->DoGetValue()); + } +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + wxPG_PYTHON_STATIC inline const wxArrayInt& GetPropertyValueAsArrayInt( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxArrayInt"), wxPG_EMPTY_ARRAYINT) + return wxPGVariantToArrayInt(p->DoGetValue()); + } +#else + wxPG_PYTHON_STATIC inline wxArrayInt GetPropertyValueAsArrayInt( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(wxT("wxArrayInt"), wxArrayInt()) + wxArrayInt arr = wxPGVariantToArrayInt(p->DoGetValue()); + return arr; + } +#endif + +#if wxUSE_DATETIME + wxPG_PYTHON_STATIC inline wxDateTime GetPropertyValueAsDateTime( wxPGId id ) wxPG_GETVALUE_CONST + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxDateTime()) + + if ( wxStrcmp(p->GetValueTypePtr()->GetCustomTypeName(),wxT("datetime")) != 0 ) + { + wxPGGetFailed(p,wxT("datetime")); + return wxDateTime(); + } + return p->DoGetValue().GetDateTime(); + } +#endif + +#ifdef __WXPYTHON__ + wxPG_PYTHON_STATIC PyObject* GetPropertyValueAsPyObject( wxPGId id ) wxPG_GETVALUE_CONST; +#endif + + inline wxString GetPropertyValueAsString( wxPGPropNameStr name ) const + { + return GetPropertyValueAsString( GetPropertyByNameI(name) ); + } + inline long GetPropertyValueAsLong( wxPGPropNameStr name ) const + { + return GetPropertyValueAsLong( GetPropertyByNameI(name) ); + } +#ifndef SWIG + inline int GetPropertyValueAsInt( wxPGPropNameStr name ) const + { + return GetPropertyValueAsInt( GetPropertyByNameI(name) ); + } +#endif + inline bool GetPropertyValueAsBool( wxPGPropNameStr name ) const + { + return GetPropertyValueAsBool( GetPropertyByNameI(name) ); + } + inline double GetPropertyValueAsDouble( wxPGPropNameStr name ) const + { + return GetPropertyValueAsDouble( GetPropertyByNameI(name) ); + } + inline const wxObject* GetPropertyValueAsWxObjectPtr ( wxPGPropNameStr name ) const + { + return GetPropertyValueAsWxObjectPtr( GetPropertyByNameI(name) ); + } +#if !wxPG_PGVARIANT_IS_VARIANT + inline const wxArrayString& GetPropertyValueAsArrayString ( wxPGPropNameStr name ) const + { + return GetPropertyValueAsArrayString( GetPropertyByNameI(name) ); + } + inline const wxPoint& GetPropertyValueAsPoint( wxPGPropNameStr name ) const + { + return GetPropertyValueAsPoint( GetPropertyByNameI(name) ); + } + inline const wxSize& GetPropertyValueAsSize( wxPGPropNameStr name ) const + { + return GetPropertyValueAsSize( GetPropertyByNameI(name) ); + } + inline const wxArrayInt& GetPropertyValueAsArrayInt( wxPGPropNameStr name ) const + { + return GetPropertyValueAsArrayInt( GetPropertyByNameI(name) ); + } +#else + inline wxArrayString GetPropertyValueAsArrayString ( wxPGPropNameStr name ) const + { + return GetPropertyValueAsArrayString( GetPropertyByNameI(name) ); + } + inline wxPoint GetPropertyValueAsPoint( wxPGPropNameStr name ) const + { + return GetPropertyValueAsPoint( GetPropertyByNameI(name) ); + } + inline wxSize GetPropertyValueAsSize( wxPGPropNameStr name ) const + { + return GetPropertyValueAsSize( GetPropertyByNameI(name) ); + } + inline wxArrayInt GetPropertyValueAsArrayInt( wxPGPropNameStr name ) const + { + return GetPropertyValueAsArrayInt( GetPropertyByNameI(name) ); + } +#endif +#if wxUSE_DATETIME + inline wxDateTime GetPropertyValueAsDateTime( wxPGPropNameStr name ) const + { + return GetPropertyValueAsDateTime( GetPropertyByNameI(name) ); + } +#endif +#ifdef __WXPYTHON__ + inline PyObject* GetPropertyValueAsPyObject( wxPGPropNameStr name ) const + { + return GetPropertyValueAsPyObject( GetPropertyByNameI(name) ); + } +#endif + + /** Returns a wxPGValueType class instance that describes + the property's data type. + */ + wxPG_VALUETYPE_MSGVAL GetPropertyValueType( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxPG_VALUETYPE(none)) + return p->GetValueType(); + } + wxPG_VALUETYPE_MSGVAL GetPropertyValueType( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxPG_VALUETYPE(none)) + return p->GetValueType(); + } + + /** Returns property value type name. + */ + inline wxString GetPVTN( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(m_emptyString) + const wxPGValueType* vt = p->GetValueTypePtr(); + return vt->GetCustomTypeName(); + } + + inline wxString GetPVTN( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(m_emptyString) + const wxPGValueType* vt = p->GetValueTypePtr(); + return vt->GetCustomTypeName(); + } + + /** Returns property value type identifier. + */ + inline size_t GetPVTI( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(0) + const wxPGValueType* vt = p->GetValueTypePtr(); + return size_t(vt); + } + + inline size_t GetPVTI( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(0) + const wxPGValueType* vt = p->GetValueTypePtr(); + return size_t(vt); + } + +#ifndef SWIG + inline wxPropertyGridState* GetState() const { return m_pState; } +#endif + + /** Returns value type class instance for given type name. + */ + static wxPGValueType* GetValueType( const wxString &type ); + +#if wxPG_VALUETYPE_IS_STRING + /** Return value type class instance for given value type class name. + */ + static wxPGValueType* GetValueTypeByName( const wxString &className ); +#endif + + /** Hides or reveals a property. + \param hide + If true, hides property, otherwise reveals it. + \remarks + Hiding properties is not compatible with priority system. Using both + at the same time will yield unpredictable results. + */ + bool HideProperty( wxPGId id, bool hide = true ); + + inline bool HideProperty( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return HideProperty(wxPGIdGen(p)); + } + +#if wxPG_INCLUDE_ADVPROPS + /** Initializes additional property editors (SpinCtrl etc.). Causes references + to most object files in the library, so calling this may cause significant increase + in executable size when linking with static library. + */ + static void RegisterAdditionalEditors(); +#else + static inline void RegisterAdditionalEditors() { } +#endif + +#if wxPG_INCLUDE_ADVPROPS + /** Initializes *all* property types. Causes references to most object + files in the library, so calling this may cause significant increase + in executable size when linking with static library. + */ + static void InitAllTypeHandlers(); +#else + static inline void InitAllTypeHandlers() { } +#endif + + /** Returns true if property is enabled. */ + inline bool IsPropertyEnabled( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return (!(p->GetFlags() & wxPG_PROP_DISABLED))?true:false; + } + + /** Returns true if property is enabled. */ + inline bool IsPropertyEnabled( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return (!(p->GetFlags() & wxPG_PROP_DISABLED))?true:false; + } + + /** Returns true if property is shown (ie. hideproperty with true not called for it). */ + inline bool IsPropertyShown( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return (!(p->GetFlags() & wxPG_PROP_HIDEABLE))?true:false; + } + + /** Returns true if property is shown (ie. hideproperty with true not called for it). */ + inline bool IsPropertyShown( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return (!(p->GetFlags() & wxPG_PROP_HIDEABLE))?true:false; + } + + /** Returns true if property's value type has name typestr. */ + inline bool IsPropertyValueType( wxPGId id, const wxChar* typestr ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return (wxStrcmp(p->GetValueTypePtr()->GetTypeName(),typestr) == 0); + } + +#if !wxPG_VALUETYPE_IS_STRING + /** Returns true if property's value type is valuetype */ + inline bool IsPropertyValueType( wxPGId id, const wxPGValueType* valuetype ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return ( p->GetValueTypePtr() == valuetype ); + } +#endif + + /** Returns true if property's value type has same name as a class. */ + inline bool IsPropertyValueType( wxPGId id, const wxClassInfo* classinfo ) + { + return IsPropertyValueType(id,classinfo->GetClassName()); + } + + /** Returns true if property's value type has name typestr. */ + inline bool IsPropertyValueType( wxPGPropNameStr name, const wxChar* typestr ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return (wxStrcmp(p->GetValueTypePtr()->GetTypeName(),typestr) == 0); + } + +#if !wxPG_VALUETYPE_IS_STRING + /** Returns true if property's value type is valuetype */ + inline bool IsPropertyValueType( wxPGPropNameStr name, const wxPGValueType* valuetype ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return ( p->GetValueType() == valuetype ); + } +#endif + + /** Returns true if property's value type has same name as a class. */ + inline bool IsPropertyValueType( wxPGPropNameStr name, const wxClassInfo* classinfo ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return IsPropertyValueType(wxPGIdGen(p),classinfo->GetClassName()); + } + + /** Returns true if given property is expanded. Naturally, always returns false + for properties that cannot be expanded. + */ + static bool IsPropertyExpanded( wxPGId id ); + inline bool IsPropertyExpanded( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return IsPropertyExpanded(wxPGIdGen(p)); + } + + /** Returns true if property is of certain type. + \param info + Preferably use WX_PG_CLASSINFO(PROPERTYNAME). Alternative is + PROPERTYNAMEClassInfo. + */ + static inline bool IsPropertyKindOf( wxPGId id, wxPGPropertyClassInfo& info ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return p->IsKindOf(info); + } + inline bool IsPropertyKindOf( wxPGPropNameStr name, wxPGPropertyClassInfo& info ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return p->IsKindOf(info); + } + + /** Returns true if property has been modified after value set or modify flag + clear by software. + + NOTE: Try to use IsPropertyModified instead. + */ + inline bool IsModified( wxPGId id ) const + { + return IsPropertyModified(id); + } + + inline bool IsModified( wxPGPropNameStr name ) + { + return IsPropertyModified(name); + } + + /** Returns true if property is a category. */ + inline bool IsPropertyCategory( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return (p->GetParentingType()>0)?true:false; + } + + inline bool IsPropertyCategory( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return (p->GetParentingType()>0)?true:false; + } + + /** Returns true if property has been modified after value set or modify flag + clear by software. + */ + inline bool IsPropertyModified( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return ( (p->GetFlags() & wxPG_PROP_MODIFIED) ? true : false ); + } + inline bool IsPropertyModified( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return ( (p->GetFlags() & wxPG_PROP_MODIFIED) ? true : false ); + } + + /** Returns true if property value is set to unspecified. + */ +#ifdef wxPG_COMPATIBILITY_1_0_0 + inline bool IsPropertyValueUnspecified( wxPGId id ) const +#else + inline bool IsPropertyUnspecified( wxPGId id ) const +#endif + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return ( (p->GetFlags() & wxPG_PROP_UNSPECIFIED) ? true : false ); + } +#ifdef wxPG_COMPATIBILITY_1_0_0 + inline bool IsPropertyValueUnspecified( wxPGPropNameStr name ) + { + return IsPropertyValueUnspecified(GetPropertyByNameI(name)); + } +#else + inline bool IsPropertyUnspecified( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return IsPropertyUnspecified(wxPGIdGen(p)); + } +#endif + + /** Basic property classes are registered by the default, but this + registers advanced ones as well. + */ + static void RegisterAdvancedPropertyClasses(); + + /** Registers property class info with specific name. Preferably use + wxPGRegisterPropertyClass(PROPERTYNAME) macro. + */ + static bool RegisterPropertyClass( const wxChar* name, wxPGPropertyClassInfo* classinfo ); + + /** Replaces property with id with newly created property. For example, + this code replaces existing property named "Flags" with one that + will have different set of items: + \code + pg->ReplaceProperty(wxT("Flags"), + wxFlagsProperty(wxT("Flags"),wxPG_LABEL,newItems)) + \endcode + For more info, see wxPropertyGrid::Insert. + */ + wxPGId ReplaceProperty( wxPGId id, wxPGProperty* property ); + + inline wxPGId ReplaceProperty( wxPGPropNameStr name, wxPGProperty* property ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return ReplaceProperty(wxPGIdGen(p),property); + } + + /** Lets user to set the strings listed in the choice dropdown of a wxBoolProperty. + Defaults are "True" and "False", so changing them to, say, "Yes" and "No" may + be useful in some less technical applications. + */ + static void SetBoolChoices( const wxChar* true_choice, const wxChar* false_choice ); + + /** Set choices of a property to specified set of labels and values. + */ + static inline void SetPropertyChoices(wxPGId id, wxPGChoices& choices) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetChoices(choices); + } + + + /** Set choices of a property to specified set of labels and values. + */ + inline void SetPropertyChoices(wxPGPropNameStr name, wxPGChoices& choices) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetChoices(choices); + } + + /** If property's set of choices is shared, then calling this method converts + it to private. + */ + inline void SetPropertyChoicesExclusive( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetChoicesExclusive(); + } + inline void SetPropertyChoicesExclusive( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetChoicesExclusive(); + } + + /** Sets an attribute of a property. Ids and relevants values are totally + specific to property classes and may affect either the given instance + or all instances of that class. See \ref attrids for list of built-in + attributes. + \param argFlags + Optional. Use wxPG_RECURSE to set the attribute to child properties + as well. + \remarks + wxVariant doesn't have int constructor (as of 2.5.4), so you will + need to cast int values (including most numeral constants) to long. + */ + inline void SetPropertyAttribute( wxPGId id, int attrid, wxVariant value, long argFlags = 0 ) + { + DoSetPropertyAttribute(id,attrid,value,argFlags); + } + inline void SetPropertyAttribute( wxPGPropNameStr name, int attrid, wxVariant value, long argFlags = 0 ) + { + wxPG_PROP_NAME_CALL_PROLOG() + DoSetPropertyAttribute(wxPGIdGen(p),attrid,value,argFlags); + } + +#ifndef SWIG + /** Sets editor control of a property. As editor argument, use + wxPG_EDITOR(EditorName), where basic built-in editor names are TextCtrl, Choice, + ComboBox, CheckBox, TextCtrlAndButton, and ChoiceAndButton. Additional editors + include SpinCtrl and DatePickerCtrl, which also require wxPropertyGrid::RegisterAdditionalEditors() + call prior using. + */ + inline void SetPropertyEditor( wxPGId id, const wxPGEditor* editor ) + { + wxPG_PROP_ID_CALL_PROLOG() + wxCHECK_RET( editor, wxT("unknown/NULL editor") ); + p->SetEditor(editor); + RefreshProperty(p); + } + inline void SetPropertyEditor( wxPGPropNameStr name, const wxPGEditor* editor ) + { + wxPG_PROP_NAME_CALL_PROLOG() + wxCHECK_RET( editor, wxT("unknown/NULL editor") ); + p->SetEditor(editor); + RefreshProperty(p); + } +#endif // #ifndef SWIG + + /** Sets editor control of a property. As editor argument, use + editor name string, such as wxT("TextCtrl") or wxT("Choice"). + */ + inline void SetPropertyEditor( wxPGId id, const wxString& editorName ) + { + SetPropertyEditor(id,GetEditorByName(editorName)); + } + inline void SetPropertyEditor( wxPGPropNameStr name, const wxString& editorName ) + { + SetPropertyEditor(name,GetEditorByName(editorName)); + } + +#if wxPG_USE_CLIENT_DATA + /** Sets client data (void*) of a property. + \remarks + This untyped client data has to be deleted manually. + */ + inline void SetPropertyClientData( wxPGId id, wxPGProperty::ClientDataType clientData ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetClientData(clientData); + } + /** Sets client data (void*) of a property. + \remarks + This untyped client data has to be deleted manually. + */ + inline void SetPropertyClientData( wxPGPropNameStr name, wxPGProperty::ClientDataType clientData ) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetClientData(clientData); + } +#endif + + /** Associates the help string with property. + \remarks + By default, text is shown either in the manager's "description" + text box or in the status bar. If extra window style wxPG_EX_HELP_AS_TOOLTIPS + is used, then the text will appear as a tooltip. + */ + inline void SetPropertyHelpString( wxPGId id, const wxString& helpString ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetHelpString(helpString); + } + + inline void SetPropertyHelpString( wxPGPropNameStr name, const wxString& helpString ) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetHelpString(helpString); + } + + /** Set wxBitmap in front of the value. + \remarks + - Bitmap will be ignored if property class has implemented OnCustomPaint. + - Bitmap will be scaled to a size returned by wxPropertyGrid::GetImageSize(); + */ + inline void SetPropertyImage( wxPGId id, wxBitmap& bmp ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetValueImage(bmp); + RefreshProperty(p); + } + + inline void SetPropertyImage( wxPGPropNameStr name, wxBitmap& bmp ) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetValueImage(bmp); + RefreshProperty(p); + } + + /** Sets max length of property's text. + */ + bool SetPropertyMaxLength( wxPGId id, int maxLen ); + + /** Sets max length of property's text. + */ + inline bool SetPropertyMaxLength( wxPGPropNameStr name, int maxLen ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return SetPropertyMaxLength(wxPGIdGen(p),maxLen); + } + + /** Property is to be hidden/shown when hider button is toggled or + when wxPropertyGrid::Compact is called. + */ + bool SetPropertyPriority( wxPGId id, int priority ); + + /** Property is to be hidden/shown when hider button is toggled or + when wxPropertyGrid::Compact is called. + */ + inline bool SetPropertyPriority( wxPGPropNameStr name, int priority ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return SetPropertyPriority(wxPGIdGen(p),priority); + } + +#if wxUSE_VALIDATORS + /** Sets validator of a property. For example + \code + // Allow property's value range from -100 to 100 + wxIntPropertyValidator validator(-100,100); + wxPGId id = pg->Append( wxIntProperty(wxT("Value 1",wxPG_LABEL,0)) ); + pg->SetPropertyValidator( id, validator ); + \endcode + */ + inline void SetPropertyValidator( wxPGId id, const wxValidator& validator ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->SetValidator(validator); + } + inline void SetPropertyValidator( wxPGPropNameStr name, const wxValidator& validator ) + { + wxPG_PROP_NAME_CALL_PROLOG() + p->SetValidator(validator); + } +#endif + + /** Toggles priority of a property between wxPG_HIGH and wxPG_LOW. + */ + inline void TogglePropertyPriority( wxPGId id ) + { + int priority = wxPG_LOW; + if ( GetPropertyPriority(id) == wxPG_LOW ) + priority = wxPG_HIGH; + SetPropertyPriority(id,priority); + } + + /** Toggles priority of a property between wxPG_HIGH and wxPG_LOW. + */ + inline void TogglePropertyPriority( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + TogglePropertyPriority(wxPGIdGen(p)); + } + +#ifdef SWIG + %pythoncode { + def MapType(class_,factory): + "Registers Python type/class to property mapping.\n\nfactory: Property builder function/class." + global _type2property + try: + mappings = _type2property + except NameError: + raise AssertionError("call only after a propertygrid or manager instance constructed") + + mappings[class_] = factory + + + def DoDefaultTypeMappings(self): + "Map built-in properties." + global _type2property + try: + mappings = _type2property + + return + except NameError: + mappings = {} + _type2property = mappings + + mappings[str] = StringProperty + mappings[unicode] = StringProperty + mappings[int] = IntProperty + mappings[float] = FloatProperty + mappings[bool] = BoolProperty + mappings[list] = ArrayStringProperty + mappings[tuple] = ArrayStringProperty + mappings[wx.Font] = FontProperty + mappings[wx.Colour] = ColourProperty + mappings[wx.Size] = SizeProperty + mappings[wx.Point] = PointProperty + mappings[wx.FontData] = FontDataProperty + + + def GetPropertyValue(self,p): + "Returns Python object value for property.\n\nCaches getters on value type id basis for performance purposes." + global _vt2getter + vtid = self.GetPVTI(p) + if not vtid: + raise TypeError("Property '%s' doesn't have valid value type"%(p.GetName())) + try: + getter = _vt2getter[vtid] + except KeyError: + + cls = PropertyContainerMethods + vtn = self.GetPVTN(p) + + if vtn == 'long': + getter = cls.GetPropertyValueAsLong + elif vtn == 'string': + getter = cls.GetPropertyValueAsString + elif vtn == 'double': + getter = cls.GetPropertyValueAsDouble + elif vtn == 'bool': + getter = cls.GetPropertyValueAsBool + elif vtn == 'arrstring': + getter = cls.GetPropertyValueAsArrayString + elif vtn == 'wxArrayInt': + getter = cls.GetPropertyValueAsArrayInt + elif vtn == 'PyObject': + getter = cls.GetPropertyValueAsPyObject + elif vtn == 'datetime': + getter = cls.GetPropertyValueAsDateTime + elif vtn == 'wxPoint': + getter = cls.GetPropertyValueAsPoint + elif vtn == 'wxSize': + getter = cls.GetPropertyValueAsSize + elif vtn.startswith('wx'): + getter = cls.GetPropertyValueAsWxObjectPtr + elif not vtn: + if p: + raise ValueError("no property with name '%s'"%p) + else: + raise ValueError("NULL property") + else: + raise AssertionError("Unregistered property grid value type '%s'"%vtn) + _vt2getter[vtid] = getter + return getter(self,p) + + + def SetPropertyValueArrstr(self,p,v): + "NB: We must implement this in Python because SWIG has problems combining" + " conversion of list to wxArrayXXX and overloaded arguments." + if not isinstance(p,basestring): + self._SetPropertyValueArrstr(p,v) + else: + self._SetPropertyValueArrstr(self.GetPropertyByNameI(p),v) + + + def SetPropertyValueArrint(self,p,v): + "NB: We must implement this in Python because SWIG has problems combining" + " conversion of list to wxArrayXXX and overloaded arguments." + if not isinstance(p,basestring): + self._SetPropertyValueArrint(p,v) + else: + self._SetPropertyValueArrint(self.GetPropertyByNameI(p),v) + + + def SetPropertyValue(self,p,v): + "Set property value from Python object.\n\nCaches setters on value type id basis for performance purposes." + cls = self.__class__ + if not isinstance(v,basestring): + _vt2setter = cls._vt2setter + vtid = self.GetPVTI(p) + try: + setter = _vt2setter[vtid] + except KeyError: + + vtn = self.GetPVTN(p) + + if vtn == 'long': + setter = cls.SetPropertyValueLong + elif vtn == 'string': + setter = cls.SetPropertyValueString + elif vtn == 'double': + setter = cls.SetPropertyValueDouble + elif vtn == 'bool': + setter = cls.SetPropertyValueBool + elif vtn == 'arrstring': + setter = cls.SetPropertyValueArrstr + elif vtn == 'wxArrayInt': + setter = cls.SetPropertyValueArrint + elif vtn == 'PyObject': + setter = cls.SetPropertyValuePyObject + elif vtn == 'datetime': + setter = cls.SetPropertyValueDatetime + elif vtn == 'wxPoint': + setter = cls.SetPropertyValuePoint + elif vtn == 'wxSize': + setter = cls.SetPropertyValueSize + elif vtn == 'wxLongLong': + setter = cls.SetPropertyValueLongLong + elif vtn == 'wxULongLong': + setter = cls.SetPropertyValueULongLong + elif vtn.startswith('wx'): + setter = cls.SetPropertyValueWxObjectPtr + elif not vtn: + if p: + raise ValueError("no property with name '%s'"%p) + else: + raise ValueError("NULL property") + else: + raise AssertionError("Unregistered property grid value type '%s'"%vtn) + _vt2setter[vtid] = setter + else: + setter = cls.SetPropertyValueString + + return setter(self,p,v) + + + def DoDefaultValueTypeMappings(self): + "Map pg value type ids to getter methods." + global _vt2getter + try: + vt2getter = _vt2getter + + return + except NameError: + vt2getter = {} + _vt2getter = vt2getter + + + def _GetValues(self,parent,fc,dict_,getter): + p = fc + + while p: + pfc = self.GetFirstChild(p) + if pfc: + self._GetValues(p,pfc,dict_,getter) + else: + dict_[p.GetName()] = getter(p) + + p = self.GetNextSibling(p) + + + def GetPropertyValues(self,dict_=None,as_strings=False): + "Returns values in the grid." + "" + "dict_: if not given, then a new one is created. dict_ can be" + " object as well, in which case it's __dict__ is used." + "as_strings: if True, then string representations of values" + " are fetched instead of native types. Useful for config and such." + "" + "Return value: dictionary with values. It is always a dictionary," + "so if dict_ was object with __dict__ attribute, then that attribute" + "is returned." + + if dict_ is None: + dict_ = {} + elif hasattr(dict_,'__dict__'): + dict_ = dict_.__dict__ + + if not as_strings: + getter = self.GetPropertyValue + else: + getter = self.GetPropertyValueAsString + + root = self.GetRoot() + self._GetValues(root,self.GetFirstChild(root),dict_,getter) + + return dict_ + + GetValues = GetPropertyValues + + + def SetPropertyValues(self,dict_): + "Sets property values from dict_, which can be either\ndictionary or an object with __dict__ attribute." + "" + "autofill: If true, keys with not relevant properties" + " are auto-created. For more info, see AutoFill." + "" + "Notes:" + " * Keys starting with underscore are ignored." + + autofill = False + + if dict_ is None: + dict_ = {} + elif hasattr(dict_,'__dict__'): + dict_ = dict_.__dict__ + + def set_sub_obj(k0,dict_): + for k,v in dict_.iteritems(): + if k[0] != '_': + try: + self.SetPropertyValue(k,v) + except: + try: + if autofill: + self._AutoFillOne(k0,k,v) + continue + except: + if isinstance(v,dict): + set_sub_obj(k,v) + elif hasattr(v,'__dict__'): + set_sub_obj(k,v.__dict__) + + + cur_page = False + is_manager = isinstance(self,PropertyGridManager) + + try: + set_sub_obj(self.GetRoot(),dict_) + except: + import traceback + traceback.print_exc() + + self.Refresh() + + + SetValues = SetPropertyValues + + + def _AutoFillMany(self,cat,dict_): + for k,v in dict_.iteritems(): + self._AutoFillOne(cat,k,v) + + + def _AutoFillOne(self,cat,k,v): + global _type2property + + factory = _type2property.get(v.__class__,None) + + if factory: + self.AppendIn( cat, factory(k,k,v) ) + elif hasattr(v,'__dict__'): + cat2 = self.AppendIn( cat, PropertyCategory(k) ) + self._AutoFillMany(cat2,v.__dict__) + elif isinstance(v,dict): + cat2 = self.AppendIn( cat, PropertyCategory(k) ) + self._AutoFillMany(cat2,v) + elif not k.startswith('_'): + raise AssertionError("member '%s' is of unregisted type/class '%s'"%(k,v.__class__)) + + + def AutoFill(self,obj,parent=None): + "Clears properties and re-fills to match members and\nvalues of given object or dictionary obj." + + self.edited_objects[parent] = obj + + cur_page = False + is_manager = isinstance(self,PropertyGridManager) + + if not parent: + if is_manager: + page = self.GetTargetPage() + self.ClearPage(page) + parent = self.GetPageRoot(page) + else: + self.Clear() + parent = self.GetRoot() + else: + p = self.GetFirstChild(parent) + while p: + self.Delete(p) + p = self.GetNextSibling(p) + + if not is_manager or page == self.GetSelectedPage(): + self.Freeze() + cur_page = True + + try: + self._AutoFillMany(parent,obj.__dict__) + except: + import traceback + traceback.print_exc() + + if cur_page: + self.Thaw() + + + def RegisterEditor(self, editor, editorName=None): + "Transform class into instance, if necessary." + if not isinstance(editor, PGEditor): + editor = editor() + if not editorName: + editorName = editor.__class__.__name__ + try: + self._editor_instances.append(editor) + except: + self._editor_instances = [editor] + RegisterEditor(editor, editorName) + + } +#endif + + /** Sets property as read-only. It's value cannot be changed by the user, but the + editor may still be created for copying purposes. + */ + void SetPropertyReadOnly( wxPGId id, bool readOnly = true ) + { + wxPG_PROP_ID_CALL_PROLOG() + if ( readOnly ) + p->SetFlag(wxPG_PROP_READONLY); + else + p->ClearFlag(wxPG_PROP_READONLY); + } + + /** Sets property as read-only. It's value cannot be changed by the user, but the + editor may still be created for copying purposes. + */ + void SetPropertyReadOnly( wxPGPropNameStr name, bool readOnly = true ) + { + wxPG_PROP_NAME_CALL_PROLOG() + if ( readOnly ) + p->SetFlag(wxPG_PROP_READONLY); + else + p->ClearFlag(wxPG_PROP_READONLY); + } + + // GetPropertyByNameI With nice assertion error message. + wxPGId GetPropertyByNameA( wxPGPropNameStr name ) const; + +#ifndef SWIG + + static wxPGEditor* GetEditorByName( const wxString& editorName ); + +protected: + + // Deriving classes must set this (it must be only or current page). + wxPropertyGridState* m_pState; + + // Default call's m_pState's BaseGetPropertyByName + virtual wxPGId DoGetPropertyByName( wxPGPropNameStr name ) const; + + virtual void RefreshProperty( wxPGProperty* p ) = 0; + + // Intermediate version needed due to wxVariant copying inefficiency + static void DoSetPropertyAttribute( wxPGId id, int attrid, wxVariant& value, long argFlags ); + + // Empty string object to return from member functions returning const wxString&. + wxString m_emptyString; + +#endif // #ifndef SWIG +}; + +// ----------------------------------------------------------------------- + + +// wxPropertyGrid::DoSelectProperty flags +#define wxPG_SEL_FOCUS 0x01 // Focuses to created editor +#define wxPG_SEL_FORCE 0x02 // Forces deletion and recreation of editor +#define wxPG_SEL_NONVISIBLE 0x04 // For example, doesn't cause EnsureVisible +#define wxPG_SEL_NOVALIDATE 0x08 // Do not validate editor's value before selecting +#define wxPG_SEL_DELETING 0x10 // Property being deselected is about to be deleted +#define wxPG_SEL_SETUNSPEC 0x20 // Property's values was set to unspecified by the user + + +// ----------------------------------------------------------------------- + +#ifndef SWIG + +// Internal flags +#define wxPG_FL_INITIALIZED 0x0001 +#define wxPG_FL_ACTIVATION_BY_CLICK 0x0002 // Set when creating editor controls if it was clicked on. +#define wxPG_FL_DONT_CENTER_SPLITTER 0x0004 +#define wxPG_FL_FOCUSED 0x0008 +#define wxPG_FL_MOUSE_CAPTURED 0x0010 +#define wxPG_FL_MOUSE_INSIDE 0x0020 +#define wxPG_FL_VALUE_MODIFIED 0x0040 +#define wxPG_FL_PRIMARY_FILLS_ENTIRE 0x0080 // don't clear background of m_wndPrimary +#define wxPG_FL_CUR_USES_CUSTOM_IMAGE 0x0100 // currently active editor uses custom image +#define wxPG_FL_HIDE_STATE 0x0200 // set when hideable properties should be hidden +#define wxPG_FL_SCROLLED 0x0400 +#define wxPG_FL_ADDING_HIDEABLES 0x0800 // set when all added/inserted properties get hideable flag +#define wxPG_FL_NOSTATUSBARHELP 0x1000 // Disables showing help strings on statusbar. +#define wxPG_FL_CREATEDSTATE 0x2000 // Marks that we created the state, so we have to destroy it too. +#define wxPG_FL_SCROLLBAR_DETECTED 0x4000 // Set if scrollbar's existence was detected in last onresize. +#define wxPG_FL_DESC_REFRESH_REQUIRED 0x8000 // Set if wxPGMan requires redrawing of description text box. +#define wxPG_FL_SELECTED_IS_PAINT_FLEXIBLE 0x00010000 // Set if selected has flexible imagesize +#define wxPG_FL_IN_MANAGER 0x00020000 // Set if contained in wxPropertyGridManager +#define wxPG_FL_GOOD_SIZE_SET 0x00040000 // Set after wxPropertyGrid is shown in its initial good size +#define wxPG_FL_IGNORE_NEXT_NAVKEY 0x00080000 // Next navigation key event will get ignored +#define wxPG_FL_IN_SELECT_PROPERTY 0x00100000 // Set when in SelectProperty. +#define wxPG_FL_STRING_IN_STATUSBAR 0x00200000 // Set when help string is shown in status bar +#define wxPG_FL_SPLITTER_PRE_SET 0x00400000 // Splitter position has been custom-set by the user +#define wxPG_FL_VALIDATION_FAILED 0x00800000 // Validation failed. Clear on modify event. +#define wxPG_FL_SELECTED_IS_FULL_PAINT 0x01000000 // Set if selected is fully painted (ie. both image and text) +#define wxPG_MAN_FL_PAGE_INSERTED 0x02000000 // Set after page has been inserted to manager +#define wxPG_FL_ABNORMAL_EDITOR 0x04000000 // Active editor control is abnormally large + +#endif // #ifndef SWIG + + +// ----------------------------------------------------------------------- + +#define wxPG_USE_STATE m_pState + +/** \class wxPropertyGrid + \ingroup classes + \brief + wxPropertyGrid is a specialized two-column grid for editing properties + such as strings, numbers, flagsets, fonts, and colours. wxPropertySheet + used to do the very same thing, but it hasn't been updated for a while + and it is currently deprecated. + + wxPropertyGrid is modeled after .NET propertygrid (hence the name), + and thus features are similar. However, inorder to keep the widget lightweight, + it does not (and will not) have toolbar for mode and page selection, nor the help + text box. wxAdvancedPropertyGrid (or something similarly named) is planned to have + these features in some distant future. + +

Derived from

+ + wxPropertyContainerMethods\n + wxScrolledWindow\n + wxPanel\n + wxWindow\n + wxEvtHandler\n + wxObject\n + +

Include files

+ + + +

Window styles

+ + @link wndflags Additional Window Styles@endlink + +

Event handling

+ + To process input from a propertygrid control, use these event handler macros to + direct input to member functions that take a wxPropertyGridEvent argument. + + + + + + + + + + + +
EVT_PG_SELECTED (id, func)Property is selected.
EVT_PG_CHANGED (id, func)Property value is modified.
EVT_PG_HIGHLIGHTED (id, func)Mouse moves over property. Event's property is NULL if hovered on area that is not a property.
EVT_PG_RIGHT_CLICK (id, func)Mouse right-clicked on a property.
EVT_PG_DOUBLE_CLICK (id, func)Mouse double-clicked on a property.
EVT_PG_ITEM_COLLAPSED (id, func)User collapses a property or category.
EVT_PG_ITEM_EXPANDED (id, func)User expands a property or category.
EVT_BUTTON (id, func)Button in a property editor was clicked. Only occurs if the property doesn't handle button clicks itself.
EVT_TEXT (id, func)wxTextCtrl based editor was updated (but property value was not yet modified)
+ + \sa @link wxPropertyGridEvent wxPropertyGridEvent@endlink + + \remarks + + - Following functions do not automatically update the screen: Append. You + probably need to explicitly call Refresh() if you called one of these + functions outside parent window constructor. + + - Use Freeze() and Thaw() respectively to disable and enable drawing. This + will also delay sorting etc. miscellaneous calculations to the last possible + moment. + + - Most methods have two versions - one which accepts property id (faster) and + another that accepts property name (which is a bit slower since it does a hashmap + lookup). + + For code examples, see the main page. + +*/ +// BM_GRID +class WXDLLIMPEXP_PG wxPropertyGrid : public wxScrolledWindow, public wxPropertyContainerMethods +{ +#ifndef SWIG + friend class wxPropertyGridState; + friend class wxPropertyContainerMethods; + friend class wxPropertyGridManager; + + DECLARE_CLASS(wxPropertyGrid) +#endif + +public: + /** Two step constructor. Call Create when this constructor is called to build up the + wxPropertyGrid + */ + +#ifdef SWIG + %pythonAppend wxPropertyGrid { + self._setOORInfo(self) + self.DoDefaultTypeMappings() + self.edited_objects = {} + self.DoDefaultValueTypeMappings() + if not hasattr(self.__class__,'_vt2setter'): + self.__class__._vt2setter = {} + } + %pythonAppend wxPropertyGrid() "" + + wxPropertyGrid( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPG_DEFAULT_STYLE, + const wxChar* name = wxPyPropertyGridNameStr ); + %RenameCtor(PrePropertyGrid, wxPropertyGrid()); + +#else + + wxPropertyGrid(); + + /** The default constructor. The styles to be used are styles valid for + the wxWindow and wxScrolledWindow. + \sa @link wndflags Additional Window Styles@endlink + */ + wxPropertyGrid( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPG_DEFAULT_STYLE, + const wxChar* name = wxPropertyGridNameStr ); + + /** Destructor */ + virtual ~wxPropertyGrid(); +#endif + + /** Appends property to the list. wxPropertyGrid assumes ownership of the object. + Becomes child of most recently added category. + \remarks + - wxPropertyGrid takes the ownership of the property pointer. + - If appending a category with name identical to a category already in the + wxPropertyGrid, then newly created category is deleted, and most recently + added category (under which properties are appended) is set to the one with + same name. This allows easier adding of items to same categories in multiple + passes. + - Does not automatically redraw the control, so you may need to call Refresh + when calling this function after control has been shown for the first time. + */ + wxPGId Append( wxPGProperty* property ); + + inline wxPGId AppendCategory( const wxString& label, const wxString& name = wxPG_LABEL ) + { + return Append( new wxPropertyCategoryClass(label,name) ); + } + +#ifndef SWIG +#if wxPG_INCLUDE_BASICPROPS + inline wxPGId Append( const wxString& label, const wxString& name = wxPG_LABEL, const wxString& value = wxEmptyString ) + { + return Append( wxStringProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name = wxPG_LABEL, int value = 0 ) + { + return Append( wxIntProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name = wxPG_LABEL, double value = 0.0 ) + { + return Append( wxFloatProperty(label,name,value) ); + } + + inline wxPGId Append( const wxString& label, const wxString& name = wxPG_LABEL, bool value = false ) + { + return Append( wxBoolProperty(label,name,value) ); + } +#endif +#endif + + inline wxPGId AppendIn( wxPGId id, wxPGProperty* property ) + { + return Insert(id,-1,property); + } + + inline wxPGId AppendIn( wxPGPropNameStr name, wxPGProperty* property ) + { + return Insert(GetPropertyByNameI(name),-1,property); + } + + inline wxPGId AppendIn( wxPGId id, const wxString& label, const wxString& propname, wxVariant& value ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + return m_pState->AppendIn( (wxPGPropertyWithChildren*)p, label, propname, value ); + } + + inline wxPGId AppendIn( wxPGPropNameStr name, const wxString& label, const wxString& propname, wxVariant& value ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return m_pState->AppendIn( (wxPGPropertyWithChildren*)p, label, propname, value ); + } + + /** This static function enables or disables automatic use of wxGetTranslation for + following strings: wxEnumProperty list labels, wxFlagsProperty sub-property + labels. + Default is false. + */ + static void AutoGetTranslation( bool enable ); + + /** Returns true if all property grid data changes have been committed. Usually + only returns false if value in active editor has been invalidated by a + wxValidator. + */ + inline bool CanClose() + { + return DoEditorValidate(); + } + + /** Returns true if all property grid data changes have been committed. Usually + only returns false if value in active editor has been invalidated by a + wxValidator. + */ + inline bool EditorValidate() + { + return DoEditorValidate(); + } + + /** Centers the splitter. If argument is true, automatic splitter centering is + enabled (only applicapple if style wxPG_SPLITTER_AUTO_CENTER was defined). + */ + void CenterSplitter( bool enable_auto_centering = false ); + + /** Two step creation. Whenever the control is created without any parameters, use Create to actually + create it. Don't access the control's public methods before this is called + \sa @link wndflags Additional Window Styles@endlink + */ + bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxPG_DEFAULT_STYLE, + const wxChar* name = wxPropertyGridNameStr ); + + /** Deletes all properties. Does not free memory allocated for arrays etc. + This should *not* be called in wxPropertyGridManager. + */ + void Clear(); + + /** Resets modified status of a property and all sub-properties. + */ + inline void ClearModifiedStatus( wxPGId id ) + { + m_pState->ClearModifiedStatus(wxPGIdToPtr(id)); + } + + /** Resets modified status of all properties. + */ + inline void ClearModifiedStatus() + { + m_pState->ClearModifiedStatus(m_pState->m_properties); + m_pState->m_anyModified = false; + } + + /** Resets value of a property to its default. */ + bool ClearPropertyValue( wxPGId id ); + + /** Resets value of a property to its default. */ + inline bool ClearPropertyValue( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return ClearPropertyValue( wxPGIdGen(p) ); + } + + /** Deselect current selection, if any. Returns true if success + (ie. validator did not intercept). */ + bool ClearSelection(); + + /** Synonymous to Clear. + */ + inline void ClearTargetPage() + { + Clear(); + } + + /** Collapses given category or property with children. + Returns true if actually collapses. + */ + inline bool Collapse( wxPGId id ) + { + return _Collapse(wxPGIdToPtr(id)); + } + + /** Collapses given category or property with children. + Returns true if actually collapses. + */ + inline bool Collapse( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return _Collapse(p); + } + + /** Collapses all items that can be collapsed. + \retval + Return false if failed (may fail if editor value cannot be validated). + */ + inline bool CollapseAll() { return m_pState->ExpandAll(0); } + + /** Shows(arg = false) or hides(arg = true) all hideable properties. */ + bool Compact( bool compact ); + + /** Disables property. */ + inline bool Disable( wxPGId id ) { return EnableProperty(id,false); } + + /** Disables property. */ + inline bool Disable( wxPGPropNameStr name ) { return EnableProperty(name,false); } + + /** Disables property. */ + inline bool DisableProperty( wxPGId id ) { return EnableProperty(id,false); } + + /** Disables property. */ + inline bool DisableProperty( wxPGPropNameStr name ) { return EnableProperty(name,false); } + + /** Enables or disables (shows/hides) categories according to parameter enable. */ + bool EnableCategories( bool enable ); + + /** Enables or disables property, depending on whether enable is true or false. */ + bool EnableProperty( wxPGId id, bool enable = true ); + + /** Enables or disables property, depending on whether enable is true or false. */ + inline bool EnableProperty( wxPGPropNameStr name, bool enable = true ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return EnableProperty( wxPGIdGen(p), enable ); + } + + /** Scrolls and/or expands items to ensure that the given item is visible. + Returns true if something was actually done. + */ + bool EnsureVisible( wxPGId id ); + + /** Scrolls and/or expands items to ensure that the given item is visible. + Returns true if something was actually done. + */ + inline bool EnsureVisible( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return EnsureVisible( wxPGIdGen(p) ); + } + + /** Expands given category or property with children. + Returns true if actually expands. + */ + inline bool Expand( wxPGId id ) + { + return _Expand(wxPGIdToPtr(id)); + } + + /** Expands given category or property with children. + Returns true if actually expands. + */ + inline bool Expand( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return _Expand(p); + } + + /** Expands all items that can be expanded. + */ + inline void ExpandAll() { m_pState->ExpandAll(1); } + +#ifndef SWIG + /** Returns a wxVariant list containing wxVariant versions of all + property values. Order is not guaranteed, but generally it should + match the visible order in the grid. + \param flags + Use wxPG_KEEP_STRUCTURE to retain category structure; each sub + category will be its own wxList of wxVariant. + \remarks + */ + wxVariant GetPropertyValues( const wxString& listname = wxEmptyString, + wxPGId baseparent = wxPGIdGen((wxPGProperty*)NULL), long flags = 0 ) const + { + return m_pState->GetPropertyValues(listname,baseparent,flags); + } +#endif + + inline wxFont& GetCaptionFont() { return m_captionFont; } + + /** Returns current category caption background colour. */ + inline wxColour GetCaptionBackgroundColour() const { return m_colCapBack; } + + /** Returns current category caption text colour. */ + inline wxColour GetCaptionForegroundColour() const { return m_colCapFore; } + + /** Returns current cell background colour. */ + inline wxColour GetCellBackgroundColour() const { return m_colPropBack; } + + /** Returns current cell text colour when disabled. */ + inline wxColour GetCellDisabledTextColour() const { return m_colDisPropFore; } + + /** Returns current cell text colour. */ + inline wxColour GetCellTextColour() const { return m_colPropFore; } + + /** Returns number of children of the root property. + */ + inline size_t GetChildrenCount() + { + return GetChildrenCount( wxPGIdGen(m_pState->m_properties) ); + } + + /** Returns number of children for the property. + + NB: Cannot be in container methods class due to name hiding. + */ + inline size_t GetChildrenCount( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(0) + return p->GetChildCount(); + } + + /** Returns number of children for the property. */ + inline size_t GetChildrenCount( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(0) + return p->GetChildCount(); + } + + /** Returns id of first item, whether it is a category or property. */ + inline wxPGId GetFirst() const + { + return m_pState->GetFirst(); + } + + /** Returns id of first visible item, whether it is a category or property. + Note that visible item means category, property, or sub-property which + user can see when control is scrolled properly. It does not only mean + items that are actually painted on the screen. + */ + inline wxPGId GetFirstVisible() const + { + wxPGProperty* p = NULL; + if ( m_pState->m_properties->GetCount() ) + { + p = m_pState->m_properties->Item(0); + if ( (m_iFlags & wxPG_FL_HIDE_STATE) && p->m_flags & wxPG_PROP_HIDEABLE ) + p = GetNeighbourItem ( p, true, 1 ); + } + return wxPGIdGen(p); + } + + /** Returns height of highest characters of used font. */ + int GetFontHeight() const { return m_fontHeight; } + + /** Returns pointer to itself. Dummy function that enables same kind + of code to use wxPropertyGrid and wxPropertyGridManager. + */ + wxPropertyGrid* GetGrid() { return this; } + + /** Returns id of first category (from target page). */ + inline wxPGId GetFirstCategory() const + { + return m_pState->GetFirstCategory(); + } + + /** Returns id of first property that is not a category. */ + inline wxPGId GetFirstProperty() + { + return m_pState->GetFirstProperty(); + } + + /** Returns size of the custom paint image in front of property. + If no argument is given, returns preferred size. + */ + wxSize GetImageSize( wxPGId id = wxPGIdGen((wxPGProperty*)NULL) ) const; + + /** Returns property (or category) at given y coordinate (relative to control's + top left). + */ + wxPGId GetItemAtY( int y ) { return wxPGIdGen(DoGetItemAtY(y)); } + + /** Returns id of last item. Ignores categories and sub-properties. + */ + inline wxPGId GetLastProperty() + { + if ( !m_pState->m_properties->GetCount() ) return wxPGIdGen((wxPGProperty*)NULL); + wxPGProperty* p = GetLastItem(false, false); + if ( p->GetParentingType() > 0 ) + return GetPrevProperty ( wxPGIdGen(p) ); + return wxPGIdGen(p); + } + + /** Returns id of last child of given property. + \remarks + Returns even sub-properties. + */ + inline wxPGId GetLastChild( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) p; + if ( !pwc->GetParentingType() || !pwc->GetCount() ) return wxNullProperty; + return wxPGIdGen(pwc->Last()); + } + inline wxPGId GetLastChild( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return GetLastChild( wxPGIdGen(p) ); + } + + /** Returns id of last visible item. Does not ignore categories sub-properties. + */ + inline wxPGId GetLastVisible() + { + return wxPGIdGen( GetLastItem (true, true) ); + } + + /** Returns colour of lines between cells. */ + inline wxColour GetLineColour() const { return m_colLine; } + + /** Returns background colour of margin. */ + inline wxColour GetMarginColour() const { return m_colMargin; } + + /** Returns id of next property. This does not iterate to sub-properties + or categories, unlike GetNextVisible. + */ + inline wxPGId GetNextProperty( wxPGId id ) + { + return m_pState->GetNextProperty(id); + } + + /** Returns id of next category after a given property (which does not have to be category). */ + inline wxPGId GetNextCategory( wxPGId id ) const + { + return m_pState->GetNextCategory(id); + } + + /** Returns id of next visible item. + Note that visible item means category, property, or sub-property which + user can see when control is scrolled properly. It does not only mean + items that are actually painted on the screen. + */ + inline wxPGId GetNextVisible( wxPGId property ) const + { + return wxPGIdGen ( GetNeighbourItem( wxPGIdToPtr(property), + true, 1 ) ); + } + + /** Returns id of previous property. Unlike GetPrevVisible, this skips categories + and sub-properties. + */ + inline wxPGId GetPrevProperty( wxPGId id ) + { + return m_pState->GetPrevProperty(id); + } + + /** Returns id of previous item under the same parent. */ + inline wxPGId GetPrevSibling( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + return wxPropertyGridState::GetPrevSibling(id); + } + inline wxPGId GetPrevSibling( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return wxPropertyGridState::GetPrevSibling(wxPGIdGen(p)); + } + + /** Returns id of previous visible property. + */ + inline wxPGId GetPrevVisible( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + return wxPGIdGen( GetNeighbourItem( wxPGIdToPtr(id), true, -1 ) ); + } + + /** Returns id of property's nearest parent category. If no category + found, returns invalid wxPGId. + */ + inline wxPGId GetPropertyCategory( wxPGId id ) const + { + return wxPGIdGen( _GetPropertyCategory ( wxPGIdToPtr(id) ) ); + } + inline wxPGId GetPropertyCategory( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + return _GetPropertyCategory(p); + } + + /** Returns cell background colour of a property. */ + wxColour GetPropertyBackgroundColour( wxPGId id ) const; + inline wxColour GetPropertyBackgroundColour( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxColour()) + return GetPropertyBackgroundColour(wxPGIdGen(p)); + } + + /** Returns cell background colour of a property. */ + inline wxColour GetPropertyColour( wxPGId id ) const + { + return GetPropertyBackgroundColour( id ); + } + inline wxColour GetPropertyColour( wxPGPropNameStr name ) const + { + return GetPropertyBackgroundColour( name ); + } + + /** Returns cell background colour of a property. */ + wxColour GetPropertyTextColour( wxPGId id ) const; + inline wxColour GetPropertyTextColour( wxPGPropNameStr name ) const + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxColour()) + return GetPropertyTextColour(wxPGIdGen(p)); + } + + /** Returns id of property with given label (case-sensitive). If there is no + property with such label, returned property id is invalid ( i.e. it will return + false with IsOk method). If there are multiple properties with identical name, + most recent added is returned. + */ + inline wxPGId GetPropertyByLabel( const wxString& name ) const + { + return m_pState->GetPropertyByLabel(name); + } + + /** Returns "root property". It does not have name, etc. and it is not + visible. It is only useful for accessing its children. + */ + wxPGId GetRoot() const { return wxPGIdGen(m_pState->m_properties); } + + /** Returns height of a single grid row (in pixels). */ + int GetRowHeight() const { return m_lineHeight; } + + inline wxPGId GetSelectedProperty () const { return GetSelection(); } + + /** Returns currently selected property. */ + inline wxPGId GetSelection() const + { + return wxPGIdGen(m_selected); + } + + /** Returns current selection background colour. */ + inline wxColour GetSelectionBackgroundColour() const { return m_colSelBack; } + + /** Returns current selection text colour. */ + inline wxColour GetSelectionForegroundColour() const { return m_colSelFore; } + + /** Returns current splitter x position. */ + inline int GetSplitterPosition() const { return m_splitterx; } + + /** Returns a binary copy of the current property state. + NOTE: Too much work to implement, and uses would be few indeed. + */ + //wxPropertyGridState* GetCopyOfState() const; + + /** Returns current vertical spacing. */ + inline int GetVerticalSpacing() const { return (int)m_vspacing; } + + /** Returns true if a property is selected. */ + inline bool HasSelection() const { return ((m_selected!=(wxPGProperty*)NULL)?true:false); } + + /** Hides all low priority properties. */ + inline void HideLowPriority() { Compact ( true ); } + + /** Inserts property to the list. + + \param priorthis + New property is inserted just prior to this. Available only + in the first variant. There are two versions of this function + to allow this parameter to be either an id or name to + a property. + + \param parent + New property is inserted under this category. Available only + in the second variant. There are two versions of this function + to allow this parameter to be either an id or name to + a property. + + \param index + Index under category. Available only in the second variant. + If index is < 0, property is appended in category. + + \param newproperty + Pointer to the inserted property. wxPropertyGrid will take + ownership of this object. + + \return + Returns id for the property, + + \remarks + + - wxPropertyGrid takes the ownership of the property pointer. + + While Append may be faster way to add items, make note that when + both data storages (categoric and + non-categoric) are active, Insert becomes even more slow. This is + especially true if current mode is non-categoric. + + Example of use: + + \code + + // append category + wxPGId my_cat_id = propertygrid->Append( new wxPropertyCategoryClass (wxT("My Category")) ); + + ... + + // insert into category - using second variant + wxPGId my_item_id_1 = propertygrid->Insert( my_cat_id, 0, new wxStringProperty(wxT("My String 1")) ); + + // insert before to first item - using first variant + wxPGId my_item_id_2 = propertygrid->Insert ( my_item_id, new wxStringProperty(wxT("My String 2")) ); + + \endcode + + */ + inline wxPGId Insert( wxPGId priorthis, wxPGProperty* newproperty ) + { + wxPGId res = _Insert( wxPGIdToPtr( priorthis ), newproperty ); + DrawItems( newproperty, (wxPGProperty*) NULL ); + return res; + } + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGPropNameStr name, wxPGProperty* newproperty ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + wxPGId res = _Insert( (wxPGPropertyWithChildren*)p, newproperty ); + DrawItems( newproperty, (wxPGProperty*) NULL ); + return res; + } + + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGId id, int index, wxPGProperty* newproperty ) + { + wxPGId res = _Insert( (wxPGPropertyWithChildren*)wxPGIdToPtr (id), index, newproperty ); + DrawItems( newproperty, (wxPGProperty*) NULL ); + return res; + } + + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGPropNameStr name, int index, wxPGProperty* newproperty ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(wxNullProperty) + wxPGId res = _Insert( (wxPGPropertyWithChildren*)p, index, newproperty ); + DrawItems( newproperty, (wxPGProperty*) NULL ); + return res; + } + + inline wxPGId InsertCategory( wxPGId id, int index, const wxString& label, const wxString& name = wxPG_LABEL ) + { + return Insert( id, index, new wxPropertyCategoryClass(label,name) ); + } + +#if wxPG_INCLUDE_BASICPROPS + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGId id, int index, const wxString& label, const wxString& name, const wxString& value = wxEmptyString ) + { + return Insert( id, index, wxStringProperty(label,name,value) ); + } + + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGId id, int index, const wxString& label, const wxString& name, int value ) + { + return Insert( id, index, wxIntProperty(label,name,value) ); + } + + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGId id, int index, const wxString& label, const wxString& name, double value ) + { + return Insert( id, index, wxFloatProperty(label,name,value) ); + } + + /** @link wxPropertyGrid::Insert Insert @endlink */ + inline wxPGId Insert( wxPGId id, int index, const wxString& label, const wxString& name, bool value ) + { + return Insert( id, index, wxBoolProperty(label,name,value) ); + } +#endif + + /** Returns true if any property has been modified by the user. */ + inline bool IsAnyModified() const { return (m_pState->m_anyModified>0); } + + /** Returns true if updating is frozen (ie. Freeze() called but not yet Thaw() ). */ + inline bool IsFrozen() const { return (m_frozen>0)?true:false; } + + /** Returns true if given property is selected. */ + inline bool IsPropertySelected( wxPGId id ) const + { + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + return ( m_selected == p ) ? true : false; + } + + /** Returns true if given property is selected. */ + inline bool IsPropertySelected( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return ( m_selected == p ) ? true : false; + } + + /** Disables (limit = true) or enables (limit = false) wxTextCtrl editor of a property, + if it is not the sole mean to edit the value. + */ + void LimitPropertyEditing( wxPGId id, bool limit = true ); + + /** Disables (limit = true) or enables (limit = false) wxTextCtrl editor of a property, + if it is not the sole mean to edit the value. + */ + inline void LimitPropertyEditing( wxPGPropNameStr name, bool limit = true ) + { + wxPG_PROP_NAME_CALL_PROLOG() + LimitPropertyEditing(wxPGIdGen(p),limit); + } + + /** Moves splitter as left as possible, while still allowing all + labels to be shown in full. + \param subProps + If false, will still allow sub-properties (ie. properties which + parent is not root or category) to be cropped. + */ + void SetSplitterLeft( bool subProps = false ); + + /** Registers a new value type. Takes ownership of the object. + \retval + Pointer to the value type that should be used. If on with + the same name already existed, then the first one will be used, + and its pointer is returned instead. + */ + static wxPGValueType* RegisterValueType( wxPGValueType* valueclass, bool noDefCheck = false, + const wxString& className = wxEmptyString ); + +#ifndef SWIG + /** Registers a new editor class. + \retval + Pointer to the editor class instance that should be used. + */ + static wxPGEditor* RegisterEditorClass( wxPGEditor* editor, const wxString& name, + bool noDefCheck = false ); +#endif + + /** Resets all colours to the original system values. + */ + void ResetColours(); + + /** Changes keyboard shortcut to push the editor button. + \remarks + You can set default with keycode 0. Good value for the platform is guessed, + but don't expect it to be very accurate. + */ + void SetButtonShortcut( int keycode, bool ctrlDown = false, bool altDown = false ); + + /** Sets text colour of a category caption (but not it's children). + */ + void SetCaptionTextColour( wxPGId id, const wxColour& col ); + inline void SetCaptionTextColour( wxPGPropNameStr name, const wxColour& col ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetCaptionTextColour( wxPGIdGen(p), col ); + } + + /** Sets the current category - Append will add non-categories under this one. + */ + inline void SetCurrentCategory( wxPGId id ) + { + wxPG_PROP_ID_CALL_PROLOG() + wxPropertyCategoryClass* pc = (wxPropertyCategoryClass*)p; +#ifdef __WXDEBUG__ + if ( pc ) wxASSERT( pc->GetParentingType() > 0 ); +#endif + m_pState->m_currentCategory = pc; + } + + /** Sets the current category - Append will add non-categories under this one. + */ + inline void SetCurrentCategory( wxPGPropNameStr name = wxEmptyString ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetCurrentCategory(wxPGIdGen(p)); + } + + /** Sets property attribute for all applicapple properties. + Be sure to use this method after all properties have been + added to the grid. + */ + void SetPropertyAttributeAll( int attrid, wxVariant value ); + + /** Sets background colour of property and all its children, recursively. Colours of + captions are not affected. Background brush cache is optimized for often + set colours to be set last. + \remarks + * Children which already have custom background colour are not affected. + */ + void SetPropertyBackgroundColour( wxPGId id, const wxColour& col ); + inline void SetPropertyBackgroundColour( wxPGPropNameStr name, const wxColour& col ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyBackgroundColour( wxPGIdGen(p), col ); + } + + /** Sets background colour of property and all its children. Colours of + captions are not affected. Background brush cache is optimized for often + set colours to be set last. + + NOTE: This function is deprecated. Use SetPropertyBackgroundColour. + */ + inline void SetPropertyColour( wxPGId id, const wxColour& col ) + { + SetPropertyBackgroundColour( id, col ); + } + inline void SetPropertyColour( wxPGPropNameStr name, const wxColour& col ) + { + SetPropertyBackgroundColour( name, col ); + } + + /** Sets text colour of property and all its children. + \remarks + * Children which already have custom text colour are not affected. + */ + void SetPropertyTextColour( wxPGId id, const wxColour& col ); + inline void SetPropertyTextColour( wxPGPropNameStr name, const wxColour& col ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyTextColour( wxPGIdGen(p), col ); + } + + /** Sets background and text colour of property and all its children to the default. */ + void SetPropertyColourToDefault( wxPGId id ); + inline void SetPropertyColourToDefault( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyColourToDefault( wxPGIdGen(p) ); + } + + /** Sets category caption background colour. */ + void SetCaptionBackgroundColour(const wxColour& col); + + /** Sets category caption text colour. */ + void SetCaptionForegroundColour(const wxColour& col); + + /** Sets default cell background colour - applies to property cells. + Note that appearance of editor widgets may not be affected. + */ + void SetCellBackgroundColour(const wxColour& col); + + /** Sets cell text colour for disabled properties. + */ + void SetCellDisabledTextColour(const wxColour& col); + + /** Sets default cell text colour - applies to property name and value text. + Note that appearance of editor widgets may not be affected. + */ + void SetCellTextColour(const wxColour& col); + + /** Sets colour of lines between cells. */ + void SetLineColour(const wxColour& col); + + /** Sets background colour of margin. */ + void SetMarginColour(const wxColour& col); + + /** Sets selection background colour - applies to selected property name background. */ + void SetSelectionBackground(const wxColour& col); + + /** Sets selection foreground colour - applies to selected property name text. */ + void SetSelectionForeground(const wxColour& col); + + /** Sets x coordinate of the splitter. */ + inline void SetSplitterPosition( int newxpos, bool refresh = true ) + { + DoSetSplitterPosition(newxpos,refresh); + m_iFlags |= wxPG_FL_SPLITTER_PRE_SET; + } + + /** Selects a property. Editor widget is automatically created, but + not focused unless focus is true. This will generate wxEVT_PG_SELECT event. + \param id + Id to property to select. + \retval + True if selection finished succesfully. Usually only fails if current + value in editor is not valid. + \sa wxPropertyGrid::Unselect + */ + inline bool SelectProperty( wxPGId id, bool focus = false ) + { + return DoSelectProperty(wxPGIdToPtr(id),focus?wxPG_SEL_FOCUS:0); + } + inline bool SelectProperty( wxPGPropNameStr name, bool focus = false ) + { + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(false) + return DoSelectProperty(p,focus?wxPG_SEL_FOCUS:0); + } + + /** Mostly useful for page switching. + */ +#ifndef SWIG + void SwitchState( wxPropertyGridState* pNewState ); +#endif + + /** Sets label of a property. + \remarks + This is the only way to set property's name. There is not + wxPGProperty::SetLabel() method. + */ + inline void SetPropertyLabel( wxPGId id, const wxString& newproplabel ) + { + wxPG_PROP_ID_CALL_PROLOG() + _SetPropertyLabel( p, newproplabel ); + } + /** Sets label of a property. + \remarks + This is the only way to set property's label. There is no + wxPGProperty::SetLabel() method. + */ + inline void SetPropertyLabel( wxPGPropNameStr name, const wxString& newproplabel ) + { + wxPG_PROP_NAME_CALL_PROLOG() + _SetPropertyLabel( p, newproplabel ); + } + + /** Sets name of a property. + \param id + Id of a property. + \param newname + New name. + \remarks + This is the only way to set property's name. There is not + wxPGProperty::SetName() method. + */ + inline void SetPropertyName( wxPGId id, const wxString& newname ) + { + DoSetPropertyName( wxPGIdToPtr(id), newname ); + } + /** Sets name of a property. + \param name + Label of a property. + \param newname + New name. + \remarks + This is the only way to set property's name. There is not + wxPGProperty::SetName() method. + */ + inline void SetPropertyName( wxPGPropNameStr name, const wxString& newname ) + { + wxPG_PROP_NAME_CALL_PROLOG() + DoSetPropertyName( p, newname ); + } + + /** Sets value (long integer) of a property. + */ + inline void SetPropertyValueLong( wxPGId id, long value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(long), wxPGVariantFromLong(value) ); + } + +#ifndef __WXPYTHON__ + /** Sets value (integer) of a property. + */ + inline void SetPropertyValue( wxPGId id, int value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(long), wxPGVariantFromLong((long)value) ); + } +#endif + /** Sets value (floating point) of a property. + */ + inline void SetPropertyValueDouble( wxPGId id, double value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(double), wxPGVariantFromDouble(value) ); + } + /** Sets value (bool) of a property. + */ + inline void SetPropertyValueBool( wxPGId id, bool value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(bool), wxPGVariantFromLong(value?(long)1:(long)0) ); + } + + /** Sets value (wxString) of a property. + \remarks + This method uses wxPGProperty::SetValueFromString, which all properties + should implement. This means that there should not be a type error, + and instead the string is converted to property's actual value type. + */ + void SetPropertyValueString( wxPGId id, const wxString& value ); + +#ifndef __WXPYTHON__ + inline void SetPropertyValue( wxPGId id, const wxChar* value ) + { + SetPropertyValue(id,wxString(value)); + } +#endif + + /** Sets value (wxArrayString) of a property. + */ + inline void SetPropertyValueArrstr2( wxPGId id, const wxArrayString& value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(wxArrayString), wxPGVariantFromArrayString(value) ); + } + /** Sets value (wxObject*) of a property. + */ + void SetPropertyValueWxObjectPtr( wxPGId id, wxObject* value ); +#ifndef __WXPYTHON__ + /** Sets value (void*) of a property. */ + inline void SetPropertyValue( wxPGId id, void* value ) + { + SetPropertyValue( id, wxPG_VALUETYPE(void), value ); + } + inline void SetPropertyValue ( wxPGId id, wxObject& value ) + { + SetPropertyValue(id,&value); + } + + /** Sets value (wxVariant&) of a property. */ + void SetPropertyValue( wxPGId id, wxVariant& value ); +#endif + + /** Sets value (wxPoint&) of a property. + */ + inline void SetPropertyValuePoint( wxPGId id, const wxPoint& value ) + { + SetPropertyValue( id, wxT("wxPoint"), wxPGVariantCreator(value) ); + } + /** Sets value (wxSize&) of a property. + */ + inline void SetPropertyValueSize( wxPGId id, const wxSize& value ) + { + SetPropertyValue( id, wxT("wxSize"), wxPGVariantCreator(value) ); + } + /** Sets value (wxLongLong&) of a property. + */ + inline void SetPropertyValueLongLong( wxPGId id, const wxLongLong& value ) + { + SetPropertyValue( id, wxT("wxLongLong"), wxPGVariantCreator(value) ); + } + /** Sets value (wxULongLong&) of a property. + */ + inline void SetPropertyValueULongLong( wxPGId id, const wxULongLong& value ) + { + SetPropertyValue( id, wxT("wxULongLong"), wxPGVariantCreator(value) ); + } + /** Sets value (wxArrayInt&) of a property. + */ + inline void SetPropertyValueArrint2( wxPGId id, const wxArrayInt& value ) + { + SetPropertyValue( id, wxT("wxArrayInt"), wxPGVariantCreator(value) ); + } + /** Sets value (wxDateTime&) of a property. + */ +#if wxUSE_DATETIME + inline void SetPropertyValueDatetime( wxPGId id, const wxDateTime& value ) + { + SetPropertyValue( id, wxT("datetime"), value ); + } +#endif +#ifdef __WXPYTHON__ + inline void SetPropertyValuePyObject( wxPGId id, PyObject* value ) + { + SetPropertyValue( id, wxT("PyObject"), wxPGVariantCreator(value) ); + } +#endif + + /** Sets value (long integer) of a property. + */ + inline void SetPropertyValueLong( wxPGPropNameStr name, long value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(long), wxPGVariantFromLong(value) ); + } +#ifndef __WXPYTHON__ + /** Sets value (integer) of a property. */ + inline void SetPropertyValue( wxPGPropNameStr name, int value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(long), wxPGVariantFromLong(value) ); + } +#endif + /** Sets value (floating point) of a property. + */ + inline void SetPropertyValueDouble( wxPGPropNameStr name, double value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(double), wxPGVariantFromDouble(value) ); + } + /** Sets value (bool) of a property. + */ + inline void SetPropertyValueBool( wxPGPropNameStr name, bool value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(bool), wxPGVariantFromLong(value?(long)1:(long)0) ); + } + /** Sets value (wxString) of a property. For properties which value type is + not string, calls wxPGProperty::SetValueFromString to translate the value. + */ + inline void SetPropertyValueString( wxPGPropNameStr name, const wxString& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueString( wxPGIdGen(p), value ); + } + +#ifndef __WXPYTHON__ + /** Sets value (wxString) of a property. For properties which value type is + not string, calls wxPGProperty::SetValueFromString to translate the value. + */ + inline void SetPropertyValue( wxPGPropNameStr name, const wxChar* value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxString(value) ); + } + + /** Sets value (void*) of a property. */ + inline void SetPropertyValue( wxPGPropNameStr name, void* value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(void), value ); + } +#endif + + /** Sets value (wxObject*) of a property. + */ + inline void SetPropertyValueWxObjectPtr( wxPGPropNameStr name, wxObject* value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueWxObjectPtr( wxPGIdGen(p), value ); + } + +#ifndef __WXPYTHON__ + inline void SetPropertyValue( wxPGPropNameStr name, wxObject& value ) + { + SetPropertyValue(name,&value); + } + + /** Sets value (wxVariant&) of a property. */ + void SetPropertyValue( wxPGPropNameStr name, wxVariant& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), value ); + } + + /** Sets value (wxArrayString) of a property. */ + inline void SetPropertyValueArrstr2( wxPGPropNameStr name, const wxArrayString& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValue( wxPGIdGen(p), wxPG_VALUETYPE(wxArrayString), wxPGVariantFromArrayString(value) ); + } + /** Sets value (wxArrayInt&) of a property. */ + inline void SetPropertyValueArrint2( wxPGPropNameStr name, const wxArrayInt& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueArrint2( wxPGIdGen(p), value ); + } +#endif + /** Sets value (wxDateTime&) of a property. + */ +#if wxUSE_DATETIME + inline void SetPropertyValueDatetime( wxPGPropNameStr name, const wxDateTime& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueDatetime( wxPGIdGen(p), value ); + } +#endif + /** Sets value (wxPoint&) of a property. + */ + inline void SetPropertyValuePoint( wxPGPropNameStr name, const wxPoint& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValuePoint( wxPGIdGen(p), value ); + } + /** Sets value (wxSize&) of a property. + */ + inline void SetPropertyValueSize( wxPGPropNameStr name, const wxSize& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueSize( wxPGIdGen(p), value ); + } + /** Sets value (wxLongLong&) of a property. + */ + inline void SetPropertyValueLongLong( wxPGPropNameStr name, const wxLongLong& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueLongLong( wxPGIdGen(p), value ); + } + /** Sets value (wxULongLong&) of a property. + */ + inline void SetPropertyValueULongLong( wxPGPropNameStr name, const wxULongLong& value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValueULongLong( wxPGIdGen(p), value ); + } +#ifdef __WXPYTHON__ + inline void SetPropertyValuePyObject( wxPGPropNameStr name, PyObject* value ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyValuePyObject( wxPGIdGen(p), value ); + } +#endif + + /** Sets property's value to unspecified. If it has children (it may be category), + then the same thing is done to them. + */ + void SetPropertyUnspecified( wxPGId id ); + inline void SetPropertyUnspecified ( wxPGPropNameStr name ) + { + wxPG_PROP_NAME_CALL_PROLOG() + SetPropertyUnspecified( wxPGIdGen(p) ); + } + +#ifndef SWIG + /** Sets various property values from a list of wxVariants. If property with + name is missing from the grid, new property is created under given default + category (or root if omitted). + */ + void SetPropertyValues( const wxVariantList& list, wxPGId default_category ) + { + m_pState->SetPropertyValues(list,default_category); + } + + inline void SetPropertyValues( const wxVariant& list, wxPGId default_category ) + { + SetPropertyValues(list.GetList(),default_category); + } + inline void SetPropertyValues( const wxVariantList& list, const wxString& default_category = wxEmptyString ) + { + SetPropertyValues(list,GetPropertyByNameI(default_category)); + } + inline void SetPropertyValues( const wxVariant& list, const wxString& default_category = wxEmptyString ) + { + SetPropertyValues(list.GetList(),GetPropertyByNameI(default_category)); + } +#endif + + /** Sets vertical spacing. Can be 1, 2, or 3 - a value relative to font + height. Value of 2 should be default on most platforms. + \remarks + On wxMSW, wxComboBox, when used as property editor widget, will spill + out with anything less than 3. + */ + inline void SetVerticalSpacing( int vspacing ) + { + m_vspacing = (unsigned char)vspacing; + CalculateFontAndBitmapStuff( vspacing ); + if ( !m_pState->m_itemsAdded ) Refresh(); + } + + /** Shows all low priority properties. */ + inline void ShowLowPriority() { Compact ( false ); } + + /** Shows an brief error message that is related to a property. */ + inline void ShowPropertyError( wxPGId id, const wxString& msg ) + { + wxPG_PROP_ID_CALL_PROLOG() + p->ShowError(msg); + } + inline void ShowPropertyError( wxPGPropNameStr name, const wxString& msg ) + { + ShowPropertyError (GetPropertyByNameI(name), msg); + } + + /** Sorts all items at all levels (except sub-properties). */ + void Sort(); + + /** Sorts children of a category. + */ + void Sort( wxPGId id ); + + /** Sorts children of a category. + */ + inline void Sort( wxPGPropNameStr name ) + { + Sort( GetPropertyByNameI(name) ); + } + + /** Overridden function. + \sa @link wndflags Additional Window Styles@endlink + */ + virtual void SetWindowStyleFlag( long style ); + + /** All properties added/inserted will have given priority by default. + \param + priority can be wxPG_HIGH (default) or wxPG_LOW. + */ + inline void SetDefaultPriority( int priority ) + { + if ( priority == wxPG_LOW ) + m_iFlags |= wxPG_FL_ADDING_HIDEABLES; + else + m_iFlags &= ~(wxPG_FL_ADDING_HIDEABLES); + } + + /** Same as SetDefaultPriority(wxPG_HIGH). */ + inline void ResetDefaultPriority() + { + SetDefaultPriority(wxPG_HIGH); + } + + /** Property editor widget helper methods. */ + //@{ + /** Call when editor widget's contents is modified. For example, this is called + when changes text in wxTextCtrl (used in wxStringProperty and wxIntProperty). + \remarks + This should only be called by properties. + \sa @link wxPGProperty::OnEvent @endlink + */ + inline void EditorsValueWasModified() { m_iFlags |= wxPG_FL_VALUE_MODIFIED; } + /** Reverse of EditorsValueWasModified(). */ + inline void EditorsValueWasNotModified() + { + m_iFlags &= ~(wxPG_FL_VALUE_MODIFIED); + } + + /** Returns true if editor's value was marked modified. */ + inline bool IsEditorsValueModified() const { return ( m_iFlags & wxPG_FL_VALUE_MODIFIED ) ? true : false; } + + /** Shortcut for creating dialog-caller button. Used, for example, by wxFontProperty. + \remarks + This should only be called by properties. + */ + wxWindow* GenerateEditorButton( const wxPoint& pos, const wxSize& sz ); + + /** Fixes position of wxTextCtrl-like control (wxSpinCtrl usually + fits as one). Call after control has been created (but before + shown). + */ + void FixPosForTextCtrl( wxWindow* ctrl ); + + /** Shortcut for creating text editor widget. + \param pos + Same as pos given for CreateEditor. + \param sz + Same as sz given for CreateEditor. + \param value + Initial text for wxTextCtrl. + \param secondary + If right-side control, such as button, also created, then create it first + and pass it as this parameter. + \param extraStyle + Extra style flags to pass for wxTextCtrl. + \remarks + Note that this should generally be called only by new classes derived + from wxPGProperty. + */ + wxWindow* GenerateEditorTextCtrl( const wxPoint& pos, + const wxSize& sz, + const wxString& value, + wxWindow* secondary, + int extraStyle = 0, + int maxLen = 0 ); + + /* Generates both textctrl and button. + */ + wxWindow* GenerateEditorTextCtrlAndButton( const wxPoint& pos, + const wxSize& sz, wxWindow** psecondary, int limited_editing, + wxPGProperty* property ); + + /** Generates position for a widget editor dialog box. + \param p + Property for which dialog is positioned. + \param sz + Known or over-approximated size of the dialog. + \retval + Position for dialog. + */ + wxPoint GetGoodEditorDialogPosition( wxPGProperty* p, + const wxSize& sz ); + + // Converts escape sequences in src_str to newlines, + // tabs, etc. and copies result to dst_str. + static wxString& ExpandEscapeSequences( wxString& dst_str, wxString& src_str ); + + // Converts newlines, tabs, etc. in src_str to escape + // sequences, and copies result to dst_str. + static wxString& CreateEscapeSequences( wxString& dst_str, wxString& src_str ); + + /** Returns rectangle that fully contains properties between and including p1 and p2. + */ + wxRect GetPropertyRect( const wxPGProperty* p1, const wxPGProperty* p2 ) const; + + /** Returns pointer to current active primary editor control (NULL if none). + + If editor uses clipper window, pointer is returned to the actual editor, not the clipper. + */ + wxWindow* GetEditorControl() const; + + inline wxWindow* GetPrimaryEditor() const + { + return m_wndPrimary; + } + + /** Returns pointer to current active secondary editor control (NULL if none). + */ + inline wxWindow* GetEditorControlSecondary() const + { + return m_wndSecondary; + } + + inline int IsNextEventIgnored() const + { + return m_ignoredEvents; + } + + inline void IgnoreNextEvent() + { + m_ignoredEvents++; + } + + inline void IgnoredEventPasses() + { + wxASSERT( m_ignoredEvents > 0 ); + m_ignoredEvents--; + } + +#ifdef __WXPYTHON__ + // Dummy method to put wxRect type info into the wrapper + wxRect DummywxRectTypeInit() const { return wxRect(1,2,3,4); } +#endif + +#ifndef SWIG + + /** Generates contents for string dst based on the convetents of wxArrayString + src. Format will be str1 str2 + and so on. Set flags to 1 inorder to convert backslashes to double-back- + slashes and ""'s to "\". + */ + static void ArrayStringToString( wxString& dst, const wxArrayString& src, + wxChar preDelim, wxChar postDelim, + int flags ); + + /** Pass this function to Connect calls in propertyclass::CreateEditor. + */ + void OnCustomEditorEvent( wxCommandEvent &event ); + /** Puts items into sl. Automatic wxGetTranslation is used if enabled. */ + void SLAlloc ( unsigned int itemcount, const wxChar** items ); + /** Returns sl. */ + inline wxArrayString& SLGet() { return m_sl; } + //@} + + inline long GetInternalFlags() const { return m_iFlags; } + inline void ClearInternalFlag( long flag ) { m_iFlags &= ~(flag); } + inline unsigned int GetBottomY() const { return m_bottomy; } + inline void SetBottomY( unsigned int y ) { m_bottomy = y; } + inline void IncFrozen() { m_frozen++; } + inline void DecFrozen() { m_frozen--; } + + /** Call after a property modified internally. + selFlags are the same as with DoSelectProperty. + NB: Avoid using this method, if possible. + */ + void PropertyWasModified( wxPGProperty* p, int selFlags = 0 ); + + void OnComboItemPaint( wxPGCustomComboControl* pCb,int item,wxDC& dc, + wxRect& rect,int flags ); + + // Used by simple check box for keyboard navigation + void SendNavigationKeyEvent( int dir ); + +#if 0 + /* Creates choices for labels and values, or returns existing choices which + point to the same memory. + */ + static wxPGChoices* CreateChoicesArray(const wxChar** labels, + const long* values, + int itemcount); + + /* Creates choices for labels and values, or returns existing choices which + point to the same memory (*only* if acceptLabelsAsId=true). + */ + static wxPGChoices* CreateChoicesArray(const wxArrayString& labels, + const wxArrayInt& values = wxPG_EMPTY_ARRAYINT, + bool acceptLabelsAsId = false); + + /* Creates choices for labels and values in wxPGChoices, or returns existing + choices which is identical. + */ + static wxPGChoices* CreateChoicesArray(wxPGChoices& choices); + +#ifdef __WXDEBUG__ + // Displays what dynamic arrays are allocated + static void DumpAllocatedChoiceSets(); +#endif + +#endif // #if 0 + + /** Standardized double-to-string conversion. + */ + static void DoubleToString( wxString& target, + double value, + int precision, + bool removeZeroes, + wxString* precTemplate ); + + +protected: + + /** wxPropertyGridState used by the grid is created here. If grid is used + in wxPropertyGridManager, there is no point overriding this - instead, + set custom wxPropertyGridPage classes. + */ + virtual wxPropertyGridState* CreateState() const; + +#ifndef DOXYGEN +public: + + // Control font changer helper. + void SetCurControlBoldFont(); + + // + // Public methods for semi-public use + // (not protected for optimization) + // + bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 ); + + // Usually called internally after items added/deleted. + void CalculateYs( wxPGPropertyWithChildren* startparent, int startindex ); + + // Overridden functions. + virtual bool Destroy(); + virtual wxSize DoGetBestSize() const; + virtual void Refresh( bool eraseBackground = true, + const wxRect *rect = (const wxRect *) NULL ); + virtual bool SetFont( const wxFont& font ); +#if wxPG_SUPPORT_TOOLTIPS + void SetToolTip( const wxString& tipString ); +#endif + virtual void Freeze(); + virtual void SetExtraStyle( long exStyle ); + virtual void Thaw(); + + +protected: + + /** 1 if calling property event handler. */ + unsigned char m_processingEvent; + +#ifndef wxPG_ICON_WIDTH + wxBitmap *m_expandbmp, *m_collbmp; +#endif + + wxCursor *m_cursorSizeWE; + + /** wxWindow pointers to editor control(s). */ + wxWindow *m_wndPrimary; + wxWindow *m_wndSecondary; + +#if wxPG_DOUBLE_BUFFER + wxBitmap *m_doubleBuffer; +#endif + + wxArrayPtrVoid *m_windowsToDelete; + + /** Local time ms when control was created. */ + wxLongLong m_timeCreated; + + /** Indicates bottom of drawn and clickable area on the control. Updated + by CalculateYs. */ + unsigned int m_bottomy; + + /** Extra Y spacing between the items. */ + int m_spacingy; + + /** Control client area width; updated on resize. */ + int m_width; + + /** Control client area height; updated on resize. */ + int m_height; + + /** Non-client width (auto-centering helper). */ + int m_fWidth; + + /** List of currently visible properties. */ + wxPGArrayProperty m_arrVisible; + + /** Previously recorded scroll start position. */ + int m_prevVY; + + /** Necessary so we know when to re-calculate visibles on resize. */ + int m_calcVisHeight; + + /** The gutter spacing in front and back of the image. This determines the amount of spacing in front + of each item */ + int m_gutterWidth; + + /** Includes separator line. */ + int m_lineHeight; + + /** Gutter*2 + image width. */ + int m_marginWidth; + + int m_buttonSpacingY; // y spacing for expand/collapse button. + + /** Extra margin for expanded sub-group items. */ + int m_subgroup_extramargin; + + /** The image width of the [+] icon. This is also calculated in the gutter */ + int m_iconWidth; + +#ifndef wxPG_ICON_WIDTH + + /** The image height of the [+] icon. This is calculated as minimal size and to align */ + int m_iconHeight; +#endif + + /** Current cursor id. */ + int m_curcursor; + + /** This captionFont is made equal to the font of the wxScrolledWindow. As extra the bold face + is set on it when this is wanted by the user (see flags) */ + wxFont m_captionFont; + +#if !wxPG_HEAVY_GFX + int m_splitterprevdrawnx; + + /** Pen used to draw splitter column when it is being dragged. */ + wxPen m_splitterpen; + +#endif + + int m_fontHeight; // Height of the font. + + int m_pushButKeyCode; // Base keycode for triggering push button. + + // + // Temporary values + // + + /** m_splitterx when drag began. */ + int m_startingSplitterX; + + /** Bits are used to indicate which colours are customized. */ + unsigned short m_coloursCustomized; + + /** 0 = not dragging, 1 = drag just started, 2 = drag in progress */ + unsigned char m_dragStatus; + + /** x - m_splitterx. */ + signed char m_dragOffset; + + /** 0 = margin, 1 = label, 2 = value. */ + unsigned char m_mouseSide; + + /** True when editor control is focused. */ + unsigned char m_editorFocused; + + /** 1 if m_latsCaption is also the bottommost caption. */ + //unsigned char m_lastCaptionBottomnest; + + /** Set to 1 when graphics frozen. */ + unsigned char m_frozen; + + unsigned char m_vspacing; + + unsigned char m_pushButKeyCodeNeedsAlt; // Does triggering push button need Alt down? + + unsigned char m_pushButKeyCodeNeedsCtrl; // Does triggering push button need Ctrl down? + + unsigned char m_keyComboConsumed; // Used to track when Alt/Ctrl+Key was consumed. + + unsigned char m_ignoredEvents; // Number of EVT_TEXT-style events to ignore. + + /** Internal flags - see wxPG_FL_XXX constants. */ + wxUint32 m_iFlags; + + /** When drawing next time, clear this many item slots at the end. */ + int m_clearThisMany; + + /** Pointer to selected property. Note that this is duplicated in + m_state for better transiency between pages so that the selected + item can be retained. + */ + wxPGProperty* m_selected; + + wxPGProperty* m_propHover; // pointer to property that has mouse on itself + + wxWindow* m_eventObject; // EventObject for wxPropertyGridEvents + + wxWindow* m_curFocused; // What (global) window is currently focused + // (needed to resolve event handling mess). + + wxEvtHandler* m_tlwHandler; // wxPGTLWHandler + + wxWindow* m_tlp; // Top level parent + + int m_splitterx; // x position for the vertical line dividing name and value + + float m_fSplitterX; // accurate splitter position + + int m_ctrlXAdjust; // x relative to splitter (needed for resize). + + wxColour m_colLine; // lines between cells + wxColour m_colPropFore; // property labels and values are written in this colour + wxColour m_colDisPropFore; // or with this colour when disabled + wxColour m_colPropBack; // background for m_colPropFore + wxColour m_colCapFore; // text color for captions + wxColour m_colCapBack; // background color for captions + wxColour m_colSelFore; // foreground for selected property + wxColour m_colSelBack; // background for selected property (actually use background color when control out-of-focus) + wxColour m_colMargin; // background colour for margin + + // NB: These *cannot* be moved to globals. + wxArrayPtrVoid m_arrBgBrushes; // Array of background colour brushes. + wxArrayPtrVoid m_arrFgCols; // Array of foreground colours. + + wxArrayString m_sl; // string control helper + +protected: + + // Sets some members to defaults (called constructors). + void Init1(); + + // Initializes some members (called by Create and complex constructor). + void Init2(); + + void OnPaint(wxPaintEvent &event ); + + // main event receivers + void OnMouseMove( wxMouseEvent &event ); + void OnMouseClick( wxMouseEvent &event ); + void OnMouseRightClick( wxMouseEvent &event ); + void OnMouseDoubleClick( wxMouseEvent &event ); + void OnMouseUp( wxMouseEvent &event ); + void OnKey( wxKeyEvent &event ); + void OnKeyUp( wxKeyEvent &event ); + void OnNavigationKey( wxNavigationKeyEvent& event ); + void OnResize( wxSizeEvent &event ); + + // event handlers + bool HandleMouseMove( int x, unsigned int y, wxMouseEvent &event ); + bool HandleMouseClick( int x, unsigned int y, wxMouseEvent &event ); + bool HandleMouseRightClick( int x, unsigned int y, wxMouseEvent &event ); + bool HandleMouseDoubleClick( int x, unsigned int y, wxMouseEvent &event ); + bool HandleMouseUp( int x, unsigned int y, wxMouseEvent &event ); + void HandleKeyEvent( wxKeyEvent &event ); + bool HandleChildKey( wxKeyEvent& event, bool canDestroy ); // Handle TAB and ESCAPE in control + + void OnMouseEntry( wxMouseEvent &event ); + + void OnIdle( wxIdleEvent &event ); + void OnFocusEvent( wxFocusEvent &event ); + void OnChildFocusEvent( wxChildFocusEvent& event ); + + bool OnMouseCommon( wxMouseEvent &event, int* px, int *py ); + bool OnMouseChildCommon( wxMouseEvent &event, int* px, int *py ); + + // sub-control event handlers + void OnMouseClickChild( wxMouseEvent &event ); + void OnMouseRightClickChild( wxMouseEvent &event ); + void OnMouseMoveChild( wxMouseEvent &event ); + void OnMouseUpChild( wxMouseEvent &event ); + void OnChildKeyDown( wxKeyEvent &event ); + void OnChildKeyUp( wxKeyEvent &event ); + //void OnFocusChild( wxFocusEvent &event ); + + void OnCaptureChange( wxMouseCaptureChangedEvent &event ); + + void OnScrollEvent( wxScrollWinEvent &event ); + + void OnSysColourChanged( wxSysColourChangedEvent &event ); + +protected: + + /** Adjust the centering of the bitmap icons (collapse / expand) when the caption font changes. They need to + be centered in the middle of the font, so a bit of deltaY adjustment is needed. + On entry, m_captionFont must be set to window font. It will be modified properly. + */ + void CalculateFontAndBitmapStuff( int vspacing ); + + inline wxRect GetEditorWidgetRect( wxPGProperty* p ); + + void CorrectEditorWidgetSizeX( int newSplitterx, int newWidth ); + +#ifdef __WXDEBUG__ + void _log_items(); + void OnScreenNote( const wxChar* format, ... ); +#endif + + void DoDrawItems( wxDC& dc, + const wxPGProperty* first_item, + const wxPGProperty* last_item, + const wxRect* clip_rect ); + + void DoDrawItems2( wxDC& dc, + const wxPGProperty* first_item, + const wxPGProperty* last_item, + const wxRect* clip_rect ) const; + + virtual void RefreshProperty( wxPGProperty* p ); + + /** Draws items from topitemy to bottomitemy */ + void DrawItems( wxDC& dc, unsigned int topitemy, unsigned int bottomitemy, + const wxRect* clip_rect = (const wxRect*) NULL ); + + void DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 ); + + // In addition to calling DoDrawItems directly, this is the + // only alternative for using wxClientDC - others just call + // RefreshRect. + void DrawItem( wxDC& dc, wxPGProperty* p ); + + inline void DrawItem( wxPGProperty* p ) + { + DrawItems(p,p); + } + + virtual void DrawItemAndChildren( wxPGProperty* p ); + + /** Draws item, children, and consequtive parents as long as category is not met. */ + void DrawItemAndValueRelated( wxPGProperty* p ); + + /** Returns property reference for given property id. */ + inline wxPGProperty& GetPropertyById( wxPGId id ) + { + return *wxPGIdToPtr(id); + } + + static wxPropertyCategoryClass* _GetPropertyCategory( wxPGProperty* p ); + + void ImprovedClientToScreen( int* px, int* py ); + + wxPGId _Insert( wxPGProperty* priorthis, wxPGProperty* newproperty ); + + inline wxPGId _Insert( wxPGPropertyWithChildren* parent, int index, wxPGProperty* newproperty ) + { + return m_pState->DoInsert(parent,index,newproperty); + } + + // Called by focus event handlers. newFocused is the window that becomes focused. + void HandleFocusChange( wxWindow* newFocused ); + + /** Reloads all non-customized colours from system settings. */ + void RegainColours(); + + bool DoEditorValidate(); + + wxPGProperty* DoGetItemAtY( int y ); + + inline wxPGProperty* DoGetItemAtY_Full( int y ) + { + wxASSERT( y >= 0 ); + + if ( (unsigned int)y >= m_bottomy ) + return NULL; + + return m_pState->m_properties->GetItemAtY ( y, m_lineHeight ); + } + + void DoPropertyChanged( wxPGProperty* p, unsigned int selFlags = 0 ); + + void DoSetSplitterPosition( int newxpos, bool refresh = true ); + + void FreeEditors(); + + wxPGProperty* GetLastItem( bool need_visible, bool allow_subprops = true ); + + void CalculateVisibles( int vy, bool full_recalc ); + + bool _Expand( wxPGProperty* p, bool sendEvent = false ); + + bool _Collapse( wxPGProperty* p, bool sendEvent = false ); + + /** Forces updating the value of property from the editor control. + Returns true if DoPropertyChanged was actually called. + */ + bool CommitChangesFromEditor( wxUint32 flags = 0 ); + + // Returns nearest paint visible property (such that will be painted unless + // window is scrolled or resized). If given property is paint visible, then + // it itself will be returned. + wxPGProperty* GetNearestPaintVisible( wxPGProperty* p ); + +/*#ifdef __WXMSW__ + virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const; +#endif*/ + + static void RegisterDefaultEditors(); + + static void RegisterDefaultValues(); + + // Sets m_bgColIndex to this property and all its children. + void SetBackgroundColourIndex( wxPGProperty* p, int index, int flags ); + + // Sets m_fgColIndex to this property and all its children. + void SetTextColourIndex( wxPGProperty* p, int index, int flags ); + + int CacheColour( const wxColour& colour ); + + void _SetPropertyLabel( wxPGProperty* p, const wxString& newproplabel ); + + void DoSetPropertyName( wxPGProperty* p, const wxString& newname ); + + void SetPropertyValue( wxPGId id, const wxPGValueType* typeclass, const wxPGVariant& value ); + + void SetPropertyValue( wxPGId id, const wxChar* typestring, const wxPGVariant& value ); + + // Setups event handling for child control + void SetupEventHandling( wxWindow* wnd, int id ); + + void CustomSetCursor( int type, bool override = false ); + + void RecalculateVirtualSize(); + + void PGAdjustScrollbars( int y ); + + inline bool UsesAutoUnspecified() const + { + return ( GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES ) ? true : false; + } + + /** When splitter is dragged to a new position, this is drawn. */ + void DrawSplitterDragColumn( wxDC& dc, int x ); + + /** If given index is -1, scans for item to either up (dir=0) or down (dir!=0) */ + //int GetNearestValidItem ( int index, int dir ); + wxPGProperty* GetNeighbourItem( wxPGProperty* item, bool need_visible, + int dir ) const; + + void PrepareAfterItemsAdded(); + + void SendEvent( int eventType, wxPGProperty* p, unsigned int selFlags = 0 ); + + bool SetPropertyPriority( wxPGProperty* p, int priority ); + +private: + + bool ButtonTriggerKeyTest( wxKeyEvent &event ); + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +private: + DECLARE_EVENT_TABLE() +#endif // #ifndef SWIG +}; + +#undef wxPG_USE_STATE + +// ----------------------------------------------------------------------- +// +// Bunch of inlines that need to resolved after all classes have been defined. +// + +#ifndef SWIG +inline bool wxPropertyGridState::IsDisplayed() const +{ + return ( this == m_pPropGrid->GetState() ); +} +#endif + +inline void wxPGProperty::SetEditor( const wxString& editorName ) +{ + EnsureDataExt(); + m_dataExt->m_customEditor = wxPropertyContainerMethods::GetEditorByName(editorName); +} + +inline bool wxPGProperty::Hide( bool hide ) +{ + return GetGrid()->HideProperty(wxPGIdGen(this),hide); +} + +inline bool wxPGProperty::SetMaxLength( int maxLen ) +{ + return GetGrid()->SetPropertyMaxLength(wxPGIdGen(this),maxLen); +} + +#if !wxPG_ID_IS_PTR +inline const wxString& wxPGId::GetName() const +{ + return m_ptr->GetName(); +} +#endif + +// ----------------------------------------------------------------------- + +/** \class wxPropertyGridEvent + \ingroup classes + \brief A propertygrid event holds information about events associated with + wxPropertyGrid objects. + +

Derived from

+ + wxNotifyEvent\n + wxCommandEvent\n + wxEvent\n + wxObject\n + +

Include files

+ + +*/ +class WXDLLIMPEXP_PG wxPropertyGridEvent : public wxCommandEvent +{ +public: + + /** Constructor. */ + wxPropertyGridEvent(wxEventType commandType=0, int id=0); +#ifndef SWIG + /** Copy constructor. */ + wxPropertyGridEvent(const wxPropertyGridEvent& event); +#endif + /** Destructor. */ + ~wxPropertyGridEvent(); + + /** Copyer. */ + virtual wxEvent* Clone() const; + + /** Enables property. */ + inline void EnableProperty( bool enable = true ) + { + m_pg->EnableProperty(wxPGIdGen(m_property),enable); + } + + /** Disables property. */ + inline void DisableProperty() + { + m_pg->EnableProperty(wxPGIdGen(m_property),false); + } + + inline wxPGId GetMainParent() const + { + wxASSERT(m_property); + return wxPGIdGen(m_property->GetMainParent()); + } + + /** Returns id of associated property. */ + wxPGId GetProperty() const + { + return wxPGIdGen(m_property); + } + +#ifndef SWIG + /** Returns pointer to associated property. */ + wxPGProperty* GetPropertyPtr() const + { + return m_property; + } +#endif + + /** Returns label of associated property. */ + const wxString& GetPropertyLabel() const + { + wxASSERT( m_property ); + return m_property->GetLabel(); + } + + /** Returns name of associated property. */ + const wxString& GetPropertyName() const + { + wxASSERT( m_property ); + return m_property->GetName(); + } + +#if wxPG_USE_CLIENT_DATA + /** Returns client data of relevant property. */ + wxPGProperty::ClientDataType GetPropertyClientData() const + { + wxASSERT( m_property ); + return m_property->GetClientData(); + } +#endif + +#ifndef SWIG + /** Returns value of relevant property. */ + wxVariant GetPropertyValue() const + { + wxASSERT( m_property ); + return m_property->GetValueAsVariant(); + } + + inline wxString GetPropertyValueAsString() const + { + return m_pg->GetPropertyValueAsString( wxPGIdGen(m_property) ); + } + inline long GetPropertyValueAsLong() const + { + return m_pg->GetPropertyValueAsLong( wxPGIdGen(m_property) ); + } + inline int GetPropertyValueAsInt() const + { + return (int)GetPropertyValueAsLong(); + } + inline long GetPropertyValueAsBool() const + { + return m_pg->GetPropertyValueAsBool( wxPGIdGen(m_property) ); + } + inline double GetPropertyValueAsDouble() const + { + return m_pg->GetPropertyValueAsDouble( wxPGIdGen(m_property) ); + } + inline const wxObject* GetPropertyValueAsWxObjectPtr() const + { + return m_pg->GetPropertyValueAsWxObjectPtr( wxPGIdGen(m_property) ); + } + inline void* GetPropertyValueAsVoidPtr() const + { + return m_pg->GetPropertyValueAsVoidPtr( wxPGIdGen(m_property) ); + } +#if !wxPG_PGVARIANT_IS_VARIANT + inline const wxArrayString& GetPropertyValueAsArrayString() const + { + return m_pg->GetPropertyValueAsArrayString( wxPGIdGen(m_property) ); + } + inline const wxPoint& GetPropertyValueAsPoint() const + { + return m_pg->GetPropertyValueAsPoint( wxPGIdGen(m_property) ); + } + inline const wxSize& GetPropertyValueAsSize() const + { + return m_pg->GetPropertyValueAsSize( wxPGIdGen(m_property) ); + } + inline const wxArrayInt& GetPropertyValueAsArrayInt() const + { + return m_pg->GetPropertyValueAsArrayInt( wxPGIdGen(m_property) ); + } +#else + inline wxArrayString GetPropertyValueAsArrayString() const + { + return m_pg->GetPropertyValueAsArrayString( wxPGIdGen(m_property) ); + } + inline wxPoint GetPropertyValueAsPoint() const + { + return m_pg->GetPropertyValueAsPoint( wxPGIdGen(m_property) ); + } + inline wxSize GetPropertyValueAsSize() const + { + return m_pg->GetPropertyValueAsSize( wxPGIdGen(m_property) ); + } + inline wxArrayInt GetPropertyValueAsArrayInt() const + { + return m_pg->GetPropertyValueAsArrayInt( wxPGIdGen(m_property) ); + } +#endif + + /** Returns value type of relevant property. */ + const wxPGValueType* GetPropertyValueType() const + { + return m_property->GetValueTypePtr(); + } + +#else + %pythoncode { + def GetPropertyValue(self): + return self.GetProperty().GetValue() + } +#endif + + /** Returns true if event has associated property. */ + inline bool HasProperty() const { return ( m_property != (wxPGProperty*) NULL ); } + + inline bool IsPropertyEnabled() const + { + return m_pg->IsPropertyEnabled(wxPGIdGen(m_property)); + } + +#ifndef SWIG + + // IsPending() == true, if sent using AddPendingEvent + inline void SetPending( bool pending ) { m_pending = pending; } + inline bool IsPending() const { return m_pending; } + +#if !wxPG_ID_IS_PTR + /** Changes the associated property. */ + void SetProperty( wxPGId id ) { m_property = wxPGIdToPtr(id); } +#endif + + /** Changes the associated property. */ + void SetProperty( wxPGProperty* p ) { m_property = p; } + + void SetPropertyGrid( wxPropertyGrid* pg ) { m_pg = pg; } + +private: + DECLARE_DYNAMIC_CLASS(wxPropertyGridEvent) + + wxPGProperty* m_property; + wxPropertyGrid* m_pg; + bool m_pending; +#endif +}; + + +#define wxPG_BASE_EVT_PRE_ID 1775 + +#ifndef SWIG +BEGIN_DECLARE_EVENT_TYPES() + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_SELECTED, wxPG_BASE_EVT_PRE_ID) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_CHANGED, wxPG_BASE_EVT_PRE_ID+1) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_HIGHLIGHTED, wxPG_BASE_EVT_PRE_ID+2) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_RIGHT_CLICK, wxPG_BASE_EVT_PRE_ID+3) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_PAGE_CHANGED, wxPG_BASE_EVT_PRE_ID+4) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_ITEM_COLLAPSED, wxPG_BASE_EVT_PRE_ID+5) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_ITEM_EXPANDED, wxPG_BASE_EVT_PRE_ID+6) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_DOUBLE_CLICK, wxPG_BASE_EVT_PRE_ID+7) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_COMPACT_MODE_ENTERED, wxPG_BASE_EVT_PRE_ID+8) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_PG, wxEVT_PG_EXPANDED_MODE_ENTERED, wxPG_BASE_EVT_PRE_ID+9) +END_DECLARE_EVENT_TYPES() +#else + enum { + wxEVT_PG_SELECTED = wxPG_BASE_EVT_PRE_ID, + wxEVT_PG_CHANGED, + wxEVT_PG_HIGHLIGHTED, + wxEVT_PG_RIGHT_CLICK, + wxEVT_PG_PAGE_CHANGED, + wxEVT_PG_ITEM_COLLAPSED, + wxEVT_PG_ITEM_EXPANDED, + wxEVT_PG_DOUBLE_CLICK, + wxEVT_PG_COMPACT_MODE_ENTERED, + wxEVT_PG_EXPANDED_MODE_ENTERED + }; +#endif + + +#define wxPG_BASE_EVT_TYPE wxEVT_PG_SELECTED +#define wxPG_MAX_EVT_TYPE (wxPG_BASE_EVT_TYPE+30) + + +#ifndef SWIG +typedef void (wxEvtHandler::*wxPropertyGridEventFunction)(wxPropertyGridEvent&); + +#define EVT_PG_SELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_CHANGED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_HIGHLIGHTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_HIGHLIGHTED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_RIGHT_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_RIGHT_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_DOUBLE_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_DOUBLE_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_PAGE_CHANGED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_PAGE_CHANGED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_ITEM_COLLAPSED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_COLLAPSED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_ITEM_EXPANDED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_EXPANDED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_COMPACT_MODE_ENTERED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_COMPACT_MODE_ENTERED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), +#define EVT_PG_EXPANDED_MODE_ENTERED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_EXPANDED_MODE_ENTERED, id, -1, (wxObjectEventFunction) (wxEventFunction) wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ), + +#define wxPropertyGridEventHandler(A) ((wxObjectEventFunction)(wxEventFunction)(wxPropertyGridEventFunction)&A) + +#endif + + +// ----------------------------------------------------------------------- + + +/** \class wxPropertyGridPopulator + \ingroup classes + \brief Allows populating wxPropertyGrid from arbitrary text source. +*/ +class WXDLLIMPEXP_PG wxPropertyGridPopulator +{ +public: + /** Constructor. + \param pg + Property grid to populate. + \param popRoot + Base parent property. Default is root. + */ + inline wxPropertyGridPopulator(wxPropertyGrid* pg = (wxPropertyGrid*) NULL, + wxPGId popRoot = wxNullProperty) + { + Init(pg, popRoot); + } + + /** Destructor. */ + ~wxPropertyGridPopulator(); + + /** Adds a new set of choices with given id, labels and optional values. + \remarks + choicesId can be any id unique in source (so it does not conflict + with sets of choices created before population process). + */ + void AddChoices(wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues = wxPG_EMPTY_ARRAYINT); + + /** Appends a property under current parent. + \param classname + Class name of a property. Understands both wxXXXProperty + and XXX style names. Thus, for example, wxStringProperty + could be created with class names "wxStringProperty", and + "String". Short class name of wxPropertyCategory is + "Category". + \param label + Label for property. Use as in constructor functions. + \param name + Name for property. Use as in constructor functions. + \param value + Value for property is interpreted from this string. + \param attributes + Attributes of a property (both pseudo-attributes like + "Disabled" and "Modified" in addition to real ones + like "Precision") are read from this string. Is intended + for string like one generated by GetPropertyAttributes. + \param choicesId + If non-zero: Id for set of choices unique in source. Pass + either id previously given to AddChoices or a new one. + If new is given, then choiceLabels and choiceValues are + loaded as the contents for the newly created set of choices. + \param choiceLabels + List of choice labels. + \param choiceValues + List of choice values. + */ + wxPGId AppendByClass(const wxString& classname, + const wxString& label, + const wxString& name = wxPG_LABEL, + const wxString& value = wxEmptyString, + const wxString& attributes = wxEmptyString, + wxPGChoicesId choicesId = (wxPGChoicesId)0, + const wxArrayString& choiceLabels = wxPG_EMPTY_ARRAYSTRING, + const wxArrayInt& choiceValues = wxPG_EMPTY_ARRAYINT); + + /** Appends a property under current parent. Works just as + AppendByClass, except accepts value type name instead of + class name (value type name of a property can be queried using + wxPropertyGrid::GetPropertyValueType(property)->GetType()). + + \remarks + Cannot generate property category. + */ + wxPGId AppendByType(const wxString& valuetype, + const wxString& label, + const wxString& name = wxPG_LABEL, + const wxString& value = wxEmptyString, + const wxString& attributes = wxEmptyString, + wxPGChoicesId choicesId = (wxPGChoicesId)0, + const wxArrayString& choiceLabels = wxPG_EMPTY_ARRAYSTRING, + const wxArrayInt& choiceValues = wxPG_EMPTY_ARRAYINT); + + /** Returns id of parent property for which children can currently be added. */ + inline wxPGId GetCurrentParent() const + { + return m_curParent; + } + + /** Returns true if set of choices with given id has already been added. */ + bool HasChoices( wxPGChoicesId id ) const; + + /** Sets the property grid to be populated. */ + inline void SetGrid( wxPropertyGrid* pg ) + { + m_propGrid = pg; + } + + /** If possible, sets the property last added as current parent. */ + bool BeginChildren(); + + /** Terminates current parent - sets its parent as the new current parent. */ + inline void EndChildren() + { + wxASSERT( wxPGIdIsOk(m_curParent) ); + m_curParent = wxPGIdGen(wxPGIdToPtr(m_curParent)->GetParent()); + m_lastProperty = wxPGIdGen((wxPGProperty*)NULL); + } + +protected: + + wxPGId DoAppend(wxPGProperty* p, + const wxString& value, + const wxString& attributes, + wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues); + + void Init( wxPropertyGrid* pg, wxPGId popRoot ); + + /** Used property grid. */ + wxPropertyGrid* m_propGrid; + + /** Population root. */ + wxPGId m_popRoot; + + /** Parent of currently added properties. */ + wxPGId m_curParent; + + /** Id of property last added. */ + wxPGId m_lastProperty; + + /** Hashmap for source-choices-id to wxPGChoicesData mapping. */ + wxPGHashMapP2P m_dictIdChoices; +}; + +// ----------------------------------------------------------------------- + +// +// Undefine macros that are not needed outside propertygrid sources +// +#ifndef __wxPG_SOURCE_FILE__ + #undef wxPG_FL_DESC_REFRESH_REQUIRED + #undef wxPG_FL_SCROLLBAR_DETECTED + #undef wxPG_FL_CREATEDSTATE + #undef wxPG_FL_NOSTATUSBARHELP + #undef wxPG_FL_SCROLLED + #undef wxPG_FL_HIDE_STATE + #undef wxPG_FL_FOCUS_INSIDE_CHILD + #undef wxPG_FL_FOCUS_INSIDE + #undef wxPG_FL_MOUSE_INSIDE_CHILD + #undef wxPG_FL_CUR_USES_CUSTOM_IMAGE + #undef wxPG_FL_PRIMARY_FILLS_ENTIRE + #undef wxPG_FL_VALUE_MODIFIED + #undef wxPG_FL_MOUSE_INSIDE + #undef wxPG_FL_FOCUSED + #undef wxPG_FL_MOUSE_CAPTURED + #undef wxPG_FL_INITIALIZED + #undef wxPG_FL_ACTIVATION_BY_CLICK + #undef wxPG_FL_DONT_CENTER_SPLITTER + #undef wxPG_SUPPORT_TOOLTIPS + #undef wxPG_DOUBLE_BUFFER + #undef wxPG_HEAVY_GFX + #undef wxPG_ICON_WIDTH + #undef wxPG_USE_RENDERER_NATIVE +// Following are needed by the manager headers +// #undef wxPGIdGen +// #undef wxPGPropNameStr +// #undef wxPGIdToPtr +#endif + +// Doxygen special +#ifdef DOXYGEN + #include "manager.h" +#endif + +// ----------------------------------------------------------------------- + +#endif // __WX_PROPGRID_PROPGRID_H__ + diff --git a/assdraw/libpropgrid/manager.cpp b/assdraw/libpropgrid/manager.cpp new file mode 100644 index 000000000..cc37e8b4e --- /dev/null +++ b/assdraw/libpropgrid/manager.cpp @@ -0,0 +1,1913 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: manager.cpp +// Purpose: wxPropertyGridManager +// Author: Jaakko Salli +// Modified by: +// Created: Jan-14-2005 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "manager.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" + #include "wx/object.h" + #include "wx/hash.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/event.h" + #include "wx/window.h" + #include "wx/panel.h" + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/button.h" + #include "wx/pen.h" + #include "wx/brush.h" + #include "wx/cursor.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/msgdlg.h" + #include "wx/choice.h" + #include "wx/stattext.h" + #include "wx/textctrl.h" + #include "wx/scrolwin.h" + #include "wx/dirdlg.h" + #include "wx/combobox.h" + #include "wx/layout.h" + #include "wx/sizer.h" + #include "wx/textdlg.h" + #include "wx/filedlg.h" + #include "wx/statusbr.h" + #include "wx/toolbar.h" + #include "wx/intl.h" +#endif + +// This define is necessary to prevent macro clearing +#define __wxPG_SOURCE_FILE__ + +#include + +#include + + +#define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss + + +// ----------------------------------------------------------------------- + +// For wxMSW cursor consistency, we must do mouse capturing even +// when using custom controls + +#define BEGIN_MOUSE_CAPTURE \ + if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \ + { \ + CaptureMouse(); \ + m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \ + } + +#define END_MOUSE_CAPTURE \ + if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \ + { \ + ReleaseMouse(); \ + m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \ + } + +// ----------------------------------------------------------------------- +// wxPropertyGridManager +// ----------------------------------------------------------------------- + +const wxChar *wxPropertyGridManagerNameStr = wxT("wxPropertyGridManager"); + + +// Categoric Mode Icon +static const char* gs_xpm_catmode[] = { +"16 16 5 1", +". c none", +"B c black", +"D c #868686", +"L c #CACACA", +"W c #FFFFFF", +".DDD............", +".DLD.BBBBBB.....", +".DDD............", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".DDD............", +".DLD.BBBBBB.....", +".DDD............", +".....DDDDD.DDD..", +"................" +}; + +// Alphabetic Mode Icon +static const char* gs_xpm_noncatmode[] = { +"16 16 5 1", +". c none", +"B c black", +"D c #868686", +"L c #000080", +"W c #FFFFFF", +"..DBD...DDD.DDD.", +".DB.BD..........", +".BBBBB..DDD.DDD.", +".B...B..........", +"...L....DDD.DDD.", +"...L............", +".L.L.L..DDD.DDD.", +"..LLL...........", +"...L....DDD.DDD.", +"................", +".BBBBB..DDD.DDD.", +"....BD..........", +"...BD...DDD.DDD.", +"..BD............", +".BBBBB..DDD.DDD.", +"................" +}; + +// Default Page Icon. +static const char* gs_xpm_defpage[] = { +"16 16 5 1", +". c none", +"B c black", +"D c #868686", +"L c #000080", +"W c #FFFFFF", +"................", +"................", +"..BBBBBBBBBBBB..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..BBBBBBBBBBBB..", +"................", +"................", +"................" +}; +/* + +// Categoric Mode Icon +static const char* gs_xpm_catmode[] = { +"12 12 5 1", +". c none", +"B c black", +"D c #868686", +"L c #CACACA", +"W c #FFFFFF", +".DDD............", +".DLD.BBBBBB.....", +".DDD............", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".....DDDDD.DDD..", +"................", +".DDD............" +}; + +// Alphabetic Mode Icon +static const char* gs_xpm_noncatmode[] = { +"12 12 5 1", +". c none", +"B c black", +"D c #868686", +"L c #000080", +"W c #FFFFFF", +"..DBD...DDD.DDD.", +".DB.BD..........", +".BBBBB..DDD.DDD.", +".B...B..........", +"...L....DDD.DDD.", +"...L............", +".L.L.L..DDD.DDD.", +"..LLL...........", +"...L....DDD.DDD.", +"................", +".BBBBB..DDD.DDD.", +"....BD.........." +}; + +// Default Page Icon. +static const char* gs_xpm_defpage[] = { +"12 12 5 1", +". c none", +"B c black", +"D c #868686", +"L c #000080", +"W c #FFFFFF", +"................", +"................", +"..BBBBBBBBBBBB..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B..", +"..B.BB.LLLLL.B..", +"..B..........B.." +};*/ + +// ----------------------------------------------------------------------- + +/** \class wxPropertyGridPageData + \ingroup classes + \brief + Simple holder of propertygrid page information. +*/ +/* +class wxPropertyGridPageData +{ +public: + + wxPropertyGridPageData() { } + ~wxPropertyGridPageData() { } + + wxString m_label; + wxPropertyGridState GetStatePtr(); + int m_id; +}; +*/ + +#define GetPageState(page) ((wxPropertyGridPage*)m_arrPages.Item(page))->GetStatePtr() + +// ----------------------------------------------------------------------- +// wxPropertyGridPage +// ----------------------------------------------------------------------- + + +IMPLEMENT_CLASS(wxPropertyGridPage, wxEvtHandler) + + +BEGIN_EVENT_TABLE(wxPropertyGridPage, wxEvtHandler) +END_EVENT_TABLE() + + +wxPropertyGridPage::wxPropertyGridPage() + : wxEvtHandler(), wxPropertyContainerMethods(), wxPropertyGridState() +{ + m_isDefault = false; + + m_pState = this; // wxPropertyContainerMethods to point to State +} + +wxPropertyGridPage::~wxPropertyGridPage() +{ +} + +void wxPropertyGridPage::RefreshProperty( wxPGProperty* p ) +{ + m_manager->RefreshProperty(p); +} + +/* +bool wxPropertyGridPage::ProcessEvent( wxEvent& event ) +{ + // By default, redirect unhandled events to the manager's parent + if ( !wxEvtHandler::ProcessEvent(event) ) + { + if ( IsHandlingAllEvents() ) + return false; + + m_manager->GetParent()->GetEventHandler()->AddPendingEvent(event); + return true; + } + return true; +}*/ + +wxPGId wxPropertyGridPage::Insert( wxPGId id, int index, wxPGProperty* property ) +{ + return m_manager->Insert(id,index,property); +} + +wxPGId wxPropertyGridPage::Insert( wxPGPropNameStr name, int index, wxPGProperty* property ) +{ + return m_manager->Insert(name,index,property); +} + +// ----------------------------------------------------------------------- +// wxPropertyGridManager +// ----------------------------------------------------------------------- + +// Final default splitter y is client height minus this. +#define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100 + +// ----------------------------------------------------------------------- + +IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel) + +#define ID_ADVTOOLBAR_OFFSET 1 +#define ID_ADVHELPCAPTION_OFFSET 2 +#define ID_ADVHELPCONTENT_OFFSET 3 +#define ID_ADVBUTTON_OFFSET 4 +#define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last. + +// ----------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel) + EVT_MOTION(wxPropertyGridManager::OnMouseMove) + EVT_SIZE(wxPropertyGridManager::OnResize) + EVT_PAINT(wxPropertyGridManager::OnPaint) + EVT_LEFT_DOWN(wxPropertyGridManager::OnMouseClick) + EVT_LEFT_UP(wxPropertyGridManager::OnMouseUp) + EVT_LEAVE_WINDOW(wxPropertyGridManager::OnMouseEntry) + //EVT_ENTER_WINDOW(wxPropertyGridManager::OnMouseEntry) +END_EVENT_TABLE() + +// ----------------------------------------------------------------------- + +wxPropertyGridManager::wxPropertyGridManager() + : wxPanel() +{ + Init1(); +} + +// ----------------------------------------------------------------------- + +wxPropertyGridManager::wxPropertyGridManager( wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxChar* name ) + : wxPanel() +{ + Init1(); + Create(parent,id,pos,size,style,name); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::Create( wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxChar* name ) +{ + + bool res = wxPanel::Create( parent, id, pos, size, + (style&0xFFFF0000)|wxWANTS_CHARS, + name ); + Init2(style); + + return res; +} + +// ----------------------------------------------------------------------- + +// +// Initialize values to defaults +// +void wxPropertyGridManager::Init1() +{ + + //m_pPropGrid = (wxPropertyGrid*) NULL; + m_pPropGrid = CreatePropertyGrid(); + +#if wxUSE_TOOLBAR + m_pToolbar = (wxToolBar*) NULL; +#endif + m_pTxtHelpCaption = (wxStaticText*) NULL; + m_pTxtHelpContent = (wxStaticText*) NULL; + m_pButCompactor = (wxButton*) NULL; + + m_targetState = (wxPropertyGridState*) NULL; + + m_emptyPage = (wxPropertyGridPage*) NULL; + + m_targetPage = 0; + + m_selPage = -1; + + m_width = m_height = 0; + + m_splitterHeight = 5; + + m_splitterY = -1; // -1 causes default to be set. + + m_nextDescBoxSize = -1; + + m_extraHeight = 0; + m_dragStatus = 0; + m_onSplitter = 0; + m_iFlags = 0; +} + +// ----------------------------------------------------------------------- + +// These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager. +#ifndef __WXMAC__ + #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxSIMPLE_BORDER| \ + wxNO_FULL_REPAINT_ON_RESIZE| \ + wxCLIP_CHILDREN) +#else + // Looks better with no border on Mac + #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxNO_BORDER| \ + wxNO_FULL_REPAINT_ON_RESIZE| \ + wxCLIP_CHILDREN) +#endif + +// Which flags can be passed to underlying wxPropertyGrid. +#define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL) + +// +// Initialize after parent etc. set +// +void wxPropertyGridManager::Init2( int style ) +{ + + if ( m_iFlags & wxPG_FL_INITIALIZED ) + return; + + m_windowStyle |= (style&0x0000FFFF); + + wxSize csz = GetClientSize(); + + m_cursorSizeNS = wxCursor(wxCURSOR_SIZENS); + + // Prepare the first page + // NB: But just prepare - you still need to call Add/InsertPage + // to actually add properties on it. + wxPropertyGridPage* pd = new wxPropertyGridPage(); + pd->m_isDefault = true; + wxPropertyGridState* state = pd->GetStatePtr(); + state->m_pPropGrid = m_pPropGrid; + m_arrPages.Add( (void*)pd ); + m_pPropGrid->m_pState = state; + m_targetState = state; + + wxWindowID baseId = GetId(); + wxWindowID useId = baseId; + if ( baseId < 0 ) + baseId = wxPG_MAN_ALTERNATE_BASE_ID; + +#ifdef __WXMAC__ + // Smaller controls on Mac + SetWindowVariant(wxWINDOW_VARIANT_SMALL); +#endif + + // Create propertygrid. + m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz, + (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK) + |wxPG_MAN_PROPGRID_FORCED_FLAGS); + + m_pPropGrid->m_eventObject = this; + + m_pPropGrid->SetId(useId); + + m_pPropGrid->m_iFlags |= wxPG_FL_IN_MANAGER; + + m_pState = m_pPropGrid->m_pState; + + m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT); + + m_nextTbInd = baseId+ID_ADVTBITEMSBASE_OFFSET + 2; + + +#ifndef __WXPYTHON__ + // Connect to property grid onselect event. + // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython + // (see wxPropertyGridManager::ProcessEvent). + Connect(m_pPropGrid->GetId()/*wxID_ANY*/, + wxEVT_PG_SELECTED, + wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect) ); +#endif + + // Connect to compactor button event. + Connect(baseId+ID_ADVBUTTON_OFFSET, + wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxPropertyGridManager::OnCompactorClick) ); + + // Connect to toolbar button events. + Connect(baseId+ID_ADVTBITEMSBASE_OFFSET,baseId+ID_ADVTBITEMSBASE_OFFSET+50, + wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick) ); + + // Optional initial controls. + m_width = -12345; + + m_iFlags |= wxPG_FL_INITIALIZED; + +} + +// ----------------------------------------------------------------------- + +wxPropertyGridManager::~wxPropertyGridManager() +{ + END_MOUSE_CAPTURE + + m_pPropGrid->DoSelectProperty(NULL); + m_pPropGrid->m_pState = NULL; + + size_t i; + for ( i=0; iSetId(winid); +} + +// ----------------------------------------------------------------------- + +wxSize wxPropertyGridManager::DoGetBestSize() const +{ + /* + //wxSize sz = m_pPropGrid->DoGetBestSize(); + wxSize sz(60,m_pPropGrid->m_lineHeight); + wxLogDebug(wxT("m_extraHeight: %i"),m_extraHeight); + sz.y += m_extraHeight; + wxLogDebug(wxT("sz.y: %i"),sz.y); + //CacheBestSize(sz); + return sz; + */ + return wxSize(60,150); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::SetFont( const wxFont& font ) +{ + bool res = wxWindow::SetFont(font); + m_pPropGrid->SetFont(font); + // TODO: Need to do caption recacalculations for other pages as well. + return res; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetExtraStyle( long exStyle ) +{ + wxWindow::SetExtraStyle( exStyle ); + m_pPropGrid->SetExtraStyle( exStyle & 0xFFFFF000 ); +#if wxUSE_TOOLBAR + if ( (exStyle & wxPG_EX_NO_FLAT_TOOLBAR) && m_pToolbar ) + RecreateControls(); +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::Freeze() +{ + m_pPropGrid->Freeze(); + wxWindow::Freeze(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::Thaw() +{ + wxWindow::Thaw(); + m_pPropGrid->Thaw(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetWindowStyleFlag( long style ) +{ + wxWindow::SetWindowStyleFlag( style ); + m_pPropGrid->SetWindowStyleFlag( (m_pPropGrid->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK)) | + (style&wxPG_MAN_PASS_FLAGS_MASK) ); +} + +// ----------------------------------------------------------------------- + +// Actually shows given page. +bool wxPropertyGridManager::DoSelectPage( int index ) +{ + // -1 means no page was selected + //wxASSERT( m_selPage >= 0 ); + + wxCHECK_MSG( index >= -1 && index < (int)GetPageCount(), + false, + wxT("invalid page index") ); + + if ( m_selPage == index ) + return true; + + if ( m_pPropGrid->m_selected ) + { + if ( !m_pPropGrid->ClearSelection() ) + return false; + } + + wxPropertyGridPage* prevPage; + + if ( m_selPage >= 0 ) + prevPage = GetPage(m_selPage); + else + prevPage = m_emptyPage; + + wxPropertyGridPage* nextPage; + + if ( index >= 0 ) + { + nextPage = (wxPropertyGridPage*)m_arrPages.Item(index); + } + else + { + if ( !m_emptyPage ) + m_emptyPage = new wxPropertyGridPage(); + + nextPage = m_emptyPage; + } + + m_iFlags |= wxPG_FL_DESC_REFRESH_REQUIRED; + + m_pPropGrid->SwitchState( nextPage->GetStatePtr() ); + + m_pState = m_pPropGrid->m_pState; + + m_selPage = index; + +#if wxUSE_TOOLBAR + if ( m_pToolbar ) + { + if ( index >= 0 ) + m_pToolbar->ToggleTool( nextPage->m_id, true ); + else + m_pToolbar->ToggleTool( prevPage->m_id, false ); + } +#endif + + return true; +} + +// ----------------------------------------------------------------------- + +// Changes page *and* set the target page for insertion operations. +void wxPropertyGridManager::SelectPage( int index ) +{ + DoSelectPage(index); + if ( index >= 0 ) + SetTargetPage(index); +} + +// ----------------------------------------------------------------------- + +int wxPropertyGridManager::GetPageByName( const wxChar* name ) const +{ + wxASSERT( name ); + + size_t i; + for ( i=0; im_label == name ) + return i; + } + return wxNOT_FOUND; +} + +// ----------------------------------------------------------------------- + +int wxPropertyGridManager::GetPageByState( wxPropertyGridState* pState ) const +{ + wxASSERT( pState ); + + size_t i; + for ( i=0; iGetStatePtr() ) + return i; + } + + return wxNOT_FOUND; +} + +// ----------------------------------------------------------------------- + +const wxString& wxPropertyGridManager::GetPageName( int index ) const +{ + wxASSERT( index >= 0 && index < (int)GetPageCount() ); + return ((wxPropertyGridPage*)m_arrPages.Item(index))->m_label; +} + +// ----------------------------------------------------------------------- + +// Sets page for append, insert, etc. operations. +void wxPropertyGridManager::SetTargetPage( int index ) +{ + wxASSERT( m_selPage >= 0 ); + wxASSERT( index >= 0 ); + wxASSERT( index < (int)GetPageCount() ); + + m_targetPage = index; + m_targetState = ((wxPropertyGridPage*)m_arrPages.Item(index))->GetStatePtr(); + +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::ClearPage( int page ) +{ + wxASSERT( page >= 0 ); + wxASSERT( page < (int)GetPageCount() ); + + if ( page >= 0 && page < (int)GetPageCount() ) + { + wxPropertyGridState* state = GetPageState(page); + + if ( state == m_pPropGrid->GetState() ) + m_pPropGrid->Clear(); + else + state->Clear(); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetPropertyAttributeAll( int attrid, wxVariant value ) +{ + size_t i; + for ( i=0; iGetStatePtr()->m_properties),attrid,value,wxPG_RECURSE); + } +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::Compact( bool compact ) +{ + bool res = m_pPropGrid->Compact(compact); + if ( res ) + { + if ( m_pButCompactor ) + { + if ( compact ) m_pButCompactor->SetLabel(wxT("Expand >>")); + else m_pButCompactor->SetLabel(wxT("<< Compact")); + } + } + return res; +} + +// ----------------------------------------------------------------------- + +size_t wxPropertyGridManager::GetPageCount() const +{ + if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) ) + return 0; + + return m_arrPages.GetCount(); +} + +// ----------------------------------------------------------------------- + +int wxPropertyGridManager::InsertPage( int index, const wxString& label, + const wxBitmap& bmp, wxPropertyGridPage* pageObj ) +{ + if ( index < 0 ) + index = GetPageCount(); + + wxCHECK_MSG( (size_t)index == GetPageCount(), -1, + wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation).")); + + bool needInit = true; + bool isPageInserted = m_iFlags & wxPG_MAN_FL_PAGE_INSERTED ? true : false; + + wxASSERT( index == 0 || isPageInserted ); + + if ( !pageObj ) + { + // No custom page object was given, so we will either re-use the default base + // page (if index==0), or create a new default page object. + if ( !isPageInserted ) + { + pageObj = GetPage(0); + // Of course, if the base page was custom, we need to delete and + // re-create it. + if ( !pageObj->m_isDefault ) + { + delete pageObj; + pageObj = new wxPropertyGridPage(); + m_arrPages[0] = pageObj; + } + needInit = false; + } + else + { + pageObj = new wxPropertyGridPage(); + } + pageObj->m_isDefault = true; + } + else + { + if ( !isPageInserted ) + { + // Initial page needs to be deleted and replaced + delete GetPage(0); + m_arrPages[0] = pageObj; + m_pPropGrid->m_pState = pageObj->GetStatePtr(); + } + } + + wxPropertyGridState* state = pageObj->GetStatePtr(); + + pageObj->m_manager = this; + + if ( needInit ) + { + state->m_pPropGrid = m_pPropGrid; + state->InitNonCatMode(); + } + + pageObj->m_label = label; + pageObj->m_id = m_nextTbInd; + + m_targetState = state; + m_targetPage = index; + + if ( isPageInserted ) + m_arrPages.Add( (void*)pageObj ); + +#if wxUSE_TOOLBAR + if ( m_windowStyle & wxPG_TOOLBAR ) + { + if ( !m_pToolbar ) + RecreateControls(); + + wxASSERT( m_pToolbar ); + + // Add separator before first page. + if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) ) + m_pToolbar->AddSeparator(); + + if ( &bmp != &wxNullBitmap ) + m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO); + //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp); + else + m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap( (const char**)gs_xpm_defpage ), + label,wxITEM_RADIO); + + m_nextTbInd++; + + m_pToolbar->Realize(); + } +#else + wxUnusedVar(bmp); +#endif + + // If selected page was above the point of insertion, fix the current page index + if ( isPageInserted ) + { + if ( m_selPage >= index ) + { + m_selPage += 1; + } + } + else + { + // Set this value only when adding the first page + m_selPage = 0; + } + + pageObj->Init(); + + m_iFlags |= wxPG_MAN_FL_PAGE_INSERTED; + + return index; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::IsAnyModified() const +{ + size_t i; + for ( i=0; iGetStatePtr()->m_anyModified ) + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::IsPageModified( size_t index ) const +{ + if ( ((wxPropertyGridPage*)m_arrPages.Item(index))->GetStatePtr()->m_anyModified ) + return true; + return false; +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridManager::GetPageRoot( int index ) const +{ + wxASSERT( index >= 0 ); + wxASSERT( index < (int)m_arrPages.GetCount() ); + + return ((wxPropertyGridPage*)m_arrPages.Item(index))->GetStatePtr()->m_properties; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::RemovePage( int page ) +{ + wxCHECK_MSG( (page >= 0) && (page < (int)GetPageCount()), + false, + wxT("invalid page index") ); + + wxPropertyGridPage* pd = (wxPropertyGridPage*)m_arrPages.Item(page); + + if ( m_arrPages.GetCount() == 1 ) + { + // Last page: do not remove page entry + m_pPropGrid->Clear(); + m_selPage = -1; + m_iFlags &= ~wxPG_MAN_FL_PAGE_INSERTED; + pd->m_label.clear(); + } + // Change selection if current is page + else if ( page == m_selPage ) + { + if ( !m_pPropGrid->ClearSelection() ) + return false; + + // Substitute page to select + int substitute = page - 1; + if ( substitute < 0 ) + substitute = page + 1; + + SelectPage(substitute); + } + + // Remove toolbar icon +#if wxUSE_TOOLBAR + if ( m_windowStyle & wxPG_TOOLBAR ) + { + wxASSERT( m_pToolbar ); + + int toolPos = GetExtraStyle() & wxPG_EX_MODE_BUTTONS ? 3 : 0; + toolPos += page; + + m_pToolbar->DeleteToolByPos(toolPos); + + // Delete separator as well, for consistency + if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) && + GetPageCount() == 1 ) + m_pToolbar->DeleteToolByPos(2); + } +#endif + + if ( m_arrPages.GetCount() > 1 ) + { + m_arrPages.RemoveAt(page); + delete pd; + } + + // Adjust indexes that were above removed + if ( m_selPage > page ) + m_selPage--; + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::ProcessEvent( wxEvent& event ) +{ + int evtType = event.GetEventType(); + +#ifdef __WXPYTHON__ + // NB: For some reason, under wxPython, Connect in Init doesn't work properly, + // so we'll need to call OnPropertyGridSelect manually. Multiple call's + // don't really matter. + if ( evtType == wxEVT_PG_SELECTED ) + OnPropertyGridSelect((wxPropertyGridEvent&)event); +#endif + + // Property grid events get special attention + if ( evtType >= wxPG_BASE_EVT_TYPE && + evtType < (wxPG_MAX_EVT_TYPE) && + m_selPage >= 0 ) + { + wxPropertyGridPage* page = GetPage(m_selPage); + wxPropertyGridEvent* pgEvent = wxDynamicCast(&event, wxPropertyGridEvent); + + // Add property grid events to appropriate custom pages + // but stop propagating to parent if page says it is + // handling everything. + if ( pgEvent && !page->m_isDefault ) + { + if ( pgEvent->IsPending() ) + page->AddPendingEvent(event); + else + page->ProcessEvent(event); + + if ( page->IsHandlingAllEvents() ) + event.StopPropagation(); + } + } + + return wxPanel::ProcessEvent(event); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::RepaintSplitter( wxDC& dc, int new_splittery, int new_width, + int new_height, bool desc_too ) +{ + int use_hei = new_height; + if ( m_pButCompactor ) + use_hei = m_pButCompactor->GetPosition().y; + + // Draw background + wxColour bgcol = GetBackgroundColour(); + dc.SetBrush( bgcol ); + dc.SetPen( bgcol ); + int rect_hei = use_hei-new_splittery; + if ( !desc_too ) + rect_hei = m_splitterHeight; + dc.DrawRectangle(0,new_splittery,new_width,rect_hei); + dc.SetPen ( wxSystemSettings::GetColour( wxSYS_COLOUR_3DDKSHADOW ) ); + int splitter_bottom = new_splittery+m_splitterHeight - 1; + int box_height = use_hei-splitter_bottom; + if ( box_height > 1 ) + dc.DrawRectangle(0,splitter_bottom,new_width,box_height); + else + dc.DrawLine(0,splitter_bottom,new_width,splitter_bottom); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::RefreshHelpBox( int new_splittery, int new_width, int new_height ) +{ + //if ( new_splittery == m_splitterY && new_width == m_width ) + // return; + + int use_hei = new_height; + if ( m_pButCompactor ) + use_hei = m_pButCompactor->GetPosition().y; + use_hei--; + + //wxRendererNative::Get().DrawSplitterSash(this,dc, + //wxSize(width,m_splitterHeight),new_splittery,wxHORIZONTAL); + + //wxRendererNative::Get().DrawSplitterBorder(this,dc, + // wxRect(0,new_splittery,new_width,m_splitterHeight)); + + // Fix help control positions. + int cap_hei = m_pPropGrid->m_fontHeight; + int cap_y = new_splittery+m_splitterHeight+5; + int cnt_y = cap_y+cap_hei+3; + int sub_cap_hei = cap_y+cap_hei-use_hei; + int cnt_hei = use_hei-cnt_y; + if ( sub_cap_hei > 0 ) + { + cap_hei -= sub_cap_hei; + cnt_hei = 0; + } + if ( cap_hei <= 2 ) + { + m_pTxtHelpCaption->Show( false ); + m_pTxtHelpContent->Show( false ); + } + else + { + m_pTxtHelpCaption->SetSize(3,cap_y,new_width-6,cap_hei); + m_pTxtHelpCaption->Show( true ); + if ( cnt_hei <= 2 ) + { + m_pTxtHelpContent->Show( false ); + } + else + { + m_pTxtHelpContent->SetSize(3,cnt_y,new_width-6,cnt_hei); + m_pTxtHelpContent->Show( true ); + } + } + + wxClientDC dc(this); + RepaintSplitter( dc, new_splittery, new_width, new_height, true ); + + m_splitterY = new_splittery; + + m_iFlags &= ~(wxPG_FL_DESC_REFRESH_REQUIRED); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::RecalculatePositions( int width, int height ) +{ + + int propgridY = 0; + int propgridBottomY = height; + + // Toolbar at the top. +#if wxUSE_TOOLBAR + if ( m_pToolbar ) + { + int tbHeight; + + #if ( wxMINOR_VERSION < 6 || (wxMINOR_VERSION == 6 && wxRELEASE_NUMBER < 2) ) + tbHeight = -1; + #else + // In wxWidgets 2.6.2+, Toolbar default height may be broken + #if defined(__WXMSW__) + tbHeight = 24; + #elif defined(__WXGTK__) + tbHeight = -1; // 22; + #elif defined(__WXMAC__) + tbHeight = 22; + #else + tbHeight = 22; + #endif + #endif + + m_pToolbar->SetSize(0,0,width,tbHeight); + propgridY = m_pToolbar->GetSize().y; + } +#endif + + // Button at the bottom. + if ( m_pButCompactor ) + { + int but_hei = m_pButCompactor->GetSize().y; + m_pButCompactor->SetSize(0,height-but_hei,width,but_hei); + propgridBottomY -= but_hei; + //button_top -= but_hei; + } + + // Help box. + if ( m_pTxtHelpCaption ) + { + int new_splittery = m_splitterY; + + // Move m_splitterY + if ( ( m_splitterY >= 0 || m_nextDescBoxSize ) && m_height > 32 ) + { + if ( m_nextDescBoxSize >= 0 ) + { + new_splittery = m_height - m_nextDescBoxSize - m_splitterHeight; + m_nextDescBoxSize = -1; + } + new_splittery += (height-m_height); + } + else + { + new_splittery = height - wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y; + if ( new_splittery < 32 ) + new_splittery = 32; + } + + // Check if beyond minimum. + int nspy_min = propgridY + m_pPropGrid->m_lineHeight; + if ( new_splittery < nspy_min ) + new_splittery = nspy_min; + + propgridBottomY = new_splittery; + + RefreshHelpBox( new_splittery, width, height ); + } + + if ( m_iFlags & wxPG_FL_INITIALIZED ) + { + int pgh = propgridBottomY - propgridY; + m_pPropGrid->SetSize( 0, propgridY, width, pgh ); + + m_extraHeight = height - pgh; + + m_width = width; + m_height = height; + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh ) +{ + if ( m_windowStyle & wxPG_DESCRIPTION ) + { + m_nextDescBoxSize = ht; + if ( refresh ) + RecalculatePositions(m_width, m_height); + } +} + +// ----------------------------------------------------------------------- + +int wxPropertyGridManager::GetDescBoxHeight() const +{ + return GetClientSize().y - m_splitterY; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) ) +{ + wxPaintDC dc(this); + + // Update everything inside the box + wxRect r = GetUpdateRegion().GetBox(); + + // Repaint splitter? + int r_bottom = r.y + r.height; + int splitter_bottom = m_splitterY + m_splitterHeight; + if ( r.y < splitter_bottom && r_bottom >= m_splitterY ) + RepaintSplitter( dc, m_splitterY, m_width, m_height, false ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect ) +{ + m_pPropGrid->Refresh(eraseBackground); + wxWindow::Refresh(eraseBackground,rect); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::RefreshProperty( wxPGProperty* p ) +{ + wxPropertyGrid* grid = p->GetGrid(); + + if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() ) + grid->RefreshProperty(p); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::RecreateControls() +{ + + bool wasShown = IsShown(); + if ( wasShown ) + Show( false ); + + wxWindowID baseId = m_pPropGrid->GetId(); + if ( baseId < 0 ) + baseId = wxPG_MAN_ALTERNATE_BASE_ID; + +#if wxUSE_TOOLBAR + if ( m_windowStyle & wxPG_TOOLBAR ) + { + // Has toolbar. + if ( !m_pToolbar ) + { + m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET, + wxDefaultPosition,wxDefaultSize, + ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT) + /*| wxTB_HORIZONTAL | wxNO_BORDER*/ ); + + #if defined(__WXMSW__) + // Eliminate toolbar flicker on XP + // NOTE: Not enabled since it corrupts drawing somewhat. + + /* + #ifndef WS_EX_COMPOSITED + #define WS_EX_COMPOSITED 0x02000000L + #endif + + HWND hWnd = (HWND)m_pToolbar->GetHWND(); + + ::SetWindowLong( hWnd, GWL_EXSTYLE, + ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED ); + */ + + #endif + + m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR ); + + if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) ) + { + wxString desc1(_("Categorized Mode")); + wxString desc2(_("Alphabetic Mode")); + m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0, + desc1,wxBitmap ( (const char**)gs_xpm_catmode ), + desc1,wxITEM_RADIO); + m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1, + desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ), + desc2,wxITEM_RADIO); + m_pToolbar->Realize(); + } + + } + + if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) ) + { + // Toggle correct mode button. + // TODO: This doesn't work in wxMSW (when changing, + // both items will get toggled). + int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0; + int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1; + if ( m_pPropGrid->m_pState->IsInNonCatMode() ) + { + toggle_but_on_ind++; + toggle_but_off_ind--; + } + + m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true); + m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false); + } + + } + else + { + // No toolbar. + if ( m_pToolbar ) + m_pToolbar->Destroy(); + m_pToolbar = (wxToolBar*) NULL; + } +#endif + + if ( m_windowStyle & wxPG_COMPACTOR ) + { + // Has button. + if ( !m_pButCompactor ) + { + m_pButCompactor = new wxButton (this,baseId+ID_ADVBUTTON_OFFSET, + !(m_pPropGrid->m_iFlags & wxPG_FL_HIDE_STATE)?_("<< Compact"):_("Expand >>")); + m_pButCompactor->SetCursor ( *wxSTANDARD_CURSOR ); + } + } + else + { + // No button. + if ( m_pButCompactor ) + m_pButCompactor->Destroy(); + m_pButCompactor = (wxButton*) NULL; + } + + if ( m_windowStyle & wxPG_DESCRIPTION ) + { + // Has help box. + m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP); + + if ( !m_pTxtHelpCaption ) + { + m_pTxtHelpCaption = new wxStaticText(this,baseId+ID_ADVHELPCAPTION_OFFSET,wxT("")); + m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont ); + m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR ); + m_pTxtHelpCaption->SetBackgroundColour(GetBackgroundColour()); + } + if ( !m_pTxtHelpContent ) + { + m_pTxtHelpContent = new wxStaticText(this,baseId+ID_ADVHELPCONTENT_OFFSET, + wxT(""),wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT|wxST_NO_AUTORESIZE); + m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR ); + m_pTxtHelpContent->SetBackgroundColour(GetBackgroundColour()); + } + } + else + { + // No help box. + m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP); + + if ( m_pTxtHelpCaption ) + m_pTxtHelpCaption->Destroy(); + + m_pTxtHelpCaption = (wxStaticText*) NULL; + + if ( m_pTxtHelpContent ) + m_pTxtHelpContent->Destroy(); + + m_pTxtHelpContent = (wxStaticText*) NULL; + } + + int width, height; + + GetClientSize(&width,&height); + + RecalculatePositions(width,height); + + if ( wasShown ) + Show( true ); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridManager::DoGetPropertyByName( wxPGPropNameStr name ) const +{ + //return GetPropertyByName2(name, (wxPropertyGridState**)NULL ); + size_t i; + for ( i=0; iGetStatePtr(); + wxPGId id = pState->BaseGetPropertyByName(name); + if ( wxPGIdIsOk(id) ) + { + //if ( ppState ) *ppState = pState; + return id; + } + } + return wxPGIdGen((wxPGProperty*)NULL); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridManager::GetPropertyByLabel( const wxString& label, + wxPropertyGridState** ppState ) const +{ + size_t i; + for ( i=0; iGetStatePtr(); + wxPGId id = pState->GetPropertyByLabel(label); + if ( wxPGIdIsOk(id) ) + { + if ( ppState ) *ppState = pState; + return id; + } + } + return wxPGIdGen((wxPGProperty*)NULL); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::EnsureVisible( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + wxPropertyGridState* parentState = p->GetParentState(); + + // Select correct page. + if ( m_pPropGrid->m_pState != parentState ) + DoSelectPage( GetPageByState(parentState) ); + + return m_pPropGrid->EnsureVisible(id); +} + +// ----------------------------------------------------------------------- + +// TODO: Transfer name-argument methods to class as inlines. + +#define wxPG_IMPLEMENT_PGMAN_METHOD_WRET0(NAME,RETVAL) \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGId id ) \ +{ \ + wxPGProperty* p = wxPGIdToPtr(id); \ + wxASSERT_MSG(p,wxT("invalid property id")); \ + if ( p ) \ + { \ + wxPropertyGridState* pState = p->GetParentState(); \ + wxASSERT( pState != (wxPropertyGridState*) NULL ); \ + if ( pState == m_pPropGrid->m_pState ) return m_pPropGrid->NAME(id); \ + return pState->NAME(p); \ + } \ + return ((RETVAL)0); \ +} \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGPropNameStr name ) \ +{ \ + wxPGId id = GetPropertyByNameI(name); \ + if ( !wxPGIdIsOk(id) ) return ((RETVAL)0); \ + return NAME(id); \ +} + +#define wxPG_IMPLEMENT_PGMAN_METHOD_WRET1(NAME,RETVAL,AT1) \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGId id, AT1 _av1_ ) \ +{ \ + wxPGProperty* p = wxPGIdToPtr(id); \ + wxASSERT_MSG(p,wxT("invalid property id")); \ + if ( p ) \ + { \ + wxPropertyGridState* pState = p->GetParentState(); \ + wxASSERT( pState != (wxPropertyGridState*) NULL ); \ + if ( pState == m_pPropGrid->m_pState ) return m_pPropGrid->NAME(id,_av1_); \ + return pState->NAME(p,_av1_); \ + } \ + return ((RETVAL)0); \ +} \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGPropNameStr name, AT1 _av1_ ) \ +{ \ + wxPGId id = GetPropertyByNameI(name); \ + if ( !wxPGIdIsOk(id) ) return ((RETVAL)0); \ + return NAME(id,_av1_); \ +} + +#define wxPG_IMPLEMENT_PGMAN_METHOD_WRET2(NAME,RETVAL,AT1,AT2) \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGId id, AT1 _av1_, AT2 _av2_ ) \ +{ \ + wxPGProperty* p = wxPGIdToPtr(id); \ + wxASSERT_MSG(p,wxT("invalid property id")); \ + if ( p ) \ + { \ + wxPropertyGridState* pState = p->GetParentState(); \ + wxASSERT( pState != (wxPropertyGridState*) NULL ); \ + if ( pState == m_pPropGrid->m_pState ) return m_pPropGrid->NAME(id,_av1_,_av2_); \ + return pState->NAME(p,_av1_,_av2_); \ + } \ + return ((RETVAL)0); \ +} \ +wxPG_IPAM_DECL RETVAL wxPropertyGridManager::NAME( wxPGPropNameStr name, AT1 _av1_, AT2 _av2_ ) \ +{ \ + wxPGId id = GetPropertyByNameI(name); \ + if ( !wxPGIdIsOk(id) ) return ((RETVAL)0); \ + return NAME(id,_av1_,_av2_); \ +} + +#define wxPG_IMPLEMENT_PGMAN_METHOD_NORET0(NAME) \ +wxPG_IPAM_DECL void wxPropertyGridManager::NAME( wxPGId id ) \ +{ \ + wxPGProperty* p = wxPGIdToPtr(id); \ + wxASSERT_MSG(p,wxT("invalid property id")); \ + if ( p ) \ + { \ + wxPropertyGridState* pState = p->GetParentState(); \ + wxASSERT( pState != (wxPropertyGridState*) NULL ); \ + if ( pState == m_pPropGrid->m_pState ) m_pPropGrid->NAME(id); \ + else pState->NAME(p); \ + } \ +} \ +wxPG_IPAM_DECL void wxPropertyGridManager::NAME( wxPGPropNameStr name ) \ +{ \ + wxPGId id = GetPropertyByNameI(name); \ + if ( !wxPGIdIsOk(id) ) return; \ + NAME(id); \ +} + + +#undef wxPG_IPAM_DECL +#define wxPG_IPAM_DECL + +wxPG_IMPLEMENT_PGMAN_METHOD_WRET0(ClearPropertyValue,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_WRET0(Collapse,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_WRET1(EnableProperty,bool,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_WRET0(Expand,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(LimitPropertyEditing,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyLabel,const wxString&) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueLong,long) +#ifndef __WXPYTHON__ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValue,int) +#endif +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueDouble,double) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueBool,bool) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueString,const wxString&) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueWxObjectPtr,wxObject*) +#ifndef __WXPYTHON__ +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValue,void*) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValue,wxVariant&) +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1(SetPropertyValueArrstr2,const wxArrayString&) +#else +wxPG_IMPLEMENT_PGMAN_METHOD_NORET1_P1(SetPropertyValueArrstr2,const wxArrayString&) +#endif +#ifdef wxPG_COMPATIBILITY_1_0_0 +wxPG_IMPLEMENT_PGMAN_METHOD_NORET0(SetPropertyValueUnspecified) +#else +wxPG_IMPLEMENT_PGMAN_METHOD_NORET0(SetPropertyUnspecified) +#endif + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::ClearModifiedStatus( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + wxPropertyGridState* pState = p->GetParentState(); + wxASSERT ( pState != (wxPropertyGridState*) NULL ); + pState->ClearModifiedStatus(p); +} + +// ----------------------------------------------------------------------- + +size_t wxPropertyGridManager::GetChildrenCount( int page_index ) +{ + return GetChildrenCount( wxPGIdGen(GetPage(page_index)->GetStatePtr()->m_properties) ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event ) +{ + int id = event.GetId(); + if ( id >= 0 ) + { + int baseId = m_pPropGrid->GetId(); + if ( baseId < 0 ) + baseId = wxPG_MAN_ALTERNATE_BASE_ID; + + if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) ) + { + // Categorized mode. + if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES ) + m_pPropGrid->EnableCategories( true ); + } + else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) ) + { + // Alphabetic mode. + if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) ) + m_pPropGrid->EnableCategories( false ); + } + else + { + // Page Switching. + + int index = -1; + size_t i; + wxPropertyGridPage* pdc; + + // Find page with given id. + for ( i=0; im_id == id ) + { + index = i; + break; + } + } + + wxASSERT( index >= 0 ); + + if ( DoSelectPage( index ) ) + { + + // Event dispatching must be last. + m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, (wxPGProperty*) NULL ); + + } + else + { + // TODO: Depress the old button on toolbar. + } + + } + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content ) +{ + if ( m_pTxtHelpCaption ) + { + wxSize osz1 = m_pTxtHelpCaption->GetSize(); + wxSize osz2 = m_pTxtHelpContent->GetSize(); + + m_pTxtHelpCaption->SetLabel(label); + m_pTxtHelpContent->SetLabel(content); + + m_pTxtHelpCaption->SetSize(-1,osz1.y); + m_pTxtHelpContent->SetSize(-1,osz2.y); + + if ( (m_iFlags & wxPG_FL_DESC_REFRESH_REQUIRED) || (osz2.x<(m_width-10)) ) + RefreshHelpBox( m_splitterY, m_width, m_height ); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p ) +{ + if ( m_pTxtHelpCaption ) + { + if ( p ) + { + SetDescription( p->GetLabel(), p->GetHelpString() ); + } + else + { + m_pTxtHelpCaption->SetLabel(wxT("")); + m_pTxtHelpContent->SetLabel(wxT("")); + } + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages ) +{ + if ( !allPages ) + { + m_pPropGrid->SetSplitterLeft(subProps); + } + else + { + wxClientDC dc(this); + dc.SetFont(m_pPropGrid->m_font); + + int highest = 0; + unsigned int i; + + for ( i=0; iGetLeftSplitterPos(dc, GetPageState(i)->m_properties, subProps ); + wxLogDebug(wxT("%i"),maxW); + if ( maxW > highest ) + highest = maxW; + } + + if ( highest > 0 ) + m_pPropGrid->SetSplitterPosition( highest ); + + m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event ) +{ + // Check id. + wxASSERT_MSG( GetId() == m_pPropGrid->GetId(), + wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") ); + + SetDescribedProperty(event.GetPropertyPtr()); + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnCompactorClick( wxCommandEvent& WXUNUSED(event) ) +{ + if ( !(m_pPropGrid->m_iFlags & wxPG_FL_HIDE_STATE) ) + { + m_pPropGrid->Compact( true ); + m_pButCompactor->SetLabel( _("Expand >>") ); + m_pPropGrid->SendEvent( wxEVT_PG_COMPACT_MODE_ENTERED, NULL ); + } + else + { + m_pPropGrid->Compact( false ); + m_pButCompactor->SetLabel( _("<< Compact") ); + m_pPropGrid->SendEvent( wxEVT_PG_EXPANDED_MODE_ENTERED, NULL ); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) ) +{ + int width, height; + + GetClientSize(&width,&height); + + if ( m_width == -12345 ) + RecreateControls(); + + RecalculatePositions(width,height); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) ) +{ + // Correct cursor. This is required atleast for wxGTK, for which + // setting button's cursor to *wxSTANDARD_CURSOR does not work. + SetCursor( wxNullCursor ); + m_onSplitter = 0; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event ) +{ + if ( !m_pTxtHelpCaption ) + return; + + int y = event.m_y; + + if ( m_dragStatus > 0 ) + { + int sy = y - m_dragOffset; + + // Calculate drag limits + int bottom_limit = m_height - m_splitterHeight + 1; + if ( m_pButCompactor ) bottom_limit -= m_pButCompactor->GetSize().y; + int top_limit = m_pPropGrid->m_lineHeight; +#if wxUSE_TOOLBAR + if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y; +#endif + + if ( sy >= top_limit && sy < bottom_limit ) + { + + int change = sy - m_splitterY; + if ( change ) + { + m_splitterY = sy; + + m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y ); + RefreshHelpBox( m_splitterY, m_width, m_height ); + + m_extraHeight -= change; + InvalidateBestSize(); + } + + } + + } + else + { + if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) ) + { + SetCursor ( m_cursorSizeNS ); + m_onSplitter = 1; + } + else + { + if ( m_onSplitter ) + { + SetCursor ( wxNullCursor ); + } + m_onSplitter = 0; + } + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event ) +{ + int y = event.m_y; + + // Click on splitter. + if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) ) + { + if ( m_dragStatus == 0 ) + { + // + // Begin draggin the splitter + // + + BEGIN_MOUSE_CAPTURE + + m_dragStatus = 1; + + m_dragOffset = y - m_splitterY; + + } + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event ) +{ + // No event type check - basicly calling this method should + // just stop dragging. + + if ( m_dragStatus >= 1 ) + { + // + // End Splitter Dragging + // + + int y = event.m_y; + + // DO NOT ENABLE FOLLOWING LINE! + // (it is only here as a reminder to not to do it) + //m_splitterY = y; + + // This is necessary to return cursor + END_MOUSE_CAPTURE + + // Set back the default cursor, if necessary + if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) ) + { + SetCursor ( wxNullCursor ); + } + + m_dragStatus = 0; + } +} + +// ----------------------------------------------------------------------- diff --git a/assdraw/libpropgrid/odcombo.cpp b/assdraw/libpropgrid/odcombo.cpp new file mode 100644 index 000000000..b5afcf104 --- /dev/null +++ b/assdraw/libpropgrid/odcombo.cpp @@ -0,0 +1,3835 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: odcombo.cpp +// Purpose: wxPGOwnerDrawnComboBox and related classes implementation +// Author: Jaakko Salli +// Modified by: +// Created: Jan-25-2005 +// RCS-ID: $Id: +// Copyright: (c) 2005 Jaakko Salli +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "odcombo.h" +#endif + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_COMBOBOX + +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/log.h" + + #include "wx/button.h" + #include "wx/combobox.h" + #include "wx/textctrl.h" + #include "wx/dcclient.h" + #include "wx/settings.h" + #include "wx/dialog.h" + +#endif + +#include "wx/dcbuffer.h" +#include "wx/tooltip.h" +#include "wx/timer.h" + +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) + #include "wx/msw/uxtheme.h" +#endif + +#include "wx/propgrid/odcombo.h" + +// +// THESE GO TO BASE FILE +// + +#define BMP_BUTTON_MARGIN 4 + +//#define DEFAULT_POPUP_HEIGHT -1 +#define DEFAULT_POPUP_HEIGHT 300 + +#define DEFAULT_TEXT_INDENT 3 + + +#if defined(__WXMSW__) + +#define ALLOW_FAKE_POPUP 0 // Use only on plats with problems with wxPopupWindow +#define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) + +//#undef wxUSE_POPUPWIN +//#define wxUSE_POPUPWIN 0 + +#elif defined(__WXGTK__) + +// Fake popup windows cause focus problems on GTK2 (but enable on GTK1.2, just in case) +#if defined(__WXGTK20__) + #define ALLOW_FAKE_POPUP 0 // Use only on plats with problems with wxPopupWindow +#else + #define ALLOW_FAKE_POPUP 1 // Use only on plats with problems with wxPopupWindow +#endif +#define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) + +#elif defined(__WXMAC__) + +#define ALLOW_FAKE_POPUP 1 // Use only on plats with problems with wxPopupWindow +#define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) + +#else + +#define ALLOW_FAKE_POPUP 1 // Use only on plats with problems with wxPopupWindow +#define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) + +#endif + + +// Popupwin is really only supported on wxMSW (not WINCE) and wxGTK, regardless +// what the wxUSE_POPUPWIN says. +#if (!defined(__WXMSW__) && !defined(__WXGTK__)) || defined(__WXWINCE__) +#undef wxUSE_POPUPWIN +#define wxUSE_POPUPWIN 0 +#endif + +#if wxUSE_POPUPWIN + #include "wx/popupwin.h" +#else + #undef USE_TRANSIENT_POPUP + #define USE_TRANSIENT_POPUP 0 +#endif + +// For versions < 2.6.2, don't enable transient popup. There may be +// problems I don't have time to test properly. +#if !wxCHECK_VERSION(2, 6, 2) + #undef USE_TRANSIENT_POPUP + #define USE_TRANSIENT_POPUP 0 +#endif + + +#if USE_TRANSIENT_POPUP + #undef ALLOW_FAKE_POPUP + #define ALLOW_FAKE_POPUP 0 + + #define wxPGComboPopupWindowBase wxPopupTransientWindow + #define INSTALL_TOPLEV_HANDLER 0 + +#elif wxUSE_POPUPWIN + + #define wxPGComboPopupWindowBase wxPopupWindow + #define INSTALL_TOPLEV_HANDLER 1 + +#else + + #define wxPGComboPopupWindowBase wxDialog + #if !ALLOW_FAKE_POPUP + #define INSTALL_TOPLEV_HANDLER 0 // Doesn't need since can monitor active event + #else + #define INSTALL_TOPLEV_HANDLER 1 + #endif + +#endif + + +// +// THESE GO TO GENERIC FILE +// + +// Some adjustments to make the generic more bearable +#if defined(__WXUNIVERSAL__) + +#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent +#define TEXTCTRLYADJUST 0 +#define TEXTXADJUST 0 // how much is read-only text's x adjusted +#define DEFAULT_DROPBUTTON_WIDTH 19 + +#elif defined(__WXMSW__) + +#define TEXTCTRLXADJUST 2 // position adjustment for wxTextCtrl, with zero indent +#define TEXTCTRLYADJUST 3 +#define TEXTXADJUST 0 // how much is read-only text's x adjusted +#define DEFAULT_DROPBUTTON_WIDTH 17 + +#elif defined(__WXGTK__) + +#define TEXTCTRLXADJUST -1 // position adjustment for wxTextCtrl, with zero indent +#define TEXTCTRLYADJUST 0 +#define TEXTXADJUST 1 // how much is read-only text's x adjusted +#define DEFAULT_DROPBUTTON_WIDTH 23 + +#elif defined(__WXMAC__) + +#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent +#define TEXTCTRLYADJUST 0 +#define TEXTXADJUST 0 // how much is read-only text's x adjusted +#define DEFAULT_DROPBUTTON_WIDTH 19 + +#else + +#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent +#define TEXTCTRLYADJUST 0 +#define TEXTXADJUST 0 // how much is read-only text's x adjusted +#define DEFAULT_DROPBUTTON_WIDTH 19 + +#endif + + +// constants +// ---------------------------------------------------------------------------- + +// TO BASE +// the margin between the text control and the combo button +static const wxCoord g_comboMargin = 2; + + +// ---------------------------------------------------------------------------- +// wxPGComboFrameEventHandler takes care of hiding the popup when events happen +// in its top level parent. +// ---------------------------------------------------------------------------- + +#if INSTALL_TOPLEV_HANDLER + +// +// This will no longer be necessary after wxTransientPopupWindow +// works well on all platforms. +// + +class wxPGComboFrameEventHandler : public wxEvtHandler +{ +public: + wxPGComboFrameEventHandler( wxPGComboControlBase* pCb ); + ~wxPGComboFrameEventHandler(); + + void OnPopup(); + + void OnIdle( wxIdleEvent& event ); + void OnMouseEvent( wxMouseEvent& event ); + void OnActivate( wxActivateEvent& event ); + void OnResize( wxSizeEvent& event ); + void OnMove( wxMoveEvent& event ); + void OnMenuEvent( wxMenuEvent& event ); + void OnClose( wxCloseEvent& event ); + +protected: + wxWindow* m_focusStart; + wxPGComboControlBase* m_combo; + +private: + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxPGComboFrameEventHandler, wxEvtHandler) + EVT_IDLE(wxPGComboFrameEventHandler::OnIdle) + EVT_LEFT_DOWN(wxPGComboFrameEventHandler::OnMouseEvent) + EVT_RIGHT_DOWN(wxPGComboFrameEventHandler::OnMouseEvent) + EVT_SIZE(wxPGComboFrameEventHandler::OnResize) + EVT_MOVE(wxPGComboFrameEventHandler::OnMove) + EVT_MENU_HIGHLIGHT(wxID_ANY,wxPGComboFrameEventHandler::OnMenuEvent) + EVT_MENU_OPEN(wxPGComboFrameEventHandler::OnMenuEvent) + EVT_ACTIVATE(wxPGComboFrameEventHandler::OnActivate) + EVT_CLOSE(wxPGComboFrameEventHandler::OnClose) +END_EVENT_TABLE() + +wxPGComboFrameEventHandler::wxPGComboFrameEventHandler( wxPGComboControlBase* combo ) + : wxEvtHandler() +{ + m_combo = combo; +} + +wxPGComboFrameEventHandler::~wxPGComboFrameEventHandler() +{ +} + +void wxPGComboFrameEventHandler::OnPopup() +{ + m_focusStart = ::wxWindow::FindFocus(); +} + +void wxPGComboFrameEventHandler::OnIdle( wxIdleEvent& event ) +{ + wxWindow* winFocused = ::wxWindow::FindFocus(); + + wxWindow* popup = m_combo->GetPopupControl(); + wxWindow* winpopup = m_combo->GetPopupWindow(); + + if ( + winFocused != m_focusStart && + winFocused != popup && + winFocused->GetParent() != popup && + winFocused != winpopup && + winFocused->GetParent() != winpopup && + winFocused != m_combo && + winFocused != m_combo->GetButton() // GTK (atleast) requires this + ) + { + m_combo->HidePopup(); + } + + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnMenuEvent( wxMenuEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnMouseEvent( wxMouseEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnClose( wxCloseEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnActivate( wxActivateEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnResize( wxSizeEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +void wxPGComboFrameEventHandler::OnMove( wxMoveEvent& event ) +{ + m_combo->HidePopup(); + event.Skip(); +} + +#endif // INSTALL_TOPLEV_HANDLER + +// ---------------------------------------------------------------------------- +// wxPGComboPopupWindow is wxPopupWindow customized for +// wxComboControl. +// ---------------------------------------------------------------------------- + +class wxPGComboPopupWindow : public wxPGComboPopupWindowBase +{ +public: + + wxPGComboPopupWindow( wxPGComboControlBase *parent, int style = wxBORDER_NONE ); + +#if USE_TRANSIENT_POPUP + virtual bool ProcessLeftDown(wxMouseEvent& event); +#endif + + void OnKeyEvent(wxKeyEvent& event); + + void OnMouseEvent( wxMouseEvent& event ); +#if !wxUSE_POPUPWIN + void OnActivate( wxActivateEvent& event ); +#endif + +protected: + +#if USE_TRANSIENT_POPUP + virtual void OnDismiss(); +#endif + +private: + DECLARE_EVENT_TABLE() +}; + + +BEGIN_EVENT_TABLE(wxPGComboPopupWindow, wxPGComboPopupWindowBase) + EVT_MOUSE_EVENTS(wxPGComboPopupWindow::OnMouseEvent) +#if !wxUSE_POPUPWIN + EVT_ACTIVATE(wxPGComboPopupWindow::OnActivate) +#endif + EVT_KEY_DOWN(wxPGComboPopupWindow::OnKeyEvent) + EVT_KEY_UP(wxPGComboPopupWindow::OnKeyEvent) +END_EVENT_TABLE() + + +wxPGComboPopupWindow::wxPGComboPopupWindow( wxPGComboControlBase *parent, + int style ) +#if wxUSE_POPUPWIN + : wxPGComboPopupWindowBase(parent,style) +#else + : wxPGComboPopupWindowBase(parent, + wxID_ANY, + wxEmptyString, + wxPoint(-21,-21), + wxSize(20,20), + style) +#endif +{ +} + +void wxPGComboPopupWindow::OnKeyEvent( wxKeyEvent& event ) +{ + // Relay keyboard event to the main child controls + // (just skipping may just cause the popup to close) + wxWindowList children = GetChildren(); + wxWindowList::iterator node = children.begin(); + wxWindow* child = (wxWindow*)*node; + child->AddPendingEvent(event); +} + +void wxPGComboPopupWindow::OnMouseEvent( wxMouseEvent& event ) +{ + event.Skip(); +} + +#if !wxUSE_POPUPWIN +void wxPGComboPopupWindow::OnActivate( wxActivateEvent& event ) +{ + if ( !event.GetActive() ) + { + // Tell combo control that we are dismissed. + wxPGComboControl* combo = (wxPGComboControl*) GetParent(); + wxASSERT( combo ); + wxASSERT( combo->IsKindOf(CLASSINFO(wxPGComboControl)) ); + + combo->HidePopup(); + + event.Skip(); + } +} +#endif + +#if USE_TRANSIENT_POPUP +bool wxPGComboPopupWindow::ProcessLeftDown(wxMouseEvent& event ) +{ + return wxPGComboPopupWindowBase::ProcessLeftDown(event); +} +#endif + +#if USE_TRANSIENT_POPUP +// First thing that happens when a transient popup closes is that this method gets called. +void wxPGComboPopupWindow::OnDismiss() +{ + wxPGComboControlBase* combo = (wxPGComboControlBase*) GetParent(); + wxASSERT ( combo->IsKindOf(CLASSINFO(wxPGComboControlBase)) ); + + combo->OnPopupDismiss(); +} +#endif + +// ---------------------------------------------------------------------------- +// wxPGComboPopup methods +// +// ---------------------------------------------------------------------------- + +wxPGComboPopup::~wxPGComboPopup() +{ +} + +void wxPGComboPopup::OnPopup() +{ +} + +void wxPGComboPopup::OnDismiss() +{ +} + +wxSize wxPGComboPopup::GetAdjustedSize( int minWidth, + int prefHeight, + int WXUNUSED(maxHeight) ) +{ + return wxSize(minWidth,prefHeight); +} + +void wxPGComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) +{ + if ( m_combo->GetWindowStyle() & wxCB_READONLY ) // ie. no textctrl + { + m_combo->DrawFocusBackground(dc,rect,0); + + dc.DrawText( GetStringValue(), + rect.x + m_combo->GetTextIndent(), + (rect.height-dc.GetCharHeight())/2 + m_combo->m_widthCustomBorder ); + } +} + +void wxPGComboPopup::OnComboKeyEvent( wxKeyEvent& event ) +{ + event.Skip(); +} + +void wxPGComboPopup::OnComboDoubleClick() +{ +} + +void wxPGComboPopup::SetStringValue( const wxString& WXUNUSED(value) ) +{ +} + +bool wxPGComboPopup::LazyCreate() +{ + return false; +} + +void wxPGComboPopup::Dismiss() +{ + m_combo->HidePopup(); +} + +// ---------------------------------------------------------------------------- +// wxPGVListBoxComboPopup is a wxVListBox customized to act as a popup control +// +// ---------------------------------------------------------------------------- + + +BEGIN_EVENT_TABLE(wxPGVListBoxComboPopup, wxVListBox) + EVT_MOTION(wxPGVListBoxComboPopup::OnMouseMove) + EVT_KEY_DOWN(wxPGVListBoxComboPopup::OnKey) + EVT_LEFT_UP(wxPGVListBoxComboPopup::OnLeftClick) +END_EVENT_TABLE() + + +wxPGVListBoxComboPopup::wxPGVListBoxComboPopup(wxPGComboControl* combo) + : wxVListBox(), wxPGComboPopup(combo) +{ + //m_callback = callback; + m_widestWidth = 0; + m_avgCharWidth = 0; + m_baseImageWidth = 0; + m_itemHeight = 0; + m_value = -1; + m_itemHover = -1; + m_clientDataItemsType = wxClientData_None; +} + +bool wxPGVListBoxComboPopup::Create(wxWindow* parent) +{ + if ( !wxVListBox::Create(parent, + wxID_ANY, + wxDefaultPosition, + wxDefaultSize, + wxBORDER_SIMPLE | wxLB_INT_HEIGHT | wxWANTS_CHARS) ) + return false; + + m_font = m_combo->GetFont(); + + wxVListBox::SetItemCount(m_strings.GetCount()); + + // TODO: Move this to SetFont + m_itemHeight = GetCharHeight() + 0; + + return true; +} + +wxPGVListBoxComboPopup::~wxPGVListBoxComboPopup() +{ + Clear(); +} + +bool wxPGVListBoxComboPopup::LazyCreate() +{ + // NB: There is a bug with wxVListBox that can be avoided by creating + // it later (bug causes empty space to be shown if initial selection + // is at the end of a list longer than the control can show at once). + return true; +} + +// paint the control itself +void wxPGVListBoxComboPopup::PaintComboControl( wxDC& dc, const wxRect& rect ) +{ + if ( !(m_combo->GetWindowStyle() & wxODCB_STD_CONTROL_PAINT) ) + { + m_combo->DrawFocusBackground(dc,rect,0); + if ( m_combo->OnDrawListItem(dc,rect,m_value,wxPGCC_PAINTING_CONTROL) ) + return; + } + + wxPGComboPopup::PaintComboControl(dc,rect); +} + +void wxPGVListBoxComboPopup::OnDrawItem( wxDC& dc, const wxRect& rect, size_t n) const +{ + dc.SetFont(m_font); + + bool isHilited = wxVListBox::GetSelection() == (int) n; + + // Set correct text colour for selected items + // (must always set the correct colour - atleast GTK may have lost it + // in between calls). + if ( isHilited ) + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); + else + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); + + if ( !m_combo->OnDrawListItem(dc,rect,(int)n,0) ) + dc.DrawText( GetString(n), rect.x + 2, rect.y ); +} + +wxCoord wxPGVListBoxComboPopup::OnMeasureItem(size_t n) const +{ + int itemHeight = m_combo->OnMeasureListItem(n); + if ( itemHeight < 0 ) + itemHeight = m_itemHeight; + + return itemHeight; +} + +void wxPGVListBoxComboPopup::OnDrawBackground(wxDC& dc, const wxRect& rect, size_t n) const +{ + // we need to render selected and current items differently + if ( IsCurrent(n) ) + { + m_combo->DrawFocusBackground( dc, rect, wxCONTROL_ISSUBMENU|wxCONTROL_SELECTED ); + } + //else: do nothing for the normal items +} + +void wxPGVListBoxComboPopup::DismissWithEvent() +{ + int selection = wxVListBox::GetSelection(); + + Dismiss(); + + if ( selection != wxNOT_FOUND ) + m_stringValue = m_strings[selection]; + else + m_stringValue = wxEmptyString; + + if ( m_stringValue != m_combo->GetValue() ) + m_combo->SetValue(m_stringValue); + + m_value = selection; + + SendComboBoxEvent(selection); +} + +void wxPGVListBoxComboPopup::SendComboBoxEvent( int selection ) +{ + wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED,m_combo->GetId()); + + evt.SetEventObject(m_combo); + + evt.SetInt(selection); + + // Set client data, if any + if ( selection >= 0 && (int)m_clientDatas.GetCount() > selection ) + { + void* clientData = m_clientDatas[selection]; + if ( m_clientDataItemsType == wxClientData_Object ) + evt.SetClientObject((wxClientData*)clientData); + else + evt.SetClientData(clientData); + } + + m_combo->GetEventHandler()->AddPendingEvent(evt); +} + +// returns true if key was consumed +bool wxPGVListBoxComboPopup::HandleKey( int keycode, bool saturate ) +{ + int value = m_value; + int itemCount = GetCount(); + + if ( keycode == WXK_DOWN || keycode == WXK_RIGHT ) + { + value++; + } + else if ( keycode == WXK_UP || keycode == WXK_LEFT ) + { + value--; + } + else if ( keycode == WXK_PAGEDOWN ) + { + value+=10; + } + else if ( keycode == WXK_PAGEUP ) + { + value-=10; + } + /* + else if ( keycode == WXK_END ) + { + value = itemCount-1; + } + else if ( keycode == WXK_HOME ) + { + value = 0; + } + */ + else + return false; + + if ( saturate ) + { + if ( value >= itemCount ) + value = itemCount - 1; + else if ( value < 0 ) + value = 0; + } + else + { + if ( value >= itemCount ) + value -= itemCount; + else if ( value < 0 ) + value += itemCount; + } + + if ( value == m_value ) + // Even if value was same, don't skip the event + // (good for consistency) + return true; + + m_value = value; + + wxString valStr; + if ( value >= 0 ) + m_combo->SetValue(m_strings[value]); + + SendComboBoxEvent(m_value); + + return true; +} + +void wxPGVListBoxComboPopup::OnComboDoubleClick() +{ + // Cycle on dclick (disable saturation to allow true cycling). + if ( !::wxGetKeyState(WXK_SHIFT) ) + HandleKey(WXK_DOWN,false); + else + HandleKey(WXK_UP,false); +} + +void wxPGVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent& event ) +{ + // Saturated key movement on + if ( !HandleKey(event.GetKeyCode(),true) ) + event.Skip(); +} + +void wxPGVListBoxComboPopup::OnPopup() +{ + // *must* set value after size is set (this is because of a vlbox bug) + wxVListBox::SetSelection(m_value); +} + +void wxPGVListBoxComboPopup::OnMouseMove(wxMouseEvent& event) +{ + // Move selection to cursor if it is inside the popup + int itemHere = GetItemAtPosition(event.GetPosition()); + if ( itemHere >= 0 ) + wxVListBox::SetSelection(itemHere); + + event.Skip(); +} + +void wxPGVListBoxComboPopup::OnLeftClick(wxMouseEvent& WXUNUSED(event)) +{ + DismissWithEvent(); +} + +void wxPGVListBoxComboPopup::OnKey(wxKeyEvent& event) +{ + // Select item if ENTER is pressed + if ( event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER ) + { + DismissWithEvent(); + } + // Hide popup if ESC is pressed + else if ( event.GetKeyCode() == WXK_ESCAPE ) + Dismiss(); + else + event.Skip(); +} + +void wxPGVListBoxComboPopup::CheckWidth( int pos ) +{ + wxCoord x = m_combo->OnMeasureListItemWidth(pos); + + if ( x < 0 ) + { + if ( !m_font.Ok() ) + m_font = m_combo->GetFont(); + + wxCoord y; + m_combo->GetTextExtent(m_strings[pos], &x, &y, 0, 0, &m_font); + x += 4; + } + + if ( m_widestWidth < x ) + { + m_widestWidth = x; + } +} + +void wxPGVListBoxComboPopup::Insert( const wxString& item, int pos ) +{ + // Need to change selection? + wxString strValue; + if ( !(m_combo->GetWindowStyle() & wxCB_READONLY) && + m_combo->GetValue() == item ) + m_value = pos; + else if ( m_value >= pos ) + m_value++; + + m_strings.Insert(item,pos); + + if ( IsCreated() ) + wxVListBox::SetItemCount( wxVListBox::GetItemCount()+1 ); + + // Calculate width + CheckWidth(pos); +} + +int wxPGVListBoxComboPopup::Append(const wxString& item) +{ + int pos = (int)m_strings.GetCount(); + + if ( m_combo->GetWindowStyle() & wxCB_SORT ) + { + // Find position + // TODO: Could be optimized with binary search + wxArrayString strings = m_strings; + unsigned int i; + + for ( i=0; i n ) + return m_clientDatas[n]; + + return NULL; +} + +void wxPGVListBoxComboPopup::Delete( wxODCIndex item ) +{ + // Remove client data, if set + if ( m_clientDatas.GetCount() ) + { + if ( m_clientDataItemsType == wxClientData_Object ) + delete (wxClientData*) m_clientDatas[item]; + + m_clientDatas.RemoveAt(item); + } + + m_strings.RemoveAt(item); + + int sel = GetSelection(); + + if ( IsCreated() ) + wxVListBox::SetItemCount( wxVListBox::GetItemCount()-1 ); + + if ( (int)item < sel ) + SetSelection(sel-1); + else if ( (int)item == sel ) + SetSelection(wxNOT_FOUND); +} + +int wxPGVListBoxComboPopup::FindString(const wxString& s) const +{ + return m_strings.Index(s); +} + +wxODCCount wxPGVListBoxComboPopup::GetCount() const +{ + return m_strings.GetCount(); +} + +wxString wxPGVListBoxComboPopup::GetString( int item ) const +{ + return m_strings[item]; +} + +void wxPGVListBoxComboPopup::SetString( int item, const wxString& str ) +{ + m_strings[item] = str; +} + +wxString wxPGVListBoxComboPopup::GetStringValue() const +{ + return m_stringValue; +} + +void wxPGVListBoxComboPopup::SetSelection( int item ) +{ + // This seems to be necessary (2.5.3 w/ MingW atleast) + if ( item < -1 || item >= (int)m_strings.GetCount() ) + item = -1; + + m_value = item; + if ( item >= 0 ) + m_stringValue = m_strings[item]; + else + m_stringValue = wxEmptyString; + + if ( IsCreated() ) + wxVListBox::SetSelection(item); +} + +int wxPGVListBoxComboPopup::GetSelection() const +{ + return m_value; +} + +void wxPGVListBoxComboPopup::SetStringValue( const wxString& value ) +{ + int index = m_strings.Index(value); + + m_stringValue = value; + + if ( index >= 0 && index < (int)wxVListBox::GetItemCount() ) + { + wxVListBox::SetSelection(index); + m_value = index; + } +} + +wxSize wxPGVListBoxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int maxHeight ) +{ + int height = 250; + + if ( m_strings.GetCount() ) + { + if ( prefHeight > 0 ) + height = prefHeight; + + if ( height > maxHeight ) + height = maxHeight; + + int totalHeight = GetTotalHeight(); // + 3; + if ( height >= totalHeight ) + { + height = totalHeight; + } + else + { + // Adjust height to a multiple of the height of the first item + // NB: Calculations that take variable height into account + // are unnecessary. + int fih = GetLineHeight(0); + int shown = height/fih; + height = shown * fih; + } + } + else + height = 50; + +#if defined(__WXMAC__) + // Set a minimum height since otherwise scrollbars won't draw properly + height = wxMax(50, height); +#endif + + // Take scrollbar into account in width calculations + int widestWidth = m_widestWidth + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X); + return wxSize(minWidth > widestWidth ? minWidth : widestWidth, + height+2); +} + +void wxPGVListBoxComboPopup::Populate( int n, const wxString choices[] ) +{ + int i; + + for ( i=0; iGetWindowStyle() & wxCB_SORT ) + m_strings.Sort(); + + // Find initial selection + wxString strValue = m_combo->GetValue(); + if ( strValue.Length() ) + m_value = m_strings.Index(strValue); +} + +// ---------------------------------------------------------------------------- +// input handling +// ---------------------------------------------------------------------------- + +// +// This is pushed to the event handler queue of either combo box +// or its textctrl (latter if not readonly combo). +// +class wxPGComboBoxTextCtrlHandler : public wxEvtHandler +{ +public: + + wxPGComboBoxTextCtrlHandler( wxPGComboControlBase* combo ) + : wxEvtHandler() + { + m_combo = combo; + } + ~wxPGComboBoxTextCtrlHandler() { } + void OnKey(wxKeyEvent& event); + void OnFocus(wxFocusEvent& event); + +protected: + wxPGComboControlBase* m_combo; + +private: + DECLARE_EVENT_TABLE() +}; + + +BEGIN_EVENT_TABLE(wxPGComboBoxTextCtrlHandler, wxEvtHandler) + EVT_KEY_DOWN(wxPGComboBoxTextCtrlHandler::OnKey) + EVT_SET_FOCUS(wxPGComboBoxTextCtrlHandler::OnFocus) +END_EVENT_TABLE() + + +void wxPGComboBoxTextCtrlHandler::OnKey(wxKeyEvent& event) +{ + // Let the wxComboCtrl event handler have a go first. + wxPGComboControlBase* combo = m_combo; + wxObject* prevObj = event.GetEventObject(); + + event.SetId(combo->GetId()); + event.SetEventObject(combo); + combo->GetEventHandler()->ProcessEvent(event); + + event.SetId(((wxWindow*)prevObj)->GetId()); + event.SetEventObject(prevObj); +} + +void wxPGComboBoxTextCtrlHandler::OnFocus(wxFocusEvent& event) +{ + // FIXME: This code does run when control is clicked, + // yet on Windows it doesn't select all the text. + if ( !(m_combo->GetInternalFlags() & wxPGCC_NO_TEXT_AUTO_SELECT) ) + { + if ( m_combo->GetTextCtrl() ) + m_combo->GetTextCtrl()->SelectAll(); + else + m_combo->SetSelection(-1,-1); + } + + // Send focus indication to parent. + // NB: This is needed for cases where the textctrl gets focus + // instead of its parent. We'll check if the focus came from + // in order to prevent a possible infinite recursion. + if ( m_combo->ConsumingTextCtrlFocusEvent() ) + { + wxFocusEvent evt2(wxEVT_SET_FOCUS,m_combo->GetId()); + evt2.SetEventObject(m_combo); + m_combo->GetEventHandler()->ProcessEvent(evt2); + } + + event.Skip(); +} + + +// +// This is pushed to the event handler queue of the control in popup. +// + +class wxPGComboPopupExtraEventHandler : public wxEvtHandler +{ +public: + + wxPGComboPopupExtraEventHandler( wxPGComboControlBase* combo ) + : wxEvtHandler() + { + m_combo = combo; + m_beenInside = false; + } + ~wxPGComboPopupExtraEventHandler() { } + + void OnMouseEvent( wxMouseEvent& event ); + + // Called from wxPGComboControlBase::OnPopupDismiss + void OnPopupDismiss() + { + m_beenInside = false; + } + +protected: + wxPGComboControlBase* m_combo; + + bool m_beenInside; + +private: + DECLARE_EVENT_TABLE() +}; + + +BEGIN_EVENT_TABLE(wxPGComboPopupExtraEventHandler, wxEvtHandler) + EVT_MOUSE_EVENTS(wxPGComboPopupExtraEventHandler::OnMouseEvent) +END_EVENT_TABLE() + + +void wxPGComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event ) +{ + wxPoint pt = event.GetPosition(); + wxSize sz = m_combo->GetPopupControl()->GetClientSize(); + int evtType = event.GetEventType(); + bool isInside = pt.x >= 0 && pt.y >= 0 && pt.x < sz.x && pt.y < sz.y; + + if ( evtType == wxEVT_MOTION || + evtType == wxEVT_LEFT_DOWN || + evtType == wxEVT_RIGHT_DOWN ) + { + // Block motion and click events outside the popup + if ( !isInside ) + { + event.Skip(false); + return; + } + } + else if ( evtType == wxEVT_LEFT_UP ) + { + // Don't let left-down events in if outside + if ( evtType == wxEVT_LEFT_DOWN ) + { + if ( !isInside ) + return; + } + + if ( !m_beenInside ) + { + if ( isInside ) + { + m_beenInside = true; + } + else + { + // + // Some mouse events to popup that happen outside it, before cursor + // has been inside the popu, need to be ignored by it but relayed to + // the dropbutton. + // + wxWindow* btn = m_combo->GetButton(); + if ( btn ) + btn->GetEventHandler()->AddPendingEvent(event); + else + m_combo->GetEventHandler()->AddPendingEvent(event); + + return; + } + + event.Skip(); + } + } + + event.Skip(); +} + +// ---------------------------------------------------------------------------- +// wxPGComboControlBase +// ---------------------------------------------------------------------------- + + +BEGIN_EVENT_TABLE(wxPGComboControlBase, wxControl) + EVT_TEXT(wxID_ANY,wxPGComboControlBase::OnTextCtrlEvent) + EVT_SIZE(wxPGComboControlBase::OnSizeEvent) + EVT_KEY_DOWN(wxPGComboControlBase::OnKeyEvent) + EVT_SET_FOCUS(wxPGComboControlBase::OnFocusEvent) + EVT_KILL_FOCUS(wxPGComboControlBase::OnFocusEvent) + //EVT_BUTTON(wxID_ANY,wxPGComboControlBase::OnButtonClickEvent) + EVT_TEXT_ENTER(wxID_ANY,wxPGComboControlBase::OnTextCtrlEvent) + EVT_SYS_COLOUR_CHANGED(wxPGComboControlBase::OnSysColourChanged) +END_EVENT_TABLE() + + +IMPLEMENT_ABSTRACT_CLASS(wxPGComboControlBase, wxControl) + +// Have global double buffer - should be enough for multiple combos +static wxBitmap* gs_doubleBuffer = (wxBitmap*) NULL; + +void wxPGComboControlBase::Init() +{ + m_winPopup = (wxWindow *)NULL; + m_popup = (wxWindow *)NULL; + m_isPopupShown = false; + m_btn = (wxWindow*) NULL; + m_text = (wxTextCtrl*) NULL; + m_popupInterface = (wxPGComboPopup*) NULL; + + m_popupExtraHandler = (wxEvtHandler*) NULL; + m_textEvtHandler = (wxEvtHandler*) NULL; + +#if INSTALL_TOPLEV_HANDLER + m_toplevEvtHandler = (wxEvtHandler*) NULL; +#endif + + m_heightPopup = -1; + + m_widthMinPopup = -1; + + m_widthCustomPaint = 0; + + m_widthCustomBorder = 0; + + m_btnState = 0; + + m_btnWidDefault = 0; + + m_blankButtonBg = false; + + m_btnWid = m_btnHei = 0; + m_btnSide = wxRIGHT; + m_btnSpacingX = 0; + + m_extLeft = 0; + m_extRight = 0; + + m_absIndent = -1; + + m_iFlags = 0; + + m_fakePopupUsage = 0; + m_skipTextCtrlFocusEvents = 0; + + m_timeCanAcceptClick = 0; +} + +bool wxPGComboControlBase::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + if ( !wxControl::Create(parent, + id, + pos, + size, + style | wxWANTS_CHARS, + validator, + name) ) + return false; + + m_valueString = value; + + // Get colours + OnThemeChange(); + m_absIndent = GetNativeTextIndent(); + + return true; +} + +void wxPGComboControlBase::InstallInputHandlers() +{ + if ( m_text ) + { + m_textEvtHandler = new wxPGComboBoxTextCtrlHandler(this); + m_text->PushEventHandler(m_textEvtHandler); + } +} + +void wxPGComboControlBase::CreateTextCtrl( int extraStyle, const wxValidator& validator ) +{ + if ( !(m_windowStyle & wxCB_READONLY) ) + { + m_text = new wxTextCtrl(this, + 12345, + m_valueString, + wxDefaultPosition, + wxDefaultSize, + // wxTE_PROCESS_TAB is needed because on Windows, wxTAB_TRAVERSAL is + // not used by the wxPropertyGrid and therefore the tab is + // processed by looking at ancestors to see if they have + // wxTAB_TRAVERSAL. The navigation event is then sent to + // the wrong window. + wxTE_PROCESS_TAB | + wxTE_PROCESS_ENTER | + //wxWANTS_CHARS | + extraStyle, + validator); + + #if defined(__WXMSW__) && !defined(__WXWINCE__) + ::SendMessage(GetHwndOf(m_text), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); + #endif + + // This is required for some platforms (GTK+ atleast) + m_text->SetSizeHints(2,4); + } +} + +void wxPGComboControlBase::OnThemeChange() +{ + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +} + +bool wxPGComboControlBase::Destroy() +{ + return wxControl::Destroy(); +} + +wxPGComboControlBase::~wxPGComboControlBase() +{ + if ( HasCapture() ) + ReleaseMouse(); + + HidePopup(); + + delete gs_doubleBuffer; + gs_doubleBuffer = (wxBitmap*) NULL; + +#if INSTALL_TOPLEV_HANDLER + delete ((wxPGComboFrameEventHandler*)m_toplevEvtHandler); + m_toplevEvtHandler = (wxEvtHandler*) NULL; +#endif + + if ( m_popup ) + m_popup->RemoveEventHandler(m_popupExtraHandler); + + delete m_popupExtraHandler; + + delete m_popupInterface; + delete m_winPopup; + + if ( m_text ) + m_text->RemoveEventHandler(m_textEvtHandler); + + delete m_textEvtHandler; +} + + +// ---------------------------------------------------------------------------- +// geometry stuff +// ---------------------------------------------------------------------------- + +// Recalculates button and textctrl areas +void wxPGComboControlBase::CalculateAreas( int btnWidth ) +{ + wxSize sz = GetClientSize(); + int customBorder = m_widthCustomBorder; + bool buttonOutside; + int btnBorder; // border for button only + + if ( ( (m_iFlags & wxPGCC_BUTTON_OUTSIDE_BORDER) || m_blankButtonBg ) && + m_btnSpacingX == 0 && m_btnWid == 0 && m_btnHei == 0 && + (!m_bmpNormal.Ok() || m_blankButtonBg) ) + { + buttonOutside = true; + m_iFlags |= wxPGCC_IFLAG_BUTTON_OUTSIDE; + btnBorder = 0; + } + else + { + buttonOutside = false; + m_iFlags &= ~(wxPGCC_IFLAG_BUTTON_OUTSIDE); + btnBorder = customBorder; + } + + // Defaul indentation + if ( m_absIndent < 0 ) + m_absIndent = GetNativeTextIndent(); + + int butWidth = btnWidth; + + if ( butWidth <= 0 ) + butWidth = m_btnWidDefault; + else + m_btnWidDefault = butWidth; + + if ( butWidth <= 0 ) + return; + + // Adjust button width + if ( m_btnWid < 0 ) + butWidth += m_btnWid; + else if ( m_btnWid > 0 ) + butWidth = m_btnWid; + + int butHeight = sz.y; + + butHeight -= btnBorder*2; + + // Adjust button height + if ( m_btnHei < 0 ) + butHeight += m_btnHei; + else if ( m_btnHei > 0 ) + butHeight = m_btnHei; + + // Use size of normal bitmap if... + // It is larger + // OR + // button width is set to default and blank button bg is not drawn + if ( m_bmpNormal.Ok() ) + { + int bmpReqWidth = m_bmpNormal.GetWidth(); + int bmpReqHeight = m_bmpNormal.GetHeight(); + + // If drawing blank button background, we need to add some margin. + if ( m_blankButtonBg ) + { + bmpReqWidth += BMP_BUTTON_MARGIN*2; + bmpReqHeight += BMP_BUTTON_MARGIN*2; + } + + if ( butWidth < bmpReqWidth || ( m_btnWid == 0 && !m_blankButtonBg ) ) + butWidth = bmpReqWidth; + if ( butHeight < bmpReqHeight || ( m_btnHei == 0 && !m_blankButtonBg ) ) + butHeight = bmpReqHeight; + + // Need to fix height? + if ( (sz.y-(customBorder*2)) < butHeight && btnWidth == 0 ) + { + int newY = butHeight+(customBorder*2); + SetClientSize(-1,newY); + sz.y = newY; + } + } + + int butAreaWid = butWidth + (m_btnSpacingX*2); + + m_btnSize.x = butWidth; + m_btnSize.y = butHeight; + + m_btnArea.x = ( m_btnSide==wxRIGHT ? sz.x - butAreaWid - btnBorder : btnBorder ); + m_btnArea.y = btnBorder; + m_btnArea.width = butAreaWid; + m_btnArea.height = sz.y - (btnBorder*2); + + if ( m_bmpNormal.Ok() || m_btnArea.width != butWidth || m_btnArea.height != butHeight ) + m_iFlags |= wxPGCC_IFLAG_HAS_NONSTANDARD_BUTTON; + else + m_iFlags &= ~wxPGCC_IFLAG_HAS_NONSTANDARD_BUTTON; + + m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + customBorder; + m_tcArea.y = customBorder; + m_tcArea.width = sz.x - butAreaWid - (customBorder*2); + m_tcArea.height = sz.y - (customBorder*2); + +/* + if ( m_text ) + { + ::wxMessageBox(wxString::Format(wxT("ButtonArea (%i,%i,%i,%i)\n"),m_btnArea.x,m_btnArea.y,m_btnArea.width,m_btnArea.height) + + wxString::Format(wxT("TextCtrlArea (%i,%i,%i,%i)"),m_tcArea.x,m_tcArea.y,m_tcArea.width,m_tcArea.height)); + } +*/ +} + +void wxPGComboControlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust ) +{ + if ( !m_text ) + return; + + wxSize sz = GetClientSize(); + int customBorder = m_widthCustomBorder; + + if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER ) + { + // Centre textctrl + int tcSizeY = m_text->GetBestSize().y; + int diff = sz.y - tcSizeY; + int y = textCtrlYAdjust + (diff/2); + + if ( y < customBorder ) + y = customBorder; + + m_text->SetSize( m_tcArea.x + m_widthCustomPaint + m_absIndent + textCtrlXAdjust, + y, + m_tcArea.width - g_comboMargin - + (textCtrlXAdjust + m_widthCustomPaint + m_absIndent), + -1 ); + + // Make sure textctrl doesn't exceed the bottom custom border + wxSize tsz = m_text->GetSize(); + diff = (y + tsz.y) - (sz.y - customBorder); + if ( diff >= 0 ) + { + tsz.y = tsz.y - diff - 1; + m_text->SetSize(tsz); + } + } + else + { + m_text->SetSize( m_tcArea.x, + 0, + sz.x - m_btnArea.x - m_widthCustomPaint - customBorder, + sz.y ); + } +} + +wxSize wxPGComboControlBase::DoGetBestSize() const +{ + wxSize sizeText(150,0); + + if ( m_text ) + sizeText = m_text->GetBestSize(); + + // TODO: Better method to calculate close-to-native control height. + + int fhei; + if ( m_font.Ok() ) + fhei = (m_font.GetPointSize()*2) + 5; + else if ( wxNORMAL_FONT->Ok() ) + fhei = (wxNORMAL_FONT->GetPointSize()*2) + 5; + else + fhei = sizeText.y + 4; + + // Need to force height to accomodate bitmap? + int btnSizeY = m_btnSize.y; + if ( m_bmpNormal.Ok() && fhei < btnSizeY ) + fhei = btnSizeY; + + // Control height doesn't depend on border +/* + // Add border + int border = m_windowStyle & wxBORDER_MASK; + if ( border == wxSIMPLE_BORDER ) + fhei += 2; + else if ( border == wxNO_BORDER ) + fhei += (m_widthCustomBorder*2); + else + // Sunken etc. + fhei += 4; +*/ + + // Final adjustments +#ifdef __WXGTK__ + fhei += 1; +#endif + + wxSize ret(sizeText.x + g_comboMargin + DEFAULT_DROPBUTTON_WIDTH, + fhei); + + CacheBestSize(ret); + return ret; +} + +void wxPGComboControlBase::DoMoveWindow(int x, int y, int width, int height) +{ + // SetSize is called last in create, so it marks the end of creation + m_iFlags |= wxPGCC_IFLAG_CREATED; + + wxControl::DoMoveWindow(x, y, width, height); +} + +void wxPGComboControlBase::OnSizeEvent( wxSizeEvent& event ) +{ + if ( !IsCreated() ) + return; + + // defined by actual wxComboControls + OnResize(); + + event.Skip(); +} + +// ---------------------------------------------------------------------------- +// standard operations +// ---------------------------------------------------------------------------- + +bool wxPGComboControlBase::Enable(bool enable) +{ + if ( !wxControl::Enable(enable) ) + return false; + + if ( m_btn ) + m_btn->Enable(enable); + if ( m_text ) + m_text->Enable(enable); + + return true; +} + +bool wxPGComboControlBase::Show(bool show) +{ + if ( !wxControl::Show(show) ) + return false; + + if (m_btn) + m_btn->Show(show); + + if (m_text) + m_text->Show(show); + + return true; +} + +bool wxPGComboControlBase::SetFont ( const wxFont& font ) +{ + if ( !wxControl::SetFont(font) ) + return false; + + if (m_text) + m_text->SetFont(font); + + return true; +} + +#if wxUSE_TOOLTIPS +void wxPGComboControlBase::DoSetToolTip(wxToolTip *tooltip) +{ + wxControl::DoSetToolTip(tooltip); + + // Set tool tip for button and text box + if ( tooltip ) + { + const wxString &tip = tooltip->GetTip(); + if ( m_text ) m_text->SetToolTip(tip); + if ( m_btn ) m_btn->SetToolTip(tip); + } + else + { + if ( m_text ) m_text->SetToolTip( (wxToolTip*) NULL ); + if ( m_btn ) m_btn->SetToolTip( (wxToolTip*) NULL ); + } +} +#endif // wxUSE_TOOLTIPS + +// ---------------------------------------------------------------------------- +// painting +// ---------------------------------------------------------------------------- + +// draw focus background on area in a way typical on platform +void wxPGComboControlBase::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) +{ + wxSize sz = GetClientSize(); + bool isEnabled; + bool doDrawFocusRect; // also selected + + // For smaller size control (and for disabled background) use less spacing + int focusSpacingX; + int focusSpacingY; + + if ( !(flags & wxCONTROL_ISSUBMENU) ) + { + // Drawing control + isEnabled = IsEnabled(); + doDrawFocusRect = ShouldDrawFocus(); + + // Windows-style: for smaller size control (and for disabled background) use less spacing + //focusSpacingX = isEnabled ? 2 : 1; + focusSpacingX = 1; + focusSpacingY = sz.y > (GetCharHeight()+500) && isEnabled ? 2 : 1; + } + else + { + // Drawing a list item + isEnabled = true; // they are never disabled + doDrawFocusRect = flags & wxCONTROL_SELECTED ? true : false; + + focusSpacingX = 0; + focusSpacingY = 0; + } + + // Set the background sub-rectangle for selection, disabled etc + wxRect selRect(rect); + selRect.y += focusSpacingY; + selRect.height -= (focusSpacingY*2); + int wcp = 0; + + if ( !(flags & wxCONTROL_ISSUBMENU) ) + wcp += m_widthCustomPaint; + + selRect.x += wcp + focusSpacingX; + selRect.width -= wcp + (focusSpacingX*2); + + wxColour bgCol; + bool doDrawSelRect = true; + + if ( isEnabled ) + { + // If popup is hidden and this control is focused, + // then draw the focus-indicator (selbgcolor background etc.). + if ( doDrawFocusRect ) + { + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); + bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + } + else + { + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); + bgCol = GetBackgroundColour(); + doDrawSelRect = false; + } + } + else + { + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) ); + bgCol = GetBackgroundColour(); + } + + dc.SetBrush( bgCol ); + if ( doDrawSelRect ) + { + dc.SetPen( bgCol ); + dc.DrawRectangle( selRect ); + } +} + +void wxPGComboControlBase::DrawButton( wxDC& dc, const wxRect& rect, int flags ) +{ + int drawState = m_btnState; + + if ( (m_iFlags & wxPGCC_BUTTON_STAYS_DOWN) && + IsPopupShown() ) + drawState |= wxCONTROL_PRESSED; + + wxRect drawRect(rect.x+m_btnSpacingX, + rect.y+((rect.height-m_btnSize.y)/2), + m_btnSize.x, + m_btnSize.y); + + // Make sure area is not larger than the control + if ( drawRect.y < rect.y ) + drawRect.y = rect.y; + if ( drawRect.height > rect.height ) + drawRect.height = rect.height; + + bool enabled = IsEnabled(); + + if ( !enabled ) + drawState |= wxCONTROL_DISABLED; + + if ( !m_bmpNormal.Ok() ) + { + if ( flags & Button_BitmapOnly ) + return; + + // Need to clear button background even if m_btn is present + if ( flags & Button_PaintBackground ) + { + wxColour bgCol; + + if ( m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE ) + bgCol = GetParent()->GetBackgroundColour(); + else + bgCol = GetBackgroundColour(); + + dc.SetBrush(bgCol); + dc.SetPen(bgCol); + dc.DrawRectangle(rect); + } + + // Draw standard button + wxRendererNative::Get().DrawComboBoxDropButton(this, + dc, + drawRect, + drawState); + } + else + { + // Draw bitmap + + wxBitmap* pBmp; + + if ( !enabled ) + pBmp = &m_bmpDisabled; + else if ( m_btnState & wxCONTROL_PRESSED ) + pBmp = &m_bmpPressed; + else if ( m_btnState & wxCONTROL_CURRENT ) + pBmp = &m_bmpHover; + else + pBmp = &m_bmpNormal; + +#if wxCHECK_VERSION(2, 7, 0) + if ( m_blankButtonBg ) + { + // If using blank button background, we need to clear its background + // with button face colour instead of colour for rest of the control. + if ( flags & Button_PaintBackground ) + { + wxColour bgCol = GetParent()->GetBackgroundColour(); //wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); + //wxColour bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + dc.SetPen(bgCol); + dc.SetBrush(bgCol); + dc.DrawRectangle(rect); + } + + if ( !(flags & Button_BitmapOnly) ) + { + wxRendererNative::Get().DrawPushButton(this, + dc, + drawRect, + drawState); + } + } + else +#endif + { + // Need to clear button background even if m_btn is present + // (assume non-button background was cleared just before this call so brushes are good) + if ( flags & Button_PaintBackground ) + dc.DrawRectangle(rect); + } + + // Draw bitmap centered in drawRect + dc.DrawBitmap(*pBmp, + drawRect.x + (drawRect.width-pBmp->GetWidth())/2, + drawRect.y + (drawRect.height-pBmp->GetHeight())/2, + true); + } +} + +void wxPGComboControlBase::RecalcAndRefresh() +{ + if ( IsCreated() ) + { + wxSizeEvent evt(GetSize(),GetId()); + GetEventHandler()->ProcessEvent(evt); + Refresh(); + } +} + +bool wxPGComboControlBase::OnDrawListItem( wxDC& WXUNUSED(dc), + const wxRect& WXUNUSED(rect), + int WXUNUSED(item), + int WXUNUSED(flags) ) +{ + return false; // signals caller to make default drawing +} + +wxCoord wxPGComboControlBase::OnMeasureListItem( int WXUNUSED(item) ) +{ + return -1; // signals caller to use default +} + +wxCoord wxPGComboControlBase::OnMeasureListItemWidth( int WXUNUSED(item) ) +{ + return -1; // signals caller to use default +} + +// ---------------------------------------------------------------------------- +// miscellaneous event handlers +// ---------------------------------------------------------------------------- + +void wxPGComboControlBase::OnTextCtrlEvent(wxCommandEvent& event) +{ + // Change event id and relay it forward + event.SetId(GetId()); + event.Skip(); +} + +// call if cursor is on button area or mouse is captured for the button +bool wxPGComboControlBase::HandleButtonMouseEvent( wxMouseEvent& event, + int flags ) +{ + int type = event.GetEventType(); + + if ( type == wxEVT_MOTION ) + { + if ( flags & wxPGCC_MF_ON_BUTTON ) + { + if ( !(m_btnState & wxCONTROL_CURRENT) ) + { + // Mouse hover begins + m_btnState |= wxCONTROL_CURRENT; + if ( HasCapture() ) // Retain pressed state. + m_btnState |= wxCONTROL_PRESSED; + Refresh(); + } + } + else if ( (m_btnState & wxCONTROL_CURRENT) ) + { + // Mouse hover ends + m_btnState &= ~(wxCONTROL_CURRENT|wxCONTROL_PRESSED); + Refresh(); + } + } + else if ( type == wxEVT_LEFT_DOWN ) + { + // Only accept event if it wasn't right after popup dismiss + //if ( ::wxGetLocalTimeMillis() > m_timeCanClick ) + { + // Need to test this, because it might be outside. + if ( flags & wxPGCC_MF_ON_BUTTON ) + { + m_btnState |= wxCONTROL_PRESSED; + Refresh(); + + if ( !(m_iFlags & wxPGCC_POPUP_ON_MOUSE_UP) ) + OnButtonClick(); + else + // If showing popup now, do not capture mouse or there will be interference + CaptureMouse(); + } + } + /*else + { + m_btnState = 0; + }*/ + } + else if ( type == wxEVT_LEFT_UP ) + { + + // Only accept event if mouse was left-press was previously accepted + if ( HasCapture() ) + ReleaseMouse(); + + if ( m_btnState & wxCONTROL_PRESSED ) + { + // If mouse was inside, fire the click event. + if ( m_iFlags & wxPGCC_POPUP_ON_MOUSE_UP ) + { + if ( flags & wxPGCC_MF_ON_BUTTON ) + OnButtonClick(); + } + + m_btnState &= ~(wxCONTROL_PRESSED); + Refresh(); + } + } + else if ( type == wxEVT_LEAVE_WINDOW ) + { + if ( m_btnState & (wxCONTROL_CURRENT|wxCONTROL_PRESSED) ) + { + m_btnState &= ~(wxCONTROL_CURRENT); + + // Mouse hover ends + if ( !m_isPopupShown ) + { + m_btnState &= ~(wxCONTROL_PRESSED); + Refresh(); + } + } + } + else + return false; + + return true; +} + +// Conversion to double-clicks and some basic filtering +// returns true if event was consumed or filtered +bool wxPGComboControlBase::PreprocessMouseEvent( wxMouseEvent& event, + int WXUNUSED(flags) ) +{ + wxLongLong t = ::wxGetLocalTimeMillis(); + int evtType = event.GetEventType(); + + if ( m_isPopupShown && + ( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) ) + { + HidePopup(); + return true; + } + + // + // Generate our own double-clicks + // (to allow on-focus dc-event on double-clicks instead of triple-clicks) + /*if ( (m_windowStyle & wxPGCC_DCLICK_CYCLES) && + !m_isPopupShown && + //!(handlerFlags & wxPGCC_MF_ON_BUTTON) ) + !(flags & wxPGCC_MF_ON_BUTTON) ) + { + if ( evtType == wxEVT_LEFT_DOWN ) + { + // Set value to avoid up-events without corresponding downs + m_downReceived = true; + } + else if ( evtType == wxEVT_LEFT_DCLICK ) + { + // We'll make our own double-clicks + //evtType = 0; + event.SetEventType(0); + return true; + } + else if ( evtType == wxEVT_LEFT_UP ) + { + if ( m_downReceived || m_timeLastMouseUp == 1 ) + { + wxLongLong timeFromLastUp = (t-m_timeLastMouseUp); + + if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD ) + { + //type = wxEVT_LEFT_DCLICK; + event.SetEventType(wxEVT_LEFT_DCLICK); + m_timeLastMouseUp = 1; + } + else + { + m_timeLastMouseUp = t; + } + + //m_downReceived = false; + } + } + }*/ + + // Filter out clicks on button immediately after popup dismiss (Windows like behaviour) + if ( evtType == wxEVT_LEFT_DOWN && t < m_timeCanAcceptClick ) + { + event.SetEventType(0); + return true; + } + + return false; +} + +void wxPGComboControlBase::HandleNormalMouseEvent( wxMouseEvent& event ) +{ + int evtType = event.GetEventType(); + + if ( (evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DCLICK) && + (m_windowStyle & wxCB_READONLY) ) + { + if ( m_isPopupShown ) + { + #if !wxUSE_POPUPWIN + // Normally do nothing - evt handler should close it for us + #if ALLOW_FAKE_POPUP + if ( m_fakePopupUsage == 2 ) + HidePopup(); + #endif + #elif !USE_TRANSIENT_POPUP + // Click here always hides the popup. + HidePopup(); + #endif + } + else + { + if ( !(m_windowStyle & wxPGCC_DCLICK_CYCLES) ) + { + // In read-only mode, clicking the text is the + // same as clicking the button. + OnButtonClick(); + } + else if ( /*evtType == wxEVT_LEFT_UP || */evtType == wxEVT_LEFT_DCLICK ) + { + //if ( m_popupInterface->CycleValue() ) + // Refresh(); + if ( m_popupInterface ) + m_popupInterface->OnComboDoubleClick(); + } + } + } + else + if ( m_isPopupShown ) + { + // relay (some) mouse events to the popup + if ( evtType == wxEVT_MOUSEWHEEL ) + m_popup->AddPendingEvent(event); + } + else if ( evtType ) + event.Skip(); +} + +void wxPGComboControlBase::OnKeyEvent( wxKeyEvent& event ) +{ + int keycode = event.GetKeyCode(); + + if ( keycode == WXK_TAB && + !IsPopupShown() ) + { + wxNavigationKeyEvent evt; + evt.SetFlags(wxNavigationKeyEvent::FromTab| + (!event.ShiftDown()?wxNavigationKeyEvent::IsForward: + wxNavigationKeyEvent::IsBackward)); + evt.SetEventObject(this); + GetParent()->GetEventHandler()->AddPendingEvent(evt); + return; + } + + if ( IsPopupShown() ) + { + // pass it to the popped up control + GetPopupControl()->AddPendingEvent(event); + } + else // no popup + { + int comboStyle = GetWindowStyle(); + wxPGComboPopup* popupInterface = GetPopup(); + + if ( !popupInterface ) + { + event.Skip(); + return; + } + + if ( (comboStyle & wxCB_READONLY) || + ( keycode != WXK_RIGHT && keycode != WXK_LEFT ) + ) + { + // Alternate keys: UP and DOWN show the popup instead of cycling + if ( (comboStyle & wxPGCC_ALT_KEYS) ) + { + if ( keycode == WXK_UP || keycode == WXK_DOWN ) + { + OnButtonClick(); + return; + } + else + event.Skip(); + } + else + popupInterface->OnComboKeyEvent(event); + } + else + event.Skip(); + } +} + +void wxPGComboControlBase::OnFocusEvent( wxFocusEvent& event ) +{ + if ( event.GetEventType() == wxEVT_SET_FOCUS ) + { + if ( m_text && m_text != ::wxWindow::FindFocus() ) + { + m_skipTextCtrlFocusEvents++; + m_text->SetFocus(); + } + } + + Refresh(); +} + +void wxPGComboControlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) +{ + OnThemeChange(); + // indentation may also have changed + if ( !(m_iFlags & wxPGCC_IFLAG_INDENT_SET) ) + m_absIndent = GetNativeTextIndent(); + RecalcAndRefresh(); +} + +// ---------------------------------------------------------------------------- +// popup handling +// ---------------------------------------------------------------------------- + +// Create popup window and the child control +void wxPGComboControlBase::CreatePopup() +{ + wxPGComboPopup* popupInterface = m_popupInterface; + wxWindow* popup; + + if ( !m_winPopup ) + m_winPopup = new wxPGComboPopupWindow( this, wxNO_BORDER ); + + popupInterface->Create(m_winPopup); + m_popup = popup = popupInterface->GetControl(); + + m_popupExtraHandler = new wxPGComboPopupExtraEventHandler(this); + popup->PushEventHandler( m_popupExtraHandler ); + + popupInterface->m_iFlags |= wxPGCP_IFLAG_CREATED; +} + +void wxPGComboControlBase::SetPopup( wxPGComboPopup* iface ) +{ + delete m_popupInterface; + delete m_winPopup; + + m_popupInterface = iface; + +#if ALLOW_FAKE_POPUP + m_fakePopupUsage = 0; +#endif + + if ( !iface->LazyCreate() || m_winPopup ) + { + CreatePopup(); + /* + m_winPopup = new wxPGComboPopupWindow( this, wxNO_BORDER ); + + // Create popup right away + iface->Create(m_winPopup); + m_popup = iface->GetControl(); + m_popupExtraHandler = new wxPGComboPopupExtraEventHandler(this); + m_popup->PushEventHandler( m_popupExtraHandler ); + + // Add interface as event handler + //m_popup->PushEventHandler( iface ); + */ + + // FIXME: This bypasses wxGTK popupwindow bug + // (i.e. window is not initially hidden when it should be) + m_winPopup->Hide(); + +#if ALLOW_FAKE_POPUP + m_fakePopupUsage = 1; +#endif + } + else + { + m_popup = (wxWindow*) NULL; + } + + // This must be after creation + if ( m_valueString.length() ) + iface->SetStringValue(m_valueString); + +} + +void wxPGComboControlBase::OnButtonClick() +{ + // Derived classes can override this method for totally custom + // popup action + ShowPopup(); +} + +void wxPGComboControlBase::ShowPopup() +{ + wxCHECK_RET( m_popupInterface, wxT("no popup interface set for wxComboControl") ); + wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") ); + + SetFocus(); + + // Space above and below + int screenHeight; + wxPoint scrPos; + int spaceAbove; + int spaceBelow; + int maxHeightPopup; + wxSize ctrlSz = GetSize(); + +#if ALLOW_FAKE_POPUP + + int existingHeight = 200; + if ( m_popup ) + existingHeight = m_popup->GetSize().y; + + int screenWidth; + GetParent()->GetClientSize(&screenWidth,&screenHeight); + screenWidth -= 2; + scrPos = GetPosition(); + + spaceAbove = scrPos.y - 2; + spaceBelow = screenHeight - spaceAbove - ctrlSz.y - 4; + + maxHeightPopup = spaceBelow; + if ( spaceAbove > spaceBelow ) + maxHeightPopup = spaceAbove; + + if ( maxHeightPopup >= existingHeight ) + { + if ( m_winPopup && m_fakePopupUsage!=2 ) + { + delete m_winPopup; + m_winPopup = (wxWindow*) NULL; + m_popup = (wxWindow*) NULL; + } + m_fakePopupUsage = 2; + } + else + { + if ( m_winPopup && m_fakePopupUsage!=1 ) + { + delete m_winPopup; + m_winPopup = (wxWindow*) NULL; + m_popup = (wxWindow*) NULL; + } + m_fakePopupUsage = 1; +#else + { +#endif + + screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ); + scrPos = GetParent()->ClientToScreen(GetPosition()); + + spaceAbove = scrPos.y; + spaceBelow = screenHeight - spaceAbove - ctrlSz.y; + + maxHeightPopup = spaceBelow; + if ( spaceAbove > spaceBelow ) + maxHeightPopup = spaceAbove; + + } + + // Width + int widthPopup = ctrlSz.x + m_extLeft + m_extRight; + + if ( widthPopup < m_widthMinPopup ) + widthPopup = m_widthMinPopup; + + wxWindow* winPopup = m_winPopup; + wxWindow* popup; + + // Need to disable tab traversal of parent + // + // NB: This is to fix a bug in wxMSW. In theory it could also be fixed + // by, for instance, adding check to window.cpp:wxWindowMSW::MSWProcessMessage + // that if transient popup is open, then tab traversal is to be ignored. + // However, I think this code would still be needed for cases where + // transient popup doesn't work yet (wxWINCE?). + wxWindow* parent = GetParent(); + int parentFlags = parent->GetWindowStyle(); + if ( parentFlags & wxTAB_TRAVERSAL ) + { + parent->SetWindowStyle( parentFlags & ~(wxTAB_TRAVERSAL) ); + m_iFlags |= wxPGCC_IFLAG_PARENT_TAB_TRAVERSAL; + } + + if ( !winPopup ) + { +#if ALLOW_FAKE_POPUP + if ( m_fakePopupUsage == 2 ) + { + winPopup = new wxWindow(); + #ifdef __WXMSW__ + // Only wxMSW supports this + winPopup->Hide(); + #endif + winPopup->Create( GetParent(), -1 ); + m_winPopup = winPopup; + } +#endif + CreatePopup(); + winPopup = m_winPopup; + popup = m_popup; + } + else + { + popup = m_popup; + } + + wxASSERT( !m_popup || m_popup == popup ); // Consistency check. + + wxSize adjustedSize = m_popupInterface->GetAdjustedSize(widthPopup, + m_heightPopup<=0?DEFAULT_POPUP_HEIGHT:m_heightPopup, + maxHeightPopup); + + popup->SetSize(adjustedSize); + popup->Move(0,0); + m_popupInterface->OnPopup(); + +#if ALLOW_FAKE_POPUP + // Make sure fake popup didn't get too big + if ( m_fakePopupUsage == 2 && popup->GetSize().x > screenWidth ) + { + popup->SetSize(screenWidth-2,popup->GetSize().y); + } +#endif + + // + // Reposition and resize popup window + // + + wxSize szp = popup->GetSize(); + + int popupX; + int popupY = scrPos.y + ctrlSz.y; + + // Anchor popup to the side the dropbutton is on + if ( m_btnSide == wxRIGHT ) + popupX = scrPos.x + ctrlSz.x + m_extRight- szp.x; + else + popupX = scrPos.x - m_extLeft; + +#if ALLOW_FAKE_POPUP + if ( m_fakePopupUsage == 2 ) + { + if ( spaceBelow < szp.y ) + { + if ( spaceAbove > spaceBelow ) + { + if ( szp.y > spaceAbove ) + { + popup->SetSize(szp.x,spaceAbove); + szp.y = spaceAbove; + } + popupY = scrPos.y - szp.y; + } + else + { + if ( szp.y > spaceBelow ) + { + popup->SetSize(szp.x,spaceBelow); + szp.y = spaceBelow; + } + } + } + } + else +#endif + if ( spaceBelow < szp.y ) + { + popupY = scrPos.y - szp.y; + } + + // Move to position + //wxLogDebug(wxT("popup scheduled position1: %i,%i"),ptp.x,ptp.y); + //wxLogDebug(wxT("popup position1: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y); + + // Some platforms (GTK) may need these two to be separate + winPopup->SetSize( szp.x, szp.y ); + winPopup->Move( popupX, popupY ); + + //wxLogDebug(wxT("popup position2: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y); + + m_popup = popup; + + // Set string selection (must be this way instead of SetStringSelection) + if ( m_text ) + { + if ( !(m_iFlags & wxPGCC_NO_TEXT_AUTO_SELECT) ) + m_text->SelectAll(); + + m_popupInterface->SetStringValue( m_text->GetValue() ); + } + else + { + // This is neede since focus/selection indication may change when popup is shown + // FIXME: But in that case, would m_isPopupShown need to go before this? + Refresh(); + } + + // This must be after SetStringValue + m_isPopupShown = true; + + // Show it +#if USE_TRANSIENT_POPUP + ((wxPopupTransientWindow*)winPopup)->Popup(popup); +#else + winPopup->Show(); +#endif + +#if INSTALL_TOPLEV_HANDLER + // If our real popup is wxDialog, then only install handler + // incase of fake popup. + #if !wxUSE_POPUPWIN + if ( m_fakePopupUsage != 2 ) + { + if ( m_toplevEvtHandler ) + { + delete m_toplevEvtHandler; + m_toplevEvtHandler = (wxEvtHandler*) NULL; + } + } + else + #endif + { + // Put top level window event handler into place + if ( !m_toplevEvtHandler ) + m_toplevEvtHandler = new wxPGComboFrameEventHandler(this); + + wxWindow* toplev = ::wxGetTopLevelParent( this ); + wxASSERT( toplev ); + ((wxPGComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup(); + toplev->PushEventHandler( m_toplevEvtHandler ); + } +#endif + +} + +void wxPGComboControlBase::OnPopupDismiss() +{ + // Just in case, avoid double dismiss + if ( !m_isPopupShown ) + return; + + // *Must* set this before focus etc. + m_isPopupShown = false; + + // Inform popup control itself + m_popupInterface->OnDismiss(); + + //((wxComboDropButton*)m_btn)->SetPopup( (wxWindow*) NULL ); + + if ( m_popupExtraHandler ) + ((wxPGComboPopupExtraEventHandler*)m_popupExtraHandler)->OnPopupDismiss(); + +#if INSTALL_TOPLEV_HANDLER + // Remove top level window event handler + if ( m_toplevEvtHandler ) + { + wxWindow* toplev = ::wxGetTopLevelParent( this ); + if ( toplev ) + toplev->RemoveEventHandler( m_toplevEvtHandler ); + } +#endif + +#if !wxUSE_POPUPWIN + if ( m_fakePopupUsage != 2 ) + GetParent()->SetFocus(); +#endif + + m_timeCanAcceptClick = ::wxGetLocalTimeMillis() + 150; + + // If cursor not on dropdown button, then clear its state + // (technically not required by all ports, but do it for all just in case) + if ( !m_btnArea.wxPGRectContains(ScreenToClient(::wxGetMousePosition())) ) + m_btnState = 0; + + // Return parent's tab traversal flag. + // See ShowPopup for notes. + if ( m_iFlags & wxPGCC_IFLAG_PARENT_TAB_TRAVERSAL ) + { + wxWindow* parent = GetParent(); + parent->SetWindowStyle( parent->GetWindowStyle() | wxTAB_TRAVERSAL ); + m_iFlags &= ~(wxPGCC_IFLAG_PARENT_TAB_TRAVERSAL); + } + + // refresh control (necessary even if m_text) + Refresh(); + +} + +void wxPGComboControlBase::HidePopup() +{ + // Should be able to call this without popup interface + //wxCHECK_RET( m_popupInterface, _T("no popup interface") ); + if ( !m_isPopupShown ) + return; + + // transfer value and show it in textctrl, if any + SetValue( m_popupInterface->GetStringValue() ); + +#if USE_TRANSIENT_POPUP + ((wxPopupTransientWindow*)m_winPopup)->Dismiss(); +#else + m_winPopup->Hide(); +#endif + + OnPopupDismiss(); +} + +// ---------------------------------------------------------------------------- +// customization methods +// ---------------------------------------------------------------------------- + +void wxPGComboControlBase::SetButtonPosition( int width, int height, + int side, int spacingX ) +{ + m_btnWid = width; + m_btnHei = height; + m_btnSide = side; + m_btnSpacingX = spacingX; + + RecalcAndRefresh(); +} + +void wxPGComboControlBase::SetButtonBitmaps( const wxBitmap& bmpNormal, + bool blankButtonBg, + const wxBitmap& bmpPressed, + const wxBitmap& bmpHover, + const wxBitmap& bmpDisabled ) +{ + m_bmpNormal = bmpNormal; + m_blankButtonBg = blankButtonBg; + + if ( bmpPressed.Ok() ) + m_bmpPressed = bmpPressed; + else + m_bmpPressed = bmpNormal; + + if ( bmpHover.Ok() ) + m_bmpHover = bmpHover; + else + m_bmpHover = bmpNormal; + + if ( bmpDisabled.Ok() ) + m_bmpDisabled = bmpDisabled; + else + m_bmpDisabled = bmpNormal; + + RecalcAndRefresh(); +} + +void wxPGComboControlBase::SetCustomPaintWidth( int width ) +{ + if ( m_text ) + { + // move textctrl accordingly + wxRect r = m_text->GetRect(); + int inc = width - m_widthCustomPaint; + r.x += inc; + r.width -= inc; + m_text->SetSize( r ); + } + + m_widthCustomPaint = width; + + RecalcAndRefresh(); +} + +void wxPGComboControlBase::SetTextIndent( int indent ) +{ + if ( indent < 0 ) + { + m_absIndent = GetNativeTextIndent(); + m_iFlags &= ~(wxPGCC_IFLAG_INDENT_SET); + } + else + { + m_absIndent = indent; + m_iFlags |= wxPGCC_IFLAG_INDENT_SET; + } + + RecalcAndRefresh(); +} + +wxCoord wxPGComboControlBase::GetNativeTextIndent() const +{ + return DEFAULT_TEXT_INDENT; +} + +// ---------------------------------------------------------------------------- +// methods forwarded to wxTextCtrl +// ---------------------------------------------------------------------------- + +wxString wxPGComboControlBase::GetValue() const +{ + if ( m_text ) + return m_text->GetValue(); + return m_valueString; +} + +void wxPGComboControlBase::SetValue(const wxString& value) +{ + if ( m_text ) + { + m_text->SetValue(value); + if ( !(m_iFlags & wxPGCC_NO_TEXT_AUTO_SELECT) ) + m_text->SelectAll(); + } + + // Since wxPGComboPopup may want to paint the combo as well, we need + // to set the string value here (as well as sometimes in ShowPopup). + if ( m_valueString != value && m_popupInterface ) + { + m_popupInterface->SetStringValue(value); + } + + m_valueString = value; + + Refresh(); +} + +void wxPGComboControlBase::Copy() +{ + if ( m_text ) + m_text->Copy(); +} + +void wxPGComboControlBase::Cut() +{ + if ( m_text ) + m_text->Cut(); +} + +void wxPGComboControlBase::Paste() +{ + if ( m_text ) + m_text->Paste(); +} + +void wxPGComboControlBase::SetInsertionPoint(long pos) +{ + if ( m_text ) + m_text->SetInsertionPoint(pos); +} + +void wxPGComboControlBase::SetInsertionPointEnd() +{ + if ( m_text ) + m_text->SetInsertionPointEnd(); +} + +long wxPGComboControlBase::GetInsertionPoint() const +{ + if ( m_text ) + return m_text->GetInsertionPoint(); + + return 0; +} + +long wxPGComboControlBase::GetLastPosition() const +{ + if ( m_text ) + return m_text->GetLastPosition(); + + return 0; +} + +void wxPGComboControlBase::Replace(long from, long to, const wxString& value) +{ + if ( m_text ) + m_text->Replace(from, to, value); +} + +void wxPGComboControlBase::Remove(long from, long to) +{ + if ( m_text ) + m_text->Remove(from, to); +} + +void wxPGComboControlBase::SetSelection(long from, long to) +{ + if ( m_text ) + m_text->SetSelection(from, to); +} + +void wxPGComboControlBase::Undo() +{ + if ( m_text ) + m_text->Undo(); +} + + +// ---------------------------------------------------------------------------- +// wxPGGenericComboControl +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(wxPGGenericComboControl, wxPGComboControlBase) + //EVT_SIZE(wxPGGenericComboControl::OnSizeEvent) + EVT_PAINT(wxPGGenericComboControl::OnPaintEvent) + EVT_MOUSE_EVENTS(wxPGGenericComboControl::OnMouseEvent) +END_EVENT_TABLE() + + +IMPLEMENT_DYNAMIC_CLASS(wxPGGenericComboControl, wxPGComboControlBase) + +void wxPGGenericComboControl::Init() +{ +} + +bool wxPGGenericComboControl::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + + // Set border + long border = style & wxBORDER_MASK; + +#if defined(__WXUNIVERSAL__) + if ( !border ) + border = wxBORDER_SIMPLE; +#elif defined(__WXMSW__) + if ( !border ) + border = wxBORDER_SIMPLE; +#else + if ( !border ) + { + border = wxBORDER_NONE; + m_widthCustomBorder = 1; + } + + Customize( wxPGCC_BUTTON_OUTSIDE_BORDER | + wxPGCC_NO_TEXT_AUTO_SELECT | + wxPGCC_BUTTON_STAYS_DOWN ); + +#endif + + style = (style & ~(wxBORDER_MASK)) | border; + + // create main window + if ( !wxPGComboControlBase::Create(parent, + id, + value, + wxDefaultPosition, + wxDefaultSize, + style | wxFULL_REPAINT_ON_RESIZE, + wxDefaultValidator, + name) ) + return false; + + // Create textctrl, if necessary + CreateTextCtrl( wxBORDER_NONE, validator ); + + // Add keyboard input handlers for main control and textctrl + InstallInputHandlers(); + + // Set background + SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering + + // SetSize should be called last + SetSize(pos.x,pos.y,size.x,size.y); + + return true; +} + +wxPGGenericComboControl::~wxPGGenericComboControl() +{ +} + +void wxPGGenericComboControl::OnResize() +{ + + // Recalculates button and textctrl areas + CalculateAreas(DEFAULT_DROPBUTTON_WIDTH); + +#if 0 + // Move separate button control, if any, to correct position + if ( m_btn ) + { + wxSize sz = GetClientSize(); + m_btn->SetSize( m_btnArea.x + m_btnSpacingX, + (sz.y-m_btnSize.y)/2, + m_btnSize.x, + m_btnSize.y ); + } +#endif + + // Move textctrl, if any, accordingly + PositionTextCtrl( TEXTCTRLXADJUST, TEXTCTRLYADJUST ); +} + +void wxPGGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) +{ + wxSize sz = GetClientSize(); + +#if !wxCHECK_VERSION(2, 7, 1) + // If size is larger, recalculate double buffer bitmap + if ( !gs_doubleBuffer || + sz.x > gs_doubleBuffer->GetWidth() || + sz.y > gs_doubleBuffer->GetHeight() ) + { + delete gs_doubleBuffer; + gs_doubleBuffer = new wxBitmap(sz.x+25,sz.y); + } + + wxBufferedPaintDC dc(this,*gs_doubleBuffer); +#else + wxAutoBufferedPaintDC dc(this); +#endif + + const wxRect& rectb = m_btnArea; + wxRect rect = m_tcArea; + + // artificial simple border + if ( m_widthCustomBorder ) + { + int customBorder = m_widthCustomBorder; + + // Set border colour + wxPen pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT), + customBorder, + wxSOLID ); + dc.SetPen( pen1 ); + + // area around both controls + wxRect rect2(0,0,sz.x,sz.y); + if ( m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE ) + { + rect2 = m_tcArea; + if ( customBorder == 1 ) + { + rect2.Inflate(1); + } + else + { + #ifdef __WXGTK__ + rect2.x -= 1; + rect2.y -= 1; + #else + rect2.x -= customBorder; + rect2.y -= customBorder; + #endif + rect2.width += 1 + customBorder; + rect2.height += 1 + customBorder; + } + } + + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + dc.DrawRectangle(rect2); + } + + wxColour winCol = GetBackgroundColour(); + dc.SetBrush(winCol); + dc.SetPen(winCol); + + //wxLogDebug(wxT("hei: %i tcy: %i tchei: %i"),GetClientSize().y,m_tcArea.y,m_tcArea.height); + //wxLogDebug(wxT("btnx: %i tcx: %i tcwid: %i"),m_btnArea.x,m_tcArea.x,m_tcArea.width); + + // clear main background + dc.DrawRectangle(rect); + + if ( !m_btn ) + // Standard button rendering + DrawButton(dc, rectb); + + // paint required portion on the control + if ( !m_text || m_widthCustomPaint ) + { + wxASSERT( m_widthCustomPaint >= 0 ); + + // this is intentionally here to allow drawed rectangle's + // right edge to be hidden + if ( m_text ) + rect.width = m_widthCustomPaint; + + dc.SetFont( GetFont() ); + + dc.SetClippingRegion(rect); + m_popupInterface->PaintComboControl(dc, rect); + } +} + +void wxPGGenericComboControl::OnMouseEvent( wxMouseEvent& event ) +{ + bool isOnButtonArea = m_btnArea.wxPGRectContains(event.m_x,event.m_y); + int handlerFlags = isOnButtonArea ? wxPGCC_MF_ON_BUTTON : 0; + + // Preprocessing fabricates double-clicks and prevents + // (it may also do other common things in future) + if ( PreprocessMouseEvent(event,handlerFlags) ) + return; + +#ifdef __WXMSW__ + const bool ctrlIsButton = true; +#else + const bool ctrlIsButton = false; +#endif + + if ( ctrlIsButton && + (m_windowStyle & (wxPGCC_DCLICK_CYCLES|wxCB_READONLY)) == wxCB_READONLY ) + { + // if no textctrl and no special double-click, then the entire control acts + // as a button + handlerFlags |= wxPGCC_MF_ON_BUTTON; + if ( HandleButtonMouseEvent(event,handlerFlags) ) + return; + } + else + { + if ( isOnButtonArea || m_btnState & wxCONTROL_PRESSED ) + { + if ( HandleButtonMouseEvent(event,handlerFlags) ) + return; + } + else if ( m_btnState ) + { + // otherwise need to clear the hover status + m_btnState = 0; + RefreshRect(m_btnArea); + } + } + + // + // This will handle left_down and left_dclick events outside button in a Windows/GTK-like manner. + // See header file for further information on this method. + HandleNormalMouseEvent(event); + +} + +// ---------------------------------------------------------------------------- +// wxComboControl +// ---------------------------------------------------------------------------- + +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) + +// Change to #if 1 to include tmschema.h for easier testing of theme +// parameters. +#if 0 + #include + #include +#else + //---------------------------------- + #define EP_EDITTEXT 1 + #define ETS_NORMAL 1 + #define ETS_HOT 2 + #define ETS_SELECTED 3 + #define ETS_DISABLED 4 + #define ETS_FOCUSED 5 + #define ETS_READONLY 6 + #define ETS_ASSIST 7 + #define TMT_FILLCOLOR 3802 + #define TMT_TEXTCOLOR 3803 + #define TMT_BORDERCOLOR 3801 + #define TMT_EDGEFILLCOLOR 3808 + #define TMT_BGTYPE 4001 + + #define BT_IMAGEFILE 0 + #define BT_BORDERFILL 1 + + #define CP_DROPDOWNBUTTON 1 + #define CP_BACKGROUND 2 // This and above are Vista and later only + #define CP_TRANSPARENTBACKGROUND 3 + #define CP_BORDER 4 + #define CP_READONLY 5 + #define CP_DROPDOWNBUTTONRIGHT 6 + #define CP_DROPDOWNBUTTONLEFT 7 + #define CP_CUEBANNER 8 + + #define CBXS_NORMAL 1 + #define CBXS_HOT 2 + #define CBXS_PRESSED 3 + #define CBXS_DISABLED 4 + + #define CBXSR_NORMAL 1 + #define CBXSR_HOT 2 + #define CBXSR_PRESSED 3 + #define CBXSR_DISABLED 4 + + #define CBXSL_NORMAL 1 + #define CBXSL_HOT 2 + #define CBXSL_PRESSED 3 + #define CBXSL_DISABLED 4 + + #define CBTBS_NORMAL 1 + #define CBTBS_HOT 2 + #define CBTBS_DISABLED 3 + #define CBTBS_FOCUSED 4 + + #define CBB_NORMAL 1 + #define CBB_HOT 2 + #define CBB_FOCUSED 3 + #define CBB_DISABLED 4 + + #define CBRO_NORMAL 1 + #define CBRO_HOT 2 + #define CBRO_PRESSED 3 + #define CBRO_DISABLED 4 + + #define CBCB_NORMAL 1 + #define CBCB_HOT 2 + #define CBCB_PRESSED 3 + #define CBCB_DISABLED 4 + +#endif + +#define NATIVE_TEXT_INDENT_XP 4 +#define NATIVE_TEXT_INDENT_CLASSIC 2 + +#define TEXTCTRLXADJUST_XP 0 +#define TEXTCTRLYADJUST_XP 4 +#define TEXTCTRLXADJUST_CLASSIC 0 +#define TEXTCTRLYADJUST_CLASSIC 4 + + +BEGIN_EVENT_TABLE(wxPGComboControl, wxPGComboControlBase) + EVT_PAINT(wxPGComboControl::OnPaintEvent) + EVT_MOUSE_EVENTS(wxPGComboControl::OnMouseEvent) +END_EVENT_TABLE() + + +IMPLEMENT_DYNAMIC_CLASS(wxPGComboControl, wxPGComboControlBase) + +void wxPGComboControl::Init() +{ +} + +bool wxPGComboControl::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + + // Set border + long border = style & wxBORDER_MASK; + + wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive(); + + if ( !border ) + { + // For XP, have 1-width custom border, for older version use sunken + if ( theme ) + { + border = wxBORDER_NONE; + m_widthCustomBorder = 1; + } + else + border = wxBORDER_SUNKEN; + + style = (style & ~(wxBORDER_MASK)) | border; + } + + //Customize( wxPGCC_BUTTON_OUTSIDE_BORDER ); + + // create main window + if ( !wxPGComboControlBase::Create(parent, + id, + value, + wxDefaultPosition, + wxDefaultSize, + style | wxFULL_REPAINT_ON_RESIZE, + wxDefaultValidator, + name) ) + return false; + + if ( theme ) + { +#if wxCHECK_VERSION(2, 8, 0) + const bool isVista = (::wxGetWinVersion() >= wxWinVersion_6); +#else + int Major = 0; + int family = wxGetOsVersion(&Major, NULL); + const bool isVista = ((family == wxWINDOWS_NT) && (Major >= 6)); +#endif + + if ( isVista ) + m_iFlags |= wxPGCC_BUTTON_STAYS_DOWN; + } + + // Create textctrl, if necessary + CreateTextCtrl( wxNO_BORDER, validator ); + + // Add keyboard input handlers for main control and textctrl + InstallInputHandlers(); + + // Prepare background for double-buffering + SetBackgroundStyle( wxBG_STYLE_CUSTOM ); + + // SetSize should be called last + SetSize(pos.x,pos.y,size.x,size.y); + + return true; +} + +wxPGComboControl::~wxPGComboControl() +{ +} + +void wxPGComboControl::OnThemeChange() +{ + wxUxThemeEngine* theme = wxUxThemeEngine::GetIfActive(); + if ( theme ) + { + wxUxThemeHandle hTheme(this, L"COMBOBOX"); + + COLORREF col; + theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_FILLCOLOR,&col); + SetBackgroundColour(wxRGBToColour(col)); + theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_NORMAL,TMT_TEXTCOLOR,&col); + SetForegroundColour(wxRGBToColour(col)); + } + else + { + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + } +} + +//void wxPGComboControl::OnSizeEvent( wxSizeEvent& event ) +void wxPGComboControl::OnResize() +{ + // + // Recalculates button and textctrl areas + + int textCtrlXAdjust; + int textCtrlYAdjust; + + if ( wxUxThemeEngine::GetIfActive() ) + { + textCtrlXAdjust = TEXTCTRLXADJUST_XP; + textCtrlYAdjust = TEXTCTRLYADJUST_XP; + } + else + { + textCtrlXAdjust = TEXTCTRLXADJUST_CLASSIC; + textCtrlYAdjust = TEXTCTRLYADJUST_CLASSIC; + } + + // Technically Classic Windows style combo has more narrow button, + // but the native renderer doesn't paint it well like that. + int btnWidth = 17; + CalculateAreas(btnWidth); + + // Position textctrl using standard routine + PositionTextCtrl(textCtrlXAdjust,textCtrlYAdjust); +} + +/* +// Draws non-XP GUI dotted line around the focus area +static void wxMSWDrawFocusRect( wxDC& dc, const wxRect& rect ) +{ +#if !defined(__WXWINCE__) + dc.SetLogicalFunction(wxINVERT); + + wxPen pen(*wxBLACK,1,wxDOT); + pen.SetCap(wxCAP_BUTT); + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(rect); + + dc.SetLogicalFunction(wxCOPY); +#else + dc.SetLogicalFunction(wxINVERT); + + dc.SetPen(wxPen(*wxBLACK,1,wxDOT)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(rect); + + dc.SetLogicalFunction(wxCOPY); +#endif +} +*/ +/* +// draw focus background on area in a way typical on platform +void wxPGComboControl::DrawFocusBackground( wxDC& dc, const wxRect& rect, int flags ) +{ + wxUxThemeEngine* theme = (wxUxThemeEngine*) NULL; + wxUxThemeHandle hTheme(this, L"COMBOBOX"); + //COLORREF cref; + + wxSize sz = GetClientSize(); + bool isEnabled; + bool isFocused; // also selected + + // For smaller size control (and for disabled background) use less spacing + int focusSpacingX; + int focusSpacingY; + + if ( !(flags & wxCONTROL_ISSUBMENU) ) + { + // Drawing control + isEnabled = IsEnabled(); + isFocused = ShouldDrawFocus(); + + // Windows-style: for smaller size control (and for disabled background) use less spacing + if ( hTheme ) + { + // WinXP Theme + focusSpacingX = isEnabled ? 2 : 1; + focusSpacingY = sz.y > (GetCharHeight()+2) && isEnabled ? 2 : 1; + } + else + { + // Classic Theme + if ( isEnabled ) + { + focusSpacingX = 1; + focusSpacingY = 1; + } + else + { + focusSpacingX = 0; + focusSpacingY = 0; + } + } + } + else + { + // Drawing a list item + isEnabled = true; // they are never disabled + isFocused = flags & wxCONTROL_SELECTED ? true : false; + + focusSpacingX = 0; + focusSpacingY = 0; + } + + // Set the background sub-rectangle for selection, disabled etc + wxRect selRect(rect); + selRect.y += focusSpacingY; + selRect.height -= (focusSpacingY*2); + int wcp = 0; + + if ( !(flags & wxCONTROL_ISSUBMENU) ) + wcp += m_widthCustomPaint; + + selRect.x += wcp + focusSpacingX; + selRect.width -= wcp + (focusSpacingX*2); + + if ( hTheme ) + theme = wxUxThemeEngine::GetIfActive(); + + wxColour bgCol; + bool drawDottedEdge = false; + + if ( isEnabled ) + { + // If popup is hidden and this control is focused, + // then draw the focus-indicator (selbgcolor background etc.). + if ( isFocused ) + { + #if 0 + // TODO: Proper theme color getting (JMS: I don't know which parts/colors to use, + // those below don't work) + if ( hTheme ) + { + theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_TEXTCOLOR,&cref); + dc.SetTextForeground( wxRGBToColour(cref) ); + theme->GetThemeColor(hTheme,EP_EDITTEXT,ETS_SELECTED,TMT_FILLCOLOR,&cref); + bgCol = wxRGBToColour(cref); + } + else + #endif + { + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); + bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + if ( m_windowStyle & wxCB_READONLY ) + drawDottedEdge = true; + } + } + else + { + bgCol = GetBackgroundColour(); + } + } + else + { + dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) ); + bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); + } + + dc.SetBrush(bgCol); + dc.SetPen(bgCol); + dc.DrawRectangle(selRect); + //if ( drawDottedEdge ) + // wxMSWDrawFocusRect(dc,selRect); +} +*/ +void wxPGComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) +{ + // TODO: Convert drawing in this function to Windows API Code + + wxSize sz = GetClientSize(); + +#if !wxCHECK_VERSION(2, 7, 1) + // If size is larger, recalculate double buffer bitmap + if ( !gs_doubleBuffer || + sz.x > gs_doubleBuffer->GetWidth() || + sz.y > gs_doubleBuffer->GetHeight() ) + { + delete gs_doubleBuffer; + gs_doubleBuffer = new wxBitmap(sz.x+25,sz.y); + } + + wxBufferedPaintDC dc(this,*gs_doubleBuffer); +#else + wxAutoBufferedPaintDC dc(this); +#endif + + const wxRect& rectButton = m_btnArea; + wxRect rectTextField = m_tcArea; + const bool isEnabled = IsEnabled(); + wxColour bgCol = GetBackgroundColour(); + + HDC hDc = GetHdcOf(dc); + HWND hWnd = GetHwndOf(this); + + wxUxThemeEngine* theme = NULL; + wxUxThemeHandle hTheme(this, L"COMBOBOX"); + + if ( hTheme ) + theme = wxUxThemeEngine::GetIfActive(); + + wxRect borderRect(0,0,sz.x,sz.y); + + if ( m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE ) + { + borderRect = m_tcArea; + borderRect.Inflate(1); + } + + int drawButFlags = 0; + + if ( hTheme ) + { +#if wxCHECK_VERSION(2, 8, 0) + const bool useVistaComboBox = (::wxGetWinVersion() >= wxWinVersion_6); +#else + int Major = 0; + int family = wxGetOsVersion(&Major, NULL); + const bool useVistaComboBox = ((family == wxWINDOWS_NT) && (Major >= 6)); +#endif + + RECT rFull; + wxCopyRectToRECT(borderRect, rFull); + + RECT rButton; + wxCopyRectToRECT(rectButton, rButton); + + RECT rBorder; + wxCopyRectToRECT(borderRect, rBorder); + + bool isNonStdButton = (m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE) || + (m_iFlags & wxPGCC_IFLAG_HAS_NONSTANDARD_BUTTON); + + // + // Get some states for themed drawing + int butState; + + if ( !isEnabled ) + { + butState = CBXS_DISABLED; + } + // Vista will display the drop-button as depressed always + // when the popup window is visilbe + else if ( (m_btnState & wxCONTROL_PRESSED) || + (useVistaComboBox && IsPopupShown()) ) + { + butState = CBXS_PRESSED; + } + else if ( m_btnState & wxCONTROL_CURRENT ) + { + butState = CBXS_HOT; + } + else + { + butState = CBXS_NORMAL; + } + + int comboBoxPart = 0; // For XP, use the 'default' part + RECT* rUseForBg = &rBorder; + + bool drawFullButton = false; + int bgState = butState; + const bool isFocused = IsFocused(); + + if ( useVistaComboBox ) + { + // FIXME: Either SetBackgroundColour or GetBackgroundColour + // doesn't work under Vista, so here's a temporary + // workaround. + bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + + // Draw the entire control as a single button? + /* + if ( !isNonStdButton ) + { + if ( HasFlag(wxCB_READONLY) ) + drawFullButton = true; + } + */ + + if ( drawFullButton ) + { + comboBoxPart = CP_READONLY; + rUseForBg = &rFull; + + // It should be safe enough to update this flag here. + m_iFlags |= wxPGCC_FULL_BUTTON; + } + else + { + comboBoxPart = CP_BORDER; + m_iFlags &= ~wxPGCC_FULL_BUTTON; + + if ( isFocused ) + bgState = CBB_FOCUSED; + else + bgState = CBB_NORMAL; + } + } + + // + // Draw parent's background, if necessary + RECT* rUseForTb = NULL; + + if ( theme->IsThemeBackgroundPartiallyTransparent( hTheme, comboBoxPart, bgState ) ) + rUseForTb = &rFull; + else if ( m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE ) + rUseForTb = &rButton; + + if ( rUseForTb ) + theme->DrawThemeParentBackground( hWnd, hDc, rUseForTb ); + + // + // Draw the control background (including the border) + if ( m_widthCustomBorder > 0 ) + { + theme->DrawThemeBackground( hTheme, hDc, comboBoxPart, bgState, rUseForBg, NULL ); + } + else + { + // No border. We can't use theme, since it cannot be relied on + // to deliver borderless drawing, even with DrawThemeBackgroundEx. + dc.SetBrush(bgCol); + dc.SetPen(bgCol); + dc.DrawRectangle(borderRect); + } + + // + // Draw the drop-button + if ( !isNonStdButton ) + { + drawButFlags = Button_BitmapOnly; + + int butPart = CP_DROPDOWNBUTTON; + + if ( useVistaComboBox && m_widthCustomBorder > 0 ) + { + if ( drawFullButton ) + { + // We need to alter the button style slightly before + // drawing the actual button (but it was good above + // when background etc was done). + if ( butState == CBXS_HOT || butState == CBXS_PRESSED ) + butState = CBXS_NORMAL; + } + + if ( m_btnSide == wxRIGHT ) + butPart = CP_DROPDOWNBUTTONRIGHT; + else + butPart = CP_DROPDOWNBUTTONLEFT; + + } + theme->DrawThemeBackground( hTheme, hDc, butPart, butState, &rButton, NULL ); + } + else if ( useVistaComboBox && + (m_iFlags & wxPGCC_IFLAG_BUTTON_OUTSIDE) ) + { + // We'll do this, because DrawThemeParentBackground + // doesn't seem to be reliable on Vista. + drawButFlags |= Button_PaintBackground; + } + } + else + { + // Windows 2000 and earlier + drawButFlags = Button_PaintBackground; + + dc.SetBrush(bgCol); + dc.SetPen(bgCol); + dc.DrawRectangle(borderRect); + } + + // Button rendering (may only do the bitmap on button, depending on the flags) + DrawButton( dc, rectButton, drawButFlags ); + + // Paint required portion of the custom image on the control + if ( (!m_text || m_widthCustomPaint) ) + { + wxASSERT( m_widthCustomPaint >= 0 ); + + // this is intentionally here to allow drawed rectangle's + // right edge to be hidden + if ( m_text ) + rectTextField.width = m_widthCustomPaint; + + dc.SetFont( GetFont() ); + + dc.SetClippingRegion(rectTextField); + m_popupInterface->PaintComboControl(dc,rectTextField); + } +} + +void wxPGComboControl::OnMouseEvent( wxMouseEvent& event ) +{ + bool isOnButtonArea = m_btnArea.wxPGRectContains(event.m_x,event.m_y); + int handlerFlags = isOnButtonArea ? wxPGCC_MF_ON_BUTTON : 0; + + // Preprocessing fabricates double-clicks and prevents + // (it may also do other common things in future) + if ( PreprocessMouseEvent(event,isOnButtonArea) ) + return; + + if ( (m_windowStyle & (wxPGCC_DCLICK_CYCLES|wxCB_READONLY)) == wxCB_READONLY ) + { + // if no textctrl and no special double-click, then the entire control acts + // as a button + handlerFlags |= wxPGCC_MF_ON_BUTTON; + if ( HandleButtonMouseEvent(event,handlerFlags) ) + return; + } + else + { + if ( isOnButtonArea || m_btnState & wxCONTROL_PRESSED ) + { + if ( HandleButtonMouseEvent(event,handlerFlags) ) + return; + } + else if ( m_btnState ) + { + // otherwise need to clear the hover status + m_btnState = 0; + RefreshRect(m_btnArea); + } + } + + // + // This will handle left_down and left_dclick events outside button in a Windows-like manner. + // See header file for further information on this method. + HandleNormalMouseEvent(event); + +} + +wxCoord wxPGComboControl::GetNativeTextIndent() const +{ + if ( wxUxThemeEngine::GetIfActive() ) + return NATIVE_TEXT_INDENT_XP; + return NATIVE_TEXT_INDENT_CLASSIC; +} + +#else + +IMPLEMENT_DYNAMIC_CLASS(wxPGComboControl, wxPGComboControlBase) + +#endif // #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) + +// ---------------------------------------------------------------------------- +// wxPGOwnerDrawnComboBox +// ---------------------------------------------------------------------------- + + +IMPLEMENT_DYNAMIC_CLASS(wxPGOwnerDrawnComboBox, wxPGComboControl) + + +BEGIN_EVENT_TABLE(wxPGOwnerDrawnComboBox, wxPGComboControl) +END_EVENT_TABLE() + + +void wxPGOwnerDrawnComboBox::Init() +{ +} + +bool wxPGOwnerDrawnComboBox::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + return wxPGComboControl::Create(parent,id,value,pos,size,style,validator,name); +} + +wxPGOwnerDrawnComboBox::wxPGOwnerDrawnComboBox(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) + : wxPGComboControl() +{ + Init(); + + Create(parent,id,value,pos,size,choices,style, validator, name); +} + +bool wxPGOwnerDrawnComboBox::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) +{ + wxCArrayString chs(choices); + + return Create(parent, id, value, pos, size, chs.GetCount(), + chs.GetStrings(), /*callback,*/ style, validator, name); +} + +bool wxPGOwnerDrawnComboBox::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + int n, + const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + + if ( !Create(parent, id, value, pos, size, style, + validator, name) ) + { + return false; + } + + wxPGVListBoxComboPopup* iface = new wxPGVListBoxComboPopup(this); + SetPopup(iface); + m_popupInterface = iface; + + // Add initial choices to the interface + iface->Populate(n,choices); + + return true; +} + +wxPGOwnerDrawnComboBox::~wxPGOwnerDrawnComboBox() +{ + if ( m_popupInterface ) + m_popupInterface->ClearClientDatas(); +} + +// ---------------------------------------------------------------------------- +// wxPGOwnerDrawnComboBox item manipulation methods +// ---------------------------------------------------------------------------- + +void wxPGOwnerDrawnComboBox::Clear() +{ + wxASSERT( m_popupInterface ); + + m_popupInterface->Clear(); + + GetTextCtrl()->SetValue(wxEmptyString); +} + +void wxPGOwnerDrawnComboBox::Delete(wxODCIndex n) +{ + wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxPGOwnerDrawnComboBox::Delete") ); + + if ( GetSelection() == (int) n ) + SetValue(wxEmptyString); + + m_popupInterface->Delete(n); +} + +wxODCCount wxPGOwnerDrawnComboBox::GetCount() const +{ + wxASSERT( m_popupInterface ); + return m_popupInterface->GetCount(); +} + +wxString wxPGOwnerDrawnComboBox::GetString(wxODCIndex n) const +{ + wxCHECK_MSG( (n >= 0) && (n < GetCount()), wxEmptyString, _T("invalid index in wxPGOwnerDrawnComboBox::GetString") ); + return m_popupInterface->GetString(n); +} + +void wxPGOwnerDrawnComboBox::SetString(wxODCIndex n, const wxString& s) +{ + wxCHECK_RET( (n >= 0) && (n < GetCount()), _T("invalid index in wxPGOwnerDrawnComboBox::SetString") ); + m_popupInterface->SetString(n,s); +} + +int wxPGOwnerDrawnComboBox::FindString(const wxString& s) const +{ + wxASSERT( m_popupInterface ); + return m_popupInterface->FindString(s); +} + +void wxPGOwnerDrawnComboBox::Select(int n) +{ + wxCHECK_RET( (n >= -1) && (n < (int)GetCount()), _T("invalid index in wxPGOwnerDrawnComboBox::Select") ); + wxASSERT( m_popupInterface ); + + m_popupInterface->SetSelection(n); + + wxString str; + if ( n >= 0 ) + str = m_popupInterface->GetString(n); + + // Refresh text portion in control + if ( m_text ) + m_text->SetValue( str ); + else + m_valueString = str; + + Refresh(); +} + +int wxPGOwnerDrawnComboBox::GetSelection() const +{ + wxASSERT( m_popupInterface ); + return m_popupInterface->GetSelection(); +} + +int wxPGOwnerDrawnComboBox::DoAppend(const wxString& item) +{ + wxASSERT( m_popupInterface ); + return m_popupInterface->Append(item); +} + +int wxPGOwnerDrawnComboBox::DoInsert(const wxString& item, wxODCIndex pos) +{ + wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list")); + wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index")); + + m_popupInterface->Insert(item,pos); + + return pos; +} + +#if wxCHECK_VERSION(2,9,0) +int wxPGOwnerDrawnComboBox::DoInsertItems(const wxArrayStringsAdapter& items, + unsigned int pos, + void **clientData, + wxClientDataType type) +{ + unsigned int i; + for ( i=0; iSetItemClientData(n,clientData, +#if wxCHECK_VERSION(2,9,0) + GetClientDataType() +#else + m_clientDataItemsType +#endif + ); +} + +void* wxPGOwnerDrawnComboBox::DoGetItemClientData(wxODCIndex n) const +{ + wxASSERT(m_popupInterface); + return m_popupInterface->GetItemClientData(n); +} + +void wxPGOwnerDrawnComboBox::DoSetItemClientObject(wxODCIndex n, wxClientData* clientData) +{ + DoSetItemClientData(n, (void*) clientData); +} + +wxClientData* wxPGOwnerDrawnComboBox::DoGetItemClientObject(wxODCIndex n) const +{ + return (wxClientData*) DoGetItemClientData(n); +} + +#endif // wxUSE_COMBOBOX diff --git a/assdraw/libpropgrid/propgrid.cpp b/assdraw/libpropgrid/propgrid.cpp new file mode 100644 index 000000000..af23e6d06 --- /dev/null +++ b/assdraw/libpropgrid/propgrid.cpp @@ -0,0 +1,13298 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: propgrid.cpp +// Purpose: wxPropertyGrid +// Author: Jaakko Salli +// Modified by: +// Created: Sep-25-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "propgrid.h" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" + #include "wx/object.h" + #include "wx/hash.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/event.h" + #include "wx/window.h" + #include "wx/panel.h" + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/dcmemory.h" + #include "wx/button.h" + #include "wx/pen.h" + #include "wx/brush.h" + #include "wx/cursor.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/msgdlg.h" + #include "wx/choice.h" + #include "wx/stattext.h" + #include "wx/scrolwin.h" + #include "wx/dirdlg.h" + #include "wx/combobox.h" + #include "wx/layout.h" + #include "wx/sizer.h" + #include "wx/textdlg.h" + #include "wx/filedlg.h" + #include "wx/statusbr.h" + #include "wx/intl.h" + #include "wx/frame.h" +#endif + + +#include "wx/timer.h" +#include "wx/dcbuffer.h" + + +// This define is necessary to prevent macro clearing +#define __wxPG_SOURCE_FILE__ + +#include + +#include + +#ifdef __WXPYTHON__ + #include + #include +#endif + +#if wxPG_USE_RENDERER_NATIVE + #include +#endif + +#include + +#ifdef __WXMSW__ + #include +#endif + + +// Two pics for the expand / collapse buttons. +// Files are not supplied with this project (since it is +// recommended to use either custom or native rendering). +// If you want them, get wxTreeMultiCtrl by Jorgen Bodde, +// and copy xpm files from archive to wxPropertyGrid src directory +// (and also comment/undef wxPG_ICON_WIDTH in propGrid.h +// and set wxPG_USE_RENDERER_NATIVE to 0). +#ifndef wxPG_ICON_WIDTH + #if defined(__WXMAC__) + #include "mac_collapse.xpm" + #include "mac_expand.xpm" + #elif defined(__WXGTK__) + #include "linux_collapse.xpm" + #include "linux_expand.xpm" + #else + #include "default_collapse.xpm" + #include "default_expand.xpm" + #endif +#endif + + +//#define wxPG_TEXT_INDENT 4 // For the wxComboControl +#define wxPG_ALLOW_CLIPPING 1 // If 1, GetUpdateRegion() in OnPaint event handler is not ignored +#define wxPG_GUTTER_DIV 3 // gutter is max(iconwidth/gutter_div,gutter_min) +#define wxPG_GUTTER_MIN 3 // gutter before and after image of [+] or [-] +#define wxPG_YSPACING_MIN 1 +#define wxPG_BUTTON_SIZEDEC 0 +#define wxPG_DEFAULT_VSPACING 2 // This matches .NET propertygrid's value, + // but causes normal combobox to spill out under MSW + +#define wxPG_OPTIMAL_WIDTH 200 // Arbitrary + +#define wxPG_CAPRECTXMARGIN 2 // space between caption and selection rectangle, +#define wxPG_CAPRECTYMARGIN 1 // horizontally and vertically + +#define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's + // value field. + +#define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing + + +#define wxPG_MIN_SCROLLBAR_WIDTH 10 // Smallest scrollbar width on any platform + // Must be larger than largest control border + // width * 2. + + +#define wxPG_DEFAULT_CURSOR wxNullCursor +#define RedrawAllVisible Refresh + + +// +// Here are some extra platform dependent defines. +// + +#if defined(__WXMSW__) + // tested + + #define wxPG_DEFAULT_SPLITTERX 110 // default splitter position + + #define wxPG_CREATE_CONTROLS_HIDDEN 0 // 1 to create controls out of sight, hide them, and then move them into correct position + + #define wxPG_NO_CHILD_EVT_MOTION 0 // 1 if splitter drag detect margin and control cannot overlap + + #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. + + #define wxPG_ALLOW_EMPTY_TOOLTIPS 1 // If 1, then setting empty tooltip actually hides it + + #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. + #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. + + #define wxPG_NAT_BUTTON_BORDER_ANY 1 + #define wxPG_NAT_BUTTON_BORDER_X 1 + #define wxPG_NAT_BUTTON_BORDER_Y 1 + + #define wxPG_TEXTCTRLYADJUST (m_spacingy+0) + + #define wxPG_CHOICEXADJUST (-1) // Extra pixels next to wxChoice/ComboBox. + #define wxPG_CHOICEYADJUST 0 // Extra pixels above wxChoice/ComboBox. + + #define wxPG_REFRESH_CONTROLS_AFTER_REPAINT 0 // If 1 then controls are refreshed after selected was drawn. + + #define wxPG_CHECKMARK_XADJ 1 + #define wxPG_CHECKMARK_YADJ (-1) + #define wxPG_CHECKMARK_WADJ 0 + #define wxPG_CHECKMARK_HADJ 0 + #define wxPG_CHECKMARK_DEFLATE 0 + +#elif defined(__WXGTK__) + // tested + + #define wxPG_DEFAULT_SPLITTERX 110 + + #define wxPG_CREATE_CONTROLS_HIDDEN 0 // 1 to create controls out of sight, hide them, and then move them into correct position + + #define wxPG_NO_CHILD_EVT_MOTION 1 // 1 if splitter drag detect margin and control cannot overlap + + #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. + + #define wxPG_ALLOW_EMPTY_TOOLTIPS 0 // If 1, then setting empty tooltip actually hides it + + #define wxPG_NAT_TEXTCTRL_BORDER_X 3 // Unremovable border of native textctrl. + #define wxPG_NAT_TEXTCTRL_BORDER_Y 3 // Unremovable border of native textctrl. + + #define wxPG_NAT_BUTTON_BORDER_ANY 1 + #define wxPG_NAT_BUTTON_BORDER_X 1 + #define wxPG_NAT_BUTTON_BORDER_Y 1 + + #define wxPG_TEXTCTRLYADJUST 0 + + #define wxPG_CHOICEXADJUST 2 // Extra pixels next to wxChoice/ComboBox. + #define wxPG_CHOICEYADJUST 0 + + #define wxPG_REFRESH_CONTROLS_AFTER_REPAINT 1 // If 1 then controls are refreshed after selected was drawn. + + #define wxPG_CHECKMARK_XADJ 0 + #define wxPG_CHECKMARK_YADJ 0 + #define wxPG_CHECKMARK_WADJ (-1) + #define wxPG_CHECKMARK_HADJ (-1) + #define wxPG_CHECKMARK_DEFLATE 3 + +#elif defined(__WXMAC__) + // *not* tested + + #define wxPG_DEFAULT_SPLITTERX 110 + + #define wxPG_CREATE_CONTROLS_HIDDEN 0 // 1 to create controls out of sight, hide them, and then move them into correct position + + #define wxPG_NO_CHILD_EVT_MOTION 0 // 1 if splitter drag detect margin and control cannot overlap + + #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. + + #define wxPG_ALLOW_EMPTY_TOOLTIPS 1 // If 1, then setting empty tooltip actually hides it + + #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. + #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. + + #define wxPG_NAT_BUTTON_BORDER_ANY 0 + #define wxPG_NAT_BUTTON_BORDER_X 0 + #define wxPG_NAT_BUTTON_BORDER_Y 0 + + #define wxPG_TEXTCTRLYADJUST 3 + + #define wxPG_CHOICEXADJUST 0 // Extra pixels next to wxChoice/ComboBox. + #define wxPG_CHOICEYADJUST 0 + + #define wxPG_REFRESH_CONTROLS_AFTER_REPAINT 0 // If 1 then controls are refreshed after selected was drawn. + + #define wxPG_CHECKMARK_XADJ 0 + #define wxPG_CHECKMARK_YADJ 0 + #define wxPG_CHECKMARK_WADJ 0 + #define wxPG_CHECKMARK_HADJ 0 + #define wxPG_CHECKMARK_DEFLATE 0 + +#else + // defaults + + #define wxPG_DEFAULT_SPLITTERX 110 + + #define wxPG_CREATE_CONTROLS_HIDDEN 0 // 1 to create controls out of sight, hide them, and then move them into correct position + + #define wxPG_NO_CHILD_EVT_MOTION 1 // 1 if splitter drag detect margin and control cannot overlap + + #define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. + + #define wxPG_ALLOW_EMPTY_TOOLTIPS 0 // If 1, then setting empty tooltip actually hides it + + #define wxPG_NAT_TEXTCTRL_BORDER_X 0 // Unremovable border of native textctrl. + #define wxPG_NAT_TEXTCTRL_BORDER_Y 0 // Unremovable border of native textctrl. + + #define wxPG_NAT_BUTTON_BORDER_ANY 0 + #define wxPG_NAT_BUTTON_BORDER_X 0 + #define wxPG_NAT_BUTTON_BORDER_Y 0 + + #define wxPG_TEXTCTRLYADJUST 0 + + #define wxPG_CHOICEXADJUST 0 // Extra pixels next to wxChoice/ComboBox. + #define wxPG_CHOICEYADJUST 0 + + #define wxPG_REFRESH_CONTROLS_AFTER_REPAINT 1 // If 1 then controls are refreshed after selected was drawn. + + #define wxPG_CHECKMARK_XADJ 0 + #define wxPG_CHECKMARK_YADJ 0 + #define wxPG_CHECKMARK_WADJ 0 + #define wxPG_CHECKMARK_HADJ 0 + #define wxPG_CHECKMARK_DEFLATE 0 + +#endif + + +#if wxPG_NO_CHILD_EVT_MOTION + + #define wxPG_SPLITTERX_DETECTMARGIN1 3 // this much on left + #define wxPG_SPLITTERX_DETECTMARGIN2 2 // this much on right + #define wxPG_CONTROL_MARGIN 0 // space between splitter and control + +#else + + #define wxPG_SPLITTERX_DETECTMARGIN1 3 // this much on left + #define wxPG_SPLITTERX_DETECTMARGIN2 2 // this much on right + #define wxPG_CONTROL_MARGIN 0 // space between splitter and control + +#endif + + +#define wxCC_CUSTOM_IMAGE_MARGIN1 4 // before image +#define wxCC_CUSTOM_IMAGE_MARGIN2 5 // after image + + +#if (!wxPG_NAT_TEXTCTRL_BORDER_X && !wxPG_NAT_TEXTCTRL_BORDER_Y) + #define wxPG_ENABLE_CLIPPER_WINDOW 0 +#else + #define wxPG_ENABLE_CLIPPER_WINDOW 1 +#endif + + +//#define wxPG_NAT_CHOICE_BORDER_ANY 0 + + +// for odcombo +#undef wxPG_CHOICEXADJUST +#define wxPG_CHOICEXADJUST 0 +#undef wxPG_CHOICEYADJUST +#define wxPG_CHOICEYADJUST 0 + +#define wxPG_DRAG_MARGIN 30 + +#define wxPG_CUSTOM_IMAGE_SPACINGY 1 // space between vertical sides of a custom image + +// Use this macro to generate standard custom image height from +#define wxPG_STD_CUST_IMAGE_HEIGHT(LINEHEIGHT) (LINEHEIGHT-3) + +// How many pixels between textctrl and button +#ifdef __WXMAC__ + #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 8 +#else + #define wxPG_TEXTCTRL_AND_BUTTON_SPACING 2 +#endif + +#define wxPG_HIDER_BUTTON_HEIGHT 25 + +// m_expanded of wxPGPropertyWithChildren is set to this code if children should +// not be deleted in destructor. +#define wxPG_EXP_OF_COPYARRAY 127 + +#define wxPG_PIXELS_PER_UNIT m_lineHeight + +#ifdef wxPG_ICON_WIDTH + #define m_iconHeight m_iconWidth +#endif + +#define wxPG_TOOLTIP_DELAY 1000 + +// Colour for the empty but visible space below last property. +#define wxPG_SLACK_BACKROUND m_colPropBack + +// Milliseconds to wait for two mouse-ups after focus inorder +// to trigger a double-click. +#define DOUBLE_CLICK_CONVERSION_TRESHOLD 500 + + +// +// Parenting types +enum +{ + PT_CUSTOMPROPERTY = -2, + PT_FIXEDCHILDREN = -1, + PT_NONE = 0, + PT_CAPTION = 1, + PT_ROOT = 2 +}; + + +// Helper to decide which way is better (ie. first macro clears +// "unspecified" state of siblings of child properties as well, while the latter is +// more precise). +//#define CLEAR_PROPERTY_UNSPECIFIED_FLAG(p) wxPropertyGridState::ClearPropertyAndChildrenFlags(p,wxPG_PROP_UNSPECIFIED) +#define CLEAR_PROPERTY_UNSPECIFIED_FLAG(p) p->ClearFlag(wxPG_PROP_UNSPECIFIED) + +#define __INTENSE_DEBUGGING__ 0 +#define __PAINT_DEBUGGING__ 0 +#define __MOUSE_DEBUGGING__ 0 + + +// ----------------------------------------------------------------------- + +#if wxUSE_INTL +void wxPropertyGrid::AutoGetTranslation ( bool enable ) +{ + WX_PG_GLOBALS_LOCKER() + + wxPGGlobalVars->m_autoGetTranslation = enable; +} +#else +void wxPropertyGrid::AutoGetTranslation ( bool ) { } +#endif + +// ----------------------------------------------------------------------- + +// This was needed to make quicker progress towards wxPropertyGridState +#define FROM_STATE(X) m_pState->X + + +// ----------------------------------------------------------------------- + +#if !wxCHECK_VERSION(2, 7, 1) + +#if defined(__WXMSW__) + +#ifndef WS_EX_COMPOSITED + #define WS_EX_COMPOSITED 0x02000000L +#endif +static bool wxPGIsWindowBuffered( const wxWindow* wnd ) +{ + while ( wnd ) + { + if ( GetWindowLong((HWND)wnd->GetHWND(), GWL_EXSTYLE) & WS_EX_COMPOSITED ) + return true; + if ( wnd->IsTopLevel() ) + break; + wnd = wnd->GetParent(); + } + + return false; +} + +#elif defined(__WXGTK20__) + +#include +static bool wxPGIsWindowBuffered( const wxWindow* wnd ) +{ + return GTK_WIDGET_DOUBLE_BUFFERED(wnd->GetHandle()); +} + +#elif defined(__WXMAC_OSX__) || defined(__WXCOCOA__) || defined(__WXDFB__) + +static bool wxPGIsWindowBuffered( const wxWindow* WXUNUSED(wnd) ) +{ + return true; +} + +#else + +static bool wxPGIsWindowBuffered( const wxWindow* WXUNUSED(wnd) ) +{ + return false; +} + +#endif + +#else + +static bool wxPGIsWindowBuffered( const wxWindow* wnd ) +{ + return wnd->IsDoubleBuffered(); +} + +#endif + + +// ----------------------------------------------------------------------- + +// DeviceContext Init Macros. + +#define wxPG_CLIENT_DC_INIT() \ + wxClientDC dc(this); \ + PrepareDC(dc); + +#define wxPG_CLIENT_DC_INIT_R(RETVAL) \ + wxClientDC dc(this); \ + PrepareDC(dc); + +#define wxPG_PAINT_DC_INIT() \ + wxPaintDC dc(this); \ + PrepareDC(dc); + +// ----------------------------------------------------------------------- + +// For wxMSW cursor consistency, we must do mouse capturing even +// when using custom controls. + +#define BEGIN_MOUSE_CAPTURE \ + if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \ + { \ + CaptureMouse(); \ + m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \ + } + +#define END_MOUSE_CAPTURE \ + if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \ + { \ + ReleaseMouse(); \ + m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \ + } + +// ----------------------------------------------------------------------- +// NOTES +// ----------------------------------------------------------------------- + +// +// ----------------------------------------------------------------------- +// TODO +// ----------------------------------------------------------------------- +// + +// +// For Next Release: +// * Fix NULL(?) focus after odcombo closed. +// + +// ----------------------------------------------------------------------- + +const wxChar *wxPropertyGridNameStr = wxT("wxPropertyGrid"); + +const wxChar *wxPGTypeName_long = wxT("long"); +const wxChar *wxPGTypeName_bool = wxT("bool"); +const wxChar *wxPGTypeName_double = wxT("double"); +const wxChar *wxPGTypeName_wxString = wxT("string"); +const wxChar *wxPGTypeName_void = wxT("void*"); +const wxChar *wxPGTypeName_wxArrayString = wxT("arrstring"); + +#ifdef __WXPYTHON__ +const wxChar *wxPGTypeName_PyObject = wxT("PyObject"); +#endif + +// ----------------------------------------------------------------------- + +static void wxPGDrawFocusRect( wxDC& dc, const wxRect& rect ) +{ +#if defined(__WXMSW__) && !defined(__WXWINCE__) + /* + RECT mswRect; + mswRect.left = rect.x; + mswRect.top = rect.y; + mswRect.right = rect.x + rect.width; + mswRect.bottom = rect.y + rect.height; + HDC hdc = (HDC) dc.GetHDC(); + SetMapMode(hdc,MM_TEXT); // Just in case... + DrawFocusRect(hdc,&mswRect); + */ + // FIXME: Use DrawFocusRect code above (currently it draws solid line + // for caption focus but works ok for other stuff). + // Also, it seems that this code may not work in future wx versions. + dc.SetLogicalFunction(wxINVERT); + + wxPen pen(*wxBLACK,1,wxDOT); + pen.SetCap(wxCAP_BUTT); + dc.SetPen(pen); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(rect); + + dc.SetLogicalFunction(wxCOPY); +#else + dc.SetLogicalFunction(wxINVERT); + + dc.SetPen(wxPen(*wxBLACK,1,wxDOT)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(rect); + + dc.SetLogicalFunction(wxCOPY); +#endif +} + + +// ----------------------------------------------------------------------- +// Choice related methods from various classes +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::AddPropertyChoice( wxPGId id, + const wxString& label, + int value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + p->InsertChoice(label,-1,value); +} + + +void wxPropertyContainerMethods::InsertPropertyChoice( wxPGId id, + const wxString& label, + int index, + int value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + p->InsertChoice(label,index,value); +} + + +void wxPropertyContainerMethods::DeletePropertyChoice( wxPGId id, + int index ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + p->DeleteChoice(index); +} + + +// ----------------------------------------------------------------------- +// Statics in one class for easy destruction. +// NB: We prefer to use wxModule, as it offers more consistent behaviour +// across platforms. However, for those rare problem situations, we +// also need to offer option to use simpler approach. +// ----------------------------------------------------------------------- + +#ifndef wxPG_USE_WXMODULE + #define wxPG_USE_WXMODULE 1 +#endif + +#if wxPG_USE_WXMODULE + +#include + +class wxPGGlobalVarsClassManager : public wxModule +{ + DECLARE_DYNAMIC_CLASS(wxPGGlobalVarsClassManager) +public: + wxPGGlobalVarsClassManager() {} + virtual bool OnInit() { wxPGGlobalVars = new wxPGGlobalVarsClass(); return true; } + virtual void OnExit() { delete wxPGGlobalVars; wxPGGlobalVars = NULL; } +}; + +IMPLEMENT_DYNAMIC_CLASS(wxPGGlobalVarsClassManager, wxModule) + +#else // !wxPG_USE_WXMODULE + +class wxPGGlobalVarsClassManager +{ +public: + wxPGGlobalVarsClassManager() {} + ~wxPGGlobalVarsClassManager() { delete wxPGGlobalVars; } +}; + +static wxPGGlobalVarsClassManager gs_pgGlobalVarsClassManager; + +#endif + + +wxPGGlobalVarsClass* wxPGGlobalVars = (wxPGGlobalVarsClass*) NULL; + + +wxPGGlobalVarsClass::wxPGGlobalVarsClass() +{ + m_boolChoices[0] = _("False"); + m_boolChoices[1] = _("True"); + m_boolChoices[2] = _("Unspecified"); + m_numBoolChoices = 2; + + m_fontFamilyChoices = (wxPGChoices*) NULL; + + m_autoGetTranslation = false; + + m_offline = 0; +} + + +wxPGGlobalVarsClass::~wxPGGlobalVarsClass() +{ + size_t i; + + // This will always have one ref + delete m_fontFamilyChoices; + +#if wxUSE_VALIDATORS + for ( i=0; isecond; + wxASSERT( pcls ); + delete pcls; + } + + // Destroy editor class instances. + // iterate over all the elements in the class + for( vt_it = m_mapEditorClasses.begin(); vt_it != m_mapEditorClasses.end(); ++vt_it ) + { + delete ((wxPGEditor*)vt_it->second); + } +} + +// ----------------------------------------------------------------------- +// wxPGProperty +// ----------------------------------------------------------------------- + +wxPGPropertyClassInfo wxBasePropertyClassInfo = {wxT("wxBaseProperty"), + (const wxPGPropertyClassInfo*) NULL, + (wxPGPropertyConstructor) NULL}; + +void wxPGProperty::Init() +{ +#ifdef __WXPYTHON__ + m_scriptObject = NULL; +#endif + + m_y = -3; + m_arrIndex = 0xFFFF; + m_parent = (wxPGPropertyWithChildren*) NULL; + +#if wxPG_USE_CLIENT_DATA + m_clientData = NULL; +#endif + + m_dataExt = (wxPGPropertyDataExt*) NULL; + + m_maxLen = 0; // infinite maximum length + + m_flags = 0; + + m_depth = 1; + m_parentingType = 0; + m_bgColIndex = 0; + m_fgColIndex = 0; +} + + +void wxPGProperty::Init( const wxString& label, const wxString& name ) +{ + m_label = label; +#ifndef __WXPYTHON__ + if ( &name != ((wxString*)NULL) ) +#else + if ( (&name != ((wxString*)NULL)) && name != wxT("_LABEL_AS_NAME") ) +#endif + DoSetName( name ); + else + DoSetName( label ); + + Init(); +} + +wxPGProperty::wxPGProperty() +#if wxPG_INCLUDE_WXOBJECT + : wxObject() +#endif +{ + Init(); +} + + +wxPGProperty::wxPGProperty( const wxString& label, const wxString& name ) +#if wxPG_INCLUDE_WXOBJECT + : wxObject() +#endif +{ + Init( label, name ); +} + + +wxPGProperty::~wxPGProperty() +{ +#ifdef __WXPYTHON__ + #if wxPG_USE_CLIENT_DATA + if ( m_clientData ) + Py_DECREF( m_clientData ); + #endif +#endif + + delete m_dataExt; +} + + +bool wxPGProperty::IsSomeParent( wxPGProperty* candidate ) const +{ + wxPGPropertyWithChildren* parent = m_parent; + do + { + if ( parent == (wxPGPropertyWithChildren*)candidate ) + return true; + parent = parent->m_parent; + } while ( parent ); + return false; +} + + +wxPropertyGridState* wxPGProperty::GetParentState() const +{ + wxASSERT( m_parent ); + return m_parent->GetParentState(); +} + + +size_t wxPGProperty::GetChildCount() const +{ + int cc = GetParentingType(); + if ( cc == 0 ) return 0; + return ((wxPGPropertyWithChildren*)this)->GetCount(); +} + + +void wxPGProperty::ShowError( const wxString& msg ) +{ + if ( !msg.length() ) + return; + +#if wxUSE_STATUSBAR + if ( !wxPGGlobalVars->m_offline ) + { + wxPropertyGrid* pg = GetParentState()->m_pPropGrid; + wxASSERT(pg); + wxWindow* topWnd = ::wxGetTopLevelParent(pg); + if ( topWnd ) + { + wxFrame* pFrame = wxDynamicCast(topWnd,wxFrame); + if ( pFrame ) + { + wxStatusBar* pStatusBar = pFrame->GetStatusBar(); + if ( pStatusBar ) + { + pStatusBar->SetStatusText(msg); + return; + } + } + } + } +#endif + ::wxLogError(msg); +} + + +wxPropertyGrid* wxPGProperty::GetGrid() const +{ + return GetParentState()->GetGrid(); +} + + +void wxPGProperty::UpdateControl( wxWindow* primary ) +{ + if ( primary ) + GetEditorClass()->UpdateControl(this,primary); +} + + +void wxPGProperty::DoSetValue( wxPGVariant ) +{ + // Actually, this should never get called + wxFAIL_MSG( wxT("must be overridden") ); +} + + +// wxPGRootPropertyClass, at least, should make use of this. +wxPGVariant wxPGProperty::DoGetValue() const +{ + return wxPGVariant((long)0); +} + + +wxString wxPGProperty::GetValueAsString( int ) const +{ + wxFAIL_MSG( wxT("must be overridden") ); + return m_name; +} + +wxVariant wxPGProperty::GetValueAsVariant() const +{ + // Return NULL variant for unspecified value + //if ( HasFlag(wxPG_PROP_UNSPECIFIED) ) + // return wxVariant(); + + wxPGVariant value = DoGetValue(); + const wxPGValueType* typeClass = GetValueTypePtr(); + wxASSERT_MSG( typeClass, wxT("Did you forgot to use wxPG_INIT_REQUIRED_TYPE(T) in constructor?") ); + return typeClass->GenerateVariant(value,m_name); +} + +bool wxPGProperty::SetValueFromString( const wxString&, int ) +{ + wxFAIL_MSG( wxT("must be overridden") ); + return false; +} + + +bool wxPGProperty::SetValueFromInt( long, int ) +{ + wxFAIL_MSG ( wxT("must be overridden") ); + return false; +} + + +wxSize wxPGProperty::GetImageSize() const +{ + if ( m_dataExt && m_dataExt->m_valueBitmap ) + return wxSize(m_dataExt->m_valueBitmap->GetWidth(),-1); + + return wxSize(0,0); +} + + +void wxPGProperty::OnCustomPaint( wxDC& dc, + const wxRect& rect, + wxPGPaintData& ) +{ + wxCHECK_RET( m_dataExt, wxT("m_dataExt is mandatory") ); + + wxBitmap* bmp = m_dataExt->m_valueBitmap; + + wxCHECK_RET( bmp && bmp->Ok(), wxT("invalid bitmap") ); + + wxCHECK_RET( rect.x >= 0, wxT("unexpected measure call") ); + + dc.DrawBitmap(*bmp,rect.x,rect.y); +} + +const wxPGEditor* wxPGProperty::DoGetEditorClass() const +{ + return wxPG_EDITOR(TextCtrl); +} + + +#ifdef __WXPYTHON__ +wxString wxPGProperty::GetEditor() const +{ + return wxEmptyString; +} +#endif + +#ifdef __WXPYTHON__ +wxString wxPGProperty::GetType() const +{ + return wxString(); +} + +const wxPGValueType* wxPGProperty::GetValueType() const +{ + wxString s = GetType(); + + const wxPGValueType* p = wxPropertyContainerMethods::GetValueType(s); + + wxCHECK_MSG( p, wxPG_VALUETYPE(none), + wxT("GetType must return string that identifies a valid type") ); + + return p; +} +#endif + +#if wxPG_VALUETYPE_IS_STRING +const wxPGValueType* wxPGProperty::GetValueTypePtr() const +{ + return wxPropertyContainerMethods::GetValueTypeByName(GetValueType()); +} +#endif + + +// Default extra property event handling - that is, none at all. +bool wxPGProperty::OnEvent( wxPropertyGrid*, wxWindow*, wxEvent& ) +{ + return false; +} + + +void wxPGProperty::SetChoiceSelection( int newValue, const wxPGChoiceInfo& choiceInfo ) +{ + // Changes value of a property with choices, but only + // works if the value type is long or string. + const wxPGValueType* vt = GetValueTypePtr(); + + wxCHECK_RET( choiceInfo.m_choices, wxT("invalid choiceinfo") ); + + if ( vt == wxPG_VALUETYPE_PTR(long) ) + { + DoSetValue( (long) newValue ); + } + else if ( vt == wxPG_VALUETYPE_PTR(wxString) ) + { + DoSetValue( choiceInfo.m_choices->GetLabel(newValue) ); + } +} + + +int wxPGProperty::InsertChoice( const wxString& label, int index, int value ) +{ + wxPropertyGrid* pg = GetGrid(); + + wxPGChoiceInfo ci; + ci.m_choices = (wxPGChoices*) NULL; + int sel = GetChoiceInfo(&ci); + + if ( ci.m_choices ) + { + int newSel = sel; + + if ( index < 0 ) + index = ci.m_choices->GetCount(); + + if ( index <= sel ) + newSel++; + + ci.m_choices->Insert(label, index, value); + + if ( sel != newSel ) + SetChoiceSelection(newSel, ci); + + if ( this == wxPGIdToPtr(pg->GetSelection()) ) + GetEditorClass()->InsertItem(pg->GetPrimaryEditor(),label,index); + + return index; + } + + return -1; +} + + +void wxPGProperty::DeleteChoice( int index ) +{ + wxPropertyGrid* pg = GetGrid(); + + wxPGChoiceInfo ci; + ci.m_choices = (wxPGChoices*) NULL; + int sel = GetChoiceInfo(&ci); + + if ( ci.m_choices ) + { + int newSel = sel; + + // Adjust current value + if ( sel == index ) + { + SetFlag( wxPG_PROP_UNSPECIFIED ); + newSel = 0; + } + else if ( index < sel ) + { + newSel--; + } + + ci.m_choices->RemoveAt(index); + + if ( sel != newSel ) + SetChoiceSelection(newSel, ci); + + if ( this == wxPGIdToPtr(pg->GetSelection()) ) + GetEditorClass()->DeleteItem(pg->GetPrimaryEditor(), index); + } +} + + +int wxPGProperty::GetChoiceInfo( wxPGChoiceInfo* ) +{ + return 0; +} + + +void wxPGProperty::SetAttribute( int, wxVariant& ) +{ +} + + +#if wxUSE_VALIDATORS +wxValidator* wxPGProperty::DoGetValidator() const +{ + return (wxValidator*) NULL; +} +#endif + + +bool wxPGProperty::SetChoices( wxPGChoices& choices ) +{ + wxPGChoiceInfo ci; + ci.m_choices = (wxPGChoices*) NULL; + + // Unref existing + GetChoiceInfo(&ci); + if ( ci.m_choices ) + { + ci.m_choices->Assign(choices); + + // This may be needed to trigger some initialization + // (but don't do it if property is somewhat uninitialized) + if ( m_parent ) + DoSetValue(GetValueTypePtr()->GetDefaultValue()); + + return true; + } + return false; +} + + +const wxPGEditor* wxPGProperty::GetEditorClass() const +{ + const wxPGEditor* editor; + + if ( !m_dataExt || !m_dataExt->m_customEditor ) + { +#ifdef __WXPYTHON__ + wxString editorName = GetEditor(); + if ( editorName.length() ) + editor = wxPropertyContainerMethods::GetEditorByName(editorName); + else +#endif + editor = DoGetEditorClass(); + } + else + { + editor = m_dataExt->m_customEditor; + } + + return editor; +} + + +bool wxPGProperty::IsKindOf( wxPGPropertyClassInfo& info ) +{ + const wxPGPropertyClassInfo* ownInfo = GetClassInfo(); + + do + { + if ( ownInfo == &info ) + return true; + + ownInfo = ownInfo->m_baseInfo; + } while ( ownInfo ); + + return false; +} + + +// Privatizes set of choices +void wxPGProperty::SetChoicesExclusive() +{ + wxPGChoiceInfo ci; + ci.m_choices = (wxPGChoices*) NULL; + + GetChoiceInfo(&ci); + if ( ci.m_choices ) + ci.m_choices->SetExclusive(); +} + + +bool wxPGProperty::PrepareValueForDialogEditing( wxPropertyGrid* propGrid ) +{ + wxWindow* primary = propGrid->GetEditorControl(); + if ( primary && propGrid->IsEditorsValueModified() ) + { + GetEditorClass()->CopyValueFromControl( this, primary ); + return true; + } + else if ( m_flags & wxPG_PROP_UNSPECIFIED ) + { + // Set default value in case it was unspecified + DoSetValue(GetValueTypePtr()->GetDefaultValue()); + } + return false; +} + + +bool wxPGProperty::RecreateEditor() +{ + wxPropertyGrid* pg = GetGrid(); + wxASSERT(pg); + + wxPGProperty* selected = pg->GetSelection(); + if ( this == selected ) + { + pg->DoSelectProperty(this, wxPG_SEL_FORCE); + return true; + } + return false; +} + + +bool wxPGProperty::EnsureDataExt() +{ + if ( !m_dataExt ) + { + m_dataExt = new wxPGPropertyDataExt(); + return true; + } + return false; +} + + +void wxPGProperty::SetValueImage( wxBitmap& bmp ) +{ + EnsureDataExt(); + + delete m_dataExt->m_valueBitmap; + + if ( &bmp && bmp.Ok() ) + { + // Resize the image + wxSize maxSz = GetGrid()->GetImageSize(); + wxSize imSz(bmp.GetWidth(),bmp.GetHeight()); + + if ( imSz.x != maxSz.x || imSz.y != maxSz.y ) + { + // Create a memory DC + wxBitmap* bmpNew = new wxBitmap(maxSz.x,maxSz.y,bmp.GetDepth()); + + wxMemoryDC dc; + dc.SelectObject(*bmpNew); + + // Scale + // FIXME: This is ugly - use image or wait for scaling patch. + double scaleX = (double)maxSz.x / (double)imSz.x; + double scaleY = (double)maxSz.y / (double)imSz.y; + + dc.SetUserScale(scaleX,scaleY); + + dc.DrawBitmap( bmp, 0, 0 ); + + m_dataExt->m_valueBitmap = bmpNew; + } + else + m_dataExt->m_valueBitmap = new wxBitmap(bmp); + + m_flags |= wxPG_PROP_CUSTOMIMAGE; + } + else + { + m_dataExt->m_valueBitmap = (wxBitmap*) NULL; + m_flags &= ~(wxPG_PROP_CUSTOMIMAGE); + } +} + + +wxPGProperty* wxPGProperty::GetMainParent() const +{ + const wxPGProperty* curChild = this; + const wxPGPropertyWithChildren* curParent = m_parent; + + while ( curParent->m_parentingType < 0 ) + { + curChild = curParent; + curParent = curParent->m_parent; + } + + return (wxPGProperty*) curChild; +} + + +const wxPGProperty* wxPGProperty::GetLastVisibleSubItem() const +{ + // + // Returns last visible sub-item, recursively. + + if ( GetParentingType() == PT_NONE ) + return this; + + const wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) this; + + unsigned int count = pwc->GetCount(); + + if ( !pwc->IsExpanded() || !count ) + return this; + + return pwc->Last()->GetLastVisibleSubItem(); +} + + +bool wxPGProperty::UsesAutoUnspecified() const +{ + if ( GetGrid()->GetExtraStyle() & wxPG_EX_AUTO_UNSPECIFIED_VALUES ) + return true; + + return false; +} + + +// ----------------------------------------------------------------------- +// wxPGPropertyWithChildren +// ----------------------------------------------------------------------- + + +wxPGPropertyClassInfo wxBaseParentPropertyClassInfo = {wxT("wxBaseParentProperty"), + &wxBasePropertyClassInfo, + (wxPGPropertyConstructor) NULL}; + + +wxPGPropertyWithChildren::wxPGPropertyWithChildren() + : wxPGProperty() +{ + m_expanded = 1; + m_y = -2; + m_parentingType = -1; +} + +wxPGPropertyWithChildren::wxPGPropertyWithChildren( const wxString &label, const wxString& name ) + : wxPGProperty(label,name) +{ + m_expanded = 1; + m_y = -2; + m_parentingType = -1; + m_parentState = (wxPropertyGridState*) NULL; +} + + +wxPGPropertyWithChildren::~wxPGPropertyWithChildren() +{ + Empty(); // this deletes items +} + + +// This is used by Insert etc. +void wxPGPropertyWithChildren::AddChild2( wxPGProperty* prop, int index, bool correct_mode ) +{ + if ( index < 0 || (size_t)index >= m_children.GetCount() ) + { + if ( correct_mode ) prop->m_arrIndex = m_children.GetCount(); + m_children.Add( (void*)prop ); + } + else + { + m_children.Insert( (void*)prop, index ); + if ( correct_mode ) FixIndexesOfChildren( index ); + } + + prop->m_parent = this; +} + +// This is used by properties that have fixed sub-properties +void wxPGPropertyWithChildren::AddChild( wxPGProperty* prop ) +{ + prop->m_arrIndex = m_children.GetCount(); + m_children.Add( (void*)prop ); + + int custImgHeight = prop->GetImageSize().y; + if ( custImgHeight < 0 /*|| custImgHeight > 1*/ ) + prop->m_flags |= wxPG_PROP_CUSTOMIMAGE; + + prop->m_parent = this; + + prop->m_y = -1; // Collapsed +} + + +void wxPGPropertyWithChildren::FixIndexesOfChildren( size_t starthere ) +{ + size_t i; + for ( i=starthere;im_arrIndex = i; +} + + +// Returns (direct) child property with given name (or NULL if not found) +wxPGProperty* wxPGPropertyWithChildren::GetPropertyByName( const wxString& name ) const +{ + size_t i; + + for ( i=0; im_name == name ) + return p; + } + + // Does it have point, then? + int pos = name.Find(wxT('.')); + if ( pos <= 0 ) + return (wxPGProperty*) NULL; + + wxPGPropertyWithChildren* pwc = + (wxPGPropertyWithChildren*) GetPropertyByName(name.substr(0,pos)); + + if ( !pwc || !pwc->GetParentingType() ) + return (wxPGProperty*) NULL; + + return pwc->GetPropertyByName(name.substr(pos+1,name.length()-pos-1)); +} + + +wxPGProperty* wxPGPropertyWithChildren::GetItemAtY( unsigned int y, unsigned int lh ) +{ + // Linear search. + unsigned int i = 0; + unsigned int iMax = GetCount(); + unsigned long py = 0xFFFFFFFF; + wxPGProperty* p = (wxPGProperty*) NULL; + + while ( i < iMax ) + { + p = Item(i); + if ( p->m_y >= 0 ) + { + py = (unsigned long)p->m_y; + if ( (py+lh) > y ) + break; + } + i++; + } + if ( py <= y && i < iMax ) + { + // perfectly this item + wxASSERT_MSG( p, wxT("invalid property id") ); + return p; + } + else + { + + // If no visible children, we must retract our steps + // (should not really happen, so right now we check that it + // really doesn't). + if ( py == 0xFFFFFFFF ) + { + wxLogDebug(wxT("wxPropertyGrid: \"%s\" (y=%i) did not have visible children (it should)."),m_label.c_str(),(int)m_y); + return (wxPGProperty*) NULL; + } + + // We are about to return a child of previous' visible item. + + #ifdef __WXDEBUG__ + if ( i < 1 ) + { + wxLogDebug( wxT("WARNING: \"%s\"->GetItemAtY: (i <= 0)"), m_label.c_str() ); + wxLogDebug( wxT(" \\--> y = %i, py = %i"), (int)y, (int)py ); + if ( p ) + wxLogDebug( wxT(" \\--> p = \"%s\""), p->GetLabel().c_str() ); + else + wxLogDebug( wxT(" \\--> p = None") ); + return (wxPGProperty*) NULL; + } + #endif + + // Get previous *visible* parent. + wxPGPropertyWithChildren* pwc; + do + { + wxASSERT( i > 0 ); + i--; + pwc = (wxPGPropertyWithChildren*)Item(i); + } while ( pwc->m_y < 0 ); + + if ( pwc->GetParentingType() != 0 ) + { + #ifdef __WXDEBUG__ + if ( !pwc->m_expanded || pwc->m_y < 0 ) + { + wxLogDebug(wxT("WARNING: wxPGPropertyWithChildren::GetItemAtY: Item %s should have been visible and expanded."),pwc->m_label.c_str()); + wxLogDebug(wxT(" (%s[%i]: %s)"),pwc->m_parent->m_label.c_str(),pwc->m_arrIndex,pwc->m_label.c_str()); + //wxLogDebug(wxT(" py=%i"),(int)py); + return (wxPGProperty*) NULL; + } + #endif + return pwc->GetItemAtY(y,lh); + } + } + return (wxPGProperty*) NULL; +} + + +void wxPGPropertyWithChildren::Empty() +{ + size_t i; + if ( m_expanded != wxPG_EXP_OF_COPYARRAY ) + { + for ( i=0; i 0, + wxString(), + wxT("If user property does not have any children, it must override GetValueAsString.") ); + + wxString text; + + int i; + int iMax = m_children.GetCount(); + + if ( iMax > PWC_CHILD_SUMMARY_LIMIT && + !(argFlags & wxPG_FULL_VALUE) ) + iMax = PWC_CHILD_SUMMARY_LIMIT; + + int iMaxMinusOne = iMax-1; + + wxPGProperty* curChild = (wxPGProperty*) m_children.Item(0); + + for ( i = 0; i < iMax; i++ ) + { + wxString s; + if ( !(curChild->m_flags & wxPG_PROP_UNSPECIFIED) ) + s = curChild->GetValueAsString(argFlags); + + if ( curChild->GetParentingType() == 0 ) + text += s; + else + text += wxT("[") + s + wxT("]"); + + if ( i < iMaxMinusOne ) + { + if ( text.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT && + !(argFlags & wxPG_EDITABLE_VALUE) && + !(argFlags & wxPG_FULL_VALUE) ) + break; + + curChild = (wxPGProperty*) m_children.Item(i+1); + + if ( curChild->GetParentingType() == 0 ) + text += wxT("; "); + else + text += wxT(" "); + } + } + + if ( (unsigned int)i < m_children.GetCount() ) + text += wxT("; ..."); + + return text; +} + + +// Convert semicolon delimited tokens into child values. +bool wxPGPropertyWithChildren::SetValueFromString( const wxString& text, int argFlags ) +{ + if ( !GetCount() ) + return false; + + unsigned int curChild = 0; + + unsigned int iMax = m_children.GetCount(); + + if ( iMax > PWC_CHILD_SUMMARY_LIMIT && + !(argFlags & wxPG_FULL_VALUE) ) + iMax = PWC_CHILD_SUMMARY_LIMIT; + + bool changed = false; + + wxString token; + size_t pos = 0; + + // Its best only to add non-empty group items + bool addOnlyIfNotEmpty = false; + const wxChar delimeter = wxT(';'); + wxChar a; + + size_t lastPos = text.length(); + size_t tokenStart = 0xFFFFFF; + + do + { + a = text[pos]; + + if ( tokenStart != 0xFFFFFF ) + { + // Token is running + if ( a == delimeter || a == 0 ) + { + token = text.substr(tokenStart,pos-tokenStart); + token.Trim(true); + size_t len = token.length(); + + if ( !addOnlyIfNotEmpty || len > 0 ) + { + wxPGProperty* child = Item(curChild); + + if ( len > 0 ) + { + bool wasUnspecified = child->IsValueUnspecified(); + if ( child->SetValueFromString( token, wxPG_REPORT_ERROR ) ) + { + // If modified, set mod flag and store value back to parent + child->SetFlag( wxPG_PROP_MODIFIED ); + + // Clear unspecified flag only if SetValueFromString didn't + // affect it. + if ( child->IsValueUnspecified() && + (wasUnspecified || !UsesAutoUnspecified()) ) + child->ClearFlag( wxPG_PROP_UNSPECIFIED ); + + ChildChanged( child ); + changed = true; + } + + } + else + { + child->SetFlag( wxPG_PROP_UNSPECIFIED ); + changed = true; + } + + curChild++; + if ( curChild >= iMax ) + break; + } + + tokenStart = 0xFFFFFF; + } + } + else + { + // Token is not running + if ( a != wxT(' ') ) + { + + addOnlyIfNotEmpty = false; + + // Is this a group of tokens? + if ( a == wxT('[') ) + { + int depth = 1; + + pos++; + size_t startPos = pos; + + // Group item - find end + do + { + a = text[pos]; + pos++; + + if ( a == wxT(']') ) + depth--; + else if ( a == wxT('[') ) + depth++; + + } while ( depth > 0 && a ); + + token = text.substr(startPos,pos-startPos-1); + + if ( !token.length() ) + break; + + wxPGProperty* child = Item(curChild); + + //wxLogDebug(wxT("child(1) %i: %s"),curChild,token.c_str()); + + if ( child->SetValueFromString( token, wxPG_REPORT_ERROR ) ) + { + // If modified, set mod flag and store value back to parent + child->SetFlag( wxPG_PROP_MODIFIED ); + ChildChanged( child ); + changed = true; + } + + curChild++; + if ( curChild >= iMax ) + break; + + addOnlyIfNotEmpty = true; + + tokenStart = 0xFFFFFF; + } + else + { + tokenStart = pos; + + if ( a == delimeter ) + { + pos--; + } + } + } + + } + pos++; + + } + while ( pos <= lastPos ); + + // This ensures that the last item is set unspecified even + // if the blank had no terminating delimiter. + if ( curChild < iMax ) + { + wxPGProperty* child = Item(curChild); + + child->SetFlag( wxPG_PROP_UNSPECIFIED ); + changed = true; + } + + return changed; +} + + +void wxPGPropertyWithChildren::RefreshChildren () +{ +} + + +// ----------------------------------------------------------------------- +// wxParentProperty +// ----------------------------------------------------------------------- + +wxPGProperty* wxParentProperty( const wxString& label, const wxString& name ) +{ + return new wxParentPropertyClass(label,name); +} + + +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxParentProperty,none,TextCtrl) +WX_PG_IMPLEMENT_CLASSINFO(wxParentProperty,wxBaseParentPropertyClass) + + +wxParentPropertyClass::wxParentPropertyClass( const wxString& label, const wxString& name ) + : wxPGPropertyWithChildren(label,name) +{ + m_parentingType = PT_CUSTOMPROPERTY; +} + + +wxParentPropertyClass::~wxParentPropertyClass() { } + + +void wxParentPropertyClass::DoSetValue( wxPGVariant value ) +{ + const wxString& str = wxPGVariantToString(value); + m_string = str; + SetValueFromString(str,wxPG_REPORT_ERROR); +} + + +wxPGVariant wxParentPropertyClass::DoGetValue() const +{ + return wxPGVariant(); +} + + +void wxParentPropertyClass::ChildChanged( wxPGProperty* WXUNUSED(p) ) +{ +} + + +wxString wxParentPropertyClass::GetValueAsString( int argFlags ) const +{ + if ( !GetCount() ) + return wxEmptyString; + + return wxPGPropertyWithChildren::GetValueAsString(argFlags); +} + + +// ----------------------------------------------------------------------- +// wxPGRootPropertyClass +// ----------------------------------------------------------------------- + +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty,none,TextCtrl) +const wxPGPropertyClassInfo* wxPGRootPropertyClass::GetClassInfo() const +{ + return (const wxPGPropertyClassInfo*) NULL; +} + + +wxPGRootPropertyClass::wxPGRootPropertyClass() + : wxPGPropertyWithChildren() +{ + m_parentingType = PT_ROOT; // this was PT_CAPTION in <= 1.1.6, but changed + // so the depth calculations can become + // more consistent. + m_depth = 0; +} + + +wxPGRootPropertyClass::~wxPGRootPropertyClass() +{ +} + + +// ----------------------------------------------------------------------- +// wxPropertyCategoryClass +// ----------------------------------------------------------------------- + +wxPGProperty* wxPropertyCategory( const wxString& label, const wxString& name ) +{ + return new wxPropertyCategoryClass(label,name); +} + + +WX_PG_IMPLEMENT_CLASSINFO(wxPropertyCategory,wxBaseParentPropertyClass) + + +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory,none,TextCtrl) + + +wxPropertyCategoryClass::wxPropertyCategoryClass() + : wxPGPropertyWithChildren() +{ + // don't set colour - prepareadditem method should do this + m_parentingType = 1; + m_capFgColIndex = 1; +} + + +wxPropertyCategoryClass::wxPropertyCategoryClass( const wxString &label, const wxString& name ) + : wxPGPropertyWithChildren(label,name) +{ + // don't set colour - prepareadditem method should do this + m_parentingType = 1; + m_capFgColIndex = 1; +} + + +wxPropertyCategoryClass::~wxPropertyCategoryClass() +{ +} + + +wxString wxPropertyCategoryClass::GetValueAsString( int ) const +{ + return wxEmptyString; +} + + +void wxPropertyCategoryClass::CalculateTextExtent( wxWindow* wnd, wxFont& font ) +{ + int x = 0, y = 0; + wnd->GetTextExtent( m_label, &x, &y, 0, 0, &font ); + m_textExtent = x; +} + + +// ----------------------------------------------------------------------- +// wxPGEditor +// ----------------------------------------------------------------------- + +wxPGEditor::~wxPGEditor() +{ +} + + +void wxPGEditor::DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const +{ + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + dc.DrawText( property->GetDisplayedString(), rect.x+wxPG_XBEFORETEXT, rect.y ); +} + + +void wxPGEditor::SetControlStringValue( wxWindow*, const wxString& ) const +{ +} + + +void wxPGEditor::SetControlIntValue( wxWindow*, int ) const +{ +} + + +int wxPGEditor::InsertItem( wxWindow*, const wxString&, int ) const +{ + return -1; +} + + +void wxPGEditor::DeleteItem( wxWindow*, int ) const +{ + return; +} + + +void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const +{ +} + + +bool wxPGEditor::CanContainCustomImage() const +{ + return false; +} + +// ----------------------------------------------------------------------- +// wxPGClipperWindow +// ----------------------------------------------------------------------- + + +#if wxPG_ENABLE_CLIPPER_WINDOW + +// +// Clipper window is used to "remove" borders from controls +// which otherwise insist on having them despite of supplied +// wxNO_BORDER window style. +// +class wxPGClipperWindow : public wxWindow +{ + DECLARE_CLASS(wxPGClipperWindow) +public: + + wxPGClipperWindow() + : wxWindow() + { + wxPGClipperWindow::Init(); + } + + wxPGClipperWindow(wxWindow* parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize) + { + Init(); + Create(parent,id,pos,size); + } + + void Create(wxWindow* parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize); + + virtual ~wxPGClipperWindow(); + + virtual bool ProcessEvent(wxEvent& event); + + inline wxWindow* GetControl() const { return m_ctrl; } + + // This is called before wxControl is constructed. + void GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ); + + // This is caleed after wxControl has been constructed. + void SetControl( wxWindow* ctrl ); + + virtual void Refresh( bool eraseBackground = true, + const wxRect *rect = (const wxRect *) NULL ); + virtual void SetFocus(); + + virtual bool SetFont(const wxFont& font); + + inline int GetXClip() const { return m_xadj; } + + inline int GetYClip() const { return m_yadj; } + +protected: + wxWindow* m_ctrl; + + int m_xadj; // Horizontal border clip. + + int m_yadj; // Vertical border clip. + +private: + void Init () + { + m_ctrl = (wxWindow*) NULL; + } +}; + + +IMPLEMENT_CLASS(wxPGClipperWindow,wxWindow) + + +// This is called before wxControl is constructed. +void wxPGClipperWindow::GetControlRect( int xadj, int yadj, wxPoint& pt, wxSize& sz ) +{ + m_xadj = xadj; + m_yadj = yadj; + pt.x = -xadj; + pt.y = -yadj; + wxSize own_size = GetSize(); + sz.x = own_size.x+(xadj*2); + sz.y = own_size.y+(yadj*2); +} + + +// This is caleed after wxControl has been constructed. +void wxPGClipperWindow::SetControl( wxWindow* ctrl ) +{ + m_ctrl = ctrl; + + // GTK requires this. + ctrl->SetSizeHints(3,3); + + // Correct size of this window to match the child. + wxSize sz = GetSize(); + wxSize chsz = ctrl->GetSize(); + + int hei_adj = chsz.y - (sz.y+(m_yadj*2)); + if ( hei_adj ) + SetSize(sz.x,chsz.y-(m_yadj*2)); + +} + + +void wxPGClipperWindow::Refresh( bool eraseBackground, const wxRect *rect ) +{ + wxWindow::Refresh(false,rect); + if ( m_ctrl ) + // FIXME: Rect to sub-ctrl refresh too + m_ctrl->Refresh(eraseBackground); +} + + +// Pass focus to control +void wxPGClipperWindow::SetFocus() +{ + if ( m_ctrl ) + m_ctrl->SetFocus(); + else + wxWindow::SetFocus(); +} + + +bool wxPGClipperWindow::SetFont(const wxFont& font) +{ + bool res = wxWindow::SetFont(font); + if ( m_ctrl ) + return m_ctrl->SetFont(font); + return res; +} + + +void wxPGClipperWindow::Create(wxWindow* parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size ) +{ + wxWindow::Create(parent,id,pos,size); +} + + +wxPGClipperWindow::~wxPGClipperWindow() +{ +} + + +bool wxPGClipperWindow::ProcessEvent(wxEvent& event) +{ + if ( event.GetEventType() == wxEVT_SIZE ) + { + if ( m_ctrl ) + { + // Maintain correct size relationship. + wxSize sz = GetSize(); + m_ctrl->SetSize(sz.x+(m_xadj*2),sz.y+(m_yadj*2)); + event.Skip(); + return false; + } + } + return wxWindow::ProcessEvent(event); +} + +#endif // wxPG_ENABLE_CLIPPER_WINDOW + +/*wxWindow* wxPropertyGrid::GetActualEditorControl( wxWindow* ctrl ) +{ +#if wxPG_ENABLE_CLIPPER_WINDOW + // Pass real control instead of clipper window + if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) + { + return ((wxPGClipperWindow*)ctrl)->GetControl(); + } +#else + return ctrl; +#endif +}*/ + +// ----------------------------------------------------------------------- +// wxPGTextCtrlEditor +// ----------------------------------------------------------------------- + +// Clipper window support macro (depending on whether it is used +// for this editor or not) +#if wxPG_NAT_TEXTCTRL_BORDER_X || wxPG_NAT_TEXTCTRL_BORDER_Y + #define wxPG_NAT_TEXTCTRL_BORDER_ANY 1 + #define wxPGDeclareRealTextCtrl(WND) \ + wxASSERT( WND ); \ + wxTextCtrl* tc = (wxTextCtrl*)((wxPGClipperWindow*)WND)->GetControl() +#else + #define wxPG_NAT_TEXTCTRL_BORDER_ANY 0 + #define wxPGDeclareRealTextCtrl(WND) \ + wxASSERT( WND ); \ + wxTextCtrl* tc = (wxTextCtrl*)WND +#endif + + +WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrl,wxPGTextCtrlEditor,wxPGEditor) + + +#ifndef __WXPYTHON__ +wxWindow* wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + wxWindow** ) const +#else +wxPGWindowPair wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz ) const +#endif +{ + wxString text; + + // If has children and limited editing, then don't create. + if ((property->GetFlags() & wxPG_PROP_NOEDITOR) && + property->GetParentingType() < 0 && + !property->IsKindOf(WX_PG_CLASSINFO(wxCustomProperty))) + return (wxWindow*) NULL; + + int flags = 0; + if ( (property->GetFlags() & wxPG_PROP_PASSWORD) && + property->IsKindOf(WX_PG_CLASSINFO(wxStringProperty)) ) + flags |= wxTE_PASSWORD; + + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + + wxWindow* wnd = propGrid->GenerateEditorTextCtrl(pos,sz,text,(wxWindow*)NULL,flags, + property->GetMaxLength()); + + return wnd; +} + + +void wxPGTextCtrlEditor::DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const +{ + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + { + wxString drawStr = property->GetDisplayedString(); + + // Code below should no longer be needed, as the obfuscation + // is now done in GetValueAsString. + /*if ( (property->GetFlags() & wxPG_PROP_PASSWORD) && + property->IsKindOf(WX_PG_CLASSINFO(wxStringProperty)) ) + { + size_t a = drawStr.length(); + drawStr.Empty(); + drawStr.Append(wxT('*'),a); + }*/ + dc.DrawText( drawStr, rect.x+wxPG_XBEFORETEXT, rect.y ); + } +} + + +void wxPGTextCtrlEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxPGDeclareRealTextCtrl(ctrl); + tc->SetValue(property->GetDisplayedString()); +} + + +// Provided so that, for example, ComboBox editor can use the same code +// (multiple inheritance would get way too messy). +bool wxPGTextCtrlEditor::OnTextCtrlEvent( wxPropertyGrid* propGrid, + wxPGProperty* property, + wxWindow* ctrl, + wxEvent& event ) +{ + if ( !ctrl ) + return false; + + if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER ) + { + if ( propGrid->IsEditorsValueModified() ) + { + return true; + } + } + else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED ) + { + wxPGDeclareRealTextCtrl(ctrl); + + // If value is unspecified and character count is zero, + // then do not set as modified. + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) || + !tc || + (tc->IsKindOf(CLASSINFO(wxTextCtrl)) && + (tc->GetLastPosition() > 0)) ) + { + + // We must check this since an 'empty' text event + // may be triggered when creating the property. + if ( !(propGrid->GetInternalFlags() & wxPG_FL_IN_SELECT_PROPERTY) ) + { + // + // Pass this event outside wxPropertyGrid so that, + // if necessary, program can tell when user is editing + // a textctrl. + // FIXME: Is it safe to change event id in the middle of event + // processing (seems to work, but...)? + event.Skip(); + event.SetId(propGrid->GetId()); + } + + propGrid->EditorsValueWasModified(); + } + } + return false; +} + + +bool wxPGTextCtrlEditor::OnEvent( wxPropertyGrid* propGrid, + wxPGProperty* property, + wxWindow* ctrl, + wxEvent& event ) const +{ + return wxPGTextCtrlEditor::OnTextCtrlEvent(propGrid,property,ctrl,event); +} + + +bool wxPGTextCtrlEditor::CopyTextCtrlValueFromControl( wxPGProperty* property, wxWindow* ctrl ) +{ +#if wxPG_ENABLE_CLIPPER_WINDOW + // Pass real control instead of clipper window + if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) + { + ctrl = ((wxPGClipperWindow*)ctrl)->GetControl(); + } +#endif + wxTextCtrl* tc = (wxTextCtrl*)ctrl; + + bool res = property->SetValueFromString(tc->GetValue(),0); + + // Changing unspecified always causes event (returning + // true here should be enough to trigger it). + if ( !res && property->IsFlagSet(wxPG_PROP_UNSPECIFIED) ) + res = true; + + return res; +} + + +bool wxPGTextCtrlEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + return wxPGTextCtrlEditor::CopyTextCtrlValueFromControl(property,ctrl); +} + + +void wxPGTextCtrlEditor::SetValueToUnspecified( wxWindow* ctrl ) const +{ + wxPGDeclareRealTextCtrl(ctrl); + + tc->Remove(0,tc->GetValue().length()); +} + + +void wxPGTextCtrlEditor::SetControlStringValue( wxWindow* ctrl, const wxString& txt ) const +{ + wxPGDeclareRealTextCtrl(ctrl); + + tc->SetValue(txt); +} + + +void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const +{ + wxPGDeclareRealTextCtrl(wnd); + + tc->SetSelection(-1,-1); +} + + +wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { } + + +// ----------------------------------------------------------------------- +// wxPGChoiceEditor +// ----------------------------------------------------------------------- + +extern const wxChar* wxPG_ClassName_wxBoolProperty; // in props.cpp + + +WX_PG_IMPLEMENT_EDITOR_CLASS(Choice,wxPGChoiceEditor,wxPGEditor) + + +// This is a special enhanced double-click processor class. +// In essence, it allows for double-clicks for which the +// first click "created" the control. +class wxPGDoubleClickProcessor : public wxEvtHandler +{ +public: + + wxPGDoubleClickProcessor( wxPGOwnerDrawnComboBox* combo ) + : wxEvtHandler() + { + m_timeLastMouseUp = 0; + m_combo = combo; + m_downReceived = false; + } + +protected: + + void OnMouseEvent( wxMouseEvent& event ) + { + wxLongLong t = ::wxGetLocalTimeMillis(); + int evtType = event.GetEventType(); + + if ( m_combo->HasFlag(wxPGCC_DCLICK_CYCLES) && + !m_combo->IsPopupShown() ) + { + // Just check that it is in the text area + wxPoint pt = event.GetPosition(); + if ( m_combo->GetTextRect().wxPGRectContains(pt) ) + { + if ( evtType == wxEVT_LEFT_DOWN ) + { + // Set value to avoid up-events without corresponding downs + m_downReceived = true; + } + else if ( evtType == wxEVT_LEFT_DCLICK ) + { + // We'll make our own double-clicks + event.SetEventType(0); + return; + } + else if ( evtType == wxEVT_LEFT_UP ) + { + if ( m_downReceived || m_timeLastMouseUp == 1 ) + { + wxLongLong timeFromLastUp = (t-m_timeLastMouseUp); + + if ( timeFromLastUp < DOUBLE_CLICK_CONVERSION_TRESHOLD ) + { + event.SetEventType(wxEVT_LEFT_DCLICK); + m_timeLastMouseUp = 1; + } + else + { + m_timeLastMouseUp = t; + } + } + } + } + } + + event.Skip(); + } + + void OnSetFocus( wxFocusEvent& event ) + { + m_timeLastMouseUp = ::wxGetLocalTimeMillis(); + event.Skip(); + } + +private: + wxLongLong m_timeLastMouseUp; + wxPGOwnerDrawnComboBox* m_combo; + bool m_downReceived; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxPGDoubleClickProcessor, wxEvtHandler) + EVT_MOUSE_EVENTS(wxPGDoubleClickProcessor::OnMouseEvent) + EVT_SET_FOCUS(wxPGDoubleClickProcessor::OnSetFocus) +END_EVENT_TABLE() + + + +class wxPGComboBox : public wxPGOwnerDrawnComboBox +{ +public: + + wxPGComboBox() + : wxPGOwnerDrawnComboBox() + { + m_dclickProcessor = (wxPGDoubleClickProcessor*) NULL; + } + + ~wxPGComboBox() + { + if ( m_dclickProcessor ) + { + RemoveEventHandler(m_dclickProcessor); + delete m_dclickProcessor; + } + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, + const wxString choices[] = (const wxString *) NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxComboBoxNameStr) + { + if ( !wxPGOwnerDrawnComboBox::Create( parent, + id, + value, + pos, + size, + n, + choices, + style, + validator, + name ) ) + return false; + + m_dclickProcessor = new wxPGDoubleClickProcessor(this); + + PushEventHandler(m_dclickProcessor); + + return true; + } + + virtual bool OnDrawListItem( wxDC& dc, const wxRect& rect, int item, int flags ) + { + wxPropertyGrid* pg = wxDynamicCast(GetParent(),wxPropertyGrid); + wxASSERT(pg); + pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,dc,(wxRect&)rect,flags); + return true; + } + virtual wxCoord OnMeasureListItem( int item ) + { + wxPropertyGrid* pg = wxDynamicCast(GetParent(),wxPropertyGrid); + wxASSERT(pg); + wxRect rect; + rect.x = -1; + rect.width = 0; + pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0); + return rect.height; + } + virtual wxCoord OnMeasureListItemWidth( int item ) + { + wxPropertyGrid* pg = wxDynamicCast(GetParent(),wxPropertyGrid); + wxASSERT(pg); + wxRect rect; + rect.x = -1; + rect.width = -1; + pg->OnComboItemPaint((wxPGCustomComboControl*)this,item,*((wxDC*)NULL),rect,0); + return rect.width; + } + +private: + wxPGDoubleClickProcessor* m_dclickProcessor; +}; + + +void wxPropertyGrid::OnComboItemPaint( wxPGCustomComboControl* pCc, + int item, + wxDC& dc, + wxRect& rect, + int flags ) +{ + wxPGOwnerDrawnComboBox* pCb = (wxPGOwnerDrawnComboBox*)pCc; + + // Sanity check + wxASSERT( IsKindOf(CLASSINFO(wxPropertyGrid)) ); + + wxPGProperty* p = m_selected; + + // + // Decide what custom image size to use + wxSize cis = GetImageSize(p); + + if ( rect.x < 0 && + !(m_iFlags & wxPG_FL_SELECTED_IS_PAINT_FLEXIBLE) ) + { + // Default measure behaviour (no flexible, custom paint image only) + if ( rect.width < 0 ) + { + wxCoord x, y; + GetTextExtent(pCb->GetString(item), &x, &y, 0, 0, &m_font); + rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9 + x; + } + + rect.height = cis.y + 2; + return; + } + + wxPGPaintData paintdata; + paintdata.m_parent = NULL; + paintdata.m_choiceItem = item; + + // This is by the current (1.0.0b) spec - if painting control, item is -1 + if ( (flags & wxPGCC_PAINTING_CONTROL) ) + paintdata.m_choiceItem = -1; + + if ( &dc ) + dc.SetBrush(*wxWHITE_BRUSH); + + if ( rect.x >= 0 ) + { + // + // DrawItem call + + wxPoint pt(rect.x + wxPG_CONTROL_MARGIN - wxPG_CHOICEXADJUST - 1, + rect.y + 1); + + if ( cis.x > 0 && + ( !p->m_dataExt || !p->m_dataExt->m_valueBitmap || item == pCb->GetSelection() ) && + ( item >= 0 || (flags & wxPGCC_PAINTING_CONTROL) ) + ) + { + pt.x += wxCC_CUSTOM_IMAGE_MARGIN1; + wxRect r(pt.x,pt.y,cis.x,cis.y); + + if ( flags & wxPGCC_PAINTING_CONTROL ) + { + //r.width = cis.x; + r.height = wxPG_STD_CUST_IMAGE_HEIGHT(m_lineHeight); + } + + if ( m_iFlags & wxPG_FL_SELECTED_IS_FULL_PAINT ) + r.width = rect.width; + + paintdata.m_drawnWidth = r.width; + + dc.SetPen(m_colPropFore); + if ( item >= 0 ) + p->OnCustomPaint( dc, r, paintdata ); + else + dc.DrawRectangle( r ); + + if ( (m_iFlags & wxPG_FL_SELECTED_IS_FULL_PAINT) ) + { + if ( paintdata.m_drawnWidth > 0 ) + return; + + // Revert pt.x + pt.x -= (wxCC_CUSTOM_IMAGE_MARGIN1+1); + } + else + pt.x += paintdata.m_drawnWidth + wxCC_CUSTOM_IMAGE_MARGIN2 - 1; + } + else + // TODO: This aligns text so that it seems to be horizontally + // on the same line as property values. Not really + // sure if its needed, but seems to not cause any harm. + pt.x -= 1; + + // + // Draw text + // + + pt.y += (rect.height-m_fontHeight)/2 - 1; + + wxString text; + if ( !(flags & wxPGCC_PAINTING_CONTROL) ) + { + text = pCb->GetString(item); + } + else + { + if ( !p->IsValueUnspecified() ) + text = p->GetValueAsString(0); + } + + dc.DrawText( text, pt.x + wxPG_XBEFORETEXT, pt.y ); + + } + else + { + // + // MeasureItem call + + p->OnCustomPaint( dc, rect, paintdata ); + rect.height = paintdata.m_drawnHeight + 2; + rect.width = cis.x + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2 + 9; + } +} + + +// CreateControls calls this with CB_READONLY in extraStyle +wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + long extraStyle ) const +{ + wxString defString; + wxPGChoiceInfo choiceInfo; + + // Get choices. + choiceInfo.m_arrWxString = (wxString*) NULL; + choiceInfo.m_arrWxChars = (const wxChar**) NULL; + choiceInfo.m_itemCount = 0; + + int index = property->GetChoiceInfo( &choiceInfo ); + + if ( property->GetFlags() & wxPG_PROP_UNSPECIFIED ) + { + index = -1; + } + else + { + defString = property->GetDisplayedString(); + } + + // SLAlloc allows fast conversion using potentially pre-allocated wxStrings + // (and appending is out of question due to performance problems on some platforms). + + // If itemcount is < 0, fill wxArrayString using GetEntry + if ( choiceInfo.m_itemCount < 0 ) + { + wxBaseEnumPropertyClass* ep = (wxBaseEnumPropertyClass*) property; + size_t i = 0; + const wxString* entryLabel; + int entryValue; + + wxArrayString& sl = propGrid->SLGet(); + + entryLabel = ep->GetEntry(i,&entryValue); + while ( entryLabel ) + { + if ( sl.GetCount() > i ) + sl[i] = *entryLabel; + else + sl.Add(*entryLabel); + i++; + entryLabel = ep->GetEntry(i,&entryValue); + } + choiceInfo.m_itemCount = ((int)i) - 1; + } + else if ( !choiceInfo.m_arrWxString ) + { + wxASSERT( choiceInfo.m_arrWxChars || !choiceInfo.m_itemCount ); + propGrid->SLAlloc( choiceInfo.m_itemCount, choiceInfo.m_arrWxChars ); + if ( choiceInfo.m_itemCount ) + choiceInfo.m_arrWxString = &propGrid->SLGet().Item(0); + } + + //wxPGOwnerDrawnComboBox* cb; + wxPGComboBox* cb; + + wxPoint po(pos); + wxSize si(sz); + po.y += wxPG_CHOICEYADJUST; + si.y -= (wxPG_CHOICEYADJUST*2); + +/*#if wxPG_NAT_CHOICE_BORDER_ANY + po.x += (wxPG_CHOICEXADJUST+wxPG_NAT_CHOICE_BORDER_X); + si.x -= (wxPG_CHOICEXADJUST+wxPG_NAT_CHOICE_BORDER_X); + wxPGClipperWindow* wnd = new wxPGClipperWindow(propGrid,wxPG_SUBID1,po,si); + wxWindow* ctrlParent = wnd; + wnd->GetControlRect(wxPG_NAT_CHOICE_BORDER_X,wxPG_NAT_CHOICE_BORDER_Y,po,si); +#else*/ + po.x += wxPG_CHOICEXADJUST; + si.x -= wxPG_CHOICEXADJUST; + wxWindow* ctrlParent = propGrid; +//#endif + + // NB: Using wxWidgets wxOwnerDrawnComboBox needs adding wxTE_PROCESS_ENTER + // into the flags. + int odcbFlags = extraStyle | wxNO_BORDER | wxPGCC_PROCESS_ENTER | wxPGCC_ALT_KEYS; + + if ( !(property->GetFlags() & wxPG_PROP_CUSTOMIMAGE) ) + odcbFlags |= wxODCB_STD_CONTROL_PAINT; + + if ( (property->GetFlags() & wxPG_PROP_USE_DCC) && + (property->GetClassName()==wxPG_ClassName_wxBoolProperty) ) + odcbFlags |= wxPGCC_DCLICK_CYCLES; + + cb = new wxPGComboBox(); +#ifdef __WXMSW__ + cb->Hide(); +#endif + cb->Create(ctrlParent, + wxPG_SUBID1, + wxString(), + po, + si, + choiceInfo.m_itemCount,choiceInfo.m_arrWxString, + //(wxComboPaintCallback) &wxPropertyGrid::OnComboItemPaint, + odcbFlags); + + int extRight = propGrid->GetClientSize().x - (po.x+si.x); + + cb->SetButtonPosition(si.y,0,wxRIGHT); + cb->SetPopupExtents( 1, extRight ); + cb->SetTextIndent(wxPG_XBEFORETEXT-2); + + if ( (property->GetFlags() & wxPG_PROP_CUSTOMIMAGE) && + !(propGrid->GetInternalFlags() & wxPG_FL_SELECTED_IS_FULL_PAINT) ) + { + wxSize imageSize = propGrid->GetImageSize(property); + cb->SetCustomPaintWidth( imageSize.x+6 ); + } + + if ( index >= 0 && index < (int)cb->GetCount() ) + { + cb->SetSelection( index ); + if ( defString.length() ) + cb->SetValue( defString ); + } + else if ( !(extraStyle & wxCB_READONLY) && defString.length() ) + cb->SetValue( defString ); + else + cb->SetSelection( -1 ); + + if ( property->HasFlag(wxPG_PROP_READONLY) ) + cb->Disable(); + +#ifdef __WXMSW__ + cb->Show(); +#endif + + return (wxWindow*) cb; +} + + +void wxPGChoiceEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxASSERT( ctrl ); + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox))); + int ind = property->GetChoiceInfo( (wxPGChoiceInfo*)NULL ); + cb->SetSelection(ind); +} + +#ifndef __WXPYTHON__ +wxWindow* wxPGChoiceEditor::CreateControls( wxPropertyGrid* propGrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz, wxWindow** ) const +#else +wxPGWindowPair wxPGChoiceEditor::CreateControls( wxPropertyGrid* propGrid, wxPGProperty* property, + const wxPoint& pos, const wxSize& sz ) const +#endif +{ + return CreateControlsBase(propGrid,property,pos,sz,wxCB_READONLY); +} + + +int wxPGChoiceEditor::InsertItem( wxWindow* ctrl, const wxString& label, int index ) const +{ + wxASSERT( ctrl ); + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox))); + + if (index < 0) + index = cb->GetCount(); + + return cb->Insert(label,index); +} + + +void wxPGChoiceEditor::DeleteItem( wxWindow* ctrl, int index ) const +{ + wxASSERT( ctrl ); + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + wxASSERT( cb->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox))); + + cb->Delete(index); +} + + +bool wxPGChoiceEditor::OnEvent( wxPropertyGrid* WXUNUSED(propGrid), wxPGProperty* WXUNUSED(property), + wxWindow* WXUNUSED(ctrl), wxEvent& event ) const +{ + if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) + { + /*if ( CopyValueFromControl( property, ctrl ) ) + { + return true; + } + + propGrid->EditorsValueWasNotModified(); + + //wxPropertyGridState::ClearPropertyAndChildrenFlags(property,wxPG_PROP_UNSPECIFIED); + CLEAR_PROPERTY_UNSPECIFIED_FLAG(property);*/ + + return true; + + } + return false; +} + + +bool wxPGChoiceEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + + int index = cb->GetSelection(); + + if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) || + // Changing unspecified always causes event (returning + // true here should be enough to trigger it). + property->IsFlagSet(wxPG_PROP_UNSPECIFIED) + ) + { + property->SetValueFromInt(index,0); + return true; + } + return false; +} + + +void wxPGChoiceEditor::SetControlStringValue( wxWindow* ctrl, const wxString& txt ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + wxASSERT( cb ); + cb->SetValue(txt); +} + + +void wxPGChoiceEditor::SetControlIntValue( wxWindow* ctrl, int value ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + wxASSERT( cb ); + cb->SetSelection(value); +} + + +void wxPGChoiceEditor::SetValueToUnspecified( wxWindow* ctrl ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + cb->SetSelection(-1); +} + + +bool wxPGChoiceEditor::CanContainCustomImage() const +{ + return true; +} + + +wxPGChoiceEditor::~wxPGChoiceEditor() { } + + +// ----------------------------------------------------------------------- +// wxPGComboBoxEditor +// ----------------------------------------------------------------------- + + +WX_PG_IMPLEMENT_EDITOR_CLASS(ComboBox,wxPGComboBoxEditor,wxPGChoiceEditor) + + +void wxPGComboBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + cb->SetValue(property->GetDisplayedString()); + + // TODO: If string matches any selection, then select that. +} + + +#ifndef __WXPYTHON__ +wxWindow* wxPGComboBoxEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + wxWindow** ) const +#else +wxPGWindowPair wxPGComboBoxEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz ) const +#endif +{ + return CreateControlsBase(propGrid,property,pos,sz,0); +} + + +bool wxPGComboBoxEditor::OnEvent( wxPropertyGrid* propGrid, + wxPGProperty* property, + wxWindow* ctrl, + wxEvent& event ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*) NULL; + wxWindow* textCtrl = (wxWindow*) NULL; + + if ( ctrl ) + { + cb = (wxPGOwnerDrawnComboBox*)ctrl; + textCtrl = cb->GetTextCtrl(); + } + + if ( wxPGTextCtrlEditor::OnTextCtrlEvent(propGrid,property,textCtrl,event) ) + return true; + + return wxPGChoiceEditor::OnEvent(propGrid,property,ctrl,event); +} + + +bool wxPGComboBoxEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + + bool res = property->SetValueFromString(cb->GetValue(),0); + + // Changing unspecified always causes event (returning + // true here should be enough to trigger it). + if ( !res && property->IsFlagSet(wxPG_PROP_UNSPECIFIED) ) + res = true; + + return res; +} + + +void wxPGComboBoxEditor::OnFocus( wxPGProperty*, wxWindow* ctrl ) const +{ + wxPGOwnerDrawnComboBox* cb = (wxPGOwnerDrawnComboBox*)ctrl; + cb->GetTextCtrl()->SetSelection(-1,-1); +} + + +wxPGComboBoxEditor::~wxPGComboBoxEditor() { } + + +// ----------------------------------------------------------------------- +// wxPGChoiceAndButtonEditor +// ----------------------------------------------------------------------- + + +// This simpler implement_editor macro doesn't define class body. +WX_PG_IMPLEMENT_EDITOR_CLASS(ChoiceAndButton,wxPGChoiceAndButtonEditor,wxPGChoiceEditor) + + +#ifndef __WXPYTHON__ +wxWindow* wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + wxWindow** psecondary ) const +#else +wxPGWindowPair wxPGChoiceAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz ) const +#endif +{ + // Use one two units smaller to match size of the combo's dropbutton. + // (normally a bigger button is used because it looks better) + int bt_wid = sz.y; + bt_wid -= 2; + wxSize bt_sz(bt_wid,bt_wid); + + // Position of button. + wxPoint bt_pos(pos.x+sz.x-bt_sz.x,pos.y); +#ifdef __WXMAC__ + bt_pos.y -= 1; +#else + bt_pos.y += 1; +#endif + + wxWindow* bt = propGrid->GenerateEditorButton( bt_pos, bt_sz ); + + // Size of choice. + wxSize ch_sz(sz.x-bt->GetSize().x,sz.y); + +#ifdef __WXMAC__ + ch_sz.x -= wxPG_TEXTCTRL_AND_BUTTON_SPACING; +#endif + + wxWindow* ch = wxPG_EDITOR(Choice)->CreateControls(propGrid,property, + pos,ch_sz +#ifndef __WXPYTHON__ + , (wxWindow**)NULL); +#else + ).m_primary; +#endif + + +#ifdef __WXMSW__ + bt->Show(); +#endif + +#ifndef __WXPYTHON__ + *psecondary = bt; + return ch; +#else + return wxPGWindowPair(ch, bt); +#endif +} + + +wxPGChoiceAndButtonEditor::~wxPGChoiceAndButtonEditor() { } + + +// ----------------------------------------------------------------------- +// wxPGTextCtrlAndButtonEditor +// ----------------------------------------------------------------------- + + +// This simpler implement_editor macro doesn't define class body. +WX_PG_IMPLEMENT_EDITOR_CLASS(TextCtrlAndButton,wxPGTextCtrlAndButtonEditor,wxPGTextCtrlEditor) + + +#ifndef __WXPYTHON__ +wxWindow* wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz, + wxWindow** psecondary ) const +{ + wxWindow* wnd = propGrid->GenerateEditorTextCtrlAndButton( pos, sz, psecondary, + property->GetFlags() & wxPG_PROP_NOEDITOR, property); + + return wnd; +} +#else +wxPGWindowPair wxPGTextCtrlAndButtonEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& sz ) const +{ + wxWindow* wnd2; + wxWindow* wnd = propGrid->GenerateEditorTextCtrlAndButton( pos, sz, &wnd2, + property->GetFlags() & wxPG_PROP_NOEDITOR, property); + + return wxPGWindowPair(wnd, wnd2); +} +#endif + + +wxPGTextCtrlAndButtonEditor::~wxPGTextCtrlAndButtonEditor() { } + + +// ----------------------------------------------------------------------- +// wxPGCheckBoxEditor +// ----------------------------------------------------------------------- + +#if wxPG_INCLUDE_CHECKBOX + +WX_PG_IMPLEMENT_EDITOR_CLASS(CheckBox,wxPGCheckBoxEditor,wxPGEditor) + + +// state argument: 0x01 = set if checked +// 0x02 = set if rectangle should be bold +static void DrawSimpleCheckBox( wxDC& dc, const wxRect& rect, int box_hei, int state, const wxColour& linecol ) +{ + + // Box rectangle. + wxRect r(rect.x+wxPG_XBEFORETEXT,rect.y+((rect.height-box_hei)/2),box_hei,box_hei); + + // Draw check mark first because it is likely to overdraw the + // surrounding rectangle. + if ( state & 1 ) + { + wxRect r2(r.x+wxPG_CHECKMARK_XADJ, + r.y+wxPG_CHECKMARK_YADJ, + r.width+wxPG_CHECKMARK_WADJ, + r.height+wxPG_CHECKMARK_HADJ); + #if wxPG_CHECKMARK_DEFLATE + r2.Deflate(wxPG_CHECKMARK_DEFLATE); + #endif + dc.DrawCheckMark(r2); + + // This would draw a simple cross check mark. + // dc.DrawLine(r.x,r.y,r.x+r.width-1,r.y+r.height-1); + // dc.DrawLine(r.x,r.y+r.height-1,r.x+r.width-1,r.y); + + } + + if ( !(state & 2) ) + { + // Pen for thin rectangle. + dc.SetPen(linecol); + } + else + { + // Pen for bold rectangle. + wxPen linepen(linecol,2,wxSOLID); + linepen.SetJoin(wxJOIN_MITER); // This prevents round edges. + dc.SetPen(linepen); + r.x++; + r.y++; + r.width--; + r.height--; + } + + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + dc.DrawRectangle(r); + dc.SetPen(*wxTRANSPARENT_PEN); +} + +// +// Real simple custom-drawn checkbox-without-label class. +// +class wxSimpleCheckBox : public wxControl +{ +public: + + void SetValue( int value ); + + wxSimpleCheckBox( wxWindow* parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize ) + : wxControl(parent,id,pos,size,wxNO_BORDER|wxWANTS_CHARS) + { + // Due to SetOwnFont stuff necessary for GTK+ 1.2, we need to have this + SetFont( parent->GetFont() ); + + m_state = 0; + m_boxHeight = ((wxPropertyGrid*)parent)->GetFontHeight(); + SetBackgroundStyle( wxBG_STYLE_COLOUR ); + } + + virtual ~wxSimpleCheckBox(); + + virtual bool ProcessEvent(wxEvent& event); + + int m_state; + int m_boxHeight; + + static wxBitmap* ms_doubleBuffer; + +}; + +wxSimpleCheckBox::~wxSimpleCheckBox() +{ + delete ms_doubleBuffer; + ms_doubleBuffer = NULL; +} + + +wxBitmap* wxSimpleCheckBox::ms_doubleBuffer = (wxBitmap*) NULL; + +// value = 2 means toggle (sorry, too lazy to do constants) +void wxSimpleCheckBox::SetValue( int value ) +{ + if ( value > 1 ) + { + m_state++; + if ( m_state > 1 ) m_state = 0; + } + else + { + m_state = value; + } + Refresh(); + + wxCommandEvent evt(wxEVT_COMMAND_CHECKBOX_CLICKED,GetParent()->GetId()); + ((wxPropertyGrid*)GetParent())->OnCustomEditorEvent(evt); +} + + +bool wxSimpleCheckBox::ProcessEvent(wxEvent& event) +{ + wxPropertyGrid* propGrid = (wxPropertyGrid*) GetParent(); + + if ( event.GetEventType() == wxEVT_NAVIGATION_KEY ) + { + //wxLogDebug(wxT("wxEVT_NAVIGATION_KEY")); + //SetFocusFromKbd(); + //event.Skip(); + //return wxControl::ProcessEvent(event); + } + else + if ( ( (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK) + && ((wxMouseEvent&)event).m_x > (wxPG_XBEFORETEXT-2) + && ((wxMouseEvent&)event).m_x <= (wxPG_XBEFORETEXT-2+m_boxHeight) ) + ) + { + SetValue(2); + return true; + } + else if ( event.GetEventType() == wxEVT_PAINT ) + { + wxSize clientSize = GetClientSize(); + wxPaintDC dc(this); + + /* + // Buffered paint DC doesn't seem to do much good + if ( !ms_doubleBuffer || + clientSize.x > ms_doubleBuffer->GetWidth() || + clientSize.y > ms_doubleBuffer->GetHeight() ) + { + delete ms_doubleBuffer; + ms_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25); + } + + wxBufferedPaintDC dc(this,*ms_doubleBuffer); + */ + + wxRect rect(0,0,clientSize.x,clientSize.y); + rect.x -= 1; + rect.width += 1; + + m_boxHeight = propGrid->GetFontHeight(); + + wxColour bgcol = GetBackgroundColour(); + dc.SetBrush( bgcol ); + dc.SetPen( bgcol ); + dc.DrawRectangle( rect ); + + wxColour txcol = GetForegroundColour(); + + int state = m_state; + if ( m_font.GetWeight() == wxBOLD ) + state |= 2; + + DrawSimpleCheckBox(dc,rect,m_boxHeight,state,txcol); + + // If focused, indicate it somehow. + /* + if ( wxWindow::FindFocus() == this ) + { + rect.x += 1; + rect.width -= 1; + + wxPGDrawFocusRect(dc,rect); + } + */ + + return true; + } + else if ( event.GetEventType() == wxEVT_SIZE || + event.GetEventType() == wxEVT_SET_FOCUS || + event.GetEventType() == wxEVT_KILL_FOCUS + ) + { + Refresh(); + } + else if ( event.GetEventType() == wxEVT_KEY_DOWN ) + { + wxKeyEvent& keyEv = (wxKeyEvent&) event; + + if ( keyEv.GetKeyCode() == WXK_TAB ) + { + propGrid->SendNavigationKeyEvent( keyEv.ShiftDown()?0:1 ); + return true; + } + else + if ( keyEv.GetKeyCode() == WXK_SPACE ) + { + SetValue(2); + return true; + } + } + return wxControl::ProcessEvent(event); +} + + +#ifndef __WXPYTHON__ +wxWindow* wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& size, + wxWindow** ) const +#else +wxPGWindowPair wxPGCheckBoxEditor::CreateControls( wxPropertyGrid* propGrid, + wxPGProperty* property, + const wxPoint& pos, + const wxSize& size ) const +#endif +{ + wxPoint pt = pos; + pt.x -= wxPG_XBEFOREWIDGET; + wxSize sz = size; + sz.x += wxPG_XBEFOREWIDGET; + + wxSimpleCheckBox* cb = new wxSimpleCheckBox(propGrid,wxPG_SUBID1,pt,sz); + + cb->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + + cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DOWN, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid ); + + cb->Connect( wxPG_SUBID1, wxEVT_LEFT_DCLICK, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) + &wxPropertyGrid::OnCustomEditorEvent, NULL, propGrid ); + + if ( property->GetChoiceInfo((wxPGChoiceInfo*)NULL) && + !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + cb->m_state = 1; + + // If mouse cursor was on the item, toggle the value now. + if ( propGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK ) + { + wxPoint pt = propGrid->ScreenToClient(::wxGetMousePosition()); + if ( pt.x <= (cb->GetPosition().x+wxPG_XBEFORETEXT-2+cb->m_boxHeight) ) + { + cb->m_state++; + + if ( cb->m_state > 1 ) + cb->m_state = 0; + + property->ClearFlag(wxPG_PROP_UNSPECIFIED); + property->SetValueFromInt(cb->m_state,0); + propGrid->PropertyWasModified(property); + } + } + + return cb; +} + + +void wxPGCheckBoxEditor::DrawValue( wxDC& dc, wxPGProperty* property, const wxRect& rect ) const +{ + int state = 0; + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + { + state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL); + if ( dc.GetFont().GetWeight() == wxBOLD ) state |= 2; + } + DrawSimpleCheckBox(dc,rect,dc.GetCharHeight(),state,dc.GetTextForeground()); +} + + +void wxPGCheckBoxEditor::UpdateControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxASSERT( ctrl ); + ((wxSimpleCheckBox*)ctrl)->m_state = property->GetChoiceInfo((wxPGChoiceInfo*)NULL); + ctrl->Refresh(); +} + + +bool wxPGCheckBoxEditor::OnEvent( wxPropertyGrid* WXUNUSED(propGrid), wxPGProperty* WXUNUSED(property), + wxWindow* WXUNUSED(ctrl), wxEvent& event ) const +{ + if ( event.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED ) + { + /*if ( CopyValueFromControl( property, ctrl ) ) + return true; + + propGrid->EditorsValueWasNotModified(); + + CLEAR_PROPERTY_UNSPECIFIED_FLAG(property);*/ + return true; + } + return false; +} + + +bool wxPGCheckBoxEditor::CopyValueFromControl( wxPGProperty* property, wxWindow* ctrl ) const +{ + wxSimpleCheckBox* cb = (wxSimpleCheckBox*)ctrl; + + int index = cb->m_state; + + if ( index != property->GetChoiceInfo( (wxPGChoiceInfo*) NULL ) || + // Changing unspecified always causes event (returning + // true here should be enough to trigger it). + property->IsFlagSet(wxPG_PROP_UNSPECIFIED) + ) + { + property->SetValueFromInt(index,0); + return true; + } + return false; +} + + +void wxPGCheckBoxEditor::SetControlIntValue( wxWindow* ctrl, int value ) const +{ + if ( value != 0 ) value = 1; + ((wxSimpleCheckBox*)ctrl)->m_state = value; + ctrl->Refresh(); +} + + +void wxPGCheckBoxEditor::SetValueToUnspecified( wxWindow* ctrl ) const +{ + ((wxSimpleCheckBox*)ctrl)->m_state = 0; + ctrl->Refresh(); +} + + +wxPGCheckBoxEditor::~wxPGCheckBoxEditor() { } + + +#endif // wxPG_INCLUDE_CHECKBOX + +// ----------------------------------------------------------------------- +// wxPGBrush +// ----------------------------------------------------------------------- + +// +// This class is a wxBrush derivative used in the background colour +// brush cache. It adds wxPG-type colour-in-long to the class. +// JMS: Yes I know wxBrush doesn't actually hold the value (refcounted +// object does), but this is simpler implementation and equally +// effective. +// + +class wxPGBrush : public wxBrush +{ +public: + wxPGBrush( const wxColour& colour ); + wxPGBrush(); + virtual ~wxPGBrush() { } + void SetColour2( const wxColour& colour ); + inline long GetColourAsLong() const { return m_colAsLong; } +private: + long m_colAsLong; +}; + + +void wxPGBrush::SetColour2( const wxColour& colour ) +{ + wxBrush::SetColour(colour); + m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); +} + + +wxPGBrush::wxPGBrush() : wxBrush() +{ + m_colAsLong = 0; +} + + +wxPGBrush::wxPGBrush( const wxColour& colour ) : wxBrush(colour) +{ + m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); +} + + +// ----------------------------------------------------------------------- +// wxPGColour +// ----------------------------------------------------------------------- + +// +// Same as wxPGBrush, but for wxColour instead. +// + +class wxPGColour : public wxColour +{ +public: + wxPGColour( const wxColour& colour ); + wxPGColour(); + virtual ~wxPGColour() { } + void SetColour2( const wxColour& colour ); + inline long GetColourAsLong() const { return m_colAsLong; } +private: + long m_colAsLong; +}; + + +void wxPGColour::SetColour2( const wxColour& colour ) +{ + *this = colour; + m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); +} + + +wxPGColour::wxPGColour() : wxColour() +{ + m_colAsLong = 0; +} + + +wxPGColour::wxPGColour( const wxColour& colour ) : wxColour(colour) +{ + m_colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); +} + + +// ----------------------------------------------------------------------- +// wxPGTLWHandler +// Intercepts Close-events sent to wxPropertyGrid's top-level parent, +// and tries to commit property value. +// ----------------------------------------------------------------------- + +class wxPGTLWHandler : public wxEvtHandler +{ +public: + + wxPGTLWHandler( wxPropertyGrid* pg ) + : wxEvtHandler() + { + m_pg = pg; + } + +protected: + + void OnClose( wxCloseEvent& event ) + { + // ClearSelection forces value validation/commit. + if ( event.CanVeto() && !m_pg->ClearSelection() ) + { + event.Veto(); + return; + } + + event.Skip(); + } + +private: + wxPropertyGrid* m_pg; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxPGTLWHandler, wxEvtHandler) + EVT_CLOSE(wxPGTLWHandler::OnClose) +END_EVENT_TABLE() + +// ----------------------------------------------------------------------- +// wxPropertyGrid +// ----------------------------------------------------------------------- + +IMPLEMENT_CLASS(wxPropertyGrid, wxScrolledWindow) + +BEGIN_EVENT_TABLE(wxPropertyGrid, wxScrolledWindow) + EVT_MOTION(wxPropertyGrid::OnMouseMove) + EVT_IDLE(wxPropertyGrid::OnIdle) + EVT_LEFT_DOWN(wxPropertyGrid::OnMouseClick) + EVT_LEFT_UP(wxPropertyGrid::OnMouseUp) + EVT_RIGHT_UP(wxPropertyGrid::OnMouseRightClick) + EVT_LEFT_DCLICK(wxPropertyGrid::OnMouseDoubleClick) + EVT_PAINT(wxPropertyGrid::OnPaint) + EVT_SIZE(wxPropertyGrid::OnResize) + EVT_KEY_DOWN(wxPropertyGrid::OnKey) + EVT_KEY_UP(wxPropertyGrid::OnKeyUp) + EVT_CHAR(wxPropertyGrid::OnKey) + EVT_ENTER_WINDOW(wxPropertyGrid::OnMouseEntry) + EVT_LEAVE_WINDOW(wxPropertyGrid::OnMouseEntry) + EVT_MOUSE_CAPTURE_CHANGED(wxPropertyGrid::OnCaptureChange) + EVT_SCROLLWIN(wxPropertyGrid::OnScrollEvent) + EVT_NAVIGATION_KEY(wxPropertyGrid::OnNavigationKey) + EVT_TEXT(wxPG_SUBID1,wxPropertyGrid::OnCustomEditorEvent) + EVT_COMBOBOX(wxPG_SUBID1,wxPropertyGrid::OnCustomEditorEvent) + EVT_BUTTON(wxPG_SUBID2,wxPropertyGrid::OnCustomEditorEvent) + EVT_CHILD_FOCUS(wxPropertyGrid::OnChildFocusEvent) + EVT_SET_FOCUS(wxPropertyGrid::OnFocusEvent) + EVT_KILL_FOCUS(wxPropertyGrid::OnFocusEvent) + EVT_TEXT_ENTER(wxPG_SUBID1,wxPropertyGrid::OnCustomEditorEvent) + EVT_SYS_COLOUR_CHANGED(wxPropertyGrid::OnSysColourChanged) +END_EVENT_TABLE() + + +// ----------------------------------------------------------------------- + +wxPropertyGrid::wxPropertyGrid() + : wxScrolledWindow() +{ + Init1(); +} + +// ----------------------------------------------------------------------- + +wxPropertyGrid::wxPropertyGrid( wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxChar* name ) + : wxScrolledWindow() +{ + Init1(); + Create(parent,id,pos,size,style,name); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::Create( wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxChar* name ) +{ + + if ( !(style&wxBORDER_MASK) ) + style |= wxSIMPLE_BORDER; + + style |= wxVSCROLL; + +#ifdef __WXMSW__ + // This prevents crash under Win2K, but still + // enables keyboard navigation + if ( style & wxTAB_TRAVERSAL ) + { + style &= ~(wxTAB_TRAVERSAL); + style |= wxWANTS_CHARS; + } +#else + if ( style & wxTAB_TRAVERSAL ) + style |= wxWANTS_CHARS; +#endif + + wxScrolledWindow::Create(parent,id,pos,size,style,name); + + Init2(); + + return true; +} + +// ----------------------------------------------------------------------- + +static void wxPGRegisterStandardPropertyClasses(); + +// +// Initialize values to defaults +// +void wxPropertyGrid::Init1() +{ + WX_PG_GLOBALS_LOCKER() + +#if !wxPG_USE_WXMODULE + if ( !wxPGGlobalVars ) + wxPGGlobalVars = new wxPGGlobalVarsClass(); +#endif + + // Register type classes, if necessary. + if ( wxPGGlobalVars->m_dictValueType.empty() ) + RegisterDefaultValues(); + + // Register editor classes, if necessary. + if ( wxPGGlobalVars->m_mapEditorClasses.empty() ) + RegisterDefaultEditors(); + + // Register property classes, if necessary + if ( wxPGGlobalVars->m_dictPropertyClassInfo.empty() ) + wxPGRegisterStandardPropertyClasses(); + + m_iFlags = 0; + m_pState = (wxPropertyGridState*) NULL; + m_wndPrimary = m_wndSecondary = (wxWindow*) NULL; + m_selected = (wxPGProperty*) NULL; + m_propHover = (wxPGProperty*) NULL; + m_eventObject = this; + m_curFocused = (wxWindow*) NULL; + m_tlwHandler = NULL; + m_processingEvent = 0; + m_dragStatus = 0; + m_mouseSide = 16; + m_editorFocused = 0; + m_coloursCustomized = 0; + m_frozen = 0; + +#if wxPG_DOUBLE_BUFFER + m_doubleBuffer = (wxBitmap*) NULL; +#endif + + m_windowsToDelete = NULL; + +#ifndef wxPG_ICON_WIDTH + m_expandbmp = NULL; + m_collbmp = NULL; + m_iconWidth = 11; + m_iconHeight = 11; +#else + m_iconWidth = wxPG_ICON_WIDTH; +#endif + + m_prevVY = -1; + + m_calcVisHeight = 0; + + m_gutterWidth = wxPG_GUTTER_MIN; + m_subgroup_extramargin = 10; + + m_lineHeight = 0; + + m_width = m_height = m_fWidth = 0; + + m_bottomy = 0; + + m_splitterx = wxPG_DEFAULT_SPLITTERX; + m_fSplitterX = (float) wxPG_DEFAULT_SPLITTERX; + +#if !wxPG_HEAVY_GFX + m_splitterpen.SetColour( *wxBLACK ); + m_splitterpen.SetWidth( 4 ); + + m_splitterprevdrawnx = -1; +#endif + + SetButtonShortcut(0); + + m_keyComboConsumed = 0; + + m_ignoredEvents = 0; +} + +// ----------------------------------------------------------------------- + +// +// Initialize after parent etc. set +// +void wxPropertyGrid::Init2() +{ + wxASSERT( !(m_iFlags & wxPG_FL_INITIALIZED ) ); + +#ifdef __WXMAC__ + // Smaller controls on Mac + SetWindowVariant(wxWINDOW_VARIANT_SMALL); +#endif + + // Now create state, if one didn't exist already + // (wxPropertyGridManager might have created it for us). + if ( !m_pState ) + { + m_pState = CreateState(); + m_pState->m_pPropGrid = this; + m_iFlags |= wxPG_FL_CREATEDSTATE; + } + + if ( !(m_windowStyle & wxPG_SPLITTER_AUTO_CENTER) ) + m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + + if ( m_windowStyle & wxPG_HIDE_CATEGORIES ) + { + m_pState->InitNonCatMode(); + + FROM_STATE(m_properties) = FROM_STATE(m_abcArray); + } + + GetClientSize(&m_width,&m_height); + +#if !wxPG_HEAVY_GFX + m_splitterpen.SetColour( *wxBLACK ); + m_splitterpen.SetWidth( 4 ); +#endif + +#ifndef wxPG_ICON_WIDTH + // create two bitmap nodes for drawing + m_expandbmp = new wxBitmap(expand_xpm); + m_collbmp = new wxBitmap(collapse_xpm); + + // calculate average font height for bitmap centering + + m_iconWidth = m_expandbmp->GetWidth(); + m_iconHeight = m_expandbmp->GetHeight(); +#endif + + m_curcursor = wxCURSOR_ARROW; + m_cursorSizeWE = new wxCursor( wxCURSOR_SIZEWE ); + + // adjust bitmap icon y position so they are centered + m_vspacing = wxPG_DEFAULT_VSPACING; + + if ( !m_font.Ok() ) + { + wxFont useFont = wxScrolledWindow::GetFont(); + wxScrolledWindow::SetOwnFont( useFont ); + } + else + // This should be otherwise called by SetOwnFont + CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING ); + + // Add base brush item + m_arrBgBrushes.Add((void*)new wxPGBrush()); + + // Add base colour items + m_arrFgCols.Add((void*)new wxPGColour()); + m_arrFgCols.Add((void*)new wxPGColour()); + + RegainColours(); + + // This helps with flicker + SetBackgroundStyle( wxBG_STYLE_CUSTOM ); + + // Hook the TLW + wxPGTLWHandler* handler = new wxPGTLWHandler(this); + m_tlp = ::wxGetTopLevelParent(this); + m_tlwHandler = handler; + m_tlp->PushEventHandler(handler); + + // set virtual size to this window size + wxSize wndsize = GetSize(); + SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth()); + + m_timeCreated = ::wxGetLocalTimeMillis(); + + m_iFlags |= wxPG_FL_INITIALIZED; + + // Need to call OnResize handler or size given in constructor/Create + // will never work. + wxSizeEvent sizeEvent(wndsize,0); + OnResize(sizeEvent); +} + +// ----------------------------------------------------------------------- + +wxPropertyGrid::~wxPropertyGrid() +{ + size_t i; + + DoSelectProperty(NULL); + + // This should do prevent things from going too badly wrong + m_iFlags &= ~(wxPG_FL_INITIALIZED); + + END_MOUSE_CAPTURE + + wxPGTLWHandler* handler = (wxPGTLWHandler*) m_tlwHandler; + m_tlp->RemoveEventHandler(handler); + delete handler; + +#ifdef __WXDEBUG__ + if ( IsEditorsValueModified() ) + ::wxMessageBox(wxT("Most recent change in property editor was lost!!!\n\n(if you don't want this to happen, close your frames and dialogs using Close(false).)"), + wxT("wxPropertyGrid Debug Warning") ); +#endif + +#if wxPG_DOUBLE_BUFFER + if ( m_doubleBuffer ) + delete m_doubleBuffer; +#endif + + delete m_windowsToDelete; + + m_selected = (wxPGProperty*) NULL; + + if ( m_iFlags & wxPG_FL_CREATEDSTATE ) + delete m_pState; + + delete m_cursorSizeWE; + +#ifndef wxPG_ICON_WIDTH + delete m_expandbmp; + delete m_collbmp; +#endif + + // Delete cached text colours. + for ( i=0; iSetDelay ( wxPG_TOOLTIP_DELAY );*/ + } + else if ( (old_style & wxPG_TOOLTIPS) && !(style & wxPG_TOOLTIPS) ) + { + // + // Tooltips disabled + // + wxScrolledWindow::SetToolTip ( (wxToolTip*) NULL ); + } + #endif + } + + wxScrolledWindow::SetWindowStyleFlag ( style ); + + if ( m_iFlags & wxPG_FL_INITIALIZED ) + { + if ( (old_style & wxPG_HIDE_MARGIN) != (style & wxPG_HIDE_MARGIN) ) + { + CalculateFontAndBitmapStuff( m_vspacing ); + RedrawAllVisible(); + } + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Freeze() +{ + m_frozen++; + wxScrolledWindow::Freeze(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Thaw() +{ + m_frozen--; + wxScrolledWindow::Thaw(); +#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + Refresh(); +#endif + + // Force property re-selection + if ( m_selected ) + DoSelectProperty(m_selected, wxPG_SEL_FORCE); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetExtraStyle( long exStyle ) +{ + if ( exStyle & wxPG_EX_NATIVE_DOUBLE_BUFFERING ) + { +#if defined(__WXMSW__) + + /* + // Don't use WS_EX_COMPOSITED just now. + HWND hWnd; + + if ( m_iFlags & wxPG_FL_IN_MANAGER ) + hWnd = (HWND)GetParent()->GetHWND(); + else + hWnd = (HWND)GetHWND(); + + ::SetWindowLong( hWnd, GWL_EXSTYLE, + ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED ); + */ + +//#elif defined(__WXGTK20__) +#endif + // Only apply wxPG_EX_NATIVE_DOUBLE_BUFFERING if the window + // truly was double-buffered. + if ( !wxPGIsWindowBuffered(this) ) + { + exStyle &= ~(wxPG_EX_NATIVE_DOUBLE_BUFFERING); + } + else + { + #if wxPG_DOUBLE_BUFFER + delete m_doubleBuffer; + m_doubleBuffer = NULL; + #endif + } + } + + wxScrolledWindow::SetExtraStyle( exStyle ); + + if ( exStyle & wxPG_EX_INIT_NOCAT ) + m_pState->InitNonCatMode (); + + if ( exStyle & wxPG_EX_HELP_AS_TOOLTIPS ) + m_windowStyle |= wxPG_TOOLTIPS; + + if ( exStyle & wxPG_EX_AUTO_UNSPECIFIED_VALUES ) + { + wxPGGlobalVars->m_numBoolChoices = 3; + } + else + { + wxPGGlobalVars->m_numBoolChoices = 2; + } +} + +// ----------------------------------------------------------------------- + +// returns the best acceptable minimal size +wxSize wxPropertyGrid::DoGetBestSize() const +{ + int hei = 15; + if ( m_lineHeight > hei ) + hei = m_lineHeight; + wxSize sz = wxSize( 60, hei+40 ); + + CacheBestSize(sz); + return sz; +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid Font and Colour Methods +// ----------------------------------------------------------------------- + +void wxPropertyGrid::CalculateFontAndBitmapStuff( int vspacing ) +{ + int x = 0, y = 0; + + m_captionFont = GetFont(); + + GetTextExtent(wxT("jG"), &x, &y, 0, 0, &m_captionFont); + m_subgroup_extramargin = x + (x/2); + m_fontHeight = y; + +#if wxPG_USE_RENDERER_NATIVE + m_iconWidth = wxPG_ICON_WIDTH; +#elif wxPG_ICON_WIDTH + // scale icon + m_iconWidth = (m_fontHeight * wxPG_ICON_WIDTH) / 13; + if ( m_iconWidth < 5 ) m_iconWidth = 5; + else if ( !(m_iconWidth & 0x01) ) m_iconWidth++; // must be odd + +#endif + + m_gutterWidth = m_iconWidth / wxPG_GUTTER_DIV; + if ( m_gutterWidth < wxPG_GUTTER_MIN ) + m_gutterWidth = wxPG_GUTTER_MIN; + + int vdiv = 6; + if ( vspacing <= 1 ) vdiv = 12; + else if ( vspacing >= 3 ) vdiv = 3; + + m_spacingy = m_fontHeight / vdiv; + if ( m_spacingy < wxPG_YSPACING_MIN ) + m_spacingy = wxPG_YSPACING_MIN; + + m_marginWidth = 0; + if ( !(m_windowStyle & wxPG_HIDE_MARGIN) ) + m_marginWidth = m_gutterWidth*2 + m_iconWidth; + + m_captionFont.SetWeight(wxBOLD); + GetTextExtent(wxT("jG"), &x, &y, 0, 0, &m_captionFont); + + m_lineHeight = m_fontHeight+(2*m_spacingy)+1; + + // button spacing + m_buttonSpacingY = (m_lineHeight - m_iconHeight) / 2; + if ( m_buttonSpacingY < 0 ) m_buttonSpacingY = 0; + + InvalidateBestSize(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnSysColourChanged( wxSysColourChangedEvent &WXUNUSED(event) ) +{ + RegainColours(); + Refresh(); +} + +// ----------------------------------------------------------------------- + +static wxColour wxPGAdjustColour(const wxColour& src, int ra, + int ga = 1000, int ba = 1000, + bool forceDifferent = false) +{ + if ( ga >= 1000 ) + ga = ra; + if ( ba >= 1000 ) + ba = ra; + + // Recursion guard (allow 2 max) + static int isinside = 0; + isinside++; + wxCHECK_MSG( isinside < 3, + *wxBLACK, + wxT("wxPGAdjustColour should not be recursively called more than once") ); + + wxColour dst; + + int r = src.Red(); + int g = src.Green(); + int b = src.Blue(); + int r2 = r + ra; + if ( r2>255 ) r2 = 255; + else if ( r2<0) r2 = 0; + int g2 = g + ga; + if ( g2>255 ) g2 = 255; + else if ( g2<0) g2 = 0; + int b2 = b + ba; + if ( b2>255 ) b2 = 255; + else if ( b2<0) b2 = 0; + + // Make sure they are somewhat different + if ( forceDifferent && (abs((r+g+b)-(r2+g2+b2)) < abs(ra/2)) ) + dst = wxPGAdjustColour(src,-(ra*2)); + else + dst = wxColour(r2,g2,b2); + + // Recursion guard (allow 2 max) + isinside--; + + return dst; +} + + +static int wxPGGetColAvg( const wxColour& col ) +{ + return (col.Red() + col.Green() + col.Blue()) / 3; +} + + +void wxPropertyGrid::RegainColours() +{ + wxColour def_bgcol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); + + if ( !(m_coloursCustomized & 0x0002) ) + { + wxColour col = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ); + + // Make sure colour is dark enough + #ifdef __WXGTK__ + int colDec = wxPGGetColAvg(col) - 230; + #else + int colDec = wxPGGetColAvg(col) - 200; + #endif + if ( colDec > 0 ) + m_colCapBack = wxPGAdjustColour(col,-colDec); + else + m_colCapBack = col; + } + + if ( !(m_coloursCustomized & 0x0001) ) + m_colMargin = m_colCapBack; + + if ( !(m_coloursCustomized & 0x0004) ) + { + #ifdef __WXGTK__ + int colDec = -90; + #else + int colDec = -72; + #endif + wxColour capForeCol = wxPGAdjustColour(m_colCapBack,colDec,5000,5000,true); + m_colCapFore = capForeCol; + + // Set the cached colour as well. + ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(capForeCol); + } + + if ( !(m_coloursCustomized & 0x0008) ) + { + wxColour bgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); + m_colPropBack = bgCol; + + // Set the cached brush as well. + ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(bgCol); + } + + if ( !(m_coloursCustomized & 0x0010) ) + { + wxColour fgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); + m_colPropFore = fgCol; + + // Set the cached colour as well. + ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(fgCol); + } + + if ( !(m_coloursCustomized & 0x0020) ) + m_colSelBack = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ); + + if ( !(m_coloursCustomized & 0x0040) ) + m_colSelFore = wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHTTEXT ); + + if ( !(m_coloursCustomized & 0x0080) ) + m_colLine = m_colCapBack; + + if ( !(m_coloursCustomized & 0x0100) ) + m_colDisPropFore = m_colCapFore; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::ResetColours() +{ + m_coloursCustomized = 0; + + RegainColours(); + + Refresh(); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::SetFont( const wxFont& font ) +{ + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::SetFont") ); +#endif + + // Must disable active editor. + if ( m_selected ) + { + bool selRes = ClearSelection(); + wxPG_CHECK_MSG_DBG( selRes, + false, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + // TODO: Following code is disabled with wxMac because + // it is reported to fail. I (JMS) cannot debug it + // personally right now. +#if !defined(__WXMAC__) + bool res = wxScrolledWindow::SetFont( font ); + if ( res ) + { + + CalculateFontAndBitmapStuff( m_vspacing ); + + if ( m_pState ) + { + // Recalculate caption text extents. + // TODO: This should also be done to other pages of manager + // (so add wxPropertyGridManager::SetFont), but since font + // is usually set before categories are added, this is + // quite low priority. + size_t i; + + for ( i=0;iGetParentingType() > 0 ) + ((wxPropertyCategoryClass*)p)->CalculateTextExtent(this,m_captionFont); + } + + CalculateYs(NULL,-1); + } + + Refresh(); + } + + return res; +#else + // ** wxMAC Only ** + // TODO: Remove after SetFont crash fixed. + if ( m_iFlags & wxPG_FL_INITIALIZED ) + { + wxLogDebug(wxT("WARNING: propGrid.cpp: wxPropertyGrid::SetFont has been disabled on wxMac since there has been crash reported in it. If you are willing to debug the cause, replace line '#if !defined(__WXMAC__)' with line '#if 1' in wxPropertyGrid::SetFont.")); + } + return false; +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetLineColour( const wxColour& col ) +{ + m_colLine = col; + m_coloursCustomized |= 0x80; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetMarginColour( const wxColour& col ) +{ + m_colMargin = col; + m_coloursCustomized |= 0x01; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCellBackgroundColour( const wxColour& col ) +{ + m_colPropBack = col; + m_coloursCustomized |= 0x08; + + // Set the cached brush as well. + ((wxPGBrush*)m_arrBgBrushes.Item(0))->SetColour2(col); + + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCellTextColour( const wxColour& col ) +{ + m_colPropFore = col; + m_coloursCustomized |= 0x10; + + // Set the cached colour as well. + ((wxPGColour*)m_arrFgCols.Item(0))->SetColour2(col); + + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCellDisabledTextColour( const wxColour& col ) +{ + m_colDisPropFore = col; + m_coloursCustomized |= 0x100; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetSelectionBackground( const wxColour& col ) +{ + m_colSelBack = col; + m_coloursCustomized |= 0x20; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetSelectionForeground( const wxColour& col ) +{ + m_colSelFore = col; + m_coloursCustomized |= 0x40; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCaptionBackgroundColour( const wxColour& col ) +{ + m_colCapBack = col; + m_coloursCustomized |= 0x02; + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCaptionForegroundColour( const wxColour& col ) +{ + m_colCapFore = col; + m_coloursCustomized |= 0x04; + + // Set the cached colour as well. + ((wxPGColour*)m_arrFgCols.Item(1))->SetColour2(col); + + Refresh(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetBackgroundColourIndex( wxPGProperty* p, int index, int flags ) +{ + unsigned char ind = index; + + if ( (p->m_bgColIndex == 0) || (flags & (wxPG_RECURSE_STARTS|wxPG_FORCE)) ) + p->m_bgColIndex = ind; + + if ( p->GetParentingType() != 0 && (flags & wxPG_RECURSE) ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + unsigned int i; + for ( i=0; iGetCount(); i++ ) + SetBackgroundColourIndex(pwc->Item(i), index, flags & ~(wxPG_RECURSE_STARTS)); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyBackgroundColour( wxPGId id, const wxColour& colour ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + size_t i; + int colInd = -1; + + long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); + + // As it is most likely that the previous colour is used, start comparison + // from the end. + for ( i=(m_arrBgBrushes.GetCount()-1); i>0; i-- ) + { + if ( ((wxPGBrush*)m_arrBgBrushes.Item(i))->GetColourAsLong() == colAsLong ) + { + colInd = i; + break; + } + } + + if ( colInd < 0 ) + { + colInd = m_arrBgBrushes.GetCount(); + wxCHECK_RET( colInd < 256, wxT("wxPropertyGrid: Warning - Only 255 different property background colours allowed.") ); + m_arrBgBrushes.Add( (void*)new wxPGBrush(colour) ); + } + + // Set indexes + SetBackgroundColourIndex(p, colInd, wxPG_RECURSE|wxPG_RECURSE_STARTS); + + // If this was on a visible grid, then draw it. + DrawItemAndChildren(p); +} + +// ----------------------------------------------------------------------- + +wxColour wxPropertyGrid::GetPropertyBackgroundColour( wxPGId id ) const +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxColour()) + + return ((wxPGBrush*)m_arrBgBrushes.Item(p->m_bgColIndex))->GetColour(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetTextColourIndex( wxPGProperty* p, int index, int flags ) +{ + unsigned char ind = index; + + if ( (p->m_fgColIndex == 0) || (flags & (wxPG_RECURSE_STARTS|wxPG_FORCE)) ) + p->m_fgColIndex = ind; + + if ( p->GetParentingType() != 0 && (flags & wxPG_RECURSE) ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + unsigned int i; + for ( i=0; iGetCount(); i++ ) + SetTextColourIndex( pwc->Item(i), index, flags&~(wxPG_RECURSE_STARTS) ); + } +} + +// ----------------------------------------------------------------------- + +int wxPropertyGrid::CacheColour( const wxColour& colour ) +{ + unsigned int i; + int colInd = -1; + + long colAsLong = wxPG_COLOUR(colour.Red(),colour.Green(),colour.Blue()); + + // As it is most likely that the previous colour is used, start comparison + // from the end. + for ( i=(m_arrFgCols.GetCount()-1); i>0; i-- ) + { + if ( ((wxPGColour*)m_arrFgCols.Item(i))->GetColourAsLong() == colAsLong ) + { + colInd = i; + break; + } + } + + if ( colInd < 0 ) + { + colInd = m_arrFgCols.GetCount(); + wxCHECK_MSG( colInd < 256, 0, wxT("wxPropertyGrid: Warning - Only 255 different property foreground colours allowed.") ); + m_arrFgCols.Add( (void*)new wxPGColour(colour) ); + } + + return colInd; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyTextColour( wxPGId id, const wxColour& colour ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + // Set indexes + SetTextColourIndex(p, CacheColour(colour), wxPG_RECURSE|wxPG_RECURSE_STARTS ); + + // If this was on a visible grid, then draw it. + DrawItemAndChildren(p); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetCaptionTextColour( wxPGId id, const wxColour& colour ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + wxCHECK_RET( p->GetParentingType() == PT_CAPTION, + wxT("Only call SetCaptionTextColour for caption properties") ); + + // Set indexes + wxPropertyCategoryClass* cat = (wxPropertyCategoryClass*) p; + cat->SetTextColIndex(CacheColour(colour)); + + // If this was on a visible grid, then draw it. + DrawItemAndChildren(p); +} + +// ----------------------------------------------------------------------- + +wxColour wxPropertyGrid::GetPropertyTextColour( wxPGId id ) const +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxColour()) + + return wxColour(*((wxPGColour*)m_arrFgCols.Item(p->m_fgColIndex))); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyColourToDefault( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + SetBackgroundColourIndex( p, 0, wxPG_RECURSE|wxPG_FORCE ); + SetTextColourIndex( p, 0, wxPG_RECURSE|wxPG_FORCE ); + + if ( p->GetParentingType() == PT_CAPTION ) + { + wxPropertyCategoryClass* cat = (wxPropertyCategoryClass*) p; + cat->SetTextColIndex(1); + } +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid property adding and removal +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGrid::Append( wxPGProperty* property ) +{ + return FROM_STATE(Append(property)); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGrid::_Insert( wxPGProperty* priorthis, wxPGProperty* property ) +{ + wxASSERT( priorthis ); + return FROM_STATE(DoInsert(priorthis->GetParent(), priorthis->GetArrIndex(), property)); +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::Delete( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + wxPropertyGridState* state = p->GetParentState(); + wxPropertyGrid* grid = state->GetGrid(); + + if ( grid->GetState() == state ) + { + bool selRes = grid->DoSelectProperty(wxPGIdGen(NULL), wxPG_SEL_DELETING); + wxPG_CHECK_RET_DBG( selRes, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + state->DoDelete( p ); + + if ( grid->GetState() == state && !grid->IsFrozen() ) + { + // This should be enough to resolve even the worst + // graphics glitch imaginable. + grid->Update(); + grid->Refresh(); + } +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyContainerMethods::ReplaceProperty( wxPGId id, wxPGProperty* property ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGProperty* replaced = wxPGIdToPtr(id); + wxCHECK_MSG( replaced && property, + wxNullProperty, + wxT("NULL property") ); + wxCHECK_MSG( replaced->GetParentingType() == 0 || replaced->GetParentingType() == -1, + wxNullProperty, + wxT("cannot replace this type of property") ); + wxCHECK_MSG( !m_pState->IsInNonCatMode(), + wxNullProperty, + wxT("cannot replace properties in alphabetic mode") ); + + // Get address to the slot + wxPGPropertyWithChildren* parent = replaced->GetParent(); + int ind = replaced->GetIndexInParent(); + + wxPropertyGridState* state = replaced->GetParentState(); + Delete(replaced); // Must use generic Delete + state->DoInsert(parent,ind,property); + + return wxPGIdGen(property); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::PrepareAfterItemsAdded() +{ + + if ( !FROM_STATE(m_itemsAdded) ) return; + +#if __INTENSE_DEBUGGING__ + wxLogDebug(wxT("PrepareAfterItemsAdded( in thread 0x%lX )"), + (unsigned long)wxThread::GetCurrentId()); +#endif + + FROM_STATE(m_itemsAdded) = 0; + + if ( m_windowStyle & wxPG_AUTO_SORT ) + { + Sort (); + } + else + { + if ( m_bottomy < 1 ) + CalculateYs( NULL, -1 ); + else + { + RecalculateVirtualSize(); + // Update visibles array (maybe not necessary here, but just in case) + CalculateVisibles ( -1, true ); + } + } + +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid property value setting and getting +// ----------------------------------------------------------------------- + +void wxPGGetFailed( const wxPGProperty* p, const wxChar* typestr ) +{ + wxPGTypeOperationFailed(p,typestr,wxT("Get")); +} + +// ----------------------------------------------------------------------- + +void wxPGTypeOperationFailed( const wxPGProperty* p, const wxChar* typestr, + const wxChar* op ) +{ + wxASSERT( p != NULL ); + wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."), + op,p->GetLabel().c_str(),wxPG_TO_WXCHAR_PTR(p->GetValueTypePtr()->GetCustomTypeName()),typestr ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyValue( wxPGId id, const wxPGValueType* typeclass, const wxPGVariant& value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + if ( p && m_pState->SetPropertyValue(p,typeclass,value) ) + DrawItemAndValueRelated( p ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyValue( wxPGId id, const wxChar* typestring, const wxPGVariant& value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + if ( p && m_pState->SetPropertyValue(p,typestring,value) ) + DrawItemAndValueRelated( p ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyValueString( wxPGId id, const wxString& value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + if ( m_pState->SetPropertyValueString(p,value) ) + DrawItemAndValueRelated( p ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyValueWxObjectPtr( wxPGId id, wxObject* value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + if ( m_pState->SetPropertyValueWxObjectPtr(p,value) ) + DrawItemAndValueRelated( p ); +} + +// ----------------------------------------------------------------------- + +#ifndef __WXPYTHON__ +void wxPropertyGrid::SetPropertyValue( wxPGId id, wxVariant& value ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + if ( m_pState->SetPropertyValue(p,value) ) + DrawItemAndValueRelated( p ); +} +#endif + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::ClearPropertyValue( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + if ( m_pState->ClearPropertyValue(p) ) + { + DrawItemAndChildren( p ); + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyUnspecified( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + m_pState->SetPropertyUnspecified(p); + DrawItemAndChildren(p); + + wxPGPropertyWithChildren* parent = p->GetParent(); + while ( parent->GetParentingType() <= PT_FIXEDCHILDREN ) + { + DrawItem(parent); + parent = parent->GetParent(); + } +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid miscellaneous GetPropertyXXX methods +// ----------------------------------------------------------------------- + +wxPropertyCategoryClass* wxPropertyGrid::_GetPropertyCategory( wxPGProperty* p ) +{ + wxPGProperty* parent = (wxPGPropertyWithChildren*)p; + wxPGProperty* grandparent = (wxPGProperty*)parent->GetParent(); + do + { + parent = grandparent; + grandparent = (wxPGProperty*)parent->GetParent(); + if ( parent->GetParentingType() >= PT_CAPTION && grandparent ) + return (wxPropertyCategoryClass*)parent; + } while ( grandparent ); + return (wxPropertyCategoryClass*) NULL; +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid property operations +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::EnableProperty( wxPGId id, bool enable ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + if ( enable ) + { + if ( !(p->m_flags & wxPG_PROP_DISABLED) ) + return false; + + // If active, Set active Editor. + if ( p == m_selected ) + DoSelectProperty( p, wxPG_SEL_FORCE ); + } + else + { + if ( p->m_flags & wxPG_PROP_DISABLED ) + return false; + + // If active, Disable as active Editor. + if ( p == m_selected ) + DoSelectProperty( p, wxPG_SEL_FORCE ); + } + + m_pState->EnableProperty(p,enable); + + DrawItemAndChildren( p ); + + return true; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::LimitPropertyEditing( wxPGId id, bool limit ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + m_pState->LimitPropertyEditing(p,limit); + if ( p == m_selected ) + DoSelectProperty( p, wxPG_SEL_FORCE ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::_SetPropertyLabel( wxPGProperty* p, const wxString& newproplabel ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + + p->m_label = newproplabel; + if ( m_windowStyle & wxPG_AUTO_SORT ) + { + Sort(p->GetParent()); + Refresh(); + } + else + DrawItem ( p ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::DoSetPropertyName( wxPGProperty* p, const wxString& newname ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::SetPropertyName( %s -> %s )"), + p->GetName().c_str(), newname.c_str() ); +#endif + + if ( p->GetName().Len() ) FROM_STATE(m_dictName).erase ( wxPGNameConv(p->GetName()) ); + if ( newname.Len() ) FROM_STATE(m_dictName)[newname] = (void*) p; + + p->DoSetName(newname); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::EnsureVisible( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + Update(); + + bool changed = false; + + // Is it inside collapsed section? + if ( p->m_y < 0 ) + { + // expand parents + wxPGProperty* parent = p->GetParent(); + wxPGProperty* grandparent = parent->GetParent(); + + if ( grandparent && grandparent != FROM_STATE(m_properties) ) + Expand ( grandparent ); + + Expand ( parent ); + changed = true; + } + + // Need to scroll? + int vx, vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + + if ( p->m_y < vy ) + { + Scroll (vx, p->m_y/wxPG_PIXELS_PER_UNIT ); + m_iFlags |= wxPG_FL_SCROLLED; + changed = true; + } + else if ( (p->m_y+m_lineHeight) > (vy+m_height) ) + { + Scroll (vx, (p->m_y-m_height+(m_lineHeight*2))/wxPG_PIXELS_PER_UNIT ); + m_iFlags |= wxPG_FL_SCROLLED; + changed = true; + } + + if ( changed ) + DrawItems ( p, p ); + + return changed; +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid helper methods called by properties +// ----------------------------------------------------------------------- + +// Fixes position of wxTextCtrl-like control (wxSpinCtrl usually +// fits into that category as well). +void wxPropertyGrid::FixPosForTextCtrl( wxWindow* ctrl ) +{ + // Center the control vertically + wxRect finalPos = ctrl->GetRect(); + int y_adj = (m_lineHeight - finalPos.height)/2 + wxPG_TEXTCTRLYADJUST; + + // Prevent over-sized control + int sz_dec = (y_adj + finalPos.height) - m_lineHeight; + if ( sz_dec < 0 ) sz_dec = 0; + + finalPos.y += y_adj; + finalPos.height -= (y_adj+sz_dec); + + // STUPID HACK: wxTextCtrl has different indentation with different + // fonts, so this is to solve most common case (ie. using MS Shell Dlg 2 + // or Tahoma - which are usually the same). +/*#ifdef __WXMSW__ + wxString faceName = m_font.GetFaceName(); + int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST; + if ( (faceName == wxT("MS Shell Dlg 2") || + faceName == wxT("Tahoma")) && + m_font.GetWeight() != wxFONTWEIGHT_BOLD ) + textCtrlXAdjust = 0; +#else*/ + const int textCtrlXAdjust = wxPG_TEXTCTRLXADJUST; +//#endif + + finalPos.x += textCtrlXAdjust; + finalPos.width -= textCtrlXAdjust; + + ctrl->SetSize(finalPos); +} + +// ----------------------------------------------------------------------- + +// Control font changer helper. +void wxPropertyGrid::SetCurControlBoldFont() +{ + wxASSERT( m_wndPrimary ); + m_wndPrimary->SetFont( m_captionFont ); +} + +// ----------------------------------------------------------------------- + +wxWindow* wxPropertyGrid::GenerateEditorTextCtrl( const wxPoint& pos, + const wxSize& sz, + const wxString& value, + wxWindow* secondary, + int extraStyle, + int maxLen ) +{ + int tcFlags = wxTE_PROCESS_ENTER | extraStyle; + + if ( m_selected->HasFlag(wxPG_PROP_READONLY) ) + tcFlags |= wxTE_READONLY; + + wxPoint p(pos.x,pos.y); + wxSize s(sz.x,sz.y); + + // Need to reduce width of text control on Mac +#if defined(__WXMAC__) + s.x -= 8; +#endif + + // Take button into acccount + if ( secondary ) + { + s.x -= (secondary->GetSize().x + wxPG_TEXTCTRL_AND_BUTTON_SPACING); + m_iFlags &= ~(wxPG_FL_PRIMARY_FILLS_ENTIRE); + } + + // If the height is significantly higher, then use border, and fill the rect exactly. + bool hasSpecialSize = false; + + if ( (sz.y - m_lineHeight) > 5 ) + hasSpecialSize = true; + +#if wxPG_NAT_TEXTCTRL_BORDER_ANY + + // Create clipper window + wxPGClipperWindow* wnd = new wxPGClipperWindow(); +#if defined(__WXMSW__) + wnd->Hide(); +#endif + wnd->Create(this,wxPG_SUBID1,p,s); + + // This generates rect of the control inside the clipper window + if ( !hasSpecialSize ) + wnd->GetControlRect(wxPG_NAT_TEXTCTRL_BORDER_X, wxPG_NAT_TEXTCTRL_BORDER_Y, p, s); + else + wnd->GetControlRect(0, 0, p, s); + + wxWindow* ctrlParent = wnd; + +#else + + wxWindow* ctrlParent = this; + + if ( !hasSpecialSize ) + tcFlags |= wxNO_BORDER; + +#endif + + wxTextCtrl* tc = new wxTextCtrl(); + +#if defined(__WXMSW__) && !wxPG_NAT_TEXTCTRL_BORDER_ANY + tc->Hide(); +#endif + tc->Create(ctrlParent,wxPG_SUBID1,value, p, s,tcFlags); + +#if wxPG_NAT_TEXTCTRL_BORDER_ANY + wxWindow* ed = wnd; + wnd->SetControl(tc); +#else + wxWindow* ed = tc; +#endif + + // Center the control vertically + if ( !hasSpecialSize ) + FixPosForTextCtrl(ed); + +#ifdef __WXMSW__ + ed->Show(); + if ( secondary ) + secondary->Show(); +#endif + + // Set maximum length + if ( maxLen > 0 ) + tc->SetMaxLength( maxLen ); + + return (wxWindow*) ed; +} + +// ----------------------------------------------------------------------- + +wxWindow* wxPropertyGrid::GenerateEditorButton( const wxPoint& pos, const wxSize& sz ) +{ +#ifdef __WXMAC__ + // Decorations are chunky on Mac, and we can't make the button square, so + // do things a bit differently on this platform. + + wxPoint p(pos.x+sz.x, + pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y); + wxSize s(25, -1); + + wxButton* but = new wxButton(); + but->Create(this,wxPG_SUBID2,wxT("..."),p,s,wxWANTS_CHARS); + + // Now that we know the size, move to the correct position + p.x = pos.x + sz.x - but->GetSize().x - 2; + but->Move(p); + +#else + wxSize s(sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2), + sz.y-(wxPG_BUTTON_SIZEDEC*2)+(wxPG_NAT_BUTTON_BORDER_Y*2)); + + // Reduce button width to lineheight + if ( s.x > m_lineHeight ) + s.x = m_lineHeight; + + wxPoint p(pos.x+sz.x-s.x, + pos.y+wxPG_BUTTON_SIZEDEC-wxPG_NAT_BUTTON_BORDER_Y); + + wxButton* but = new wxButton(); +#ifdef __WXMSW__ + but->Hide(); +#endif + but->Create(this,wxPG_SUBID2,wxT("..."),p,s,wxWANTS_CHARS); + + but->SetFont( m_captionFont ); +#endif + + if ( m_selected->HasFlag(wxPG_PROP_READONLY) ) + but->Disable(); + + return but; +} + +// ----------------------------------------------------------------------- + +wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos, + const wxSize& sz, + wxWindow** psecondary, + int limitedEditing, + wxPGProperty* property ) +{ + wxButton* but = (wxButton*)GenerateEditorButton(pos,sz); + *psecondary = (wxWindow*)but; + + if ( limitedEditing ) + { + #ifdef __WXMSW__ + // There is button Show in GenerateEditorTextCtrl as well + but->Show(); + #endif + return (wxWindow*) NULL; + } + + wxString text; + + if ( !(property->GetFlags() & wxPG_PROP_UNSPECIFIED) ) + text = property->GetValueAsString(property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + + return GenerateEditorTextCtrl(pos,sz,text,but,property->m_maxLen); +} + +// ----------------------------------------------------------------------- + +wxPoint wxPropertyGrid::GetGoodEditorDialogPosition( wxPGProperty* p, + const wxSize& sz ) +{ +#if wxPG_SMALL_SCREEN + // On small-screen devices, always show dialogs with default position and size. + return wxDefaultPosition; +#else + int x = m_splitterx; + int y = p->m_y; + + wxCHECK_MSG( y >= 0, wxPoint(-1,-1), wxT("invalid y?") ); + wxCHECK_MSG( y < (int)m_bottomy, wxPoint(-1,-1), wxT("invalid y?") ); + + ImprovedClientToScreen( &x, &y ); + + int sw = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_X ); + int sh = wxSystemSettings::GetMetric( ::wxSYS_SCREEN_Y ); + + int new_x; + int new_y; + + if ( x > (sw/2) ) + // left + new_x = x + (m_width-m_splitterx) - sz.x; + else + // right + new_x = x; + + if ( y > (sh/2) ) + // above + new_y = y - sz.y; + else + // below + new_y = y + m_lineHeight; + + return wxPoint(new_x,new_y); +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SLAlloc( unsigned int itemcount, const wxChar** items ) +{ + wxArrayString& sl = m_sl; + unsigned int i; + unsigned int sl_oldcount = sl.GetCount(); + if ( sl_oldcount > itemcount ) sl_oldcount = itemcount; +#if wxUSE_INTL + if ( !wxPGGlobalVars->m_autoGetTranslation ) + { +#endif + for ( i=0; i= wxT(' ') + #if !wxUSE_UNICODE + || a < 0 + #endif + ) + { + // This surely is not something that requires an escape sequence. + dst_str << a; + } + else + { + // This might need... + if ( a == wxT('\r') ) + { + // DOS style line end. + // Already taken care below + //dst_str = wxT("\\n"); + //src++; + } + else if ( a == wxT('\n') ) + // UNIX style line end. + dst_str << wxT("\\n"); + else if ( a == wxT('\t') ) + // Tab. + dst_str << wxT('\t'); + else + { + //wxLogDebug(wxT("WARNING: Could not create escape sequence for character #%i"),(int)a); + dst_str << a; + } + } + + prev_a = a; + } + return dst_str; +} + +// ----------------------------------------------------------------------- +// Item iteration macros +// ----------------------------------------------------------------------- + +#define II_INVALID_I 0x00FFFFFF + +#define ITEM_ITERATION_VARIABLES \ + wxPGPropertyWithChildren* parent; \ + unsigned int i; \ + unsigned int iMax; + +#define ITEM_ITERATION_DCAE_VARIABLES \ + wxPGPropertyWithChildren* parent; \ + unsigned int i; \ + unsigned int iMax; + +#define ITEM_ITERATION_INIT_FROM_THE_TOP \ + parent = FROM_STATE(m_properties); \ + i = 0; + +#define ITEM_ITERATION_INIT(startparent,startindex) \ + parent = startparent; \ + i = (unsigned int)startindex; \ + if ( parent == (wxPGPropertyWithChildren*) NULL ) \ + { \ + parent = FROM_STATE(m_properties); \ + i = 0; \ + } + +#define ITEM_ITERATION_LOOP_BEGIN \ + unsigned char parent_expanded; \ + do \ + { \ + parent_expanded = (unsigned char)parent->m_expanded; \ + if ( parent->m_parent && !parent->m_parent->m_expanded ) \ + parent_expanded = 0; \ + iMax = parent->GetCount(); \ + while ( i < iMax ) \ + { \ + wxPGProperty* p = parent->Item(i); \ + int parenting = p->GetParentingType(); + +#define ITEM_ITERATION_LOOP_END \ + if ( parenting ) \ + { \ + i = 0; \ + parent = (wxPGPropertyWithChildren*)p; \ + if ( parent_expanded ) \ + parent_expanded = (unsigned char)parent->m_expanded; \ + else \ + parent_expanded = 0; \ + iMax = parent->GetCount(); \ + } \ + else \ + i++; \ + } \ + i = parent->m_arrIndex + 1; \ + parent = parent->m_parent; \ + } \ + while ( parent != NULL ); + +// DCAE = Don't care about parent_expanded (this is the least space hungry method). +#define ITEM_ITERATION_DCAE_LOOP_BEGIN \ + do \ + { \ + iMax = parent->GetCount(); \ + while ( i < iMax ) \ + { \ + wxPGProperty* p = parent->Item(i); \ + int parenting = p->GetParentingType(); + +#define ITEM_ITERATION_DCAE_LOOP_END \ + if ( parenting ) \ + { \ + i = 0; \ + parent = (wxPGPropertyWithChildren*)p; \ + iMax = parent->GetCount(); \ + } \ + else \ + i++; \ + } \ + i = parent->m_arrIndex + 1; \ + parent = parent->m_parent; \ + } \ + while ( parent != NULL ); + +// DCAE_ISP = Don't care about parent_expanded, Ignore sub-properties. +// Note that this treats fixed sub-properties same as sub-properties +// of wxParentProperty. Mode conversion requires this behaviour. +#define ITEM_ITERATION_DCAE_ISP_LOOP_BEGIN \ + do \ + { \ + iMax = parent->GetCount(); \ + while ( i < iMax ) \ + { \ + wxPGProperty* p = parent->Item(i); \ + int parenting = p->GetParentingType(); + +#define ITEM_ITERATION_DCAE_ISP_LOOP_END \ + if ( parenting > 0 ) \ + { \ + i = 0; \ + parent = (wxPGPropertyWithChildren*)p; \ + iMax = parent->GetCount(); \ + } \ + else \ + i++; \ + } \ + i = parent->m_arrIndex + 1; \ + parent = parent->m_parent; \ + } \ + while ( parent != (wxPGPropertyWithChildren*) NULL ); + + +// VO = Visible only (including those outside the scrolled section). +#define ITEM_ITERATION_VO_LOOP_BEGIN \ + if ( (parent == FROM_STATE(m_properties) || parent->m_y >= 0) && parent->m_expanded ) \ + { \ + do \ + { \ + iMax = parent->GetCount(); \ + while ( i < iMax ) \ + { \ + wxPGProperty* p = parent->Item(i); \ + if ( p->m_y >= 0 ) \ + { \ + int parenting = p->GetParentingType(); + +#define ITEM_ITERATION_VO_LOOP_END \ + if ( parenting && ((wxPGPropertyWithChildren*)p)->m_expanded ) \ + { \ + parent = (wxPGPropertyWithChildren*)p; \ + i = 0; \ + break; \ + } \ + } \ + i++; \ + } \ + if ( i >= iMax ) \ + { \ + i = parent->m_arrIndex + 1; \ + parent = parent->m_parent; \ + } \ + } \ + while ( parent != (wxPGPropertyWithChildren*) NULL ); \ + } + +// ----------------------------------------------------------------------- +// wxPropertyGrid visibility related methods +// ----------------------------------------------------------------------- + +void wxPropertyGrid::CalculateYs( wxPGPropertyWithChildren* startparent, + int startindex ) +{ + // Selection must be temporarily cleared during y-recalc + wxPGProperty* prevSelected = m_selected; + if ( prevSelected ) + { + bool selRes = ClearSelection(); + wxPG_CHECK_RET_DBG( selRes, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + ITEM_ITERATION_VARIABLES + +#if __INTENSE_DEBUGGING__ + wxLogDebug(wxT("CalculateYs(startsfrom: %s[%i] ) "), + startparent?startparent->m_label.c_str():wxT("NULL"), + startindex); +#endif + + ITEM_ITERATION_INIT(startparent,startindex) + + wxASSERT( !m_frozen ); + + int cury = 0; + int lh = m_lineHeight; + + if ( startparent != NULL ) + cury = parent->Item(i)->m_y; + + wxASSERT_MSG( cury >= 0, wxT("CalculateYs first item was not visible!!!") ); + + long hide_state = m_iFlags & wxPG_FL_HIDE_STATE; + bool inside_hidden_part = false; + //parent_expanded = (unsigned char)parent->m_expanded; + wxPGPropertyWithChildren* nearest_expanded = (wxPGPropertyWithChildren*) NULL; + + // Find first visible and expanded parent. + while ( !parent->IsExpanded() || + ( (parent->m_flags & wxPG_PROP_HIDEABLE) && hide_state ) + ) + { + parent = parent->GetParent(); + i = 0; + } + + wxASSERT( parent ); + + //parent = nearest_expanded; + + do + { + iMax = parent->GetCount(); + + if ( !inside_hidden_part ) + { + while ( i < iMax ) + { + wxPGProperty* p = parent->Item(i); + + int parenting = p->GetParentingType(); + if ( !(p->m_flags & wxPG_PROP_HIDEABLE) || (!hide_state) ) + { + // item is visible (all parents are expanded, non-hideable or not in hide state) + p->m_y = (int)cury; + cury += lh; + + } + else + { + p->m_y = -1; + } + + if ( parenting ) + { + wxPGPropertyWithChildren* p2 = (wxPGPropertyWithChildren*)p; + + if ( !p2->m_expanded || + ( (p2->m_flags & wxPG_PROP_HIDEABLE) && hide_state ) + ) + { + inside_hidden_part = true; + nearest_expanded = parent; + } + + parent = p2; + i = 0; + + break; + } + + i++; + } + } + else + { + while ( i < iMax ) + { + wxPGProperty* p = parent->Item(i); + int parenting = p->GetParentingType(); + p->m_y = -1; + if ( parenting ) + { + parent = (wxPGPropertyWithChildren*)p; + i = 0; + break; + } + i++; + } + } + if ( i >= iMax ) + { + i = parent->m_arrIndex + 1; + parent = parent->m_parent; + if ( inside_hidden_part && parent == nearest_expanded ) + { + inside_hidden_part = false; + } + } + } + while ( parent != (wxPGPropertyWithChildren*) NULL ); + + m_bottomy = cury; + +#if __INTENSE_DEBUGGING__ + wxLogDebug(wxT(" \\-> m_bottomy = %i"),(int)m_bottomy); +#endif + + // Forces a new DoGetBestSize() call. + wxScrolledWindow::InvalidateBestSize(); + + // Visibles need to be recalculated *always* after y recalculation + // (but make sure it stays here, above RecalculateVirtualSize). + CalculateVisibles( -1, true ); + + RecalculateVirtualSize(); + + // Reselect + if ( prevSelected ) + DoSelectProperty( prevSelected, wxPG_SEL_NONVISIBLE ); + +} + +// ----------------------------------------------------------------------- + +// Call when scroll position changes. Do not pre-fill m_prevVY. +void wxPropertyGrid::CalculateVisibles( int vy, bool full_recalc ) +{ + if ( vy < 0 ) + { + int vx; + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; + if ( full_recalc ) + m_prevVY = -1; + } + + // Control not yet properly built. + if ( vy >= (int)m_bottomy ) + return; + + if ( m_height < 0 ) + return; + + // Hide popup + // FIXME: Delete after transient popup support fully added + if ( m_wndPrimary && m_wndPrimary->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) ) + ((wxPGOwnerDrawnComboBox*)m_wndPrimary)->HidePopup(); + + int vy2 = vy + m_height; + + if ( vy2 > (int)m_bottomy ) + vy2 = m_bottomy; + + unsigned int arr_index = 0; + unsigned int vis_height = vy2-vy; + unsigned int new_item_count = vis_height/m_lineHeight; + if ( vis_height % m_lineHeight ) + new_item_count++; + + wxPGArrayProperty& arr = m_arrVisible; + + arr.SetCount ( new_item_count ); + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::CalculateVisibles ( vy=%i, vy2=%i, m_height=%i, newitemcount=%i, lineheight=%i )"), + (int)vy, (int)vy2, (int)m_height, (int)new_item_count, (int)m_lineHeight ); +#endif + + //wxASSERT( vy != m_prevVY ); + wxASSERT( vy >= 0 ); + + if ( !new_item_count ) + { + arr.Empty(); + return; + } + + ITEM_ITERATION_VARIABLES + + wxPGProperty* base = NULL; + + // Will simpler operation be enough? + if ( m_prevVY >= 0 ) + { + if ( m_calcVisHeight == m_height ) + { + if ( m_iFlags & wxPG_FL_SCROLLED ) + { + int diff = vy - m_prevVY; + if ( diff == m_lineHeight ) + { + // Scrolled one down + base = DoGetItemAtY_Full( vy2 - 1 ); + wxASSERT( base ); + arr_index = new_item_count - 1; + for ( i=0; iarr_index; i-- ) + arr.Item(i) = arr.Item(i-1); + arr.Item(arr_index) = base; + base = (wxPGProperty*) NULL; + } + else + base = DoGetItemAtY_Full( vy ); + } + else + base = DoGetItemAtY_Full( vy ); + } + else + if ( m_prevVY == vy && !(m_iFlags & wxPG_FL_SCROLLED) ) + { + if ( m_height > m_calcVisHeight ) + { + // Increased height - add missing items + arr_index = (m_calcVisHeight-1)/m_lineHeight; + if ( arr_index >= new_item_count ) + { + // Now, were probably below last item here + //if ( (vy+m_calcVisHeight) >= (int)m_bottomy ) + base = NULL; + /*else + arr_index = arr.GetCount()-1;*/ + } + else + { + base = (wxPGProperty*) arr.Item( arr_index ); + } + } + else + { + // Decreased height - do nothing + //base = NULL; + } + } + else + base = DoGetItemAtY_Full( vy ); + } + else + { + base = DoGetItemAtY_Full( vy ); + } + + if ( base ) + { + ITEM_ITERATION_INIT(base->m_parent,base->m_arrIndex) + + #if __INTENSE_DEBUGGING__ + wxLogDebug( wxT(" Starting at index %i"), (int)arr_index ); + #endif + + ITEM_ITERATION_VO_LOOP_BEGIN + + //wxASSERT( p->m_y >= 0 ); + + // update visibility limit reached? + if ( p->m_y >= vy2 ) { parent = NULL; break; } + + #ifdef __WXDEBUG__ + if ( arr_index >= arr.GetCount() ) + { + wxLogDebug(wxT(" wxPropertyGrid::CalculateVisibles Loop overflow (index=%i,vy+vis_height=%i,p->m_y=%i)"), + (int)arr_index,(int)(vy+vis_height),(int)p->m_y); + } + #endif + + arr.Item(arr_index) = (void*)p; + arr_index++; + + ITEM_ITERATION_VO_LOOP_END + } + + // Adjust controls + /*if ( m_selected ) + { + int adjust = prevVY - vy; + if ( adjust ) + { + wxPoint cp(0,adjust); + + if ( m_wndPrimary ) + m_wndPrimary->Move ( m_wndPrimary->GetPosition() + cp ); + + if ( m_wndSecondary ) + m_wndSecondary->Move ( m_wndSecondary->GetPosition() + cp ); + } + }*/ + + m_iFlags &= ~(wxPG_FL_SCROLLED); + + m_prevVY = vy; + + m_calcVisHeight = m_height; + +} + +// ----------------------------------------------------------------------- + +// This version uses the visible item cache. +wxPGProperty* wxPropertyGrid::DoGetItemAtY( int y ) +{ + + //wxASSERT( m_prevVY >= 0 ); + + // Outside(check 1)? + if ( y >= (int)m_bottomy || y < 0 ) + { + /* + #if __PAINT_DEBUGGING__ + wxLogDebug(wxT("WARNING: DoGetItemAtY(a): y = %i"),y); + #endif + */ + return (wxPGProperty*) NULL; + } + + int vx, vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + + // Need to recalculate visibility cache + // Note: need to check for y < m_prevVY is a hack. + if ( m_prevVY != vy ||y < m_prevVY ) //m_iFlags & wxPG_FL_SCROLLED || + CalculateVisibles( vy, true ); + + // Outside(check 2)? + if ( y >= (vy+m_height) ) + { + /* + #if __PAINT_DEBUGGING__ + wxLogDebug(wxT("WARNING: DoGetItemAtY(b): y = %i"),y); + #endif + */ + return (wxPGProperty*) NULL; + } + + unsigned int index = (unsigned int)((y - vy) / m_lineHeight); + + // Consistency checks + if ( !m_arrVisible.GetCount() ) + return (wxPGProperty*) NULL; + + if ( index >= m_arrVisible.GetCount() ) + { +#ifdef __WXDEBUG__ + wxLogDebug(wxT(" index = %i"),(int)index); + wxLogDebug(wxT(" (height/lineheight+1) = %i"),(int)((m_height/m_lineHeight)+1)); + wxLogDebug(wxT(" m_arrVisible.GetCount() = %i"),(int)m_arrVisible.GetCount()); + + // This was wxCHECK_MSG, but I don't want it to show, since it can happen from + // time to time, and I probably won't fix in the current version of wxPropertyGrid. + wxLogDebug( wxT("Not enough entries in m_arrVisible (y was < m_bottomy).") ); +#endif + + return (wxPGProperty*) NULL; + } + + if ( index >= m_arrVisible.GetCount() ) + { + index = m_arrVisible.GetCount()-1; + } + + return (wxPGProperty*)m_arrVisible.Item(index); +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid graphics related methods +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) +{ + + wxPG_PAINT_DC_INIT() + + // Don't paint after destruction has begun + if ( !(m_iFlags & wxPG_FL_INITIALIZED) ) + return; + +#if __PAINT_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::OnPaint()") ); +#endif + + // Find out where the window is scrolled to + int vx,vy; // Top left corner of client + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; + + // Update everything inside the box + wxRect r = GetUpdateRegion().GetBox(); + + r.y += vy; + + // Repaint this rectangle + //if ( r.height > 0 ) + DrawItems ( dc, r.y, r.y + r.height, + #if wxPG_ALLOW_CLIPPING + NULL //&r + #else + NULL + #endif + ); + + // We assume that the size set when grid is shown + // is what is desired. + m_iFlags |= wxPG_FL_GOOD_SIZE_SET; + +} + +// ----------------------------------------------------------------------- + +// +// This is the one called by OnPaint event handler and others. +// topy and bottomy are already unscrolled +// Clears any area in coordinates that doesn't have items. +// +void wxPropertyGrid::DrawItems( wxDC& dc, + unsigned int topy, + unsigned int bottomy, + const wxRect* clipRect ) +{ + if ( m_frozen || m_height < 1 || bottomy < topy || !m_pState ) return; + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT("wxPropertyGrid::DrawItems ( %i -> %i, clipRect = 0x%X )"),topy,bottomy, + (unsigned int)clipRect); +#endif + + // items added check + if ( FROM_STATE(m_itemsAdded) ) PrepareAfterItemsAdded(); + + unsigned int vx, vy; // Top left corner of client + GetViewStart((int*)&vx,(int*)&vy); + vy *= wxPG_PIXELS_PER_UNIT; + + unsigned int client_bottom = (unsigned int)m_height + vy; + + // Clip topy and bottomy + if ( bottomy > client_bottom ) + bottomy = client_bottom; + if ( topy < vy ) + topy = vy; + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT(" \\--> ( final area %i -> %i )"),topy,bottomy); +#endif + + // + // Determine first and last item to draw + // (don't draw if already over the top) + // + + if ( topy < client_bottom && topy < m_bottomy && FROM_STATE(m_properties)->GetCount() > 0 ) + { + + wxPGProperty* firstItem = DoGetItemAtY(topy); + + if ( firstItem == (wxPGProperty*) NULL ) + { + #ifdef __WXDEBUG__ + wxString msg; + msg.Printf(wxT("WARNING: wxPropertyGrid::DrawItems(): firstItem == NULL!")); + wxMessageBox(msg); + wxLogDebug(msg); + wxLogDebug(wxT(" More info: y: %i -> %i visible_window: %i -> %i"), + (int)topy,(int)bottomy,(int)vy,(int)client_bottom); + // This is here for debugging purposes. + DoGetItemAtY(topy); + #endif + return; + } + + wxPGProperty* lastItem = (wxPGProperty*) NULL; + + // lastItem may be NULL on call to DoDrawItems + // in this case lastItem will truly become the last item + + if ( bottomy > topy && bottomy < m_bottomy ) + { + lastItem = DoGetItemAtY(bottomy-1); + #if __PAINT_DEBUGGING__ + wxLogDebug( wxT(" \\--> WARNING: lastItem acquisition failed (should not)!")); + #endif + } + + DoDrawItems( dc, firstItem, lastItem, clipRect ); + } + + // Clear area beyond m_bottomy? + if ( bottomy > m_bottomy ) + { + wxColour& bgc = wxPG_SLACK_BACKROUND; + //wxColour& bgc = wxColour(255,0,255); + dc.SetPen ( wxPen(bgc) ); + dc.SetBrush ( wxBrush(bgc) ); + unsigned int clear_top = m_bottomy; + if ( topy > clear_top ) clear_top = topy; + dc.DrawRectangle ( 0, clear_top, m_width, m_height-(clear_top-vy) ); + } +} + +// ----------------------------------------------------------------------- + +#define DECLARE_ITEM_ITERATION_UVC_VARIABLES \ + unsigned int ind; \ + wxPGProperty* p; + +// UVC = Use Visibility Cache +// VISTART = index to first item from visibility cache to use. +// BOTTOMY = Logical y coordinate of last item to draw. +#define ITEM_ITERATION_UVC_LOOP_BEGIN(VISTART,BOTTOMY) \ + ind = VISTART; \ + do \ + { \ + p = (wxPGProperty*)m_arrVisible.Item(ind); \ + ind++; \ + int parenting = p->GetParentingType(); + +#define ITEM_ITERATION_UVC_LOOP_END(BOTTOMY) \ + } while ( p->m_y < BOTTOMY ); \ + + +void wxPropertyGrid::DoDrawItems( wxDC& dcMain, + const wxPGProperty* firstItem, + const wxPGProperty* lastItem, + const wxRect* clipRect ) +{ + if ( m_frozen || m_height < 1 ) + return; + + //wxCHECK_RET( !FROM_STATE(m_itemsAdded), wxT("m_itemsAdded must be zero at this point") ); + + // items added check + if ( FROM_STATE(m_itemsAdded) ) PrepareAfterItemsAdded(); + + wxCHECK_RET( firstItem != NULL, wxT("invalid first item") ); + wxASSERT( FROM_STATE(m_properties->GetCount()) ); + + // Make sure visibility cache is up-to-date + int vy; + int vx; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + if ( vy != m_prevVY ) + CalculateVisibles(vy,true); + + if ( vy != m_prevVY ) + return; + + // Determine last item, if not given (but requires clipRect). + if ( lastItem == NULL ) + { + if ( clipRect != NULL ) + { + unsigned int bottomy = clipRect->y + clipRect->height; + + if ( bottomy <= (unsigned int)firstItem->m_y ) + lastItem = firstItem; + } + + if ( lastItem == NULL ) + { + lastItem = DoGetItemAtY(vy+m_height-1); + if ( lastItem == NULL ) + lastItem = GetLastItem(true); + } + } + + DoDrawItems2(dcMain, firstItem, lastItem, clipRect); +} + +// +// Uses three pass approach, so it is optimized for drawing +// multiple items at once. +// +// IMPORTANT NOTES: +// - Clipping rectangle must be of physical coordinates. +// +// +void wxPropertyGrid::DoDrawItems2( wxDC& dcMain, + const wxPGProperty* firstItem, + const wxPGProperty* lastItem, + const wxRect* clipRect ) const +{ + int lh = m_lineHeight; + + int vy; + int vx; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + + int firstItemTopY = firstItem->m_y; + int lastItemBottomY = lastItem->m_y+lh-1; + + int yRelMod = 0; + + // Entire range outside scrolled, visible area? + if ( firstItemTopY >= (vy+m_height) || lastItemBottomY <= vy ) + return; + + wxCHECK_RET( firstItemTopY < lastItemBottomY, wxT("invalid y values") ); + + wxDC* dcPtr; + +#if wxPG_DOUBLE_BUFFER + wxMemoryDC* bufferDC = NULL; + const wxRect* blitClipRect = NULL; + int renderHeight = lastItem->m_y - firstItemTopY + m_lineHeight; + + if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) ) + { + if ( !m_doubleBuffer ) + return; + + // Must fit to double-buffer + #ifdef __WXDEBUG__ + if ( (lastItemBottomY - firstItemTopY) > m_doubleBuffer->GetHeight() ) + { + wxString msg; + msg.Printf( wxT("wxPropertyGrid: DOUBLE-BUFFER TOO SMALL ( drawn %i vs db height %i vs client_height %i)!"), + (int)(lastItemBottomY - firstItemTopY), + (int)(m_doubleBuffer->GetHeight()), + (int)m_height ); + wxLogError(msg); + wxLogDebug(msg); + } + #endif + + bufferDC = new wxMemoryDC(); + bufferDC->SelectObject( *m_doubleBuffer ); + dcPtr = bufferDC; + + blitClipRect = clipRect; + + //if ( m_iFlags & wxPG_FL_CHANGED || + // !(m_iFlags & wxPG_FL_HANDLING_PAINT_EVENT) ) + //{ + } + else +#endif + { + dcPtr = &dcMain; + } + + wxDC& dc = *dcPtr; + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT(" -> DoDrawItems ( \"%s\" -> \"%s\", height=%i (ch=%i), clipRect = 0x%lX )"), + firstItem->GetLabel().c_str(), + lastItem->GetLabel().c_str(), + (int)(lastItemBottomY - firstItemTopY), + (int)m_height, + (unsigned long)clipRect ); +#endif + + wxPGPaintData paintdata; + wxRect r; + + DECLARE_ITEM_ITERATION_UVC_VARIABLES + + // Get first and last indexes to visibility cache + unsigned int viStart = (firstItemTopY - vy) / lh; + int vi_end_y = lastItem->m_y; + + if ( viStart >= m_arrVisible.GetCount() ) + { + wxLogDebug(wxT("WARNING: viStart >= m_arrVisible.GetCount() ( %i >= %i )"), + (int)viStart, (int)m_arrVisible.GetCount() ); + return; + } + +#ifdef __WXDEBUG__ + unsigned int viEnd = (lastItem->m_y - vy) / lh; + if ( viEnd >= m_arrVisible.GetCount() ) + { + wxLogDebug(wxT("WARNING: viEnd >= m_arrVisible.GetCount() ( %i >= %i )"), + (int)viEnd, (int)m_arrVisible.GetCount() ); + return; + } +#endif + + int x = m_marginWidth; + int y; + + long window_style = m_windowStyle; + int extraStyle = GetExtraStyle(); + + // + // With wxPG_DOUBLE_BUFFER, do double buffering + // - buffer's y = 0, so align cliprect and coordinates to that + // +#if wxPG_DOUBLE_BUFFER + if ( bufferDC ) + { + wxRect cr2; + + //yRelMod = firstItemTopY; + yRelMod = vy; + + // + // clipRect conversion + if ( clipRect ) + { + cr2 = *clipRect; + cr2.y -= yRelMod; + clipRect = &cr2; + } + //int renderHeight = lastItem->m_y - firstItemTopY + m_lineHeight; + //lastItemBottomY -= firstItemTopY; + //firstItemTopY = 0; + firstItemTopY -= vy; + lastItemBottomY -= vy; + } +#endif + + const wxFont& normalfont = m_font; + + bool reallyFocused = (m_iFlags & wxPG_FL_FOCUSED) ? true : false; + + bool isEnabled = IsEnabled(); + + // + // Prepare some pens and brushes that are often changed to. + // + + wxBrush marginBrush(m_colMargin); + wxPen marginPen(m_colMargin); + wxBrush capbgbrush(m_colCapBack,wxSOLID); + wxPen linepen(m_colLine,1,wxSOLID); + + // pen that has same colour as text + wxPen outlinepen(m_colPropFore,1,wxSOLID); + + if ( clipRect ) + dc.SetClippingRegion( *clipRect ); + + // + // Clear margin with background colour + // + dc.SetBrush( marginBrush ); + if ( !(window_style & wxPG_HIDE_MARGIN) ) + { + dc.SetPen( *wxTRANSPARENT_PEN ); + dc.DrawRectangle(-1,firstItemTopY-1,m_marginWidth+2,lastItemBottomY-firstItemTopY+3); + } + + /* + // This colorizer helps to debug painting. + bool small_draw = false; + if ( renderHeight < (m_height-(lh*3)) ) + { + if ( firstItem == lastItem ) + { + bgbrush = wxBrush(wxColour(255,128,128)); + linepen = wxPen(wxColour(128,0,255)); + //boxbrush = wxBrush(wxColour(192,192,192)); + } + else + { + bgbrush = wxBrush(wxColour(128,255,128)); + linepen = wxPen(wxColour(0,0,255)); + //boxbrush = wxBrush(wxColour(230,230,230)); + } + small_draw = true; + } + */ + + //dc.SetPen ( *wxTRANSPARENT_PEN ); + //dc.SetFont(normalfont); + + wxPGProperty* selected = m_selected; + +/*#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + bool selected_painted = false; +#endif*/ + + // NOTE: Clipping and pen/brush switching are main reasons for multi-pass approach. + + // + // zero'th pass: Wireframes. + // (this could be embedded in another loop) + + dc.SetBrush( marginBrush ); + + unsigned long cur_first_ind = viStart; + unsigned long next_cur_first_ind = 0xFFFFFFFF; + wxPGPropertyWithChildren* cur_category = (wxPGPropertyWithChildren*) NULL; + int vcache_last_item_y = vy + m_height; + if ( vcache_last_item_y > (int)m_bottomy ) vcache_last_item_y = m_bottomy; + vcache_last_item_y -= lh; + + ITEM_ITERATION_UVC_LOOP_BEGIN(viStart,vi_end_y) + + wxPGPropertyWithChildren* parent = p->GetParent(); + + // Should not happen (but this is better than a crash)... + wxCHECK_RET( parent, wxT("NULL parent") ); + + // Does this wireframe end? + // Conditions: + // A) This is last item within its parent, and parent is category. + // B) Next is category. + // C) This is collapsed category. + // D) This is the last item drawn. + + if ( p->m_y >= vi_end_y ) + { + // This is the last item. + //wxLogDebug(wxT("--> last item")); + next_cur_first_ind = ind; + } + else if ( p->m_arrIndex >= (parent->GetCount()-1) && parent->GetParentingType() >= PT_CAPTION && + ( parenting <= 0 /*|| ((wxPGPropertyWithChildren*)p)->GetCount() < 1*/ ) + ) + { + // This is last item within its parent, and parent is category, but this isn't + // an non-empty category. + //wxLogDebug(wxT("--> category ends")); + cur_category = (wxPropertyCategoryClass*)parent; + next_cur_first_ind = ind; + } + else if ( ((wxPGProperty*)m_arrVisible.Item(ind))->GetParentingType() >= PT_CAPTION ) + { + // Next item is a category. + //wxLogDebug(wxT("--> next item is category")); + next_cur_first_ind = ind; + } + else if ( parenting > 0 && + (!((wxPGPropertyWithChildren*)p)->IsExpanded() || + !((wxPGPropertyWithChildren*)p)->GetCount()) ) + { + // This is collapsed category. + //wxLogDebug(wxT("--> collapsed category")); + cur_category = (wxPropertyCategoryClass*)p; + next_cur_first_ind = ind; + } + + // When new category begins or old ends, draw wireframe for items in-between + if ( next_cur_first_ind < 0xFFFFFF ) + { + + wxPGProperty* cur_first = (wxPGProperty*)m_arrVisible.Item(cur_first_ind); + wxPGPropertyWithChildren* cur_last_item = (wxPGPropertyWithChildren*)p; + + if ( !cur_category ) + { + if ( cur_first->GetParentingType() >= PT_CAPTION ) + { + cur_category = (wxPropertyCategoryClass*)cur_first; + } + else if ( !(m_windowStyle & wxPG_HIDE_CATEGORIES) ) + { + cur_category = _GetPropertyCategory(cur_first); + /*if ( !cur_category ) + cur_category = (wxPropertyCategoryClass*)FROM_STATE(m_properties);*/ + } + } + + int draw_top = cur_first->m_y - yRelMod; + int draw_bottom = cur_last_item->m_y + lh - yRelMod; + int frame_top = draw_top; + int frame_bottom = draw_bottom; + int margin_top = draw_top; + int margin_bottom = draw_bottom; + + int ly = frame_top + lh - 1; + + if ( cur_first->GetParentingType() >= PT_CAPTION ) + { + wxPropertyCategoryClass* pc = ((wxPropertyCategoryClass*)cur_first); + frame_top += lh; + if ( !pc->IsExpanded() ) + { + // Category collapsed. + frame_top = frame_bottom + 1; + } + } + + int grey_x = x; + if ( cur_category /*!(window_style & wxPG_HIDE_CATEGORIES)*/ ) + grey_x += ((unsigned int)((cur_category->GetDepth()-1)*m_subgroup_extramargin)); + + //wxLogDebug( wxT("wireframe: %s -> %s (grey_x:%i)"), cur_first->GetLabel().c_str(), + // cur_last_item->GetLabel().c_str(),((int)grey_x-x)); + + dc.SetPen( *wxTRANSPARENT_PEN ); + + // Clear extra margin area. + dc.DrawRectangle( x-1, margin_top, grey_x - x + 1, margin_bottom-margin_top ); + + dc.SetPen( linepen ); + + if ( frame_bottom > frame_top ) + { + + //if ( cat_top < firstItemTopY ) + // cat_top = firstItemTopY; + + + // Margin Edge + dc.DrawLine ( grey_x, frame_top, grey_x, frame_bottom ); + + // Splitter + dc.DrawLine ( m_splitterx, frame_top, m_splitterx, frame_bottom ); + + // Horizontal Lines + while ( ly < (frame_bottom-1) ) + { + dc.DrawLine ( grey_x, ly, m_width, ly ); + ly += lh; + } + } + + int use_depth = grey_x; // Default is to simply tidy up this wireframe. + + // Properly draw top line of next wireframe, if adjacent. + + // Get next item. + wxPGProperty* next_item; + //if ( ind < m_arrVisible.GetCount() ) + if ( cur_last_item->m_y < vcache_last_item_y ) + { + next_item = (wxPGProperty*)m_arrVisible.Item(ind); + } + else + { + // Was not in visibility cache, so use clumsier method. + next_item = GetNeighbourItem(cur_last_item,true,1); + if (!next_item) + next_item = cur_last_item; // This will serve our purpose. + } + //wxLogDebug(wxT("next_item: %s"),next_item->GetLabel().c_str()); + + // Just take the depth and is-it-category out of it. + int next_parenting = next_item->GetParentingType(); + int last_parenting = cur_last_item->GetParentingType(); + + // A) If both are categories, draw line with background colour. + // B) If only next is category, use its category's depth. + // C) If only last is category, use grey_x as depth. + // D) If neither is a category, use smaller. + if ( next_parenting > 0 ) + { + // Next is category. + + if ( last_parenting > 0 ) + { + // Last is a category too - draw complete line with background colour. + dc.SetPen ( marginPen ); + use_depth = x; + } + } + else + { + // Next is not a category. + wxPropertyCategoryClass* next_cat = _GetPropertyCategory(next_item); + int depth_next = x; + if ( next_cat && /*cur_category*/ !(window_style & wxPG_HIDE_CATEGORIES) ) + { + //wxLogDebug(wxT("next_item_cat: %s"),next_cat->GetLabel().c_str()); + depth_next += ((unsigned int)((next_cat->GetDepth()-1)*m_subgroup_extramargin)); + } + + if ( last_parenting <= 0 ) + { + // Last is not a category - use lesser depth + if ( depth_next < grey_x ) + use_depth = depth_next; + //wxLogDebug(wxT("- neither is category")); + } + else + { + // Last is a category + use_depth = depth_next; + //wxLogDebug(wxT("last only is category")); + } + } + + //wxLogDebug(wxT("last_line_use_depth: %i"),(int)use_depth); + dc.DrawLine( use_depth, ly, m_width, ly ); + + cur_first_ind = next_cur_first_ind; + next_cur_first_ind = 0xFFFFFFFF; + //cur_first = (wxPGPropertyWithChildren*)p; + cur_category = (wxPGPropertyWithChildren*) NULL; + } + + //cur_last_item = p; + + ITEM_ITERATION_UVC_LOOP_END(vi_end_y) + + // + // First pass: Category background and text, Images, Label+value background. + // + + //wxLogDebug(wxT(" \\--> first pass...")); + y = firstItemTopY; + + dc.SetFont( m_captionFont ); + dc.SetPen( *wxTRANSPARENT_PEN ); + + ITEM_ITERATION_UVC_LOOP_BEGIN(viStart,vi_end_y) + + y += m_spacingy; + + int text_x = x + ((unsigned int)((p->GetDepth()-1)*m_subgroup_extramargin)); + + if ( parenting > 0 ) + { + + dc.SetBrush( capbgbrush ); // Category label background colour. + + // Category - draw background, text and possibly selection rectangle. + wxPropertyCategoryClass* pc = (wxPropertyCategoryClass*)p; + + // Note how next separator line is overdrawn if next item is category . + int useLh = lh; + if ( ind < (m_arrVisible.GetCount()) && + ( ((wxPGProperty*)m_arrVisible[ind])->GetParentingType() <= 0 ) ) + useLh -= 1; + + if ( isEnabled && p->IsEnabled() ) + dc.SetTextForeground( *(wxPGColour*)m_arrFgCols[pc->GetTextColIndex()] ); + else + dc.SetTextForeground( m_colDisPropFore ); + + dc.DrawRectangle( text_x, y-m_spacingy, m_width-text_x, useLh ); + dc.DrawText( pc->GetLabel(), text_x+wxPG_XBEFORETEXT, y ); + + // active caption gets nice dotted rectangle + if ( p == selected ) + { + wxRect focusRect(text_x+wxPG_XBEFORETEXT-wxPG_CAPRECTXMARGIN, + y-wxPG_CAPRECTYMARGIN, + pc->GetTextExtent()+(wxPG_CAPRECTXMARGIN*2), + m_fontHeight+(wxPG_CAPRECTYMARGIN*2)); + wxPGDrawFocusRect(dc,focusRect); + + dc.SetPen( *wxTRANSPARENT_PEN ); + } + + } + else + { + + // Basic background colour. + dc.SetBrush( *(wxPGBrush*)m_arrBgBrushes[p->m_bgColIndex] ); + + //wxLogDebug(wxT("%s: %i"),p->m_label.c_str(),(int)p->m_depthBgCol); + + int greyDepth = 0; + if ( !(window_style & wxPG_HIDE_CATEGORIES) ) + greyDepth = (((int)p->m_depthBgCol)-1) * m_subgroup_extramargin; + + // In two parts to retain splitter + + if ( p == m_selected ) + { + // Selected get different label background. + if ( reallyFocused ) + dc.SetBrush( m_colSelBack ); + else + dc.SetBrush( m_colLine ); + + dc.DrawRectangle( x+greyDepth+1, y-m_spacingy, m_splitterx-greyDepth-x-1, lh-1 ); + + } + else + { + dc.DrawRectangle( x+greyDepth+1, y-m_spacingy, m_splitterx-greyDepth-x-1, lh-1 ); + } + + dc.DrawRectangle( m_splitterx+1, y-m_spacingy, m_width-m_splitterx, lh-1 ); + + } + + y += m_fontHeight+m_spacingy+1; + + ITEM_ITERATION_UVC_LOOP_END(vi_end_y) + + dc.SetFont( normalfont ); + + // + // Second pass: Expander Buttons, Labels. + // + // Second pass happens entirely on the left side, so sometimes + // we can just skip it. + + if ( clipRect == NULL || clipRect->x < m_splitterx ) + { + //wxLogDebug(wxT(" \\--> second pass...")); + + y = firstItemTopY; + + r = wxRect(0,y,m_splitterx,lastItemBottomY); + dc.SetClippingRegion ( r ); + + dc.SetFont(normalfont); + + ITEM_ITERATION_UVC_LOOP_BEGIN(viStart,vi_end_y) + + if ( isEnabled && (p->IsEnabled() || !(extraStyle & wxPG_EX_GREY_LABEL_WHEN_DISABLED)) ) + dc.SetTextForeground( *(wxPGColour*)m_arrFgCols[p->m_fgColIndex] ); + else + dc.SetTextForeground( m_colDisPropFore ); + + // + // Expand/collapse button image. + if ( parenting != 0 && + !(window_style & wxPG_HIDE_MARGIN) && + ((wxPGPropertyWithChildren*)p)->GetChildCount() ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + int depth = p->m_depth - 1; + + #ifdef wxPG_ICON_WIDTH + int imageX = m_gutterWidth + ( depth * m_subgroup_extramargin ); + #endif + + y += m_buttonSpacingY; + + #if (wxPG_USE_RENDERER_NATIVE) + // Prepare rectangle to be used + r.x = imageX; r.y = y; + r.width = m_iconWidth; r.height = m_iconHeight; + #elif wxPG_ICON_WIDTH + // Drawing expand/collapse button manually + dc.SetPen(m_colPropFore); + if ( parenting > 0 ) + { + dc.SetBrush(*wxTRANSPARENT_BRUSH); + } + else + { + dc.SetBrush(m_colPropBack); + } + dc.DrawRectangle( imageX, y, m_iconWidth, m_iconWidth ); + int _y = y+(m_iconWidth/2); + dc.DrawLine(imageX+2,_y,imageX+m_iconWidth-2,_y); + #else + wxBitmap* bmp; + #endif + + if ( pwc->m_expanded ) + { + // wxRenderer functions are non-mutating in nature, so it + // should be safe to cast "const wxPropertyGrid*" to "wxWindow*". + // Hopefully this does not cause problems. + #if (wxPG_USE_RENDERER_NATIVE) + wxRendererNative::Get().DrawTreeItemButton( + (wxWindow*)this, + dc, + r, + wxCONTROL_EXPANDED + ); + #elif wxPG_ICON_WIDTH + // + #else + bmp = m_collbmp; + #endif + + } + else + { + #if (wxPG_USE_RENDERER_NATIVE) + wxRendererNative::Get().DrawTreeItemButton( + (wxWindow*)this, + dc, + r, + 0 + ); + #elif wxPG_ICON_WIDTH + int _x = imageX+(m_iconWidth/2); + dc.DrawLine(_x,y+2,_x,y+m_iconWidth-2); + #else + bmp = m_expandbmp; + #endif + } + + #if (wxPG_USE_RENDERER_NATIVE) + // + #elif wxPG_ICON_WIDTH + // + #else + dc.DrawBitmap( *bmp, m_gutterWidth, y, true ); + #endif + + y -= m_buttonSpacingY; + } + + y += m_spacingy; + + if ( parenting <= 0 ) + { + // Non-categories. + + int text_x = x; + // Use basic depth if in non-categoric mode and parent is base array. + if ( !(window_style & wxPG_HIDE_CATEGORIES) || p->GetParent() != FROM_STATE(m_properties) ) + { + text_x += ((unsigned int)((p->m_depth-1)*m_subgroup_extramargin)); + } + /* + else + { + wxLogDebug( wxT("%s"), p->GetLabel().c_str() ); + text_x = x; + } + */ + + if ( p != selected ) + { + dc.DrawText( p->m_label, text_x+wxPG_XBEFORETEXT, y ); + } + else + { + // Selected gets different colour. + if ( reallyFocused ) + dc.SetTextForeground( m_colSelFore ); + + dc.DrawText( p->m_label, text_x+wxPG_XBEFORETEXT, y ); + } + } + else + { + /*// switch background colour + bgbrush.SetColour ( ((wxPropertyCategoryClass*)p)->m_colCellBg ); + dc.SetBrush ( bgbrush );*/ + } + + y += m_fontHeight+m_spacingy+1; + + ITEM_ITERATION_UVC_LOOP_END(vi_end_y) + } + + + // + // Third pass: Values + // + dc.DestroyClippingRegion(); + + if ( clipRect ) + { + // third pass happens entirely on the right side, so sometimes + // we can just skip it + if ( (clipRect->x + clipRect->width) < m_splitterx ) + x = -1; + dc.SetClippingRegion ( *clipRect ); + } + + // This used with value drawer method. + wxRect valueRect(0,0, + m_width-(m_splitterx+wxPG_CONTROL_MARGIN), + m_fontHeight); + + wxSize imageSize; + + if ( x != -1 ) + { + + r.x = m_splitterx+1+wxPG_CONTROL_MARGIN; + r.width = m_width-m_splitterx-wxPG_CONTROL_MARGIN; + //r.x = m_splitterx+wxPG_DIST_SPLITTER_TO_IMAGE; + //r.width = m_width-m_splitterx-wxPG_DIST_SPLITTER_TO_IMAGE-1; + r.height = lh-1; + + /*#if wxCC_CORRECT_CONTROL_POSITION + const int vy2 = vy; + #endif*/ + + //wxLogDebug(wxT(" \\--> third pass...")); + + // Altough this line may seem unnecessary, it isn't + dc.SetFont(normalfont); + + dc.SetPen( *wxTRANSPARENT_PEN ); + + // Prepare paintdata. + paintdata.m_parent = this; + paintdata.m_choiceItem = -1; // Not drawing list item at this time. + + y = firstItemTopY; + + ITEM_ITERATION_UVC_LOOP_BEGIN(viStart,vi_end_y) + + if ( parenting <= 0 ) + { + r.y = y; + y += m_spacingy; + + // background + dc.SetBrush( *(wxPGBrush*)m_arrBgBrushes[p->m_bgColIndex] ); + + if ( isEnabled && p->IsEnabled() ) + dc.SetTextForeground( *(wxPGColour*)m_arrFgCols[p->m_fgColIndex] ); + else + dc.SetTextForeground( m_colDisPropFore ); + + // draw value string only if editor widget not open + // (exception: no primary editor widget or it is hidden) + if ( p != selected || !m_wndPrimary + // "if not primary shown" is required because + // primary is not usually shown during splitter + // movement. + || m_dragStatus > 0 + ) + { + + valueRect.x = m_splitterx+wxPG_CONTROL_MARGIN; + valueRect.y = y; + + // Draw background + if ( p != selected ) + { + dc.DrawRectangle( r ); + } + else + { + if ( m_wndPrimary ) + dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + else + dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + + dc.DrawRectangle( r ); + } + + // Set bold font? + if ( p->m_flags & wxPG_PROP_MODIFIED && (window_style & wxPG_BOLD_MODIFIED) ) + dc.SetFont( m_captionFont ); + + const wxPGEditor* editor = p->GetEditorClass(); + bool fullPaint = false; + + if ( p->m_flags & wxPG_PROP_CUSTOMIMAGE ) + { + imageSize = p->GetImageSize(); + + wxRect imageRect(r.x + wxPG_CONTROL_MARGIN + wxCC_CUSTOM_IMAGE_MARGIN1, + r.y+wxPG_CUSTOM_IMAGE_SPACINGY, + wxPG_CUSTOM_IMAGE_WIDTH, + r.height-(wxPG_CUSTOM_IMAGE_SPACINGY*2)); + + if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH ) + { + fullPaint = true; + imageRect.width = m_width - imageRect.x; + } + + dc.SetPen( outlinepen ); + + paintdata.m_drawnWidth = imageRect.width; + + if ( !(p->m_flags & wxPG_PROP_UNSPECIFIED) ) + { + p->OnCustomPaint( dc, imageRect, paintdata ); + } + else + { + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(imageRect); + } + dc.SetPen( *wxTRANSPARENT_PEN ); + } + else + paintdata.m_drawnWidth = 0; + + if ( paintdata.m_drawnWidth > 0 ) + valueRect.x += paintdata.m_drawnWidth + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; + else + fullPaint = false; + + if ( !fullPaint ) + editor->DrawValue(dc,p,valueRect); + + // Return original font? + if ( p->m_flags & wxPG_PROP_MODIFIED && (window_style & wxPG_BOLD_MODIFIED) ) + dc.SetFont(normalfont); + } + else + { + + if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) || + m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE ) + { + //wxLogDebug(wxT("Primary doesn't fill entire")); + dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); + dc.DrawRectangle( r ); + } + if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE ) + { + wxRect imagerect(r.x + wxPG_CONTROL_MARGIN + wxCC_CUSTOM_IMAGE_MARGIN1, + r.y+wxPG_CUSTOM_IMAGE_SPACINGY,wxPG_CUSTOM_IMAGE_WIDTH, + r.height-(wxPG_CUSTOM_IMAGE_SPACINGY*2)); + + dc.SetPen ( outlinepen ); + if ( !(p->m_flags & wxPG_PROP_UNSPECIFIED) ) + { + p->OnCustomPaint( dc, imagerect, paintdata ); + } + else + { + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle(imagerect); + } + } + dc.SetPen( *wxTRANSPARENT_PEN ); + } + + y += m_fontHeight+m_spacingy + 1; + } + else + { + // caption item + y += lh; + } + + //if ( y > lastItemBottomY ) { parent = NULL; break; } + + ITEM_ITERATION_UVC_LOOP_END(vi_end_y) + + } + + dc.DestroyClippingRegion(); // Is this really necessary? + +#if wxPG_DOUBLE_BUFFER + //} + //else wxLogDebug(wxT("Used Cache")); + + if ( bufferDC ) + { + if ( blitClipRect ) + dcMain.SetClippingRegion( *blitClipRect ); + //wxLogDebug(wxT(" \\--> (0,%i)"),(int)final_y); + dcMain.Blit ( 0, firstItem->m_y, m_width, renderHeight, + &dc, 0, firstItem->m_y-vy, wxCOPY ); + //dcMain.Blit ( 0, 0, m_width, m_height, + // &dc, 0, 0, wxCOPY ); + dcMain.DestroyClippingRegion(); // Is this really necessary? + delete bufferDC; + } +#endif + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT(" \\--> ends...")); +#endif + +} + +// ----------------------------------------------------------------------- + +wxRect wxPropertyGrid::GetPropertyRect( const wxPGProperty* p1, const wxPGProperty* p2 ) const +{ + wxRect r; + + if ( m_width < 10 || m_height < 10 || + !FROM_STATE(m_properties)->GetCount() || + p1 == (wxPGProperty*) NULL ) + return wxRect(0,0,0,0); + + int vx,vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + + // + // Return rect which encloses the given property range + + int visTop = p1->m_y; + int visBottom = m_bottomy; + if ( p2 ) + visBottom = p2->m_y + m_lineHeight; + + // If seleced property is inside the range, we'll extend the range to include + // control's size. + wxPGProperty* selected = m_selected; + if ( selected && selected->m_y >= visTop && selected->m_y < visBottom ) + { + wxWindow* editor = GetEditorControl(); + if ( editor ) + { + int visBottom2 = selected->m_y + editor->GetSize().y; + if ( visBottom2 > visBottom ) + visBottom = visBottom2; + } + } + + return wxRect(0,visTop-vy,m_width,visBottom-visTop); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 ) +{ + if ( m_frozen ) + return; + + if ( FROM_STATE(m_itemsAdded) ) + PrepareAfterItemsAdded(); + + wxRect r = GetPropertyRect(p1, p2); + if ( r.width > 0 ) + RefreshRect(r); +} + +// ----------------------------------------------------------------------- + +// In addition to calling DoDrawItems directly, this is the +// only alternative for using wxClientDC - others just call +// RefreshRect. +void wxPropertyGrid::DrawItem( wxDC& dc, wxPGProperty* p ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + + // do not draw a single item if multiple pending + if ( FROM_STATE(m_itemsAdded) ) + return; + + if ( p->m_y < 0 ) + return; + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT("wxPropertyGrid::DrawItem( %s )"), p->GetLabel().c_str() ); +#endif + + DoDrawItems( dc, p, p, NULL ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::RefreshProperty( wxPGProperty* p ) +{ + if ( p == m_selected ) + DoSelectProperty(p, wxPG_SEL_FORCE); + + DrawItemAndChildren(p); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::DrawItemAndValueRelated( wxPGProperty* p ) +{ + if ( m_frozen ) + return; + + // Draw item, children, and parent too, if it is not category + wxPGProperty* parent = p->GetParent(); + + while ( parent && + parent->GetParentingType() < PT_NONE ) + { + DrawItem(parent); + parent = parent->GetParent(); + } + + DrawItemAndChildren(p); +} + +void wxPropertyGrid::DrawItemAndChildren( wxPGProperty* p ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + + // Do not draw if in non-visible page + if ( p->GetParentState() != m_pState ) + return; + + // do not draw a single item if multiple pending + if ( FROM_STATE(m_itemsAdded) || p->m_y < 0 || m_frozen ) + return; + +#if __PAINT_DEBUGGING__ + wxLogDebug(wxT("wxPropertyGrid::DrawItemAndChildren( %s )"), p->GetLabel().c_str() ); +#endif + + // Update child control. + if ( m_selected && m_selected->GetParent() == p ) + m_selected->UpdateControl(m_wndPrimary); + + const wxPGProperty* lastDrawn = p->GetLastVisibleSubItem(); + + DrawItems(p, lastDrawn); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Refresh( bool WXUNUSED(eraseBackground), + const wxRect *rect ) +{ + // Refresh implies forced redraw + //m_iFlags |= wxPG_FL_CHANGED; + + wxWindow::Refresh(false,rect); +#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + // I think this really helps only GTK+1.2 + if ( m_wndPrimary ) m_wndPrimary->Refresh(); + if ( m_wndSecondary ) m_wndSecondary->Refresh(); +#endif +} + +// ----------------------------------------------------------------------- + +/* +void wxPropertyGrid::RedrawAllVisible () +{ + // TODO: Is this safe? + //Update(); + + if ( m_frozen || !IsShown() ) + return; + + wxPG_CLIENT_DC_INIT() + +#if __PAINT_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::RedrawAllVisible()") ); +#endif + + int vx,vy; // Top left corner of client + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; + + int y1 = vy; + int y2 = y1 + m_height; + + // Repaint this rectangle + DrawItems ( dc, y1, y2, (wxRect*) NULL ); + +} +*/ + +// ----------------------------------------------------------------------- + +#if wxPG_HEAVY_GFX +void wxPropertyGrid::DrawSplitterDragColumn( wxDC&, int ) { } +#else +void wxPropertyGrid::DrawSplitterDragColumn( wxDC& dc, int x ) +{ + int vx, vy; + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; + + dc.SetLogicalFunction(wxINVERT); + dc.DestroyClippingRegion(); + + dc.SetPen( m_splitterpen ); + dc.DrawLine(x,vy,x,vy+m_height); + +} +#endif + +// ----------------------------------------------------------------------- +// wxPropertyGrid global operations +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Clear() +{ + if ( m_selected ) + { + bool selRes = DoSelectProperty(wxPGIdGen(NULL), wxPG_SEL_DELETING); // This must be before state clear + wxPG_CHECK_RET_DBG( selRes, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + FROM_STATE(Clear()); + + m_propHover = NULL; + m_bottomy = 0; + + m_prevVY = 0; + m_arrVisible.Empty(); + + RecalculateVirtualSize(); + + // Need to clear some area at the end + if ( !m_frozen ) + RefreshRect(wxRect(0, 0, m_width, m_height)); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::EnableCategories( bool enable ) +{ + if ( !ClearSelection() ) + return false; + + if ( enable ) + { + // + // Enable categories + // + + m_windowStyle &= ~(wxPG_HIDE_CATEGORIES); + } + else + { + // + // Disable categories + // + m_windowStyle |= wxPG_HIDE_CATEGORIES; + } + + if ( !m_pState->EnableCategories(enable) ) + return false; + + if ( !m_frozen ) + { + if ( m_windowStyle & wxPG_AUTO_SORT ) + { + FROM_STATE(m_itemsAdded) = 1; // force + PrepareAfterItemsAdded(); + } + else + { + CalculateYs(NULL,-1); + //CalculateVisibles( -1 ); + } + } + else + FROM_STATE(m_itemsAdded) = 1; + + Refresh(); + + return true; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SwitchState( wxPropertyGridState* pNewState ) +{ + wxASSERT( pNewState ); + + wxPGProperty* oldSelection = m_selected; + + // Deselect + if ( m_selected ) + { + bool selRes = ClearSelection(); + wxPG_CHECK_RET_DBG( selRes, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + m_pState->m_selected = oldSelection; + + bool orig_mode = m_pState->IsInNonCatMode(); + bool new_state_mode = pNewState->IsInNonCatMode(); + + m_pState = pNewState; + + m_bottomy = 0; // This is necessary or y's won't get updated. + m_propHover = (wxPGProperty*) NULL; + + // If necessary, convert state to correct mode. + if ( orig_mode != new_state_mode ) + { + // This should refresh as well. + EnableCategories ( orig_mode?false:true ); + } + else if ( !m_frozen ) + { + // Refresh, if not frozen. + if ( FROM_STATE(m_itemsAdded) ) + PrepareAfterItemsAdded(); + else + CalculateYs(NULL,-1); + + // Reselect + if ( FROM_STATE(m_selected) ) + DoSelectProperty( FROM_STATE(m_selected) ); + + //RedrawAllVisible(); + Refresh(); + } + else + m_pState->m_itemsAdded = 1; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Sort( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + m_pState->Sort( p ); + + // Because order changed, Y's need to be changed as well + if ( p->GetParentState() == m_pState ) + CalculateYs ( p->m_parent, p->m_arrIndex ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::Sort() +{ + bool selRes = ClearSelection(); // This must be before state clear + wxPG_CHECK_RET_DBG( selRes, + wxT("failed to deselect a property (editor probably had invalid value)") ); + + m_pState->Sort(); + + CalculateYs( NULL, -1 ); +} + +// ----------------------------------------------------------------------- + +// Call to SetSplitterPosition will always disable splitter auto-centering +// if parent window is shown. +void wxPropertyGrid::DoSetSplitterPosition( int newxpos, bool refresh ) +{ + if ( ( newxpos < wxPG_DRAG_MARGIN ) ) + return; + // ( m_width > wxPG_DRAG_MARGIN && newxpos > (m_width-wxPG_DRAG_MARGIN) ) + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::DoSetSplitterPosition ( %i )"), newxpos ); +#endif + +#if wxPG_HEAVY_GFX + m_splitterx = newxpos; + m_fSplitterX = (float) newxpos; + + if ( refresh ) + { + if ( m_selected ) + CorrectEditorWidgetSizeX( m_splitterx, m_width ); + + Refresh(); + //RedrawAllVisible(); // no flicker + } +#else + if ( !m_dragStatus ) + { + // Only do this if this was not a call from HandleMouseUp + m_startingSplitterX = m_splitterx; + m_splitterx = newxpos; + m_fSplitterX = (float) newxpos; + } + + // Clear old + if ( m_splitterprevdrawnx != -1 ) + { + wxPG_CLIENT_DC_INIT() + + DrawSplitterDragColumn( dc, m_splitterprevdrawnx ); + m_splitterprevdrawnx = -1; + } + + // Redraw only if drag really moved + if ( m_splitterx != m_startingSplitterX && refresh ) + { + if ( m_selected) + CorrectEditorWidgetSizeX( m_splitterx, m_width ); + + Update(); // This fixes a graphics-mess in wxMSW + + Refresh(); + //RedrawAllVisible(); // no flicker + } +#endif + + // Don't allow initial splitter auto-positioning after this. + m_iFlags |= wxPG_FL_SPLITTER_PRE_SET; + +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::CenterSplitter( bool enable_auto_centering ) +{ + SetSplitterPosition ( m_width/2, true ); + if ( enable_auto_centering && ( m_windowStyle & wxPG_SPLITTER_AUTO_CENTER ) ) + m_iFlags &= ~(wxPG_FL_DONT_CENTER_SPLITTER); +} + +// ----------------------------------------------------------------------- + +// Moves splitter so that all labels are visible, but just. +void wxPropertyGrid::SetSplitterLeft( bool subProps ) +{ + wxClientDC dc(this); + dc.SetFont(m_font); + + int maxW = m_pState->GetLeftSplitterPos(dc, m_pState->m_properties, subProps ); + + if ( maxW > 0 ) + SetSplitterPosition( maxW ); + + m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; +} + + +// ----------------------------------------------------------------------- +// wxPropertyGrid item iteration (GetNextProperty etc.) methods +// ----------------------------------------------------------------------- + +// Returns nearest paint visible property (such that will be painted unless +// window is scrolled or resized). If given property is paint visible, then +// it itself will be returned +wxPGProperty* wxPropertyGrid::GetNearestPaintVisible( wxPGProperty* p ) +{ + int vx,vy1;// Top left corner of client + GetViewStart(&vx,&vy1); + vy1 *= wxPG_PIXELS_PER_UNIT; + + int vy2 = vy1 + m_height; + + if ( (p->m_y + m_lineHeight) < vy1 ) + { + // Too high + return DoGetItemAtY( vy1 ); + } + else if ( p->m_y > vy2 ) + { + // Too low + return DoGetItemAtY( vy2 ); + } + + // Itself paint visible + return p; + +} + +// ----------------------------------------------------------------------- + +wxPGProperty* wxPropertyGrid::GetNeighbourItem( wxPGProperty* item, + bool need_visible, + int dir ) const +{ + wxPGPropertyWithChildren* parent = item->m_parent; + unsigned int indinparent = item->GetIndexInParent(); + + if ( dir > 0 ) + { + if ( item->GetChildCount() == 0 || + (!((wxPGPropertyWithChildren*)item)->m_expanded && need_visible) ) + { + // current item did not have any expanded children + if ( indinparent < (parent->GetCount()-1) ) + { + // take next in parent's array + item = parent->Item(indinparent+1); + } + else + { + // no more in parent's array; move up until found; + wxPGPropertyWithChildren* p2 = parent; + parent = parent->m_parent; + item = (wxPGProperty*) NULL; + while ( parent ) + { + if ( p2->m_arrIndex < (parent->GetCount()-1) ) + { + item = parent->Item(p2->m_arrIndex+1); + break; + } + p2 = parent; + parent = parent->m_parent; + } + } + } + else + { + // take first of current item's children + wxPGPropertyWithChildren* p2 = (wxPGPropertyWithChildren*)item; + item = p2->Item(0); + //indinparent = 0; + } + } + else + { + + // items in array left? + if ( indinparent > 0 ) + { + // take prev in parent's array + item = parent->Item(indinparent-1); + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)item; + + // Recurse to it's last child + while ( item->GetParentingType() != 0 && pwc->GetCount() && + ( pwc->m_expanded || !need_visible ) + ) + { + item = pwc->Last(); + pwc = (wxPGPropertyWithChildren*)item; + } + + } + else + { + // If we were at first, go to parent + item = parent; + } + } + + if ( item == FROM_STATE(m_properties) ) + return (wxPGProperty*) NULL; + + // If item was hidden and need_visible, get next. + if ( (m_iFlags & wxPG_FL_HIDE_STATE) && need_visible && item ) + { + if ( item->m_flags & wxPG_PROP_HIDEABLE ) + { + // Speed-up: If parent is hidden as well, then skip to last child or to itself + if ( parent->m_flags & wxPG_PROP_HIDEABLE ) + { + item = parent; // if dir up + if ( dir > 0 ) + item = parent->Last(); // if dir down + } + + return GetNeighbourItem ( item, need_visible, dir ); + } + } + + return item; +} + +// ----------------------------------------------------------------------- + +// This is used in DoDrawItems. +wxPGProperty* wxPropertyGrid::GetLastItem ( bool need_visible, bool allowSubprops ) +{ + if ( FROM_STATE(m_properties)->GetCount() < 1 ) + return (wxPGProperty*) NULL; + + wxPGProperty* p = FROM_STATE(m_properties)->Last(); + + int parenting = p->GetParentingType(); + + while ( parenting != 0 && ( allowSubprops || parenting >= PT_CAPTION ) ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + parenting = 0; + if ( pwc->GetCount() ) + { + + if ( (!need_visible || pwc->m_expanded) ) + { + p = pwc->Last(); + parenting = p->GetParentingType(); + } + else + parenting = 0; + } + } + + // If item was hidden and need_visible, get previous. + if ( (m_iFlags & wxPG_FL_HIDE_STATE) && + need_visible && + p && ( p->m_flags & wxPG_PROP_HIDEABLE ) + ) + return GetNeighbourItem( p, need_visible, -1 ); + + return p; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetButtonShortcut( int keycode, bool ctrlDown, bool altDown ) +{ + if ( keycode ) + { + m_pushButKeyCode = keycode; + m_pushButKeyCodeNeedsCtrl = ctrlDown ? 1 : 0; + m_pushButKeyCodeNeedsAlt = altDown ? 1 : 0; + } + else + { + m_pushButKeyCode = WXK_DOWN; + m_pushButKeyCodeNeedsCtrl = 0; + m_pushButKeyCodeNeedsAlt = 1; + } +} + +// ----------------------------------------------------------------------- +// Methods related to change in value, value modification and sending events +// ----------------------------------------------------------------------- + +// commits any changes in editor of selected property +// return true if validation did not fail +// flags are same as with DoSelectProperty +bool wxPropertyGrid::CommitChangesFromEditor( wxUint32 flags ) +{ + if ( m_wndPrimary && IsEditorsValueModified() && + (m_iFlags & wxPG_FL_INITIALIZED) ) + { + wxCHECK_MSG( m_selected, false, wxT("no selection") ); + + bool wasUnspecified = m_selected->IsValueUnspecified(); + + // JACS - necessary to avoid new focus being found spuriously within OnIdle + // due to another window getting focus + wxWindow* oldFocus = m_curFocused; + + if ( !(flags & (wxPG_SEL_NOVALIDATE|wxPG_SEL_FORCE)) && + !DoEditorValidate() ) + { + if (oldFocus) + { + oldFocus->SetFocus(); + m_curFocused = oldFocus; + } + + return false; + } + + // Save value (only if truly modified). + if ( !m_selected->GetEditorClass()->CopyValueFromControl( m_selected, m_wndPrimary ) ) + EditorsValueWasNotModified(); + + if ( m_selected->IsValueUnspecified() && !wasUnspecified && UsesAutoUnspecified() ) + flags |= wxPG_SEL_SETUNSPEC; + + DoPropertyChanged( m_selected, flags ); + + return true; + } + + return true; +} + +// ----------------------------------------------------------------------- + +// flags are same as with DoSelectProperty +void wxPropertyGrid::DoPropertyChanged( wxPGProperty* p, unsigned int selFlags ) +{ + if ( m_processingEvent ) + return; + +#if __INTENSE_DEBUGGING__ + wxLogDebug(wxT("wxPropertyGrid::DoPropertyChanged( %s )"),p->GetLabel().c_str()); +#endif + + m_pState->m_anyModified = 1; + + m_processingEvent = 1; + + // No longer unspecified (but not if the value was set to unspecified by + // user modification) + if ( !(selFlags & wxPG_SEL_SETUNSPEC) ) + CLEAR_PROPERTY_UNSPECIFIED_FLAG(p); + + if ( m_iFlags & wxPG_FL_VALUE_MODIFIED ) + { + m_iFlags &= ~(wxPG_FL_VALUE_MODIFIED); + + // Set as Modified (not if dragging just began) + if ( !(p->m_flags & wxPG_PROP_MODIFIED) ) + { + p->m_flags |= wxPG_PROP_MODIFIED; + if ( p == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) ) + { + if ( m_wndPrimary ) + SetCurControlBoldFont(); + } + } + + wxPGProperty* curChild = p; + wxPGPropertyWithChildren* curParent = p->m_parent; + + // Also update parent(s), if any + // (but not if its wxCustomProperty) + + while ( curParent && + curParent->GetParentingType() < 0 /*&& + wxStrcmp(curParent->GetClassName(),wxT("wxCustomProperty")) != 0*/ ) + { + // Set as Modified + if ( !(curParent->m_flags & wxPG_PROP_MODIFIED) ) + { + curParent->m_flags |= wxPG_PROP_MODIFIED; + if ( curParent == m_selected && (m_windowStyle & wxPG_BOLD_MODIFIED) ) + { + if ( m_wndPrimary ) + SetCurControlBoldFont(); + } + } + + curParent->ChildChanged( curChild ); + + DrawItem( curParent ); + + curChild = curParent; + curParent = curParent->GetParent(); + } + + // Draw the actual property + if ( ( p != m_selected ) || !m_wndPrimary || + ( p->GetParentingType() < 0 ) || + ( p->m_flags & wxPG_PROP_CUSTOMIMAGE ) ) + { + DrawItemAndChildren( p ); + } + + if ( curChild != p && !(selFlags & wxPG_SEL_SETUNSPEC) ) + //m_pState->ClearPropertyAndChildrenFlags(curChild,wxPG_PROP_UNSPECIFIED); + CLEAR_PROPERTY_UNSPECIFIED_FLAG(curChild); + + wxPGProperty* changedProperty; + + // Call wx event handler for property (or its topmost parent, but only + // when dealing with legitemate sub-properties - see above). + if ( curChild->GetParentingType() != PT_CUSTOMPROPERTY ) + changedProperty = curChild; + else + changedProperty = p; + + // Maybe need to update control +#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + if ( m_wndPrimary ) m_wndPrimary->Refresh(); + if ( m_wndSecondary ) m_wndSecondary->Refresh(); +#endif + + SendEvent( wxEVT_PG_CHANGED, changedProperty, selFlags ); + } + + m_processingEvent = 0; +} + +// ----------------------------------------------------------------------- + +// Runs wxValidator for the selected property +bool wxPropertyGrid::DoEditorValidate() +{ +#if wxUSE_VALIDATORS + if ( m_iFlags & wxPG_FL_VALIDATION_FAILED ) + { + return false; + } + + wxWindow* wnd = GetEditorControl(); + + wxValidator* validator = m_selected->GetValidator(); + if ( validator && wnd ) + { + // Use TextCtrl of ODComboBox instead + if ( wnd->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) ) + { + wnd = ((wxPGOwnerDrawnComboBox*)wnd)->GetTextCtrl(); + + if ( !wnd ) + return true; + } + + validator->SetWindow(wnd); + + // Instead setting the flag after the failure, we set + // it before checking and then clear afterwards if things + // went fine. This trick is necessary since focus events + // may be triggered while in Validate. + m_iFlags |= wxPG_FL_VALIDATION_FAILED; + if ( !validator->Validate(this) ) + { + // If you dpm't want to display message multiple times per change, + // comment the following line. + m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED); + return false; + } + m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED); + } +#endif + return true; +} + +// ----------------------------------------------------------------------- + +#if wxUSE_VALIDATORS +bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* propGrid, + wxValidator* validator, + const wxString& value ) +{ + if ( !validator ) + return true; + + wxTextCtrl* tc = m_textCtrl; + + if ( !tc ) + { + { + tc = new wxTextCtrl( propGrid, wxPG_SUBID_TEMP1, wxEmptyString, + wxPoint(30000,30000)); + tc->Hide(); + } + + m_textCtrl = tc; + } + + //wxString oldValue = tc->GetValue(); + tc->SetValue(value); + + validator->SetWindow(tc); + bool res = validator->Validate(propGrid); + + //tc->SetValue(oldValue); + return res; +} +#else +bool wxPGInDialogValidator::DoValidate( wxPropertyGrid* WXUNUSED(propGrid), + wxValidator* WXUNUSED(validator), + const wxString& WXUNUSED(value) ) +{ + return true; +} +#endif + +// ----------------------------------------------------------------------- + +// NB: It may really not be wxCommandEvent - must check if necessary +// (usually not). +void wxPropertyGrid::OnCustomEditorEvent( wxCommandEvent &event ) +{ + wxPGProperty* selected = m_selected; + + // + // Somehow, event is handled after property has been deselected. + // Possibly, but very rare. + if ( !selected ) + return; + + bool wasUnspecified = selected->IsValueUnspecified(); + bool usesAutoUnspecified = UsesAutoUnspecified(); + wxWindow* wnd = m_wndPrimary; + bool res1, res2; + + m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED); + + // First call editor class' event handler. + const wxPGEditor* editor = selected->GetEditorClass(); + res1 = editor->OnEvent( this, selected, wnd, event ); + + if ( res1 ) + { + // If changes, validate them + if ( DoEditorValidate() ) + { + if ( editor->CopyValueFromControl( selected, wnd ) ) + { + } + else + { + // False alarm + res1 = false; + + EditorsValueWasNotModified(); + + // However, even moot editing will clear the unspecified status + if ( wasUnspecified || !usesAutoUnspecified ) + CLEAR_PROPERTY_UNSPECIFIED_FLAG(selected); + } + } + else + { + res1 = false; + EditorsValueWasNotModified(); + if ( wasUnspecified || !usesAutoUnspecified ) + CLEAR_PROPERTY_UNSPECIFIED_FLAG(selected); + return; + } + } + + // Then the property's custom handler (must be always called). + res2 = selected->OnEvent( this, wnd, event ); + + if ( res1 || res2 ) + { + // Setting this is not required if res was true, so we do it now. + m_iFlags |= wxPG_FL_VALUE_MODIFIED; + + int selFlags = ( !wasUnspecified && selected->IsValueUnspecified() && usesAutoUnspecified ) ? wxPG_SEL_SETUNSPEC : 0; + + DoPropertyChanged(selected, selFlags); + } + else + // Let unhandled button click events go to the parent + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED,GetId()); + GetEventHandler()->AddPendingEvent(evt); + } +} + +// ----------------------------------------------------------------------- + +// When a property's value was modified internally (using SetValueFromString +// or SetValueFromInt, for example), then this should be called afterwards. +// NB: Avoid using this method, if possible. +void wxPropertyGrid::PropertyWasModified( wxPGProperty* p, int selFlags ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + EditorsValueWasModified(); + DoPropertyChanged(p, selFlags); +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid editor control helper methods +// ----------------------------------------------------------------------- + +wxWindow* wxPropertyGrid::GetEditorControl() const +{ + wxWindow* ctrl = m_wndPrimary; + + if ( !ctrl ) + return ctrl; + + // If it's clipper window, return its child instead +#if wxPG_ENABLE_CLIPPER_WINDOW + if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) + { + return ((wxPGClipperWindow*)ctrl)->GetControl(); + } +#endif + + return ctrl; +} + +// ----------------------------------------------------------------------- + +// inline because it is used exactly once in the code +inline wxRect wxPropertyGrid::GetEditorWidgetRect( wxPGProperty* p ) +{ + //wxASSERT( p->m_y >= 0 ); // item is not visible + + int itemy = p->m_y; + int vx,vy;// Top left corner of client + GetViewStart(&vx,&vy); + vy *= wxPG_PIXELS_PER_UNIT; + int cust_img_space = 0; + + //m_iFlags &= ~(wxPG_FL_CUR_USES_CUSTOM_IMAGE); + + // TODO: If custom image detection changes from current, change this. + if ( m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE /*p->m_flags & wxPG_PROP_CUSTOMIMAGE*/ ) + { + //m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE; + int imwid = p->GetImageSize().x; + if ( imwid < 1 ) imwid = wxPG_CUSTOM_IMAGE_WIDTH; + cust_img_space = imwid + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; + } + + return wxRect + ( + m_splitterx+cust_img_space+wxPG_XBEFOREWIDGET+wxPG_CONTROL_MARGIN+1, + itemy-vy, + m_width-m_splitterx-wxPG_XBEFOREWIDGET-wxPG_CONTROL_MARGIN-cust_img_space-1, + m_lineHeight-1 + ); +} + +// ----------------------------------------------------------------------- + +// return size of custom paint image +wxSize wxPropertyGrid::GetImageSize( wxPGId id ) const +{ + if ( wxPGIdIsOk(id) ) + { + wxSize cis = wxPGIdToPtr(id)->GetImageSize(); + + if ( cis.x < 0 ) + { + if ( cis.x <= -1 ) + cis.x = wxPG_CUSTOM_IMAGE_WIDTH; + } + if ( cis.y <= 0 ) + { + if ( cis.y >= -1 ) + cis.y = wxPG_STD_CUST_IMAGE_HEIGHT(m_lineHeight); + else + cis.y = -cis.y; + } + return cis; + } + // If called with NULL property, then return default image + // size for properties that use image. + return wxSize(wxPG_CUSTOM_IMAGE_WIDTH,wxPG_STD_CUST_IMAGE_HEIGHT(m_lineHeight)); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::CorrectEditorWidgetSizeX( int newSplitterx, int newWidth ) +{ + wxASSERT( m_selected ); + + int secWid = 0; + + if ( m_wndSecondary ) + { + // if width change occurred, move secondary wnd by that amount + wxRect r = m_wndSecondary->GetRect(); + secWid = r.width; + r.x = newWidth - secWid; + //r.y += yAdj; + + m_wndSecondary->SetSize ( r ); + + // if primary is textctrl, then we have to add some extra space +#ifdef __WXMAC__ + if ( m_wndPrimary ) +#else + if ( m_wndPrimary && m_wndPrimary->IsKindOf(CLASSINFO(wxTextCtrl)) ) +#endif + secWid += wxPG_TEXTCTRL_AND_BUTTON_SPACING; + } + + if ( m_wndPrimary ) + { + wxRect r = m_wndPrimary->GetRect(); + + r.x = newSplitterx+m_ctrlXAdjust; + //r.y += yAdj; + r.width = newWidth - r.x - secWid; + + m_wndPrimary->SetSize(r); + } + +/* + int sec_wid = 0; + + int vx, vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + int propY = m_selected->m_y - vy; + + if ( m_wndSecondary ) + { + // if width change occurred, move secondary wnd by that amount + wxRect r = m_wndSecondary->GetRect(); + int adjust = r.y % wxPG_PIXELS_PER_UNIT; + if ( adjust > (wxPG_PIXELS_PER_UNIT/2) ) + adjust = adjust - wxPG_PIXELS_PER_UNIT; + int y = propY + adjust; + sec_wid = r.width; + + m_wndSecondary->Move ( new_width-r.width,y ); + + // if primary is textctrl, then we have to add some extra space + if ( m_wndPrimary && m_wndPrimary->IsKindOf(CLASSINFO(wxTextCtrl)) ) + sec_wid += wxPG_TEXTCTRL_AND_BUTTON_SPACING; + } + + if ( m_wndPrimary ) + { + wxRect r = m_wndPrimary->GetRect(); + int adjust = r.y % wxPG_PIXELS_PER_UNIT; + if ( adjust > (wxPG_PIXELS_PER_UNIT/2) ) + adjust = adjust - wxPG_PIXELS_PER_UNIT; + wxLogDebug(wxT("adjust: %i"),adjust); + int y = propY + adjust; + + m_wndPrimary->SetSize( + new_splitterx+m_ctrlXAdjust, + y, + new_width-(new_splitterx+m_ctrlXAdjust)-sec_wid, + r.height + ); + } +*/ + + if ( m_wndSecondary ) + m_wndSecondary->Refresh(); + +} + +// ----------------------------------------------------------------------- + +/*void wxPropertyGrid::CorrectEditorWidgetSizeY( int cy ) +{ + if ( m_selected ) + { + wxPoint cp(0,cy); + + if ( m_wndPrimary ) + m_wndPrimary->Move ( m_wndPrimary->GetPosition() + cp ); + + if ( m_wndSecondary ) + m_wndSecondary->Move ( m_wndSecondary->GetPosition() + cp ); + } +}*/ + +// ----------------------------------------------------------------------- + +// takes scrolling into account +void wxPropertyGrid::ImprovedClientToScreen( int* px, int* py ) +{ + int vx, vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + vx*=wxPG_PIXELS_PER_UNIT; + *px -= vx; + *py -= vy; + ClientToScreen ( px, py ); +} + +// ----------------------------------------------------------------------- + +// custom set cursor +void wxPropertyGrid::CustomSetCursor( int type, bool override ) +{ + if ( type == m_curcursor && !override ) return; + + wxCursor* cursor = &wxPG_DEFAULT_CURSOR; + + if ( type == wxCURSOR_SIZEWE ) + cursor = m_cursorSizeWE; + + SetCursor ( *cursor ); + + //if ( m_wndPrimary ) m_wndPrimary->SetCursor(wxNullCursor); + + m_curcursor = type; +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid property selection +// ----------------------------------------------------------------------- + +#define CONNECT_CHILD(EVT,FUNCTYPE,FUNC) \ + wnd->Connect(id, EVT, \ + (wxObjectEventFunction) (wxEventFunction) \ + FUNCTYPE (&wxPropertyGrid::FUNC), \ + NULL, this ); + +/* +class MyEvtHandler : public wxEvtHandler +{ +public: + virtual bool ProcessEvent( wxEvent& event ) + { + if ( event.GetEventType() == wxEVT_NAVIGATION_KEY ) + wxLogDebug(wxT("wxEVT_NAVIGATION_KEY(id=%i)"),event.GetId()); + else if ( event.GetEventType() == wxEVT_KEY_DOWN ) + wxLogDebug(wxT("wxEVT_KEY_DOWN")); + event.Skip(); + return wxEvtHandler::ProcessEvent(event); + } +}; +*/ + +// Setups event handling for child control +void wxPropertyGrid::SetupEventHandling( wxWindow* argWnd, int id ) +{ + wxWindow* wnd = argWnd; + +#if wxPG_ENABLE_CLIPPER_WINDOW + // Pass real control instead of clipper window + if ( wnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) + { + wnd = ((wxPGClipperWindow*)argWnd)->GetControl(); + } +#endif + + if ( argWnd == m_wndPrimary ) + { + CONNECT_CHILD(wxEVT_MOTION,(wxMouseEventFunction),OnMouseMoveChild) + CONNECT_CHILD(wxEVT_LEFT_UP,(wxMouseEventFunction),OnMouseUpChild) + CONNECT_CHILD(wxEVT_LEFT_DOWN,(wxMouseEventFunction),OnMouseClickChild) + //CONNECT_CHILD(wxEVT_LEFT_DCLICK,(wxMouseEventFunction),OnMouseClickChild) + CONNECT_CHILD(wxEVT_RIGHT_UP,(wxMouseEventFunction),OnMouseRightClickChild) + CONNECT_CHILD(wxEVT_ENTER_WINDOW,(wxMouseEventFunction),OnMouseEntry) + CONNECT_CHILD(wxEVT_LEAVE_WINDOW,(wxMouseEventFunction),OnMouseEntry) + } + else + { + CONNECT_CHILD(wxEVT_NAVIGATION_KEY,(wxNavigationKeyEventFunction),OnNavigationKey) + } + CONNECT_CHILD(wxEVT_KEY_DOWN,(wxCharEventFunction),OnChildKeyDown) + CONNECT_CHILD(wxEVT_KEY_UP,(wxCharEventFunction),OnChildKeyUp) + CONNECT_CHILD(wxEVT_KILL_FOCUS,(wxFocusEventFunction),OnFocusEvent) +} + +void wxPropertyGrid::FreeEditors() +{ + // Do not free editors immediately if processing events + if ( !m_windowsToDelete ) + m_windowsToDelete = new wxArrayPtrVoid; + + if ( m_wndSecondary ) + { + m_windowsToDelete->push_back(m_wndSecondary); + m_wndSecondary->Hide(); + m_wndSecondary = (wxWindow*) NULL; + } + + if ( m_wndPrimary ) + { + m_windowsToDelete->push_back(m_wndPrimary); + m_wndPrimary->Hide(); + m_wndPrimary = (wxWindow*) NULL; + } +} + +// Call with NULL to de-select property +bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) +{ + +#if __INTENSE_DEBUGGING__ + if (p) + wxLogDebug(wxT("SelectProperty( %s (%s[%i]) )"),p->m_label.c_str(), + p->m_parent->m_label.c_str(),p->GetIndexInParent()); + else + wxLogDebug(wxT("SelectProperty( NULL, -1 )")); +#endif + + // + // Delete windows pending for deletion + if ( m_windowsToDelete && !m_processingEvent && m_windowsToDelete->size() ) + { + unsigned int i; + + for ( i=0; isize(); i++ ) + delete ((wxWindow*)((*m_windowsToDelete)[i])); + + m_windowsToDelete->clear(); + } + + wxPGProperty* prev = m_selected; + + // + // If we are frozen, then just set the values. + if ( m_frozen ) + { + m_iFlags &= ~(wxPG_FL_ABNORMAL_EDITOR); + m_editorFocused = 0; + m_selected = p; + FROM_STATE(m_selected) = p; + + // If frozen, always free controls. But don't worry, as Thaw will + // recall SelectProperty to recreate them. + FreeEditors(); + + // Prevent any further selection measures in this call + p = (wxPGProperty*) NULL; + } + else + { + // Is it the same? + if ( m_selected == p && !(flags & wxPG_SEL_FORCE) ) + { + // Only set focus if not deselecting + if ( p ) + { + if ( flags & wxPG_SEL_FOCUS ) + { + if ( m_wndPrimary ) + { + m_wndPrimary->SetFocus(); + m_editorFocused = 1; + } + } + else + { + wxScrolledWindow::SetFocus(); + m_editorFocused = 0; + } + } + + return true; + } + + wxClientDC dc(this); + PrepareDC(dc); + + // Don't put this earlier, due to return statements + m_iFlags |= wxPG_FL_IN_SELECT_PROPERTY; + + // + // First, deactivate previous + if ( m_selected ) + { + + #if __INTENSE_DEBUGGING__ + wxLogDebug(wxT(" (closing previous (%s))"), m_selected->m_label.c_str() ); + #endif + + // Must double-check if this is an selected in case of forceswitch + if ( p != prev ) + { + if ( !CommitChangesFromEditor(flags) ) + { + // Validation has failed, so we can't exit the previous editor + //::wxMessageBox(_("Please correct the value or press ESC to cancel the edit."), + // _("Invalid Value"),wxOK|wxICON_ERROR); + return false; + } + } + + FreeEditors(); + + m_iFlags &= ~(wxPG_FL_SELECTED_IS_PAINT_FLEXIBLE|wxPG_FL_SELECTED_IS_FULL_PAINT); + m_selected = (wxPGProperty*) NULL; + FROM_STATE(m_selected) = (wxPGProperty*) NULL; + + // Make sure the previous selection is refreshed + + // JACS: must use paint handler whenever possible + Refresh(false); + + /*if ( m_iFlags & wxPG_FL_ABNORMAL_EDITOR ) + Refresh(false); + else if ( prev->m_y < (int)m_bottomy ) + DoDrawItems( dc, prev, prev, NULL ); + */ + + m_iFlags &= ~(wxPG_FL_VALUE_MODIFIED|wxPG_FL_ABNORMAL_EDITOR); + } + + // + // Then, activate the one given. + if ( p ) + { + + m_editorFocused = 0; + m_selected = p; + FROM_STATE(m_selected) = p; + m_iFlags |= wxPG_FL_PRIMARY_FILLS_ENTIRE; + if ( p != prev ) + m_iFlags &= ~(wxPG_FL_VALIDATION_FAILED); + + //m_wndPrimary = (wxWindow*) NULL; + wxASSERT( m_wndPrimary == (wxWindow*) NULL ); + + + // Do we need OnMeasureCalls? + wxSize imsz = p->GetImageSize(); + if ( imsz.y < -1 ) + m_iFlags |= wxPG_FL_SELECTED_IS_PAINT_FLEXIBLE; + + // Is the entire cell/row custom painted? + if ( imsz.x == wxPG_FULL_CUSTOM_PAINT_WIDTH ) + m_iFlags |= wxPG_FL_SELECTED_IS_FULL_PAINT; + + + // + // Only create editor for non-disabled non-caption + if ( p->GetParentingType() <= 0 && !(p->m_flags & wxPG_PROP_DISABLED) ) + { + // do this for non-caption items + + // Do we need to paint the custom image, if any? + m_iFlags &= ~(wxPG_FL_CUR_USES_CUSTOM_IMAGE); + if ( (p->m_flags & wxPG_PROP_CUSTOMIMAGE) && + !p->GetEditorClass()->CanContainCustomImage() + ) + m_iFlags |= wxPG_FL_CUR_USES_CUSTOM_IMAGE; + + wxRect grect = GetEditorWidgetRect(p); + wxPoint good_pos = grect.GetPosition(); + #if wxPG_CREATE_CONTROLS_HIDDEN + int coord_adjust = m_height - good_pos.y; + good_pos.y += coord_adjust; + #endif + + const wxPGEditor* editor = p->GetEditorClass(); + wxCHECK_MSG(editor, false, + wxT("NULL editor class not allowed")); + + #ifndef __WXPYTHON__ + m_wndPrimary = editor->CreateControls(this, + p, + good_pos, + grect.GetSize(), + &m_wndSecondary); + #else + wxPGWindowPair wndPair = editor->CreateControls(this, + p, + good_pos, + grect.GetSize()); + m_wndPrimary = wndPair.m_primary; + m_wndSecondary = wndPair.m_secondary; + #endif + + // NOTE: It is allowed for m_wndPrimary to be NULL - in this case + // value is drawn as normal, and m_wndSecondary is assumed + // to be a right-aligned button that triggers a separate editor + // window. + + if ( m_wndPrimary ) + { + //wxLogDebug(wxT("%s Editor created for %s"),editor->GetName(),p->GetName().c_str()); + + // Set validator, if any + /*#if wxUSE_VALIDATORS + if ( validator ) m_wndPrimary->SetValidator(*validator); + #endif*/ + + if ( m_wndPrimary->GetSize().y > (m_lineHeight+6) ) + m_iFlags |= wxPG_FL_ABNORMAL_EDITOR; + + // If it has modified status, use bold font + // (must be done before capturing m_ctrlXAdjust) + if ( (p->m_flags & wxPG_PROP_MODIFIED) && (m_windowStyle & wxPG_BOLD_MODIFIED) ) + SetCurControlBoldFont(); + + // + // Fix TextCtrl indentation + #if defined(__WXMSW__) && !defined(__WXWINCE__) + wxTextCtrl* tc = wxDynamicCast(m_wndPrimary, wxTextCtrl); + if ( tc ) + ::SendMessage(GetHwndOf(tc), EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0)); + #endif + + // Store x relative to splitter (we'll need it). + m_ctrlXAdjust = m_wndPrimary->GetPosition().x - m_splitterx; + + // Check if background clear is not necessary + wxPoint pos = m_wndPrimary->GetPosition(); + if ( pos.x > (m_splitterx+1) || pos.y > p->m_y ) + { + m_iFlags &= ~(wxPG_FL_PRIMARY_FILLS_ENTIRE); + } + + m_wndPrimary->SetSizeHints(3,3); + + #if wxPG_CREATE_CONTROLS_HIDDEN + m_wndPrimary->Show(false); + m_wndPrimary->Freeze(); + + good_pos = m_wndPrimary->GetPosition(); + good_pos.y -= coord_adjust; + m_wndPrimary->Move( good_pos ); + #endif + + SetupEventHandling(m_wndPrimary, wxPG_SUBID1); + + // Focus and select all (wxTextCtrl, wxComboBox etc) + if ( flags & wxPG_SEL_FOCUS ) + { + wxWindow* ctrl = m_wndPrimary; + ctrl->SetFocus(); + + #if wxPG_NAT_TEXTCTRL_BORDER_ANY + // Take into account textctrl in clipper window + if ( ctrl->IsKindOf(CLASSINFO(wxPGClipperWindow)) ) + ctrl = ((wxPGClipperWindow*)ctrl)->GetControl(); + #endif + + p->GetEditorClass()->OnFocus(p,m_wndPrimary); + } + } + + if ( m_wndSecondary ) + { + + m_wndSecondary->SetSizeHints(3,3); + + #if wxPG_CREATE_CONTROLS_HIDDEN + wxRect sec_rect = m_wndSecondary->GetRect(); + sec_rect.y -= coord_adjust; + + // Fine tuning required to fix "oversized" + // button disappearance bug. + if ( sec_rect.y < 0 ) + { + sec_rect.height += sec_rect.y; + sec_rect.y = 0; + } + m_wndSecondary->SetSize( sec_rect ); + #endif + m_wndSecondary->Show(); + + SetupEventHandling(m_wndSecondary,wxPG_SUBID2); + + // If no primary editor, focus to button to allow + // it to interprete ENTER etc. + // NOTE: Due to problems focusing away from it, this + // has been disabled. + /* + if ( (flags & wxPG_SEL_FOCUS) && !m_wndPrimary ) + m_wndSecondary->SetFocus(); + */ + + } + + if ( flags & wxPG_SEL_FOCUS ) + m_editorFocused = 1; + + } + else + { + // wxGTK atleast seems to need this (wxMSW not) + SetFocus(); + } + + m_iFlags &= ~(wxPG_FL_VALUE_MODIFIED); + + //Update(); + + // If it's inside collapsed section, expand parent, scroll, etc. + // Also, if it was partially visible, scroll it into view. + int vx, vy; + GetViewStart(&vx,&vy); + vy*=wxPG_PIXELS_PER_UNIT; + int vy2 = vy + m_height; + + if ( (p->m_y < vy || + (p->m_y <= vy2 && + (p->m_y+m_lineHeight) > vy2)) && + !(flags & wxPG_SEL_NONVISIBLE) ) + EnsureVisible( wxPGIdGen(p) ); + + if ( m_wndPrimary ) + { + // Clear its background + // (why can't this be optimized by some other drawing?) + if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW) ); + dc.DrawRectangle(m_splitterx+1,p->m_y, + m_width-m_splitterx,m_lineHeight-1); + } + + #if wxPG_CREATE_CONTROLS_HIDDEN + m_wndPrimary->Thaw(); + #endif + m_wndPrimary->Show(true); + } + + DoDrawItems( dc, p, p, (const wxRect*) NULL ); + + } + } + +#if wxUSE_STATUSBAR + + // + // Show help text in status bar. + // (if found and grid not embedded in manager with help box and + // style wxPG_EX_HELP_AS_TOOLTIPS is not used). + // + + if ( !(GetExtraStyle() & wxPG_EX_HELP_AS_TOOLTIPS) ) + { + wxStatusBar* statusbar = (wxStatusBar*) NULL; + if ( !(m_iFlags & wxPG_FL_NOSTATUSBARHELP) ) + { + wxFrame* frame = wxDynamicCast(::wxGetTopLevelParent(this),wxFrame); + if ( frame ) + statusbar = frame->GetStatusBar(); + } + + if ( statusbar ) + { + const wxString* pHelpString = (const wxString*) NULL; + + if ( p && p->m_dataExt ) + { + pHelpString = &p->m_dataExt->m_helpString; + if ( pHelpString->length() ) + { + // Set help box text. + statusbar->SetStatusText( *pHelpString ); + m_iFlags |= wxPG_FL_STRING_IN_STATUSBAR; + } + } + + if ( (!pHelpString || !pHelpString->length()) && + (m_iFlags & wxPG_FL_STRING_IN_STATUSBAR) ) + { + // Clear help box - but only if it was written + // by us at previous time. + statusbar->SetStatusText( m_emptyString ); + m_iFlags &= ~(wxPG_FL_STRING_IN_STATUSBAR); + } + } + } +#endif + + m_iFlags &= ~(wxPG_FL_IN_SELECT_PROPERTY); + + // call wx event handler (here so that it also occurs on deselection) + SendEvent( wxEVT_PG_SELECTED, m_selected, flags ); + + return true; +} + +// ----------------------------------------------------------------------- + +// This method is not inline because it called dozens of times +// (i.e. two-arg function calls create smaller code size). +bool wxPropertyGrid::ClearSelection() +{ + return DoSelectProperty((wxPGProperty*)NULL); +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid expand/collapse state and priority (compact mode) related +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::_Collapse( wxPGProperty* p, bool sendEvents ) +{ + wxCHECK_MSG( p, false, wxT("invalid property id") ); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->GetParentingType() == 0 ) return false; + + if ( !pwc->m_expanded ) return false; + + // If active editor was inside collapsed section, then disable it + if ( m_selected && m_selected->IsSomeParent (p) ) + { + if ( !ClearSelection() ) + return false; + } + + // Store dont-center-splitter flag 'cause we need to temporarily set it + wxUint32 old_flag = m_iFlags & wxPG_FL_DONT_CENTER_SPLITTER; + m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + + // m_expanded must be set just before call to CalculateYs + pwc->m_expanded = 0; + + // Redraw etc. only if collapsed was visible. + if (pwc->m_y >= 0 && + !m_frozen && + ( pwc->GetParentingType() != 1 || !(m_windowStyle & wxPG_HIDE_CATEGORIES) ) ) + { + /*int y_adjust = 0; + + if ( m_selected && m_selected->m_y > pwc->m_y ) + { + wxPGProperty* next_vis = GetNeighbourItem(pwc,true,1); + wxASSERT( next_vis ); + + y_adjust = next_vis->m_y - pwc->m_y - m_lineHeight; + }*/ + + CalculateYs( pwc->m_parent, pwc->m_arrIndex ); + + // Fix control position. + /*if ( y_adjust ) + CorrectEditorWidgetSizeY ( -y_adjust );*/ + + // When item is collapsed so that scrollbar would move, + // graphics mess is about (unless we redraw everything). + Refresh(); + } + + // Clear dont-center-splitter flag if it wasn't set + m_iFlags = m_iFlags & ~(wxPG_FL_DONT_CENTER_SPLITTER) | old_flag; + + if ( sendEvents ) + SendEvent( wxEVT_PG_ITEM_COLLAPSED, p ); + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::_Expand( wxPGProperty* p, bool sendEvents ) +{ + wxCHECK_MSG( p, false, wxT("invalid property id") ); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->GetParentingType() == 0 ) return false; + + if ( pwc->m_expanded ) return false; + + // Store dont-center-splitter flag 'cause we need to temporarily set it + wxUint32 old_flag = m_iFlags & wxPG_FL_DONT_CENTER_SPLITTER; + m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + + // m_expanded must be set just before call to CalculateYs + pwc->m_expanded = 1; + + // Redraw etc. only if expanded was visible. + if ( pwc->m_y >= 0 && !m_frozen && + ( pwc->GetParentingType() != 1 || !(m_windowStyle & wxPG_HIDE_CATEGORIES) ) + ) + { + CalculateYs( pwc->m_parent, pwc->m_arrIndex ); + + /*int y_adjust = pwc->GetCount()*m_lineHeight; + + // Fix widget position as well + if ( m_selected && m_selected->m_y > pwc->m_y ) + CorrectEditorWidgetSizeY ( y_adjust );*/ + + // Redraw + #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + Refresh(); + #else + //wxPG_CLIENT_DC_INIT_R(true) + //DrawItems( dc, pwc->m_y, m_bottomy ); + DrawItems(pwc,(wxPGProperty*) NULL); + #endif + } + + // Clear dont-center-splitter flag if it wasn't set + m_iFlags = m_iFlags & ~(wxPG_FL_DONT_CENTER_SPLITTER) | old_flag; + + if ( sendEvents ) + SendEvent( wxEVT_PG_ITEM_EXPANDED, p ); + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::Compact( bool compact ) +{ +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::Compact()") ); +#endif + if ( compact ) + { + if ( !(m_iFlags & wxPG_FL_HIDE_STATE) ) + { + // Deselect selected if it was hideable + if ( m_selected && ( m_selected->m_flags & wxPG_PROP_HIDEABLE ) ) + { + if ( !ClearSelection() ) + return false; + } + + m_iFlags |= wxPG_FL_HIDE_STATE; + + if ( !m_frozen ) + { + CalculateYs( NULL, -1 ); + RedrawAllVisible(); + } + } + } + else + { + if ( m_iFlags & wxPG_FL_HIDE_STATE ) + { + + m_iFlags &= ~(wxPG_FL_HIDE_STATE); + + if ( !m_frozen ) + { + CalculateYs( NULL, -1 ); + RedrawAllVisible(); + } + } + } + return true; +} + +// ----------------------------------------------------------------------- + +// Used by HideProperty as well +bool wxPropertyGrid::SetPropertyPriority( wxPGProperty* p, int priority ) +{ + /* + // Old code (Commented Aug-09-2007) + if ( m_frozen ) + return m_pState->SetPropertyPriority(p,priority); + + if ( (m_iFlags & wxPG_FL_HIDE_STATE) && m_selected && + ( m_selected == p || m_selected->IsSomeParent(p) ) + ) + { + if ( !ClearSelection() ) + return false; + } + + m_pState->SetPropertyPriority(p,priority); + + if ( m_iFlags & wxPG_FL_HIDE_STATE ) + { + CalculateYs(NULL,-1); + RedrawAllVisible(); + } + + return true; + */ + // Stefan Battmer: + // Changed in a way that this update is only forced when the + // properties new priority actually differs from the current + // priority to improve update speed + if ( p ) + { + int oldPriority = ( p->IsFlagSet(wxPG_PROP_HIDEABLE) ) ? wxPG_LOW : wxPG_HIGH; + if( oldPriority != priority ) + { + if ( m_frozen ) + return m_pState->SetPropertyPriority(p,priority); + + if ( (m_iFlags & wxPG_FL_HIDE_STATE) && m_selected && + ( m_selected == p || m_selected->IsSomeParent(p) ) + ) + { + if ( !ClearSelection() ) + return false; + } + + m_pState->SetPropertyPriority(p,priority); + if ( m_iFlags & wxPG_FL_HIDE_STATE ) + { + CalculateYs(NULL,-1); + RedrawAllVisible(); + } + return true; + } + } + return false; +} + + +// ----------------------------------------------------------------------- +// wxPropertyGrid size related methods +// ----------------------------------------------------------------------- + +// This is called by CalculateYs (so those calling it won't need to call this) +void wxPropertyGrid::RecalculateVirtualSize() +{ + + int x = m_width; + int y = m_bottomy; + + //SetClientSize(x,y); + + // Now adjust virtual size. + SetVirtualSize(x, y); + + PGAdjustScrollbars(y); + + // + // FIXME: Is this really needed? I mean, can't OnResize handle this? + int width, height; + GetClientSize(&width,&height); + + if ( m_selected && width != m_width ) + { + CorrectEditorWidgetSizeX( m_splitterx, width ); + } + + m_width = width; + m_height = height; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::PGAdjustScrollbars( int y ) +{ + // Adjust scrollbars. + + y += wxPG_PIXELS_PER_UNIT+2; // One more scrollbar unit + 2 pixels. + int y_amount = y/wxPG_PIXELS_PER_UNIT; + + int y_pos = GetScrollPos( wxVERTICAL ); + SetScrollbars( 0, wxPG_PIXELS_PER_UNIT, 0, + y_amount, 0, y_pos, true ); +} + +// ----------------------------------------------------------------------- + +/* +bool wxPropertyGrid::DetectScrollbar() +{ + // Call at every time scrollbar may have appeared/disappeared + // Returns true if scrollbar was toggled + + bool toggled = false; + + // Use functions instead of m_width for total independence + wxCoord width = GetSize().x; + wxCoord cwidth = GetClientSize().x; + + if ( abs(width-cwidth) >= wxPG_MIN_SCROLLBAR_WIDTH ) + { + // There is a scrollbar. + if ( !(m_iFlags & wxPG_FL_SCROLLBAR_DETECTED) ) + { + //wxLogDebug(wxT("Scrollbar Appeared")); + toggled = true; + m_iFlags |= wxPG_FL_SCROLLBAR_DETECTED; + } + } + else if ( m_iFlags & wxPG_FL_SCROLLBAR_DETECTED ) + { + //wxLogDebug(wxT("Scrollbar Disappeared")); + toggled = true; + m_iFlags &= ~(wxPG_FL_SCROLLBAR_DETECTED); + } + + return toggled; +} +*/ + +void wxPropertyGrid::OnResize( wxSizeEvent& event ) +{ + + if ( !(m_iFlags & wxPG_FL_INITIALIZED) ) + return; + + if ( FROM_STATE(m_itemsAdded) && !m_frozen ) + PrepareAfterItemsAdded(); + + int width, height; + GetClientSize(&width,&height); + +#if __INTENSE_DEBUGGING__ + wxLogDebug(wxT("wxPropertyGrid::OnResize ( %i, %i )"),width,height); +#endif + + //int old_width = m_width; + //int old_height = m_height; + int old_fwidth = m_fWidth; // non-client width + int old_splitterx = m_splitterx; + + int fwidth = event.GetSize().x; + m_fWidth = fwidth; + m_width = width; + m_height = height; + + int widthDiff = fwidth - old_fwidth; + +#if wxPG_DOUBLE_BUFFER + if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) ) + { + int dblh = (m_lineHeight*2); + if ( !m_doubleBuffer ) + { + // Create double buffer bitmap to draw on, if none + int w = (width>250)?width:250; + int h = height + dblh; + h = (h>400)?h:400; + m_doubleBuffer = new wxBitmap ( w, h ); + } + else + { + int w = m_doubleBuffer->GetWidth(); + int h = m_doubleBuffer->GetHeight(); + + // Double buffer must be large enough + if ( w < width || h < (height+dblh) ) + { + if ( w < width ) w = width; + if ( h < (height+dblh) ) h = height + dblh; + delete m_doubleBuffer; + m_doubleBuffer = new wxBitmap ( w, h ); + } + } + } + + // Consider full update on every resize + //m_iFlags |= wxPG_FL_CHANGED; + +#endif + + // + // Center splitter when... + // * always when propGrid not shown yet or its full size is not realized yet + // and then only if splitter's position was not pre-set + // * auto-centering is enabled and scrollbar was not toggled + // + + // Need to center splitter? + //if ( width!=old_width ) + { + bool needSplitterCheck = true; + + //if ( !sb_vis_toggled ) + { + if ( m_windowStyle & wxPG_SPLITTER_AUTO_CENTER ) + { + float centerX = float(width) * 0.5; + + float splitterX = m_fSplitterX + (float(widthDiff) * 0.5); + + float deviation = fabs(centerX - splitterX); + //wxLogDebug(wxT("deviation: %.1f"),deviation); + + // If deviated too far from the center, reset it + if ( deviation > 30.0 ) + splitterX = centerX; + + DoSetSplitterPosition( (int)splitterX, false ); + + m_fSplitterX = splitterX; // needed to retain accuracy + + needSplitterCheck = false; + } + else if ( !(m_iFlags & wxPG_FL_SPLITTER_PRE_SET) ) + { + long timeSinceCreation = (::wxGetLocalTimeMillis() - m_timeCreated).ToLong(); + + if ( m_pState->m_properties->GetCount() || timeSinceCreation > 750 ) + { + SetSplitterLeft( false ); + needSplitterCheck = false; + } + else + { + DoSetSplitterPosition( width / 2, false ); + m_iFlags &= ~(wxPG_FL_SPLITTER_PRE_SET); + needSplitterCheck = false; + } + } + } + + if ( needSplitterCheck && (m_splitterx + wxPG_DRAG_MARGIN) > width ) + { + long timeSinceCreation = (::wxGetLocalTimeMillis() - m_timeCreated).ToLong(); + + if ( timeSinceCreation >= 750 ) + { + DoSetSplitterPosition( width - wxPG_DRAG_MARGIN - 1, false ); + } + } + } + + // Need to correct widget position? + if ( m_selected /*&& (width != old_width || sb_vis_toggled)*/ ) + { + // Take splitter position change into account + CorrectEditorWidgetSizeX( m_splitterx, width ); + } + + if ( !m_frozen ) + { + + // Need to recalculate visibles array? + //if ( height != old_height ) + if ( height > m_calcVisHeight ) + CalculateVisibles( -1, false ); + + /*if ( sb_vis_toggled ) + { + Refresh(); + } + else*/ + if ( m_splitterx != old_splitterx ) + { + Refresh(); + /*if ( abs(height-old_height) < 100 ) + { + Update(); // Necessary, atleast on wxMSW + RedrawAllVisible(); + } + else + { + Refresh(); + }*/ + } + } + + // Without this, virtual size (atleast under wxGTK) will be skewed + RecalculateVirtualSize(); +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid mouse event handling +// ----------------------------------------------------------------------- + +// selFlags uses same values DoSelectProperty's flags +void wxPropertyGrid::SendEvent( int eventType, wxPGProperty* p, unsigned int selFlags ) +{ + // Send property grid event of specific type and with specific property + wxPropertyGridEvent evt( eventType, GetId() ); + evt.SetPropertyGrid(this); + evt.SetEventObject(m_eventObject); + evt.SetProperty(p); + wxEvtHandler* evtHandler = GetEventHandler(); + + // Always need to process event immediately if the property in question is + // about to be deleted. + if ( (selFlags & wxPG_SEL_DELETING) || + (GetExtraStyle() & wxPG_EX_PROCESS_EVENTS_IMMEDIATELY) ) + { + evtHandler->ProcessEvent(evt); + } + else + { + evt.SetPending(true); + evtHandler->AddPendingEvent(evt); + } +} + +// ----------------------------------------------------------------------- + +// Return false if should be skipped +bool wxPropertyGrid::HandleMouseClick( int x, unsigned int y, wxMouseEvent &event ) +{ + bool res = true; + +#if __MOUSE_DEBUGGING__ + wxLogDebug( wxT(" \\--> HandleMouseClick") ); +#endif + + // Need to set focus? + if ( !(m_iFlags & wxPG_FL_FOCUSED) ) + { + SetFocus(); + } + + if ( y < m_bottomy ) + { + + wxPGProperty* p = DoGetItemAtY(y); + + if ( p ) + { + int parenting = p->GetParentingType(); + int depth = (int)p->GetDepth() - 1; + + int marginEnds = m_marginWidth + ( depth * m_subgroup_extramargin ); + + if ( x >= marginEnds ) + { + // Outside margin. + + if ( parenting > 0 ) + { + // This is category. + wxPropertyCategoryClass* pwc = (wxPropertyCategoryClass*)p; + + int text_x = m_marginWidth + ((unsigned int)((pwc->m_depth-1)*m_subgroup_extramargin)); + + // Expand, collapse, activate etc. if click on text or left of splitter. + if ( x >= text_x + && + ( x < (text_x+pwc->GetTextExtent()+(wxPG_CAPRECTXMARGIN*2)) + || + x < m_splitterx + ) + ) + { + if ( !DoSelectProperty( p ) ) + return res; + + // On double-click, expand/collapse. + if ( event.ButtonDClick() && !(m_windowStyle & wxPG_HIDE_MARGIN) ) + { + if ( pwc->m_expanded ) _Collapse ( p, true ); + else _Expand ( p, true ); + } + } + } + else if ( x > (m_splitterx + wxPG_SPLITTERX_DETECTMARGIN2) || + x < (m_splitterx - wxPG_SPLITTERX_DETECTMARGIN1) ) + { + // Click on value. + unsigned int selFlag = 0; + if ( x > m_splitterx ) + { + m_iFlags |= wxPG_FL_ACTIVATION_BY_CLICK; + selFlag = wxPG_SEL_FOCUS; + } + if ( !DoSelectProperty( p, selFlag ) ) + return res; + + m_iFlags &= ~(wxPG_FL_ACTIVATION_BY_CLICK); + + if ( p->GetParentingType() < 0 ) + // On double-click, expand/collapse. + if ( event.ButtonDClick() && !(m_windowStyle & wxPG_HIDE_MARGIN) ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->m_expanded ) _Collapse ( p, true ); + else _Expand ( p, true ); + } + + res = false; + } + else + { + // click on splitter + if ( !(m_windowStyle & wxPG_STATIC_SPLITTER) ) + { + + if ( event.GetEventType() == wxEVT_LEFT_DCLICK ) + { + // Double-clicking the splitter causes auto-centering + CenterSplitter( true ); + // TODO: Would this be more natural? + // .NET grid doesn't do it but maybe we should. + //CustomSetCursor ( wxCURSOR_ARROW ); + } + else if ( m_dragStatus == 0 ) + { + // + // Begin draggin the splitter + // + #if __MOUSE_DEBUGGING__ + wxLogDebug( wxT(" dragging begins at splitter + %i"), + (int)(x - m_splitterx) ); + #endif + + if ( m_wndPrimary ) + { + // Changes must be committed here or the + // value won't be drawn correctly + if ( !CommitChangesFromEditor() ) + return res; + + m_wndPrimary->Show ( false ); + } + + BEGIN_MOUSE_CAPTURE + + m_dragStatus = 1; + + m_dragOffset = x - m_splitterx; + + wxPG_CLIENT_DC_INIT() + + #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + // Fixes button disappearance bug + if ( m_wndSecondary ) + m_wndSecondary->Show ( false ); + #endif + + m_startingSplitterX = m_splitterx; + #if wxPG_HEAVY_GFX + #else + Update(); // clear graphics mess + DrawSplitterDragColumn( dc, m_splitterx ); + m_splitterprevdrawnx = m_splitterx; + #endif + + } + } + } + } + else + { + // Click on margin. + if ( parenting != 0 ) + { + int nx = x + m_marginWidth - marginEnds; // Normalize x. + + if ( (nx >= m_gutterWidth && nx < (m_gutterWidth+m_iconWidth)) ) + { + int y2 = y - p->m_y; + if ( (y2 >= m_buttonSpacingY && y2 < (m_buttonSpacingY+m_iconHeight)) ) + { + // On click on expander button, expand/collapse + if ( ((wxPGPropertyWithChildren*)p)->m_expanded ) + _Collapse ( p, true ); + else + _Expand ( p, true ); + } + } + } + } + } + } + return res; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::HandleMouseRightClick( int WXUNUSED(x), unsigned int y, + wxMouseEvent& WXUNUSED(event) ) +{ + if ( y < m_bottomy ) + { + // Select property here as well + wxPGProperty* p = m_propHover; + if ( p != m_selected ) + DoSelectProperty( p ); + + // Send right click event. + SendEvent( wxEVT_PG_RIGHT_CLICK, p ); + + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::HandleMouseDoubleClick( int WXUNUSED(x), unsigned int y, + wxMouseEvent& WXUNUSED(event) ) +{ + if ( y < m_bottomy ) + { + // Select property here as well + wxPGProperty* p = m_propHover; + + if ( p != m_selected ) + DoSelectProperty( p ); + + // Send double-click event. + SendEvent( wxEVT_PG_DOUBLE_CLICK, m_propHover ); + + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +/* +// Splits text into lines so that each will have width less than arg maxWidth. +// * Returns string with line breaks inserted into appropriate positions. +// * Keeps words together. +// * Useful in conjunction with wxWindow::SetToolTip and wxDC::DrawLabel. +static wxString SplitTextByPixelWidth(wxDC& dc, const wxString& text, int lineWidth) +{ + if ( !text.length() ) + return text; + + wxString resultLine; + wxArrayInt extents; + + unsigned int index = 0; + unsigned int maxIndex = text.length() - 1; + unsigned int prevSplitIndex = 0; + unsigned int prevCanSplitIndex = 0; + int lineCheckWidth = lineWidth; + wxChar prevA = wxT('\0'); + + dc.GetPartialTextExtents(text,extents); + + wxASSERT( text.length() == extents.GetCount() ); + + while ( index <= maxIndex ) + { + const wxChar A = text[index]; + + if ( !wxIsalnum(prevA) ) + { + // Can split here + prevCanSplitIndex = index; + } + else + { + // Can't split here + } + + if ( ( (extents[index] >= lineCheckWidth || A == wxT('\n')) && + index > prevCanSplitIndex ) || + index == maxIndex ) + { + // Need to split now + + unsigned int useSplit = prevCanSplitIndex; + if ( useSplit <= prevSplitIndex || + index >= maxIndex ) + useSplit = index; + + resultLine << text.Mid(prevSplitIndex,useSplit-prevSplitIndex); + + if ( index >= maxIndex ) + break; + else + if ( A != wxT('\n') ) + { + resultLine.Append(_T("\n")); + //resultLine.Append(text.Mid(useSplit,text.length()-useSplit)); + //break; + } + prevSplitIndex = useSplit; + lineCheckWidth = extents[useSplit] + lineWidth; + //widSum = 0; + index = useSplit; + prevA = wxT('\0'); + } + else + { + index++; + prevA = A; + } + } + + return resultLine; +} +*/ +// ----------------------------------------------------------------------- + +#if wxPG_SUPPORT_TOOLTIPS + +void wxPropertyGrid::SetToolTip( const wxString& tipString ) +{ + if ( tipString.length() ) + { + //wxClientDC dc(this); + //wxString finalString = SplitTextByPixelWidth(dc,tipString,350); + //wxScrolledWindow::SetToolTip(finalString); + wxScrolledWindow::SetToolTip(tipString); + } + else + { + #if wxPG_ALLOW_EMPTY_TOOLTIPS + wxScrolledWindow::SetToolTip( m_emptyString ); + #else + wxScrolledWindow::SetToolTip( NULL ); + #endif + } +} + +#endif // #if wxPG_SUPPORT_TOOLTIPS + +// ----------------------------------------------------------------------- + +// Return false if should be skipped +bool wxPropertyGrid::HandleMouseMove( int x, unsigned int y, wxMouseEvent &event ) +{ + // Safety check (needed because mouse capturing may + // otherwise freeze the control) + if ( m_dragStatus > 0 && !event.Dragging() ) + { + //wxLogDebug(wxT("MOUSE CAPTURE SAFETY RELEASE TRIGGERED")); + HandleMouseUp(x,y,event); + } + + if ( m_dragStatus > 0 ) + { + + if ( x > (m_marginWidth + wxPG_DRAG_MARGIN) && + x < (m_width - wxPG_DRAG_MARGIN) ) + { + + #if wxPG_HEAVY_GFX + + int new_splitterx = x - m_dragOffset; + + // Splitter redraw required? + if ( new_splitterx != m_splitterx ) + { + + if ( m_selected ) + CorrectEditorWidgetSizeX( new_splitterx, m_width ); + + // Move everything + m_splitterx = new_splitterx; + m_fSplitterX = (float) new_splitterx; + + Update(); + RedrawAllVisible(); + + } + + #else + + if ( x != m_splitterx ) + { + wxPG_CLIENT_DC_INIT_R(false) + + if ( m_splitterprevdrawnx != -1 ) + DrawSplitterDragColumn( dc, m_splitterprevdrawnx ); + + m_splitterx = x; + m_fSplitterX = (float) x; + + DrawSplitterDragColumn( dc, x ); + + m_splitterprevdrawnx = x; + } + + #endif + + m_dragStatus = 2; + + } + + return false; + } + else + { + + int ih = m_lineHeight; + int sy = y; + + #if wxPG_SUPPORT_TOOLTIPS + wxPGProperty* prevHover = m_propHover; + unsigned char prevSide = m_mouseSide; + #endif + + // On which item it hovers + if ( ( !m_propHover && y < m_bottomy) + || + ( m_propHover && ( sy < m_propHover->m_y || sy >= (m_propHover->m_y+ih) ) ) + ) + { + // Mouse moves on another property + + m_propHover = DoGetItemAtY(y); + + // Send hover event + SendEvent( wxEVT_PG_HIGHLIGHTED, m_propHover ); + } + + #if wxPG_SUPPORT_TOOLTIPS + // Store which side we are on + m_mouseSide = 0; + if ( x >= m_splitterx ) + m_mouseSide = 2; + else if ( x >= m_marginWidth ) + m_mouseSide = 1; + + // + // If tooltips are enabled, show label or value as a tip + // in case it doesn't otherwise show in full length. + // + if ( m_windowStyle & wxPG_TOOLTIPS ) + { + wxToolTip* tooltip = GetToolTip(); + + if ( m_propHover != prevHover || prevSide != m_mouseSide ) + { + if ( m_propHover && m_propHover->GetParentingType() <= 0 ) + { + + if ( GetExtraStyle() & wxPG_EX_HELP_AS_TOOLTIPS ) + { + // Show help string as a tooltip + wxString tipString = m_propHover->GetHelpString(); + + SetToolTip(tipString); + } + else + { + // Show cropped value string as a tooltip + wxString tipString; + int space = 0; + + if ( m_mouseSide == 1 ) + { + tipString = m_propHover->m_label; + space = m_splitterx-m_marginWidth-3; + } + else if ( m_mouseSide == 2 ) + { + tipString = m_propHover->GetDisplayedString(); + + space = m_width - m_splitterx; + if ( m_propHover->m_flags & wxPG_PROP_CUSTOMIMAGE ) + space -= wxPG_CUSTOM_IMAGE_WIDTH + wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; + } + + if ( space ) + { + int tw, th; + GetTextExtent( tipString, &tw, &th, 0, 0, &m_font ); + if ( tw > space ) + { + SetToolTip( tipString ); + } + } + else + { + if ( tooltip ) + { + #if wxPG_ALLOW_EMPTY_TOOLTIPS + wxScrolledWindow::SetToolTip( m_emptyString ); + #else + wxScrolledWindow::SetToolTip( NULL ); + #endif + } + } + + } + } + else + { + if ( tooltip ) + { + #if wxPG_ALLOW_EMPTY_TOOLTIPS + wxScrolledWindow::SetToolTip( m_emptyString ); + #else + wxScrolledWindow::SetToolTip( NULL ); + #endif + } + } + } + } + #endif + + if ( x > (m_splitterx + wxPG_SPLITTERX_DETECTMARGIN2) || + x < (m_splitterx - wxPG_SPLITTERX_DETECTMARGIN1) || + y >= m_bottomy || + (m_windowStyle & wxPG_STATIC_SPLITTER) ) + { + // hovering on something else + if ( m_curcursor != wxCURSOR_ARROW ) + CustomSetCursor( wxCURSOR_ARROW ); + } + else + { + // Do not allow splitter cursor on caption items. + // (also not if we were dragging and its started + // outside the splitter region) + + if ( m_propHover && + m_propHover->GetParentingType() <= 0 && + !event.Dragging() ) + { + + // hovering on splitter + + // NB: Condition disabled since MouseLeave event (from the editor control) cannot be + // reliably detected. + //if ( m_curcursor != wxCURSOR_SIZEWE ) + CustomSetCursor( wxCURSOR_SIZEWE, true ); + + return false; + } + else + { + // hovering on something else + if ( m_curcursor != wxCURSOR_ARROW ) + CustomSetCursor( wxCURSOR_ARROW ); + } + } + } + return true; +} + +// ----------------------------------------------------------------------- + +// Also handles Leaving event +bool wxPropertyGrid::HandleMouseUp( int x, unsigned int y, wxMouseEvent &WXUNUSED(event) ) +{ + bool res = false; + +#if __MOUSE_DEBUGGING__ + wxLogDebug( wxT(" \\--> HandleMouseUp") ); +#endif + + // No event type check - basicly calling this method should + // just stop dragging. + //if( event.LeftUp() || event.Leaving() ) + //{ + // Left up after dragged? + if ( m_dragStatus >= 1 ) + { + // + // End Splitter Dragging + // + #if __MOUSE_DEBUGGING__ + wxLogDebug( wxT(" dragging ends") ); + #endif + + // DO NOT ENABLE FOLLOWING LINE! + // (it is only here as a reminder to not to do it) + //m_splitterx = x; + + #if wxPG_HEAVY_GFX + //Refresh(); + #else + DoSetSplitterPosition( -1 ); // -1 tells not to make change + + // Hack to clear-up editor graphics mess (on wxMSW, atleast) + if ( m_selected ) + DrawItem ( m_selected ); + + #endif + // Disable splitter auto-centering + m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; + + // This is necessary to return cursor + END_MOUSE_CAPTURE + + // Set back the default cursor, if necessary + if ( x > (m_splitterx + wxPG_SPLITTERX_DETECTMARGIN2) || + x < (m_splitterx - wxPG_SPLITTERX_DETECTMARGIN1) || + y >= m_bottomy ) + { + CustomSetCursor( wxCURSOR_ARROW ); + } + + m_dragStatus = 0; + + #if wxPG_HEAVY_GFX + // Control background needs to be cleared + if ( !(m_iFlags & wxPG_FL_PRIMARY_FILLS_ENTIRE) && m_selected ) + DrawItem ( m_selected ); + #endif + + if ( m_wndPrimary ) + { + m_wndPrimary->Show ( true ); + } + + #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT + // Fixes button disappearance bug + if ( m_wndSecondary ) + m_wndSecondary->Show ( true ); + #endif + + // This clears the focus. + m_editorFocused = 0; + + } + //} + return res; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::OnMouseCommon( wxMouseEvent& event, int* px, int* py ) +{ + int ux, uy; + CalcUnscrolledPosition( event.m_x, event.m_y, &ux, &uy ); + + // Hide popup on clicks + // FIXME: Not necessary after transient window implemented + if ( event.GetEventType() != wxEVT_MOTION ) + if ( m_wndPrimary && m_wndPrimary->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) ) + { + ((wxPGOwnerDrawnComboBox*)m_wndPrimary)->HidePopup(); + } + + //if (printmsg) wxLogDebug( wxT("On") wxT(#func) wxT("( %i, %i )"),(int)ux,(int)uy ); + wxRect r; + wxWindow* wnd = m_wndPrimary; + if ( wnd ) + r = wnd->GetRect(); + if ( wnd == (wxWindow*) NULL || m_dragStatus || + ( + ux <= (m_splitterx + wxPG_SPLITTERX_DETECTMARGIN2) || + event.m_y < r.y || + event.m_y >= (r.y+r.height) + ) + ) + { + *px = ux; + *py = uy; + return true; + } + else + { + if ( m_curcursor != wxCURSOR_ARROW ) CustomSetCursor ( wxCURSOR_ARROW ); + } + return false; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseClick( wxMouseEvent &event ) +{ + int x, y; + if ( OnMouseCommon( event, &x, &y ) ) + { + HandleMouseClick(x,y,event); + } + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseRightClick( wxMouseEvent &event ) +{ + int x, y; + CalcUnscrolledPosition( event.m_x, event.m_y, &x, &y ); + HandleMouseRightClick(x,y,event); + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseDoubleClick( wxMouseEvent &event ) +{ + // Always run standard mouse-down handler as well + OnMouseClick(event); + + int x, y; + CalcUnscrolledPosition( event.m_x, event.m_y, &x, &y ); + HandleMouseDoubleClick(x,y,event); + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseMove( wxMouseEvent &event ) +{ + int x, y; + if ( OnMouseCommon ( event, &x, &y ) ) + { + HandleMouseMove(x,y,event); + } + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseUp( wxMouseEvent &event ) +{ + int x, y; + if ( OnMouseCommon ( event, &x, &y ) ) + { + HandleMouseUp(x,y,event); + } + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnMouseEntry( wxMouseEvent &event ) +{ + // This may get called from child control as well, so event's + // mouse position cannot be relied on. + //int x = event.m_x; + //int y = event.m_y; + + if ( event.Entering() ) + { + if ( !(m_iFlags & wxPG_FL_MOUSE_INSIDE) ) + { + #if __MOUSE_DEBUGGING__ + wxLogDebug(wxT("Mouse Enters Window")); + #endif + //SetCursor ( *wxSTANDARD_CURSOR ); + // TODO: Fix this (detect parent and only do + // cursor trick if it is a manager). + wxASSERT( GetParent() ); + GetParent()->SetCursor(wxNullCursor); + + m_iFlags |= wxPG_FL_MOUSE_INSIDE; + //if ( m_wndPrimary ) m_wndPrimary->Show ( true ); + } + else + GetParent()->SetCursor(wxNullCursor); + } + else if ( event.Leaving() ) + { + // Without this, wxSpinCtrl editor will sometimes have wrong cursor + SetCursor( wxNullCursor ); + + // Get real cursor position + wxPoint pt = ScreenToClient(::wxGetMousePosition()); + + if ( ( pt.x <= 0 || pt.y <= 0 || pt.x >= m_width || pt.y >= m_height ) ) + { + //if ( CommitChangesFromEditor() ) + { + + if ( (m_iFlags & wxPG_FL_MOUSE_INSIDE) ) + { + #if __MOUSE_DEBUGGING__ + wxLogDebug(wxT("Mouse Leaves Window")); + #endif + m_iFlags &= ~(wxPG_FL_MOUSE_INSIDE); + //if ( m_wndPrimary ) m_wndPrimary->Show ( false ); + } + + if ( m_dragStatus ) + wxPropertyGrid::HandleMouseUp ( -1, 10000, event ); + + } + } + else + { + /*#if wxPG_NO_CHILD_EVT_MOTION + // cursor must be reset because EVT_MOTION handler is not there to do it + if ( m_curcursor != wxCURSOR_ARROW ) CustomSetCursor ( wxCURSOR_ARROW ); + #endif*/ + } + } + + event.Skip(); +} + +// ----------------------------------------------------------------------- + +// if (printmsg) wxLogDebug( wxT("On") wxT(#func) wxT("Child ( %i, %i )"),(int)event.m_x,(int)event.m_y ); + +// Common code used by various OnMouseXXXChild methods. +bool wxPropertyGrid::OnMouseChildCommon( wxMouseEvent &event, int* px, int *py ) +{ + wxWindow* topCtrlWnd = (wxWindow*)event.GetEventObject(); + wxASSERT( topCtrlWnd ); + int x, y; + event.GetPosition(&x,&y); + +#if wxPG_ENABLE_CLIPPER_WINDOW + // Take clipper window into account + if (topCtrlWnd->GetPosition().x < 1 && + !topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow))) + { + topCtrlWnd = topCtrlWnd->GetParent(); + wxASSERT( topCtrlWnd->IsKindOf(CLASSINFO(wxPGClipperWindow)) ); + x -= ((wxPGClipperWindow*)topCtrlWnd)->GetXClip(); + y -= ((wxPGClipperWindow*)topCtrlWnd)->GetYClip(); + } +#endif + + wxRect r = topCtrlWnd->GetRect(); + if ( !m_dragStatus && + x > (m_splitterx-r.x+wxPG_SPLITTERX_DETECTMARGIN2) && + y >= 0 && y < r.height \ + ) + { + if ( m_curcursor != wxCURSOR_ARROW ) CustomSetCursor ( wxCURSOR_ARROW ); + event.Skip(); + } + else + { + CalcUnscrolledPosition( event.m_x + r.x, event.m_y + r.y, \ + px, py ); + return true; + } + return false; +} + +/*void wxPropertyGrid::OnMouseEntryChild ( wxMouseEvent &event ) +{ + wxLogDebug(wxT("Entering/Leaving Child...")); + event.Skip(); +}*/ + +void wxPropertyGrid::OnMouseClickChild( wxMouseEvent &event ) +{ + int x,y; + if ( OnMouseChildCommon(event,&x,&y) ) + { + bool res = HandleMouseClick(x,y,event); + if ( !res ) event.Skip(); + + /*if ( event.GetEventType() == wxEVT_LEFT_DCLICK ) + { + HandleMouseDoubleClick( x, y, event ); + event.Skip(); + }*/ + } +} + +void wxPropertyGrid::OnMouseRightClickChild( wxMouseEvent &event ) +{ + int x,y; + wxASSERT( m_wndPrimary ); + // These coords may not be exact (about +-2), + // but that should not matter (right click is about item, not position). + wxPoint pt = m_wndPrimary->GetPosition(); + CalcUnscrolledPosition( event.m_x + pt.x, event.m_y + pt.y, &x, &y ); + wxASSERT( m_selected ); + m_propHover = m_selected; + bool res = HandleMouseRightClick(x,y,event); + if ( !res ) event.Skip(); +} + +void wxPropertyGrid::OnMouseMoveChild( wxMouseEvent &event ) +{ + int x,y; + if ( OnMouseChildCommon(event,&x,&y) ) + { + bool res = HandleMouseMove(x,y,event); + if ( !res ) event.Skip(); + } +} + +void wxPropertyGrid::OnMouseUpChild( wxMouseEvent &event ) +{ + int x,y; + if ( OnMouseChildCommon(event,&x,&y) ) + { + bool res = HandleMouseUp(x,y,event); + if ( !res ) event.Skip(); + } +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid keyboard event handling +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SendNavigationKeyEvent( int dir ) +{ + wxNavigationKeyEvent evt; + evt.SetFlags(wxNavigationKeyEvent::FromTab| + (dir?wxNavigationKeyEvent::IsForward: + wxNavigationKeyEvent::IsBackward)); + evt.SetEventObject(this); + GetEventHandler()->AddPendingEvent(evt); +} + +void wxPropertyGrid::HandleKeyEvent(wxKeyEvent &event) +{ + + // + // Handles key event when editor control is not focused. + // + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::HandleKeyEvent(%i)"),(int)event.GetKeyCode() ); +#endif + + wxASSERT( !m_frozen ); + if ( m_frozen ) + return; + + // Travelsal between items, collapsing/expanding, etc. + int keycode = event.GetKeyCode(); + + if ( keycode == WXK_TAB ) + { + SendNavigationKeyEvent( event.ShiftDown()?0:1 ); + return; + } + + // Ignore Alt and Control when they are down alone + if ( keycode == WXK_ALT || + keycode == WXK_CONTROL ) + { + event.Skip(); + return; + } + + if ( m_selected ) + { + + // Show dialog? + if ( ButtonTriggerKeyTest(event) ) + return; + + wxPGProperty* p = m_selected; + + int selectDir = -2; + + if ( p->GetParentingType() != 0 && + !(p->m_flags & wxPG_PROP_DISABLED) + ) + { + //wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( keycode == WXK_LEFT ) + { + if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Collapse ( p ) ) + keycode = 0; + } + else if ( keycode == WXK_RIGHT ) + { + if ( (m_windowStyle & wxPG_HIDE_MARGIN) || Expand ( p ) ) + keycode = 0; + } + } + + if ( keycode ) + { + if ( keycode == WXK_UP || keycode == WXK_LEFT ) + { + selectDir = 0; + } + else if ( keycode == WXK_DOWN || keycode == WXK_RIGHT ) + { + selectDir = 1; + } + else + { + event.Skip(); + } + + } + + if ( selectDir >= -1 ) + { + p = GetNeighbourItem( p, true, selectDir ); + if ( p ) + DoSelectProperty(p); + } + + } + else + { + // If nothing was selected, select the first item now + // (or navigate out of tab). + if ( keycode != WXK_ESCAPE ) + { + wxPGProperty* p = GetFirst(); + if ( p ) DoSelectProperty(p); + } + } +} + +// ----------------------------------------------------------------------- + +// Potentially handles a keyboard event for editor controls. +// Returns false if event should *not* be skipped (on true it can +// be optionally skipped). +// Basicly, false means that SelectProperty was called (or was about +// to be called, if canDestroy was false). +bool wxPropertyGrid::HandleChildKey( wxKeyEvent& event, bool canDestroy ) +{ + int keycode = event.GetKeyCode(); + bool res = true; + +#if __INTENSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid::HandleChildKey(%i)"),(int)event.GetKeyCode() ); +#endif + + // Unfocus? + if ( keycode == WXK_ESCAPE ) + { + // Esc cancels any changes + EditorsValueWasNotModified(); + + wxPGProperty* p = m_selected; + + res = false; + + if ( canDestroy ) + { + DoSelectProperty( (wxPGProperty*)NULL, wxPG_SEL_NOVALIDATE ); + DoSelectProperty( p ); + } + + } + + return res; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnKey( wxKeyEvent &event ) +{ + + // + // Events to editor controls should get relayed here. + // + wxWindow* focused = wxWindow::FindFocus(); + //wxLogDebug(wxT("OnKey")); + + if ( m_wndPrimary && + (focused==m_wndPrimary + || m_editorFocused + #if wxPG_ENABLE_CLIPPER_WINDOW + || ((m_wndPrimary->IsKindOf(CLASSINFO(wxPGClipperWindow))) && + ((wxPGClipperWindow*)m_wndPrimary)->GetControl() == focused) + #endif + ) ) + { + // Child key must be processed here, since it can + // destroy the control which is referred by its own + // event handling. + HandleChildKey( event, true ); + } + else + HandleKeyEvent( event ); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnKeyUp(wxKeyEvent &event) +{ + m_keyComboConsumed = 0; + + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnNavigationKey( wxNavigationKeyEvent& event ) +{ + // Ignore events that occur very close to focus set + if ( m_iFlags & wxPG_FL_IGNORE_NEXT_NAVKEY ) + { + m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY); + event.Skip(); + return; + } + + wxPGProperty* next = (wxPGProperty*) NULL; + + int dir = event.GetDirection()?1:0; + + if ( m_selected ) + { + if ( dir == 1 && (m_wndPrimary || m_wndSecondary) ) + { + wxWindow* focused = wxWindow::FindFocus(); + + wxWindow* wndToCheck = GetEditorControl(); + + // ODComboBox focus goes to its text ctrl, so we need to use it instead + if ( wndToCheck && wndToCheck->IsKindOf(CLASSINFO(wxPGOwnerDrawnComboBox)) ) + { + wxTextCtrl* comboTextCtrl = ((wxPGOwnerDrawnComboBox*)wndToCheck)->GetTextCtrl(); + if ( comboTextCtrl ) + wndToCheck = comboTextCtrl; + } + + /* + // Because of problems navigating from wxButton, do not go to it. + if ( !wndToCheck ) + { + // No primary, use secondary + wndToCheck = m_wndSecondary; + } + // If it has editor button, focus to it after the primary editor. + // NB: Doesn't work since wxButton on wxMSW doesn't seem to propagate + // key events (yes, I'm using wxWANTS_CHARS with it, and yes I + // have somewhat debugged in window.cpp itself). + else if ( focused == wndToCheck && + m_wndSecondary && + !(GetExtraStyle() & wxPG_EX_NO_TAB_TO_BUTTON) ) + { + wndToCheck = m_wndSecondary; + wxLogDebug(wxT("Exp1")); + } + */ + + if ( focused != wndToCheck && + wndToCheck ) + { + wndToCheck->SetFocus(); + + // Select all text in wxTextCtrl etc. + if ( m_wndPrimary && wndToCheck == m_wndPrimary ) + m_selected->GetEditorClass()->OnFocus(m_selected,wndToCheck); + + m_editorFocused = 1; + next = m_selected; + } + } + + if ( !next ) + { + next = GetNeighbourItem(m_selected,true,dir); + + if ( next ) + { + // This allows preventing NavigateOut to occur + DoSelectProperty( next, wxPG_SEL_FOCUS ); + } + } + } + + if ( !next ) + event.Skip(); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGrid::ButtonTriggerKeyTest( wxKeyEvent &event ) +{ + int keycode = event.GetKeyCode(); + + // Does the keycode trigger button? + if ( keycode == m_pushButKeyCode && + m_wndSecondary && + (!m_pushButKeyCodeNeedsAlt || event.AltDown()) && + (!m_pushButKeyCodeNeedsCtrl || event.ControlDown()) ) + { + m_keyComboConsumed = 1; + + wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED,m_wndSecondary->GetId()); + GetEventHandler()->AddPendingEvent(evt); + return true; + } + + return false; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnChildKeyDown( wxKeyEvent &event ) +{ + int keycode = event.GetKeyCode(); + + // Ignore Alt and Control when they are down alone + if ( keycode == WXK_ALT || + keycode == WXK_CONTROL ) + { + event.Skip(); + return; + } + + if ( ButtonTriggerKeyTest(event) ) + return; + + // Since event handling may destroy the control which + // triggered this event, we need to send it separately + // to the wxPropertyGrid itself. Also, to allow pushed + // event handler to grab ENTER, ESC and such, this + // has been changed to add all keys as events. + if ( HandleChildKey(event,false) == true ) + event.Skip(); + + GetEventHandler()->AddPendingEvent(event); +} + +void wxPropertyGrid::OnChildKeyUp( wxKeyEvent &event ) +{ + m_keyComboConsumed = 0; + + GetEventHandler()->AddPendingEvent(event); + + event.Skip(); +} + +// ----------------------------------------------------------------------- +// wxPropertyGrid miscellaneous event handling +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnIdle( wxIdleEvent& WXUNUSED(event) ) +{ + // + // Check if the focus is in this control or one of its children + wxWindow* newFocused = wxWindow::FindFocus(); + + if ( newFocused != m_curFocused ) + HandleFocusChange( newFocused ); +} + +// Called by focus event handlers. newFocused is the window that becomes focused. +void wxPropertyGrid::HandleFocusChange( wxWindow* newFocused ) +{ + unsigned int oldFlags = m_iFlags; + + //wxLogDebug(wxT("HandleFocusChange: %s"),newFocused?newFocused->GetClassInfo()->GetClassName():wxT("NULL")); + + m_iFlags &= ~(wxPG_FL_FOCUSED); + + wxWindow* parent = newFocused; + + // This must be one of nextFocus' parents. + while ( parent ) + { + // Use m_eventObject, which is either wxPropertyGrid or + // wxPropertyGridManager, as appropriate. + if ( parent == m_eventObject ) + { + m_iFlags |= wxPG_FL_FOCUSED; + break; + } + parent = parent->GetParent(); + } + + m_curFocused = newFocused; + + if ( (m_iFlags & wxPG_FL_FOCUSED) != + (oldFlags & wxPG_FL_FOCUSED) ) + { + // On each focus kill, mark the next nav key event + // to be ignored (can't do on set focus since the + // event would occur before it). + if ( !(m_iFlags & wxPG_FL_FOCUSED) ) + { + m_iFlags |= wxPG_FL_IGNORE_NEXT_NAVKEY; + + // Need to store changed value + CommitChangesFromEditor(); + } + else + { + /* + // + // Preliminary code for tab-order respecting + // tab-traversal (but should be moved to + // OnNav handler) + // + wxWindow* prevFocus = event.GetWindow(); + wxWindow* useThis = this; + if ( m_iFlags & wxPG_FL_IN_MANAGER ) + useThis = GetParent(); + + if ( prevFocus && + prevFocus->GetParent() == useThis->GetParent() ) + { + wxList& children = useThis->GetParent()->GetChildren(); + + wxNode* node = children.Find(prevFocus); + + if ( node->GetNext() && + useThis == node->GetNext()->GetData() ) + DoSelectProperty(GetFirst()); + else if ( node->GetPrevious () && + useThis == node->GetPrevious()->GetData() ) + DoSelectProperty(GetLastProperty()); + + } + */ + + m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY); + } + + // Redraw selected + if ( m_selected && (m_iFlags & wxPG_FL_INITIALIZED) ) + DrawItem( m_selected ); + } +} + +void wxPropertyGrid::OnFocusEvent( wxFocusEvent& event ) +{ +#if 1 + if ( event.GetEventType() == wxEVT_SET_FOCUS ) + HandleFocusChange((wxWindow*)event.GetEventObject()); + // Line changed to "else" when applying patch #1675902 + //else if ( event.GetWindow() ) + else + HandleFocusChange(event.GetWindow()); + + event.Skip(); +#else + unsigned int oldFlags = m_iFlags; + + // + // Determine the current focus state + if ( event.GetEventType() == wxEVT_SET_FOCUS || + event.GetEventType() == wxEVT_CHILD_FOCUS ) + { + m_iFlags |= wxPG_FL_FOCUSED; + } + else + { + wxWindow* nextFocus = event.GetWindow(); + + m_iFlags &= ~(wxPG_FL_FOCUSED); + + wxWindow* parent = nextFocus; + //wxLogDebug(wxT("KillFocus: %s"),parent->GetClassInfo()->GetClassName()); + + // This must be one of nextFocus' parents. + while ( parent ) + { + if ( parent == this ) + { + m_iFlags |= wxPG_FL_FOCUSED; + break; + } + parent = parent->GetParent(); + } + } + + if ( (m_iFlags & wxPG_FL_FOCUSED) != + (oldFlags & wxPG_FL_FOCUSED) ) + { + // On each focus kill, mark the next nav key event + // to be ignored (can't do on set focus since the + // event would occur before it). + if ( !(m_iFlags & wxPG_FL_FOCUSED) ) + { + m_iFlags |= wxPG_FL_IGNORE_NEXT_NAVKEY; + + // Need to store changed value + CommitChangesFromEditor(); + } + else + { + /* + // + // Preliminary code for tab-order respecting + // tab-traversal (but should be moved to + // OnNav handler) + // + wxWindow* prevFocus = event.GetWindow(); + wxWindow* useThis = this; + if ( m_iFlags & wxPG_FL_IN_MANAGER ) + useThis = GetParent(); + + if ( prevFocus && + prevFocus->GetParent() == useThis->GetParent() ) + { + wxList& children = useThis->GetParent()->GetChildren(); + + wxNode* node = children.Find(prevFocus); + + if ( node->GetNext() && + useThis == node->GetNext()->GetData() ) + DoSelectProperty(GetFirst()); + else if ( node->GetPrevious () && + useThis == node->GetPrevious()->GetData() ) + DoSelectProperty(GetLastProperty()); + + } + */ + + m_iFlags &= ~(wxPG_FL_IGNORE_NEXT_NAVKEY); + } + + // Redraw selected + if ( m_selected && (m_iFlags & wxPG_FL_INITIALIZED) ) + DrawItem( m_selected ); + } + + event.Skip(); +#endif +} + +void wxPropertyGrid::OnChildFocusEvent( wxChildFocusEvent& event ) +{ + HandleFocusChange((wxWindow*)event.GetEventObject()); + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnScrollEvent( wxScrollWinEvent &event ) +{ + m_iFlags |= wxPG_FL_SCROLLED; + + event.Skip(); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::OnCaptureChange( wxMouseCaptureChangedEvent& WXUNUSED(event) ) +{ + if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) + { + #if __MOUSE_DEBUGGING__ + wxLogDebug( wxT("wxPropertyGrid: mouse capture lost") ); + #endif + m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); + } +} + +// ----------------------------------------------------------------------- +// Property text-based storage +// ----------------------------------------------------------------------- + +#define wxPG_PROPERTY_FLAGS_COUNT 8 + +// property-flag-to-text array +static const wxChar* gs_property_flag_to_string[wxPG_PROPERTY_FLAGS_COUNT] = +{ + wxT("Modified"), + wxT("Disabled"), + wxT("LowPriority"), + (const wxChar*) NULL, // wxPG_PROP_CUSTOMIMAGE is auto-generated flag + wxT("LimitedEditing"), + wxT("Unspecified"), + (const wxChar*) NULL, // Special flags cannot be stored as-is + (const wxChar*) NULL // +}; + + +wxString wxPGProperty::GetAttributes( unsigned int flagmask ) +{ + wxASSERT(this); + + wxString s; + unsigned int i; + unsigned int flags = ((unsigned int)m_flags) & + flagmask & + ~(wxPG_PROP_CUSTOMIMAGE | + wxPG_PROP_CLASS_SPECIFIC_1 | + wxPG_PROP_CLASS_SPECIFIC_2); + + if ( !flags ) + return wxEmptyString; + + for ( i=0; iGetParentingType() != 1 ) + { + const wxChar* src = p->GetClassName(); + wxString s; + if ( src[0] == wxT('w') && src[1] == wxT('x') ) + s = &src[2]; + else + s = src; + wxASSERT( (((int)s.length())-8) > 0 ); + s.Truncate(s.length()-8); + //s.LowerCase(); + return s; + } + return wxT("Category"); +} + +wxPGId wxPropertyContainerMethods::GetPropertyByNameA( wxPGPropNameStr name ) const +{ + wxPGId id = GetPropertyByName(name); + wxASSERT_MSG(wxPGIdIsOk(id),wxString::Format(wxT("no property with name '%s'"),name.c_str())); + return id; +} + +// ---------------------------------------------------------------------------- +// VariantDatas +// ---------------------------------------------------------------------------- + +#if wxPG_PGVARIANT_IS_VARIANT + +IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataPoint, wxVariantData) +IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataSize, wxVariantData) +IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataArrayInt, wxVariantData) +IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataLongLong, wxVariantData) +IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataULongLong, wxVariantData) +#ifdef __WXPYTHON__ + IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataPyObject, wxVariantData) +#endif + +#endif + +// ----------------------------------------------------------------------- +// Value type related methods (should all be pretty much static). + +wxPGValueType::~wxPGValueType() +{ +} + +wxPG_CONST_WXCHAR_PTR wxPGValueType::GetCustomTypeName() const +{ + return GetTypeName(); +} + +// Implement default types. +WX_PG_IMPLEMENT_VALUE_TYPE(wxString,wxStringProperty,wxPGTypeName_wxString,GetString,wxEmptyString) +WX_PG_IMPLEMENT_VALUE_TYPE(long,wxIntProperty,wxPGTypeName_long,GetLong,(long)0) +WX_PG_IMPLEMENT_VALUE_TYPE(double,wxFloatProperty,wxPGTypeName_double,GetDouble,0.0) +WX_PG_IMPLEMENT_VALUE_TYPE(wxArrayString,wxArrayStringProperty,wxPGTypeName_wxArrayString,GetArrayString,wxArrayString()) + +// Bool is a special case... thanks to the C++'s bool vs int vs long inconsistency issues. +const wxPGValueType *wxPGValueType_bool = (wxPGValueType *) NULL; +class wxPGValueTypeboolClass : public wxPGValueType +{ +public: + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return wxPGTypeName_long; } + virtual wxPG_CONST_WXCHAR_PTR GetCustomTypeName() const { return wxPGTypeName_bool; } + virtual wxPGVariant GetDefaultValue() const { return wxPGVariant((long)0); } + virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const + { return wxVariant ( value.GetBool(), name ); } + virtual wxPGProperty* GenerateProperty( const wxString& label, const wxString& name ) const + { + return wxPG_NEWPROPERTY(Bool,label,name,false); + } + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const + { +#if defined(__WXDEBUG__) || defined(__WXPYTHON__) + wxCHECK_RET( wxStrcmp(wxPGTypeName_bool,value.GetType().c_str()) == 0, + wxT("SetValueFromVariant: wxVariant type mismatch.") ); +#endif + property->DoSetValue(value.GetBool()?(long)1:(long)0); + } +}; + +// Implement nonetype. +const wxPGValueType *wxPGValueType_none = (wxPGValueType*) NULL; +class wxPGValueTypenoneClass : public wxPGValueType +{ +public: + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return wxT("null"); } + virtual wxPGVariant GetDefaultValue() const { return wxPGVariant((long)0); } + virtual wxVariant GenerateVariant( wxPGVariant, const wxString& name ) const + { return wxVariant( (long)0, name ); } + virtual wxPGProperty* GenerateProperty( const wxString&, const wxString& ) const + { return (wxPGProperty*) NULL; } + virtual void SetValueFromVariant( wxPGProperty*, wxVariant& ) const + { } +}; + +// Implement void* type. +const wxPGValueType *wxPGValueType_void = (wxPGValueType*) NULL; +class wxPGValueTypevoidClass : public wxPGValueType +{ +public: + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return wxPGTypeName_void; } + virtual wxPGVariant GetDefaultValue() const { return wxPGVariant((void*)NULL); } + virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const + { return wxVariant( wxPGVariantToVoidPtr(value), name ); } + virtual wxPGProperty* GenerateProperty( const wxString&, const wxString& ) const + { return (wxPGProperty*) NULL; } + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const + { +#if defined(__WXDEBUG__) || defined(__WXPYTHON__) + wxCHECK_RET( wxStrcmp(GetTypeName(),value.GetType().c_str()) == 0, + wxT("SetValueFromVariant: wxVariant type mismatch.") ); +#endif + property->DoSetValue(value.GetVoidPtr()); + } +}; + +#ifdef __WXPYTHON__ +// Implement PyObject* type. +const wxPGValueType *wxPGValueType_PyObject = (wxPGValueType*) NULL; +class wxPGValueTypePyObjectClass : public wxPGValueType +{ +public: + virtual wxPG_CONST_WXCHAR_PTR GetTypeName() const { return wxT("PyObject"); } + virtual wxPGVariant GetDefaultValue() const + { + return wxVariant( new wxPGVariantDataPyObject(Py_None) ); + } + virtual wxVariant GenerateVariant( wxPGVariant value, const wxString& name ) const + { + value.SetName( name ); + return value; // Can be done since under wxPython, wxPGVariant is wxVariant + } + virtual wxPGProperty* GenerateProperty( const wxString&, const wxString& ) const + { + return (wxPGProperty*) NULL; + } + virtual void SetValueFromVariant( wxPGProperty* property, wxVariant& value ) const + { +#if defined(__WXDEBUG__) || defined(__WXPYTHON__) + wxCHECK_RET( wxStrcmp(GetTypeName(),value.GetType().c_str()) == 0, + wxT("SetValueFromVariant: wxVariant type mismatch.") ); +#endif + property->DoSetValue(value); + } +}; +#endif // __WXPYTHON__ + +// Registers all default value types +void wxPropertyGrid::RegisterDefaultValues() +{ + wxPGRegisterDefaultValueType( none ); + wxPGRegisterDefaultValueType( wxString ); + wxPGRegisterDefaultValueType( long ); + wxPGRegisterDefaultValueType( bool ); + wxPGRegisterDefaultValueType( double ); + wxPGRegisterDefaultValueType( void ); + wxPGRegisterDefaultValueType( wxArrayString ); +#ifdef __WXPYTHON__ + wxPGRegisterDefaultValueType( PyObject ); +#endif +} + +// noDefCheck = true prevents infinite recursion. +wxPGValueType* wxPropertyGrid::RegisterValueType( wxPGValueType* valueclass, bool noDefCheck, const wxString& className ) +{ + wxASSERT( valueclass ); + + WX_PG_GLOBALS_LOCKER() + + if ( !noDefCheck && wxPGGlobalVars->m_dictValueType.empty() ) + RegisterDefaultValues(); + + wxString temp_str; + wxPG_CONST_WXCHAR_PTR name_ = valueclass->GetType(); + const wxChar* name = wxPG_TO_WXCHAR_PTR(name_); + + wxPGValueType* p_at_slot = (wxPGValueType*) wxPGGlobalVars->m_dictValueType[name]; + + if ( !p_at_slot ) + { + wxPGGlobalVars->m_dictValueType[name] = (void*) valueclass; + + #if wxPG_VALUETYPE_IS_STRING + wxPGGlobalVars->m_dictValueTypeByClass[className] = (void*) valueclass; + #else + wxUnusedVar(className); + #endif + + return valueclass; + } + + // Delete given object instance, but only if it wasn't the same as in the hashmap. + if ( p_at_slot != valueclass ) + { + delete valueclass; + } + + return p_at_slot; +} + + +/* + * wxPGVariantDataWxObj + */ + +//IMPLEMENT_DYNAMIC_CLASS(wxPGVariantDataWxObj, wxVariantData) + +wxPGVariantDataWxObj::wxPGVariantDataWxObj() + : wxVariantData() +{ +} + +wxPGVariantDataWxObj::~wxPGVariantDataWxObj() +{ +} + +#if wxUSE_STD_IOSTREAM +bool wxPGVariantDataWxObj::Write(wxSTD ostream&) const +{ + // Not implemented + return true; +} +#endif + +bool wxPGVariantDataWxObj::Write(wxString&) const +{ + // Not implemented + return true; +} + +#if wxUSE_STD_IOSTREAM +bool wxPGVariantDataWxObj::Read(wxSTD istream& WXUNUSED(str)) +{ + // Not implemented + return false; +} +#endif + +bool wxPGVariantDataWxObj::Read(wxString& WXUNUSED(str)) +{ + // Not implemented + return false; +} + +// ----------------------------------------------------------------------- +// Editor class specific. + +// noDefCheck = true prevents infinite recursion. +wxPGEditor* wxPropertyGrid::RegisterEditorClass( wxPGEditor* editorclass, + const wxString& name, + bool noDefCheck ) +{ + wxASSERT( editorclass ); + + WX_PG_GLOBALS_LOCKER() + + if ( !noDefCheck && wxPGGlobalVars->m_mapEditorClasses.empty() ) + RegisterDefaultEditors(); + + wxPGGlobalVars->m_mapEditorClasses[name] = (void*)editorclass; + + return editorclass; +} + +// Registers all default editor classes +void wxPropertyGrid::RegisterDefaultEditors() +{ + wxPGRegisterDefaultEditorClass( TextCtrl ); + wxPGRegisterDefaultEditorClass( Choice ); + wxPGRegisterDefaultEditorClass( ComboBox ); + wxPGRegisterDefaultEditorClass( TextCtrlAndButton ); +#if wxPG_INCLUDE_CHECKBOX + wxPGRegisterDefaultEditorClass( CheckBox ); +#endif + wxPGRegisterDefaultEditorClass( ChoiceAndButton ); + + // Register SpinCtrl etc. editors before use + RegisterAdditionalEditors(); +} + +wxPGEditor* wxPropertyContainerMethods::GetEditorByName( const wxString& editor_name ) +{ + wxPGEditor* editor = (wxPGEditor*) wxPGGlobalVars->m_mapEditorClasses[editor_name]; + wxASSERT_MSG( editor, + wxT("unregistered editor name") ); + return editor; +} + +// ----------------------------------------------------------------------- +// wxPGStringTokenizer +// Needed to handle C-style string lists (e.g. "str1" "str2") +// ----------------------------------------------------------------------- + +wxPGStringTokenizer::wxPGStringTokenizer( const wxString& str, wxChar delimeter ) + : m_str(&str), m_curPos(str.begin()), m_delimeter(delimeter) +{ +} + +wxPGStringTokenizer::~wxPGStringTokenizer() +{ +} + +bool wxPGStringTokenizer::HasMoreTokens() +{ + const wxString& str = *m_str; + + //wxASSERT_MSG( m_curPos != str.end(), wxT("Do not call wxPGStringTokenizer methods after HasMoreTokens has returned false.")); + + wxString::const_iterator i = m_curPos; + + wxUniChar delim = m_delimeter; + wxUniChar a; + wxUniChar prev_a = wxT('\0'); + + bool inToken = false; + + while ( i != str.end() ) + { + a = wxPGGetIterChar(str, i); + + if ( !inToken ) + { + if ( a == delim ) + { + inToken = true; + m_readyToken.clear(); + } + } + else + { + if ( prev_a != wxT('\\') ) + { + if ( a != delim ) + { + if ( a != wxT('\\') ) + m_readyToken << a; + } + else + { + //wxLogDebug(m_readyToken); + i++; + m_curPos = i; + return true; + } + prev_a = a; + } + else + { + m_readyToken << a; + prev_a = wxT('\0'); + } + } + i++; + } + + m_curPos = str.end(); + + if ( inToken ) + return true; + + return false; + +/* + const wxChar* ptr = m_curPos; + const wxChar* ptr_end = &m_str->c_str()[m_str->length()]; + + size_t store_index = 0xFFFFFFFF; + +#if !wxUSE_STL + wxChar* store_ptr_base = (wxChar*) NULL; +#endif + + wxChar delim = m_delimeter; + wxChar a = *ptr; + wxChar prev_a = 0; + + while ( a ) + { + if ( store_index == 0xFFFFFFFF ) + { + if ( a == delim ) + { + size_t req_len = ptr_end-ptr+1; + #if wxUSE_STL + if ( m_readyToken.length() < req_len ) + m_readyToken.resize( req_len, wxT(' ') ); + #else + store_ptr_base = m_readyToken.GetWriteBuf( req_len ); + #endif + store_index = 0; + prev_a = 0; + } + } + else + { + if ( prev_a != wxT('\\') ) + { + if ( a != delim ) + { + if ( a != wxT('\\') ) + { + #if wxUSE_STL + m_readyToken[store_index] = a; + #else + store_ptr_base[store_index] = a; + #endif + store_index++; + } + } + else + { + #if wxUSE_STL + m_readyToken[store_index] = 0; + m_readyToken.resize(store_index,wxT(' ')); + #else + store_ptr_base[store_index] = 0; + m_readyToken.UngetWriteBuf( store_index ); + #endif + m_curPos = ptr+1; + return true; + } + prev_a = a; + } + else + { + #if wxUSE_STL + m_readyToken[store_index] = a; + #else + store_ptr_base[store_index] = a; + #endif + store_index++; + prev_a = 0; + } + } + ptr++; + a = *ptr; + } +#if !wxUSE_STL + if ( store_index != 0xFFFFFFFF ) + m_readyToken.UngetWriteBuf( store_index ); +#endif + m_curPos = (const wxChar*) NULL; + return false; +*/ +} + +wxString wxPGStringTokenizer::GetNextToken() +{ + //wxASSERT_MSG( m_curPos != m_str->end(), wxT("Do not call wxPGStringTokenizer methods after HasMoreTokens has returned false.")); + return m_readyToken; +} + +// ----------------------------------------------------------------------- +// wxPGChoicesData +// ----------------------------------------------------------------------- + +wxPGChoicesData::wxPGChoicesData() +{ + m_refCount = 1; +} + +wxPGChoicesData::~wxPGChoicesData() +{ +} + +// ----------------------------------------------------------------------- +// wxPGChoices +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxChar* label, int value ) +{ + EnsureData(); + + if ( value != wxPG_INVALID_VALUE && m_data->m_arrLabels.GetCount() == m_data->m_arrValues.GetCount() ) + m_data->m_arrValues.Add( value ); + else if ( m_data->m_arrValues.GetCount() > 0 ) + m_data->m_arrValues.Add( 0 ); + + m_data->m_arrLabels.Add ( label ); +} + +// ----------------------------------------------------------------------- + +#if wxCHECK_VERSION(2,9,0) +void wxPGChoices::Insert( const wxString& label, int index, int value ) +#else +void wxPGChoices::Insert( const wxChar* label, int index, int value ) +#endif +{ + EnsureData(); + + if ( value != wxPG_INVALID_VALUE && m_data->m_arrLabels.GetCount() == m_data->m_arrValues.GetCount() ) + m_data->m_arrValues.Insert( value, index ); + else if ( m_data->m_arrValues.GetCount() > 0 ) + m_data->m_arrValues.Insert( 0, index ); + + m_data->m_arrLabels.Insert( label, index ); +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::AddAsSorted( const wxString& label, int value ) +{ + //wxASSERT_MSG( IsOk(), + // wxT("do not add items to invalid wxPGChoices") ); + EnsureData(); + + size_t index = 0; + + wxArrayString& labels = m_data->m_arrLabels; + wxArrayInt& values = m_data->m_arrValues; + + while ( index < labels.GetCount() ) + { + int cmpRes = labels[index].Cmp(label); + if ( cmpRes > 0 ) + break; + index++; + } + + if ( value != wxPG_INVALID_VALUE && + labels.GetCount() == values.GetCount() ) + values.Insert ( value, index ); + + labels.Insert ( label, index ); +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxChar** labels, const long* values ) +{ + //wxASSERT_MSG( IsOk(), + // wxT("do not add items to invalid wxPGChoices") ); + EnsureData(); + + unsigned int itemcount = 0; + const wxChar** p = &labels[0]; + while ( *p ) { p++; itemcount++; } + + wxArrayString& i_labels = m_data->m_arrLabels; + wxArrayInt& i_values = m_data->m_arrValues; + + unsigned int i; + for ( i = 0; i < itemcount; i++ ) + { + i_labels.Add ( labels[i] ); + } + if ( values ) + { + for ( i = 0; i < itemcount; i++ ) + { + i_values.Add ( values[i] ); + } + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxArrayString& arr, const long* values ) +{ + //wxASSERT_MSG( IsOk(), + // wxT("do not add items to invalid wxPGChoices") ); + EnsureData(); + + wxArrayString& labels = m_data->m_arrLabels; + wxArrayInt& i_values = m_data->m_arrValues; + + unsigned int i; + unsigned int itemcount = arr.GetCount(); + + for ( i = 0; i < itemcount; i++ ) + { + labels.Add ( arr[i] ); + } + if ( values ) + { + for ( i = 0; i < itemcount; i++ ) + i_values.Add ( values[i] ); + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint ) +{ + //wxASSERT_MSG( IsOk(), + // wxT("do not add items to invalid wxPGChoices") ); + EnsureData(); + + wxArrayString& labels = m_data->m_arrLabels; + wxArrayInt& values = m_data->m_arrValues; + + unsigned int i; + unsigned int itemcount = arr.GetCount(); + + for ( i = 0; i < itemcount; i++ ) + { + labels.Add ( arr[i] ); + } + + if ( &arrint && arrint.GetCount() ) + for ( i = 0; i < itemcount; i++ ) + { + values.Add ( arrint[i] ); + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::AssignData( wxPGChoicesData* data ) +{ + Free(); + + if ( data != wxPGChoicesEmptyData ) + { + m_data = data; + data->m_refCount++; + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Init() +{ + m_data = wxPGChoicesEmptyData; +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Free() +{ + if ( m_data != wxPGChoicesEmptyData ) + { + m_data->m_refCount--; + if ( m_data->m_refCount < 1 ) + delete m_data; + m_data = wxPGChoicesEmptyData; + } +} + +// ----------------------------------------------------------------------- +// wxPropertyGridEvent +// ----------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxPropertyGridEvent, wxCommandEvent) + + +DEFINE_EVENT_TYPE( wxEVT_PG_SELECTED ) +DEFINE_EVENT_TYPE( wxEVT_PG_CHANGED ) +DEFINE_EVENT_TYPE( wxEVT_PG_HIGHLIGHTED ) +DEFINE_EVENT_TYPE( wxEVT_PG_RIGHT_CLICK ) +DEFINE_EVENT_TYPE( wxEVT_PG_PAGE_CHANGED ) +DEFINE_EVENT_TYPE( wxEVT_PG_ITEM_EXPANDED ) +DEFINE_EVENT_TYPE( wxEVT_PG_ITEM_COLLAPSED ) +DEFINE_EVENT_TYPE( wxEVT_PG_DOUBLE_CLICK ) +DEFINE_EVENT_TYPE( wxEVT_PG_COMPACT_MODE_ENTERED ) +DEFINE_EVENT_TYPE( wxEVT_PG_EXPANDED_MODE_ENTERED ) + + +wxPropertyGridEvent::wxPropertyGridEvent(wxEventType commandType, int id) + : wxCommandEvent(commandType,id) +{ + m_property = NULL; + m_pending = false; +} + +// ----------------------------------------------------------------------- + +wxPropertyGridEvent::wxPropertyGridEvent(const wxPropertyGridEvent& event) + : wxCommandEvent(event) +{ + m_eventType = event.GetEventType(); + m_eventObject = event.m_eventObject; + m_pg = event.m_pg; + m_property = event.m_property; + m_pending = false; +} + +// ----------------------------------------------------------------------- + +wxPropertyGridEvent::~wxPropertyGridEvent() +{ +} + +// ----------------------------------------------------------------------- + +wxEvent* wxPropertyGridEvent::Clone() const +{ + return new wxPropertyGridEvent( *this ); +} + +// ----------------------------------------------------------------------- +// wxPropertyContainerMethods +// - common methods for wxPropertyGrid and wxPropertyGridManager - +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::DoSetPropertyAttribute( wxPGId id, int attrid, + wxVariant& value, long argFlags ) +{ + wxPG_PROP_ID_CALL_PROLOG() + + p->SetAttribute(attrid,value); + + if ( ( argFlags & wxPG_RECURSE ) && p->GetParentingType() != 0 ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + DoSetPropertyAttribute(pwc->Item(i),attrid,value,argFlags); + } +} + + +// ----------------------------------------------------------------------- + +void wxPropertyGrid::SetPropertyAttributeAll( int attrid, wxVariant value ) +{ + DoSetPropertyAttribute(GetRoot(),attrid,value,wxPG_RECURSE); +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::SetBoolChoices( const wxChar* true_choice, + const wxChar* false_choice ) +{ + WX_PG_GLOBALS_LOCKER() + wxPGGlobalVars->m_boolChoices[0] = false_choice; + wxPGGlobalVars->m_boolChoices[1] = true_choice; +} + +// ----------------------------------------------------------------------- + +wxPGChoices gs_emptyChoices; + +wxPGChoices& wxPropertyContainerMethods::GetPropertyChoices( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(gs_emptyChoices) + + wxPGChoiceInfo ci; + ci.m_choices = (wxPGChoices*) NULL; + + p->GetChoiceInfo(&ci); + + if ( !ci.m_choices ) + return gs_emptyChoices; + + return *ci.m_choices; +} + +// ----------------------------------------------------------------------- + +wxPGChoices& wxPropertyContainerMethods::GetPropertyChoices( wxPGPropNameStr name ) +{ + wxPG_PROP_NAME_CALL_PROLOG_RETVAL(gs_emptyChoices) + return GetPropertyChoices(wxPGIdGen(p)); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyContainerMethods::DoGetPropertyByName( wxPGPropNameStr name ) const +{ + return m_pState->BaseGetPropertyByName(name); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyContainerMethods::GetPropertyByName( wxPGPropNameStr name, + wxPGPropNameStr subname ) const +{ + wxPGId id = DoGetPropertyByName(name); + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) wxPGIdToPtr(id); + if ( !pwc || !pwc->GetParentingType() ) + return wxNullProperty; + + return wxPGIdGen(pwc->GetPropertyByName(subname)); +} + +// ----------------------------------------------------------------------- + +// Since GetPropertyByName is used *a lot*, this makes sense +// since non-virtual method can be called with less code. +wxPGId wxPropertyContainerMethods::GetPropertyByName( wxPGPropNameStr name ) const +{ + wxPGId id = DoGetPropertyByName(name); + if ( wxPGIdIsOk(id) ) + return id; + + // Check if its "Property.SubProperty" format + int pos = name.Find(wxT('.')); + if ( pos <= 0 ) + return id; + + return GetPropertyByName(name.substr(0,pos), + name.substr(pos+1,name.length()-pos-1)); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyContainerMethods::HideProperty( wxPGId id, bool hide ) +{ + // Hiding properties requires that we are always in the compact mode + m_pState->GetGrid()->Compact(true); + return SetPropertyPriority(id,hide?wxPG_LOW:wxPG_HIGH); +} + +// ----------------------------------------------------------------------- + +// Used by HideProperty as well +bool wxPropertyContainerMethods::SetPropertyPriority( wxPGId id, int priority ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + wxPropertyGrid* pg = m_pState->GetGrid(); + + if ( pg == p->GetGrid() ) + return pg->SetPropertyPriority(p,priority); + else + m_pState->SetPropertyPriority(p,priority); + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyContainerMethods::SetPropertyMaxLength( wxPGId id, int maxLen ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + + wxPropertyGrid* pg = m_pState->GetGrid(); + + p->m_maxLen = (short) maxLen; + + // Adjust control if selected currently + if ( pg == p->GetGrid() && p == m_pState->GetSelection() ) + { + wxWindow* wnd = pg->GetEditorControl(); + wxTextCtrl* tc = wxDynamicCast(wnd,wxTextCtrl); + if ( tc ) + tc->SetMaxLength( maxLen ); + else + // Not a text ctrl + return false; + } + + return true; +} + +// ----------------------------------------------------------------------- +// GetPropertyValueAsXXX methods + +#define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \ +TRET wxPropertyContainerMethods::GetPropertyValueAs##BIGNAME( wxPGId id ) wxPG_GETVALUE_CONST \ +{ \ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(DEFRETVAL) \ + if ( p->GetValueTypePtr()->GetTypeName() != wxPGTypeName_##T ) \ + { \ + wxPGGetFailed(p,wxPGTypeName_##T); \ + return (TRET)DEFRETVAL; \ + } \ + return (TRET)wxPGVariantTo##BIGNAME(p->DoGetValue()); \ +} + +// String is different than others. +wxString wxPropertyContainerMethods::GetPropertyValueAsString( wxPGId id ) wxPG_GETVALUE_CONST +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxEmptyString) + return p->GetValueAsString(wxPG_FULL_VALUE); +} + +IMPLEMENT_GET_VALUE(long,long,Long,0) +IMPLEMENT_GET_VALUE(long,bool,Bool,false) +IMPLEMENT_GET_VALUE(double,double,Double,0.0) +IMPLEMENT_GET_VALUE(void,void*,VoidPtr,NULL) +#ifdef __WXPYTHON__ + IMPLEMENT_GET_VALUE(PyObject,PyObject*,PyObject,Py_None) +#endif + +#if !wxPG_PGVARIANT_IS_VARIANT + IMPLEMENT_GET_VALUE(wxArrayString,const wxArrayString&,ArrayString,*((wxArrayString*)NULL)) +#endif + +// wxObject is different than others. +const wxObject* wxPropertyContainerMethods::GetPropertyValueAsWxObjectPtr( wxPGId id ) wxPG_GETVALUE_CONST +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL((const wxObject*)NULL) + wxPG_CONST_WXCHAR_PTR typestr = p->GetValueTypePtr()->GetTypeName(); + if ( typestr[0] != wxT('w') || typestr[1] != wxT('x') ) + { + wxPGGetFailed(p,wxT("wxObject")); + return (const wxObject*) NULL; + } + return (const wxObject*)wxPGVariantGetWxObjectPtr(p->DoGetValue()); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyContainerMethods::IsPropertyExpanded( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(false) + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->GetParentingType() == 0 ) + return false; + return pwc->IsExpanded(); +} + +// ----------------------------------------------------------------------- + +// returns value type class for type name +wxPGValueType* wxPropertyContainerMethods::GetValueType(const wxString &type) +{ + wxPGHashMapS2P::iterator it; + + it = wxPGGlobalVars->m_dictValueType.find(type); + + if ( it != wxPGGlobalVars->m_dictValueType.end() ) + return (wxPGValueType*) it->second; + + return (wxPGValueType*) NULL; +} + +// ----------------------------------------------------------------------- + +#if wxPG_VALUETYPE_IS_STRING +wxPGValueType* wxPropertyContainerMethods::GetValueTypeByName(const wxString &className) +{ + wxPGHashMapS2P::iterator it; + + it = wxPGGlobalVars->m_dictValueTypeByClass.find(className); + + if ( it != wxPGGlobalVars->m_dictValueTypeByClass.end() ) + return (wxPGValueType*) it->second; + + return (wxPGValueType*) NULL; +} +#endif + +// ----------------------------------------------------------------------- + +wxPGProperty* wxPropertyContainerMethods::CreatePropertyByType(const wxString &valuetype, + const wxString &label, + const wxString &name) +{ + wxPGHashMapS2P::iterator it; + + it = wxPGGlobalVars->m_dictValueType.find(valuetype); + + if ( it != wxPGGlobalVars->m_dictValueType.end() ) + { + wxPGValueType* vt = (wxPGValueType*) it->second; + wxPGProperty* p = vt->GenerateProperty(label,name); + #ifdef __WXDEBUG__ + if ( !p ) + { + wxLogDebug(wxT("WARNING: CreatePropertyByValueType generated NULL property for ValueType \"%s\""),valuetype.c_str()); + return (wxPGProperty*) NULL; + } + #endif + return p; + } + + wxLogDebug(wxT("WARNING: No value type registered with name \"%s\""),valuetype.c_str()); + return (wxPGProperty*) NULL; +} + +// ----------------------------------------------------------------------- + +wxPGProperty* wxPropertyContainerMethods::CreatePropertyByClass(const wxString &classname, + const wxString &label, + const wxString &name) +{ + wxPGHashMapS2P* cis = + (wxPGHashMapS2P*) &wxPGGlobalVars->m_dictPropertyClassInfo; + + const wxString* pClassname = &classname; + wxString s; + + // Translate to long name, if necessary + if ( (pClassname->GetChar(0) != wxT('w') || pClassname->GetChar(1) != wxT('x')) && + pClassname->Find(wxT("Property")) < 0 ) + { + if ( classname != wxT("Category") ) + s.Printf(wxT("wx%sProperty"),pClassname->c_str()); + else + s = wxT("wxPropertyCategory"); + pClassname = &s; + } + + wxPGHashMapS2P::iterator it; + it = cis->find(*pClassname); + + if ( it != cis->end() ) + { + wxPGPropertyClassInfo* pci = (wxPGPropertyClassInfo*) it->second; + wxPGProperty* p = pci->m_constructor(label,name); + return p; + } + wxLogError(wxT("No such property class: %s"),pClassname->c_str()); + return (wxPGProperty*) NULL; +} + +// ----------------------------------------------------------------------- + +// lazy way to prevent RegisterPropertyClass infinite recursion +static int gs_registering_standard_props = 0; + +bool wxPropertyContainerMethods::RegisterPropertyClass( const wxChar* name, + wxPGPropertyClassInfo* classinfo ) +{ + + WX_PG_GLOBALS_LOCKER() + + // Standard classes must be registered first! + if ( !gs_registering_standard_props && + wxPGGlobalVars->m_dictPropertyClassInfo.empty() + ) + wxPGRegisterStandardPropertyClasses(); + + wxPGHashMapS2P::iterator it; + + it = wxPGGlobalVars->m_dictPropertyClassInfo.find(name); + + // only register if not registered already + if ( it == wxPGGlobalVars->m_dictPropertyClassInfo.end() ) + { + wxPGGlobalVars->m_dictPropertyClassInfo[name] = classinfo; + return true; + } + + wxLogDebug(wxT("WARNING: Property class named \"%s\" was already registered."),name); + + return false; +} + +// ----------------------------------------------------------------------- + +static void wxPGRegisterStandardPropertyClasses() +{ + + if ( gs_registering_standard_props ) + return; + + gs_registering_standard_props = 1; // no need to reset this + + wxPGRegisterPropertyClass(wxStringProperty); + wxPGRegisterPropertyClass(wxIntProperty); + wxPGRegisterPropertyClass(wxUIntProperty); + wxPGRegisterPropertyClass(wxFloatProperty); + wxPGRegisterPropertyClass(wxBoolProperty); + wxPGRegisterPropertyClass(wxEnumProperty); + wxPGRegisterPropertyClass(wxFlagsProperty); + wxPGRegisterPropertyClass(wxLongStringProperty); + + wxPGRegisterPropertyClass(wxPropertyCategory); + wxPGRegisterPropertyClass(wxParentProperty); + wxPGRegisterPropertyClass(wxCustomProperty); + + // TODO: Are these really "standard" ? + wxPGRegisterPropertyClass(wxArrayStringProperty); + wxPGRegisterPropertyClass(wxFileProperty); + wxPGRegisterPropertyClass(wxDirProperty); + +#ifdef __WXPYTHON__ + wxPropertyContainerMethods::RegisterAdvancedPropertyClasses(); +#endif +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState +// ----------------------------------------------------------------------- + +// reset helper macro +#undef FROM_STATE +#define FROM_STATE(A) A + +// ----------------------------------------------------------------------- +// wxPropertyGridState item iteration methods +// ----------------------------------------------------------------------- + +// Skips categories and sub-properties (unless in wxCustomProperty/wxParentProperty). +wxPGId wxPropertyGridState::GetFirstProperty() const +{ + if ( !m_properties->GetCount() ) return wxPGIdGen((wxPGProperty*)NULL); + wxPGProperty* p = m_properties->Item(0); + int parenting = p->GetParentingType(); + if ( parenting > 0 ) + return GetNextProperty ( wxPGIdGen(p) ); + return wxPGIdGen(p); +} + +// ----------------------------------------------------------------------- + +// Skips categories and sub-properties (unless in wxParentProperty). +wxPGId wxPropertyGridState::GetNextProperty( wxPGId id ) const +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + // Go with first child? + int parenting = pwc->GetParentingType(); + if ( parenting == 0 || parenting == -1 || !pwc->GetCount() ) + { + // No... + + wxPGPropertyWithChildren* parent = pwc->m_parent; + + // As long as last item, go up and get parent' sibling + while ( pwc->m_arrIndex >= (parent->GetCount()-1) ) + { + pwc = parent; + if ( pwc == m_properties ) return wxPGIdGen((wxPGProperty*)NULL); + parent = parent->m_parent; + } + + pwc = (wxPGPropertyWithChildren*)parent->Item(pwc->m_arrIndex+1); + + // Go with the next sibling of parent's parent? + } + else + { + // Yes... + pwc = (wxPGPropertyWithChildren*)pwc->Item(0); + } + + // If it's category or parentproperty, then go recursive + parenting = pwc->GetParentingType(); + if ( parenting > PT_NONE ) + return GetNextProperty( wxPGIdGen(pwc) ); + + return wxPGIdGen(pwc); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::GetNextSibling( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGPropertyWithChildren* parent = p->m_parent; + size_t next_ind = p->m_arrIndex + 1; + if ( next_ind >= parent->GetCount() ) return wxPGIdGen((wxPGProperty*)NULL); + return wxPGIdGen(parent->Item(next_ind)); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::GetPrevSibling( wxPGId id ) +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + size_t ind = p->m_arrIndex; + if ( ind < 1 ) return wxPGIdGen((wxPGProperty*)NULL); + return wxPGIdGen(p->m_parent->Item(ind-1)); +} + +// ----------------------------------------------------------------------- + +// Skips categories and sub-properties (unless in wxParentProperty). +wxPGId wxPropertyGridState::GetPrevProperty( wxPGId id ) const +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGPropertyWithChildren* p2 = (wxPGPropertyWithChildren*) p; + wxPGPropertyWithChildren* parent = p2->m_parent; + + // Is there a previous sibling? + if ( p2->m_arrIndex > 0 ) + { + // There is! + p2 = (wxPGPropertyWithChildren*)parent->Item ( p2->m_arrIndex-1 ); + int parenting = p2->GetParentingType(); + + // Do we return it's last child? + while ( (parenting > 0 || parenting == PT_CUSTOMPROPERTY) && p2->GetCount() ) + { + p2 = (wxPGPropertyWithChildren*)p2->Last(); + parenting = p2->GetParentingType(); + } + } + else if ( parent != m_properties ) + // Return parent if it isnt' the root + p2 = parent; + else + return wxPGIdGen((wxPGProperty*)NULL); + + // Skip category and parentproperty. + int parenting = p2->GetParentingType(); + if ( parenting > PT_NONE ) + return GetPrevProperty ( wxPGIdGen(p2) ); + + return wxPGIdGen(p2); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::GetFirstCategory() const +{ + //if ( IsInNonCatMode() ) + // return wxPGIdGen((wxPGProperty*)NULL); + + wxPGProperty* found = (wxPGProperty*)NULL; + + size_t i; + for ( i=0; iGetParentingType() > 0 ) + { + found = p; + break; + } + } + return wxPGIdGen(found); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::GetNextCategory( wxPGId id ) const +{ + wxPG_PROP_ID_CALL_PROLOG_RETVAL(wxNullProperty) + + wxPGPropertyWithChildren* current = (wxPGPropertyWithChildren*)p; + + wxCHECK_MSG( !IsInNonCatMode() || current->GetParentingType() == 1, wxPGIdGen((wxPGProperty*)NULL), + wxT("GetNextCategory should not be called with non-category argument in non-categoric mode.") ); + + wxPGPropertyWithChildren* parent = current->m_parent; + wxPGProperty* found = (wxPGProperty*) NULL; + size_t i; + + // Find sub-category, if any. + if ( current->GetParentingType() > 0 ) + { + // Find first sub-category in current's array. + for ( i = 0; iGetCount(); i++ ) + { + wxPGProperty* p = current->Item(i); + if ( p->GetParentingType() > 0 ) + { + found = p; + break; + } + } + if ( found ) + return wxPGIdGen(found); + } + + // Find next category in parent's array. + // (and go up in hierarchy until one found or + // top is reached). + do + { + for ( i = current->m_arrIndex+1; iGetCount(); i++ ) + { + wxPGProperty* p = parent->Item(i); + if ( p->GetParentingType() > 0 ) + { + found = p; + break; + } + } + current = parent; + parent = parent->m_parent; + } while ( !found && parent ); + + return wxPGIdGen(found); +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState GetPropertyXXX methods +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::GetPropertyByLabel( const wxString& label, + wxPGPropertyWithChildren* parent ) const +{ + + size_t i; + + if ( !parent ) parent = (wxPGPropertyWithChildren*) &m_regularArray; + + for ( i=0; iGetCount(); i++ ) + { + wxPGProperty* p = parent->Item(i); + if ( p->m_label == label ) + return wxPGIdGen(p); + // Check children recursively. + if ( p->GetParentingType() != 0 ) + { + p = wxPGIdToPtr(GetPropertyByLabel(label,(wxPGPropertyWithChildren*)p)); + if ( p ) + return wxPGIdGen(p); + } + } + + return wxPGIdGen((wxPGProperty*) NULL); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::BaseGetPropertyByName( wxPGPropNameStr name ) const +{ + wxPGHashMapS2P::const_iterator it; + it = m_dictName.find(name); + if ( it != m_dictName.end() ) + return wxPGIdGen( (wxPGProperty*) it->second ); + return wxPGIdGen( (wxPGProperty*) NULL ); +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState global operations +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::EnableCategories( bool enable ) +{ + ITEM_ITERATION_VARIABLES + + if ( enable ) + { + // + // Enable categories + // + + if ( !IsInNonCatMode() ) + return false; + + m_properties = &m_regularArray; + + // fix parents, indexes, and depths + ITEM_ITERATION_INIT_FROM_THE_TOP + + ITEM_ITERATION_LOOP_BEGIN + + p->m_arrIndex = i; + + p->m_parent = parent; + + // If parent was category, and this is not, + // then the depth stays the same. + if ( parent->GetParentingType() == 1 && + p->GetParentingType() <= 0 ) + p->m_depth = parent->m_depth; + else + p->m_depth = parent->m_depth + 1; + + ITEM_ITERATION_LOOP_END + + } + else + { + // + // Disable categories + // + + if ( IsInNonCatMode() ) + return false; + + // Create array, if necessary. + if ( !m_abcArray ) + InitNonCatMode(); + + m_properties = m_abcArray; + + // fix parents, indexes, and depths + ITEM_ITERATION_INIT_FROM_THE_TOP + + //ITEM_ITERATION_DCAE_ISP_LOOP_BEGIN + ITEM_ITERATION_DCAE_LOOP_BEGIN + + p->m_arrIndex = i; + + p->m_parent = parent; + + p->m_depth = parent->m_depth + 1; + + //ITEM_ITERATION_DCAE_ISP_LOOP_END + ITEM_ITERATION_DCAE_LOOP_END + + } + + return true; +} + +// ----------------------------------------------------------------------- + +static int wxPG_SortFunc(void **p1, void **p2) +{ + wxPGProperty *pp1 = *((wxPGProperty**)p1); + wxPGProperty *pp2 = *((wxPGProperty**)p2); + return pp1->GetLabel().compare( pp2->GetLabel() ); +} + +void wxPropertyGridState::Sort( wxPGProperty* p ) +{ + if ( !p ) + p = (wxPGProperty*)m_properties; + + wxCHECK_RET( p->GetParentingType() != 0, + wxT("cannot sort non-parenting property") ); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + // Can only sort items with children + if ( pwc->m_children.GetCount() < 1 ) + return; + + pwc->m_children.Sort( wxPG_SortFunc ); + + // Fix indexes + pwc->FixIndexesOfChildren(); + +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::Sort() +{ + Sort( m_properties ); + + // Sort categories as well + if ( !IsInNonCatMode() ) + { + size_t i; + for ( i=0;iGetCount();i++) + { + wxPGProperty* p = m_properties->Item(i); + if ( p->GetParentingType() > 0 ) + Sort ( p ); + } + } +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::ExpandAll( unsigned char doExpand ) +{ + ITEM_ITERATION_DCAE_VARIABLES + + bool isGrid = m_pPropGrid->GetState() == this; + + if ( isGrid && + m_selected && + m_selected->GetParent() != m_properties ) + { + if ( !m_pPropGrid->ClearSelection() ) + return false; + } + + if ( !doExpand ) + { + if ( isGrid ) + { + if ( !m_pPropGrid->ClearSelection() ) + return false; + } + else m_selected = (wxPGProperty*) NULL; + } + + ITEM_ITERATION_INIT_FROM_THE_TOP + + ITEM_ITERATION_DCAE_LOOP_BEGIN + + if ( parenting != 0 ) + ((wxPGPropertyWithChildren*)p)->m_expanded = doExpand; + + ITEM_ITERATION_DCAE_LOOP_END + + if ( m_pPropGrid->GetState() == this ) + { + m_pPropGrid->CalculateYs((wxPGPropertyWithChildren*)NULL,-1); + + m_pPropGrid->RedrawAllVisible(); + } + + return true; +} + +// ----------------------------------------------------------------------- + +// Used by SetSplitterLeft +int wxPropertyGridState::GetLeftSplitterPos(wxClientDC& dc, + wxPGPropertyWithChildren* pwc, + bool subProps) +{ + wxPropertyGrid* pg = m_pPropGrid; + size_t i; + int maxW = 0; + int w, h; + + for ( i=0; iGetCount(); i++ ) + { + wxPGProperty* p = pwc->Item(i); + if ( p->GetParentingType() <= 0 ) + { + dc.GetTextExtent( p->GetLabel(), &w, &h ); + + w += pg->m_marginWidth + ( ((int)p->m_depth-1) * pg->m_subgroup_extramargin ) + (wxPG_XBEFORETEXT*2); + + if ( w > maxW ) + maxW = w; + } + + if ( p->GetParentingType() && + ( subProps || p->GetParentingType() > 0 ) ) + { + w = GetLeftSplitterPos( dc, (wxPGPropertyWithChildren*) p, subProps ); + + if ( w > maxW ) + maxW = w; + } + } + + return maxW; +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState property value setting and getting +// ----------------------------------------------------------------------- + +void wxPropertyGridState::SetPropVal( wxPGProperty* p, const wxPGVariant& value ) +{ + p->DoSetValue(value); + if ( m_selected==p && this==m_pPropGrid->GetState() ) + p->UpdateControl(m_pPropGrid->m_wndPrimary); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::ClearPropertyValue( wxPGProperty* p ) +{ + if ( p ) + { + const wxPGValueType* valueclass = p->GetValueTypePtr(); + + if ( valueclass != wxPG_VALUETYPE_PTR(none) ) + { + // wnd_primary has to be given so the editor control can be updated as well. + SetPropVal(p,valueclass->GetDefaultValue()); + + return true; + } + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyValue( wxPGProperty* p, + const wxPGValueType* typeclass, + const wxPGVariant& value ) +{ + if ( p ) + { + if ( p->GetValueTypePtr()->GetTypeName() == typeclass->GetTypeName() ) + { + CLEAR_PROPERTY_UNSPECIFIED_FLAG(p); + + SetPropVal(p,value); + + return true; + } + wxPGTypeOperationFailed ( p, typeclass->GetTypeName(), wxT("Set") ); + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyValue( wxPGProperty* p, const wxChar* typestring, const wxPGVariant& value ) +{ + if ( p ) + { + if ( wxStrcmp(p->GetValueTypePtr()->GetCustomTypeName(),typestring) == 0 ) + { + // wnd_primary has to be given so the control can be updated as well. + + SetPropVal(p,value); + return true; + } + wxPGTypeOperationFailed ( p, typestring, wxT("Set") ); + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyValueString( wxPGProperty* p, const wxString& value ) +{ + if ( p ) + { + int flags = wxPG_REPORT_ERROR|wxPG_FULL_VALUE; + CLEAR_PROPERTY_UNSPECIFIED_FLAG(p); + + if ( p->GetMaxLength() <= 0 ) + p->SetValueFromString( value, flags ); + else + p->SetValueFromString( value.Mid(0,p->GetMaxLength()), flags ); + + if ( m_selected==p && this==m_pPropGrid->GetState() ) + p->UpdateControl(m_pPropGrid->m_wndPrimary); + + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyValue( wxPGProperty* p, wxVariant& value ) +{ + if ( p ) + { + CLEAR_PROPERTY_UNSPECIFIED_FLAG(p); + p->GetValueTypePtr()->SetValueFromVariant(p,value); + if ( m_selected==p && this==m_pPropGrid->GetState() ) + p->UpdateControl(m_pPropGrid->m_wndPrimary); + + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyValueWxObjectPtr( wxPGProperty* p, wxObject* value ) +{ + if ( p ) + { + if ( wxStrcmp( p->GetValueTypePtr()->GetTypeName(), + value->GetClassInfo()->GetClassName() + ) == 0 + ) + { + CLEAR_PROPERTY_UNSPECIFIED_FLAG(p); + // wnd_primary has to be given so the control can be updated as well. + SetPropVal(p,wxPGVariantFromWxObject(value)); + return true; + } + wxPGTypeOperationFailed ( p, wxT("wxObject"), wxT("Set") ); + } + return false; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::SetPropertyUnspecified( wxPGProperty* p ) +{ + wxCHECK_RET( p, wxT("invalid property id") ); + + if ( !(p->m_flags & wxPG_PROP_UNSPECIFIED) ) + { + // Flag should be set first - editor class methods may need it + p->m_flags |= wxPG_PROP_UNSPECIFIED; + + wxASSERT( m_pPropGrid ); + + if ( m_pPropGrid->GetState() == this ) + { + if ( m_pPropGrid->m_selected == p && m_pPropGrid->m_wndPrimary ) + { + p->GetEditorClass()->SetValueToUnspecified(m_pPropGrid->m_wndPrimary); + } + } + + if ( p->GetParentingType() != 0 ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + SetPropertyUnspecified( pwc->Item(i) ); + } + } + +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState property operations +// ----------------------------------------------------------------------- + +void wxPropertyGridState::LimitPropertyEditing( wxPGProperty* p, bool limit ) +{ + if ( p ) + { + if ( limit ) + p->m_flags |= wxPG_PROP_NOEDITOR; + else + p->m_flags &= ~(wxPG_PROP_NOEDITOR); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::ClearModifiedStatus( wxPGProperty* p ) +{ + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + if ( p->m_flags & wxPG_PROP_MODIFIED ) + { + p->m_flags &= ~(wxPG_PROP_MODIFIED); + + if ( m_pPropGrid->GetState() == this ) + { + // Clear active editor bold + if ( p == m_selected && m_pPropGrid->m_wndPrimary ) + m_pPropGrid->m_wndPrimary->SetFont( m_pPropGrid->GetFont() ); + + m_pPropGrid->DrawItem( p ); + } + } + + if ( pwc->GetParentingType() != 0 ) + { + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + ClearModifiedStatus( pwc->Item(i) ); + } +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::Collapse( wxPGProperty* p ) +{ + wxCHECK_MSG( p, false, wxT("invalid property id") ); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->GetParentingType() == 0 ) return false; + + if ( !pwc->m_expanded ) return false; + + // m_expanded must be set just before call to CalculateYs + pwc->m_expanded = 0; + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::Expand( wxPGProperty* p ) +{ + wxCHECK_MSG( p, false, wxT("invalid property id") ); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + if ( pwc->GetParentingType() == 0 ) return false; + + if ( pwc->m_expanded ) return false; + + // m_expanded must be set just before call to CalculateYs + pwc->m_expanded = 1; + + return true; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::DoSelectProperty( wxPGProperty* p, unsigned int flags ) +{ + if ( this == m_pPropGrid->GetState() ) + return m_pPropGrid->DoSelectProperty( p, flags ); + + m_selected = p; + return true; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::SetPropertyLabel( wxPGProperty* p, const wxString& newlabel ) +{ + wxCHECK_RET(p, wxT("invalid property id")); + p->SetLabel(newlabel); + if ( m_pPropGrid->GetWindowStyleFlag() & wxPG_AUTO_SORT ) + Sort(p->GetParent()); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::SetPropertyPriority( wxPGProperty* p, int priority ) +{ + int parenting = p->GetParentingType(); + + if ( priority == wxPG_HIGH ) p->ClearFlag( wxPG_PROP_HIDEABLE ); + else p->SetFlag( wxPG_PROP_HIDEABLE ); + + if ( parenting != 0 ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + SetPropertyPriority(pwc->Item(i),priority); + } + + return true; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::SetPropertyAndChildrenFlags( wxPGProperty* p, long flags ) +{ + p->m_flags |= flags; + + if ( p->GetParentingType() != 0 ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + ClearPropertyAndChildrenFlags ( pwc->Item(i), flags ); + } +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::ClearPropertyAndChildrenFlags( wxPGProperty* p, long flags ) +{ + p->m_flags &= ~(flags); + + if ( p->GetParentingType() != 0 ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + ClearPropertyAndChildrenFlags ( pwc->Item(i), flags ); + } +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridState::EnableProperty( wxPGProperty* p, bool enable ) +{ + if ( p ) + { + if ( enable ) + { + if ( !(p->m_flags & wxPG_PROP_DISABLED) ) + return false; + + // Enabling + + p->m_flags &= ~(wxPG_PROP_DISABLED); + } + else + { + if ( p->m_flags & wxPG_PROP_DISABLED ) + return false; + + // Disabling + + p->m_flags |= wxPG_PROP_DISABLED; + + } + + if ( p->GetParentingType() == 0 ) + return true; + + // Apply same to sub-properties as well + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)p; + + size_t i; + for ( i = 0; i < pwc->GetCount(); i++ ) + EnableProperty ( pwc->Item(i), enable ); + + return true; + } + return false; +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState wxVariant related routines +// ----------------------------------------------------------------------- + +// Returns list of wxVariant objects (non-categories and non-sub-properties only). +// Never includes sub-properties (unless they are parented by wxParentProperty). +wxVariant wxPropertyGridState::GetPropertyValues( const wxString& listname, + wxPGId baseparent, + long flags ) const +{ + ITEM_ITERATION_DCAE_VARIABLES + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)wxPGIdToPtr(baseparent); + + // Root is the default base-parent. + if ( !pwc ) + pwc = m_properties; + + wxVariantList temp_list; + wxVariant v( temp_list, listname ); + + if ( flags & wxPG_KEEP_STRUCTURE ) + { + wxASSERT( (pwc->GetParentingType() < -1) || (pwc->GetParentingType() > 0) ); + + size_t i; + for ( i=0; iGetCount(); i++ ) + { + wxPGProperty* p = pwc->Item(i); + int parenting = p->GetParentingType(); + if ( parenting == 0 || parenting == -1 ) + { + v.Append( p->GetValueAsVariant() ); + } + else + { + v.Append( GetPropertyValues(p->m_name,wxPGIdGen(p),wxPG_KEEP_STRUCTURE) ); + } + } + } + else + { + ITEM_ITERATION_INIT((wxPGPropertyWithChildren*)wxPGIdToPtr(baseparent),0) + ITEM_ITERATION_DCAE_ISP_LOOP_BEGIN + + // Use a trick to ignore wxParentProperty itself, but not its sub-properties. + if ( parenting == PT_CUSTOMPROPERTY ) + { + parenting = PT_CAPTION; + } + else if ( parenting <= 0 ) + { + v.Append ( p->GetValueAsVariant() ); + } + + ITEM_ITERATION_DCAE_ISP_LOOP_END + } + + return v; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::SetPropertyValues( const wxVariantList& list, wxPGId default_category ) +{ + + unsigned char origFrozen = 1; + + if ( m_pPropGrid->GetState() == this ) + { + origFrozen = m_pPropGrid->m_frozen; + if ( !origFrozen ) m_pPropGrid->Freeze(); + } + + wxPropertyCategoryClass* use_category = (wxPropertyCategoryClass*)wxPGIdToPtr(default_category); + + if ( !use_category ) + use_category = (wxPropertyCategoryClass*)m_properties; + + // Let's iterate over the list of variants. + wxVariantList::const_iterator node; + + //for ( wxVariantList::Node *node = list.GetFirst(); node; node = node->GetNext() ) + for ( node = list.begin(); node != list.end(); node++ ) + { + wxVariant *current = (wxVariant*)*node; + + // Make sure it is wxVariant. + wxASSERT( current ); + wxASSERT( wxStrcmp(current->GetClassInfo()->GetClassName(),wxT("wxVariant")) == 0 ); + + if ( current->GetName().length() > 0 ) + { + wxPGId foundProp = BaseGetPropertyByName(current->GetName()); + if ( wxPGIdIsOk(foundProp) ) + { + wxPGProperty* p = wxPGIdToPtr(foundProp); + + const wxPGValueType* vtype = p->GetValueTypePtr(); + + // If it was a list, we still have to go through it. + if ( current->GetType() == wxT("list") ) + { + SetPropertyValues( current->GetList(), + wxPGIdGen( + p->GetParentingType()>0?p:((wxPGProperty*)NULL) + ) ); + } + else + { + #ifdef __WXDEBUG__ + if ( current->GetType() != vtype->GetTypeName() && + current->GetType() != vtype->GetCustomTypeName() ) + { + wxLogDebug(wxT("wxPropertyGridState::SetPropertyValues Warning: Setting value of property \"%s\" from variant"), + p->m_name.c_str()); + wxLogDebug(wxT(" but variant's type name (%s) doesn't match either base type name (%s) nor custom type name (%s)."), + #ifndef __WXPYTHON__ + current->GetType().c_str(),vtype->GetTypeName(),vtype->GetCustomTypeName()); + #else + current->GetType().c_str(),vtype->GetTypeName().c_str(),vtype->GetCustomTypeName().c_str()); + #endif + } + #endif + + vtype->SetValueFromVariant(p,*current); + } + } + else + { + // Is it list? + if ( current->GetType() != wxT("list") ) + { + // Not. + AppendIn(use_category,current->GetName(),wxPG_LABEL,(wxVariant&)*current); + } + else + { + // Yes, it is; create a sub category and append contents there. + wxPGId newCat = DoInsert(use_category,-1,new wxPropertyCategoryClass(current->GetName(),wxPG_LABEL)); + SetPropertyValues( current->GetList(), newCat ); + } + } + } + } + + if ( !origFrozen ) + { + m_pPropGrid->Thaw(); + + if ( this == m_pPropGrid->GetState() ) + { + m_selected->UpdateControl(m_pPropGrid->m_wndPrimary); + } + } + +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState property adding and removal +// ----------------------------------------------------------------------- + +// Call for after sub-properties added with AddChild +void wxPGPropertyWithChildren::PrepareSubProperties() +{ + // TODO: When in 1.0.5, move extra stuff from AddChild to here. + wxPropertyGridState* state = GetParentState(); + + wxASSERT(state); + + if ( !GetCount() ) + return; + + wxByte depth = m_depth + 1; + wxByte depthBgCol = m_depthBgCol; + + wxByte inheritFlags = m_flags & wxPG_INHERITED_PROPFLAGS; + + wxByte bgColIndex = m_bgColIndex; + wxByte fgColIndex = m_fgColIndex; + + // + // Set some values to the children + // + size_t i = 0; + wxPGPropertyWithChildren* nparent = this; + + while ( i < nparent->GetCount() ) + { + wxPGProperty* np = nparent->Item(i); + + np->m_flags |= inheritFlags; // Hideable also if parent. + np->m_depth = depth; + np->m_depthBgCol = depthBgCol; + np->m_bgColIndex = bgColIndex; + np->m_fgColIndex = fgColIndex; + + // Also handle children of children + if ( np->GetParentingType() != 0 && + ((wxPGPropertyWithChildren*)np)->GetCount() > 0 ) + { + nparent = (wxPGPropertyWithChildren*) np; + i = 0; + + // Init + nparent->m_expanded = 0; + nparent->m_parentState = state; + depth++; + } + else + { + // Next sibling + i++; + } + + // After reaching last sibling, go back to processing + // siblings of the parent + while ( i >= nparent->GetCount() ) + { + // Exit the loop when top parent hit + if ( nparent == this ) + break; + + depth--; + + i = nparent->GetArrIndex() + 1; + nparent = nparent->GetParent(); + } + } +} + +// ----------------------------------------------------------------------- + +// Call after fixed sub-properties added/removed after creation. +// if oldSelInd >= 0 and < new max items, then selection is +// moved to it. Note: oldSelInd -2 indicates that this property +// should be selected. +void wxPGPropertyWithChildren::SubPropsChanged( int oldSelInd ) +{ + wxPropertyGridState* state = GetParentState(); + wxPropertyGrid* grid = state->GetGrid(); + + PrepareSubProperties(); + + wxPGProperty* sel = (wxPGProperty*) NULL; + if ( oldSelInd >= (int)m_children.GetCount() ) + oldSelInd = (int)m_children.GetCount() - 1; + + if ( oldSelInd >= 0 ) + sel = (wxPGProperty*) m_children[oldSelInd]; + else if ( oldSelInd == -2 ) + sel = this; + + if ( sel ) + state->DoSelectProperty(sel); + + if ( state == grid->GetState() ) + { + if ( m_expanded ) + grid->CalculateYs( GetParent(), m_arrIndex ); + grid->Refresh(); + } +} + +// ----------------------------------------------------------------------- + +int wxPropertyGridState::PrepareToAddItem( wxPGProperty* property, + wxPGPropertyWithChildren* scheduledParent ) +{ + wxPropertyGrid* propGrid = m_pPropGrid; + wxASSERT( propGrid ); + + int parenting = property->GetParentingType(); + + // This will allow better behaviour. + if ( scheduledParent == m_properties ) + scheduledParent = (wxPGPropertyWithChildren*) NULL; + + if ( parenting > 0 ) + { + /* + if ( scheduledParent ) + wxLogDebug(wxT("scheduledParent= %s, %i"), + scheduledParent->GetName().c_str(), (int)scheduledParent->GetParentingType()); + */ + + // Parent of a category must be either root or another category + // (otherwise Bad Things might happen). + wxASSERT_MSG( scheduledParent == (wxPGPropertyWithChildren*) NULL || + scheduledParent == m_properties || + scheduledParent->GetParentingType() > 0, + wxT("Parent of a category must be either root or another category.")); + + /* + wxASSERT_MSG( m_properties == &m_regularArray, + wxT("Do not add categories in non-categoric mode!")); + */ + + // If we already have category with same name, delete given property + // and use it instead as most recent caption item. + wxPGId found_id = BaseGetPropertyByName( property->GetName() ); + if ( wxPGIdIsOk(found_id) ) + { + wxPropertyCategoryClass* pwc = (wxPropertyCategoryClass*)wxPGIdToPtr(found_id); + if ( pwc->GetParentingType() > 0 ) // Must be a category. + { + delete property; + m_currentCategory = pwc; + return 2; // Tells the caller what we did. + } + } + } + +#ifdef __WXDEBUG__ + // Warn for identical names in debug mode. + if ( property->GetName().length() && + wxPGIdIsOk(BaseGetPropertyByName(property->GetName())) && + (!scheduledParent || scheduledParent->GetParentingType() >= 1) ) + wxLogError(wxT("wxPropertyGrid: Warning - item with name \"%s\" already exists."), + property->GetName().c_str()); +#endif + + // Make sure nothing is selected. + if ( propGrid && propGrid->m_selected ) + { + bool selRes = propGrid->ClearSelection(); + wxPG_CHECK_MSG_DBG( selRes, + -1, + wxT("failed to deselect a property (editor probably had invalid value)") ); + } + + property->m_y = -1; + + if ( scheduledParent ) + { + // Use parent's colours. + property->m_bgColIndex = scheduledParent->m_bgColIndex; + property->m_fgColIndex = scheduledParent->m_fgColIndex; + } + + // If in hideable adding mode, or if assigned parent is hideable, then + // make this one hideable. + if ( + ( scheduledParent && (scheduledParent->m_flags & wxPG_PROP_HIDEABLE) ) || + ( propGrid && (propGrid->m_iFlags & wxPG_FL_ADDING_HIDEABLES) ) + ) + property->SetFlag ( wxPG_PROP_HIDEABLE ); + + // Set custom image flag. + int custImgHeight = property->GetImageSize().y; + if ( custImgHeight < 0 /*|| custImgHeight > 1*/ ) + { + property->m_flags |= wxPG_PROP_CUSTOMIMAGE; + } + + if ( propGrid->GetWindowStyleFlag() & wxPG_LIMITED_EDITING ) + property->m_flags |= wxPG_PROP_NOEDITOR; + + if ( parenting < 1 ) + { + // This is not a category. + + wxASSERT_MSG( property->GetEditorClass(), wxT("Editor class not initialized!") ); + + // Depth. + // + unsigned char depth = 1; + if ( scheduledParent ) + { + depth = scheduledParent->m_depth; + if ( scheduledParent->GetParentingType() != PT_CAPTION ) + depth++; + } + property->m_depth = depth; + unsigned char greyDepth = depth; + + if ( scheduledParent ) + { + wxPropertyCategoryClass* pc; + + if ( scheduledParent->GetParentingType() >= PT_CAPTION ) + pc = (wxPropertyCategoryClass*)scheduledParent; + else + // This conditional compile is necessary to + // bypass some compiler bug. + pc = wxPropertyGrid::_GetPropertyCategory(scheduledParent); + + if ( pc ) + greyDepth = pc->GetDepth(); + else + greyDepth = scheduledParent->m_depthBgCol; + } + + property->m_depthBgCol = greyDepth; + + // Add children to propertywithchildren. + if ( parenting < PT_NONE ) + { + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)property; + + pwc->m_parentState = this; + + pwc->m_expanded = 0; // Properties with children are not expanded by default. + if ( propGrid && propGrid->GetWindowStyleFlag() & wxPG_HIDE_MARGIN ) + pwc->m_expanded = 1; // ...unless it cannot not be expanded. + + if ( pwc->GetCount() ) + { + pwc->PrepareSubProperties(); + } + + // + // If children were added prior to append, then this is considered + // a "fixed" parent (otherwise the PT_CUSTOMPROPERTY is set, see below, + // to mark it as customizable). + /*if ( pwc->GetCount() ) + { + pwc->PrepareSubProperties(); + } + else + { + pwc->m_parentingType = PT_CUSTOMPROPERTY; + }*/ + } + } + else + { + // This is a category. + + // depth + unsigned char depth = 1; + if ( scheduledParent ) + { + depth = scheduledParent->m_depth + 1; + } + property->m_depth = depth; + property->m_depthBgCol = depth; + + m_currentCategory = (wxPropertyCategoryClass*)property; + + wxPropertyCategoryClass* pc = (wxPropertyCategoryClass*)property; + pc->m_parentState = this; + + // Calculate text extent for caption item. + pc->CalculateTextExtent(propGrid,propGrid->GetCaptionFont()); + } + + return parenting; +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::BeginAddChildren( wxPGId id ) +{ + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) wxPGIdToPtr(id); + wxCHECK_RET( pwc, wxT("NULL property") ); + wxCHECK_RET( pwc->GetParentingType() == PT_FIXEDCHILDREN, wxT("only call on properties with fixed children") ); + pwc->m_parentingType = PT_CUSTOMPROPERTY; +} + +// ----------------------------------------------------------------------- + +void wxPropertyContainerMethods::EndAddChildren( wxPGId id ) +{ + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*) wxPGIdToPtr(id); + wxCHECK_RET( pwc, wxT("NULL property") ); + wxCHECK_RET( pwc->GetParentingType() == PT_CUSTOMPROPERTY, wxT("only call on properties for which BeginAddChildren was called prior") ); + pwc->m_parentingType = PT_FIXEDCHILDREN; +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::Append( wxPGProperty* property ) +{ + wxPropertyCategoryClass* cur_cat = m_currentCategory; + if ( property->GetParentingType() > 0 ) + cur_cat = (wxPropertyCategoryClass*) NULL; + + return DoInsert( cur_cat, -1, property ); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::DoInsert( wxPGPropertyWithChildren* parent, int index, wxPGProperty* property ) +{ + if ( !parent ) + parent = m_properties; + + wxPropertyGrid* propGrid = m_pPropGrid; + + wxCHECK_MSG( parent->GetParentingType() != PT_NONE, + wxNullProperty, + wxT("this parent cannot accomodate children") ); + + wxCHECK_MSG( parent->GetParentingType() != PT_FIXEDCHILDREN, + wxNullProperty, + wxT("when adding properties to fixed parents, use BeginAddChildren and EndAddChildren.") ); + + int parenting = PrepareToAddItem( property, (wxPropertyCategoryClass*)parent ); + + // This type of invalid parenting value indicates we should exit now, returning + // id of most recent category. + if ( parenting > PT_CAPTION ) + return wxPGIdGen(m_currentCategory); + + // Note that item must be added into current mode later. + + // If parent is wxParentProperty, just stick it in... + // If parent is root (m_properties), then... + // In categoric mode: Add as last item in m_abcArray (if not category). + // Add to given index in m_regularArray. + // In non-cat mode: Add as last item in m_regularArray. + // Add to given index in m_abcArray. + // If parent is category, then... + // 1) Add to given category in given index. + // 2) Add as last item in m_abcArray. + + int parents_parenting = parent->GetParentingType(); + if ( parents_parenting < 0 ) + { + // Parent is wxParentingProperty: Just stick it in... + parent->AddChild2( property, index ); + } + else + { + // Parent is Category or Root. + + if ( m_properties == &m_regularArray ) + { + // Categorized mode + + // Only add non-categories to m_abcArray. + if ( m_abcArray && parenting <= 0 ) + m_abcArray->AddChild2( property, -1, false ); + + // Add to current mode. + parent->AddChild2( property, index ); + + } + else + { + // Non-categorized mode. + + if ( parent != m_properties ) + // Parent is category. + parent->AddChild2( property, index, false ); + else + // Parent is root. + m_regularArray.AddChild2( property, -1, false ); + + // Add to current mode (no categories). + if ( parenting <= 0 ) + m_abcArray->AddChild2( property, index ); + } + } + + // category stuff + if ( parenting > PT_NONE ) + { + // This is a category caption item. + + // Last caption is not the bottom one (this info required by append) + m_lastCaptionBottomnest = 0; + } + + // Only add name to hashmap if parent is root or category + if ( parent->GetParentingType() >= PT_CAPTION && property->m_name.length() ) + m_dictName[property->m_name] = (void*) property; + + m_itemsAdded = 1; + + if ( propGrid ) + propGrid->m_bottomy = 0; // this signals y recalculation + + return wxPGIdGen(property); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridState::AppendIn( wxPGPropertyWithChildren* pwc, + const wxString& label, + const wxString& propname, + wxVariant& value ) +{ + wxPGProperty* p = wxPropertyContainerMethods:: + CreatePropertyByType(value.GetType(),label,propname); + + if ( p ) + { + p->GetValueTypePtr()->SetValueFromVariant(p,value); + return DoInsert(pwc,-1,p); + } + return wxPGIdGen((wxPGProperty*)NULL); +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::DoDelete( wxPGProperty* item ) +{ + wxCHECK_RET( item != &m_regularArray && item != m_abcArray, + wxT("wxPropertyGrid: Do not attempt to remove the root item.") ); + + size_t i; + int parenting = item->GetParentingType(); + unsigned int indinparent = item->GetIndexInParent(); + + wxPGPropertyWithChildren* pwc = (wxPGPropertyWithChildren*)item; + + wxCHECK_RET( item->GetParent()->GetParentingType() != -1, + wxT("wxPropertyGrid: Do not attempt to remove sub-properties.") ); + + if ( parenting > 0 ) + { + // deleting a category + + // erase category entries from the hash table + for ( i=0; iGetCount(); i++ ) + { + wxPGProperty* sp = pwc->Item( i ); + if ( sp->GetName().Len() ) m_dictName.erase( wxPGNameConv(sp->GetName()) ); + } + + if ( pwc == m_currentCategory ) + m_currentCategory = (wxPropertyCategoryClass*) NULL; + + if ( m_abcArray ) + { + // Remove children from non-categorized array. + for ( i=0; iGetCount(); i++ ) + { + wxPGProperty * p = pwc->Item( i ); + wxASSERT( p != NULL ); + if ( p->GetParentingType() <= PT_NONE ) + m_abcArray->m_children.Remove( (void*)p ); + } + + if ( IsInNonCatMode() ) + m_abcArray->FixIndexesOfChildren(); + } + } + + if ( !IsInNonCatMode() ) + { + // categorized mode - non-categorized array + + // Remove from non-cat array, but only if parent is in it + if ( parenting <= 0 && item->GetParent()->GetParentingType() == PT_CAPTION ) + { + if ( m_abcArray ) + { + m_abcArray->m_children.Remove( item ); + } + } + + // categorized mode - categorized array + item->m_parent->m_children.RemoveAt(indinparent); + item->m_parent->FixIndexesOfChildren(/*indinparent*/); + } + else + { + // non-categorized mode - categorized array + + // We need to find location of item. + wxPGPropertyWithChildren* cat_parent = &m_regularArray; + int cat_index = m_regularArray.GetCount(); + size_t i; + for ( i = 0; i < m_regularArray.GetCount(); i++ ) + { + wxPGProperty* p = m_regularArray.Item(i); + if ( p == item ) { cat_index = i; break; } + if ( p->GetParentingType() > 0 ) + { + int subind = ((wxPGPropertyWithChildren*)p)->Index(item); + if ( subind != wxNOT_FOUND ) + { + cat_parent = ((wxPGPropertyWithChildren*)p); + cat_index = subind; + break; + } + } + } + cat_parent->m_children.RemoveAt(cat_index); + + // non-categorized mode - non-categorized array + if ( parenting <= 0 ) + { + wxASSERT( item->m_parent == m_abcArray ); + item->m_parent->m_children.RemoveAt(indinparent); + item->m_parent->FixIndexesOfChildren(indinparent); + } + } + + if ( item->GetName().Len() ) m_dictName.erase( wxPGNameConv(item->GetName()) ); + +#ifdef __WXPYTHON__ + // For some reason, Py_DECREF always crashes, even though we make + // matching Py_INCREF call in propgrid_cbacks.cpp. Maybe refcount is decremented + // somewhere automatically? Unlikely though... + //if ( item->m_scriptObject ) + // Py_DECREF( item->m_scriptObject ); +#endif + + // We can actually delete it now + delete item; + + m_itemsAdded = 1; // Not a logical assignment (but required nonetheless). + + if ( this == m_pPropGrid->GetState() ) + { + //m_pPropGrid->m_clearThisMany = 1; + m_pPropGrid->m_bottomy = 0; // this signals y recalculation + } +} + +// ----------------------------------------------------------------------- +// wxPropertyGridState init etc. +// ----------------------------------------------------------------------- + +void wxPropertyGridState::InitNonCatMode() +{ + ITEM_ITERATION_DCAE_VARIABLES + + if ( !m_abcArray ) + { + m_abcArray = new wxPGRootPropertyClass(); + m_abcArray->SetParentState(this); + m_abcArray->m_expanded = wxPG_EXP_OF_COPYARRAY; + } + + // Must be called when FROM_STATE(m_properties) still points to regularArray. + wxPGPropertyWithChildren* oldProperties = m_properties; + + // Must use temp value in FROM_STATE(m_properties) for item iteration loop + // to run as expected. + m_properties = &m_regularArray; + + // Copy items. + ITEM_ITERATION_INIT_FROM_THE_TOP + + ITEM_ITERATION_DCAE_ISP_LOOP_BEGIN + + if ( parenting < 1 && + ( parent == m_properties || parent->GetParentingType() > 0 ) ) + { + + m_abcArray->AddChild2 ( p ); + p->m_parent = &FROM_STATE(m_regularArray); + } + //else wxLogDebug("OUT: %s",p->m_label.c_str()); + + ITEM_ITERATION_DCAE_ISP_LOOP_END + + m_properties = oldProperties; + +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridState::Clear() +{ + m_regularArray.Empty(); + if ( m_abcArray ) + m_abcArray->Empty(); + + m_dictName.clear(); + + m_currentCategory = (wxPropertyCategoryClass*) NULL; + m_lastCaptionBottomnest = 1; + m_itemsAdded = 0; + + m_selected = (wxPGProperty*) NULL; +} + +// ----------------------------------------------------------------------- + +wxPropertyGridState::wxPropertyGridState() +{ + m_pPropGrid = (wxPropertyGrid*) NULL; + m_regularArray.SetParentState(this); + m_properties = &m_regularArray; + m_abcArray = (wxPGRootPropertyClass*) NULL; + m_currentCategory = (wxPropertyCategoryClass*) NULL; + m_selected = (wxPGProperty*) NULL; + m_lastCaptionBottomnest = 1; + m_itemsAdded = 0; + m_anyModified = 0; +} + +// ----------------------------------------------------------------------- + +wxPropertyGridState::~wxPropertyGridState() +{ + delete m_abcArray; +} + +// ----------------------------------------------------------------------- +// wxPropertyGridPopulator +// ----------------------------------------------------------------------- + +void wxPropertyGridPopulator::Init( wxPropertyGrid* pg, wxPGId popRoot ) +{ + WX_PG_GLOBALS_LOCKER() + + m_propGrid = pg; + m_popRoot = popRoot; + wxPGGlobalVars->m_offline++; +} + +// ----------------------------------------------------------------------- + +wxPropertyGridPopulator::~wxPropertyGridPopulator() +{ + + // + // Free unused sets of choices + wxPGHashMapP2P::iterator it; + + for( it = m_dictIdChoices.begin(); it != m_dictIdChoices.end(); ++it ) + { + wxPGChoicesData* data = (wxPGChoicesData*) it->second; + data->m_refCount--; + if ( data->m_refCount < 1 ) + delete data; + } + + wxPGGlobalVars->m_offline--; +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridPopulator::HasChoices( wxPGChoicesId id ) const +{ + wxPGHashMapP2P::const_iterator it = m_dictIdChoices.find(id); + return ( it != m_dictIdChoices.end() ); +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridPopulator::BeginChildren() +{ + if ( wxPGIdIsOk(m_lastProperty) && + wxPGIdToPtr(m_lastProperty)->CanHaveExtraChildren() ) + { + wxLogDebug(wxT("New Parent: %s"),wxPGIdToPtr(m_lastProperty)->GetLabel().c_str()); + m_curParent = m_lastProperty; + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridPopulator::AddChoices(wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues) +{ +#ifdef __WXDEBUG__ + // Make sure the id is not used yet + wxPGHashMapP2P::iterator it = m_dictIdChoices.find(choicesId); + wxCHECK_RET( it == m_dictIdChoices.end(), + wxT("added set of choices to same id twice (use HasChoices if necessary)") ); +#endif + + wxCHECK_RET( choicesId != (wxPGChoicesId)0, + wxT("choicesId must not be 0/NULL")); + + wxPGChoices chs(choiceLabels,choiceValues); + wxPGChoicesData* data = chs.ExtractData(); + m_dictIdChoices[choicesId] = (void*) data; + + // Artifically reduce refcount to 0 (since nothing uses it yet) + //data->m_refCount = 0; + +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridPopulator::DoAppend(wxPGProperty* p, + const wxString& value, + const wxString& attributes, + wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues) +{ + wxASSERT( m_propGrid ); + + // Make sure m_curParent is ok + if ( !wxPGIdIsOk(m_curParent) ) + { + if ( !wxPGIdIsOk(m_popRoot) ) + m_popRoot = m_propGrid->GetRoot(); + m_curParent = m_popRoot; + } + + if ( p ) + { + + // Set choices + if ( choicesId ) + { + wxPGHashMapP2P::iterator it = m_dictIdChoices.find(choicesId); + + wxPGChoices chs; + + if ( it != m_dictIdChoices.end() ) + { + // Already found + wxPGChoicesData* foundData = (wxPGChoicesData*) it->second; + chs.AssignData(foundData); + } + else + { + chs.Set(choiceLabels,choiceValues); + m_dictIdChoices[choicesId] = (void*) chs.GetData(); + } + + p->SetChoices(chs); + + } + + // Value setter must be before append + if ( value.length() ) + { + p->SetValueFromString(value,wxPG_FULL_VALUE); + } + + // Set attributes + if ( attributes.length() ) + wxPropertyGrid::SetPropertyAttributes(p,attributes); + + // Append to grid + m_propGrid->AppendIn(m_curParent,p); + + m_lastProperty = p; + } + return wxPGIdGen(p); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridPopulator::AppendByClass(const wxString& classname, + const wxString& label, + const wxString& name, + const wxString& value, + const wxString& attributes, + wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues) +{ + wxPGProperty* p = m_propGrid->CreatePropertyByClass(classname,label,name); + return DoAppend(p,value,attributes,choicesId,choiceLabels,choiceValues); +} + +// ----------------------------------------------------------------------- + +wxPGId wxPropertyGridPopulator::AppendByType(const wxString& valuetype, + const wxString& label, + const wxString& name, + const wxString& value, + const wxString& attributes, + wxPGChoicesId choicesId, + const wxArrayString& choiceLabels, + const wxArrayInt& choiceValues) +{ + wxPGProperty* p = m_propGrid->CreatePropertyByType(valuetype,label,name); + return DoAppend(p,value,attributes,choicesId,choiceLabels,choiceValues); +} + +// ----------------------------------------------------------------------- diff --git a/assdraw/libpropgrid/props.cpp b/assdraw/libpropgrid/props.cpp new file mode 100644 index 000000000..80d788513 --- /dev/null +++ b/assdraw/libpropgrid/props.cpp @@ -0,0 +1,2716 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: props.cpp +// Purpose: Basic Property Classes +// Author: Jaakko Salli +// Modified by: +// Created: May-14-2004 +// RCS-ID: $Id: +// Copyright: (c) Jaakko Salli +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" + #include "wx/object.h" + #include "wx/hash.h" + #include "wx/string.h" + #include "wx/log.h" + #include "wx/event.h" + #include "wx/window.h" + #include "wx/panel.h" + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/dcmemory.h" + #include "wx/button.h" + #include "wx/pen.h" + #include "wx/brush.h" + #include "wx/cursor.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/msgdlg.h" + #include "wx/choice.h" + #include "wx/stattext.h" + #include "wx/scrolwin.h" + #include "wx/dirdlg.h" + #include "wx/combobox.h" + #include "wx/layout.h" + #include "wx/sizer.h" + #include "wx/textdlg.h" + #include "wx/filedlg.h" + #include "wx/statusbr.h" + #include "wx/intl.h" +#endif + +#include + +#include + +#include + + +#define wxPG_CUSTOM_IMAGE_WIDTH 20 // for wxColourProperty etc. + + +// ----------------------------------------------------------------------- +// wxStringProperty +// ----------------------------------------------------------------------- + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxStringProperty,wxBaseProperty, + wxString,const wxString&,TextCtrl) + +wxStringPropertyClass::wxStringPropertyClass( const wxString& label, + const wxString& name, + const wxString& value ) + : wxPGProperty(label,name) +{ + DoSetValue(value); +} + +wxStringPropertyClass::~wxStringPropertyClass() { } + +void wxStringPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToString(value); +} + +wxPGVariant wxStringPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +wxString wxStringPropertyClass::GetValueAsString( int argFlags ) const +{ + // If string is password and value is for visual purposes, + // then return asterisks instead the actual string. + if ( (m_flags & wxPG_PROP_PASSWORD) && !(argFlags & (wxPG_FULL_VALUE|wxPG_EDITABLE_VALUE)) ) + return wxString(wxChar('*'), m_value.Length()); + + return m_value; +} + +bool wxStringPropertyClass::SetValueFromString( const wxString& text, int ) +{ + if ( m_value != text ) + return StdValidationProcedure(text); + + return false; +} + +void wxStringPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_STRING_PASSWORD ) + { + m_flags &= ~(wxPG_PROP_PASSWORD); + if ( value.GetLong() ) m_flags |= wxPG_PROP_PASSWORD; + RecreateEditor(); + } +} + +// ----------------------------------------------------------------------- +// wxIntProperty +// ----------------------------------------------------------------------- + +wxPG_BEGIN_PROPERTY_CLASS_BODY(wxIntProperty,wxPGProperty,long,long) + WX_PG_DECLARE_BASIC_TYPE_METHODS() + virtual bool SetValueFromInt( long value, int flags ); +#if wxUSE_VALIDATORS + static wxValidator* GetClassValidator(); + virtual wxValidator* DoGetValidator() const; +#endif +wxPG_END_PROPERTY_CLASS_BODY() + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxIntProperty,wxBaseProperty, + long,long,TextCtrl) + +wxIntPropertyClass::wxIntPropertyClass( const wxString& label, const wxString& name, + long value ) : wxPGProperty(label,name) +{ + DoSetValue(value); +} + +wxIntPropertyClass::~wxIntPropertyClass() { } + +void wxIntPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToLong(value); +} + +wxPGVariant wxIntPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +wxString wxIntPropertyClass::GetValueAsString( int ) const +{ + return wxString::Format(wxT("%li"),m_value); +} + +bool wxIntPropertyClass::SetValueFromString( const wxString& text, int argFlags ) +{ + wxString s; + long value; + + if ( text.length() == 0 ) + { + SetValueToUnspecified(); + return true; + } + + // We know it is a number, but let's still check + // the return value. + if ( text.IsNumber() && text.ToLong( &value, 0 ) ) + { + if ( m_value != value ) + { + return StdValidationProcedure(value); + } + } + else if ( argFlags & wxPG_REPORT_ERROR ) + { + s.Printf( wxT("! %s: \"%s\" is not a number."), m_label.c_str(), text.c_str() ); + ShowError(s); + } + return false; +} + +bool wxIntPropertyClass::SetValueFromInt( long value, int WXUNUSED(flags) ) +{ + if ( m_value != value ) + { + m_value = value; + return true; + } + return false; +} + +#if wxUSE_VALIDATORS + +wxValidator* wxIntPropertyClass::GetClassValidator() +{ + WX_PG_DOGETVALIDATOR_ENTRY() + + // Atleast wxPython 2.6.2.1 required that the string argument is given + static wxString v; + wxTextValidator* validator = new wxTextValidator(wxFILTER_NUMERIC,&v); + + WX_PG_DOGETVALIDATOR_EXIT(validator) +} + +wxValidator* wxIntPropertyClass::DoGetValidator() const +{ + return GetClassValidator(); +} + +#endif + +// ----------------------------------------------------------------------- +// wxUIntProperty +// ----------------------------------------------------------------------- + + +#define wxPG_UINT_TEMPLATE_MAX 8 + +static const wxChar* gs_uintTemplates[wxPG_UINT_TEMPLATE_MAX] = { + wxT("%x"),wxT("0x%x"),wxT("$%x"), + wxT("%X"),wxT("0x%X"),wxT("$%X"), + wxT("%u"),wxT("%o") +}; + +wxPG_BEGIN_PROPERTY_CLASS_BODY(wxUIntProperty,wxBasePropertyClass,long,unsigned long) + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() + virtual bool SetValueFromInt ( long value, int flags ); +protected: + wxByte m_base; + wxByte m_realBase; // translated to 8,16,etc. + wxByte m_prefix; +wxPG_END_PROPERTY_CLASS_BODY() + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxUIntProperty,wxBaseProperty, + long,unsigned long,TextCtrl) + +wxUIntPropertyClass::wxUIntPropertyClass( const wxString& label, const wxString& name, + unsigned long value ) : wxBasePropertyClass(label,name) +{ + m_base = 6; // This is magic number for dec base (must be same as in setattribute) + m_realBase = 10; + m_prefix = wxPG_PREFIX_NONE; + + DoSetValue((long)value); +} + +wxUIntPropertyClass::~wxUIntPropertyClass() { } + +void wxUIntPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToLong(value); +} + +wxPGVariant wxUIntPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +wxString wxUIntPropertyClass::GetValueAsString( int ) const +{ + //return wxString::Format(wxPGGlobalVars->m_uintTemplate.c_str(),m_value); + + size_t index = m_base + m_prefix; + if ( index >= wxPG_UINT_TEMPLATE_MAX ) + index = wxPG_BASE_DEC; + + return wxString::Format(gs_uintTemplates[index],m_value); +} + +bool wxUIntPropertyClass::SetValueFromString( const wxString& text, int WXUNUSED(argFlags) ) +{ + //wxString s; + long unsigned value = 0; + + if ( text.length() == 0 ) + { + SetValueToUnspecified(); + return true; + } + + size_t start = 0; + if ( text.length() > 0 && !wxIsalnum(text[0]) ) + start++; + + wxString s = text.substr(start, text.length() - start); + bool res = s.ToULong(&value, (unsigned int)m_realBase); + + //wxChar *end; + //value = wxStrtoul(text.c_str() + ((size_t)start), &end, (unsigned int)m_realBase); + + if ( res && m_value != (long)value ) + { + return StdValidationProcedure((long)value); + } + /*} + else if ( argFlags & wxPG_REPORT_ERROR ) + { + s.Printf ( wxT("! %s: \"%s\" is not a number."), m_label.c_str(), text.c_str() ); + ShowError(s); + }*/ + return false; +} + +bool wxUIntPropertyClass::SetValueFromInt( long value, int WXUNUSED(flags) ) +{ + if ( m_value != value ) + { + m_value = value; + return true; + } + return false; +} + +void wxUIntPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_UINT_BASE ) + { + int val = value.GetLong(); + + m_realBase = (wxByte) val; + if ( m_realBase > 16 ) + m_realBase = 16; + + // + // Translate logical base to a template array index + m_base = 7; // oct + if ( val == wxPG_BASE_HEX ) + m_base = 3; + else if ( val == wxPG_BASE_DEC ) + m_base = 6; + else if ( val == wxPG_BASE_HEXL ) + m_base = 0; + } + else if ( id == wxPG_UINT_PREFIX ) + m_prefix = (wxByte) value.GetLong(); +} + +// ----------------------------------------------------------------------- +// wxFloatProperty +// ----------------------------------------------------------------------- + +wxPG_BEGIN_PROPERTY_CLASS_BODY(wxFloatProperty,wxPGProperty,double,double) + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() +protected: + int m_precision; +#if wxUSE_VALIDATORS + //static wxValidator* GetClassValidator (); + virtual wxValidator* DoGetValidator () const; +#endif +wxPG_END_PROPERTY_CLASS_BODY() + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFloatProperty,wxBaseProperty, + double,double,TextCtrl) + +wxFloatPropertyClass::wxFloatPropertyClass( const wxString& label, + const wxString& name, + double value ) + : wxPGProperty(label,name) +{ + m_precision = -1; + DoSetValue(value); +} + +wxFloatPropertyClass::~wxFloatPropertyClass() { } + +void wxFloatPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToDouble(value); +} + +wxPGVariant wxFloatPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +// This helper method provides standard way for floating point-using +// properties to convert values to string. +void wxPropertyGrid::DoubleToString(wxString& target, + double value, + int precision, + bool removeZeroes, + wxString* precTemplate) +{ + if ( precision >= 0 ) + { + wxString text1; + if (!precTemplate) + precTemplate = &text1; + + if ( !precTemplate->length() ) + { + *precTemplate = wxT("%."); + *precTemplate << wxString::Format( wxT("%i"), precision ); + *precTemplate << wxT('f'); + } + + target.Printf( precTemplate->c_str(), value ); + } + else + { + target.Printf( wxT("%f"), value ); + } + + if ( removeZeroes && precision != 0 && target.length() ) + { + // Remove excess zeroes (do not remove this code just yet, + // since sprintf can't do the same consistently across platforms). + wxString::const_iterator i = target.end() - 1; + size_t new_len = target.length() - 1; + + for ( ; i != target.begin(); i-- ) + { + if ( wxPGGetIterChar(target, i) != wxT('0') ) + break; + new_len--; + } + + wxChar cur_char = wxPGGetIterChar(target, i); + if ( cur_char != wxT('.') && cur_char != wxT(',') ) + new_len++; + + if ( new_len != target.length() ) + target.resize(new_len); + + /* + unsigned int cur_pos = target.length() - 1; + wxChar a; + a = target.GetChar( cur_pos ); + while ( a == wxT('0') && cur_pos > 0 ) + { + cur_pos--; + a = target.GetChar( cur_pos ); + } + + wxChar cur_char = target.GetChar( cur_pos ); + if ( cur_char != wxT('.') && cur_char != wxT(',') ) + cur_pos += 1; + + if ( cur_pos < target.length() ) + target.Truncate( cur_pos ); + */ + } +} + +wxString wxFloatPropertyClass::GetValueAsString( int argFlags ) const +{ + wxString text; + wxPropertyGrid::DoubleToString(text,m_value, + m_precision, + !(argFlags & wxPG_FULL_VALUE), + (wxString*) NULL); + return text; +} + +bool wxFloatPropertyClass::SetValueFromString( const wxString& text, int argFlags ) +{ + wxString s; + double value; + + if ( text.length() == 0 ) + { + SetValueToUnspecified(); + return true; + } + + bool res = text.ToDouble(&value); + if ( res ) + { + if ( m_value != value ) + { + m_value = value; + return true; + } + } + else if ( argFlags & wxPG_REPORT_ERROR ) + { + ShowError(wxString::Format( _("\"%s\" is not a floating-point number"), text.c_str() )); + } + return false; +} + +void wxFloatPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_FLOAT_PRECISION ) + { + m_precision = value.GetLong(); + } +} + +#if wxUSE_VALIDATORS + +wxValidator* wxFloatPropertyClass::DoGetValidator() const +{ + return wxIntPropertyClass::GetClassValidator(); +} + +#endif + +// ----------------------------------------------------------------------- +// wxBoolProperty +// ----------------------------------------------------------------------- + +wxPG_BEGIN_PROPERTY_CLASS_BODY2(wxBoolPropertyClass,wxPGProperty,bool,long,bool,class) + WX_PG_DECLARE_BASIC_TYPE_METHODS() + WX_PG_DECLARE_CHOICE_METHODS() + WX_PG_DECLARE_ATTRIBUTE_METHODS() +wxPG_END_PROPERTY_CLASS_BODY() + +// We cannot use standard WX_PG_IMPLEMENT_PROPERTY_CLASS macro, since +// there is a custom GetEditorClass. + +WX_PG_IMPLEMENT_CONSTFUNC(wxBoolProperty,bool) +WX_PG_IMPLEMENT_CLASSINFO(wxBoolProperty,wxBasePropertyClass) +wxPG_GETCLASSNAME_IMPLEMENTATION(wxBoolProperty) +wxPG_VALUETYPE_MSGVAL wxBoolPropertyClass::GetValueType() const { return wxPG_VALUETYPE(bool); } + +const wxChar* wxPG_ClassName_wxBoolProperty = wxBoolProperty_ClassName; + +const wxPGEditor* wxBoolPropertyClass::DoGetEditorClass() const +{ + // Select correct editor control. +#if wxPG_INCLUDE_CHECKBOX + if ( !(m_flags & wxPG_PROP_USE_CHECKBOX) ) + return wxPG_EDITOR(Choice); + return wxPG_EDITOR(CheckBox); +#else + return wxPG_EDITOR(Choice); +#endif +} + +wxBoolPropertyClass::wxBoolPropertyClass( const wxString& label, const wxString& name, bool value ) : + wxPGProperty(label,name) +{ + int useVal; + if ( value ) useVal = 1; + else useVal = 0; + DoSetValue((long)useVal); + + m_flags |= wxPG_PROP_USE_DCC; +} + +wxBoolPropertyClass::~wxBoolPropertyClass() { } + +void wxBoolPropertyClass::DoSetValue( wxPGVariant value ) +{ + long v = wxPGVariantToLong(value); + if ( v == 2 ) + SetValueToUnspecified(); + else if ( v != 0 ) + m_value = 1; + else + m_value = 0; +} + +wxPGVariant wxBoolPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +wxString wxBoolPropertyClass::GetValueAsString( int argFlags ) const +{ + if ( !(argFlags & wxPG_FULL_VALUE) ) + { + return wxPGGlobalVars->m_boolChoices[m_value]; + } + wxString text; + + if (m_value) text = wxT("true"); + else text = wxT("false"); + + return text; +} + +int wxBoolPropertyClass::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) +{ + if ( choiceinfo ) + { + // 3 choice mode (ie. true, false, unspecified) does not work well (yet). + //choiceinfo->m_itemCount = wxPGGlobalVars->m_numBoolChoices; + choiceinfo->m_itemCount = 2; + choiceinfo->m_arrWxString = wxPGGlobalVars->m_boolChoices; + } + return m_value; +} + +bool wxBoolPropertyClass::SetValueFromString( const wxString& text, int /*argFlags*/ ) +{ + int value = 0; + if ( text.CmpNoCase(wxPGGlobalVars->m_boolChoices[1]) == 0 || text.CmpNoCase(wxT("true")) == 0 ) + value = 1; + + if ( text.length() == 0 ) + { + SetValueToUnspecified(); + return true; + } + + if ( (m_value && !value) || (!m_value && value) ) + { + DoSetValue( (long) value ); + return true; + } + /* + else if ( argFlags & wxPG_REPORT_ERROR ) + { + wxLogError ( wxT("Property %s: \"%s\" is not a boolean value (True and False are valid)."), m_label.c_str(), text.c_str() ); + } + */ + return false; +} + +bool wxBoolPropertyClass::SetValueFromInt( long value, int ) +{ + if ( value != 0 ) value = 1; + + if ( (m_value && !value) || (!m_value && value) ) + { + // (wxPG_BOOLPROP_VAL_INTERNAL_LONG) + m_value = value; + return true; + } + return false; +} + +void wxBoolPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + int ival = value.GetLong(); +#if wxPG_INCLUDE_CHECKBOX + if ( id == wxPG_BOOL_USE_CHECKBOX ) + { + if ( ival ) + m_flags |= wxPG_PROP_USE_CHECKBOX; + else + m_flags &= ~(wxPG_PROP_USE_CHECKBOX); + } + //else +#endif + if ( id == wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING ) + { + if ( ival ) + m_flags |= wxPG_PROP_USE_DCC; + else + m_flags &= ~(wxPG_PROP_USE_DCC); + } +} + +// ----------------------------------------------------------------------- +// wxBaseEnumPropertyClass +// ----------------------------------------------------------------------- + +// Class body is in propdev.h. + +wxBaseEnumPropertyClass::wxBaseEnumPropertyClass( const wxString& label, const wxString& name ) + : wxPGProperty(label,name) +{ +} + +/** If has values array, then returns number at index with value - + otherwise just returns the value. +*/ +int wxBaseEnumPropertyClass::GetIndexForValue( int value ) const +{ + return value; +} + +void wxBaseEnumPropertyClass::DoSetValue( wxPGVariant value ) +{ + int intval = (int) value.GetLong(); + m_index = GetIndexForValue(intval); +} + +wxPGVariant wxBaseEnumPropertyClass::DoGetValue() const +{ + if ( m_index < 0 ) + return wxPGVariant((long)-1); + + int val; + GetEntry(m_index,&val); + + return wxPGVariantCreator(val); +} + +wxString wxBaseEnumPropertyClass::GetValueAsString( int ) const +{ + if ( m_index >= 0 ) + { + int unused_val; + const wxString* pstr = GetEntry( m_index, &unused_val ); + + if ( pstr ) + return *pstr; + } + return wxEmptyString; +} + +bool wxBaseEnumPropertyClass::SetValueFromString ( const wxString& text, int WXUNUSED(argFlags) ) +{ + size_t i = 0; + const wxString* entry_label; + int entry_value; + int use_index = -1; + long use_value = 0; + + entry_label = GetEntry(i,&entry_value); + while ( entry_label ) + { + if ( text.CmpNoCase(*entry_label) == 0 ) + { + use_index = (int)i; + use_value = (long)entry_value; + break; + } + + i++; + entry_label = GetEntry(i,&entry_value); + } + + if ( m_index != use_index ) + { + if ( use_index != -1 ) + // FIXME: Why can't this be virtual call? + wxBaseEnumPropertyClass::DoSetValue ( use_value ); + else + m_index = -1; + + return true; + } + /*} + else if ( argFlags & wxPG_REPORT_ERROR ) + { + wxString s; + s.Printf ( wxT("\"%s\" was not among valid choices."), text.c_str() ); + ShowError(s); + }*/ + return false; +} + +bool wxBaseEnumPropertyClass::SetValueFromInt ( long value, int argFlags ) +{ + if ( argFlags & wxPG_FULL_VALUE ) + { + DoSetValue(value); + return true; + } + else + { + if ( m_index != value ) + { + m_index = value; + return true; + } + } + return false; +} + +// ----------------------------------------------------------------------- +// wxEnumProperty +// ----------------------------------------------------------------------- + +// Class body is in propdev.h. + +wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, int value ) +{ + return new wxEnumPropertyClass (label,name,labels,values,value); +} + +wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, int value ) +{ + return new wxEnumPropertyClass(label,name,labels,values,value); +} + +wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, int value ) +{ + return new wxEnumPropertyClass (label,name,labels,*((const wxArrayInt*)NULL),value); +} + +wxPGProperty* wxEnumProperty( const wxString& label, const wxString& name, + wxPGChoices& choices, int value ) +{ + return new wxEnumPropertyClass (label,name,choices,value); +} + +WX_PG_IMPLEMENT_CLASSINFO(wxEnumProperty,wxBasePropertyClass) + +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEnumProperty,long,Choice) + +wxEnumPropertyClass::wxEnumPropertyClass ( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, int value ) : wxBaseEnumPropertyClass(label,name) +{ + m_index = 0; + + if ( labels ) + { + m_choices.Add(labels,values); + + if ( GetItemCount() ) + wxEnumPropertyClass::DoSetValue( (long)value ); + } +} + +wxEnumPropertyClass::wxEnumPropertyClass ( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, wxPGChoices* choicesCache, int value ) + : wxBaseEnumPropertyClass(label,name) +{ + m_index = 0; + + wxASSERT( choicesCache ); + + if ( choicesCache->IsOk() ) + { + m_choices.Assign( *choicesCache ); + } + else if ( labels ) + { + m_choices.Add(labels,values); + + if ( GetItemCount() ) + wxEnumPropertyClass::DoSetValue( (long)value ); + } +} + +wxEnumPropertyClass::wxEnumPropertyClass ( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, int value ) : wxBaseEnumPropertyClass(label,name) +{ + m_index = 0; + + if ( &labels ) + { + wxPGChoices choices(labels,values); + m_choices = choices.ExtractData(); + + if ( GetItemCount() ) + wxEnumPropertyClass::DoSetValue( (long)value ); + } +} + +wxEnumPropertyClass::wxEnumPropertyClass ( const wxString& label, const wxString& name, + wxPGChoices& choices, int value ) + : wxBaseEnumPropertyClass(label,name) +{ + m_choices.Assign( choices ); + + if ( GetItemCount() ) + wxEnumPropertyClass::DoSetValue( (long)value ); +} + +int wxEnumPropertyClass::GetIndexForValue( int value ) const +{ + if ( !m_choices.IsOk() ) + return -1; + + const wxArrayInt& arrValues = m_choices.GetValues(); + + if ( arrValues.GetCount() ) + { + int intval = arrValues.Index(value); + + // TODO: Use real default instead of 0. + if ( intval < 0 ) + intval = 0; + + return intval; + } + return value; +} + +wxEnumPropertyClass::~wxEnumPropertyClass () +{ +} + +const wxString* wxEnumPropertyClass::GetEntry( size_t index, int* pvalue ) const +{ + if ( m_choices.IsOk() && index < m_choices.GetCount() ) + { + const wxArrayInt& arrValues = m_choices.GetValues(); + + int value = (int)index; + if ( arrValues.GetCount() ) + value = arrValues[index]; + + *pvalue = value; + + return &m_choices.GetLabel(index); + } + return (const wxString*) NULL; +} + +int wxEnumPropertyClass::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) +{ + if ( choiceinfo ) + { + if ( !(m_flags & wxPG_PROP_STATIC_CHOICES) ) + choiceinfo->m_choices = &m_choices; + + if ( !m_choices.IsOk() ) + return -1; + + choiceinfo->m_itemCount = m_choices.GetCount(); + if ( m_choices.GetCount() ) + choiceinfo->m_arrWxString = (wxString*)&m_choices.GetLabel(0); + } + + if ( !m_choices.IsOk() ) + return -1; + + return m_index; +} + +// ----------------------------------------------------------------------- +// wxEditEnumProperty +// ----------------------------------------------------------------------- + +class wxEditEnumPropertyClass : public wxEnumPropertyClass +{ + WX_PG_DECLARE_PROPERTY_CLASS() +public: + + wxEditEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, const wxString& value ); + wxEditEnumPropertyClass( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, const wxString& value ); + wxEditEnumPropertyClass( const wxString& label, const wxString& name, + wxPGChoices& choices, const wxString& value ); + + // Special constructor for caching choices (used by derived class) + wxEditEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, wxPGChoices* choicesCache, const wxString& value ); + + WX_PG_DECLARE_BASIC_TYPE_METHODS() + + int GetChoiceInfo( wxPGChoiceInfo* choiceinfo ); + + virtual ~wxEditEnumPropertyClass (); + +protected: + wxString m_value_wxString; +}; + + +wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, const wxString& value ) +{ + return new wxEditEnumPropertyClass(label,name,labels,values,value); +} + +wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, const wxString& value ) +{ + return new wxEditEnumPropertyClass(label,name,labels,values,value); +} + +wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxString& value ) +{ + return new wxEditEnumPropertyClass(label,name,labels,*((const wxArrayInt*)NULL),value); +} + +wxPGProperty* wxEditEnumProperty( const wxString& label, const wxString& name, + wxPGChoices& choices, const wxString& value ) +{ + return new wxEditEnumPropertyClass(label,name,choices,value); +} + +WX_PG_IMPLEMENT_CLASSINFO(wxEditEnumProperty,wxBasePropertyClass) + +WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxEditEnumProperty,wxString,ComboBox) + +wxEditEnumPropertyClass::wxEditEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, const wxString& value ) + : wxEnumPropertyClass(label,name,labels,values,0) +{ + wxEditEnumPropertyClass::DoSetValue( value ); +} + +wxEditEnumPropertyClass::wxEditEnumPropertyClass( const wxString& label, const wxString& name, const wxChar** labels, + const long* values, wxPGChoices* choicesCache, const wxString& value ) + : wxEnumPropertyClass(label,name,labels,values,choicesCache,0) +{ + wxEditEnumPropertyClass::DoSetValue( value ); +} + +wxEditEnumPropertyClass::wxEditEnumPropertyClass( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, const wxString& value ) + : wxEnumPropertyClass(label,name,labels,values,0) +{ + wxEditEnumPropertyClass::DoSetValue( value ); +} + +wxEditEnumPropertyClass::wxEditEnumPropertyClass( const wxString& label, const wxString& name, + wxPGChoices& choices, const wxString& value ) + : wxEnumPropertyClass(label,name,choices,0) +{ + wxEditEnumPropertyClass::DoSetValue( value ); +} + +wxEditEnumPropertyClass::~wxEditEnumPropertyClass() +{ +} + +void wxEditEnumPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value_wxString = wxPGVariantToString(value); +} + +wxPGVariant wxEditEnumPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value_wxString); +} + +wxString wxEditEnumPropertyClass::GetValueAsString( int ) const +{ + return m_value_wxString; +} + +bool wxEditEnumPropertyClass::SetValueFromString( const wxString& text, int ) +{ + if ( m_value_wxString != text ) + return StdValidationProcedure(text); + + return false; +} + +int wxEditEnumPropertyClass::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) +{ + wxEnumPropertyClass::GetChoiceInfo(choiceinfo); + + // However, select index using the current value + wxPGChoices& choices = m_choices; + const wxString& value = m_value_wxString; + int index = -1; + unsigned int k; + + for ( k=0; kGetParentState(); parent = parent->GetParent(); } + wxASSERT( state ); + + if ( state ) + { + wxPGProperty* selected = state->GetSelection(); + if ( selected ) + { + if ( selected->GetParent() == this ) + oldSel = selected->GetArrIndex(); + else if ( selected == this ) + oldSel = -2; + } + } + state->ClearSelection(); + } + + // Delete old children + for ( i=0; im_autoGetTranslation ) + { + bool_prop = wxBoolProperty( ::wxGetTranslation ( GetLabel(i) ), wxEmptyString, child_val ); + } + else + #endif + { + bool_prop = wxBoolProperty( GetLabel(i), wxEmptyString, child_val ); + } + AddChild(bool_prop); + } + + m_oldChoicesData = m_choices.GetDataPtr(); + } + + if ( prevChildCount ) + SubPropsChanged(oldSel); +} + +wxFlagsPropertyClass::wxFlagsPropertyClass ( const wxString& label, const wxString& name, + const wxChar** labels, const long* values, long value ) : wxPGPropertyWithChildren(label,name) +{ + + m_value = 0; + m_oldChoicesData = (wxPGChoicesData*) NULL; + + if ( labels ) + { + m_choices.Set(labels,values); + + wxASSERT ( GetItemCount() ); + + DoSetValue( value ); + } +} + +wxFlagsPropertyClass::wxFlagsPropertyClass ( const wxString& label, const wxString& name, + const wxArrayString& labels, const wxArrayInt& values, int value ) + : wxPGPropertyWithChildren(label,name) +{ + + m_value = 0; + m_oldChoicesData = (wxPGChoicesData*) NULL; + + if ( &labels ) + { + m_choices.Set(labels,values); + + wxASSERT( GetItemCount() ); + + DoSetValue( (long)value ); + } +} + +wxFlagsPropertyClass::wxFlagsPropertyClass ( const wxString& label, const wxString& name, + wxPGChoices& choices, long value ) + : wxPGPropertyWithChildren(label,name) +{ + m_oldChoicesData = (wxPGChoicesData*) NULL; + + m_choices.Assign(choices); + + wxASSERT ( GetItemCount() ); + + DoSetValue( value ); +} + +wxFlagsPropertyClass::~wxFlagsPropertyClass () +{ + //wxPGUnRefChoices(m_choices); +} + +void wxFlagsPropertyClass::DoSetValue ( wxPGVariant value ) +{ + if ( !m_choices.IsOk() || !GetItemCount() ) + { + m_value = 0; + return; + } + + long val = value.GetLong(); + + long full_flags = 0; + + // normalize the value (i.e. remove extra flags) + unsigned int i; + const wxArrayInt& values = GetValues(); + if ( values.GetCount() ) + { + for ( i = 0; i < GetItemCount(); i++ ) + full_flags |= values[i]; + } + else + { + for ( i = 0; i < GetItemCount(); i++ ) + full_flags |= (1< 1 ) + text.Truncate ( text.Len() - 2 ); + + return text; +} + +// Translate string into flag tokens +bool wxFlagsPropertyClass::SetValueFromString ( const wxString& text, int ) +{ + if ( !m_choices.IsOk() || !GetItemCount() ) + return false; + + long new_flags = 0; + + // semicolons are no longer valid delimeters + WX_PG_TOKENIZER1_BEGIN(text,wxT(',')) + + if ( token.length() ) + { + // Determine which one it is + long bit = IdToBit( token ); + + if ( bit != -1 ) + { + // Changed? + new_flags |= bit; + } + else + { + // Unknown identifier + wxString s; + s.Printf ( wxT("! %s: Unknown flag identifier \"%s\""), m_label.c_str(), token.c_str() ); + ShowError(s); + } + } + + WX_PG_TOKENIZER1_END() + + if ( new_flags != m_value ) + { + // Set child modified states + unsigned int i; + const wxArrayInt& values = GetValues(); + if ( values.GetCount() ) + for ( i = 0; i < GetItemCount(); i++ ) + { + long flag = values[i]; + if ( (new_flags & flag) != (m_value & flag) ) + ((wxPGProperty*)m_children.Item( i ))->SetFlag ( wxPG_PROP_MODIFIED ); + } + else + for ( i = 0; i < GetItemCount(); i++ ) + { + long flag = (1<SetFlag ( wxPG_PROP_MODIFIED ); + } + + DoSetValue ( new_flags ); + + return TRUE; + } + + return FALSE; +} + +// Converts string id to a relevant bit. +long wxFlagsPropertyClass::IdToBit ( const wxString& id ) const +{ + unsigned int i; + const wxArrayInt& values = GetValues(); + for ( i = 0; i < GetItemCount(); i++ ) + { +#if wxCHECK_VERSION(2,9,0) + const wxString ptr = GetLabel(i); +#else + const wxChar* ptr = GetLabel(i); +#endif + if ( id == ptr ) + { + //*pindex = i; + if ( values.GetCount() ) + return values[i]; + return (1<DoSetValue ( ((long)((flags & values[i])?TRUE:FALSE)) ); + else + for ( i = 0; i < GetItemCount(); i++ ) + Item(i)->DoSetValue ( ((long)((flags & (1<GetParent() ); + + const wxArrayInt& values = GetValues(); + long val = p->DoGetValue().GetLong(); // bypass type checking + unsigned int iip = p->GetIndexInParent(); + unsigned long vi = (1<m_choices = &m_choices; + return -1; +} + +// ----------------------------------------------------------------------- +// wxDirProperty +// ----------------------------------------------------------------------- + + +class wxDirPropertyClass : public wxLongStringPropertyClass +{ + WX_PG_DECLARE_DERIVED_PROPERTY_CLASS() +public: + wxDirPropertyClass( const wxString& name, const wxString& label, const wxString& value ); + virtual ~wxDirPropertyClass(); + + WX_PG_DECLARE_ATTRIBUTE_METHODS() + WX_PG_DECLARE_VALIDATOR_METHODS() + + virtual bool OnButtonClick ( wxPropertyGrid* propGrid, wxString& value ); + +protected: + wxString m_dlgMessage; +}; + + +WX_PG_IMPLEMENT_DERIVED_PROPERTY_CLASS(wxDirProperty,wxLongStringProperty,const wxString&) + +wxDirPropertyClass::wxDirPropertyClass( const wxString& name, const wxString& label, const wxString& value ) + : wxLongStringPropertyClass(name,label,value) +{ + m_flags |= wxPG_NO_ESCAPE; +} +wxDirPropertyClass::~wxDirPropertyClass() { } + +#if wxUSE_VALIDATORS + +wxValidator* wxDirPropertyClass::DoGetValidator() const +{ + return wxFilePropertyClass::GetClassValidator(); +} + +#endif + +bool wxDirPropertyClass::OnButtonClick( wxPropertyGrid* propGrid, wxString& value ) +{ + wxSize dlg_sz(300,400); + + wxDirDialog dlg( propGrid, + m_dlgMessage.length() ? m_dlgMessage : wxString(_("Choose a directory:")), + value, + 0, +#if !wxPG_SMALL_SCREEN + propGrid->GetGoodEditorDialogPosition(this,dlg_sz), + dlg_sz ); +#else + wxDefaultPosition, + wxDefaultSize ); +#endif + + if ( dlg.ShowModal() == wxID_OK ) + { + value = dlg.GetPath(); + return true; + } + return false; +} + +void wxDirPropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_DIR_DIALOG_MESSAGE ) + { + m_dlgMessage = value.GetString(); + } +} + +// ----------------------------------------------------------------------- +// wxFileProperty +// ----------------------------------------------------------------------- + +// Class body is in propdev.h. + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxFileProperty,wxBaseProperty, + wxString,const wxString&,TextCtrlAndButton) + +wxFilePropertyClass::wxFilePropertyClass( const wxString& label, const wxString& name, + const wxString& value ) : wxPGProperty(label,name) +{ + m_wildcard = _("All files (*.*)|*.*"); + m_flags |= wxPG_PROP_SHOW_FULL_FILENAME; + m_indFilter = -1; + + DoSetValue(value); +} + +wxFilePropertyClass::~wxFilePropertyClass() {} + +#if wxUSE_VALIDATORS + +wxValidator* wxFilePropertyClass::GetClassValidator() +{ + WX_PG_DOGETVALIDATOR_ENTRY() + + // Atleast wxPython 2.6.2.1 required that the string argument is given + static wxString v; + wxTextValidator* validator = new wxTextValidator(wxFILTER_EXCLUDE_CHAR_LIST,&v); + + wxArrayString exChars; + exChars.Add(wxT("?")); + exChars.Add(wxT("*")); + exChars.Add(wxT("|")); + exChars.Add(wxT("<")); + exChars.Add(wxT(">")); + exChars.Add(wxT("\"")); + + validator->SetExcludes(exChars); + + WX_PG_DOGETVALIDATOR_EXIT(validator) +} + +wxValidator* wxFilePropertyClass::DoGetValidator() const +{ + return GetClassValidator(); +} + +#endif + +void wxFilePropertyClass::DoSetValue( wxPGVariant value ) +{ + const wxString& str = wxPGVariantToString(value); + + m_fnstr = str; + m_filename = str; + + if ( !m_filename.HasName() ) + { + m_fnstr = wxEmptyString; + m_filename.Clear(); + } + + // Find index for extension. + if ( m_indFilter < 0 && m_fnstr.length() ) + { + wxString ext = m_filename.GetExt(); + int curind = 0; + size_t pos = 0; + size_t len = m_wildcard.length(); + + pos = m_wildcard.find(wxT("|"), pos); + while ( pos != wxString::npos && pos < (len-3) ) + { + size_t ext_begin = pos + 3; + + pos = m_wildcard.find(wxT("|"), ext_begin); + if ( pos == wxString::npos ) + pos = len; + wxString found_ext = m_wildcard.substr(ext_begin, pos-ext_begin); + + if ( found_ext.length() > 0 ) + { + if ( found_ext[0] == wxT('*') ) + { + m_indFilter = curind; + break; + } + if ( ext.CmpNoCase(found_ext) == 0 ) + { + m_indFilter = curind; + break; + } + } + + if ( pos != len ) + pos = m_wildcard.find(wxT("|"), pos+1); + + curind++; + } + + /* + wxChar a = wxT(' '); + const wxChar* p = m_wildcard.c_str(); + wxString ext = m_filename.GetExt(); + int curind = 0; + do + { + while ( a && a != wxT('|') ) { a = *p; p++; } + if ( !a ) break; + + a = *p; + p++; + if ( !a ) break; + a = *p; + p++; + + const wxChar* ext_begin = p; + + if ( *ext_begin == wxT('*') ) + { + m_indFilter = curind; + break; + } + + while ( a && a != '|' ) { a = *p; p++; } + + a = wxT(' '); + + int count = p-ext_begin-1; + if ( count > 0 ) + { + wxASSERT( count < 32 ); + wxString found_ext = m_wildcard.Mid(ext_begin-m_wildcard.c_str(),count); + + if ( ext.CmpNoCase(found_ext) == 0 ) + { + m_indFilter = curind; + break; + } + } + + curind++; + + } while ( a ); + */ + } +} + +wxPGVariant wxFilePropertyClass::DoGetValue() const +{ + return wxPGVariant(m_fnstr); +} + +wxString wxFilePropertyClass::GetValueAsString( int argFlags ) const +{ + if ( argFlags & wxPG_FULL_VALUE ) + { + return m_filename.GetFullPath(); + } + else if ( m_flags & wxPG_PROP_SHOW_FULL_FILENAME ) + { + if ( m_basePath.Length() ) + { + wxFileName fn2(m_filename); + fn2.MakeRelativeTo(m_basePath); + return fn2.GetFullPath(); + } + return m_filename.GetFullPath(); + } + + return m_filename.GetFullName(); +} + +bool wxFilePropertyClass::OnEvent( wxPropertyGrid* propGrid, + wxWindow* primary, + wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + // If text in control is changed, then update it to value. + PrepareValueForDialogEditing(propGrid); + + wxString path; + path = m_filename.GetPath(); + + wxFileDialog dlg( propGrid, + m_dlgTitle.length() ? m_dlgTitle : wxString(_("Choose a file")), + !m_initialPath.empty() ? m_initialPath : m_filename.GetPath(), + wxEmptyString, + m_wildcard, + 0, + wxDefaultPosition ); + + if ( m_indFilter >= 0 ) + dlg.SetFilterIndex( m_indFilter ); + + if ( dlg.ShowModal() == wxID_OK ) + { + m_indFilter = dlg.GetFilterIndex(); + wxString path = dlg.GetPath(); + SetValueFromString( path, wxPG_FULL_VALUE ); + if ( primary ) + GetEditorClass()->SetControlStringValue( primary, GetValueAsString(0) ); + return true; + } + } + return false; +} + +bool wxFilePropertyClass::SetValueFromString( const wxString& text, int argFlags ) +{ + if ( (m_flags & wxPG_PROP_SHOW_FULL_FILENAME) || (argFlags & wxPG_FULL_VALUE) ) + { + if ( m_filename != text ) + { + return StdValidationProcedure( text ); + } + } + else + { + if ( m_filename.GetFullName() != text ) + { + wxFileName fn = m_filename; + fn.SetFullName(text); + wxString val = fn.GetFullPath(); + return StdValidationProcedure( val ); + } + } + + return false; +} + +void wxFilePropertyClass::SetAttribute( int id, wxVariant& value ) +{ + if ( id == wxPG_FILE_SHOW_FULL_PATH ) + { + if ( value.GetLong() ) + m_flags |= wxPG_PROP_SHOW_FULL_FILENAME; + else + m_flags &= ~(wxPG_PROP_SHOW_FULL_FILENAME); + } + else if ( id == wxPG_FILE_WILDCARD ) + { + m_wildcard = value.GetString(); + } + else if ( id == wxPG_FILE_SHOW_RELATIVE_PATH ) + { + m_basePath = value.GetString(); + } + else if ( id == wxPG_FILE_INITIAL_PATH ) + { + m_initialPath = value.GetString(); + } + else if ( id == wxPG_FILE_DIALOG_TITLE ) + { + m_dlgTitle = value.GetString(); + } +} + +// ----------------------------------------------------------------------- +// wxLongStringProperty +// ----------------------------------------------------------------------- + +// Class body is in propdev.h. + + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxLongStringProperty,wxBaseProperty, + wxString,const wxString&,TextCtrlAndButton) + +wxLongStringPropertyClass::wxLongStringPropertyClass( const wxString& label, const wxString& name, + const wxString& value ) : wxBasePropertyClass(label,name) +{ + DoSetValue(value); +} + +wxLongStringPropertyClass::~wxLongStringPropertyClass() {} + +void wxLongStringPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToString(value); +} + +wxPGVariant wxLongStringPropertyClass::DoGetValue() const +{ + return wxPGVariant(m_value); +} + +wxString wxLongStringPropertyClass::GetValueAsString( int ) const +{ + return m_value; +} + +bool wxLongStringPropertyClass::OnEvent( wxPropertyGrid* propGrid, wxWindow* primary, + wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + // Update the value + PrepareValueForDialogEditing(propGrid); + + wxString val1 = GetValueAsString(0); + wxString val_orig = val1; + + wxString value; + if ( !(m_flags & wxPG_PROP_NO_ESCAPE) ) + wxPropertyGrid::ExpandEscapeSequences(value,val1); + else + value = wxString(val1); + + // Run editor dialog. + if ( OnButtonClick(propGrid,value) ) + { + if ( !(m_flags & wxPG_PROP_NO_ESCAPE) ) + wxPropertyGrid::CreateEscapeSequences(val1,value); + else + val1 = value; + + if ( val1 != val_orig ) + { + SetValueFromString ( val1, 0 ); + UpdateControl ( primary ); + return true; + } + } + } + return false; +} + +bool wxLongStringPropertyClass::OnButtonClick( wxPropertyGrid* propGrid, wxString& value ) +{ + // launch editor dialog + wxDialog* dlg = new wxDialog(propGrid,-1,m_label,wxDefaultPosition,wxDefaultSize, + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxCLIP_CHILDREN); + + dlg->SetFont(propGrid->GetFont()); // To allow entering chars of the same set as the propGrid + + // Multi-line text editor dialog. +#if !wxPG_SMALL_SCREEN + const int spacing = 8; +#else + const int spacing = 4; +#endif + wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL ); + wxTextCtrl* ed = new wxTextCtrl(dlg,11,value, + wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE); + + rowsizer->Add( ed, 1, wxEXPAND|wxALL, spacing ); + topsizer->Add( rowsizer, 1, wxEXPAND, 0 ); + rowsizer = new wxBoxSizer( wxHORIZONTAL ); + const int but_sz_flags = + wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT; + rowsizer->Add( new wxButton(dlg,wxID_OK,_("Ok")), + 0, but_sz_flags, spacing ); + rowsizer->Add( new wxButton(dlg,wxID_CANCEL,_("Cancel")), + 0, but_sz_flags, spacing ); + topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 ); + + dlg->SetSizer( topsizer ); + topsizer->SetSizeHints( dlg ); + +#if !wxPG_SMALL_SCREEN + dlg->SetSize(400,300); + + dlg->Move( propGrid->GetGoodEditorDialogPosition(this,dlg->GetSize()) ); +#endif + + int res = dlg->ShowModal(); + + if ( res == wxID_OK ) + { + value = ed->GetValue(); + dlg->Destroy(); + return true; + } + dlg->Destroy(); + return false; +} + +bool wxLongStringPropertyClass::SetValueFromString( const wxString& text, int ) +{ + if ( m_value != text ) + { + DoSetValue ( text ); + return true; + } + return false; +} + +// ----------------------------------------------------------------------- +// wxArrayEditorDialog +// ----------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(wxArrayEditorDialog, wxDialog) + EVT_IDLE(wxArrayEditorDialog::OnIdle) + EVT_LISTBOX(24, wxArrayEditorDialog::OnListBoxClick) + EVT_TEXT_ENTER(21, wxArrayEditorDialog::OnAddClick) + EVT_BUTTON(22, wxArrayEditorDialog::OnAddClick) + EVT_BUTTON(23, wxArrayEditorDialog::OnDeleteClick) + EVT_BUTTON(25, wxArrayEditorDialog::OnUpClick) + EVT_BUTTON(26, wxArrayEditorDialog::OnDownClick) + EVT_BUTTON(27, wxArrayEditorDialog::OnUpdateClick) + //EVT_BUTTON(28, wxArrayEditorDialog::OnCustomEditClick) +END_EVENT_TABLE() + +IMPLEMENT_ABSTRACT_CLASS(wxArrayEditorDialog, wxDialog) + +#include + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnIdle(wxIdleEvent& event) +{ + // + // Do control focus detection here. + // + + wxWindow* focused = FindFocus(); + + // This strange focus thing is a workaround for wxGTK wxListBox focus + // reporting bug. + if ( m_curFocus == 0 && focused != m_edValue && + focused != m_butAdd && focused != m_butUpdate && + m_lbStrings->GetSelection() >= 0 ) + { + //wxLogDebug(wxT("Focused: %s"),focused?focused->GetClassInfo()->GetClassName():wxT("NULL")); + // ListBox was just focused. + m_butAdd->Enable(false); + m_butUpdate->Enable(false); + m_butRemove->Enable(true); + m_butUp->Enable(true); + m_butDown->Enable(true); + m_curFocus = 1; + } + else if ( (m_curFocus == 1 && focused == m_edValue) /*|| m_curFocus == 2*/ ) + { + //wxLogDebug(wxT("Focused: %s"),focused?focused->GetClassInfo()->GetClassName():wxT("NULL")); + // TextCtrl was just focused. + m_butAdd->Enable(true); + bool upd_enable = false; + if ( m_lbStrings->GetCount() && m_lbStrings->GetSelection() >= 0 ) + upd_enable = true; + m_butUpdate->Enable(upd_enable); + m_butRemove->Enable(false); + m_butUp->Enable(false); + m_butDown->Enable(false); + m_curFocus = 0; + } + + event.Skip(); +} + +// ----------------------------------------------------------------------- + +wxArrayEditorDialog::wxArrayEditorDialog() + : wxDialog() +{ + Init(); +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::Init() +{ + m_custBtText = (const wxChar*) NULL; + //m_pCallingClass = (wxArrayStringPropertyClass*) NULL; +} + +// ----------------------------------------------------------------------- + +wxArrayEditorDialog::wxArrayEditorDialog( wxWindow *parent, + const wxString& message, + const wxString& caption, + long style, + const wxPoint& pos, + const wxSize& sz ) + : wxDialog() +{ + Init(); + Create(parent,message,caption,style,pos,sz); +} + +// ----------------------------------------------------------------------- + +bool wxArrayEditorDialog::Create( wxWindow *parent, + const wxString& message, + const wxString& caption, + long style, + const wxPoint& pos, + const wxSize& sz ) +{ + // On wxMAC the dialog shows incorrectly if style is not exactly wxCAPTION + // FIXME: This should be only a temporary fix. +#ifdef __WXMAC__ + int useStyle = wxCAPTION; +#else + int useStyle = style; +#endif + + bool res = wxDialog::Create(parent, wxID_ANY, caption, pos, sz, useStyle); + + SetFont(parent->GetFont()); // To allow entering chars of the same set as the propGrid + +#if !wxPG_SMALL_SCREEN + const int spacing = 4; +#else + const int spacing = 3; +#endif + + m_modified = false; + + m_curFocus = 1; + + const int but_sz_flags = + wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxALL; //wxBOTTOM|wxLEFT|wxRIGHT; + + wxBoxSizer* topsizer = new wxBoxSizer( wxVERTICAL ); + + // Message + if ( message.length() ) + topsizer->Add( new wxStaticText(this,-1,message), + 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing ); + + // String editor + wxBoxSizer* rowsizer = new wxBoxSizer( wxHORIZONTAL ); + m_edValue = new wxTextCtrl(this,21,wxEmptyString, + wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER); + wxValidator* validator = GetTextCtrlValidator(); + if ( validator ) + { + m_edValue->SetValidator( *validator ); + delete validator; + } + rowsizer->Add( m_edValue, + 1, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxALL, spacing ); + + // Add button + m_butAdd = new wxButton(this,22,_("Add")); + rowsizer->Add( m_butAdd, + 0, wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, spacing ); + topsizer->Add( rowsizer, 0, wxEXPAND, spacing ); + + // Separator line + topsizer->Add( new wxStaticLine(this,-1), + 0, wxEXPAND|wxBOTTOM|wxLEFT|wxRIGHT, spacing ); + + rowsizer = new wxBoxSizer( wxHORIZONTAL ); + + // list box + m_lbStrings = new wxListBox(this, 24, wxDefaultPosition, wxDefaultSize); + unsigned int i; + for ( i=0; iAppend( ArrayGet(i) ); + rowsizer->Add( m_lbStrings, 1, wxEXPAND|wxRIGHT, spacing ); + + // Manipulator buttons + wxBoxSizer* colsizer = new wxBoxSizer( wxVERTICAL ); + m_butCustom = (wxButton*) NULL; + if ( m_custBtText ) + { + m_butCustom = new wxButton(this,28,::wxGetTranslation(m_custBtText)); + colsizer->Add( m_butCustom, + 0, wxALIGN_CENTER|wxTOP/*wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT*/, + spacing ); + } + m_butUpdate = new wxButton(this,27,_("Update")); + colsizer->Add( m_butUpdate, + 0, wxALIGN_CENTER|wxTOP, spacing ); + m_butRemove = new wxButton(this,23,_("Remove")); + colsizer->Add( m_butRemove, + 0, wxALIGN_CENTER|wxTOP, spacing ); + m_butUp = new wxButton(this,25,_("Up")); + colsizer->Add( m_butUp, + 0, wxALIGN_CENTER|wxTOP, spacing ); + m_butDown = new wxButton(this,26,_("Down")); + colsizer->Add( m_butDown, + 0, wxALIGN_CENTER|wxTOP, spacing ); + rowsizer->Add( colsizer, 0, 0, spacing ); + + topsizer->Add( rowsizer, 1, wxLEFT|wxRIGHT|wxEXPAND, spacing ); + + // Separator line + topsizer->Add( new wxStaticLine(this,-1), + 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, spacing ); + + // buttons + rowsizer = new wxBoxSizer( wxHORIZONTAL ); + /* + const int but_sz_flags = + wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL|wxBOTTOM|wxLEFT|wxRIGHT; + */ + rowsizer->Add( new wxButton(this,wxID_OK,_("Ok")), + 0, but_sz_flags, spacing ); + rowsizer->Add( new wxButton(this,wxID_CANCEL,_("Cancel")), + 0, but_sz_flags, spacing ); + topsizer->Add( rowsizer, 0, wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL, 0 ); + + m_edValue->SetFocus(); + + SetSizer( topsizer ); + topsizer->SetSizeHints( this ); + +#if !wxPG_SMALL_SCREEN + if ( sz.x == wxDefaultSize.x && + sz.y == wxDefaultSize.y ) + SetSize( wxSize(275,360) ); + else + SetSize(sz); +#endif + + return res; +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnAddClick(wxCommandEvent& ) +{ + wxString text = m_edValue->GetValue(); + if ( text.length() ) + { + if ( ArrayInsert( text, -1 ) ) + { + m_lbStrings->Append( text ); + m_modified = true; + m_edValue->Clear(); + } + } +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnDeleteClick(wxCommandEvent& ) +{ + int index = m_lbStrings->GetSelection(); + if ( index >= 0 ) + { + ArrayRemoveAt( index ); + m_lbStrings->Delete ( index ); + m_modified = true; + } +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnUpClick(wxCommandEvent& ) +{ + int index = m_lbStrings->GetSelection(); + if ( index > 0 ) + { + ArraySwap(index-1,index); + /*wxString old_str = m_array[index-1]; + wxString new_str = m_array[index]; + m_array[index-1] = new_str; + m_array[index] = old_str;*/ + m_lbStrings->SetString ( index-1, ArrayGet(index-1) ); + m_lbStrings->SetString ( index, ArrayGet(index) ); + m_lbStrings->SetSelection ( index-1 ); + m_modified = true; + } +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnDownClick(wxCommandEvent& ) +{ + int index = m_lbStrings->GetSelection(); + int lastStringIndex = ((int) m_lbStrings->GetCount()) - 1; + if ( index >= 0 && index < lastStringIndex ) + { + ArraySwap(index,index+1); + /*wxString old_str = m_array[index+1]; + wxString new_str = m_array[index]; + m_array[index+1] = new_str; + m_array[index] = old_str;*/ + m_lbStrings->SetString ( index+1, ArrayGet(index+1) ); + m_lbStrings->SetString ( index, ArrayGet(index) ); + m_lbStrings->SetSelection ( index+1 ); + m_modified = true; + } +} + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnUpdateClick(wxCommandEvent& ) +{ + int index = m_lbStrings->GetSelection(); + if ( index >= 0 ) + { + wxString str = m_edValue->GetValue(); + if ( ArraySet(index,str) ) + { + m_lbStrings->SetString ( index, str ); + //m_array[index] = str; + m_modified = true; + } + } +} + +// ----------------------------------------------------------------------- + +/*void wxArrayEditorDialog::OnCustomEditClick(wxCommandEvent& ) +{ + wxASSERT ( m_pCallingClass ); + wxString str = m_edValue->GetValue(); + if ( m_pCallingClass->OnCustomStringEdit(m_parent,str) ) + { + //m_edValue->SetValue ( str ); + if ( ArrayInsert(-1,str) ) + { + m_lbStrings->Append ( str ); + m_modified = true; + } + } +}*/ + +// ----------------------------------------------------------------------- + +void wxArrayEditorDialog::OnListBoxClick(wxCommandEvent& ) +{ + int index = m_lbStrings->GetSelection(); + if ( index >= 0 ) + { + m_edValue->SetValue( m_lbStrings->GetString(index) ); + } +} + +// ----------------------------------------------------------------------- +// wxArrayStringEditorDialog +// ----------------------------------------------------------------------- + +class wxArrayStringEditorDialog : public wxArrayEditorDialog +{ +public: + wxArrayStringEditorDialog(); + + void Init(); + + virtual void SetDialogValue( const wxVariant& value ) + { + m_array = value.GetArrayString(); + } + + virtual wxVariant GetDialogValue() const + { + return m_array; + } + + inline void SetCustomButton( const wxChar* custBtText, wxArrayStringPropertyClass* pcc ) + { + m_custBtText = custBtText; + m_pCallingClass = pcc; + } + + void OnCustomEditClick(wxCommandEvent& event); + +protected: + wxArrayString m_array; + + wxArrayStringPropertyClass* m_pCallingClass; + + virtual wxString ArrayGet( size_t index ); + virtual size_t ArrayGetCount(); + virtual bool ArrayInsert( const wxString& str, int index ); + virtual bool ArraySet( size_t index, const wxString& str ); + virtual void ArrayRemoveAt( int index ); + virtual void ArraySwap( size_t first, size_t second ); + +private: + DECLARE_DYNAMIC_CLASS_NO_COPY(wxArrayStringEditorDialog) + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxArrayStringEditorDialog, wxArrayEditorDialog) + EVT_BUTTON(28, wxArrayStringEditorDialog::OnCustomEditClick) +END_EVENT_TABLE() + +IMPLEMENT_DYNAMIC_CLASS(wxArrayStringEditorDialog, wxArrayEditorDialog) + +// ----------------------------------------------------------------------- + +wxString wxArrayStringEditorDialog::ArrayGet( size_t index ) +{ + return m_array[index]; +} + +size_t wxArrayStringEditorDialog::ArrayGetCount() +{ + return m_array.GetCount(); +} + +bool wxArrayStringEditorDialog::ArrayInsert( const wxString& str, int index ) +{ + if (index<0) + m_array.Add(str); + else + m_array.Insert(str,index); + return true; +} + +bool wxArrayStringEditorDialog::ArraySet( size_t index, const wxString& str ) +{ + m_array[index] = str; + return true; +} + +void wxArrayStringEditorDialog::ArrayRemoveAt( int index ) +{ + m_array.RemoveAt(index); +} + +void wxArrayStringEditorDialog::ArraySwap( size_t first, size_t second ) +{ + wxString old_str = m_array[first]; + wxString new_str = m_array[second]; + m_array[first] = new_str; + m_array[second] = old_str; +} + +wxArrayStringEditorDialog::wxArrayStringEditorDialog() + : wxArrayEditorDialog() +{ + Init(); +} + +void wxArrayStringEditorDialog::Init() +{ + m_pCallingClass = (wxArrayStringPropertyClass*) NULL; +} + +void wxArrayStringEditorDialog::OnCustomEditClick(wxCommandEvent& ) +{ + wxASSERT( m_pCallingClass ); + wxString str = m_edValue->GetValue(); + if ( m_pCallingClass->OnCustomStringEdit(m_parent,str) ) + { + //m_edValue->SetValue ( str ); + m_lbStrings->Append ( str ); + m_array.Add ( str ); + m_modified = true; + } +} + +// ----------------------------------------------------------------------- +// wxArrayStringProperty +// ----------------------------------------------------------------------- + +// Class body is in propdev.h + +WX_PG_IMPLEMENT_PROPERTY_CLASS(wxArrayStringProperty, // Property name + wxBaseProperty, // Property we inherit from + wxArrayString, // Value type name + const wxArrayString&, // Value type, as given in constructor + TextCtrlAndButton) // Initial editor + +wxArrayStringPropertyClass::wxArrayStringPropertyClass( const wxString& label, + const wxString& name, + const wxArrayString& array ) + : wxPGProperty(label,name) +{ + DoSetValue( array ); +} + +wxArrayStringPropertyClass::~wxArrayStringPropertyClass() { } + +void wxArrayStringPropertyClass::DoSetValue( wxPGVariant value ) +{ + m_value = wxPGVariantToArrayString(value); + GenerateValueAsString(); +} + +wxPGVariant wxArrayStringPropertyClass::DoGetValue() const +{ + return wxPGVariantCreator(m_value); +} + +wxString wxArrayStringPropertyClass::GetValueAsString( int WXUNUSED(argFlags) ) const +{ + return m_display; +} + +// Converts wxArrayString to a string separated by delimeters and spaces. +// preDelim is useful for "str1" "str2" style. Set flags to 1 to do slash +// conversion. +void wxPropertyGrid::ArrayStringToString( wxString& dst, const wxArrayString& src, + wxChar preDelim, wxChar postDelim, + int flags ) +{ + wxString pdr; + + unsigned int i; + unsigned int itemCount = src.GetCount(); + + wxChar preas[2]; + + dst.Empty(); + + if ( !preDelim ) + preas[0] = 0; + else if ( (flags & 1) ) + { + preas[0] = preDelim; + preas[1] = 0; + pdr = wxT("\\"); + pdr += preDelim; + } + + if ( itemCount ) + dst.append( preas ); + + wxASSERT( postDelim ); + + for ( i = 0; i < itemCount; i++ ) + { + wxString str( src.Item(i) ); + + // Do some character conversion. + // Convertes \ to \\ and to \ + // Useful when preDelim and postDelim are "\"". + if ( flags & 1 ) + { + str.Replace( wxT("\\"), wxT("\\\\"), true ); + if ( pdr.length() ) + str.Replace( preas, pdr, true ); + } + + dst.append ( str ); + + if ( i < (itemCount-1) ) + { + dst.append( wxString(postDelim) ); + dst.append( wxT(" ") ); + dst.append( wxString(preas) ); + } + else if ( preDelim ) + dst.append( wxString(postDelim) ); + } +} + +#define ARRSTRPROP_ARRAY_TO_STRING(STRING,ARRAY) \ + wxPropertyGrid::ArrayStringToString(STRING,ARRAY,wxT('"'),wxT('"'),1); + +void wxArrayStringPropertyClass::GenerateValueAsString() +{ + ARRSTRPROP_ARRAY_TO_STRING(m_display, m_value) +} + +// Default implementation doesn't do anything. +bool wxArrayStringPropertyClass::OnCustomStringEdit( wxWindow*, wxString& ) +{ + return false; +} + +wxArrayEditorDialog* wxArrayStringPropertyClass::CreateEditorDialog() +{ + return new wxArrayStringEditorDialog(); +} + +bool wxArrayStringPropertyClass::OnButtonClick( wxPropertyGrid* propGrid, + wxWindow* primaryCtrl, + const wxChar* cbt ) +{ + // Update the value + PrepareValueForDialogEditing(propGrid); + + if ( !propGrid->EditorValidate() ) + return false; + + // Create editor dialog. + wxArrayEditorDialog* dlg = CreateEditorDialog(); + wxValidator* validator = GetValidator(); + wxPGInDialogValidator dialogValidator; + + wxArrayStringEditorDialog* strEdDlg = wxDynamicCast(dlg, wxArrayStringEditorDialog); + + if ( strEdDlg ) + strEdDlg->SetCustomButton(cbt, this); + + dlg->SetDialogValue( wxVariant(m_value) ); + dlg->Create(propGrid, wxEmptyString, m_label); + +#if !wxPG_SMALL_SCREEN + dlg->Move( propGrid->GetGoodEditorDialogPosition(this,dlg->GetSize()) ); +#endif + + bool retVal; + + for (;;) + { + retVal = false; + + int res = dlg->ShowModal(); + + if ( res == wxID_OK && dlg->IsModified() ) + { + wxVariant value = dlg->GetDialogValue(); + if ( !value.IsNull() ) + { + wxArrayString actualValue = value.GetArrayString(); + wxString tempStr; + ARRSTRPROP_ARRAY_TO_STRING(tempStr, actualValue) + if ( dialogValidator.DoValidate( propGrid, validator, tempStr ) ) + { + DoSetValue( actualValue ); + UpdateControl( primaryCtrl ); + retVal = true; + break; + } + } + else + break; + } + else + break; + } + + delete dlg; + + return retVal; +} + +bool wxArrayStringPropertyClass::OnEvent( wxPropertyGrid* propGrid, + wxWindow* primary, + wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + return OnButtonClick(propGrid,primary,(const wxChar*) NULL); + return false; +} + +bool wxArrayStringPropertyClass::SetValueFromString( const wxString& text, int ) +{ + m_value.Empty(); + + WX_PG_TOKENIZER2_BEGIN(text,wxT('"')) + + // Need to replace backslashes with empty characters + // (opposite what is done in GenerateValueString). + token.Replace ( wxT("\\"), wxT(""), true ); + + m_value.Add ( token ); + + WX_PG_TOKENIZER2_END() + + GenerateValueAsString(); + + return true; +} + +// ----------------------------------------------------------------------- +// wxCustomProperty +// ----------------------------------------------------------------------- + +wxPGProperty* wxCustomProperty( const wxString& label, const wxString& name ) +{ + return new wxCustomPropertyClass (label,name); +} + +WX_PG_IMPLEMENT_CLASSINFO(wxCustomProperty,wxBaseParentPropertyClass) +wxPG_GETCLASSNAME_IMPLEMENTATION(wxCustomProperty) + +wxPG_VALUETYPE_MSGVAL wxCustomPropertyClass::GetValueType() const +{ + return wxPG_VALUETYPE(wxString); +} + +const wxPGEditor* wxCustomPropertyClass::DoGetEditorClass() const +{ + return wxPG_EDITOR(TextCtrl); +} + +wxCustomPropertyClass::wxCustomPropertyClass(const wxString& label, + const wxString& name) + : wxPGPropertyWithChildren(label,name) +{ + m_parentingType = -2; +#ifdef wxPG_COMPATIBILITY_1_0_0 + m_callback = (wxPropertyGridCallback) NULL; +#endif + //m_choices = &wxPGGlobalVars->m_emptyChoicesData; + m_paintCallback = (wxPGPaintCallback) NULL; +} + +wxCustomPropertyClass::~wxCustomPropertyClass() +{ + //wxPGUnRefChoices(m_choices); +} + +void wxCustomPropertyClass::DoSetValue ( wxPGVariant value ) +{ + m_value = value.GetString(); +} + +wxPGVariant wxCustomPropertyClass::DoGetValue () const +{ + return m_value; +} + +bool wxCustomPropertyClass::SetValueFromString ( const wxString& text, int /*flags*/ ) +{ + if ( text != m_value ) + { + m_value = text; + return true; + } + return false; +} + +wxString wxCustomPropertyClass::GetValueAsString ( int /*argFlags*/ ) const +{ + return m_value; +} + +// Need to do some extra event handling. +#ifdef wxPG_COMPATIBILITY_1_0_0 +bool wxCustomPropertyClass::OnEvent ( wxPropertyGrid* propGrid, wxWindow* primary, wxEvent& event ) +{ + if ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) + { + if ( m_callback ) + return m_callback(propGrid,this,primary,0); + } + return false; +} + +#endif + +wxSize wxCustomPropertyClass::GetImageSize() const +{ + if ( m_paintCallback ) + return wxSize(-wxPG_CUSTOM_IMAGE_WIDTH,-wxPG_CUSTOM_IMAGE_WIDTH); + + return wxPGPropertyWithChildren::GetImageSize(); +} + +void wxCustomPropertyClass::OnCustomPaint( wxDC& dc, + const wxRect& rect, + wxPGPaintData& paintData ) +{ + if ( m_paintCallback ) + m_paintCallback(this,dc,rect,paintData); + else + wxPGPropertyWithChildren::OnCustomPaint(dc,rect,paintData); +} + +bool wxCustomPropertyClass::SetValueFromInt ( long value, int ) +{ + size_t index = value; + const wxArrayInt& values = m_choices.GetValues(); + if ( values.GetCount() ) + index = values.Index(value); + + const wxString& sAtIndex = m_choices.GetLabel(index); + if ( sAtIndex != m_value ) + { + m_value = sAtIndex; + return true; + } + + return false; +} + +int wxCustomPropertyClass::GetChoiceInfo( wxPGChoiceInfo* choiceinfo ) +{ + if ( choiceinfo ) + { + choiceinfo->m_choices = &m_choices; + + if ( !m_choices.IsOk() ) + return -1; + + choiceinfo->m_itemCount = m_choices.GetCount(); + + if ( m_choices.GetCount() ) + choiceinfo->m_arrWxString = (wxString*)&m_choices.GetLabel(0); + + } + + if ( !m_choices.IsOk() ) + return -1; + + return m_choices.GetLabels().Index(m_value); +} + +void wxCustomPropertyClass::SetAttribute ( int id, wxVariant& value ) +{ +#ifdef wxPG_COMPATIBILITY_1_0_0 + wxPropertyGrid* grid = GetGrid(); + if ( id == wxPG_CUSTOM_EDITOR ) + { + if ( grid ) + grid->SetPropertyEditor( wxPGIdGen(this), (wxPGEditor*) value.GetVoidPtr() ); + else + SetEditor( (wxPGEditor*) value.GetVoidPtr() ); + } + else if ( id == wxPG_CUSTOM_IMAGE ) + { + wxBitmap* bmp = (wxBitmap*) value.GetWxObjectPtr(); + if ( grid ) + grid->SetPropertyImage(wxPGIdGen(this),*bmp); + else + SetValueImage(*bmp); + } + else if ( id == wxPG_CUSTOM_CALLBACK ) + { + m_callback = (wxPropertyGridCallback) value.GetVoidPtr(); + } + else +#endif + if ( id == wxPG_CUSTOM_PAINT_CALLBACK ) + { + void* voidValue = value.GetVoidPtr(); + m_paintCallback = (wxPGPaintCallback) voidValue; + if ( voidValue ) + m_flags |= wxPG_PROP_CUSTOMIMAGE; + else if ( !GetValueImage() ) + m_flags &= ~(wxPG_PROP_CUSTOMIMAGE); + } + else + if ( id == wxPG_CUSTOM_PRIVATE_CHILDREN ) + { + if ( value.GetLong() ) + m_parentingType = -1; + else + m_parentingType = -2; + } +} + +// ----------------------------------------------------------------------- diff --git a/assdraw/src/Makefile.am b/assdraw/src/Makefile.am new file mode 100644 index 000000000..3704b5126 --- /dev/null +++ b/assdraw/src/Makefile.am @@ -0,0 +1,46 @@ +SUFFIXES = .cpp + +SUBDIRS = wxAGG xpm + +AM_CXXFLAGS = @WX_CPPFLAGS@ @LIBAGG_CFLAGS@ -I../libpropgrid/include + +bin_PROGRAMS = assdraw +#assdraw_CPPFLAGS = +assdraw_LDFLAGS = -L../libpropgrid -lpropgrid @WX_LIBS@ @LIBAGG_LIBS@ +assdraw_LDADD = wxAGG/libaggwindow.a xpm/libres.a + +assdraw_SOURCES = \ + wxAGG/AGGWindow.cpp \ + agg_bcspline.cpp \ + agg_vcgen_bcspline.cpp \ + assdraw.cpp \ + assdraw_settings.cpp \ + canvas.cpp \ + canvas_mouse.cpp \ + cmd.cpp \ + dlgctrl.cpp \ + engine.cpp \ + library.cpp \ + settings.cpp + +assdraw_SOURCES += \ + agg_bcspline.h \ + agg_conv_bcspline.h \ + agg_vcgen_bcspline.h \ + resource.h \ + wxAGG/AGGWindow.h \ + wxAGG/PixelFormatConvertor.h + +EXTRA_DIST = \ + _common.hpp \ + agghelper.hpp + assdraw.hpp \ + canvas.hpp \ + canvas_mouse.hpp \ + cmd.hpp \ + dlgctrl.hpp \ + engine.hpp \ + enums.hpp \ + include_once.hpp \ + library.hpp \ + settings.hpp diff --git a/assdraw/src/Makefile.in b/assdraw/src/Makefile.in new file mode 100644 index 000000000..3a87e624e --- /dev/null +++ b/assdraw/src/Makefile.in @@ -0,0 +1,639 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = assdraw$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_assdraw_OBJECTS = AGGWindow.$(OBJEXT) agg_bcspline.$(OBJEXT) \ + agg_vcgen_bcspline.$(OBJEXT) assdraw.$(OBJEXT) \ + assdraw_settings.$(OBJEXT) canvas.$(OBJEXT) \ + canvas_mouse.$(OBJEXT) cmd.$(OBJEXT) dlgctrl.$(OBJEXT) \ + engine.$(OBJEXT) library.$(OBJEXT) settings.$(OBJEXT) +assdraw_OBJECTS = $(am_assdraw_OBJECTS) +assdraw_DEPENDENCIES = wxAGG/libaggwindow.a xpm/libres.a +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(assdraw_SOURCES) +DIST_SOURCES = $(assdraw_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +SUFFIXES = .cpp +SUBDIRS = wxAGG xpm +AM_CXXFLAGS = @WX_CPPFLAGS@ @LIBAGG_CFLAGS@ -I../libpropgrid/include +#assdraw_CPPFLAGS = +assdraw_LDFLAGS = -L../libpropgrid -lpropgrid @WX_LIBS@ @LIBAGG_LIBS@ +assdraw_LDADD = wxAGG/libaggwindow.a xpm/libres.a +assdraw_SOURCES = wxAGG/AGGWindow.cpp agg_bcspline.cpp \ + agg_vcgen_bcspline.cpp assdraw.cpp assdraw_settings.cpp \ + canvas.cpp canvas_mouse.cpp cmd.cpp dlgctrl.cpp engine.cpp \ + library.cpp settings.cpp agg_bcspline.h agg_conv_bcspline.h \ + agg_vcgen_bcspline.h resource.h wxAGG/AGGWindow.h \ + wxAGG/PixelFormatConvertor.h +EXTRA_DIST = \ + _common.hpp \ + agghelper.hpp + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +assdraw$(EXEEXT): $(assdraw_OBJECTS) $(assdraw_DEPENDENCIES) + @rm -f assdraw$(EXEEXT) + $(CXXLINK) $(assdraw_LDFLAGS) $(assdraw_OBJECTS) $(assdraw_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AGGWindow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agg_bcspline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agg_vcgen_bcspline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assdraw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assdraw_settings.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canvas.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canvas_mouse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlgctrl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/engine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/library.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settings.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +AGGWindow.o: wxAGG/AGGWindow.cpp +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT AGGWindow.o -MD -MP -MF "$(DEPDIR)/AGGWindow.Tpo" -c -o AGGWindow.o `test -f 'wxAGG/AGGWindow.cpp' || echo '$(srcdir)/'`wxAGG/AGGWindow.cpp; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/AGGWindow.Tpo" "$(DEPDIR)/AGGWindow.Po"; else rm -f "$(DEPDIR)/AGGWindow.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='wxAGG/AGGWindow.cpp' object='AGGWindow.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o AGGWindow.o `test -f 'wxAGG/AGGWindow.cpp' || echo '$(srcdir)/'`wxAGG/AGGWindow.cpp + +AGGWindow.obj: wxAGG/AGGWindow.cpp +@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT AGGWindow.obj -MD -MP -MF "$(DEPDIR)/AGGWindow.Tpo" -c -o AGGWindow.obj `if test -f 'wxAGG/AGGWindow.cpp'; then $(CYGPATH_W) 'wxAGG/AGGWindow.cpp'; else $(CYGPATH_W) '$(srcdir)/wxAGG/AGGWindow.cpp'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/AGGWindow.Tpo" "$(DEPDIR)/AGGWindow.Po"; else rm -f "$(DEPDIR)/AGGWindow.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='wxAGG/AGGWindow.cpp' object='AGGWindow.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o AGGWindow.obj `if test -f 'wxAGG/AGGWindow.cpp'; then $(CYGPATH_W) 'wxAGG/AGGWindow.cpp'; else $(CYGPATH_W) '$(srcdir)/wxAGG/AGGWindow.cpp'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-binPROGRAMS clean-generic clean-libtool \ + clean-recursive ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-recursive distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + + assdraw.hpp \ + canvas.hpp \ + canvas_mouse.hpp \ + cmd.hpp \ + dlgctrl.hpp \ + engine.hpp \ + enums.hpp \ + include_once.hpp \ + library.hpp \ + settings.hpp +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/assdraw/src/assdraw.cpp b/assdraw/src/assdraw.cpp index 8635a0236..5c9165846 100644 --- a/assdraw/src/assdraw.cpp +++ b/assdraw/src/assdraw.cpp @@ -43,6 +43,9 @@ #include #include +#if !defined(__WINDOWS__) +#include "xpm/res.h" +#endif ///////////// // Libraries diff --git a/assdraw/src/canvas.cpp b/assdraw/src/canvas.cpp index e5a2fa2f6..2a2e90eca 100644 --- a/assdraw/src/canvas.cpp +++ b/assdraw/src/canvas.cpp @@ -875,9 +875,11 @@ void ASSDrawCanvas::OnMouseRightDClick(wxMouseEvent& event) dblclicked_point_right = pointedAt_point; pointedAt_point = NULL; wxMenuItem *cmdmenuitem = new wxMenuItem(menu, MENU_DUMMY, dblclicked_point_right->cmd_main->ToString()); +#ifdef __WINDOWS__ wxFont f = cmdmenuitem->GetFont(); f.SetWeight(wxFONTWEIGHT_BOLD); cmdmenuitem->SetFont(f); +#endif menu->Append(cmdmenuitem); menu->Enable(MENU_DUMMY, false); switch (dblclicked_point_right->cmd_main->type) diff --git a/assdraw/src/dlgctrl.cpp b/assdraw/src/dlgctrl.cpp index 37e5a6991..ceb759eab 100644 --- a/assdraw/src/dlgctrl.cpp +++ b/assdraw/src/dlgctrl.cpp @@ -35,6 +35,10 @@ #include "assdraw.hpp" +#if !defined(__WINDOWS__) +#include "xpm/res.h" +#endif + BEGIN_EVENT_TABLE(ASSDrawSrcTxtCtrl, wxTextCtrl) EVT_CHAR(ASSDrawSrcTxtCtrl::CustomOnChar) EVT_TEXT(wxID_ANY, ASSDrawSrcTxtCtrl::CustomOnText) diff --git a/assdraw/src/library.cpp b/assdraw/src/library.cpp index 170a4846c..c2bda6acc 100644 --- a/assdraw/src/library.cpp +++ b/assdraw/src/library.cpp @@ -30,6 +30,10 @@ #include +#if !defined(__WINDOWS__) +#include "xpm/res.h" +#endif + BEGIN_EVENT_TABLE(ASSDrawShapePreview, ASSDrawEngine) EVT_SIZE(ASSDrawShapePreview::OnSize) END_EVENT_TABLE() @@ -153,9 +157,11 @@ void ASSDrawShapeLibrary::OnMouseRightClick(wxMouseEvent &event) activepreview = prev; wxMenu *menu = new wxMenu; wxMenuItem *menuload = new wxMenuItem(menu, MENU_LOAD, _T("Load to canvas")); +#ifdef __WINDOWS__ wxFont f = menuload->GetFont(); f.SetWeight(wxFONTWEIGHT_BOLD); menuload->SetFont(f); +#endif menu->Append(menuload); //menu->Append(MENU_LOAD, _T("Load to canvas"))->GetFont().SetWeight(wxFONTWEIGHT_BOLD); menu->Append(MENU_COPYCLIPBOARD, _T("Copy commands to clipboard")); diff --git a/assdraw/src/wxAGG/Makefile.am b/assdraw/src/wxAGG/Makefile.am new file mode 100644 index 000000000..30e088286 --- /dev/null +++ b/assdraw/src/wxAGG/Makefile.am @@ -0,0 +1,8 @@ +AM_CXXFLAGS = @WX_CPPFLAGS@ @LIBAGG_CFLAGS@ + +noinst_LIBRARIES = libaggwindow.a + +libaggwindow_a_SOURCES = \ + AGGWindow.cpp \ + AGGWindow.h \ + PixelFormatConvertor.h diff --git a/assdraw/src/wxAGG/Makefile.in b/assdraw/src/wxAGG/Makefile.in new file mode 100644 index 000000000..0051e5c25 --- /dev/null +++ b/assdraw/src/wxAGG/Makefile.in @@ -0,0 +1,452 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/wxAGG +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libaggwindow_a_AR = $(AR) $(ARFLAGS) +libaggwindow_a_LIBADD = +am_libaggwindow_a_OBJECTS = AGGWindow.$(OBJEXT) +libaggwindow_a_OBJECTS = $(am_libaggwindow_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libaggwindow_a_SOURCES) +DIST_SOURCES = $(libaggwindow_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +AM_CXXFLAGS = @WX_CPPFLAGS@ @LIBAGG_CFLAGS@ +noinst_LIBRARIES = libaggwindow.a +libaggwindow_a_SOURCES = \ + AGGWindow.cpp \ + AGGWindow.h \ + PixelFormatConvertor.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/wxAGG/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/wxAGG/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libaggwindow.a: $(libaggwindow_a_OBJECTS) $(libaggwindow_a_DEPENDENCIES) + -rm -f libaggwindow.a + $(libaggwindow_a_AR) libaggwindow.a $(libaggwindow_a_OBJECTS) $(libaggwindow_a_LIBADD) + $(RANLIB) libaggwindow.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AGGWindow.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/assdraw/src/xpm/Makefile.am b/assdraw/src/xpm/Makefile.am new file mode 100644 index 000000000..77d90ad68 --- /dev/null +++ b/assdraw/src/xpm/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libres.a + +libres_a_SOURCES = res.cpp res.h + diff --git a/assdraw/src/xpm/Makefile.in b/assdraw/src/xpm/Makefile.in new file mode 100644 index 000000000..b39e16229 --- /dev/null +++ b/assdraw/src/xpm/Makefile.in @@ -0,0 +1,447 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/xpm +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +libres_a_AR = $(AR) $(ARFLAGS) +libres_a_LIBADD = +am_libres_a_OBJECTS = res.$(OBJEXT) +libres_a_OBJECTS = $(am_libres_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libres_a_SOURCES) +DIST_SOURCES = $(libres_a_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBAGG_CFLAGS = @LIBAGG_CFLAGS@ +LIBAGG_LIBS = @LIBAGG_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WX_CFLAGS = @WX_CFLAGS@ +WX_CFLAGS_ONLY = @WX_CFLAGS_ONLY@ +WX_CONFIG_PATH = @WX_CONFIG_PATH@ +WX_CPPFLAGS = @WX_CPPFLAGS@ +WX_CXXFLAGS = @WX_CXXFLAGS@ +WX_CXXFLAGS_ONLY = @WX_CXXFLAGS_ONLY@ +WX_LIBS = @WX_LIBS@ +WX_LIBS_STATIC = @WX_LIBS_STATIC@ +WX_RESCOMP = @WX_RESCOMP@ +WX_VERSION = @WX_VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +noinst_LIBRARIES = libres.a +libres_a_SOURCES = res.cpp res.h +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/xpm/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/xpm/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libres.a: $(libres_a_OBJECTS) $(libres_a_DEPENDENCIES) + -rm -f libres.a + $(libres_a_AR) libres.a $(libres_a_OBJECTS) $(libres_a_LIBADD) + $(RANLIB) libres.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/res.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/assdraw/src/xpm/add__xpm.xpm b/assdraw/src/xpm/add__xpm.xpm new file mode 100644 index 000000000..9b47c8eb5 --- /dev/null +++ b/assdraw/src/xpm/add__xpm.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *add_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c black", +". c #99999999FFFF", +"X c None", +/* pixels */ +"XXXXX XXXXX", +"XXXXX .... XXXXX", +"XXXXX .... XXXXX", +"XXXXX .... XXXXX", +"X .... X", +"X ............ X", +"X ............ X", +"X ............ X", +"X ............ X", +"X .... X", +"XXXXX .... XXXXX", +"XXXXX .... XXXXX", +"XXXXX .... XXXXX", +"XXXXX XXXXX", +"XXXXXXXXXXXXXXXX" +}; diff --git a/assdraw/src/xpm/appico_xpm.xpm b/assdraw/src/xpm/appico_xpm.xpm new file mode 100644 index 000000000..d03428574 --- /dev/null +++ b/assdraw/src/xpm/appico_xpm.xpm @@ -0,0 +1,292 @@ +/* XPM */ +static char *appico_xpm[] = { +/* columns rows colors chars-per-pixel */ +"32 32 254 2", +" c black", +". c #121508", +"X c #1E1913", +"o c #222200", +"O c #252817", +"+ c #313117", +"@ c #15152A", +"# c #2A002A", +"$ c #3F003F", +"% c #3F1F3F", +"& c #332023", +"* c #26392C", +"= c #333223", +"- c #322E36", +"; c #2C3939", +": c #4D313F", +"> c #55383E", +", c #555500", +"< c #464F2B", +"1 c #54542A", +"2 c #4D4E3F", +"3 c #575937", +"4 c #5E672D", +"5 c #6D7029", +"6 c #362B56", +"7 c #363571", +"8 c #4C355F", +"9 c #583B55", +"0 c #443579", +"q c #3C4575", +"w c #4A4757", +"e c #644D5D", +"r c #6A5D5A", +"t c #50624A", +"y c #626448", +"u c #626D51", +"i c #787A55", +"p c #554875", +"a c #67537A", +"s c #70517F", +"d c #756C60", +"f c #7F7C65", +"g c #626D75", +"h c #637479", +"j c #AB713F", +"k c #AF7D4C", +"l c #8F7662", +"z c #9C7277", +"x c #E76F5B", +"c c #81992A", +"v c #D3B80F", +"b c #EFBE0F", +"n c #C1A821", +"m c #F5CE11", +"M c #DDCC22", +"N c #90805C", +"B c #97A447", +"V c #8BBB4C", +"C c #91B648", +"Z c #99AA55", +"A c #91BB5D", +"S c #A5B859", +"D c #8B8F65", +"F c #959469", +"G c #878B7D", +"H c #989970", +"J c #AB956B", +"K c #BABC6D", +"L c #ACA977", +"P c #B8B376", +"I c #C7814B", +"U c #EB8D50", +"Y c #DB8A69", +"T c #DAA87A", +"R c #A0C64B", +"E c #BEC254", +"W c #A9D058", +"Q c #AEC96B", +"! c #AAD071", +"~ c #D1D647", +"^ c #DBDF5C", +"/ c #CCE252", +"( c #D8ED5F", +") c #E5EC56", +"_ c #E2F35A", +"` c #FEFE59", +"' c #CECF6F", +"] c #C6D460", +"[ c #D7DC65", +"{ c #CFD47E", +"} c #D5D879", +"| c #CAE365", +" . c #D3EB6C", +".. c #D0EA72", +"X. c #E3E864", +"o. c #EBF268", +"O. c #FDFD66", +"+. c #E3E976", +"@. c #E8F376", +"#. c #FDFD74", +"$. c #3B3D8E", +"%. c #3B3CA8", +"&. c #413DB3", +"*. c #554887", +"=. c #405587", +"-. c #494197", +";. c #544894", +":. c #5E5896", +">. c #654F9C", +",. c #655A9B", +"<. c #785E98", +"1. c #577494", +"2. c #67718D", +"3. c #78778A", +"4. c #65639A", +"5. c #756499", +"6. c #667F99", +"7. c #73769E", +"8. c #4C4BB1", +"9. c #6E5CA1", +"0. c #745DA2", +"q. c #615AB9", +"w. c #6B66A8", +"e. c #7B65A7", +"r. c #797BA3", +"t. c #6B66B7", +"y. c #7565B2", +"u. c #7A7BB5", +"i. c #4443C6", +"p. c #6E63CC", +"a. c #796BC6", +"s. c #7673C2", +"d. c #6B64D8", +"f. c #766DD7", +"g. c #7C74D6", +"h. c #7C74E0", +"j. c #816CAF", +"k. c #8964B8", +"l. c #867AB6", +"z. c #8479D8", +"x. c #917BD3", +"c. c #887BE7", +"v. c #917BE8", +"b. c #8D79F4", +"n. c #987CF9", +"m. c #6481A1", +"M. c #7B83B8", +"N. c #868289", +"B. c #979D80", +"V. c #888695", +"C. c #8C929A", +"Z. c #9A9898", +"A. c #A69898", +"S. c #98BF95", +"D. c #B3AE8E", +"F. c #B7B98C", +"G. c #ACAB96", +"H. c #B6B792", +"J. c #8A88A8", +"K. c #9285AA", +"L. c #9996A3", +"P. c #8480BE", +"I. c #978EBC", +"U. c #9E9DBA", +"Y. c #A39BB6", +"T. c #93B8B1", +"R. c #A8A0A6", +"E. c #B3A9AF", +"W. c #B4B0A4", +"Q. c #A8A6B6", +"!. c #B3AFBF", +"~. c #B9B6B6", +"^. c #D3AC80", +"/. c #DABC98", +"(. c #E1AC82", +"). c #FFBB89", +"_. c #E9BD91", +"`. c #C5B7A7", +"'. c #BEC18C", +"]. c #A6C19D", +"[. c #98C6B1", +"{. c #A4C7AA", +"}. c #C8C385", +"|. c #D1D28E", +" X c #C7C998", +".X c #CCD59C", +"XX c #FFC18C", +"oX c #E9C994", +"OX c #F4C890", +"+X c #E9D198", +"@X c #FFD698", +"#X c #DAE082", +"$X c #D8ED9A", +"%X c #FFE19F", +"&X c #F0F09E", +"*X c #D5CEA3", +"=X c #D9D9A5", +"-X c #C7C3B8", +";X c #D4C8BB", +":X c #DCD8B8", +">X c #EBCAA2", +",X c #FADBA1", +".i.%.7 ,X,X,X6XZXZXoXx x Y ZXZX6X@X_.eXkXkXg.q.h.w. ", +" p 9 ;.i.&.0 l >X2X6XZXZX6XoX_.5XZXZX6X2X/.0XkXc.t.q.t.9X ", +" & *.i.&.0 6 6 K.-XVXAXZXZXZXZXZXZX4X`.:.z.kX8.8.p e 5. ", +" -.i.%.9 6 6 &.8.w.V. XZXZX2XG.J.w.8.8.c.iX8.-.a > 9 ", +" 7 %.7 X X 7 %.=.T.N I I j 1.1.$.7 8.c.t.%.6 - ", +" ; $.B v c c t m.[.[.J U U k [.T.u H.Z.7Xg q t o ", +" * v m m +.! [.bX[.k U U J ].4X c #A2A29F9F9F9F", +", c #B6B6B6B6B6B6", +"< c gray74", +"1 c #C5C5C5C5C5C5", +"2 c #C9C9C9C9CACA", +"3 c gray80", +"4 c #CDCDCDCDCDCD", +"5 c #CECECECECECE", +"6 c #D0D0D0D0D0D0", +"7 c #D1D1D1D1D0D0", +"8 c gray82", +"9 c gray83", +"0 c #D7D7D7D7D6D6", +"q c #D7D7D7D7D7D7", +"w c gainsboro", +"e c #DFDFDFDFDFDF", +"r c #E2E2E2E2E2E2", +"t c gray90", +"y c #E6E6E6E6E6E6", +"u c #EAEAEAEAEAEA", +"i c #ECECECECECEC", +"p c gray93", +"a c #F2F2F3F3F2F2", +"s c #F9F9F9F9F9F9", +"d c gray99", +"f c gray100", +"g c None", +/* pixels */ +"ggggyggggggggggg", +"gggg-9gggggggggg", +"gggg- 8ggggggggg", +"gggg-0 5gggggggg", +"gggg-f,#5ggggggg", +"gggg-fs* 5gggggg", +"gggg-dp,* 4ggggg", +"gggg-ae2>* 5gggg", +"gggg-t7X uggg", +"gggg-0% X193gggg", +"gggg-$<@ &gggggg", +"gggg-6w: oqggggg", +"ggggiggrO =ggggg", +"gggggggw;.+pgggg", +"ggggggggt +ugggg" +}; diff --git a/assdraw/src/xpm/arr__xpm.xpm b/assdraw/src/xpm/arr__xpm.xpm new file mode 100644 index 000000000..c136cc3c9 --- /dev/null +++ b/assdraw/src/xpm/arr__xpm.xpm @@ -0,0 +1,64 @@ +/* XPM */ +static char *arr__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 43 1", +" c black", +". c gray1", +"X c gray2", +"o c gray9", +"O c #282828282828", +"+ c #2A2A2A2A2A2A", +"@ c #3A3A3A3A3A3A", +"# c #3C3C3C3C3C3C", +"$ c #494949494949", +"% c gray35", +"& c #747473737373", +"* c #777777777777", +"= c #888887878787", +"- c #8F8F8E8E8E8E", +"; c gray60", +": c #9D9D9D9D9D9D", +"> c #A2A29F9F9F9F", +", c #B6B6B6B6B6B6", +"< c gray74", +"1 c #C5C5C5C5C5C5", +"2 c #C9C9C9C9CACA", +"3 c gray80", +"4 c #CDCDCDCDCDCD", +"5 c #CECECECECECE", +"6 c #D0D0D0D0D0D0", +"7 c #D1D1D1D1D0D0", +"8 c gray82", +"9 c gray83", +"0 c #D7D7D7D7D6D6", +"q c #D7D7D7D7D7D7", +"w c gainsboro", +"e c #DFDFDFDFDFDF", +"r c #E2E2E2E2E2E2", +"t c gray90", +"y c #E6E6E6E6E6E6", +"u c #EAEAEAEAEAEA", +"i c #ECECECECECEC", +"p c gray93", +"a c #F2F2F3F3F2F2", +"s c #F9F9F9F9F9F9", +"d c gray99", +"f c gray100", +"g c None", +/* pixels */ +"ggggyggggggggggg", +"gggg-9gggggggggg", +"gggg- 8ggggggggg", +"gggg-0 5gggggggg", +"gggg-f,#5ggggggg", +"gggg-fs* 5gggggg", +"gggg-dp,* 4ggggg", +"gggg-ae2>* 5gggg", +"gggg-t7X uggg", +"gggg-0% X193gggg", +"gggg-$<@ &gggggg", +"gggg-6w: oqggggg", +"ggggiggrO =ggggg", +"gggggggw;.+pgggg", +"ggggggggt +ugggg" +}; diff --git a/assdraw/src/xpm/assdraw3_xpm.xpm b/assdraw/src/xpm/assdraw3_xpm.xpm new file mode 100644 index 000000000..200164532 --- /dev/null +++ b/assdraw/src/xpm/assdraw3_xpm.xpm @@ -0,0 +1,362 @@ +/* XPM */ +static char *assdraw3__xpm[] = { +/* columns rows colors chars-per-pixel */ +"400 100 256 2", +" c #28AB0BFA0F09", +". c #28960E0E13CB", +"X c #765D23C626EF", +"o c #5590382452C9", +"O c #7143583C597E", +"+ c #72C050027049", +"@ c #83F81A0E1A0E", +"# c #8C6430583368", +"$ c #87FC3C8E4395", +"% c #917749A94FF5", +"& c #910059486920", +"* c #90BF6D3E70D5", +"= c #A1096E346C0F", +"- c #AF2F96FE721A", +"; c #E654B694684E", +": c #F2CAC2D668DF", +"> c #36C239BEABF3", +", c #37064141AE58", +"< c #3A9D4229AE8E", +"1 c #3AC846E1B34F", +"2 c #3C664C47B584", +"3 c #3BF750FEB66D", +"4 c #3D4E5802BC51", +"5 c #3DC96161BF79", +"6 c #7636552590B8", +"7 c #42114D5DB551", +"8 c #40404F4FB8B8", +"9 c #43FB5266B639", +"0 c #48C55424B730", +"q c #431255BABB08", +"w c #43E45BA1BCB2", +"e c #4DB45926BA20", +"r c #4AD25C1DBC76", +"t c #49CD6262BE4E", +"y c #52676459BEE3", +"u c #3DDF6E97C9D7", +"i c #4CA86B87C7C7", +"p c #497E78D9CCD2", +"a c #568C78CFCC0E", +"s c #49297A84D662", +"d c #55427C03D410", +"f c #5C9C7BFCD1E1", +"g c #933A70B08E99", +"h c #9CB272409D38", +"j c #93B971DCAEBB", +"k c #C4C47F7F8181", +"l c #994977CACA20", +"z c #993C778ED200", +"x c #A3097D4AC62C", +"c c #3EBF8808D757", +"v c #062B96DFFFFF", +"b c #18349E22FFFF", +"n c #343E8F05FFFF", +"m c #3A3A8F8FFFFF", +"M c #341392F7FFFF", +"N c #3BD4949CFFFF", +"B c #32339C25FFFF", +"V c #3C0D9BCEFFFF", +"C c #2222A2A2FFFF", +"Z c #2CFFA676FFFF", +"A c #2E92AC92FFFF", +"S c #313FA3C1FFFF", +"D c #3C29A42BFFF8", +"F c #340BAB35FFFF", +"G c #3C4AACD6FFE6", +"H c #2CE2B584FFFF", +"J c #2C41B8DBFFFF", +"K c #33D1B5BCFFFF", +"L c #3C20B48CFF30", +"P c #3450B985FFFF", +"I c #3C65BACAFF95", +"U c #56F68383CEA6", +"Y c #487F87FED841", +"T c #4C358CDFD71A", +"R c #582F8856D760", +"E c #5852979FDC15", +"W c #66CD8807D103", +"Q c #65B489C4D61F", +"! c #66D796E9DB25", +"~ c #74009813DB2B", +"^ c #5D38A1EADF83", +"/ c #6E44A421DE0C", +"( c #4F5F8B86E567", +") c #48969863E8D8", +"_ c #587D97F7E9E9", +"` c #496A97B0F5EB", +"' c #43A49648FE2B", +"] c #43689BE0FF5B", +"[ c #4B189CEBFF90", +"{ c #55CC9C62F711", +"} c #66E799F6E703", +"| c #726B9C5AE460", +" . c #488DA8B4ECBC", +".. c #586DA881E935", +"X. c #4E4EB0B0EFEF", +"o. c #5A4DB224EDFF", +"O. c #46F4A98AF404", +"+. c #4321A3AFFF1B", +"@. c #4D27A393FF7A", +"#. c #4354ABEDFEE4", +"$. c #4BD7AC56FEFA", +"%. c #55A2A7C4F48D", +"&. c #53DDA385FE94", +"*. c #5BE8A589FF9D", +"=. c #5363AC12FEB9", +"-. c #5C99AB49FFB8", +";. c #4807B49BF5C3", +":. c #4317B372FF10", +">. c #4C03B446FECA", +",. c #43A1BD08FF53", +"<. c #4B12BCE2FE59", +"1. c #56B2B52EF88E", +"2. c #5296B4E1FF39", +"3. c #5480BAE7FF1E", +"4. c #5C2ABBB4FF9F", +"5. c #678AA81EE7FD", +"6. c #775EA85EE91D", +"7. c #66F9B3C5EC19", +"8. c #7987B6D6EB12", +"9. c #63F0AB70FF9C", +"0. c #67F1AA89FB42", +"q. c #7568ACF4F599", +"w. c #65CEB620FA05", +"e. c #6BE7B352FFDB", +"r. c #62D6BCE6FFC1", +"t. c #69D7BDA0FFC7", +"y. c #7445B41AFFB0", +"u. c #7771B90BFB58", +"i. c #7CFBBBB9FFDA", +"p. c #465DC0C0FFFF", +"a. c #4B39C159FFF4", +"s. c #5402C363FFEE", +"d. c #5C08C549FFC7", +"f. c #5E4AC8C8FFD7", +"g. c #7D27C0C0EFEF", +"h. c #6BC1C26CF6EA", +"j. c #637AC51CFF58", +"k. c #6C8BC406FF82", +"l. c #6459C983FFF2", +"z. c #6BF1CB67FFDA", +"x. c #78EFC45FF587", +"c. c #73ACC4B8FF4E", +"v. c #7AE0C563FFC1", +"b. c #73FECDDAFFD6", +"n. c #7D0ACC39FFD0", +"m. c #7676D100FFFF", +"M. c #7CECD1F1FFFD", +"N. c #AD418EA89292", +"B. c #A8A196DE9560", +"V. c #AE7D90C8B02F", +"C. c #B1EEA9E1B4A9", +"Z. c #D93B929299E1", +"A. c #CC5EB10F930F", +"S. c #E9BAA4369224", +"D. c #CF39B2CFAFCF", +"F. c #F80AB8E3B4B4", +"G. c #BE3EC7C7BCBC", +"H. c #DF84CDC89EFE", +"J. c #FA24EA148F39", +"K. c #FB99E9B995EB", +"L. c #FA72E78F983D", +"P. c #FC13E9B69A64", +"I. c #FACEC494BCA2", +"U. c #E9F1D33EB055", +"Y. c #FADAEAF3A8DA", +"T. c #AD4398F3D9D9", +"R. c #B4BE9084D060", +"E. c #B21DB290CB18", +"W. c #8974B187EC76", +"Q. c #8633B972EC03", +"!. c #8A5CBB6CF842", +"~. c #8432BCD8FFAD", +"^. c #94D6BD38F488", +"/. c #C7AAA02ED27C", +"(. c #C9D8AC35D1A5", +"). c #C5459E61E9D8", +"_. c #C88A9F32F3A5", +"`. c #CAE6A742E767", +"'. c #C6D7A24FEDA6", +"]. c #CADFA3EEEDB2", +"[. c #D42DB04CED0D", +"{. c #C72AA224F318", +"}. c #CA9BA2E3F33B", +"|. c #CC28A631F61E", +" X c #BB02C666DB8D", +".X c #899BC340EECB", +"XX c #9309C49CEF02", +"oX c #8CCCCB08F4F2", +"OX c #86BDC4C7F8A3", +"+X c #8C8AC3A3FFB1", +"@X c #84A6CC40FFA5", +"#X c #8B89CD17FF99", +"$X c #9A4EC6C5F75E", +"%X c #9372CCE5F4BA", +"&X c #9414C4D3FE9F", +"*X c #942ECC3DFF0A", +"=X c #9CA4CB6BFEA6", +"-X c #844ED403FFF3", +";X c #8BE4D56DFFC1", +":X c #8E73D8EAFFFF", +">X c #99B5D2B3F720", +",X c #93F0D3D0FEA2", +".@.[ [ [ $.,.,.[ $.,.,.$.@.@.:.,.,.#.] #.I I I I I D ] L P P G V N N N N D P D V P V N F K N F K V N N N V F P P K V N K P P P P K V V K P K D V D K P F N D P F N N N N D K K N D P K D V V F P P F N F P P P K K D V K P P F V N N N N D P D V P V N F K N F K V N N N V F P P K V N K P P P P K V V K P K D V D K P F N D P F N N N N D K K N D P K D V V F P P F N F P P P K K D V K P P F V N N N N D P D V P V N F K N F K V N N N V F P P K V N K P P P P K V V K P K D V D K P F N D P F N N N N D K K N D P K D V V F P P F N F P P P K K D V K P P F V N N N N D P D V P V N F K N F K V N N N V F P P K V N K P P P P K V V K P K D V D K P F N D P F N N N N D K K N D P K D V V F P P F N F P ", +"P P P K G V V L P P K G N N N N G L N L D V P D V K D N N N D L I I L D ] L L I I ,.,.,.#.[ #.,.,.,.<.<.<.<.$.[ <.a.>.[ &.[ &.=.<.a.=.&.>.a.<.<.<.,.,.<.@.@.,.,.,.,.,.:.:.] +.L I I L G ' ' ' N G L N L D V P D V K D N N N D K P P L D V G K K P P P P G N D P P K P P P K V N L P G N N N N V K P V N L P P P P P P L V V L P P P P K G V V L P P K G N N N N G L N L D V P D V K D N N N D K P P L D V G K K P P P P G N D P P K P P P K V N L P G N N N N V K P V N L P P P P P P L V V L P P P P K G V V L P P K G N N N N G L N L D V P D V K D N N N D K P P L D V G K K P P P P G N D P P K P P P K V N L P G N N N N V K P V N L P P P P P P L V V L P P P P K G V V L P P K G N N N N G L N L D V P D V K D N N N D K P P L D V G K K P P P P G N D P P K P P P K V N L P G N N N N V K P V N L P P P P P P L V V L P ", +"P L D V V V N V D G L P L D N N V L V D D V D V D G V N D L I I L D ] ' ] ] ] ] :.,.,.,.,.$.[ $.<.<.a.a.3.=.&.&.3.s.2.&.&.&.&.=.s.s.2.&.=.3.s.a.a.a.>.&.&.>.<.,.,.:.$.[ [ [ [ ] +.:.I I L +.' ' +.L V D D V D V D G V N D L P I L D V N V V V V L P I I L D N D L I P P L V V V L P G N N N N V I I D N V G I P P P G V V L P P P L D V V V N V D G L P L D N N V L V D D V D V D G V N D L P I L D V N V V V V L P I I L D N D L I P P L V V V L P G N N N N V I I D N V G I P P P G V V L P P P L D V V V N V D G L P L D N N V L V D D V D V D G V N D L P I L D V N V V V V L P I I L D N D L I P P L V V V L P G N N N N V I I D N V G I P P P G V V L P P P L D V V V N V D G L P L D N N V L V D D V D V D G V N D L P I L D V N V V V V L P I I L D N D L I P P L V V V L P G N N N N V I I D N V G I P P P G V V L P P ", +"L ] ] G L L L G D ' +.G I I L +.' D ] ' ] ] ] ' D ] ] G I I G +.] ] +.:.,.,.:.$.[ $.<.<.<.a.2.&.&.=.2.2.*.-.4.-.s.s.4.*.*.*.*.-.d.s.4.-.-.*.-.3.2.=.*.&.3.a.a.<.<.@.@.$.>.<.:.:.@.[ +.#.,.I L +.' +.] ' ] ] ] ' D ] ] G I I G +.] ] D L I I L D ' D I I I I G ' ] D D D ] ] G ] I I G ' ' ' ' ] I I G ] D ' D G G +.] ] L I I I L ] ] G L L L G D ' +.G I I L +.' D ] ' ] ] ] ' D ] ] G I I G +.] ] D L I I L D ' D I I I I G ' ] D D D ] ] G ] I I G ' ' ' ' ] I I G ] D ' D G G +.] ] L I I I L ] ] G L L L G D ' +.G I I L +.' D ] ' ] ] ] ' D ] ] G I I G +.] ] D L I I L D ' D I I I I G ' ] D D D ] ] G ] I I G ' ' ' ' ] I I G ] D ' D G G +.] ] L I I I L ] ] G L L L G D ' +.G I I L +.' D ] ' ] ] ] ' D ] ] G I I G +.] ] D L I I L D ' D I I I I G ' ] D D D ] ] G ] I I G ' ' ' ' ] I I G ] D ' D G G +.] ] L I I I ", +"+.] L I I I I I I L +.] ] +.L I +.' ] G L I L +.' ] L I #.+.] ] #.:.,.,.,.,.,.<.$.&.=.<.a.s.s.3.-.-.-.-.-.4.4.9.d.d.d.w.9.9.9.r.d.f.w.9.d.-.-.-.-.-.4.s.s.s.s.s.=.&.2.a.a.a.<.<.,.:.$.[ [ #.:.,.+.' ] #.L I L +.' ] L I G +.] ] #.L I I I I I I +.' #.I I I I L +.] ] +.+.L L ] L I L +.] ' ] G I I +.+.I +.] ] ] ] #.I I I I I +.] L I I I I I I L +.] ' +.L L +.' ' G L L L +.' ] L I G ] ] ] G L I I I I I I +.' D L I I I G +.] ] ] +.L L ] L L L +.] ' ] G I I +.+.I +.] ] ] ] #.I I I I I +.] L I I I I I I L +.] ] +.L I +.' ] G L I L +.' ] L I G +.] ] #.L I I I I I I +.' #.I I I I L +.] ] +.+.L L ] L I I +.] ' ] L I I +.+.I +.] ] ] ] #.I I I I I +.] L I I I I I I L +.] ] +.L I +.' ] G L I L +.' ] L I G +.] ] #.L I I I I I I +.' #.I I I I L +.] ] +.+.L L ] L I I +.] ' ] L I I +.+.I +.] ] ] ] #.I I I I I ", +"] #.I I :.:.:.:.I I I :.#.+.] +.] ] :.I I I I I #.' +.] ] +.:.,.,.,.,.>.>.>.<.a.<.&.&.s.s.s.d.d.d.d.d.j.f.l.j.9.r.l.l.j.j.j.j.l.l.j.e.r.l.l.j.j.j.f.f.d.d.d.d.s.-.2.s.s.3.2.>.<.<.<.<.<.>.@.[ @.[ +.:.,.,.,.,.I #.' +.] ] +.:.I I I :.:.#.#.I I I ] ] I I I I I I I :.:.I I I ] #.I I L L L L I I L ] #.I I I :.:.I I I I I I I ] #.I I L G G L I I I L G ] ] ] ' ] L I L I I I +.' +.] ] +.G I I L L G G G L I L ] ] L I I I I I L L L I I L ] D I I L L L L I I L ] #.I I I L L I I I I I I I ] #.I I :.:.:.:.I I I :.#.+.] +.] ] :.I I I I I #.' +.] ] +.:.I I I :.:.#.#.I I I ] ] I I I I I I I :.:.I I I ] #.I I I I :.I I I :.] #.I I I :.:.I I I I I I I ] #.I I :.:.:.:.I I I :.#.+.] +.] ] :.I I I I I #.' +.] ] +.:.I I I :.:.#.#.I I I ] ] I I I I I I I :.:.I I I ] #.I I I I :.I I I :.] #.I I I :.:.I I I I I I I ", +"[ :.,.:.+.] ] [ +.+.#.:.,.,.:.+.' :.,.,.,.,.,.,.,.+.[ #.:.,.,.:.$.@.@.&.[ &.=.s.s.2.*.d.d.d.f.f.j.l.l.l.l.l.l.t.e.k.z.z.z.z.z.z.k.e.y.k.z.z.l.l.l.l.l.l.j.f.d.d.9.d.d.4.-.*.*.&.&.=.2.<.<.<.>.@.[ >.,.,.,.,.,.,.,.+.] #.:.,.,.:.#.+.[ ] ] ] #.,.,.#.[ ,.,.,.,.,.,.,.,.I I ,.I +.] #.L I I I I I :.] ] :.I ,.I I ,.,.,.,.,.,.,.,.] :.I :.] ' ' ] ] +.#.:.L L #.] ' #.I I I :.I I :.+.] #.:.I I :.#.] ] ' ' ' +.I L +.' L L L I I L I I I L L I +.' #.L L L L L I #.] ] :.I I I I I I I I I I ,.,.[ :.,.:.+.] ] [ +.+.#.:.,.,.:.+.' :.,.,.,.,.,.,.,.+.] #.:.,.,.:.#.+.[ ] ] ] #.,.,.#.[ ,.,.,.,.,.,.,.,.,.,.,.,.#.[ #.,.,.,.,.,.,.:.+.[ :.,.,.,.,.,.,.,.,.,.,.,.,.[ :.,.:.+.] ] [ +.+.#.:.,.,.:.+.' :.,.,.,.,.,.,.,.+.] #.:.,.,.:.#.+.[ ] ] ] #.,.,.#.[ ,.,.,.,.,.,.,.,.,.,.,.,.#.[ #.,.,.,.,.,.,.:.+.[ :.,.,.,.,.,.,.,.,.,.,.,.,.", +"[ ,.,.#.[ [ [ [ [ [ [ [ @.#.:.+.[ ,.,.,.+.+.:.,.,.#.[ #.$.@.@.[ [ [ [ &.&.&.*.s.d.4.9.d.f.l.l.l.l.l.z.z.z.z.z.b.u.y.u.c.c.c.c.u.y.y.c.b.b.z.z.z.z.z.z.z.l.l.l.j.9.j.f.4.9.*.*.*.*.&.&.&.&.=.>.@.[ <.<.,.$.@.:.,.,.#.[ #.#.+.[ [ [ [ [ [ [ [ [ ,.,.:.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.+.' +.+.#.#.#.+.] ] #.,.,.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.#.' ' ' ' ' ' ' ' ] +.#.] ' :.:.:.+.] #.,.,.+.] #.+.+.] ' ' ' ' ' ' ' ' :.:.#.' :.L L :.L L L L L L L L :.] ' ] +.#.#.#.+.] ' #.:.:.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.#.[ [ [ [ [ [ [ [ @.#.:.+.[ ,.,.,.+.+.:.,.,.#.[ #.#.+.[ [ [ [ [ [ [ [ [ ,.,.:.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.+.[ +.#.:.:.:.#.[ [ #.,.,.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.#.[ [ [ [ [ [ [ [ @.#.:.+.[ ,.,.,.+.+.:.,.,.#.[ #.#.+.[ [ [ [ [ [ [ [ [ ,.,.:.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.+.[ +.#.:.:.:.#.[ [ #.,.,.,.,.,.,.,.,.,.,.,.,.,.", +"[ ,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.,.@.[ $.,.,.$.[ [ [ [ &.&.&.&.&.*.*.*.-.d.d.r.9.j.l.l.z.z.z.z.b.b.b.b.m.m.b.v.i.i.i.v.i.i.i.i.v.b.b.b.b.b.b.b.b.z.z.z.z.z.e.l.l.r.9.9.9.9.*.*.*.*.*.{ &.&.&.<.<.<.@.[ $.,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.#.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.:.+.` ` [ +.` ` ` ` #.:.,.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.#.` ` ` ` ` ` ` ` ` ` ` ` ` :.:.:.[ ` +.,.:.#.` ` ` ` ` ` ` ` ` ` ` ` ` ;.;.O.` ;.:.:.:.:.:.:.:.:.:.;.:.:.;.+.` ` ` +.` ` ` ` O.:.:.:.,.,.,.,.,.,.,.,.,.,.[ ,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.,.@.[ $.,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.#.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.,.$.[ [ @.$.@.@.[ [ $.,.,.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.,.@.[ $.,.,.$.[ [ [ [ [ [ [ [ [ [ [ [ [ ,.,.#.[ ,.,.,.,.,.,.,.,.,.,.,.,.,.,.$.[ [ @.$.@.@.[ [ $.,.,.,.,.,.,.,.,.,.,.,.,.,.", +"@.,.,.>.[ [ [ [ [ [ [ @.$.>.<.$.[ <.p.,.>.$.<.p.<.$.@.>.>.>.=.&.&.*.*.*.*.*.9.f.j.t.e.z.z.z.z.b.b.b.m.m.M.M.M.n.@X~.~.~.~.@X+X~.~.@X-XM.M.M.M.M.M.m.m.b.b.b.b.b.y.z.z.t.0.0.9.9.9.9.-.-.-.3.3.2.&.3.a.a.>.$.<.p.<.$.@.>.>.$.$.@.[ [ [ [ [ [ @.,.,.>.@.,.,.,.,.,.,.,.,.,.,.,.,.:.O.` ` ` ` +.` ` ` +.:.,.,.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.#.` ` ` ` ` ` ` ` O.O.O.O.` ;.;.;.O.+.;.,.;.+.` #.#.O.+.` ` ` ` ` ` ` ` ;.;.O.` ;.;.;.;.;.;.;.;.;.;.;.;.;.O.` ` ` ` +.` ` ` +.;.;.;.;.;.:.,.,.,.,.,.,.,.,.[ ,.,.>.[ [ [ [ [ [ [ @.$.>.<.$.[ <.p.,.>.$.<.p.,.$.@.>.>.$.$.@.[ [ [ [ [ [ @.,.,.>.@.,.,.,.,.,.,.,.,.,.,.,.,.,.$.[ [ @.@.$.@.@.[ $.,.p.p.,.,.,.,.,.,.,.,.,.,.,.[ ,.,.$.[ [ [ [ [ [ [ @.$.>.<.$.[ <.p.,.>.$.<.p.,.$.@.>.>.$.$.@.[ [ [ [ [ [ @.,.,.>.@.,.,.,.,.,.,.,.,.,.,.,.,.,.$.[ [ @.@.$.@.@.[ $.,.p.p.,.,.,.,.,.,.,.,.p.,.,.", +"@.<.p.<.$.@.@.@.$.>.<.<.<.>.$.@.[ $.<.p.p.<.a.a.>.&.&.=.2.3.s.s.3.4.-.9.9.9.r.l.l.t.y.z.b.b.b.m.M.M.M.M.-X-X-X@X+X+X#X;X;X;X;X;X#X+X#X-X-X-X-X-X-X-XM.M.M.M.b.b.u.b.b.z.t.e.e.e.e.r.j.d.d.4.-.-.*.2.s.a.a.a.a.a.>.&.[ @.>.<.<.<.<.>.$.@.[ @.>.p.p.$.@.<.<.p.<.p.,.<.<.<.<.<.,.$.` ` O.O.;.;.;.O.O.` $.,.,.,.,.<.<.<.<.<.<.<.,.<.[ ;.,.;.@.` ` ` O.O.O.;.;.O.` ` ` O.;.;.;.;.;.;.O.` ` ` O.;.;.;.O.O.` ` ` ` O.;.;.` ` O.O.O.O.O.O.O.O.O.O.O.;.O.` ` O.O.;.O.O.O.` ` O.;.;.;.;.;.;.;.,.,.,.,.,.<.[ >.<.<.$.@.@.@.$.>.<.<.<.>.$.@.[ $.<.p.p.<.p.p.>.@.[ @.>.<.<.<.<.>.$.@.[ @.>.,.,.$.[ <.,.,.<.<.<.<.,.,.<.<.p.>.@.@.$.<.<.<.<.>.$.@.>.<.<.,.,.,.,.,.<.<.<.<.<.<.[ >.<.<.@.[ [ @.$.>.>.<.<.>.$.@.[ $.<.p.p.<.p.p.>.@.[ @.>.<.<.<.<.>.$.@.[ @.>.p.p.$.@.<.<.p.<.p.p.<.<.<.<.<.p.>.@.@.$.<.<.<.<.>.$.@.>.<.<.p.p.p.p.p.p.p.p.p.<.<.", +"&.$.<.<.<.<.<.<.<.<.<.>.$.&.@.>.@.&.>.<.<.a.a.<.=.&.2.=.&.=.2.3.d.d.f.f.j.l.l.z.k.y.y.b.b.m.M.M.-X-X-X-X;X;X;X*X&X,X1X1X1X1X1X1X1X*X&X,X:X:X;X;X;X;X-X-X-X-XM.M.i.v.b.b.b.c.z.z.z.l.j.r.w.9.9.4.-.*.3.s.s.s.a.3.=.&.=.=.&.@.$.<.a.a.a.<.<.<.a.a.>.&.&.<.<.a.<.a.<.<.<.<.<.<.;.[ ` O.;.;.;.;.;.;.;.O.` $.<.<.<.<.<.<.<.<.<.<.<.<.[ @.;.;.;.O.O.O.;.;.O.O.` ` ` O.` ` O.;.;.;.;.O.` ` O.O.` ` O.O.;.;.;.O.O.O.O.O.O.` ` O.O.O. .O. . .O.O.O.O.O.` ` O.O.O.O.O.O.O.O.` ` O.;.;.;.;.;.;.;.;.;.<.<.<.[ $.<.<.<.<.<.<.<.<.<.>.$.&.@.>.@.&.>.<.<.a.a.<.@.[ $.$.@.@.$.<.<.a.<.<.<.<.<.<.>.[ @.<.<.<.<.<.<.<.<.<.<.<.<.@.@.>.a.<.a.<.<.a.<.$.[ >.<.<.<.<.<.<.<.<.<.<.<.<.[ @.<.<.<.>.>.<.<.<.<.>.@.@.@.>.@.&.>.<.<.a.a.<.$.&.$.$.&.@.$.<.a.a.a.<.<.<.a.a.>.&.&.<.<.a.<.a.a.a.a.a.a.a.<.@.&.>.a.<.a.<.a.a.<.$.&.>.a.<.<.a.a.a.a.a.<.a.<.<.", +"$.&.>.a.a.a.a.a.<.$.&.&.=.>.<.<.=.&.&.=.2.>.=.&.&.&.2.s.3.2.-.-.9.r.j.l.l.z.z.z.y.i.i.n.M.-X-X-X;X#X#X,X3X XH.U.H. X2X2X.<.a.a.a.a.<.&.&.=.<.a.a.a.<.<.>.>.>.>.;.;.` O.;. .) Y Y ) .;.;.` @.<.<.>.>.>.>.<.<.<.<.<.<.O.` O.;.;.;.;.O.O.` ` ` ` .O. .` ` ` ` .O.` ` ` ` O.O.O.O.` ` ` O.O.O.O.O. . .) ) ) . . . . . .) ) ) . . .) . . . .) ` .O.O.O.` ` O.O.O.O.O.O.;.;.;.;.;.<.$.[ $.<.<.<.a.<.<.$.&.&.$.>.<.<.=.&.[ $.>.>.$.&.[ [ $.<.<.$.@.&.@.>.<.<.<.<.<.<.&.&.$.<.<.<.<.<.>.>.>.>.>.<.<.[ >.a.<.<.>.$.>.<.<.<.&.$.<.<.>.>.>.>.<.<.<.<.<.<.$.[ $.<.<.<.<.<.>.$.@.[ $.>.<.>.&.&.&.=.>.>.$.&.&.&.>.<.<.>.&.&.=.>.<.a.a.a.a.<.&.&.=.<.a.a.a.<.<.>.>.>.<.<.<.&.>.a.a.<.>.=.>.<.a.<.=.=.a.a.<.>.>.>.<.a.a.a.a.<.", +"<.=.&.=.2.2.2.=.&.&.=.3.<.<.2.&.&.2.&.&.&.&.&.*.=.=.*.-.4.d.d.r.9.9.e.t.k.c.u.y.i.n.n.-X-X-X;X#X&X&XG.A.H.L.L.P.P.H.- 4X5X5X5X9XqXqX9X9X2X9X5X=X=XC.C.C.G.1X:X;X;X+X~.+X@Xn.v.i.y.y.t.k.z.l.t.e.9.r.9.9.-.*.*.*.=.=.&.=.3.s.3.2.=.&.&.=.2.2.=.&.&.3.3.a.a.a.<.=.&.&.{ { { $.O.` ;. .Y 4 2 2 4 s .;.O.@.;.@.{ { { { &.>.<.<.<.;.;.@.` ` O. . .) s s Y Y Y Y Y ( ) ) Y s s ( ) ` ` ` ` ` .O. . .) Y s Y Y Y s s ( ) ) Y c Y ) ) ( ( ( s s s Y s ) ) Y s s s s Y Y Y Y ) .` ` ` ` ` ` O.;.;.;.;.>.@.{ &.>.>.=.&.&.&.=.>.<.<.2.&.&.2.&.&.&.{ &.{ =.=.{ &.>.<.<.>.&.&.&.=.>.>.=.{ &.>.>.<.<.<.>.$.&.{ { { { =.2.&.<.<.<.&.{ &.&.=.<.<.=.=.<.&.{ { { { &.>.<.<.;.;.;.@.{ @.$.$.$.@.{ { $.>.<.<.=.&.&.2.&.&.&.{ &.&.=.=.&.=.3.a.<.2.=.&.&.=.2.2.=.&.&.3.3.a.a.a.<.2.&.&.&.&.&.2.2.&.<.a.3.=.&.&.&.2.a.a.2.=.<.=.&.&.&.&.=.2.a.a.a.a.", +"s.3.2.=.=.=.&.&.2.3.s.s.2.=.&.&.2.3.&.2.=.=.3.-.3.4.-.9.9.r.j.l.l.k.e.y.y.u.i.v.M.-X-X-X;X;X*X&XH.A.H.P.K.L.P.K.J.K.L.- B.V.V.R.R.R.R.V.V.V.C.B.A.P.P.P.L.A.1X1X1X:X#X+X+X+X~.~.v.n.b.b.c.y.e.e.r.j.9.r.-.-.4.-.4.3.*.*.*.2.3.s.s.3.=.&.&.=.=.2.s.s.s.s.s.3.=.&.=.2.2.>.=.{ { ` X.) 5 , 1 1 , 3 Y .O.{ @.&.=.>.>.2.&.{ $.<.;.;.;.;.O.` ) Y s p 4 3 3 3 2 2 4 i Y p 4 2 4 s ) ) ) .) ( ( ) Y Y s 4 2 2 1 2 2 4 p c u 4 3 4 u Y ( Y p 4 2 1 2 4 u p 4 1 1 2 2 2 3 3 4 p s s Y ) ) .` ` O.;.;.;.;.;.$.&.&.&.{ { =.2.<.<.2.&.{ &.=.2.&.2.=.=.2.&.=.>.&.{ { =.>.<.<.>.&.{ { &.&.=.<.<.<.<.<.>.&.{ &.>.>.>.=.&.&.&.3.<.2.{ { &.&.&.<.<.=.&.&.&.=.>.>.$.&.{ O.;.;.;.;.;.O.%.&.{ { { %.>.<.<.2.&.{ &.2.3.&.2.=.=.3.=.2.3.&.&.&.2.3.s.s.3.=.&.&.=.=.2.s.s.s.s.s.3.=.&.=.2.3.3.2.&.=.&.3.s.2.&.&.&.&.&.3.s.2.=.=.=.2.3.3.2.=.&.2.s.s.s.", +"s.s.s.s.3.=.=.3.s.s.3.=.*.*.*.=.s.2.*.s.=.-.3.4.-.d.4.9.9.9.e.t.z.z.z.c.i.v.M.M.-X-X;X:X,X=X6X- H.Y.P.P.P.P.P.P.K.K.K.P.N./.`.]._.}.{.].'.(.N.Y.L.K.K.K.P.L.C.2X2X1X1X:X;X+X+X-X-XM.n.v.u.y.y.e.z.t.e.j.w.9.d.4.-.d.4.*.*.*.-.2.s.s.s.3.=.2.s.s.s.s.s.s.3.=.&.2.3.3.<.<.<.X.{ ` X.T 3 1 JXJX3 , 5 ) %.{ %.;.<.<.3.3.3.=.{ %.;.;.X.;.X. .Y 4 2 3 3 3 2 2 2 2 2 2 3 2 2 1 , 3 s ) ) .) ( ( s 4 2 3 3 3 2 2 2 3 3 3 3 3 3 1 > 2 u s u 3 , 1 2 1 2 2 2 2 2 2 2 1 2 2 3 2 2 2 3 3 5 s ) .` ` %.;.;.;.;.;.<.1.&.&.>.<.3.2.=.&.&.{ &.3.=.&.3.=.&.3.=.&.<.=.{ { { &.=.<.<.<.2.&.=.<.<.<.<.<.<.1.&.{ =.1.;.<.<.3.2.&.{ 3.3.2.{ { &.{ &.3.<.=.{ &.>.<.<.;.;.;.%.{ %.;.;.X.;.;.;.X.{ { ;.;.;.1.=.&.&.{ &.3.2.*.3.=.=.3.2.=.s.2.*.*.*.=.2.s.s.s.3.=.2.s.s.s.s.s.s.3.=.*.3.s.s.s.s.s.3.*.*.3.s.3.*.*.*.*.*.3.s.2.*.=.s.s.s.s.s.s.=.*.2.s.s.", +"s.s.s.s.-.*.3.s.s.2.-.*.*.*.*.3.s.*.2.s.-.*.4.d.9.4.d.9.9.0.e.e.y.c.b.b.n.~.@X-X;X:X1X1X 4 Y ( ) ) s i 3 > 1 4 FXFXFXFXFXFXFX4 2 4 FXFX2 > 1 2 1 , 3 FXFXFXFX4 4 FXFXFXFXFXFXFXFXFX4 2 3 3 2 2 5 Y ) ) ` X.X.X.;.;.X.%.{ 1.<.1.%.&.{ { { { 1.3.&.=.3.&.{ 1.1.{ 1.1.%.{ { { { %.1.1.1.1.{ =.<.1.1.1.1.%.{ %.;.1.1.1.1.1.3.=.&.1.3.1.{ { { { &.3.3.%.{ 1.1.1.X.X.X.;.X.%.{ X.X.X.X.X.X.{ { X.X.X.%.{ { { &.&.3.3.*.2.s.-.*.3.3.*.3.s.-.*.*.*.*.-.3.s.s.3.*.3.s.s.s.s.s.2.*.3.s.s.3.3.3.s.s.3.*.3.s.3.*.*.*.*.-.s.s.-.-.3.s.s.3.3.s.s.s.-.-.3.s.", +"s.s.s.4.-.4.s.s.-.*.*.*.*.*.4.s.4.-.4.4.-.9.4.d.w.w.l.t.e.e.e.y.y.u.v.M.M.+X+X;X:X1X1X2XA.H.Y.P.P.P.K.K.P.P.L.P.P.L.P.K.K.Y.- V.C./.`./.A.Y.P.P.K.K.K.K.K.K.P.- V.C.qX2X=X > > 2 FXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFXFX4 2 3 5 Y ( ) X.X.X.X.X.{ %.1.1.%.{ { { { { %.1.1.&.1.1.&.{ %.1.%.%.1.%.{ { { { { { %.1.1.%.%.1.1.1.1.X.{ %.X.X.%.{ { { %.1.1.%.%.3.3.&.{ { { %.1.1.{ %.1.X.%.{ { %.X.X.X._ %.X.X.X.X. ._ .X.X.%.{ { { { { =.3.1.*.3.3.-.*.4.s.-.-.s.4.-.*.*.*.*.-.4.s.s.-.-.s.s.s.s.4.-.-.s.s.4.-.*.-.4.s.s.-.-.s.s.-.*.*.*.4.s.4.*.4.s.s.-.*.-.-.s.s.4.-.4.s.", +"d.d.d.4.-.d.d.4.-.*.*.*.*.-.d.d.-.-.d.4.9.9.9.j.r.9.j.l.t.e.y.y.y.i.v.-X-X#X+X1X1X1X2X- Y.P.P.K.P.P.K.K.P.P.K.P.P.P.K.K.L.Y.- Y.Y.A.V.N.Y.P.K.P.K.L.K.P.P.K.L.Y.N.`.V.B.7X2X2X > > AXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAX3 , 4 p Y .X.X.X.%.{ X.X.X.{ { { { { { 1.1.%.%.1.%.{ { %.1.%.{ X.X.%._ _ { { { %.X.X.%.{ X.X.X.X.%.{ .) T ( _ { { { 1.1.1.%.1.1.%.{ { { 1.1.%.{ X.X.%.{ _ _ _ %.X.X.) ( T Y Y Y Y s Y T ( ( _ { { { %.1.3.*.-.s.4.*.*.-.d.4.-.4.d.-.*.*.*.*.*.-.d.d.4.-.d.d.d.d.4.*.4.d.d.-.*.*.*.-.4.d.4.-.4.d.-.*.*.-.4.d.4.-.4.d.4.-.*.*.*.4.d.d.-.-.d.", +"d.d.d.4.-.d.d.4.-.9.*.9.9.4.d.4.9.4.d.9.9.9.9.j.j.e.t.z.k.y.y.i.i.~.OX-X;X#X*X1X2XqXA.Y.P.K.P.P.P.P.P.P.K.K.K.P.P.L.P.K.K.P.; P.J.P.= Y.L.K.K.K.P.K.K.K.K.K.L.K.A.`.{.`.V.C. X 3 VXVXVXVXVXVX4 3 3 2 4 VXVXVXVXVXVXVX2 > > > 3 VXVXVXVXVXVXVX4 2 2 2 2 3 3 2 4 VXVXVXVXVXVXVXVX4 3 2 4 Y . .X. ._ X.X.%.{ _ _ { { %.1.%.{ %.X.%.{ { { X.X.{ %.X.X._ _ _ _ _ { X.X.%._ X.X.X.X.%.( Y 5 3 w s ( _ { %.1.1.%.%.1.%.{ { { 1.1.{ _ ) T s ( ( _ _ _ X. .) s 4 3 3 3 2 2 3 3 4 p ( ( { { %.3.1.*.4.d.-.-.9.-.d.d.-.4.d.d.-.9.9.*.9.-.d.d.4.-.d.d.d.d.4.9.d.d.4.-.9.9.9.9.-.d.d.-.4.d.4.9.9.-.d.d.-.-.d.4.-.9.-.-.-.-.d.d.4.-.d.", +"f.d.f.4.9.4.f.d.9.9.9.9.9.d.d.9.9.d.d.9.9.9.0.j.l.t.e.z.b.c.i.i.~.~.#X;X:X*X=X2XqX- Y.P.P.K.P.P.L.P.P.P.K.K.K.P.P.P.P.P.K.; L.L.P.L.L.P.K.P.K.K.P.K.K.K.K.K.L.K.U./.}.].].}.V.V.9X=X=X&X*X;X;X+X+Xn.n.i.y.y.y.k.z.t.e.j.l.r.9.9.9.9.r.d.d.9.9.d.f.d.f.4.9.d.d.4.*.*.{ { { _ ..) 4 2 sXsXsXsXsXsX2 q ( X.%.{ { { { { %.1.1.%._ Y 3 4 sXsXsXsXsX4 2 2 2 2 2 2 2 4 sXsXsXsXsX1 , 5 u 2 3 sXsXsXsXsX4 2 2 3 3 2 2 2 4 sXsXsXsXsX2 > > > 1 sXsXsXsXsX5 1 2 2 2 2 2 3 2 2 2 3 2 4 sXsXsXsXsXsXsX4 , 4 T . ..._ ..X.X._ _ _ _ { X.X.{ { X.X.{ _ _ _ ..X._ Y T T Y s s s s Y ) ._ _ X.X.X.X.) s 4 < , , 3 s _ _ { %.1.%.{ 1.o.{ { %.1.%._ Y 5 2 2 w s ( ( _ .) s 3 , 1 2 2 2 2 2 3 3 2 w s _ %.1.1.-.-.4.4.-.9.9.9.4.d.4.9.d.d.4.9.9.9.9.4.d.d.9.9.d.f.d.f.4.9.d.d.4.9.9.9.9.9.9.4.d.4.9.d.4.9.9.9.d.4.9.4.d.9.9.9.9.9.9.w.f.d.4.9.d.", +"f.f.f.d.9.9.d.f.d.w.9.w.d.f.4.9.r.l.j.9.9.0.e.t.z.z.y.c.b.b.v.~.+X#X;X:X,X=X 4 sXsXsXsX1 > 1 1 2 sXsXsXsXsX4 2 4 p Y Y s p 4 , 4 sXsXsXsX2 > , , 1 sXsXsXsXsX2 3 p Y s s Y Y s s p 4 2 2 2 q sXsXsXsXsXsX4 3 p ) . .( Y Y T T _ _ _ ..X..._ ..X..._ _ _ _ _ ..Y q 2 3 3 2 2 2 2 3 5 s ( ..........T w , 4 sX4 > q R _ _ { o.o.{ %.o.{ _ %.X._ ( t , 1 1 > 3 s ( . .T 4 > 1 sXsXsXsXsXsXsXsX4 < w ( o.1.1.*.1.d.4.9.9.9.9.w.f.d.9.r.f.f.r.9.9.r.f.f.r.9.r.f.f.f.f.d.9.r.f.f.r.9.9.9.9.9.9.d.d.9.r.f.9.9.r.f.9.9.f.r.9.9.9.9.9.w.d.f.d.9.r.f.", +"l.l.l.l.r.9.r.j.l.j.j.l.j.j.w.9.j.l.t.e.e.e.e.e.z.z.u.i.n.M.M.-X;X;X1X1X=X5XqXA.Y.P.P.P.K.P.P.P.K.K.K.K.K.P.P.P.P.K.K.P.Y.A.P.P.P.; P.P.P.K.P.P.K.K.K.P.K.K.K.K.K.A.[.].}.}.}.}.`.V.3X2X2X1X*X&X;X-X@X~.~.i.i.u.b.z.y.e.k.l.l.l.l.l.l.j.9.9.j.f.f.f.d.d.w.9.4.4.1.1.%.{ _ _ R w , w tXtXtXtXtXtXq 2 s _ _ _ { %.o.o.o.o.%.R t < 5 tXtXtXtXq w p T ) ......) p 3 2 tXtXtXtX1 > > > 4 tXtXtXtX4 4 p T ...._ _ ) Y 4 2 tXtXtXtX2 1 u i 1 3 tXtXtX4 2 i ( .._ _ ...._ ....R s i q 2 2 4 tXtXtXtXtX2 4 Y ) ) p q 2 3 5 Y ......T Y s T T T ( _ _ _ ( Y 4 , 1 2 2 2 2 3 3 1 , 3 p T .......Y 2 1 tXtXtX1 2 s _ _ _ ..o..._ o._ _ ...._ T 3 1 tXtX3 , w T ....s 2 > 1 tXtXtXtXtXtXtXtXtX4 3 Y ..1.%.0.4.d.w.9.9.9.9.9.j.l.w.9.j.l.l.l.j.l.l.j.9.9.j.l.l.l.j.j.r.9.j.l.j.r.e.9.9.9.9.r.l.w.w.j.e.9.j.j.9.r.j.9.9.9.9.9.r.l.l.j.w.9.j.l.", +"l.l.l.l.j.w.9.r.j.l.l.l.j.e.9.9.j.l.t.e.e.e.y.y.b.b.v.i.~.@X-X-X;X1X,X=X5XqX8XH.P.L.P.L.P.K.P.P.K.K.K.K.K.K.K.P.P.P.K.Y.A.A.U.U.H.= Y.P.K.K.P.K.K.K.K.K.K.L.K.K.K.Y./.'.}.}.}.}._.{.V.8XqX=X=X&X,X;X#X~.~.~.i.i.b.b.t.y.e.k.z.l.l.l.r.e.e.j.j.j.j.j.j.j.r.0.0.1.1.1.o.%._ _ i 1 1 wXwXwXwXwXwXwXwX3 w R _ _ %.o.o.o.o.%._ T 3 1 wXwXwXwX4 2 i _ .........._ ( i 2 4 wXwXwX1 > > 1 wXwXwXwX3 2 p ) ...._ _ ....) p 2 4 wXwXwX2 2 p p 2 2 wXwXwX2 2 Y ( .._ _ ...._ o..._ _ ( T p 4 , 4 wXwXwXwX4 , 4 Y Y 4 , 1 1 , 4 p T p w 2 2 3 3 w i d ( _ Y 4 , 3 wXwXwXwXwXwXwXwXq 2 2 i T ....) p 2 q wXwXwX3 3 Y _ _ _ _ ..E d E _ _ ...._ T 2 2 wXwXwX4 2 p E ( s 4 > > 1 2 2 2 4 wXwXwXwXwX3 t _ %.%.0.4.d.w.0.9.9.9.e.l.l.r.9.e.j.l.l.l.l.r.9.e.j.l.l.l.l.l.j.j.e.e.j.l.l.j.r.9.9.9.9.j.j.9.j.r.e.l.r.e.j.r.9.9.9.w.j.l.l.j.e.9.j.j.j.", +"l.l.l.l.l.l.t.e.e.t.t.t.e.e.t.e.l.z.t.e.y.y.y.u.b.b.v.~.OX~.+X#X*X=X=X5XqXuX- P.J.K.P.L.P.P.K.K.K.K.K.K.P.K.K.P.P.P.Y.A.R./.V.V.o V.D.Y.K.P.P.K.K.K.P.P.P.P.K.K.K.Y.* `._.}.}.|.|.}.'.V.0X9X q qXqXqXqXqXqXqXqX3 2 d _ o.o.o.o..._ _ _ R 2 2 qXqXqXw , t T _ _ _ _ _ _ _ _ s 2 1 qXqXqX1 > > 2 qXqXqX4 > q T _ _ _ _ ........T 3 1 qXqXqX2 4 s p 2 2 qXqXqX2 2 Y _ _ _ _ .._ ..o._ _ ....o...Y 4 , q qXqXqXqX1 1 i i 1 1 qXqX3 , 1 2 2 2 2 2 3 3 2 2 w d ( s 2 1 qXqXqXqXqXqXqXqXqXqXqX4 2 p E _ Y q 2 qXqXqXqX2 4 T .._ _ ( s t 2 w s _ _ _ _ Y 2 2 qXqXqXqX2 w s ( R p 4 2 2 2 2 1 , 4 qXqXqXqX2 2 R 5.0.0.r.j.w.0.0.0.e.e.l.l.t.e.e.e.e.t.t.e.e.e.j.l.l.l.l.j.t.e.e.e.e.e.e.j.l.l.j.t.e.0.e.j.e.e.e.e.t.e.t.j.e.e.e.j.l.l.j.t.e.e.e.e.e.e.", +"l.l.l.l.l.l.l.k.t.e.e.e.t.k.k.e.k.z.z.t.y.y.u.c.m.M.@XOX-X+X+X&X=X=X > > 4 9X9X9X2 1 i ( _ _ ....o.o.....T w > 1 2 1 2 i T p 2 2 9X9X9X2 2 s _ _ _ _ _ } %.5.{ o.o.o..._ _ s 4 2 9X9X9X9X4 , 1 1 > 2 9X9X9Xq 2 2 w 9X9X9X9X9X9X4 2 i R Y 2 1 9X9X9X9X4 4 9X9X9X9X9X9X2 4 p R p 2 2 9X9X9Xq 2 i _ ...._ s 9 , , > q s ( _ _ R q 2 9X9X9X9X2 2 s E E T Y p p p p p 3 , 4 9X9X9X2 2 R o.o.0.w.j.j.w.0.0.e.k.l.l.t.e.l.t.e.e.e.e.t.l.l.l.l.l.k.e.e.t.k.k.k.t.e.e.e.t.l.l.k.e.e.t.e.e.e.e.e.e.e.e.e.t.l.l.k.e.e.e.t.k.l.l.k.e.", +"z.z.z.z.z.z.z.z.z.z.k.z.z.z.z.e.t.z.z.b.b.c.b.b.M.n.~.@X;X;X,X1X2X2XqXuXxXA.L.K.P.K.K.P.K.P.P.K.K.P.K.K.P.K.P.A.N.V.`.]._.|./.* D.V.}.`.D.Y.L.L.L.P.P.P.P.P.P.P.K.K.Y.V.}.}.}._._.}.}.}.}.V.qX5X 1 , > 1 > > 4 ,X,X,X2 1 p _ ..o.o.o.o...R 3 3 ,X,X,Xq 3 p ......o.o.o.o.o.o.o._ _ T T T Y i 1 2 ,X,X,Xw 2 p E ....o.o.o.o.o.o.o.} _ E T T T T E ..E p 2 w ,X,X2 2 d ..o.o.7.w.w.w.0.0.0.0.0.7.o.o.o.E w 2 ,X,X,X,X1 1 t 3 , 4 ,X,X,X,X,X,X,X,X,X,X,X,X4 > 2 Y E p q 2 2 2 4 p p 4 , 3 ,X,X,X,X1 1 p Y 2 2 ,X,X,X2 2 Y _ _ _ d 2 1 ,X,X,X1 3 T .._ _ d 2 2 ,X,X,X2 2 Y E E E E p 4 2 1 2 1 , 4 ,X,X,X3 3 E o.w.0.0.w.h.k.z.z.z.z.k.e.e.k.z.z.z.z.z.z.z.z.z.z.z.z.e.t.z.z.k.k.k.k.z.z.z.k.k.e.e.e.e.e.k.z.z.z.z.z.t.y.e.e.e.t.k.z.z.z.z.k.k.k.z.z.", +"z.z.z.z.z.z.z.z.z.z.z.z.z.z.z.b.u.y.i.v.v.v.n.@X~.~.#X;X,X1X2X2XqXqXiX4X; L.K.P.P.K.K.K.K.K.P.K.P.P.U.A.N./.|.}.R.}.].'.}.V.Z.hXjXV.].'.V./.D.Y.P.P.K.K.P.L.P.K.K.K.P.A.`.}.{.}.|.}.{.}._.{.R.C.0X5X=X , > 2 ,X,X,Xq < w E ....5.} } } d 2 2 ,X,X,Xq 3 p ......o.o.o.o.o.o.o.o._ _ _ _ _ U 2 2 ,X,X,Xw 2 p E ....o.o.o.o.o.o.7.} o.o...} } _ _ _ _ U 2 2 ,X,X2 2 R o.o.7.7.w.w.w.0.0.w.w.w.7.7.5.} _ i 2 q ,X,X,X2 1 p p 1 2 ,X,X,X,X,X,Xw 2 2 2 2 1 > > w T E R d p Y p Y T T p 1 > 4 ,X,X,X2 1 p Y 2 2 ,X,X,X2 2 d _ ....Y 2 2 ,X,X,X3 2 T ...._ d 2 2 ,X,X,X2 2 p R R R p 4 , 1 2 2 2 w ,X,X,X,X3 t E 7.7.w.0.0.e.t.t.k.k.t.y.y.k.z.z.z.z.z.z.z.z.z.z.z.z.z.y.z.z.k.y.y.y.y.y.t.k.k.z.z.k.y.y.k.z.z.z.z.z.z.z.y.y.t.k.z.z.k.t.y.y.y.y.y.t.z.", +"z.z.z.z.z.z.z.z.z.z.z.b.b.b.b.b.b.i.i.i.i.OX~.+X~.!.#X,X1X1X2XqXuXiXiX- P.K.P.L.K.K.K.K.P.K.P.Y.A.N.V.`.].].|.R.).{.|.}.`.D.B.lXlXV.'.}.V.h /.D.Y.J.K.K.L.P.P.K.K.K.K.H./.{.}.}.}.{.{.{.{.{.}.h iX9X5X=X=X*X&X+X~.~.@XM.M.n.m.b.b.b.b.z.z.z.k.h.0.h.h.w.5.5.} } } } d q 2 #X#X#X#Xw , 4 i 9 2 #X#X#X#X1 2 R } } } } } } d 2 2 #X#X#X#X3 w E ....o.o.7.7.7.7.7.o.o.} } _ _ d 2 2 #X#X#X#X2 w T ......o.7.7.7.7.7.5.7.7.5.} } } } } _ d 2 2 #X#Xw 2 p ..7.5.0.w.h.h.w.0.w.w.0.0.5.} } } d 2 2 #X#X#X2 2 p Y w 2 #X#X#X#X#Xw , 1 3 2 2 2 2 q p R E R R U p U U U U i 1 > 2 #X#X#X2 1 p p 2 1 #X#X#X2 2 a R _ _ U 2 2 #X#X#X2 2 U ...._ d 2 2 #X#X#X2 2 a R R d q , 4 #X#X#X#X#X#X#X#Xw 3 U ..7.w.w.t.w.q.e.y.u.y.y.y.y.c.z.z.z.z.z.z.z.z.z.z.z.z.z.y.z.z.c.y.y.y.y.y.y.y.y.y.u.c.y.y.b.z.z.u.y.c.z.z.t.y.c.t.y.y.y.y.y.y.y.y.y.y.z.", +"b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.v.i.i.i.~.@X+X+X!.#X1X1X1X2XqXqXuXiXaXH.P.K.L.K.P.P.K.J.P.Y.- N./.`.{.}._.{.).x }.}.|.].g zXU.kXlXV.].].V.h [.R.H.L.K.K.K.K.P.K.K.K.K.Y.V.{.{.}.{.{.{.{.}.{.{.NXg 0X5X5X=X=X*X&X+X+X-X-XM.M.M.b.b.b.b.b.z.z.k.h.q.h.w.5.Q R R R R a q < q @X@X@X@X2 4 p R i 2 w @X@X@Xw 7 a } } } } } } R w 2 @X@X@X@X3 1 p ......o.7.7.7.7.7.7.5.} } } _ R q 2 @X@X@X@X2 1 p ^ ....o.7.7.7.7.7.5.7.7.5.} } } } } } d 2 2 @X@X@X2 t E 7.5.5.w.h.h.w.q.q.q.q.0.5.5.} } d 2 2 @X@X@X2 2 U E p 2 w @X@X@X@X2 1 p T U d d d d E E E R p w 2 2 2 2 2 1 > > 4 @X@X@X4 1 i p 2 1 @X@X@X2 2 a R R R d 2 2 @X@X@X2 2 U ...._ d 2 2 @X@X@X2 2 d R R d 2 < @X@X@X@X@X@X@X@X@X3 3 T 7.7.7.w.w.q.q.y.y.u.u.y.y.u.b.b.b.b.b.b.b.b.b.b.b.b.b.b.y.b.b.c.y.y.y.y.y.y.y.y.y.y.y.y.y.b.b.b.y.y.u.b.b.c.y.y.y.y.y.y.y.y.y.y.y.y.y.b.", +"b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.v.i.i.v.n.-X-X-X;X#X&X,X1X2XqXqXuXiXeX% Y.K.P.K.P.K.K.P.L.A.- R.]._.|.}.'.}.'./.R.}.).].R.zXU.kXlXkXN.`.}.h zX/.{.V.H.L.K.K.P.K.K.K.K.P.P.N.{.{.'.'.'.'.'.'.{.'.NXV.0XwXqX2X2X1X,X*X+X#X-X-XM.M.M.M.b.b.b.b.c.h.h.q.w.7.R r 7 7 7 7 1 < q n.n.n.n.9 2 p E E d 2 2 n.n.n.n.3 w R } } } } } } i 2 w n.n.n.w < q U ....5.7.7.7.7.7.5.} } 5.5...E p 2 q n.n.n.w < q U ....5.7.7.7.7.7.5.7.7.7.} } } } } } d 8 2 n.n.n.7 3 E 7.7.q.w.h.h.y.q.t.t.w.q.q.5.} } d 2 2 n.n.n.2 2 U E U 2 2 n.n.n.n.3 w E ..} } _ ......^ E p 8 < 1 2 2 2 2 2 2 w n.n.n.n.n.1 3 w 1 1 n.n.n.2 2 a E E _ U 2 2 n.n.n.2 2 U ...._ d w 2 n.n.n.2 2 d E E d q < q n.n.n.n.n.n.n.n.3 2 U 5.7.7.w.q.q.u.c.c.b.b.c.i.y.c.b.b.b.b.b.b.b.b.b.b.b.b.b.y.b.b.c.y.y.y.y.y.y.y.u.i.c.b.i.y.b.b.b.c.i.b.b.b.i.y.c.c.c.i.u.y.y.y.y.y.y.y.b.", +"b.b.b.b.b.b.b.b.b.b.b.b.b.m.n.i.i.n.M.-X-X-X;X;X,X*X=X w R E E R w 2 v.v.v.v.2 2 d ..5.5.} } } d 2 3 v.v.v.v.q < q p R E ..7.7.7.7.5.} 5.7.5.5...R 3 2 v.v.v.v.q < q p R E ..7.7.7.7.5.7.7.7.5.5.5.5.5.5.R 3 3 v.v.v.7 9 E 7.7.w.h.h.c.q.q.y.u.h.h.w.7.7.5.R 7 2 v.v.v.2 2 U E U 2 2 v.v.v.w 3 p ^ } } 5.........E U q < 8 v.v.v.v.v.v.v.v.v.v.v.v.v.1 > , > 2 v.v.v.2 2 U ^ ^ _ R w 2 v.v.v.3 3 R ..E E R i 2 w v.v.2 2 d E ! R a q < 1 2 w v.v.v.v.v.t < t E 7.7.q.q.t.h.c.b.b.b.b.b.v.i.c.b.b.b.b.b.b.b.b.b.b.b.b.u.b.b.b.i.i.i.i.i.c.b.b.b.c.v.i.y.v.b.b.b.b.b.b.c.u.y.i.c.b.b.b.b.c.i.i.y.i.c.b.", +"b.b.b.b.b.b.b.b.b.v.v.v.n.n.n.~.n.M.-X-X@X#X#X:X1X1X=X9XqXuXwXtX X& Y.J.K.K.P.L.N.D.[.NXNXV.NXPXPXPXNX[.`.h h `.}.{.R.zXvXD.lXkXlXgX[.'.h vXN.`.{.].V.U.K.J.K.K.K.P.P.K.A.[.[.NXNXPXPXPXfXPXPXPXPX* iXwXqX9X < > 2 c.c.c.2 2 U E E ! E p 2 q c.c.3 3 R ^ E ! E d 2 2 c.c.3 3 U ^ ^ ^ E U w 2 2 2 3 w c.c.c.c.q 9 d 5.7.q.u.h.c.c.c.u.v.b.b.b.i.v.m.b.b.v.v.v.b.b.b.m.b.b.i.i.b.b.b.b.b.b.b.b.b.v.i.i.i.v.i.i.v.b.b.m.m.b.i.i.v.v.i.i.v.b.m.m.m.b.b.b.m.b.", +"n.n.n.n.b.n.n.v.i.i.i.i.~.v.n.~.-X-X@X+X+X&X&X*X1X2X 2 t.t.t.t.t < q a U R ! } ! R q < q t.t.t.t.t.t.t.t.w 1 < 1 r d 5.7.5.} } } } R w < q t.t.t.t.t.t.t.t.w 1 < 2 t R 5.6.5.7.7.5.5.| } R 9 9 t.t.t.7 9 R 6.6.q.q.q.u.u.q.u.u.x.u.8.q.6.5.R 9 7 t.t.t.2 2 U E E i 2 w t.t.2 7 d } } 5.7.5.} } d 7 1 t.t.t.t.w 2 2 2 2 2 q t.t.t.t.t.2 2 i i 2 w t.t.t.2 q R ^ ^ ! a 7 w t.t.7 7 d ! ! ! ! d 2 2 t.t.2 2 d ! ! ! } } } 5.5.^ U q < w t.t.t.9 9 Q q.q.u.x.u.u.u.i.i.i.n.M.v.i.i.i.v.n.n.v.i.i.v.M.M.M.n.v.i.i.v.n.v.i.i.i.v.n.n.n.v.i.i.n.i.i.i.i.i.i.v.v.i.i.n.M.n.n.i.i.i.v.v.n.v.i.", +"M.M.M.M.n.~.~.n.M.M.M.M.-X@X+X~.-X;X#X&X&X&X=X=X2XqX9X6X0XaXaX* fXU.; A.PXPXPXPXPX[.`.].j ].}.}.}._.}.V.vXg [.'.].V.lXlXN.lXlXvXkXkXg ].V.vXlXD.`.{.}.}.].V.H.Y.K.K.L.K.P.* _.{.{.{.{.`.x ].[.NXPXPXN.rXrX0X5X5X2X2X*X&X*X;X;X-X-X@Xn.u.q.u.x.8.7.7.5.R 9 7 r.r.r.r.r.r.r.r.r.r.r.r.w 7 7 1 > > w r.r.r.r.r.w 9 9 9 w a Q ! R a w 2 2 w r.r.r.r.r.r.r.r.t 2 < 0 U E 5.} } } } ! U w 7 7 q r.r.r.r.r.r.r.r.w 2 < w U ! 5.6.6.6.6.5.5.E 9 9 r.r.r.9 9 R 7.6.q.u.q.u.x.q.q.q.u.u.8.7.7.5.R 7 7 r.r.r.3 2 U ! ! a 7 3 r.r.9 9 R } | 5.7.5.| } a 7 r r.r.r.q < q a U p q < q r.r.r.r.2 2 a a 2 2 r.r.r.2 1 a ! ! R w 8 r.r.r.w 7 a Q ! ! Q i 7 w r.r.2 2 d ! ! ! ! } 5.5.5.5.! a 1 7 r.r.r.9 9 E q.q.u.x.x.u.i.i.~.~.n.M.@X~.OXn.M.M.M.M.M.OX~.v.M.M.M.n.n.OXOX~.~.~.v.n.M.M.n.~.~.~.v.n.~.n.OXOXn.~.n.n.~.~.~.@Xn.M.M.n.OX~.~.~.OXv.", +"M.M.M.M.@X~.@XM.-X@X@X@X-X-X@X+X#X;X;X&X&X&X=X=X2XqX0X0XaXaXo KXPXC.zXPXPXPXNX[./.'.'.).|.'.}.{.{.}.].(.vXh '.}.x PXkXkXgXlXlXlXkXkXD.[.V.vXkXvXh |.}.}.|.].R.D.K.K.L.K.K.- [.}.{.}.}.`.x ].].'.`.NXNXrXrX0X0X9X2X2X=X*X,X;X;X#X@X@Xn.x.u.q.8.8.8.7.5.U 2 7 4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.4.w w 4.4.4.4.4.4.4.4.t 2 < q a ! ! E R i 1 > 1 q 4.4.4.4.4.4.4.4.r 7 9 i ! } } } } } ! R i 1 > 1 w 4.4.4.4.4.4.4.4.t 9 9 i ! 7.6.6.7.7.7.R 9 7 4.4.4.9 9 Q 7.6.q.8.u.q.x.u.q.q.q.q.q.8.7.5.d 7 r 4.4.4.9 9 U ! Q a 9 w 4.4.9 9 R 5.| 5.7.7.| Q r 7 4.4.4.4.7 q U E ! E a q 2 4.4.4.4.2 2 U U 2 7 4.4.4.w < w R ! d 7 9 4.4.4.4.7 w R ! ^ R q 2 4.4.4.2 2 U ! ! ! ^ 5.5.5.5.5.} d 7 9 4.4.4.9 9 ! q.q.u.x.x.u.i.~.~.OXM.M.OX~.n.M.M.n.n.M.M.M.OX~.n.M.M.M.M.M.n.OXOXn.M.M.n.@X~.~.~.OXM.@X~.M.OX~.n.@X~.M.@X~.~.~.~.@XM.M.M.n.OX@XM.M.", +"-X-X-X@X~.OX-X-X@X+X~.+X@X-X-X+X+X;X:X&X&X=X=X9XqXqX0XtXaXeX+ PXPXPXPXPXNX[.'.{.}.}.'.x ].].}.{.'.}.j vXzXV.].).V.lXkXD.vXlXlXkXkXlXzXR.R.zXlXU.N.[._.}.{.'.}./.A.Y.K.K.K.Y./.].].{.}.].j ].}.{.{.'.[.h rXrX0X9XqX2X=X,X1X,X#X!.!.OX@Xn.x.q.8.8.8.5.R w < r 3.3.3.3.3.r r 3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.3.q < w d ! ! E i 1 > > > 1 w 3.3.3.3.3.3.3.3.q 9 U } | } } } ^ ! i 1 > > > 1 q 3.3.3.3.3.3.3.3.w 9 U 5.6.7.7.7.5.R 7 7 3.3.3.9 7 Q 7.6.6.8.u.q.u.x.q.q.q.q.6.6.7.! t 9 3.3.3.3.9 9 U ! R w 9 3.3.3.7 9 E 7.6.6.7.7.6.Q 7 7 3.3.3.r 7 a ! ! ! ! ! a 9 w 3.3.3.9 w R U 7 1 3.3.3.3.9 7 i d i 9 r 3.3.3.3.7 7 U ! ! U 2 7 3.3.3.2 2 U ^ ! ! ! 5.5.5.5.5.} U 9 9 3.3.3.7 9 ! 8.q.u.x.x.~.~.~.~.@X-X@X~.@X-X-X@X~.~.@X-X-X@X~.@X-X-X-X-X-XOX~.@X-X-X@X~.~.~.~.~.@X-X~.@X-X+X~.@X@X~.@X-X+X~.~.~.~.OX@X-X-X@X~.@X-X", +"-X-X-X@X~.@X-X-X~.~.~.~.+X;X;X#X&X,X1X*X=X=X5XqXqXwX0XaXaXB.gXPXPXPXNX`.).'.}.{.{.}.}.R.].'.{.'.}.T.gXkXgX(.R.R.zXkXlXN.lXkXlXlXlXlXlXh /.zXlXlXN.j ].}._.|._.}.R.A.P.K.K.Y.h ].}.'.{.'.j ].|.}.{.}.`.h rXrX0XwXqX9X=X > > 1 2 2 7 7 q 2.2.2.2.2.2.9 t Q | | | / ! a 9 > > > 1 7 7 7 7 w 2.2.2.2.2.2.9 t Q 6.7.7.6.| Q 7 7 2.2.2.9 7 ! 8.6.6.q.8.8.q.8.8.q.6.6.6.6.| d 2 9 2.2.2.2.9 t R ! R 9 9 2.2.2.7 7 Q 7.6.6.8.8.6.Q 7 7 2.2.2.7 9 R ! ! ! ! ! U 9 9 2.2.w 9 a ! R r < r 2.2.2.2.r 7 7 1 9 2.2.2.2.2.r 7 a ! ! a 2 q 2.2.2.7 1 i U U R ! / 5.5.5.5.| R 9 9 2.2.2.7 9 ! 8.8.q.x.n.~.~.~.~.@X-X@X+X@X-X@X~.~.~.~.@X-X-X@X+X-X-X-X-X@X~.@X-X-X@X~.~.~.~.~.@X-X@X~.@X@X+X~.@X-X@X+X-X@X~.~.~.~.~.~.@X-X-X+X+X-X", +"-X-X-X@X~.-X-X@X~.~.~.~.!.+X;X;X&X*X1X,X=X5X5XqXqX0XtXaXsXo PXPXNXj '.|.R.'._.{.}.}.).T.'.}.}._.].V.zXkXB.V.|.N.vXlXlXA.lXvXvXlXlXlXlXV.[.D.kXlXjX+ [.'.).}.].}.|.`.N.Y.L.K.- `.}.{.}.'.j ].}.}.}.}.'.g yXrXrXwXqX5X9X2X.>.>.>.q < 0 a a r 9 9 9 9 9 9 r >.>.>.>.>.>.>.>.>.>.>.>.>.>.9 w U Q a 9 < < > > t a i q 1 > 1 r >.>.>.>.r 9 a ! | | ! U 9 < < > < r a i q 1 < 1 w >.>.>.>.t 9 a 5.7.6.6.| Q 7 7 >.>.>.7 r ! 6.6.6.6.8.8.q.8.8.8.6.6.6.| d q < t >.>.>.t 9 a ! | R 9 9 >.>.>.7 7 Q 8.8.6.8.8.6.Q 7 9 >.>.>.r 9 a ! ! ! ! Q a 9 r >.>.9 9 R / ! a 1 2 >.>.>.>.>.r 7 9 i >.>.>.>.>.>.7 q a a q 7 >.>.>.>.1 > 1 7 9 w a E ^ / / 5.! a 2 9 >.>.>.7 7 Q 8.u.u.i.n.OX~.~.~.-X-X+X+X-X@X~.~.~.~.~.+X-X-X@X+X-X-X-X-X@X~.-X-X@X~.~.~.~.~.+X-X-X+X+X-X@X~.~.+X-X@X+X@X-X+X~.~.~.~.~.+X-X-X@X+X-X", +"-X-X-X#X~.-X-X-X+X~.+X+X&X&X#X1X*X=X1X w U ! a i r 1 < r :.:.:.:.9 r Q | | Q r < q :.9 < q a Q a a r 1 < r :.:.:.:.9 r ! 8.6.6.| Q 7 7 :.:.t 7 a 5.6.6.6.6.8.8.6.8.8.8.6.6.| f 0 < w :.:.:.:.9 t ! 5.| R 9 9 :.:.:.7 7 Q 8.8.8.6.8.8.Q 7 9 :.:.:.:.9 q a ! ! Q a q 9 :.:.:.9 9 R 5.5.Q t < r :.:.:.:.:.:.:.:.:.:.:.:.:.:.r < 1 1 < r :.:.:.q > > > > 1 7 7 r a R R R a q < t :.:.:.7 9 Q 8.x.!.!.@X@X~.!.+X-X#X+X#X-X+X~.~.~.~.~.+X-X-X#X+X-X-X-X-X#X+X-X-X#X+X~.~.~.~.#X-X#X~.#X-X+X+X~.+X-X-X+X#X-X-X+X~.~.~.~.+X-X-X#X+X-X", +";X;X;X;X+X#X;X;X#X+X+X&X&X&X&X,X1X=X > > q G G r 9 9 9 9 9 7 9 t G G G G 9 y | 8.g.OX!.OX@X!.!.#X;X+X+X;X#X+X+X+X!.+X+X;X;X;X+X#X;X;X;X;X#X+X#X;X;X+X+X+X!.+X;X;X+X+X;X;X+X+X!.+X#X;X#X+X;X;X#X+X!.+X+X#X;X;X+X+X;X", +";X;X;X;X#X+X;X;X;X;X*X&X&X&X&X*X1X=X=X2X9X5XwXwXrXaXaX3X+ `.'.].j ].{.].j }.}.}.].].j ].}.'.].x D.kXlXlXN.`.g vXkXkXU.jXkXlXlXlXlXlXlXzXN.+ vXkXlXlXzXV.j '.}.}.}.}.}.R.).`.R.`.{.}.}.'.6 `.}.].].{.}.R.yXyXaXaX0XwXqX9X5X=X=X&X*X#XoXOX!.| i 7 G G G G G r < r Q 6.6.8.8.g.8.q.8.g.8.6.6.~ Q Q ! ! a r < t G G G G 7 7 a Q a 7 7 G G G 7 7 U ! ! ! ! f 7 7 G G G G 7 9 W | 5.R 7 7 G G G 7 7 a ! / / / U 7 9 G G G G 9 9 Q 8.8.8.! r 7 G G G 7 1 U / 6.6.6.6.6.8.8.| ! ! U t 9 9 t G G G G r < t ! 6.6.6.Q 9 7 G G r 9 f 6.6.8.8.8.8.8.6.f 9 t G G G G r 7 7 7 9 9 t G G G G 9 9 Q 8.6.6.| U 9 r G G G G G G G G t 9 r G G G G G G G G G G q > > > 1 G G G G G t 9 9 9 r G G G G G r 9 f 6.W.!.OXOXOX-X+X!.;X;X+X;X;X+X+X+X+X+X#X;X:X;X#X+X;X;X;X;X;X;X+X+X;X;X;X#X+X#X;X;X;X+X#X;X;X+X+X+X+X#X;X;X+X#X;X;X#X+X+X#X;X;X#X+X#X:X", +";X;X:X;X;X&X&X;X:X:X,X*X&X&X&X=X r F F F r < r Q 8.8.8.g.g.g.Q.W..Xg.Q.W.W.W.W.8.8.8.6.f 7 2 F F F F 7 1 i W a 7 7 F F F w 7 i ! / / ! a 1 7 F F F F 7 9 W | 6.W 7 9 F F F e 7 a ! / ! ! a 2 9 F F F F 9 9 Q 6.8.8.! 9 9 F F F r < w a W Q Q Q Q ! ! a r 9 9 9 t F F F F F r < r Q 6.8.8.8.Q 9 > 7 7 < y ~ 6.W.W.Q.8.W.8.8.| y 9 F F F F F F r 9 t F F F F F F 9 9 ! 8.8.6.6.! i 9 9 t F F F F F r < < < 0 F F F F F F F F q < 2 9 2 9 F F F F F F F F F F F F F F r < y | W.W.!.OXOX!.#X#X+X;X#X&X;X#X&X&X&X#X;X:X:X;X#X&X;X;X;X:X:X:X:X#X&X#X;X:X;X;X;X;X;X#X&X;X:X#X&X&X&X&X&X;X:X*X&X;X:X:X;X;X:X:X;X&X&X;X:X", +":X,X*X&X&X&X&X&X*X,X1X1X1X*X=X=X=X2X5X9X9X0XwXrXtXaXyX+ `.|.}.R.[.{.}.].R.].}.}.}.|.R.'.).}.`.(.kXlXlXvXg g vXlXkXkXA.vXlXlXlXlXlXlXlXlXvXO zXkXkXlXkXvXg }.}.R.x ).|.R.}.|.}.|.|.}.}.}.j `.{._.}.].].R.E.yXyXrXtXwX0X0X9X > 7 0 0 0 y Q 6.8..X.X.XOX!.!.!.OXOX!.W.W.W.W.W.8.8.8.~ r < t Z Z Z r < 0 U U 7 7 Z Z Z Z 7 9 a a U a 0 < r Z Z Z Z 7 9 Q | 6.W 7 9 Z Z Z Z 7 q a U f a 0 < r Z Z Z Z 7 9 Q 6.6.8.! 9 9 Z Z Z Z r < 7 7 7 9 9 9 9 9 9 9 9 y Z Z Z Z Z Z r < r Q 6.8.6.6.6.~ r > > > r ! 8.Q.W.W.Q..XQ.Q.Q.6.W 0 r Z Z Z Z Z Z Z Z Z Z Z Z Z Z 9 y / 8.8.8.8.6.~ W r < 7 0 9 9 9 9 y a e < 0 Z Z Z Z Z Z 0 < 0 a Q a 9 0 Z Z Z Z Z Z Z Z Z Z Z r 9 0 y ! 8.!.!.!.OX#X+X+X#X&X*X&X*X,X&X&X*X,X:X:X,X*X&X&X&X&X&X&X;X:X:X:X:X*X&X*X:X:X:X:X,X*X&X&X,X:X*X&X&X&X&X&X:X:X*X&X&X,X:X:X:X:X,X&X&X,X:X:X", +",X*X&X*X,X,X,X,X*X&X*X,X1X1XX>X%X%XoXoXoX.X!.!..X.XoXoXoXoXoXoXoXoX;X#X&X&X;X;XoXoXoXoXoXoX.XW.Q.8.Q r 9 b b b b < > < > 7 b b b b b b b b b b b b b b b r 0 W 6.8.8.8.! 9 7 b b b b b b b b b b b b b b b r 9 W 8.Q.Q.Q.8.! 0 0 b b b b b b b b b b b b b b b b b b b y 7 < r W / 8..X.XW.Q..X.X.X.X.X.XoXoXoXoXoX!.!.^.!.^.oXoXoXoXoX.XW.Q y 0 0 0 0 0 0 0 0 0 7 < r ! Q.W.Q..X.X.XoXoXoX.X.X.X.X.X.XW.Q..X.XQ.Q.8./ ~ ~ ~ ~ ~ / 8.8.8.8.8.8.8.~ ! W y 0 0 0 0 y W ~ 6.Q..X.XoXoX^.^.&X&X&X,X1X1X1X1X1X*X=X=X=X=X*X,X1X1X1X1X,X,X,X1X1X1X=X=X1X1X1X1X1X1X1X1X1X1X1X1X=X,X1X1X1X1X,X1X1X1X1X=X,X1X1X1X1X1X1X1X1X1X1X1X1X", +"=X1X1X1X=X=X=X=X=X > > > 7 b b b b b b b b b b b b b b r < y ~ 8.8.8.8.! 9 9 b b b b b b b b b b b b b b r < y / Q.Q.Q.Q.Q.~ 0 0 b b b b b b b b b b b b b b b y 0 0 0 0 0 y ! Q..X.X.X.X!..XoXoX!.^.!.^.^.XXoXoXoXoXoX&X^.%X,XoXoXoXoXoX.XW.| ~ ~ ~ ~ ~ ~ W y 0 0 y ~ Q..X!.!.oXoXoXoXoXoXoXoXoXoXoXoX!.!.!..X.X.X.X.X.XQ.W.W.Q..XQ.Q.Q.Q.Q.Q.Q.Q.Q.8./ ~ ~ ~ ~ ~ W.W.W.!.!.oXoXoX%X%X&X&X,X1X1X1X1X1X1X1X=X=X,X1X1X1X,X,X=X=X=X=X=X > 7 7 > 7 b b b b r r b b b b b y 0 0 0 y Q 8.Q.W.W.Q.~ 0 9 b b b b r r b b b b b y 0 0 0 y Q Q..X.X.X.X.X~ 0 7 b b b b y 0 0 0 0 0 0 0 0 0 0 0 0 0 y W ~ 6.Q..X.XoXoXoX^.oXoXoX^.^.^.^.^.^.^.&X&X&X*X&X&X,X,X,X$X&X%XoXoXXX!.!.Q.Q.W.W.W.W.| ~ ~ | W.oXoXoX^.%X%X%X%X%X%X%X%X%XoXoXoXoX^.^.^.XX.X.X.X!.!.W.!..X.X.X.X.X.X.X.X.X.X.X.X.XW..X.X!.W.W.^.^.^.^.^.^.&X$X*X*X$XX>X%X$X>X,X,X,X,X,X,X1X1X1X2X1X1XX=X$X>XX$X>X>X=X$X$X$X$X$X$X$X$X=XX>X>X$X$X%X%XXXXX^.^.^.^.^.^.^.$X%X%X$X$X>X>XX>X>X>X>X>X>X>X$X$X$X$X$X$X$X$X^.$X%X%X%X%X%X%X%X%X%X%X%X%X%X%X^.%X%X$X^.^.^.^.$X$X$X$X$X>XX%X%X%XXX.XQ.Q.Q.Q.Q.! 0 7 v v 7 7 f ~ ~ ~ ~ ~ 6.Q..X^.^.^.XXXXXX.X.X.X~ 0 7 v v 7 7 W 6.~ ~ ~ ~ ~ W.XX%X%X^.^.%X%X%X%X%X%X%XQ.6./ / / 6.W.W.Q..X.X.X.X.X^.^.^.XX%X%X%X%X%X%X%X>X>X>X>X>X$XX$X$X$X%X%X%X%X%X$X$X$X^.$X$X>X>X$X$XX>X>X>XX>X>X>X>X$X$X$X>X>X>X>X>X>X>X>X>X>X>X>X>X$X%X>X%X$X$X$X$X$X=X>X>X>X>X5X5X5XX>X%X%X%XXXXX.XQ.Q.Q.~ y < 7 7 < y ~ Q.Q.Q..XXX^.^.^.^.XX^.^.XX%X%XXXXX6.y 7 7 7 < y ~ Q..X.X.XXXXX%X%X%X%X^.$X%X%X%X%X%X%X%X%X%X%X%X%X^.^.XX%XXX%XXX%X%X%XXX^.XX%X%X%X%X>X>X>X>X>XX>X>X>X>X>X>X>X>X>X$X=XX>X>X>X$X$X>X>X>X>X>X>XX>X>X>X>X>X$X$XXX>X$XXXXXXXXX.XQ.Q.~ r > > r ~ Q..XXXXX^.^.^.$X$X%X%X$X$X^.$XXXXXXXW.~ e > > y ~ W.W.^.XXXX%X%X%X%X>X$X$X$X>X>X>X>X>X>X>X$X$X%X%X%X^.$X%X%X%XXX$X$X%X%X%X$X$X>X>X>X>X>X>XX>X>X>XX>X$X$X$X$X$X$X$X^.^.^.W.~ i y ~ Q.XXXX^.^.^.$X$X$X$X$X$X>X>XX$X>X>X>X$X$X$X$X$X>X>X$X$X>X$X$X5X5X5X5X9XqXqXqXqXqX9X5X9XqXqX9X9X5X9X9XqXqXqX9X9X9XqX5X5X5X5X5X5X9X9X5X5X9XqX9X9X5X6X6X6X6X6X5X6X6X9X9XqXqX8X8X8X6X6X6X$X6X9X9X5XqXqX9X5X6X6X6X6X8X8X6X6Xg E.6X6X6X6X6X9X9X9X9X9X9X5X5X5X9X9X9X6X6X6X6X8XX C.8X6X6X9X5X5X5X5X5X6X9X9X6X6X8X8X8X8X6X6X6X9X9X9X9X5X9XqXqXqXqXqXqX9X9X5X9X9X5X9XqX9XqXqXqX9X5X5X5X9XqXqXqX9XqX9X9X5X5X5X9XqXqXqXqXqX", +"uXqXwX0X0X0X0X0XwXwXuXiXwX0XrXrXtXaXtXaXyXyXsXMXVXN.o CXDX Xh '.}.}.}.'.R.].|.}.{.l j V.vXvXB.. . . * lXjXjXhXhXI.I.F.I.I.hXhXhXjXN. . * gXvXkXN.].].}.}.}.}.}.{.].j T.{.}.{.'.}.`.E.CXCXZXVXsXsXyXyXrXtXaXiXiXwX0X0X0X0X0X0XuXuXuXuXuXqX0X0X0XwXwXwX0X0X0X0XqXuXwX0X0X0X0X0XqXqX9X5X5X5X9X9X>X$X$X^.$X%XXXXXQ.W.W.W.^.^.^.^.$X>X>X>X>X5X5X5X5X9X6X>X$X$X>X$X$XXXW.W.W.$X%X%X%X$X$X$X5X5X5X5XqX9X9X9XqX9X5X5X5X9X9X9X5X6X5X6X>X>X>X5X5X6X6X6XX$X$X$X>X%X%X%X%X%X$X$X$X>X>X>X9X5X6X5X6X5X9X9X5X9X5X5X>X5X$X>X$X$X$X$X$X$X>X>X>X9X5X5X9XqXqXqXqXqXqX5X5X9XqXqXqXqX9X9X5X6X9X9X9X6X6X6X6X5X9XqX9X6X6XqXqXqXqXqXqX0X0XwXuXuXuXuXuXuXwX0X0XwXuXuXwX0X0X0X0X0XuXwX0XwX0X0XwXwX0XwX9X0X0X6X0X8X8X8X8X8XX C.8X8X8X8X8X8Xg & 7X8X8X8XE.X 8X8X6X6XwXwXwX6X7X7X7X7X X8X7XE.B.8X8XwXwXwX8X8X6X8X8X8XwXwXwXwXwX6X6X8X8X8X8X7XX g 7X7X8X8X6XwX0X0X8X8X6X8X7X7XE.7X7X7X8X8X8X8X6X8XwXwXwXwXwXuXwX0X0XwXuXuXuXuXuXwX0X0XwXuXwX0X0X0X0X0XwXuX0X0X0XwXuXuXuXuXuX0X0XwXuXuX", +"iXiXiXiX0X0XwXiXiXwX0XrXrXrXrXaXaXyXyXsXyXMXVXZXVXO nXCXDXC.R.}.{.{._.).).R.).}._.j + (.A. . * gXvXlXlXkXjXI.I.I.F.F.F.F.F.F.F.F.F.F.I.D.gXgXD.* . . . h ).}.}.|.}.].}.{.{.6 R.}.{.}._.].+ FXCXCXZXZXMXsXsXyXyXyXrXrXrXtXiXiXwX0XwXiXiXiXiXiXwX0XwXiXiXiXwXwXiXiXwX0XwXiXwX0X0X0X0X0XiXiX0X0XwXwXwX9X9XqX9X9X6X6X9X>X>X>X>X>X6X6X9X9X9X6X6X6X6X6X6X9XqX6X8X9X6X6X9X9X6X5X9X6X6X6X6X6X6X9X9X9X9X6X9XqXqXwXwXwX0X0X0XwXwXwXwXqXqXqX8X6X9XqX9X6X6X6X6X0XqXqX0X0XwXwXwXwXwXwXuXiX0X0XwXiXiXiXiXiX0X0XwXiXiXwX0X0X0X0X0XwXiX0XwXiX0X0XwXwX0XwXiX0X0X0X0X0X0X8X8X8X$ E.7X8X8X8X8X8XE.X 7X8X8X7X* & 8XwX0X0XwXwX8X7X7X7XV.% X & 7X7X7X8X8X8X8X8X8X8X7X7X8XwXwXwXwXwX0X7X8X8X8X7X7X3X$ g 7X7X8X7X8X8X7X7X8X8X7X7XB.$ X g 3X3X3X7X7X7X7X7X8XwXwXwXiXiXwX0XwXiXiXiXwXwXiXiXwX0XwXiXwX0X0X0X0X0XiXiX0X0XwXiXiXwXwXiXiXiX0X0XwXiX", +"iXiXiXwX0XwXiXiXwXrXrXrXrXrXtXaXtXyXsXsXyXMXVXZXVX* AXAXDXC.R._.{.}.].j V.V.].{._.6 O gXvX . B.zXvXlXlXlXlXkXhXI.I.F.F.F.F.F.F.F.F.F.F.F.I.F.hXjXlXlXvXD.O . . . |.].}.|.}.}.}.{.{.6 R.}.}.'.{.[.& FXCXCXCXZXVXVXdXsXyXyXrXrXrXrXtXiXiXwXwXiXiXiXiXwX0XwXiXiXwX0X0X0XwXiXiX0XwXiXiX0X0XrX0XwXiXwX0XwXiXwX0X0X0X0XwXqX9X6X6X8X8X8X8X9X6X6X8X8X8X6X6X6X6X6X0XwXwX0XwXwX6X6X9XqX6X6X8X6X6X6X6X6X6X6X8XqXwX0X0XwXiXwXiXwX0X0XiXiXwX0X0X0XwXwXwX0X0XwXwX0X6X0X6X0XwXwX0X0XwXwX0X0X0XwXiXiXwX0XwXiXiXiXiXwX0XwXiXiXwX0XrXrXrXrXwXiXwX0XwXwX0XrXwXiXwXwXiXwX0XrX0XrX7X7X7X4X$ V.3X4X4X4X4X7XE.X C.4X7X7X$ N.8XwXwXrXrXwX8X7X7X& # g B.X E.3X4X8X7XE.V.g g % X X X X % wXwX8X7X8X8X8X7X7XE.3X$ g 3X4X7X7X7X8X7X7X7X4X7X$ $ N.* # E.# V.3X3X4XE.7X7X8XwXwXiXwX0XwXiXiXwX0X0X0XwXiXiX0XwXiXiX0X0XrX0XwXiXwX0XwXiXiXwX0X0XwXiXiXwX0XwXiX", +"iXiXiXwXrXiXiXwXrXrXrXrXrXrXaXaXyXyXsXsXyXMXVXZXD. XAXAXFXE.R.{.{.{.}.6 V.V.`.{.'.6 o vXlXO zXzXlXlXlXlXkXkXjXI.hXhXF.F.F.F.F.F.F.F.F.F.F.F.hXhXhXkXkXlXlXlXgXo g ).].}.|.}.}.}.{.}.6 R.{.'.}.{./.FXFXCXCXCXZXVXMXsXsXyXyXyXrXrXrXtXaXiXtXrXiXiXiXiXwXrXwXiXiXrXrXrXrXrXwXiXwXrXiXiXrXrXrXrXwXiXtXrXiXiXwXrX0X0X0X0XwXwX0X6X8XqX8X8X8X6X8XqX8X6X0X0X0X0X0XwXwX0X0XwXwX0X0X0XwX8X6X8X8X8X6X6X6X6X6X0XwXwXwX0XiXiXiXiXwXrXwXiXiX0X0X0X0X0XwXiXwX0XwXwX0X0X0X0XwXiXwX0XwXiXwXrXrXrXrXtXiXiXrXrXiXiXiXiXwXrXiXiXwXrXrXrXrXrXrXiXiXrXrXiXwXrXrXrXiXwXrXwXiXtXrXrXrX7X7X7X4X$ * 3X4X4X4X4X3X3X# C.3X3X3X# 7X7XeXwXeXrXeXeX7X% $ E.3X3X% C.3X4X7XV.g g g g g C.E.E.E.eXeXeXeX7XeXeXE.& # # 3X$ g 3X4X3XE.E.7X7X7X7XC.$ & 3X X X# V.@ g E. X* X V.3XeXeXwXiXwXrXwXiXiXrXrXrXrXrXwXiXwXrXiXiXrXrXrXrXwXiXtXrXiXiXtXrXrXrXrXtXiXiXrXrXiX", +"aXaXaXtXrXaXaXaXrXrXrXrXrXtXaXaXyXsXsXyXMXMXMXZXZXCXCXAXFXE.R.}.}.}.[.6 D.zX/.{.].(.N.vXkXvXkXkXjXjXgXkXjXkXhXjXjXjXI.F.I.I.F.hXF.I.hXhXF.hXhXI.kXkXkXlXkXlXlXvXO V.|.}.}.}.}.}.}.{.].6 R.{.'.}.}.g FXDXCXCXCXZXZXVXVXdXsXyXyXyXrXrXtXaXaXtXrXaXaXaXaXtXrXaXaXtXrXrXrXrXrXtXaXaXrXtXaXtXrXrXrXaXaXrXtXaXaXrXrXrXrXrXrXiXiXwX0XwXwXwXwX0X0XwXwXwX0XrXrXrXrXtXaXtXrXtXiXrXrXrX0XwXwX0X0XwXwX0X0X0X0XrXrXiXiXtXrXaXaXaXaXtXrXaXaXtXrXrXrXrXrXtXaXaXrXtXaXtXrXrXrXaXaXrXtXaXaXrXrXrXrXrXtXaXaXtXrXaXaXaXaXtXrXaXaXaXrXrXrXrXrXtXaXtXrXtXaXtXrXrXrXaXaXrXtXaXaXrXrXrX7X7X7X4X$ @ & V.3X3X3X3X3X% % 3X3XV.$ 3X7XeXeXeX7XeXeX& & 3X X X X% C.& * 3X7X7X7X7XeXtXeXeX7XeXeXeXeXeX7X3X& X % g g 3X$ g 3X3XE.# % 3X3X3X3X$ N.3X X X X# E.# V.E.V.@ @ % 3X4XeXeXaXtXrXaXaXtXrXrXrXrXrXtXaXaXrXtXaXtXrXrXrXaXaXrXtXaXaXrXrXrXrXrXtXaXaXtXrXaX", +"aXaXaXtXrXtXaXaXtXrXrXrXtXaXaXyXyXsXsXMXMXMXMXZXAXCXCXAXFXE.R.|.}.]./.g D.vXN.|.R.PXD.gXkXlXkXjXD.jXD.kXkXjXjXkXjXjXI.hXhXhXhXhXI.hXjXhXhXjXjXjXkXkXjXkXkXkXjXkXC./.|.}.}.}.}.}.}.}.].6 R.{.}.}.|.g FXDXCXCXCXZXZXVXMXdXdXsXyXyXyXyXaXaXaXtXtXaXaXaXaXtXrXaXaXaXrXrXrXrXrXrXtXaXtXrXaXaXrXrXtXaXtXrXaXaXtXrXrXrXrXrXtXaXaXtXrXtXiXwXiXtXrXtXiXaXrXrXrXrXtXaXaXtXtXaXaXrXrXrXrXtXaXtXrXwXaXtXrXrXrXrXtXaXaXrXtXaXaXaXaXtXrXaXaXaXrXrXrXrXrXrXtXaXtXrXaXaXrXrXtXaXtXrXaXaXtXrXrXrXrXrXtXaXaXtXtXaXaXaXaXtXrXtXaXaXtXrXrXrXtXaXaXtXtXaXaXtXrXrXrXaXaXtXtXaXaXtXrXrX7X7X4X4X% # # @ # % N.3X3XC.# E.3X& * 3X7X7XeXeXeX7Xg g 3XE.E. X= # E.% * 3X7X7X7X7XeXaXtXeXeXeXeXeXeX4XE.X % C.3X3X3X3X% g 3X3X& @ @ V.3X3X& V. X XE.E.= # (.# = E.% @ # # 3X4XeXeXaXtXrXaXaXaXrXrXrXrXrXrXtXaXtXrXaXaXrXrXtXaXtXrXaXaXtXrXrXrXrXrXtXaXaXtXtXaX", +"aXaXaXaXtXtXaXaXaXyXyXyXsXsXsXyXsXdXdXMXMXMXVXCXAXAXCXFXFXE.R.}.{.].g h N.vXgX`.h vXgXU.jXjXjXjXjXjXjXjXkXjXkXkXjXjXjXjXjXjXjXjXjXjXkXjXkXkXkXkXkXkXkXjXjXjXjXkXV.].{.{.}.|.}.}.}.).|.j T.}.}.}.R.Z.FXDXDXCXCXCXZXZXMXVXdXsXsXyXyXsXaXaXaXyXaXaXaXaXaXaXtXtXaXaXtXrXrXrXrXrXtXaXaXtXaXaXtXrXtXaXtXtXaXtXrXrXrXrXrXtXaXaXaXrXtXaXaXaXaXaXrXtXaXaXaXtXtXtXaXaXaXyXtXaXaXrXrXrXrXtXaXaXrXtXaXaXtXrXtXtXaXaXaXyXaXaXaXaXaXaXtXtXaXaXtXrXrXrXrXrXtXaXaXtXaXaXtXrXtXaXtXtXaXtXrXrXrXrXrXtXaXaXaXtXtXaXaXaXaXaXtXtXaXaXaXtXtXtXaXaXaXyXtXaXaXtXrXrXyXtXaXaXrXtXaXaXtXeXeXeX4X4X% % XV.& # @ & 3X X% % 3X# V.3X7X7XeXeXeXeX4X4X3XV.% # @ # X% g 3X7X7XeXeXtXaXtXeXeXeXeXeXeXE.X g 4X4X4X3X3X3Xg % 3XE.# g # & 3X3X3X X XN.% # # & (.# = V.@ & C.@ N.4X4XeXpXtXrXtXaXaXtXrXrXrXrXrXtXaXaXtXaXaXtXrXtXaXtXtXaXtXrXrXrXrXrXtXaXaXaXtXtXaX", +"aXaXaXaXaXyXyXaXaXaXsXsXsXsXyXyXsXdXVXMXMXMXVXCXAXAXCXDXFXE.V.{.{.`.= V.V.vXlXV.h zXjXD.jXjXhXjXlXkXjXjXjXkXkXkXkXkXkXkXjXkXlXlXlXlXlXkXkXkXkXlXkXkXjXjXjXjXhXjXV.].{.}.}.}.}.}.].R.}.j ).|.|.{.h HXFXDXDXCXCXCXZXZXVXMXdXdXdXsXsXsXsXsXyXyXaXaXaXaXaXaXyXyXaXaXaXaXyXyXyXyXyXyXaXyXyXaXyXyXaXaXyXaXaXyXyXyXyXyXaXaXaXaXtXyXaXaXaXaXaXaXtXyXtXaXaXaXaXaXaXaXyXyXaXaXaXyXyXrXyXyXaXaXyXyXaXaXaXaXaXaXaXaXyXyXaXaXaXaXaXaXyXyXaXaXaXaXyXyXyXyXyXyXaXyXyXaXyXyXaXaXyXaXaXyXyXyXyXyXaXaXaXaXyXyXaXaXaXaXaXaXaXyXyXaXaXaXaXaXaXaXyXyXaXaXaXyXyXyXyXyXaXaXyXyXaXaXaXaXeXeX4X4Xg # X X XC.# # 3X XN.@ % # 3X3X4XeXeXeXeXeX4X4X= @ # % # % X% g 3X4XeXeXpXaXaXeXeXtXeXeXeXE.X B.3X4X4X4X4X4X4XN.# X& % X= # 3X3X3XbX% @ # % # = (.# % # % XbX# % 4XeXeXeXaXyXyXaXaXaXaXyXyXyXyXyXyXaXyXyXaXyXyXaXaXyXaXaXyXyXyXyXyXaXaXaXaXyXyXaXaX", +"sXsXsXsXsXyXyXsXsXsXsXsXsXyXyXyXdXdXVXMXMXVXCXCXAXAXDXDXFX Xh }.{.V.fXV.'.h zXV.V.zXlXB.jXhXhXI.hXhXhXhXjXkXkXkXkXlXlXlXF.jXlXlXlXlXjXkXlXkXkXlXkXjXjXjXjXjXhXjXh '.}.}.}.}.}.'.R.[.).j {.{.{.}.g HXFXDXDXDXCXCXZXZXVXMXVXVXdXdXdXsXsXyXyXsXsXsXsXsXsXsXsXyXyXsXsXsXsXsXyXyXyXyXsXsXyXsXsXyXsXsXyXsXsXyXyXyXyXsXsXsXsXyXyXsXsXsXsXsXsXsXsXyXyXsXsXsXsXsXsXyXyXyXsXsXsXyXyXyXyXyXsXsXsXyXyXsXsXsXsXsXsXyXyXsXsXsXsXsXsXsXsXyXyXsXsXsXsXsXyXyXyXyXsXsXyXsXsXyXsXsXyXsXsXyXyXyXyXsXsXsXsXyXyXsXsXsXsXsXsXsXsXyXyXsXsXsXsXsXsXyXyXyXsXsXsXyXyXyXyXyXsXsXsXyXyXsXsXsXpXeX4X3Xh # C.bXbXC.# % bXbXbX% @ # % 4X4XeXeXeXeXeX4XC.@ % E.V.# % bX% g 3X4XeXpXpXsXyXyXpXpXyXeXeX% & 4X4X4X4X4X4X4X4XC.@ & @ C.3XE.@ E.bXbXg @ = (.k # = fX% @ # C.bXbX& X V.eXeXpXsXsXyXyXsXsXsXsXsXyXyXyXyXsXsXyXsXsXyXsXsXyXsXsXyXyXyXyXsXsXsXsXyXyXsXsXsX", +"sXsXsXsXsXsXsXyXyXsXsXsXyXyXsXMXZXZXVXMXMXCXCXCXAXAXFXDXFXE.g |.{.g IXh ).l g V.V.vXvXN.jXhXI.I.I.I.hXhXjXjXkXkXlXlXkXlXN.Z.Z.Z.Z.Z.Z.N.lXkXkXlXkXjXjXhXhXI.I.hXh }.}.}.}.].}.}.j ].R.j |.'.'.'.g HXFXDXDXDXCXCXAXZXVXVXVXMXVXVXsXyXyXyXsXdXsXsXsXsXyXyXyXyXyXyXyXsXsXsXsXsXyXyXyXsXyXyXyXyXsXyXsXsXyXyXyXsXsXsXsXsXyXyXyXyXyXyXsXsXsXsXsXsXsXyXyXsXsXsXyXyXsXyXsXsXsXyXyXyXyXyXsXsXsXyXyXyXyXsXsXyXyXyXsXdXsXsXsXsXyXyXyXyXyXyXyXsXsXsXsXsXyXyXyXsXyXyXyXyXsXyXsXsXyXyXyXsXsXsXsXsXyXyXyXyXyXyXsXsXsXsXsXsXsXyXyXsXsXsXyXyXsXyXsXsXsXyXyXyXyXyXsXsXsXyXyXyXyXsXyXeX4XnXC.@ # & % # % E.bXbXbXE.# X g 4XeXeXeXeXeXeXnXg @ % & @ @ # bX% % 4XeXpXpXyXyXyXyXyXyXeXeXeXX % 4X4X4XnXE.g * E.bX# X & bXbXbX# & bXbX% @ = % @ @ & bX% @ N.bXbXbXC.X X E.eXeXyXyXyXyXyXyXsXsXsXsXsXyXyXyXsXyXyXyXyXsXyXsXsXyXyXyXsXsXsXsXsXyXyXyXyXyXyX", +"dXdXdXdXdXdXdXsXsXyXyXyXsXdXVXMXVXZXZXVXCXCXCXAXAXAXDXDXFXFXg ).].N.IXh T.l l j 6 g V.+ zXhXI.I.I.I.I.hXjXjXkXlXlXlXlXjXZ.S.S.Z.Z.Z.Z.N.lXvXlXlXkXjXhXhXI.I.I.hXV.{.}.}.}.].'.|.T.'.R.j |.R.|.R.D.HXFXFXDXDXCXAXAXZXVXVXZXVXVXMXMXMXsXdXdXdXdXdXsXyXyXsXsXsXsXsXyXyXyXsXsXdXsXyXyXsXyXyXyXyXyXyXyXyXyXsXdXdXsXyXyXyXsXsXdXsXsXyXyXsXdXdXdXdXdXsXsXyXyXyXsXsXsXyXsXdXsXsXyXyXyXsXdXdXsXyXdXsXyXyXyXyXsXsXdXdXdXdXsXyXyXsXsXsXsXsXyXyXyXsXsXdXsXyXyXsXyXyXyXyXyXyXyXyXyXsXdXdXsXyXyXyXsXsXdXsXsXyXyXsXdXdXdXdXdXsXsXyXyXyXsXsXsXyXsXdXsXsXyXyXyXsXdXdXsXyXdXsXyXyXyXeXeXeX4X# X # % N.bXbXnXnXnXbX$ $ nXnXeXyXpXyXmXeXnXE.# # # # % V.bX& X E.eXeXyXyXyXsXdXsXsXyXmXeXB.X $ $ X X $ N.nXnXnX$ # XnXnXnX% # E.bXN.# # # # & E.bXV.h bXbXnX4X4X* B.eXeXyXyXsXsXsXsXyXyXyXsXsXdXsXyXyXsXyXyXyXyXyXyXyXyXyXsXdXdXsXyXyXyXsXsXdXsXsXyX", +"dXdXdXdXdXdXdXdXdXdXZXZXZXZXZXMXVXZXZXZXZXAXAXAXAXAXDXFXHXSX+ ]./.(.IX& T.l z l l l l 6 zXhXI.I.I.I.I.hXhXjXkXlXlXkXkXlX= Z.S.S.S.Z.S.N.lXlXlXlXjXhXhXhXI.I.F.hXR.{.'.{.'._.'.V.].}.x l |.j '.6 GXJXHXFXFXFXAXAXAXAXCXVXZXZXZXZXZXZXZXZXdXdXdXdXVXMXVXdXdXdXdXdXdXdXVXMXMXVXdXdXVXMXMXVXdXdXdXVXMXMXVXdXVXMXMXMXVXdXdXdXdXdXdXdXVXMXVXdXdXdXdXdXdXdXdXdXdXdXdXMXVXdXdXdXdXdXdXdXdXdXMXVXdXdXdXdXdXdXdXdXdXdXdXdXVXMXVXdXdXdXdXdXdXdXVXMXMXVXdXdXVXMXMXVXdXdXdXVXMXMXVXdXVXMXMXMXVXdXdXdXdXdXdXdXVXMXVXdXdXdXdXdXdXdXdXdXdXdXdXMXVXdXdXdXdXdXdXdXdXdXMXVXdXdXdXdXsXpXBXmXmXE.C. XnXnXnXnXnXnXnXnX# C.nXnXmXmXpXsXMXmXmXnXnXnXbXbXbXbXnXV.& mXmXmXVXsXdXdXdXdXdXsXmXmXmXmXE.E.E. XmXmXmXmXmXB. XnXnXnXnXN.X C.nXnXnXbXbXbXnXnXnXnXnXnXnXmXmXmXmXBXmXmXVXdXdXdXdXdXdXdXVXMXMXVXdXdXVXMXMXVXdXdXdXVXMXMXVXdXVXMXMXMXVXdXdXdXdXdXdXdX", +"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXVXVXZXZXZXAXAXAXAXAXDXDXFXHXSX+ `.g JXIX& T.z z z z l l g = jXhXI.I.I.I.hXjXjXkXlXlXlXkXlXZ.Z.Z.Z.Z.Z.k jXlXlXkXkXjXjXhXhXI.I.I.hXR.|.'.}.}.}.}.j '.}.j j '.T.|.& GXGXHXHXFXFXAXAXAXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXMXVXZXZXZXVXVXZXZXZXZXZXVXVXMXVXMXVXVXZXZXZXZXZXVXMXVXMXMXVXVXZXZXZXZXVXVXVXZXZXZXMXMXZXZXZXZXZXZXZXZXZXZXZXZXVXMXVXZXZXZXZXZXZXVXVXMXZXZXZXZXZXZXZXZXZXZXZXZXZXMXVXZXZXZXVXVXZXZXZXZXZXVXVXMXVXMXVXVXZXZXZXZXZXVXMXVXMXMXVXVXZXZXZXZXVXVXVXZXZXZXMXMXZXZXZXZXZXZXZXZXZXZXZXZXVXMXVXZXZXZXZXZXZXVXVXMXZXZXZXZXZXZXVXBXBXBXmXmXmXnXmXmXmXmXnXnXnX# E.mXmXmXmXMXMXMXmXmXmXmXnXnXnXnXnXnXnXmXmXBXVXVXVXZXVXVXVXVXVXVXmXmXBXBXBXBXBXBXBXBXBXBXmXmXmXmXmXmXmXE.mXmXnXnXnXnXnXnXnXmXmXmXmXBXBXBXBXBXBXMXVXVXZXVXVXVXZXZXZXZXZXVXVXMXVXMXVXVXZXZXZXZXZXVXMXVXMXMXVXVXZXZXZXZXVXVXVXZXZX", +"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXVXCXCXCXAXAXAXAXDXDXFXHXHXHX+ [.+ IXIX& T.z l l z l l E.KXZ.jXI.I.I.hXhXjXkXlXlXlXlXlXlXlXF.Z.N.Z.Z.lXlXlXkXkXkXjXjXhXhXI.I.I.F.`.{.{.'.'.|.T.j `._.j l j |.`.N.GXGXGXFXFXFXFXAXCXCXAXAXAXZXZXZXZXZXZXZXZXZXZXZXVXZXZXZXVXMXMXVXVXVXVXZXZXZXZXVXMXVXZXZXZXZXZXZXZXVXMXVXZXZXZXZXVXVXVXMXMXMXVXZXZXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXVXVXVXVXVXVXVXVXVXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXVXZXZXZXVXMXMXVXVXVXVXZXZXZXZXVXMXVXZXZXZXZXZXZXZXVXMXVXZXZXZXZXVXVXVXMXMXMXVXZXZXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXVXVXVXVXVXVXVXVXVXVXVXZXZXZXZXZXZXZXVXVXBXBXBXBXmXBXBXmXmXmXnX X# XmXmXBXBXVXVXMXVXBXBXBXmXmXmXmXmXmXmXBXBXVXVXVXVXVXMXMXMXVXZXZXBXmXBXBXBXBXBXBXBXBXBXBXBXBXBXmXmXmXmXmXmXmXmXmXmXmXmXmXBXBXBXBXBXBXBXBXVXVXVXMXVXZXVXVXMXMXVXVXVXVXZXZXZXZXVXMXVXZXZXZXZXZXZXZXVXMXVXZXZXZXZXVXVXVXMXMXMXVXZX", +"ZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXZXAXCXCXCXCXCXCXDXDXDXFXFXHXHX+ (.JXIXIX+ R.z z l l z j UXUXg V.gXI.I.hXhXjXkXkXlXlXlXlXlXlXkXlXlXkXlXlXlXlXkXkXkXkXjXhXhXhXI.hXN.`.{.{.}.}.'.j 6 `.}.j R.+ '.x JXJXGXGXGXFXFXDXDXDXCXAXAXAXAXAXZXZXZXZXZXZXZXZXZXVXZXZXVXMXMXVXVXVXMXVXVXVXVXZXVXVXZXZXZXVXVXZXZXZXVXVXVXVXVXVXVXMXMXVXVXVXVXVXZXZXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXZXVXVXVXVXVXVXVXVXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXVXZXZXVXMXMXVXVXVXMXVXVXVXVXZXVXVXZXZXZXVXVXZXZXZXVXVXVXVXVXVXVXMXMXVXVXVXVXVXZXZXVXVXZXZXZXZXZXZXZXZXZXZXZXZXZXZXVXVXVXVXVXVXVXVXVXVXZXZXZXZXZXZXZXZXZXVXBXBXBXmXVXBXBXmXmXmXE.X mXmXmXmXBXVXVXMXZXZXVXmXmXBXBXBXmXmXBXBXMXMXMXMXMXVXVXVXVXMXZXZXVXMXVXVXVXVXVXVXVXVXVXVXVXVXVXVXMXmXmXmXmXmXmXmXmXmXBXBXBXBXVXVXZXZXZXZXZXZXZXMXZXZXVXMXMXVXVXVXMXVXVXVXVXZXVXVXZXZXZXVXVXZXZXZXVXVXVXVXVXVXVXMXMXVXVXVXVXVXZX", +"ZXZXZXZXZXZXZXZXZXZXZXZXAXAXAXAXAXCXCXCXCXAXDXDXDXFXFXHXHXJXB.g JXIXIX& R.z z z l l g UXUXh l o N.gXzXkXkXkXkXkXlXlXkXlXlXlXkXkXkXkXlXlXlXlXkXkXkXkXjXhXjXzXV.+ |.{.}.}.}.|.6 6 [.|.g + & `.g JXJXGXGXGXFXFXFXDXDXAXAXAXAXAXAXAXAXAXZXZXZXZXZXZXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXAXZXAXCXCXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXZXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXCXCXCXCXCXCXCXCXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXAXZXAXCXCXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZXZXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXCXCXCXCXCXCXCXCXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXMXZXZXCXmXmXmXE.X E.mXmXmXMXMXCXCXZXZXZXCXMXCXZXZXCXMXMXMXMXCXCXCXCXCXCXCXCXCXZXZXCXCXZXZXZXZXZXZXZXZXZXZXZXZXZXCXMXMXCXMXCXCXMXMXCXZXZXZXZXZXZXZXZXZXZXZXZXZXZXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXAXZXAXCXCXCXZXZXCXCXCXCXCXCXCXCXCXCXCXCXCXCXZX", +"AXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXFXFXFXDXFXHXHXJXh & JXIXIX= R.z z z z l V.UXUX& l + h j g (.zXzXkXlXlXlXkXlXlXlXlXlXkXkXlXlXkXkXkXkXkXjXjXlXgXg j 6 |.{.}.{.}.j l j [.].+ N.& [.* IXGXGXGXHXHXFXFXFXDXDXAXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXCXCXCXCXAXAXCXCXAXAXAXAXCXAXAXAXCXCXAXAXCXCXCXCXCXCXCXCXCXCXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXCXCXCXCXAXAXCXCXAXAXAXAXCXAXAXAXCXCXAXAXCXCXCXCXCXCXCXCXCXCXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXCXmXmXmXmXX B.mXmXCXCXAXCXCXAXAXAXCXCXAXAXAXCXCXAXAXCXCXCXCXCXCXCXCXCXCXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXCXCXCXCXAXAXCXCXAXAXAXAXCXAXAXAXCXCXAXAXCXCXCXCXCXCXCXCXCXCXAX", +"AXAXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXFXFXFXFXFXFXFXFXHXJXJXSXJXIXIXxXR.l l z z j UXUXUX& V.g & j l j g V.gXzXzXlXlXlXlXlXlXlXvXkXlXlXkXkXlXlXzXgXD.g j l l 6 |.}.{.}.|.6 l l R.).+ KXfX(.(.LXGXJXJXJXHXHXFXHXFXFXDXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXAXCXCXCXCXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXAXCXCXCXCXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXMXCXCXbXnXCXAXAXAXCXCXCXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXAXCXCXCXCXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXCXCXCXCXCXAXAXAXAXAXCXCXCXAXAXAXAXAXAXAXAXCXCXCXAXAXAXAXAXAXCXCXCXCXAXAX", +"AXAXAXAXAXAXAXAXAXAXAXAXAXAXAXDXAXAXFXFXFXFXFXFXHXHXGXGXJXJXJXJXIXIXIXxXh l l l l + UXUXUX(.x KX& x l l l l j j h (.zXzXlXlXlXlXkXkXlXkXlXzXgXV.h j j l l l l 6 |.}.}.}.R.l z l 6 R.Z.UXfXh N.LXJXJXJXJXGXGXFXFXFXFXDXDXFXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXCXCXCXAXCXCXAXAXAXAXAXAXCXCXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXCXCXCXAXCXCXAXAXAXAXAXAXCXCXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXCXCXCXCXAXCXCXAXAXAXAXAXAXCXCXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXCXAXAXAXAXAXAXAXAXAXAXAXAXAXCXCXAXAXAXAXAXAXAXAXAXAXCXCXCXAXCXCXAXAXAXAXAXAXCXCXAXAXCXCXAXAXAXAXAXAXAXAXAXAX", +"AXAXAXAXAXAXAXAXDXDXDXDXDXAXAXDXFXFXFXDXDXDXDXFXHXHXGXGXJXGXGXLXLXLXIXIXg l l l l NXUXUXUXfXh KXD.j z z z l l l j 6 + & A.jXlXlXjXD.A.N.* g j l z l l l l l z 6 }.'._.|.j l z l 6 V.D.UXKX& fXLXJXJXJXGXGXGXGXFXHXFXFXDXFXDXDXDXDXDXDXAXAXAXAXAXAXDXAXAXAXAXAXAXAXAXDXDXDXAXAXAXDXDXDXDXAXAXAXDXDXDXAXAXAXAXDXDXDXAXAXAXAXAXAXAXDXDXDXAXAXAXAXAXDXDXDXDXDXAXAXDXAXAXAXDXDXDXDXAXAXAXAXDXAXDXDXDXDXDXDXAXAXAXAXAXAXDXAXAXAXAXAXAXAXAXDXDXDXAXAXAXDXDXDXDXAXAXAXDXDXDXAXAXAXAXDXDXDXAXAXAXAXAXAXAXDXDXDXAXAXAXAXAXDXDXDXDXDXAXAXDXAXAXAXDXDXDXDXAXAXAXAXDXAXDXDXDXDXDXDXAXAXAXAXAXAXDXAXAXAXAXAXAXAXCXDXDXDXAXAXAXDXDXDXDXAXAXAXDXDXDXAXAXAXAXDXDXDXAXAXAXAXAXAXAXDXDXDXAXAXAXAXAXDXDXDXDXDXAXAXDXAXAXAXDXDXDXDXAXAXAXAXDXAXDXDXDXDXDXDXAXAXAXAXAXAXDXAXAXAXAXAXAXAXAXDXDXDXAXAXAXDXDXDXDXAXAXAXDXDXDXAXAXAXAXDXDXDXAXAXAXAXAXAXAX", +"FXFXFXFXFXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXFXGXGXHXJXGXGXGXGXJXIXIXIXIXIX* l l l 6 UXUXUXUXUX* KXUXg l l l z j j V.fXfX* S.- - = N.Z.S.Z.g j j j l z l + R.l l 6 |.'.}.R.j l z l o g gXUXUX* IXIXIXJXJXGXGXGXGXGXHXHXFXFXFXFXFXFXFXFXDXDXFXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXFXDXDXDXDXDXDXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXDXDXFXFXFXDXDXDXFXFXFXFXDXDXFXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXFXDXDXDXDXDXDXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXDXDXFXFXFXDXDXDXFXFXFXFXDXDXFXFXFXFXFXDXDXDXFXFXFXDXDXDXDXFXFXFXFXDXDXFXDXDXDXDXDXDXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDXDXDXDXFXFXFXDXDXDXFXFXFXFXDXDXFXFXFXFXFXDXDXDXFXFXFXDXDXDXFXFXFXFXFXDXDXFXDXDXDXDXDXDXFXDXDXDXFXFXFXFXDXDXDXFXFXFXDXDX", +"FXFXFXHXFXFXDXFXFXFXFXFXFXFXDXDXFXFXFXDXFXGXGXGXHXJXGXGXGXJXJXIXIXIXIXUXB.j l l + UXUXUXUXUXO KXUX% j z l R.o C.fXfXfXN.S.S.S.S.S.S.S.- fXfXfXC.j l g * R.l l + |.|.].g j z l 6 O * UXUXUXN.IXLXIXJXJXGXGXGXGXGXHXHXFXDXFXFXFXFXFXFXFXFXDXFXFXFXHXFXFXFXFXFXDXDXFXFXHXFXFXFXDXDXFXFXDXFXFXFXFXFXFXFXDXDXDXFXFXHXFXFXFXDXDXFXFXFXFXHXFXHXFXFXDXFXFXFXFXFXFXFXDXDXFXFXFXDXDXDXDXDXFXHXFXDXFXFXFXFXFXFXFXFXDXFXFXFXHXFXFXFXFXFXDXDXFXFXHXFXFXFXDXDXFXFXDXFXFXFXFXFXFXFXDXDXDXFXFXHXFXFXFXDXDXFXFXFXFXHXFXHXFXFXDXFXFXFXFXFXFXFXDXDXFXFXFXDXDXDXDXDXFXHXFXDXFXFXFXFXFXFXFXFXDXFXFXFXHXFXFXFXFXDXDXDXFXFXFXFXFXFXDXDXFXFXDXFXFXFXFXFXFXFXDXDXDXFXFXHXFXFXFXDXDXFXFXFXFXHXFXHXFXFXDXFXFXFXFXFXFXFXDXDXFXFXFXDXDXDXDXDXFXHXFXDXFXFXFXFXFXFXFXFXDXFXFXFXHXFXFXFXFXFXDXDXFXFXHXFXFXFXDXDXFXFXDXFXFXFXFXFXFXFXDXDXDXFXFXHXFXFXFXDXDXFXFXFX", +"HXHXHXHXFXFXFXHXHXFXFXFXHXFXFXFXFXHXFXGXGXGXGXGXJXJXGXGXJXJXIXIXKXcXcXcXKXg l j (.UXUXUXUXUXO KXUXgXh z j g E.fXfXfXfXB.S.S.S.S.S.S.S.= fXC.fXfXV.h N.U.+ j 6 + `.{.`.V.g z j C.- - KXUXUXIXIXIXIXIXIXLXGXGXGXfXJXHXGXGXGXHXFXFXFXHXHXHXFXFXFXHXHXHXHXHXFXFXFXFXHXHXFXFXFXFXFXFXHXFXFXFXFXFXFXFXFXHXFXFXFXFXFXFXHXHXHXFXFXFXHXHXHXHXHXHXFXFXFXHXHXFXFXFXHXFXFXFXFXHXFXFXFXFXFXFXHXHXFXFXFXHXFXFXFXHXHXHXFXFXFXHXHXHXHXHXFXFXFXFXHXHXFXFXFXFXFXFXHXFXFXFXFXFXFXFXFXHXFXFXFXFXFXFXHXHXHXFXFXFXHXHXHXHXHXHXFXFXFXHXHXFXFXFXHXFXFXFXFXHXFXFXFXFXFXFXHXHXFXFXFXHXFXFXFXHXHXHXFXFXFXHXHXHXHXHXFXFXFXFXHXHXFXFXFXFXFXFXHXFXFXFXFXFXFXFXFXHXFXFXFXFXFXFXHXHXHXFXFXFXHXHXHXHXHXHXFXFXFXHXHXFXFXFXHXFXFXFXFXHXFXFXFXFXFXFXHXHXFXFXFXHXFXFXFXHXHXHXFXFXFXHXHXHXHXHXFXFXFXFXHXHXFXFXFXFXFXFXHXFXFXFXFXFXFXFXFXHXFXFXFXFXFXFXHXHXHXFXFXFXHXHX", +"HXHXHXFXGXGXHXHXFXGXGXGXGXHXHXGXGXHXHXGXGXGXGXGXJXJXGXJXJXIXIXIXIXIXUXUXUXO z g Y.H.; J.PXUXB.PXUXUXO 6 C.fXfXfXfXfXD.N.S.S.S.S.S.S.S.= B.fXfXfXNX. D.A.zXvXgXg /._.g vXg l g UXH.UXUXUXUXUXIXIXIXIXIXLXGXGXGXGXJXJXGXGXHXHXGXGXGXGXHXHXFXGXGXHXHXHXHXHXGXGXFXHXHXGXGXGXGXGXGXFXHXGXGXHXGXGXFXFXGXFXHXGXGXGXGXGXGXFXHXHXFXGXFXHXHXHXHXFXGXGXHXHXFXGXGXGXGXHXHXGXGXHXHXGXGXGXGXGXHXFXGXGXHXHXGXGXGXGXHXHXFXGXGXHXHXHXHXHXGXGXFXHXHXGXGXGXGXGXGXFXHXGXGXHXGXGXFXFXGXFXHXGXGXGXGXGXGXFXHXHXFXGXFXHXHXHXHXFXGXGXHXHXFXGXGXGXGXHXHXGXGXHXHXGXGXGXGXGXHXFXGXGXHXHXGXGXGXGXHXHXFXGXGXHXHXHXHXHXGXGXFXHXHXGXGXGXGXGXGXFXHXGXGXHXGXGXFXFXGXFXHXGXGXGXGXGXGXFXHXHXFXGXFXHXHXHXHXFXGXGXHXHXFXGXGXGXGXHXHXGXGXHXHXGXGXGXGXGXHXFXGXGXHXHXGXGXGXGXHXHXFXGXGXHXHXHXHXHXGXGXFXHXHXGXGXGXGXGXGXFXHXGXGXHXGXGXFXFXGXFXHXGXGXGXGXGXGXFXHXHXFXGXFXHX", +"JXJXJXGXGXHXHXHXGXGXGXGXGXHXHXGXGXJXJXGXGXGXGXJXJXJXLXIXIXIXIXIXIXIXUXUXUXA.j g ; ; : ; ; ; A.H.H.H.O fXfXfXfXfXfXfXB.= S.S.S.S.S.S.S.& fXfXB.D.D.= kXkXkXkXlXlX(.V.D.cXg 6 UXUXU.UXUXUXUXUXUXIXIXIXIXLXLXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXGXJXJXGXGXGXGXGXGXGXJXGXGXHXHXGXGXGXJXGXGXJXGXGXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXHXHXHXGXGXGXGXGXHXHXGXGXHXJXGXGXGXGXGXHXGXGXHXHXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXGXJXJXGXGXGXGXGXGXGXJXGXGXHXHXGXGXGXJXGXGXJXGXGXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXHXHXHXGXGXGXGXGXHXHXGXGXHXJXGXGXGXGXGXHXGXGXHXHXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXGXJXJXGXGXGXGXGXGXGXJXGXGXHXHXGXGXGXJXGXGXJXGXGXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXHXHXHXGXGXGXGXGXHXHXGXGXHXJXGXGXGXGXGXHXGXGXHXHXGXGXGXGXGXGXJXJXGXGXJXHXHXHXGXGXGXJXJXGXGXGXGXGXGXGXJXGXGXHXHXGXGXGXJXGXGXJXGXGXGXGXGXGXGXGXJXJXGXGXJX", +"JXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXGXGXGXGXJXJXLXIXIXIXIXIXIXIXUXUXUXUXUX+ N.; : : : : : - cXcXcXO fXfXfXfXfXfXfX+ N.S.S.S.S.S.S.Z.D.fX+ vXlXzXgXlXkXkXkXlXkXzX* UXgX+ vXUXUXUXUXUXUXUXUXUXIXIXIXIXIXLXLXLXJXJXGXGXJXJXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXGXGXJXJXJXJXGXGXJXJXJXGXGXGXGXGXGXJXJXGXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJX", +"JXJXJXJXGXJXJXJXGXGXGXGXGXGXJXJXJXGXJXJXLXLXLXIXIXLXIXIXIXIXIXIXUXUXUXUXUXUXO - ; : : : : : - cXcXcXH.* fXfXfXfXfXfXN.S.S.S.S.S.S.S.B.fXfXC.kXcXN.PXlXlXlXlXlXzXzXkXPXfXC.UXUXUXUXUXUXUXUXUXUXUXIXIXIXIXLXLXIXIXJXLXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXJXJXJXGXJXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXJXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXGXJXJXJXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXJXJXJXGXJXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXJXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXGXJXJXJXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXJXJXJXGXJXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXJXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXGXJXJXJXGXJXJXGXGXGXJXJXGXJXJXGXGXGXGXGXGXGXJXJXGXGXJXJXJXJXJXGXJXJXJXGXGXGXGXGXJXJXJXGXJXJXGXGXGXGXJXJXGXGXJXJXGXGXGXGXGXGXJXJXJXGXJX", +"JXJXJXJXLXIXJXJXIXLXLXLXLXLXLXJXJXLXIXIXLXLXIXIXIXIXIXIXIXIXIXUXUXUXUXUXUXUXA.- ; : : : : : - cXcXcXY.- - - C.fXfXfXB.Z.S.S.S.S.S.N.fXfXfX* jXN.N.D.D.gXlXlXlXlXkXlX* A.H.gXUXUXUXUXUXUXUXUXUXUXUXIXIXIXIXLXIXIXIXIXIXIXLXLXLXLXLXIXJXJXJXLXIXJXJXJXJXIXLXIXJXJXLXLXLXLXLXJXJXLXLXJXJXLXLXLXLXIXJXIXLXJXJXIXLXLXLXLXIXJXJXLXLXJXJXJXJXJXLXIXJXJXIXLXLXLXLXLXLXJXJXLXIXJXLXLXIXJXLXIXJXIXLXLXLXLXLXIXJXJXJXLXIXJXJXJXJXIXLXIXJXJXLXLXLXLXLXJXJXLXLXJXJXLXLXLXLXIXJXIXLXJXJXIXLXLXLXLXIXJXJXLXLXJXJXJXJXJXLXIXJXJXIXLXLXLXLXLXLXJXJXLXIXJXLXLXIXJXLXIXJXIXLXLXLXLXLXIXJXJXJXLXIXJXJXJXJXIXLXIXJXJXLXLXLXLXLXJXJXLXLXJXJXLXLXLXLXIXJXIXLXJXJXIXLXLXLXLXIXJXJXLXLXJXJXJXJXJXLXIXJXJXIXLXLXLXLXLXLXJXJXLXIXJXLXLXIXJXLXIXJXIXLXLXLXLXLXIXJXJXJXLXIXJXJXJXJXIXLXIXJXJXLXLXLXLXLXJXJXLXLXJXJXLXLXLXLXIXJXIXLXJXJXIXLXLXLXLXIXJXJXLXLXJX", +"IXIXIXIXIXIXIXIXIXIXIXLXLXLXLXIXIXIXIXIXIXIXIXIXIXIXIXIXIXUXUXUXUXUXUXUXUXU.A.H.; : : : : : - cXcXcXcX- U.- fXfXfXfXD.A.S.S.S.S.- fXfXfXfXC.* vXvXkXjXI.B.U.lXkXkXkXA.: : : ; gXUXUXUXUXUXUXUXUXUXUXUXIXIXIXIXIXIXIXIXIXLXLXLXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXLXIXIXIXLXLXLXLXIXIXIXLXIXIXIXIXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXLXLXLXLXIXIXIXIXIXIXLXIXIXLXIXIXIXLXLXLXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXLXIXIXIXLXLXLXLXIXIXIXLXIXIXIXIXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXLXLXLXLXIXIXIXIXIXIXLXIXIXLXIXIXIXLXLXLXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXLXIXIXIXLXLXLXLXIXIXIXLXIXIXIXIXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXLXLXLXLXIXIXIXIXIXIXLXIXIXLXIXIXIXLXLXLXIXIXIXIXIXIXLXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXIXLXIXIXIXLXLXLXLXIXIXIXLXIXIXIXIXIXIXIXIXIXIXLXIXIX" +}; diff --git a/assdraw/src/xpm/b__xpm.xpm b/assdraw/src/xpm/b__xpm.xpm new file mode 100644 index 000000000..8123f655e --- /dev/null +++ b/assdraw/src/xpm/b__xpm.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *b__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c gray20", +". c #12120000FFFF", +"X c None", +/* pixels */ +"XX.XXXXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +".....XXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +"XX.XX XXXX", +"XXXXX XXX", +"XXXXX XXXX XXX", +"XXXXX XXXX XXX", +"XXXXX XXXX", +"XXXXX XXX", +"XXXXX XXXX XXX", +"XXXXX XXXX XXX", +"XXXXX XXX", +"XXXXX XXXX", +"XXXXXXXXXXXXXXXX" +}; diff --git a/assdraw/src/xpm/c__xpm.xpm b/assdraw/src/xpm/c__xpm.xpm new file mode 100644 index 000000000..cd0f8db9b --- /dev/null +++ b/assdraw/src/xpm/c__xpm.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *c__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c gray20", +". c #12120000FFFF", +"X c None", +/* pixels */ +"XX.XXXXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +".....XXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +"XX.XXXX XXXXX", +"XXXXXX XXXX", +"XXXXX XX XXX", +"XXXXX XXXX XXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXX XXXX", +"XXXXX XX XXX", +"XXXXXX XXXX", +"XXXXXXX XXXXX", +"XXXXXXXXXXXXXXXX" +}; diff --git a/assdraw/src/xpm/check__xpm.xpm b/assdraw/src/xpm/check__xpm.xpm new file mode 100644 index 000000000..ba5602d64 --- /dev/null +++ b/assdraw/src/xpm/check__xpm.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static char *check_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 6 1", +" c black", +". c gray25", +"X c #808080808080", +"o c #D4D4D0D0C8C8", +"O c gray100", +"+ c None", +/* pixels */ +"++++++++++++++++", +"++XXXXXXXXXXXX++", +"++X..........o++", +"++X.OOOOOOOOOo++", +"++X.OOOOOOO Oo++", +"++X.OOOOOO Oo++", +"++X.O OOO Oo++", +"++X.O O OOo++", +"++X.O OOOo++", +"++X.OO OOOOo++", +"++X.OOO OOOOOo++", +"++X.OOOOOOOOOo++", +"++Xooooooooooo++", +"++++++++++++++++", +"++++++++++++++++" +}; diff --git a/assdraw/src/xpm/del__xpm.xpm b/assdraw/src/xpm/del__xpm.xpm new file mode 100644 index 000000000..cd88997a2 --- /dev/null +++ b/assdraw/src/xpm/del__xpm.xpm @@ -0,0 +1,90 @@ +/* XPM */ +static char *del__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 69 1", +" c black", +". c #0C0C0C0C0C0C", +"X c gray5", +"o c gray9", +"O c #191919191919", +"+ c gray11", +"@ c #262625252424", +"# c #313131313131", +"$ c #323232323232", +"% c #353534343232", +"& c #373735353333", +"* c #373737373737", +"= c #383838383737", +"- c #3E3E3E3E3E3E", +"; c #414141414141", +": c #575755555252", +"> c #555555555555", +", c #5D5D5A5A5757", +"< c gray35", +"1 c gray36", +"2 c #646464646464", +"3 c gray42", +"4 c #70706E6E6A6A", +"5 c #71716F6F6B6B", +"6 c #818181818181", +"7 c #868686868686", +"8 c #878787878686", +"9 c #888888888787", +"0 c #8F8F8C8C8787", +"q c gray55", +"w c #8F8F8E8E8D8D", +"e c #979793938D8D", +"r c gray57", +"t c #969695959292", +"y c gray59", +"u c #9F9F9F9F9F9F", +"i c #A3A39F9F9999", +"p c #A0A0A0A0A0A0", +"a c gray64", +"s c #AAAAA6A6A0A0", +"d c #AEAEACACA7A7", +"f c #A9A9A9A9A9A9", +"g c #B1B1AEAEA7A7", +"h c #B3B3B0B0A9A9", +"j c #B7B7B4B4ADAD", +"k c #B9B9B7B7B1B1", +"l c #BEBEBBBBB5B5", +"z c #BCBCBCBCBCBC", +"x c #C2C2BFBFB8B8", +"c c #C3C3C0C0B8B8", +"v c #C3C3C0C0B9B9", +"b c #C7C7C3C3BBBB", +"n c #C6C6C3C3BCBC", +"m c gray78", +"M c #CBCBC8C8C0C0", +"N c #CFCFCBCBC4C4", +"B c #C8C8C8C8C8C8", +"V c gray80", +"C c #D2D2CECEC6C6", +"Z c #D3D3CFCFC7C7", +"A c #D0D0D0D0D0D0", +"S c LightGray", +"D c gray86", +"F c #DDDDDDDDDDDD", +"G c gray90", +"H c gray93", +"J c #F4F4F4F4F4F4", +"K c #F6F6F6F6F6F6", +"L c None", +/* pixels */ +"LLLLN*LLLLLLLLLL", +"LLLLk=0LLLLLLLLL", +"LLLZt &LLLLLLLLL", +"LLLv9<-iLLLLLLLL", +"LLZtB1p%LL L", +"LLlyH1F$eLLLLLLL", +"LCwAH1Ff@cLLLLLL", +"LdaJHuFS>5LLLLLL", +"n8KJH FSm+sLLLLL", +"LrqJHDFS3:xLLLLL", +"Lb#DHGFzohLLLLLL", +"LL46HGF2,LLLLLLL", +"LLgOHGF LLLLLLLL", +"LLX..X...LLLLLLL", +"LLM;V7.XjLLLLLLL" +}; diff --git a/assdraw/src/xpm/del_cross_xpm.xpm b/assdraw/src/xpm/del_cross_xpm.xpm new file mode 100644 index 000000000..41084cd96 --- /dev/null +++ b/assdraw/src/xpm/del_cross_xpm.xpm @@ -0,0 +1,106 @@ +/* XPM */ +static char *delcross_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 85 1", +" c #3F3F14141818", +". c #4C4C19192121", +"X c #656522222626", +"o c #797927272C2C", +"O c #6E6E24243333", +"+ c #82822A2A2D2D", +"@ c #919130303434", +"# c #949431313535", +"$ c #979732323434", +"% c #979732323B3B", +"& c #9E9E35353D3D", +"* c #9E9E34343F3F", +"= c #A0A036363939", +"- c #A5A538383C3C", +"; c #A7A73A3A3E3E", +": c #ACAC3B3B3E3E", +"> c #B5B53D3D3D3D", +", c #9E9E34344848", +"< c #A5A539394242", +"1 c #AEAE3D3D4040", +"2 c #A3A337374D4D", +"3 c #B7B73F3F4343", +"4 c #B3B33F3F4747", +"5 c #B5B53F3F4545", +"6 c #B3B33C3C5353", +"7 c #B1B13D3D5454", +"8 c #B3B33C3C5656", +"9 c #B5B53D3D5959", +"0 c #B7B740404141", +"q c #BDBD42424545", +"w c #B7B741414848", +"e c #B3B340405C5C", +"r c #BFBF45455E5E", +"t c #C3C345454C4C", +"y c #D0D04B4B5252", +"u c #C9C948486666", +"i c #CFCF4B4B6868", +"p c #D0D04C4C6A6A", +"a c #D2D24C4C6C6C", +"s c #E4E457577575", +"d c #E2E258587676", +"f c #E7E75B5B7979", +"g c #EAEA5B5B7A7A", +"h c #E8E85C5C7979", +"j c #EAEA5C5C7A7A", +"k c #F1F160607B7B", +"l c #F1F162627F7F", +"z c #F4F464648080", +"x c #F6F666668080", +"c c #F5F564648282", +"v c #F7F766668585", +"b c #FAFA69698484", +"n c #FFFF6D6D8686", +"m c #FCFC6B6B8888", +"M c #FFFF6D6D8989", +"N c #FFFF6F6F8B8B", +"B c #FFFF71718989", +"V c #FFFF74748F8F", +"C c #FFFF83839B9B", +"Z c #FFFF89899B9B", +"A c #FFFF89899D9D", +"S c #FFFF8D8DA2A2", +"D c #FFFF9393A5A5", +"F c #FFFF9595A6A6", +"G c #FFFF9E9EA7A7", +"H c #FFFFA6A6ABAB", +"J c #FFFFA5A5B1B1", +"K c #FFFFAFAFB1B1", +"L c #FFFFADADB4B4", +"P c #FFFFB0B0B2B2", +"I c #FFFFB0B0B9B9", +"U c #FFFFB5B5B8B8", +"Y c #FFFFB4B4BCBC", +"T c #FFFFBBBBBBBB", +"R c #FFFFBCBCBBBB", +"E c #FFFFB8B8BDBD", +"W c #FFFFC0C0BEBE", +"Q c #FFFFC0C0C2C2", +"! c #FFFFC4C4C2C2", +"~ c #FFFFC3C3C4C4", +"^ c #FFFFC4C4C7C7", +"/ c #FFFFC7C7C6C6", +"( c #FFFFC7C7C7C7", +") c #FFFFCCCCC9C9", +"_ c None", +/* pixels */ +"_^jY____________", +"_DqtJ________S__", +"_Fh;5C_____Iym__", +"__Eg10l___c4V___", +"____Aw3vQN>M____", +"_____~p-& c #52528282D0D0", +", c #63638E8ED5D5", +"< c #69699292D7D7", +"1 c #71719898D9D9", +"2 c #79799E9EDBDB", +"3 c #7C7CA0A0DCDC", +"4 c #8989A9A9DFDF", +"5 c #8C8CACACE0E0", +"6 c #9595B2B2E3E3", +"7 c #9A9AB6B6E4E4", +"8 c #9B9BB7B7E5E5", +"9 c #A6A6BFBFE8E8", +"0 c #A8A8C0C0E8E8", +"q c #ADADC4C4E9E9", +"w c #B1B1C7C7EBEB", +"e c #B8B8CCCCECEC", +"r c #BEBED0D0EEEE", +"t c #C4C4D5D5F0F0", +"y c #CBCBD9D9F1F1", +"u c #CCCCDADAF2F2", +"i c #D2D2DFDFF4F4", +"p c #D9D9E4E4F5F5", +"a c #DCDCE6E6F6F6", +"s c #DFDFE8E8F7F7", +"d c #E2E2EAEAF8F8", +"f c #EAEAF0F0FAFA", +"g c #EDEDF2F2FBFB", +"h c #F0F0F5F5FCFC", +"j c #F5F5F8F8FDFD", +"k c #F7F7F9F9FDFD", +"l c #FAFAFCFCFEFE", +"z c #FDFDFEFEFFFF", +"x c gray100", +"c c None", +/* pixels */ +"ccc%%%%%%%o-cccc", +"ccc%urw073%4-ccc", +"ccc%iurw07%k4>cc", +"cc9$$$<0w0%kk4$c", +"c1 @2,O c gray43", +", c #6F6F6F6F6F6F", +"< c gray44", +"1 c #767676767676", +"2 c #797979797979", +"3 c #7C7C7C7C7C7C", +"4 c #7F7F7F7F7F7F", +"5 c #818181818181", +"6 c #8D8D8D8D8D8D", +"7 c #8E8E8E8E8E8E", +"8 c #939393939393", +"9 c gray58", +"0 c #959595959595", +"q c gray59", +"w c gray60", +"e c #9A9A9A9A9A9A", +"r c #A4A4A1A19696", +"t c #A8A8A6A69C9C", +"y c #A7A7A7A7A7A7", +"u c gray66", +"i c #B1B1AFAFA5A5", +"p c #B3B3B1B1A8A8", +"a c #BDBDBBBBAFAF", +"s c gray70", +"d c #CDCDCACABCBC", +"f c #C8C8C8C8C8C8", +"g c #CACACACACACA", +"h c #CDCDCDCDCDCD", +"j c gray81", +"k c gray83", +"l c #D5D5D5D5D5D5", +"z c #D7D7D7D7D7D7", +"x c #D8D8D8D8D8D8", +"c c gray86", +"v c #DFDFDFDFDFDF", +"b c #E7E7E4E4D3D3", +"n c #E4E4E4E4E4E4", +"m c #E7E7E7E7E7E7", +"M c gray91", +"N c gray92", +"B c #EEEEEEEEEEEE", +"V c #EFEFEFEFEFEF", +"C c #F1F1F1F1F1F1", +"Z c gray95", +"A c #F3F3F3F3F3F3", +"S c #F6F6F6F6F6F6", +"D c gray100", +"F c None", +/* pixels */ +"FFFFFFFFFFFFFFFF", +"FFFFFFFFFFFFFFFF", +"FFFFFFFa@-------", +"FFFFFFaOZBnzhf,;", +"FFFFFaOZCmcjf<0$", +"FFFFaOZANvkf9755>%+2q.rFF", +"b;sxxxklf*6.rFFF", +"p8SSSSSSu4.rFFFF", +"1MDDDDDV&.rFFFFF", +"ooooooo+ rFFFFFF", +"FFFFFFFFFFFFFFFF", +"FFFFFFFFFFFFFFFF" +}; diff --git a/assdraw/src/xpm/nut__xpm.xpm b/assdraw/src/xpm/nut__xpm.xpm new file mode 100644 index 000000000..c35f62dc4 --- /dev/null +++ b/assdraw/src/xpm/nut__xpm.xpm @@ -0,0 +1,76 @@ +/* XPM */ +static char *nut__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 55 1", +" c #7F7F00000000", +". c #000013137F7F", +"X c #030315157F7F", +"o c #6C6C41416060", +"O c #808007070707", +"+ c #808009090909", +"@ c #838313131313", +"# c #848412121212", +"$ c #868618181818", +"% c #88881D1D1D1D", +"& c #88881E1E1E1E", +"* c #8A8A24242424", +"= c #8E8E30303030", +"- c #92923C3C3C3C", +"; c #949442424242", +": c #969648484848", +"> c #98984E4E4E4E", +", c #9A9A54545454", +"< c #9D9D5A5A5A5A", +"1 c #A1A165656565", +"2 c #A3A36B6B6B6B", +"3 c #A5A56F6F6F6F", +"4 c #A5A571717171", +"5 c #A7A777777777", +"6 c #A9A97D7D7D7D", +"7 c #0A0A1C1C8181", +"8 c #0C0C1C1C8080", +"9 c #0D0D1F1F8282", +"0 c #151525258484", +"q c #151525258585", +"w c #171728288686", +"e c #1F1F2F2F8888", +"r c #242432328A8A", +"t c #2A2A38388C8C", +"y c #2D2D3B3B8D8D", +"u c #61616A6A9F9F", +"i c #64646C6CA0A0", +"p c #74747C7CA6A6", +"a c #77777E7EA7A7", +"s c #AFAF8F8F8F8F", +"d c #B3B39B9B9B9B", +"f c #83838989ABAB", +"g c #89898E8EADAD", +"h c #8D8D9292AEAE", +"j c #8F8F9494AFAF", +"k c #9B9B9F9FB3B3", +"l c #B5B5A1A1A1A1", +"z c #B7B7A7A7A7A7", +"x c #B9B9ADADADAD", +"c c #A7A7A9A9B7B7", +"v c #BBBBB3B3B3B3", +"b c #B3B3B4B4BBBB", +"n c #BDBDB9B9B9B9", +"m c #B9B9BABABDBD", +"M c None", +/* pixels */ +"# @nMMMM", +" MMMMebMMM:5MMMM", +" MMMc9.MMMs=MMMM", +" ......pMMM#xMMM", +" h........0<1MMM", +" Mc......tkd*MMM", +" MMuX....bMM&lMM", +" MMy.....jMM1d7.MM...fMM=sM", +"z4*$,dMMa.wmM5:M", +"MMMz2*$,dgqiMv#n", +"MMMMMMz2*$o8MM;6", +"MMMMMMMMMz2*$,3-", +"MMMMMMMMMMMMz2%O" +}; diff --git a/assdraw/src/xpm/p__xpm.xpm b/assdraw/src/xpm/p__xpm.xpm new file mode 100644 index 000000000..3c541d8c8 --- /dev/null +++ b/assdraw/src/xpm/p__xpm.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *p__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c gray20", +". c #12120000FFFF", +"X c None", +/* pixels */ +"XX.XXXXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +".....XXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +"XX.XX XXXXX", +"XXXXX XXXX", +"XXXXX XXX XXXX", +"XXXXX XXX XXXX", +"XXXXX XXXX", +"XXXXX XXXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXXXXXXX", +"XXXXXXXXXXXXXXXX" +}; diff --git a/assdraw/src/xpm/pan_bg_xpm.xpm b/assdraw/src/xpm/pan_bg_xpm.xpm new file mode 100644 index 000000000..10a558609 --- /dev/null +++ b/assdraw/src/xpm/pan_bg_xpm.xpm @@ -0,0 +1,87 @@ +/* XPM */ +static char *pan_bg_xpm[] = { +/* columns rows colors chars-per-pixel */ +"24 15 66 1", +" c #2A2A35354D4D", +". c #2C2C38384B4B", +"X c #36364A4A6464", +"o c #474757576E6E", +"O c #4D4D5C5C7272", +"+ c #5E5E66667171", +"@ c #606060606060", +"# c #C1C14B4B2B2B", +"$ c #CFCF55553636", +"% c #CBCB75752424", +"& c #BABA6D6D6666", +"* c #CCCC69695656", +"= c #C9C973736666", +"- c #FFFF7F7F7F7F", +"; c #EDEDA0A04C4C", +": c #EFEFA5A54F4F", +"> c #585866668585", +", c #646475759696", +"< c #7D7D89899E9E", +"1 c #72728383A7A7", +"2 c #80808A8A9D9D", +"3 c #86868E8E9D9D", +"4 c #89899999AFAF", +"5 c #8A8A9A9AAEAE", +"6 c #81819292BABA", +"7 c #9696A3A3B4B4", +"8 c #9D9DA7A7BBBB", +"9 c #A3A3ABABBABA", +"0 c #D3D396968D8D", +"q c #D2D297978D8D", +"w c #DDDDA5A59B9B", +"e c #E8E8C3C39393", +"r c #83839999C7C7", +"t c #9090A5A5C3C3", +"y c #9191A5A5C3C3", +"u c #9191A5A5C4C4", +"i c #9292A6A6C5C5", +"p c #9292A7A7C5C5", +"a c #9191A5A5C6C6", +"s c #9393A7A7C6C6", +"d c #9393A7A7C7C7", +"f c #9898A8A8C5C5", +"g c #9898AAAAC5C5", +"h c #9797A7A7C9C9", +"j c #9595A8A8CFCF", +"k c #9B9BB1B1DFDF", +"l c #AAAAB4B4C7C7", +"z c #D4D4C3C3D0D0", +"x c #CDCDDADAE9E9", +"c c #D2D2D8D8E2E2", +"v c #D6D6DCDCE6E6", +"b c #C8C8DADAFDFD", +"n c #D2D2DDDDF0F0", +"m c #D5D5DFDFF1F1", +"M c #E1E1E5E5ECEC", +"N c #F2F2E2E2E2E2", +"B c #F5F5E5E5E2E2", +"V c #F1F1E9E9ECEC", +"C c #EBEBEFEFFBFB", +"Z c #EFEFF5F5F9F9", +"A c #F1F1F4F4FAFA", +"S c #F2F2F5F5FCFC", +"D c #FAFAFBFBFEFE", +"F c #FDFDFEFEFEFE", +"G c gray100", +"H c None", +/* pixels */ +"HHHHH@HHHHHHHHHHHHHHHHHH", +"HHHHH@HHHHHHHHHHHHHHHHHH", +"HHHHH@HHHHHHHHHHHHHHHHHH", +"HHHHH@HHHHHHassdssyyygHH", +"H@@@@@@@@@HHsGFGABw0VXHH", +"H@HHH@---@HHiGGAAqe:&XHH", +"H@HHH@---@HHsGGZZ=;%#XHH", +"H@HHH@---@HHpGGvxN*$zXHH", +"H@HHH@---@HHiGc4.XHH", +"H@HHHHHHH@HHyXXXXXXXXXHH", +"H@HHHHHHH@HHHHHHHHHHHHHH", +"H@@@@@@@@@HHHHHHHHHHHHHH" +}; diff --git a/assdraw/src/xpm/pan_both_xpm.xpm b/assdraw/src/xpm/pan_both_xpm.xpm new file mode 100644 index 000000000..c181fe904 --- /dev/null +++ b/assdraw/src/xpm/pan_both_xpm.xpm @@ -0,0 +1,97 @@ +/* XPM */ +static char *pan_both_xpm[] = { +/* columns rows colors chars-per-pixel */ +"24 15 76 1", +" c #1B1B22225353", +". c #0D0D0D0D6767", +"X c #0F0F14146161", +"o c #111115156464", +"O c #121219196262", +"+ c #131313136969", +"@ c #131314146C6C", +"# c #111115156F6F", +"$ c #19191A1A6E6E", +"% c #1E1E1E1E6F6F", +"& c #1D1D21217878", +"* c #232330306262", +"= c #282837376262", +"- c #2A2A2A2A7575", +"; c #3C3C3C3C7E7E", +": c #36364A4A6464", +"> c #606060606060", +", c #C1C14B4B2B2B", +"< c #CFCF55553636", +"1 c #CBCB75752424", +"2 c #BABA6D6D6666", +"3 c #CCCC69695656", +"4 c #C9C973736666", +"5 c #FFFF7F7F7F7F", +"6 c #EDEDA0A04C4C", +"7 c #EFEFA5A54F4F", +"8 c #484848488484", +"9 c #5A5A5A5A8E8E", +"0 c #45454B4B9696", +"q c #5F5F5F5F9090", +"w c #656565659292", +"e c #777777779B9B", +"r c #7E7E7E7E9F9F", +"t c #B2B20000FFFF", +"y c #7D7D89899E9E", +"u c #7B7B8888B1B1", +"i c #83838383A1A1", +"p c #89899999AFAF", +"a c #8A8A9A9AAEAE", +"s c #9B9B9B9BADAD", +"d c #9696A3A3B4B4", +"f c #A1A1A1A1B0B0", +"g c #A7A7A7A7B3B3", +"h c #B9B9B9B9BCBC", +"j c #D3D396968D8D", +"k c #D2D297978D8D", +"l c #DDDDA5A59B9B", +"z c #E8E8C3C39393", +"x c #9090A5A5C3C3", +"c c #9191A5A5C3C3", +"v c #9191A5A5C4C4", +"b c #9292A6A6C5C5", +"n c #9292A7A7C5C5", +"m c #9191A5A5C6C6", +"M c #9393A7A7C6C6", +"N c #9393A7A7C7C7", +"B c #9898AAAAC5C5", +"V c #9595A8A8CFCF", +"C c #AAAAB3B3D4D4", +"Z c #D4D4C3C3D0D0", +"A c #C0C0CACAE3E3", +"S c #CDCDDADAE9E9", +"D c #D2D2D8D8E2E2", +"F c #D6D6DCDCE6E6", +"G c #E1E1E5E5ECEC", +"H c #F2F2E2E2E2E2", +"J c #F5F5E5E5E2E2", +"K c #F1F1E9E9ECEC", +"L c #EBEBEFEFFBFB", +"P c #EFEFF5F5F9F9", +"I c #F1F1F4F4FAFA", +"U c #F2F2F5F5FCFC", +"Y c #FAFAFBFBFEFE", +"T c #FDFDFEFEFEFE", +"R c gray100", +"E c None", +/* pixels */ +"EEEEE>EEEEEmMMNMMcccBEEE", +"EEEEE>EEEEEMRTRIJljK:EEE", +"EEEEE>EEEEEbRRIIkz72:EEE", +"EEEEE>EEEEEMRRPP461,:EEE", +"E>>>>>>>>>EnRRFSH3EEE>555>EbRDpyu$@0*EEE", +"E>EEE>555>EvGaUCott O%sE", +"E>EEE>555>EvdYA&tttttt-f", +"E>EEE>555>ExLV#tttttttt+", +"E>>>>>>>>>Ec::=Xttttttw9", +"E>EEEEEEE>EEEEEe8ttttt-h", +"E>EEEEEEE>EEEEEE9wttt-sE", +"E>EEEEEEE>EEEEEEE;itqqEE", +"E>EEEEEEE>EEEEEEEh-r-hEE", +"E>>>>>>>>>EEEEEEEEg.fEEE" +}; diff --git a/assdraw/src/xpm/pan_shape_xpm.xpm b/assdraw/src/xpm/pan_shape_xpm.xpm new file mode 100644 index 000000000..7f9fb0718 --- /dev/null +++ b/assdraw/src/xpm/pan_shape_xpm.xpm @@ -0,0 +1,63 @@ +/* XPM */ +static char *pan_shape_xpm[] = { +/* columns rows colors chars-per-pixel */ +"30 15 42 1", +" c black", +". c #010101010101", +"X c #070707070707", +"o c #0C0C0C0C0C0C", +"O c #484848484848", +"+ c #FFFF00006E6E", +"@ c #121223238585", +"# c #141424248585", +"$ c #181829298787", +"% c #1D1D2E2E8989", +"& c #1E1E2E2E8989", +"* c #2A2A39398D8D", +"= c #30303E3E8F8F", +"- c #363644449191", +"; c #3A3A48489292", +": c #3C3C49499393", +"> c #42424E4E9595", +", c #484854549797", +"< c #4E4E59599999", +"1 c #5A5A64649D9D", +"2 c #66666F6FA2A2", +"3 c #78787F7FA8A8", +"4 c #39395050D3D3", +"5 c #3C3C5252D4D4", +"6 c #3F3F5555D5D5", +"7 c #42425858D6D6", +"8 c #45455A5AD7D7", +"9 c #47475C5CD7D7", +"0 c #4B4B6060D9D9", +"q c #54546868DCDC", +"w c #5A5A6D6DDEDE", +"e c #5D5D7070DFDF", +"r c #60607373E0E0", +"t c #84848A8AACAC", +"y c #8A8A8F8FAEAE", +"u c #90909595B0B0", +"i c #A2A2A5A5B6B6", +"p c #A8A8AAAAB8B8", +"a c #AEAEB0B0BABA", +"s c #B4B4B5B5BCBC", +"d c #BABABBBBBEBE", +"f c None", +/* pixels */ +"ffffOfffffffffffffffffffffffff", +"ffff fffffffffffffffffffffffff", +"ffff fffffffffffffffu%3fffffff", +"ffff fffffffffffffi:=9,$3fffff", +"X .fffffffa<&7rrrq,$3fff", +" fff +++ fffffd2&4rrrrrrrq,$3f", +" fff +++ fffft&1wrrrrrrrrrrq,=", +" fff +++ fff#;qrrrrrrrrrrrrr5,", +" fff +++ fff>6rrrrrrrrrrrq1@,p", +" fffy-rrrrrrrrr8:$2aff", +" fffffff fffd@wrrrrre4&-tfffff", +" fffffff ffff,5rrrq1@ c #656565659292", +", c #777777779B9B", +"< c #7D7D7D7D9E9E", +"1 c #7E7E7E7E9F9F", +"2 c #A1A14949D3D3", +"3 c #A6A64D4DD6D6", +"4 c #A9A95050D7D7", +"5 c #AAAA5151D8D8", +"6 c #ACAC5353D9D9", +"7 c #AFAF5656DADA", +"8 c #B5B55C5CDDDD", +"9 c #B8B85F5FDFDF", +"0 c #83838383A1A1", +"q c #8F8F8F8FA7A7", +"w c #9B9B9B9BADAD", +"e c #A1A1A1A1B0B0", +"r c #A7A7A7A7B3B3", +"t c #ADADADADB6B6", +"y c #B9B9B9B9BCBC", +"u c None", +/* pixels */ +"uuuuu&uuuuuuuuuuuuuuuuuu", +"uuuuu&uuuuuuuuuuuuuuuuuu", +"uuuuu&uuuuuuuuuuuuuuuuuu", +"uuuuu&uuuuuuuuwOX=;uu", +"u&uuu&***&uuu,-99993@yuu", +"u&&&&&&&&&uuuu;>998@wuuu", +"u&uuuuuuu&uuuuu%09::uuuu", +"u&uuuuuuu&uuuuuy@1@yuuuu", +"u&uuuuuuu&uuuuuur euuuuu", +"u&uuuuuuu&uuuuuuuuuuuuuu", +"u&&&&&&&&&uuuuuuuuuuuuuu" +}; diff --git a/assdraw/src/xpm/preview__xpm.xpm b/assdraw/src/xpm/preview__xpm.xpm new file mode 100644 index 000000000..4bbb73f5f --- /dev/null +++ b/assdraw/src/xpm/preview__xpm.xpm @@ -0,0 +1,100 @@ +/* XPM */ +static char *preview__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 79 1", +" c gray20", +". c #353535353535", +"X c gray21", +"o c gray22", +"O c gray23", +"+ c #3C3C3C3C3C3C", +"@ c #3E3E3E3E3E3E", +"# c #3F3F3F3F3F3F", +"$ c gray25", +"% c #414141414141", +"& c gray26", +"* c #434343434343", +"= c gray27", +"- c #464646464646", +"; c #484848484848", +": c #494949494949", +"> c gray29", +", c #4B4B4B4B4B4B", +"< c #4C4C4C4C4C4C", +"1 c gray30", +"2 c #505050505050", +"3 c gray32", +"4 c gray33", +"5 c #555555555555", +"6 c #565656565656", +"7 c gray34", +"8 c gray35", +"9 c #5A5A5A5A5A5A", +"0 c #5B5B5B5B5B5B", +"q c #5D5D5D5D5D5D", +"w c #676767676767", +"e c #6D6D6D6D6D6D", +"r c gray43", +"t c #6F6F6F6F6F6F", +"y c gray44", +"u c #727272727272", +"i c gray46", +"p c #777777777777", +"a c gray47", +"s c #7B7B7B7B7B7B", +"d c gray49", +"f c #7E7E7E7E7E7E", +"g c #808080808080", +"h c #848484848484", +"j c #898989898989", +"k c gray54", +"l c #8B8B8B8B8B8B", +"z c gray55", +"x c #8D8D8D8D8D8D", +"c c #909090909090", +"v c gray57", +"b c gray58", +"n c gray59", +"m c #979797979797", +"M c #9A9A9A9A9A9A", +"N c #9B9B9B9B9B9B", +"B c #9D9D9D9D9D9D", +"V c #9F9F9F9F9F9F", +"C c #A0A0A0A0A0A0", +"Z c gray63", +"A c gray64", +"S c #A4A4A4A4A4A4", +"D c #A5A5A5A5A5A5", +"F c gray65", +"G c #A7A7A7A7A7A7", +"H c #A9A9A9A9A9A9", +"J c gray67", +"K c #ACACACACACAC", +"L c gray68", +"P c #AEAEAEAEAEAE", +"I c #B4B4B4B4B4B4", +"U c gray71", +"Y c #B9B9B9B9B9B9", +"T c gray73", +"R c #BBBBBBBBBBBB", +"E c gray74", +"W c gray", +"Q c gray75", +"! c None", +/* pixels */ +"!!!!!!!!d.6Q!!!!", +"!!!!!!!coI4j!!!!", +"!!!r,51%P!zq!E!!", +"!!B*DCAW!!F@a$&S", +"!!V:!!!!!!QguJk6", +"!!!-m!!!!!!!!!k0", +"!!!st!!!!!!!!sXG", +"!!Y+n!!!!!!l*5K!", +"!R=f!!!!!!x#N!!!", +"!5t!!!!!!!wp!!!!", +"N+!!!!!!!!HoM!!!", +"8l!!!y5t!!!ZO!!!", +"3n!!99G2h!!b!!L RU.B!!!", +"!h>7T!!!i;=f!!!!" +}; diff --git a/assdraw/src/xpm/res.cpp b/assdraw/src/xpm/res.cpp new file mode 100644 index 000000000..0f0a787a0 --- /dev/null +++ b/assdraw/src/xpm/res.cpp @@ -0,0 +1,30 @@ +#define static +#include "appico_xpm.xpm" +#include "add__xpm.xpm" +#include "arr_1_xpm.xpm" +#include "arr__xpm.xpm" +#include "assdraw3_xpm.xpm" +#include "b__xpm.xpm" +#include "c__xpm.xpm" +#include "check__xpm.xpm" +#include "del__xpm.xpm" +#include "del_cross_xpm.xpm" +#include "help__xpm.xpm" +#include "help_xpm.xpm" +#include "l__xpm.xpm" +#include "m__xpm.xpm" +#include "n__xpm.xpm" +#include "new__xpm.xpm" +#include "nut__xpm.xpm" +#include "p__xpm.xpm" +#include "pan_bg_xpm.xpm" +#include "pan_both_xpm.xpm" +#include "pan_shape_xpm.xpm" +#include "pan_shp_xpm.xpm" +#include "preview__xpm.xpm" +#include "rot__xpm.xpm" +#include "s__xpm.xpm" +#include "sc_rot__xpm.xpm" +#include "src__xpm.xpm" +#include "transform_xpm.xpm" +#include "uncheck__xpm.xpm" diff --git a/assdraw/src/xpm/res.h b/assdraw/src/xpm/res.h new file mode 100644 index 000000000..58753b313 --- /dev/null +++ b/assdraw/src/xpm/res.h @@ -0,0 +1,29 @@ +extern char *appico_xpm[]; +extern char *add_xpm[]; +extern char *arr___xpm[]; +extern char *arr__xpm[]; +extern char *assdraw3__xpm[]; +extern char *b__xpm[]; +extern char *c__xpm[]; +extern char *check_xpm[]; +extern char *del__xpm[]; +extern char *delcross_xpm[]; +extern char *help__xpm[]; +extern char *help_xpm[]; +extern char *l__xpm[]; +extern char *m__xpm[]; +extern char *n__xpm[]; +extern char *new__xpm[]; +extern char *nut__xpm[]; +extern char *p__xpm[]; +extern char *pan_bg_xpm[]; +extern char *pan_both_xpm[]; +extern char *pan_shape_xpm[]; +extern char *pan_shp_xpm[]; +extern char *preview__xpm[]; +extern char *rot__xpm[]; +extern char *s__xpm[]; +extern char *sc_rot__xpm[]; +extern char *src__xpm[]; +extern char *transform_xpm[]; +extern char *uncheck_xpm[]; diff --git a/assdraw/src/xpm/rot__xpm.xpm b/assdraw/src/xpm/rot__xpm.xpm new file mode 100644 index 000000000..d5f93a4fe --- /dev/null +++ b/assdraw/src/xpm/rot__xpm.xpm @@ -0,0 +1,102 @@ +/* XPM */ +static char *rot__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 81 1", +" c #62625858C4C4", +". c #62625959C4C4", +"X c #64645A5AC4C4", +"o c #65655B5BC4C4", +"O c #65655B5BC5C5", +"+ c #66665C5CC4C4", +"@ c #66665D5DC5C5", +"# c #67675D5DC5C5", +"$ c #67675E5EC5C5", +"% c #68685E5EC5C5", +"& c #69695F5FC5C5", +"* c #69696060C6C6", +"= c #6A6A6161C6C6", +"- c #6E6E6565C7C7", +"; c #6F6F6767C7C7", +": c #73736A6AC7C7", +"> c #77776E6EC7C7", +", c #73736A6AC8C8", +"< c #73736B6BC8C8", +"1 c #74746B6BC8C8", +"2 c #76766D6DC8C8", +"3 c #7D7D7474C9C9", +"4 c #7E7E7575C9C9", +"5 c #7E7E7676C9C9", +"6 c #7E7E7676CBCB", +"7 c #7F7F7676CBCB", +"8 c #80807777CACA", +"9 c #81817878CBCB", +"0 c #81817979CDCD", +"q c #82827A7ACCCC", +"w c #87877F7FCCCC", +"e c #88887F7FCCCC", +"r c #88888080CDCD", +"t c #8E8E8686CDCD", +"y c #91918989CFCF", +"u c #93938A8ACECE", +"i c #92928A8ACFCF", +"p c #96968E8ECECE", +"a c #92928B8BD0D0", +"s c #A1A19999D0D0", +"d c #A3A39B9BD3D3", +"f c #A4A49D9DD3D3", +"g c #A5A59E9ED2D2", +"h c #A7A79F9FD3D3", +"j c #A3A39D9DD4D4", +"k c #A4A49D9DD4D4", +"l c #A6A69E9ED5D5", +"z c #A7A7A0A0D4D4", +"x c #ABABA4A4D2D2", +"c c #A8A8A1A1D5D5", +"v c #A9A9A2A2D4D4", +"b c #AAAAA3A3D7D7", +"n c #A7A7A0A0D8D8", +"m c #B1B1ABABD5D5", +"M c #B7B7B0B0D7D7", +"N c #BABAB3B3D7D7", +"B c #BBBBB5B5D5D5", +"V c #BFBFB9B9D6D6", +"C c #BFBFBABAD9D9", +"Z c #C3C3BDBDDADA", +"A c #C2C2BDBDDEDE", +"S c #C4C4BFBFDCDC", +"D c #C5C5C0C0DCDC", +"F c #C7C7C2C2DEDE", +"G c #C8C8C2C2DADA", +"H c #CACAC5C5D8D8", +"J c #C9C9C4C4DADA", +"K c #CBCBC6C6DBDB", +"L c #CCCCC7C7DFDF", +"P c #D1D1CCCCDCDC", +"I c #D4D4CFCFDEDE", +"U c #D6D6D1D1DDDD", +"Y c #D0D0CACAE1E1", +"T c #D2D2CCCCE1E1", +"R c #D4D4CFCFE0E0", +"E c #D3D3CECEE4E4", +"W c #D6D6D1D1E1E1", +"Q c #D8D8D3D3E1E1", +"! c #D8D8D2D2E3E3", +"~ c #DBDBD7D7E5E5", +"^ c None", +/* pixels */ +"^^^^^^^^^^^^^^^^", +"^^En0&+^^^^^^^^^", +"^A9O ~^^^^^^^^", +"TqO7bY^^^^^^!^^^", +"c*6L^^^^^^^WkF^^", +"rOl^^^^^^^WjpV^^^^^", +"^^^^^^^^^^^^^^^^" +}; diff --git a/assdraw/src/xpm/s__xpm.xpm b/assdraw/src/xpm/s__xpm.xpm new file mode 100644 index 000000000..af2990ccd --- /dev/null +++ b/assdraw/src/xpm/s__xpm.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char *s__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 3 1", +" c gray20", +". c #12120000FFFF", +"X c None", +/* pixels */ +"XX.XXXXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +".....XXXXXXXXXXX", +"XX.XXXXXXXXXXXXX", +"XX.XXX XXXXX", +"XXXXX XXXX", +"XXXXX XXX XXXX", +"XXXXX XXXXXXXXX", +"XXXXX XXXXX", +"XXXXXX XXXX", +"XXXXXXXXXX XXXX", +"XXXXX XXX XXXX", +"XXXXX XXXX", +"XXXXXX XXXXX", +"XXXXXXXXXXXXXXXX" +}; diff --git a/assdraw/src/xpm/sc_rot__xpm.xpm b/assdraw/src/xpm/sc_rot__xpm.xpm new file mode 100644 index 000000000..53086f5c8 --- /dev/null +++ b/assdraw/src/xpm/sc_rot__xpm.xpm @@ -0,0 +1,140 @@ +/* XPM */ +static char *sc_rot__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 119 2", +" c #212126264747", +". c #2B2B2B2B4848", +"X c #363636364D4D", +"o c #3B3B3B3B5C5C", +"O c #141425256565", +"+ c #0B0B27277D7D", +"@ c #282828286262", +"# c #373737376060", +"$ c #363636366363", +"% c #323232327878", +"& c #3C3C4C4C5858", +"* c #35354F4F6161", +"= c #2F2F56567373", +"- c #303055557070", +"; c #404040405454", +": c #41414F4F5959", +"> c #505050505050", +", c #505050505959", +"< c #585858585858", +"1 c #434343437F7F", +"2 c #4B4B4B4B7979", +"3 c #6F6F6F6F7676", +"4 c #686868687D7D", +"5 c gray44", +"6 c gray47", +"7 c #7C7C7C7C7C7C", +"8 c #0B0B27279C9C", +"9 c #202020208C8C", +"0 c #16161C1CA0A0", +"q c #00003737A0A0", +"w c #00003737ACAC", +"e c #0B0B2727BBBB", +"r c #00003737B9B9", +"t c #22222222A2A2", +"y c #25252525A5A5", +"u c #28282828A8A8", +"i c #2F2F2F2FAFAF", +"p c #35353535A2A2", +"a c #37373737B7B7", +"s c #3B3B3B3BBBBB", +"d c #3E3E3E3EBEBE", +"f c #181843438585", +"g c #28285F5F8888", +"h c #1F1F67679E9E", +"j c #202062629595", +"k c #242465659494", +"l c #222267679A9A", +"z c #222268689A9A", +"x c #00004747B0B0", +"c c #00005050B9B9", +"v c #16167777BDBD", +"b c #20206A6AA0A0", +"n c #4B4B4B4B8686", +"m c #474747478888", +"M c #474747478D8D", +"N c #474747478F8F", +"B c #525252528D8D", +"V c #474747479393", +"C c #414141419595", +"Z c #474747479494", +"A c #474747479595", +"S c #474747479A9A", +"D c #474747479B9B", +"F c #474747479C9C", +"G c #5E5E5E5E9090", +"H c #5E5E5E5E9292", +"J c #696969698080", +"K c #606060608A8A", +"L c #6A6A6A6A9898", +"P c #797979799696", +"I c #757575759D9D", +"U c #767676769E9E", +"Y c #47474747A0A0", +"T c #47474747A1A1", +"R c #47474747A3A3", +"E c #44444444A5A5", +"W c #47474747A6A6", +"Q c #47474747A7A7", +"! c #47474747ACAC", +"~ c #47474747AEAE", +"^ c #47474747AFAF", +"/ c #47474747B4B4", +"( c #47474747B9B9", +") c #47474747BABA", +"_ c #00003737C5C5", +"` c #00003737CCCC", +"' c #00003737D2D2", +"] c #00003737D8D8", +"[ c #00003737DFDF", +"{ c #00005A5AC3C3", +"} c #00006C6CD6D6", +"| c #00007F7FE9E9", +" . c #47474747C0C0", +".. c #47474747C1C1", +"X. c #44444444C4C4", +"o. c #46464646C6C6", +"O. c #47474747C6C6", +"+. c #47474747C7C7", +"@. c #00009191FCFC", +"#. c #00009494FFFF", +"$. c #909090909090", +"%. c #80808080A2A2", +"&. c #82828282A3A3", +"*. c #8C8C8C8CA8A8", +"=. c #8F8F8F8FA9A9", +"-. c #98989898ADAD", +";. c #99999999AEAE", +":. c #A4A4A4A4A4A4", +">. c gray66", +",. c #ACACACACACAC", +"<. c #A3A3A3A3B2B2", +"1. c #A4A4A4A4B3B3", +"2. c #A7A7A7A7B4B4", +"3. c #B0B0B0B0B8B8", +"4. c #B1B1B1B1B9B9", +"5. c #BCBCBCBCBDBD", +"6. c #BCBCBCBCBEBE", +"7. c gray75", +"8. c None", +/* pixels */ +": * = g j b b : 7 >.8.8.8.8.8.8.", +"k v z - O c f 4 , > 6 >.8.8.8.", +"b #.#.@.q ] ` 8 D N n 2 o ; 3 ,.", +"b #.#.| w [ [ e +.+. ./ W C % . ", +"b #.#.} r [ [ e +.+.+.+.+.+.) G ", +"b #.#.{ _ [ [ e +.+.+.+.+.+.~ I ", +"b #.#.x ' [ [ e +.+.+.+.+.+.T *.", +"& l h + e e e 0 X.+.+.+.+.+.Z 1.", +"$.5 <.A +.+.+.d t o.+.+.+.O.m 6.", +"8.< P R +.+.+.+.a u +.+.+.( H 8.", +"8.:.# ^ +.+.+.+.+.i i +.+.! U 8.", +"8.8.$ p +.+.+.+.+.+.u a +.Y =.8.", +"8.5.J @ M S Q / ..+.o.y s V 2.8.", +"8.8.8.8.4.;.&.L B N F E 9 1 7.8.", +"8.8.8.8.8.8.8.8.8.3.-.%.K X 8.8." +}; diff --git a/assdraw/src/xpm/src__xpm.xpm b/assdraw/src/xpm/src__xpm.xpm new file mode 100644 index 000000000..7f18d122b --- /dev/null +++ b/assdraw/src/xpm/src__xpm.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char *src__xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 4 1", +" c black", +". c #0000BFBFBFBF", +"X c cyan", +"o c None", +/* pixels */ +"oooooo ooooooo", +"ooo oo . oo oooo", +"oo X o o X ooo", +"o X. XXX .. oo", +"oo XX..... ooo", +"ooo X. .. oooo", +" X. ooo .. o", +" X .. ooo X. . o", +" .. ooo X. o", +"ooo .. X. oooo", +"oo ...XX.. ooo", +"o X. ... .. oo", +"oo . o o . ooo", +"ooo oo . oo oooo", +"oooooo ooooooo" +}; diff --git a/assdraw/src/xpm/transform_xpm.xpm b/assdraw/src/xpm/transform_xpm.xpm new file mode 100644 index 000000000..4efd941ff --- /dev/null +++ b/assdraw/src/xpm/transform_xpm.xpm @@ -0,0 +1,65 @@ +/* XPM */ +static char *transform_xpm[] = { +/* columns rows colors chars-per-pixel */ +"224 56 3 1", +" c black", +". c red", +"X c gray100", +/* pixels */ +"................................................................................................................................................................................................................................", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXX XXXXXX XX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXX XXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXX XXXXX XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXX X XXXX XXXXXXXXXXXXXXX XXXXXX X XX XXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX X XX XXXXXX XXXXXXXXX XXXXX XX XXXX XXXX X XXXXXXXXXXXXXX X XX XX X XXX XXXX XXXXXXXXXXXXX XXXXX X XX X XXXX XXXXX.", +".XXXXX XXXXX XXX XXXXX XXXXXXXXXXXXXXX XXXXX XX XX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXX XX XX XXXXX XXXXXXXX XXXXXX XX XXXX XXXXX XXX XXXXXXXXXXXXXX XX XX XX XXX XXXX XXXX XXXXXXXXXXXXX XXXX XX XX XXX XXXXX XXXXX.", +".XXXXX XXXXXX X XXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXXX XXXXXXX XXXXXXX XX XXXX XXXXXX X XXXX XXX XXX XXX XXX X XXXXX XXXX XXXXXXXXXXXXX XXXXX XXX XXX X XXXXXX XXXXX.", +".XXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXXX XXXXXX XXXXXXXX XX XXXX XXXXXXX XXXXXXXXXXXXXXXXX XXX XXX XXXX XXXXXX XXXX XXXXXXXXXXXXX XXXXX XXX XXXX XXXXXXX XXXXX.", +".XXXXX XXXXXX X XXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXXX XXXXX XXXXXXXXX XX XXXX XXXXXX X XXXXXXXXXXXXXXXX XXX XXX XXX X XXXXX XXXX XXXXXXXXXXXXX XXXXX XXX XXX X XXXXXX XXXXX.", +".XXXXX XXXXX XXX XXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXXX XXXX XXXX XXXXX XX XXXXXXXXXX XXX XXXXXXXXXXXXXXX XXX XXX XX XXX XXXXXXXXX XXXXXXXXXXXXX XXXXX XXX XX XXX XXXXX XXXXX.", +".XXXXX XXXX X XXXX XXXXXXXXXXXXXXX XXXXX X X XXX XXXXX XXXXXXXXXXXXXXXXX X X XXX XXX XXXXX XX XXXXX XXX X XXXXXXXXXXXXX X X X XX XXXXX XXXXXXXXXXXXX XXXX X X XXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXX XXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXX XXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XX XXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXX XXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXX XXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX XXX XXX XXXXXX XX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XX XXXX XXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXX XXXXX XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXX X XXXX XXXXXXXXXXXXXXX XXXXXX X XX XXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXX X XX XXXXXXXX XXXXXXX XXXXX XX XXXX XXXX X XXXXXXXXXXXXXX X XX XX X XXX XXXX XXXXXXXXXXXXX XXXXX X XX X XXXX XXXXX.", +".XXXXX XXXXX XXX XXXXX XXXXXXXXXXXXXXX XXXXX XX XX XXXXXX XXXXXX XXXXXXXXXXXXXXXXXX XX XX XXXXXX XXXXXXX XXXXXX XX XXXX XXXXX XXX XXXXXXXXXXXXXX XX XX XX XXX XXXX XXXX XXXXXXXXXXXXX XXXX XX XX XXX XXXXX XXXXX.", +".XXXXX XXXXX XXX XXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXXX XXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXXX XXXXXXX XXXXXXX XX XXXX XXXXX XXX XXX XXX XXX XXX XX XXX XXXX XXXX XXXXXXXXXXXXX XXXXX XXX XX XXX XXXXX XXXXX.", +".XXXXX XXXXXX X XXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXXX XXXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXXX XXXXXXX XXXXXXXX XX XXXX XXXXXX X XXXXXXXXXXXXXXXX XXX XXX XXX X XXXXX XXXX XXXXXXXXXXXXX XXXXX XXX XXX X XXXXXX XXXXX.", +".XXXXX XXXXXX X XXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XXX XXXXXXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XXX XXXXXXX XXXXXXXXX XX XXXX XXXXXX X XXXXXXXXXXXXXXXX XXX XXX XXX X XXXXX XXXX XXXXXXXXXXXXX XXXXX XXX XXX X XXXXXX XXXXX.", +".XXXXX XXXXXXX XXXXXX XXXXXXXXXXXXXXX XXXXXX XXX XXX XX XXXX XXXXX XXXXXXXXXXXXXXXXXXX XXX XXX XX XXXX XX XXXX XXXXX XX XXXXXXXXXXXX XXXXXXXXXXXXXXXX XXX XXX XXXX XXXXXXXXXX XXXXXXXXXXXXX XXXXX XXX XXXX XXXXXX XXXXX.", +".XXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXX XXXXX X X X XXXX XXXXXXXXXXXXXXXXX X X X XX XXXXX XX XXXXX XXXXXX XXXXXXXXXXXXXXXX X X XXX XXXXX XXXXX XXXXXXXXXXXXX XXXX X XXX XXXXXXX XXXXX.", +".XXXXX XXXXXXX XXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXX XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXX XXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXX XXXXXXX XXXXX.", +".XXXXX XXXXXX XXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXX XXXXX.", +".XXXXX XXXX XXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXX XXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +".XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.", +"................................................................................................................................................................................................................................" +}; diff --git a/assdraw/src/xpm/uncheck__xpm.xpm b/assdraw/src/xpm/uncheck__xpm.xpm new file mode 100644 index 000000000..dfe60f4ed --- /dev/null +++ b/assdraw/src/xpm/uncheck__xpm.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char *uncheck_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 5 1", +" c gray25", +". c #808080808080", +"X c #D4D4D0D0C8C8", +"o c gray100", +"O c None", +/* pixels */ +"OOOOOOOOOOOOOOOO", +"OO............OO", +"OO. XOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO. oooooooooXOO", +"OO.XXXXXXXXXXXOO", +"OOOOOOOOOOOOOOOO", +"OOOOOOOOOOOOOOOO" +};