Lots of selection and focus code.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38887 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2006-04-24 12:33:24 +00:00
parent d7903e1336
commit cab0703813

View File

@@ -27,6 +27,7 @@
#include "wx/popupwin.h"
#include "wx/renderer.h"
#include "wx/timer.h"
#include "wx/settings.h"
#ifdef __WXMSW__
#include "wx/msw/wrapwin.h"
@@ -125,6 +126,8 @@ private:
// wxDataViewMainWindow
//-----------------------------------------------------------------------------
WX_DEFINE_SORTED_ARRAY_SIZE_T( size_t, wxDataViewSelection );
class wxDataViewMainWindow: public wxWindow
{
public:
@@ -149,8 +152,11 @@ public:
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();
@@ -160,6 +166,25 @@ public:
void FinishEditing( wxTextCtrl *text );
void ScrollWindow( int dx, int dy, const wxRect *rect );
bool HasCurrentRow() { return m_currentRow != (size_t)-1; }
bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE); };
bool IsEmpty() { return GetRowCount() == 0; }
int GetCountPerPage();
int 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;
@@ -167,11 +192,17 @@ private:
wxDataViewColumn *m_currentCol;
size_t m_currentRow;
wxDataViewSelection m_selection;
wxDataViewRenameTimer *m_renameTimer;
wxDataViewTextCtrlWrapper *m_textctrlWrapper;
bool m_lastOnSame;
wxBrush *m_highlightBrush,
*m_highlightUnfocusedBrush;
bool m_hasFocus;
private:
DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow)
DECLARE_EVENT_TABLE()
@@ -633,6 +664,7 @@ void wxDataViewHeaderWindow::OnMouse( wxMouseEvent &WXUNUSED(event) )
void wxDataViewHeaderWindow::OnSetFocus( wxFocusEvent &event )
{
GetParent()->SetFocus();
event.Skip();
}
@@ -797,17 +829,29 @@ void wxDataViewTextCtrlWrapper::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, 0, name ),
m_selection( wxDataViewSelectionCmp )
{
SetOwner( parent );
@@ -821,6 +865,26 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
// TODO: we need to calculate this smartly
m_lineHeight = 20;
m_highlightBrush = new wxBrush
(
wxSystemSettings::GetColour
(
wxSYS_COLOUR_HIGHLIGHT
),
wxSOLID
);
m_highlightUnfocusedBrush = new wxBrush
(
wxSystemSettings::GetColour
(
wxSYS_COLOUR_BTNSHADOW
),
wxSOLID
);
m_hasFocus = false;
UpdateDisplay();
}
@@ -828,6 +892,8 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
wxDataViewMainWindow::~wxDataViewMainWindow()
{
delete m_renameTimer;
delete m_highlightBrush;
delete m_highlightUnfocusedBrush;
}
void wxDataViewMainWindow::OnRenameTimer()
@@ -973,9 +1039,34 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
wxDataViewListModel *model = GetOwner()->GetModel();
size_t item_start = wxMax( 0, (update.y / m_lineHeight) );
size_t item_count = wxMin( ((update.y + update.height) / m_lineHeight) - item_start + 1,
size_t item_count = wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
(int)(model->GetNumberOfRows()-item_start) );
if (m_hasFocus)
dc.SetBrush( *m_highlightBrush );
else
dc.SetBrush( *m_highlightUnfocusedBrush );
dc.SetPen( *wxTRANSPARENT_PEN );
size_t item;
for (item = item_start; item < item_start+item_count; item++)
{
if (m_selection.Index( item ) != wxNOT_FOUND)
{
wxRect rect( 0, item*m_lineHeight+1, 10000, m_lineHeight-2 );
dc.DrawRectangle( rect );
}
}
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.SetPen( *wxBLACK_PEN );
if (HasCurrentRow())
{
wxRect rect( 0, m_currentRow*m_lineHeight+1, 10000, m_lineHeight-2 );
dc.DrawRectangle( rect );
}
wxRect cell_rect;
cell_rect.x = 0;
cell_rect.height = m_lineHeight;
@@ -987,7 +1078,6 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
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;
@@ -1013,6 +1103,254 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
}
}
int wxDataViewMainWindow::GetCountPerPage()
{
wxSize size = GetClientSize();
return size.y / m_lineHeight;
}
int wxDataViewMainWindow::GetRowCount()
{
return GetOwner()->GetModel()->GetNumberOfRows();
}
void wxDataViewMainWindow::SelectAllRows( bool on )
{
m_selection.Clear();
if (on)
{
size_t i;
for (i = 0; i < m_selection.GetCount(); i++)
m_selection.Add( i );
}
Refresh();
}
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 );
Refresh( 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, 10000, 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, 10000, (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, 10000, 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 < (size_t)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 );
m_currentRow = 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
{
Refresh( oldCurrent );
// all previously selected items are unselected unless ctrl is held
if ( !event.ControlDown() )
SelectAllRows(false);
m_currentRow = newCurrent;
if ( !event.ControlDown() )
SelectRow( m_currentRow, true );
}
// 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 < (size_t)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 )
{
int x = event.GetX();
@@ -1082,6 +1420,8 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
// Update selection here...
m_currentCol = col;
m_currentRow = row;
RefreshRow( oldCurrentRow );
RefreshRow( m_currentRow );
m_lastOnSame = (col == oldCurrentCol) && (row == oldCurrentRow);
@@ -1093,6 +1433,21 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
void wxDataViewMainWindow::OnSetFocus( wxFocusEvent &event )
{
m_hasFocus = true;
if (HasCurrentRow())
Refresh();
event.Skip();
}
void wxDataViewMainWindow::OnKillFocus( wxFocusEvent &event )
{
m_hasFocus = false;
if (HasCurrentRow())
Refresh();
event.Skip();
}