Rewrite handling cell value changes in wxOSX/Cocoa wxDVC.
Instead of using a chain of dynamic_cast<>s to find the right type of the value, construct a wxVariant corresponding to the type of the object we receive in NSOutlineView:setObjectValue:forTableColumn:byItem and pass it to a wxDataViewRenderer virtual function. This fixes assert and allows to edit icon text items under OS X. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62436 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
8e59cbe40c
commit
0599fe19d9
@ -82,6 +82,14 @@ public:
|
||||
|
||||
void SetNativeData(wxDataViewRendererNativeData* newNativeDataPtr);
|
||||
|
||||
|
||||
#if wxOSX_USE_COCOA
|
||||
// called when a value was edited by user
|
||||
virtual void OSXOnCellChanged(const wxVariant& value,
|
||||
const wxDataViewItem& item,
|
||||
unsigned col);
|
||||
#endif // Cocoa
|
||||
|
||||
private:
|
||||
//
|
||||
// variables
|
||||
@ -272,6 +280,13 @@ public:
|
||||
//
|
||||
virtual bool MacRender();
|
||||
|
||||
#if wxOSX_USE_COCOA
|
||||
// called when a value was edited by user
|
||||
virtual void OSXOnCellChanged(const wxVariant& value,
|
||||
const wxDataViewItem& item,
|
||||
unsigned col);
|
||||
#endif // Cocoa
|
||||
|
||||
protected:
|
||||
private:
|
||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewIconTextRenderer)
|
||||
|
@ -516,47 +516,31 @@ 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];
|
||||
|
||||
if (((dynamic_cast<wxDataViewTextRenderer*>(col->GetRenderer()) != NULL) || (dynamic_cast<wxDataViewIconTextRenderer*>(col->GetRenderer()) != NULL)) &&
|
||||
([object isKindOfClass:[NSString class]] == YES))
|
||||
{
|
||||
model->SetValue(wxVariant(wxCFStringRef([((NSString*) object) retain]).AsString()),dataViewItem,col->GetModelColumn()); // the string has to be retained before being passed to wxCFStringRef
|
||||
model->ValueChanged(dataViewItem,col->GetModelColumn());
|
||||
}
|
||||
else if (dynamic_cast<wxDataViewChoiceRenderer*>(col->GetRenderer()) != NULL)
|
||||
{
|
||||
if ([object isKindOfClass:[NSNumber class]] == YES)
|
||||
{
|
||||
model->SetValue(wxVariant(dynamic_cast<wxDataViewChoiceRenderer*>(col->GetRenderer())->GetChoice([((NSNumber*) object) intValue])),
|
||||
dataViewItem,col->GetModelColumn());
|
||||
model->ValueChanged(dataViewItem,col->GetModelColumn());
|
||||
}
|
||||
else if ([object isKindOfClass:[NSString class]] == YES) // do not know if this case can occur but initializing using strings works
|
||||
{
|
||||
model->SetValue(wxVariant(wxCFStringRef((NSString*) object).AsString()),dataViewItem,col->GetModelColumn());
|
||||
model->ValueChanged(dataViewItem,col->GetModelColumn());
|
||||
}
|
||||
}
|
||||
else if ((dynamic_cast<wxDataViewDateRenderer*>(col->GetRenderer()) != NULL) && ([object isKindOfClass:[NSDate class]] == YES))
|
||||
{
|
||||
wxDateTime wxDateTimeValue(1,wxDateTime::Jan,1970);
|
||||
wxDateTime dt(1, wxDateTime::Jan, 1970);
|
||||
dt.Add(wxTimeSpan(0,0,seconds));
|
||||
|
||||
wxLongLong 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);
|
||||
|
||||
seconds.Assign([((NSDate*) object) timeIntervalSince1970]); // get the number of seconds since 1970-01-01 UTC and this is
|
||||
// the only way to convert a double to a wxLongLong
|
||||
// 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:
|
||||
wxDateTimeValue.Add(wxTimeSpan(0,0,seconds));
|
||||
wxDateTimeValue.MakeFromTimezone(wxDateTime::UTC);
|
||||
model->SetValue(wxVariant(wxDateTimeValue),dataViewItem,col->GetModelColumn());
|
||||
model->ValueChanged(dataViewItem,col->GetModelColumn());
|
||||
}
|
||||
else if ((dynamic_cast<wxDataViewToggleRenderer*>(col->GetRenderer()) != NULL) && ([object isKindOfClass:[NSNumber class]] == YES))
|
||||
{
|
||||
model->SetValue(wxVariant((bool) [((NSNumber*) object) boolValue]),dataViewItem,col->GetModelColumn());
|
||||
model->ValueChanged(dataViewItem,col->GetModelColumn());
|
||||
value = dt;
|
||||
}
|
||||
|
||||
col->GetRenderer()->
|
||||
OSXOnCellChanged(value, dataViewItem, col->GetModelColumn());
|
||||
}
|
||||
|
||||
-(void) outlineView:(NSOutlineView*)outlineView sortDescriptorsDidChange:(NSArray*)oldDescriptors
|
||||
@ -2196,8 +2180,14 @@ void wxDataViewRendererNativeData::ApplyLineBreakMode(NSCell *cell)
|
||||
// ---------------------------------------------------------
|
||||
// wxDataViewRenderer
|
||||
// ---------------------------------------------------------
|
||||
wxDataViewRenderer::wxDataViewRenderer(const wxString& varianttype, wxDataViewCellMode mode, int align)
|
||||
:wxDataViewRendererBase(varianttype,mode,align), m_alignment(align), m_mode(mode), m_NativeDataPtr(NULL)
|
||||
|
||||
wxDataViewRenderer::wxDataViewRenderer(const wxString& varianttype,
|
||||
wxDataViewCellMode mode,
|
||||
int align)
|
||||
: wxDataViewRendererBase(varianttype, mode, align),
|
||||
m_alignment(align),
|
||||
m_mode(mode),
|
||||
m_NativeDataPtr(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -2241,6 +2231,15 @@ wxEllipsizeMode wxDataViewRenderer::GetEllipsizeMode() const
|
||||
return GetNativeData()->GetEllipsizeMode();
|
||||
}
|
||||
|
||||
void wxDataViewRenderer::OSXOnCellChanged(const wxVariant& value,
|
||||
const wxDataViewItem& item,
|
||||
unsigned col)
|
||||
{
|
||||
wxDataViewModel *model = GetOwner()->GetOwner()->GetModel();
|
||||
model->SetValue(value, item, col);
|
||||
model->ValueChanged(item, col);
|
||||
}
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer,wxDataViewRendererBase)
|
||||
|
||||
// ---------------------------------------------------------
|
||||
@ -2477,6 +2476,20 @@ bool wxDataViewIconTextRenderer::MacRender()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxDataViewIconTextRenderer::OSXOnCellChanged(const wxVariant& 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());
|
||||
|
||||
wxDataViewRenderer::OSXOnCellChanged(valueIconText, item, col);
|
||||
}
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxDataViewIconTextRenderer,wxDataViewRenderer)
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user