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
|
||||
|
||||
#include "wx/evtloop.h"
|
||||
#include "wx/hashmap.h"
|
||||
|
||||
#if wxUSE_CARET
|
||||
#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
|
||||
|
||||
class wxCocoaGesturesImpl;
|
||||
WX_DECLARE_HASH_MAP(wxWidgetCocoaImpl*, wxCocoaGesturesImpl*,
|
||||
wxPointerHash, wxPointerEqual,
|
||||
wxCocoaGesturesImplMap);
|
||||
|
||||
// Class containing data used for gestures support.
|
||||
class wxCocoaGesturesImpl
|
||||
{
|
||||
@@ -1602,58 +1596,11 @@ public:
|
||||
[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 TouchesMoved(NSEvent* event);
|
||||
void TouchesEnded(NSEvent* event);
|
||||
|
||||
private:
|
||||
static wxCocoaGesturesImplMap ms_map;
|
||||
|
||||
wxWindowMac* const m_win;
|
||||
NSView* const m_view;
|
||||
|
||||
@@ -1673,7 +1620,21 @@ private:
|
||||
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)
|
||||
{
|
||||
@@ -1875,7 +1836,7 @@ enum TrackedGestures
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesBegan(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||
gestures->TouchesBegan(event);
|
||||
}
|
||||
|
||||
@@ -1932,7 +1893,7 @@ void wxCocoaGesturesImpl::TouchesBegan(NSEvent* event)
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesMoved(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||
gestures->TouchesMoved(event);
|
||||
}
|
||||
|
||||
@@ -1988,7 +1949,7 @@ void wxCocoaGesturesImpl::TouchesMoved(NSEvent* event)
|
||||
|
||||
void wxWidgetCocoaImpl::TouchesEnded(WX_NSEvent event)
|
||||
{
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGesturesImpl::FromWindow(this) )
|
||||
if ( wxCocoaGesturesImpl* gestures = wxCocoaGestures::FromWindow(this) )
|
||||
gestures->TouchesEnded(event);
|
||||
}
|
||||
|
||||
@@ -2540,7 +2501,7 @@ wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
|
||||
CFRelease(m_osxView);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -3469,7 +3430,7 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
if ( eventsMask == wxTOUCH_NONE )
|
||||
{
|
||||
if ( wxCocoaGesturesImpl::EraseForWindow(this) )
|
||||
if ( wxCocoaGestures::EraseForWindow(this) )
|
||||
{
|
||||
[m_osxView setAcceptsTouchEvents:NO];
|
||||
}
|
||||
@@ -3477,7 +3438,7 @@ bool wxWidgetCocoaImpl::EnableTouchEvents(int eventsMask)
|
||||
}
|
||||
else // We do want to have gesture events.
|
||||
{
|
||||
wxCocoaGesturesImpl::StoreForWindow
|
||||
wxCocoaGestures::StoreForWindow
|
||||
(
|
||||
this,
|
||||
new wxCocoaGesturesImpl(this, m_osxView, eventsMask)
|
||||
|
Reference in New Issue
Block a user