// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
#if wxUSE_DATAVIEWCTRL
#include "wx/dataview.h"
#ifdef wxUSE_GENERICDATAVIEWCTRL
#ifndef WX_PRECOMP
+ #ifdef __WXMSW__
+ #include "wx/msw/wrapwin.h"
+ #endif
#include "wx/sizer.h"
#include "wx/log.h"
+ #include "wx/dcclient.h"
+ #include "wx/timer.h"
+ #include "wx/settings.h"
#endif
#include "wx/stockitem.h"
-#include "wx/dcclient.h"
#include "wx/calctrl.h"
#include "wx/popupwin.h"
#include "wx/renderer.h"
-#include "wx/timer.h"
-
-#ifdef __WXMSW__
- #include "wx/msw/wrapwin.h"
-#endif
//-----------------------------------------------------------------------------
// classes
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
const wxString &name = wxT("wxdataviewctrlheaderwindow") );
- ~wxDataViewHeaderWindow();
+ virtual ~wxDataViewHeaderWindow();
void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; }
wxDataViewCtrl *GetOwner() { return m_owner; }
wxTextCtrl *m_text;
wxString m_startValue;
wxDataViewListModel *m_model;
- size_t m_col;
+ size_t m_col;
size_t m_row;
bool m_finished;
bool m_aboutToFinish;
// wxDataViewMainWindow
//-----------------------------------------------------------------------------
+WX_DEFINE_SORTED_ARRAY_SIZE_T( size_t, wxDataViewSelection );
+
class wxDataViewMainWindow: public wxWindow
{
public:
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
const wxString &name = wxT("wxdataviewctrlmainwindow") );
- ~wxDataViewMainWindow();
+ virtual ~wxDataViewMainWindow();
// notifications from wxDataViewListModel
bool RowAppended();
wxDataViewCtrl *GetOwner() { return m_owner; }
void OnPaint( wxPaintEvent &event );
+ void OnArrowChar(size_t newCurrent, const wxKeyEvent& event);
+ void OnChar( wxKeyEvent &event );
void OnMouse( wxMouseEvent &event );
void OnSetFocus( wxFocusEvent &event );
+ void OnKillFocus( wxFocusEvent &event );
void UpdateDisplay();
void RecalculateDisplay();
void FinishEditing( wxTextCtrl *text );
void ScrollWindow( int dx, int dy, const wxRect *rect );
+
+ bool HasCurrentRow() { return m_currentRow != (size_t)-1; }
+ void ChangeCurrentRow( size_t row );
+
+ bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE); };
+ bool IsEmpty() { return GetRowCount() == 0; }
+
+ int GetCountPerPage();
+ int GetEndOfLastCol();
+ size_t GetFirstVisibleRow();
+ size_t GetLastVisibleRow();
+ size_t GetRowCount();
+
+ void SelectAllRows( bool on );
+ void SelectRow( size_t row, bool on );
+ void SelectRows( size_t from, size_t to, bool on );
+ void ReverseRowSelection( size_t row );
+ bool IsRowSelected( size_t row );
+
+ void RefreshRow( size_t row );
+ void RefreshRows( size_t from, size_t to );
+ void RefreshRowsAfter( size_t firstRow );
+
private:
wxDataViewCtrl *m_owner;
int m_lineHeight;
bool m_dirty;
-
+
wxDataViewColumn *m_currentCol;
size_t m_currentRow;
-
+ wxDataViewSelection m_selection;
+
wxDataViewRenameTimer *m_renameTimer;
wxDataViewTextCtrlWrapper *m_textctrlWrapper;
bool m_lastOnSame;
+ bool m_hasFocus;
+
+ int m_dragCount;
+ wxPoint m_dragStart;
+
+ // for double click logic
+ size_t m_lineLastClicked,
+ m_lineBeforeLastClicked,
+ m_lineSelectSingleOnUp;
+
private:
DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow)
DECLARE_EVENT_TABLE()
{
m_toggle = value.GetBool();
- return true;;
+ return true;
}
bool wxDataViewToggleCell::GetValue( wxVariant &WXUNUSED(value) )
rect.width = 20;
rect.y = cell.y + cell.height/2 - 10;
rect.height = 20;
-
+
int flags = 0;
if (m_toggle)
flags |= wxCONTROL_CHECKED;
if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE)
flags |= wxCONTROL_DISABLED;
- wxRendererNative::Get().DrawCheckButton(
+ wxRendererNative::Get().DrawCheckBox(
GetOwner()->GetOwner(),
*dc,
rect,
sizer->Fit( this );
}
- virtual void OnDismiss()
- {
- }
-
void OnCalendar( wxCalendarEvent &event );
wxCalendarCtrl *m_cal;
size_t m_col;
size_t m_row;
+protected:
+ virtual void OnDismiss()
+ {
+ }
+
private:
DECLARE_EVENT_TABLE()
};
IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
-wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewCell *cell,
- size_t model_column, int flags ) :
+wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewCell *cell, size_t model_column,
+ int fixed_width, wxDataViewColumnSizing sizing, int flags ) :
wxDataViewColumnBase( title, cell, model_column, flags )
{
- m_width = 80;
+ m_sizing = sizing;
+
+ m_width = fixed_width;
+ m_fixedWidth = fixed_width;
}
wxDataViewColumn::~wxDataViewColumn()
}
+int wxDataViewColumn::GetWidth()
+{
+ return m_width;
+}
+
+void wxDataViewColumn::SetFixedWidth( int width )
+{
+ m_fixedWidth = width;
+
+ if (m_sizing == wxDATAVIEW_COL_WIDTH_FIXED)
+ {
+ m_width = width;
+ // Set dirty
+ }
+}
+
+int wxDataViewColumn::GetFixedWidth()
+{
+ return m_fixedWidth;
+}
+
//-----------------------------------------------------------------------------
// wxDataViewHeaderWindow
//-----------------------------------------------------------------------------
wxDataViewColumn *col = GetOwner()->GetColumn( i );
int width = col->GetWidth();
- // the width of the rect to draw: make it smaller to fit entirely
- // inside the column rect
-#ifdef __WXMAC__
int cw = width;
int ch = h;
-#else
- int cw = width - 2;
- int ch = h - 2;
-#endif
wxRendererNative::Get().DrawHeaderButton
(
this,
dc,
- wxRect(xpos, 0, cw, ch),
+ wxRect(xpos, 0, cw, ch-1),
m_parent->IsEnabled() ? 0
: (int)wxCONTROL_DISABLED
);
void wxDataViewHeaderWindow::OnSetFocus( wxFocusEvent &event )
{
+ GetParent()->SetFocus();
event.Skip();
}
m_model = model;
m_row = row;
m_col = col;
- m_text = text;
-
+ m_text = text;
+
m_finished = false;
m_aboutToFinish = false;
-
+
wxVariant value;
model->GetValue( value, col, row );
m_startValue = value.GetString();
-
+
m_owner->GetOwner()->CalcScrolledPosition(
rectLabel.x, rectLabel.y, &rectLabel.x, &rectLabel.y );
wxPoint(rectLabel.x-2,rectLabel.y-2),
wxSize(rectLabel.width+7,rectLabel.height+4) );
m_text->SetFocus();
-
+
m_text->PushEventHandler(this);
}
AcceptChanges();
//if ( !AcceptChanges() )
// m_owner->OnRenameCancelled( m_itemEdited );
-
+
Finish();
}
// wxDataViewMainWindow
//-----------------------------------------------------------------------------
+int LINKAGEMODE wxDataViewSelectionCmp( size_t row1, size_t row2 )
+{
+ if (row1 > row2) return 1;
+ if (row1 == row2) return 0;
+ return -1;
+}
+
+
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, 0, name )
+ wxWindow( parent, id, pos, size, wxWANTS_CHARS, name ),
+ m_selection( wxDataViewSelectionCmp )
+
{
SetOwner( parent );
m_lastOnSame = false;
m_renameTimer = new wxDataViewRenameTimer( this );
m_textctrlWrapper = NULL;
-
+
// TODO: user better initial values/nothing selected
m_currentCol = NULL;
m_currentRow = 0;
// TODO: we need to calculate this smartly
m_lineHeight = 20;
+ m_dragCount = 0;
+ m_dragStart = wxPoint(0,0);
+ m_lineLastClicked = (size_t) -1;
+ m_lineBeforeLastClicked = (size_t) -1;
+ m_lineSelectSingleOnUp = (size_t) -1;
+
+ m_hasFocus = false;
+
+ SetBackgroundColour( *wxWHITE );
+
UpdateDisplay();
}
wxClassInfo *textControlClass = CLASSINFO(wxTextCtrl);
wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject();
- m_textctrlWrapper = new wxDataViewTextCtrlWrapper(this, text, GetOwner()->GetModel(),
+ m_textctrlWrapper = new wxDataViewTextCtrlWrapper(this, text, GetOwner()->GetModel(),
m_currentCol->GetModelColumn(), m_currentRow, labelRect );
}
bool wxDataViewMainWindow::RowsReordered( size_t *WXUNUSED(new_order) )
{
Refresh();
-
+
return true;
}
wxDataViewListModel *model = GetOwner()->GetModel();
- size_t item_start = wxMax( 0, update.y / m_lineHeight );
- size_t item_count = wxMin( (update.height / m_lineHeight) + 1,
- (int)(model->GetNumberOfRows()-item_start) );
+ size_t item_start = wxMax( 0, (update.y / m_lineHeight) );
+ size_t item_count = wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
+ (int)(model->GetNumberOfRows()-item_start) );
+
+
+
+ size_t item;
+ for (item = item_start; item < item_start+item_count; item++)
+ {
+ if (m_selection.Index( item ) != wxNOT_FOUND)
+ {
+ int flags = wxCONTROL_SELECTED;
+ if (item == m_currentRow)
+ flags |= wxCONTROL_CURRENT;
+ if (m_hasFocus)
+ flags |= wxCONTROL_FOCUSED;
+ wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
+ wxRendererNative::Get().DrawItemSelectionRect
+ (
+ this,
+ dc,
+ rect,
+ flags
+ );
+ }
+ else
+ {
+ if (item == m_currentRow)
+ {
+ int flags = wxCONTROL_CURRENT;
+ if (m_hasFocus)
+ flags |= wxCONTROL_FOCUSED; // should have no effect
+ wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
+ wxRendererNative::Get().DrawItemSelectionRect
+ (
+ this,
+ dc,
+ rect,
+ flags
+ );
+
+ }
+ }
+ }
wxRect cell_rect;
cell_rect.x = 0;
wxDataViewCell *cell = col->GetCell();
cell_rect.width = col->GetWidth();
- size_t item;
for (item = item_start; item < item_start+item_count; item++)
{
cell_rect.y = item*m_lineHeight;
}
}
+int wxDataViewMainWindow::GetCountPerPage()
+{
+ wxSize size = GetClientSize();
+ return size.y / m_lineHeight;
+}
+
+int wxDataViewMainWindow::GetEndOfLastCol()
+{
+ int width = 0;
+ size_t i;
+ for (i = 0; i < GetOwner()->GetNumberOfColumns(); i++)
+ {
+ wxDataViewColumn *c = GetOwner()->GetColumn( i );
+ width += c->GetWidth();
+ }
+ return width;
+}
+
+size_t wxDataViewMainWindow::GetFirstVisibleRow()
+{
+ int x = 0;
+ int y = 0;
+ m_owner->CalcUnscrolledPosition( x, y, &x, &y );
+
+ return y / m_lineHeight;
+}
+
+size_t wxDataViewMainWindow::GetLastVisibleRow()
+{
+ wxSize client_size = GetClientSize();
+ m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, &client_size.x, &client_size.y );
+
+ return wxMin( GetRowCount()-1, ((unsigned)client_size.y/m_lineHeight)+1 );
+}
+
+size_t wxDataViewMainWindow::GetRowCount()
+{
+ return GetOwner()->GetModel()->GetNumberOfRows();
+}
+
+void wxDataViewMainWindow::ChangeCurrentRow( size_t row )
+{
+ m_currentRow = row;
+
+ // send event
+}
+
+void wxDataViewMainWindow::SelectAllRows( bool on )
+{
+ if (IsEmpty())
+ return;
+
+ if (on)
+ {
+ m_selection.Clear();
+ for (size_t i = 0; i < GetRowCount(); i++)
+ m_selection.Add( i );
+ Refresh();
+ }
+ else
+ {
+ size_t first_visible = GetFirstVisibleRow();
+ size_t last_visible = GetLastVisibleRow();
+ size_t i;
+ for (i = 0; i < m_selection.GetCount(); i++)
+ {
+ size_t row = m_selection[i];
+ if ((row >= first_visible) && (row <= last_visible))
+ RefreshRow( row );
+ }
+ m_selection.Clear();
+ }
+}
+
+void wxDataViewMainWindow::SelectRow( size_t row, bool on )
+{
+ if (m_selection.Index( row ) == wxNOT_FOUND)
+ {
+ if (on)
+ {
+ m_selection.Add( row );
+ RefreshRow( row );
+ }
+ }
+ else
+ {
+ if (!on)
+ {
+ m_selection.Remove( row );
+ RefreshRow( row );
+ }
+ }
+}
+
+void wxDataViewMainWindow::SelectRows( size_t from, size_t to, bool on )
+{
+ if (from > to)
+ {
+ size_t tmp = from;
+ from = to;
+ to = tmp;
+ }
+
+ size_t i;
+ for (i = from; i <= to; i++)
+ {
+ if (m_selection.Index( i ) == wxNOT_FOUND)
+ {
+ if (on)
+ m_selection.Add( i );
+ }
+ else
+ {
+ if (!on)
+ m_selection.Remove( i );
+ }
+ }
+ RefreshRows( from, to );
+}
+
+void wxDataViewMainWindow::ReverseRowSelection( size_t row )
+{
+ if (m_selection.Index( row ) == wxNOT_FOUND)
+ m_selection.Add( row );
+ else
+ m_selection.Remove( row );
+ RefreshRow( row );
+}
+
+bool wxDataViewMainWindow::IsRowSelected( size_t row )
+{
+ return (m_selection.Index( row ) != wxNOT_FOUND);
+}
+
+void wxDataViewMainWindow::RefreshRow( size_t row )
+{
+ wxRect rect( 0, row*m_lineHeight, GetEndOfLastCol(), m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::RefreshRows( size_t from, size_t to )
+{
+ if (from > to)
+ {
+ size_t tmp = to;
+ to = from;
+ from = tmp;
+ }
+
+ wxRect rect( 0, from*m_lineHeight, GetEndOfLastCol(), (to-from+1) * m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::RefreshRowsAfter( size_t firstRow )
+{
+ size_t count = GetRowCount();
+ if (firstRow > count)
+ return;
+
+ wxRect rect( 0, firstRow*m_lineHeight, GetEndOfLastCol(), count * m_lineHeight );
+ m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+
+ wxSize client_size = GetClientSize();
+ wxRect client_rect( 0, 0, client_size.x, client_size.y );
+ wxRect intersect_rect = client_rect.Intersect( rect );
+ if (intersect_rect.width > 0)
+ Refresh( true, &intersect_rect );
+}
+
+void wxDataViewMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event)
+{
+ wxCHECK_RET( newCurrent < GetRowCount(),
+ _T("invalid item index in OnArrowChar()") );
+
+ // if there is no selection, we cannot move it anywhere
+ if (!HasCurrentRow())
+ return;
+
+ size_t oldCurrent = m_currentRow;
+
+ // in single selection we just ignore Shift as we can't select several
+ // items anyhow
+ if ( event.ShiftDown() && !IsSingleSel() )
+ {
+ RefreshRow( oldCurrent );
+
+ ChangeCurrentRow( newCurrent );
+
+ // select all the items between the old and the new one
+ if ( oldCurrent > newCurrent )
+ {
+ newCurrent = oldCurrent;
+ oldCurrent = m_currentRow;
+ }
+
+ SelectRows( oldCurrent, newCurrent, true );
+ }
+ else // !shift
+ {
+ RefreshRow( oldCurrent );
+
+ // all previously selected items are unselected unless ctrl is held
+ if ( !event.ControlDown() )
+ SelectAllRows(false);
+
+ ChangeCurrentRow( newCurrent );
+
+ if ( !event.ControlDown() )
+ SelectRow( m_currentRow, true );
+ else
+ RefreshRow( m_currentRow );
+ }
+
+ // MoveToFocus();
+}
+
+void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
+{
+ if (event.GetKeyCode() == WXK_TAB)
+ {
+ wxNavigationKeyEvent nevent;
+ nevent.SetWindowChange( event.ControlDown() );
+ nevent.SetDirection( !event.ShiftDown() );
+ nevent.SetEventObject( GetParent()->GetParent() );
+ nevent.SetCurrentFocus( m_parent );
+ if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent ))
+ return;
+ }
+
+ // no item -> nothing to do
+ if (!HasCurrentRow())
+ {
+ event.Skip();
+ return;
+ }
+
+ // don't use m_linesPerPage directly as it might not be computed yet
+ const int pageSize = GetCountPerPage();
+ wxCHECK_RET( pageSize, _T("should have non zero page size") );
+
+ switch ( event.GetKeyCode() )
+ {
+ case WXK_UP:
+ if ( m_currentRow > 0 )
+ OnArrowChar( m_currentRow - 1, event );
+ break;
+
+ case WXK_DOWN:
+ if ( m_currentRow < GetRowCount() - 1 )
+ OnArrowChar( m_currentRow + 1, event );
+ break;
+
+ case WXK_END:
+ if (!IsEmpty())
+ OnArrowChar( GetRowCount() - 1, event );
+ break;
+
+ case WXK_HOME:
+ if (!IsEmpty())
+ OnArrowChar( 0, event );
+ break;
+
+ case WXK_PAGEUP:
+ {
+ int steps = pageSize - 1;
+ int index = m_currentRow - steps;
+ if (index < 0)
+ index = 0;
+
+ OnArrowChar( index, event );
+ }
+ break;
+
+ case WXK_PAGEDOWN:
+ {
+ int steps = pageSize - 1;
+ size_t index = m_currentRow + steps;
+ size_t count = GetRowCount();
+ if ( index >= count )
+ index = count - 1;
+
+ OnArrowChar( index, event );
+ }
+ break;
+
+ default:
+ event.Skip();
+ }
+}
+
void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
{
+ if (event.GetEventType() == wxEVT_MOUSEWHEEL)
+ {
+ // let the base handle mouse wheel events.
+ event.Skip();
+ return;
+ }
+
int x = event.GetX();
int y = event.GetY();
m_owner->CalcUnscrolledPosition( x, y, &x, &y );
return;
wxDataViewCell *cell = col->GetCell();
- size_t row = y / m_lineHeight;
+ size_t current = y / m_lineHeight;
+
+ if ((current > GetRowCount()) || (x > GetEndOfLastCol()))
+ {
+ // Unselect all if below the last row ?
+ return;
+ }
wxDataViewListModel *model = GetOwner()->GetModel();
+ if (event.Dragging())
+ {
+ if (m_dragCount == 0)
+ {
+ // we have to report the raw, physical coords as we want to be
+ // able to call HitTest(event.m_pointDrag) from the user code to
+ // get the item being dragged
+ m_dragStart = event.GetPosition();
+ }
+
+ m_dragCount++;
+
+ if (m_dragCount != 3)
+ return;
+
+ if (event.LeftIsDown())
+ {
+ // Notify cell about drag
+ }
+ return;
+ }
+ else
+ {
+ m_dragCount = 0;
+ }
+
+ bool forceClick = false;
+
if (event.ButtonDClick())
{
m_renameTimer->Stop();
if (event.LeftDClick())
{
- if (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)
+ if ( current == m_lineLastClicked )
{
- wxVariant value;
- model->GetValue( value, col->GetModelColumn(), row );
- cell->SetValue( value );
- wxRect cell_rect( xpos, row * m_lineHeight, col->GetWidth(), m_lineHeight );
- cell->Activate( cell_rect, model, col->GetModelColumn(), row );
+ if (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)
+ {
+ wxVariant value;
+ model->GetValue( value, col->GetModelColumn(), current );
+ cell->SetValue( value );
+ wxRect cell_rect( xpos, current * m_lineHeight, col->GetWidth(), m_lineHeight );
+ cell->Activate( cell_rect, model, col->GetModelColumn(), current );
+ }
+ return;
}
+ else
+ {
+ // The first click was on another item, so don't interpret this as
+ // a double click, but as a simple click instead
+ forceClick = true;
+ }
+ }
- return;
- } else
if (event.LeftUp())
{
+ if (m_lineSelectSingleOnUp != (size_t)-1)
+ {
+ // select single line
+ SelectAllRows( false );
+ SelectRow( m_lineSelectSingleOnUp, true );
+ }
+
if (m_lastOnSame)
{
- if ((col == m_currentCol) & (row == m_currentRow) &&
+ if ((col == m_currentCol) && (current == m_currentRow) &&
(cell->GetMode() == wxDATAVIEW_CELL_EDITABLE) )
{
m_renameTimer->Start( 100, true );
}
m_lastOnSame = false;
- } else
- if (event.LeftDown())
+ m_lineSelectSingleOnUp = (size_t)-1;
+ }
+ else
{
- wxDataViewColumn *oldCurrentCol = m_currentCol;
+ // This is necessary, because after a DnD operation in
+ // from and to ourself, the up event is swallowed by the
+ // DnD code. So on next non-up event (which means here and
+ // now) m_lineSelectSingleOnUp should be reset.
+ m_lineSelectSingleOnUp = (size_t)-1;
+ }
+
+ if (event.RightDown())
+ {
+ m_lineBeforeLastClicked = m_lineLastClicked;
+ m_lineLastClicked = current;
+
+ // If the item is already selected, do not update the selection.
+ // Multi-selections should not be cleared if a selected item is clicked.
+ if (!IsRowSelected(current))
+ {
+ SelectAllRows(false);
+ ChangeCurrentRow(current);
+ SelectRow(m_currentRow,true);
+ }
+
+ // notify cell about right click
+ // cell->...
+
+ // Allow generation of context menu event
+ event.Skip();
+ }
+ else if (event.MiddleDown())
+ {
+ // notify cell about middle click
+ // cell->...
+ }
+ if (event.LeftDown() || forceClick)
+ {
+#ifdef __WXMSW__
+ SetFocus();
+#endif
+
+ m_lineBeforeLastClicked = m_lineLastClicked;
+ m_lineLastClicked = current;
+
size_t oldCurrentRow = m_currentRow;
-
+ bool oldWasSelected = IsRowSelected(m_currentRow);
+
+ bool cmdModifierDown = event.CmdDown();
+ if ( IsSingleSel() || !(cmdModifierDown || event.ShiftDown()) )
+ {
+ if ( IsSingleSel() || !IsRowSelected(current) )
+ {
+ SelectAllRows( false );
+
+ ChangeCurrentRow(current);
+
+ SelectRow(m_currentRow,true);
+ }
+ else // multi sel & current is highlighted & no mod keys
+ {
+ m_lineSelectSingleOnUp = current;
+ ChangeCurrentRow(current); // change focus
+ }
+ }
+ else // multi sel & either ctrl or shift is down
+ {
+ if (cmdModifierDown)
+ {
+ ChangeCurrentRow(current);
+
+ ReverseRowSelection(m_currentRow);
+ }
+ else if (event.ShiftDown())
+ {
+ ChangeCurrentRow(current);
+
+ size_t lineFrom = oldCurrentRow,
+ lineTo = current;
+
+ if ( lineTo < lineFrom )
+ {
+ lineTo = lineFrom;
+ lineFrom = m_currentRow;
+ }
+
+ SelectRows(lineFrom, lineTo, true);
+ }
+ else // !ctrl, !shift
+ {
+ // test in the enclosing if should make it impossible
+ wxFAIL_MSG( _T("how did we get here?") );
+ }
+ }
+
+ if (m_currentRow != oldCurrentRow)
+ RefreshRow( oldCurrentRow );
+
+ wxDataViewColumn *oldCurrentCol = m_currentCol;
+
// Update selection here...
m_currentCol = col;
- m_currentRow = row;
-
- m_lastOnSame = (col == oldCurrentCol) && (row == oldCurrentRow);
-
- return;
+
+ m_lastOnSame = !forceClick && ((col == oldCurrentCol) && (current == oldCurrentRow)) && oldWasSelected;
}
+}
+
+void wxDataViewMainWindow::OnSetFocus( wxFocusEvent &event )
+{
+ m_hasFocus = true;
+
+ if (HasCurrentRow())
+ Refresh();
event.Skip();
}
-void wxDataViewMainWindow::OnSetFocus( wxFocusEvent &event )
+void wxDataViewMainWindow::OnKillFocus( wxFocusEvent &event )
{
+ m_hasFocus = false;
+
+ if (HasCurrentRow())
+ Refresh();
+
event.Skip();
}
#endif
m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
+#ifdef __WXMSW__
+ m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22) );
+#else
m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,25) );
+#endif
SetTargetWindow( m_clientArea );
#endif
// wxUSE_DATAVIEWCTRL
-