#include "wx/listctrl.h"
-#if (!defined(__WXMSW__) || defined(__WXUNIVERSAL__)) && !defined(__WXMAC__)
+#if ((!defined(__WXMSW__) && !(defined(__WXMAC__) && wxOSX_USE_CARBON)) || defined(__WXUNIVERSAL__))
// if we have a native version, its implementation file does all this
IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
#include "wx/dcscreen.h"
#include "wx/math.h"
#include "wx/settings.h"
+ #include "wx/sizer.h"
#endif
#include "wx/imaglist.h"
#include "wx/renderer.h"
#ifdef __WXMAC__
- #include "wx/mac/private.h"
+ #include "wx/osx/private.h"
+ // for themeing support
+ #include <Carbon/Carbon.h>
#endif
#else
static const int EXTRA_WIDTH = 4;
#endif
+
+#ifdef __WXGTK__
+static const int EXTRA_HEIGHT = 6;
+#else
static const int EXTRA_HEIGHT = 4;
+#endif
// margin between the window and the items
static const int EXTRA_BORDER_X = 2;
// wxListLineData (internal)
//-----------------------------------------------------------------------------
-WX_DECLARE_EXPORTED_LIST(wxListItemData, wxListItemDataList);
+WX_DECLARE_LIST(wxListItemData, wxListItemDataList);
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxListItemDataList)
int width);
};
-WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData, wxListLineDataArray);
+WX_DECLARE_OBJARRAY(wxListLineData, wxListLineDataArray);
#include "wx/arrimpl.cpp"
WX_DEFINE_OBJARRAY(wxListLineDataArray)
// needs refresh
bool m_dirty;
+ // Update main window's column later
+ bool m_sendSetColumnWidth;
+ int m_colToSend;
+ int m_widthToSend;
+
+ virtual void OnInternalIdle();
+
private:
// common part of all ctors
void Init();
// it wasn't vetoed, i.e. if we should proceed
bool SendListEvent(wxEventType type, const wxPoint& pos);
- DECLARE_DYNAMIC_CLASS(wxListHeaderWindow)
DECLARE_EVENT_TABLE()
};
wxTextCtrl *GetText() const { return m_text; }
- void AcceptChangesAndFinish();
+ void EndEdit( bool discardChanges );
protected:
void OnChar( wxKeyEvent &event );
void OnKillFocus( wxFocusEvent &event );
bool AcceptChanges();
- void Finish();
+ void Finish( bool setfocus );
private:
wxListMainWindow *m_owner;
wxTextCtrl *m_text;
wxString m_startValue;
size_t m_itemEdited;
- bool m_finished;
bool m_aboutToFinish;
DECLARE_EVENT_TABLE()
// wxListMainWindow (internal)
//-----------------------------------------------------------------------------
-WX_DECLARE_EXPORTED_LIST(wxListHeaderData, wxListHeaderDataList);
+WX_DECLARE_LIST(wxListHeaderData, wxListHeaderDataList);
#include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxListHeaderDataList)
-class wxListMainWindow : public wxScrolledWindow
+class wxListMainWindow : public wxWindow
{
public:
wxListMainWindow();
return m_textctrlWrapper ? m_textctrlWrapper->GetText() : NULL;
}
- void FinishEditing(wxTextCtrl *text)
+ void ResetTextControl(wxTextCtrl *text)
{
delete text;
m_textctrlWrapper = NULL;
- SetFocusIgnoringChildren();
}
- // suspend/resume redrawing the control
- void Freeze();
- void Thaw();
-
void OnRenameTimer();
bool OnRenameAccept(size_t itemEdit, const wxString& value);
void OnRenameCancelled(size_t itemEdit);
void OnPaint( wxPaintEvent &event );
+ void OnChildFocus(wxChildFocusEvent& event);
+
void DrawImage( int index, wxDC *dc, int x, int y );
void GetImageSize( int index, int &width, int &height ) const;
int GetTextLength( const wxString &s ) const;
void SetItemState( long item, long state, long stateMask );
void SetItemStateAll( long state, long stateMask );
int GetItemState( long item, long stateMask ) const;
- void GetItemRect( long index, wxRect &rect ) const;
+ bool GetItemRect( long item, wxRect &rect ) const
+ {
+ return GetSubItemRect(item, wxLIST_GETSUBITEMRECT_WHOLEITEM, rect);
+ }
+ bool GetSubItemRect( long item, long subItem, wxRect& rect ) const;
wxRect GetViewRect() const;
bool GetItemPosition( long item, wxPoint& pos ) const;
int GetSelectedItemCount() const;
// override base class virtual to reset m_lineHeight when the font changes
virtual bool SetFont(const wxFont& font)
{
- if ( !wxScrolledWindow::SetFont(font) )
+ if ( !wxWindow::SetFont(font) )
return false;
m_lineHeight = 0;
wxBrush *m_highlightBrush,
*m_highlightUnfocusedBrush;
- // if this is > 0, the control is frozen and doesn't redraw itself
- size_t m_freezeCount;
-
// wrapper around the text control currently used for in place editing or
// NULL if no item is being edited
wxListTextCtrlWrapper *m_textctrlWrapper;
- DECLARE_DYNAMIC_CLASS(wxListMainWindow)
DECLARE_EVENT_TABLE()
friend class wxGenericListCtrl;
#ifdef __WXMAC__
{
if (m_owner->HasFocus()
-#if !defined(__WXUNIVERSAL__)
+#if !defined(__WXUNIVERSAL__) && wxOSX_USE_CARBON
&& IsControlActive( (ControlRef)m_owner->GetHandle() )
#endif
)
if ( highlighted )
dc->SetBrush( *m_owner->GetHighlightBrush() );
else
- dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
+ dc->SetBrush(wxBrush(attr->GetBackgroundColour(), wxBRUSHSTYLE_SOLID));
dc->SetPen( *wxTRANSPARENT_PEN );
{
int flags = wxCONTROL_SELECTED;
if (m_owner->HasFocus()
-#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
+#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) && wxOSX_USE_CARBON
&& IsControlActive( (ControlRef)m_owner->GetHandle() )
#endif
)
int xOld = x;
x += width;
+ const int wText = width - 8;
+ wxDCClipper clipper(*dc, xOld, rect.y, wText, rect.height);
+
if ( item->HasImage() )
{
int ix, iy;
}
if ( item->HasText() )
- DrawTextFormatted(dc, item->GetText(), col, xOld, yMid, width - 8);
+ DrawTextFormatted(dc, item->GetText(), col, xOld, yMid, wText);
}
}
// wxListHeaderWindow
//-----------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow,wxWindow)
-
BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow)
EVT_PAINT (wxListHeaderWindow::OnPaint)
EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse)
void wxListHeaderWindow::Init()
{
- m_currentCursor = (wxCursor *) NULL;
+ m_currentCursor = NULL;
m_isDragging = false;
m_dirty = false;
+ m_sendSetColumnWidth = false;
}
wxListHeaderWindow::wxListHeaderWindow()
{
Init();
- m_owner = (wxListMainWindow *) NULL;
- m_resizeCursor = (wxCursor *) NULL;
+ m_owner = NULL;
+ m_resizeCursor = NULL;
}
wxListHeaderWindow::wxListHeaderWindow( wxWindow *win,
// scrollbar: this allows us to always use logical coords
void wxListHeaderWindow::AdjustDC(wxDC& dc)
{
+ wxGenericListCtrl *parent = m_owner->GetListCtrl();
+
int xpix;
- m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
+ parent->GetScrollPixelsPerUnit( &xpix, NULL );
int view_start;
- m_owner->GetViewStart( &view_start, NULL );
+ parent->GetViewStart( &view_start, NULL );
int org_x = 0;
void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
+ wxGenericListCtrl *parent = m_owner->GetListCtrl();
+
wxPaintDC dc( this );
- PrepareDC( dc );
AdjustDC( dc );
dc.SetFont( GetFont() );
// width and height of the entire header window
int w, h;
GetClientSize( &w, &h );
- m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+ parent->CalcUnscrolledPosition(w, 0, &w, NULL);
- dc.SetBackgroundMode(wxTRANSPARENT);
+ dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
dc.SetTextForeground(GetForegroundColour());
int x = HEADER_OFFSET_X;
flags |= wxCONTROL_SELECTED;
#endif
+ if (i == 0)
+ flags |= wxCONTROL_SPECIAL; // mark as first column
+
wxRendererNative::Get().DrawHeaderButton
(
this,
x += wCol;
}
+
+ // Fill in what's missing to the right of the columns, otherwise we will
+ // leave an unpainted area when columns are removed (and it looks better)
+ if ( x < w )
+ {
+ wxRendererNative::Get().DrawHeaderButton
+ (
+ this,
+ dc,
+ wxRect(x, HEADER_OFFSET_Y, w - x, h),
+ wxCONTROL_DIRTY // mark as last column
+ );
+ }
+}
+
+void wxListHeaderWindow::OnInternalIdle()
+{
+ wxWindow::OnInternalIdle();
+
+ if (m_sendSetColumnWidth)
+ {
+ m_owner->SetColumnWidth( m_colToSend, m_widthToSend );
+ m_sendSetColumnWidth = false;
+ }
}
void wxListHeaderWindow::DrawCurrent()
{
#if 1
- m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
+ // m_owner->SetColumnWidth( m_column, m_currentX - m_minX );
+ m_sendSetColumnWidth = true;
+ m_colToSend = m_column;
+ m_widthToSend = m_currentX - m_minX;
#else
int x1 = m_currentX;
int y1 = 0;
void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
{
+ wxGenericListCtrl *parent = m_owner->GetListCtrl();
+
// we want to work with logical coords
int x;
- m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
+ parent->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
int y = event.GetY();
if (m_isDragging)
// there
int w = 0;
GetClientSize( &w, NULL );
- m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+ parent->CalcUnscrolledPosition(w, 0, &w, NULL);
w -= 6;
// erase the line if it was drawn
{
m_owner = owner;
m_text = text;
- m_finished = false;
m_aboutToFinish = false;
+ wxGenericListCtrl *parent = m_owner->GetListCtrl();
+
wxRect rectLabel = owner->GetLineLabelRect(itemEdit);
- m_owner->CalcScrolledPosition(rectLabel.x, rectLabel.y,
+ parent->CalcScrolledPosition(rectLabel.x, rectLabel.y,
&rectLabel.x, &rectLabel.y);
m_text->Create(owner, wxID_ANY, m_startValue,
m_text->PushEventHandler(this);
}
-void wxListTextCtrlWrapper::Finish()
+void wxListTextCtrlWrapper::EndEdit(bool discardChanges)
{
- if ( !m_finished )
+ m_aboutToFinish = true;
+
+ if ( discardChanges )
{
- m_finished = true;
+ m_owner->OnRenameCancelled(m_itemEdited);
- m_text->RemoveEventHandler(this);
- m_owner->FinishEditing(m_text);
+ Finish( true );
+ }
+ else
+ {
+ // Notify the owner about the changes
+ AcceptChanges();
- wxPendingDelete.Append( this );
+ // Even if vetoed, close the control (consistent with MSW)
+ Finish( true );
}
}
+void wxListTextCtrlWrapper::Finish( bool setfocus )
+{
+ m_text->RemoveEventHandler(this);
+ m_owner->ResetTextControl( m_text );
+
+ wxPendingDelete.Append( this );
+
+ if (setfocus)
+ m_owner->SetFocus();
+}
+
bool wxListTextCtrlWrapper::AcceptChanges()
{
const wxString value = m_text->GetValue();
return true;
}
-void wxListTextCtrlWrapper::AcceptChangesAndFinish()
-{
- m_aboutToFinish = true;
-
- // Notify the owner about the changes
- AcceptChanges();
-
- // Even if vetoed, close the control (consistent with MSW)
- Finish();
-}
-
void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
{
switch ( event.m_keyCode )
{
case WXK_RETURN:
- AcceptChangesAndFinish();
+ EndEdit( false );
break;
case WXK_ESCAPE:
- m_owner->OnRenameCancelled( m_itemEdited );
- Finish();
+ EndEdit( true );
break;
default:
void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
{
- if (m_finished)
+ if (m_aboutToFinish)
{
- event.Skip();
- return;
+ // auto-grow the textctrl:
+ wxSize parentSize = m_owner->GetSize();
+ wxPoint myPos = m_text->GetPosition();
+ wxSize mySize = m_text->GetSize();
+ int sx, sy;
+ m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
+ if (myPos.x + sx > parentSize.x)
+ sx = parentSize.x - myPos.x;
+ if (mySize.x > sx)
+ sx = mySize.x;
+ m_text->SetSize(sx, wxDefaultCoord);
}
- // auto-grow the textctrl:
- wxSize parentSize = m_owner->GetSize();
- wxPoint myPos = m_text->GetPosition();
- wxSize mySize = m_text->GetSize();
- int sx, sy;
- m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
- if (myPos.x + sx > parentSize.x)
- sx = parentSize.x - myPos.x;
- if (mySize.x > sx)
- sx = mySize.x;
- m_text->SetSize(sx, wxDefaultCoord);
-
event.Skip();
}
void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
{
- if ( !m_finished && !m_aboutToFinish )
+ if ( !m_aboutToFinish )
{
if ( !AcceptChanges() )
m_owner->OnRenameCancelled( m_itemEdited );
- Finish();
+ Finish( false );
}
// We must let the native text control handle focus
// wxListMainWindow
//-----------------------------------------------------------------------------
-IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow,wxScrolledWindow)
-
-BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledWindow)
+BEGIN_EVENT_TABLE(wxListMainWindow,wxScrolledCanvas)
EVT_PAINT (wxListMainWindow::OnPaint)
EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
EVT_CHAR (wxListMainWindow::OnChar)
EVT_SET_FOCUS (wxListMainWindow::OnSetFocus)
EVT_KILL_FOCUS (wxListMainWindow::OnKillFocus)
EVT_SCROLLWIN (wxListMainWindow::OnScroll)
+ EVT_CHILD_FOCUS (wxListMainWindow::OnChildFocus)
END_EVENT_TABLE()
void wxListMainWindow::Init()
m_headerWidth =
m_lineHeight = 0;
- m_small_image_list = (wxImageList *) NULL;
- m_normal_image_list = (wxImageList *) NULL;
+ m_small_image_list = NULL;
+ m_normal_image_list = NULL;
m_small_spacing = 30;
m_normal_spacing = 40;
m_lineLastClicked =
m_lineSelectSingleOnUp =
m_lineBeforeLastClicked = (size_t)-1;
-
- m_freezeCount = 0;
}
wxListMainWindow::wxListMainWindow()
Init();
m_highlightBrush =
- m_highlightUnfocusedBrush = (wxBrush *) NULL;
+ m_highlightUnfocusedBrush = NULL;
}
wxListMainWindow::wxListMainWindow( wxWindow *parent,
const wxSize& size,
long style,
const wxString &name )
- : wxScrolledWindow( parent, id, pos, size,
- style | wxHSCROLL | wxVSCROLL, name )
+ : wxWindow( parent, id, pos, size, style, name )
{
Init();
(
wxSYS_COLOUR_HIGHLIGHT
),
- wxSOLID
+ wxBRUSHSTYLE_SOLID
);
m_highlightUnfocusedBrush = new wxBrush
(
wxSYS_COLOUR_BTNSHADOW
),
- wxSOLID
+ wxBRUSHSTYLE_SOLID
);
- SetScrollbars( 0, 0, 0, 0, 0, 0 );
-
wxVisualAttributes attr = wxGenericListCtrl::GetClassDefaultAttributes();
SetOwnForegroundColour( attr.colFg );
SetOwnBackgroundColour( attr.colBg );
wxRect rect = GetLineRect(line);
- CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+ GetListCtrl()->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
RefreshRect( rect );
}
rect.width = GetClientSize().x;
rect.height = GetLineY(lineTo) - rect.y + GetLineHeight();
- CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+ GetListCtrl()->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
RefreshRect( rect );
}
else // !report
wxRect rect;
rect.x = 0;
rect.y = GetLineY(lineFrom);
- CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+ GetListCtrl()->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
wxSize size = GetClientSize();
rect.width = size.x;
}
}
-void wxListMainWindow::Freeze()
-{
- m_freezeCount++;
-}
-
-void wxListMainWindow::Thaw()
-{
- wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen list control?") );
-
- if ( --m_freezeCount == 0 )
- Refresh();
-}
-
void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
// Note: a wxPaintDC must be constructed even if no drawing is
// done (a Windows requirement).
wxPaintDC dc( this );
- if ( IsEmpty() || m_freezeCount )
+ if ( IsEmpty() )
+ {
// nothing to draw or not the moment to draw it
return;
+ }
if ( m_dirty )
- // delay the repainting until we calculate all the items positions
- return;
+ RecalculatePositions( false );
- PrepareDC( dc );
+ GetListCtrl()->PrepareDC( dc );
int dev_x, dev_y;
- CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
+ GetListCtrl()->CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
dc.SetFont( GetFont() );
if ( HasFlag(wxLC_HRULES) )
{
- wxPen pen(GetRuleColour(), 1, wxSOLID);
+ wxPen pen(GetRuleColour(), 1, wxPENSTYLE_SOLID);
wxSize clientSize = GetClientSize();
size_t i = visibleFrom;
// Draw vertical rules if required
if ( HasFlag(wxLC_VRULES) && !IsEmpty() )
{
- wxPen pen(GetRuleColour(), 1, wxSOLID);
+ wxPen pen(GetRuleColour(), 1, wxPENSTYLE_SOLID);
wxRect firstItemRect, lastItemRect;
GetItemRect(visibleFrom, firstItemRect);
}
}
+void wxListMainWindow::OnChildFocus(wxChildFocusEvent& WXUNUSED(event))
+{
+ // Do nothing here. This prevents the default handler in wxScrolledWindow
+ // from needlessly scrolling the window when the edit control is
+ // dismissed. See ticket #9563.
+}
+
void wxListMainWindow::SendNotify( size_t line,
wxEventType command,
const wxPoint& point )
// listctrl because the order of events is different (or something like
// that), so explicitly end the edit if it is active.
if ( event.LeftDown() && m_textctrlWrapper )
- m_textctrlWrapper->AcceptChangesAndFinish();
+ m_textctrlWrapper->EndEdit( false );
#endif // __WXMAC__
if ( event.LeftDown() )
- SetFocusIgnoringChildren();
+ SetFocus();
event.SetEventObject( GetParent() );
if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
int x = event.GetX();
int y = event.GetY();
- CalcUnscrolledPosition( x, y, &x, &y );
+ GetListCtrl()->CalcUnscrolledPosition( x, y, &x, &y );
// where did we hit it (if we did)?
long hitResult = 0;
ResetVisibleLinesRange();
if (rect.y < view_y)
- Scroll( -1, rect.y / hLine );
+ GetListCtrl()->Scroll( -1, rect.y / hLine );
if (rect.y + rect.height + 5 > view_y + client_h)
- Scroll( -1, (rect.y + rect.height - client_h + hLine) / hLine );
+ GetListCtrl()->Scroll( -1, (rect.y + rect.height - client_h + hLine) / hLine );
#ifdef __WXMAC__
// At least on Mac the visible lines value will get reset inside of
}
else // !report
{
+ int sx = -1,
+ sy = -1;
+
if (rect.x-view_x < 5)
- Scroll( (rect.x - 5) / SCROLL_UNIT_X, -1 );
+ sx = (rect.x - 5) / SCROLL_UNIT_X;
if (rect.x + rect.width - 5 > view_x + client_w)
- Scroll( (rect.x + rect.width - client_w + SCROLL_UNIT_X) / SCROLL_UNIT_X, -1 );
+ sx = (rect.x + rect.width - client_w + SCROLL_UNIT_X) / SCROLL_UNIT_X;
+
+ if (rect.y-view_y < 5)
+ sy = (rect.y - 5) / hLine;
+ if (rect.y + rect.height - 5 > view_y + client_h)
+ sy = (rect.y + rect.height - client_h + hLine) / hLine;
+
+ GetListCtrl()->Scroll(sx, sy);
}
}
int hLine = GetLineHeight();
- Scroll(-1, top + dy / hLine);
+ GetListCtrl()->Scroll(-1, top + dy / hLine);
#ifdef __WXMAC__
// see comment in MoveToItem() for why we do this
wxWindow *parent = GetParent();
// propagate the key event upwards
- wxKeyEvent ke( wxEVT_KEY_DOWN );
- ke.m_shiftDown = event.m_shiftDown;
- ke.m_controlDown = event.m_controlDown;
- ke.m_altDown = event.m_altDown;
- ke.m_metaDown = event.m_metaDown;
- ke.m_keyCode = event.m_keyCode;
- ke.m_x = event.m_x;
- ke.m_y = event.m_y;
+ wxKeyEvent ke(event);
ke.SetEventObject( parent );
- if (parent->GetEventHandler()->ProcessEvent( ke )) return;
+ if (parent->GetEventHandler()->ProcessEvent( ke ))
+ return;
event.Skip();
}
wxWindow *parent = GetParent();
// propagate the key event upwards
- wxKeyEvent ke( wxEVT_KEY_UP );
- ke.m_shiftDown = event.m_shiftDown;
- ke.m_controlDown = event.m_controlDown;
- ke.m_altDown = event.m_altDown;
- ke.m_metaDown = event.m_metaDown;
- ke.m_keyCode = event.m_keyCode;
- ke.m_x = event.m_x;
- ke.m_y = event.m_y;
- ke.SetEventObject( parent );
- if (parent->GetEventHandler()->ProcessEvent( ke )) return;
+ wxKeyEvent ke(event);
+ if (parent->GetEventHandler()->ProcessEvent( ke ))
+ return;
event.Skip();
}
parent->GetEventHandler()->ProcessEvent( le );
}
- // propagate the char event upwards
- wxKeyEvent ke( wxEVT_CHAR );
- ke.m_shiftDown = event.m_shiftDown;
- ke.m_controlDown = event.m_controlDown;
- ke.m_altDown = event.m_altDown;
- ke.m_metaDown = event.m_metaDown;
- ke.m_keyCode = event.m_keyCode;
- ke.m_x = event.m_x;
- ke.m_y = event.m_y;
- ke.SetEventObject( parent );
- if (parent->GetEventHandler()->ProcessEvent( ke )) return;
-
- if (event.GetKeyCode() == WXK_TAB)
+ if ( (event.GetKeyCode() != WXK_UP) &&
+ (event.GetKeyCode() != WXK_DOWN) &&
+ (event.GetKeyCode() != WXK_RIGHT) &&
+ (event.GetKeyCode() != WXK_LEFT) &&
+ (event.GetKeyCode() != WXK_PAGEUP) &&
+ (event.GetKeyCode() != WXK_PAGEDOWN) &&
+ (event.GetKeyCode() != WXK_END) &&
+ (event.GetKeyCode() != WXK_HOME) )
{
- wxNavigationKeyEvent nevent;
- nevent.SetWindowChange( event.ControlDown() );
- nevent.SetDirection( !event.ShiftDown() );
- nevent.SetEventObject( GetParent()->GetParent() );
- nevent.SetCurrentFocus( m_parent );
- if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent ))
+ // propagate the char event upwards
+ wxKeyEvent ke(event);
+ ke.SetEventObject( parent );
+ if (parent->GetEventHandler()->ProcessEvent( ke ))
return;
}
+ if ( HandleAsNavigationKey(event) )
+ return;
+
// no item -> nothing to do
if (!HasCurrent())
{
_T("SetColumnWidth() can only be called in report mode.") );
m_dirty = true;
+
wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
if ( headerWin )
headerWin->m_dirty = true;
wxRect wxListMainWindow::GetViewRect() const
{
- wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
- _T("wxListCtrl::GetViewRect() only works in icon mode") );
+ wxASSERT_MSG( !HasFlag(wxLC_LIST), "not implemented for list view" );
// we need to find the longest/tallest label
wxCoord xMax = 0, yMax = 0;
{
for ( int i = 0; i < count; i++ )
{
- wxRect r;
- GetItemRect(i, r);
+ // we need logical, not physical, coordinates here, so use
+ // GetLineRect() instead of GetItemRect()
+ wxRect r = GetLineRect(i);
wxCoord x = r.GetRight(),
y = r.GetBottom();
return wxRect(0, 0, xMax, yMax);
}
-void wxListMainWindow::GetItemRect( long index, wxRect &rect ) const
+bool
+wxListMainWindow::GetSubItemRect(long item, long subItem, wxRect& rect) const
{
- wxCHECK_RET( index >= 0 && (size_t)index < GetItemCount(),
- _T("invalid index in GetItemRect") );
+ wxCHECK_MSG( subItem == wxLIST_GETSUBITEMRECT_WHOLEITEM || InReportView(),
+ false,
+ _T("GetSubItemRect only meaningful in report view") );
+ wxCHECK_MSG( item >= 0 && (size_t)item < GetItemCount(), false,
+ _T("invalid item in GetSubItemRect") );
// ensure that we're laid out, otherwise we could return nonsense
if ( m_dirty )
RecalculatePositions(true /* no refresh */);
}
- rect = GetLineRect((size_t)index);
+ rect = GetLineRect((size_t)item);
+
+ // Adjust rect to specified column
+ if ( subItem != wxLIST_GETSUBITEMRECT_WHOLEITEM )
+ {
+ wxCHECK_MSG( subItem >= 0 && subItem < GetColumnCount(), false,
+ _T("invalid subItem in GetSubItemRect") );
+
+ for (int i = 0; i < subItem; i++)
+ {
+ rect.x += GetColumnWidth(i);
+ }
+ rect.width = GetColumnWidth(subItem);
+ }
+
+ GetListCtrl()->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
- CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
+ return true;
}
bool wxListMainWindow::GetItemPosition(long item, wxPoint& pos) const
const size_t count = GetItemCount();
int iconSpacing;
- if ( HasFlag(wxLC_ICON) )
+ if ( HasFlag(wxLC_ICON) && m_normal_image_list )
iconSpacing = m_normal_spacing;
- else if ( HasFlag(wxLC_SMALL_ICON) )
+ else if ( HasFlag(wxLC_SMALL_ICON) && m_small_image_list )
iconSpacing = m_small_spacing;
else
iconSpacing = 0;
ResetVisibleLinesRange();
- SetScrollbars( SCROLL_UNIT_X, lineHeight,
+ GetListCtrl()->SetScrollbars( SCROLL_UNIT_X, lineHeight,
GetHeaderWidth() / SCROLL_UNIT_X,
(entireHeight + lineHeight - 1) / lineHeight,
- GetScrollPos(wxHORIZONTAL),
- GetScrollPos(wxVERTICAL),
+ GetListCtrl()->GetScrollPos(wxHORIZONTAL),
+ GetListCtrl()->GetScrollPos(wxVERTICAL),
true );
}
else // !report
}
}
- SetScrollbars
+ GetListCtrl()->SetScrollbars
(
SCROLL_UNIT_X,
lineHeight,
(x + SCROLL_UNIT_X) / SCROLL_UNIT_X,
(y + lineHeight) / lineHeight,
- GetScrollPos( wxHORIZONTAL ),
- GetScrollPos( wxVERTICAL ),
+ GetListCtrl()->GetScrollPos( wxHORIZONTAL ),
+ GetListCtrl()->GetScrollPos( wxVERTICAL ),
true
);
}
}
}
- SetScrollbars
+ GetListCtrl()->SetScrollbars
(
SCROLL_UNIT_X,
lineHeight,
(entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X,
0,
- GetScrollPos( wxHORIZONTAL ),
+ GetListCtrl()->GetScrollPos( wxHORIZONTAL ),
0,
true
);
long wxListMainWindow::HitTest( int x, int y, int &flags ) const
{
- CalcUnscrolledPosition( x, y, &x, &y );
+ GetListCtrl()->CalcUnscrolledPosition( x, y, &x, &y );
size_t count = GetItemCount();
// sorting
// ----------------------------------------------------------------------------
-wxListCtrlCompare list_ctrl_compare_func_2;
-long list_ctrl_compare_data;
+static wxListCtrlCompare list_ctrl_compare_func_2;
+static long list_ctrl_compare_data;
int LINKAGEMODE list_ctrl_compare_func_1( wxListLineData **arg1, wxListLineData **arg2 )
{
void wxListMainWindow::OnScroll(wxScrollWinEvent& event)
{
- // FIXME
-#if ( defined(__WXGTK__) || defined(__WXMAC__) ) && !defined(__WXUNIVERSAL__)
- wxScrolledWindow::OnScroll(event);
-#else
- HandleOnScroll( event );
-#endif
-
// update our idea of which lines are shown when we redraw the window the
// next time
ResetVisibleLinesRange();
BEGIN_EVENT_TABLE(wxGenericListCtrl,wxControl)
EVT_SIZE(wxGenericListCtrl::OnSize)
+ EVT_SCROLLWIN(wxGenericListCtrl::OnScroll)
END_EVENT_TABLE()
-wxGenericListCtrl::wxGenericListCtrl()
+void wxGenericListCtrl::Init()
{
- m_imageListNormal = (wxImageList *) NULL;
- m_imageListSmall = (wxImageList *) NULL;
- m_imageListState = (wxImageList *) NULL;
+ m_imageListNormal = NULL;
+ m_imageListSmall = NULL;
+ m_imageListState = NULL;
m_ownsImageListNormal =
m_ownsImageListSmall =
m_ownsImageListState = false;
- m_mainWin = (wxListMainWindow*) NULL;
- m_headerWin = (wxListHeaderWindow*) NULL;
- m_headerHeight = 0;
+ m_mainWin = NULL;
+ m_headerWin = NULL;
+ m_headerHeight = wxRendererNative::Get().GetHeaderButtonHeight(this);
}
wxGenericListCtrl::~wxGenericListCtrl()
delete m_imageListState;
}
-void wxGenericListCtrl::CalculateAndSetHeaderHeight()
+void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded()
{
- if ( m_headerWin )
- {
-#ifdef __WXMAC__
- SInt32 h;
- GetThemeMetric( kThemeMetricListHeaderHeight, &h );
-#else
- // we use 'g' to get the descent, too
- int w, h, d;
- m_headerWin->GetTextExtent(wxT("Hg"), &w, &h, &d);
- h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
-#endif
+ bool needs_header = HasHeader();
+ bool has_header = (m_headerWin != NULL);
- // only update if changed
- if ( h != m_headerHeight )
- {
- m_headerHeight = h;
-
- if ( HasHeader() )
- ResizeReportView(true);
- else //why is this needed if it doesn't have a header?
- m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
- }
- }
-}
+ if (needs_header == has_header)
+ return;
-void wxGenericListCtrl::CreateHeaderWindow()
-{
- m_headerWin = new wxListHeaderWindow
+ if (needs_header)
+ {
+ m_headerWin = new wxListHeaderWindow
(
this, wxID_ANY, m_mainWin,
wxPoint(0,0),
wxSize(GetClientSize().x, m_headerHeight),
wxTAB_TRAVERSAL
);
- CalculateAndSetHeaderHeight();
+
+#if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
+ wxFont font;
+#if wxOSX_USE_ATSU_TEXT
+ font.MacCreateFromThemeFont( kThemeSmallSystemFont );
+#else
+ font.MacCreateFromUIFont( kCTFontSystemFontType );
+#endif
+ m_headerWin->SetFont( font );
+#endif
+
+ GetSizer()->Prepend( m_headerWin, 0, wxGROW );
+ }
+ else
+ {
+ GetSizer()->Detach( m_headerWin );
+
+ delete m_headerWin;
+
+ m_headerWin = NULL;
+ }
}
bool wxGenericListCtrl::Create(wxWindow *parent,
const wxValidator &validator,
const wxString &name)
{
- m_imageListNormal =
- m_imageListSmall =
- m_imageListState = (wxImageList *) NULL;
- m_ownsImageListNormal =
- m_ownsImageListSmall =
- m_ownsImageListState = false;
-
- m_mainWin = (wxListMainWindow*) NULL;
- m_headerWin = (wxListHeaderWindow*) NULL;
-
- m_headerHeight = 0;
+ Init();
- if ( !(style & wxLC_MASK_TYPE) )
- {
- style = style | wxLC_LIST;
- }
+ // just like in other ports, an assert will fail if the user doesn't give any type style:
+ wxASSERT_MSG( (style & wxLC_MASK_TYPE),
+ _T("wxListCtrl style should have exactly one mode bit set") );
- if ( !wxControl::Create( parent, id, pos, size, style, validator, name ) )
+ if ( !wxControl::Create( parent, id, pos, size, style|wxVSCROLL|wxHSCROLL, validator, name ) )
return false;
- // this window itself shouldn't get the focus, only m_mainWin should
- SetCanFocus(false);
-
- // don't create the inner window with the border
+#ifdef __WXGTK__
style &= ~wxBORDER_MASK;
+ style |= wxBORDER_THEME;
+#endif
m_mainWin = new wxListMainWindow( this, wxID_ANY, wxPoint(0, 0), size, style );
-#ifdef __WXMAC__
- // Human Interface Guidelines ask us for a special font in this case
- if ( GetWindowVariant() == wxWINDOW_VARIANT_NORMAL )
+ SetTargetWindow( m_mainWin );
+
+ wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
+ sizer->Add( m_mainWin, 1, wxGROW );
+ SetSizer( sizer );
+
+ CreateOrDestroyHeaderWindowAsNeeded();
+
+ SetInitialSize(size);
+
+ return true;
+}
+
+wxBorder wxGenericListCtrl::GetDefaultBorder() const
+{
+ return wxBORDER_THEME;
+}
+
+#ifdef __WXMSW__
+WXLRESULT wxGenericListCtrl::MSWWindowProc(WXUINT nMsg,
+ WXWPARAM wParam,
+ WXLPARAM lParam)
+{
+ WXLRESULT rc = wxControl::MSWWindowProc(nMsg, wParam, lParam);
+
+#ifndef __WXWINCE__
+ // we need to process arrows ourselves for scrolling
+ if ( nMsg == WM_GETDLGCODE )
{
- wxFont font;
- font.MacCreateFromThemeFont( kThemeViewsFont );
- SetFont( font );
+ rc |= DLGC_WANTARROWS;
}
#endif
- if ( InReportView() )
- {
- CreateHeaderWindow();
-
-#ifdef __WXMAC__
- if (m_headerWin)
- {
- wxFont font;
- font.MacCreateFromThemeFont( kThemeSmallSystemFont );
- m_headerWin->SetFont( font );
- CalculateAndSetHeaderHeight();
- }
+ return rc;
+}
#endif
- if ( HasFlag(wxLC_NO_HEADER) )
- // VZ: why do we create it at all then?
- m_headerWin->Show( false );
- }
+wxSize wxGenericListCtrl::GetSizeAvailableForScrollTarget(const wxSize& size)
+{
+ wxSize newsize = size;
+ if (m_headerWin)
+ newsize.y -= m_headerWin->GetSize().y;
- SetInitialSize(size);
+ return newsize;
+}
- return true;
+void wxGenericListCtrl::OnScroll(wxScrollWinEvent& event)
+{
+ // update our idea of which lines are shown when we redraw
+ // the window the next time
+ m_mainWin->ResetVisibleLinesRange();
+
+ HandleOnScroll( event );
+
+ if ( event.GetOrientation() == wxHORIZONTAL && HasHeader() )
+ {
+ m_headerWin->Refresh();
+ m_headerWin->Update();
+ }
}
void wxGenericListCtrl::SetSingleStyle( long style, bool add )
else
flag &= ~style;
- SetWindowStyleFlag( flag );
+ // some styles can be set without recreating everything (as happens in
+ // SetWindowStyleFlag() which calls wxListMainWindow::DeleteEverything())
+ if ( !(style & ~(wxLC_HRULES | wxLC_VRULES)) )
+ {
+ Refresh();
+ wxWindow::SetWindowStyleFlag(flag);
+ }
+ else
+ {
+ SetWindowStyleFlag( flag );
+ }
}
void wxGenericListCtrl::SetWindowStyleFlag( long flag )
{
if (m_mainWin)
{
- m_mainWin->DeleteEverything();
+ // m_mainWin->DeleteEverything(); wxMSW doesn't do that
- // has the header visibility changed?
- bool hasHeader = HasHeader();
- bool willHaveHeader = (flag & wxLC_REPORT) && !(flag & wxLC_NO_HEADER);
-
- if ( hasHeader != willHaveHeader )
- {
- // toggle it
- if ( hasHeader )
- {
- if ( m_headerWin )
- {
- // don't delete, just hide, as we can reuse it later
- m_headerWin->Show(false);
- }
- //else: nothing to do
- }
- else // must show header
- {
- if (!m_headerWin)
- {
- CreateHeaderWindow();
- }
- else // already have it, just show
- {
- m_headerWin->Show( true );
- }
- }
+ CreateOrDestroyHeaderWindowAsNeeded();
- ResizeReportView(willHaveHeader);
- }
+ GetSizer()->Layout();
}
wxWindow::SetWindowStyleFlag( flag );
return m_mainWin->GetViewRect();
}
-bool wxGenericListCtrl::GetItemRect( long item, wxRect &rect, int WXUNUSED(code) ) const
+bool wxGenericListCtrl::GetItemRect(long item, wxRect& rect, int code) const
+{
+ return GetSubItemRect(item, wxLIST_GETSUBITEMRECT_WHOLEITEM, rect, code);
+}
+
+bool wxGenericListCtrl::GetSubItemRect(long item,
+ long subItem,
+ wxRect& rect,
+ int WXUNUSED(code)) const
{
- m_mainWin->GetItemRect( item, rect );
+ if ( !m_mainWin->GetSubItemRect( item, subItem, rect ) )
+ return false;
+
if ( m_mainWin->HasHeader() )
rect.y += m_headerHeight + 1;
+
return true;
}
bool wxGenericListCtrl::SetItemPosition( long WXUNUSED(item), const wxPoint& WXUNUSED(pos) )
{
- return 0;
+ return false;
}
int wxGenericListCtrl::GetItemCount() const
return info.GetBackgroundColour();
}
-int wxGenericListCtrl::GetScrollPos( int orient ) const
-{
- return m_mainWin->GetScrollPos( orient );
-}
-
-void wxGenericListCtrl::SetScrollPos( int orient, int pos, bool refresh )
-{
- m_mainWin->SetScrollPos( orient, pos, refresh );
-}
-
void wxGenericListCtrl::SetItemFont( long item, const wxFont &f )
{
wxListItem info;
else if (which == wxIMAGE_LIST_STATE)
return m_imageListState;
- return (wxImageList *) NULL;
+ return NULL;
}
void wxGenericListCtrl::SetImageList( wxImageList *imageList, int which )
m_mainWin->DeleteColumn( col );
// if we don't have the header any longer, we need to relayout the window
- if ( !GetColumnCount() )
- ResizeReportView(false /* no header */);
+ // if ( !GetColumnCount() )
+
return true;
}
// if we hadn't had a header before but have one now
// then we need to relayout the window
- if ( GetColumnCount() == 1 && m_mainWin->HasHeader() )
- ResizeReportView(true /* have header */);
+ // if ( GetColumnCount() == 1 && m_mainWin->HasHeader() )
m_headerWin->Refresh();
void wxGenericListCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
{
- if ( !m_mainWin )
- return;
+ if (!m_mainWin) return;
- ResizeReportView(m_mainWin->HasHeader());
- m_mainWin->RecalculatePositions();
-}
+ // We need to override OnSize so that our scrolled
+ // window a) does call Layout() to use sizers for
+ // positioning the controls but b) does not query
+ // the sizer for their size and use that for setting
+ // the scrollable area as set that ourselves by
+ // calling SetScrollbar() further down.
-void wxGenericListCtrl::ResizeReportView(bool showHeader)
-{
- int cw, ch;
- GetClientSize( &cw, &ch );
+ Layout();
- if ( showHeader )
- {
- m_headerWin->SetSize( 0, 0, cw, m_headerHeight );
- if(ch > m_headerHeight)
- m_mainWin->SetSize( 0, m_headerHeight + 1,
- cw, ch - m_headerHeight - 1 );
- else
- m_mainWin->SetSize( 0, m_headerHeight + 1,
- cw, 0);
- }
- else // no header window
- {
- m_mainWin->SetSize( 0, 0, cw, ch );
- }
+ m_mainWin->RecalculatePositions();
+
+ AdjustScrollbars();
}
void wxGenericListCtrl::OnInternalIdle()
{
wxWindow::OnInternalIdle();
- // do it only if needed
- if ( !m_mainWin->m_dirty )
- return;
-
- m_mainWin->RecalculatePositions();
+ if (m_mainWin->m_dirty)
+ m_mainWin->RecalculatePositions();
}
// ----------------------------------------------------------------------------
if (m_headerWin)
{
m_headerWin->SetFont( font );
- CalculateAndSetHeaderHeight();
+ // CalculateAndSetHeaderHeight();
}
Refresh();
#else
wxUnusedVar(variant);
wxVisualAttributes attr;
- attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+ attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOXTEXT);
attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
attr.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
return attr;
}
}
-void wxGenericListCtrl::Freeze()
-{
- m_mainWin->Freeze();
-}
-
-void wxGenericListCtrl::Thaw()
-{
- m_mainWin->Thaw();
-}
-
#endif // wxUSE_LISTCTRL