]> git.saurik.com Git - wxWidgets.git/commitdiff
Use virtual functions to convert NSObject to the correct type in wxDVC.
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 23 Oct 2009 23:49:26 +0000 (23:49 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 23 Oct 2009 23:49:26 +0000 (23:49 +0000)
Instead of trying to determine the type of the value which should be extracted
from the NSObject we receive from NSOutlineView, just pass it to a virtual
method in the renderer which knows which type does it need.

This fixes the problem with editing boolean/checkbox columns and makes the
code more elegant.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62490 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/osx/dataview.h
src/osx/cocoa/dataview.mm

index 42df0c23c6704ae25a6277d9580d85fb15d279f7..3ed73d59654a309ab874aa8df235aaf59d085e15 100644 (file)
@@ -85,7 +85,7 @@ public:
 
 #if wxOSX_USE_COCOA
   // called when a value was edited by user
-  virtual void OSXOnCellChanged(const wxVariant& value,
+  virtual void OSXOnCellChanged(NSObject *value,
                                 const wxDataViewItem& item,
                                 unsigned col);
 #endif // Cocoa
@@ -197,7 +197,12 @@ public:
 //
   virtual bool MacRender();
 
-protected:
+#if wxOSX_USE_COCOA
+  virtual void OSXOnCellChanged(NSObject *value,
+                                const wxDataViewItem& item,
+                                unsigned col);
+#endif // Cocoa
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer)
 };
@@ -281,8 +286,7 @@ public:
   virtual bool MacRender();
 
 #if wxOSX_USE_COCOA
-  // called when a value was edited by user
-  virtual void OSXOnCellChanged(const wxVariant& value,
+  virtual void OSXOnCellChanged(NSObject *value,
                                 const wxDataViewItem& item,
                                 unsigned col);
 #endif // Cocoa
@@ -306,7 +310,12 @@ public:
 //
   virtual bool MacRender();
 
-protected:
+#if wxOSX_USE_COCOA
+  virtual void OSXOnCellChanged(NSObject *value,
+                                const wxDataViewItem& item,
+                                unsigned col);
+#endif // Cocoa
+
 private:
   DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewToggleRenderer)
 };
@@ -326,7 +335,12 @@ public:
 //
   virtual bool MacRender();
 
-protected:
+#if wxOSX_USE_COCOA
+  virtual void OSXOnCellChanged(NSObject *value,
+                                const wxDataViewItem& item,
+                                unsigned col);
+#endif // Cocoa
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewProgressRenderer)
 };
@@ -345,7 +359,12 @@ public:
 //
   virtual bool MacRender();
 
-protected:
+#if wxOSX_USE_COCOA
+  virtual void OSXOnCellChanged(NSObject *value,
+                                const wxDataViewItem& item,
+                                unsigned col);
+#endif // Cocoa
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewDateRenderer)
 };
index 1d63bdf4fa5a2602077295950d4f3eaccf83384e..8140fd610149460d29a3a437dce8180b61e8f403 100644 (file)
 namespace
 {
 
+// convert from NSObject to different C++ types: all these functions check
+// that the conversion really makes sense and assert if it doesn't
+wxString ObjectToString(NSObject *object)
+{
+    wxCHECK_MSG( [object isKindOfClass:[NSString class]], "",
+                 wxString::Format
+                 (
+                    "string expected but got %s",
+                    wxCFStringRef::AsString([object className])
+                 ));
+
+    return wxCFStringRef([((NSString*) object) retain]).AsString();
+}
+
+bool ObjectToBool(NSObject *object)
+{
+    // actually the value must be of NSCFBoolean class but it's private so we
+    // can't check for it directly
+    wxCHECK_MSG( [object isKindOfClass:[NSNumber class]], false,
+                 wxString::Format
+                 (
+                    "number expected but got %s",
+                    wxCFStringRef::AsString([object className])
+                 ));
+
+    return [(NSNumber *)object boolValue];
+}
+
+long ObjectToLong(NSObject *object)
+{
+    wxCHECK_MSG( [object isKindOfClass:[NSNumber class]], -1,
+                 wxString::Format
+                 (
+                    "number expected but got %s",
+                    wxCFStringRef::AsString([object className])
+                 ));
+
+    return [(NSNumber *)object longValue];
+}
+
+wxDateTime ObjectToDate(NSObject *object)
+{
+    wxCHECK_MSG( [object isKindOfClass:[NSDate class]], wxInvalidDateTime,
+                 wxString::Format
+                 (
+                    "date expected but got %s",
+                    wxCFStringRef::AsString([object className])
+                 ));
+
+    // get the number of seconds since 1970-01-01 UTC and this is the only
+    // way to convert a double to a wxLongLong
+    const wxLongLong seconds = [((NSDate*) object) timeIntervalSince1970];
+
+    wxDateTime dt(1, wxDateTime::Jan, 1970);
+    dt.Add(wxTimeSpan(0,0,seconds));
+
+    // the user has entered a date in the local timezone but seconds
+    // contains the number of seconds from date in the local timezone
+    // since 1970-01-01 UTC; therefore, the timezone information has to be
+    // transferred to wxWidgets, too:
+    dt.MakeFromTimezone(wxDateTime::UTC);
+
+    return dt;
+}
+
 NSInteger CompareItems(id item1, id item2, void* context)
 {
     NSArray* const sortDescriptors = (NSArray*) context;
@@ -516,31 +581,8 @@ outlineView:(NSOutlineView*)outlineView
 
     wxDataViewItem dataViewItem([((wxPointerObject*) item) pointer]);
 
-    wxVariant value;
-    if ( [object isKindOfClass:[NSString class]] )
-        value = wxCFStringRef([((NSString*) object) retain]).AsString();
-    else if ( [object isKindOfClass:[NSNumber class]] )
-        value = (long)[((NSNumber *)object) intValue];
-    else if ( [object isKindOfClass:[NSDate class]] )
-    {
-        // get the number of seconds since 1970-01-01 UTC and this is the only
-        // way to convert a double to a wxLongLong
-        const wxLongLong seconds = [((NSDate*) object) timeIntervalSince1970];
-
-        wxDateTime dt(1, wxDateTime::Jan, 1970);
-        dt.Add(wxTimeSpan(0,0,seconds));
-
-        // the user has entered a date in the local timezone but seconds
-        // contains the number of seconds from date in the local timezone
-        // since 1970-01-01 UTC; therefore, the timezone information has to be
-        // transferred to wxWidgets, too:
-        dt.MakeFromTimezone(wxDateTime::UTC);
-
-        value = dt;
-    }
-
     col->GetRenderer()->
-        OSXOnCellChanged(value, dataViewItem, col->GetModelColumn());
+        OSXOnCellChanged(object, dataViewItem, col->GetModelColumn());
 }
 
 -(void) outlineView:(NSOutlineView*)outlineView sortDescriptorsDidChange:(NSArray*)oldDescriptors
@@ -2231,10 +2273,35 @@ wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
     return GetNativeData()->GetEllipsizeMode();
 }
 
-void wxDataViewRenderer::OSXOnCellChanged(const wxVariant& value,
-                                          const wxDataViewItem& item,
-                                          unsigned col)
+void
+wxDataViewRenderer::OSXOnCellChanged(NSObject *object,
+                                     const wxDataViewItem& item,
+                                     unsigned col)
 {
+    // TODO: we probably should get rid of this code entirely and make this
+    //       function pure virtual, but currently we still have some native
+    //       renderers (wxDataViewChoiceRenderer) which don't override it and
+    //       there is also wxDataViewCustomRenderer for which it's not obvious
+    //       how it should be implemented so keep this "auto-deduction" of
+    //       variant type from NSObject for now
+
+    wxVariant value;
+    if ( [object isKindOfClass:[NSString class]] )
+        value = ObjectToString(object);
+    else if ( [object isKindOfClass:[NSNumber class]] )
+        value = ObjectToLong(object);
+    else if ( [object isKindOfClass:[NSDate class]] )
+        value = ObjectToDate(object);
+    else
+    {
+        wxFAIL_MSG( wxString::Format
+                    (
+                     "unknown value type %s",
+                     wxCFStringRef::AsString([object className])
+                    ));
+        return;
+    }
+
     wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
     model->ChangeValue(value, item, col);
 }
@@ -2293,6 +2360,15 @@ bool wxDataViewTextRenderer::MacRender()
     }
 }
 
+void
+wxDataViewTextRenderer::OSXOnCellChanged(NSObject *value,
+                                         const wxDataViewItem& item,
+                                         unsigned col)
+{
+    wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+    model->ChangeValue(ObjectToString(value), item, col);
+}
+
 IMPLEMENT_CLASS(wxDataViewTextRenderer,wxDataViewRenderer)
 
 // ---------------------------------------------------------
@@ -2434,6 +2510,15 @@ bool wxDataViewDateRenderer::MacRender()
     }
 }
 
+void
+wxDataViewDateRenderer::OSXOnCellChanged(NSObject *value,
+                                         const wxDataViewItem& item,
+                                         unsigned col)
+{
+    wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+    model->ChangeValue(ObjectToDate(value), item, col);
+}
+
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer,wxDataViewRenderer)
 
 // ---------------------------------------------------------
@@ -2476,17 +2561,15 @@ bool wxDataViewIconTextRenderer::MacRender()
 }
 
 void
-wxDataViewIconTextRenderer::OSXOnCellChanged(const wxVariant& value,
+wxDataViewIconTextRenderer::OSXOnCellChanged(NSObject *value,
                                              const wxDataViewItem& item,
                                              unsigned col)
 {
-    // we receive just the text (because it's the only component which can be
-    // edited by user) from the native control but we need wxDataViewIconText
-    // for the model, so construct it here
     wxVariant valueIconText;
-    valueIconText << wxDataViewIconText(value.GetString());
+    valueIconText << wxDataViewIconText(ObjectToString(value));
 
-    wxDataViewRenderer::OSXOnCellChanged(valueIconText, item, col);
+    wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+    model->ChangeValue(valueIconText, item, col);
 }
 
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
@@ -2524,6 +2607,15 @@ bool wxDataViewToggleRenderer::MacRender()
     }
 }
 
+void
+wxDataViewToggleRenderer::OSXOnCellChanged(NSObject *value,
+                                           const wxDataViewItem& item,
+                                           unsigned col)
+{
+    wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+    model->ChangeValue(ObjectToBool(value), item, col);
+}
+
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer,wxDataViewRenderer)
 
 // ---------------------------------------------------------
@@ -2558,6 +2650,15 @@ bool wxDataViewProgressRenderer::MacRender()
     }
 }
 
+void
+wxDataViewProgressRenderer::OSXOnCellChanged(NSObject *value,
+                                             const wxDataViewItem& item,
+                                             unsigned col)
+{
+    wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
+    model->ChangeValue(ObjectToLong(value), item, col);
+}
+
 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer,wxDataViewRenderer)
 
 // ---------------------------------------------------------