KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_line_properties.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) 2017 Seth Hillbrand <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <bitmaps.h>
22#include <sch_line.h>
27#include <sch_edit_frame.h>
28#include <stroke_params.h>
31#include <sch_commit.h>
32#include <line_ending.h>
33
34
36{
37 wxSizer* mainSizer = GetSizer();
38 wxCHECK_RET( mainSizer, wxT( "Line properties dialog has no main sizer" ) );
39
40 wxGridBagSizer* gbSizerEndings = new wxGridBagSizer( 3, 0 );
41 gbSizerEndings->SetFlexibleDirection( wxBOTH );
42 gbSizerEndings->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
43 gbSizerEndings->SetEmptyCellSize( wxSize( 20, -1 ) );
44
45 m_startShapeLabel = new wxStaticText( this, wxID_ANY, _( "Start Shape:" ) );
46 gbSizerEndings->Add( m_startShapeLabel, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ),
47 wxALIGN_CENTER_VERTICAL | wxRIGHT, 5 );
48
49 m_startShapeChoice = new wxBitmapComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0,
50 nullptr, wxCB_READONLY );
51 gbSizerEndings->Add( m_startShapeChoice, wxGBPosition( 0, 1 ), wxGBSpan( 1, 2 ),
52 wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 );
53
54 m_endShapeLabel = new wxStaticText( this, wxID_ANY, _( "End Shape:" ) );
55 gbSizerEndings->Add( m_endShapeLabel, wxGBPosition( 0, 4 ), wxGBSpan( 1, 1 ),
56 wxALIGN_CENTER_VERTICAL | wxRIGHT, 5 );
57
58 m_endShapeChoice = new wxBitmapComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0,
59 nullptr, wxCB_READONLY );
60 gbSizerEndings->Add( m_endShapeChoice, wxGBPosition( 0, 5 ), wxGBSpan( 1, 2 ),
61 wxALIGN_CENTER_VERTICAL | wxEXPAND, 5 );
62
63 auto addEndingValue =
64 [&]( int aRow, int aCol, const wxString& aLabel, wxStaticText*& aLabelCtrl, wxTextCtrl*& aValueCtrl,
65 wxStaticText*& aUnitsCtrl, int aFlags )
66 {
67 aLabelCtrl = new wxStaticText( this, wxID_ANY, aLabel );
68 gbSizerEndings->Add( aLabelCtrl, wxGBPosition( aRow, aCol ), wxGBSpan( 1, 1 ),
69 wxALIGN_CENTER_VERTICAL | wxLEFT | aFlags, 15 );
70
71 aValueCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1, -1 ), 0 );
72 gbSizerEndings->Add( aValueCtrl, wxGBPosition( aRow, aCol + 1 ), wxGBSpan( 1, 1 ),
73 wxALIGN_CENTER_VERTICAL | wxLEFT | wxEXPAND, 15 );
74
75 aUnitsCtrl = new wxStaticText( this, wxID_ANY, _( "unit" ) );
76 gbSizerEndings->Add( aUnitsCtrl, wxGBPosition( aRow, aCol + 2 ), wxGBSpan( 1, 1 ),
77 wxALIGN_CENTER_VERTICAL | wxLEFT, 3 );
78 };
79
80 addEndingValue( 1, 0, _( "Length:" ), m_startLengthLabel, m_startLengthCtrl, m_startLengthUnits, wxRIGHT );
81 addEndingValue( 1, 4, _( "Length:" ), m_endLengthLabel, m_endLengthCtrl, m_endLengthUnits, wxLEFT | wxRIGHT );
82 addEndingValue( 2, 0, _( "Width:" ), m_startWidthLabel, m_startWidthCtrl, m_startWidthUnits, wxRIGHT );
83 addEndingValue( 2, 4, _( "Width:" ), m_endWidthLabel, m_endWidthCtrl, m_endWidthUnits, wxLEFT | wxRIGHT );
84 addEndingValue( 3, 0, _( "Thickness:" ), m_startThicknessLabel, m_startThicknessCtrl, m_startThicknessUnits,
85 wxRIGHT );
86 addEndingValue( 3, 4, _( "Thickness:" ), m_endThicknessLabel, m_endThicknessCtrl, m_endThicknessUnits,
87 wxLEFT | wxRIGHT );
88
89 gbSizerEndings->AddGrowableCol( 1 );
90 gbSizerEndings->AddGrowableCol( 5 );
91
92 m_endingsSizer->Add( gbSizerEndings, 0, wxEXPAND, 0 );
93
94 m_endingsHelpLabel = new wxStaticText( this, wxID_ANY, wxEmptyString );
95 m_endingsSizer->Add( m_endingsHelpLabel, 0, wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, 10 );
96
97 wxColour fg = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
98 wxSize iconSize = GetTextExtent( wxT( "XXXXXX" ) );
99
100 struct
101 {
102 wxString name;
103 LINE_ENDING_STYLE style;
104 } shapeItems[] = {
105 { _( "None" ), LINE_ENDING_STYLE::NONE },
106 { _( "Arrow" ), LINE_ENDING_STYLE::ARROW },
107 { _( "Open Arrow" ), LINE_ENDING_STYLE::ARROW_OPEN },
108 { _( "Circle" ), LINE_ENDING_STYLE::CIRCLE },
109 { _( "Square" ), LINE_ENDING_STYLE::SQUARE },
110 };
111
112 for( const auto& item : shapeItems )
113 {
114 wxBitmap startBmp = MakeLineEndingBitmap( item.style, iconSize, fg, this, false );
115 wxBitmap endBmp = MakeLineEndingBitmap( item.style, iconSize, fg, this, true );
116 m_startShapeChoice->Append( item.name, startBmp );
117 m_endShapeChoice->Append( item.name, endBmp );
118 }
119
120 m_startShapeChoice->SetSelection( 0 );
121 m_endShapeChoice->SetSelection( 0 );
122
123 m_startLength = std::make_unique<UNIT_BINDER>( aParent, m_startLengthLabel, m_startLengthCtrl, m_startLengthUnits,
124 true );
125 m_startWidth = std::make_unique<UNIT_BINDER>( aParent, m_startWidthLabel, m_startWidthCtrl, m_startWidthUnits,
126 true );
127 m_startThickness = std::make_unique<UNIT_BINDER>( aParent, m_startThicknessLabel, m_startThicknessCtrl,
128 m_startThicknessUnits, true );
129 m_endLength = std::make_unique<UNIT_BINDER>( aParent, m_endLengthLabel, m_endLengthCtrl, m_endLengthUnits, true );
130 m_endWidth = std::make_unique<UNIT_BINDER>( aParent, m_endWidthLabel, m_endWidthCtrl, m_endWidthUnits, true );
131 m_endThickness = std::make_unique<UNIT_BINDER>( aParent, m_endThicknessLabel, m_endThicknessCtrl,
132 m_endThicknessUnits, true );
133}
134
135
136DIALOG_LINE_PROPERTIES::DIALOG_LINE_PROPERTIES( SCH_EDIT_FRAME* aParent, std::deque<SCH_LINE*>& aLines ) :
138 m_frame( aParent ),
139 m_lines( aLines ),
141{
142 createLineEndingControls( aParent );
143
144 m_colorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
145
146 KIGFX::COLOR4D canvas = m_frame->GetColorSettings()->GetColor( LAYER_SCHEMATIC_BACKGROUND );
147 m_colorSwatch->SetSwatchBackground( canvas.ToColour() );
148
149 m_helpLabel1->SetFont( KIUI::GetInfoFont( this ).Italic() );
150 m_helpLabel2->SetFont( KIUI::GetInfoFont( this ).Italic() );
151
152 m_endingsHelpLabel->SetFont( KIUI::GetInfoFont( this ).Italic() );
153 m_endingsHelpLabel->SetLabel( wxString::Format( _( "Set line ending sizes to 0 for automatic (%g\u00d7 line width)." ),
155
157
158 for( const auto& [ lineStyle, lineStyleDesc ] : lineTypeNames )
159 m_typeCombo->Append( lineStyleDesc.name, KiBitmapBundle( lineStyleDesc.bitmap ) );
160
162
163 // Now all widgets have the size fixed, call FinishDialogSettings
165}
166
167
169{
170 SCH_LINE* first_stroke_item = m_lines.front();
171
172 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
173 [&]( const SCH_LINE* r )
174 {
175 return r->GetStroke().GetWidth() == first_stroke_item->GetStroke().GetWidth();
176 } ) )
177 {
178 m_width.SetValue( first_stroke_item->GetStroke().GetWidth() );
179 }
180 else
181 {
182 m_width.SetValue( INDETERMINATE_ACTION );
183 }
184
185 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
186 [&]( const SCH_LINE* r )
187 {
188 return r->GetStroke().GetColor() == first_stroke_item->GetStroke().GetColor();
189 } ) )
190 {
191 m_colorSwatch->SetSwatchColor( first_stroke_item->GetStroke().GetColor(), false );
192 }
193 else
194 {
195 m_colorSwatch->SetIndeterminate();
196 }
197
198 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
199 [&]( const SCH_LINE* r )
200 {
201 return r->GetStroke().GetLineStyle() == first_stroke_item->GetStroke().GetLineStyle();
202 } ) )
203 {
204 int style = static_cast<int>( first_stroke_item->GetStroke().GetLineStyle() );
205
206 if( style >= 0 && style < (int) lineTypeNames.size() )
207 m_typeCombo->SetSelection( style );
208 else
209 m_typeCombo->SetSelection( 0 );
210 }
211 else
212 {
214 m_typeCombo->SetStringSelection( INDETERMINATE_STYLE );
215 }
216
217 // Line endings - Start Shape
218 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
219 [&]( const SCH_LINE* r )
220 {
221 return r->GetStartEndingStyle() == first_stroke_item->GetStartEndingStyle();
222 } ) )
223 {
224 m_startShapeChoice->SetSelection( LINE_ENDING::StyleToChoiceIndex( first_stroke_item->GetStartEndingStyle() ) );
225 }
226 else
227 {
229 m_startShapeChoice->SetStringSelection( INDETERMINATE_STYLE );
230 }
231
232 // End Shape
233 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
234 [&]( const SCH_LINE* r )
235 {
236 return r->GetEndEndingStyle() == first_stroke_item->GetEndEndingStyle();
237 } ) )
238 {
239 m_endShapeChoice->SetSelection( LINE_ENDING::StyleToChoiceIndex( first_stroke_item->GetEndEndingStyle() ) );
240 }
241 else
242 {
244 m_endShapeChoice->SetStringSelection( INDETERMINATE_STYLE );
245 }
246
247 // Start Length
248 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
249 [&]( const SCH_LINE* r )
250 {
251 return r->GetStartEndingLength() == first_stroke_item->GetStartEndingLength();
252 } ) )
253 {
254 m_startLength->SetValue( first_stroke_item->GetStartEndingLength() );
255 }
256 else
257 {
259 }
260
261 // Start Width
262 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
263 [&]( const SCH_LINE* r )
264 {
265 return r->GetStartEndingWidth() == first_stroke_item->GetStartEndingWidth();
266 } ) )
267 {
268 m_startWidth->SetValue( first_stroke_item->GetStartEndingWidth() );
269 }
270 else
271 {
273 }
274
275 // Start Stroke Width
276 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
277 [&]( const SCH_LINE* r )
278 {
279 return r->GetStartEndingStrokeWidth() == first_stroke_item->GetStartEndingStrokeWidth();
280 } ) )
281 {
282 m_startThickness->SetValue( first_stroke_item->GetStartEndingStrokeWidth() );
283 }
284 else
285 {
287 }
288
289 // End Length
290 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
291 [&]( const SCH_LINE* r )
292 {
293 return r->GetEndEndingLength() == first_stroke_item->GetEndEndingLength();
294 } ) )
295 {
296 m_endLength->SetValue( first_stroke_item->GetEndEndingLength() );
297 }
298 else
299 {
301 }
302
303 // End Width
304 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
305 [&]( const SCH_LINE* r )
306 {
307 return r->GetEndEndingWidth() == first_stroke_item->GetEndEndingWidth();
308 } ) )
309 {
310 m_endWidth->SetValue( first_stroke_item->GetEndEndingWidth() );
311 }
312 else
313 {
314 m_endWidth->SetValue( INDETERMINATE_ACTION );
315 }
316
317 // End Stroke Width
318 if( std::all_of( m_lines.begin() + 1, m_lines.end(),
319 [&]( const SCH_LINE* r )
320 {
321 return r->GetEndEndingStrokeWidth() == first_stroke_item->GetEndEndingStrokeWidth();
322 } ) )
323 {
324 m_endThickness->SetValue( first_stroke_item->GetEndEndingStrokeWidth() );
325 }
326 else
327 {
329 }
330
331 return true;
332}
333
334
335void DIALOG_LINE_PROPERTIES::resetDefaults( wxCommandEvent& event )
336{
337 m_width.SetValue( 0 );
338 m_colorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false );
339
340 m_typeCombo->SetStringSelection( DEFAULT_LINE_STYLE_LABEL );
341
342 m_startShapeChoice->SetSelection( 0 );
343 m_endShapeChoice->SetSelection( 0 );
344 m_startLength->SetValue( 0 );
345 m_startWidth->SetValue( 0 );
346 m_startThickness->SetValue( 0 );
347 m_endLength->SetValue( 0 );
348 m_endWidth->SetValue( 0 );
349 m_endThickness->SetValue( 0 );
350
351 Refresh();
352}
353
354
356{
357 SCH_COMMIT commit( m_frame );
358
359 for( SCH_LINE* line : m_lines )
360 {
361 // Commit the change only if the line is not new. If new this is useless
362 // and can create dangling pointers if the line creation is aborted
363 if( !line->HasFlag( IS_NEW ) )
364 commit.Modify( line, m_frame->GetScreen() );
365
366 if( !m_width.IsIndeterminate() )
367 line->SetLineWidth( std::max( 0, m_width.GetIntValue() ) );
368
369 if( m_typeCombo->GetStringSelection() != INDETERMINATE_STYLE )
370 {
371 auto it = lineTypeNames.begin();
372 std::advance( it, m_typeCombo->GetSelection() );
373
374 if( it == lineTypeNames.end() )
375 line->SetLineStyle( LINE_STYLE::DEFAULT );
376 else
377 line->SetLineStyle( it->first );
378 }
379
380 if( !m_colorSwatch->IsIndeterminate() )
381 line->SetLineColor( m_colorSwatch->GetSwatchColor() );
382
383 // Line endings
384 if( m_startShapeChoice->GetStringSelection() != INDETERMINATE_STYLE )
385 {
386 int startSel = m_startShapeChoice->GetSelection();
387
388 if( startSel >= 0 && startSel < LINE_ENDING::s_defaultChoiceCount )
389 line->SetStartEndingStyle( LINE_ENDING::s_defaultChoiceOrder[startSel] );
390 }
391
392 if( m_endShapeChoice->GetStringSelection() != INDETERMINATE_STYLE )
393 {
394 int endSel = m_endShapeChoice->GetSelection();
395
396 if( endSel >= 0 && endSel < LINE_ENDING::s_defaultChoiceCount )
397 line->SetEndEndingStyle( LINE_ENDING::s_defaultChoiceOrder[endSel] );
398 }
399
400 if( !m_startLength->IsIndeterminate() )
401 line->SetStartEndingLength( std::max( 0, m_startLength->GetIntValue() ) );
402
403 if( !m_startWidth->IsIndeterminate() )
404 line->SetStartEndingWidth( std::max( 0, m_startWidth->GetIntValue() ) );
405
406 if( !m_startThickness->IsIndeterminate() )
407 line->SetStartEndingStrokeWidth( std::max( 0, m_startThickness->GetIntValue() ) );
408
409 if( !m_endLength->IsIndeterminate() )
410 line->SetEndEndingLength( std::max( 0, m_endLength->GetIntValue() ) );
411
412 if( !m_endWidth->IsIndeterminate() )
413 line->SetEndEndingWidth( std::max( 0, m_endWidth->GetIntValue() ) );
414
415 if( !m_endThickness->IsIndeterminate() )
416 line->SetEndEndingStrokeWidth( std::max( 0, m_endThickness->GetIntValue() ) );
417 }
418
419 commit.Push( m_lines.size() == 1 ? _( "Edit Line" ) : _( "Edit Lines" ) );
420 return true;
421}
const char * name
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:102
DIALOG_LINE_PROPERTIES_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Line Properties"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
std::unique_ptr< UNIT_BINDER > m_endLength
std::unique_ptr< UNIT_BINDER > m_endThickness
std::deque< SCH_LINE * > m_lines
DIALOG_LINE_PROPERTIES(SCH_EDIT_FRAME *aParent, std::deque< SCH_LINE * > &aLines)
void resetDefaults(wxCommandEvent &event) override
std::unique_ptr< UNIT_BINDER > m_endWidth
void createLineEndingControls(SCH_EDIT_FRAME *aParent)
std::unique_ptr< UNIT_BINDER > m_startLength
wxBitmapComboBox * m_endShapeChoice
std::unique_ptr< UNIT_BINDER > m_startWidth
std::unique_ptr< UNIT_BINDER > m_startThickness
wxBitmapComboBox * m_startShapeChoice
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:94
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
wxColour ToColour() const
Definition color4d.cpp:221
static constexpr double DEFAULT_RATIO_LENGTH
static const int s_defaultChoiceCount
static const LINE_ENDING_STYLE s_defaultChoiceOrder[]
Dropdown display order for line ending style choosers.
Definition line_ending.h:40
static int StyleToChoiceIndex(LINE_ENDING_STYLE aStyle)
Return the dropdown index for the given style, or 0 (NONE) if not found.
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
Schematic editor (Eeschema) main window.
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
int GetStartEndingStrokeWidth() const
Definition sch_line.h:223
int GetEndEndingLength() const
Definition sch_line.h:218
virtual STROKE_PARAMS GetStroke() const override
Definition sch_line.h:198
int GetEndEndingWidth() const
Definition sch_line.h:220
int GetStartEndingWidth() const
Definition sch_line.h:215
LINE_ENDING_STYLE GetEndEndingStyle() const
Definition sch_line.h:210
int GetEndEndingStrokeWidth() const
Definition sch_line.h:225
LINE_ENDING_STYLE GetStartEndingStyle() const
Definition sch_line.h:207
int GetStartEndingLength() const
Definition sch_line.h:213
int GetWidth() const
KIGFX::COLOR4D GetColor() const
#define _(s)
#define IS_NEW
New item, just created.
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:516
LINE_ENDING_STYLE
Line ending styles for graphic lines, arcs, and beziers.
Definition line_ending.h:44
wxBitmap MakeLineEndingBitmap(LINE_ENDING_STYLE aStyle, const wxSize &aSize, const wxColour &aForeground, wxWindow *aWindow, bool aShapeOnRight)
Generate a DPI-aware bitmap icon showing a line ending style.
KICOMMON_API wxFont GetInfoFont(wxWindow *aWindow)
const std::map< LINE_STYLE, struct LINE_STYLE_DESC > lineTypeNames
Conversion map between LINE_STYLE values and style names displayed.
#define INDETERMINATE_STYLE
#define DEFAULT_LINE_STYLE_LABEL
#define INDETERMINATE_ACTION
Definition ui_common.h:48