KiCad PCB EDA Suite
Loading...
Searching...
No Matches
zoom_correction_ctrl.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
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * Inspired by the Inkscape preferences widget, which is
17 * Authors:
18 * Marco Scholten
19 * Bruno Dilly <[email protected]>
20 *
21 * Copyright (C) 2004, 2006, 2007 Authors
22 *
23 * Released under GNU GPL v2+
24 */
25
26#include <advanced_config.h>
28#include <widgets/ui_common.h>
29
30#include <wx/dcclient.h>
31#include <wx/sizer.h>
32#include <wx/spinctrl.h>
33
34class ZOOM_CORRECTION_RULER : public wxPanel
35{
36public:
37 ZOOM_CORRECTION_RULER( wxWindow* aParent ) :
38 wxPanel( aParent, wxID_ANY, wxDefaultPosition, wxSize( 200, 40 ) )
39 {
40 Bind( wxEVT_PAINT, &ZOOM_CORRECTION_RULER::OnPaint, this );
41 }
42
43private:
44 void OnPaint( wxPaintEvent& )
45 {
46 wxPaintDC dc( this );
47 wxSize size = GetClientSize();
48
49 // Draw baseline
50 dc.DrawLine( 0, size.y - 1, size.x, size.y - 1 );
51 ZOOM_CORRECTION_CTRL* parent = static_cast<ZOOM_CORRECTION_CTRL*>( GetParent() );
52
53 if( !parent )
54 return;
55
56 double value = parent->GetValue();
57 ZOOM_CORRECTION_UNITS units = static_cast<ZOOM_CORRECTION_UNITS>( parent->GetUnitsSelection() );
58
59 double dpi = ADVANCED_CFG::GetCfg().m_ScreenDPI;
60 double unitsPerInch = 25.4;
61
62 if( units == ZOOM_CORRECTION_UNITS::CM )
63 unitsPerInch = 2.54;
64 else if( units == ZOOM_CORRECTION_UNITS::INCH )
65 unitsPerInch = 1.0;
66
67 double pxPerUnit = dpi / unitsPerInch * value;
68
69 // Minimum spacing between number labels to prevent overlap (in pixels)
70 const int MIN_LABEL_SPACING = 30;
71 double lastLabelX = -MIN_LABEL_SPACING;
72
73 // Draw major and minor tick marks with numbering
74 if( units == ZOOM_CORRECTION_UNITS::INCH )
75 {
76 double pxPerMinorTick = pxPerUnit / 4.0; // 1/4 inch intervals
77
78 for( double x = 0; x <= size.x; x += pxPerMinorTick )
79 {
80 int tickCount = (int)round( x / pxPerMinorTick );
81
82 if( tickCount % 4 == 0 )
83 {
84 // Major tick (inch mark)
85 dc.DrawLine( x, size.y - 1, x, size.y - 16 );
86
87 int inchNum = tickCount / 4;
88
89 if( inchNum > 0 && x < size.x - 10 && ( x - lastLabelX ) >= MIN_LABEL_SPACING )
90 {
91 wxString label = wxString::Format( wxT("%d"), inchNum );
92 wxSize textSize = dc.GetTextExtent( label );
93 dc.DrawText( label, x - textSize.x / 2, size.y - 40 );
94 lastLabelX = x;
95 }
96 }
97 else
98 {
99 // Minor tick (1/4 inch mark)
100 dc.DrawLine( x, size.y - 1, x, size.y - 8 );
101 }
102 }
103 }
104 else if( units == ZOOM_CORRECTION_UNITS::CM )
105 {
106 double pxPerMinorTick = pxPerUnit / 10.0; // 1mm intervals
107
108 for( double x = 0; x <= size.x; x += pxPerMinorTick )
109 {
110 int tickCount = (int)round( x / pxPerMinorTick );
111
112 if( tickCount % 10 == 0 )
113 {
114 // Major tick (cm mark)
115 dc.DrawLine( x, size.y - 1, x, size.y - 16 );
116
117 int cmNum = tickCount / 10;
118
119 if( cmNum > 0 && x < size.x - 10 && ( x - lastLabelX ) >= MIN_LABEL_SPACING )
120 {
121 wxString label = wxString::Format( wxT("%d"), cmNum );
122 wxSize textSize = dc.GetTextExtent( label );
123 dc.DrawText( label, x - textSize.x / 2, size.y - 40 );
124 lastLabelX = x;
125 }
126 }
127 else
128 {
129 // Minor tick (mm mark)
130 dc.DrawLine( x, size.y - 1, x, size.y - 8 );
131 }
132 }
133 }
134 else // MM
135 {
136 // For mm: Same as cm ruler but numbers count by 10 (so 10mm, 20mm, etc.)
137 double pxPerMinorTick = pxPerUnit;
138
139 for( double x = 0; x <= size.x; x += pxPerMinorTick )
140 {
141 int tickCount = (int)round( x / pxPerMinorTick );
142
143 if( tickCount % 10 == 0 )
144 {
145 // Major tick (10mm mark)
146 dc.DrawLine( x, size.y - 1, x, size.y - 16 );
147
148 if( tickCount > 0 && x < size.x - 15 && ( x - lastLabelX ) >= MIN_LABEL_SPACING )
149 {
150 wxString label = wxString::Format( wxT("%d"), tickCount );
151 wxSize textSize = dc.GetTextExtent( label );
152 dc.DrawText( label, x - textSize.x / 2, size.y - 40 );
153 lastLabelX = x;
154 }
155 }
156 else
157 {
158 dc.DrawLine( x, size.y - 1, x, size.y - 8 );
159 }
160 }
161 }
162 }
163};
164
165ZOOM_CORRECTION_CTRL::ZOOM_CORRECTION_CTRL( wxWindow* aParent, double& aValue ) :
166 wxPanel( aParent, wxID_ANY ),
167 m_value( &aValue )
168{
169 wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
170
171 // Top section: Slider and spinner
172 wxBoxSizer* controlsSizer = new wxBoxSizer( wxHORIZONTAL );
173 m_slider = new wxSlider( this, wxID_ANY, (int)( aValue * 100 ), 10, 1000, wxDefaultPosition, wxDefaultSize,
174 wxSL_HORIZONTAL | wxSL_VALUE_LABEL );
175 controlsSizer->Add( m_slider, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, KIUI::GetStdMargin() );
176
177 m_spinner = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
178 wxSP_ARROW_KEYS, 10, 1000, (int)( aValue * 100 ) );
179 controlsSizer->Add( m_spinner, 0, wxALIGN_CENTER_VERTICAL );
180
181 topSizer->Add( controlsSizer, 0, wxEXPAND | wxALL, KIUI::GetStdMargin() );
182
183 // Middle section: Ruler and units choice
184 wxBoxSizer* rulerSizer = new wxBoxSizer( wxHORIZONTAL );
185
186 m_ruler = new ZOOM_CORRECTION_RULER( this );
187 rulerSizer->Add( m_ruler, 1, wxEXPAND | wxRIGHT, KIUI::GetStdMargin() );
188
189 wxArrayString choices;
190 choices.Add( wxT( "mm" ) );
191 choices.Add( wxT( "cm" ) );
192 choices.Add( wxT( "in" ) );
193 m_unitsChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices );
194 m_unitsChoice->SetSelection( 0 ); // Default to MM
195 rulerSizer->Add( m_unitsChoice, 0, wxALIGN_CENTER_VERTICAL );
196
197 topSizer->Add( rulerSizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, KIUI::GetStdMargin() );
198
199 SetSizer( topSizer );
200
201 m_slider->Bind( wxEVT_SLIDER, &ZOOM_CORRECTION_CTRL::sliderChanged, this );
202 m_spinner->Bind( wxEVT_SPINCTRL, &ZOOM_CORRECTION_CTRL::spinnerChanged, this );
203 m_unitsChoice->Bind( wxEVT_CHOICE, &ZOOM_CORRECTION_CTRL::unitsChanged, this );
204
205 // Ensure initial synchronization of all controls
206 m_ruler->Refresh();
207}
208
210{
211 m_slider->SetValue( (int)( aValue * 100 ) );
212 m_spinner->SetValue( (int)( aValue * 100 ) );
213 m_ruler->Refresh();
214}
215
217{
218 return m_slider->GetValue() / 100.0;
219}
220
222{
223 return m_unitsChoice->GetSelection();
224}
225
226
228{
229 m_slider->SetValue( (int)( *m_value * 100 ) );
230 m_spinner->SetValue( (int)( *m_value * 100 ) );
231 m_ruler->Refresh();
232 return true;
233}
234
236{
237 *m_value = GetValue();
238 return true;
239}
240
242{
243 *m_value = GetValue();
244 m_spinner->SetValue( m_slider->GetValue() );
245 m_ruler->Refresh();
246}
247
249{
250 *m_value = m_spinner->GetValue() / 100.0;
251 m_slider->SetValue( m_spinner->GetValue() );
252 m_ruler->Refresh();
253}
254
256{
257 m_ruler->Refresh();
258}
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Control to calibrate screen zoom to match real-world size.
void sliderChanged(wxCommandEvent &aEvent)
void spinnerChanged(wxSpinEvent &aEvent)
void unitsChanged(wxCommandEvent &aEvent)
ZOOM_CORRECTION_RULER * m_ruler
bool TransferDataToWindow() override
ZOOM_CORRECTION_CTRL(wxWindow *aParent, double &aValue)
void SetDisplayedValue(double aValue)
bool TransferDataFromWindow() override
ZOOM_CORRECTION_RULER(wxWindow *aParent)
void OnPaint(wxPaintEvent &)
int m_ScreenDPI
Screen DPI setting for display calculations.
KICOMMON_API int GetStdMargin()
Get the standard margin around a widget in the KiCad UI.
Definition ui_common.cpp:49
Functions to provide common constants and other functions to assist in making a consistent UI.
ZOOM_CORRECTION_UNITS