int m_scrollOffsetX;
int m_buttonHeight;
+ bool m_vetoColumnDrag;
bool m_delayedUpdate;
wxImageList *m_imageList;
const wxSize &size = wxDefaultSize,
const wxString &name = wxT("wxdataviewctrlmainwindow") );
virtual ~wxDataViewMainWindow();
-
+
bool IsVirtualList() const { return m_root == NULL; }
// notifications from wxDataViewModel
}
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();
}
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,
// 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;
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());
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,
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();
-
- unsigned int cols = GetOwner()->GetColumnCount();
- unsigned int col;
- int height = m_lineHeight;
- for (col = 0; col < cols; col++)
- {
+ 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)
+ }
+
+ 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 );
- }
-
- start += height;
+ }
+
+
+ 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();
-
- 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)
+ }
+
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() );
{
if (!m_root)
{
- return wxDataViewItem( (void*) row );
+ return wxDataViewItem( wxUIntToPtr(row) );
}
else
{
wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) const
{
wxASSERT( !IsVirtualList() );
-
+
RowToTreeNodeJob job( row , -2, m_root );
Walker( m_root , job );
return job.GetResult();
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;
{
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;
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;
}