#define LVS_OWNERDATA 0x1000
#endif
+// mingw32/cygwin don't have declarations for comctl32.dll 4.70+ stuff
+#ifndef NM_CACHEHINT
+ typedef struct tagNMLVCACHEHINT
+ {
+ NMHDR hdr;
+ int iFrom;
+ int iTo;
+ } NMLVCACHEHINT;
+
+ #define NM_CACHEHINT NMLVCACHEHINT
+#endif
+
+#ifndef LVN_ODCACHEHINT
+ #define LVN_ODCACHEHINT (-113)
+#endif
+
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
wstyle |= LVS_SORTDESCENDING;
}
+#if !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
if ( style & wxLC_VIRTUAL )
{
int ver = wxTheApp->GetComCtl32Version();
if ( ver < 470 )
{
- wxLogWarning(_("Please install a newer version of comctl32.dll\n"
- "(at least version 4.70 is required but you have "
- "%d.%02d)\n"
- "or this program won't operate correctly."),
+ wxLogWarning(_("Please install a newer version of comctl32.dll\n(at least version 4.70 is required but you have %d.%02d)\nor this program won't operate correctly."),
ver / 100, ver % 100);
}
wstyle |= LVS_OWNERDATA;
}
+#endif
return wstyle;
}
}
else
{
- wxConvertFromMSWListItem(GetHwnd(), info, lvItem);
+ // give NULL as hwnd as we already have everything we need
+ wxConvertFromMSWListItem(NULL, info, lvItem);
}
if (lvItem.pszText)
{
wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) );
- // VS: ListView_EditLabel requires that the list has focus.
+ // VS: ListView_EditLabel requires that the list has focus.
SetFocus();
HWND hWnd = (HWND) ListView_EditLabel(GetHwnd(), item);
// or zero if the two items are equivalent.
// data is arbitrary data to be passed to the sort function.
+
+// FIXME: this is horrible and MT-unsafe and everything else but I don't have
+// time for anything better right now (VZ)
+static long gs_sortData = 0;
+static wxListCtrl *gs_sortCtrl = NULL;
+static wxListCtrlCompare gs_sortFunction = NULL;
+
+int wxCMPFUNC_CONV wxListCtrlCompareFn(const void *arg1, const void *arg2)
+{
+ int n1 = *(const int *)arg1,
+ n2 = *(const int *)arg2;
+
+ return gs_sortFunction(gs_sortCtrl->GetItemData(n1),
+ gs_sortCtrl->GetItemData(n2),
+ gs_sortData);
+}
+
bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
{
- return (ListView_SortItems(GetHwnd(), (PFNLVCOMPARE) fn, data) != 0);
+ // sort the attributes too
+ if ( m_hasAnyAttr )
+ {
+ int n,
+ count = GetItemCount();
+ int *aItems = new int[count];
+ for ( n = 0; n < count; n++ )
+ {
+ aItems[n] = n;
+ }
+
+ gs_sortData = data;
+ gs_sortCtrl = this;
+ gs_sortFunction = fn;
+
+ qsort(aItems, count, sizeof(int), wxListCtrlCompareFn);
+
+ gs_sortData = 0;
+ gs_sortCtrl = NULL;
+ gs_sortFunction = NULL;
+
+ wxHashTable attrsNew(wxKEY_INTEGER, 1000);
+ for ( n = 0; n < count; n++ )
+ {
+ wxObject *attr = m_attrs.Delete(aItems[n]);
+ if ( attr )
+ {
+ attrsNew.Put(n, attr);
+ }
+ }
+
+ m_attrs.Destroy();
+ m_attrs = attrsNew;
+
+ delete [] aItems;
+ }
+
+ if ( !ListView_SortItems(GetHwnd(), (PFNLVCOMPARE)fn, data) )
+ {
+ wxLogDebug(_T("ListView_SortItems() failed"));
+
+ return FALSE;
+ }
+
+ return TRUE;
}
+
+
// ----------------------------------------------------------------------------
// message processing
// ----------------------------------------------------------------------------
break;
#endif // 0
-#if defined(_WIN32_IE) && _WIN32_IE >= 0x300
+#if defined(_WIN32_IE) && _WIN32_IE >= 0x300 \
+ && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
case NM_CUSTOMDRAW:
*result = OnCustomDraw(lParam);
return TRUE;
#endif // _WIN32_IE >= 0x300
+ case LVN_ODCACHEHINT:
+ {
+ const NM_CACHEHINT *cacheHint = (NM_CACHEHINT *)lParam;
+
+ eventType = wxEVT_COMMAND_LIST_CACHE_HINT;
+
+ // we get some really stupid cache hints like ones for items in
+ // range 0..0 for an empty control or, after deleting an item,
+ // for items in invalid range - filter this garbage out
+ if ( cacheHint->iFrom < cacheHint->iTo )
+ {
+ event.m_oldItemIndex = cacheHint->iFrom;
+
+ long iMax = GetItemCount();
+ event.m_itemIndex = cacheHint->iTo < iMax ? cacheHint->iTo
+ : iMax - 1;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ break;
+
case LVN_GETDISPINFO:
if ( IsVirtual() )
{
return TRUE;
case LVN_ENDLABELEDIT:
- {
- *result = event.IsAllowed();
- return TRUE;
- }
+ // logic here is inversed compared to all the other messages
+ *result = event.IsAllowed();
+
+ return TRUE;
}
*result = !event.IsAllowed();
int itemCount = GetItemCount();
int i;
- for (i = 0; i < itemCount; i++)
+ if (drawHRules)
{
- if (GetItemRect(i, itemRect))
+ long top = GetTopItem();
+ for (i = top; i < top + GetCountPerPage() + 1; i++)
{
- cy = itemRect.GetTop();
- if (i != 0) // Don't draw the first one
- {
- dc.DrawLine(0, cy, clientSize.x, cy);
- }
- // Draw last line
- if (i == (GetItemCount() - 1))
+ if (GetItemRect(i, itemRect))
{
- cy = itemRect.GetBottom();
- dc.DrawLine(0, cy, clientSize.x, cy);
+ cy = itemRect.GetTop();
+ if (i != 0) // Don't draw the first one
+ {
+ dc.DrawLine(0, cy, clientSize.x, cy);
+ }
+ // Draw last line
+ if (i == itemCount - 1)
+ {
+ cy = itemRect.GetBottom();
+ dc.DrawLine(0, cy, clientSize.x, cy);
+ }
}
}
}
- i = (GetItemCount() - 1);
+ i = itemCount - 1;
if (drawVRules && (i > -1))
{
wxRect firstItemRect;
// virtual list controls
// ----------------------------------------------------------------------------
-wxString wxListCtrl::OnGetItemText(long item, long col) const
+wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) const
{
// this is a pure virtual function, in fact - which is not really pure
// because the controls which are not virtual don't need to implement it
return wxEmptyString;
}
-int wxListCtrl::OnGetItemImage(long item) const
+int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
{
// same as above
wxFAIL_MSG( _T("not supposed to be called") );
return -1;
}
-wxListItemAttr *wxListCtrl::OnGetItemAttr(long item) const
+wxListItemAttr *wxListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const
{
wxASSERT_MSG( item >= 0 && item < GetItemCount(),
_T("invalid item index in OnGetItemAttr()") );
void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
{
- for ( long item = itemFrom; item <= itemTo; item++ )
- {
- RefreshItem(item);
- }
+ wxRect rect1, rect2;
+ GetItemRect(itemFrom, rect1);
+ GetItemRect(itemTo, rect2);
+
+ wxRect rect = rect1;
+ rect.height = rect2.GetBottom() - rect1.GetTop();
+
+ RefreshRect(rect);
}
// ----------------------------------------------------------------------------