X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bdc72a22686ac141e9bc4559a1171d017fdcb094..18d2e17080a0bea4b85e0ad7223cfc6bcdab0e1e:/src/msw/listctrl.cpp diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 5bb0d8f862..f747968d69 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -19,6 +19,7 @@ #ifdef __GNUG__ #pragma implementation "listctrl.h" + #pragma implementation "listctrlbase.h" #endif // For compilers that support precompilation, includes "wx.h". @@ -39,7 +40,7 @@ #include "wx/msw/private.h" -#if defined(__GNUWIN32__) && !defined(wxUSE_NORLANDER_HEADERS) +#ifdef __GNUWIN32_OLD__ #include "wx/msw/gnuwin32/extra.h" #else #include @@ -61,15 +62,48 @@ static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, L // macros // ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl) - IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) -#endif // USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl) +IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) // ============================================================================ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxListEvent +// ---------------------------------------------------------------------------- + +void wxListEvent::CopyObject(wxObject& object_dest) const +{ + wxListEvent *obj = (wxListEvent *)&object_dest; + + wxNotifyEvent::CopyObject(object_dest); + + obj->m_code = m_code; + obj->m_itemIndex = m_itemIndex; + obj->m_oldItemIndex = m_oldItemIndex; + obj->m_col = m_col; + obj->m_cancelled = m_cancelled; + obj->m_pointDrag = m_pointDrag; + obj->m_item.m_mask = m_item.m_mask; + obj->m_item.m_itemId = m_item.m_itemId; + obj->m_item.m_col = m_item.m_col; + obj->m_item.m_state = m_item.m_state; + obj->m_item.m_stateMask = m_item.m_stateMask; + obj->m_item.m_text = m_item.m_text; + obj->m_item.m_image = m_item.m_image; + obj->m_item.m_data = m_item.m_data; + obj->m_item.m_format = m_item.m_format; + obj->m_item.m_width = m_item.m_width; + + if ( m_item.HasAttributes() ) + { + obj->m_item.SetTextColour(m_item.GetTextColour()); + obj->m_item.SetBackgroundColour(m_item.GetBackgroundColour()); + obj->m_item.SetFont(m_item.GetFont()); + } +} + // ---------------------------------------------------------------------------- // wxListCtrl construction // ---------------------------------------------------------------------------- @@ -93,7 +127,10 @@ bool wxListCtrl::Create(wxWindow *parent, const wxValidator& validator, const wxString& name) { +#if wxUSE_VALIDATORS SetValidator(validator); +#endif // wxUSE_VALIDATORS + SetName(name); int x = pos.x; @@ -202,9 +239,30 @@ void wxListCtrl::UpdateStyle() } } +void wxListCtrl::FreeAllAttrs(bool dontRecreate) +{ + if ( m_hasAnyAttr ) + { + for ( wxNode *node = m_attrs.Next(); node; node = m_attrs.Next() ) + { + delete (wxListItemAttr *)node->Data(); + } + + m_attrs.Destroy(); + if ( !dontRecreate ) + { + m_attrs.Create(wxKEY_INTEGER, 1000); // just as def ctor + } + + m_hasAnyAttr = FALSE; + } +} + wxListCtrl::~wxListCtrl() { - if (m_textCtrl) + FreeAllAttrs(TRUE /* no need to recreate hash any more */); + + if ( m_textCtrl ) { m_textCtrl->UnsubclassWin(); m_textCtrl->SetHWND(0); @@ -364,14 +422,28 @@ long wxListCtrl::ConvertToMSWStyle(long& oldStyle, long style) const // accessors // ---------------------------------------------------------------------------- -// Sets the background colour (GetBackgroundColour already implicit in -// wxWindow class) +// Sets the foreground, i.e. text, colour +bool wxListCtrl::SetForegroundColour(const wxColour& col) +{ + if ( !wxWindow::SetForegroundColour(col) ) + return FALSE; + + ListView_SetTextColor(GetHwnd(), wxColourToRGB(col)); + + return TRUE; +} + +// Sets the background colour bool wxListCtrl::SetBackgroundColour(const wxColour& col) { if ( !wxWindow::SetBackgroundColour(col) ) return FALSE; - ListView_SetBkColor(GetHwnd(), PALETTERGB(col.Red(), col.Green(), col.Blue())); + // we set the same colour for both the "empty" background and the items + // background + COLORREF color = wxColourToRGB(col); + ListView_SetBkColor(GetHwnd(), color); + ListView_SetTextBkColor(GetHwnd(), color); return TRUE; } @@ -482,13 +554,13 @@ bool wxListCtrl::SetColumnWidth(int col, int width) // visible area of the list control (list or report view) // or the total number of items in the list control (icon // or small icon view) -int wxListCtrl::GetCountPerPage(void) const +int wxListCtrl::GetCountPerPage() const { return ListView_GetCountPerPage(GetHwnd()); } // Gets the edit control for editing labels. -wxTextCtrl* wxListCtrl::GetEditControl(void) const +wxTextCtrl* wxListCtrl::GetEditControl() const { return m_textCtrl; } @@ -549,20 +621,10 @@ bool wxListCtrl::SetItem(wxListItem& info) // check whether it has any custom attributes if ( info.HasAttributes() ) { - // FIXME it should be... - wxASSERT_MSG( !info.GetData(), - _T("can't have custom attributes and client data") ); - - item.mask |= LVIF_PARAM; - item.lParam = (long)info.GetAttributes(); + m_attrs.Put(item.iItem, (wxObject *)new wxListItemAttr(*info.GetAttributes())); m_hasAnyAttr = TRUE; } - else if ( m_hasAnyAttr ) - { - item.mask |= LVIF_PARAM; - item.lParam = 0; - } item.cchTextMax = 0; bool ok = ListView_SetItem(GetHwnd(), &item) != 0; @@ -725,7 +787,7 @@ bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos) } // Gets the number of items in the list control -int wxListCtrl::GetItemCount(void) const +int wxListCtrl::GetItemCount() const { return ListView_GetItemCount(GetHwnd()); } @@ -739,13 +801,13 @@ int wxListCtrl::GetItemSpacing(bool isSmall) const } // Gets the number of selected items in the list control -int wxListCtrl::GetSelectedItemCount(void) const +int wxListCtrl::GetSelectedItemCount() const { return ListView_GetSelectedCount(GetHwnd()); } // Gets the text colour of the listview -wxColour wxListCtrl::GetTextColour(void) const +wxColour wxListCtrl::GetTextColour() const { COLORREF ref = ListView_GetTextColor(GetHwnd()); wxColour col(GetRValue(ref), GetGValue(ref), GetBValue(ref)); @@ -760,7 +822,7 @@ void wxListCtrl::SetTextColour(const wxColour& col) // Gets the index of the topmost visible item when in // list or report view -long wxListCtrl::GetTopItem(void) const +long wxListCtrl::GetTopItem() const { return (long) ListView_GetTopIndex(GetHwnd()); } @@ -1048,20 +1110,10 @@ long wxListCtrl::InsertItem(wxListItem& info) // check whether it has any custom attributes if ( info.HasAttributes() ) { - // FIXME it should be... - wxASSERT_MSG( !info.GetData(), - _T("can't have custom attributes and client data") ); - - item.mask |= LVIF_PARAM; - item.lParam = (long)info.GetAttributes(); + m_attrs.Put(item.iItem, (wxObject *)new wxListItemAttr(*info.GetAttributes())); m_hasAnyAttr = TRUE; } - else if ( m_hasAnyAttr ) - { - item.mask |= LVIF_PARAM; - item.lParam = 0; - } return (long) ListView_InsertItem(GetHwnd(), & item); } @@ -1270,24 +1322,11 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) } case LVN_DELETEALLITEMS: - // what's the sense of generating a wxWin event for this when - // it's absolutely not portable? -#if 0 eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS; event.m_itemIndex = -1; -#endif // 0 - // return TRUE to suppress all additional LVN_DELETEITEM - // notifications - this makes deleting all items from a list ctrl - // much faster (but we can't do it if we have any custom drawn - // items because we need to delete their attributes in - // LVN_DELETEITEM below) - if ( !m_hasAnyAttr ) - { - *result = TRUE; + FreeAllAttrs(); - return TRUE; - } break; case LVN_DELETEITEM: @@ -1298,8 +1337,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) if ( m_hasAnyAttr ) { - wxListItemAttr *attr = (wxListItemAttr *)hdr->lParam; - delete attr; + delete (wxListItemAttr *)m_attrs.Delete(hdr->iItem); } } break; @@ -1403,9 +1441,16 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) } // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event + // if it happened on an item (and not on empty place) { - eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; + if ( hdr->iItem == -1 ) + { + // not on item + return FALSE; + } + + eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; event.m_itemIndex = hdr->iItem; } break; @@ -1457,14 +1502,14 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; #endif // 0 -#ifdef NM_CUSTOMDRAW +#if defined(_WIN32_IE) && _WIN32_IE >= 0x300 case NM_CUSTOMDRAW: { LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam; NMCUSTOMDRAW& nmcd = lplvcd->nmcd; switch( nmcd.dwDrawStage ) { - case CDDS_PREPAINT : + case CDDS_PREPAINT: // if we've got any items with non standard attributes, // notify us before painting each item *result = m_hasAnyAttr ? CDRF_NOTIFYITEMDRAW @@ -1473,34 +1518,72 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) case CDDS_ITEMPREPAINT: { - if ( !nmcd.lItemlParam ) + wxListItemAttr *attr = + (wxListItemAttr *)m_attrs.Get(nmcd.dwItemSpec); + + if ( !attr ) { // nothing to do for this item return CDRF_DODEFAULT; } - wxListItemAttr *attr = - (wxListItemAttr *)nmcd.lItemlParam; + HFONT hFont; + wxColour colText, colBack; + if ( attr->HasFont() ) + { + wxFont font = attr->GetFont(); + hFont = (HFONT)font.GetResourceHandle(); + } + else + { + hFont = 0; + } + + if ( attr->HasTextColour() ) + { + colText = attr->GetTextColour(); + } + else + { + colText = GetTextColour(); + } + + if ( attr->HasBackgroundColour() ) + { + colBack = attr->GetBackgroundColour(); + } + else + { + colBack = GetBackgroundColour(); + } + + // note that if we wanted to set colours for + // individual columns (subitems), we would have + // returned CDRF_NOTIFYSUBITEMREDRAW from here + if ( hFont ) + { + ::SelectObject(nmcd.hdc, hFont); - ::SelectObject(nmcd.hdc, - (HFONT)((wxFont &)attr->GetFont()). - GetResourceHandle()); - lplvcd->clrText = - wxColourToRGB(attr->GetTextColour()); - lplvcd->clrTextBk = - wxColourToRGB(attr->GetBackgroundColour()); + *result = CDRF_NEWFONT; + } + else + { + *result = CDRF_DODEFAULT; + } - // if we wanted to set colours for individual - // columns (subitems), we would have returned - // CDRF_NOTIFYSUBITEMREDRAW from here - *result = CDRF_NEWFONT; + lplvcd->clrText = wxColourToRGB(colText); + lplvcd->clrTextBk = wxColourToRGB(colBack); return TRUE; } + + default: + *result = CDRF_DODEFAULT; + return TRUE; } } break; -#endif // NM_CUSTOMDRAW +#endif // _WIN32_IE >= 0x300 default: return wxControl::MSWOnNotify(idCtrl, lParam, result); @@ -1520,6 +1603,14 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) switch ( (int)nmhdr->code ) { + case LVN_DELETEALLITEMS: + // always return TRUE to suppress all additional LVN_DELETEITEM + // notifications - this makes deleting all items from a list ctrl + // much faster + *result = TRUE; + + return TRUE; + case LVN_GETDISPINFO: { LV_DISPINFO *info = (LV_DISPINFO *)lParam; @@ -1539,8 +1630,6 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) *result = event.IsAllowed(); return TRUE; } - default: - break; } *result = !event.IsAllowed(); @@ -1582,6 +1671,29 @@ wxListItem::wxListItem() m_attr = NULL; } +void wxListItem::Clear() +{ + m_mask = 0; + m_itemId = 0; + m_col = 0; + m_state = 0; + m_stateMask = 0; + m_image = 0; + m_data = 0; + m_format = wxLIST_FORMAT_CENTRE; + m_width = 0; + m_text = wxEmptyString; + + if (m_attr) delete m_attr; + m_attr = NULL; +} + +void wxListItem::ClearAttributes() +{ + if (m_attr) delete m_attr; + m_attr = NULL; +} + static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo) { info.m_data = lvItem.lParam;