Extract "external field" approach in a reusable class
Add wxExternalField<> template that can be used for other fields and/or in other ports too.
This commit is contained in:
84
include/wx/private/extfield.h
Normal file
84
include/wx/private/extfield.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: wx/private/extfield.h
|
||||||
|
// Purpose: Declare wxExternalField helper
|
||||||
|
// Author: Vadim Zeitlin
|
||||||
|
// Created: 2017-11-21
|
||||||
|
// Copyright: (c) 2017 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _WX_PRIVATE_EXTFIELD_H_
|
||||||
|
#define _WX_PRIVATE_EXTFIELD_H_
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxExternalField: store object data outside of it
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// This class allows to store some data without consuming space for the objects
|
||||||
|
// that don't need it and can be useful for avoiding to add rarely used fields
|
||||||
|
// to the classes that are used by many objects, e.g. wxWindow.
|
||||||
|
//
|
||||||
|
// Note that using this class costs in speed and convenience of access to the
|
||||||
|
// field, which requires a hash lookup instead of accessing it directly. It
|
||||||
|
// also only currently works for heap-allocated fields as it's probably never
|
||||||
|
// worth using it for fields of simple types.
|
||||||
|
//
|
||||||
|
// Template parameter Object is the class that "contains" the field, Field is
|
||||||
|
// the type of the field itself and FieldMap is the hash map, defined
|
||||||
|
// separately using WX_DECLARE_HASH_MAP(), with Object* as the key and Field*
|
||||||
|
// as the value type.
|
||||||
|
template <typename Object, typename Field, typename FieldMap>
|
||||||
|
class wxExternalField
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Object ObjectType;
|
||||||
|
typedef Field FieldType;
|
||||||
|
typedef FieldMap MapType;
|
||||||
|
|
||||||
|
// Store the field object to be used for the given object, replacing the
|
||||||
|
// existing one, if any.
|
||||||
|
//
|
||||||
|
// This method takes ownership of the field pointer which will be destroyed
|
||||||
|
// by EraseForWindow().
|
||||||
|
static void StoreForWindow(ObjectType* obj, FieldType* field)
|
||||||
|
{
|
||||||
|
const typename MapType::iterator it = ms_map.find(obj);
|
||||||
|
if ( it != ms_map.end() )
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
it->second = field;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ms_map.insert(typename MapType::value_type(obj, field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the object for the corresponding window.
|
||||||
|
static FieldType* FromWindow(ObjectType* obj)
|
||||||
|
{
|
||||||
|
const typename MapType::const_iterator it = ms_map.find(obj);
|
||||||
|
return it == ms_map.end() ? NULL : it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erase the object used for the corresponding window, return true if there
|
||||||
|
// was one or false otherwise.
|
||||||
|
static bool EraseForWindow(ObjectType* obj)
|
||||||
|
{
|
||||||
|
const typename MapType::iterator it = ms_map.find(obj);
|
||||||
|
if ( it == ms_map.end() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
delete it->second;
|
||||||
|
ms_map.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static FieldMap ms_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename O, typename F, typename M>
|
||||||
|
M wxExternalField<O, F, M>::ms_map;
|
||||||
|
|
||||||
|
#endif // _WX_PRIVATE_EXTFIELD_H_
|
@@ -24,7 +24,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/evtloop.h"
|
#include "wx/evtloop.h"
|
||||||
#include "wx/hashmap.h"
|
|
||||||
|
|
||||||
#if wxUSE_CARET
|
#if wxUSE_CARET
|
||||||
#include "wx/caret.h"
|
#include "wx/caret.h"
|
||||||
@@ -1502,11 +1501,6 @@ void wxWidgetCocoaImpl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
|
|||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||||
|
|
||||||
class wxCocoaGesturesImpl;
|
|
||||||
WX_DECLARE_HASH_MAP(wxWidgetCocoaImpl*, wxCocoaGesturesImpl*,
|
|
||||||
wxPointerHash, wxPointerEqual,
|
|
||||||
wxCocoaGesturesImplMap);
|
|
||||||
|
|
||||||
// Class containing data used for gestures support.
|
// Class containing data used for gestures support.
|
||||||
class wxCocoaGesturesImpl
|
class wxCocoaGesturesImpl
|
||||||
{
|
{
|
||||||
@@ -1602,58 +1596,11 @@ public:
|
|||||||
[m_initialTouch release];
|
[m_initialTouch release];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We keep all existing wxCocoaGesturesImpl objects in a
|
|
||||||
// wxWidgetCocoaImpl-indexed map. We do this instead of just having a data
|
|
||||||
// member containing wxCocoaGesturesImpl pointer in wxWidgetCocoaImpl
|
|
||||||
// itself because most windows don't need it and it seems wasteful to
|
|
||||||
// always increase their size unnecessarily.
|
|
||||||
|
|
||||||
// Store the object to be used for the given window, replacing the existing
|
|
||||||
// one, if any.
|
|
||||||
//
|
|
||||||
// This method takes ownership of wxCocoaGesturesImpl pointer which will be
|
|
||||||
// destroyed by EraseForWindow().
|
|
||||||
static void StoreForWindow(wxWidgetCocoaImpl* impl, wxCocoaGesturesImpl* obj)
|
|
||||||
{
|
|
||||||
const wxCocoaGesturesImplMap::iterator it = ms_map.find(impl);
|
|
||||||
if ( it != ms_map.end() )
|
|
||||||
{
|
|
||||||
delete it->second;
|
|
||||||
it->second = obj;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ms_map.insert(wxCocoaGesturesImplMap::value_type(impl, obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the object for the corresponding window.
|
|
||||||
static wxCocoaGesturesImpl* FromWindow(wxWidgetCocoaImpl* impl)
|
|
||||||
{
|
|
||||||
const wxCocoaGesturesImplMap::const_iterator it = ms_map.find(impl);
|
|
||||||
return it == ms_map.end() ? NULL : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Erase the object used for the corresponding window, return true if there
|
|
||||||
// was one or false otherwise.
|
|
||||||
static bool EraseForWindow(wxWidgetCocoaImpl* impl)
|
|
||||||
{
|
|
||||||
const wxCocoaGesturesImplMap::iterator it = ms_map.find(impl);
|
|
||||||
if ( it == ms_map.end() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
delete it->second;
|
|
||||||
ms_map.erase(it);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TouchesBegan(NSEvent* event);
|
void TouchesBegan(NSEvent* event);
|
||||||
void TouchesMoved(NSEvent* event);
|
void TouchesMoved(NSEvent* event);
|
||||||
void TouchesEnded(NSEvent* event);
|
void TouchesEnded(NSEvent* event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static wxCocoaGesturesImplMap ms_map;
|
|
||||||
|
|
||||||
wxWindowMac* const m_win;
|
wxWindowMac* const m_win;
|
||||||
NSView* const m_view;
|
NSView* const m_view;
|
||||||
|
|
||||||
@@ -1673,7 +1620,21 @@ private:
|
|||||||
wxDECLARE_NO_COPY_CLASS(wxCocoaGesturesImpl);
|
wxDECLARE_NO_COPY_CLASS(wxCocoaGesturesImpl);
|
||||||
};
|
};
|
||||||
|
|
||||||
wxCocoaGesturesImplMap wxCocoaGesturesImpl::ms_map;
|
// We keep all existing wxCocoaGesturesImpl objects in a
|
||||||
|
// wxWidgetCocoaImpl-indexed map. We do this instead of just having a data
|
||||||
|
// member containing wxCocoaGesturesImpl pointer in wxWidgetCocoaImpl
|
||||||
|
// itself because most windows don't need it and it seems wasteful to
|
||||||
|
// always increase their size unnecessarily.
|
||||||
|
|
||||||
|
#include "wx/hashmap.h"
|
||||||
|
WX_DECLARE_HASH_MAP(wxWidgetCocoaImpl*, wxCocoaGesturesImpl*,
|
||||||
|
wxPointerHash, wxPointerEqual,
|
||||||
|
wxCocoaGesturesImplMap);
|
||||||
|
|
||||||
|
#include "wx/private/extfield.h"
|
||||||
|
typedef wxExternalField<wxWidgetCocoaImpl,
|
||||||
|
wxCocoaGesturesImpl,
|
||||||
|
wxCocoaGesturesImplMap> wxCocoaGestures;
|
||||||
|
|
||||||
void wxWidgetCocoaImpl::PanGestureEvent(NSPanGestureRecognizer* panGestureRecognizer)
|
void wxWidgetCocoaImpl::PanGestureEvent(NSPanGestureRecognizer* panGestureRecognizer)
|
||||||
{
|
{
|
||||||
@@ -1875,7 +1836,7 @@ enum TrackedGestures
|
|||||||
|
|
||||||
void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event)
|
void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event)
|
||||||
{
|
{
|
||||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||||
gestures->TouchesBegan(event);
|
gestures->TouchesBegan(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1932,7 +1893,7 @@ void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event)
|
|||||||
|
|
||||||
void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event)
|
void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event)
|
||||||
{
|
{
|
||||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||||
gestures->TouchesMoved(event);
|
gestures->TouchesMoved(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1988,7 +1949,7 @@ void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event)
|
|||||||
|
|
||||||
void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event)
|
void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event)
|
||||||
{
|
{
|
||||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||||
gestures->TouchesEnded(event);
|
gestures->TouchesEnded(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2540,7 +2501,7 @@ wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
|||||||
CFRelease(m_osxView);
|
CFRelease(m_osxView);
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||||
wxCocoaGesturesImpl::EraseForWindow(this);
|
wxCocoaGestures::EraseForWindow(this);
|
||||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3469,7 +3430,7 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
|||||||
{
|
{
|
||||||
if ( eventsMask == wxTOUCH_NONE )
|
if ( eventsMask == wxTOUCH_NONE )
|
||||||
{
|
{
|
||||||
if ( wxCocoaGesturesImpl::EraseForWindow(this) )
|
if ( wxCocoaGestures::EraseForWindow(this) )
|
||||||
{
|
{
|
||||||
[m_osxView setAcceptsTouchEvents:NO];
|
[m_osxView setAcceptsTouchEvents:NO];
|
||||||
}
|
}
|
||||||
@@ -3477,7 +3438,7 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
|||||||
}
|
}
|
||||||
else // We do want to have gesture events.
|
else // We do want to have gesture events.
|
||||||
{
|
{
|
||||||
wxCocoaGesturesImpl::StoreForWindow
|
wxCocoaGestures::StoreForWindow
|
||||||
(
|
(
|
||||||
this,
|
this,
|
||||||
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
||||||
|
Reference in New Issue
Block a user