dialog_fp_lib_table.cpp 20.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
 *
 * 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
 */


Dick Hollenbeck's avatar
Dick Hollenbeck committed
27 28 29 30 31 32 33 34
/*  TODO:

*)  Check for duplicate nicknames per table

*)  Grab text from any pending ChoiceEditor when OK button pressed.

*)  Test wxRE_ADVANCED on Windows.

35 36
*)  Do environment variable substitution on lookup

Dick Hollenbeck's avatar
Dick Hollenbeck committed
37 38 39 40
*/



41
#include <fctsys.h>
42 43
#include <dialog_fp_lib_table_base.h>
#include <fp_lib_table.h>
44
#include <wx/grid.h>
45 46
#include <wx/clipbrd.h>
#include <wx/tokenzr.h>
Dick Hollenbeck's avatar
Dick Hollenbeck committed
47 48 49
#include <wx/arrstr.h>
#include <wx/regex.h>
#include <set>
50

Dick Hollenbeck's avatar
Dick Hollenbeck committed
51 52 53
/**
 * Class FP_TBL_MODEL
 * mixes in wxGridTableBase into FP_LIB_TABLE so that the latter can be used
Dick Hollenbeck's avatar
Dick Hollenbeck committed
54
 * as a table within wxGrid.
Dick Hollenbeck's avatar
Dick Hollenbeck committed
55
 */
56 57 58 59
class FP_TBL_MODEL : public wxGridTableBase, public FP_LIB_TABLE
{
public:

60
    enum COL_ORDER      ///<  grid column order, established by this sequence
61 62 63 64 65 66 67 68 69
    {
        COL_NICKNAME,
        COL_URI,
        COL_TYPE,
        COL_OPTIONS,
        COL_DESCR,
        COL_COUNT       // keep as last
    };

70 71
    /**
     * Constructor FP_TBL_MODEL
Dick Hollenbeck's avatar
Dick Hollenbeck committed
72 73
     * is a copy constructor that builds a wxGridTableBase (table model) by wrapping
     * an FP_LIB_TABLE.
74 75 76 77 78 79 80 81 82
     */
    FP_TBL_MODEL( const FP_LIB_TABLE& aTableToEdit ) :
        FP_LIB_TABLE( aTableToEdit )    // copy constructor
    {
    }

    //-----<wxGridTableBase overloads>-------------------------------------------

    int         GetNumberRows () { return rows.size(); }
83
    int         GetNumberCols () { return COL_COUNT; }
84 85 86 87 88 89 90 91 92

    wxString    GetValue( int aRow, int aCol )
    {
        if( unsigned( aRow ) < rows.size() )
        {
            const ROW&  r  = rows[aRow];

            switch( aCol )
            {
93 94 95 96 97
            case COL_NICKNAME:  return r.GetNickName();
            case COL_URI:       return r.GetFullURI();
            case COL_TYPE:      return r.GetType();
            case COL_OPTIONS:   return r.GetOptions();
            case COL_DESCR:     return r.GetDescr();
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
            default:
                ;       // fall thru to wxEmptyString
            }
        }

        return wxEmptyString;
    }

    void    SetValue( int aRow, int aCol, const wxString &aValue )
    {
        if( unsigned( aRow ) < rows.size() )
        {
            ROW&  r  = rows[aRow];

            switch( aCol )
            {
114 115 116 117 118
            case COL_NICKNAME:  r.SetNickName( aValue );    break;
            case COL_URI:       r.SetFullURI( aValue );     break;
            case COL_TYPE:      r.SetType( aValue  );       break;
            case COL_OPTIONS:   r.SetOptions( aValue );     break;
            case COL_DESCR:     r.SetDescr( aValue );       break;
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
            }
        }
    }

    bool IsEmptyCell( int aRow, int aCol )
    {
        if( unsigned( aRow ) < rows.size() )
            return false;
        return true;
    }

    bool InsertRows( size_t aPos = 0, size_t aNumRows = 1 )
    {
        if( aPos < rows.size() )
        {
            rows.insert( rows.begin() + aPos, aNumRows, ROW() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
135 136 137 138 139 140 141 142 143 144 145 146

            // use the (wxGridStringTable) source Luke.
            if( GetView() )
            {
                wxGridTableMessage msg( this,
                                        wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
                                        aPos,
                                        aNumRows );

                GetView()->ProcessTableMessage( msg );
            }

147 148 149 150 151 152 153
            return true;
        }
        return false;
    }

    bool AppendRows( size_t aNumRows = 1 )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
154 155
        // do not modify aNumRows, original value needed for wxGridTableMessage below
        for( int i = aNumRows; i; --i )
156
            rows.push_back( ROW() );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
157 158 159 160 161 162 163 164 165 166

        if( GetView() )
        {
            wxGridTableMessage msg( this,
                                    wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
                                    aNumRows );

            GetView()->ProcessTableMessage( msg );
        }

167 168 169 170 171 172 173 174 175
        return true;
    }

    bool DeleteRows( size_t aPos, size_t aNumRows )
    {
        if( aPos + aNumRows <= rows.size() )
        {
            ROWS_ITER start = rows.begin() + aPos;
            rows.erase( start, start + aNumRows );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
176 177 178 179 180 181 182 183 184 185 186

            if( GetView() )
            {
                wxGridTableMessage msg( this,
                                        wxGRIDTABLE_NOTIFY_ROWS_DELETED,
                                        aPos,
                                        aNumRows );

                GetView()->ProcessTableMessage( msg );
            }

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
            return true;
        }
        return false;
    }

    void Clear()
    {
        rows.clear();
        nickIndex.clear();
    }

    wxString GetColLabelValue( int aCol )
    {
        switch( aCol )
        {
202 203
        case COL_NICKNAME:  return _( "Nickname" );
        case COL_URI:       return _( "Library Path" );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
204 205 206

        // keep this text fairly long so column is sized wide enough
        case COL_TYPE:      return _( "Plugin Type" );
207 208 209
        case COL_OPTIONS:   return _( "Options" );
        case COL_DESCR:     return _( "Description" );
        default:            return wxEmptyString;
210 211 212 213 214 215 216
        }
    }

    //-----</wxGridTableBase overloads>------------------------------------------
};


Dick Hollenbeck's avatar
Dick Hollenbeck committed
217
// It works for table data on clipboard for an Excell spreadsheet,
218 219 220 221
// why not us too for now.
#define COL_SEP     wxT( '\t' )
#define ROW_SEP     wxT( '\n' )

222 223 224 225 226 227 228 229

/**
 * Class DIALOG_FP_LIB_TABLE
 * shows and edits the PCB library tables.  Two tables are expected, one global
 * and one project specific.
 */
class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
230 231
    typedef FP_LIB_TABLE::ROW   ROW;

232 233 234 235 236 237 238 239
    enum
    {
        ID_CUT,     //  = wxID_HIGHEST + 1,
        ID_COPY,
        ID_PASTE,
    };

    // row & col "selection" acquisition
Dick Hollenbeck's avatar
Dick Hollenbeck committed
240 241 242 243 244 245
    // selected area by cell coordinate and count
    int selRowStart;
    int selColStart;
    int selRowCount;
    int selColCount;

246
    /// Gets the selected area into a sensible rectangle of sel{Row,Col}{Start,Count} above.
Dick Hollenbeck's avatar
Dick Hollenbeck committed
247 248 249 250 251
    void getSelectedArea()
    {
        wxGridCellCoordsArray topLeft  = m_cur_grid->GetSelectionBlockTopLeft();
        wxGridCellCoordsArray botRight = m_cur_grid->GetSelectionBlockBottomRight();

252 253 254 255 256
        wxArrayInt  cols = m_cur_grid->GetSelectedCols();
        wxArrayInt  rows = m_cur_grid->GetSelectedRows();

        D(printf("topLeft.Count():%zd botRight:Count():%zd\n", topLeft.Count(), botRight.Count() );)

Dick Hollenbeck's avatar
Dick Hollenbeck committed
257 258 259 260 261 262 263 264
        if( topLeft.Count() && botRight.Count() )
        {
            selRowStart = topLeft[0].GetRow();
            selColStart = topLeft[0].GetCol();

            selRowCount = botRight[0].GetRow() - selRowStart + 1;
            selColCount = botRight[0].GetCol() - selColStart + 1;
        }
265 266 267 268 269 270 271 272 273 274 275 276 277 278
        else if( cols.Count() )
        {
            selColStart = cols[0];
            selColCount = cols.Count();
            selRowStart = 0;
            selRowCount = m_cur_grid->GetNumberRows();
        }
        else if( rows.Count() )
        {
            selColStart = 0;
            selColCount = m_cur_grid->GetNumberCols();
            selRowStart = rows[0];
            selRowCount = rows.Count();
        }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
279 280 281 282 283 284 285 286
        else
        {
            selRowStart = -1;
            selColStart = -1;
            selRowCount = 0;
            selColCount = 0;
        }

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
        // D(printf("selRowStart:%d selColStart:%d selRowCount:%d selColCount:%d\n", selRowStart, selColStart, selRowCount, selColCount );)
    }

    void rightClickCellPopupMenu()
    {
        wxMenu      menu;

        menu.Append( ID_CUT, _( "Cut" ),      _( "Clear selected cells" ) );
        menu.Append( ID_COPY, _( "Copy" ),    _( "Copy selected cells to clipboard" ) );
        menu.Append( ID_PASTE, _( "Paste" ),  _( "Paste clipboard cells to matrix at current cell" ) );

        getSelectedArea();

        // if nothing is selected, diable cut and copy.
        if( !selRowCount && !selColCount )
        {
            menu.Enable( ID_CUT,  false );
            menu.Enable( ID_COPY, false );
        }

        // if there is no current cell cursor, disable paste.
        if( m_cur_row == -1 || m_cur_col == -1 )
            menu.Enable( ID_PASTE, false );

        PopupMenu( &menu );

        // passOnFocus();
    }

    // the user clicked on a popup menu choice:
    void onPopupSelection( wxCommandEvent& event )
    {
        int     menuId = event.GetId();

        // assume getSelectedArea() was called by rightClickPopupMenu() and there's
        // no way to have gotten here without that having been called.

        switch( menuId )
        {
        case ID_CUT:
        case ID_COPY:
328
            // this format is compatible with most spreadsheets
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
            if( wxTheClipboard->Open() )
            {
                wxGridTableBase*    tbl = m_cur_grid->GetTable();
                wxString            txt;

                for( int row = selRowStart;  row < selRowStart + selRowCount;  ++row )
                {
                    for( int col = selColStart;  col < selColStart + selColCount; ++col )
                    {
                        txt += tbl->GetValue( row, col );

                        if( col < selColStart + selColCount - 1 )   // that was not last column
                            txt += COL_SEP;

                        if( menuId == ID_CUT )
                            tbl->SetValue( row, col, wxEmptyString );
                    }
                    txt += ROW_SEP;
                }

                wxTheClipboard->SetData( new wxTextDataObject( txt ) );
                wxTheClipboard->Close();
                m_cur_grid->ForceRefresh();
            }
            break;

        case ID_PASTE:
            D(printf( "paste\n" );)
357
            // assume format came from a spreadsheet or us.
358 359 360 361 362 363 364 365 366 367 368
            if( wxTheClipboard->Open() )
            {
                if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
                {
                    wxGridTableBase*    tbl = m_cur_grid->GetTable();
                    wxTextDataObject    data;

                    wxTheClipboard->GetData( data );

                    wxStringTokenizer   rows( data.GetText(), ROW_SEP, wxTOKEN_RET_EMPTY );

Dick Hollenbeck's avatar
Dick Hollenbeck committed
369
                    // if clipboard rows would extend past end of current table size...
370 371 372 373 374 375
                    if( int( rows.CountTokens() ) > tbl->GetNumberRows() - m_cur_row )
                    {
                        int newRowsNeeded = rows.CountTokens() - ( tbl->GetNumberRows() - m_cur_row );
                        tbl->AppendRows( newRowsNeeded );
                    }

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
                    for( int row = m_cur_row;  rows.HasMoreTokens();  ++row )
                    {
                        wxString rowTxt = rows.GetNextToken();

                        wxStringTokenizer   cols( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );

                        for( int col = m_cur_col; cols.HasMoreTokens();  ++col )
                        {
                            wxString cellTxt = cols.GetNextToken();
                            tbl->SetValue( row, col, cellTxt );
                        }
                    }
                }

                wxTheClipboard->Close();
                m_cur_grid->ForceRefresh();
            }
            break;
        }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
395
    }
Dick Hollenbeck's avatar
Dick Hollenbeck committed
396

397 398 399 400 401
    //-----<event handlers>----------------------------------

    void pageChangedHandler( wxAuiNotebookEvent& event )
    {
        int pageNdx = m_auinotebook->GetSelection();
402
        m_cur_grid = ( pageNdx == 0 ) ? m_global_grid : m_project_grid;
403 404 405 406
    }

    void appendRowHandler( wxMouseEvent& event )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
407
        m_cur_grid->AppendRows( 1 );
408 409 410 411
    }

    void deleteRowHandler( wxMouseEvent& event )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
412 413
        int curRow = m_cur_grid->GetGridCursorRow();
        m_cur_grid->DeleteRows( curRow );
414 415 416 417
    }

    void moveUpHandler( wxMouseEvent& event )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
418 419 420
        int curRow = m_cur_grid->GetGridCursorRow();
        if( curRow >= 1 )
        {
421
            int curCol = m_cur_grid->GetGridCursorCol();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
422

423
            FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) m_cur_grid->GetTable();
Dick Hollenbeck's avatar
Dick Hollenbeck committed
424

425
            ROW move_me = tbl->rows[curRow];
Dick Hollenbeck's avatar
Dick Hollenbeck committed
426

427 428 429
            tbl->rows.erase( tbl->rows.begin() + curRow );
            --curRow;
            tbl->rows.insert( tbl->rows.begin() + curRow, move_me );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
430 431 432

            if( tbl->GetView() )
            {
433
                // fire a msg to cause redrawing
Dick Hollenbeck's avatar
Dick Hollenbeck committed
434 435 436 437 438 439 440
                wxGridTableMessage msg( tbl,
                                        wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
                                        curRow,
                                        0 );

                tbl->GetView()->ProcessTableMessage( msg );
            }
441 442

            m_cur_grid->SetGridCursor( curRow, curCol );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
443
        }
444 445 446 447
    }

    void moveDownHandler( wxMouseEvent& event )
    {
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
        FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) m_cur_grid->GetTable();

        int curRow = m_cur_grid->GetGridCursorRow();
        if( unsigned( curRow + 1 ) < tbl->rows.size() )
        {
            int curCol  = m_cur_grid->GetGridCursorCol();

            ROW move_me = tbl->rows[curRow];

            tbl->rows.erase( tbl->rows.begin() + curRow );
             ++curRow;
            tbl->rows.insert( tbl->rows.begin() + curRow, move_me );

            if( tbl->GetView() )
            {
                // fire a msg to cause redrawing
                wxGridTableMessage msg( tbl,
                                        wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
                                        curRow - 1,
                                        0 );

                tbl->GetView()->ProcessTableMessage( msg );
            }

            m_cur_grid->SetGridCursor( curRow, curCol );
        }
474 475 476 477 478
        D(printf("%s\n", __func__);)
    }

    void onCancelButtonClick( wxCommandEvent& event )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
479
        EndModal( 0 );
480 481 482 483
    }

    void onOKButtonClick( wxCommandEvent& event )
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
484
        int dialogRet = 0;
485

Dick Hollenbeck's avatar
Dick Hollenbeck committed
486 487 488
        if( m_global_model != *m_global )
        {
            dialogRet |= 1;
489

Dick Hollenbeck's avatar
Dick Hollenbeck committed
490 491 492
            *m_global  = m_global_model;
            m_global->reindex();
        }
493

Dick Hollenbeck's avatar
Dick Hollenbeck committed
494 495 496 497 498 499 500 501 502 503
        if( m_project_model != *m_project )
        {
            dialogRet |= 2;

            *m_project = m_project_model;
            m_project->reindex();
        }

        EndModal( dialogRet );
    }
504

505 506 507 508 509 510 511 512 513 514 515 516 517 518
    void onGridCellLeftClick( wxGridEvent& event )
    {
        event.Skip();
    }

    void onGridCellLeftDClick( wxGridEvent& event )
    {
        event.Skip();
    }

    void onGridCellRightClick( wxGridEvent& event )
    {
        rightClickCellPopupMenu();
    }
519

520 521 522 523 524 525 526 527 528 529 530
    void onGridCmdSelectCell( wxGridEvent& event )
    {
        m_cur_row = event.GetRow();
        m_cur_col = event.GetCol();

        D(printf("change cursor(%d,%d)\n", m_cur_row, m_cur_col );)

        // somebody else wants this
        event.Skip();
    }

Dick Hollenbeck's avatar
Dick Hollenbeck committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
    /// Populate the readonly environment variable table with names and values
    /// by examining all the full_uri columns.
    void populateEnvironReadOnlyTable()
    {
        wxRegEx re( wxT( ".*?\\$\\{(.+?)\\}.*?" ), wxRE_ADVANCED );
        wxASSERT( re.IsValid() );   // wxRE_ADVANCED is required.

        std::set< wxString >        unique;
        typedef std::set<wxString>::const_iterator      SET_CITER;

        m_path_subs_grid->DeleteRows( 0, m_path_subs_grid->GetNumberRows() );

        int gblRowCount = m_global_model.GetNumberRows();
        int prjRowCount = m_project_model.GetNumberRows();
        int row;

        for( row = 0;  row < gblRowCount;  ++row )
        {
            wxString uri = m_global_model.GetValue( row, FP_TBL_MODEL::COL_URI );

            while( re.Matches( uri ) )
            {
                wxString envvar = re.GetMatch( uri, 1 );

                // ignore duplicates
                unique.insert( envvar );

                // delete the last match and search again
                uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
            }
        }
562

Dick Hollenbeck's avatar
Dick Hollenbeck committed
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
        for( row = 0;  row < prjRowCount;  ++row )
        {
            wxString uri = m_project_model.GetValue( row, FP_TBL_MODEL::COL_URI );

            while( re.Matches( uri ) )
            {
                wxString envvar = re.GetMatch( uri, 1 );

                // ignore duplicates
                unique.insert( envvar );

                // delete the last match and search again
                uri.Replace( re.GetMatch( uri, 0 ), wxEmptyString );
            }
        }

        m_path_subs_grid->AppendRows( unique.size() );

        row = 0;
        for( SET_CITER it = unique.begin();  it != unique.end();  ++it, ++row )
        {
            wxString    evName = *it;
            wxString    evValue;

            m_path_subs_grid->SetCellValue( row, 0, evName );

            if( wxGetEnv( evName, &evValue ) )
                m_path_subs_grid->SetCellValue( row, 1, evValue );
        }

        m_path_subs_grid->AutoSizeColumns();
    }

596
    //-----</event handlers>---------------------------------
597 598 599 600 601

    // caller's tables are modified only on OK button.
    FP_LIB_TABLE*       m_global;
    FP_LIB_TABLE*       m_project;

602 603 604
    // local copies which are edited, but aborted if Cancel button.
    FP_TBL_MODEL        m_global_model;
    FP_TBL_MODEL        m_project_model;
605 606 607

    wxGrid*             m_cur_grid;     ///< changed based on tab choice

608 609 610 611
    // wxGrid makes it difficult to know if the cursor is yet visible,
    // use this to solve that, initial values are -1
    int                 m_cur_row;      ///< cursor position
    int                 m_cur_col;
612 613

public:
614 615 616 617
    DIALOG_FP_LIB_TABLE( wxFrame* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject ) :
        DIALOG_FP_LIB_TABLE_BASE( aParent ),
        m_global( aGlobal ),
        m_project( aProject ),
618
        m_global_model( *aGlobal ),
619 620 621
        m_project_model( *aProject ),
        m_cur_row( -1 ),
        m_cur_col( -1 )
622
    {
623 624
        m_global_grid->SetTable( (wxGridTableBase*) &m_global_model );
        m_project_grid->SetTable( (wxGridTableBase*) &m_project_model );
625 626 627 628

        m_global_grid->AutoSizeColumns( false );
        m_project_grid->AutoSizeColumns( false );

Dick Hollenbeck's avatar
Dick Hollenbeck committed
629 630 631 632
        wxArrayString choices;
        choices.Add( IO_MGR::ShowType( IO_MGR::KICAD ) );
        choices.Add( IO_MGR::ShowType( IO_MGR::LEGACY ) );
        choices.Add( IO_MGR::ShowType( IO_MGR::EAGLE ) );
633
        choices.Add( IO_MGR::ShowType( IO_MGR::GEDA_PCB ) );
Dick Hollenbeck's avatar
Dick Hollenbeck committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647

        wxGridCellAttr* attr;

        attr = new wxGridCellAttr;
        attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
        m_project_grid->SetColAttr( FP_TBL_MODEL::COL_TYPE, attr );

        attr = new wxGridCellAttr;
        attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
        m_global_grid->SetColAttr(  FP_TBL_MODEL::COL_TYPE, attr );

        m_global_grid->AutoSizeColumns();
        m_project_grid->AutoSizeColumns();

648 649 650
        Connect( ID_CUT, ID_PASTE, wxEVT_COMMAND_MENU_SELECTED,
            wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );

Dick Hollenbeck's avatar
Dick Hollenbeck committed
651 652 653 654 655
        populateEnvironReadOnlyTable();

        /* This scrunches the dialog hideously
        Fit();
        */
Dick Hollenbeck's avatar
Dick Hollenbeck committed
656 657 658 659

        // fire pageChangedHandler() so m_cur_grid gets set
        wxAuiNotebookEvent uneventful;
        pageChangedHandler( uneventful );
660
    }
661 662 663

    ~DIALOG_FP_LIB_TABLE()
    {
Dick Hollenbeck's avatar
Dick Hollenbeck committed
664 665 666 667 668 669 670 671
        Disconnect( ID_CUT, ID_PASTE, wxEVT_COMMAND_MENU_SELECTED,
            wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );

        // ~wxGrid() examines its table, and the tables will have been destroyed before
        // the wxGrids are, so remove the tables from the wxGrids' awareness.
        // Otherwise there is a segfault.
        m_global_grid->SetTable( NULL );
        m_project_grid->SetTable( NULL );
672
    }
673 674 675 676 677
};


int InvokePcbLibTableEditor( wxFrame* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject )
{
Dick Hollenbeck's avatar
Dick Hollenbeck committed
678
    DIALOG_FP_LIB_TABLE dlg( aParent, aGlobal, aProject );
679

Dick Hollenbeck's avatar
Dick Hollenbeck committed
680
    int dialogRet = dlg.ShowModal();    // returns value passed to EndModal() above
681

Dick Hollenbeck's avatar
Dick Hollenbeck committed
682
    return dialogRet;
683 684
}