#include "wx/textctrl.h"
#endif
-#include "wx/imaglist.h"
-#include "wx/listctrl.h"
+// under Win32 we always use the native version and also may use the generic
+// one, however some things should be done only if we use only the generic
+// version
+#if defined(__WIN32__) && !defined(__WXUNIVERSAL__)
+ #define HAVE_NATIVE_LISTCTRL
+#endif
+
+// if we have the native control, wx/listctrl.h declares it and not this one
+#ifdef HAVE_NATIVE_LISTCTRL
+ #include "wx/generic/listctrl.h"
+#else // !HAVE_NATIVE_LISTCTRL
+ #include "wx/listctrl.h"
+
+ // if we have a native version, its implementation file does all this
+ IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
+ IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
+ IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
+
+ IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl)
+#endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL
#if defined(__WXGTK__)
#include <gtk/gtk.h>
void SetItemCount(size_t count) { m_count = count; }
// special case of SetItemCount(0)
- void Clear() { m_itemsSel.Clear(); m_count = 0; }
+ void Clear() { m_itemsSel.Clear(); m_count = 0; m_defaultState = FALSE; }
// must be called when a new item is inserted/added
void OnItemAdd(size_t item) { wxFAIL_MSG( _T("TODO") ); }
const wxListItemAttr *attr,
bool highlight);
+ // draw the text on the DC with the correct justification; also add an
+ // ellipsis if the text is too large to fit in the current width
+ void DrawTextFormatted(wxDC *dc, const wxString &text, int col, int x, int y, int width);
+
// these are only used by GetImage/SetImage above, we don't support images
// with subitems at the public API level yet
void SetImage( int index, int image );
const wxPoint &pos = wxDefaultPosition,
const wxSize &size = wxDefaultSize,
long style = 0,
- const wxString &name = "wxlistctrlcolumntitles" );
+ const wxString &name = wxT("wxlistctrlcolumntitles") );
virtual ~wxListHeaderWindow();
void GetImageSize( int index, int &width, int &height ) const;
int GetTextLength( const wxString &s ) const;
- void SetImageList( wxImageList *imageList, int which );
+ void SetImageList( wxImageListType *imageList, int which );
void SetItemSpacing( int spacing, bool isSmall = FALSE );
int GetItemSpacing( bool isSmall = FALSE );
wxColour *m_highlightColour;
int m_xScroll,
m_yScroll;
- wxImageList *m_small_image_list;
- wxImageList *m_normal_image_list;
+ wxImageListType *m_small_image_list;
+ wxImageListType *m_normal_image_list;
int m_small_spacing;
int m_normal_spacing;
bool m_hasFocus;
DECLARE_DYNAMIC_CLASS(wxListMainWindow)
DECLARE_EVENT_TABLE()
+
+ friend class wxGenericListCtrl;
};
// ============================================================================
width -= ix;
}
- wxDCClipper clipper(*dc, xOld, y, width, rect.height);
+ wxDCClipper clipper(*dc, xOld, y, width - 8, rect.height);
if ( item->HasText() )
{
- dc->DrawText( item->GetText(), xOld, y );
+ DrawTextFormatted(dc, item->GetText(), col, xOld, y, width - 8);
+ }
+ }
+}
+
+void wxListLineData::DrawTextFormatted(wxDC *dc,
+ const wxString &text,
+ int col,
+ int x,
+ int y,
+ int width)
+{
+ wxString drawntext, ellipsis;
+ wxCoord w, h, base_w;
+ wxListItem item;
+
+ // determine if the string can fit inside the current width
+ dc->GetTextExtent(text, &w, &h);
+ if (w <= width)
+ {
+ // it can, draw it using the items alignment
+ m_owner->GetColumn(col, item);
+ switch ( item.GetAlign() )
+ {
+ default:
+ wxFAIL_MSG( _T("unknown list item format") );
+ // fall through
+
+ case wxLIST_FORMAT_LEFT:
+ // nothing to do
+ break;
+
+ case wxLIST_FORMAT_RIGHT:
+ x += width - w;
+ break;
+
+ case wxLIST_FORMAT_CENTER:
+ x += (width - w) / 2;
+ break;
+ }
+
+ dc->DrawText(text, x, y);
+ }
+ else // otherwise, truncate and add an ellipsis if possible
+ {
+ // determine the base width
+ ellipsis = wxString(wxT("..."));
+ dc->GetTextExtent(ellipsis, &base_w, &h);
+
+ // continue until we have enough space or only one character left
+ drawntext = text.Left(text.Length() - 1);
+ while (drawntext.Length() > 1)
+ {
+ dc->GetTextExtent(drawntext, &w, &h);
+ if (w + base_w <= width)
+ break;
+ drawntext = drawntext.Left(drawntext.Length() - 1);
+ }
+
+ // if still not enough space, remove ellipsis characters
+ while (ellipsis.Length() > 0 && w + base_w > width)
+ {
+ ellipsis = ellipsis.Left(ellipsis.Length() - 1);
+ dc->GetTextExtent(ellipsis, &base_w, &h);
}
+
+ // now draw the text
+ dc->DrawText(drawntext, x, y);
+ dc->DrawText(ellipsis, x + w, y);
}
}
delete m_resizeCursor;
}
+#ifdef __WXUNIVERSAL__
+#include "wx/univ/renderer.h"
+#include "wx/univ/theme.h"
+#endif
+
void wxListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
{
#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
(GdkRectangle*) NULL, m_wxwindow,
(char *)"button", // const_cast
x-1, y-1, w+2, h+2);
-#elif defined( __WXMAC__ )
+#elif defined(__WXUNIVERSAL__)
+ wxTheme *theme = wxTheme::Get();
+ wxRenderer *renderer = theme->GetRenderer();
+ renderer->DrawBorder( *dc, wxBORDER_RAISED, wxRect(x,y,w,h), 0 );
+#elif defined(__WXMAC__)
const int m_corner = 1;
dc->SetBrush( *wxTRANSPARENT_BRUSH );
DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 );
- // if we have an image, draw it on the right of the label
- int image = item.m_image;
+ // see if we have enough space for the column label
+
+ // for this we need the width of the text
+ wxCoord wLabel;
+ dc.GetTextExtent(item.GetText(), &wLabel, NULL);
+ wLabel += 2*EXTRA_WIDTH;
+
+ // and the width of the icon, if any
+ static const int MARGIN_BETWEEN_TEXT_AND_ICON = 2;
+ int ix = 0, // init them just to suppress the compiler warnings
+ iy = 0;
+ const int image = item.m_image;
+ wxImageListType *imageList;
if ( image != -1 )
{
- wxImageList *imageList = m_owner->m_small_image_list;
+ imageList = m_owner->m_small_image_list;
if ( imageList )
{
- int ix, iy;
imageList->GetSize(image, ix, iy);
+ wLabel += ix + MARGIN_BETWEEN_TEXT_AND_ICON;
+ }
+ }
+ else
+ {
+ imageList = NULL;
+ }
- imageList->Draw
- (
- image,
- dc,
- x + cw - ix - 1,
- HEADER_OFFSET_Y + (h - 4 - iy)/2,
- wxIMAGELIST_DRAW_TRANSPARENT
- );
+ // ignore alignment if there is not enough space anyhow
+ int xAligned;
+ switch ( wLabel < cw ? item.GetAlign() : wxLIST_FORMAT_LEFT )
+ {
+ default:
+ wxFAIL_MSG( _T("unknown list item format") );
+ // fall through
- cw -= ix + 2;
- }
- //else: ignore the column image
+ case wxLIST_FORMAT_LEFT:
+ xAligned = x;
+ break;
+
+ case wxLIST_FORMAT_RIGHT:
+ xAligned = x + cw - wLabel;
+ break;
+
+ case wxLIST_FORMAT_CENTER:
+ xAligned = x + (cw - wLabel) / 2;
+ break;
+ }
+
+
+ // if we have an image, draw it on the right of the label
+ if ( imageList )
+ {
+ imageList->Draw
+ (
+ image,
+ dc,
+ xAligned + wLabel - ix - MARGIN_BETWEEN_TEXT_AND_ICON,
+ HEADER_OFFSET_Y + (h - 4 - iy)/2,
+ wxIMAGELIST_DRAW_TRANSPARENT
+ );
+
+ cw -= ix + MARGIN_BETWEEN_TEXT_AND_ICON;
}
// draw the text clipping it so that it doesn't overwrite the column
wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
dc.DrawText( item.GetText(),
- x + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT );
+ xAligned + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT );
x += wCol;
}
m_headerWidth =
m_lineHeight = 0;
- m_small_image_list = (wxImageList *) NULL;
- m_normal_image_list = (wxImageList *) NULL;
+ m_small_image_list = (wxImageListType *) NULL;
+ m_normal_image_list = (wxImageListType *) NULL;
m_small_spacing = 30;
m_normal_spacing = 40;
if ( y < SCROLL_UNIT_Y )
y = SCROLL_UNIT_Y;
- y += EXTRA_HEIGHT;
+ if ( m_small_image_list && m_small_image_list->GetImageCount() )
+ {
+ int iw = 0;
+ int ih = 0;
+ m_small_image_list->GetSize(0, iw, ih);
+ y = wxMax(y, ih);
+ }
+
+ y += EXTRA_HEIGHT;
self->m_lineHeight = y + LINE_SPACING;
}
{
if ( HasFlag(wxLC_REPORT) )
{
- size_t visibleFrom;
- GetVisibleLinesRange(&visibleFrom, NULL);
+ size_t visibleFrom, visibleTo;
+ GetVisibleLinesRange(&visibleFrom, &visibleTo);
if ( lineFrom < visibleFrom )
lineFrom = visibleFrom;
+ else if ( lineFrom > visibleTo )
+ return;
wxRect rect;
rect.x = 0;
rect.y = GetLineY(lineFrom);
+ CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
wxSize size = GetClientSize();
rect.width = size.x;
// refresh till the bottom of the window
rect.height = size.y - rect.y;
- CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
RefreshRect( rect );
}
else // !report
wxPen pen(GetRuleColour(), 1, wxSOLID);
wxSize clientSize = GetClientSize();
- for ( size_t i = visibleFrom; i <= visibleTo; i++ )
+ // Don't draw the first one
+ for ( size_t i = visibleFrom+1; i <= visibleTo; i++ )
{
dc.SetPen(pen);
dc.SetBrush( *wxTRANSPARENT_BRUSH );
}
// Draw last horizontal rule
- if ( visibleTo > visibleFrom )
+ if ( visibleTo == GetItemCount() - 1 )
{
dc.SetPen(pen);
dc.SetBrush( *wxTRANSPARENT_BRUSH );
- dc.DrawLine(0 - dev_x, m_lineTo*lineHeight,
- clientSize.x - dev_x , m_lineTo*lineHeight );
+ dc.DrawLine(0 - dev_x, (m_lineTo+1)*lineHeight,
+ clientSize.x - dev_x , (m_lineTo+1)*lineHeight );
}
}
int col = 0;
wxRect firstItemRect;
wxRect lastItemRect;
- GetItemRect(0, firstItemRect);
- GetItemRect(GetItemCount() - 1, lastItemRect);
+ GetItemRect(visibleFrom, firstItemRect);
+ GetItemRect(visibleTo, lastItemRect);
int x = firstItemRect.GetX();
dc.SetPen(pen);
dc.SetBrush(* wxTRANSPARENT_BRUSH);
{
int colWidth = GetColumnWidth(col);
x += colWidth;
- dc.DrawLine(x - dev_x, firstItemRect.GetY() - 1 - dev_y,
- x - dev_x, lastItemRect.GetBottom() + 1 - dev_y);
+ dc.DrawLine(x - dev_x - 2, firstItemRect.GetY() - 1 - dev_y,
+ x - dev_x - 2, lastItemRect.GetBottom() + 1 - dev_y);
}
}
}
m_renameTimer->Stop();
m_lastOnSame = FALSE;
-#ifdef __WXGTK__
- // FIXME: wxGTK generates bad sequence of events prior to doubleclick
- // ("down, up, down, double, up" while other ports
- // do "down, up, double, up"). We have to have this hack
- // in place till somebody fixes wxGTK...
- if ( current == m_lineBeforeLastClicked )
-#else
if ( current == m_lineLastClicked )
-#endif
{
SendNotify( current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED );
wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, GetParent()->GetId() );
le.m_itemIndex = m_current;
GetLine(m_current)->GetItem( 0, le.m_item );
- le.m_code = (int)event.KeyCode();
+ le.m_code = event.GetKeyCode();
le.SetEventObject( parent );
parent->GetEventHandler()->ProcessEvent( le );
}
ke.SetEventObject( parent );
if (parent->GetEventHandler()->ProcessEvent( ke )) return;
- if (event.KeyCode() == WXK_TAB)
+ if (event.GetKeyCode() == WXK_TAB)
{
wxNavigationKeyEvent nevent;
nevent.SetWindowChange( event.ControlDown() );
return;
}
- switch (event.KeyCode())
+ switch (event.GetKeyCode())
{
case WXK_UP:
if ( m_current > 0 )
return lw + AUTOSIZE_COL_MARGIN;
}
-void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
+void wxListMainWindow::SetImageList( wxImageListType *imageList, int which )
{
m_dirty = TRUE;
{
m_small_image_list = imageList;
m_small_spacing = width + 14;
+ m_lineHeight = 0; // ensure that the line height will be recalc'd
}
}
line->SetItem( item.m_col, item );
}
- if ( InReportView() )
- {
- // just refresh the line to show the new value of the text/image
- RefreshLine((size_t)id);
- }
- else // !report
- {
- // refresh everything (resulting in horrible flicker - FIXME!)
- m_dirty = TRUE;
- }
+ // update the item on screen
+ wxRect rectItem;
+ GetItemRect(id, rectItem);
+ RefreshRect(rectItem);
}
void wxListMainWindow::SetItemState( long litem, long state, long stateMask )
int mode = 0;
if ( HasFlag(wxLC_REPORT) )
+ {
mode = wxLC_REPORT;
+ ResetVisibleLinesRange();
+ }
else if ( HasFlag(wxLC_LIST) )
mode = wxLC_LIST;
else if ( HasFlag(wxLC_ICON) )
*to = m_lineTo;
}
-// -------------------------------------------------------------------------------------
-// wxListItem
-// -------------------------------------------------------------------------------------
-
-#if !defined(__WIN32__)
-IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
-#endif
-
// -------------------------------------------------------------------------------------
// wxGenericListCtrl
// -------------------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxGenericListCtrl, wxControl)
-#if !defined(__WIN32__)
-IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
-
-IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
-#endif
-
BEGIN_EVENT_TABLE(wxGenericListCtrl,wxControl)
EVT_SIZE(wxGenericListCtrl::OnSize)
EVT_IDLE(wxGenericListCtrl::OnIdle)
END_EVENT_TABLE()
-#if !defined(__WXMSW__) || defined(__WIN16__) || defined(__WXUNIVERSAL__)
-/*
- * wxListCtrl has to be a real class or we have problems with
- * the run-time information.
- */
-
-IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxGenericListCtrl)
-#endif
-
wxGenericListCtrl::wxGenericListCtrl()
{
- m_imageListNormal = (wxImageList *) NULL;
- m_imageListSmall = (wxImageList *) NULL;
- m_imageListState = (wxImageList *) NULL;
+ m_imageListNormal = (wxImageListType *) NULL;
+ m_imageListSmall = (wxImageListType *) NULL;
+ m_imageListState = (wxImageListType *) NULL;
m_ownsImageListNormal =
m_ownsImageListSmall =
{
m_imageListNormal =
m_imageListSmall =
- m_imageListState = (wxImageList *) NULL;
+ m_imageListState = (wxImageListType *) NULL;
m_ownsImageListNormal =
m_ownsImageListSmall =
m_ownsImageListState = FALSE;
long wxGenericListCtrl::GetTopItem() const
{
- return 0;
+ size_t top;
+ m_mainWin->GetVisibleLinesRange(&top, NULL);
+ return (long)top;
}
long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const
return m_mainWin->GetNextItem( item, geom, state );
}
-wxImageList *wxGenericListCtrl::GetImageList(int which) const
+wxImageListType *wxGenericListCtrl::GetImageList(int which) const
{
if (which == wxIMAGE_LIST_NORMAL)
{
{
return m_imageListState;
}
- return (wxImageList *) NULL;
+ return (wxImageListType *) NULL;
}
-void wxGenericListCtrl::SetImageList( wxImageList *imageList, int which )
+void wxGenericListCtrl::SetImageList( wxImageListType *imageList, int which )
{
if ( which == wxIMAGE_LIST_NORMAL )
{
m_mainWin->SetImageList( imageList, which );
}
-void wxGenericListCtrl::AssignImageList(wxImageList *imageList, int which)
+void wxGenericListCtrl::AssignImageList(wxImageListType *imageList, int which)
{
SetImageList(imageList, which);
if ( which == wxIMAGE_LIST_NORMAL )