1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/listbox.cpp
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
17 #include "wx/listbox.h"
20 #include "wx/dynarray.h"
21 #include "wx/settings.h"
25 #include "wx/dcscreen.h"
27 #include "wx/scrolwin.h"
29 #include "wx/window.h"
32 #include "wx/os2/dcclient.h"
33 #include "wx/os2/private.h"
39 #include "wx/ownerdrw.h"
42 // ============================================================================
43 // list box item declaration and implementation
44 // ============================================================================
48 class wxListBoxItem
: public wxOwnerDrawn
51 wxListBoxItem(wxListBox
*parent
)
52 { m_parent
= parent
; }
54 wxListBox
*GetParent() const
58 { return m_parent
->GetItemIndex(const_cast<wxListBoxItem
*>(this)); }
60 wxString
GetName() const
61 { return m_parent
->GetString(GetIndex()); }
67 wxOwnerDrawn
* wxListBox::CreateItem( size_t WXUNUSED(n
) )
69 return new wxListBoxItem(this);
70 } // end of wxListBox::CreateItem
72 #endif //USE_OWNER_DRAWN
74 // ============================================================================
75 // list box control implementation
76 // ============================================================================
79 wxListBox::wxListBox()
83 } // end of wxListBox::wxListBox
85 bool wxListBox::Create(
90 , const wxArrayString
& asChoices
92 , const wxValidator
& rValidator
93 , const wxString
& rsName
96 wxCArrayString
chs(asChoices
);
98 return Create(pParent
, vId
, rPos
, rSize
, chs
.GetCount(), chs
.GetStrings(),
99 lStyle
, rValidator
, rsName
);
102 bool wxListBox::Create( wxWindow
* pParent
,
107 const wxString asChoices
[],
109 const wxValidator
& rValidator
,
110 const wxString
& rsName
)
118 SetValidator(rValidator
);
122 pParent
->AddChild(this);
124 wxSystemSettings vSettings
;
126 SetBackgroundColour(vSettings
.GetColour(wxSYS_COLOUR_WINDOW
));
127 SetForegroundColour(pParent
->GetForegroundColour());
129 m_windowId
= (vId
== -1) ? (int)NewControlId() : vId
;
133 int nWidth
= rSize
.x
;
134 int nHeight
= rSize
.y
;
136 m_windowStyle
= lStyle
;
140 if (m_windowStyle
& wxCLIP_SIBLINGS
)
141 lStyle
|= WS_CLIPSIBLINGS
;
142 if (m_windowStyle
& wxLB_MULTIPLE
)
143 lStyle
|= LS_MULTIPLESEL
;
144 else if (m_windowStyle
& wxLB_EXTENDED
)
145 lStyle
|= LS_EXTENDEDSEL
;
146 if (m_windowStyle
& wxLB_HSCROLL
)
147 lStyle
|= LS_HORZSCROLL
;
148 if (m_windowStyle
& wxLB_OWNERDRAW
)
149 lStyle
|= LS_OWNERDRAW
;
152 // Without this style, you get unexpected heights, so e.g. constraint layout
153 // doesn't work properly
155 lStyle
|= LS_NOADJUSTPOS
;
157 m_hWnd
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) // Parent
158 ,WC_LISTBOX
// Default Listbox class
159 ,"LISTBOX" // Control's name
160 ,lStyle
// Initial Style
161 ,0, 0, 0, 0 // Position and size
162 ,GetWinHwnd(pParent
) // Owner
164 ,(HMENU
)m_windowId
// Id
165 ,NULL
// Control Data
166 ,NULL
// Presentation Parameters
174 // Subclass again for purposes of dialog editing mode
180 for (lUi
= 0; lUi
< (LONG
)n
; lUi
++)
182 Append(asChoices
[lUi
]);
184 wxFont
* pTextFont
= new wxFont( 10
192 // Set OS/2 system colours for Listbox items and highlighting
196 vColour
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
198 LONG lColor
= (LONG
)vColour
.GetPixel();
200 ::WinSetPresParam( m_hWnd
201 ,PP_HILITEFOREGROUNDCOLOR
205 vColour
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
206 lColor
= (LONG
)vColour
.GetPixel();
207 ::WinSetPresParam( m_hWnd
208 ,PP_HILITEBACKGROUNDCOLOR
222 } // end of wxListBox::Create
224 wxListBox::~wxListBox()
227 } // end of wxListBox::~wxListBox
229 void wxListBox::SetupColours()
231 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
232 SetForegroundColour(GetParent()->GetForegroundColour());
233 } // end of wxListBox::SetupColours
235 // ----------------------------------------------------------------------------
236 // implementation of wxListBoxBase methods
237 // ----------------------------------------------------------------------------
239 void wxListBox::DoSetFirstItem(int N
)
241 wxCHECK_RET( IsValid(N
),
242 wxT("invalid index in wxListBox::SetFirstItem") );
244 ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX
, MPFROMLONG(N
), (MPARAM
)0);
245 } // end of wxListBox::DoSetFirstItem
247 void wxListBox::DoDeleteOneItem(unsigned int n
)
249 wxCHECK_RET( IsValid(n
),
250 wxT("invalid index in wxListBox::Delete") );
252 #if wxUSE_OWNER_DRAWN
254 m_aItems
.RemoveAt(n
);
255 #endif // wxUSE_OWNER_DRAWN
257 ::WinSendMsg(GetHwnd(), LM_DELETEITEM
, (MPARAM
)n
, (MPARAM
)0);
259 } // end of wxListBox::DoSetFirstItem
261 int wxListBox::DoInsertItems(const wxArrayStringsAdapter
& items
,
264 wxClientDataType type
)
268 bool incrementPos
= false;
271 lIndexType
= LIT_SORTASCENDING
;
272 else if (pos
== GetCount())
273 lIndexType
= LIT_END
;
276 lIndexType
= (LONG
)pos
;
282 unsigned int count
= items
.GetCount();
283 for (unsigned int i
= 0; i
< count
; i
++)
285 n
= (int)::WinSendMsg(GetHwnd(), LM_INSERTITEM
, (MPARAM
)lIndexType
, (MPARAM
)items
[i
].wx_str());
288 wxLogLastError(wxT("WinSendMsg(LM_INSERTITEM)"));
294 #if wxUSE_OWNER_DRAWN
295 if (HasFlag(wxLB_OWNERDRAW
))
297 wxOwnerDrawn
* pNewItem
= CreateItem(n
); // dummy argument
298 pNewItem
->SetFont(GetFont());
299 m_aItems
.Insert(pNewItem
, n
);
302 AssignNewItemClientData(n
, clientData
, i
, type
);
309 } // end of wxListBox::DoInsertAppendItemsWithData
311 void wxListBox::DoClear()
313 #if wxUSE_OWNER_DRAWN
314 if ( m_windowStyle
& wxLB_OWNERDRAW
)
316 WX_CLEAR_ARRAY(m_aItems
);
318 #endif // wxUSE_OWNER_DRAWN
319 ::WinSendMsg(GetHwnd(), LM_DELETEALL
, (MPARAM
)0, (MPARAM
)0);
322 } // end of wxListBox::Clear
324 void wxListBox::DoSetSelection( int N
, bool bSelect
)
326 wxCHECK_RET( IsValid(N
),
327 wxT("invalid index in wxListBox::SetSelection") );
328 ::WinSendMsg( GetHwnd()
333 if(m_windowStyle
& wxLB_OWNERDRAW
)
335 } // end of wxListBox::SetSelection
337 bool wxListBox::IsSelected( int N
) const
339 wxCHECK_MSG( IsValid(N
), false,
340 wxT("invalid index in wxListBox::Selected") );
344 if (GetWindowStyleFlag() & wxLB_EXTENDED
)
347 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0));
349 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)(N
- 1), (MPARAM
)0));
353 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0));
355 return (lItem
== (LONG
)N
&& lItem
!= LIT_NONE
);
356 } // end of wxListBox::IsSelected
358 void* wxListBox::DoGetItemClientData(unsigned int n
) const
360 wxCHECK_MSG( IsValid(n
), NULL
,
361 wxT("invalid index in wxListBox::GetClientData") );
363 return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE
, MPFROMLONG(n
), (MPARAM
)0));
364 } // end of wxListBox::DoGetItemClientData
366 void wxListBox::DoSetItemClientData(unsigned int n
, void* pClientData
)
368 wxCHECK_RET( IsValid(n
),
369 wxT("invalid index in wxListBox::SetClientData") );
371 ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(n
), MPFROMP(pClientData
));
372 } // end of wxListBox::DoSetItemClientData
374 bool wxListBox::HasMultipleSelection() const
376 return (m_windowStyle
& wxLB_MULTIPLE
) || (m_windowStyle
& wxLB_EXTENDED
);
377 } // end of wxListBox::HasMultipleSelection
379 int wxListBox::GetSelections( wxArrayInt
& raSelections
) const
385 raSelections
.Empty();
386 if (HasMultipleSelection())
388 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
394 if (lItem
!= LIT_NONE
)
397 while ((lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
406 raSelections
.Alloc(nCount
);
407 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
414 raSelections
.Add((int)lItem
);
415 while ((lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
422 raSelections
.Add((int)lItem
);
427 else // single-selection listbox
429 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
435 raSelections
.Add((int)lItem
);
439 } // end of wxListBox::GetSelections
441 int wxListBox::GetSelection() const
443 wxCHECK_MSG( !HasMultipleSelection(),
445 wxT("GetSelection() can't be used with multiple-selection "
446 "listboxes, use GetSelections() instead.") );
448 return(LONGFROMMR(::WinSendMsg( GetHwnd()
454 } // end of wxListBox::GetSelection
456 wxString
wxListBox::GetString(unsigned int n
) const
462 wxCHECK_MSG( IsValid(n
), wxEmptyString
,
463 wxT("invalid index in wxListBox::GetClientData") );
465 lLen
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH
, (MPARAM
)n
, (MPARAM
)0));
466 zBuf
= new wxChar
[lLen
+ 1];
467 ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT
, MPFROM2SHORT((SHORT
)n
, (SHORT
)lLen
), (MPARAM
)zBuf
);
472 } // end of wxListBox::GetString
474 void wxListBox::SetString(unsigned int n
, const wxString
& rsString
)
476 wxCHECK_RET( IsValid(n
),
477 wxT("invalid index in wxListBox::SetString") );
480 // Remember the state of the item
482 bool bWasSelected
= IsSelected(n
);
483 void* pOldData
= NULL
;
484 wxClientData
* pOldObjData
= NULL
;
486 if ( HasClientUntypedData() )
487 pOldData
= GetClientData(n
);
488 else if ( HasClientObjectData() )
489 pOldObjData
= GetClientObject(n
);
492 // Delete and recreate it
494 ::WinSendMsg( GetHwnd()
502 if (n
== (m_nNumItems
- 1))
505 ::WinSendMsg( GetHwnd()
508 ,(MPARAM
)rsString
.wx_str()
512 // Restore the client data
515 SetClientData(n
, pOldData
);
516 else if (pOldObjData
)
517 SetClientObject(n
, pOldObjData
);
520 // We may have lost the selection
524 } // end of wxListBox::SetString
526 unsigned int wxListBox::GetCount() const
531 // ----------------------------------------------------------------------------
533 // ----------------------------------------------------------------------------
535 wxSize
wxListBox::DoGetBestSize() const
538 // Find the widest string
544 wxFont vFont
= (wxFont
)GetFont();
546 for (unsigned int i
= 0; i
< m_nNumItems
; i
++)
548 wxString
vStr(GetString(i
));
550 GetTextExtent( vStr
, &nLine
, NULL
);
551 if (nLine
> nListbox
)
556 // Give it some reasonable default value if there are no strings in the
563 // The listbox should be slightly larger than the widest string
565 wxGetCharSize( GetHWND()
572 int hListbox
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy
) * (wxMax(m_nNumItems
, 7));
574 return wxSize( nListbox
577 } // end of wxListBox::DoGetBestSize
579 // ----------------------------------------------------------------------------
581 // ----------------------------------------------------------------------------
583 bool wxListBox::OS2Command(
585 , WXWORD
WXUNUSED(wId
))
587 wxEventType eEvtType
;
589 if (uParam
== LN_SELECT
)
591 eEvtType
= wxEVT_COMMAND_LISTBOX_SELECTED
;
593 else if (uParam
== LN_ENTER
)
595 eEvtType
= wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
;
600 // Some event we're not interested in
604 wxCommandEvent
vEvent( eEvtType
608 vEvent
.SetEventObject(this);
610 wxArrayInt aSelections
;
612 int nCount
= GetSelections(aSelections
);
617 if (HasClientObjectData())
618 vEvent
.SetClientObject(GetClientObject(n
));
619 else if ( HasClientUntypedData() )
620 vEvent
.SetClientData(GetClientData(n
));
621 vEvent
.SetString(GetString(n
));
628 return HandleWindowEvent(vEvent
);
629 } // end of wxListBox::OS2Command
631 // ----------------------------------------------------------------------------
632 // wxCheckListBox support
633 // ----------------------------------------------------------------------------
635 #if wxUSE_OWNER_DRAWN
641 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
643 long wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT
* pItem
)
646 pItem
= (WXMEASUREITEMSTRUCT
*)new OWNERITEM
;
648 POWNERITEM pMeasureStruct
= (POWNERITEM
)pItem
;
652 // Only owner-drawn control should receive this message
654 wxCHECK( ((m_windowStyle
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), FALSE
);
656 vDc
.SetFont(GetFont());
665 pMeasureStruct
->rclItem
.xRight
= (USHORT
)vWidth
;
666 pMeasureStruct
->rclItem
.xLeft
= 0;
667 pMeasureStruct
->rclItem
.yTop
= 0;
668 pMeasureStruct
->rclItem
.yBottom
= 0;
670 vHeight
= (wxCoord
)(vDc
.GetCharHeight() * 2.5);
671 pMeasureStruct
->rclItem
.yTop
= (USHORT
)vHeight
;
673 return long(MRFROM2SHORT((USHORT
)vHeight
, (USHORT
)vWidth
));
674 } // end of wxListBox::OS2OnMeasure
676 bool wxListBox::OS2OnDraw (
677 WXDRAWITEMSTRUCT
* pItem
680 POWNERITEM pDrawStruct
= (POWNERITEM
)pItem
;
685 // Only owner-drawn control should receive this message
687 wxCHECK(((m_windowStyle
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), false);
691 // The item may be -1 for an empty listbox
693 if (pDrawStruct
->idItem
== -1L)
696 wxListBoxItem
* pData
= (wxListBoxItem
*)m_aItems
[pDrawStruct
->idItem
];
698 wxClientDC
vDc(this);
699 wxPMDCImpl
*impl
= (wxPMDCImpl
*) vDc
.GetImpl();
700 wxPoint
pt1( pDrawStruct
->rclItem
.xLeft
, pDrawStruct
->rclItem
.yTop
);
701 wxPoint
pt2( pDrawStruct
->rclItem
.xRight
, pDrawStruct
->rclItem
.yBottom
);
702 wxRect
vRect( pt1
, pt2
);
704 impl
->SetHPS(pDrawStruct
->hps
);
706 if (pDrawStruct
->fsAttribute
== pDrawStruct
->fsAttributeOld
)
709 // Entire Item needs to be redrawn (either it has reappeared from
710 // behind another window or is being displayed for the first time
712 eAction
= wxOwnerDrawn::wxODDrawAll
;
714 if (pDrawStruct
->fsAttribute
& MIA_HILITED
)
717 // If it is currently selected we let the system handle it
719 eStatus
|= wxOwnerDrawn::wxODSelected
;
721 if (pDrawStruct
->fsAttribute
& MIA_CHECKED
)
724 // If it is currently checked we draw our own
726 eStatus
|= wxOwnerDrawn::wxODChecked
;
727 pDrawStruct
->fsAttributeOld
= pDrawStruct
->fsAttribute
&= ~MIA_CHECKED
;
729 if (pDrawStruct
->fsAttribute
& MIA_DISABLED
)
732 // If it is currently disabled we let the system handle it
734 eStatus
|= wxOwnerDrawn::wxODDisabled
;
737 // Don't really care about framed (indicationg focus) or NoDismiss
742 if (pDrawStruct
->fsAttribute
& MIA_HILITED
)
744 eAction
= wxOwnerDrawn::wxODDrawAll
;
745 eStatus
|= wxOwnerDrawn::wxODSelected
;
747 // Keep the system from trying to highlight with its bogus colors
749 pDrawStruct
->fsAttributeOld
= pDrawStruct
->fsAttribute
&= ~MIA_HILITED
;
751 else if (!(pDrawStruct
->fsAttribute
& MIA_HILITED
))
753 eAction
= wxOwnerDrawn::wxODDrawAll
;
756 // Keep the system from trying to highlight with its bogus colors
758 pDrawStruct
->fsAttribute
= pDrawStruct
->fsAttributeOld
&= ~MIA_HILITED
;
763 // For now we don't care about anything else
764 // just ignore the entire message!
769 return pData
->OnDrawItem( vDc
771 ,(wxOwnerDrawn::wxODAction
)eAction
772 ,(wxOwnerDrawn::wxODStatus
)(eStatus
| wxOwnerDrawn::wxODHidePrefix
)
774 } // end of wxListBox::OS2OnDraw
776 #endif // ndef for wxUSE_OWNER_DRAWN
778 #endif // wxUSE_LISTBOX