#include "wx/renderer.h"
+#ifdef __WXMAC__
+ #include "wx/mac/private.h"
+#endif
+
+// NOTE: If using the wxListBox visual attributes works everywhere then this can
+// be removed, as well as the #else case below.
+#define _USE_VISATTR 0
+
+
// ----------------------------------------------------------------------------
// events
// ----------------------------------------------------------------------------
// // the height of the header window (FIXME: should depend on its font!)
// static const int HEADER_HEIGHT = 23;
-// the scrollbar units
static const int SCROLL_UNIT_X = 15;
-static const int SCROLL_UNIT_Y = 15;
// the spacing between the lines (in report mode)
static const int LINE_SPACING = 0;
// extra margins around the text label
-static const int EXTRA_WIDTH = 3;
+static const int EXTRA_WIDTH = 4;
static const int EXTRA_HEIGHT = 4;
// margin between the window and the items
// do we have a header window?
bool HasHeader() const
- { return HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER); }
+ { return InReportView() && !HasFlag(wxLC_NO_HEADER); }
void HighlightAll( bool on );
else // has label
{
dc->GetTextExtent( s, &lw, &lh );
- if (lh < SCROLL_UNIT_Y)
- lh = SCROLL_UNIT_Y;
lw += EXTRA_WIDTH;
lh += EXTRA_HEIGHT;
s = item->GetTextForMeasuring();
dc->GetTextExtent( s, &lw, &lh );
- if (lh < SCROLL_UNIT_Y)
- lh = SCROLL_UNIT_Y;
lw += EXTRA_WIDTH;
lh += EXTRA_HEIGHT;
bool wxListLineData::Highlight( bool on )
{
- wxCHECK_MSG( !m_owner->IsVirtual(), FALSE, _T("unexpected call to Highlight") );
+ wxCHECK_MSG( !IsVirtual(), FALSE, _T("unexpected call to Highlight") );
if ( on == m_highlighted )
return FALSE;
m_owner = owner;
m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
- SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+#if _USE_VISATTR
+ wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
+ SetDefaultForegroundColour( attr.colFg );
+ SetDefaultBackgroundColour( attr.colBg );
+ SetDefaultFont( attr.font );
+#else
+ SetDefaultForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+ SetDefaultBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
+ SetDefaultFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT ));
+#endif
}
wxListHeaderWindow::~wxListHeaderWindow()
dc.SetBackgroundMode(wxTRANSPARENT);
- // do *not* use the listctrl colour for headers - one day we will have a
- // function to set it separately
- //dc.SetTextForeground( *wxBLACK );
- dc.SetTextForeground(wxSystemSettings::
- GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
-
+ dc.SetTextForeground(GetForegroundColour());
+
int x = HEADER_OFFSET_X;
int numColumns = m_owner->GetColumnCount();
// for this we need the width of the text
wxCoord wLabel;
- dc.GetTextExtent(item.GetText(), &wLabel, NULL);
+ wxCoord hLabel;
+ dc.GetTextExtent(item.GetText(), &wLabel, &hLabel);
wLabel += 2*EXTRA_WIDTH;
// and the width of the icon, if any
wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
dc.DrawText( item.GetText(),
- xAligned + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT );
+ xAligned + EXTRA_WIDTH, h / 2 - hLabel / 2 ); //HEADER_OFFSET_Y + EXTRA_HEIGHT );
x += wCol;
}
{
m_isDragging = TRUE;
m_currentX = x;
- DrawCurrent();
CaptureMouse();
+ DrawCurrent();
}
//else: column resizing was vetoed by the user code
}
void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
{
m_owner->SetFocus();
+ m_owner->Update();
}
bool wxListHeaderWindow::SendListEvent(wxEventType type, wxPoint pos)
{
// We must finish regardless of success, otherwise we'll get focus problems
Finish();
-
+
if ( !AcceptChanges() )
m_owner->OnRenameCancelled( m_itemEdited );
}
-
+
event.Skip();
}
wxSize sz = size;
sz.y = 25;
- SetScrollbars( SCROLL_UNIT_X, SCROLL_UNIT_Y, 0, 0, 0, 0 );
+ SetScrollbars( 0, 0, 0, 0, 0, 0 );
- SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX ) );
+ wxVisualAttributes attr = wxGenericListCtrl::GetClassDefaultAttributes();
+ SetDefaultForegroundColour( attr.colFg );
+ SetDefaultBackgroundColour( attr.colBg );
+ SetDefaultFont( attr.font );
}
wxListMainWindow::~wxListMainWindow()
wxCoord wxListMainWindow::GetLineHeight() const
{
- wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") );
-
// we cache the line height as calling GetTextExtent() is slow
if ( !m_lineHeight )
{
wxCoord y;
dc.GetTextExtent(_T("H"), NULL, &y);
- if ( y < SCROLL_UNIT_Y )
- y = SCROLL_UNIT_Y;
-
if ( m_small_image_list && m_small_image_list->GetImageCount() )
{
int iw = 0;
wxCoord wxListMainWindow::GetLineY(size_t line) const
{
- wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("only works in report mode") );
+ wxASSERT_MSG( InReportView(), _T("only works in report mode") );
return LINE_SPACING + line*GetLineHeight();
}
void wxListMainWindow::RefreshLine( size_t line )
{
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
size_t visibleFrom, visibleTo;
GetVisibleLinesRange(&visibleFrom, &visibleTo);
wxASSERT_MSG( lineTo < GetItemCount(), _T("invalid line range") );
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
size_t visibleFrom, visibleTo;
GetVisibleLinesRange(&visibleFrom, &visibleTo);
void wxListMainWindow::RefreshAfter( size_t lineFrom )
{
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
size_t visibleFrom, visibleTo;
GetVisibleLinesRange(&visibleFrom, &visibleTo);
dc.SetFont( GetFont() );
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
int lineHeight = GetLineHeight();
{
wxPen pen(GetRuleColour(), 1, wxSOLID);
- int col = 0;
wxRect firstItemRect;
wxRect lastItemRect;
GetItemRect(visibleFrom, firstItemRect);
int x = firstItemRect.GetX();
dc.SetPen(pen);
dc.SetBrush(* wxTRANSPARENT_BRUSH);
- for (col = 0; col < GetColumnCount(); col++)
+ for (int col = 0; col < GetColumnCount(); col++)
{
int colWidth = GetColumnWidth(col);
x += colWidth;
}
}
+#ifndef __WXMAC__
+ // Don't draw rect outline under Mac at all.
if ( HasCurrent() )
{
- // don't draw rect outline under Max if we already have the background
- // color but under other platforms only draw it if we do: it is a bit
- // silly to draw "focus rect" if we don't have focus!
-#ifdef __WXMAC__
- if ( !m_hasFocus )
-#else // !__WXMAC__
if ( m_hasFocus )
-#endif // __WXMAC__/!__WXMAC__
{
dc.SetPen( *wxBLACK_PEN );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle( GetLineHighlightRect(m_current) );
}
}
+#endif
dc.EndDrawing();
}
le.IsAllowed();
}
-#ifdef __VMS__ // Ignore unreacheable code
-# pragma message disable initnotreach
-#endif
-
void wxListMainWindow::OnRenameCancelled(size_t itemEdit)
{
- // wxMSW seems not to notify the program about
- // cancelled label edits.
- return;
-
// let owner know that the edit was cancelled
wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() );
-
- // These only exist for wxTreeCtrl, which should probably be changed
- // le.m_editCancelled = TRUE;
- // le.m_label = wxEmptyString;
-
+
+ le.SetEditCanceled(TRUE);
+
le.SetEventObject( GetParent() );
le.m_itemIndex = itemEdit;
GetEventHandler()->ProcessEvent( le );
}
-#ifdef __VMS__
-# pragma message enable initnotreach
-#endif
void wxListMainWindow::OnMouse( wxMouseEvent &event )
{
size_t count = GetItemCount(),
current;
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
current = y / GetLineHeight();
if ( current < count )
int client_w, client_h;
GetClientSize( &client_w, &client_h );
+ const int hLine = GetLineHeight();
+
int view_x = SCROLL_UNIT_X*GetScrollPos( wxHORIZONTAL );
- int view_y = SCROLL_UNIT_Y*GetScrollPos( wxVERTICAL );
+ int view_y = hLine*GetScrollPos( wxVERTICAL );
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
// the next we need the range of lines shown it might be different, so
// recalculate it
ResetVisibleLinesRange();
if (rect.y < view_y )
- Scroll( -1, rect.y/SCROLL_UNIT_Y );
+ Scroll( -1, rect.y/hLine );
if (rect.y+rect.height+5 > view_y+client_h)
- Scroll( -1, (rect.y+rect.height-client_h+SCROLL_UNIT_Y)/SCROLL_UNIT_Y );
+ Scroll( -1, (rect.y+rect.height-client_h+hLine)/hLine );
}
else // !report
{
{
ChangeCurrent(newCurrent);
+ // refresh the old focus to remove it
+ RefreshLine( oldCurrent );
+
// select all the items between the old and the new one
if ( oldCurrent > newCurrent )
{
HighlightAll(FALSE);
ChangeCurrent(newCurrent);
-
+
// refresh the old focus to remove it
RefreshLine( oldCurrent );
HighlightLine( m_current, TRUE );
}
}
-
+
RefreshLine( m_current );
MoveToFocus();
case WXK_PRIOR:
{
- int steps = 0;
- if ( HasFlag(wxLC_REPORT) )
- {
- steps = m_linesPerPage - 1;
- }
- else
- {
- steps = m_current % m_linesPerPage;
- }
+ int steps = InReportView() ? m_linesPerPage - 1 : m_current % m_linesPerPage;
int index = m_current - steps;
if (index < 0)
case WXK_NEXT:
{
- int steps = 0;
- if ( HasFlag(wxLC_REPORT) )
- {
- steps = m_linesPerPage - 1;
- }
- else
- {
- steps = m_linesPerPage - (m_current % m_linesPerPage) - 1;
- }
+ int steps = InReportView()
+ ? m_linesPerPage - 1
+ : m_linesPerPage - (m_current % m_linesPerPage) - 1;
size_t index = m_current + steps;
size_t count = GetItemCount();
break;
case WXK_LEFT:
- if ( !HasFlag(wxLC_REPORT) )
+ if ( !InReportView() )
{
int index = m_current - m_linesPerPage;
if (index < 0)
break;
case WXK_RIGHT:
- if ( !HasFlag(wxLC_REPORT) )
+ if ( !InReportView() )
{
size_t index = m_current + m_linesPerPage;
void wxListMainWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
{
+ if ( GetParent() )
+ {
+ wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
+ event.SetEventObject( GetParent() );
+ if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
+ return;
+ }
+
// wxGTK sends us EVT_SET_FOCUS events even if we had never got
// EVT_KILL_FOCUS before which means that we finish by redrawing the items
// which are already drawn correctly resulting in horrible flicker - avoid
RefreshSelected();
}
-
- if ( !GetParent() )
- return;
-
- wxFocusEvent event( wxEVT_SET_FOCUS, GetParent()->GetId() );
- event.SetEventObject( GetParent() );
- GetParent()->GetEventHandler()->ProcessEvent( event );
}
void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
{
+ if ( GetParent() )
+ {
+ wxFocusEvent event( wxEVT_KILL_FOCUS, GetParent()->GetId() );
+ event.SetEventObject( GetParent() );
+ if ( GetParent()->GetEventHandler()->ProcessEvent( event) )
+ return;
+ }
m_hasFocus = FALSE;
-
RefreshSelected();
}
{
m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
}
- else if ( HasFlag(wxLC_REPORT) && (m_small_image_list))
+ else if ( InReportView() && (m_small_image_list))
{
m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
}
{
m_small_image_list->GetSize( index, width, height );
}
- else if ( HasFlag(wxLC_REPORT) && m_small_image_list )
+ else if ( InReportView() && m_small_image_list )
{
m_small_image_list->GetSize( index, width, height );
}
wxCHECK_RET( col >= 0 && col < GetColumnCount(),
_T("invalid column index") );
- wxCHECK_RET( HasFlag(wxLC_REPORT),
+ wxCHECK_RET( InReportView(),
_T("SetColumnWidth() can only be called in report mode.") );
m_dirty = TRUE;
clientHeight;
GetSize( &clientWidth, &clientHeight );
- if ( HasFlag(wxLC_REPORT) )
+ const int lineHeight = GetLineHeight();
+
+ if ( InReportView() )
{
// all lines have the same height and we scroll one line per step
- int lineHeight = GetLineHeight();
-
int entireHeight = count*lineHeight + LINE_SPACING;
m_linesPerPage = clientHeight / lineHeight;
SetScrollbars
(
SCROLL_UNIT_X,
- SCROLL_UNIT_Y,
+ lineHeight,
(x + SCROLL_UNIT_X) / SCROLL_UNIT_X,
- (y + SCROLL_UNIT_Y) / SCROLL_UNIT_Y,
+ (y + lineHeight) / lineHeight,
GetScrollPos( wxHORIZONTAL ),
GetScrollPos( wxVERTICAL ),
TRUE
// the window, we recalculate after subtracting the space taken by the
// scrollbar
- int entireWidth = 0,
- entireHeight = 0;
+ int entireWidth = 0;
for (int tries = 0; tries < 2; tries++)
{
entireWidth = 2*EXTRA_BORDER_X;
- entireHeight = 2*EXTRA_BORDER_Y;
if (tries == 1)
{
clientHeight -= wxSystemSettings::
GetMetric(wxSYS_HSCROLL_Y);
m_linesPerPage = 0;
- currentlyVisibleLines = 0;
break;
}
SetScrollbars
(
SCROLL_UNIT_X,
- SCROLL_UNIT_Y,
+ lineHeight,
(entireWidth + SCROLL_UNIT_X) / SCROLL_UNIT_X,
0,
GetScrollPos( wxHORIZONTAL ),
size_t count = GetItemCount();
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
size_t current = y / GetLineHeight();
if ( current < count )
m_dirty = TRUE;
+ #if 0
+ // this is unused variable
int mode = 0;
- if ( HasFlag(wxLC_REPORT) )
+ #endif
+ if ( InReportView() )
{
+ #if 0
+ // this is unused variable
mode = wxLC_REPORT;
+ #endif
ResetVisibleLinesRange();
}
else if ( HasFlag(wxLC_LIST) )
+ #if 0
+ // this is unused variable
mode = wxLC_LIST;
+ #else
+ {}
+ #endif
else if ( HasFlag(wxLC_ICON) )
+ #if 0
+ // this is unused variable
mode = wxLC_ICON;
+ #else
+ {}
+ #endif
else if ( HasFlag(wxLC_SMALL_ICON) )
+ #if 0
+ // this is unused variable
mode = wxLC_ICON; // no typo
+ #else
+ {}
+ #endif
else
{
wxFAIL_MSG( _T("unknown mode") );
m_dirty = TRUE;
+ // If an item is selected at or below the point of insertion, we need to
+ // increment the member variables because the current row's index has gone
+ // up by one
+ if ( HasCurrent() && m_current >= id )
+ {
+ m_current++;
+ }
+
SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM);
RefreshLines(id, GetItemCount() - 1);
void wxListMainWindow::InsertColumn( long col, wxListItem &item )
{
m_dirty = TRUE;
- if ( HasFlag(wxLC_REPORT) )
+ if ( InReportView() )
{
if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
item.m_width = GetTextLength( item.m_text );
void wxListMainWindow::GetVisibleLinesRange(size_t *from, size_t *to)
{
- wxASSERT_MSG( HasFlag(wxLC_REPORT), _T("this is for report mode only") );
+ wxASSERT_MSG( InReportView(), _T("this is for report mode only") );
if ( m_lineFrom == (size_t)-1 )
{
void wxGenericListCtrl::CalculateAndSetHeaderHeight()
{
- // we use the letter "H" for calculating the needed space, basing on the current font
- int w, h;
- m_headerWin->GetTextExtent(wxT("H"), &w, &h);
- m_headerHeight = h + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
- m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
+ if ( m_headerWin )
+ {
+ // 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;
+
+ // only update if changed
+ if ( h != m_headerHeight )
+ {
+ m_headerHeight = h;
+
+ m_headerWin->SetSize(m_headerWin->GetSize().x, m_headerHeight);
+
+ if ( HasHeader() )
+ ResizeReportView(TRUE);
+ }
+ }
}
void wxGenericListCtrl::CreateHeaderWindow()
m_mainWin = (wxListMainWindow*) NULL;
m_headerWin = (wxListHeaderWindow*) NULL;
+ m_headerHeight = 0;
+
if ( !(style & wxLC_MASK_TYPE) )
{
style = style | wxLC_LIST;
m_mainWin = new wxListMainWindow( this, -1, wxPoint(0,0), size, style );
- if ( HasFlag(wxLC_REPORT) )
+#if defined( __WXMAC__ ) && __WXMAC_CARBON__
+ wxFont font ;
+ font.MacCreateThemeFont( kThemeViewsFont ) ;
+ SetFont( font ) ;
+#endif
+ if ( InReportView() )
{
CreateHeaderWindow();
}
}
+ SetBestSize(size);
+
return TRUE;
}
m_mainWin->DeleteEverything();
// has the header visibility changed?
- bool hasHeader = HasFlag(wxLC_REPORT) && !HasFlag(wxLC_NO_HEADER),
- willHaveHeader = (flag & wxLC_REPORT) && !(flag & wxLC_NO_HEADER);
+ bool hasHeader = HasHeader();
+ bool willHaveHeader = (flag & wxLC_REPORT) && !(flag & wxLC_NO_HEADER);
if ( hasHeader != willHaveHeader )
{
void wxGenericListCtrl::OnInternalIdle()
{
wxWindow::OnInternalIdle();
-
+
// do it only if needed
if ( !m_mainWin->m_dirty )
return;
return TRUE;
}
+
+
+#if _USE_VISATTR
+#include "wx/listbox.h"
+#endif
+
+//static
+wxVisualAttributes
+wxGenericListCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
+{
+#if _USE_VISATTR
+ // Use the same color scheme as wxListBox
+ return wxListBox::GetClassDefaultAttributes(variant);
+#else
+ wxUnusedVar(variant);
+ wxVisualAttributes attr;
+ attr.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+ attr.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX);
+ attr.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ return attr;
+#endif
+}
+
// ----------------------------------------------------------------------------
// methods forwarded to m_mainWin
// ----------------------------------------------------------------------------
return -1;
}
-wxListItemAttr *wxGenericListCtrl::OnGetItemAttr(long item) const
+wxListItemAttr *
+wxGenericListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
{
wxASSERT_MSG( item >= 0 && item < GetItemCount(),
_T("invalid item index in OnGetItemAttr()") );