KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_package.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) 2021 Andrew Lutsenko, anlutsenko at gmail dot com
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <math/util.h>
22#include <wx/dcclient.h>
23
24#include "panel_package.h"
25
26PANEL_PACKAGE::PANEL_PACKAGE( wxWindow* parent, const ActionCallback& aCallback,
27 const PinCallback& aPinCallback, const PACKAGE_VIEW_DATA& aData ) :
28 PANEL_PACKAGE_BASE( parent ),
29 m_actionCallback( aCallback ),
30 m_pinCallback( aPinCallback ),
31 m_data( aData )
32{
33 // correct the min size from wxfb with fromdip
34 SetMinSize( FromDIP( GetMinSize() ) );
35
36 // Propagate clicks on static elements to the panel handler.
37 m_name->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
38 m_desc->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
39 m_bitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
40
41 wxColour bgColor = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
42 m_desc->SetBackgroundColour( bgColor );
43 m_name->SetBackgroundColour( bgColor );
44 m_bitmap->SetBackgroundColour( bgColor );
45
46 m_name->SetFont( m_name->GetFont().Bold() );
47
48 m_name->SetLabelText( m_data.package.name );
49 m_bitmap->SetBitmap( *m_data.bitmap );
50
51 // Set min width to 0 otherwise wxStaticLabel really doesn't want to shrink on resize
52 m_desc->SetMinSize( wxSize( 0, -1 ) );
53
54 m_minHeight = GetMinHeight();
55
56 double descLineHeight = m_desc->GetTextExtent( wxT( "X" ) ).GetHeight() * 1.2 /* leading */;
57 m_desc->SetLabelText( m_data.package.description );
58
59#if wxCHECK_VERSION( 3, 3, 2 )
60 m_desc->SetWindowStyle( wxST_WRAP );
61#else
62 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
63#endif
64
65 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
66
67 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
68 wxSize minSize = GetMinSize();
69 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + FromDIP( 15 ), m_minHeight );
70 SetMinSize( minSize );
71
72 m_splitButton->SetLabel( _( "Update" ) );
73 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
74
75 wxMenu* splitMenu = m_splitButton->GetSplitButtonMenu();
77 splitMenu->Append( wxID_ANY, _( "Pin package" ),
78 _( "Pinned packages don't affect available update notification and "
79 "will not be updated with 'Update All' button." ),
80 wxITEM_CHECK );
81 splitMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_PACKAGE::OnPinVersionClick, this,
82 m_pinVersionMenuItem->GetId() );
83
84 m_actionMenuItem = splitMenu->Append( wxID_ANY, _( "Uninstall" ) );
85
86 SetState( m_data.state, m_data.pinned );
87}
88
89
90void PANEL_PACKAGE::OnSize( wxSizeEvent& event )
91{
92 Layout();
93
94 double descLineHeight = m_desc->GetTextExtent( wxT( "X" ) ).GetHeight() * 1.2 /* leading */;
95
96#if !wxCHECK_VERSION( 3, 3, 2 )
97 m_desc->SetLabelText( m_data.package.description );
98 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
99#endif
100
101 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
102
103 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
104 wxSize minSize = GetMinSize();
105 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + 15, m_minHeight );
106 SetMinSize( minSize );
107}
108
109
110void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState, bool aPinned )
111{
112 m_data.state = aState;
113 m_data.pinned = aPinned;
114 m_splitButton->GetSplitButtonMenu()->Check( m_pinVersionMenuItem->GetId(), aPinned );
115
116 switch( aState )
117 {
119 m_splitButton->Hide();
120 m_button->Show();
121 m_button->SetLabel( _( "Install" ) );
122 m_button->Enable();
123 break;
125 m_splitButton->Hide();
126 m_button->Show();
127 m_button->SetLabel( _( "Install" ) );
128 m_button->Disable();
129 break;
131 m_button->Hide();
132 m_splitButton->Show();
133
134 m_splitButton->SetLabel( _( "Uninstall" ) );
135 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
136
137 m_actionMenuItem->SetItemLabel( _( "Update" ) );
138 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), false );
139
140 break;
142 m_splitButton->Hide();
143 m_button->Show();
144 m_button->SetLabel( _( "Install Pending" ) );
145 m_button->Disable();
146 break;
148 m_splitButton->Hide();
149 m_button->Show();
150 m_button->SetLabel( _( "Uninstall Pending" ) );
151 m_button->Disable();
152 break;
154 m_button->Hide();
155 m_splitButton->Show();
156
157 if( aPinned )
158 {
159 m_splitButton->SetLabel( _( "Uninstall" ) );
160 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnUninstallClick, this );
161
162 m_actionMenuItem->SetItemLabel( _( "Update" ) );
163 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
164 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
166 m_actionMenuItem->GetId() );
167 }
168 else
169 {
170 m_splitButton->SetLabel( _( "Update" ) );
171 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
172
173 m_actionMenuItem->SetItemLabel( _( "Uninstall" ) );
174 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
175 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
177 m_actionMenuItem->GetId() );
178 }
179 break;
181 m_splitButton->Hide();
182 m_button->Show();
183 m_button->SetLabel( _( "Update Pending" ) );
184 m_button->Disable();
185 break;
186 }
187
188 // Relayout to change button size to fit the label.
189 Layout();
190}
191
192
193void PANEL_PACKAGE::OnButtonClicked( wxCommandEvent& event )
194{
195 if( m_data.state == PPS_AVAILABLE )
196 {
197 wxString version = GetPreferredVersion();
198
199 if( version.IsEmpty() )
200 return;
201
203 }
204 else if( m_data.state == PPS_UPDATE_AVAILABLE )
205 {
206 m_actionCallback( m_data, PPA_UPDATE, m_data.update_version );
207 }
208 else
209 {
210 m_actionCallback( m_data, PPA_UNINSTALL, m_data.current_version );
211 }
212}
213
214
215void PANEL_PACKAGE::OnPinVersionClick( wxCommandEvent& event )
216{
217 m_data.pinned = event.IsChecked();
218
219 m_pinCallback( m_data.package.identifier, m_data.state, m_data.pinned );
220}
221
222
223void PANEL_PACKAGE::OnUninstallClick( wxCommandEvent& event )
224{
225 if( m_data.state == PPS_UPDATE_AVAILABLE )
226 {
227 m_actionCallback( m_data, PPA_UNINSTALL, m_data.current_version );
228 }
229 else
230 {
231 // Clicking uninstall menu item of the split button should not be possible
232 // for any state other than UPDATE_AVAILABLE
233 wxLogError( wxT( "Uninstall clicked in unexpected state" ) );
234 }
235}
236
237
238void PANEL_PACKAGE::SetSelectCallback( const std::function<void()>& aCallback )
239{
240 m_selectCallback = aCallback;
241}
242
243
244void PANEL_PACKAGE::OnClick( wxMouseEvent& event )
245{
247}
248
249
250void PANEL_PACKAGE::OnPaint( wxPaintEvent& event )
251{
252 wxRect rect( wxPoint( 1, 1 ), GetClientSize() - wxSize( 1, 1 ) );
253 wxPaintDC dc( this );
254 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
255 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
256
257 if( m_selected )
258 {
259 rect.Deflate( 1 );
260 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_HOTLIGHT ), 3 ) );
261 }
262
263 dc.DrawRectangle( rect );
264}
265
266
267void PANEL_PACKAGE::SetSelected( bool aSelected )
268{
269 m_selected = aSelected;
270 Refresh();
271}
272
273
275{
276 // Versions are already presorted in descending order
277
278 // Find last stable compatible version
279 auto ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
280 []( const PACKAGE_VERSION& ver )
281 {
282 return ver.compatible && ver.status == PVS_STABLE;
283 } );
284
285 // If not found then find any compatible version
286 if( ver_it == m_data.package.versions.end() )
287 {
288 ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
289 []( const PACKAGE_VERSION& ver )
290 {
291 return ver.compatible;
292 } );
293 }
294
295 if( ver_it == m_data.package.versions.end() )
296 return wxEmptyString; // Shouldn't happen
297
298 return ver_it->version;
299}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
wxStaticBitmap * m_bitmap
PANEL_PACKAGE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxBORDER_NONE|wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
SPLIT_BUTTON * m_splitButton
void OnClick(wxMouseEvent &event) override
void OnUninstallClick(wxCommandEvent &event)
wxMenuItem * m_actionMenuItem
void OnPinVersionClick(wxCommandEvent &event)
void OnPaint(wxPaintEvent &event) override
void SetSelected(bool aSelected)
void OnButtonClicked(wxCommandEvent &event) override
Changes state of the (un)install button.
const ActionCallback & m_actionCallback
const PinCallback & m_pinCallback
wxMenuItem * m_pinVersionMenuItem
PACKAGE_VIEW_DATA m_data
void SetState(PCM_PACKAGE_STATE aState, bool aPinned)
Called when anywhere on the panel is clicked (except install button)
PANEL_PACKAGE(wxWindow *parent, const ActionCallback &aCallback, const PinCallback &aPinCallback, const PACKAGE_VIEW_DATA &aData)
Sets callback for OnClick action.
void OnSize(wxSizeEvent &event) override
Get preferred version. If criteria are not met, return wxEmptyString.
std::function< void()> m_selectCallback
void SetSelectCallback(const std::function< void()> &aCallback)
Marks panel as selected.
wxString GetPreferredVersion() const
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
std::function< void(const wxString &aPackageId, const PCM_PACKAGE_STATE aState, const bool aPinned)> PinCallback
std::function< void(const PACKAGE_VIEW_DATA &aData, PCM_PACKAGE_ACTION aAction, const wxString &aVersion)> ActionCallback
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
PCM_PACKAGE_STATE
Definition pcm.h:58
@ PPS_INSTALLED
Definition pcm.h:61
@ PPS_PENDING_UPDATE
Definition pcm.h:65
@ PPS_UNAVAILABLE
Definition pcm.h:60
@ PPS_UPDATE_AVAILABLE
Definition pcm.h:64
@ PPS_PENDING_UNINSTALL
Definition pcm.h:63
@ PPS_PENDING_INSTALL
Definition pcm.h:62
@ PPS_AVAILABLE
Definition pcm.h:59
@ PPA_UNINSTALL
Definition pcm.h:73
@ PPA_UPDATE
Definition pcm.h:74
@ PPA_INSTALL
Definition pcm.h:72
< Package version metadataPackage metadata
Definition pcm_data.h:92
< Collection of data relevant to the package display panelCallback for (un)install button