///////////////////////////////////////////////////////////////////////////////
// Name: listbox.cpp
// Purpose: wxListBox
-// Author: AUTHOR
+// Author: David Webster
// Modified by:
-// Created: ??/??/98
+// Created: 10/09/99
// RCS-ID: $Id$
-// Copyright: (c) AUTHOR
+// Copyright: (c) David Webster
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation "listbox.h"
-#endif
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#include "wx/window.h"
+#include "wx/os2/private.h"
+#ifndef WX_PRECOMP
#include "wx/listbox.h"
#include "wx/settings.h"
+#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
+#include <os2.h>
+
#include "wx/dynarray.h"
#include "wx/log.h"
-#if !USE_SHARED_LIBRARY
- IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
+#if wxUSE_LISTBOX
+
+#if wxUSE_OWNER_DRAWN
+ #include "wx/ownerdrw.h"
#endif
+ IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
+
+// ============================================================================
+// list box item declaration and implementation
+// ============================================================================
+
+#if wxUSE_OWNER_DRAWN
+
+class wxListBoxItem : public wxOwnerDrawn
+{
+public:
+ wxListBoxItem(const wxString& rsStr = "");
+};
+
+wxListBoxItem::wxListBoxItem(
+ const wxString& rsStr
+)
+: wxOwnerDrawn( rsStr
+ ,FALSE
+ )
+{
+ //
+ // No bitmaps/checkmarks
+ //
+ SetMarginWidth(0);
+} // end of wxListBoxItem::wxListBoxItem
+
+wxOwnerDrawn* wxListBox::CreateItem(
+ size_t n
+)
+{
+ return new wxListBoxItem();
+} // end of wxListBox::CreateItem
+
+#endif //USE_OWNER_DRAWN
+
// ============================================================================
// list box control implementation
// ============================================================================
// 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 *parent, wxWindowID id,
- const wxPoint& pos,
- const wxSize& size,
- int n, const wxString choices[],
- long style,
- const wxValidator& validator,
- const wxString& name)
+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_noItems = n;
- m_selected = 0;
+ m_nNumItems = 0;
+ m_hWnd = 0;
+ m_nSelected = 0;
- SetName(name);
- SetValidator(validator);
-
- if (parent) parent->AddChild(this);
+ SetName(rsName);
+#if wxUSE_VALIDATORS
+ SetValidator(rValidator);
+#endif
- wxSystemSettings settings;
- SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
+ if (pParent)
+ pParent->AddChild(this);
+
+ wxSystemSettings vSettings;
+
+ SetBackgroundColour(vSettings.GetSystemColour(wxSYS_COLOUR_WINDOW));
+ SetForegroundColour(pParent->GetForegroundColour());
+
+ m_windowId = (vId == -1) ? (int)NewControlId() : vId;
+
+ int nX = rPos.x;
+ int nY = rPos.y;
+ int nWidth = rSize.x;
+ int nHeight = rSize.y;
+
+ m_windowStyle = lStyle;
+
+ lStyle = WS_VISIBLE;
+
+ if (m_windowStyle & wxCLIP_SIBLINGS )
+ lStyle |= WS_CLIPSIBLINGS;
+ if (m_windowStyle & wxLB_MULTIPLE)
+ lStyle |= LS_MULTIPLESEL;
+ else if (m_windowStyle & wxLB_EXTENDED)
+ lStyle |= LS_EXTENDEDSEL;
+ if (m_windowStyle & wxLB_HSCROLL)
+ 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
+ //
+ 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)
+ {
+ return FALSE;
+ }
- m_windowId = ( id == -1 ) ? (int)NewControlId() : id;
+ //
+ // Subclass again for purposes of dialog editing mode
+ //
+ SubclassWin(m_hWnd);
- // TODO create listbox
+ LONG lUi;
- 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("WHITE"));
+
+ LONG lColor = (LONG)vColour.GetPixel();
+
+ ::WinSetPresParam( m_hWnd
+ ,PP_HILITEFOREGROUNDCOLOR
+ ,sizeof(LONG)
+ ,(PVOID)&lColor
+ );
+ vColour.Set(wxString("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 lUiCount = m_aItems.Count();
-void wxListBox::SetFirstItem(int N)
-{
- // TODO
-}
+ while (lUiCount-- != 0)
+ {
+ delete m_aItems[lUiCount];
+ }
+#endif // wxUSE_OWNER_DRAWN
+} // end of wxListBox::~wxListBox
-void wxListBox::SetFirstItem(const wxString& s)
+void wxListBox::SetupColours()
{
- // TODO
-}
+ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ SetForegroundColour(GetParent()->GetForegroundColour());
+} // end of wxListBox::SetupColours
+
+// ----------------------------------------------------------------------------
+// implementation of wxListBoxBase methods
+// ----------------------------------------------------------------------------
-void wxListBox::Delete(int N)
+void wxListBox::DoSetFirstItem(
+ int N
+)
{
- m_noItems --;
- // TODO
-}
+ wxCHECK_RET( N >= 0 && N < m_nNumItems,
+ wxT("invalid index in wxListBox::SetFirstItem") );
+
+ ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX, MPFROMLONG(N), (MPARAM)0);
+} // end of wxListBox::DoSetFirstItem
-void wxListBox::Append(const wxString& item)
+void wxListBox::Delete(
+ int N
+)
{
- m_noItems ++;
+ wxCHECK_RET( N >= 0 && N < m_nNumItems,
+ wxT("invalid index in wxListBox::Delete") );
+
+#if wxUSE_OWNER_DRAWN
+ delete m_aItems[N];
+ m_aItems.RemoveAt(N);
+#else // !wxUSE_OWNER_DRAWN
+ if (HasClientObjectData())
+ {
+ delete GetClientObject(N);
+ }
+#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
- // TODO
-}
+ ::WinSendMsg(GetHwnd(), LM_DELETEITEM, (MPARAM)N, (MPARAM)0);
+ m_nNumItems--;
+} // end of wxListBox::DoSetFirstItem
-void wxListBox::Append(const wxString& item, char *Client_data)
+int wxListBox::DoAppend(
+ const wxString& rsItem
+)
{
- m_noItems ++;
+ long lIndex = 0;
+ LONG lIndexType = 0;
+
+ if (m_windowStyle & wxLB_SORT)
+ lIndexType = LIT_SORTASCENDING;
+ else
+ lIndexType = LIT_END;
+ lIndex = (long)::WinSendMsg(GetHwnd(), LM_INSERTITEM, (MPARAM)lIndexType, (MPARAM)rsItem.c_str());
+ m_nNumItems++;
+
+#if wxUSE_OWNER_DRAWN
+ if (m_windowStyle & wxLB_OWNERDRAW)
+ {
+ wxOwnerDrawn* pNewItem = CreateItem(lIndex); // dummy argument
+ wxScreenDC vDc;
- // TODO
-}
-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
+)
{
- m_noItems = n;
+ BOOL bHideAndShow = IsShown();
+ int i;
+ LONG lIndexType = 0;
- // TODO
-}
+ if (bHideAndShow)
+ {
+ ::WinShowWindow(GetHwnd(), FALSE);
+ }
+ ::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
+ 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
+ }
+ }
-int wxListBox::FindString(const wxString& s) const
+#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);
+
+ pNewItem->SetName(raChoices[ui]);
+ m_aItems.Add(pNewItem);
+ ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(ui), MPFROMP(pNewItem));
+ }
+ }
+#endif // wxUSE_OWNER_DRAWN
+ ::WinShowWindow(GetHwnd(), TRUE);
+} // end of wxListBox::DoSetItems
+
+int wxListBox::FindString(
+ const wxString& rsString
+) const
{
- // TODO
- return -1;
-}
+ int nPos;
+ LONG lTextLength;
+ PSZ zStr;
+
+
+ for (nPos = 0; nPos < m_nNumItems; nPos++)
+ {
+ lTextLength = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)nPos, (MPARAM)0));
+ zStr = new char[lTextLength + 1];
+ ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT, MPFROM2SHORT(nPos, (SHORT)lTextLength), (MPARAM)zStr);
+ if (rsString == (char*)zStr)
+ {
+ delete [] zStr;
+ break;
+ }
+ delete [] zStr;
+ }
+ return nPos;
+} // end of wxListBox::FindString
void wxListBox::Clear()
{
- m_noItems = 0;
- // TODO
-}
+#if wxUSE_OWNER_DRAWN
+ size_t lUiCount = m_aItems.Count();
-void wxListBox::SetSelection(int N, bool select)
+ while (lUiCount-- != 0)
+ {
+ delete m_aItems[lUiCount];
+ }
+
+ m_aItems.Clear();
+#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_nNumItems = 0;
+} // end of wxListBox::Clear
+
+void wxListBox::SetSelection(
+ int N
+, bool bSelect
+)
{
- // TODO
-}
+ 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") );
+
+ LONG lItem;
-bool wxListBox::Selected(int N) const
+ if (GetWindowStyleFlag() & wxLB_EXTENDED)
+ {
+ 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
+ {
+ lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0));
+ }
+ return (lItem == (LONG)N && lItem != LIT_NONE);
+} // end of wxListBox::IsSelected
+
+wxClientData* wxListBox::DoGetItemClientObject(
+ int n
+) const
{
- // TODO
- return FALSE;
+ return (wxClientData *)DoGetItemClientData(n);
}
-void wxListBox::Deselect(int N)
+void* wxListBox::DoGetItemClientData(
+ int n
+) const
{
- // TODO
-}
+ wxCHECK_MSG( n >= 0 && n < m_nNumItems, NULL,
+ wxT("invalid index in wxListBox::GetClientData") );
+
+ return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE, MPFROMLONG(n), (MPARAM)0));
+} // end of wxListBox::DoGetItemClientData
-char *wxListBox::GetClientData(int N) const
+void wxListBox::DoSetItemClientObject(
+ int n
+, wxClientData* pClientData
+)
{
- // TODO
- return (char *)NULL;
-}
+ DoSetItemClientData( n
+ ,pClientData
+ );
+} // end of wxListBox::DoSetItemClientObject
+
+void wxListBox::DoSetItemClientData(
+ int n
+, void* pClientData
+)
+{
+ wxCHECK_RET( n >= 0 && n < m_nNumItems,
+ wxT("invalid index in wxListBox::SetClientData") );
+
+#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
-void wxListBox::SetClientData(int N, char *Client_data)
+bool wxListBox::HasMultipleSelection() const
{
- // TODO
-}
+ 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;
-/* TODO
- if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
- {
- int no_sel = ??
- for ( int n = 0; n < no_sel; n++ )
- aSelections.Add(??);
- return no_sel;
+ raSelections.Empty();
+ if (HasMultipleSelection())
+ {
+ 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 0;
}
else // single-selection listbox
{
- aSelections.Add(??);
-
+ 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
{
- // TODO
- return -1;
-}
-
-// Find string for position
-wxString wxListBox::GetString(int N) const
+ wxCHECK_MSG( !HasMultipleSelection(),
+ -1,
+ wxT("GetSelection() can't be used with multiple-selection "
+ "listboxes, use GetSelections() instead.") );
+
+ return(LONGFROMMR(::WinSendMsg( GetHwnd()
+ ,LM_QUERYSELECTION
+ ,(MPARAM)LIT_FIRST
+ ,(MPARAM)0
+ )
+ ));
+} // end of wxListBox::GetSelection
+
+wxString wxListBox::GetString(
+ int N
+) const
{
- // TODO
- return wxString("");
-}
-
-void wxListBox::SetSize(int x, int y, int width, int height, int sizeFlags)
+ LONG lLen = 0;
+ char* zBuf;
+ wxString sResult;
+
+ wxCHECK_MSG( N >= 0 && N < m_nNumItems, "",
+ wxT("invalid index in wxListBox::GetClientData") );
+
+ lLen = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)N, (MPARAM)0));
+ zBuf = new char[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
+)
{
- // TODO
-}
+ wxCHECK_RET( nPos >= 0 && nPos <= m_nNumItems,
+ wxT("invalid index in wxListBox::InsertItems") );
-void wxListBox::InsertItems(int nItems, const wxString items[], int pos)
-{
- m_noItems += nItems;
+ int nItems = asItems.GetCount();
- // TODO
-}
+ for (int i = 0; i < nItems; i++)
+ {
+ 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;
+ }
+} // end of wxListBox::DoInsertItems
-void wxListBox::SetString(int N, const wxString& s)
+void wxListBox::SetString(
+ int N
+, const wxString& rsString
+)
{
- // TODO
-}
-
-int wxListBox::Number () const
+ wxCHECK_RET( N >= 0 && N < m_nNumItems,
+ wxT("invalid index in wxListBox::SetString") );
+
+ //
+ // 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);
+
+#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::GetCount() const
{
- return m_noItems;
+ return m_nNumItems;
}
-// For single selection items only
-wxString wxListBox::GetStringSelection () const
+// ----------------------------------------------------------------------------
+// helpers
+// ----------------------------------------------------------------------------
+
+wxSize wxListBox::DoGetBestSize() const
{
- int sel = GetSelection ();
- if (sel > -1)
- return this->GetString (sel);
- else
- return wxString("");
-}
+ //
+ // Find the widest string
+ //
+ int nLine;
+ int nListbox = 0;
+ int nCx;
+ int nCy;
+
+ for (int i = 0; i < m_nNumItems; i++)
+ {
+ wxString vStr(GetString(i));
+
+ GetTextExtent( vStr
+ ,&nLine
+ ,NULL
+ );
+ if (nLine > nListbox)
+ nListbox = nLine;
+ }
-bool wxListBox::SetStringSelection (const wxString& s, bool flag)
+ //
+ // 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
+ ,(wxFont*)&GetFont()
+ );
+ 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))
{
- int sel = FindString (s);
- if (sel > -1)
+ wxEventType eEvtType;
+
+ if (uParam == LN_SELECT)
{
- SetSelection (sel, flag);
- return TRUE;
+ eEvtType = wxEVT_COMMAND_LISTBOX_SELECTED;
}
- else
- return FALSE;
-}
+ if (uParam == LN_ENTER)
+ {
+ eEvtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED;
+ }
+ else
+ {
+ //
+ // Some event we're not interested in
+ //
+ return FALSE;
+ }
+ wxCommandEvent vEvent( eEvtType
+ ,m_windowId
+ );
+
+ vEvent.SetEventObject(this);
+
+ wxArrayInt aSelections;
+ int n;
+ int nCount = GetSelections(aSelections);
+
+ if (nCount > 0)
+ {
+ n = aSelections[0];
+ if (HasClientObjectData())
+ vEvent.SetClientObject(GetClientObject(n));
+ else if ( HasClientUntypedData() )
+ vEvent.SetClientData(GetClientData(n));
+ vEvent.SetString(GetString(n));
+ }
+ else
+ {
+ n = -1;
+ }
+ vEvent.m_commandInt = n;
+ return GetEventHandler()->ProcessEvent(vEvent);
+} // end of wxListBox::OS2Command
+
+// ----------------------------------------------------------------------------
+// wxCheckListBox support
+// ----------------------------------------------------------------------------
+
+#if wxUSE_OWNER_DRAWN
-void wxListBox::Command (wxCommandEvent & event)
+//
+// Drawing
+// -------
+//
+#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
+
+long wxListBox::OS2OnMeasure(
+ WXMEASUREITEMSTRUCT* pItem
+)
+{
+ if (!pItem)
+ pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
+
+ POWNERITEM pMeasureStruct = (POWNERITEM)pItem;
+ wxScreenDC vDc;
+
+ //
+ // Only owner-drawn control should receive this message
+ //
+ wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
+
+ vDc.SetFont(GetFont());
+
+ wxCoord vHeight;
+ wxCoord vWidth;
+
+ GetSize( &vWidth
+ ,NULL
+ );
+
+ 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
+)
{
- if (event.m_extraLong)
- SetSelection (event.m_commandInt);
- else
+ POWNERITEM pDrawStruct = (POWNERITEM)pItem;
+ LONG lItemID = pDrawStruct->idItem;
+ int eAction = 0;
+ int eStatus = 0;
+
+ //
+ // Only owner-drawn control should receive this message
+ //
+ wxCHECK(((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE);
+
+
+ //
+ // The item may be -1 for an empty listbox
+ //
+ if (lItemID == -1L)
+ return FALSE;
+
+ wxListBoxItem* pData = (wxListBoxItem*)PVOIDFROMMR( ::WinSendMsg( GetHwnd()
+ ,LM_QUERYITEMHANDLE
+ ,MPFROMLONG(pDrawStruct->idItem)
+ ,(MPARAM)0
+ )
+ );
+
+ wxCHECK(pData, FALSE );
+
+ wxDC vDc;
+ wxRect vRect( wxPoint( pDrawStruct->rclItem.xLeft
+ ,pDrawStruct->rclItem.yTop
+ )
+ ,wxPoint( pDrawStruct->rclItem.xRight
+ ,pDrawStruct->rclItem.yBottom
+ )
+ );
+
+ vDc.SetHPS(pDrawStruct->hps);
+
+ if (pDrawStruct->fsAttribute == pDrawStruct->fsAttributeOld)
{
- Deselect (event.m_commandInt);
- return;
+ //
+ // 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;
+
+ 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
+ //
}
- ProcessCommand (event);
-}
+ 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
+
+#endif // ndef for wxUSE_OWNER_DRAWN
+
+#endif // ndef for wxUSE_LISTBOX