KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_choice.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 The 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>
22#include <wx/dc.h>
23#include <wx/pen.h>
24
25wxColour FOOTPRINT_CHOICE::m_grey( 0x808080 );
26
27
28FOOTPRINT_CHOICE::FOOTPRINT_CHOICE( wxWindow* aParent, int aId ) :
29 wxOwnerDrawnComboBox( aParent, aId, wxEmptyString, wxDefaultPosition, wxDefaultSize,
30 /* n */ 0, /* choices */ nullptr, wxCB_READONLY ),
31 m_last_selection( 0 )
32{
33}
34
35
37{
38}
39
40
41void FOOTPRINT_CHOICE::DoSetPopupControl( wxComboPopup* aPopup )
42{
43 using namespace std::placeholders;
44 wxOwnerDrawnComboBox::DoSetPopupControl( aPopup );
45
46 // Bind events to intercept selections, so the separator can be made nonselectable.
47
48 GetVListBoxComboPopup()->Bind( wxEVT_MOTION, &FOOTPRINT_CHOICE::TryVetoMouse, this );
49 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DOWN, &FOOTPRINT_CHOICE::TryVetoMouse, this );
50 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_UP, &FOOTPRINT_CHOICE::TryVetoMouse, this );
51 GetVListBoxComboPopup()->Bind( wxEVT_LEFT_DCLICK, &FOOTPRINT_CHOICE::TryVetoMouse, this );
52 GetVListBoxComboPopup()->Bind( wxEVT_LISTBOX, std::bind( &FOOTPRINT_CHOICE::TryVetoSelect,
53 this, _1, true ) );
54 Bind( wxEVT_COMBOBOX, std::bind( &FOOTPRINT_CHOICE::TryVetoSelect, this, _1, false ) );
55}
56
57
58void FOOTPRINT_CHOICE::OnDrawItem( wxDC& aDC, wxRect const& aRect, int aItem, int aFlags ) const
59{
60 wxString text = SafeGetString( aItem );
61
62 if( text == wxEmptyString )
63 {
64 wxPen pen( m_grey, 1, wxPENSTYLE_SOLID );
65
66 aDC.SetPen( pen );
67 aDC.DrawLine( aRect.x, aRect.y + aRect.height / 2, aRect.x + aRect.width,
68 aRect.y + aRect.height / 2 );
69 }
70 else
71 {
72 wxCoord x, y;
73
74 if( aFlags & wxODCB_PAINTING_CONTROL )
75 {
76 x = aRect.x + GetMargins().x;
77 y = ( aRect.height - aDC.GetCharHeight() ) / 2 + aRect.y;
78 }
79 else
80 {
81 x = aRect.x + 2;
82 y = aRect.y;
83 }
84
85 // If this item has a footprint and that footprint has a ":" delimiter, find the
86 // library component, then find that in the display string and grey it out.
87 size_t start_grey = 0;
88 size_t end_grey = 0;
89
90 wxString lib = static_cast<wxStringClientData*>( GetClientObject( aItem ) )->GetData();
91 size_t colon_index = lib.rfind( ':' );
92
93 if( colon_index != wxString::npos )
94 {
95 wxString library_part = lib.SubString( 0, colon_index );
96 size_t library_index = text.rfind( library_part );
97
98 if( library_index != wxString::npos )
99 {
100 start_grey = library_index;
101 end_grey = start_grey + library_part.Length();
102 }
103 }
104
105 if( start_grey != end_grey && !( aFlags & wxODCB_PAINTING_SELECTED ) )
106 {
107 x = DrawTextFragment( aDC, x, y, text.SubString( 0, start_grey - 1 ) );
108
109 wxColour standard_color = aDC.GetTextForeground();
110
111 aDC.SetTextForeground( m_grey );
112 x = DrawTextFragment( aDC, x, y, text.SubString( start_grey, end_grey - 1 ) );
113
114 aDC.SetTextForeground( standard_color );
115 x = DrawTextFragment( aDC, x, y, text.SubString( end_grey, text.Length() - 1 ) );
116 }
117 else
118 {
119 aDC.DrawText( text, x, y );
120 }
121 }
122}
123
124
125wxCoord FOOTPRINT_CHOICE::OnMeasureItem( size_t aItem ) const
126{
127 if( SafeGetString( aItem ) == wxS( "" ) )
128 return 11;
129 else
130 return wxOwnerDrawnComboBox::OnMeasureItem( aItem );
131}
132
133
134wxCoord FOOTPRINT_CHOICE::OnMeasureItemWidth( size_t aItem ) const
135{
136 if( SafeGetString( aItem ) == wxS( "" ) )
137 return GetTextRect().GetWidth() - 2;
138 else
139 return wxOwnerDrawnComboBox::OnMeasureItemWidth( aItem );
140}
141
142
143wxCoord FOOTPRINT_CHOICE::DrawTextFragment( wxDC& aDC, wxCoord x, wxCoord y, wxString const& aText )
144{
145 aDC.DrawText( aText, x, y );
146 return x + aDC.GetTextExtent( aText ).GetWidth();
147}
148
149
150void FOOTPRINT_CHOICE::TryVetoMouse( wxMouseEvent& aEvent )
151{
152 int item = GetVListBoxComboPopup()->VirtualHitTest( aEvent.GetPosition().y );
153
154 if( SafeGetString( item ) != wxS( "" ) )
155 aEvent.Skip();
156}
157
158
159void FOOTPRINT_CHOICE::TryVetoSelect( wxCommandEvent& aEvent, bool aInner )
160{
161 int sel = GetSelectionEither( aInner );
162
163 if( sel >= 0 && sel < (int) GetCount() )
164 {
165 wxString text = SafeGetString( sel );
166
167 if( text == "" )
168 {
170 }
171 else
172 {
173 m_last_selection = sel;
174 aEvent.Skip();
175 }
176 }
177}
178
179
180wxString FOOTPRINT_CHOICE::SafeGetString( int aItem ) const
181{
182 if( aItem >= 0 && aItem < (int) GetCount() )
183 return GetVListBoxComboPopup()->GetString( aItem );
184 else
185 return wxEmptyString;
186}
187
188
190{
191 if( aInner )
192 return GetVListBoxComboPopup()->wxVListBox::GetSelection();
193 else
194 return GetSelection();
195}
196
197
198void FOOTPRINT_CHOICE::SetSelectionEither( bool aInner, int aSel )
199{
200 if( aSel >= 0 && aSel < (int) GetCount() )
201 {
202 if( aInner )
203 return GetVListBoxComboPopup()->wxVListBox::SetSelection( aSel );
204 else
205 return SetSelection( aSel );
206 }
207}
wxString SafeGetString(int aItem) const
Safely get a string for an item, returning wxEmptyString if the item doesn't exist.
virtual wxCoord OnMeasureItem(size_t aItem) const override
void TryVetoSelect(wxCommandEvent &aEvent, bool aInner)
Veto a select event for the separator.
static wxColour m_grey
virtual ~FOOTPRINT_CHOICE()
static wxCoord DrawTextFragment(wxDC &aDC, wxCoord x, wxCoord y, const wxString &aText)
Draw a fragment of text, then return the next x coordinate to continue drawing.
void SetSelectionEither(bool aInner, int aSel)
Safely set selection for either the outer (combo box) or inner (popup) list, doing nothing for invali...
FOOTPRINT_CHOICE(wxWindow *aParent, int aId)
virtual wxCoord OnMeasureItemWidth(size_t aItem) const override
void TryVetoMouse(wxMouseEvent &aEvent)
Veto a mouseover event if in the separator.
virtual void DoSetPopupControl(wxComboPopup *aPopup) override
int GetSelectionEither(bool aInner) const
Get selection from either the outer (combo box) or inner (popup) list.
virtual void OnDrawItem(wxDC &aDC, const wxRect &aRect, int aItem, int aFlags) const override