KiCad PCB EDA Suite
ui_common.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) 2018 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 <wx/dcclient.h>
21 #include <wx/checkbox.h>
22 #include <wx/choice.h>
23 #include <wx/listbox.h>
24 #include <wx/dataview.h>
25 #include <wx/radiobut.h>
26 #include <wx/slider.h>
27 #include <wx/spinctrl.h>
28 #include <wx/srchctrl.h>
29 #include <wx/stc/stc.h>
30 #include <widgets/ui_common.h>
31 
32 #include <algorithm>
33 #include <dialog_shim.h>
34 #include <pgm_base.h>
35 #include <wx/settings.h>
36 #include <bitmaps/bitmap_types.h>
37 
39 {
40  // This is the value used in (most) wxFB dialogs
41  return 5;
42 }
43 
44 
45 SEVERITY SeverityFromString( const wxString& aSeverity )
46 {
47  if( aSeverity == wxT( "warning" ) )
48  return RPT_SEVERITY_WARNING;
49  else if( aSeverity == wxT( "ignore" ) )
50  return RPT_SEVERITY_IGNORE;
51  else
52  return RPT_SEVERITY_ERROR;
53 }
54 
55 
56 wxString SeverityToString( const SEVERITY& aSeverity )
57 {
58  if( aSeverity == RPT_SEVERITY_IGNORE )
59  return wxT( "ignore" );
60  else if( aSeverity == RPT_SEVERITY_WARNING )
61  return wxT( "warning" );
62  else
63  return wxT( "error" );
64 }
65 
66 
67 wxSize KIUI::GetTextSize( const wxString& aSingleLine, wxWindow* aWindow )
68 {
69  wxCoord width;
70  wxCoord height;
71 
72  {
73  wxClientDC dc( aWindow );
74  dc.SetFont( aWindow->GetFont() );
75  dc.GetTextExtent( aSingleLine, &width, &height );
76  }
77 
78  return wxSize( width, height );
79 }
80 
81 
83 {
84  static int guiFontSize = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ).GetPointSize();
85 
86  wxFont font( guiFontSize, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
87 
88 #ifdef __WXMAC__
89  // https://trac.wxwidgets.org/ticket/19210
90  if( font.GetFaceName().IsEmpty() )
91  font.SetFaceName( "Menlo" );
92 #endif
93 
94  return font;
95 }
96 
97 
98 wxFont getGUIFont( wxWindow* aWindow, int aRelativeSize )
99 {
100  wxFont font = aWindow->GetFont();
101 
102  font.SetPointSize( font.GetPointSize() + aRelativeSize );
103 
104  if( Pgm().GetCommonSettings()->m_Appearance.apply_icon_scale_to_fonts )
105  {
106  double icon_scale_fourths;
107 
108  if( Pgm().GetCommonSettings()->m_Appearance.icon_scale <= 0 )
109  icon_scale_fourths = KiIconScale( aWindow );
110  else
111  icon_scale_fourths = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
112 
113  font.SetPointSize( KiROUND( icon_scale_fourths * font.GetPointSize() / 4.0 ) );
114  }
115 
116 #ifdef __WXMAC__
117  // https://trac.wxwidgets.org/ticket/19210
118  if( font.GetFaceName().IsEmpty() )
119  font.SetFaceName( "San Francisco" );
120  // OSX 10.1 .. 10.9: Lucida Grande
121  // OSX 10.10: Helvetica Neue
122  // OSX 10.11 .. : San Francisco
123 #endif
124 
125  return font;
126 }
127 
128 
129 wxFont KIUI::GetStatusFont( wxWindow* aWindow )
130 {
131 #ifdef __WXMAC__
132  int scale = -2;
133 #else
134  int scale = 0;
135 #endif
136 
137  return getGUIFont( aWindow, scale );
138 }
139 
140 
141 wxFont KIUI::GetInfoFont( wxWindow* aWindow )
142 {
143  return getGUIFont( aWindow, -1 );
144 }
145 
146 
147 wxFont KIUI::GetControlFont( wxWindow* aWindow )
148 {
149  return getGUIFont( aWindow, 0 );
150 }
151 
152 
153 bool KIUI::EnsureTextCtrlWidth( wxTextCtrl* aCtrl, const wxString* aString )
154 {
155  wxWindow* window = aCtrl->GetParent();
156 
157  if( !window )
158  window = aCtrl;
159 
160  wxString ctrlText;
161 
162  if( !aString )
163  {
164  ctrlText = aCtrl->GetValue();
165  aString = &ctrlText;
166  }
167 
168  wxSize textz = GetTextSize( *aString, window );
169  wxSize ctrlz = aCtrl->GetSize();
170 
171  if( ctrlz.GetWidth() < textz.GetWidth() + 10 )
172  {
173  ctrlz.SetWidth( textz.GetWidth() + 10 );
174  aCtrl->SetSizeHints( ctrlz );
175  return true;
176  }
177 
178  return false;
179 }
180 
181 
182 void KIUI::SelectReferenceNumber( wxTextEntry* aTextEntry )
183 {
184  wxString ref = aTextEntry->GetValue();
185 
186  if( ref.find_first_of( '?' ) != ref.npos )
187  {
188  aTextEntry->SetSelection( ref.find_first_of( '?' ), ref.find_last_of( '?' ) + 1 );
189  }
190  else if( ref.find_first_of( '*' ) != ref.npos )
191  {
192  aTextEntry->SetSelection( ref.find_first_of( '*' ), ref.find_last_of( '*' ) + 1 );
193  }
194  else
195  {
196  wxString num = ref;
197 
198  while( !num.IsEmpty() && ( !isdigit( num.Last() ) || !isdigit( num.GetChar( 0 ) ) ) )
199  {
200  // Trim non-digit from end
201  if( !isdigit( num.Last() ) )
202  num.RemoveLast();
203 
204  // Trim non-digit from the start
205  if( !num.IsEmpty() && !isdigit( num.GetChar( 0 ) ) )
206  num = num.Right( num.Length() - 1 );
207  }
208 
209  aTextEntry->SetSelection( ref.Find( num ), ref.Find( num ) + num.Length() );
210 
211  if( num.IsEmpty() )
212  aTextEntry->SetSelection( -1, -1 );
213  }
214 }
215 
216 
217 bool KIUI::IsInputControlFocused( wxWindow* aFocus )
218 {
219  if( aFocus == nullptr )
220  aFocus = wxWindow::FindFocus();
221 
222  if( !aFocus )
223  return false;
224 
225  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( aFocus );
226  wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( aFocus );
227  wxListBox* listBox = dynamic_cast<wxListBox*>( aFocus );
228  wxSearchCtrl* searchCtrl = dynamic_cast<wxSearchCtrl*>( aFocus );
229  wxCheckBox* checkboxCtrl = dynamic_cast<wxCheckBox*>( aFocus );
230  wxChoice* choiceCtrl = dynamic_cast<wxChoice*>( aFocus );
231  wxRadioButton* radioBtn = dynamic_cast<wxRadioButton*>( aFocus );
232  wxSpinCtrl* spinCtrl = dynamic_cast<wxSpinCtrl*>( aFocus );
233  wxSpinCtrlDouble* spinDblCtrl = dynamic_cast<wxSpinCtrlDouble*>( aFocus );
234  wxSlider* sliderCtl = dynamic_cast<wxSlider*>( aFocus );
235 
236  // Data view control is annoying, the focus is on a "wxDataViewCtrlMainWindow" class that
237  // is not formerly exported via the header.
238  wxDataViewCtrl* dataViewCtrl = nullptr;
239 
240  wxWindow* parent = aFocus->GetParent();
241 
242  if( parent )
243  dataViewCtrl = dynamic_cast<wxDataViewCtrl*>( parent );
244 
245  return ( textEntry || styledText || listBox || searchCtrl || checkboxCtrl || choiceCtrl
246  || radioBtn || spinCtrl || spinDblCtrl || sliderCtl || dataViewCtrl );
247 }
248 
249 
250 bool KIUI::IsInputControlEditable( wxWindow* aFocus )
251 {
252  wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( aFocus );
253  wxStyledTextCtrl* styledText = dynamic_cast<wxStyledTextCtrl*>( aFocus );
254  wxSearchCtrl* searchCtrl = dynamic_cast<wxSearchCtrl*>( aFocus );
255 
256  if( textEntry )
257  return textEntry->IsEditable();
258  else if( styledText )
259  return styledText->IsEditable();
260  else if( searchCtrl )
261  return searchCtrl->IsEditable();
262 
263  return true; // Must return true if we can't determine the state, intentionally true for non inputs as well
264 }
265 
266 
268 {
269  return Pgm().m_ModalDialogCount > 0;
270 }
void SelectReferenceNumber(wxTextEntry *aTextEntry)
Select the number (or "?") in a reference for ease of editing.
Definition: ui_common.cpp:182
bool IsModalDialogFocused()
Definition: ui_common.cpp:267
bool IsInputControlEditable(wxWindow *aControl)
Check if a input control has focus.
Definition: ui_common.cpp:250
wxFont GetMonospacedUIFont()
Definition: ui_common.cpp:82
int KiIconScale(wxWindow *aWindow)
Return the automatic scale factor that would be used for a given window by KiScaledBitmap and KiScale...
Definition: bitmap.cpp:122
wxFont GetInfoFont(wxWindow *aWindow)
Definition: ui_common.cpp:141
int GetStdMargin()
Get the standard margin around a widget in the KiCad UI.
Definition: ui_common.cpp:38
wxFont GetControlFont(wxWindow *aWindow)
Definition: ui_common.cpp:147
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
bool EnsureTextCtrlWidth(wxTextCtrl *aCtrl, const wxString *aString=nullptr)
Set the minimum pixel width on a text control in order to make a text string be fully visible within ...
Definition: ui_common.cpp:153
bool IsInputControlFocused(wxWindow *aFocus=nullptr)
Check if a input control has focus.
Definition: ui_common.cpp:217
wxSize GetTextSize(const wxString &aSingleLine, wxWindow *aWindow)
Return the size of aSingleLine of text when it is rendered in aWindow using whatever font is currentl...
Definition: ui_common.cpp:67
Functions to provide common constants and other functions to assist in making a consistent UI.
SEVERITY
wxFont GetStatusFont(wxWindow *aWindow)
Definition: ui_common.cpp:129
const int scale
see class PGM_BASE
wxString SeverityToString(const SEVERITY &aSeverity)
Definition: ui_common.cpp:56
wxFont getGUIFont(wxWindow *aWindow, int aRelativeSize)
Definition: ui_common.cpp:98
SEVERITY SeverityFromString(const wxString &aSeverity)
Definition: ui_common.cpp:45
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:73