int m_scrollOffsetX;
int m_buttonHeight;
+ bool m_vetoColumnDrag;
bool m_delayedUpdate;
wxImageList *m_imageList;
unsigned int GetNodeNumber() const { return m_nodes.GetCount(); }
int GetIndentLevel() const
{
- int ret = 0 ;
+ int ret = 0;
const wxDataViewTreeNode * node = this;
while( node->GetParent()->GetParent() != NULL )
{
bool IsOpen() const
{
- return m_open ;
+ return m_open;
}
void ToggleOpen()
{
int len = m_nodes.GetCount();
int sum = 0;
- for ( int i = 0 ;i < len ; i ++)
+ for ( int i = 0;i < len; i ++)
sum += m_nodes[i]->GetSubTreeCount();
sum += m_leaves.GetCount();
void ChangeSubTreeCount( int num )
{
if( !m_open )
- return ;
+ return;
m_subTreeCount += num;
if( m_parent )
m_parent->ChangeSubTreeCount(num);
const wxSize &size = wxDefaultSize,
const wxString &name = wxT("wxdataviewctrlmainwindow") );
virtual ~wxDataViewMainWindow();
-
+
bool IsVirtualList() const { return m_root == NULL; }
// notifications from wxDataViewModel
unsigned int GetFirstVisibleRow() const;
//I change this method to un const because in the tree view, the displaying number of the tree are changing along with the expanding/collapsing of the tree nodes
unsigned int GetLastVisibleRow();
- unsigned int GetRowCount() ;
+ unsigned int GetRowCount();
wxDataViewItem GetSelection() const;
wxDataViewSelection GetSelections(){ return m_selection; }
}
wxRect GetLineRect( unsigned int row ) const;
-
+
int GetLineStart( unsigned int row ) const; // row * m_lineHeight in fixed mode
int GetLineHeight( unsigned int row ) const; // m_lineHeight in fixed mode
int GetLineAt( unsigned int y ) const; // y / m_lineHeight in fixed mode
//Some useful functions for row and item mapping
wxDataViewItem GetItemByRow( unsigned int row ) const;
int GetRowByItem( const wxDataViewItem & item ) const;
-
+
//Methods for building the mapping tree
void BuildTree( wxDataViewModel * model );
void DestroyTree();
//We did not need this temporarily
//wxDataViewTreeNode * GetTreeNodeByItem( const wxDataViewItem & item );
- int RecalculateCount() ;
+ int RecalculateCount();
wxDataViewEvent SendExpanderEvent( wxEventType type, const wxDataViewItem & item );
void OnExpanding( unsigned int row );
}
void wxDataViewRenderer::SetAlignment( int align )
-{
+{
m_align=align;
}
}
int wxDataViewRenderer::CalculateAlignment() const
-{
+{
if (m_align == wxDVR_DEFAULT_ALIGNMENT)
{
if (GetOwner() == NULL)
return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL;
-
+
return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
}
-
+
return m_align;
}
m_scrollOffsetX = 0;
m_delayedUpdate = false;
+ m_vetoColumnDrag = false;
m_buttonHeight = wxRendererNative::Get().GetHeaderButtonHeight( this );
int x = pos.x == wxDefaultCoord ? 0 : pos.x,
}
m_imageList = new wxImageList( 16, 16 );
- Header_SetImageList( (HWND) m_hWnd, m_imageList->GetHIMAGELIST() );
+ (void)Header_SetImageList((HWND) m_hWnd, m_imageList->GetHIMAGELIST());
// we need to subclass the m_hWnd to force wxWindow::HandleNotify
// to call wxDataViewHeaderWindow::MSWOnNotify
// remove old columns
for (int j=0, max=Header_GetItemCount((HWND)m_hWnd); j < max; j++)
Header_DeleteItem((HWND)m_hWnd, 0);
-
+
m_imageList->RemoveAll();
// add the updated array of columns to the header control
hdi.fmt = HDF_LEFT | HDF_STRING;
if (col->GetBitmap().IsOk())
hdi.fmt |= HDF_IMAGE;
-
+
//hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
if (col->IsSortable() && GetOwner()->GetSortingColumn() == col)
NMHEADER *nmHDR = (NMHEADER *)nmhdr;
switch ( nmhdr->code )
{
+ case NM_RELEASEDCAPTURE:
+ {
+ // user has released the mouse
+ m_vetoColumnDrag = false;
+ }
+ break;
+
case HDN_BEGINTRACK:
// user has started to resize a column:
// do we need to veto it?
break;
case HDN_BEGINDRAG:
- // user has started to reorder a column
- if ((nmHDR->iItem != -1) && (!GetColumn(nmHDR->iItem)->IsReorderable()))
+ // valid column
+ if (nmHDR->iItem != -1)
+ {
+ // user has started to reorder a valid column
+ if ((m_vetoColumnDrag == true) || (!GetColumn(nmHDR->iItem)->IsReorderable()))
+ {
+ // veto it!
+ *result = TRUE;
+ m_vetoColumnDrag = true;
+ }
+ }
+ else
{
// veto it!
- *result = TRUE;
+ m_vetoColumnDrag = true;
}
break;
m_root->SetHasChildren(true);
//Make m_count = -1 will cause the class recaculate the real displaying number of rows.
- m_count = -1 ;
+ m_count = -1;
m_underMouse = NULL;
UpdateDisplay();
}
cell_rect.x = x_start;
for (unsigned int i = col_start; i < col_last; i++)
{
-
+
wxDataViewColumn *col = GetOwner()->GetColumn( i );
wxDataViewRenderer *cell = col->GetRenderer();
cell_rect.width = col->GetWidth();
}
else
{
- dataitem = wxDataViewItem( (void*) item );
+ dataitem = wxDataViewItem( wxUIntToPtr(item) );
}
model->GetValue( value, dataitem, col->GetModelColumn());
// change the cell_rect.x to the appropriate pos
int expander_x = indent + EXPANDER_MARGIN;
int expander_y = cell_rect.y + EXPANDER_MARGIN + (GetLineHeight(item) / 2) - (expander_width/2) - EXPANDER_OFFSET;
- indent = indent + m_lineHeight ; //try to use the m_lineHeight as the expander space
+ indent = indent + m_lineHeight; //try to use the m_lineHeight as the expander space
dc.SetPen( m_penExpander );
dc.SetBrush( wxNullBrush );
if( node->HasChildren() )
{
// Yes, if the node does not have any child, it must be a leaf which
// mean that it is a temporarily created by GetTreeNodeByRow
- wxDELETE(node)
+ wxDELETE(node);
}
// cannot be bigger than allocated space
break;
xpos += c->GetWidth();
}
- wxRect labelRect( xpos,
+ wxRect labelRect( xpos,
GetLineStart( m_currentRow ),
- m_currentCol->GetWidth(),
+ m_currentCol->GetWidth(),
GetLineHeight( m_currentRow ) );
GetOwner()->CalcScrolledPosition( labelRect.x, labelRect.y,
class DoJob
{
public:
- DoJob(){};
- virtual ~DoJob(){};
+ DoJob() { }
+ virtual ~DoJob() { }
//The return value control how the tree-walker tranverse the tree
// 0: Job done, stop tranverse and return
// 1: Ignore the current node's subtree and continue
// 2: Job not done, continue
enum { OK = 0 , IGR = 1, CONT = 2 };
- virtual int operator() ( wxDataViewTreeNode * node ) = 0 ;
+ virtual int operator() ( wxDataViewTreeNode * node ) = 0;
virtual int operator() ( void * n ) = 0;
};
switch( func( node ) )
{
case DoJob::OK :
- return true ;
+ return true;
case DoJob::IGR:
return false;
case DoJob::CONT:
- default:
- ;
+ default:
+ ;
}
wxDataViewTreeNodes nodes = node->GetNodes();
int len = leaves.GetCount();
int i = 0, nodes_i = 0;
- for( ; i < len ; i ++ )
+ for(; i < len; i ++ )
{
void * n = leaves[i];
if( nodes_i < len_nodes && n == nodes[nodes_i]->GetItem().GetID() )
switch( func( n ) )
{
case DoJob::OK :
- return true ;
+ return true;
case DoJob::IGR:
continue;
case DoJob::CONT:
default:
- ;
+ ;
}
}
return false;
wxDataViewTreeNode * n = NULL;
wxDataViewTreeNodes nodes = node->GetNodes();
int len = nodes.GetCount();
- for( int i = 0 ; i < len; i ++)
+ for( int i = 0; i < len; i ++)
{
if( nodes[i]->GetItem() == item )
{
if (start > client_size.y) return;
wxRect rect( 0, start, client_size.x, client_size.y - start );
-
+
Refresh( true, &rect );
}
int wxDataViewMainWindow::GetLineStart( unsigned int row ) const
{
const wxDataViewModel *model = GetOwner()->GetModel();
-
+
if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
{
// TODO make more efficient
-
+
int start = 0;
-
+
unsigned int r;
for (r = 0; r < row; r++)
{
const wxDataViewTreeNode* node = GetTreeNodeByRow(r);
if (!node) return start;
-
+
wxDataViewItem item = node->GetItem();
-
+
if (node && !node->HasChildren())
{
// Yes, if the node does not have any child, it must be a leaf which
// mean that it is a temporarily created by GetTreeNodeByRow
- wxDELETE(node)
+ wxDELETE(node);
}
-
+
unsigned int cols = GetOwner()->GetColumnCount();
unsigned int col;
int height = m_lineHeight;
const wxDataViewColumn *column = GetOwner()->GetColumn(col);
if (column->IsHidden())
continue; // skip it!
-
+
if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
continue; // skip it!
-
+
const wxDataViewRenderer *renderer = column->GetRenderer();
wxVariant value;
model->GetValue( value, item, column->GetModelColumn() );
renderer2->SetValue( value );
height = wxMax( height, renderer->GetSize().y );
}
-
-
+
+
start += height;
}
-
+
return start;
}
else
{
const wxDataViewModel *model = GetOwner()->GetModel();
- if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
+ // check for the easy case first
+ if ( !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT) )
+ return y / m_lineHeight;
+
+ // TODO make more efficient
+ unsigned int row = 0;
+ unsigned int yy = 0;
+ for (;;)
{
- // TODO make more efficient
-
- unsigned int row = 0;
- unsigned int yy = 0;
- for (;;)
+ const wxDataViewTreeNode* node = GetTreeNodeByRow(row);
+ if (!node)
+ {
+ // not really correct...
+ return row + ((y-yy) / m_lineHeight);
+ }
+
+ wxDataViewItem item = node->GetItem();
+
+ if (node && !node->HasChildren())
{
- const wxDataViewTreeNode* node = GetTreeNodeByRow(row);
- if (!node)
- {
- // not really correct...
- return row + ((y-yy) / m_lineHeight);
- }
-
- wxDataViewItem item = node->GetItem();
-
- if (node && !node->HasChildren())
- {
- // Yes, if the node does not have any child, it must be a leaf which
- // mean that it is a temporarily created by GetTreeNodeByRow
- wxDELETE(node)
- }
-
- unsigned int cols = GetOwner()->GetColumnCount();
- unsigned int col;
- int height = m_lineHeight;
- for (col = 0; col < cols; col++)
- {
- const wxDataViewColumn *column = GetOwner()->GetColumn(col);
- if (column->IsHidden())
- continue; // skip it!
-
- if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
- continue; // skip it!
-
- const wxDataViewRenderer *renderer = column->GetRenderer();
- wxVariant value;
- model->GetValue( value, item, column->GetModelColumn() );
- wxDataViewRenderer *renderer2 = const_cast<wxDataViewRenderer*>(renderer);
- renderer2->SetValue( value );
- height = wxMax( height, renderer->GetSize().y );
- }
-
- yy += height;
- if (y < yy)
- return row;
-
- row++;
+ // Yes, if the node does not have any child, it must be a leaf which
+ // mean that it is a temporarily created by GetTreeNodeByRow
+ wxDELETE(node);
}
-
- return -1;
- }
- else
- {
- return y / m_lineHeight;
+
+ unsigned int cols = GetOwner()->GetColumnCount();
+ unsigned int col;
+ int height = m_lineHeight;
+ for (col = 0; col < cols; col++)
+ {
+ const wxDataViewColumn *column = GetOwner()->GetColumn(col);
+ if (column->IsHidden())
+ continue; // skip it!
+
+ if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
+ continue; // skip it!
+
+ const wxDataViewRenderer *renderer = column->GetRenderer();
+ wxVariant value;
+ model->GetValue( value, item, column->GetModelColumn() );
+ wxDataViewRenderer *renderer2 = const_cast<wxDataViewRenderer*>(renderer);
+ renderer2->SetValue( value );
+ height = wxMax( height, renderer->GetSize().y );
+ }
+
+ yy += height;
+ if (y < yy)
+ return row;
+
+ row++;
}
}
int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
{
const wxDataViewModel *model = GetOwner()->GetModel();
-
+
if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
{
wxASSERT( !IsVirtualList() );
-
+
const wxDataViewTreeNode* node = GetTreeNodeByRow(row);
// wxASSERT( node );
if (!node) return m_lineHeight;
wxDataViewItem item = node->GetItem();
-
+
if (node && !node->HasChildren())
{
// Yes, if the node does not have any child, it must be a leaf which
// mean that it is a temporarily created by GetTreeNodeByRow
- wxDELETE(node)
+ wxDELETE(node);
}
-
+
int height = m_lineHeight;
-
+
unsigned int cols = GetOwner()->GetColumnCount();
unsigned int col;
for (col = 0; col < cols; col++)
if ((col != 0) && model->IsContainer(item) && !model->HasContainerColumns(item))
continue; // skip it!
-
+
const wxDataViewRenderer *renderer = column->GetRenderer();
wxVariant value;
model->GetValue( value, item, column->GetModelColumn() );
class RowToItemJob: public DoJob
{
public:
- RowToItemJob( unsigned int row , int current ) { this->row = row; this->current = current ;}
- virtual ~RowToItemJob(){};
+ RowToItemJob( unsigned int row , int current ) { this->row = row; this->current = current;}
+ virtual ~RowToItemJob() { }
virtual int operator() ( wxDataViewTreeNode * node )
{
current ++;
if( current == static_cast<int>(row))
{
- ret = node->GetItem() ;
+ ret = node->GetItem();
return DoJob::OK;
}
current ++;
if( current == static_cast<int>(row))
{
- ret = wxDataViewItem( n ) ;
+ ret = wxDataViewItem( n );
return DoJob::OK;
}
return DoJob::CONT;
wxDataViewItem GetResult(){ return ret; }
private:
unsigned int row;
- int current ;
+ int current;
wxDataViewItem ret;
};
{
if (!m_root)
{
- return wxDataViewItem( (void*) row );
+ return wxDataViewItem( wxUIntToPtr(row) );
}
else
{
RowToTreeNodeJob( unsigned int row , int current, wxDataViewTreeNode * node )
{
this->row = row;
- this->current = current ;
- ret = NULL ;
+ this->current = current;
+ ret = NULL;
parent = node;
}
- virtual ~RowToTreeNodeJob(){};
+ virtual ~RowToTreeNodeJob(){ }
virtual int operator() ( wxDataViewTreeNode * node )
{
current ++;
if( current == static_cast<int>(row))
{
- ret = node ;
+ ret = node;
return DoJob::OK;
}
{
int index = static_cast<int>(row) - current - 1;
void * n = node->GetChildren().Item( index );
- ret = new wxDataViewTreeNode( parent ) ;
+ ret = new wxDataViewTreeNode( parent );
ret->SetItem( wxDataViewItem( n ));
ret->SetHasChildren(false);
return DoJob::OK;
current ++;
if( current == static_cast<int>(row))
{
- ret = new wxDataViewTreeNode( parent ) ;
+ ret = new wxDataViewTreeNode( parent );
ret->SetItem( wxDataViewItem( n ));
ret->SetHasChildren(false);
return DoJob::OK;
wxDataViewTreeNode * GetResult(){ return ret; }
private:
unsigned int row;
- int current ;
+ int current;
wxDataViewTreeNode * ret;
- wxDataViewTreeNode * parent ;
+ wxDataViewTreeNode * parent;
};
wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) const
{
wxASSERT( !IsVirtualList() );
-
+
RowToTreeNodeJob job( row , -2, m_root );
Walker( m_root , job );
return job.GetResult();
void wxDataViewMainWindow::OnExpanding( unsigned int row )
{
+ if (IsVirtualList())
+ return;
+
wxDataViewTreeNode * node = GetTreeNodeByRow(row);
if( node != NULL )
{
void wxDataViewMainWindow::OnCollapsing(unsigned int row)
{
+ if (IsVirtualList())
+ return;
+
wxDataViewTreeNode * node = GetTreeNodeByRow(row);
if( node != NULL )
{
node = node->GetParent();
if( node != NULL )
{
- int parent = GetRowByItem( node->GetItem() ) ;
+ int parent = GetRowByItem( node->GetItem() );
if( parent >= 0 )
{
SelectRow( row, false);
//Find the item along the parent-chain.
//This algorithm is designed to speed up the node-finding method
wxDataViewTreeNode * node = m_root;
- for( ItemList::const_iterator iter = list.begin(); iter !=list.end() ; iter++ )
+ for( ItemList::const_iterator iter = list.begin(); iter !=list.end(); iter++ )
{
if( node->HasChildren() )
{
wxDataViewTreeNodes nodes = node->GetNodes();
unsigned int i;
bool found = false;
-
+
for (i = 0; i < nodes.GetCount(); i ++)
{
if (nodes[i]->GetItem() == (**iter))
{
if (nodes[i]->GetItem() == item)
return nodes[i];
-
+
node = nodes[i];
found = true;
break;
class ItemToRowJob : public DoJob
{
public:
- ItemToRowJob(const wxDataViewItem & item, ItemList::const_iterator iter )
- { this->item = item ; ret = -1 ; m_iter = iter ; }
- virtual ~ItemToRowJob(){};
+ ItemToRowJob(const wxDataViewItem& item_, ItemList::const_iterator iter)
+ : m_iter(iter),
+ item(item_)
+ {
+ ret = -1;
+ }
//Maybe binary search will help to speed up this process
virtual int operator() ( wxDataViewTreeNode * node)
if( node->GetItem() == **m_iter )
{
- m_iter++ ;
+ m_iter++;
return DoJob::CONT;
}
else
return DoJob::CONT;
}
//the row number is begin from zero
- int GetResult(){ return ret -1 ; }
+ int GetResult() { return ret -1; }
+
private:
ItemList::const_iterator m_iter;
wxDataViewItem item;
static void BuildTreeHelper( wxDataViewModel * model, wxDataViewItem & item, wxDataViewTreeNode * node)
{
if( !model->IsContainer( item ) )
- return ;
+ return;
wxDataViewItemArray children;
unsigned int num = model->GetChildren( item, children);
{
wxDataViewTreeNode * n = new wxDataViewTreeNode( node );
n->SetItem(children[index]);
- n->SetHasChildren( true ) ;
+ n->SetHasChildren( true );
node->AddNode( n );
}
else
if (GetOwner()->GetModel()->IsVirtualListModel())
{
- m_count = -1 ;
+ m_count = -1;
return;
}
wxDataViewItem item;
SortPrepare();
BuildTreeHelper( model, item, m_root);
- m_count = -1 ;
+ m_count = -1;
}
static void DestroyTreeHelper( wxDataViewTreeNode * node )
if( node->GetNodeNumber() != 0 )
{
int len = node->GetNodeNumber();
- int i = 0 ;
+ int i = 0;
wxDataViewTreeNodes& nodes = node->GetNodes();
- for( ; i < len; i ++ )
+ for(; i < len; i ++ )
{
DestroyTreeHelper(nodes[i]);
}
{
int indent = node->GetIndentLevel();
indent = GetOwner()->GetIndent()*indent;
- wxRect rect( xpos + indent + EXPANDER_MARGIN,
+ wxRect rect( xpos + indent + EXPANDER_MARGIN,
GetLineStart( current ) + EXPANDER_MARGIN + (GetLineHeight(current)/2) - (m_lineHeight/2) - EXPANDER_OFFSET,
m_lineHeight-2*EXPANDER_MARGIN,
m_lineHeight-2*EXPANDER_MARGIN + EXPANDER_OFFSET);
{
int indent = node->GetIndentLevel();
indent = GetOwner()->GetIndent()*indent;
- wxRect rect( xpos + indent + EXPANDER_MARGIN,
+ wxRect rect( xpos + indent + EXPANDER_MARGIN,
GetLineStart( current ) + EXPANDER_MARGIN + (GetLineHeight(current)/2) - (m_lineHeight/2) - EXPANDER_OFFSET,
m_lineHeight-2*EXPANDER_MARGIN,
m_lineHeight-2*EXPANDER_MARGIN + EXPANDER_OFFSET);
-
+
if( rect.Contains( x, y) )
{
expander = true;
wxFAIL_MSG( _T("how did we get here?") );
}
}
-
+
if (m_currentRow != oldCurrentRow)
RefreshRow( oldCurrentRow );
if (m_notifier)
GetModel()->RemoveNotifier( m_notifier );
- wxDataViewColumnList::const_iterator iter;
- for (iter = m_cols.begin(); iter!=m_cols.end(); iter++)
- {
- delete *iter;
- }
+ m_cols.Clear();
}
void wxDataViewCtrl::Init()
{
+ m_cols.DeleteContents(true);
m_notifier = NULL;
}
{
if ( (style & wxBORDER_MASK) == 0)
style |= wxBORDER_SUNKEN;
-
+
if (!wxControl::Create( parent, id, pos, size,
style | wxScrolledWindowStyle, validator))
return false;
Init();
#ifdef __WXMAC__
- MacSetClipChildren( true ) ;
+ MacSetClipChildren( true );
#endif
m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
return true;
}
+bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
+{
+ if (!wxDataViewCtrlBase::InsertColumn(pos,col))
+ return false;
+
+ m_cols.Insert( pos, col );
+ OnColumnChange();
+ return true;
+}
+
void wxDataViewCtrl::OnColumnChange()
{
if (m_headerArea)
void wxDataViewCtrl::ColumnMoved( wxDataViewColumn* col, unsigned int new_pos )
{
if (new_pos > m_cols.GetCount()) return;
+
+ // Exchange position
+ m_cols.DeleteContents(false);
m_cols.DeleteObject( col );
m_cols.Insert( new_pos, col );
+ m_cols.DeleteContents(true);
m_clientArea->UpdateDisplay();
}
bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
{
- wxDataViewColumnList::compatibility_iterator ret = m_cols.Find( column );
+ wxDataViewColumnList::compatibility_iterator ret = m_cols.Find( column );
if (!ret)
return false;
m_cols.Erase(ret);
- delete column;
OnColumnChange();
return true;
bool wxDataViewCtrl::ClearColumns()
{
- m_cols.clear();
+ m_cols.Clear();
OnColumnChange();
return true;
}
void wxDataViewCtrl::SetSelections( const wxDataViewItemArray & sel )
{
- wxDataViewSelection selection(wxDataViewSelectionCmp) ;
+ wxDataViewSelection selection(wxDataViewSelectionCmp);
int len = sel.GetCount();
for( int i = 0; i < len; i ++ )
{
void wxDataViewCtrl::SetSelections( const wxArrayInt & sel )
{
- wxDataViewSelection selection(wxDataViewSelectionCmp) ;
+ wxDataViewSelection selection(wxDataViewSelectionCmp);
int len = sel.GetCount();
for( int i = 0; i < len; i ++ )
{