diff --git a/include/wx/private/extfield.h b/include/wx/private/extfield.h new file mode 100644 index 0000000000..f180ab0b47 --- /dev/null +++ b/include/wx/private/extfield.h @@ -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 +// 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 +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 +M wxExternalField::ms_map; + +#endif // _WX_PRIVATE_EXTFIELD_H_ diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index ae28a12e2e..cc89d8ef92 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -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 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)