dialog_page_settings.cpp 23.8 KB
Newer Older
1 2 3
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
4
 * Copyright (C) 1992-2013 Kicad Developers, see AUTHORS.txt for contributors.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22
 */
23

24 25
/**
 * @file dialog_page_settings.cpp
26 27
 */

28
#include <fctsys.h>
29
#include <macros.h>              // DIM()
30
#include <common.h>
31
#include <confirm.h>
32
#include <gr_basic.h>
33 34 35 36
#include <base_struct.h>
#include <class_drawpanel.h>
#include <class_title_block.h>
#include <wxstruct.h>
37
#include <worksheet_shape_builder.h>
38
#include <class_base_screen.h>
39
#include <wildcards_and_files_ext.h>
40 41

#include <wx/valgen.h>
42
#include <wx/tokenzr.h>
43 44

#ifdef EESCHEMA
45 46
#include <class_sch_screen.h>
#include <general.h>
47 48
#endif

49
#include <worksheet.h>
50
#include <dialog_page_settings.h>
51

52

53 54 55 56 57
// List of page formats.
// should be statically initialized, because we need both
// the translated and the not translated version.
// when displayed in dialog we should explicitely call wxGetTranslation()
// to show the translated version.
58
static const wxString pageFmts[] =
59 60 61 62 63 64 65 66 67 68 69
{
    _("A4 210x297mm"),
    _("A3 297x420mm"),
    _("A2 420x594mm"),
    _("A1 594x841mm"),
    _("A0 841x1189mm"),
    _("A 8.5x11in"),
    _("B 11x17in"),
    _("C 17x22in"),
    _("D 22x34in"),
    _("E 34x44in"),
70 71 72
    _("USLetter 8.5x11in"),     // USLetter without space is correct
    _("USLegal 8.5x14in"),      // USLegal without space is correct
    _("USLedger 11x17in"),      // USLedger without space is correct
73 74
    _("User (Custom)"),
};
75

76
void EDA_DRAW_FRAME::Process_PageSettings( wxCommandEvent& event )
77
{
78 79 80
    DIALOG_PAGES_SETTINGS dlg( this );
    dlg.SetWksFileName( BASE_SCREEN::m_PageLayoutDescrFileName );
    int diag = dlg.ShowModal();
81

82 83
    if( m_canvas && diag )
        m_canvas->Refresh();
84 85 86
}


87
DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* parent ) :
88
    DIALOG_PAGES_SETTINGS_BASE( parent ),
89
    m_initialized( false )
90
{
91 92
    m_parent   = parent;
    m_screen   = m_parent->GetScreen();
93
    m_page_bitmap = NULL;
94
    m_tb = m_parent->GetTitleBlock();
95
    m_customFmt = false;
96
    m_localPrjConfigChanged = false;
97

98
    initDialog();
99

100
    GetSizer()->SetSizeHints( this );
101 102 103
    Centre();
}

104

105 106
DIALOG_PAGES_SETTINGS::~DIALOG_PAGES_SETTINGS()
{
107 108
    if( m_page_bitmap )
        delete m_page_bitmap;
109 110
}

111

112 113
void DIALOG_PAGES_SETTINGS::initDialog()
{
114
    wxString    msg;
115 116
    double      customSizeX;
    double      customSizeY;
117

118
    // initalize page format choice box and page format list.
119
    // The first shows translated strings, the second contains not translated strings
120
    m_paperSizeComboBox->Clear();
121

122
    for( unsigned ii = 0; ii < DIM(pageFmts); ii++ )
123 124 125 126 127
    {
        m_pageFmt.Add( pageFmts[ii] );
        m_paperSizeComboBox->Append( wxGetTranslation( pageFmts[ii] ) );
    }

128
    // initialize the page layout descr filename
129
    SetWksFileName( BASE_SCREEN::m_PageLayoutDescrFileName );
130

131

132
#ifdef EESCHEMA
133
    // Init display value for schematic sub-sheet number
134
    wxString format = m_TextSheetCount->GetLabel();
135
    msg.Printf( format, m_screen->m_NumberOfScreens );
136
    m_TextSheetCount->SetLabel( msg );
137

138
    format = m_TextSheetNumber->GetLabel();
139
    msg.Printf( format, m_screen->m_ScreenNumber );
140
    m_TextSheetNumber->SetLabel( msg );
141
#else
142 143
    m_TextSheetCount->Show( false );
    m_TextSheetNumber->Show( false );
144
#endif
145

146
    m_pageInfo = m_parent->GetPageSettings();
147 148
    SetCurrentPageSizeSelection( m_pageInfo.GetType() );
    m_orientationComboBox->SetSelection( m_pageInfo.IsPortrait() );
149

150 151
    // only a click fires the "selection changed" event, so have to fabricate this check
    wxCommandEvent dummy;
152
    OnPaperSizeChoice( dummy );
153

154 155 156 157 158 159 160 161 162 163 164
    if( m_customFmt)    // The custom value is defined by the page size
    {
        customSizeX = m_pageInfo.GetWidthMils();
        customSizeY = m_pageInfo.GetHeightMils();
    }
    else    // The custom value is set to a default value, or the last defined value
    {
        customSizeX = m_pageInfo.GetCustomWidthMils();
        customSizeY = m_pageInfo.GetCustomHeightMils();
    }

165
    switch( g_UserUnit )
166
    {
167
    case MILLIMETRES:
168 169
        customSizeX *= 25.4e-3;
        customSizeY *= 25.4e-3;
170

171
        msg.Printf( wxT( "%.2f" ), customSizeX );
172
        m_TextUserSizeX->SetValue( msg );
173

174
        msg.Printf( wxT( "%.2f" ), customSizeY );
175 176 177
        m_TextUserSizeY->SetValue( msg );
        break;

178
    default:
179
    case INCHES:
180 181
        customSizeX /= 1000.0;
        customSizeY /= 1000.0;
182

183
        msg.Printf( wxT( "%.3f" ), customSizeX );
184
        m_TextUserSizeX->SetValue( msg );
185

186
        msg.Printf( wxT( "%.3f" ), customSizeY );
187 188
        m_TextUserSizeY->SetValue( msg );
        break;
189
    }
190

191
    m_TextRevision->SetValue( m_tb.GetRevision() );
192
    m_TextDate->SetValue( m_tb.GetDate() );
193 194 195 196 197 198
    m_TextTitle->SetValue( m_tb.GetTitle() );
    m_TextCompany->SetValue( m_tb.GetCompany() );
    m_TextComment1->SetValue( m_tb.GetComment1() );
    m_TextComment2->SetValue( m_tb.GetComment2() );
    m_TextComment3->SetValue( m_tb.GetComment3() );
    m_TextComment4->SetValue( m_tb.GetComment4() );
199 200

#ifndef EESCHEMA
201
    m_RevisionExport->Show( false );
202
    m_DateExport->Show( false );
203 204 205 206 207 208
    m_TitleExport->Show( false );
    m_CompanyExport->Show( false );
    m_Comment1Export->Show( false );
    m_Comment2Export->Show( false );
    m_Comment3Export->Show( false );
    m_Comment4Export->Show( false );
209
#endif
210

211 212 213
    GetPageLayoutInfoFromDialog();
    UpdatePageLayoutExample();

214 215
    // Make the OK button the default.
    m_sdbSizer1OK->SetDefault();
216
    m_initialized = true;
217 218 219 220 221
}


void DIALOG_PAGES_SETTINGS::OnOkClick( wxCommandEvent& event )
{
222
    if( SavePageSettings() )
223
    {
224 225 226 227 228 229 230
        m_screen->SetModify();
        m_parent->GetCanvas()->Refresh();

        if( m_localPrjConfigChanged )
            m_parent->SaveProjectSettings( true );

        EndModal( true );
231
    }
232 233 234 235 236
}


void DIALOG_PAGES_SETTINGS::OnCancelClick( wxCommandEvent& event )
{
237
    EndModal( false );
238 239 240
}


241
void DIALOG_PAGES_SETTINGS::OnPaperSizeChoice( wxCommandEvent& event )
242
{
243
    int idx = m_paperSizeComboBox->GetSelection();
244

245 246
    if( idx < 0 )
        idx = 0;
247

248
    const wxString paperType = m_pageFmt[idx];
249

250
    if( paperType.Contains( PAGE_INFO::Custom ) )
251
    {
252
        m_orientationComboBox->Enable( false );
253 254
        m_TextUserSizeX->Enable( true );
        m_TextUserSizeY->Enable( true );
255
        m_customFmt = true;
256 257 258
    }
    else
    {
259
        m_orientationComboBox->Enable( true );
260

261 262 263 264
#if 0
        // ForcePortrait() does not exist, but could be useful.
        // so I leave these lines, which could be seen as a todo feature
        if( paperType.ForcePortrait() )
265 266 267
        {
            m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
            m_orientationComboBox->Enable( false );
268
        }
269
#endif
270 271
        m_TextUserSizeX->Enable( false );
        m_TextUserSizeY->Enable( false );
272
        m_customFmt = false;
273
    }
274

275 276
    GetPageLayoutInfoFromDialog();
    UpdatePageLayoutExample();
277 278 279
}


280
void DIALOG_PAGES_SETTINGS::OnUserPageSizeXTextUpdated( wxCommandEvent& event )
281
{
282 283 284 285 286 287
    if( m_initialized && m_TextUserSizeX->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        UpdatePageLayoutExample();
    }
}
288 289


290 291 292 293 294 295 296 297
void DIALOG_PAGES_SETTINGS::OnUserPageSizeYTextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextUserSizeY->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        UpdatePageLayoutExample();
    }
}
298

299

300 301 302 303 304 305 306 307
void DIALOG_PAGES_SETTINGS::OnPageOrientationChoice( wxCommandEvent& event )
{
    if( m_initialized )
    {
        GetPageLayoutInfoFromDialog();
        UpdatePageLayoutExample();
    }
}
308

309 310 311 312

void DIALOG_PAGES_SETTINGS::OnRevisionTextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextRevision->IsModified() )
313
    {
314 315 316 317 318
        GetPageLayoutInfoFromDialog();
        m_tb.SetRevision( m_TextRevision->GetValue() );
        UpdatePageLayoutExample();
    }
}
319 320


321 322 323 324 325 326 327 328 329 330 331
void DIALOG_PAGES_SETTINGS::OnDateTextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextDate->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetDate( m_TextDate->GetValue() );
        UpdatePageLayoutExample();
    }
}


332 333 334 335 336 337 338
void DIALOG_PAGES_SETTINGS::OnTitleTextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextTitle->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetTitle( m_TextTitle->GetValue() );
        UpdatePageLayoutExample();
339
    }
340
}
341

342

343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
void DIALOG_PAGES_SETTINGS::OnCompanyTextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextCompany->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetCompany( m_TextCompany->GetValue() );
        UpdatePageLayoutExample();
    }
}


void DIALOG_PAGES_SETTINGS::OnComment1TextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextComment1->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetComment1( m_TextComment1->GetValue() );
        UpdatePageLayoutExample();
    }
}


void DIALOG_PAGES_SETTINGS::OnComment2TextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextComment2->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetComment2( m_TextComment2->GetValue() );
        UpdatePageLayoutExample();
    }
}


void DIALOG_PAGES_SETTINGS::OnComment3TextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextComment3->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetComment3( m_TextComment3->GetValue() );
        UpdatePageLayoutExample();
    }
}


void DIALOG_PAGES_SETTINGS::OnComment4TextUpdated( wxCommandEvent& event )
{
    if( m_initialized && m_TextComment4->IsModified() )
    {
        GetPageLayoutInfoFromDialog();
        m_tb.SetComment4( m_TextComment4->GetValue() );
        UpdatePageLayoutExample();
    }
}

397 398 399 400
void DIALOG_PAGES_SETTINGS::OnDateApplyClick( wxCommandEvent& event )
{
    m_TextDate->SetValue( FormatDateLong( m_PickDate->GetValue() ) );
}
401

402 403

bool DIALOG_PAGES_SETTINGS::SavePageSettings()
404
{
405
    bool retSuccess = false;
406

407
    wxString fileName = GetWksFileName();
408

409
    if( fileName != BASE_SCREEN::m_PageLayoutDescrFileName )
410
    {
411
        if( !fileName.IsEmpty() )
412
        {
413
            wxString fullFileName = WORKSHEET_LAYOUT::MakeFullFileName( fileName );
414 415 416 417 418 419 420 421 422 423
            if( !wxFileExists( fullFileName ) )
            {
                wxString msg;
                msg.Printf( _("Page layout description file <%s> not found. Abort"),
                            GetChars( fullFileName ) );
                wxMessageBox( msg );
                return false;
            }
        }

424
        BASE_SCREEN::m_PageLayoutDescrFileName = fileName;
425
        WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance();
426
        pglayout.SetPageLayout( fileName );
427 428
        m_localPrjConfigChanged = true;
    }
429

430
    int idx = m_paperSizeComboBox->GetSelection();
431

432 433
    if( idx < 0 )
        idx = 0;
434

435
    const wxString paperType = m_pageFmt[idx];
436

437 438
    if( paperType.Contains( PAGE_INFO::Custom ) )
    {
439 440 441
        GetCustomSizeMilsFromDialog();

        retSuccess = m_pageInfo.SetType( PAGE_INFO::Custom );
442

443 444 445 446 447 448 449 450 451 452 453 454 455
        if( retSuccess )
        {
            if( m_layout_size.x < MIN_PAGE_SIZE || m_layout_size.y < MIN_PAGE_SIZE ||
                m_layout_size.x > MAX_PAGE_SIZE || m_layout_size.y > MAX_PAGE_SIZE )
            {
                wxString msg = wxString::Format( _( "Selected custom paper size\nis out of the permissible \
limits\n%.1f - %.1f %s!\nSelect another custom paper size?" ),
                        g_UserUnit == INCHES ? MIN_PAGE_SIZE / 1000. : MIN_PAGE_SIZE * 25.4 / 1000,
                        g_UserUnit == INCHES ? MAX_PAGE_SIZE / 1000. : MAX_PAGE_SIZE * 25.4 / 1000,
                        g_UserUnit == INCHES ? _( "inches" ) : _( "mm" ) );

                if( wxMessageBox( msg, _( "Warning!" ), wxYES_NO | wxICON_EXCLAMATION, this ) == wxYES )
                {
456
                    return false;
457
                }
458

459 460 461 462 463 464
                m_layout_size.x = Clamp( MIN_PAGE_SIZE, m_layout_size.x, MAX_PAGE_SIZE );
                m_layout_size.y = Clamp( MIN_PAGE_SIZE, m_layout_size.y, MAX_PAGE_SIZE );
            }

            PAGE_INFO::SetCustomWidthMils( m_layout_size.x );
            PAGE_INFO::SetCustomHeightMils( m_layout_size.y );
465

466 467
            m_pageInfo.SetWidthMils( m_layout_size.x );
            m_pageInfo.SetHeightMils( m_layout_size.y );
468
        }
469 470 471
    }
    else
    {
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
        // search for longest common string first, e.g. A4 before A
        if( paperType.Contains( PAGE_INFO::USLetter ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::USLetter );
        else if( paperType.Contains( PAGE_INFO::USLegal ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::USLegal );
        else if( paperType.Contains( PAGE_INFO::USLedger ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::USLedger );
        else if( paperType.Contains( PAGE_INFO::GERBER ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::GERBER );
        else if( paperType.Contains( PAGE_INFO::A4 ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A4 );
        else if( paperType.Contains( PAGE_INFO::A3 ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A3 );
        else if( paperType.Contains( PAGE_INFO::A2 ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A2 );
        else if( paperType.Contains( PAGE_INFO::A1 ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A1 );
        else if( paperType.Contains( PAGE_INFO::A0 ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A0 );
        else if( paperType.Contains( PAGE_INFO::A ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::A );
        else if( paperType.Contains( PAGE_INFO::B ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::B );
        else if( paperType.Contains( PAGE_INFO::C ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::C );
        else if( paperType.Contains( PAGE_INFO::D ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::D );
        else if( paperType.Contains( PAGE_INFO::E ) )
            retSuccess = m_pageInfo.SetType( PAGE_INFO::E );

        if( retSuccess )
503
        {
504 505
            int choice = m_orientationComboBox->GetSelection();
            m_pageInfo.SetPortrait( choice != 0 );
506
        }
507
    }
508

509 510 511 512
    if( !retSuccess )
    {
        wxASSERT_MSG( false, wxT( "the translation for paper size must preserve original spellings" ) );
        m_pageInfo.SetType( PAGE_INFO::A4 );
513
    }
514

515
    m_parent->SetPageSettings( m_pageInfo );
516 517

    m_tb.SetRevision( m_TextRevision->GetValue() );
518
    m_tb.SetDate(     m_TextDate->GetValue() );
519 520 521 522 523 524 525
    m_tb.SetCompany(  m_TextCompany->GetValue() );
    m_tb.SetTitle(    m_TextTitle->GetValue() );
    m_tb.SetComment1( m_TextComment1->GetValue() );
    m_tb.SetComment2( m_TextComment2->GetValue() );
    m_tb.SetComment3( m_TextComment3->GetValue() );
    m_tb.SetComment4( m_TextComment4->GetValue() );

526 527
    m_parent->SetTitleBlock( m_tb );

528

529
#ifdef EESCHEMA
530
    // Exports settings to other sheets if requested:
531 532
    SCH_SCREEN* screen;

533
    // Build the screen list
534
    SCH_SCREENS ScreenList;
535

536
    // Update title blocks for all screens
537 538
    for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
    {
539
        if( screen == m_screen )
540 541
            continue;

542 543
        TITLE_BLOCK tb2 = screen->GetTitleBlock();

544
        if( m_RevisionExport->IsChecked() )
545
            tb2.SetRevision( m_tb.GetRevision() );
546

547 548 549
        if( m_DateExport->IsChecked() )
            tb2.SetDate( m_tb.GetDate() );

550
        if( m_TitleExport->IsChecked() )
551
            tb2.SetTitle( m_tb.GetTitle() );
552 553

        if( m_CompanyExport->IsChecked() )
554
            tb2.SetCompany( m_tb.GetCompany() );
555 556

        if( m_Comment1Export->IsChecked() )
557
            tb2.SetComment1( m_tb.GetComment1() );
558 559

        if( m_Comment2Export->IsChecked() )
560
            tb2.SetComment2( m_tb.GetComment2() );
561 562

        if( m_Comment3Export->IsChecked() )
563
            tb2.SetComment3( m_tb.GetComment3() );
564 565

        if( m_Comment4Export->IsChecked() )
566
            tb2.SetComment4( m_tb.GetComment4() );
567 568

        screen->SetTitleBlock( tb2 );
569
    }
570

571 572
#endif

573
    return true;
574 575 576
}


577
void DIALOG_PAGES_SETTINGS::SetCurrentPageSizeSelection( const wxString& aPaperSize )
578
{
579 580
    // search all the not translated label list containing our paper type
    for( unsigned i = 0; i < m_pageFmt.GetCount(); ++i )
581
    {
582
        // parse each label looking for aPaperSize within it
583
        wxStringTokenizer st( m_pageFmt[i] );
584 585

        while( st.HasMoreTokens() )
586
        {
587
            if( st.GetNextToken() == aPaperSize )
588
            {
589
                m_paperSizeComboBox->SetSelection( i );
590 591
                return;
            }
592
        }
593 594
    }
}
595

596 597 598 599 600 601 602 603 604 605 606 607 608 609 610

void DIALOG_PAGES_SETTINGS::UpdatePageLayoutExample()
{
    int lyWidth, lyHeight;

    wxSize clamped_layout_size( Clamp( MIN_PAGE_SIZE, m_layout_size.x, MAX_PAGE_SIZE ),
                                Clamp( MIN_PAGE_SIZE, m_layout_size.y, MAX_PAGE_SIZE ) );

    double lyRatio = clamped_layout_size.x < clamped_layout_size.y ?
                        (double) clamped_layout_size.y / clamped_layout_size.x :
                        (double) clamped_layout_size.x / clamped_layout_size.y;

    if( clamped_layout_size.x < clamped_layout_size.y )
    {
        lyHeight = MAX_PAGE_EXAMPLE_SIZE;
611
        lyWidth = KiROUND( (double) lyHeight / lyRatio );
612 613 614 615
    }
    else
    {
        lyWidth = MAX_PAGE_EXAMPLE_SIZE;
616
        lyHeight = KiROUND( (double) lyWidth / lyRatio );
617 618 619 620 621 622 623 624 625
    }

    if( m_page_bitmap )
    {
        m_PageLayoutExampleBitmap->SetBitmap( wxNullBitmap );
        delete m_page_bitmap;
    }

    m_page_bitmap = new wxBitmap( lyWidth + 1, lyHeight + 1 );
626

627 628 629
    if( m_page_bitmap->IsOk() )
    {
        // Calculate layout preview scale.
630
        int appScale = m_screen->MilsToIuScalar();
631

632 633 634 635
        double scaleW = (double) lyWidth  / clamped_layout_size.x / appScale;
        double scaleH = (double) lyHeight / clamped_layout_size.y / appScale;

        // Prepare DC.
636
        wxSize example_size( lyWidth + 1, lyHeight + 1 );
637 638
        wxMemoryDC memDC;
        memDC.SelectObject( *m_page_bitmap );
639
        memDC.SetClippingRegion( wxPoint( 0, 0 ), example_size );
640 641 642 643 644 645
        memDC.Clear();
        memDC.SetUserScale( scaleW, scaleH );

        // Get logical page size and margins.
        PAGE_INFO pageDUMMY;

646 647 648 649 650 651
        // Get page type
        int idx = m_paperSizeComboBox->GetSelection();

        if( idx < 0 )
            idx = 0;

652 653 654 655 656 657 658 659
        wxString pageFmtName = m_pageFmt[idx].BeforeFirst( ' ' );
        bool portrait = clamped_layout_size.x < clamped_layout_size.y;
        pageDUMMY.SetType( pageFmtName, portrait );
        if( m_customFmt )
        {
            pageDUMMY.SetWidthMils( clamped_layout_size.x );
            pageDUMMY.SetHeightMils( clamped_layout_size.y );
        }
660

661 662
        // Draw layout preview.
        wxString emptyString;
663
        GRResetPenAndBrush( &memDC );
664

665
        DrawPageLayout( &memDC, NULL, pageDUMMY,
666
                        emptyString, emptyString,
667 668
                        m_tb, m_screen->m_NumberOfScreens,
                        m_screen->m_ScreenNumber, 1, appScale, DARKGRAY, RED );
669 670 671 672 673 674 675 676 677 678 679 680 681

        memDC.SelectObject( wxNullBitmap );
        m_PageLayoutExampleBitmap->SetBitmap( *m_page_bitmap );

        // Refresh the dialog.
        Layout();
        Refresh();
    }
}


void DIALOG_PAGES_SETTINGS::GetPageLayoutInfoFromDialog()
{
682
    int idx = m_paperSizeComboBox->GetSelection();
683

684 685
    if( idx < 0 )
        idx = 0;
686

687
    const wxString paperType = m_pageFmt[idx];
688 689 690 691 692

    // here we assume translators will keep original paper size spellings
    if( paperType.Contains( PAGE_INFO::Custom ) )
    {
        GetCustomSizeMilsFromDialog();
693

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
        if( m_layout_size.x && m_layout_size.y )
        {
            if( m_layout_size.x < m_layout_size.y )
                m_orientationComboBox->SetStringSelection( _( "Portrait" ) );
            else
                m_orientationComboBox->SetStringSelection( _( "Landscape" ) );
        }
    }
    else
    {
        PAGE_INFO       pageInfo;   // SetType() later to lookup size

        static const wxString* papers[] = {
            // longest common string first, since sequential search below
            &PAGE_INFO::A4,
            &PAGE_INFO::A3,
            &PAGE_INFO::A2,
            &PAGE_INFO::A1,
            &PAGE_INFO::A0,
            &PAGE_INFO::A,
            &PAGE_INFO::B,
            &PAGE_INFO::C,
            &PAGE_INFO::D,
            &PAGE_INFO::E,
            &PAGE_INFO::USLetter,
            &PAGE_INFO::USLegal,
            &PAGE_INFO::USLedger,
        };

        unsigned i;
724

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
        for( i=0;  i < DIM( papers );  ++i )
        {
            if( paperType.Contains( *papers[i] ) )
            {
                pageInfo.SetType( *papers[i] );
                break;
            }
        }

        wxASSERT( i != DIM(papers) );   // dialog UI match the above list?

        m_layout_size = pageInfo.GetSizeMils();

        // swap sizes to match orientation
        bool isPortrait = (bool) m_orientationComboBox->GetSelection();

        if( ( isPortrait  && m_layout_size.x >= m_layout_size.y ) ||
            ( !isPortrait && m_layout_size.x <  m_layout_size.y ) )
        {
            m_layout_size.Set( m_layout_size.y, m_layout_size.x );
        }
    }
}


void DIALOG_PAGES_SETTINGS::GetCustomSizeMilsFromDialog()
{
    double      customSizeX;
    double      customSizeY;
    wxString    msg;

    msg = m_TextUserSizeX->GetValue();
    msg.ToDouble( &customSizeX );

    msg = m_TextUserSizeY->GetValue();
    msg.ToDouble( &customSizeY );

    switch( g_UserUnit )
    {
    case MILLIMETRES:
        customSizeX *= 1000. / 25.4;
        customSizeY *= 1000. / 25.4;
        break;

    default:
    case INCHES:
        customSizeX *= 1000.;
        customSizeY *= 1000.;
    }

    // Prepare to painless double -> int conversion.
    customSizeX = Clamp( double( INT_MIN ), customSizeX, double( INT_MAX ) );
    customSizeY = Clamp( double( INT_MIN ), customSizeY, double( INT_MAX ) );
778
    m_layout_size = wxSize( KiROUND( customSizeX ), KiROUND( customSizeY ) );
779
}
780 781

// Called on .kicad_wks file description selection change
782
void DIALOG_PAGES_SETTINGS::OnWksFileSelection( wxCommandEvent& event )
783
{
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
    // Display a file picker dialog
    wxFileDialog fileDialog( this, _( "Select Page Layout Descr File" ),
                             wxGetCwd(), GetWksFileName(),
                             PageLayoutDescrFileWildcard,
                             wxFD_DEFAULT_STYLE | wxFD_FILE_MUST_EXIST );

    if( fileDialog.ShowModal() != wxID_OK )
        return;

    wxString fileName = fileDialog.GetPath();

    // Try to remove the path, if the path is the current working dir,
    // or the dir of kicad.pro (template)
    wxString shortFileName = WORKSHEET_LAYOUT::MakeShortFileName( fileName );
    wxFileName fn = shortFileName;

    // For Win/Linux/macOS compatibility, a relative path is a good idea
    if( fn.IsAbsolute() && fileName != GetWksFileName() )
    {
        fn.MakeRelativeTo( wxGetCwd() );
        wxString msg;
        msg.Printf( _( "The page layout descr filename has changed\n"
                       "Do you want to use the relative path:\n%s"),
                       fn.GetFullPath().GetData() );
        if( IsOK( this, msg ) )
            shortFileName = fn.GetFullPath();
    }

    SetWksFileName( shortFileName );
813
}