X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/35ec54d3c5e64c8c479192cf53bf75897afc923c..29149a64916d6fdc53e445adca9ef83bc58fb6c3:/src/msw/listctrl.cpp diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 8d58bde1da..1d73b061d6 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -29,6 +29,8 @@ #pragma hdrstop #endif +#if wxUSE_LISTCTRL + #ifdef __WIN95__ #ifndef WX_PRECOMP @@ -40,12 +42,12 @@ #include "wx/textctrl.h" #include "wx/imaglist.h" - #include "wx/listctrl.h" +#include "wx/dcclient.h" #include "wx/msw/private.h" -#ifdef __GNUWIN32_OLD__ +#if ((defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) && !defined(__CYGWIN10__)) #include "wx/msw/gnuwin32/extra.h" #else #include @@ -72,12 +74,33 @@ static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem, HWND getFullInfo = 0); // ---------------------------------------------------------------------------- -// macros +// events // ---------------------------------------------------------------------------- +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK) +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) + IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) +BEGIN_EVENT_TABLE(wxListCtrl, wxControl) + EVT_PAINT(wxListCtrl::OnPaint) +END_EVENT_TABLE() + // ============================================================================ // implementation // ============================================================================ @@ -126,6 +149,7 @@ void wxListCtrl::Init() m_imageListNormal = NULL; m_imageListSmall = NULL; m_imageListState = NULL; + m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE; m_baseStyle = 0; m_colCount = 0; m_textCtrl = NULL; @@ -168,6 +192,10 @@ bool wxListCtrl::Create(wxWindow *parent, DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | LVS_SHAREIMAGELISTS | LVS_SHOWSELALWAYS; + + if ( m_windowStyle & wxCLIP_SIBLINGS ) + wstyle |= WS_CLIPSIBLINGS; + if ( wxStyleHasBorder(m_windowStyle) ) wstyle |= WS_BORDER; m_baseStyle = wstyle; @@ -280,6 +308,10 @@ wxListCtrl::~wxListCtrl() delete m_textCtrl; m_textCtrl = NULL; } + + if (m_ownsImageListNormal) delete m_imageListNormal; + if (m_ownsImageListSmall) delete m_imageListSmall; + if (m_ownsImageListState) delete m_imageListState; } // ---------------------------------------------------------------------------- @@ -599,6 +631,9 @@ bool wxListCtrl::GetItem(wxListItem& info) const if (info.m_mask & wxLIST_MASK_DATA) lvItem.mask |= LVIF_PARAM; + if (info.m_mask & wxLIST_MASK_IMAGE) + lvItem.mask |= LVIF_IMAGE; + if ( info.m_mask & wxLIST_MASK_STATE ) { lvItem.mask |= LVIF_STATE; @@ -629,27 +664,40 @@ bool wxListCtrl::SetItem(wxListItem& info) LV_ITEM item; wxConvertToMSWListItem(this, info, item); + item.cchTextMax = 0; + if ( !ListView_SetItem(GetHwnd(), &item) ) + { + wxLogDebug(_T("ListView_SetItem() failed")); + + return FALSE; + } + + // we need to update the item immediately to show the new image + bool updateNow = (info.m_mask & wxLIST_MASK_IMAGE) != 0; + // check whether it has any custom attributes if ( info.HasAttributes() ) { - wxListItemAttr *attr; - attr = (wxListItemAttr*) m_attrs.Get(item.iItem); - if (attr == NULL) + wxListItemAttr *attr = (wxListItemAttr *)m_attrs.Get(item.iItem); + + if ( attr == NULL ) m_attrs.Put(item.iItem, (wxObject *)new wxListItemAttr(*info.GetAttributes())); - else *attr = *info.GetAttributes(); + else + *attr = *info.GetAttributes(); m_hasAnyAttr = TRUE; + + // if the colour has changed, we must redraw the item + updateNow = TRUE; } - item.cchTextMax = 0; - bool ok = ListView_SetItem(GetHwnd(), &item) != 0; - if ( ok && (info.m_mask & wxLIST_MASK_IMAGE) ) + if ( updateNow ) { - // make the change visible + // we need this to make the change visible right now ListView_Update(GetHwnd(), item.iItem); } - return ok; + return TRUE; } long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId) @@ -697,7 +745,7 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask) } // Sets the item image -bool wxListCtrl::SetItemImage(long item, int image, int selImage) +bool wxListCtrl::SetItemImage(long item, int image, int WXUNUSED(selImage)) { wxListItem info; @@ -901,21 +949,38 @@ void wxListCtrl::SetImageList(wxImageList *imageList, int which) if ( which == wxIMAGE_LIST_NORMAL ) { flags = LVSIL_NORMAL; + if (m_ownsImageListNormal) delete m_imageListNormal; m_imageListNormal = imageList; + m_ownsImageListNormal = FALSE; } else if ( which == wxIMAGE_LIST_SMALL ) { flags = LVSIL_SMALL; + if (m_ownsImageListSmall) delete m_imageListSmall; m_imageListSmall = imageList; + m_ownsImageListSmall = FALSE; } else if ( which == wxIMAGE_LIST_STATE ) { flags = LVSIL_STATE; + if (m_ownsImageListState) delete m_imageListState; m_imageListState = imageList; + m_ownsImageListState = FALSE; } ListView_SetImageList(GetHwnd(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags); } +void wxListCtrl::AssignImageList(wxImageList *imageList, int which) +{ + SetImageList(imageList, which); + if ( which == wxIMAGE_LIST_NORMAL ) + m_ownsImageListNormal = TRUE; + else if ( which == wxIMAGE_LIST_SMALL ) + m_ownsImageListSmall = TRUE; + else if ( which == wxIMAGE_LIST_STATE ) + m_ownsImageListState = TRUE; +} + // ---------------------------------------------------------------------------- // Operations // ---------------------------------------------------------------------------- @@ -990,6 +1055,8 @@ wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) { wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) ); + // VS: ListView_EditLabel requires that the list has focus. + SetFocus(); HWND hWnd = (HWND) ListView_EditLabel(GetHwnd(), item); if (m_textCtrl) @@ -1008,7 +1075,7 @@ wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass) } // End label editing, optionally cancelling the edit -bool wxListCtrl::EndEditLabel(bool cancel) +bool wxListCtrl::EndEditLabel(bool WXUNUSED(cancel)) { wxFAIL; @@ -1048,8 +1115,10 @@ long wxListCtrl::FindItem(long start, const wxString& str, bool partial) // ListView_FindItem() excludes the first item from search and to look // through all the items you need to start from -1 which is unnatural and - // inconsitent with the generic version - so we adjust the index - return ListView_FindItem(GetHwnd(), (int) start - 1, &findInfo); + // inconsistent with the generic version - so we adjust the index + if (start != -1) + start --; + return ListView_FindItem(GetHwnd(), (int) start, &findInfo); } // Find an item whose data matches this data, starting from the item after 'start' @@ -1128,10 +1197,14 @@ long wxListCtrl::InsertItem(wxListItem& info) // check whether it has any custom attributes if ( info.HasAttributes() ) { + wxListItemAttr *attr; attr = (wxListItemAttr*) m_attrs.Get(item.iItem); + if (attr == NULL) + m_attrs.Put(item.iItem, (wxObject *)new wxListItemAttr(*info.GetAttributes())); + else *attr = *info.GetAttributes(); m_hasAnyAttr = TRUE; @@ -1433,10 +1506,13 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - // or activate the selected item if any - if ( lItem != -1 && (wVKey == VK_RETURN || wVKey == VK_SPACE) ) + // or activate the selected item if any (but + // not with Shift and/or Ctrl as then they have a predefined + // meaning for the list view) + if ( lItem != -1 && + (wVKey == VK_RETURN || wVKey == VK_SPACE) && + !(wxIsShiftDown() || wxIsCtrlDown()) ) { - // TODO this behaviour probably should be optional eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; event.m_itemIndex = lItem; } @@ -1503,6 +1579,8 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { eventType = wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK; event.m_itemIndex = lvhti.iItem; + event.m_pointDrag.x = lvhti.pt.x; + event.m_pointDrag.y = lvhti.pt.y; } } } @@ -1606,7 +1684,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) return TRUE; } } - break; +// break; // can never be reached #endif // _WIN32_IE >= 0x300 default: @@ -1674,6 +1752,71 @@ wxChar *wxListCtrl::AddPool(const wxString& str) return (wxChar *)node->Data(); } +// Necessary for drawing hrules and vrules, if specified +void wxListCtrl::OnPaint(wxPaintEvent& event) +{ + wxPaintDC dc(this); + + wxControl::OnPaint(event); + + // Reset the device origin since it may have been set + dc.SetDeviceOrigin(0, 0); + + bool drawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0); + bool drawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0); + + if (!drawHRules && !drawVRules) + return; + if ((GetWindowStyle() & wxLC_REPORT) == 0) + return; + + wxPen pen(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID); + dc.SetPen(pen); + dc.SetBrush(* wxTRANSPARENT_BRUSH); + + wxSize clientSize = GetClientSize(); + wxRect itemRect; + int cy=0; + + int itemCount = GetItemCount(); + int i; + for (i = 0; i < itemCount; i++) + { + if (GetItemRect(i, itemRect)) + { + 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)) + { + cy = itemRect.GetBottom(); + dc.DrawLine(0, cy, clientSize.x, cy); + } + } + } + i = (GetItemCount() - 1); + if (drawVRules && (i > -1)) + { + wxRect firstItemRect; + GetItemRect(0, firstItemRect); + + if (GetItemRect(i, itemRect)) + { + int col; + int x = itemRect.GetX(); + for (col = 0; col < GetColumnCount(); col++) + { + int colWidth = GetColumnWidth(col); + x += colWidth ; + dc.DrawLine(x, firstItemRect.GetY() - 2, x, itemRect.GetBottom()); + } + } + } +} + // ---------------------------------------------------------------------------- // wxListItem // ---------------------------------------------------------------------------- @@ -1718,7 +1861,7 @@ void wxListItem::ClearAttributes() m_attr = NULL; } -static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo) +static void wxConvertFromMSWListItem(const wxListCtrl *WXUNUSED(ctrl), wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo) { info.m_data = lvItem.lParam; info.m_mask = 0; @@ -1849,7 +1992,7 @@ static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ } else { - lvItem.pszText = WXSTRINGCAST info.m_text; + lvItem.pszText = info.m_text; if ( lvItem.pszText ) lvItem.cchTextMax = info.m_text.Length(); else @@ -1880,3 +2023,4 @@ wxListEvent::wxListEvent(wxEventType commandType, int id) #endif // __WIN95__ +#endif // wxUSE_LISTCTRL