KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_re_bitmap_overlay_panel.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) 2024 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 2
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 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
22
23#include <bitmaps.h>
24
25#include <wx/bmpbndl.h>
26#include <wx/checkbox.h>
27#include <wx/dcbuffer.h>
28#include <wx/dcclient.h>
29#include <wx/stattext.h>
30
31
33 wxPanel(),
35 m_baseBitmapSize( 0, 0 )
36{
37 // Must set background style BEFORE creating the window
38 SetBackgroundStyle( wxBG_STYLE_PAINT );
39 Create( aParent, aId );
40
41 Bind( wxEVT_PAINT, &DRC_RE_BITMAP_OVERLAY_PANEL::OnPaint, this );
42 Bind( wxEVT_DPI_CHANGED, &DRC_RE_BITMAP_OVERLAY_PANEL::OnDPIChanged, this );
43 Bind( wxEVT_SYS_COLOUR_CHANGED, &DRC_RE_BITMAP_OVERLAY_PANEL::OnThemeChange, this );
44}
45
46
50
51
52void DRC_RE_BITMAP_OVERLAY_PANEL::OnPaint( wxPaintEvent& aEvent )
53{
54 wxAutoBufferedPaintDC dc( this );
55
56 dc.SetBackground( wxBrush( GetBackgroundColour() ) );
57 dc.Clear();
58
59 if( !m_bitmap.IsOk() )
60 return;
61
62 dc.DrawBitmap( m_bitmap, 0, 0, true );
63}
64
65
66void DRC_RE_BITMAP_OVERLAY_PANEL::OnDPIChanged( wxDPIChangedEvent& aEvent )
67{
68 LoadBitmap();
70 Refresh();
71 aEvent.Skip();
72}
73
74
75void DRC_RE_BITMAP_OVERLAY_PANEL::OnThemeChange( wxSysColourChangedEvent& aEvent )
76{
77 LoadBitmap();
78 Refresh();
79 aEvent.Skip();
80}
81
82
84{
85 // Platform handles focus ring automatically.
86 // Could add custom highlighting here if needed.
87 aEvent.Skip();
88}
89
90
91void DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldBlur( wxFocusEvent& aEvent )
92{
93 // Platform handles focus ring automatically.
94 aEvent.Skip();
95}
96
97
99{
100 if( !aControl )
101 return;
102
103 // Bind focus events to track active field
104 aControl->Bind( wxEVT_SET_FOCUS, &DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldFocus, this );
105 aControl->Bind( wxEVT_KILL_FOCUS, &DRC_RE_BITMAP_OVERLAY_PANEL::OnFieldBlur, this );
106}
107
108
110{
112 return;
113
114 wxBitmapBundle bundle = KiBitmapBundle( m_bitmapId );
115
116 m_bitmap = bundle.GetBitmapFor( this );
117 m_baseBitmapSize = bundle.GetDefaultSize();
118
119 Refresh();
120}
121
122
124{
125 m_bitmapId = aBitmap;
126 LoadBitmap();
127
128 if( m_bitmap.IsOk() )
129 SetMinSize( m_baseBitmapSize );
130}
131
132
134{
135 for( const auto& field : m_fields )
136 {
137 const DRC_RE_FIELD_POSITION& pos = field->GetPosition();
138 wxControl* ctrl = field->GetControl();
139
140 if( !ctrl )
141 continue;
142
143 wxPoint scaledPos( pos.xStart, pos.yTop );
144 int width = pos.xEnd - pos.xStart + DRC_RE_OVERLAY_WE;
145 wxSize scaledSize( width, ctrl->GetBestSize().GetHeight() );
146
147 ctrl->SetPosition( scaledPos );
148 ctrl->SetSize( scaledSize );
149
150 // Position label if present
151 if( field->HasLabel() )
152 PositionLabel( field.get() );
153 }
154}
155
156
158{
159 wxStaticText* label = aField->GetLabel();
160 wxControl* ctrl = aField->GetControl();
161
162 if( !label || !ctrl )
163 return;
164
165 const DRC_RE_FIELD_POSITION& pos = aField->GetPosition();
166 wxPoint ctrlPos = ctrl->GetPosition();
167 wxSize ctrlSize = ctrl->GetSize();
168 wxSize labelSize = label->GetBestSize();
169
170 wxPoint labelPos;
171 constexpr int GAP = 4;
172
173 switch( pos.labelPosition )
174 {
176 labelPos.x = ctrlPos.x - labelSize.GetWidth() - GAP;
177 labelPos.y = ctrlPos.y + ( ctrlSize.GetHeight() - labelSize.GetHeight() ) / 2;
178 break;
179
181 labelPos.x = ctrlPos.x + ctrlSize.GetWidth() + GAP;
182 labelPos.y = ctrlPos.y + ( ctrlSize.GetHeight() - labelSize.GetHeight() ) / 2;
183 break;
184
186 labelPos.x = ctrlPos.x + ( ctrlSize.GetWidth() - labelSize.GetWidth() ) / 2;
187 labelPos.y = ctrlPos.y - labelSize.GetHeight() - GAP;
188 break;
189
191 labelPos.x = ctrlPos.x + ( ctrlSize.GetWidth() - labelSize.GetWidth() ) / 2;
192 labelPos.y = ctrlPos.y + ctrlSize.GetHeight() + GAP;
193 break;
194
196 default:
197 return;
198 }
199
200 label->SetPosition( labelPos );
201}
202
203
205{
206 // Base implementation does nothing; derived classes override to populate fields
207 return true;
208}
209
210
212{
213 // Base implementation does nothing; derived classes override to read fields
214 return true;
215}
216
217
219{
220 for( const auto& field : m_fields )
221 field->ShowError( false );
222}
223
224
225void DRC_RE_BITMAP_OVERLAY_PANEL::ShowFieldError( const wxString& aFieldId )
226{
227 auto it = m_fieldIdMap.find( aFieldId );
228
229 if( it != m_fieldIdMap.end() )
230 it->second->ShowError( true );
231}
232
233
235 const DRC_RE_FIELD_POSITION& aPosition )
236{
237 wxCheckBox* checkbox = new wxCheckBox( this, wxID_ANY, wxEmptyString );
238
239 auto field = std::make_unique<DRC_RE_OVERLAY_FIELD>( this, aId, checkbox, aPosition );
240 DRC_RE_OVERLAY_FIELD* fieldPtr = field.get();
241
242 SetupFieldStyling( checkbox );
243
244 wxPoint pos( aPosition.xStart, aPosition.yTop );
245 checkbox->SetPosition( pos );
246
247 // Create label if specified
248 fieldPtr->CreateLabel();
249
250 if( fieldPtr->HasLabel() )
251 PositionLabel( fieldPtr );
252
253 m_fieldIdMap[aId] = fieldPtr;
254 m_fields.push_back( std::move( field ) );
255
256 return fieldPtr;
257}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
BITMAPS
A list of all bitmap identifiers.
@ INVALID_BITMAP
DRC_RE_OVERLAY_FIELD * AddCheckbox(const wxString &aId, const DRC_RE_FIELD_POSITION &aPosition)
Create and position a checkbox control on the bitmap overlay.
void LoadBitmap()
Load the appropriate bitmap variant for the current theme and DPI.
void OnThemeChange(wxSysColourChangedEvent &aEvent)
wxBitmap m_bitmap
Current background bitmap.
void OnDPIChanged(wxDPIChangedEvent &aEvent)
void PositionLabel(DRC_RE_OVERLAY_FIELD *aField)
Position a label relative to its field control based on the label position setting.
void ShowFieldError(const wxString &aFieldId)
Show an error indicator on the specified field.
void SetupFieldStyling(wxControl *aControl)
Apply transparent styling to a field control.
std::map< wxString, DRC_RE_OVERLAY_FIELD * > m_fieldIdMap
Field ID to field lookup.
void SetBackgroundBitmap(BITMAPS aBitmap)
Set the background bitmap for this panel.
wxSize m_baseBitmapSize
Bitmap size at 1x scale.
DRC_RE_BITMAP_OVERLAY_PANEL(wxWindow *aParent, wxWindowID aId=wxID_ANY)
void ClearFieldErrors()
Clear error indicators from all fields.
BITMAPS m_bitmapId
BITMAPS enum value.
void PositionFields()
Position all fields based on the current scale factor.
void OnFieldFocus(wxFocusEvent &aEvent)
std::vector< std::unique_ptr< DRC_RE_OVERLAY_FIELD > > m_fields
All overlay fields.
Wraps a wxControl positioned over a bitmap overlay panel.
wxStaticText * GetLabel() const
void CreateLabel()
Create and associate a label with this field.
const DRC_RE_FIELD_POSITION & GetPosition() const
wxControl * GetControl() const
constexpr int DRC_RE_OVERLAY_WE
@ BOTTOM
Label below the field.
@ RIGHT
Label to the right of the field.
@ TOP
Label above the field.
@ LEFT
Label to the left of the field.
Specifies the position and size of a field overlaid on a constraint bitmap.
LABEL_POSITION labelPosition
Position of label relative to field.
int xEnd
Right edge X coordinate where the field ends.
int xStart
Left edge X coordinate where the field starts.
int yTop
Top edge Y coordinate of the field.