1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/listbox.cpp
4 // Author: David Webster
7 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/listbox.h"
19 #include "wx/dynarray.h"
20 #include "wx/settings.h"
24 #include "wx/dcscreen.h"
26 #include "wx/scrolwin.h"
28 #include "wx/window.h"
31 #include "wx/os2/dcclient.h"
32 #include "wx/os2/private.h"
38 #include "wx/ownerdrw.h"
41 // ============================================================================
42 // list box item declaration and implementation
43 // ============================================================================
47 class wxListBoxItem
: public wxOwnerDrawn
50 wxListBoxItem(wxListBox
*parent
)
51 { m_parent
= parent
; }
53 wxListBox
*GetParent() const
57 { return m_parent
->GetItemIndex(const_cast<wxListBoxItem
*>(this)); }
59 wxString
GetName() const
60 { return m_parent
->GetString(GetIndex()); }
66 wxOwnerDrawn
* wxListBox::CreateItem( size_t WXUNUSED(n
) )
68 return new wxListBoxItem(this);
69 } // end of wxListBox::CreateItem
71 #endif //USE_OWNER_DRAWN
73 // ============================================================================
74 // list box control implementation
75 // ============================================================================
78 wxListBox::wxListBox()
82 } // end of wxListBox::wxListBox
84 bool wxListBox::Create(
89 , const wxArrayString
& asChoices
91 , const wxValidator
& rValidator
92 , const wxString
& rsName
95 wxCArrayString
chs(asChoices
);
97 return Create(pParent
, vId
, rPos
, rSize
, chs
.GetCount(), chs
.GetStrings(),
98 lStyle
, rValidator
, rsName
);
101 bool wxListBox::Create( wxWindow
* pParent
,
106 const wxString asChoices
[],
108 const wxValidator
& rValidator
,
109 const wxString
& rsName
)
117 SetValidator(rValidator
);
121 pParent
->AddChild(this);
123 wxSystemSettings vSettings
;
125 SetBackgroundColour(vSettings
.GetColour(wxSYS_COLOUR_WINDOW
));
126 SetForegroundColour(pParent
->GetForegroundColour());
128 m_windowId
= (vId
== -1) ? (int)NewControlId() : vId
;
132 int nWidth
= rSize
.x
;
133 int nHeight
= rSize
.y
;
135 m_windowStyle
= lStyle
;
139 if (m_windowStyle
& wxCLIP_SIBLINGS
)
140 lStyle
|= WS_CLIPSIBLINGS
;
141 if (m_windowStyle
& wxLB_MULTIPLE
)
142 lStyle
|= LS_MULTIPLESEL
;
143 else if (m_windowStyle
& wxLB_EXTENDED
)
144 lStyle
|= LS_EXTENDEDSEL
;
145 if (m_windowStyle
& wxLB_HSCROLL
)
146 lStyle
|= LS_HORZSCROLL
;
147 if (m_windowStyle
& wxLB_OWNERDRAW
)
148 lStyle
|= LS_OWNERDRAW
;
151 // Without this style, you get unexpected heights, so e.g. constraint layout
152 // doesn't work properly
154 lStyle
|= LS_NOADJUSTPOS
;
156 m_hWnd
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) // Parent
157 ,WC_LISTBOX
// Default Listbox class
158 ,"LISTBOX" // Control's name
159 ,lStyle
// Initial Style
160 ,0, 0, 0, 0 // Position and size
161 ,GetWinHwnd(pParent
) // Owner
163 ,(HMENU
)m_windowId
// Id
164 ,NULL
// Control Data
165 ,NULL
// Presentation Parameters
173 // Subclass again for purposes of dialog editing mode
179 for (lUi
= 0; lUi
< (LONG
)n
; lUi
++)
181 Append(asChoices
[lUi
]);
183 wxFont
* pTextFont
= new wxFont( 10
191 // Set OS/2 system colours for Listbox items and highlighting
195 vColour
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
197 LONG lColor
= (LONG
)vColour
.GetPixel();
199 ::WinSetPresParam( m_hWnd
200 ,PP_HILITEFOREGROUNDCOLOR
204 vColour
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
205 lColor
= (LONG
)vColour
.GetPixel();
206 ::WinSetPresParam( m_hWnd
207 ,PP_HILITEBACKGROUNDCOLOR
221 } // end of wxListBox::Create
223 wxListBox::~wxListBox()
226 } // end of wxListBox::~wxListBox
228 void wxListBox::SetupColours()
230 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
231 SetForegroundColour(GetParent()->GetForegroundColour());
232 } // end of wxListBox::SetupColours
234 // ----------------------------------------------------------------------------
235 // implementation of wxListBoxBase methods
236 // ----------------------------------------------------------------------------
238 void wxListBox::DoSetFirstItem(int N
)
240 wxCHECK_RET( IsValid(N
),
241 wxT("invalid index in wxListBox::SetFirstItem") );
243 ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX
, MPFROMLONG(N
), (MPARAM
)0);
244 } // end of wxListBox::DoSetFirstItem
246 void wxListBox::DoDeleteOneItem(unsigned int n
)
248 wxCHECK_RET( IsValid(n
),
249 wxT("invalid index in wxListBox::Delete") );
251 #if wxUSE_OWNER_DRAWN
253 m_aItems
.RemoveAt(n
);
254 #endif // wxUSE_OWNER_DRAWN
256 ::WinSendMsg(GetHwnd(), LM_DELETEITEM
, (MPARAM
)n
, (MPARAM
)0);
258 } // end of wxListBox::DoSetFirstItem
260 int wxListBox::DoInsertItems(const wxArrayStringsAdapter
& items
,
263 wxClientDataType type
)
266 bool incrementPos
= false;
269 lIndexType
= LIT_SORTASCENDING
;
270 else if (pos
== GetCount())
271 lIndexType
= LIT_END
;
274 lIndexType
= (LONG
)pos
;
280 unsigned int count
= items
.GetCount();
281 for (unsigned int i
= 0; i
< count
; i
++)
283 n
= (int)::WinSendMsg(GetHwnd(), LM_INSERTITEM
, (MPARAM
)lIndexType
, (MPARAM
)items
[i
].wx_str());
286 wxLogLastError(wxT("WinSendMsg(LM_INSERTITEM)"));
292 #if wxUSE_OWNER_DRAWN
293 if (HasFlag(wxLB_OWNERDRAW
))
295 wxOwnerDrawn
* pNewItem
= CreateItem(n
); // dummy argument
296 pNewItem
->SetFont(GetFont());
297 m_aItems
.Insert(pNewItem
, n
);
300 AssignNewItemClientData(n
, clientData
, i
, type
);
307 } // end of wxListBox::DoInsertAppendItemsWithData
309 void wxListBox::DoClear()
311 #if wxUSE_OWNER_DRAWN
312 if ( m_windowStyle
& wxLB_OWNERDRAW
)
314 WX_CLEAR_ARRAY(m_aItems
);
316 #endif // wxUSE_OWNER_DRAWN
317 ::WinSendMsg(GetHwnd(), LM_DELETEALL
, (MPARAM
)0, (MPARAM
)0);
320 } // end of wxListBox::Clear
322 void wxListBox::DoSetSelection( int N
, bool bSelect
)
324 wxCHECK_RET( IsValid(N
),
325 wxT("invalid index in wxListBox::SetSelection") );
326 ::WinSendMsg( GetHwnd()
331 if(m_windowStyle
& wxLB_OWNERDRAW
)
333 } // end of wxListBox::SetSelection
335 bool wxListBox::IsSelected( int N
) const
337 wxCHECK_MSG( IsValid(N
), false,
338 wxT("invalid index in wxListBox::Selected") );
342 if (GetWindowStyleFlag() & wxLB_EXTENDED
)
345 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0));
347 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)(N
- 1), (MPARAM
)0));
351 lItem
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0));
353 return (lItem
== (LONG
)N
&& lItem
!= LIT_NONE
);
354 } // end of wxListBox::IsSelected
356 void* wxListBox::DoGetItemClientData(unsigned int n
) const
358 wxCHECK_MSG( IsValid(n
), NULL
,
359 wxT("invalid index in wxListBox::GetClientData") );
361 return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE
, MPFROMLONG(n
), (MPARAM
)0));
362 } // end of wxListBox::DoGetItemClientData
364 void wxListBox::DoSetItemClientData(unsigned int n
, void* pClientData
)
366 wxCHECK_RET( IsValid(n
),
367 wxT("invalid index in wxListBox::SetClientData") );
369 ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(n
), MPFROMP(pClientData
));
370 } // end of wxListBox::DoSetItemClientData
372 bool wxListBox::HasMultipleSelection() const
374 return (m_windowStyle
& wxLB_MULTIPLE
) || (m_windowStyle
& wxLB_EXTENDED
);
375 } // end of wxListBox::HasMultipleSelection
377 int wxListBox::GetSelections( wxArrayInt
& raSelections
) const
383 raSelections
.Empty();
384 if (HasMultipleSelection())
386 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
392 if (lItem
!= LIT_NONE
)
395 while ((lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
404 raSelections
.Alloc(nCount
);
405 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
412 raSelections
.Add((int)lItem
);
413 while ((lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
420 raSelections
.Add((int)lItem
);
425 else // single-selection listbox
427 lItem
= LONGFROMMR(::WinSendMsg( GetHwnd()
433 raSelections
.Add((int)lItem
);
437 } // end of wxListBox::GetSelections
439 int wxListBox::GetSelection() const
441 wxCHECK_MSG( !HasMultipleSelection(),
443 wxT("GetSelection() can't be used with multiple-selection "
444 "listboxes, use GetSelections() instead.") );
446 return(LONGFROMMR(::WinSendMsg( GetHwnd()
452 } // end of wxListBox::GetSelection
454 wxString
wxListBox::GetString(unsigned int n
) const
460 wxCHECK_MSG( IsValid(n
), wxEmptyString
,
461 wxT("invalid index in wxListBox::GetClientData") );
463 lLen
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH
, (MPARAM
)n
, (MPARAM
)0));
464 zBuf
= new wxChar
[lLen
+ 1];
465 ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT
, MPFROM2SHORT((SHORT
)n
, (SHORT
)lLen
), (MPARAM
)zBuf
);
470 } // end of wxListBox::GetString
472 void wxListBox::SetString(unsigned int n
, const wxString
& rsString
)
474 wxCHECK_RET( IsValid(n
),
475 wxT("invalid index in wxListBox::SetString") );
478 // Remember the state of the item
480 bool bWasSelected
= IsSelected(n
);
481 void* pOldData
= NULL
;
482 wxClientData
* pOldObjData
= NULL
;
484 if ( HasClientUntypedData() )
485 pOldData
= GetClientData(n
);
486 else if ( HasClientObjectData() )
487 pOldObjData
= GetClientObject(n
);
490 // Delete and recreate it
492 ::WinSendMsg( GetHwnd()
500 if (n
== (m_nNumItems
- 1))
503 ::WinSendMsg( GetHwnd()
506 ,(MPARAM
)rsString
.wx_str()
510 // Restore the client data
513 SetClientData(n
, pOldData
);
514 else if (pOldObjData
)
515 SetClientObject(n
, pOldObjData
);
518 // We may have lost the selection
522 } // end of wxListBox::SetString
524 unsigned int wxListBox::GetCount() const
529 // ----------------------------------------------------------------------------
531 // ----------------------------------------------------------------------------
533 wxSize
wxListBox::DoGetBestSize() const
536 // Find the widest string
542 wxFont vFont
= (wxFont
)GetFont();
544 for (unsigned int i
= 0; i
< m_nNumItems
; i
++)
546 wxString
vStr(GetString(i
));
548 GetTextExtent( vStr
, &nLine
, NULL
);
549 if (nLine
> nListbox
)
554 // Give it some reasonable default value if there are no strings in the
561 // The listbox should be slightly larger than the widest string
563 wxGetCharSize( GetHWND()
570 int hListbox
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy
) * (wxMax(m_nNumItems
, 7));
572 return wxSize( nListbox
575 } // end of wxListBox::DoGetBestSize
577 // ----------------------------------------------------------------------------
579 // ----------------------------------------------------------------------------
581 bool wxListBox::OS2Command(
583 , WXWORD
WXUNUSED(wId
))
585 wxEventType eEvtType
;
587 if (uParam
== LN_SELECT
)
589 eEvtType
= wxEVT_LISTBOX
;
591 else if (uParam
== LN_ENTER
)
593 eEvtType
= wxEVT_LISTBOX_DCLICK
;
598 // Some event we're not interested in
602 wxCommandEvent
vEvent( eEvtType
606 vEvent
.SetEventObject(this);
608 wxArrayInt aSelections
;
610 int nCount
= GetSelections(aSelections
);
615 if (HasClientObjectData())
616 vEvent
.SetClientObject(GetClientObject(n
));
617 else if ( HasClientUntypedData() )
618 vEvent
.SetClientData(GetClientData(n
));
619 vEvent
.SetString(GetString(n
));
626 return HandleWindowEvent(vEvent
);
627 } // end of wxListBox::OS2Command
629 // ----------------------------------------------------------------------------
630 // wxCheckListBox support
631 // ----------------------------------------------------------------------------
633 #if wxUSE_OWNER_DRAWN
639 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
641 long wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT
* pItem
)
644 pItem
= (WXMEASUREITEMSTRUCT
*)new OWNERITEM
;
646 POWNERITEM pMeasureStruct
= (POWNERITEM
)pItem
;
650 // Only owner-drawn control should receive this message
652 wxCHECK( ((m_windowStyle
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), FALSE
);
654 vDc
.SetFont(GetFont());
663 pMeasureStruct
->rclItem
.xRight
= (USHORT
)vWidth
;
664 pMeasureStruct
->rclItem
.xLeft
= 0;
665 pMeasureStruct
->rclItem
.yTop
= 0;
666 pMeasureStruct
->rclItem
.yBottom
= 0;
668 vHeight
= (wxCoord
)(vDc
.GetCharHeight() * 2.5);
669 pMeasureStruct
->rclItem
.yTop
= (USHORT
)vHeight
;
671 return long(MRFROM2SHORT((USHORT
)vHeight
, (USHORT
)vWidth
));
672 } // end of wxListBox::OS2OnMeasure
674 bool wxListBox::OS2OnDraw (
675 WXDRAWITEMSTRUCT
* pItem
678 POWNERITEM pDrawStruct
= (POWNERITEM
)pItem
;
683 // Only owner-drawn control should receive this message
685 wxCHECK(((m_windowStyle
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), false);
689 // The item may be -1 for an empty listbox
691 if (pDrawStruct
->idItem
== -1L)
694 wxListBoxItem
* pData
= (wxListBoxItem
*)m_aItems
[pDrawStruct
->idItem
];
696 wxClientDC
vDc(this);
697 wxPMDCImpl
*impl
= (wxPMDCImpl
*) vDc
.GetImpl();
698 wxPoint
pt1( pDrawStruct
->rclItem
.xLeft
, pDrawStruct
->rclItem
.yTop
);
699 wxPoint
pt2( pDrawStruct
->rclItem
.xRight
, pDrawStruct
->rclItem
.yBottom
);
700 wxRect
vRect( pt1
, pt2
);
702 impl
->SetHPS(pDrawStruct
->hps
);
704 if (pDrawStruct
->fsAttribute
== pDrawStruct
->fsAttributeOld
)
707 // Entire Item needs to be redrawn (either it has reappeared from
708 // behind another window or is being displayed for the first time
710 eAction
= wxOwnerDrawn::wxODDrawAll
;
712 if (pDrawStruct
->fsAttribute
& MIA_HILITED
)
715 // If it is currently selected we let the system handle it
717 eStatus
|= wxOwnerDrawn::wxODSelected
;
719 if (pDrawStruct
->fsAttribute
& MIA_CHECKED
)
722 // If it is currently checked we draw our own
724 eStatus
|= wxOwnerDrawn::wxODChecked
;
725 pDrawStruct
->fsAttributeOld
= pDrawStruct
->fsAttribute
&= ~MIA_CHECKED
;
727 if (pDrawStruct
->fsAttribute
& MIA_DISABLED
)
730 // If it is currently disabled we let the system handle it
732 eStatus
|= wxOwnerDrawn::wxODDisabled
;
735 // Don't really care about framed (indicationg focus) or NoDismiss
740 if (pDrawStruct
->fsAttribute
& MIA_HILITED
)
742 eAction
= wxOwnerDrawn::wxODDrawAll
;
743 eStatus
|= wxOwnerDrawn::wxODSelected
;
745 // Keep the system from trying to highlight with its bogus colors
747 pDrawStruct
->fsAttributeOld
= pDrawStruct
->fsAttribute
&= ~MIA_HILITED
;
749 else if (!(pDrawStruct
->fsAttribute
& MIA_HILITED
))
751 eAction
= wxOwnerDrawn::wxODDrawAll
;
754 // Keep the system from trying to highlight with its bogus colors
756 pDrawStruct
->fsAttribute
= pDrawStruct
->fsAttributeOld
&= ~MIA_HILITED
;
761 // For now we don't care about anything else
762 // just ignore the entire message!
767 return pData
->OnDrawItem( vDc
769 ,(wxOwnerDrawn::wxODAction
)eAction
770 ,(wxOwnerDrawn::wxODStatus
)(eStatus
| wxOwnerDrawn::wxODHidePrefix
)
772 } // end of wxListBox::OS2OnDraw
774 #endif // ndef for wxUSE_OWNER_DRAWN
776 #endif // wxUSE_LISTBOX