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 (C) 1992-2022 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 // Propagate clicks on static elements to the panel handler.
34 m_name->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
35 m_desc->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
36 m_bitmap->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( PANEL_PACKAGE::OnClick ), NULL, this );
37
38 wxColour bgColor = wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK );
39 m_desc->SetBackgroundColour( bgColor );
40 m_name->SetBackgroundColour( bgColor );
41 m_bitmap->SetBackgroundColour( bgColor );
42
43 m_name->SetFont( m_name->GetFont().Bold() );
44
45 m_name->SetLabelText( m_data.package.name );
46 m_bitmap->SetBitmap( *m_data.bitmap );
47
48 // Set min width to 0 otherwise wxStaticLabel really doesn't want to shrink on resize
49 m_desc->SetMinSize( wxSize( 0, -1 ) );
50
51 m_minHeight = GetMinHeight();
52
53 double descLineHeight = m_desc->GetTextExtent( wxT( "X" ) ).GetHeight() * 1.2 /* leading */;
54 m_desc->SetLabelText( m_data.package.description );
55 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
56 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
57
58 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
59 wxSize minSize = GetMinSize();
60 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + 15, m_minHeight );
61 SetMinSize( minSize );
62
63 m_splitButton->SetLabel( _( "Update" ) );
64 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
65
66 wxMenu* splitMenu = m_splitButton->GetSplitButtonMenu();
68 splitMenu->Append( wxID_ANY, _( "Pin package" ),
69 _( "Pinned packages don't affect available update notification and "
70 "will not be updated with 'Update All' button." ),
71 wxITEM_CHECK );
72 splitMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_PACKAGE::OnPinVersionClick, this,
73 m_pinVersionMenuItem->GetId() );
74
75 m_actionMenuItem = splitMenu->Append( wxID_ANY, _( "Uninstall" ) );
76
78}
79
80
81void PANEL_PACKAGE::OnSize( wxSizeEvent& event )
82{
83 Layout();
84
85 double descLineHeight = m_desc->GetTextExtent( wxT( "X" ) ).GetHeight() * 1.2 /* leading */;
86 m_desc->SetLabelText( m_data.package.description );
87 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
88 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
89
90 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
91 wxSize minSize = GetMinSize();
92 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + 15, m_minHeight );
93 SetMinSize( minSize );
94}
95
96
97void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState, bool aPinned )
98{
99 m_data.state = aState;
100 m_data.pinned = aPinned;
101 m_splitButton->GetSplitButtonMenu()->Check( m_pinVersionMenuItem->GetId(), aPinned );
102
103 switch( aState )
104 {
105 case PCM_PACKAGE_STATE::PPS_AVAILABLE:
106 m_splitButton->Hide();
107 m_button->Show();
108 m_button->SetLabel( _( "Install" ) );
109 m_button->Enable();
110 break;
111 case PCM_PACKAGE_STATE::PPS_UNAVAILABLE:
112 m_splitButton->Hide();
113 m_button->Show();
114 m_button->SetLabel( _( "Install" ) );
115 m_button->Disable();
116 break;
117 case PCM_PACKAGE_STATE::PPS_INSTALLED:
118 m_button->Hide();
119 m_splitButton->Show();
120
121 m_splitButton->SetLabel( _( "Uninstall" ) );
122 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
123
124 m_actionMenuItem->SetItemLabel( _( "Update" ) );
125 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), false );
126
127 break;
128 case PCM_PACKAGE_STATE::PPS_PENDING_INSTALL:
129 m_splitButton->Hide();
130 m_button->Show();
131 m_button->SetLabel( _( "Install Pending" ) );
132 m_button->Disable();
133 break;
134 case PCM_PACKAGE_STATE::PPS_PENDING_UNINSTALL:
135 m_splitButton->Hide();
136 m_button->Show();
137 m_button->SetLabel( _( "Uninstall Pending" ) );
138 m_button->Disable();
139 break;
140 case PCM_PACKAGE_STATE::PPS_UPDATE_AVAILABLE:
141 m_button->Hide();
142 m_splitButton->Show();
143
144 if( aPinned )
145 {
146 m_splitButton->SetLabel( _( "Uninstall" ) );
147 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnUninstallClick, this );
148
149 m_actionMenuItem->SetItemLabel( _( "Update" ) );
150 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
151 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
153 m_actionMenuItem->GetId() );
154 }
155 else
156 {
157 m_splitButton->SetLabel( _( "Update" ) );
158 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
159
160 m_actionMenuItem->SetItemLabel( _( "Uninstall" ) );
161 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
162 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
164 m_actionMenuItem->GetId() );
165 }
166 break;
167 case PCM_PACKAGE_STATE::PPS_PENDING_UPDATE:
168 m_splitButton->Hide();
169 m_button->Show();
170 m_button->SetLabel( _( "Update Pending" ) );
171 m_button->Disable();
172 break;
173 }
174
175 // Relayout to change button size to fit the label.
176 Layout();
177}
178
179
180void PANEL_PACKAGE::OnButtonClicked( wxCommandEvent& event )
181{
182 if( m_data.state == PPS_AVAILABLE )
183 {
184 wxString version = GetPreferredVersion();
185
186 if( version.IsEmpty() )
187 return;
188
190 }
191 else if( m_data.state == PPS_UPDATE_AVAILABLE )
192 {
194 }
195 else
196 {
198 }
199}
200
201
202void PANEL_PACKAGE::OnPinVersionClick( wxCommandEvent& event )
203{
204 m_data.pinned = event.IsChecked();
205
207}
208
209
210void PANEL_PACKAGE::OnUninstallClick( wxCommandEvent& event )
211{
213 {
215 }
216 else
217 {
218 // Clicking uninstall menu item of the split button should not be possible
219 // for any state other than UPDATE_AVAILABLE
220 wxLogError( wxT( "Uninstall clicked in unexpected state" ) );
221 }
222}
223
224
225void PANEL_PACKAGE::SetSelectCallback( const std::function<void()>& aCallback )
226{
227 m_selectCallback = aCallback;
228}
229
230
231void PANEL_PACKAGE::OnClick( wxMouseEvent& event )
232{
234}
235
236
237void PANEL_PACKAGE::OnPaint( wxPaintEvent& event )
238{
239 wxRect rect( wxPoint( 1, 1 ), GetClientSize() - wxSize( 1, 1 ) );
240 wxPaintDC dc( this );
241 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
242 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
243
244 if( m_selected )
245 {
246 rect.Deflate( 1 );
247 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_HOTLIGHT ), 3 ) );
248 }
249
250 dc.DrawRectangle( rect );
251}
252
253
254void PANEL_PACKAGE::SetSelected( bool aSelected )
255{
256 m_selected = aSelected;
257 Refresh();
258}
259
260
262{
263 // Versions are already presorted in descending order
264
265 // Find last stable compatible version
266 auto ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
267 []( const PACKAGE_VERSION& ver )
268 {
269 return ver.compatible && ver.status == PVS_STABLE;
270 } );
271
272 // If not found then find any compatible version
273 if( ver_it == m_data.package.versions.end() )
274 {
275 ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
276 []( const PACKAGE_VERSION& ver )
277 {
278 return ver.compatible;
279 } );
280 }
281
282 if( ver_it == m_data.package.versions.end() )
283 return wxEmptyString; // Shouldn't happen
284
285 return ver_it->version;
286}
Class PANEL_PACKAGE_BASE.
wxStaticText * m_name
wxStaticBitmap * m_bitmap
wxStaticText * m_desc
SPLIT_BUTTON * m_splitButton
wxBoxSizer * m_descSizer
void OnClick(wxMouseEvent &event) override
void OnUninstallClick(wxCommandEvent &event)
wxMenuItem * m_actionMenuItem
Definition: panel_package.h:99
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
Definition: panel_package.h:98
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
void SetLabel(const wxString &aLabel) override
wxMenu * GetSplitButtonMenu()
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
Definition: panel_package.h:60
std::function< void(const PACKAGE_VIEW_DATA &aData, PCM_PACKAGE_ACTION aAction, const wxString &aVersion)> ActionCallback
Definition: panel_package.h:57
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:57
@ PPS_UPDATE_AVAILABLE
Definition: pcm.h:63
@ PPS_AVAILABLE
Definition: pcm.h:58
@ PPA_UNINSTALL
Definition: pcm.h:72
@ PPA_UPDATE
Definition: pcm.h:73
@ PPA_INSTALL
Definition: pcm.h:71
< Package version metadata Package metadata
Definition: pcm_data.h:75
< Collection of data relevant to the package display panel Callback for (un)install button
Definition: panel_package.h:31
wxString update_version
Definition: panel_package.h:39
wxString current_version
Definition: panel_package.h:38
const PCM_PACKAGE package
Definition: panel_package.h:32
wxBitmap * bitmap
Definition: panel_package.h:33
PCM_PACKAGE_STATE state
Definition: panel_package.h:34
wxString description
Definition: pcm_data.h:98
wxString identifier
Definition: pcm_data.h:100
wxString name
Definition: pcm_data.h:97
std::vector< PACKAGE_VERSION > versions
Definition: pcm_data.h:108
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85