diff --git a/Makefile.in b/Makefile.in index 2d2e47810d..4c8c304036 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5975,6 +5975,7 @@ COND_TOOLKIT_OSX_COCOA___GUI_SRC_OBJECTS = \ monodll_osx_cocoa_menu.o \ monodll_osx_cocoa_menuitem.o \ monodll_osx_cocoa_msgdlg.o \ + monodll_cocoa_nativewin.o \ monodll_cocoa_nonownedwnd.o \ monodll_osx_cocoa_notebook.o \ monodll_osx_cocoa_radiobut.o \ @@ -8351,6 +8352,7 @@ COND_TOOLKIT_OSX_COCOA___GUI_SRC_OBJECTS_1 = \ monolib_osx_cocoa_menu.o \ monolib_osx_cocoa_menuitem.o \ monolib_osx_cocoa_msgdlg.o \ + monolib_cocoa_nativewin.o \ monolib_cocoa_nonownedwnd.o \ monolib_osx_cocoa_notebook.o \ monolib_osx_cocoa_radiobut.o \ @@ -10884,6 +10886,7 @@ COND_TOOLKIT_OSX_COCOA___GUI_SRC_OBJECTS_2 = \ coredll_osx_cocoa_menu.o \ coredll_osx_cocoa_menuitem.o \ coredll_osx_cocoa_msgdlg.o \ + coredll_cocoa_nativewin.o \ coredll_cocoa_nonownedwnd.o \ coredll_osx_cocoa_notebook.o \ coredll_osx_cocoa_radiobut.o \ @@ -12663,6 +12666,7 @@ COND_TOOLKIT_OSX_COCOA___GUI_SRC_OBJECTS_3 = \ corelib_osx_cocoa_menu.o \ corelib_osx_cocoa_menuitem.o \ corelib_osx_cocoa_msgdlg.o \ + corelib_cocoa_nativewin.o \ corelib_cocoa_nonownedwnd.o \ corelib_osx_cocoa_notebook.o \ corelib_osx_cocoa_radiobut.o \ @@ -18308,6 +18312,9 @@ monodll_osx_cocoa_menuitem.o: $(srcdir)/src/osx/cocoa/menuitem.mm $(MONODLL_ODEP monodll_osx_cocoa_msgdlg.o: $(srcdir)/src/osx/cocoa/msgdlg.mm $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/msgdlg.mm +monodll_cocoa_nativewin.o: $(srcdir)/src/osx/cocoa/nativewin.mm $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nativewin.mm + monodll_cocoa_nonownedwnd.o: $(srcdir)/src/osx/cocoa/nonownedwnd.mm $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nonownedwnd.mm @@ -24233,6 +24240,9 @@ monolib_osx_cocoa_menuitem.o: $(srcdir)/src/osx/cocoa/menuitem.mm $(MONOLIB_ODEP monolib_osx_cocoa_msgdlg.o: $(srcdir)/src/osx/cocoa/msgdlg.mm $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/msgdlg.mm +monolib_cocoa_nativewin.o: $(srcdir)/src/osx/cocoa/nativewin.mm $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nativewin.mm + monolib_cocoa_nonownedwnd.o: $(srcdir)/src/osx/cocoa/nonownedwnd.mm $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nonownedwnd.mm @@ -30839,6 +30849,9 @@ coredll_osx_cocoa_menuitem.o: $(srcdir)/src/osx/cocoa/menuitem.mm $(COREDLL_ODEP coredll_osx_cocoa_msgdlg.o: $(srcdir)/src/osx/cocoa/msgdlg.mm $(COREDLL_ODEP) $(CXXC) -c -o $@ $(COREDLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/msgdlg.mm +coredll_cocoa_nativewin.o: $(srcdir)/src/osx/cocoa/nativewin.mm $(COREDLL_ODEP) + $(CXXC) -c -o $@ $(COREDLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nativewin.mm + coredll_cocoa_nonownedwnd.o: $(srcdir)/src/osx/cocoa/nonownedwnd.mm $(COREDLL_ODEP) $(CXXC) -c -o $@ $(COREDLL_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nonownedwnd.mm @@ -35240,6 +35253,9 @@ corelib_osx_cocoa_menuitem.o: $(srcdir)/src/osx/cocoa/menuitem.mm $(CORELIB_ODEP corelib_osx_cocoa_msgdlg.o: $(srcdir)/src/osx/cocoa/msgdlg.mm $(CORELIB_ODEP) $(CXXC) -c -o $@ $(CORELIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/msgdlg.mm +corelib_cocoa_nativewin.o: $(srcdir)/src/osx/cocoa/nativewin.mm $(CORELIB_ODEP) + $(CXXC) -c -o $@ $(CORELIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nativewin.mm + corelib_cocoa_nonownedwnd.o: $(srcdir)/src/osx/cocoa/nonownedwnd.mm $(CORELIB_ODEP) $(CXXC) -c -o $@ $(CORELIB_OBJCXXFLAGS) $(srcdir)/src/osx/cocoa/nonownedwnd.mm diff --git a/autoconf_inc.m4 b/autoconf_inc.m4 index 810bcee64a..5b34ce9f5d 100644 --- a/autoconf_inc.m4 +++ b/autoconf_inc.m4 @@ -854,6 +854,12 @@ dnl ### begin block 20_COND_TOOLKIT_OSX_COCOA_USE_GUI_1[wx.bkl] ### COND_TOOLKIT_OSX_COCOA_USE_GUI_1="" fi AC_SUBST(COND_TOOLKIT_OSX_COCOA_USE_GUI_1) +dnl ### begin block 20_COND_TOOLKIT_OSX_COCOA_WXUNIV_0[../../samples/widgets/widgets.bkl] ### + COND_TOOLKIT_OSX_COCOA_WXUNIV_0="#" + if test "x$TOOLKIT" = "xOSX_COCOA" -a "x$WXUNIV" = "x0" ; then + COND_TOOLKIT_OSX_COCOA_WXUNIV_0="" + fi + AC_SUBST(COND_TOOLKIT_OSX_COCOA_WXUNIV_0) dnl ### begin block 20_COND_TOOLKIT_OSX_IPHONE[../../demos/bombs/bombs.bkl,../../demos/forty/forty.bkl,../../demos/fractal/fractal.bkl,../../demos/life/life.bkl,../../demos/poem/poem.bkl,../../samples/access/access.bkl,../../samples/animate/anitest.bkl,../../samples/artprov/artprov.bkl,../../samples/aui/auidemo.bkl,../../samples/calendar/calendar.bkl,../../samples/caret/caret.bkl,../../samples/clipboard/clipboard.bkl,../../samples/collpane/collpane.bkl,../../samples/combo/combo.bkl,../../samples/config/config.bkl,../../samples/controls/controls.bkl,../../samples/dataview/dataview.bkl,../../samples/debugrpt/debugrpt.bkl,../../samples/dialogs/dialogs.bkl,../../samples/dialup/dialup.bkl,../../samples/display/display.bkl,../../samples/dll/dll.bkl,../../samples/dnd/dnd.bkl,../../samples/docview/docview.bkl,../../samples/dragimag/dragimag.bkl,../../samples/drawing/drawing.bkl,../../samples/erase/erase.bkl,../../samples/event/event.bkl,../../samples/except/except.bkl,../../samples/exec/exec.bkl,../../samples/font/font.bkl,../../samples/fswatcher/fswatcher.bkl,../../samples/grid/grid.bkl,../../samples/help/help.bkl,../../samples/htlbox/htlbox.bkl,../../samples/html/about/about.bkl,../../samples/html/help/help.bkl,../../samples/html/helpview/helpview.bkl,../../samples/html/htmlctrl/htmlctrl.bkl,../../samples/html/printing/printing.bkl,../../samples/html/test/test.bkl,../../samples/html/virtual/virtual.bkl,../../samples/html/widget/widget.bkl,../../samples/html/zip/zip.bkl,../../samples/image/image.bkl,../../samples/internat/internat.bkl,../../samples/ipc/ipc.bkl,../../samples/joytest/joytest.bkl,../../samples/keyboard/keyboard.bkl,../../samples/layout/layout.bkl,../../samples/listctrl/listctrl.bkl,../../samples/mdi/mdi.bkl,../../samples/mediaplayer/mediaplayer.bkl,../../samples/memcheck/memcheck.bkl,../../samples/menu/menu.bkl,../../samples/minimal-mariano/minimal.bkl,../../samples/minimal/minimal.bkl,../../samples/nativdlg/nativdlg.bkl,../../samples/notebook/notebook.bkl,../../samples/oleauto/oleauto.bkl,../../samples/opengl/cube/cube.bkl,../../samples/opengl/isosurf/isosurf.bkl,../../samples/opengl/penguin/penguin.bkl,../../samples/ownerdrw/ownerdrw.bkl,../../samples/popup/popup.bkl,../../samples/power/power.bkl,../../samples/preferences/preferences.bkl,../../samples/printing/printing.bkl,../../samples/propgrid/propgrid.bkl,../../samples/regtest/regtest.bkl,../../samples/render/render.bkl,../../samples/ribbon/ribbon.bkl,../../samples/richtext/richtext.bkl,../../samples/sashtest/sashtest.bkl,../../samples/scroll/scroll.bkl,../../samples/shaped/shaped.bkl,../../samples/sockets/sockets.bkl,../../samples/sound/sound.bkl,../../samples/splash/splash.bkl,../../samples/splitter/splitter.bkl,../../samples/statbar/statbar.bkl,../../samples/stc/stctest.bkl,../../samples/svg/svgtest.bkl,../../samples/taborder/taborder.bkl,../../samples/taskbar/taskbar.bkl,../../samples/taskbarbutton/taskbarbutton.bkl,../../samples/text/text.bkl,../../samples/thread/thread.bkl,../../samples/toolbar/toolbar.bkl,../../samples/treectrl/treectrl.bkl,../../samples/treelist/treelist.bkl,../../samples/typetest/typetest.bkl,../../samples/uiaction/uiaction.bkl,../../samples/validate/validate.bkl,../../samples/vscroll/vscroll.bkl,../../samples/webview/webview.bkl,../../samples/widgets/widgets.bkl,../../samples/wizard/wizard.bkl,../../samples/wrapsizer/wrapsizer.bkl,../../samples/xrc/xrcdemo.bkl,../../samples/xti/xti.bkl,../../tests/benchmarks/bench.bkl,../../tests/test.bkl,../../utils/helpview/src/helpview.bkl,../../utils/screenshotgen/src/screenshotgen.bkl,wx.bkl] ### COND_TOOLKIT_OSX_IPHONE="#" if test "x$TOOLKIT" = "xOSX_IPHONE" ; then diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 925d6a3e84..5baee04998 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -2545,6 +2545,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/cocoa/menu.mm src/osx/cocoa/menuitem.mm src/osx/cocoa/msgdlg.mm + src/osx/cocoa/nativewin.mm src/osx/cocoa/nonownedwnd.mm src/osx/cocoa/notebook.mm src/osx/cocoa/radiobut.mm diff --git a/build/files b/build/files index b388423eb5..db44285c0b 100644 --- a/build/files +++ b/build/files @@ -2149,6 +2149,7 @@ OSX_COCOA_SRC = src/osx/cocoa/menu.mm src/osx/cocoa/menuitem.mm src/osx/cocoa/msgdlg.mm + src/osx/cocoa/nativewin.mm src/osx/cocoa/nonownedwnd.mm src/osx/cocoa/notebook.mm src/osx/cocoa/radiobut.mm diff --git a/configure b/configure index 93340ce7b4..a7b969b9b4 100755 --- a/configure +++ b/configure @@ -715,6 +715,7 @@ COND_TOOLKIT_QT COND_TOOLKIT_OSX_IPHONE_USE_GUI_1_WXUNIV_0 COND_TOOLKIT_OSX_IPHONE_USE_GUI_1 COND_TOOLKIT_OSX_IPHONE +COND_TOOLKIT_OSX_COCOA_WXUNIV_0 COND_TOOLKIT_OSX_COCOA_USE_GUI_1 COND_TOOLKIT_OSX_COCOA COND_TOOLKIT_OSX_CARBON_USE_GUI_1 @@ -40051,6 +40052,11 @@ EOF COND_TOOLKIT_OSX_COCOA_USE_GUI_1="" fi + COND_TOOLKIT_OSX_COCOA_WXUNIV_0="#" + if test "x$TOOLKIT" = "xOSX_COCOA" -a "x$WXUNIV" = "x0" ; then + COND_TOOLKIT_OSX_COCOA_WXUNIV_0="" + fi + COND_TOOLKIT_OSX_IPHONE="#" if test "x$TOOLKIT" = "xOSX_IPHONE" ; then COND_TOOLKIT_OSX_IPHONE="" diff --git a/docs/changes.txt b/docs/changes.txt index 8707982594..689e8c11ed 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -45,6 +45,8 @@ Changes in behaviour which may result in build errors - wxQt branch implementing Qt5-based port of wxWidgets API was merged into the trunk (Mariano Reingart, Google Summer of Code project). +- Added wxNativeWindow allowing to embed native widgets in wxWidgets programs. + All: - Allow calling wxItemContainer::Add() and similar with std::vector<> argument. diff --git a/docs/doxygen/mainpages/const_cpp.h b/docs/doxygen/mainpages/const_cpp.h index 0dccb52800..d2ebb87df1 100644 --- a/docs/doxygen/mainpages/const_cpp.h +++ b/docs/doxygen/mainpages/const_cpp.h @@ -207,6 +207,7 @@ Currently the following symbols exist: decide whether some function should be overloaded for both long and long long types.} @itemdef{wxHAS_MULTIPLE_FILEDLG_FILTERS, Defined if wxFileDialog supports multiple ('|'-separated) filters.} +@itemdef{wxHAS_NATIVE_WINDOW, Defined if wxNativeWindow class is available.} @itemdef{wxHAS_IMAGES_IN_RESOURCES, Defined if Windows resource files or OS/2 resource files are available on the current platform.} @itemdef{wxHAS_POWER_EVENTS, Defined if wxPowerEvent are ever generated on the current platform.} diff --git a/include/wx/nativewin.h b/include/wx/nativewin.h index fbbc0d1efa..21d7496af1 100644 --- a/include/wx/nativewin.h +++ b/include/wx/nativewin.h @@ -12,11 +12,13 @@ #include "wx/toplevel.h" -// this symbol can be tested in the user code to see if the current wx port has -// support for creating wxNativeContainerWindow from native windows +// These symbols can be tested in the user code to see if the current wx port +// has support for creating wxNativeContainerWindow and wxNativeWindow from +// native windows. // -// be optimistic by default, we undefine it below if we don't have it finally +// Be optimistic by default, we undefine them below if necessary. #define wxHAS_NATIVE_CONTAINER_WINDOW +#define wxHAS_NATIVE_WINDOW // we define the following typedefs for each of the platform supporting native // windows wrapping: @@ -28,16 +30,16 @@ // window, i.e. HWND/GdkNativeWindow/NSWindow (so it's the same as above for // all platforms except GTK where we also can work with Window/XID) // -// later we'll also have -// -// - wxNativeWindowHandle for child windows (which will be wrapped by -// wxNativeWindow class), it is HWND/GtkWidget*/ControlRef +// - wxNativeWindowHandle for child windows, i.e. HWND/GtkWidget*/NSControl #if defined(__WXMSW__) #include "wx/msw/wrapwin.h" typedef HWND wxNativeContainerWindowId; typedef HWND wxNativeContainerWindowHandle; + typedef HWND wxNativeWindowHandle; #elif defined(__WXGTK__) + #include + // GdkNativeWindow is guint32 under GDK/X11 and gpointer under GDK/WIN32 #ifdef __UNIX__ typedef unsigned long wxNativeContainerWindowId; @@ -45,11 +47,51 @@ typedef void *wxNativeContainerWindowId; #endif typedef GdkWindow *wxNativeContainerWindowHandle; + typedef GtkWidget *wxNativeWindowHandle; +#elif defined(__WXOSX_COCOA__) + typedef NSView *wxNativeWindowHandle; + + // no support for using native TLWs yet + #undef wxHAS_NATIVE_CONTAINER_WINDOW #else // no support for using native windows under this platform yet #undef wxHAS_NATIVE_CONTAINER_WINDOW + #undef wxHAS_NATIVE_WINDOW #endif +#ifdef wxHAS_NATIVE_WINDOW + +// ---------------------------------------------------------------------------- +// wxNativeWindow: for using native windows inside wxWidgets windows +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxNativeWindow : public wxWindow +{ +public: + // Default ctor, Create() must be called later to really create the window. + wxNativeWindow() { } + + // Create a window from an existing native window handle. + // + // Notice that this ctor doesn't take the usual pos and size parameters, + // they're taken from the window handle itself. + // + // Use GetHandle() to check if the creation was successful, it will return + // 0 if the handle was invalid. + wxNativeWindow(wxWindow* parent, wxWindowID winid, wxNativeWindowHandle handle) + { + Create(parent, winid, handle); + } + + // Same as non-default ctor, but with a return code. + bool Create(wxWindow* parent, wxWindowID winid, wxNativeWindowHandle handle); + +private: + wxDECLARE_NO_COPY_CLASS(wxNativeWindow); +}; + +#endif // wxHAS_NATIVE_WINDOW + #ifdef wxHAS_NATIVE_CONTAINER_WINDOW // ---------------------------------------------------------------------------- diff --git a/interface/wx/nativewin.h b/interface/wx/nativewin.h new file mode 100644 index 0000000000..c35cc6ac68 --- /dev/null +++ b/interface/wx/nativewin.h @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/nativewin.h +// Purpose: wxNativeWindow documentation. +// Author: Vadim Zeitlin +// Created: 2015-07-31 +// Copyright: (c) 2015 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +/** + @class wxNativeWindow + + Allows to embed a native widget in an application using wxWidgets. + + This class can be used as a bridge between wxWidgets and native GUI + toolkit, i.e. standard Windows controls under MSW, GTK+ widgets or Cocoa + views. Using it involves writing code specific to each platform, at the + very least for creating the native window, but possibly also to handle its + events, but this class takes care of all the generic parts. + + @note Check whether @c wxHAS_NATIVE_WINDOW is defined before using this + class as it is not available under all platforms. + + For example, to embed a native GTK+ "light switch" control in a wxWidgets + dialog you could do the following: + @code + #include + + wxNativeWindow* switch = new wxNativeWindow(parent, wxID_ANY, gtk_switch_new()); + @endcode + and then use @c switch as usual, e.g. add it to a sizer to layout it + correctly. Of course, you will still have to use the native GTK+ functions + to handle its events and change or retrieve its state. + + See the "native" page of the widgets sample for another example of using + it. + + @since 3.1.0 + + @library{core} + @category{ctrl} + */ +class wxNativeWindow : public wxWindow +{ +public: + /** + Default ctor, Create() must be called later to really create the window. + */ + wxNativeWindow(); + + /** + Create a window from an existing native window handle. + + Notice that this ctor doesn't take the usual @c pos and @c size + parameters, they're taken from the window handle itself. + + Use GetHandle() to check if the creation was successful, it will return + 0 if the handle was invalid. + + See Create() for the detailed parameters documentation. + */ + wxNativeWindow(wxWindow* parent, wxWindowID winid, wxNativeWindowHandle handle) + + /** + Really create the window after using the default ctor to create the C++ + object. + + @param parent A non-NULL parent window. For the platforms where the + parent is used for creating the native window (e.g. MSW), this must + be the wxWindow corresponding to the parent handle used when + creating the native window. + @param winid ID for the new window which will be used for the events + generated by it and can also be used to FindWindowById(). + @param handle A valid native window handle, i.e. HWND under MSW. + @return @true if the creation was successful or @false if it failed, + typically because the supplied parameters are invalid. + */ + bool Create(wxWindow* parent, wxWindowID winid, wxNativeWindowHandle handle); +}; diff --git a/samples/widgets/Makefile.in b/samples/widgets/Makefile.in index 5adc5baee8..d94108b5a5 100644 --- a/samples/widgets/Makefile.in +++ b/samples/widgets/Makefile.in @@ -22,6 +22,7 @@ LIBS = @LIBS@ LDFLAGS_GUI = @LDFLAGS_GUI@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ +OBJCXXFLAGS = @OBJCXXFLAGS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ WX_LIB_FLAVOUR = @WX_LIB_FLAVOUR@ @@ -49,6 +50,10 @@ WIDGETS_CXXFLAGS = -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) \ $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) \ -I$(srcdir) $(__DLLFLAG_p) -I$(srcdir)/../../samples $(CXXWARNINGS) \ $(SAMPLES_CXXFLAGS) $(CPPFLAGS) $(CXXFLAGS) +WIDGETS_OBJCXXFLAGS = -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) \ + $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) \ + $(__THREAD_DEFINE_p) -I$(srcdir) $(__DLLFLAG_p) -I$(srcdir)/../../samples \ + $(CPPFLAGS) $(OBJCXXFLAGS) WIDGETS_OBJECTS = \ widgets_activityindicator.o \ widgets_bmpcombobox.o \ @@ -68,6 +73,8 @@ WIDGETS_OBJECTS = \ widgets_hyperlnk.o \ widgets_itemcontainer.o \ widgets_listbox.o \ + $(__NATIVE_OBJCPP_SRC_OBJECTS) \ + widgets_native.o \ widgets_notebook.o \ widgets_odcombobox.o \ widgets_radiobox.o \ @@ -131,6 +138,8 @@ COND_PLATFORM_OS2_1___widgets___os2_emxbindcmd = $(NM) widgets$(EXEEXT) | if \ @COND_TOOLKIT_OSX_IPHONE@ = $(__widgets_app_Contents_PkgInfo___depname) @COND_TOOLKIT_COCOA@____widgets_BUNDLE_TGT_REF_DEP = \ @COND_TOOLKIT_COCOA@ $(__widgets_app_Contents_PkgInfo___depname) +@COND_TOOLKIT_OSX_COCOA_WXUNIV_0@__NATIVE_OBJCPP_SRC_OBJECTS \ +@COND_TOOLKIT_OSX_COCOA_WXUNIV_0@ = widgets_native_wrapper.o COND_MONOLITHIC_0___WXLIB_ADV_p = \ -lwx_$(PORTNAME)$(WXUNIVNAME)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_adv-$(WX_RELEASE)$(HOST_SUFFIX) @COND_MONOLITHIC_0@__WXLIB_ADV_p = $(COND_MONOLITHIC_0___WXLIB_ADV_p) @@ -265,6 +274,12 @@ widgets_itemcontainer.o: $(srcdir)/itemcontainer.cpp widgets_listbox.o: $(srcdir)/listbox.cpp $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $(srcdir)/listbox.cpp +widgets_native_wrapper.o: $(srcdir)/native_wrapper.mm + $(CXXC) -c -o $@ $(WIDGETS_OBJCXXFLAGS) $(srcdir)/native_wrapper.mm + +widgets_native.o: $(srcdir)/native.cpp + $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $(srcdir)/native.cpp + widgets_notebook.o: $(srcdir)/notebook.cpp $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $(srcdir)/notebook.cpp diff --git a/samples/widgets/icons/native.xpm b/samples/widgets/icons/native.xpm new file mode 100644 index 0000000000..c33e30cd96 --- /dev/null +++ b/samples/widgets/icons/native.xpm @@ -0,0 +1,81 @@ +/* XPM */ +static const char *const native_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 59 1 ", +" c #E40000", +". c #E50000", +"X c #E70000", +"o c #EA0000", +"O c #EB0000", +"+ c #ED0000", +"@ c #F10000", +"# c #F20000", +"$ c #F60000", +"% c #FA0000", +"& c #FB0000", +"* c #FC0000", +"= c #FC0001", +"- c #FE0002", +"; c #FF2C35", +": c #FF4F4F", +"> c #75ED00", +", c #76ED00", +"< c #76EE00", +"1 c #76F000", +"2 c #77F100", +"3 c #79F600", +"4 c #7AF700", +"5 c #7BF700", +"6 c #7AF900", +"7 c #7BF900", +"8 c #7CFB00", +"9 c #7DFC00", +"0 c #7EFE00", +"q c #81FF04", +"w c #82FF07", +"e c #8AFF17", +"r c #8CFF1B", +"t c #8CFF1D", +"y c #A7FF15", +"u c #92FF26", +"i c #92FF27", +"p c #93FF29", +"a c #9AFF37", +"s c #9CFF3B", +"d c #A1FF46", +"f c #A1FF4D", +"g c #AAFF56", +"h c #A4FF5C", +"j c #A2FF68", +"k c #B0FF62", +"l c #B6FF71", +"z c #B8FF73", +"x c #C5FF67", +"c c #FFA6A6", +"v c #FFB4B4", +"b c #C0FF83", +"n c #CBFF98", +"m c #E2FFB3", +"M c #B5D9FF", +"N c #D2E6FF", +"B c #D2E7FF", +"V c #DBECFF", +"C c None", +/* pixels */ +"CCCCCCVVMNCCCCCC", +"CCCBBBBBBBBBCCCC", +"CNNNNNNNNNNNNNCC", +"C-MMMMMMMMMMMMVC", +"CXoMMMMMMMMMMjsC", +"Co ;MMMMMh9>>qC", +"C+X X%Mfq7>>>>iC", +"C# y>57>>>>dC", +"C$ Xy6pe>>>>gC", +"C% X$%x3>3i2>>kC", +"C:%%X y>>>>t7>lC", +"Cco y>>>>>9tbC", +"CCv+ y>>>>>2gCC", +"CCCC# y>>>9zCCCC", +"CCCCC%y>anCCCCCC", +"CCCCCCmCCCCCCCCC" +}; diff --git a/samples/widgets/makefile.bcc b/samples/widgets/makefile.bcc index 333b714532..991ea88449 100644 --- a/samples/widgets/makefile.bcc +++ b/samples/widgets/makefile.bcc @@ -54,6 +54,7 @@ WIDGETS_OBJECTS = \ $(OBJS)\widgets_hyperlnk.obj \ $(OBJS)\widgets_itemcontainer.obj \ $(OBJS)\widgets_listbox.obj \ + $(OBJS)\widgets_native.obj \ $(OBJS)\widgets_notebook.obj \ $(OBJS)\widgets_odcombobox.obj \ $(OBJS)\widgets_radiobox.obj \ @@ -318,6 +319,9 @@ $(OBJS)\widgets_itemcontainer.obj: .\itemcontainer.cpp $(OBJS)\widgets_listbox.obj: .\listbox.cpp $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) .\listbox.cpp +$(OBJS)\widgets_native.obj: .\native.cpp + $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) .\native.cpp + $(OBJS)\widgets_notebook.obj: .\notebook.cpp $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) .\notebook.cpp diff --git a/samples/widgets/makefile.gcc b/samples/widgets/makefile.gcc index 28957a0d19..53af196de6 100644 --- a/samples/widgets/makefile.gcc +++ b/samples/widgets/makefile.gcc @@ -47,6 +47,7 @@ WIDGETS_OBJECTS = \ $(OBJS)\widgets_hyperlnk.o \ $(OBJS)\widgets_itemcontainer.o \ $(OBJS)\widgets_listbox.o \ + $(OBJS)\widgets_native.o \ $(OBJS)\widgets_notebook.o \ $(OBJS)\widgets_odcombobox.o \ $(OBJS)\widgets_radiobox.o \ @@ -307,6 +308,9 @@ $(OBJS)\widgets_itemcontainer.o: ./itemcontainer.cpp $(OBJS)\widgets_listbox.o: ./listbox.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\widgets_native.o: ./native.cpp + $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\widgets_notebook.o: ./notebook.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< diff --git a/samples/widgets/makefile.unx b/samples/widgets/makefile.unx index eb5fe9d350..6ec2d07a6e 100644 --- a/samples/widgets/makefile.unx +++ b/samples/widgets/makefile.unx @@ -71,6 +71,7 @@ WIDGETS_OBJECTS = \ widgets_hyperlnk.o \ widgets_itemcontainer.o \ widgets_listbox.o \ + widgets_native.o \ widgets_notebook.o \ widgets_odcombobox.o \ widgets_radiobox.o \ @@ -173,6 +174,9 @@ widgets_itemcontainer.o: ./itemcontainer.cpp widgets_listbox.o: ./listbox.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< +widgets_native.o: ./native.cpp + $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< + widgets_notebook.o: ./notebook.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $(CPPDEPS) $< diff --git a/samples/widgets/makefile.vc b/samples/widgets/makefile.vc index 818b1361a3..0990e005ce 100644 --- a/samples/widgets/makefile.vc +++ b/samples/widgets/makefile.vc @@ -49,6 +49,7 @@ WIDGETS_OBJECTS = \ $(OBJS)\widgets_hyperlnk.obj \ $(OBJS)\widgets_itemcontainer.obj \ $(OBJS)\widgets_listbox.obj \ + $(OBJS)\widgets_native.obj \ $(OBJS)\widgets_notebook.obj \ $(OBJS)\widgets_odcombobox.obj \ $(OBJS)\widgets_radiobox.obj \ @@ -441,6 +442,9 @@ $(OBJS)\widgets_itemcontainer.obj: .\itemcontainer.cpp $(OBJS)\widgets_listbox.obj: .\listbox.cpp $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) .\listbox.cpp +$(OBJS)\widgets_native.obj: .\native.cpp + $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) .\native.cpp + $(OBJS)\widgets_notebook.obj: .\notebook.cpp $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) .\notebook.cpp diff --git a/samples/widgets/native.cpp b/samples/widgets/native.cpp new file mode 100644 index 0000000000..f4c257fa46 --- /dev/null +++ b/samples/widgets/native.cpp @@ -0,0 +1,281 @@ +///////////////////////////////////////////////////////////////////////////// +// Program: wxWidgets Widgets Sample +// Name: native.cpp +// Purpose: Part of the widgets sample showing native control integration +// Author: Vadim Zeitlin +// Created: 2015-07-30 +// Copyright: (c) 2015 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// this file is included from native.mm which ensures that it is compiled as +// Objective C++, but it's also still compiled by the makefiles directly as C++ +// source because we can't easily exclude it, so check for this and only +// compile the rest of this file once +#if !defined(__WXOSX_COCOA__) || defined(__OBJC__) + +// for all others, include the necessary headers +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/checkbox.h" + #include "wx/log.h" + #include "wx/menu.h" + #include "wx/sizer.h" +#endif // !WX_PRECOMP + +#include "wx/nativewin.h" + +#ifdef wxHAS_NATIVE_WINDOW + +#include "widgets.h" + +#include "icons/native.xpm" + +// Helper to create a menu to be shown in our button. +// +// The menu is supposed to be initially empty, don't call this more than once +// for the same object. +void BuildTestMenu(wxMenu *menu) +{ + menu->Append(wxID_NEW, "Do it with a new file"); + menu->Append(wxID_OPEN, "Do it with an existing file"); + menu->AppendSeparator(); + menu->Append(wxID_ABOUT); +} + +// Create the native control in a -- necessarily -- platform-specific way. +#ifdef __WXMSW__ + +#include "wx/msw/wrapcctl.h" // for BS_SPLITBUTTON + +class NativeWindow : public wxNativeWindow +{ +public: + explicit NativeWindow(wxWindow* parent) + : wxNativeWindow() + { + // When creating the native window, we must specify the valid parent + // and while we don't have to specify any position if it's going to be + // laid out by sizers, we do need the size. + const wxSize size = FromDIP(wxSize(140, 30)); + + HWND hwnd = ::CreateWindow + ( + TEXT("BUTTON"), + TEXT("Press me to do it"), + WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON, + 0, 0, size.x, size.y, + (HWND)parent->GetHWND(), 0, NULL, NULL + ); + if ( !hwnd ) + { + wxLogError("Creating split button failed."); + return; + } + + (void)Create(parent, wxID_ANY, hwnd); + } + +protected: + // Split buttons under MSW don't show the menu on their own, unlike their + // equivalents under the other platforms, so do it manually here. This also + // shows how to handle a native event in MSW (for the specific case of + // WM_NOTIFY, more generally MSWHandleMessage() could be overridden). + virtual bool + MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxOVERRIDE + { + const NMHDR* hdr = reinterpret_cast(lParam); + if ( hdr->code != BCN_DROPDOWN ) + return wxNativeWindow::MSWOnNotify(idCtrl, lParam, result); + + const NMBCDROPDOWN* dd = reinterpret_cast(lParam); + + wxMenu menu; + BuildTestMenu(&menu); + PopupMenu(&menu, wxPoint(dd->rcButton.right, dd->rcButton.bottom)); + + return true; + } +}; + +#elif defined(__WXGTK__) + +class NativeWindow : public wxNativeWindow +{ +public: + explicit NativeWindow(wxWindow* parent) + : wxNativeWindow() + { +#if GTK_CHECK_VERSION(3,6,0) + BuildTestMenu(&m_menu); + + GtkWidget* const widget = gtk_menu_button_new(); + gtk_menu_button_set_popup(GTK_MENU_BUTTON(widget), m_menu.m_menu); +#else // GTK+ < 3.6 + // Menu buttons are only available since GTK+ 3.6, so use something + // even simpler for earlier versions (including GTK+ 2) just as a + // placeholder. + GtkWidget* const widget = gtk_label_new(""); + gtk_label_set_markup + ( + GTK_LABEL(widget), + "Sorry, but your GTK+ is too old to have menu buttons." + ); +#endif // GTK+ 3.6/earlier + + (void)Create(parent, wxID_ANY, widget); + } + +private: + wxMenu m_menu; +}; + +#elif defined(__WXOSX_COCOA__) + +#import + +class NativeWindow : public wxNativeWindow +{ +public: + explicit NativeWindow(wxWindow* parent) + : wxNativeWindow() + { + // Neither the position nor the size really matter: the former because + // the window will be positioned by the sizers, the latter because its + // "fitting" size will be used as the best size by default. + NSPopUpButton* const v = [[NSPopUpButton alloc] + initWithFrame:NSMakeRect(0, 0, 0, 0) + pullsDown:YES]; + + wxMenu menu; + BuildTestMenu(&menu); + [v setMenu:(NSMenu*)menu.GetHMenu()]; + + // In a pull down (but not pop up) buttons, items start with 1 and the + // 0-th one is used as title. + [v insertItemWithTitle:@"Press me to do it" atIndex:0]; + + // By default the control would disable the button title because it + // doesn't appear in the list of the menu items, prevent this from + // happening. + [v setAutoenablesItems:NO]; + + (void)Create(parent, wxID_ANY, v); + } +}; + +#else // some other platform + +// The sample should be updated if wxNativeCtrl is implemented for some new +// platform in wx/nativectrl.h. +#error "Native control creation not implemented for this platform" + +#endif // platforms + +// ---------------------------------------------------------------------------- +// NativeWidgetsPage +// ---------------------------------------------------------------------------- + +class NativeWidgetsPage : public WidgetsPage +{ +public: + NativeWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist); + + virtual wxWindow *GetWidget() const wxOVERRIDE { return m_nativeWindow; } + virtual void RecreateWidget() wxOVERRIDE; + + // lazy creation of the content + virtual void CreateContent() wxOVERRIDE; + +private: + void OnCheckExpand(wxCommandEvent& event); + + wxCheckBox* m_chkExpand; + + wxNativeWindow* m_nativeWindow; + wxSizer* m_sizerCtrl; + + DECLARE_WIDGETS_PAGE(NativeWidgetsPage) +}; + +// ============================================================================ +// implementation +// ============================================================================ + +IMPLEMENT_WIDGETS_PAGE(NativeWidgetsPage, wxS("Native"), NATIVE_CTRLS); + +NativeWidgetsPage::NativeWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist) + : WidgetsPage(book, imaglist, native_xpm) +{ + m_nativeWindow = NULL; +} + +void NativeWidgetsPage::CreateContent() +{ + wxSizer* const sizerTop = new wxBoxSizer(wxHORIZONTAL); + + wxSizer* const sizerLeft = new wxBoxSizer(wxVERTICAL); + m_chkExpand = new wxCheckBox(this, wxID_ANY, "&Expand to all available size"); + m_chkExpand->Bind(wxEVT_CHECKBOX, &NativeWidgetsPage::OnCheckExpand, this); + sizerLeft->Add(m_chkExpand, wxSizerFlags().Border()); + sizerTop->Add(sizerLeft); + + m_sizerCtrl = new wxBoxSizer(wxHORIZONTAL); + + RecreateWidget(); + + sizerTop->Add(m_sizerCtrl, wxSizerFlags(1).Expand()); + SetSizer(sizerTop); +} + +// ---------------------------------------------------------------------------- +// operations +// ---------------------------------------------------------------------------- + +void NativeWidgetsPage::RecreateWidget() +{ + delete m_nativeWindow; + m_nativeWindow = new NativeWindow(this); + + m_sizerCtrl->Clear(); + if ( m_chkExpand->IsChecked() ) + { + m_sizerCtrl->Add(m_nativeWindow, wxSizerFlags(1).Expand().Border()); + } + else + { + m_sizerCtrl->AddStretchSpacer(); + m_sizerCtrl->Add(m_nativeWindow, wxSizerFlags().Centre()); + m_sizerCtrl->AddStretchSpacer(); + } + + m_sizerCtrl->Layout(); +} + +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- + +void NativeWidgetsPage::OnCheckExpand(wxCommandEvent& WXUNUSED(event)) +{ + RecreateWidget(); +} + +#endif // wxHAS_NATIVE_WINDOW + +#endif // !OSX/Cocoa compilation as Objective C source file diff --git a/samples/widgets/native_wrapper.mm b/samples/widgets/native_wrapper.mm new file mode 100644 index 0000000000..56fa07ec0e --- /dev/null +++ b/samples/widgets/native_wrapper.mm @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////////////////////// +// Program: wxWidgets Widgets Sample +// Name: native_wrapper.mm +// Purpose: Helper to compile native.cpp as Objective C++ code +// Author: Vadim Zeitlin +// Created: 2015-08-02 +// Copyright: (c) 2015 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// As explained in widgets.bkl, we need to compile native.cpp using Objective +// C++ compiler, but there is no simple way to do it at the build system level, +// so we just include that file from this file, which has .mm extension +// ensuring that the correct compiler is used. +#include "native.cpp" diff --git a/samples/widgets/widgets.bkl b/samples/widgets/widgets.bkl index 8c722cfbf1..41dc5907e2 100644 --- a/samples/widgets/widgets.bkl +++ b/samples/widgets/widgets.bkl @@ -3,6 +3,23 @@ + + + + + + + native_wrapper.mm + + + activityindicator.cpp @@ -23,6 +40,8 @@ hyperlnk.cpp itemcontainer.cpp listbox.cpp + $(NATIVE_OBJCPP_SRC) + native.cpp notebook.cpp odcombobox.cpp radiobox.cpp diff --git a/samples/widgets/widgets_vc7.vcproj b/samples/widgets/widgets_vc7.vcproj index bfc565a52c..4e3099fe7c 100644 --- a/samples/widgets/widgets_vc7.vcproj +++ b/samples/widgets/widgets_vc7.vcproj @@ -337,6 +337,9 @@ + + diff --git a/samples/widgets/widgets_vc8.vcproj b/samples/widgets/widgets_vc8.vcproj index bc14353d8a..5c0f0ba2a4 100644 --- a/samples/widgets/widgets_vc8.vcproj +++ b/samples/widgets/widgets_vc8.vcproj @@ -878,6 +878,10 @@ RelativePath=".\listbox.cpp" > + + diff --git a/samples/widgets/widgets_vc9.vcproj b/samples/widgets/widgets_vc9.vcproj index 7d29fc0c2c..8d4d6aaee9 100644 --- a/samples/widgets/widgets_vc9.vcproj +++ b/samples/widgets/widgets_vc9.vcproj @@ -850,6 +850,10 @@ RelativePath=".\listbox.cpp" > + + diff --git a/src/gtk/nativewin.cpp b/src/gtk/nativewin.cpp index c40ed6d0d5..e0f5ad7a3e 100644 --- a/src/gtk/nativewin.cpp +++ b/src/gtk/nativewin.cpp @@ -38,6 +38,45 @@ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxNativeWindow +// ---------------------------------------------------------------------------- + +bool +wxNativeWindow::Create(wxWindow* parent, + wxWindowID winid, + wxNativeWindowHandle widget) +{ + wxCHECK_MSG( widget, false, wxS("Invalid null GtkWidget") ); + + // Standard wxGTK controls use PreCreation() but we never have any size + // specified at this stage, so don't bother with it. + if ( !CreateBase(parent, winid) ) + return false; + + // Add a reference to the widget to match g_object_unref() in wxWindow dtor + // (and by using the "_sink" version we avoid memory leaks when we're + // passed a newly allocated widget, as is typically the case). + m_widget = widget; + g_object_ref_sink(m_widget); + + parent->DoAddChild(this); + + PostCreation(); + + // Ensure that the best (and minimal) size is set to fully display the + // widget. + GtkRequisition req; + gtk_widget_size_request(widget, &req); + SetInitialSize(wxSize(req.width, req.height)); + + return true; +} + +// ---------------------------------------------------------------------------- +// wxNativeContainerWindow +// ---------------------------------------------------------------------------- + // TODO: we probably need equivalent code for other GDK platforms #ifdef GDK_WINDOWING_X11 diff --git a/src/msw/nativewin.cpp b/src/msw/nativewin.cpp index b84bb44372..c08d52a350 100644 --- a/src/msw/nativewin.cpp +++ b/src/msw/nativewin.cpp @@ -32,6 +32,57 @@ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxNativeWindow +// ---------------------------------------------------------------------------- + +bool +wxNativeWindow::Create(wxWindow* parent, + wxWindowID winid, + wxNativeWindowHandle hwnd) +{ + wxCHECK_MSG( hwnd, false, wxS("Invalid null HWND") ); + wxCHECK_MSG( parent, false, wxS("Must have a valid parent") ); + wxASSERT_MSG( ::GetParent(hwnd) == GetHwndOf(parent), + wxS("The native window has incorrect parent") ); + + const wxRect r = wxRectFromRECT(wxGetWindowRect(hwnd)); + + // Skip wxWindow::Create() which would try to create a new HWND, we don't + // want this as we already have one. + if ( !CreateBase(parent, winid, + r.GetPosition(), r.GetSize(), + 0, wxDefaultValidator, wxS("nativewindow")) ) + return false; + + parent->AddChild(this); + + SubclassWin(hwnd); + + if ( winid == wxID_ANY ) + { + // We allocated a new ID to the control, use it at Windows level as + // well because we assume that our and MSW IDs are the same in many + // places and it seems prudent to avoid breaking this assumption. + SetId(GetId()); + } + else // We used a fixed ID. + { + // For the same reason as above, check that it's the same as the one + // used by the native HWND. + wxASSERT_MSG( ::GetWindowLong(hwnd, GWL_ID) == winid, + wxS("Mismatch between wx and native IDs") ); + } + + InheritAttributes(); + + return true; +} + +// ---------------------------------------------------------------------------- +// wxNativeContainerWindow +// ---------------------------------------------------------------------------- + bool wxNativeContainerWindow::Create(wxNativeContainerWindowHandle hwnd) { if ( !::IsWindow(hwnd) ) diff --git a/src/osx/cocoa/nativewin.mm b/src/osx/cocoa/nativewin.mm new file mode 100644 index 0000000000..ca3c199a43 --- /dev/null +++ b/src/osx/cocoa/nativewin.mm @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/cocoa/nativewin.mm +// Purpose: wxNativeWindow implementation for wxOSX/Cocoa +// Author: Vadim Zeitlin +// Created: 2015-08-01 +// Copyright: (c) 2015 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/nativewin.h" + +#include "wx/osx/private.h" + +// ============================================================================ +// implementation +// ============================================================================ + +bool +wxNativeWindow::Create(wxWindow* parent, + wxWindowID winid, + wxNativeWindowHandle view) +{ + wxCHECK_MSG( view, false, wxS("NULL NSView pointer") ); + + DontCreatePeer(); + + if ( !wxWindow::Create(parent, winid) ) + return false; + + // We have to ensure that the internal label is synchronized with the label + // at the native window, otherwise calling SetLabel() later might not work + // and, even worse, the native label would be reset to match the (empty) wx + // label by SetPeer(). + // + // Notice that the selectors tested here are the same ones currently used + // by wxWidgetCocoaImpl::SetLabel() and this code would need to be updated + // if that method is. + // + // Also note the casts to "id" needed to suppress the "NSView may not + // respond to selector" warnings: we do test that it responds to them, so + // these warnings are not useful here. + if ( [view respondsToSelector:@selector(title)] ) + m_label = wxCFStringRef::AsString([(id)view title]); + else if ( [view respondsToSelector:@selector(stringValue)] ) + m_label = wxCFStringRef::AsString([(id)view stringValue]); + + SetPeer(new wxWidgetCocoaImpl(this, view)); + + // It doesn't seem necessary to use MacPostControlCreate() here as we never + // change the native control geometry here. + + return true; +}