KiCad PCB EDA Suite
Loading...
Searching...
No Matches
wx_combobox.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <functional>
21#include <widgets/wx_combobox.h>
22#include <wx/dc.h>
23#include <wx/pen.h>
24#include <wx/settings.h>
25
26
27#define SEPARATOR wxT( "---" )
28
29
30WX_COMBOBOX::WX_COMBOBOX( wxWindow* aParent, int aId, const wxString& aValue, const wxPoint& aPos,
31 const wxSize& aSize, int n, const wxString choices[], long style ) :
32 wxOwnerDrawnComboBox( aParent, aId, aValue, aPos, aSize, n, choices, style ),
33 m_lastSelection( 0 )
34{
35}
36
37
39{
40}
41
42
43void WX_COMBOBOX::DoSetPopupControl( wxComboPopup* aPopup )
44{
45 using namespace std::placeholders;
46 wxOwnerDrawnComboBox::DoSetPopupControl( aPopup );
47
48 // Bind events to intercept selections, so the separator can be made nonselectable.
49
50 GetVListBoxComboPopup()->Bind( wxEVT_MOTION, &WX_COMBOBOX::TryVetoMouse, this );
51 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DOWN, &WX_COMBOBOX::TryVetoMouse, this );
52 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_UP, &WX_COMBOBOX::TryVetoMouse, this );
53 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DCLICK, &WX_COMBOBOX::TryVetoMouse, this );
54 GetVListBoxComboPopup()->Bind( wxEVT_LISTBOX, std::bind( &WX_COMBOBOX::TryVetoSelect,
55 this, _1, true ) );
56
57 Bind( wxEVT_COMBOBOX, std::bind( &WX_COMBOBOX::TryVetoSelect, this, _1, false ) );
58}
59
60
61void WX_COMBOBOX::OnDrawItem( wxDC& aDC, wxRect const& aRect, int aItem, int aFlags ) const
62{
63 wxString text = GetMenuText( aItem );
64
65 if( text == SEPARATOR )
66 {
67 wxPen pen( wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT ), 1 );
68
69 aDC.SetPen( pen );
70 aDC.DrawLine( aRect.x, aRect.y + aRect.height / 2, aRect.x + aRect.width,
71 aRect.y + aRect.height / 2 );
72 }
73 else
74 {
75 wxCoord x, y;
76
77 if( aFlags & wxODCB_PAINTING_CONTROL )
78 {
79 x = aRect.x + GetMargins().x;
80 y = ( aRect.height - aDC.GetCharHeight() ) / 2 + aRect.y;
81 }
82 else
83 {
84 x = aRect.x + 2;
85 y = aRect.y;
86 }
87
88 aDC.DrawText( text, x, y );
89 }
90}
91
92
94{
95 return wxOwnerDrawnComboBox::GetCharHeight() + 2;
96}
97
98
99wxCoord WX_COMBOBOX::OnMeasureItem( size_t aItem ) const
100{
101 if( GetMenuText( aItem ) == SEPARATOR )
102 return 11;
103 else
104 return wxOwnerDrawnComboBox::OnMeasureItem( aItem );
105}
106
107
108wxCoord WX_COMBOBOX::OnMeasureItemWidth( size_t aItem ) const
109{
110 if( GetMenuText( aItem ) == SEPARATOR )
111 return GetTextRect().GetWidth() - 2;
112 else
113 return wxOwnerDrawnComboBox::OnMeasureItemWidth( aItem );
114}
115
116
117void WX_COMBOBOX::TryVetoMouse( wxMouseEvent& aEvent )
118{
119 int item = GetVListBoxComboPopup()->VirtualHitTest( aEvent.GetPosition().y );
120
121 if( GetMenuText( item ) != SEPARATOR )
122 aEvent.Skip();
123}
124
125
126void WX_COMBOBOX::TryVetoSelect( wxCommandEvent& aEvent, bool aInner )
127{
128 int sel = GetSelectionEither( aInner );
129
130 if( sel >= 0 && sel < (int) GetCount() )
131 {
132 wxString text = GetMenuText( sel );
133
134 if( text == SEPARATOR )
135 {
137 }
138 else
139 {
140 m_lastSelection = sel;
141 aEvent.Skip();
142 }
143 }
144}
145
146
147void WX_COMBOBOX::Append( const wxString& aText, const wxString& aMenuText )
148{
149 if( !aMenuText.IsEmpty() )
150 m_menuText[ GetCount() ] = aMenuText;
151
152 wxOwnerDrawnComboBox::Append( aText );
153}
154
155
156wxString WX_COMBOBOX::GetMenuText( int aItem ) const
157{
158 if( m_menuText.count( aItem ) )
159 return m_menuText.at( aItem );
160 else if( aItem >= 0 && aItem < (int) GetCount() )
161 return GetVListBoxComboPopup()->GetString( aItem );
162 else
163 return wxEmptyString;
164}
165
166
167int WX_COMBOBOX::GetSelectionEither( bool aInner ) const
168{
169 if( aInner )
170 return GetVListBoxComboPopup()->wxVListBox::GetSelection();
171 else
172 return GetSelection();
173}
174
175
176void WX_COMBOBOX::SetSelectionEither( bool aInner, int aSel )
177{
178 if( aSel >= 0 && aSel < (int) GetCount() )
179 {
180 if( aInner )
181 return GetVListBoxComboPopup()->wxVListBox::SetSelection( aSel );
182 else
183 return SetSelection( aSel );
184 }
185}
virtual wxCoord OnMeasureItemWidth(size_t aItem) const override
void Append(const wxString &aText, const wxString &aMenuText=wxEmptyString)
WX_COMBOBOX(wxWindow *aParent, int aId=wxID_ANY, const wxString &aValue=wxEmptyString, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize, int n=0, const wxString choices[]=nullptr, long style=0)
Definition: wx_combobox.cpp:30
virtual void DoSetPopupControl(wxComboPopup *aPopup) override
Definition: wx_combobox.cpp:43
void TryVetoSelect(wxCommandEvent &aEvent, bool aInner)
Veto a select event for the separator.
void SetSelectionEither(bool aInner, int aSel)
Safely set selection for either the outer (combo box) or inner (popup) list, doing nothing for invali...
int m_lastSelection
Definition: wx_combobox.h:80
virtual ~WX_COMBOBOX()
Definition: wx_combobox.cpp:38
virtual wxCoord OnMeasureItem(size_t aItem) const override
Definition: wx_combobox.cpp:99
std::map< int, wxString > m_menuText
Definition: wx_combobox.h:79
void TryVetoMouse(wxMouseEvent &aEvent)
Veto a mouseover event if in the separator.
int GetSelectionEither(bool aInner) const
Get selection from either the outer (combo box) or inner (popup) list.
wxString GetMenuText(int aItem) const
Safely get a string for an item, returning wxEmptyString if the item doesn't exist.
virtual void OnDrawItem(wxDC &aDC, const wxRect &aRect, int aItem, int aFlags) const override
Definition: wx_combobox.cpp:61
int GetCharHeight() const override
Definition: wx_combobox.cpp:93
#define SEPARATOR
Definition: wx_combobox.cpp:27