From cdaed652d7d2b20bc9f508d45f77a280f88279d9 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 30 Sep 2010 10:27:07 +0000 Subject: [PATCH] Merge of SOC2010_RTC_IMAGES branch. Added floating images and image property dialog to wxRichTextCtrl, by Mingquan Yang as part of GSOC 2010. Also changed image block creation to use a memory stream instead of creating a temporary file. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65676 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- Makefile.in | 21 +- build/bakefiles/files.bkl | 2 + build/msw/makefile.bcc | 20 +- build/msw/makefile.gcc | 20 +- build/msw/makefile.vc | 20 +- build/msw/makefile.wat | 20 +- build/msw/wx_core.dsp | 4 + build/msw/wx_richtext.dsp | 8 + build/msw/wx_vc7_core.vcproj | 3 + build/msw/wx_vc7_richtext.vcproj | 6 + build/msw/wx_vc8_core.vcproj | 4 + build/msw/wx_vc8_richtext.vcproj | 8 + build/msw/wx_vc9_core.vcproj | 4 + build/msw/wx_vc9_richtext.vcproj | 8 + include/wx/richtext/richtextbuffer.h | 198 ++- include/wx/richtext/richtextctrl.h | 20 +- include/wx/richtext/richtextimagedlg.h | 142 +++ samples/richtext/richtext.cpp | 78 ++ src/richtext/readme | 54 + src/richtext/richtextbuffer.cpp | 1034 +++++++++++---- src/richtext/richtextctrl.cpp | 60 +- src/richtext/richtextdialogs.pjd | 1618 +++++++++++++++++++++++- src/richtext/richtexthtml.cpp | 36 +- src/richtext/richtextimagedlg.cpp | 554 ++++++++ src/richtext/richtextxml.cpp | 4 +- 25 files changed, 3650 insertions(+), 296 deletions(-) create mode 100644 include/wx/richtext/richtextimagedlg.h create mode 100644 src/richtext/readme create mode 100644 src/richtext/richtextimagedlg.cpp diff --git a/Makefile.in b/Makefile.in index cfffa313f8..e6ca34ef69 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1882,7 +1882,8 @@ RICHTEXTDLL_OBJECTS = \ richtextdll_richtextformatdlg.o \ richtextdll_richtextsymboldlg.o \ richtextdll_richtextstyledlg.o \ - richtextdll_richtextprint.o + richtextdll_richtextprint.o \ + richtextdll_richtextimagedlg.o RICHTEXTDLL_ODEP = $(_____pch_wxprec_richtextdll_wx_wxprec_h_gch___depname) RICHTEXTLIB_CXXFLAGS = $(__richtextlib_PCH_INC) -D__WX$(TOOLKIT)__ \ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) \ @@ -1898,7 +1899,8 @@ RICHTEXTLIB_OBJECTS = \ richtextlib_richtextformatdlg.o \ richtextlib_richtextsymboldlg.o \ richtextlib_richtextstyledlg.o \ - richtextlib_richtextprint.o + richtextlib_richtextprint.o \ + richtextlib_richtextimagedlg.o RICHTEXTLIB_ODEP = $(_____pch_wxprec_richtextlib_wx_wxprec_h_gch___depname) STCDLL_CXXFLAGS = $(__stcdll_PCH_INC) -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) \ $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \ @@ -4132,6 +4134,7 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \ wx/richtext/richtextsymboldlg.h \ wx/richtext/richtextstyledlg.h \ wx/richtext/richtextprint.h \ + wx/richtext/richtextimagedlg.h \ wx/stc/stc.h @COND_USE_GUI_1@ALL_GUI_HEADERS = $(COND_USE_GUI_1_ALL_GUI_HEADERS) COND_MONOLITHIC_1_SHARED_1___monodll___depname = \ @@ -4426,6 +4429,7 @@ COND_USE_GUI_1___MONOLIB_GUI_SRC_OBJECTS = \ monodll_richtextsymboldlg.o \ monodll_richtextstyledlg.o \ monodll_richtextprint.o \ + monodll_richtextimagedlg.o \ monodll_stc.o \ monodll_PlatWX.o \ monodll_ScintillaWX.o @@ -6299,6 +6303,7 @@ COND_USE_GUI_1___MONOLIB_GUI_SRC_OBJECTS_1 = \ monolib_richtextsymboldlg.o \ monolib_richtextstyledlg.o \ monolib_richtextprint.o \ + monolib_richtextimagedlg.o \ monolib_stc.o \ monolib_PlatWX.o \ monolib_ScintillaWX.o @@ -17148,6 +17153,9 @@ monodll_richtextstyledlg.o: $(srcdir)/src/richtext/richtextstyledlg.cpp $(MONODL monodll_richtextprint.o: $(srcdir)/src/richtext/richtextprint.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/richtext/richtextprint.cpp +monodll_richtextimagedlg.o: $(srcdir)/src/richtext/richtextimagedlg.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/richtext/richtextimagedlg.cpp + monodll_stc.o: $(srcdir)/src/stc/stc.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/stc/stc.cpp @@ -22368,6 +22376,9 @@ monolib_richtextstyledlg.o: $(srcdir)/src/richtext/richtextstyledlg.cpp $(MONOLI monolib_richtextprint.o: $(srcdir)/src/richtext/richtextprint.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/richtext/richtextprint.cpp +monolib_richtextimagedlg.o: $(srcdir)/src/richtext/richtextimagedlg.cpp $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/richtext/richtextimagedlg.cpp + monolib_stc.o: $(srcdir)/src/stc/stc.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/stc/stc.cpp @@ -36024,6 +36035,9 @@ richtextdll_richtextstyledlg.o: $(srcdir)/src/richtext/richtextstyledlg.cpp $(RI richtextdll_richtextprint.o: $(srcdir)/src/richtext/richtextprint.cpp $(RICHTEXTDLL_ODEP) $(CXXC) -c -o $@ $(RICHTEXTDLL_CXXFLAGS) $(srcdir)/src/richtext/richtextprint.cpp +richtextdll_richtextimagedlg.o: $(srcdir)/src/richtext/richtextimagedlg.cpp $(RICHTEXTDLL_ODEP) + $(CXXC) -c -o $@ $(RICHTEXTDLL_CXXFLAGS) $(srcdir)/src/richtext/richtextimagedlg.cpp + richtextlib_richtextctrl.o: $(srcdir)/src/richtext/richtextctrl.cpp $(RICHTEXTLIB_ODEP) $(CXXC) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(srcdir)/src/richtext/richtextctrl.cpp @@ -36051,6 +36065,9 @@ richtextlib_richtextstyledlg.o: $(srcdir)/src/richtext/richtextstyledlg.cpp $(RI richtextlib_richtextprint.o: $(srcdir)/src/richtext/richtextprint.cpp $(RICHTEXTLIB_ODEP) $(CXXC) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(srcdir)/src/richtext/richtextprint.cpp +richtextlib_richtextimagedlg.o: $(srcdir)/src/richtext/richtextimagedlg.cpp $(RICHTEXTLIB_ODEP) + $(CXXC) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(srcdir)/src/richtext/richtextimagedlg.cpp + stcdll_version_rc.o: $(srcdir)/src/msw/version.rc $(STCDLL_ODEP) $(WINDRES) -i$< -o$@ --define __WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p_63) $(__DEBUG_DEFINE_p_61) $(__EXCEPTIONS_DEFINE_p_61) $(__RTTI_DEFINE_p_61) $(__THREAD_DEFINE_p_61) --define WXBUILDING --define WXDLLNAME=$(WXDLLNAMEPREFIXGUI)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_stc$(WXCOMPILER)$(VENDORTAG)$(WXDLLVERSIONTAG) $(__RCDEFDIR_p) --include-dir $(top_srcdir)/include $(__INC_TIFF_BUILD_p_62) $(__INC_TIFF_p_62) $(__INC_JPEG_p_62) $(__INC_PNG_p_61) $(__INC_ZLIB_p_63) $(__INC_REGEX_p_61) $(__INC_EXPAT_p_61) --include-dir $(top_srcdir)/src/stc/scintilla/include --include-dir $(top_srcdir)/src/stc/scintilla/src --define __WX__ --define SCI_LEXER --define LINK_LEXERS --define WXUSINGDLL --define WXMAKINGDLL_STC diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 56fb7c0aa8..3b0b289b24 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -3596,6 +3596,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/richtext/richtextsymboldlg.cpp src/richtext/richtextstyledlg.cpp src/richtext/richtextprint.cpp + src/richtext/richtextimagedlg.cpp wx/richtext/richtextctrl.h @@ -3607,6 +3608,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/richtext/richtextsymboldlg.h wx/richtext/richtextstyledlg.h wx/richtext/richtextprint.h + wx/richtext/richtextimagedlg.h diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index ebaec950f2..ba00f19f07 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -1399,7 +1399,8 @@ RICHTEXTDLL_OBJECTS = \ $(OBJS)\richtextdll_richtextformatdlg.obj \ $(OBJS)\richtextdll_richtextsymboldlg.obj \ $(OBJS)\richtextdll_richtextstyledlg.obj \ - $(OBJS)\richtextdll_richtextprint.obj + $(OBJS)\richtextdll_richtextprint.obj \ + $(OBJS)\richtextdll_richtextimagedlg.obj RICHTEXTLIB_CXXFLAGS = $(__RUNTIME_LIBS) -I$(BCCDIR)\include $(__DEBUGINFO) \ $(__OPTIMIZEFLAG) $(__THREADSFLAG) -D__WXMSW__ $(__WXUNIV_DEFINE_p) \ $(__DEBUG_DEFINE_p) $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) \ @@ -1419,7 +1420,8 @@ RICHTEXTLIB_OBJECTS = \ $(OBJS)\richtextlib_richtextformatdlg.obj \ $(OBJS)\richtextlib_richtextsymboldlg.obj \ $(OBJS)\richtextlib_richtextstyledlg.obj \ - $(OBJS)\richtextlib_richtextprint.obj + $(OBJS)\richtextlib_richtextprint.obj \ + $(OBJS)\richtextlib_richtextimagedlg.obj STCDLL_CXXFLAGS = $(__RUNTIME_LIBS) -I$(BCCDIR)\include $(__DEBUGINFO) \ $(__OPTIMIZEFLAG) $(__THREADSFLAG) -D__WXMSW__ $(__WXUNIV_DEFINE_p) \ $(__DEBUG_DEFINE_p) $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) \ @@ -1663,6 +1665,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_richtextsymboldlg.obj \ $(OBJS)\monodll_richtextstyledlg.obj \ $(OBJS)\monodll_richtextprint.obj \ + $(OBJS)\monodll_richtextimagedlg.obj \ $(OBJS)\monodll_stc.obj \ $(OBJS)\monodll_PlatWX.obj \ $(OBJS)\monodll_ScintillaWX.obj @@ -2383,6 +2386,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_richtextsymboldlg.obj \ $(OBJS)\monolib_richtextstyledlg.obj \ $(OBJS)\monolib_richtextprint.obj \ + $(OBJS)\monolib_richtextimagedlg.obj \ $(OBJS)\monolib_stc.obj \ $(OBJS)\monolib_PlatWX.obj \ $(OBJS)\monolib_ScintillaWX.obj @@ -6793,6 +6797,9 @@ $(OBJS)\monodll_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cpp $(OBJS)\monodll_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\monodll_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\monodll_stc.obj: ..\..\src\stc\stc.cpp $(CXX) -q -c -P -o$@ $(MONODLL_CXXFLAGS) ..\..\src\stc\stc.cpp @@ -9028,6 +9035,9 @@ $(OBJS)\monolib_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cpp $(OBJS)\monolib_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\monolib_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\monolib_stc.obj: ..\..\src\stc\stc.cpp $(CXX) -q -c -P -o$@ $(MONOLIB_CXXFLAGS) ..\..\src\stc\stc.cpp @@ -14633,6 +14643,9 @@ $(OBJS)\richtextdll_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cp $(OBJS)\richtextdll_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) -q -c -P -o$@ $(RICHTEXTDLL_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\richtextdll_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -q -c -P -o$@ $(RICHTEXTDLL_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\richtextlib_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) -q -c -P -o$@ $(RICHTEXTLIB_CXXFLAGS) -H ..\..\src\common\dummy.cpp @@ -14663,6 +14676,9 @@ $(OBJS)\richtextlib_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cp $(OBJS)\richtextlib_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) -q -c -P -o$@ $(RICHTEXTLIB_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\richtextlib_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -q -c -P -o$@ $(RICHTEXTLIB_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\stcdll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) -H ..\..\src\common\dummy.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 0fe7a187a0..e49c3a6292 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -1402,7 +1402,8 @@ RICHTEXTDLL_OBJECTS = \ $(OBJS)\richtextdll_richtextformatdlg.o \ $(OBJS)\richtextdll_richtextsymboldlg.o \ $(OBJS)\richtextdll_richtextstyledlg.o \ - $(OBJS)\richtextdll_richtextprint.o + $(OBJS)\richtextdll_richtextprint.o \ + $(OBJS)\richtextdll_richtextimagedlg.o RICHTEXTLIB_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) \ $(GCCFLAGS) -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) \ $(__DEBUG_DEFINE_p) $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) \ @@ -1422,7 +1423,8 @@ RICHTEXTLIB_OBJECTS = \ $(OBJS)\richtextlib_richtextformatdlg.o \ $(OBJS)\richtextlib_richtextsymboldlg.o \ $(OBJS)\richtextlib_richtextstyledlg.o \ - $(OBJS)\richtextlib_richtextprint.o + $(OBJS)\richtextlib_richtextprint.o \ + $(OBJS)\richtextlib_richtextimagedlg.o STCDLL_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) $(GCCFLAGS) \ -DHAVE_W32API_H -D__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \ $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \ @@ -1673,6 +1675,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_richtextsymboldlg.o \ $(OBJS)\monodll_richtextstyledlg.o \ $(OBJS)\monodll_richtextprint.o \ + $(OBJS)\monodll_richtextimagedlg.o \ $(OBJS)\monodll_stc.o \ $(OBJS)\monodll_PlatWX.o \ $(OBJS)\monodll_ScintillaWX.o @@ -2399,6 +2402,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_richtextsymboldlg.o \ $(OBJS)\monolib_richtextstyledlg.o \ $(OBJS)\monolib_richtextprint.o \ + $(OBJS)\monolib_richtextimagedlg.o \ $(OBJS)\monolib_stc.o \ $(OBJS)\monolib_PlatWX.o \ $(OBJS)\monolib_ScintillaWX.o @@ -6943,6 +6947,9 @@ $(OBJS)\monodll_richtextstyledlg.o: ../../src/richtext/richtextstyledlg.cpp $(OBJS)\monodll_richtextprint.o: ../../src/richtext/richtextprint.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monodll_richtextimagedlg.o: ../../src/richtext/richtextimagedlg.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monodll_stc.o: ../../src/stc/stc.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -9178,6 +9185,9 @@ $(OBJS)\monolib_richtextstyledlg.o: ../../src/richtext/richtextstyledlg.cpp $(OBJS)\monolib_richtextprint.o: ../../src/richtext/richtextprint.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\monolib_richtextimagedlg.o: ../../src/richtext/richtextimagedlg.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\monolib_stc.o: ../../src/stc/stc.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -14783,6 +14793,9 @@ $(OBJS)\richtextdll_richtextstyledlg.o: ../../src/richtext/richtextstyledlg.cpp $(OBJS)\richtextdll_richtextprint.o: ../../src/richtext/richtextprint.cpp $(CXX) -c -o $@ $(RICHTEXTDLL_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\richtextdll_richtextimagedlg.o: ../../src/richtext/richtextimagedlg.cpp + $(CXX) -c -o $@ $(RICHTEXTDLL_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\richtextlib_dummy.o: ../../src/common/dummy.cpp $(CXX) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(CPPDEPS) $< @@ -14813,6 +14826,9 @@ $(OBJS)\richtextlib_richtextstyledlg.o: ../../src/richtext/richtextstyledlg.cpp $(OBJS)\richtextlib_richtextprint.o: ../../src/richtext/richtextprint.cpp $(CXX) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\richtextlib_richtextimagedlg.o: ../../src/richtext/richtextimagedlg.cpp + $(CXX) -c -o $@ $(RICHTEXTLIB_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\stcdll_dummy.o: ../../src/common/dummy.cpp $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 46b9031bc9..af9255f2a1 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -1502,7 +1502,8 @@ RICHTEXTDLL_OBJECTS = \ $(OBJS)\richtextdll_richtextformatdlg.obj \ $(OBJS)\richtextdll_richtextsymboldlg.obj \ $(OBJS)\richtextdll_richtextstyledlg.obj \ - $(OBJS)\richtextdll_richtextprint.obj + $(OBJS)\richtextdll_richtextprint.obj \ + $(OBJS)\richtextdll_richtextimagedlg.obj RICHTEXTDLL_RESOURCES = \ $(OBJS)\richtextdll_version.res RICHTEXTLIB_CXXFLAGS = /M$(__RUNTIME_LIBS_534)$(__DEBUGRUNTIME) /DWIN32 \ @@ -1526,7 +1527,8 @@ RICHTEXTLIB_OBJECTS = \ $(OBJS)\richtextlib_richtextformatdlg.obj \ $(OBJS)\richtextlib_richtextsymboldlg.obj \ $(OBJS)\richtextlib_richtextstyledlg.obj \ - $(OBJS)\richtextlib_richtextprint.obj + $(OBJS)\richtextlib_richtextprint.obj \ + $(OBJS)\richtextlib_richtextimagedlg.obj STCDLL_CXXFLAGS = /M$(__RUNTIME_LIBS_550)$(__DEBUGRUNTIME) /DWIN32 \ $(__DEBUGINFO) \ /Fd$(LIBDIRNAME)\wx$(PORTNAME)$(WXUNIVNAME)$(WX_VERSION_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_stc_vc$(VENDORTAG).pdb \ @@ -1871,6 +1873,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_richtextsymboldlg.obj \ $(OBJS)\monodll_richtextstyledlg.obj \ $(OBJS)\monodll_richtextprint.obj \ + $(OBJS)\monodll_richtextimagedlg.obj \ $(OBJS)\monodll_stc.obj \ $(OBJS)\monodll_PlatWX.obj \ $(OBJS)\monodll_ScintillaWX.obj @@ -2597,6 +2600,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_richtextsymboldlg.obj \ $(OBJS)\monolib_richtextstyledlg.obj \ $(OBJS)\monolib_richtextprint.obj \ + $(OBJS)\monolib_richtextimagedlg.obj \ $(OBJS)\monolib_stc.obj \ $(OBJS)\monolib_PlatWX.obj \ $(OBJS)\monolib_ScintillaWX.obj @@ -7373,6 +7377,9 @@ $(OBJS)\monodll_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cpp $(OBJS)\monodll_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\monodll_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\monodll_stc.obj: ..\..\src\stc\stc.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\stc\stc.cpp @@ -9608,6 +9615,9 @@ $(OBJS)\monolib_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cpp $(OBJS)\monolib_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\monolib_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\monolib_stc.obj: ..\..\src\stc\stc.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\stc\stc.cpp @@ -15213,6 +15223,9 @@ $(OBJS)\richtextdll_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cp $(OBJS)\richtextdll_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) /c /nologo /TP /Fo$@ $(RICHTEXTDLL_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\richtextdll_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) /c /nologo /TP /Fo$@ $(RICHTEXTDLL_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\richtextlib_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) /c /nologo /TP /Fo$@ $(RICHTEXTLIB_CXXFLAGS) /Ycwx/wxprec.h ..\..\src\common\dummy.cpp @@ -15243,6 +15256,9 @@ $(OBJS)\richtextlib_richtextstyledlg.obj: ..\..\src\richtext\richtextstyledlg.cp $(OBJS)\richtextlib_richtextprint.obj: ..\..\src\richtext\richtextprint.cpp $(CXX) /c /nologo /TP /Fo$@ $(RICHTEXTLIB_CXXFLAGS) ..\..\src\richtext\richtextprint.cpp +$(OBJS)\richtextlib_richtextimagedlg.obj: ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) /c /nologo /TP /Fo$@ $(RICHTEXTLIB_CXXFLAGS) ..\..\src\richtext\richtextimagedlg.cpp + $(OBJS)\stcdll_dummy.obj: ..\..\src\common\dummy.cpp $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) /Ycwx/wxprec.h ..\..\src\common\dummy.cpp diff --git a/build/msw/makefile.wat b/build/msw/makefile.wat index b0c2f5dead..d7d68c40ca 100644 --- a/build/msw/makefile.wat +++ b/build/msw/makefile.wat @@ -231,6 +231,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_OBJECTS = & $(OBJS)\monodll_richtextsymboldlg.obj & $(OBJS)\monodll_richtextstyledlg.obj & $(OBJS)\monodll_richtextprint.obj & + $(OBJS)\monodll_richtextimagedlg.obj & $(OBJS)\monodll_stc.obj & $(OBJS)\monodll_PlatWX.obj & $(OBJS)\monodll_ScintillaWX.obj @@ -962,6 +963,7 @@ ____MONOLIB_GUI_SRC_FILENAMES_1_OBJECTS = & $(OBJS)\monolib_richtextsymboldlg.obj & $(OBJS)\monolib_richtextstyledlg.obj & $(OBJS)\monolib_richtextprint.obj & + $(OBJS)\monolib_richtextimagedlg.obj & $(OBJS)\monolib_stc.obj & $(OBJS)\monolib_PlatWX.obj & $(OBJS)\monolib_ScintillaWX.obj @@ -4653,7 +4655,8 @@ RICHTEXTDLL_OBJECTS = & $(OBJS)\richtextdll_richtextformatdlg.obj & $(OBJS)\richtextdll_richtextsymboldlg.obj & $(OBJS)\richtextdll_richtextstyledlg.obj & - $(OBJS)\richtextdll_richtextprint.obj + $(OBJS)\richtextdll_richtextprint.obj & + $(OBJS)\richtextdll_richtextimagedlg.obj RICHTEXTLIB_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) & $(__RUNTIME_LIBS) -d__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) & $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) & @@ -4673,7 +4676,8 @@ RICHTEXTLIB_OBJECTS = & $(OBJS)\richtextlib_richtextformatdlg.obj & $(OBJS)\richtextlib_richtextsymboldlg.obj & $(OBJS)\richtextlib_richtextstyledlg.obj & - $(OBJS)\richtextlib_richtextprint.obj + $(OBJS)\richtextlib_richtextprint.obj & + $(OBJS)\richtextlib_richtextimagedlg.obj STCDLL_CXXFLAGS = -bd $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__THREADSFLAG) & $(__RUNTIME_LIBS) -d__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) & $(__NDEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) & @@ -7202,6 +7206,9 @@ $(OBJS)\monodll_richtextstyledlg.obj : .AUTODEPEND ..\..\src\richtext\richtexts $(OBJS)\monodll_richtextprint.obj : .AUTODEPEND ..\..\src\richtext\richtextprint.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< +$(OBJS)\monodll_richtextimagedlg.obj : .AUTODEPEND ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< + $(OBJS)\monodll_stc.obj : .AUTODEPEND ..\..\src\stc\stc.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONODLL_CXXFLAGS) $< @@ -9437,6 +9444,9 @@ $(OBJS)\monolib_richtextstyledlg.obj : .AUTODEPEND ..\..\src\richtext\richtexts $(OBJS)\monolib_richtextprint.obj : .AUTODEPEND ..\..\src\richtext\richtextprint.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< +$(OBJS)\monolib_richtextimagedlg.obj : .AUTODEPEND ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< + $(OBJS)\monolib_stc.obj : .AUTODEPEND ..\..\src\stc\stc.cpp $(CXX) -bt=nt -zq -fo=$^@ $(MONOLIB_CXXFLAGS) $< @@ -15042,6 +15052,9 @@ $(OBJS)\richtextdll_richtextstyledlg.obj : .AUTODEPEND ..\..\src\richtext\richt $(OBJS)\richtextdll_richtextprint.obj : .AUTODEPEND ..\..\src\richtext\richtextprint.cpp $(CXX) -bt=nt -zq -fo=$^@ $(RICHTEXTDLL_CXXFLAGS) $< +$(OBJS)\richtextdll_richtextimagedlg.obj : .AUTODEPEND ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(RICHTEXTDLL_CXXFLAGS) $< + $(OBJS)\richtextlib_dummy.obj : .AUTODEPEND ..\..\src\common\dummy.cpp $(CXX) -bt=nt -zq -fo=$^@ $(RICHTEXTLIB_CXXFLAGS) $< @@ -15072,6 +15085,9 @@ $(OBJS)\richtextlib_richtextstyledlg.obj : .AUTODEPEND ..\..\src\richtext\richt $(OBJS)\richtextlib_richtextprint.obj : .AUTODEPEND ..\..\src\richtext\richtextprint.cpp $(CXX) -bt=nt -zq -fo=$^@ $(RICHTEXTLIB_CXXFLAGS) $< +$(OBJS)\richtextlib_richtextimagedlg.obj : .AUTODEPEND ..\..\src\richtext\richtextimagedlg.cpp + $(CXX) -bt=nt -zq -fo=$^@ $(RICHTEXTLIB_CXXFLAGS) $< + $(OBJS)\stcdll_dummy.obj : .AUTODEPEND ..\..\src\common\dummy.cpp $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $< diff --git a/build/msw/wx_core.dsp b/build/msw/wx_core.dsp index c634d9e470..c928a10c6d 100644 --- a/build/msw/wx_core.dsp +++ b/build/msw/wx_core.dsp @@ -6529,6 +6529,10 @@ SOURCE=..\..\include\wx\richtext\richtexthtml.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\richtext\richtextimagedlg.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\richtext\richtextprint.h # End Source File # Begin Source File diff --git a/build/msw/wx_richtext.dsp b/build/msw/wx_richtext.dsp index 3a639cf68a..0c111c88d7 100644 --- a/build/msw/wx_richtext.dsp +++ b/build/msw/wx_richtext.dsp @@ -546,6 +546,10 @@ SOURCE=..\..\include\wx\richtext\richtexthtml.h # End Source File # Begin Source File +SOURCE=..\..\include\wx\richtext\richtextimagedlg.h +# End Source File +# Begin Source File + SOURCE=..\..\include\wx\richtext\richtextprint.h # End Source File # Begin Source File @@ -586,6 +590,10 @@ SOURCE=..\..\src\richtext\richtexthtml.cpp # End Source File # Begin Source File +SOURCE=..\..\src\richtext\richtextimagedlg.cpp +# End Source File +# Begin Source File + SOURCE=..\..\src\richtext\richtextprint.cpp # End Source File # Begin Source File diff --git a/build/msw/wx_vc7_core.vcproj b/build/msw/wx_vc7_core.vcproj index 9293774b68..ca414ca1a5 100644 --- a/build/msw/wx_vc7_core.vcproj +++ b/build/msw/wx_vc7_core.vcproj @@ -5491,6 +5491,9 @@ + + diff --git a/build/msw/wx_vc7_richtext.vcproj b/build/msw/wx_vc7_richtext.vcproj index 2389754928..cce08cd91b 100644 --- a/build/msw/wx_vc7_richtext.vcproj +++ b/build/msw/wx_vc7_richtext.vcproj @@ -791,6 +791,9 @@ + + @@ -823,6 +826,9 @@ + + diff --git a/build/msw/wx_vc8_core.vcproj b/build/msw/wx_vc8_core.vcproj index f98f79ee34..6546f94c0a 100644 --- a/build/msw/wx_vc8_core.vcproj +++ b/build/msw/wx_vc8_core.vcproj @@ -7339,6 +7339,10 @@ RelativePath="..\..\include\wx\richtext\richtexthtml.h" > + + diff --git a/build/msw/wx_vc8_richtext.vcproj b/build/msw/wx_vc8_richtext.vcproj index 4c875a3477..6f017c412f 100644 --- a/build/msw/wx_vc8_richtext.vcproj +++ b/build/msw/wx_vc8_richtext.vcproj @@ -1074,6 +1074,10 @@ RelativePath="..\..\include\wx\richtext\richtexthtml.h" > + + @@ -1116,6 +1120,10 @@ RelativePath="..\..\src\richtext\richtexthtml.cpp" > + + diff --git a/build/msw/wx_vc9_core.vcproj b/build/msw/wx_vc9_core.vcproj index a24a454467..9d3c2c5e41 100644 --- a/build/msw/wx_vc9_core.vcproj +++ b/build/msw/wx_vc9_core.vcproj @@ -7335,6 +7335,10 @@ RelativePath="..\..\include\wx\richtext\richtexthtml.h" > + + diff --git a/build/msw/wx_vc9_richtext.vcproj b/build/msw/wx_vc9_richtext.vcproj index 600c860691..4232ad14a2 100644 --- a/build/msw/wx_vc9_richtext.vcproj +++ b/build/msw/wx_vc9_richtext.vcproj @@ -1070,6 +1070,10 @@ RelativePath="..\..\include\wx\richtext\richtexthtml.h" > + + @@ -1112,6 +1116,10 @@ RelativePath="..\..\src\richtext\richtexthtml.cpp" > + + diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index c1ba9cb454..f819000135 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -113,6 +113,7 @@ enum wxRichTextFileType class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextCtrl; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextObject; +class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextImage; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextCacheObject; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextObjectList; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextLine; @@ -123,6 +124,8 @@ class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextListStyleDefinition; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextEvent; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextRenderer; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextBuffer; +class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextAnchoredObject; +class wxRichTextFloatCollector; /*! * Flags determining the available space, passed to Layout @@ -232,6 +235,69 @@ enum wxRichTextHitTestFlags #define wxSCRIPT_MUL_FACTOR 1.5 +// Image align/floating +#define wxRICHTEXT_LEFT 0x00 +#define wxRICHTEXT_CENTRE 0x01 +#define wxRICHTEXT_RIGHT 0x02 + +#define wxRICHTEXT_FLOAT_NONE 0x00 +#define wxRICHTEXT_FLOAT_LEFT 0x01 +#define wxRICHTEXT_FLOAT_RIGHT 0x02 + +// Image width/height scale +#define wxRICHTEXT_PX 0x00 +#define wxRICHTEXT_MM 0x01 + +/*! + * wxRichTextAnchoredObjectAttr class declaration + */ +class WXDLLIMPEXP_RICHTEXT wxRichTextAnchoredObjectAttr +{ +public: + wxRichTextAnchoredObjectAttr() { Init(); } + wxRichTextAnchoredObjectAttr(const wxRichTextAnchoredObjectAttr& attr) { Copy(attr); } + + void Init(); + + void operator= (const wxRichTextAnchoredObjectAttr& attr) { Copy(attr); } + void Copy(const wxRichTextAnchoredObjectAttr& attr); + + /// Is this anchored? TODO: difference between anchored and floating? + bool IsAnchored() const { return m_floating != wxRICHTEXT_FLOAT_NONE; } + + /// Is this floating? + bool IsFloating() const { return m_floating != wxRICHTEXT_FLOAT_NONE; } + void SetFloatingMode(int floating) { m_floating = floating; } + + int GetAlignment() const { return m_align; } + void SetAlignment(int align) { m_align = align; } + + int GetOffset() const { return m_offset; } + void SetOffset(int offset) { m_offset = offset; } + + int GetUnitsOffset() const { return m_unitsOffset; } + void SetUnitsOffset(int offset) { m_unitsOffset = offset; } + + int GetUnitsW() const { return m_unitsW; } + void SetUnitsW(int u) { m_unitsW = u; } + + int GetUnitsH() const { return m_unitsH; } + void SetUnitsH(int u) { m_unitsH = u; } + + int GetWidth() const { return m_width; } + void SetWidth(int w) { m_width = w; } + + int GetHeight() const { return m_height; } + void SetHeight(int h) { m_height = h; } + + int m_align; + int m_floating; + int m_offset; + int m_unitsOffset; + int m_unitsW, m_unitsH; + int m_width, m_height; +}; + /*! * wxRichTextFontTable * Manages quick access to a pool of fonts for rendering rich text @@ -377,6 +443,18 @@ public: /// Returns true if the object is empty virtual bool IsEmpty() const { return false; } + /// Whether this object floatable + virtual bool IsFloatable() const { return false; } + + /// Whether this object is currently floating + virtual bool IsFloating() const { return false; } + + /// Whether this object is a place holding one + // virtual bool IsPlaceHolding() const { return false; } + + /// Floating direction + virtual int GetFloatDirection() const { return wxRICHTEXT_FLOAT_NONE; } + /// Get any text in this object for the given range virtual wxString GetTextForRange(const wxRichTextRange& WXUNUSED(range)) const { return wxEmptyString; } @@ -389,6 +467,12 @@ public: /// Dump to output stream for debugging virtual void Dump(wxTextOutputStream& stream); + + /// Can we edit properties via a GUI? + virtual bool CanEditProperties() const { return false; } + + /// Edit properties via a GUI + virtual bool EditProperties(wxWindow* WXUNUSED(parent), wxRichTextBuffer* WXUNUSED(buffer)) { return false; } // Accessors @@ -455,7 +539,7 @@ public: void Dereference(); /// Convert units in tenths of a millimetre to device units - int ConvertTenthsMMToPixels(wxDC& dc, int units); + int ConvertTenthsMMToPixels(wxDC& dc, int units) const; static int ConvertTenthsMMToPixels(int ppi, int units); protected: @@ -617,9 +701,14 @@ public: wxRichTextParagraphLayoutBox(wxRichTextObject* parent = NULL); wxRichTextParagraphLayoutBox(const wxRichTextParagraphLayoutBox& obj): wxRichTextBox() { Init(); Copy(obj); } + ~wxRichTextParagraphLayoutBox(); // Overrideables + /// Hit-testing: returns a flag indicating hit test details, plus + /// information about position + virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition); + /// Draw the item virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style); @@ -653,6 +742,11 @@ public: virtual wxRichTextStyleSheet* GetStyleSheet() const { return NULL; } // Operations + /// Draw the floats of this buffer + void DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style); + + /// Move an anchored object to another paragraph + void MoveAnchoredObjectToParagraph(wxRichTextParagraph* from, wxRichTextParagraph* to, wxRichTextAnchoredObject* obj); /// Initialize the object. void Init(); @@ -726,6 +820,9 @@ public: /// Set text attributes: character and/or paragraph styles. virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttr& style, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO); + /// Set image attribute + void SetImageStyle(wxRichTextImage *image, const wxRichTextAnchoredObjectAttr& style, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO); + /// Get the conbined text attributes for this position. virtual bool GetStyle(long position, wxTextAttr& style); @@ -821,10 +918,18 @@ public: /// Invalidate the buffer. With no argument, invalidates whole buffer. void Invalidate(const wxRichTextRange& invalidRange = wxRICHTEXT_ALL); + + /// Gather information about floating objects. If untilObj is non-NULL, + /// will stop getting information if the current object is this, since we + /// will collect the rest later. + virtual bool UpdateFloatingObjects(int width, wxRichTextObject* untilObj = NULL); /// Get invalid range, rounding to entire paragraphs if argument is true. wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const; + /// Get the wxRichTextFloatCollector of this object + wxRichTextFloatCollector* GetFloatCollector() { return m_floatCollector; } + protected: wxRichTextCtrl* m_ctrl; wxTextAttr m_defaultAttributes; @@ -834,6 +939,9 @@ protected: // Is the last paragraph partial or complete? bool m_partialParagraph; + + // The floating layout state + wxRichTextFloatCollector* m_floatCollector; }; /*! @@ -1038,12 +1146,17 @@ public: /// Get default tabstop array static const wxArrayInt& GetDefaultTabs() { return sm_defaultTabs; } + /// Layout the floats object + void LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector); + protected: /// The lines that make up the wrapped paragraph wxRichTextLineList m_cachedLines; /// Default tabstops static wxArrayInt sm_defaultTabs; + +friend class wxRichTextFloatCollector; }; /*! @@ -1151,6 +1264,12 @@ public: // Make an image block from the wxImage in the given // format. virtual bool MakeImageBlock(wxImage& image, wxBitmapType imageType, int quality = 80); + + // Uses a const wxImage for efficiency, but can't set quality (only relevant for JPEG) + virtual bool MakeImageBlockDefaultQuality(const wxImage& image, wxBitmapType imageType); + + // Makes the image block + virtual bool DoMakeImageBlock(const wxImage& image, wxBitmapType imageType); // Write to a file bool Write(const wxString& filename); @@ -1206,22 +1325,58 @@ protected: wxBitmapType m_imageType; }; +/*! + * wxRichTextAnchoredObject class declaration + * This object is an abstract one that represent some objects which can floats + */ +class WXDLLIMPEXP_RICHTEXT wxRichTextAnchoredObject: public wxRichTextObject +{ + DECLARE_CLASS(wxRichTextAnchoredObject) +public: +// Constructors + wxRichTextAnchoredObject(wxRichTextObject* parent = NULL, const wxRichTextAnchoredObjectAttr& attr = wxRichTextAnchoredObjectAttr()); + wxRichTextAnchoredObject(const wxRichTextAnchoredObject& obj) : wxRichTextObject(obj) /* , m_ph(NULL) */ { Copy(obj); } + ~wxRichTextAnchoredObject(); + +// Virtuals + virtual bool IsFloatable() const { return true; } + + /// Whether this object is currently floating + virtual bool IsFloating() const { return m_anchoredAttr.m_floating != wxRICHTEXT_FLOAT_NONE; } + + virtual void SetParent(wxRichTextObject* parent); + +// Accessors + const wxRichTextAnchoredObjectAttr& GetAnchoredAttr() const { return m_anchoredAttr; } + void SetAnchoredAttr(const wxRichTextAnchoredObjectAttr& attr); + + /// The floating direction + virtual int GetFloatDirection() const { return m_anchoredAttr.m_floating; } + + void operator=(const wxRichTextAnchoredObject&) { wxASSERT("Nobody can reset this object using ="); } + +// Functions + void Copy(const wxRichTextAnchoredObject& obj); + +protected: + wxRichTextAnchoredObjectAttr m_anchoredAttr; +}; /*! * wxRichTextImage class declaration * This object represents an image. */ -class WXDLLIMPEXP_RICHTEXT wxRichTextImage: public wxRichTextObject +class WXDLLIMPEXP_RICHTEXT wxRichTextImage: public wxRichTextAnchoredObject { DECLARE_DYNAMIC_CLASS(wxRichTextImage) public: // Constructors - wxRichTextImage(wxRichTextObject* parent = NULL): wxRichTextObject(parent) { } + wxRichTextImage(wxRichTextObject* parent = NULL): wxRichTextAnchoredObject(parent) { } wxRichTextImage(const wxImage& image, wxRichTextObject* parent = NULL, wxTextAttr* charStyle = NULL); wxRichTextImage(const wxRichTextImageBlock& imageBlock, wxRichTextObject* parent = NULL, wxTextAttr* charStyle = NULL); - wxRichTextImage(const wxRichTextImage& obj): wxRichTextObject() { Copy(obj); } + wxRichTextImage(const wxRichTextImage& obj): wxRichTextAnchoredObject(obj) { Copy(obj); } // Overrideables @@ -1236,15 +1391,24 @@ public: virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; /// Returns true if the object is empty - virtual bool IsEmpty() const { return !m_image.Ok(); } + virtual bool IsEmpty() const { return !m_imageBlock.Ok(); } + + /// Can we edit properties via a GUI? + virtual bool CanEditProperties() const { return true; } + + /// Edit properties via a GUI + virtual bool EditProperties(wxWindow* parent, wxRichTextBuffer* buffer); // Accessors - /// Get the image - const wxImage& GetImage() const { return m_image; } + /// Get the image cache (scaled bitmap) + const wxBitmap& GetImageCache() const { return m_imageCache; } - /// Set the image - void SetImage(const wxImage& image) { m_image = image; } + /// Set the image cache + void SetImageCache(const wxBitmap& bitmap) { m_imageCache = bitmap; } + + /// Reset the image cache + void ResetImageCache() { m_imageCache = wxNullBitmap; } /// Get the image block containing the raw data wxRichTextImageBlock& GetImageBlock() { return m_imageBlock; } @@ -1257,17 +1421,12 @@ public: /// Clone virtual wxRichTextObject* Clone() const { return new wxRichTextImage(*this); } - /// Load wxImage from the block - virtual bool LoadFromBlock(); - - /// Make block from the wxImage - virtual bool MakeBlock(); + /// Create a cached image at the required size + virtual bool LoadImageCache(wxDC& dc, bool resetCache = false); protected: - // TODO: reduce the multiple representations of data - wxImage m_image; - wxBitmap m_bitmap; wxRichTextImageBlock m_imageBlock; + wxBitmap m_imageCache; }; @@ -1535,7 +1694,10 @@ public: bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags = 0); /// Submit command to insert the given image - bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags = 0); + bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags = 0, const wxRichTextAnchoredObjectAttr& floatAttr = wxRichTextAnchoredObjectAttr()); + + /// Submit command to insert an object + bool InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags); /// Submit command to delete this range bool DeleteRangeWithUndo(const wxRichTextRange& range, wxRichTextCtrl* ctrl); diff --git a/include/wx/richtext/richtextctrl.h b/include/wx/richtext/richtextctrl.h index 9973ba7b81..abf7f449a9 100644 --- a/include/wx/richtext/richtextctrl.h +++ b/include/wx/richtext/richtextctrl.h @@ -184,6 +184,10 @@ public: long GetSelectionAnchor() const { return m_selectionAnchor; } void SetSelectionAnchor(long anchor) { m_selectionAnchor = anchor; } + /// The wxRichTextObject object under mouse if any + wxRichTextObject* GetCurrentObject() const { return m_currentObject; } + void SetCurrentObject(wxRichTextObject* obj) { m_currentObject = obj; } + // Operations // editing @@ -222,6 +226,9 @@ public: virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttr& style); virtual bool GetStyle(long position, wxTextAttr& style); + // Set an image style + void SetImageStyle(wxRichTextImage *image, const wxRichTextAnchoredObjectAttr& style); + // get the common set of styles for the range virtual bool GetStyleForRange(const wxRichTextRange& range, wxTextAttr& style); // extended style setting operation with flags including: @@ -309,17 +316,17 @@ public: /// Write an image at the current insertion point. Supply optional type to use /// for internal and file storage of the raw data. - virtual bool WriteImage(const wxImage& image, wxBitmapType bitmapType = wxBITMAP_TYPE_PNG); + virtual bool WriteImage(const wxImage& image, wxBitmapType bitmapType = wxBITMAP_TYPE_PNG, const wxRichTextAnchoredObjectAttr& attr = wxRichTextAnchoredObjectAttr()); /// Write a bitmap at the current insertion point. Supply optional type to use /// for internal and file storage of the raw data. - virtual bool WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType = wxBITMAP_TYPE_PNG); + virtual bool WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType = wxBITMAP_TYPE_PNG, const wxRichTextAnchoredObjectAttr& attr = wxRichTextAnchoredObjectAttr()); /// Load an image from file and write at the current insertion point. - virtual bool WriteImage(const wxString& filename, wxBitmapType bitmapType); + virtual bool WriteImage(const wxString& filename, wxBitmapType bitmapType, const wxRichTextAnchoredObjectAttr& attr = wxRichTextAnchoredObjectAttr()); /// Write an image block at the current insertion point. - virtual bool WriteImage(const wxRichTextImageBlock& imageBlock); + virtual bool WriteImage(const wxRichTextImageBlock& imageBlock, const wxRichTextAnchoredObjectAttr& attr = wxRichTextAnchoredObjectAttr()); /// Insert a newline (actually paragraph) at the current insertion point. virtual bool Newline(); @@ -621,6 +628,7 @@ public: void OnUndo(wxCommandEvent& event); void OnRedo(wxCommandEvent& event); void OnSelectAll(wxCommandEvent& event); + void OnImage(wxCommandEvent& event); void OnClear(wxCommandEvent& event); void OnUpdateCut(wxUpdateUIEvent& event); @@ -629,6 +637,7 @@ public: void OnUpdateUndo(wxUpdateUIEvent& event); void OnUpdateRedo(wxUpdateUIEvent& event); void OnUpdateSelectAll(wxUpdateUIEvent& event); + void OnUpdateImage(wxUpdateUIEvent& event); void OnUpdateClear(wxUpdateUIEvent& event); // Show a context menu for Rich Edit controls (the standard @@ -883,6 +892,9 @@ private: wxCursor m_urlCursor; static wxArrayString sm_availableFontNames; + /// The wxRichTextObject object under mouse if any + wxRichTextObject* m_currentObject; + long m_imagePropertyId; }; /*! diff --git a/include/wx/richtext/richtextimagedlg.h b/include/wx/richtext/richtextimagedlg.h new file mode 100644 index 0000000000..f2865c016a --- /dev/null +++ b/include/wx/richtext/richtextimagedlg.h @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/richtext/richtextimagedlg.h +// Purpose: +// Author: Mingquan Yang +// Modified by: +// Created: Wed 02 Jun 2010 11:27:23 CST +// RCS-ID: +// Copyright: (c) Mingquan Yang +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _RICHTEXTIMAGEDLG_H_ +#define _RICHTEXTIMAGEDLG_H_ + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) +#pragma interface "wx/richtext/richtextimagedlg.h" +#endif + +/*! + * Includes + */ +#include "wx/richtext/richtextbuffer.h" +////@begin includes +#include "wx/statline.h" +////@end includes + +/*! + * Forward declarations + */ + +////@begin forward declarations +////@end forward declarations + +/*! + * Control identifiers + */ + +////@begin control identifiers +#define SYMBOL_WXRICHTEXTIMAGEDIALOG_STYLE wxDEFAULT_DIALOG_STYLE|wxTAB_TRAVERSAL +#define SYMBOL_WXRICHTEXTIMAGEDIALOG_TITLE _("Image Properties") +#define SYMBOL_WXRICHTEXTIMAGEDIALOG_IDNAME ID_WXRICHTEXTIMAGEPAGE +#define SYMBOL_WXRICHTEXTIMAGEDIALOG_SIZE wxSize(400, 300) +#define SYMBOL_WXRICHTEXTIMAGEDIALOG_POSITION wxDefaultPosition +////@end control identifiers + + +/*! + * wxRichTextImageDialog class declaration + */ + +class WXDLLIMPEXP_RICHTEXT wxRichTextImageDialog: public wxDialog +{ + DECLARE_DYNAMIC_CLASS( wxRichTextImageDialog ) + DECLARE_EVENT_TABLE() + +public: + /// Constructors + wxRichTextImageDialog(); + wxRichTextImageDialog( wxWindow* parent, wxWindowID id = SYMBOL_WXRICHTEXTIMAGEDIALOG_IDNAME, const wxString& caption = SYMBOL_WXRICHTEXTIMAGEDIALOG_TITLE, const wxPoint& pos = SYMBOL_WXRICHTEXTIMAGEDIALOG_POSITION, const wxSize& size = SYMBOL_WXRICHTEXTIMAGEDIALOG_SIZE, long style = SYMBOL_WXRICHTEXTIMAGEDIALOG_STYLE ); + + /// Creation + bool Create( wxWindow* parent, wxWindowID id = SYMBOL_WXRICHTEXTIMAGEDIALOG_IDNAME, const wxString& caption = SYMBOL_WXRICHTEXTIMAGEDIALOG_TITLE, const wxPoint& pos = SYMBOL_WXRICHTEXTIMAGEDIALOG_POSITION, const wxSize& size = SYMBOL_WXRICHTEXTIMAGEDIALOG_SIZE, long style = SYMBOL_WXRICHTEXTIMAGEDIALOG_STYLE ); + + /// Destructor + ~wxRichTextImageDialog(); + + /// Initialises member variables + void Init(); + + /// Creates the controls and sizers + void CreateControls(); + +////@begin wxRichTextImageDialog event handler declarations + + /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_RICHTEXTIMAGEDIALOG_PARA_UP + void OnRichtextimagedialogParaUpClick( wxCommandEvent& event ); + + /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_RICHTEXTIMAGEDIALOG_DOWN + void OnRichtextimagedialogDownClick( wxCommandEvent& event ); + +////@end wxRichTextImageDialog event handler declarations + +////@begin wxRichTextImageDialog member function declarations + + /// Retrieves bitmap resources + wxBitmap GetBitmapResource( const wxString& name ); + + /// Retrieves icon resources + wxIcon GetIconResource( const wxString& name ); +////@end wxRichTextImageDialog member function declarations + + /// Should we show tooltips? + static bool ShowToolTips(); + + /// Set the image attribute + void SetImageAttr(const wxRichTextAnchoredObjectAttr& attr); + wxRichTextImage* ApplyImageAttr(); + + /// Set the anchored object + void SetImageObject(wxRichTextImage *image, wxRichTextBuffer* buffer); + + virtual bool TransferDataFromWindow(); + virtual bool TransferDataToWindow(); +private: + /// Convert CM to MM + bool ConvertFromString(const wxString& string, int& ret, int scale); +private: + wxRichTextAnchoredObjectAttr m_attr; +////@begin wxRichTextImageDialog member variables + wxComboBox* m_alignment; + wxComboBox* m_float; + wxTextCtrl* m_width; + wxComboBox* m_unitsW; + wxTextCtrl* m_height; + wxComboBox* m_unitsH; + wxTextCtrl* m_offset; + wxComboBox* m_unitsOffset; + wxButton* m_saveButton; + wxButton* m_cancelButton; + /// Control identifiers + enum { + ID_WXRICHTEXTIMAGEPAGE = 10015, + ID_COMBOBOX_ALIGN = 10016, + ID_RICHTEXTIMAGEDIALOG_FLOATING_MODE = 10017, + ID_RICHTEXTIMAGEDIALOG_WIDTH = 10018, + ID_RICHTEXTIMAGEDIALOG_UNITS_W = 10019, + ID_RICHTEXTIMAGEDIALOG_HEIGHT = 10020, + ID_RICHTEXTIMAGEDIALOG_UNITS_H = 10021, + ID_RICHTEXTIMAGEDIALOG_OFFSET = 10022, + ID_RICHTEXTIMAGEDIALOG_OFFSET_UNITS = 10023, + ID_RICHTEXTIMAGEDIALOG_PARA_UP = 10024, + ID_RICHTEXTIMAGEDIALOG_DOWN = 10025 + }; +////@end wxRichTextImageDialog member variables + + wxRichTextBuffer* m_buffer; + wxRichTextObject* m_image; + wxRichTextObject* m_parent; +}; + +#endif + // _RICHTEXTIMAGEDLG_H_ diff --git a/samples/richtext/richtext.cpp b/samples/richtext/richtext.cpp index 168a2046f9..58367e0b95 100644 --- a/samples/richtext/richtext.cpp +++ b/samples/richtext/richtext.cpp @@ -78,6 +78,7 @@ #include "wx/richtext/richtextsymboldlg.h" #include "wx/richtext/richtextstyledlg.h" #include "wx/richtext/richtextprint.h" +#include "wx/richtext/richtextimagedlg.h" // ---------------------------------------------------------------------------- // resources @@ -145,6 +146,8 @@ public: void OnIndentLess(wxCommandEvent& event); void OnFont(wxCommandEvent& event); + void OnImage(wxCommandEvent& event); + void OnUpdateImage(wxUpdateUIEvent& event); void OnParagraph(wxCommandEvent& event); void OnFormat(wxCommandEvent& event); void OnUpdateFormat(wxUpdateUIEvent& event); @@ -181,6 +184,7 @@ public: void OnPreview(wxCommandEvent& event); void OnPageSetup(wxCommandEvent& event); + void OnInsertImage(wxCommandEvent& event); protected: // Forward command events to the current rich text control, if any @@ -211,6 +215,7 @@ enum ID_FORMAT_ITALIC, ID_FORMAT_UNDERLINE, ID_FORMAT_FONT, + ID_FORMAT_IMAGE, ID_FORMAT_PARAGRAPH, ID_FORMAT_CONTENT, @@ -218,6 +223,7 @@ enum ID_INSERT_SYMBOL, ID_INSERT_URL, + ID_INSERT_IMAGE, ID_FORMAT_ALIGN_LEFT, ID_FORMAT_ALIGN_CENTRE, @@ -286,10 +292,12 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnUpdateAlignRight) EVT_MENU(ID_FORMAT_FONT, MyFrame::OnFont) + EVT_MENU(ID_FORMAT_IMAGE, MyFrame::OnImage) EVT_MENU(ID_FORMAT_PARAGRAPH, MyFrame::OnParagraph) EVT_MENU(ID_FORMAT_CONTENT, MyFrame::OnFormat) EVT_UPDATE_UI(ID_FORMAT_CONTENT, MyFrame::OnUpdateFormat) EVT_UPDATE_UI(ID_FORMAT_FONT, MyFrame::OnUpdateFormat) + EVT_UPDATE_UI(ID_FORMAT_IMAGE, MyFrame::OnUpdateImage) EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH, MyFrame::OnUpdateFormat) EVT_MENU(ID_FORMAT_INDENT_MORE, MyFrame::OnIndentMore) EVT_MENU(ID_FORMAT_INDENT_LESS, MyFrame::OnIndentLess) @@ -305,6 +313,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol) EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL) + EVT_MENU(ID_INSERT_IMAGE, MyFrame::OnInsertImage) EVT_MENU(ID_FORMAT_NUMBER_LIST, MyFrame::OnNumberList) EVT_MENU(ID_FORMAT_BULLETS_AND_NUMBERING, MyFrame::OnBulletsAndNumbering) @@ -621,6 +630,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing")); formatMenu->AppendSeparator(); formatMenu->Append(ID_FORMAT_FONT, _("&Font...")); + formatMenu->Append(ID_FORMAT_IMAGE, _("Image Property")); formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph...")); formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F")); formatMenu->AppendSeparator(); @@ -640,6 +650,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, wxMenu* insertMenu = new wxMenu; insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I")); insertMenu->Append(ID_INSERT_URL, _("&URL...")); + insertMenu->Append(ID_INSERT_IMAGE, _("&Image...")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); @@ -689,6 +700,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxEmptyString, wxBitmap(indentmore_xpm), _("Indent More")); toolBar->AddSeparator(); toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font")); + toolBar->AddTool(ID_FORMAT_IMAGE, wxString("Im"), wxBitmap(font_xpm), _("Image Property")); wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1)); toolBar->AddControl(combo); @@ -742,6 +754,8 @@ void MyFrame::WriteInitialText() r.BeginSuppressUndo(); + r.Freeze(); + r.BeginParagraphSpacing(0, 20); r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE); @@ -768,6 +782,18 @@ void MyFrame::WriteInitialText() r.EndAlignment(); + r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT); + wxRichTextAnchoredObjectAttr anchoredAttr; + anchoredAttr.m_floating = wxRICHTEXT_FLOAT_LEFT; + r.WriteText(wxString(wxT("This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side."))); + r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, anchoredAttr); + anchoredAttr.m_floating = wxRICHTEXT_FLOAT_RIGHT; + anchoredAttr.m_offset = 200; + r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, anchoredAttr); + r.WriteText(wxString(wxT("This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side."))); + r.EndAlignment(); + r.Newline(); + r.WriteText(wxT("What can you do with this thing? ")); r.WriteImage(wxBitmap(smiley_xpm)); @@ -923,6 +949,8 @@ void MyFrame::WriteInitialText() r.EndParagraphSpacing(); + r.Thaw(); + r.EndSuppressUndo(); } @@ -1154,6 +1182,27 @@ void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event)) #endif } +void MyFrame::OnImage(wxCommandEvent& WXUNUSED(event)) +{ + wxRichTextRange range; + wxASSERT(m_richTextCtrl->HasSelection()); + + range = m_richTextCtrl->GetSelectionRange(); + wxASSERT(range.ToInternal().GetLength() == 1); + + wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetBuffer().GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage); + if (image) + { + wxRichTextImageDialog imageDlg(this); + imageDlg.SetImageObject(image, &m_richTextCtrl->GetBuffer()); + + if (imageDlg.ShowModal() == wxID_OK) + { + image = imageDlg.ApplyImageAttr(); + } + } +} + void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event)) { wxRichTextRange range; @@ -1197,6 +1246,25 @@ void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event) event.Enable(m_richTextCtrl->HasSelection()); } +void MyFrame::OnUpdateImage(wxUpdateUIEvent& event) +{ + wxRichTextRange range; + wxRichTextObject *obj; + + range = m_richTextCtrl->GetSelectionRange(); + if (range.ToInternal().GetLength() == 1) + { + obj = m_richTextCtrl->GetBuffer().GetLeafObjectAtPosition(range.GetStart()); + if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage))) + { + event.Enable(true); + return; + } + } + + event.Enable(false); +} + void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event)) { wxRichTextAttr attr; @@ -1562,6 +1630,16 @@ void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event)) } } +void MyFrame::OnInsertImage(wxCommandEvent& WXUNUSED(event)) +{ + wxFileDialog dialog(this, _("Choose an image"), "", "", "BMP and GIF files (*.bmp;*.gif)|*.bmp;*.gif|PNG files (*.png)|*.png"); + if (dialog.ShowModal() == wxID_OK) + { + wxString path = dialog.GetPath(); + m_richTextCtrl->WriteImage(path, wxBITMAP_TYPE_ANY); + } +} + void MyFrame::OnURL(wxTextUrlEvent& event) { wxMessageBox(event.GetString()); diff --git a/src/richtext/readme b/src/richtext/readme new file mode 100644 index 0000000000..0354470476 --- /dev/null +++ b/src/richtext/readme @@ -0,0 +1,54 @@ +Implement detail of floating layout + +1. Data Structure + +Mainly, we maintain two floating list data for a wxRichTextBuffer. +'struct FloatRectMap' is used to represent a floating object's region, +and 'class wxFloatCollector' is a container of all 'struct FloatRectMap'. +It maintains all the information of the positions of all the floating +objects with two list of 'struct FloatRectMap', one for objects floated +to left and the other for right. + +wxRichTextAnchoredObject is introduced to represent a kind of objects +that can be floated. wxRichTextImage is made to be a child class of +this one. In future, we may introduce some other floating object type +like wxRichTextTable. And we also introduce a twin object of this one, +it is wxRichTextPlaceHoldingObject. When the object is set to be a +floating one, we will place a 'placing holding' object in its origin +position, this makes us to record the position of the object correctly +even if the containing paragraph change its content. + +Also, along with wxRichTextAnchoredObject, we also introduce a +wxRichTextAnchoredObjectAttr class, which contains the attributes of +floating direction, floating offset and etc. wxRichTextImageAttr is made +to be a subclass of this one. + +Finally, wxRichTextImageDlg is a image control dialog, in which users can +set the alignment, floating direction, size, offset of the image, in addition, +users can also move the image between paragraph with this dialog. + +2. Layout Algorithm + +With floating objects, when we layout a paragraph, wxFloatCollector will +firstly collect all the floating objects of the paragraphs before this +one. And then, layout the floating objects of this paragraph, then layout +the normal objects using the available rect info according the floating +objects' state. + +Generally, the basic paragraph layout algorithm: +1. All paragraphs before this one is layout well, so use wxFloatCollector + to collect the floating objects state; +2. Collect all the 'place holding objects' of the paragraph, layout the + floating objects with the space available for it; +3. For other objects left, make line break as: + GetAvailableWidth with a pair, where y is the vertical position + of the line and h is the minimum height of the line. + After we get the width, do line break and normal layout. + +3. Some Note + +If we use floating attributes with list style, it may cause some problems. +Something like image/text overlap may happen. Since, list style is applied +to the paragraph after its normal layout, in which phrase, floating layout +is done, list style will change the position of the paragraph and so may +cause some overlap. diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 1b3ff5896f..9acc9bd0f4 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -36,9 +36,11 @@ #include "wx/sstream.h" #include "wx/textfile.h" #include "wx/hashmap.h" +#include "wx/dynarray.h" #include "wx/richtext/richtextctrl.h" #include "wx/richtext/richtextstyles.h" +#include "wx/richtext/richtextimagedlg.h" #include "wx/listimpl.cpp" @@ -53,10 +55,338 @@ WX_DEFINE_LIST(wxRichTextLineList) const wxChar wxRichTextLineBreakChar = (wxChar) 29; -// Helpers for efficiency +// Helper classes for floating layout +struct wxRichTextFloatRectMap +{ + wxRichTextFloatRectMap(int sY, int eY, int w, wxRichTextObject* obj) + { + startY = sY; + endY = eY; + width = w; + anchor = obj; + } + + int startY, endY; + int width; + wxRichTextObject* anchor; +}; + +WX_DEFINE_SORTED_ARRAY(wxRichTextFloatRectMap*, wxRichTextFloatRectMapArray); + +int wxRichTextFloatRectMapCmp(wxRichTextFloatRectMap* r1, wxRichTextFloatRectMap* r2) +{ + return r1->startY - r2->startY; +} + +class wxRichTextFloatCollector +{ +public: + wxRichTextFloatCollector(int width); + ~wxRichTextFloatCollector(); + + // Collect the floating objects info in the given paragraph + void CollectFloat(wxRichTextParagraph* para); + void CollectFloat(wxRichTextParagraph* para, wxRichTextObject* floating); + + // Return the last paragraph we collected + wxRichTextParagraph* LastParagraph(); + + // Given the start y position and the height of the line, + // find out how wide the line can be + wxRect GetAvailableRect(int startY, int endY); + + // Given a floating box, find its fit position + int GetFitPosition(int direction, int start, int height) const; + int GetFitPosition(const wxRichTextFloatRectMapArray& array, int start, int height) const; + + // Find the last y position + int GetLastRectBottom(); + + // Draw the floats inside a rect + void Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style); + + // HitTest the floats + int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition); + + static int SearchAdjacentRect(const wxRichTextFloatRectMapArray& array, int point); + + static int GetWidthFromFloatRect(const wxRichTextFloatRectMapArray& array, int index, int startY, int endY); + + static void FreeFloatRectMapArray(wxRichTextFloatRectMapArray& array); + + static void DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style); + + static int HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& WXUNUSED(dc), const wxPoint& pt, long& textPosition); + +private: + wxRichTextFloatRectMapArray m_left; + wxRichTextFloatRectMapArray m_right; + int m_width; + wxRichTextParagraph* m_para; +}; + +/* + * Binary search helper function + * The argument point is the Y coordinate, and this fuction + * always return the floating rect that contain this coordinate + * or under this coordinate. + */ +int wxRichTextFloatCollector::SearchAdjacentRect(const wxRichTextFloatRectMapArray& array, int point) +{ + int end = array.GetCount() - 1; + int start = 0; + int ret = 0; + + wxASSERT(end >= 0); + + while (true) + { + if (start > end) + { + break; + } + + int mid = (start + end) / 2; + if (array[mid]->startY <= point && array[mid]->endY >= point) + return mid; + else if (array[mid]->startY > point) + { + end = mid - 1; + ret = mid; + } + else if (array[mid]->endY < point) + { + start = mid + 1; + ret = start; + } + } + + return ret; +} + +int wxRichTextFloatCollector::GetWidthFromFloatRect(const wxRichTextFloatRectMapArray& array, int index, int startY, int endY) +{ + int ret = 0; + int len = array.GetCount(); + + wxASSERT(index >= 0 && index < len); + + if (array[index]->startY < startY && array[index]->endY > startY) + ret = ret < array[index]->width ? array[index]->width : ret; + while (index < len && array[index]->startY <= endY) + { + ret = ret < array[index]->width ? array[index]->width : ret; + index++; + } + + return ret; +} + +wxRichTextFloatCollector::wxRichTextFloatCollector(int width) : m_left(wxRichTextFloatRectMapCmp), m_right(wxRichTextFloatRectMapCmp) +{ + m_width = width; + m_para = NULL; +} + +void wxRichTextFloatCollector::FreeFloatRectMapArray(wxRichTextFloatRectMapArray& array) +{ + int len = array.GetCount(); + for (int i = 0; i < len; i++) + delete array[i]; +} + +wxRichTextFloatCollector::~wxRichTextFloatCollector() +{ + FreeFloatRectMapArray(m_left); + FreeFloatRectMapArray(m_right); +} + +int wxRichTextFloatCollector::GetFitPosition(const wxRichTextFloatRectMapArray& array, int start, int height) const +{ + if (array.GetCount() == 0) + return start; + + unsigned int i = SearchAdjacentRect(array, start); + int last = start; + while (i < array.GetCount()) + { + if (array[i]->startY - last >= height) + return last + 1; + last = array[i]->endY; + i++; + } + + return last + 1; +} + +int wxRichTextFloatCollector::GetFitPosition(int direction, int start, int height) const +{ + if (direction == wxRICHTEXT_FLOAT_LEFT) + return GetFitPosition(m_left, start, height); + else if (direction == wxRICHTEXT_FLOAT_RIGHT) + return GetFitPosition(m_right, start, height); + else + { + wxASSERT("Never should be here"); + return start; + } +} + +void wxRichTextFloatCollector::CollectFloat(wxRichTextParagraph* para, wxRichTextObject* floating) +{ + int direction = floating->GetFloatDirection(); + wxPoint pos = floating->GetPosition(); + wxSize size = floating->GetCachedSize(); + wxRichTextFloatRectMap *map = new wxRichTextFloatRectMap(pos.y, pos.y + size.y, size.x, floating); + + switch (direction) + { + case wxRICHTEXT_FLOAT_NONE: + delete map; + break; + case wxRICHTEXT_FLOAT_LEFT: + // Just a not-enough simple assertion + wxASSERT (m_left.Index(map) == wxNOT_FOUND); + m_left.Add(map); + break; + case wxRICHTEXT_FLOAT_RIGHT: + wxASSERT (m_right.Index(map) == wxNOT_FOUND); + m_right.Add(map); + break; + default: + delete map; + wxASSERT("Must some error occurs"); + } + + m_para = para; +} + +void wxRichTextFloatCollector::CollectFloat(wxRichTextParagraph* para) +{ + wxRichTextObjectList::compatibility_iterator node = para->GetChildren().GetFirst(); + while (node) + { + wxRichTextObject* floating = node->GetData(); + + if (floating->IsFloating()) + { + wxRichTextAnchoredObject* anchor = wxDynamicCast(floating, wxRichTextAnchoredObject); + if (anchor && anchor->GetAnchoredAttr().IsAnchored()) + { + CollectFloat(para, floating); + } + } + + node = node->GetNext(); + } + + m_para = para; +} + +wxRichTextParagraph* wxRichTextFloatCollector::LastParagraph() +{ + return m_para; +} + +wxRect wxRichTextFloatCollector::GetAvailableRect(int startY, int endY) +{ + int widthLeft = 0, widthRight = 0; + if (m_left.GetCount() != 0) + { + unsigned int i = SearchAdjacentRect(m_left, startY); + if (i >= 0 && i < m_left.GetCount()) + widthLeft = GetWidthFromFloatRect(m_left, i, startY, endY); + } + if (m_right.GetCount() != 0) + { + unsigned int j = SearchAdjacentRect(m_right, startY); + if (j >= 0 && j < m_right.GetCount()) + widthRight = GetWidthFromFloatRect(m_right, j, startY, endY); + } + + return wxRect(widthLeft, 0, m_width - widthLeft - widthRight, 0); +} + +int wxRichTextFloatCollector::GetLastRectBottom() +{ + int ret = 0; + int len = m_left.GetCount(); + if (len) { + ret = ret > m_left[len-1]->endY ? ret : m_left[len-1]->endY; + } + len = m_right.GetCount(); + if (len) { + ret = ret > m_right[len-1]->endY ? ret : m_right[len-1]->endY; + } + return ret; +} + +void wxRichTextFloatCollector::DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, const wxRichTextRange& WXUNUSED(range), const wxRichTextRange& WXUNUSED(selectionRange), const wxRect& rect, int descent, int style) +{ + int start = rect.y; + int end = rect.y + rect.height; + unsigned int i, j; + i = SearchAdjacentRect(array, start); + if (i < 0 || i >= array.GetCount()) + return; + j = SearchAdjacentRect(array, end); + if (j < 0 || j >= array.GetCount()) + j = array.GetCount() - 1; + while (i <= j) + { + wxRichTextObject* obj = array[i]->anchor; + wxRichTextRange r = obj->GetRange(); + obj->Draw(dc, r, wxRichTextRange(0, -1), wxRect(obj->GetPosition(), obj->GetCachedSize()), descent, style); + i++; + } +} + +void wxRichTextFloatCollector::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style) +{ + if (m_left.GetCount() > 0) + DrawFloat(m_left, dc, range, selectionRange, rect, descent, style); + if (m_right.GetCount() > 0) + DrawFloat(m_right, dc, range, selectionRange, rect, descent, style); +} + +int wxRichTextFloatCollector::HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& WXUNUSED(dc), const wxPoint& pt, long& textPosition) +{ + unsigned int i; + if (array.GetCount() == 0) + return wxRICHTEXT_HITTEST_NONE; + i = SearchAdjacentRect(array, pt.y); + if (i < 0 || i >= array.GetCount()) + return wxRICHTEXT_HITTEST_NONE; + wxPoint point = array[i]->anchor->GetPosition(); + wxSize size = array[i]->anchor->GetCachedSize(); + if (point.x <= pt.x && point.x + size.x >= pt.x + && point.y <= pt.y && point.y + size.y >= pt.y) + { + textPosition = array[i]->anchor->GetRange().GetStart(); + if (pt.x > (pt.x + pt.x + size.x) / 2) + return wxRICHTEXT_HITTEST_BEFORE; + else + return wxRICHTEXT_HITTEST_AFTER; + } + + return wxRICHTEXT_HITTEST_NONE; +} + +int wxRichTextFloatCollector::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition) +{ + int ret = HitTestFloat(m_left, dc, pt, textPosition); + if (ret == wxRICHTEXT_HITTEST_NONE) + { + ret = HitTestFloat(m_right, dc, pt, textPosition); + } + return ret; +} + +// Helpers for efficiency inline void wxCheckSetFont(wxDC& dc, const wxFont& font) { + // JACS: did I do this some time ago when testing? Should we re-enable it? #if 0 const wxFont& font1 = dc.GetFont(); if (font1.IsOk() && font.IsOk()) @@ -99,6 +429,34 @@ inline void wxCheckSetBrush(wxDC& dc, const wxBrush& brush) dc.SetBrush(brush); } +void wxRichTextAnchoredObjectAttr::Init() +{ + m_align = wxRICHTEXT_CENTRE; + m_floating = wxRICHTEXT_FLOAT_NONE; + m_offset = 0; + m_unitsOffset = wxRICHTEXT_PX; + + m_unitsW = wxRICHTEXT_PX; + m_unitsH = wxRICHTEXT_PX; + + // Unspecified to begin with (use actual image size) + m_width = -1; + m_height = -1; +} + +void wxRichTextAnchoredObjectAttr::Copy(const wxRichTextAnchoredObjectAttr& attr) +{ + m_align = attr.m_align; + m_floating = attr.m_floating; + m_offset = attr.m_offset; + m_unitsOffset = attr.m_unitsOffset; + + m_unitsW = attr.m_unitsW; + m_unitsH = attr.m_unitsH; + m_width = attr.m_width; + m_height = attr.m_height; +} + /*! * wxRichTextObject * This is the base for drawable objects. @@ -154,7 +512,7 @@ void wxRichTextObject::SetMargins(int leftMargin, int rightMargin, int topMargin } // Convert units in tenths of a millimetre to device units -int wxRichTextObject::ConvertTenthsMMToPixels(wxDC& dc, int units) +int wxRichTextObject::ConvertTenthsMMToPixels(wxDC& dc, int units) const { int p = ConvertTenthsMMToPixels(dc.GetPPI().x, units); @@ -553,6 +911,15 @@ wxRichTextParagraphLayoutBox::wxRichTextParagraphLayoutBox(wxRichTextObject* par Init(); } +wxRichTextParagraphLayoutBox::~wxRichTextParagraphLayoutBox() +{ + if (m_floatCollector) + { + delete m_floatCollector; + m_floatCollector = NULL; + } +} + /// Initialize the object. void wxRichTextParagraphLayoutBox::Init() { @@ -567,11 +934,61 @@ void wxRichTextParagraphLayoutBox::Init() m_topMargin = 4; m_bottomMargin = 4; m_partialParagraph = false; + m_floatCollector = NULL; +} + +// Gather information about floating objects +bool wxRichTextParagraphLayoutBox::UpdateFloatingObjects(int width, wxRichTextObject* untilObj) +{ + if (m_floatCollector != NULL) + delete m_floatCollector; + m_floatCollector = new wxRichTextFloatCollector(width); + wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); + while (node && node->GetData() != untilObj) + { + wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph); + wxASSERT (child != NULL); + if (child) + m_floatCollector->CollectFloat(child); + node = node->GetNext(); + } + + return true; +} + +// HitTest +int wxRichTextParagraphLayoutBox::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition) +{ + int ret = wxRICHTEXT_HITTEST_NONE; + if (m_floatCollector) + ret = m_floatCollector->HitTest(dc, pt, textPosition); + + if (ret == wxRICHTEXT_HITTEST_NONE) + return wxRichTextCompositeObject::HitTest(dc, pt, textPosition); + else + return ret; +} + +/// Draw the floating objects +void wxRichTextParagraphLayoutBox::DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style) +{ + if (m_floatCollector) + m_floatCollector->Draw(dc, range, selectionRange, rect, descent, style); +} + +void wxRichTextParagraphLayoutBox::MoveAnchoredObjectToParagraph(wxRichTextParagraph* from, wxRichTextParagraph* to, wxRichTextAnchoredObject* obj) +{ + if (from == to) + return; + + from->RemoveChild(obj); + to->AppendChild(obj); } /// Draw the item bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style) { + DrawFloats(dc, range, selectionRange, rect, descent, style); wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); while (node) { @@ -675,6 +1092,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl } } + UpdateFloatingObjects(availableSpace.width, node ? node->GetData() : (wxRichTextObject*) NULL); + // A way to force speedy rest-of-buffer layout (the 'else' below) bool forceQuickLayout = false; @@ -1886,6 +2305,35 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const return true; } +void wxRichTextParagraphLayoutBox::SetImageStyle(wxRichTextImage *image, const wxRichTextAnchoredObjectAttr& attr, int flags) +{ + bool withUndo = flags & wxRICHTEXT_SETSTYLE_WITH_UNDO; + bool haveControl = (GetRichTextCtrl() != NULL); + wxRichTextParagraph* newPara wxDUMMY_INITIALIZE(NULL); + wxRichTextParagraph* para = GetParagraphAtPosition(image->GetRange().GetStart()); + wxRichTextAction *action = NULL; + wxRichTextAnchoredObjectAttr oldAttr = image->GetAnchoredAttr(); + + if (haveControl && withUndo) + { + action = new wxRichTextAction(NULL, _("Change Image Style"), wxRICHTEXT_CHANGE_STYLE, & GetRichTextCtrl()->GetBuffer(), GetRichTextCtrl()); + action->SetRange(image->GetRange().FromInternal()); + action->SetPosition(GetRichTextCtrl()->GetCaretPosition()); + image->SetAnchoredAttr(attr); + // Set the new attribute + newPara = new wxRichTextParagraph(*para); + action->GetNewParagraphs().AppendChild(newPara); + // Change back to the old one + image->SetAnchoredAttr(oldAttr); + action->GetOldParagraphs().AppendChild(new wxRichTextParagraph(*para)); + } + else + newPara = para; + + if (haveControl && withUndo) + GetRichTextCtrl()->GetBuffer().SubmitAction(action); +} + /// Get the text attributes for this position. bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttr& style) { @@ -2596,11 +3044,10 @@ wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagrap if (wholeParagraphs) { wxRichTextParagraph* para1 = GetParagraphAtPosition(range.GetStart()); - wxRichTextParagraph* para2 = GetParagraphAtPosition(range.GetEnd()); if (para1) range.SetStart(para1->GetRange().GetStart()); - if (para2) - range.SetEnd(para2->GetRange().GetEnd()); + // floating layout make all child should be relayout + range.SetEnd(GetRange().GetEnd()); } return range; } @@ -3183,7 +3630,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR if (GetChildren().GetCount() > 0) { wxRichTextObject* firstObj = (wxRichTextObject*) GetChildren().GetFirst()->GetData(); - if (firstObj->GetAttributes().HasFont()) + if (!firstObj->IsFloatable() && firstObj->GetAttributes().HasFont()) { wxRichTextApplyStyle(bulletAttr, firstObj->GetAttributes()); } @@ -3262,7 +3709,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR { wxRichTextObject* child = node2->GetData(); - if (child->GetRange().GetLength() > 0 && !child->GetRange().IsOutside(lineRange) && !lineRange.IsOutside(range)) + if (!child->IsFloating() && child->GetRange().GetLength() > 0 && !child->GetRange().IsOutside(lineRange) && !lineRange.IsOutside(range)) { // Draw this part of the line at the correct position wxRichTextRange objectRange(child->GetRange()); @@ -3324,6 +3771,13 @@ static int wxRichTextGetRangeWidth(const wxRichTextParagraph& para, const wxRich /// Lay the item out bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { + // Deal with floating objects firstly before the normal layout + wxRichTextBuffer* buffer = GetBuffer(); + wxASSERT(buffer); + wxRichTextFloatCollector* collector = buffer->GetFloatCollector(); + wxASSERT(collector); + LayoutFloat(dc, rect, style, collector); + wxTextAttr attr = GetCombinedAttributes(); // ClearLines(); @@ -3344,18 +3798,10 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) lineSpacing = (int) (double(dc.GetCharHeight()) * (double(attr.GetLineSpacing())/10.0 - 1.0)); } - // Available space for text on each line differs. - int availableTextSpaceFirstLine = rect.GetWidth() - leftIndent - rightIndent; - - // Bullets start the text at the same position as subsequent lines - if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) - availableTextSpaceFirstLine -= leftSubIndent; - - int availableTextSpaceSubsequentLines = rect.GetWidth() - leftIndent - rightIndent - leftSubIndent; - // Start position for each line relative to the paragraph int startPositionFirstLine = leftIndent; int startPositionSubsequentLines = leftIndent + leftSubIndent; + wxRect availableRect; // If we have a bullet in this paragraph, the start position for the first line's text // is actually leftIndent + leftSubIndent. @@ -3374,6 +3820,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) int maxAscent = 0; int maxDescent = 0; int lineCount = 0; + int lineAscent = 0; + int lineDescent = 0; wxRichTextObjectList::compatibility_iterator node; @@ -3411,7 +3859,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { wxRichTextObject* child = node->GetData(); - if (child->GetRange().GetLength() == 0) + // If floating, ignore. We already laid out floats. + if (child->IsFloating() || child->GetRange().GetLength() == 0) { node = node->GetNext(); continue; @@ -3424,11 +3873,6 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // can't tell the position until the size is determined. So possibly introduce // another layout phase. - // Available width depends on whether we're on the first or subsequent lines - int availableSpaceForText = (lineCount == 0 ? availableTextSpaceFirstLine : availableTextSpaceSubsequentLines); - - currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); - // We may only be looking at part of a child, if we searched back for wrapping // and found a suitable point some way into the child. So get the size for the fragment // if necessary. @@ -3459,19 +3903,36 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) #endif } + // Available width depends on the floating objects and the line height + // Note: the floating objects may be placed vertically along the two side of + // buffer, so we may have different available line width with different + // [startY, endY]. So, we should can't determine how wide the available + // space is until we know the exact line height. + lineDescent = wxMax(childDescent, maxDescent); + lineAscent = wxMax(childSize.y-childDescent, maxAscent); + lineHeight = lineDescent + lineAscent; + availableRect = collector->GetAvailableRect(rect.y + currentPosition.y, rect.y + currentPosition.y + lineHeight); + + currentPosition.x = (lineCount == 0 ? availableRect.x + startPositionFirstLine : availableRect.x + startPositionSubsequentLines); + // Cases: // 1) There was a line break BEFORE the natural break // 2) There was a line break AFTER the natural break // 3) The child still fits (carry on) - if ((lineBreakInThisObject && (childSize.x + currentWidth <= availableSpaceForText)) || - (childSize.x + currentWidth > availableSpaceForText)) + if ((lineBreakInThisObject && (childSize.x + currentWidth <= availableRect.width)) || + (childSize.x + currentWidth > availableRect.width)) { long wrapPosition = 0; + int indent = lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines; + indent += rightIndent; // Find a place to wrap. This may walk back to previous children, // for example if a word spans several objects. - if (!FindWrapPosition(wxRichTextRange(lastCompletedEndPos+1, child->GetRange().GetEnd()), dc, availableSpaceForText, wrapPosition, & partialExtents)) + // Note: one object must contains only one wxTextAtrr, so the line height will not + // change inside one object. Thus, we can pass the remain line width to the + // FindWrapPosition function. + if (!FindWrapPosition(wxRichTextRange(lastCompletedEndPos+1, child->GetRange().GetEnd()), dc, availableRect.width - indent, wrapPosition, & partialExtents)) { // If the function failed, just cut it off at the end of this child. wrapPosition = child->GetRange().GetEnd(); @@ -3557,7 +4018,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // Substract -1 because the last position is always the end-paragraph position. if (lastCompletedEndPos <= GetRange().GetEnd()-1) { - currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); + currentPosition.x = (lineCount == 0 ? availableRect.x + startPositionFirstLine : availableRect.x + startPositionSubsequentLines); wxRichTextLine* line = AllocateLine(lineCount); @@ -3783,6 +4244,22 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz wxRichTextObject* child = node->GetData(); if (!child->GetRange().IsOutside(range)) { + // Floating objects have a zero size within the paragraph. + if (child->IsFloating()) + { + if (partialExtents) + { + int lastSize; + if (partialExtents->GetCount() > 0) + lastSize = (*partialExtents)[partialExtents->GetCount()-1]; + else + lastSize = 0; + + partialExtents->Add(0 /* zero size */ + lastSize); + } + } + else + { wxSize childSize; wxRichTextRange rangeToUse = range; @@ -3827,6 +4304,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz } } } + } if (p) p->Clear(); @@ -3862,7 +4340,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz { wxRichTextObject* child = node2->GetData(); - if (!child->GetRange().IsOutside(lineRange)) + if (!child->IsFloating() && !child->GetRange().IsOutside(lineRange)) { wxRichTextRange rangeToUse = lineRange; rangeToUse.LimitTo(child->GetRange()); @@ -4035,7 +4513,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition // Let's see if we can be more precise about // which side of the position it's on. - int midPoint = (nextX - lastX)/2 + lastX; + int midPoint = (nextX + lastX)/2; if (pt.x >= midPoint) return wxRICHTEXT_HITTEST_AFTER; else @@ -4066,7 +4544,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition // Let's see if we can be more precise about // which side of the position it's on. - int midPoint = (nextX - lastX)/2 + lastX; + int midPoint = (nextX + lastX)/2; if (pt.x >= midPoint) return wxRICHTEXT_HITTEST_AFTER; else @@ -4511,6 +4989,37 @@ void wxRichTextParagraph::ClearDefaultTabs() sm_defaultTabs.Clear(); } +void wxRichTextParagraph::LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector) +{ + wxRichTextObjectList::compatibility_iterator node = GetChildren().GetFirst(); + while (node) + { + wxRichTextAnchoredObject* anchored = wxDynamicCast(node->GetData(), wxRichTextAnchoredObject); + if (anchored && anchored->IsFloating()) + { + wxSize size; + int descent, x = 0; + anchored->GetRangeSize(anchored->GetRange(), size, descent, dc, style); + wxRichTextAnchoredObjectAttr attr = anchored->GetAnchoredAttr(); + int pos = floatCollector->GetFitPosition(attr.m_floating, rect.y + attr.m_offset, size.y); + + /* Update the offset */ + attr.m_offset = pos - rect.y; + anchored->SetAnchoredAttr(attr); + + if (attr.m_floating == wxRICHTEXT_FLOAT_LEFT) + x = 0; + else if (attr.m_floating == wxRICHTEXT_FLOAT_RIGHT) + x = rect.width - size.x; + anchored->SetPosition(wxPoint(x, pos)); + anchored->SetCachedSize(size); + floatCollector->CollectFloat(this, anchored); + } + + node = node->GetNext(); + } +} + /// Get the first position from pos that has a line break character. long wxRichTextParagraph::GetFirstLineBreakPosition(long pos) { @@ -5434,7 +5943,7 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int } /// Submit command to insert the given image -bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags) +bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags, const wxRichTextAnchoredObjectAttr& floatAttr) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, this, ctrl, false); @@ -5455,6 +5964,7 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara); newPara->AppendChild(imageObject); + imageObject->SetAnchoredAttr(floatAttr); action->GetNewParagraphs().AppendChild(newPara); action->GetNewParagraphs().UpdateRanges(); @@ -5470,6 +5980,41 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& return true; } +// Insert an object with no change of it +bool wxRichTextBuffer::InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags) +{ + wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert object"), wxRICHTEXT_INSERT, this, ctrl, false); + + wxTextAttr* p = NULL; + wxTextAttr paraAttr; + if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) + { + paraAttr = GetStyleForNewParagraph(pos); + if (!paraAttr.IsDefault()) + p = & paraAttr; + } + + wxTextAttr attr(GetDefaultStyle()); + + wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr); + if (p) + newPara->SetAttributes(*p); + + newPara->AppendChild(object); + action->GetNewParagraphs().AppendChild(newPara); + action->GetNewParagraphs().UpdateRanges(); + + action->GetNewParagraphs().SetPartialParagraph(true); + + action->SetPosition(pos); + + // Set the range we'll need to delete in Undo + action->SetRange(wxRichTextRange(pos, pos)); + + SubmitAction(action); + + return true; +} /// Get the style that is appropriate for a new paragraph at this position. /// If the previous paragraph has a paragraph style name, look up the next-paragraph /// style. @@ -6880,7 +7425,7 @@ bool wxRichTextAction::Undo() } /// Update the control appearance -void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, wxArrayInt* optimizationLineCharPositions, wxArrayInt* optimizationLineYPositions, bool isDoCmd) +void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, wxArrayInt* WXUNUSED(optimizationLineCharPositions), wxArrayInt* WXUNUSED(optimizationLineYPositions), bool WXUNUSED(isDoCmd)) { if (m_ctrl) { @@ -6888,145 +7433,8 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent if (!m_ctrl->IsFrozen()) { m_ctrl->LayoutContent(); - -#if wxRICHTEXT_USE_OPTIMIZED_DRAWING - // Find refresh rectangle if we are in a position to optimise refresh - if ((m_cmdId == wxRICHTEXT_INSERT || m_cmdId == wxRICHTEXT_DELETE) && optimizationLineCharPositions) - { - size_t i; - - wxSize clientSize = m_ctrl->GetClientSize(); - wxPoint firstVisiblePt = m_ctrl->GetFirstVisiblePoint(); - - // Start/end positions - int firstY = 0; - int lastY = firstVisiblePt.y + clientSize.y; - - bool foundEnd = false; - - // position offset - how many characters were inserted - int positionOffset = GetRange().GetLength(); - - // Determine whether this is Do or Undo, and adjust positionOffset accordingly - if ((m_cmdId == wxRICHTEXT_DELETE && isDoCmd) || (m_cmdId == wxRICHTEXT_INSERT && !isDoCmd)) - positionOffset = - positionOffset; - - // find the first line which is being drawn at the same position as it was - // before. Since we're talking about a simple insertion, we can assume - // that the rest of the window does not need to be redrawn. - - wxRichTextParagraph* para = m_buffer->GetParagraphAtPosition(GetPosition()); - if (para) - { - // Find line containing GetPosition(). - wxRichTextLine* line = NULL; - wxRichTextLineList::compatibility_iterator node2 = para->GetLines().GetFirst(); - while (node2) - { - wxRichTextLine* l = node2->GetData(); - wxRichTextRange range = l->GetAbsoluteRange(); - if (range.Contains(GetRange().GetStart()-1)) - { - line = l; - break; - } - node2 = node2->GetNext(); - } - - if (line) - { - // Step back a couple of lines to where we can be sure of reformatting correctly - wxRichTextLineList::compatibility_iterator lineNode = para->GetLines().Find(line); - if (lineNode) - { - lineNode = lineNode->GetPrevious(); - if (lineNode) - { - line = (wxRichTextLine*) lineNode->GetData(); - lineNode = lineNode->GetPrevious(); - if (lineNode) - line = (wxRichTextLine*) lineNode->GetData(); - } - } - - firstY = line->GetAbsolutePosition().y; - } - } - - wxRichTextObjectList::compatibility_iterator node = m_buffer->GetChildren().Find(para); - while (node) - { - wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData(); - wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst(); - while (node2) - { - wxRichTextLine* line = node2->GetData(); - wxPoint pt = line->GetAbsolutePosition(); - wxRichTextRange range = line->GetAbsoluteRange(); - - // we want to find the first line that is in the same position - // as before. This will mean we're at the end of the changed text. - - if (pt.y > lastY) // going past the end of the window, no more info - { - node2 = wxRichTextLineList::compatibility_iterator(); - node = wxRichTextObjectList::compatibility_iterator(); - } - // Detect last line in the buffer - else if (!node2->GetNext() && para->GetRange().Contains(m_buffer->GetRange().GetEnd())) - { - // If deleting text, make sure we refresh below as well as above - if (positionOffset >= 0) - { - foundEnd = true; - lastY = pt.y + line->GetSize().y; - } - - node2 = wxRichTextLineList::compatibility_iterator(); - node = wxRichTextObjectList::compatibility_iterator(); - - break; - } - else - { - // search for this line being at the same position as before - for (i = 0; i < optimizationLineCharPositions->GetCount(); i++) - { - if (((*optimizationLineCharPositions)[i] + positionOffset == range.GetStart()) && - ((*optimizationLineYPositions)[i] == pt.y)) - { - // Stop, we're now the same as we were - foundEnd = true; - - lastY = pt.y; - - node2 = wxRichTextLineList::compatibility_iterator(); - node = wxRichTextObjectList::compatibility_iterator(); - - break; - } - } - } - - if (node2) - node2 = node2->GetNext(); - } - - if (node) - node = node->GetNext(); - } - - firstY = wxMax(firstVisiblePt.y, firstY); - if (!foundEnd) - lastY = firstVisiblePt.y + clientSize.y; - - // Convert to device coordinates - wxRect rect(m_ctrl->GetPhysicalPoint(wxPoint(firstVisiblePt.x, firstY)), wxSize(clientSize.x, lastY - firstY)); - m_ctrl->RefreshRect(rect); - } - else -#endif - m_ctrl->Refresh(false); + // TODO Refresh the whole client area now + m_ctrl->Refresh(false); #if wxRICHTEXT_USE_OWN_CARET m_ctrl->PositionCaret(); @@ -7087,65 +7495,193 @@ bool wxRichTextRange::LimitTo(const wxRichTextRange& range) return true; } +#if 0 +/*! + * wxRichTextPlaceHoldingObject implementation + */ + +IMPLEMENT_DYNAMIC_CLASS(wxRichTextPlaceHoldingObject, wxRichTextObject) + +wxRichTextPlaceHoldingObject::wxRichTextPlaceHoldingObject(wxRichTextObject *parent, wxRichTextAnchoredObject *real) + : wxRichTextObject(parent), m_real(real) +{ +} + +wxRichTextPlaceHoldingObject::~wxRichTextPlaceHoldingObject() +{ +} + +bool wxRichTextPlaceHoldingObject::Draw(wxDC& WXUNUSED(dc), const wxRichTextRange& WXUNUSED(range), const wxRichTextRange& WXUNUSED(selectionrange), const wxRect& WXUNUSED(rect), int WXUNUSED(descent), int WXUNUSED(style)) +{ + return true; +} + +bool wxRichTextPlaceHoldingObject::Layout(wxDC& WXUNUSED(dc), const wxRect& WXUNUSED(rect), int WXUNUSED(style)) +{ + SetCachedSize(wxSize(0, 0)); + return true; +} + +bool wxRichTextPlaceHoldingObject::GetRangeSize(const wxRichTextRange& WXUNUSED(range), wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags), wxPoint WXUNUSED(position), wxArrayInt* partialExtents) const +{ + size.x = size.y = 0; + if (partialExtents) + partialExtents->Add(0); + return true; +} + +void wxRichTextPlaceHoldingObject::Copy(const wxRichTextPlaceHoldingObject& obj) +{ + wxRichTextObject::Copy(obj); + wxASSERT (obj.m_real); + wxRichTextObject* o = obj.m_real->Clone(); + wxASSERT (o->IsFloatable()); + wxRichTextAnchoredObject* anchor = wxDynamicCast(o, wxRichTextAnchoredObject); + wxASSERT (anchor); + anchor->SetPlaceHoldingObject(this); + m_real = anchor; +} + +void wxRichTextPlaceHoldingObject::SetParent(wxRichTextObject* parent) +{ + wxRichTextObject::SetParent(parent); + if (m_real) + { + m_real->wxRichTextObject::SetParent(parent); + } + +} + +#endif + +/*! + * wxRichTextAnchoredObject implementation + */ +IMPLEMENT_CLASS(wxRichTextAnchoredObject, wxRichTextObject) + +wxRichTextAnchoredObject::wxRichTextAnchoredObject(wxRichTextObject* parent, const wxRichTextAnchoredObjectAttr& attr): + wxRichTextObject(parent), m_anchoredAttr(attr) +{ +} + +wxRichTextAnchoredObject::~wxRichTextAnchoredObject() +{ +} + +void wxRichTextAnchoredObject::SetAnchoredAttr(const wxRichTextAnchoredObjectAttr& attr) +{ + m_anchoredAttr = attr; +} + +void wxRichTextAnchoredObject::Copy(const wxRichTextAnchoredObject& obj) +{ + wxRichTextObject::Copy(obj); + m_anchoredAttr = obj.m_anchoredAttr; +} + +void wxRichTextAnchoredObject::SetParent(wxRichTextObject* parent) +{ + wxRichTextObject::SetParent(parent); +} + /*! * wxRichTextImage implementation * This object represents an image. */ -IMPLEMENT_DYNAMIC_CLASS(wxRichTextImage, wxRichTextObject) +IMPLEMENT_DYNAMIC_CLASS(wxRichTextImage, wxRichTextAnchoredObject) wxRichTextImage::wxRichTextImage(const wxImage& image, wxRichTextObject* parent, wxTextAttr* charStyle): - wxRichTextObject(parent) + wxRichTextAnchoredObject(parent) { - m_image = image; + m_imageBlock.MakeImageBlockDefaultQuality(image, wxBITMAP_TYPE_PNG); if (charStyle) SetAttributes(*charStyle); } wxRichTextImage::wxRichTextImage(const wxRichTextImageBlock& imageBlock, wxRichTextObject* parent, wxTextAttr* charStyle): - wxRichTextObject(parent) + wxRichTextAnchoredObject(parent) { m_imageBlock = imageBlock; - m_imageBlock.Load(m_image); if (charStyle) SetAttributes(*charStyle); } -/// Load wxImage from the block -bool wxRichTextImage::LoadFromBlock() +/// Create a cached image at the required size +bool wxRichTextImage::LoadImageCache(wxDC& dc, bool resetCache) { - m_imageBlock.Load(m_image); - return m_imageBlock.Ok(); -} + if (resetCache || !m_imageCache.IsOk() /* || m_imageCache.GetWidth() != size.x || m_imageCache.GetHeight() != size.y */) + { + if (!m_imageBlock.IsOk()) + return false; + + wxImage image; + m_imageBlock.Load(image); + if (!image.IsOk()) + return false; + + int width = image.GetWidth(); + int height = image.GetHeight(); + + if (m_anchoredAttr.m_width != -1) + { + // Calculate the user specified length + if (m_anchoredAttr.m_unitsW == wxRICHTEXT_MM) + { + width = ConvertTenthsMMToPixels(dc, m_anchoredAttr.m_width); + } + else + { + width = m_anchoredAttr.m_width; + } + } -/// Make block from the wxImage -bool wxRichTextImage::MakeBlock() -{ - wxBitmapType type = m_imageBlock.GetImageType(); - if ( type == wxBITMAP_TYPE_ANY || type == wxBITMAP_TYPE_INVALID ) - m_imageBlock.SetImageType(type = wxBITMAP_TYPE_PNG); + if (m_anchoredAttr.m_height != -1) + { + if (m_anchoredAttr.m_unitsH == wxRICHTEXT_MM) + { + height = ConvertTenthsMMToPixels(dc, m_anchoredAttr.m_height); + } + else + { + height = m_anchoredAttr.m_height; + } + } - m_imageBlock.MakeImageBlock(m_image, type); - return m_imageBlock.Ok(); + if (image.GetWidth() == width && image.GetHeight() == height) + m_imageCache = wxBitmap(image); + else + { + // If the original width and height is small, e.g. 400 or below, + // scale up and then down to improve image quality. This can make + // a big difference, with not much performance hit. + int upscaleThreshold = 400; + wxImage img; + if (image.GetWidth() <= upscaleThreshold || image.GetHeight() <= upscaleThreshold) + { + img = image.Scale(image.GetWidth()*2, image.GetHeight()*2); + img.Rescale(width, height, wxIMAGE_QUALITY_HIGH); + } + else + img = image.Scale(width, height, wxIMAGE_QUALITY_HIGH); + m_imageCache = wxBitmap(img); + } + } + + return m_imageCache.IsOk(); } - /// Draw the item bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int WXUNUSED(descent), int WXUNUSED(style)) { - if (!m_image.Ok() && m_imageBlock.Ok()) - LoadFromBlock(); - - if (!m_image.Ok()) + // Don't need cached size AFAIK + // wxSize size = GetCachedSize(); + if (!LoadImageCache(dc)) return false; + + int y = rect.y + (rect.height - m_imageCache.GetHeight()); - if (m_image.Ok() && !m_bitmap.Ok()) - m_bitmap = wxBitmap(m_image); - - int y = rect.y + (rect.height - m_image.GetHeight()); - - if (m_bitmap.Ok()) - dc.DrawBitmap(m_bitmap, rect.x, y, true); + dc.DrawBitmap(m_imageCache, rect.x, y, true); if (selectionRange.Contains(range.GetStart())) { @@ -7160,43 +7696,40 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT } /// Lay the item out -bool wxRichTextImage::Layout(wxDC& WXUNUSED(dc), const wxRect& rect, int WXUNUSED(style)) +bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, int WXUNUSED(style)) { - if (!m_image.Ok()) - LoadFromBlock(); + if (!LoadImageCache(dc)) + return false; - if (m_image.Ok()) - { - SetCachedSize(wxSize(m_image.GetWidth(), m_image.GetHeight())); - SetPosition(rect.GetPosition()); - } + SetCachedSize(wxSize(m_imageCache.GetWidth(), m_imageCache.GetHeight())); + SetPosition(rect.GetPosition()); return true; } /// Get/set the object size for the given range. Returns false if the range /// is invalid for this object. -bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags), wxPoint WXUNUSED(position), wxArrayInt* partialExtents) const +bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& dc, int WXUNUSED(flags), wxPoint WXUNUSED(position), wxArrayInt* partialExtents) const { if (!range.IsWithin(GetRange())) return false; - if (!m_image.Ok()) - ((wxRichTextImage*) this)->LoadFromBlock(); - - if (partialExtents) + if (!((wxRichTextImage*)this)->LoadImageCache(dc)) { - if (m_image.Ok()) - partialExtents->Add(m_image.GetWidth()); - else + size.x = 0; size.y = 0; + if (partialExtents) partialExtents->Add(0); + return false; } + + int width = m_imageCache.GetWidth(); + int height = m_imageCache.GetHeight(); - if (!m_image.Ok()) - return false; + if (partialExtents) + partialExtents->Add(width); - size.x = m_image.GetWidth(); - size.y = m_image.GetHeight(); + size.x = width; + size.y = height; return true; } @@ -7204,12 +7737,26 @@ bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, i /// Copy void wxRichTextImage::Copy(const wxRichTextImage& obj) { - wxRichTextObject::Copy(obj); + wxRichTextAnchoredObject::Copy(obj); - m_image = obj.m_image; m_imageBlock = obj.m_imageBlock; } +/// Edit properties via a GUI +bool wxRichTextImage::EditProperties(wxWindow* parent, wxRichTextBuffer* buffer) +{ + wxRichTextImageDialog imageDlg(wxGetTopLevelParent(parent)); + imageDlg.SetImageObject(this, buffer); + + if (imageDlg.ShowModal() == wxID_OK) + { + imageDlg.ApplyImageAttr(); + return true; + } + else + return false; +} + /*! * Utilities * @@ -7503,39 +8050,48 @@ bool wxRichTextImageBlock::MakeImageBlock(const wxString& filename, wxBitmapType // format. bool wxRichTextImageBlock::MakeImageBlock(wxImage& image, wxBitmapType imageType, int quality) { - m_imageType = imageType; image.SetOption(wxT("quality"), quality); if (imageType == wxBITMAP_TYPE_INVALID) return false; // Could not determine image type - wxString tempFile = wxFileName::CreateTempFileName(_("image")) ; - wxASSERT(!tempFile.IsEmpty()); + return DoMakeImageBlock(image, imageType); +} - if (!image.SaveFile(tempFile, m_imageType)) +// Uses a const wxImage for efficiency, but can't set quality (only relevant for JPEG) +bool wxRichTextImageBlock::MakeImageBlockDefaultQuality(const wxImage& image, wxBitmapType imageType) +{ + if (imageType == wxBITMAP_TYPE_INVALID) + return false; // Could not determine image type + + return DoMakeImageBlock(image, imageType); +} + +// Makes the image block +bool wxRichTextImageBlock::DoMakeImageBlock(const wxImage& image, wxBitmapType imageType) +{ + wxMemoryOutputStream memStream; + if (!image.SaveFile(memStream, imageType)) { - if (wxFileExists(tempFile)) - wxRemoveFile(tempFile); return false; } - - wxFile file; - if (!file.Open(tempFile)) - return false; - - m_dataSize = (size_t) file.Length(); - file.Close(); - + + unsigned char* block = new unsigned char[memStream.GetSize()]; + if (!block) + return NULL; + if (m_data) delete[] m_data; - m_data = ReadBlock(tempFile, m_dataSize); + m_data = block; + + m_imageType = imageType; + m_dataSize = memStream.GetSize(); - wxRemoveFile(tempFile); + memStream.CopyTo(m_data, m_dataSize); return (m_data != NULL); } - // Write to a file bool wxRichTextImageBlock::Write(const wxString& filename) { diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index d46d6c31dd..4ef99e9f6b 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -300,12 +300,21 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va m_contextMenu->AppendSeparator(); m_contextMenu->Append(wxID_SELECTALL, _("Select &All")); + long ids = wxNewId(); + m_contextMenu->AppendSeparator(); + m_contextMenu->Append(ids, _("&Properties")); + + Connect(ids, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(wxRichTextCtrl::OnUpdateImage)); + Connect(ids, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxRichTextCtrl::OnImage)); + m_imagePropertyId = ids; return true; } wxRichTextCtrl::~wxRichTextCtrl() { GetBuffer().RemoveEventHandler(this); + Disconnect(m_imagePropertyId, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(wxRichTextCtrl::OnUpdateImage)); + Disconnect(m_imagePropertyId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxRichTextCtrl::OnImage)); delete m_contextMenu; } @@ -326,6 +335,7 @@ void wxRichTextCtrl::Init() m_fullLayoutSavedPosition = 0; m_delayedLayoutThreshold = wxRICHTEXT_DEFAULT_DELAYED_LAYOUT_THRESHOLD; m_caretPositionForDefaultStyle = -2; + m_currentObject = NULL; } void wxRichTextCtrl::DoThaw() @@ -2387,34 +2397,34 @@ void wxRichTextCtrl::AppendText(const wxString& text) } /// Write an image at the current insertion point -bool wxRichTextCtrl::WriteImage(const wxImage& image, wxBitmapType bitmapType) +bool wxRichTextCtrl::WriteImage(const wxImage& image, wxBitmapType bitmapType, const wxRichTextAnchoredObjectAttr& attr) { wxRichTextImageBlock imageBlock; wxImage image2 = image; if (imageBlock.MakeImageBlock(image2, bitmapType)) - return WriteImage(imageBlock); + return WriteImage(imageBlock, attr); return false; } -bool wxRichTextCtrl::WriteImage(const wxString& filename, wxBitmapType bitmapType) +bool wxRichTextCtrl::WriteImage(const wxString& filename, wxBitmapType bitmapType, const wxRichTextAnchoredObjectAttr& attr) { wxRichTextImageBlock imageBlock; wxImage image; if (imageBlock.MakeImageBlock(filename, bitmapType, image, false)) - return WriteImage(imageBlock); + return WriteImage(imageBlock, attr); return false; } -bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock) +bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock, const wxRichTextAnchoredObjectAttr& attr) { - return GetBuffer().InsertImageWithUndo(m_caretPosition+1, imageBlock, this); + return GetBuffer().InsertImageWithUndo(m_caretPosition+1, imageBlock, this, NULL, attr); } -bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType) +bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType, const wxRichTextAnchoredObjectAttr& attr) { if (bitmap.Ok()) { @@ -2422,7 +2432,7 @@ bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType) wxImage image = bitmap.ConvertToImage(); if (image.Ok() && imageBlock.MakeImageBlock(image, bitmapType)) - return WriteImage(imageBlock); + return WriteImage(imageBlock, attr); } return false; @@ -2824,6 +2834,18 @@ void wxRichTextCtrl::OnUpdateSelectAll(wxUpdateUIEvent& event) event.Enable(GetLastPosition() > 0); } +void wxRichTextCtrl::OnImage(wxCommandEvent& WXUNUSED(event)) +{ + if (GetCurrentObject() && GetCurrentObject()->CanEditProperties()) + GetCurrentObject()->EditProperties(this, & GetBuffer()); + SetCurrentObject(NULL); +} + +void wxRichTextCtrl::OnUpdateImage(wxUpdateUIEvent& event) +{ + event.Enable(GetCurrentObject() != NULL && GetCurrentObject()->CanEditProperties()); +} + void wxRichTextCtrl::OnContextMenu(wxContextMenuEvent& event) { if (event.GetEventObject() != this) @@ -2832,6 +2854,23 @@ void wxRichTextCtrl::OnContextMenu(wxContextMenuEvent& event) return; } + wxClientDC dc(this); + PrepareDC(dc); + dc.SetFont(GetFont()); + + long position = 0; + wxPoint pt = event.GetPosition(); + wxPoint logicalPt = GetLogicalPoint(ScreenToClient(pt)); + int hit = GetBuffer().HitTest(dc, logicalPt, position); + if (hit == wxRICHTEXT_HITTEST_ON || hit == wxRICHTEXT_HITTEST_BEFORE || hit == wxRICHTEXT_HITTEST_AFTER) + { + m_currentObject = GetBuffer().GetLeafObjectAtPosition(position); + } + else + { + m_currentObject = NULL; + } + if (m_contextMenu) PopupMenu(m_contextMenu); return; @@ -2847,6 +2886,11 @@ bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxTextAttr& st return GetBuffer().SetStyle(range.ToInternal(), style); } +void wxRichTextCtrl::SetImageStyle(wxRichTextImage *image, const wxRichTextAnchoredObjectAttr& attr) +{ + GetBuffer().SetImageStyle(image, attr); +} + // extended style setting operation with flags including: // wxRICHTEXT_SETSTYLE_WITH_UNDO, wxRICHTEXT_SETSTYLE_OPTIMIZE, wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY. // see richtextbuffer.h for more details. diff --git a/src/richtext/richtextdialogs.pjd b/src/richtext/richtextdialogs.pjd index 35faf900d6..793bbc3a8a 100644 --- a/src/richtext/richtextdialogs.pjd +++ b/src/richtext/richtextdialogs.pjd @@ -160,6 +160,7 @@ "Yes" "Yes" "Yes" + "sys" "Yes" "%EXECUTABLE%" "" @@ -553,7 +554,6 @@ 0 "" "" - 0 "wxRichTextFontListBox: ID_RICHTEXTFONTPAGE_FACELISTBOX" @@ -806,7 +806,6 @@ 0 "" "" - 0 "wxListBox: ID_RICHTEXTFONTPAGE_SIZELISTBOX" @@ -1049,6 +1048,7 @@ 0 1 0 + 0 0 0 0 @@ -1211,6 +1211,7 @@ 0 1 0 + 0 0 0 0 @@ -1373,6 +1374,7 @@ 0 1 0 + 0 0 0 0 @@ -2234,6 +2236,14 @@ "wbBoxSizerProxy" "Vertical" "" + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 0 0 0 @@ -3723,6 +3733,7 @@ 0 1 0 + 0 0 0 0 @@ -4536,6 +4547,7 @@ 0 1 0 + 0 0 0 0 @@ -6095,6 +6107,7 @@ 0 1 0 + 0 0 0 0 @@ -6393,6 +6406,7 @@ 1 0 0 + 0 0 0 0 @@ -6627,6 +6641,7 @@ 1 0 0 + 0 0 0 0 @@ -6792,6 +6807,7 @@ 1 0 0 + 0 0 0 0 @@ -7537,6 +7553,7 @@ 1 0 0 + 0 0 0 0 @@ -7673,6 +7690,7 @@ 1 0 0 + 0 0 0 0 @@ -8024,6 +8042,7 @@ 0 1 0 + 0 0 0 0 @@ -8187,6 +8206,7 @@ 0 1 0 + 0 0 0 0 @@ -8699,6 +8719,7 @@ 0 1 0 + 0 0 0 0 @@ -9023,7 +9044,6 @@ 300 0 "" - 0 "wxBoxSizer V" "dialog-control-document" @@ -11509,6 +11529,7 @@ 0 1 0 + 0 0 0 0 @@ -11807,6 +11828,7 @@ 1 0 0 + 0 0 0 0 @@ -12041,6 +12063,7 @@ 1 0 0 + 0 0 0 0 @@ -12206,6 +12229,7 @@ 1 0 0 + 0 0 0 0 @@ -14470,6 +14494,7 @@ 0 1 0 + 0 0 0 0 @@ -14574,6 +14599,1593 @@ + + "wxRichTextImageDialog" + "dialog-document" + "" + "dialog" + 0 + 1 + 0 + 0 + "wbDialogProxy" + 10000 + 0 + "" + 0 + "" + "Standard" + 0 + 0 + "ID_WXRICHTEXTIMAGEPAGE" + 10015 + "wxRichTextImageDialog" + "wxDialog" + "wxDialog" + "richtextimagedlg.cpp" + "../../include/wx/richtext/richtextimagedlg.h" + "" + "Image Properties" + 1 + "" + 0 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "Tiled" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + "" + 1 + 1 + -1 + -1 + 400 + 300 + 0 + "" + + "wxBoxSizer V" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Vertical" + "" + 0 + 0 + 0 + "<Any platform>" + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Expand" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "<Any platform>" + + "wxFlexGridSizer" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbFlexGridSizerProxy" + "" + "" + 2 + 0 + 0 + 0 + "" + "<Any platform>" + "Centre" + "Top" + 0 + 5 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "Alignment:" + -1 + "" + "" + "" + "" + "" + 1 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_COMBOBOX_ALIGN" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "ID_COMBOBOX_ALIGN" + 10016 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_alignment" + "Left|Centre|Right" + "Left" + "" + "" + "" + "" + "" + 1 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 80 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "&Floating mode:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Right" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_RICHTEXTIMAGEDIALOG_FLOATING_MODE" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "ID_RICHTEXTIMAGEDIALOG_FLOATING_MODE" + 10017 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_float" + "None|Left|Right" + "None" + "How the image will float relative to the text." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 80 + -1 + "Left" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "&Width:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Right" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Left" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxTextCtrl: ID_RICHTEXTIMAGEDIALOG_WIDTH" + "dialog-control-document" + "" + "textctrl" + 0 + 1 + 0 + 0 + "wbTextCtrlProxy" + "ID_RICHTEXTIMAGEDIALOG_WIDTH" + 10018 + "" + "wxTextCtrl" + "wxTextCtrl" + 1 + 0 + "" + "" + "m_width" + "" + 0 + "The image width to be shown - does not change the source image width." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 65 + -1 + "Left" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_RICHTEXTIMAGEDIALOG_UNITS_W" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "ID_RICHTEXTIMAGEDIALOG_UNITS_W" + 10019 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_unitsW" + "px|cm" + "px" + "Units for the image width." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 60 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "&Height:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Right" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Left" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxTextCtrl: ID_RICHTEXTIMAGEDIALOG_HEIGHT" + "dialog-control-document" + "" + "textctrl" + 0 + 1 + 0 + 0 + "wbTextCtrlProxy" + "ID_RICHTEXTIMAGEDIALOG_HEIGHT" + 10020 + "" + "wxTextCtrl" + "wxTextCtrl" + 1 + 0 + "" + "" + "m_height" + "" + 0 + "The image height to be shown - does not change the source image height." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 65 + -1 + "Left" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_RICHTEXTIMAGEDIALOG_UNITS_H" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "ID_RICHTEXTIMAGEDIALOG_UNITS_H" + 10021 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_unitsH" + "px|cm" + "px" + "Units for the image height." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 60 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "Image Vertical &Offset:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Right" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Left" + "Centre" + 1 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxTextCtrl: ID_RICHTEXTIMAGEDIALOG_OFFSET" + "dialog-control-document" + "" + "textctrl" + 0 + 1 + 0 + 0 + "wbTextCtrlProxy" + "ID_RICHTEXTIMAGEDIALOG_OFFSET" + 10022 + "" + "wxTextCtrl" + "wxTextCtrl" + 1 + 0 + "" + "" + "m_offset" + "" + 10 + "The vertical offset relative to the paragraph." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 65 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxComboBox: ID_RICHTEXTIMAGEDIALOG_OFFSET_UNITS" + "dialog-control-document" + "" + "combobox" + 0 + 1 + 0 + 0 + "wbComboBoxProxy" + "ID_RICHTEXTIMAGEDIALOG_OFFSET_UNITS" + 10023 + "" + "wxComboBox" + "wxComboBox" + 1 + 0 + "" + "" + "m_unitsOffset" + "px|cm" + "px" + "Units for the image offset." + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + 60 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + "wxStaticText: wxID_STATIC" + "dialog-control-document" + "" + "statictext" + 0 + 1 + 0 + 0 + "wbStaticTextProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticText" + "wxStaticText" + 1 + 0 + "" + "" + "" + "&Move the image to:" + -1 + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + "" + "" + "" + "" + "" + "" + "" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Right" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxBoxSizer H" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbBoxSizerProxy" + "Horizontal" + "" + "Left" + "Centre" + 0 + 5 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "<Any platform>" + + "wxButton: ID_RICHTEXTIMAGEDIALOG_PARA_UP" + "dialog-control-document" + "" + "dialogcontrol" + 0 + 1 + 0 + 0 + "wbButtonProxy" + "wxEVT_COMMAND_BUTTON_CLICKED|OnRichtextimagedialogParaUpClick|NONE||wxRichTextImageDialog" + "ID_RICHTEXTIMAGEDIALOG_PARA_UP" + 10024 + "" + "wxButton" + "wxButton" + 1 + 0 + "" + "" + "" + "&Previous Paragraph" + 0 + "Moves the image to the previous paragraph." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxButton: ID_RICHTEXTIMAGEDIALOG_DOWN" + "dialog-control-document" + "" + "dialogcontrol" + 0 + 1 + 0 + 0 + "wbButtonProxy" + "wxEVT_COMMAND_BUTTON_CLICKED|OnRichtextimagedialogDownClick|NONE||wxRichTextImageDialog" + "ID_RICHTEXTIMAGEDIALOG_DOWN" + 10025 + "" + "wxButton" + "wxButton" + 1 + 0 + "" + "" + "" + "&Next Paragraph" + 0 + "Moves the image to the next paragraph." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + + + "wxStaticLine: wxID_STATIC" + "dialog-control-document" + "" + "staticline" + 0 + 1 + 0 + 0 + "wbStaticLineProxy" + "wxID_STATIC" + 5105 + "" + "wxStaticLine" + "wxStaticLine" + 1 + 0 + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Expand" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + + + "wxStdDialogButtonSizer" + "dialog-control-document" + "" + "sizer" + 0 + 1 + 0 + 0 + "wbStdDialogButtonSizerProxy" + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + "" + "Expand" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "<Any platform>" + + "wxButton: wxID_OK" + "dialog-control-document" + "" + "dialogcontrol" + 0 + 1 + 0 + 1 + "wbButtonProxy" + "wxID_OK" + 5100 + "" + "wxButton" + "wxButton" + 1 + 0 + "" + "" + "m_saveButton" + "OK" + 0 + "Click to confirm your changes." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxButton: wxID_CANCEL" + "dialog-control-document" + "" + "dialogcontrol" + 0 + 1 + 0 + 1 + "wbButtonProxy" + "wxID_CANCEL" + 5101 + "" + "wxButton" + "wxButton" + 1 + 0 + "" + "" + "m_cancelButton" + "Cancel" + 0 + "Click to discard your changes." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + + "Sources" diff --git a/src/richtext/richtexthtml.cpp b/src/richtext/richtexthtml.cpp index c5df308797..ec723334ca 100644 --- a/src/richtext/richtexthtml.cpp +++ b/src/richtext/richtexthtml.cpp @@ -470,20 +470,27 @@ void wxRichTextHTMLHandler::WriteImage(wxRichTextImage* image, wxOutputStream& s #if wxUSE_FILESYSTEM if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY) { +#if 0 if (!image->GetImage().Ok() && image->GetImageBlock().GetData()) image->LoadFromBlock(); if (image->GetImage().Ok() && !image->GetImageBlock().GetData()) image->MakeBlock(); +#endif - if (image->GetImage().Ok()) + if (image->GetImageBlock().IsOk()) { - wxString ext(image->GetImageBlock().GetExtension()); - wxString tempFilename(wxString::Format(wxT("image%d.%s"), sm_fileCounter, ext)); - wxMemoryFSHandler::AddFile(tempFilename, image->GetImage(), image->GetImageBlock().GetImageType()); + wxImage img; + image->GetImageBlock().Load(img); + if (img.IsOk()) + { + wxString ext(image->GetImageBlock().GetExtension()); + wxString tempFilename(wxString::Format(wxT("image%d.%s"), sm_fileCounter, ext)); + wxMemoryFSHandler::AddFile(tempFilename, img, image->GetImageBlock().GetImageType()); - m_imageLocations.Add(tempFilename); + m_imageLocations.Add(tempFilename); - str << wxT("memory:") << tempFilename; + str << wxT("memory:") << tempFilename; + } } else str << wxT("memory:?"); @@ -492,12 +499,14 @@ void wxRichTextHTMLHandler::WriteImage(wxRichTextImage* image, wxOutputStream& s } else if (GetFlags() & wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES) { +#if 0 if (!image->GetImage().Ok() && image->GetImageBlock().GetData()) image->LoadFromBlock(); if (image->GetImage().Ok() && !image->GetImageBlock().GetData()) image->MakeBlock(); +#endif - if (image->GetImage().Ok()) + if (image->GetImageBlock().Ok()) { wxString tempDir(GetTempDir()); if (tempDir.IsEmpty()) @@ -522,14 +531,17 @@ void wxRichTextHTMLHandler::WriteImage(wxRichTextImage* image, wxOutputStream& s str << wxT("data:"); str << GetMimeType(image->GetImageBlock().GetImageType()); str << wxT(";base64,"); - +#if 0 if (image->GetImage().Ok() && !image->GetImageBlock().GetData()) image->MakeBlock(); +#endif + if (image->GetImageBlock().Ok()) + { + wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() ); + str << data; - wxChar* data = b64enc( image->GetImageBlock().GetData(), image->GetImageBlock().GetDataSize() ); - str << data; - - delete[] data; + delete[] data; + } } str << wxT("\" />"); diff --git a/src/richtext/richtextimagedlg.cpp b/src/richtext/richtextimagedlg.cpp new file mode 100644 index 0000000000..dc670e17cc --- /dev/null +++ b/src/richtext/richtextimagedlg.cpp @@ -0,0 +1,554 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: src/richtext/richtextimagedlg.cpp +// Purpose: +// Author: Mingquan Yang +// Modified by: +// Created: Wed 02 Jun 2010 11:27:23 CST +// RCS-ID: +// Copyright: (c) Mingquan Yang +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) +#pragma implementation "wx/richtext/richtextimagedlg.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/wx.h" +#endif + +////@begin includes +////@end includes + +#include "wx/richtext/richtextimagedlg.h" +#include "wx/richtext/richtextctrl.h" + +////@begin XPM images +////@end XPM images + + +/*! + * wxRichTextImageDialog type definition + */ + +IMPLEMENT_DYNAMIC_CLASS( wxRichTextImageDialog, wxDialog ) + + +/*! + * wxRichTextImageDialog event table definition + */ + +BEGIN_EVENT_TABLE( wxRichTextImageDialog, wxDialog ) + +////@begin wxRichTextImageDialog event table entries + EVT_BUTTON( ID_RICHTEXTIMAGEDIALOG_PARA_UP, wxRichTextImageDialog::OnRichtextimagedialogParaUpClick ) + + EVT_BUTTON( ID_RICHTEXTIMAGEDIALOG_DOWN, wxRichTextImageDialog::OnRichtextimagedialogDownClick ) + +////@end wxRichTextImageDialog event table entries + +END_EVENT_TABLE() + + +/*! + * wxRichTextImageDialog constructors + */ + +wxRichTextImageDialog::wxRichTextImageDialog() +{ + Init(); +} + +wxRichTextImageDialog::wxRichTextImageDialog( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) +{ + Init(); + Create(parent, id, caption, pos, size, style); +} + + +/*! + * wxRichTextImageDlg creator + */ + +bool wxRichTextImageDialog::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style ) +{ +////@begin wxRichTextImageDialog creation + SetExtraStyle(wxDIALOG_EX_CONTEXTHELP); + wxDialog::Create( parent, id, caption, pos, size, style ); + + CreateControls(); + if (GetSizer()) + { + GetSizer()->SetSizeHints(this); + } + Centre(); +////@end wxRichTextImageDialog creation + return true; +} + + +/*! + * wxRichTextImageDialog destructor + */ + +wxRichTextImageDialog::~wxRichTextImageDialog() +{ +////@begin wxRichTextImageDialog destruction +////@end wxRichTextImageDialog destruction +} + + +/*! + * Member initialisation + */ + +void wxRichTextImageDialog::Init() +{ +////@begin wxRichTextImageDialog member initialisation + m_alignment = NULL; + m_float = NULL; + m_width = NULL; + m_unitsW = NULL; + m_height = NULL; + m_unitsH = NULL; + m_offset = NULL; + m_unitsOffset = NULL; + m_saveButton = NULL; + m_cancelButton = NULL; +////@end wxRichTextImageDialog member initialisation +} + + +/*! + * Control creation for wxRichTextImageDlg + */ + +void wxRichTextImageDialog::CreateControls() +{ +#ifdef __WXMAC__ + SetWindowVariant(wxWINDOW_VARIANT_SMALL); +#endif + +////@begin wxRichTextImageDialog content construction + wxRichTextImageDialog* itemDialog1 = this; + + wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL); + itemDialog1->SetSizer(itemBoxSizer2); + + wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxHORIZONTAL); + itemBoxSizer2->Add(itemBoxSizer3, 0, wxGROW|wxALL, 5); + + wxFlexGridSizer* itemFlexGridSizer4 = new wxFlexGridSizer(0, 2, 0, 0); + itemBoxSizer3->Add(itemFlexGridSizer4, 0, wxALIGN_TOP|wxRIGHT, 5); + + wxStaticText* itemStaticText5 = new wxStaticText( itemDialog1, wxID_STATIC, _("Alignment:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemStaticText5->Show(false); + itemFlexGridSizer4->Add(itemStaticText5, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxArrayString m_alignmentStrings; + m_alignmentStrings.Add(_("Left")); + m_alignmentStrings.Add(_("Centre")); + m_alignmentStrings.Add(_("Right")); + m_alignment = new wxComboBox( itemDialog1, ID_COMBOBOX_ALIGN, _("Left"), wxDefaultPosition, wxSize(80, -1), m_alignmentStrings, wxCB_READONLY ); + m_alignment->SetStringSelection(_("Left")); + m_alignment->Show(false); + itemFlexGridSizer4->Add(m_alignment, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticText* itemStaticText7 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Floating mode:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemFlexGridSizer4->Add(itemStaticText7, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxArrayString m_floatStrings; + m_floatStrings.Add(_("None")); + m_floatStrings.Add(_("Left")); + m_floatStrings.Add(_("Right")); + m_float = new wxComboBox( itemDialog1, ID_RICHTEXTIMAGEDIALOG_FLOATING_MODE, _("None"), wxDefaultPosition, wxSize(80, -1), m_floatStrings, wxCB_READONLY ); + m_float->SetStringSelection(_("None")); + m_float->SetHelpText(_("How the image will float relative to the text.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_float->SetToolTip(_("How the image will float relative to the text.")); + itemFlexGridSizer4->Add(m_float, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticText* itemStaticText9 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Width:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemFlexGridSizer4->Add(itemStaticText9, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxBoxSizer* itemBoxSizer10 = new wxBoxSizer(wxHORIZONTAL); + itemFlexGridSizer4->Add(itemBoxSizer10, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); + + m_width = new wxTextCtrl( itemDialog1, ID_RICHTEXTIMAGEDIALOG_WIDTH, wxEmptyString, wxDefaultPosition, wxSize(65, -1), 0 ); + m_width->SetHelpText(_("The image width to be shown - does not change the source image width.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_width->SetToolTip(_("The image width to be shown - does not change the source image width.")); + itemBoxSizer10->Add(m_width, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxArrayString m_unitsWStrings; + m_unitsWStrings.Add(_("px")); + m_unitsWStrings.Add(_("cm")); + m_unitsW = new wxComboBox( itemDialog1, ID_RICHTEXTIMAGEDIALOG_UNITS_W, _("px"), wxDefaultPosition, wxSize(60, -1), m_unitsWStrings, wxCB_READONLY ); + m_unitsW->SetStringSelection(_("px")); + m_unitsW->SetHelpText(_("Units for the image width.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_unitsW->SetToolTip(_("Units for the image width.")); + itemBoxSizer10->Add(m_unitsW, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticText* itemStaticText13 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Height:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemFlexGridSizer4->Add(itemStaticText13, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL); + itemFlexGridSizer4->Add(itemBoxSizer14, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); + + m_height = new wxTextCtrl( itemDialog1, ID_RICHTEXTIMAGEDIALOG_HEIGHT, wxEmptyString, wxDefaultPosition, wxSize(65, -1), 0 ); + m_height->SetHelpText(_("The image height to be shown - does not change the source image height.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_height->SetToolTip(_("The image height to be shown - does not change the source image height.")); + itemBoxSizer14->Add(m_height, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxArrayString m_unitsHStrings; + m_unitsHStrings.Add(_("px")); + m_unitsHStrings.Add(_("cm")); + m_unitsH = new wxComboBox( itemDialog1, ID_RICHTEXTIMAGEDIALOG_UNITS_H, _("px"), wxDefaultPosition, wxSize(60, -1), m_unitsHStrings, wxCB_READONLY ); + m_unitsH->SetStringSelection(_("px")); + m_unitsH->SetHelpText(_("Units for the image height.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_unitsH->SetToolTip(_("Units for the image height.")); + itemBoxSizer14->Add(m_unitsH, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticText* itemStaticText17 = new wxStaticText( itemDialog1, wxID_STATIC, _("Image Vertical &Offset:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemFlexGridSizer4->Add(itemStaticText17, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxBoxSizer* itemBoxSizer18 = new wxBoxSizer(wxHORIZONTAL); + itemFlexGridSizer4->Add(itemBoxSizer18, 1, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); + + m_offset = new wxTextCtrl( itemDialog1, ID_RICHTEXTIMAGEDIALOG_OFFSET, wxEmptyString, wxDefaultPosition, wxSize(65, -1), 0 ); + m_offset->SetMaxLength(10); + m_offset->SetHelpText(_("The vertical offset relative to the paragraph.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_offset->SetToolTip(_("The vertical offset relative to the paragraph.")); + itemBoxSizer18->Add(m_offset, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxArrayString m_unitsOffsetStrings; + m_unitsOffsetStrings.Add(_("px")); + m_unitsOffsetStrings.Add(_("cm")); + m_unitsOffset = new wxComboBox( itemDialog1, ID_RICHTEXTIMAGEDIALOG_OFFSET_UNITS, _("px"), wxDefaultPosition, wxSize(60, -1), m_unitsOffsetStrings, wxCB_READONLY ); + m_unitsOffset->SetStringSelection(_("px")); + m_unitsOffset->SetHelpText(_("Units for the image offset.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_unitsOffset->SetToolTip(_("Units for the image offset.")); + itemBoxSizer18->Add(m_unitsOffset, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxStaticText* itemStaticText21 = new wxStaticText( itemDialog1, wxID_STATIC, _("&Move the image to:"), wxDefaultPosition, wxDefaultSize, 0 ); + itemFlexGridSizer4->Add(itemStaticText21, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxBoxSizer* itemBoxSizer22 = new wxBoxSizer(wxHORIZONTAL); + itemFlexGridSizer4->Add(itemBoxSizer22, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); + + wxButton* itemButton23 = new wxButton( itemDialog1, ID_RICHTEXTIMAGEDIALOG_PARA_UP, _("&Previous Paragraph"), wxDefaultPosition, wxDefaultSize, 0 ); + itemButton23->SetHelpText(_("Moves the image to the previous paragraph.")); + if (wxRichTextImageDialog::ShowToolTips()) + itemButton23->SetToolTip(_("Moves the image to the previous paragraph.")); + itemBoxSizer22->Add(itemButton23, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + wxButton* itemButton24 = new wxButton( itemDialog1, ID_RICHTEXTIMAGEDIALOG_DOWN, _("&Next Paragraph"), wxDefaultPosition, wxDefaultSize, 0 ); + itemButton24->SetHelpText(_("Moves the image to the next paragraph.")); + if (wxRichTextImageDialog::ShowToolTips()) + itemButton24->SetToolTip(_("Moves the image to the next paragraph.")); + itemBoxSizer22->Add(itemButton24, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxTOP|wxBOTTOM, 5); + + wxStaticLine* itemStaticLine25 = new wxStaticLine( itemDialog1, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + itemBoxSizer2->Add(itemStaticLine25, 0, wxGROW|wxALL, 5); + + wxStdDialogButtonSizer* itemStdDialogButtonSizer26 = new wxStdDialogButtonSizer; + + itemBoxSizer2->Add(itemStdDialogButtonSizer26, 0, wxGROW|wxALL, 5); + m_saveButton = new wxButton( itemDialog1, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 ); + m_saveButton->SetHelpText(_("Click to confirm your changes.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_saveButton->SetToolTip(_("Click to confirm your changes.")); + itemStdDialogButtonSizer26->AddButton(m_saveButton); + + m_cancelButton = new wxButton( itemDialog1, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + m_cancelButton->SetHelpText(_("Click to discard your changes.")); + if (wxRichTextImageDialog::ShowToolTips()) + m_cancelButton->SetToolTip(_("Click to discard your changes.")); + itemStdDialogButtonSizer26->AddButton(m_cancelButton); + + itemStdDialogButtonSizer26->Realize(); + +////@end wxRichTextImageDialog content construction +} + + +/*! + * Should we show tooltips? + */ + +bool wxRichTextImageDialog::ShowToolTips() +{ + return true; +} + +/*! + * Get bitmap resources + */ + +wxBitmap wxRichTextImageDialog::GetBitmapResource( const wxString& name ) +{ + // Bitmap retrieval +////@begin wxRichTextImageDialog bitmap retrieval + wxUnusedVar(name); + return wxNullBitmap; +////@end wxRichTextImageDialog bitmap retrieval +} + +/*! + * Get icon resources + */ + +wxIcon wxRichTextImageDialog::GetIconResource( const wxString& name ) +{ + // Icon retrieval +////@begin wxRichTextImageDialog icon retrieval + wxUnusedVar(name); + return wxNullIcon; +////@end wxRichTextImageDialog icon retrieval +} + +/*! + * Set the image attribute + */ +void wxRichTextImageDialog::SetImageAttr(const wxRichTextAnchoredObjectAttr& attr) +{ + m_attr = attr; + TransferDataToWindow(); +} + +/*! + * Apply the new style + */ +wxRichTextImage* wxRichTextImageDialog::ApplyImageAttr() +{ + wxRichTextImage* image = wxDynamicCast(m_image, wxRichTextImage); + + TransferDataFromWindow(); + if (m_buffer->GetRichTextCtrl()) + { + m_buffer->GetRichTextCtrl()->SetImageStyle(image, m_attr); + } + return image; +} + +void wxRichTextImageDialog::SetImageObject(wxRichTextImage* image, wxRichTextBuffer* buffer) +{ + wxRichTextObject* parent = image->GetParent(); + + m_buffer = buffer; + m_image = image; + m_parent = parent; + SetImageAttr(image->GetAnchoredAttr()); + if (image->GetImageCache().IsOk()) + { + if (m_attr.m_width == -1) + { + m_attr.m_width = image->GetImageCache().GetWidth(); + wxASSERT(m_attr.m_unitsW == wxRICHTEXT_PX); + + m_attr.m_unitsW = wxRICHTEXT_PX; + } + if (m_attr.m_height == -1) + { + m_attr.m_height = image->GetImageCache().GetHeight(); + wxASSERT(m_attr.m_unitsH == wxRICHTEXT_PX); + + m_attr.m_unitsH = wxRICHTEXT_PX; + } + } +} + +bool wxRichTextImageDialog::TransferDataToWindow() +{ + int remain = 100; + + m_alignment->SetSelection(m_attr.m_align); + m_float->SetSelection(m_attr.m_floating); + + // Update scale + m_unitsW->SetSelection(m_attr.m_unitsW); + m_unitsH->SetSelection(m_attr.m_unitsH); + m_unitsOffset->SetSelection(m_attr.m_unitsOffset); + + // Update metric + m_width->Clear(); + if (m_attr.m_unitsW == wxRICHTEXT_MM) + { + int remainder = m_attr.m_width % remain; + *m_width << m_attr.m_width / remain; + if (remainder) + { + *m_width << '.' << remainder; + } + } + else + { + *m_width << m_attr.m_width; + } + + m_height->Clear(); + if (m_attr.m_unitsH == wxRICHTEXT_MM) + { + int remainder = m_attr.m_height % remain; + *m_height << m_attr.m_height / remain; + if (remainder) + { + *m_height << '.' << remainder; + } + } + else + { + *m_height << m_attr.m_height; + } + + m_offset->Clear(); + if (m_attr.m_unitsOffset == wxRICHTEXT_MM) + { + int remainder = m_attr.m_offset % remain; + *m_offset << m_attr.m_offset / remain; + if (remainder) + { + *m_offset << '.' << remainder; + } + } + else + { + *m_offset << m_attr.m_offset; + } + + return true; +} + +bool wxRichTextImageDialog::TransferDataFromWindow() +{ + wxString width = m_width->GetValue(); + wxString height = m_height->GetValue(); + wxString offset = m_offset->GetValue(); + int w, h, o; + + m_attr.m_align = m_alignment->GetSelection(); + m_attr.m_floating = m_float->GetSelection(); + + m_attr.m_unitsW = m_unitsW->GetSelection(); + m_attr.m_unitsH = m_unitsH->GetSelection(); + m_attr.m_unitsOffset = m_unitsOffset->GetSelection(); + + if (ConvertFromString(width, w, m_attr.m_unitsW)) + m_attr.m_width = w; + if (ConvertFromString(height, h, m_attr.m_unitsH)) + m_attr.m_height = h; + if (ConvertFromString(offset, o, m_attr.m_unitsOffset)) + m_attr.m_offset = o; + + return true; +} + +bool wxRichTextImageDialog::ConvertFromString(const wxString& string, int& ret, int scale) +{ + const wxChar* chars = string.GetData(); + int remain = 2; + bool dot = false; + ret = 0; + + for (unsigned int i = 0; i < string.Len() && remain; i++) + { + if (!(chars[i] >= '0' && chars[i] <= '9') && !(scale == wxRICHTEXT_MM && chars[i] == '.')) + return false; + + if (chars[i] == '.') + { + dot = true; + continue; + } + + if (dot) + remain--; + + ret = ret * 10 + chars[i] - '0'; + } + + while (remain-- > 0 && scale == wxRICHTEXT_MM) + ret *= 10; + + return true; +} + + +/*! + * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_PARA_UP + */ +void wxRichTextImageDialog::OnRichtextimagedialogParaUpClick( wxCommandEvent& WXUNUSED(event)) +{ + // Before editing this code, remove the block markers. + wxRichTextRange range = m_image->GetRange(); + wxRichTextObjectList::compatibility_iterator iter = m_buffer->GetChildren().GetFirst(); + if (iter == NULL) + return; + + while (iter) + { + if (iter->GetData() == m_parent) + break; + iter = iter->GetNext(); + } + + iter = iter->GetPrevious(); + if (iter == NULL) + return; + + wxRichTextObject *obj = iter->GetData(); + wxRichTextRange rg = obj->GetRange(); + m_image = m_image->Clone(); + + m_buffer->DeleteRangeWithUndo(range, m_buffer->GetRichTextCtrl()); + m_buffer->InsertObjectWithUndo(rg.GetEnd(), m_image, m_buffer->GetRichTextCtrl(), 0); + m_parent = obj; + m_image->SetRange(wxRichTextRange(rg.GetEnd(), rg.GetEnd())); +} + + +/*! + * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_PARA_DOWN + */ + +void wxRichTextImageDialog::OnRichtextimagedialogDownClick( wxCommandEvent& WXUNUSED(event)) +{ + // Before editing this code, remove the block markers. + wxRichTextRange range = m_image->GetRange(); + wxRichTextObjectList::compatibility_iterator iter = m_buffer->GetChildren().GetFirst(); + if (iter == NULL) + return; + + while (iter) + { + if (iter->GetData() == m_parent) + break; + iter = iter->GetNext(); + } + + iter = iter->GetNext(); + if (iter == NULL) + return; + + wxRichTextObject *obj = iter->GetData(); + wxRichTextRange rg = obj->GetRange(); + m_image = m_image->Clone(); + + m_buffer->DeleteRangeWithUndo(range, m_buffer->GetRichTextCtrl()); + m_buffer->InsertObjectWithUndo(rg.GetEnd(), m_image, m_buffer->GetRichTextCtrl(), 0); + m_parent = obj; + m_image->SetRange(wxRichTextRange(rg.GetEnd(), rg.GetEnd())); +} + diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp index e257814c1e..d7963e6163 100644 --- a/src/richtext/richtextxml.cpp +++ b/src/richtext/richtextxml.cpp @@ -813,8 +813,8 @@ bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxString style = CreateStyle(obj.GetAttributes(), false); - if (imageObj.GetImage().Ok() && !imageObj.GetImageBlock().Ok()) - imageObj.MakeBlock(); + //if (imageObj.GetImage().Ok() && !imageObj.GetImageBlock().Ok()) + // imageObj.MakeBlock(); OutputIndentation(stream, indent); OutputString(stream, wxT("<") + objectName, convMem, convFile); -- 2.45.2