+IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow, wxWindow)
+
+BEGIN_EVENT_TABLE(wxDataViewMainWindow,wxWindow)
+ EVT_PAINT (wxDataViewMainWindow::OnPaint)
+ EVT_MOUSE_EVENTS (wxDataViewMainWindow::OnMouse)
+ EVT_SET_FOCUS (wxDataViewMainWindow::OnSetFocus)
+ EVT_KILL_FOCUS (wxDataViewMainWindow::OnKillFocus)
+ EVT_CHAR (wxDataViewMainWindow::OnChar)
+END_EVENT_TABLE()
+
+wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID id,
+ const wxPoint &pos, const wxSize &size, const wxString &name ) :
+ wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE, name ),
+ m_selection( wxDataViewSelectionCmp )
+
+{
+ SetOwner( parent );
+
+ m_lastOnSame = false;
+ m_renameTimer = new wxDataViewRenameTimer( this );
+
+ // TODO: user better initial values/nothing selected
+ m_currentCol = NULL;
+ m_currentRow = 0;
+
+ m_lineHeight = wxMax( 17, GetCharHeight() + 2 ); // 17 = mini icon height + 1
+
+#if wxUSE_DRAG_AND_DROP
+ m_dragCount = 0;
+ m_dragStart = wxPoint(0,0);
+
+ m_dragEnabled = false;
+ m_dropEnabled = false;
+ m_dropHint = false;
+ m_dropHintLine = (unsigned int) -1;
+#endif // wxUSE_DRAG_AND_DROP
+
+ m_lineLastClicked = (unsigned int) -1;
+ m_lineBeforeLastClicked = (unsigned int) -1;
+ m_lineSelectSingleOnUp = (unsigned int) -1;
+
+ m_hasFocus = false;
+
+ SetBackgroundColour( *wxWHITE );
+
+ SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+
+ m_penRule = wxPen(GetRuleColour());
+
+ // compose a pen whichcan draw black lines
+ // TODO: maybe there is something system colour to use
+ m_penExpander = wxPen(wxColour(0,0,0));
+
+ m_root = new wxDataViewTreeNode( NULL );
+ m_root->SetHasChildren(true);
+
+ // Make m_count = -1 will cause the class recaculate the real displaying number of rows.
+ m_count = -1;
+ m_underMouse = NULL;
+ UpdateDisplay();
+}
+
+wxDataViewMainWindow::~wxDataViewMainWindow()
+{
+ DestroyTree();
+ delete m_renameTimer;
+}
+
+
+#if wxUSE_DRAG_AND_DROP
+bool wxDataViewMainWindow::EnableDragSource( const wxDataFormat &format )
+{
+ m_dragFormat = format;
+ m_dragEnabled = format != wxDF_INVALID;
+
+ return true;
+}
+
+bool wxDataViewMainWindow::EnableDropTarget( const wxDataFormat &format )
+{
+ m_dropFormat = format;
+ m_dropEnabled = format != wxDF_INVALID;
+
+ if (m_dropEnabled)
+ SetDropTarget( new wxDataViewDropTarget( new wxCustomDataObject( format ), this ) );
+
+ return true;
+}
+
+void wxDataViewMainWindow::RemoveDropHint()
+{
+ if (m_dropHint)
+ {
+ m_dropHint = false;
+ RefreshRow( m_dropHintLine );
+ m_dropHintLine = (unsigned int) -1;
+ }
+}
+
+wxDragResult wxDataViewMainWindow::OnDragOver( wxDataFormat format, wxCoord x,
+ wxCoord y, wxDragResult def )
+{
+ int xx = x;
+ int yy = y;
+ m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+ unsigned int row = GetLineAt( yy );
+
+ if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
+ {
+ RemoveDropHint();
+ return wxDragNone;
+ }
+
+ wxDataViewItem item = GetItemByRow( row );
+
+ wxDataViewModel *model = GetOwner()->GetModel();
+
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetItem( item );
+ event.SetModel( model );
+ event.SetDataFormat( format );
+ if (!m_owner->HandleWindowEvent( event ))
+ {
+ RemoveDropHint();
+ return wxDragNone;
+ }
+
+ if (!event.IsAllowed())
+ {
+ RemoveDropHint();
+ return wxDragNone;
+ }
+
+
+ if (m_dropHint && (row != m_dropHintLine))
+ RefreshRow( m_dropHintLine );
+ m_dropHint = true;
+ m_dropHintLine = row;
+ RefreshRow( row );
+
+ return def;
+}
+
+bool wxDataViewMainWindow::OnDrop( wxDataFormat format, wxCoord x, wxCoord y )
+{
+ RemoveDropHint();
+
+ int xx = x;
+ int yy = y;
+ m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+ unsigned int row = GetLineAt( yy );
+
+ if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
+ return false;
+
+ wxDataViewItem item = GetItemByRow( row );
+
+ wxDataViewModel *model = GetOwner()->GetModel();
+
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetItem( item );
+ event.SetModel( model );
+ event.SetDataFormat( format );
+ if (!m_owner->HandleWindowEvent( event ))
+ return false;
+
+ if (!event.IsAllowed())
+ return false;
+
+ return true;
+}
+
+wxDragResult wxDataViewMainWindow::OnData( wxDataFormat format, wxCoord x, wxCoord y,
+ wxDragResult def )
+{
+ int xx = x;
+ int yy = y;
+ m_owner->CalcUnscrolledPosition( xx, yy, &xx, &yy );
+ unsigned int row = GetLineAt( yy );
+
+ if ((row >= GetRowCount()) || (xx > GetEndOfLastCol()))
+ return wxDragNone;
+
+ wxDataViewItem item = GetItemByRow( row );
+
+ wxDataViewModel *model = GetOwner()->GetModel();
+
+ wxCustomDataObject *obj = (wxCustomDataObject *) GetDropTarget()->GetDataObject();
+
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, m_owner->GetId() );
+ event.SetEventObject( m_owner );
+ event.SetItem( item );
+ event.SetModel( model );
+ event.SetDataFormat( format );
+ event.SetDataSize( obj->GetSize() );
+ event.SetDataBuffer( obj->GetData() );
+ if (!m_owner->HandleWindowEvent( event ))
+ return wxDragNone;
+
+ if (!event.IsAllowed())
+ return wxDragNone;
+
+ return def;
+}
+
+void wxDataViewMainWindow::OnLeave()
+{
+ RemoveDropHint();
+}
+
+wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent )
+{
+ int height = GetLineHeight( row );
+ int width = 0;
+ unsigned int cols = GetOwner()->GetColumnCount();
+ unsigned int col;
+ for (col = 0; col < cols; col++)
+ {
+ wxDataViewColumn *column = GetOwner()->GetColumnAt(col);
+ if (column->IsHidden())
+ continue; // skip it!
+ width += column->GetWidth();
+ }
+
+ indent = 0;
+ if (!IsList())
+ {
+ wxDataViewTreeNode *node = GetTreeNodeByRow(row);
+ indent = GetOwner()->GetIndent() * node->GetIndentLevel();
+ indent = indent + m_lineHeight;
+ // try to use the m_lineHeight as the expander space