Add wxNativeWindow allowing to easily embed native widgets in wx.

Implement the class for wxMSW, wxGTK and wxOSX/Cocoa, show it in the widgets
sample and add documentation for it.
This commit is contained in:
Vadim Zeitlin
2015-08-03 17:47:09 +02:00
parent ce95913319
commit 9bc3ab1ea7
24 changed files with 757 additions and 7 deletions

View File

@@ -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

View File

@@ -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) )

View File

@@ -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 <vadim@wxwidgets.org>
// 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;
}