X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fb9010ed40454cc978a9cbaa6de2ee41ea8b6c84..2b0246530d08cf7724d94c70d631c166f9717c2c:/src/os2/listbox.cpp?ds=sidebyside diff --git a/src/os2/listbox.cpp b/src/os2/listbox.cpp index a3df98c3cf..475e9f8143 100644 --- a/src/os2/listbox.cpp +++ b/src/os2/listbox.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: listbox.cpp +// Name: src/os2/listbox.cpp // Purpose: wxListBox // Author: David Webster // Modified by: @@ -21,7 +21,9 @@ #include "wx/brush.h" #include "wx/font.h" #include "wx/dc.h" +#include "wx/dcscreen.h" #include "wx/utils.h" +#include "wx/scrolwin.h" #endif #define INCL_M @@ -30,13 +32,13 @@ #include "wx/dynarray.h" #include "wx/log.h" +#if wxUSE_LISTBOX + #if wxUSE_OWNER_DRAWN #include "wx/ownerdrw.h" #endif -#if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) -#endif // ============================================================================ // list box item declaration and implementation @@ -47,19 +49,26 @@ class wxListBoxItem : public wxOwnerDrawn { public: - wxListBoxItem(const wxString& str = ""); + wxListBoxItem(const wxString& rsStr = wxEmptyString); }; -wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE) +wxListBoxItem::wxListBoxItem( + const wxString& rsStr +) +: wxOwnerDrawn( rsStr + ,false + ) { - // no bitmaps/checkmarks + // + // No bitmaps/checkmarks + // SetMarginWidth(0); -} +} // end of wxListBoxItem::wxListBoxItem -wxOwnerDrawn *wxListBox::CreateItem(size_t n) +wxOwnerDrawn* wxListBox::CreateItem( size_t WXUNUSED(n) ) { return new wxListBoxItem(); -} +} // end of wxListBox::CreateItem #endif //USE_OWNER_DRAWN @@ -67,675 +76,870 @@ wxOwnerDrawn *wxListBox::CreateItem(size_t n) // list box control implementation // ============================================================================ -bool wxListBox::OS2Command(WXUINT param, WXWORD WXUNUSED(id)) -{ -/* - if (param == LBN_SELCHANGE) - { - wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId); - wxArrayInt aSelections; - int count = GetSelections(aSelections); - if ( count > 0 ) - { - event.m_commandInt = aSelections[0] ; - event.m_clientData = GetClientData(event.m_commandInt); - wxString str(GetString(event.m_commandInt)); - if (str != wxT("")) - { - event.m_commandString = str; - } - } - else - { - event.m_commandInt = -1 ; - event.m_commandString.Empty(); - } - - event.SetEventObject( this ); - ProcessCommand(event); - return TRUE; - } - else if (param == LBN_DBLCLK) - { - wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId); - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event) ; - return TRUE; - } -*/ - return FALSE; -} // Listbox item wxListBox::wxListBox() { - m_noItems = 0; - m_selected = 0; -} + m_nNumItems = 0; + m_nSelected = 0; +} // end of wxListBox::wxListBox + +bool wxListBox::Create( + wxWindow* pParent +, wxWindowID vId +, const wxPoint& rPos +, const wxSize& rSize +, const wxArrayString& asChoices +, long lStyle +, const wxValidator& rValidator +, const wxString& rsName +) +{ + wxCArrayString chs(asChoices); + + return Create(pParent, vId, rPos, rSize, chs.GetCount(), chs.GetStrings(), + lStyle, rValidator, rsName); +} + +bool wxListBox::Create( + wxWindow* pParent +, wxWindowID vId +, const wxPoint& rPos +, const wxSize& rSize +, int n +, const wxString asChoices[] +, long lStyle +, const wxValidator& rValidator +, const wxString& rsName +) +{ + m_nNumItems = 0; + m_hWnd = 0; + m_nSelected = 0; + + SetName(rsName); +#if wxUSE_VALIDATORS + SetValidator(rValidator); +#endif -bool wxListBox::Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos, - const wxSize& size, - int n, const wxString choices[], - long style, - const wxValidator& validator, - const wxString& name) -{ - m_noItems = n; - m_hWnd = 0; - m_selected = 0; + if (pParent) + pParent->AddChild(this); - SetName(name); - SetValidator(validator); + wxSystemSettings vSettings; - if (parent) parent->AddChild(this); + SetBackgroundColour(vSettings.GetColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(pParent->GetForegroundColour()); - wxSystemSettings settings; - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); - SetForegroundColour(parent->GetForegroundColour()); + m_windowId = (vId == -1) ? (int)NewControlId() : vId; - m_windowId = ( id == -1 ) ? (int)NewControlId() : id; + int nX = rPos.x; + int nY = rPos.y; + int nWidth = rSize.x; + int nHeight = rSize.y; - int x = pos.x; - int y = pos.y; - int width = size.x; - int height = size.y; - m_windowStyle = style; + m_windowStyle = lStyle; - // TODO create listbox -/* - DWORD wstyle = WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | - LBS_NOTIFY | LBS_HASSTRINGS; + lStyle = WS_VISIBLE; + + if (m_windowStyle & wxCLIP_SIBLINGS ) + lStyle |= WS_CLIPSIBLINGS; if (m_windowStyle & wxLB_MULTIPLE) - wstyle |= LBS_MULTIPLESEL; + lStyle |= LS_MULTIPLESEL; else if (m_windowStyle & wxLB_EXTENDED) - wstyle |= LBS_EXTENDEDSEL; - - if (m_windowStyle & wxLB_ALWAYS_SB) - wstyle |= LBS_DISABLENOSCROLL ; + lStyle |= LS_EXTENDEDSEL; if (m_windowStyle & wxLB_HSCROLL) - wstyle |= WS_HSCROLL; - if (m_windowStyle & wxLB_SORT) - wstyle |= LBS_SORT; - -#if wxUSE_OWNER_DRAWN - if ( m_windowStyle & wxLB_OWNERDRAW ) { - // we don't support LBS_OWNERDRAWVARIABLE yet - wstyle |= LBS_OWNERDRAWFIXED; - } -#endif + lStyle |= LS_HORZSCROLL; + if (m_windowStyle & wxLB_OWNERDRAW) + lStyle |= LS_OWNERDRAW; + // // Without this style, you get unexpected heights, so e.g. constraint layout // doesn't work properly - wstyle |= LBS_NOINTEGRALHEIGHT; - - bool want3D; - WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; - - // Even with extended styles, need to combine with WS_BORDER - // for them to look right. - if ( want3D || wxStyleHasBorder(m_windowStyle) ) + // + lStyle |= LS_NOADJUSTPOS; + + m_hWnd = (WXHWND)::WinCreateWindow( GetWinHwnd(pParent) // Parent + ,WC_LISTBOX // Default Listbox class + ,"LISTBOX" // Control's name + ,lStyle // Initial Style + ,0, 0, 0, 0 // Position and size + ,GetWinHwnd(pParent) // Owner + ,HWND_TOP // Z-Order + ,(HMENU)m_windowId // Id + ,NULL // Control Data + ,NULL // Presentation Parameters + ); + if (m_hWnd == 0) { - wstyle |= WS_BORDER; + return false; } - m_hWnd = (WXHWND)::CreateWindowEx(exStyle, wxT("LISTBOX"), NULL, - wstyle | WS_CHILD, - 0, 0, 0, 0, - (HWND)parent->GetHWND(), (HMENU)m_windowId, - wxGetInstance(), NULL); - -#if wxUSE_CTL3D - if (want3D) - { - Ctl3dSubclassCtl(GetHwnd()); - m_useCtl3D = TRUE; - } -#endif - - // Subclass again to catch messages + // + // Subclass again for purposes of dialog editing mode + // SubclassWin(m_hWnd); - size_t ui; - for (ui = 0; ui < (size_t)n; ui++) { - Append(choices[ui]); - } - - if ( (m_windowStyle & wxLB_MULTIPLE) == 0 ) - SendMessage(GetHwnd(), LB_SETCURSEL, 0, 0); - - SetFont(parent->GetFont()); - - SetSize(x, y, width, height); + LONG lUi; - Show(TRUE); -*/ - - return FALSE; -} + for (lUi = 0; lUi < (LONG)n; lUi++) + { + Append(asChoices[lUi]); + } + wxFont* pTextFont = new wxFont( 10 + ,wxMODERN + ,wxNORMAL + ,wxNORMAL + ); + SetFont(*pTextFont); + + // + // Set standard wxWidgets colors for Listbox items and highlighting + // + wxColour vColour; + + vColour.Set(wxString(wxT("WHITE"))); + + LONG lColor = (LONG)vColour.GetPixel(); + + ::WinSetPresParam( m_hWnd + ,PP_HILITEFOREGROUNDCOLOR + ,sizeof(LONG) + ,(PVOID)&lColor + ); + vColour.Set(wxString(wxT("NAVY"))); + lColor = (LONG)vColour.GetPixel(); + ::WinSetPresParam( m_hWnd + ,PP_HILITEBACKGROUNDCOLOR + ,sizeof(LONG) + ,(PVOID)&lColor + ); + + SetSize( nX + ,nY + ,nWidth + ,nHeight + ); + delete pTextFont; + return true; +} // end of wxListBox::Create wxListBox::~wxListBox() { #if wxUSE_OWNER_DRAWN - size_t uiCount = m_aItems.Count(); - while ( uiCount-- != 0 ) { - delete m_aItems[uiCount]; + size_t lUiCount = m_aItems.Count(); + + while (lUiCount-- != 0) + { + delete m_aItems[lUiCount]; } #endif // wxUSE_OWNER_DRAWN -} +} // end of wxListBox::~wxListBox void wxListBox::SetupColours() { - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); SetForegroundColour(GetParent()->GetForegroundColour()); -} +} // end of wxListBox::SetupColours -void wxListBox::SetFirstItem(int N) -{ - wxCHECK_RET( N >= 0 && N < m_noItems, - wxT("invalid index in wxListBox::SetFirstItem") ); +// ---------------------------------------------------------------------------- +// implementation of wxListBoxBase methods +// ---------------------------------------------------------------------------- - // TODO SendMessage(GetHwnd(),LB_SETTOPINDEX,(WPARAM)N,(LPARAM)0) ; -} - -void wxListBox::SetFirstItem(const wxString& s) +void wxListBox::DoSetFirstItem( + int N +) { - int N = FindString(s) ; + wxCHECK_RET( N >= 0 && N < m_nNumItems, + wxT("invalid index in wxListBox::SetFirstItem") ); - if ( N >= 0 ) - SetFirstItem(N) ; -} + ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX, MPFROMLONG(N), (MPARAM)0); +} // end of wxListBox::DoSetFirstItem -void wxListBox::Delete(int N) +void wxListBox::Delete( + int N +) { - wxCHECK_RET( N >= 0 && N < m_noItems, + wxCHECK_RET( N >= 0 && N < m_nNumItems, wxT("invalid index in wxListBox::Delete") ); - // TODO SendMessage(GetHwnd(), LB_DELETESTRING, N, 0); - m_noItems --; - SetHorizontalExtent(""); -} - -void wxListBox::Append(const wxString& item) -{ - int index=0; // TODO = ListBox_AddString(GetHwnd(), item); - m_noItems ++; - #if wxUSE_OWNER_DRAWN - if ( m_windowStyle & wxLB_OWNERDRAW ) { - wxOwnerDrawn *pNewItem = CreateItem(index); // dummy argument - pNewItem->SetName(item); - m_aItems.Add(pNewItem); -// ListBox_SetItemData(GetHwnd(), index, pNewItem); + delete m_aItems[N]; + m_aItems.RemoveAt(N); +#else // !wxUSE_OWNER_DRAWN + if (HasClientObjectData()) + { + delete GetClientObject(N); } -#endif +#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN - SetHorizontalExtent(item); -} + ::WinSendMsg(GetHwnd(), LM_DELETEITEM, (MPARAM)N, (MPARAM)0); + m_nNumItems--; +} // end of wxListBox::DoSetFirstItem -void wxListBox::Append(const wxString& item, void *Client_data) +int wxListBox::DoAppend( + const wxString& rsItem +) { - int index; // TODO = ListBox_AddString(GetHwnd(), item); - m_noItems ++; + long lIndex = 0; + LONG lIndexType = 0; -#if wxUSE_OWNER_DRAWN - if ( m_windowStyle & wxLB_OWNERDRAW ) { - // client data must be pointer to wxOwnerDrawn, otherwise we would crash - // in OnMeasure/OnDraw. - wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); - } + if (m_windowStyle & wxLB_SORT) + lIndexType = LIT_SORTASCENDING; else -#endif + lIndexType = LIT_END; + lIndex = (long)::WinSendMsg(GetHwnd(), LM_INSERTITEM, (MPARAM)lIndexType, (MPARAM)rsItem.c_str()); + m_nNumItems++; - // TODO ListBox_SetItemData(GetHwnd(), index, Client_data); +#if wxUSE_OWNER_DRAWN + if (m_windowStyle & wxLB_OWNERDRAW) + { + wxOwnerDrawn* pNewItem = CreateItem(lIndex); // dummy argument + wxScreenDC vDc; - SetHorizontalExtent(item); -} -void wxListBox::Set(int n, const wxString *choices, char** clientData) + pNewItem->SetName(rsItem); + m_aItems.Insert(pNewItem, lIndex); + ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, (MPARAM)lIndex, MPFROMP(pNewItem)); + pNewItem->SetFont(GetFont()); + } +#endif + return (int)lIndex; +} // end of wxListBox::DoAppend + +void wxListBox::DoSetItems( + const wxArrayString& raChoices +, void** ppClientData +) { -// ShowWindow(GetHwnd(), SW_HIDE); -// ListBox_ResetContent(GetHwnd()); - int i; - for (i = 0; i < n; i++) + BOOL bHideAndShow = IsShown(); + int i; + LONG lIndexType = 0; + + if (bHideAndShow) { -// ListBox_AddString(GetHwnd(), choices[i]); -// if ( clientData ) -// ListBox_SetItemData(GetHwnd(), i, clientData[i]); + ::WinShowWindow(GetHwnd(), FALSE); } - m_noItems = n; + ::WinSendMsg(GetHwnd(), LM_DELETEALL, (MPARAM)0, (MPARAM)0); + m_nNumItems = raChoices.GetCount(); + for (i = 0; i < m_nNumItems; i++) + { + + if (m_windowStyle & wxLB_SORT) + lIndexType = LIT_SORTASCENDING; + else + lIndexType = LIT_END; + ::WinSendMsg(GetHwnd(), LM_INSERTITEM, (MPARAM)lIndexType, (MPARAM)raChoices[i].c_str()); + if (ppClientData) + { #if wxUSE_OWNER_DRAWN - if ( m_windowStyle & wxLB_OWNERDRAW ) { - // first delete old items - size_t ui = m_aItems.Count(); - while ( ui-- != 0 ) { - delete m_aItems[ui]; + wxASSERT_MSG(ppClientData[i] == NULL, + wxT("Can't use client data with owner-drawn listboxes")); +#else // !wxUSE_OWNER_DRAWN + ::WinSendMsg(WinUtil_GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(lCount), MPFROMP(ppClientData[i])); +#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN } - m_aItems.Empty(); + } - // then create new ones - for (ui = 0; ui < (size_t)n; ui++) { - wxOwnerDrawn *pNewItem = CreateItem(ui); - pNewItem->SetName(choices[ui]); - m_aItems.Add(pNewItem); -// ListBox_SetItemData(GetHwnd(), ui, pNewItem); +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) + { + // + // First delete old items + // + WX_CLEAR_ARRAY(m_aItems); + + // + // Then create new ones + // + for (size_t ui = 0; ui < (size_t)m_nNumItems; ui++) + { + wxOwnerDrawn* pNewItem = CreateItem(ui); - wxASSERT_MSG(clientData[ui] == NULL, - wxT("Can't use client data with owner-drawn listboxes")); + pNewItem->SetName(raChoices[ui]); + m_aItems.Add(pNewItem); + ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(ui), MPFROMP(pNewItem)); } } -#endif - - SetHorizontalExtent(""); -// ShowWindow(GetHwnd(), SW_SHOW); -} - -int wxListBox::FindString(const wxString& s) const -{ - int pos; // = ListBox_FindStringExact(GetHwnd(), (WPARAM)-1, s); -// if (pos == LB_ERR) -// return -1; -// else - return pos; -} +#endif // wxUSE_OWNER_DRAWN + ::WinShowWindow(GetHwnd(), TRUE); +} // end of wxListBox::DoSetItems void wxListBox::Clear() { -// ListBox_ResetContent(GetHwnd()); - #if wxUSE_OWNER_DRAWN - size_t uiCount = m_aItems.Count(); - while ( uiCount-- != 0 ) { - delete m_aItems[uiCount]; + size_t lUiCount = m_aItems.Count(); + + while (lUiCount-- != 0) + { + delete m_aItems[lUiCount]; } m_aItems.Clear(); -#endif // wxUSE_OWNER_DRAWN +#else // !wxUSE_OWNER_DRAWN + if (HasClientObjectData()) + { + for (size_t n = 0; n < (size_t)m_lNumItems; n++) + { + delete GetClientObject(n); + } + } +#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN + ::WinSendMsg(GetHwnd(), LM_DELETEALL, (MPARAM)0, (MPARAM)0); - m_noItems = 0; -// ListBox_GetHorizontalExtent(GetHwnd()); -} + m_nNumItems = 0; +} // end of wxListBox::Clear -void wxListBox::SetSelection(int N, bool select) +void wxListBox::DoSetSelection( + int N +, bool bSelect +) { - wxCHECK_RET( N >= 0 && N < m_noItems, + wxCHECK_RET( N >= 0 && N < m_nNumItems, wxT("invalid index in wxListBox::SetSelection") ); + ::WinSendMsg( GetHwnd() + ,LM_SELECTITEM + ,MPFROMLONG(N) + ,(MPARAM)bSelect + ); + if(m_windowStyle & wxLB_OWNERDRAW) + Refresh(); +} // end of wxListBox::SetSelection + +bool wxListBox::IsSelected( + int N +) const +{ + wxCHECK_MSG( N >= 0 && N < m_nNumItems, false, + wxT("invalid index in wxListBox::Selected") ); - if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) + LONG lItem; + + if (GetWindowStyleFlag() & wxLB_EXTENDED) { -// SendMessage(GetHwnd(), LB_SETSEL, select, N); + if (N == 0) + lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0)); + else + lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)(N - 1), (MPARAM)0)); } else { - int N1 = N; - if (!select) - N1 = -1; -// SendMessage(GetHwnd(), LB_SETCURSEL, N1, 0); + lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0)); } -} + return (lItem == (LONG)N && lItem != LIT_NONE); +} // end of wxListBox::IsSelected -bool wxListBox::Selected(int N) const +wxClientData* wxListBox::DoGetItemClientObject( + int n +) const { - wxCHECK_MSG( N >= 0 && N < m_noItems, FALSE, - wxT("invalid index in wxListBox::Selected") ); - -// return SendMessage(GetHwnd(), LB_GETSEL, N, 0) == 0 ? FALSE : TRUE; - return FALSE; + return (wxClientData *)DoGetItemClientData(n); } -void wxListBox::Deselect(int N) +void* wxListBox::DoGetItemClientData( + int n +) const { - wxCHECK_RET( N >= 0 && N < m_noItems, - wxT("invalid index in wxListBox::Deselect") ); + wxCHECK_MSG( n >= 0 && n < m_nNumItems, NULL, + wxT("invalid index in wxListBox::GetClientData") ); - if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) - { -// SendMessage(GetHwnd(), LB_SETSEL, FALSE, N); - } -} + return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE, MPFROMLONG(n), (MPARAM)0)); +} // end of wxListBox::DoGetItemClientData -void *wxListBox::GetClientData(int N) const +void wxListBox::DoSetItemClientObject( + int n +, wxClientData* pClientData +) { - wxCHECK_MSG( N >= 0 && N < m_noItems, NULL, - wxT("invalid index in wxListBox::GetClientData") ); - -// return (void *)SendMessage(GetHwnd(), LB_GETITEMDATA, N, 0); - return (char *)NULL; -} + DoSetItemClientData( n + ,pClientData + ); +} // end of wxListBox::DoSetItemClientObject -void wxListBox::SetClientData(int N, void *Client_data) +void wxListBox::DoSetItemClientData( + int n +, void* pClientData +) { - wxCHECK_RET( N >= 0 && N < m_noItems, + wxCHECK_RET( n >= 0 && n < m_nNumItems, wxT("invalid index in wxListBox::SetClientData") ); -// if ( ListBox_SetItemData(GetHwnd(), N, Client_data) == LB_ERR ) -// wxLogDebug(wxT("LB_SETITEMDATA failed")); -} +#if wxUSE_OWNER_DRAWN + if ( m_windowStyle & wxLB_OWNERDRAW ) + { + // + // Client data must be pointer to wxOwnerDrawn, otherwise we would crash + // in OnMeasure/OnDraw. + // + wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); + } +#endif // wxUSE_OWNER_DRAWN + + ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(n), MPFROMP(pClientData)); +} // end of wxListBox::DoSetItemClientData + +bool wxListBox::HasMultipleSelection() const +{ + return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED); +} // end of wxListBox::HasMultipleSelection -// Return number of selections and an array of selected integers -int wxListBox::GetSelections(wxArrayInt& aSelections) const +int wxListBox::GetSelections( wxArrayInt& raSelections ) const { - aSelections.Empty(); + int nCount = 0; + LONG lItem; - if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) + + raSelections.Empty(); + if (HasMultipleSelection()) { - int no_sel; // = ListBox_GetSelCount(GetHwnd()); - if (no_sel != 0) { - int *selections = new int[no_sel]; -// if ( ListBox_GetSelItems(GetHwnd(), no_sel, selections) == LB_ERR ) { -// wxFAIL_MSG(wxT("This listbox can't have single-selection style!")); -// } - - aSelections.Alloc(no_sel); - for ( int n = 0; n < no_sel; n++ ) - aSelections.Add(selections[n]); - - delete [] selections; + lItem = LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)LIT_FIRST + ,(MPARAM)0 + ) + ); + if (lItem != LIT_NONE) + { + nCount++; + while ((lItem = LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)lItem + ,(MPARAM)0 + ) + )) != LIT_NONE) + { + nCount++; + } + raSelections.Alloc(nCount); + lItem = LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)LIT_FIRST + ,(MPARAM)0 + ) + ); + + raSelections.Add((int)lItem); + while ((lItem = LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)lItem + ,(MPARAM)0 + ) + )) != LIT_NONE) + { + raSelections.Add((int)lItem); + } + return nCount; } - - return no_sel; } else // single-selection listbox { -// aSelections.Add(ListBox_GetCurSel(GetHwnd())); - + lItem = LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)LIT_FIRST + ,(MPARAM)0 + ) + ); + raSelections.Add((int)lItem); return 1; } -} + return 0; +} // end of wxListBox::GetSelections -// Get single selection, for single choice list items int wxListBox::GetSelection() const { - wxCHECK_MSG( !(m_windowStyle & wxLB_MULTIPLE) && - !(m_windowStyle & wxLB_EXTENDED), + wxCHECK_MSG( !HasMultipleSelection(), -1, wxT("GetSelection() can't be used with multiple-selection " "listboxes, use GetSelections() instead.") ); -// return ListBox_GetCurSel(GetHwnd()); - return -1; -} + return(LONGFROMMR(::WinSendMsg( GetHwnd() + ,LM_QUERYSELECTION + ,(MPARAM)LIT_FIRST + ,(MPARAM)0 + ) + )); +} // end of wxListBox::GetSelection -// Find string for position -wxString wxListBox::GetString(int N) const +wxString wxListBox::GetString( + int N +) const { - wxCHECK_MSG( N >= 0 && N < m_noItems, "", - wxT("invalid index in wxListBox::GetClientData") ); + LONG lLen = 0; + wxChar* zBuf; + wxString sResult; -// int len = ListBox_GetTextLen(GetHwnd(), N); - - // +1 for terminating NUL - wxString result; -// ListBox_GetText(GetHwnd(), N, result.GetWriteBuf(len + 1)); - result.UngetWriteBuf(); + wxCHECK_MSG( N >= 0 && N < m_nNumItems, wxEmptyString, + wxT("invalid index in wxListBox::GetClientData") ); - return result; -} + lLen = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)N, (MPARAM)0)); + zBuf = new wxChar[lLen + 1]; + ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT, MPFROM2SHORT((SHORT)N, (SHORT)lLen), (MPARAM)zBuf); + zBuf[lLen] = '\0'; + sResult = zBuf; + delete [] zBuf; + return sResult; +} // end of wxListBox::GetString + +void wxListBox::DoInsertItems( + const wxArrayString& asItems +, int nPos +) +{ + wxCHECK_RET( nPos >= 0 && nPos <= m_nNumItems, + wxT("invalid index in wxListBox::InsertItems") ); -// OS/2-PM-specific code to set the horizontal extent of the listbox, if -// necessary. If s is non-NULL, it's used to calculate the horizontal extent. -// Otherwise, all strings are used. -void wxListBox::SetHorizontalExtent(const wxString& s) -{ -/* - // Only necessary if we want a horizontal scrollbar - if (!(m_windowStyle & wxHSCROLL)) - return; - TEXTMETRIC lpTextMetric; + int nItems = asItems.GetCount(); - if (s != wxT("")) + for (int i = 0; i < nItems; i++) { - int existingExtent = (int)SendMessage(GetHwnd(), LB_GETHORIZONTALEXTENT, 0, 0L); - HDC dc = GetWindowDC(GetHwnd()); - HFONT oldFont = 0; - if (GetFont().Ok() && GetFont().GetResourceHandle()) - oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); - - GetTextMetrics(dc, &lpTextMetric); - SIZE extentXY; - ::GetTextExtentPoint(dc, (LPTSTR) (const wxChar *)s, s.Length(), &extentXY); - int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); - - if (oldFont) - ::SelectObject(dc, oldFont); - - ReleaseDC(GetHwnd(), dc); - if (extentX > existingExtent) - SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(extentX), 0L); - return; - } - else - { - int largestExtent = 0; - HDC dc = GetWindowDC(GetHwnd()); - HFONT oldFont = 0; - if (GetFont().Ok() && GetFont().GetResourceHandle()) - oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); - - GetTextMetrics(dc, &lpTextMetric); - int i; - for (i = 0; i < m_noItems; i++) - { - int len = (int)SendMessage(GetHwnd(), LB_GETTEXT, i, (LONG)wxBuffer); - wxBuffer[len] = 0; - SIZE extentXY; - ::GetTextExtentPoint(dc, (LPTSTR)wxBuffer, len, &extentXY); - int extentX = (int)(extentXY.cx + lpTextMetric.tmAveCharWidth); - if (extentX > largestExtent) - largestExtent = extentX; - } - if (oldFont) - ::SelectObject(dc, oldFont); - - ReleaseDC(GetHwnd(), dc); - SendMessage(GetHwnd(), LB_SETHORIZONTALEXTENT, LOWORD(largestExtent), 0L); + int nIndex = (int)::WinSendMsg( GetHwnd() + ,LM_INSERTITEM + ,MPFROMLONG((LONG)(i + nPos)) + ,(MPARAM)asItems[i].c_str() + ); + + wxOwnerDrawn* pNewItem = CreateItem(nIndex); + + pNewItem->SetName(asItems[i]); + pNewItem->SetFont(GetFont()); + m_aItems.Insert(pNewItem, nIndex); + ::WinSendMsg( GetHwnd() + ,LM_SETITEMHANDLE + ,(MPARAM)((LONG)nIndex) + ,MPFROMP(pNewItem) + ); + m_nNumItems += nItems; } -*/ -} -void wxListBox::InsertItems(int nItems, const wxString items[], int pos) -{ - wxCHECK_RET( pos >= 0 && pos <= m_noItems, - wxT("invalid index in wxListBox::InsertItems") ); - - int i; -// for (i = 0; i < nItems; i++) -// ListBox_InsertString(GetHwnd(), i + pos, items[i]); - m_noItems += nItems; - - SetHorizontalExtent(wxT("")); -} +} // end of wxListBox::DoInsertItems -void wxListBox::SetString(int N, const wxString& s) +void wxListBox::SetString( + int N +, const wxString& rsString +) { - wxCHECK_RET( N >= 0 && N < m_noItems, + wxCHECK_RET( N >= 0 && N < m_nNumItems, wxT("invalid index in wxListBox::SetString") ); - int sel = -1; - if (!(m_windowStyle & wxLB_MULTIPLE) && !(m_windowStyle & wxLB_EXTENDED)) - sel = GetSelection(); + // + // Remember the state of the item + // + bool bWasSelected = IsSelected(N); + void* pOldData = NULL; + wxClientData* pOldObjData = NULL; + + if (m_clientDataItemsType == wxClientData_Void) + pOldData = GetClientData(N); + else if (m_clientDataItemsType == wxClientData_Object) + pOldObjData = GetClientObject(N); + + // + // Delete and recreate it + // + ::WinSendMsg( GetHwnd() + ,LM_DELETEITEM + ,(MPARAM)N + ,(MPARAM)0 + ); + + int nNewN = N; + + if (N == m_nNumItems - 1) + nNewN = -1; + + ::WinSendMsg( GetHwnd() + ,LM_INSERTITEM + ,(MPARAM)nNewN + ,(MPARAM)rsString.c_str() + ); + + // + // Restore the client data + // + if (pOldData) + SetClientData( N + ,pOldData + ); + else if (pOldObjData) + SetClientObject( N + ,pOldObjData + ); + + // + // We may have lost the selection + // + if (bWasSelected) + Select(N); - void *oldData = wxListBox::GetClientData(N); - -// SendMessage(GetHwnd(), LB_DELETESTRING, N, 0); - - int newN = N; - if (N == (m_noItems - 1)) - newN = -1; - -// SendMessage(GetHwnd(), LB_INSERTSTRING, newN, (LPARAM) (const wxChar *)s); - if (oldData) - wxListBox::SetClientData(N, oldData); - - // Selection may have changed - if (sel >= 0) - SetSelection(sel); - -#if wxUSE_OWNER_DRAWN - if ( m_windowStyle & wxLB_OWNERDRAW ) - // update item's text - m_aItems[N]->SetName(s); +#if wxUSE_OWNER_DRAWN + if (m_windowStyle & wxLB_OWNERDRAW) + // + // Update item's text + // + m_aItems[N]->SetName(rsString); #endif //USE_OWNER_DRAWN -} +} // end of wxListBox::SetString -int wxListBox::Number () const +int wxListBox::GetCount() const { - return m_noItems; + return m_nNumItems; } -// For single selection items only -wxString wxListBox::GetStringSelection () const -{ - int sel = GetSelection (); - if (sel > -1) - return this->GetString (sel); - else - return wxString(""); -} +// ---------------------------------------------------------------------------- +// helpers +// ---------------------------------------------------------------------------- -bool wxListBox::SetStringSelection (const wxString& s, bool flag) +wxSize wxListBox::DoGetBestSize() const { - int sel = FindString (s); - if (sel > -1) + // + // Find the widest string + // + int nLine; + int nListbox = 0; + int nCx; + int nCy; + wxFont vFont = (wxFont)GetFont(); + + for (int i = 0; i < m_nNumItems; i++) { - SetSelection (sel, flag); - return TRUE; + wxString vStr(GetString(i)); + + GetTextExtent( vStr + ,&nLine + ,NULL + ); + if (nLine > nListbox) + nListbox = nLine; } - else - return FALSE; -} -wxSize wxListBox::DoGetBestSize() -{ - // find the widest string - int wLine; - int wListbox = 0; - for ( int i = 0; i < m_noItems; i++ ) + // + // Give it some reasonable default value if there are no strings in the + // list. + // + if (nListbox == 0) + nListbox = 100; + + // + // The listbox should be slightly larger than the widest string + // + wxGetCharSize( GetHWND() + ,&nCx + ,&nCy + ,&vFont + ); + nListbox += 3 * nCx; + + int hListbox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * (wxMax(m_nNumItems, 7)); + + return wxSize( nListbox + ,hListbox + ); +} // end of wxListBox::DoGetBestSize + +// ---------------------------------------------------------------------------- +// callbacks +// ---------------------------------------------------------------------------- + +bool wxListBox::OS2Command( + WXUINT uParam +, WXWORD WXUNUSED(wId)) +{ + wxEventType eEvtType; + + if (uParam == LN_SELECT) { - wxString str(GetString(i)); - GetTextExtent(str, &wLine, NULL); - if ( wLine > wListbox ) - wListbox = wLine; + eEvtType = wxEVT_COMMAND_LISTBOX_SELECTED; } + else if (uParam == LN_ENTER) + { + eEvtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED; + } + else + { + // + // Some event we're not interested in + // + return false; + } + wxCommandEvent vEvent( eEvtType + ,m_windowId + ); - // give it some reasonable default value if there are no strings in the - // list - if ( wListbox == 0 ) - wListbox = 100; - - // the listbox should be slightly larger than the widest string - int cx, cy; - wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); - - wListbox += 3*cx; - - int hListbox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)*(wxMax(m_noItems, 7)); + vEvent.SetEventObject(this); - return wxSize(wListbox, hListbox); -} + wxArrayInt aSelections; + int n; + int nCount = GetSelections(aSelections); -void wxListBox::Command (wxCommandEvent & event) -{ - if (event.m_extraLong) - SetSelection (event.m_commandInt); - else + if (nCount > 0) { - Deselect (event.m_commandInt); - return; + n = aSelections[0]; + if (HasClientObjectData()) + vEvent.SetClientObject(GetClientObject(n)); + else if ( HasClientUntypedData() ) + vEvent.SetClientData(GetClientData(n)); + vEvent.SetString(GetString(n)); } - ProcessCommand (event); -} - -WXHBRUSH wxListBox::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, - WXUINT message, WXWPARAM wParam, WXLPARAM lParam) -{ -/* -#if wxUSE_CTL3D - if ( m_useCtl3D ) + else { - HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam); - return (WXHBRUSH) hbrush; + n = -1; } -#endif - - if (GetParent()->GetTransparentBackground()) - SetBkMode((HDC) pDC, TRANSPARENT); - else - SetBkMode((HDC) pDC, OPAQUE); + vEvent.SetInt(n); + return GetEventHandler()->ProcessEvent(vEvent); +} // end of wxListBox::OS2Command - ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); - ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); +// ---------------------------------------------------------------------------- +// wxCheckListBox support +// ---------------------------------------------------------------------------- - wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); +#if wxUSE_OWNER_DRAWN - // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush - // has a zero usage count. - backgroundBrush->RealizeResource(); -*/ - wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); - return (WXHBRUSH) backgroundBrush->GetResourceHandle(); -} +// +// Drawing +// ------- +// +#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1) -MRESULT wxListBox::OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +long wxListBox::OS2OnMeasure( + WXMEASUREITEMSTRUCT* pItem +) { - return wxControl::OS2WindowProc(hwnd, nMsg, wParam, lParam); -} + if (!pItem) + pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM; -#if wxUSE_OWNER_DRAWN + POWNERITEM pMeasureStruct = (POWNERITEM)pItem; + wxScreenDC vDc; -// drawing -// ------- + // + // Only owner-drawn control should receive this message + // + wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE ); -// space beneath/above each row in pixels -// "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly. -#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1) + vDc.SetFont(GetFont()); + + wxCoord vHeight; + wxCoord vWidth; -// the height is the same for all items -// TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes + GetSize( &vWidth + ,NULL + ); -// NB: can't forward this to wxListBoxItem because LB_SETITEMDATA -// message is not yet sent when we get here! -bool wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT *item) + pMeasureStruct->rclItem.xRight = (USHORT)vWidth; + pMeasureStruct->rclItem.xLeft = 0; + pMeasureStruct->rclItem.yTop = 0; + pMeasureStruct->rclItem.yBottom = 0; + + vHeight = (wxCoord)(vDc.GetCharHeight() * 2.5); + pMeasureStruct->rclItem.yTop = (USHORT)vHeight; + + return long(MRFROM2SHORT((USHORT)vHeight, (USHORT)vWidth)); +} // end of wxListBox::OS2OnMeasure + +bool wxListBox::OS2OnDraw ( + WXDRAWITEMSTRUCT* pItem +) { - // only owner-drawn control should receive this message - wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE ); + POWNERITEM pDrawStruct = (POWNERITEM)pItem; + LONG lItemID = pDrawStruct->idItem; + int eAction = 0; + int eStatus = 0; -// MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item; + // + // Only owner-drawn control should receive this message + // + wxCHECK(((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), false); - wxDC dc; -// TODO: dc.SetHDC((WXHDC)CreateIC(wxT("DISPLAY"), NULL, NULL, 0)); - dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_ANSI_VAR_FONT)); -// pStruct->itemHeight = dc.GetCharHeight() + 2*OWNER_DRAWN_LISTBOX_EXTRA_SPACE; -// pStruct->itemWidth = dc.GetCharWidth(); + // + // The item may be -1 for an empty listbox + // + if (lItemID == -1L) + return false; - return TRUE; -} + wxListBoxItem* pData = (wxListBoxItem*)PVOIDFROMMR( ::WinSendMsg( GetHwnd() + ,LM_QUERYITEMHANDLE + ,MPFROMLONG(pDrawStruct->idItem) + ,(MPARAM)0 + ) + ); -// forward the message to the appropriate item -bool wxListBox::OS2OnDraw(WXDRAWITEMSTRUCT *item) -{ - // only owner-drawn control should receive this message - wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE ); -/* - DRAWITEMSTRUCT *pStruct = (DRAWITEMSTRUCT *)item; + wxCHECK(pData, false ); - long data = ListBox_GetItemData(GetHwnd(), pStruct->itemID); + wxDC vDc; + wxPoint pt1( pDrawStruct->rclItem.xLeft, pDrawStruct->rclItem.yTop ); + wxPoint pt2( pDrawStruct->rclItem.xRight, pDrawStruct->rclItem.yBottom ); + wxRect vRect( pt1, pt2 ); - wxCHECK( data && (data != LB_ERR), FALSE ); + vDc.SetHPS(pDrawStruct->hps); - wxListBoxItem *pItem = (wxListBoxItem *)data; + if (pDrawStruct->fsAttribute == pDrawStruct->fsAttributeOld) + { + // + // Entire Item needs to be redrawn (either it has reappeared from + // behind another window or is being displayed for the first time + // + eAction = wxOwnerDrawn::wxODDrawAll; - wxDC dc; - dc.SetHDC((WXHDC)pStruct->hDC, FALSE); - wxRect rect(wxPoint(pStruct->rcItem.left, pStruct->rcItem.top), - wxPoint(pStruct->rcItem.right, pStruct->rcItem.bottom)); + if (pDrawStruct->fsAttribute & MIA_HILITED) + { + // + // If it is currently selected we let the system handle it + // + eStatus |= wxOwnerDrawn::wxODSelected; + } + if (pDrawStruct->fsAttribute & MIA_CHECKED) + { + // + // If it is currently checked we draw our own + // + eStatus |= wxOwnerDrawn::wxODChecked; + pDrawStruct->fsAttributeOld = pDrawStruct->fsAttribute &= ~MIA_CHECKED; + } + if (pDrawStruct->fsAttribute & MIA_DISABLED) + { + // + // If it is currently disabled we let the system handle it + // + eStatus |= wxOwnerDrawn::wxODDisabled; + } + // + // Don't really care about framed (indicationg focus) or NoDismiss + // + } + else + { + if (pDrawStruct->fsAttribute & MIA_HILITED) + { + eAction = wxOwnerDrawn::wxODDrawAll; + eStatus |= wxOwnerDrawn::wxODSelected; + // + // Keep the system from trying to highlight with its bogus colors + // + pDrawStruct->fsAttributeOld = pDrawStruct->fsAttribute &= ~MIA_HILITED; + } + else if (!(pDrawStruct->fsAttribute & MIA_HILITED)) + { + eAction = wxOwnerDrawn::wxODDrawAll; + eStatus = 0; + // + // Keep the system from trying to highlight with its bogus colors + // + pDrawStruct->fsAttribute = pDrawStruct->fsAttributeOld &= ~MIA_HILITED; + } + else + { + // + // For now we don't care about anything else + // just ignore the entire message! + // + return true; + } + } + return pData->OnDrawItem( vDc + ,vRect + ,(wxOwnerDrawn::wxODAction)eAction + ,(wxOwnerDrawn::wxODStatus)eStatus + ); +} // end of wxListBox::OS2OnDraw - return pItem->OnDrawItem(dc, rect, - (wxOwnerDrawn::wxODAction)pStruct->itemAction, - (wxOwnerDrawn::wxODStatus)pStruct->itemState); -*/ - return FALSE; -} +#endif // ndef for wxUSE_OWNER_DRAWN -#endif - // wxUSE_OWNER_DRAWN +#endif // ndef for wxUSE_LISTBOX