initial commit
Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
339
libs/wxWidgets-3.3.1/samples/widgets/native.cpp
Normal file
339
libs/wxWidgets-3.3.1/samples/widgets/native.cpp
Normal file
@@ -0,0 +1,339 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 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"
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
#ifndef BS_SPLITBUTTON
|
||||
#define BS_SPLITBUTTON 0x000c
|
||||
#endif // BS_SPLITBUTTON
|
||||
|
||||
#ifndef BCN_DROPDOWN
|
||||
#define BCN_DROPDOWN (-1248)
|
||||
#endif // defined(BCN_DROPDOWN)
|
||||
|
||||
// This duplicates the standard NMBCDROPDOWN struct which is not defined in
|
||||
// some old (up to at least 4.9.1) MinGW-w64 headers even though, annoyingly,
|
||||
// BCN_DROPDOWN is, so we can't even use as an indicator of whether the struct
|
||||
// is defined or not.
|
||||
struct wxNMBCDROPDOWN
|
||||
{
|
||||
NMHDR hdr;
|
||||
RECT rcButton;
|
||||
};
|
||||
|
||||
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, nullptr, nullptr
|
||||
);
|
||||
if ( !hwnd )
|
||||
{
|
||||
wxLogError("Creating split button failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
(void)Create(parent, wxID_ANY, hwnd);
|
||||
}
|
||||
|
||||
virtual ~NativeWindow()
|
||||
{
|
||||
// If you don't call this, you need to call DestroyWindow() later.
|
||||
//
|
||||
// Also notice that a HWND can't continue to exist under MSW if its
|
||||
// parent its destroyed, so you may also want to reparent it under some
|
||||
// other window if the parent of this window is also getting destroyed.
|
||||
Disown();
|
||||
}
|
||||
|
||||
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) override
|
||||
{
|
||||
const NMHDR* hdr = reinterpret_cast<NMHDR*>(lParam);
|
||||
if ( hdr->code != BCN_DROPDOWN )
|
||||
return wxNativeWindow::MSWOnNotify(idCtrl, lParam, result);
|
||||
|
||||
const wxNMBCDROPDOWN* dd = reinterpret_cast<wxNMBCDROPDOWN*>(lParam);
|
||||
|
||||
wxMenu menu;
|
||||
BuildTestMenu(&menu);
|
||||
PopupMenu(&menu, wxPoint(dd->rcButton.right, dd->rcButton.bottom));
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#elif defined(__WXGTK__)
|
||||
|
||||
// Avoid a bunch of warnings from gtk.h for some GTK+ versions.
|
||||
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
||||
wxGCC_WARNING_SUPPRESS(parentheses)
|
||||
#include <gtk/gtk.h>
|
||||
wxGCC_WARNING_RESTORE(parentheses)
|
||||
wxGCC_WARNING_RESTORE(deprecated-declarations)
|
||||
|
||||
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),
|
||||
"<b>Sorry</b>, but your GTK+ is too old to have menu buttons."
|
||||
);
|
||||
#endif // GTK+ 3.6/earlier
|
||||
|
||||
wxGCC_WARNING_SUPPRESS(ignored-qualifiers)
|
||||
g_object_ref_sink(widget);
|
||||
wxGCC_WARNING_RESTORE(ignored-qualifiers)
|
||||
|
||||
(void)Create(parent, wxID_ANY, widget);
|
||||
}
|
||||
|
||||
virtual ~NativeWindow()
|
||||
{
|
||||
// If you don't call this, you need to call g_object_unref() on the
|
||||
// widget yourself. The advantage of this is that you don't necessarily
|
||||
// have to do it right now and could keep using the native widget and
|
||||
// destroy it later. But if you don't need it any longer, as is the
|
||||
// case here, it's simpler to just call Disown() to let it be destroyed
|
||||
// immediately.
|
||||
Disown();
|
||||
}
|
||||
|
||||
private:
|
||||
wxMenu m_menu;
|
||||
};
|
||||
|
||||
#elif defined(__WXOSX_COCOA__)
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
virtual ~NativeWindow()
|
||||
{
|
||||
// If you don't call this, you need to call -release: on the button
|
||||
// manually (see the comment in wxGTK version above) if using manual
|
||||
// reference counting. If you build with ARC, you must *not* call
|
||||
// Disown() to let the native view be destroyed automatically.
|
||||
Disown();
|
||||
}
|
||||
};
|
||||
|
||||
#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, wxVector<wxBitmapBundle>& imaglist);
|
||||
|
||||
virtual wxWindow *GetWidget() const override { return m_nativeWindow; }
|
||||
virtual void RecreateWidget() override;
|
||||
|
||||
// lazy creation of the content
|
||||
virtual void CreateContent() override;
|
||||
|
||||
private:
|
||||
void OnCheckExpand(wxCommandEvent& event);
|
||||
|
||||
wxCheckBox* m_chkExpand;
|
||||
|
||||
wxNativeWindow* m_nativeWindow;
|
||||
wxSizer* m_sizerCtrl;
|
||||
|
||||
DECLARE_WIDGETS_PAGE(NativeWidgetsPage)
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
IMPLEMENT_WIDGETS_PAGE(NativeWidgetsPage, "Native", NATIVE_CTRLS);
|
||||
|
||||
NativeWidgetsPage::NativeWidgetsPage(WidgetsBookCtrl *book, wxVector<wxBitmapBundle>& imaglist)
|
||||
: WidgetsPage(book, imaglist, native_xpm)
|
||||
{
|
||||
m_nativeWindow = nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
NotifyWidgetRecreation(m_nativeWindow);
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user