Files
wxWidgets/src/common/datavcmn.cpp
Vadim Zeitlin d4cf50c8b2 Remove the item before notifying about it in wxDataViewIndexListModel.
Remove the item from the internal representation of the model before calling
ItemDeleted() callback so that the callback sees the model in a consistent
state.

This is more consistent with the other callbacks (e.g. ItemAdded()) and other
models (e.g. wxDataViewVirtualListModel) and should fix crashes in wxOSX
version of the control.

Closes #13753.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69990 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2011-12-12 13:08:46 +00:00

2525 lines
72 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/common/datavcmn.cpp
// Purpose: wxDataViewCtrl base classes and common parts
// Author: Robert Roebling
// Created: 2006/02/20
// RCS-ID: $Id$
// Copyright: (c) 2006, Robert Roebling
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_DATAVIEWCTRL
#include "wx/dataview.h"
#ifndef WX_PRECOMP
#include "wx/dc.h"
#include "wx/settings.h"
#include "wx/log.h"
#include "wx/crt.h"
#endif
#include "wx/datectrl.h"
#include "wx/spinctrl.h"
#include "wx/choice.h"
#include "wx/imaglist.h"
const char wxDataViewCtrlNameStr[] = "dataviewCtrl";
namespace
{
// Custom handler pushed on top of the edit control used by wxDataViewCtrl to
// forward some events to the main control itself.
class wxDataViewEditorCtrlEvtHandler: public wxEvtHandler
{
public:
wxDataViewEditorCtrlEvtHandler(wxWindow *editor, wxDataViewRenderer *owner)
{
m_editorCtrl = editor;
m_owner = owner;
m_finished = false;
}
void AcceptChangesAndFinish();
void SetFocusOnIdle( bool focus = true ) { m_focusOnIdle = focus; }
protected:
void OnChar( wxKeyEvent &event );
void OnTextEnter( wxCommandEvent &event );
void OnKillFocus( wxFocusEvent &event );
void OnIdle( wxIdleEvent &event );
private:
wxDataViewRenderer *m_owner;
wxWindow *m_editorCtrl;
bool m_finished;
bool m_focusOnIdle;
private:
DECLARE_EVENT_TABLE()
};
} // anonymous namespace
// ---------------------------------------------------------
// wxDataViewItemAttr
// ---------------------------------------------------------
wxFont wxDataViewItemAttr::GetEffectiveFont(const wxFont& font) const
{
if ( !HasFont() )
return font;
wxFont f(font);
if ( GetBold() )
f.MakeBold();
if ( GetItalic() )
f.MakeItalic();
return f;
}
// ---------------------------------------------------------
// wxDataViewModelNotifier
// ---------------------------------------------------------
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxDataViewModelNotifiers)
bool wxDataViewModelNotifier::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
{
size_t count = items.GetCount();
size_t i;
for (i = 0; i < count; i++)
if (!ItemAdded( parent, items[i] )) return false;
return true;
}
bool wxDataViewModelNotifier::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
{
size_t count = items.GetCount();
size_t i;
for (i = 0; i < count; i++)
if (!ItemDeleted( parent, items[i] )) return false;
return true;
}
bool wxDataViewModelNotifier::ItemsChanged( const wxDataViewItemArray &items )
{
size_t count = items.GetCount();
size_t i;
for (i = 0; i < count; i++)
if (!ItemChanged( items[i] )) return false;
return true;
}
// ---------------------------------------------------------
// wxDataViewModel
// ---------------------------------------------------------
wxDataViewModel::wxDataViewModel()
{
m_notifiers.DeleteContents( true );
}
bool wxDataViewModel::ItemAdded( const wxDataViewItem &parent, const wxDataViewItem &item )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemAdded( parent, item ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ItemDeleted( const wxDataViewItem &parent, const wxDataViewItem &item )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemDeleted( parent, item ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ItemChanged( const wxDataViewItem &item )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemChanged( item ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ItemsAdded( const wxDataViewItem &parent, const wxDataViewItemArray &items )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemsAdded( parent, items ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ItemsDeleted( const wxDataViewItem &parent, const wxDataViewItemArray &items )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemsDeleted( parent, items ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ItemsChanged( const wxDataViewItemArray &items )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ItemsChanged( items ))
ret = false;
}
return ret;
}
bool wxDataViewModel::ValueChanged( const wxDataViewItem &item, unsigned int col )
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->ValueChanged( item, col ))
ret = false;
}
return ret;
}
bool wxDataViewModel::Cleared()
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->Cleared())
ret = false;
}
return ret;
}
bool wxDataViewModel::BeforeReset()
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->BeforeReset())
ret = false;
}
return ret;
}
bool wxDataViewModel::AfterReset()
{
bool ret = true;
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
if (!notifier->AfterReset())
ret = false;
}
return ret;
}
void wxDataViewModel::Resort()
{
wxDataViewModelNotifiers::iterator iter;
for (iter = m_notifiers.begin(); iter != m_notifiers.end(); ++iter)
{
wxDataViewModelNotifier* notifier = *iter;
notifier->Resort();
}
}
void wxDataViewModel::AddNotifier( wxDataViewModelNotifier *notifier )
{
m_notifiers.push_back( notifier );
notifier->SetOwner( this );
}
void wxDataViewModel::RemoveNotifier( wxDataViewModelNotifier *notifier )
{
m_notifiers.DeleteObject( notifier );
}
int wxDataViewModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
unsigned int column, bool ascending ) const
{
// sort branches before leaves
bool item1_is_container = IsContainer(item1);
bool item2_is_container = IsContainer(item2);
if (item1_is_container && !item2_is_container)
return 1;
if (item2_is_container && !item1_is_container)
return -1;
wxVariant value1,value2;
GetValue( value1, item1, column );
GetValue( value2, item2, column );
if (!ascending)
{
wxVariant temp = value1;
value1 = value2;
value2 = temp;
}
if (value1.GetType() == wxT("string"))
{
wxString str1 = value1.GetString();
wxString str2 = value2.GetString();
int res = str1.Cmp( str2 );
if (res)
return res;
}
else if (value1.GetType() == wxT("long"))
{
long l1 = value1.GetLong();
long l2 = value2.GetLong();
long res = l1-l2;
if (res)
return res;
}
else if (value1.GetType() == wxT("double"))
{
double d1 = value1.GetDouble();
double d2 = value2.GetDouble();
if (d1 < d2)
return 1;
if (d1 > d2)
return -1;
}
else if (value1.GetType() == wxT("datetime"))
{
wxDateTime dt1 = value1.GetDateTime();
wxDateTime dt2 = value2.GetDateTime();
if (dt1.IsEarlierThan(dt2))
return 1;
if (dt2.IsEarlierThan(dt1))
return -1;
}
// items must be different
wxUIntPtr id1 = wxPtrToUInt(item1.GetID()),
id2 = wxPtrToUInt(item2.GetID());
return ascending ? id1 - id2 : id2 - id1;
}
// ---------------------------------------------------------
// wxDataViewIndexListModel
// ---------------------------------------------------------
static int my_sort( int *v1, int *v2 )
{
return *v2-*v1;
}
wxDataViewIndexListModel::wxDataViewIndexListModel( unsigned int initial_size )
{
// IDs are ordered until an item gets deleted or inserted
m_ordered = true;
// build initial index
unsigned int i;
for (i = 1; i < initial_size+1; i++)
m_hash.Add( wxDataViewItem(wxUIntToPtr(i)) );
m_nextFreeID = initial_size + 1;
}
void wxDataViewIndexListModel::Reset( unsigned int new_size )
{
/* wxDataViewModel:: */ BeforeReset();
m_hash.Clear();
// IDs are ordered until an item gets deleted or inserted
m_ordered = true;
// build initial index
unsigned int i;
for (i = 1; i < new_size+1; i++)
m_hash.Add( wxDataViewItem(wxUIntToPtr(i)) );
m_nextFreeID = new_size + 1;
/* wxDataViewModel:: */ AfterReset();
}
void wxDataViewIndexListModel::RowPrepended()
{
m_ordered = false;
unsigned int id = m_nextFreeID;
m_nextFreeID++;
wxDataViewItem item( wxUIntToPtr(id) );
m_hash.Insert( item, 0 );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewIndexListModel::RowInserted( unsigned int before )
{
m_ordered = false;
unsigned int id = m_nextFreeID;
m_nextFreeID++;
wxDataViewItem item( wxUIntToPtr(id) );
m_hash.Insert( item, before );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewIndexListModel::RowAppended()
{
unsigned int id = m_nextFreeID;
m_nextFreeID++;
wxDataViewItem item( wxUIntToPtr(id) );
m_hash.Add( item );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewIndexListModel::RowDeleted( unsigned int row )
{
m_ordered = false;
wxDataViewItem item( m_hash[row] );
m_hash.RemoveAt( row );
/* wxDataViewModel:: */ ItemDeleted( wxDataViewItem(0), item );
}
void wxDataViewIndexListModel::RowsDeleted( const wxArrayInt &rows )
{
m_ordered = false;
wxDataViewItemArray array;
unsigned int i;
for (i = 0; i < rows.GetCount(); i++)
{
wxDataViewItem item( m_hash[rows[i]] );
array.Add( item );
}
wxArrayInt sorted = rows;
sorted.Sort( my_sort );
for (i = 0; i < sorted.GetCount(); i++)
m_hash.RemoveAt( sorted[i] );
/* wxDataViewModel:: */ ItemsDeleted( wxDataViewItem(0), array );
}
void wxDataViewIndexListModel::RowChanged( unsigned int row )
{
/* wxDataViewModel:: */ ItemChanged( GetItem(row) );
}
void wxDataViewIndexListModel::RowValueChanged( unsigned int row, unsigned int col )
{
/* wxDataViewModel:: */ ValueChanged( GetItem(row), col );
}
unsigned int wxDataViewIndexListModel::GetRow( const wxDataViewItem &item ) const
{
if (m_ordered)
return wxPtrToUInt(item.GetID())-1;
// assert for not found
return (unsigned int) m_hash.Index( item );
}
wxDataViewItem wxDataViewIndexListModel::GetItem( unsigned int row ) const
{
wxASSERT( row < m_hash.GetCount() );
return wxDataViewItem( m_hash[row] );
}
bool wxDataViewIndexListModel::HasDefaultCompare() const
{
return !m_ordered;
}
int wxDataViewIndexListModel::Compare(const wxDataViewItem& item1,
const wxDataViewItem& item2,
unsigned int WXUNUSED(column),
bool ascending) const
{
if (m_ordered)
{
unsigned int pos1 = wxPtrToUInt(item1.GetID()); // -1 not needed here
unsigned int pos2 = wxPtrToUInt(item2.GetID()); // -1 not needed here
if (ascending)
return pos1 - pos2;
else
return pos2 - pos1;
}
if (ascending)
return GetRow(item1) - GetRow(item2);
return GetRow(item2) - GetRow(item1);
}
unsigned int wxDataViewIndexListModel::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
{
if (item.IsOk())
return 0;
children = m_hash;
return m_hash.GetCount();
}
// ---------------------------------------------------------
// wxDataViewVirtualListModel
// ---------------------------------------------------------
#ifndef __WXMAC__
wxDataViewVirtualListModel::wxDataViewVirtualListModel( unsigned int initial_size )
{
m_size = initial_size;
}
void wxDataViewVirtualListModel::Reset( unsigned int new_size )
{
/* wxDataViewModel:: */ BeforeReset();
m_size = new_size;
/* wxDataViewModel:: */ AfterReset();
}
void wxDataViewVirtualListModel::RowPrepended()
{
m_size++;
wxDataViewItem item( wxUIntToPtr(1) );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewVirtualListModel::RowInserted( unsigned int before )
{
m_size++;
wxDataViewItem item( wxUIntToPtr(before+1) );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewVirtualListModel::RowAppended()
{
m_size++;
wxDataViewItem item( wxUIntToPtr(m_size) );
ItemAdded( wxDataViewItem(0), item );
}
void wxDataViewVirtualListModel::RowDeleted( unsigned int row )
{
m_size--;
wxDataViewItem item( wxUIntToPtr(row+1) );
/* wxDataViewModel:: */ ItemDeleted( wxDataViewItem(0), item );
}
void wxDataViewVirtualListModel::RowsDeleted( const wxArrayInt &rows )
{
m_size -= rows.GetCount();
wxArrayInt sorted = rows;
sorted.Sort( my_sort );
wxDataViewItemArray array;
unsigned int i;
for (i = 0; i < sorted.GetCount(); i++)
{
wxDataViewItem item( wxUIntToPtr(sorted[i]+1) );
array.Add( item );
}
/* wxDataViewModel:: */ ItemsDeleted( wxDataViewItem(0), array );
}
void wxDataViewVirtualListModel::RowChanged( unsigned int row )
{
/* wxDataViewModel:: */ ItemChanged( GetItem(row) );
}
void wxDataViewVirtualListModel::RowValueChanged( unsigned int row, unsigned int col )
{
/* wxDataViewModel:: */ ValueChanged( GetItem(row), col );
}
unsigned int wxDataViewVirtualListModel::GetRow( const wxDataViewItem &item ) const
{
return wxPtrToUInt( item.GetID() ) -1;
}
wxDataViewItem wxDataViewVirtualListModel::GetItem( unsigned int row ) const
{
return wxDataViewItem( wxUIntToPtr(row+1) );
}
bool wxDataViewVirtualListModel::HasDefaultCompare() const
{
return true;
}
int wxDataViewVirtualListModel::Compare(const wxDataViewItem& item1,
const wxDataViewItem& item2,
unsigned int WXUNUSED(column),
bool ascending) const
{
unsigned int pos1 = wxPtrToUInt(item1.GetID()); // -1 not needed here
unsigned int pos2 = wxPtrToUInt(item2.GetID()); // -1 not needed here
if (ascending)
return pos1 - pos2;
else
return pos2 - pos1;
}
unsigned int wxDataViewVirtualListModel::GetChildren( const wxDataViewItem &WXUNUSED(item), wxDataViewItemArray &WXUNUSED(children) ) const
{
return 0; // should we report an error ?
}
#endif // __WXMAC__
//-----------------------------------------------------------------------------
// wxDataViewIconText
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxDataViewIconText,wxObject)
IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxDataViewIconText, WXDLLIMPEXP_ADV)
// ---------------------------------------------------------
// wxDataViewRendererBase
// ---------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxDataViewRendererBase, wxObject)
wxDataViewRendererBase::wxDataViewRendererBase( const wxString &varianttype,
wxDataViewCellMode WXUNUSED(mode),
int WXUNUSED(align) )
{
m_variantType = varianttype;
m_owner = NULL;
}
wxDataViewRendererBase::~wxDataViewRendererBase()
{
}
wxDataViewCtrl* wxDataViewRendererBase::GetView() const
{
return const_cast<wxDataViewRendererBase*>(this)->GetOwner()->GetOwner();
}
bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect labelRect )
{
wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
// Before doing anything we send an event asking if editing of this item is really wanted.
wxDataViewEvent start_event( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, dv_ctrl->GetId() );
start_event.SetDataViewColumn( GetOwner() );
start_event.SetModel( dv_ctrl->GetModel() );
start_event.SetItem( item );
start_event.SetEventObject( dv_ctrl );
dv_ctrl->GetEventHandler()->ProcessEvent( start_event );
if( !start_event.IsAllowed() )
return false;
m_item = item; // remember for later
unsigned int col = GetOwner()->GetModelColumn();
wxVariant value;
dv_ctrl->GetModel()->GetValue( value, item, col );
m_editorCtrl = CreateEditorCtrl( dv_ctrl->GetMainWindow(), labelRect, value );
// there might be no editor control for the given item
if(!m_editorCtrl)
return false;
wxDataViewEditorCtrlEvtHandler *handler =
new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, (wxDataViewRenderer*) this );
m_editorCtrl->PushEventHandler( handler );
#if defined(__WXGTK20__) && !defined(wxUSE_GENERICDATAVIEWCTRL)
handler->SetFocusOnIdle();
#else
m_editorCtrl->SetFocus();
#endif
// Now we should send Editing Started event
wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, dv_ctrl->GetId() );
event.SetDataViewColumn( GetOwner() );
event.SetModel( dv_ctrl->GetModel() );
event.SetItem( item );
event.SetEventObject( dv_ctrl );
dv_ctrl->GetEventHandler()->ProcessEvent( event );
return true;
}
void wxDataViewRendererBase::DestroyEditControl()
{
// Remove our event handler first to prevent it from (recursively) calling
// us again as it would do via a call to FinishEditing() when the editor
// loses focus when we hide it below.
wxEvtHandler * const handler = m_editorCtrl->PopEventHandler();
// Hide the control immediately but don't delete it yet as there could be
// some pending messages for it.
m_editorCtrl->Hide();
wxPendingDelete.Append(handler);
wxPendingDelete.Append(m_editorCtrl);
}
void wxDataViewRendererBase::CancelEditing()
{
if (!m_editorCtrl)
return;
DestroyEditControl();
}
bool wxDataViewRendererBase::FinishEditing()
{
if (!m_editorCtrl)
return true;
wxVariant value;
GetValueFromEditorCtrl( m_editorCtrl, value );
wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
DestroyEditControl();
dv_ctrl->GetMainWindow()->SetFocus();
bool isValid = Validate(value);
unsigned int col = GetOwner()->GetModelColumn();
// Now we should send Editing Done event
wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, dv_ctrl->GetId() );
event.SetDataViewColumn( GetOwner() );
event.SetModel( dv_ctrl->GetModel() );
event.SetItem( m_item );
event.SetValue( value );
event.SetColumn( col );
event.SetEditCanceled( !isValid );
event.SetEventObject( dv_ctrl );
dv_ctrl->GetEventHandler()->ProcessEvent( event );
if ( isValid && event.IsAllowed() )
{
dv_ctrl->GetModel()->ChangeValue(value, m_item, col);
return true;
}
return false;
}
void wxDataViewRendererBase::PrepareForItem(const wxDataViewModel *model,
const wxDataViewItem& item,
unsigned column)
{
wxVariant value;
model->GetValue(value, item, column);
SetValue(value);
wxDataViewItemAttr attr;
model->GetAttr(item, column, attr);
SetAttr(attr);
SetEnabled(model->IsEnabled(item, column));
}
// ----------------------------------------------------------------------------
// wxDataViewCustomRendererBase
// ----------------------------------------------------------------------------
bool wxDataViewCustomRendererBase::ActivateCell(const wxRect& cell,
wxDataViewModel *model,
const wxDataViewItem & item,
unsigned int col,
const wxMouseEvent* mouseEvent)
{
// Compatibility code
if ( mouseEvent )
return LeftClick(mouseEvent->GetPosition(), cell, model, item, col);
else
return Activate(cell, model, item, col);
}
void
wxDataViewCustomRendererBase::WXCallRender(wxRect rectCell, wxDC *dc, int state)
{
wxCHECK_RET( dc, "no DC to draw on in custom renderer?" );
// adjust the rectangle ourselves to account for the alignment
wxRect rectItem = rectCell;
const int align = GetAlignment();
if ( align != wxDVR_DEFAULT_ALIGNMENT )
{
const wxSize size = GetSize();
// take alignment into account only if there is enough space, otherwise
// show as much contents as possible
//
// notice that many existing renderers (e.g. wxDataViewSpinRenderer)
// return hard-coded size which can be more than they need and if we
// trusted their GetSize() we'd draw the text out of cell bounds
// entirely
if ( size.x >= 0 && size.x < rectCell.width )
{
if ( align & wxALIGN_CENTER_HORIZONTAL )
rectItem.x += (rectCell.width - size.x)/2;
else if ( align & wxALIGN_RIGHT )
rectItem.x += rectCell.width - size.x;
// else: wxALIGN_LEFT is the default
rectItem.width = size.x;
}
if ( size.y >= 0 && size.y < rectCell.height )
{
if ( align & wxALIGN_CENTER_VERTICAL )
rectItem.y += (rectCell.height - size.y)/2;
else if ( align & wxALIGN_BOTTOM )
rectItem.y += rectCell.height - size.y;
// else: wxALIGN_TOP is the default
rectItem.height = size.y;
}
}
// set up the DC attributes
// override custom foreground with the standard one for the selected items
// because we currently don't allow changing the selection background and
// custom colours may be unreadable on it
wxColour col;
if ( state & wxDATAVIEW_CELL_SELECTED )
col = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
else if ( m_attr.HasColour() )
col = m_attr.GetColour();
else // use default foreground
col = GetOwner()->GetOwner()->GetForegroundColour();
wxDCTextColourChanger changeFg(*dc, col);
wxDCFontChanger changeFont(*dc);
if ( m_attr.HasFont() )
changeFont.Set(m_attr.GetEffectiveFont(dc->GetFont()));
Render(rectItem, dc, state);
}
wxSize wxDataViewCustomRendererBase::GetTextExtent(const wxString& str) const
{
const wxDataViewCtrl *view = GetView();
if ( m_attr.HasFont() )
{
wxFont font(m_attr.GetEffectiveFont(view->GetFont()));
wxSize size;
view->GetTextExtent(str, &size.x, &size.y, NULL, NULL, &font);
return size;
}
else
{
return view->GetTextExtent(str);
}
}
void
wxDataViewCustomRendererBase::RenderText(const wxString& text,
int xoffset,
wxRect rect,
wxDC *dc,
int WXUNUSED(state))
{
wxRect rectText = rect;
rectText.x += xoffset;
rectText.width -= xoffset;
// check if we want to ellipsize the text if it doesn't fit
wxString ellipsizedText;
if ( GetEllipsizeMode() != wxELLIPSIZE_NONE )
{
ellipsizedText = wxControl::Ellipsize
(
text,
*dc,
GetEllipsizeMode(),
rectText.width,
wxELLIPSIZE_FLAGS_NONE
);
}
// get the alignment to use
int align = GetAlignment();
if ( align == wxDVR_DEFAULT_ALIGNMENT )
{
// if we don't have an explicit alignment ourselves, use that of the
// column in horizontal direction and default vertical alignment
align = GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
}
dc->DrawLabel(ellipsizedText.empty() ? text : ellipsizedText,
rectText, align);
}
//-----------------------------------------------------------------------------
// wxDataViewEditorCtrlEvtHandler
//-----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
EVT_CHAR (wxDataViewEditorCtrlEvtHandler::OnChar)
EVT_KILL_FOCUS (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
EVT_IDLE (wxDataViewEditorCtrlEvtHandler::OnIdle)
EVT_TEXT_ENTER (-1, wxDataViewEditorCtrlEvtHandler::OnTextEnter)
END_EVENT_TABLE()
void wxDataViewEditorCtrlEvtHandler::OnIdle( wxIdleEvent &event )
{
if (m_focusOnIdle)
{
m_focusOnIdle = false;
if (wxWindow::FindFocus() != m_editorCtrl)
m_editorCtrl->SetFocus();
}
event.Skip();
}
void wxDataViewEditorCtrlEvtHandler::OnTextEnter( wxCommandEvent &WXUNUSED(event) )
{
m_finished = true;
m_owner->FinishEditing();
}
void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
{
switch ( event.m_keyCode )
{
case WXK_RETURN:
m_finished = true;
m_owner->FinishEditing();
break;
case WXK_ESCAPE:
{
m_finished = true;
m_owner->CancelEditing();
break;
}
default:
event.Skip();
}
}
void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
{
if (!m_finished)
{
m_finished = true;
m_owner->FinishEditing();
}
event.Skip();
}
// ---------------------------------------------------------
// wxDataViewColumnBase
// ---------------------------------------------------------
void wxDataViewColumnBase::Init(wxDataViewRenderer *renderer,
unsigned int model_column)
{
m_renderer = renderer;
m_model_column = model_column;
m_owner = NULL;
m_renderer->SetOwner( (wxDataViewColumn*) this );
}
wxDataViewColumnBase::~wxDataViewColumnBase()
{
delete m_renderer;
}
// ---------------------------------------------------------
// wxDataViewCtrlBase
// ---------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(wxDataViewCtrlBase, wxControl)
wxDataViewCtrlBase::wxDataViewCtrlBase()
{
m_model = NULL;
m_expander_column = 0;
m_indent = 8;
}
wxDataViewCtrlBase::~wxDataViewCtrlBase()
{
if (m_model)
{
m_model->DecRef();
m_model = NULL;
}
}
bool wxDataViewCtrlBase::AssociateModel( wxDataViewModel *model )
{
if (m_model)
{
m_model->DecRef(); // discard old model, if any
}
// add our own reference to the new model:
m_model = model;
if (m_model)
{
m_model->IncRef();
}
return true;
}
wxDataViewModel* wxDataViewCtrlBase::GetModel()
{
return m_model;
}
const wxDataViewModel* wxDataViewCtrlBase::GetModel() const
{
return m_model;
}
void wxDataViewCtrlBase::ExpandAncestors( const wxDataViewItem & item )
{
if (!m_model) return;
if (!item.IsOk()) return;
wxVector<wxDataViewItem> parentChain;
// at first we get all the parents of the selected item
wxDataViewItem parent = m_model->GetParent(item);
while (parent.IsOk())
{
parentChain.push_back(parent);
parent = m_model->GetParent(parent);
}
// then we expand the parents, starting at the root
while (!parentChain.empty())
{
Expand(parentChain.back());
parentChain.pop_back();
}
}
wxDataViewItem wxDataViewCtrlBase::GetCurrentItem() const
{
return HasFlag(wxDV_MULTIPLE) ? DoGetCurrentItem()
: GetSelection();
}
void wxDataViewCtrlBase::SetCurrentItem(const wxDataViewItem& item)
{
wxCHECK_RET( item.IsOk(), "Can't make current an invalid item." );
if ( HasFlag(wxDV_MULTIPLE) )
DoSetCurrentItem(item);
else
Select(item);
}
wxDataViewItem wxDataViewCtrlBase::GetSelection() const
{
if ( GetSelectedItemsCount() != 1 )
return wxDataViewItem();
wxDataViewItemArray selections;
GetSelections(selections);
return selections[0];
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendTextColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewTextRenderer( wxT("string"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendIconTextColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendToggleColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewToggleRenderer( wxT("bool"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendProgressColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendDateColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewDateRenderer( wxT("datetime"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendBitmapColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendTextColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewTextRenderer( wxT("string"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendIconTextColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendToggleColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewToggleRenderer( wxT("bool"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendProgressColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendDateColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewDateRenderer( wxT("datetime"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::AppendBitmapColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
model_column, width, align, flags );
AppendColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependTextColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewTextRenderer( wxT("string"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependIconTextColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependToggleColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewToggleRenderer( wxT("bool"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependProgressColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependDateColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewDateRenderer( wxT("datetime"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependBitmapColumn( const wxString &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependTextColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewTextRenderer( wxT("string"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependIconTextColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependToggleColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewToggleRenderer( wxT("bool"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependProgressColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependDateColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewDateRenderer( wxT("datetime"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
wxDataViewColumn *
wxDataViewCtrlBase::PrependBitmapColumn( const wxBitmap &label, unsigned int model_column,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewBitmapRenderer( wxT("wxBitmap"), mode ),
model_column, width, align, flags );
PrependColumn( ret );
return ret;
}
bool
wxDataViewCtrlBase::AppendColumn( wxDataViewColumn *col )
{
col->SetOwner( (wxDataViewCtrl*) this );
return true;
}
bool
wxDataViewCtrlBase::PrependColumn( wxDataViewColumn *col )
{
col->SetOwner( (wxDataViewCtrl*) this );
return true;
}
bool
wxDataViewCtrlBase::InsertColumn( unsigned int WXUNUSED(pos), wxDataViewColumn *col )
{
col->SetOwner( (wxDataViewCtrl*) this );
return true;
}
// ---------------------------------------------------------
// wxDataViewEvent
// ---------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxDataViewEvent,wxNotifyEvent)
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_COLUMN_REORDERED, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_CACHE_HINT, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, wxDataViewEvent );
wxDEFINE_EVENT( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, wxDataViewEvent );
// -------------------------------------
// wxDataViewSpinRenderer
// -------------------------------------
wxDataViewSpinRenderer::wxDataViewSpinRenderer( int min, int max, wxDataViewCellMode mode, int alignment ) :
wxDataViewCustomRenderer(wxT("long"), mode, alignment )
{
m_min = min;
m_max = max;
}
wxWindow* wxDataViewSpinRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
{
long l = value;
wxSize size = labelRect.GetSize();
#ifdef __WXMAC__
size = wxSize( wxMax(70,labelRect.width ), -1 );
#endif
wxString str;
str.Printf( wxT("%d"), (int) l );
wxSpinCtrl *sc = new wxSpinCtrl( parent, wxID_ANY, str,
labelRect.GetTopLeft(), size, wxSP_ARROW_KEYS|wxTE_PROCESS_ENTER, m_min, m_max, l );
#ifdef __WXMAC__
size = sc->GetSize();
wxPoint pt = sc->GetPosition();
sc->SetSize( pt.x - 4, pt.y - 4, size.x, size.y );
#endif
return sc;
}
bool wxDataViewSpinRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
{
wxSpinCtrl *sc = (wxSpinCtrl*) editor;
long l = sc->GetValue();
value = l;
return true;
}
bool wxDataViewSpinRenderer::Render( wxRect rect, wxDC *dc, int state )
{
wxString str;
str.Printf(wxT("%d"), (int) m_data );
RenderText( str, 0, rect, dc, state );
return true;
}
wxSize wxDataViewSpinRenderer::GetSize() const
{
wxSize sz = GetTextExtent(wxString::Format("%d", (int)m_data));
// Allow some space for the spin buttons, which is approximately the size
// of a scrollbar (and getting pixel-exact value would be complicated).
// Also add some whitespace between the text and the button:
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
sz.x += GetTextExtent("M").x;
return sz;
}
bool wxDataViewSpinRenderer::SetValue( const wxVariant &value )
{
m_data = value.GetLong();
return true;
}
bool wxDataViewSpinRenderer::GetValue( wxVariant &value ) const
{
value = m_data;
return true;
}
// -------------------------------------
// wxDataViewChoiceRenderer
// -------------------------------------
#if defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXOSX_CARBON__)
wxDataViewChoiceRenderer::wxDataViewChoiceRenderer( const wxArrayString& choices, wxDataViewCellMode mode, int alignment ) :
wxDataViewCustomRenderer(wxT("string"), mode, alignment )
{
m_choices = choices;
}
wxWindow* wxDataViewChoiceRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
{
wxChoice* c = new wxChoice
(
parent,
wxID_ANY,
labelRect.GetTopLeft(),
wxSize(labelRect.GetWidth(), -1),
m_choices
);
c->Move(labelRect.GetRight() - c->GetRect().width, wxDefaultCoord);
c->SetStringSelection( value.GetString() );
return c;
}
bool wxDataViewChoiceRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
{
wxChoice *c = (wxChoice*) editor;
wxString s = c->GetStringSelection();
value = s;
return true;
}
bool wxDataViewChoiceRenderer::Render( wxRect rect, wxDC *dc, int state )
{
RenderText( m_data, 0, rect, dc, state );
return true;
}
wxSize wxDataViewChoiceRenderer::GetSize() const
{
wxSize sz;
for ( wxArrayString::const_iterator i = m_choices.begin(); i != m_choices.end(); ++i )
sz.IncTo(GetTextExtent(*i));
// Allow some space for the right-side button, which is approximately the
// size of a scrollbar (and getting pixel-exact value would be complicated).
// Also add some whitespace between the text and the button:
sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
sz.x += GetTextExtent("M").x;
return sz;
}
bool wxDataViewChoiceRenderer::SetValue( const wxVariant &value )
{
m_data = value.GetString();
return true;
}
bool wxDataViewChoiceRenderer::GetValue( wxVariant &value ) const
{
value = m_data;
return true;
}
// ----------------------------------------------------------------------------
// wxDataViewChoiceByIndexRenderer
// ----------------------------------------------------------------------------
wxDataViewChoiceByIndexRenderer::wxDataViewChoiceByIndexRenderer( const wxArrayString &choices,
wxDataViewCellMode mode, int alignment ) :
wxDataViewChoiceRenderer( choices, mode, alignment )
{
}
wxWindow* wxDataViewChoiceByIndexRenderer::CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
{
wxVariant string_value = GetChoice( value.GetLong() );
return wxDataViewChoiceRenderer::CreateEditorCtrl( parent, labelRect, string_value );
}
bool wxDataViewChoiceByIndexRenderer::GetValueFromEditorCtrl( wxWindow* editor, wxVariant &value )
{
wxVariant string_value;
if (!wxDataViewChoiceRenderer::GetValueFromEditorCtrl( editor, string_value ))
return false;
value = (long) GetChoices().Index( string_value.GetString() );
return true;
}
bool wxDataViewChoiceByIndexRenderer::SetValue( const wxVariant &value )
{
wxVariant string_value = GetChoice( value.GetLong() );
return wxDataViewChoiceRenderer::SetValue( string_value );
}
bool wxDataViewChoiceByIndexRenderer::GetValue( wxVariant &value ) const
{
wxVariant string_value;
if (!wxDataViewChoiceRenderer::GetValue( string_value ))
return false;
value = (long) GetChoices().Index( string_value.GetString() );
return true;
}
#endif
// ---------------------------------------------------------
// wxDataViewDateRenderer
// ---------------------------------------------------------
#if (defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXGTK__)) && wxUSE_DATEPICKCTRL
wxDataViewDateRenderer::wxDataViewDateRenderer(const wxString& varianttype,
wxDataViewCellMode mode, int align)
: wxDataViewCustomRenderer(varianttype, mode, align)
{
}
wxWindow *
wxDataViewDateRenderer::CreateEditorCtrl(wxWindow *parent, wxRect labelRect, const wxVariant& value)
{
return new wxDatePickerCtrl
(
parent,
wxID_ANY,
value.GetDateTime(),
labelRect.GetTopLeft(),
labelRect.GetSize()
);
}
bool wxDataViewDateRenderer::GetValueFromEditorCtrl(wxWindow *editor, wxVariant& value)
{
wxDatePickerCtrl *ctrl = static_cast<wxDatePickerCtrl*>(editor);
value = ctrl->GetValue();
return true;
}
bool wxDataViewDateRenderer::SetValue(const wxVariant& value)
{
m_date = value.GetDateTime();
return true;
}
bool wxDataViewDateRenderer::GetValue(wxVariant& value) const
{
value = m_date;
return true;
}
bool wxDataViewDateRenderer::Render(wxRect cell, wxDC* dc, int state)
{
wxString tmp = m_date.FormatDate();
RenderText( tmp, 0, cell, dc, state );
return true;
}
wxSize wxDataViewDateRenderer::GetSize() const
{
return GetTextExtent(m_date.FormatDate());
}
#endif // (defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXGTK__)) && wxUSE_DATEPICKCTRL
//-----------------------------------------------------------------------------
// wxDataViewListStore
//-----------------------------------------------------------------------------
wxDataViewListStore::wxDataViewListStore()
{
}
wxDataViewListStore::~wxDataViewListStore()
{
wxVector<wxDataViewListStoreLine*>::iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it)
{
wxDataViewListStoreLine* line = *it;
delete line;
}
}
void wxDataViewListStore::PrependColumn( const wxString &varianttype )
{
m_cols.Insert( varianttype, 0 );
}
void wxDataViewListStore::InsertColumn( unsigned int pos, const wxString &varianttype )
{
m_cols.Insert( varianttype, pos );
}
void wxDataViewListStore::AppendColumn( const wxString &varianttype )
{
m_cols.Add( varianttype );
}
unsigned int wxDataViewListStore::GetColumnCount() const
{
return m_cols.GetCount();
}
wxString wxDataViewListStore::GetColumnType( unsigned int pos ) const
{
return m_cols[pos];
}
void wxDataViewListStore::AppendItem( const wxVector<wxVariant> &values, wxClientData *data )
{
wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
line->m_values = values;
m_data.push_back( line );
RowAppended();
}
void wxDataViewListStore::PrependItem( const wxVector<wxVariant> &values, wxClientData *data )
{
wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
line->m_values = values;
m_data.insert( m_data.begin(), line );
RowPrepended();
}
void wxDataViewListStore::InsertItem( unsigned int row, const wxVector<wxVariant> &values,
wxClientData *data )
{
wxDataViewListStoreLine *line = new wxDataViewListStoreLine( data );
line->m_values = values;
m_data.insert( m_data.begin()+row, line );
RowInserted( row );
}
void wxDataViewListStore::DeleteItem( unsigned int row )
{
wxVector<wxDataViewListStoreLine*>::iterator it = m_data.begin() + row;
delete *it;
m_data.erase( it );
RowDeleted( row );
}
void wxDataViewListStore::DeleteAllItems()
{
wxVector<wxDataViewListStoreLine*>::iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it)
{
wxDataViewListStoreLine* line = *it;
delete line;
}
m_data.clear();
Reset( 0 );
}
void wxDataViewListStore::GetValueByRow( wxVariant &value, unsigned int row, unsigned int col ) const
{
wxDataViewListStoreLine *line = m_data[row];
value = line->m_values[col];
}
bool wxDataViewListStore::SetValueByRow( const wxVariant &value, unsigned int row, unsigned int col )
{
wxDataViewListStoreLine *line = m_data[row];
line->m_values[col] = value;
return true;
}
//-----------------------------------------------------------------------------
// wxDataViewListCtrl
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxDataViewListCtrl,wxDataViewCtrl)
BEGIN_EVENT_TABLE(wxDataViewListCtrl,wxDataViewCtrl)
EVT_SIZE( wxDataViewListCtrl::OnSize )
END_EVENT_TABLE()
wxDataViewListCtrl::wxDataViewListCtrl()
{
}
wxDataViewListCtrl::wxDataViewListCtrl( wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style,
const wxValidator& validator )
{
Create( parent, id, pos, size, style, validator );
}
wxDataViewListCtrl::~wxDataViewListCtrl()
{
}
bool wxDataViewListCtrl::Create( wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style,
const wxValidator& validator )
{
if ( !wxDataViewCtrl::Create( parent, id, pos, size, style, validator ) )
return false;
wxDataViewListStore *store = new wxDataViewListStore;
AssociateModel( store );
store->DecRef();
return true;
}
bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *column, const wxString &varianttype )
{
GetStore()->AppendColumn( varianttype );
return wxDataViewCtrl::AppendColumn( column );
}
bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *column, const wxString &varianttype )
{
GetStore()->PrependColumn( varianttype );
return wxDataViewCtrl::PrependColumn( column );
}
bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *column, const wxString &varianttype )
{
GetStore()->InsertColumn( pos, varianttype );
return wxDataViewCtrl::InsertColumn( pos, column );
}
bool wxDataViewListCtrl::PrependColumn( wxDataViewColumn *col )
{
return PrependColumn( col, "string" );
}
bool wxDataViewListCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
{
return InsertColumn( pos, col, "string" );
}
bool wxDataViewListCtrl::AppendColumn( wxDataViewColumn *col )
{
return AppendColumn( col, "string" );
}
wxDataViewColumn *wxDataViewListCtrl::AppendTextColumn( const wxString &label,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
GetStore()->AppendColumn( wxT("string") );
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewTextRenderer( wxT("string"), mode ),
GetStore()->GetColumnCount()-1, width, align, flags );
wxDataViewCtrl::AppendColumn( ret );
return ret;
}
wxDataViewColumn *wxDataViewListCtrl::AppendToggleColumn( const wxString &label,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
GetStore()->AppendColumn( wxT("bool") );
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewToggleRenderer( wxT("bool"), mode ),
GetStore()->GetColumnCount()-1, width, align, flags );
wxDataViewCtrl::AppendColumn( ret );
return ret;
}
wxDataViewColumn *wxDataViewListCtrl::AppendProgressColumn( const wxString &label,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
GetStore()->AppendColumn( wxT("long") );
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewProgressRenderer( wxEmptyString, wxT("long"), mode ),
GetStore()->GetColumnCount()-1, width, align, flags );
wxDataViewCtrl::AppendColumn( ret );
return ret;
}
wxDataViewColumn *wxDataViewListCtrl::AppendIconTextColumn( const wxString &label,
wxDataViewCellMode mode, int width, wxAlignment align, int flags )
{
GetStore()->AppendColumn( wxT("wxDataViewIconText") );
wxDataViewColumn *ret = new wxDataViewColumn( label,
new wxDataViewIconTextRenderer( wxT("wxDataViewIconText"), mode ),
GetStore()->GetColumnCount()-1, width, align, flags );
wxDataViewCtrl::AppendColumn( ret );
return ret;
}
void wxDataViewListCtrl::OnSize( wxSizeEvent &event )
{
event.Skip( true );
}
//-----------------------------------------------------------------------------
// wxDataViewTreeStore
//-----------------------------------------------------------------------------
wxDataViewTreeStoreNode::wxDataViewTreeStoreNode(
wxDataViewTreeStoreNode *parent,
const wxString &text, const wxIcon &icon, wxClientData *data )
{
m_parent = parent;
m_text = text;
m_icon = icon;
m_data = data;
}
wxDataViewTreeStoreNode::~wxDataViewTreeStoreNode()
{
if (m_data)
delete m_data;
}
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxDataViewTreeStoreNodeList)
wxDataViewTreeStoreContainerNode::wxDataViewTreeStoreContainerNode(
wxDataViewTreeStoreNode *parent, const wxString &text,
const wxIcon &icon, const wxIcon &expanded, wxClientData *data ) :
wxDataViewTreeStoreNode( parent, text, icon, data )
{
m_iconExpanded = expanded;
m_isExpanded = false;
m_children.DeleteContents(true);
}
wxDataViewTreeStoreContainerNode::~wxDataViewTreeStoreContainerNode()
{
}
//-----------------------------------------------------------------------------
wxDataViewTreeStore::wxDataViewTreeStore()
{
m_root = new wxDataViewTreeStoreContainerNode( NULL, wxEmptyString );
}
wxDataViewTreeStore::~wxDataViewTreeStore()
{
delete m_root;
}
wxDataViewItem wxDataViewTreeStore::AppendItem( const wxDataViewItem& parent,
const wxString &text, const wxIcon &icon, wxClientData *data )
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreNode *node =
new wxDataViewTreeStoreNode( parent_node, text, icon, data );
parent_node->GetChildren().Append( node );
return node->GetItem();
}
wxDataViewItem wxDataViewTreeStore::PrependItem( const wxDataViewItem& parent,
const wxString &text, const wxIcon &icon, wxClientData *data )
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreNode *node =
new wxDataViewTreeStoreNode( parent_node, text, icon, data );
parent_node->GetChildren().Insert( node );
return node->GetItem();
}
wxDataViewItem
wxDataViewTreeStore::InsertItem(const wxDataViewItem& parent,
const wxDataViewItem& previous,
const wxString& text,
const wxIcon& icon,
wxClientData *data)
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreNode *previous_node = FindNode( previous );
int pos = parent_node->GetChildren().IndexOf( previous_node );
if (pos == wxNOT_FOUND) return wxDataViewItem(0);
wxDataViewTreeStoreNode *node =
new wxDataViewTreeStoreNode( parent_node, text, icon, data );
parent_node->GetChildren().Insert( (size_t) pos, node );
return node->GetItem();
}
wxDataViewItem wxDataViewTreeStore::PrependContainer( const wxDataViewItem& parent,
const wxString &text, const wxIcon &icon, const wxIcon &expanded,
wxClientData *data )
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreContainerNode *node =
new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
parent_node->GetChildren().Insert( node );
return node->GetItem();
}
wxDataViewItem
wxDataViewTreeStore::AppendContainer(const wxDataViewItem& parent,
const wxString &text,
const wxIcon& icon,
const wxIcon& expanded,
wxClientData * data)
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreContainerNode *node =
new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
parent_node->GetChildren().Append( node );
return node->GetItem();
}
wxDataViewItem
wxDataViewTreeStore::InsertContainer(const wxDataViewItem& parent,
const wxDataViewItem& previous,
const wxString& text,
const wxIcon& icon,
const wxIcon& expanded,
wxClientData * data)
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreNode *previous_node = FindNode( previous );
int pos = parent_node->GetChildren().IndexOf( previous_node );
if (pos == wxNOT_FOUND) return wxDataViewItem(0);
wxDataViewTreeStoreContainerNode *node =
new wxDataViewTreeStoreContainerNode( parent_node, text, icon, expanded, data );
parent_node->GetChildren().Insert( (size_t) pos, node );
return node->GetItem();
}
bool wxDataViewTreeStore::IsContainer( const wxDataViewItem& item ) const
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return false;
return node->IsContainer();
}
wxDataViewItem wxDataViewTreeStore::GetNthChild( const wxDataViewItem& parent, unsigned int pos ) const
{
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent );
if (!parent_node) return wxDataViewItem(0);
wxDataViewTreeStoreNodeList::compatibility_iterator node = parent_node->GetChildren().Item( pos );
if (node)
return wxDataViewItem(node->GetData());
return wxDataViewItem(0);
}
int wxDataViewTreeStore::GetChildCount( const wxDataViewItem& parent ) const
{
wxDataViewTreeStoreNode *node = FindNode( parent );
if (!node) return -1;
if (!node->IsContainer())
return 0;
wxDataViewTreeStoreContainerNode *container_node = (wxDataViewTreeStoreContainerNode*) node;
return (int) container_node->GetChildren().GetCount();
}
void wxDataViewTreeStore::SetItemText( const wxDataViewItem& item, const wxString &text )
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return;
node->SetText( text );
}
wxString wxDataViewTreeStore::GetItemText( const wxDataViewItem& item ) const
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return wxEmptyString;
return node->GetText();
}
void wxDataViewTreeStore::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return;
node->SetIcon( icon );
}
const wxIcon &wxDataViewTreeStore::GetItemIcon( const wxDataViewItem& item ) const
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return wxNullIcon;
return node->GetIcon();
}
void wxDataViewTreeStore::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
{
wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
if (!node) return;
node->SetExpandedIcon( icon );
}
const wxIcon &wxDataViewTreeStore::GetItemExpandedIcon( const wxDataViewItem& item ) const
{
wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
if (!node) return wxNullIcon;
return node->GetExpandedIcon();
}
void wxDataViewTreeStore::SetItemData( const wxDataViewItem& item, wxClientData *data )
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return;
node->SetData( data );
}
wxClientData *wxDataViewTreeStore::GetItemData( const wxDataViewItem& item ) const
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return NULL;
return node->GetData();
}
void wxDataViewTreeStore::DeleteItem( const wxDataViewItem& item )
{
if (!item.IsOk()) return;
wxDataViewItem parent_item = GetParent( item );
wxDataViewTreeStoreContainerNode *parent_node = FindContainerNode( parent_item );
if (!parent_node) return;
wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
if (!node) return;
parent_node->GetChildren().DeleteObject( node );
}
void wxDataViewTreeStore::DeleteChildren( const wxDataViewItem& item )
{
wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
if (!node) return;
node->GetChildren().clear();
}
void wxDataViewTreeStore::DeleteAllItems()
{
DeleteChildren(wxDataViewItem(m_root));
}
void
wxDataViewTreeStore::GetValue(wxVariant &variant,
const wxDataViewItem &item,
unsigned int WXUNUSED(col)) const
{
// if (col != 0) return;
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return;
wxIcon icon( node->GetIcon());
if (node->IsContainer())
{
wxDataViewTreeStoreContainerNode *container = (wxDataViewTreeStoreContainerNode*) node;
if (container->IsExpanded() && container->GetExpandedIcon().IsOk())
icon = container->GetExpandedIcon();
}
wxDataViewIconText data( node->GetText(), icon );
variant << data;
}
bool
wxDataViewTreeStore::SetValue(const wxVariant& variant,
const wxDataViewItem& item,
unsigned int WXUNUSED(col))
{
// if (col != 0) return false;
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return false;
wxDataViewIconText data;
data << variant;
node->SetText( data.GetText() );
node->SetIcon( data.GetIcon() );
return true;
}
wxDataViewItem wxDataViewTreeStore::GetParent( const wxDataViewItem &item ) const
{
wxDataViewTreeStoreNode *node = FindNode( item );
if (!node) return wxDataViewItem(0);
wxDataViewTreeStoreNode *parent = node->GetParent();
if (!parent) return wxDataViewItem(0);
if (parent == m_root)
return wxDataViewItem(0);
return parent->GetItem();
}
unsigned int wxDataViewTreeStore::GetChildren( const wxDataViewItem &item, wxDataViewItemArray &children ) const
{
wxDataViewTreeStoreContainerNode *node = FindContainerNode( item );
if (!node) return 0;
wxDataViewTreeStoreNodeList::iterator iter;
for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
{
wxDataViewTreeStoreNode* child = *iter;
children.Add( child->GetItem() );
}
return node->GetChildren().GetCount();
}
int wxDataViewTreeStore::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
unsigned int WXUNUSED(column), bool WXUNUSED(ascending) ) const
{
wxDataViewTreeStoreNode *node1 = FindNode( item1 );
wxDataViewTreeStoreNode *node2 = FindNode( item2 );
if (!node1 || !node2)
return 0;
wxDataViewTreeStoreContainerNode* parent1 =
(wxDataViewTreeStoreContainerNode*) node1->GetParent();
wxDataViewTreeStoreContainerNode* parent2 =
(wxDataViewTreeStoreContainerNode*) node2->GetParent();
if (parent1 != parent2)
{
wxLogError( wxT("Comparing items with different parent.") );
return 0;
}
if (node1->IsContainer() && !node2->IsContainer())
return -1;
if (node2->IsContainer() && !node1->IsContainer())
return 1;
return parent1->GetChildren().IndexOf( node1 ) - parent2->GetChildren().IndexOf( node2 );
}
wxDataViewTreeStoreNode *wxDataViewTreeStore::FindNode( const wxDataViewItem &item ) const
{
if (!item.IsOk())
return m_root;
return (wxDataViewTreeStoreNode*) item.GetID();
}
wxDataViewTreeStoreContainerNode *wxDataViewTreeStore::FindContainerNode( const wxDataViewItem &item ) const
{
if (!item.IsOk())
return (wxDataViewTreeStoreContainerNode*) m_root;
wxDataViewTreeStoreNode* node = (wxDataViewTreeStoreNode*) item.GetID();
if (!node->IsContainer())
return NULL;
return (wxDataViewTreeStoreContainerNode*) node;
}
//-----------------------------------------------------------------------------
// wxDataViewTreeCtrl
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxDataViewTreeCtrl,wxDataViewCtrl)
BEGIN_EVENT_TABLE(wxDataViewTreeCtrl,wxDataViewCtrl)
EVT_DATAVIEW_ITEM_EXPANDED(-1, wxDataViewTreeCtrl::OnExpanded)
EVT_DATAVIEW_ITEM_COLLAPSED(-1, wxDataViewTreeCtrl::OnCollapsed)
EVT_SIZE( wxDataViewTreeCtrl::OnSize )
END_EVENT_TABLE()
bool wxDataViewTreeCtrl::Create( wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator )
{
if ( !wxDataViewCtrl::Create( parent, id, pos, size, style, validator ) )
return false;
// create the standard model and a column in the tree
wxDataViewTreeStore *store = new wxDataViewTreeStore;
AssociateModel( store );
store->DecRef();
AppendIconTextColumn
(
wxString(), // no label (header is not shown anyhow)
0, // the only model column
wxDATAVIEW_CELL_EDITABLE,
-1, // default width
wxALIGN_NOT, // and alignment
0 // not resizable
);
return true;
}
wxDataViewItem wxDataViewTreeCtrl::AppendItem( const wxDataViewItem& parent,
const wxString &text, int iconIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
AppendItem( parent, text, GetImage(iconIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
wxDataViewItem wxDataViewTreeCtrl::PrependItem( const wxDataViewItem& parent,
const wxString &text, int iconIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
PrependItem( parent, text, GetImage(iconIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
wxDataViewItem wxDataViewTreeCtrl::InsertItem( const wxDataViewItem& parent, const wxDataViewItem& previous,
const wxString &text, int iconIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
InsertItem( parent, previous, text, GetImage(iconIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
wxDataViewItem wxDataViewTreeCtrl::PrependContainer( const wxDataViewItem& parent,
const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
PrependContainer( parent, text,
GetImage(iconIndex), GetImage(expandedIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
wxDataViewItem wxDataViewTreeCtrl::AppendContainer( const wxDataViewItem& parent,
const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
AppendContainer( parent, text,
GetImage(iconIndex), GetImage(expandedIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
wxDataViewItem wxDataViewTreeCtrl::InsertContainer( const wxDataViewItem& parent, const wxDataViewItem& previous,
const wxString &text, int iconIndex, int expandedIndex, wxClientData *data )
{
wxDataViewItem res = GetStore()->
InsertContainer( parent, previous, text,
GetImage(iconIndex), GetImage(expandedIndex), data );
GetStore()->ItemAdded( parent, res );
return res;
}
void wxDataViewTreeCtrl::SetItemText( const wxDataViewItem& item, const wxString &text )
{
GetStore()->SetItemText(item,text);
// notify control
GetStore()->ValueChanged( item, 0 );
}
void wxDataViewTreeCtrl::SetItemIcon( const wxDataViewItem& item, const wxIcon &icon )
{
GetStore()->SetItemIcon(item,icon);
// notify control
GetStore()->ValueChanged( item, 0 );
}
void wxDataViewTreeCtrl::SetItemExpandedIcon( const wxDataViewItem& item, const wxIcon &icon )
{
GetStore()->SetItemExpandedIcon(item,icon);
// notify control
GetStore()->ValueChanged( item, 0 );
}
void wxDataViewTreeCtrl::DeleteItem( const wxDataViewItem& item )
{
wxDataViewItem parent_item = GetStore()->GetParent( item );
GetStore()->DeleteItem(item);
// notify control
GetStore()->ItemDeleted( parent_item, item );
}
void wxDataViewTreeCtrl::DeleteChildren( const wxDataViewItem& item )
{
wxDataViewTreeStoreContainerNode *node = GetStore()->FindContainerNode( item );
if (!node) return;
wxDataViewItemArray array;
wxDataViewTreeStoreNodeList::iterator iter;
for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++)
{
wxDataViewTreeStoreNode* child = *iter;
array.Add( child->GetItem() );
}
GetStore()->DeleteChildren( item );
// notify control
GetStore()->ItemsDeleted( item, array );
}
void wxDataViewTreeCtrl::DeleteAllItems()
{
GetStore()->DeleteAllItems();
GetStore()->Cleared();
}
void wxDataViewTreeCtrl::OnExpanded( wxDataViewEvent &event )
{
if (HasImageList()) return;
wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
if (!container) return;
container->SetExpanded( true );
GetStore()->ItemChanged( event.GetItem() );
}
void wxDataViewTreeCtrl::OnCollapsed( wxDataViewEvent &event )
{
if (HasImageList()) return;
wxDataViewTreeStoreContainerNode* container = GetStore()->FindContainerNode( event.GetItem() );
if (!container) return;
container->SetExpanded( false );
GetStore()->ItemChanged( event.GetItem() );
}
void wxDataViewTreeCtrl::OnSize( wxSizeEvent &event )
{
#if defined(wxUSE_GENERICDATAVIEWCTRL)
// automatically resize our only column to take the entire control width
if ( GetColumnCount() )
{
wxSize size = GetClientSize();
GetColumn(0)->SetWidth(size.x);
}
#endif
event.Skip( true );
}
#endif // wxUSE_DATAVIEWCTRL