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 // 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 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
59 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
60
61 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
62 wxSize minSize = GetMinSize();
63 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + FromDIP( 15 ), m_minHeight );
64 SetMinSize( minSize );
65
66 m_splitButton->SetLabel( _( "Update" ) );
67 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
68
69 wxMenu* splitMenu = m_splitButton->GetSplitButtonMenu();
71 splitMenu->Append( wxID_ANY, _( "Pin package" ),
72 _( "Pinned packages don't affect available update notification and "
73 "will not be updated with 'Update All' button." ),
74 wxITEM_CHECK );
75 splitMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_PACKAGE::OnPinVersionClick, this,
76 m_pinVersionMenuItem->GetId() );
77
78 m_actionMenuItem = splitMenu->Append( wxID_ANY, _( "Uninstall" ) );
79
81}
82
83
84void PANEL_PACKAGE::OnSize( wxSizeEvent& event )
85{
86 Layout();
87
88 double descLineHeight = m_desc->GetTextExtent( wxT( "X" ) ).GetHeight() * 1.2 /* leading */;
89 m_desc->SetLabelText( m_data.package.description );
90 m_desc->Wrap( m_descSizer->GetSize().GetWidth() );
91 descLineHeight = wxSplit( m_desc->GetLabel(), '\n' ).size() * descLineHeight;
92
93 int nameLineHeight = m_name->GetTextExtent( wxT( "X" ) ).GetHeight();
94 wxSize minSize = GetMinSize();
95 minSize.y = std::max( nameLineHeight + KiROUND( descLineHeight ) + 15, m_minHeight );
96 SetMinSize( minSize );
97}
98
99
100void PANEL_PACKAGE::SetState( PCM_PACKAGE_STATE aState, bool aPinned )
101{
102 m_data.state = aState;
103 m_data.pinned = aPinned;
104 m_splitButton->GetSplitButtonMenu()->Check( m_pinVersionMenuItem->GetId(), aPinned );
105
106 switch( aState )
107 {
108 case PCM_PACKAGE_STATE::PPS_AVAILABLE:
109 m_splitButton->Hide();
110 m_button->Show();
111 m_button->SetLabel( _( "Install" ) );
112 m_button->Enable();
113 break;
114 case PCM_PACKAGE_STATE::PPS_UNAVAILABLE:
115 m_splitButton->Hide();
116 m_button->Show();
117 m_button->SetLabel( _( "Install" ) );
118 m_button->Disable();
119 break;
120 case PCM_PACKAGE_STATE::PPS_INSTALLED:
121 m_button->Hide();
122 m_splitButton->Show();
123
124 m_splitButton->SetLabel( _( "Uninstall" ) );
125 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
126
127 m_actionMenuItem->SetItemLabel( _( "Update" ) );
128 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), false );
129
130 break;
131 case PCM_PACKAGE_STATE::PPS_PENDING_INSTALL:
132 m_splitButton->Hide();
133 m_button->Show();
134 m_button->SetLabel( _( "Install Pending" ) );
135 m_button->Disable();
136 break;
137 case PCM_PACKAGE_STATE::PPS_PENDING_UNINSTALL:
138 m_splitButton->Hide();
139 m_button->Show();
140 m_button->SetLabel( _( "Uninstall Pending" ) );
141 m_button->Disable();
142 break;
143 case PCM_PACKAGE_STATE::PPS_UPDATE_AVAILABLE:
144 m_button->Hide();
145 m_splitButton->Show();
146
147 if( aPinned )
148 {
149 m_splitButton->SetLabel( _( "Uninstall" ) );
150 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnUninstallClick, this );
151
152 m_actionMenuItem->SetItemLabel( _( "Update" ) );
153 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
154 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
156 m_actionMenuItem->GetId() );
157 }
158 else
159 {
160 m_splitButton->SetLabel( _( "Update" ) );
161 m_splitButton->Bind( wxEVT_BUTTON, &PANEL_PACKAGE::OnButtonClicked, this );
162
163 m_actionMenuItem->SetItemLabel( _( "Uninstall" ) );
164 m_splitButton->GetSplitButtonMenu()->Enable( m_actionMenuItem->GetId(), true );
165 m_splitButton->GetSplitButtonMenu()->Bind( wxEVT_COMMAND_MENU_SELECTED,
167 m_actionMenuItem->GetId() );
168 }
169 break;
170 case PCM_PACKAGE_STATE::PPS_PENDING_UPDATE:
171 m_splitButton->Hide();
172 m_button->Show();
173 m_button->SetLabel( _( "Update Pending" ) );
174 m_button->Disable();
175 break;
176 }
177
178 // Relayout to change button size to fit the label.
179 Layout();
180}
181
182
183void PANEL_PACKAGE::OnButtonClicked( wxCommandEvent& event )
184{
185 if( m_data.state == PPS_AVAILABLE )
186 {
187 wxString version = GetPreferredVersion();
188
189 if( version.IsEmpty() )
190 return;
191
193 }
194 else if( m_data.state == PPS_UPDATE_AVAILABLE )
195 {
197 }
198 else
199 {
201 }
202}
203
204
205void PANEL_PACKAGE::OnPinVersionClick( wxCommandEvent& event )
206{
207 m_data.pinned = event.IsChecked();
208
210}
211
212
213void PANEL_PACKAGE::OnUninstallClick( wxCommandEvent& event )
214{
216 {
218 }
219 else
220 {
221 // Clicking uninstall menu item of the split button should not be possible
222 // for any state other than UPDATE_AVAILABLE
223 wxLogError( wxT( "Uninstall clicked in unexpected state" ) );
224 }
225}
226
227
228void PANEL_PACKAGE::SetSelectCallback( const std::function<void()>& aCallback )
229{
230 m_selectCallback = aCallback;
231}
232
233
234void PANEL_PACKAGE::OnClick( wxMouseEvent& event )
235{
237}
238
239
240void PANEL_PACKAGE::OnPaint( wxPaintEvent& event )
241{
242 wxRect rect( wxPoint( 1, 1 ), GetClientSize() - wxSize( 1, 1 ) );
243 wxPaintDC dc( this );
244 dc.SetBrush( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
245 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVEBORDER ), 1 ) );
246
247 if( m_selected )
248 {
249 rect.Deflate( 1 );
250 dc.SetPen( wxPen( wxSystemSettings::GetColour( wxSYS_COLOUR_HOTLIGHT ), 3 ) );
251 }
252
253 dc.DrawRectangle( rect );
254}
255
256
257void PANEL_PACKAGE::SetSelected( bool aSelected )
258{
259 m_selected = aSelected;
260 Refresh();
261}
262
263
265{
266 // Versions are already presorted in descending order
267
268 // Find last stable compatible version
269 auto ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
270 []( const PACKAGE_VERSION& ver )
271 {
272 return ver.compatible && ver.status == PVS_STABLE;
273 } );
274
275 // If not found then find any compatible version
276 if( ver_it == m_data.package.versions.end() )
277 {
278 ver_it = std::find_if( m_data.package.versions.begin(), m_data.package.versions.end(),
279 []( const PACKAGE_VERSION& ver )
280 {
281 return ver.compatible;
282 } );
283 }
284
285 if( ver_it == m_data.package.versions.end() )
286 return wxEmptyString; // Shouldn't happen
287
288 return ver_it->version;
289}
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:58
@ PPS_UPDATE_AVAILABLE
Definition: pcm.h:64
@ 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 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