Commit 1731e895 authored by Dick Hollenbeck's avatar Dick Hollenbeck

*) Factor out Cut, Copy, and Paste for wxGrid into class common/GRID_TRICKS.

*) Use it on 3 grids total in DIALOG_FP_PLUGIN_OPTIONS and DIALOG_FP_LIB_TABLE.
*) Fix bug when pasting "(fp_lib_table" text into FP_LIB_TABLE.
parent 2033181b
......@@ -73,6 +73,7 @@ set(COMMON_SRCS
filter_reader.cpp
gestfich.cpp
getrunningmicrosecs.cpp
grid_tricks.cpp
gr_basic.cpp
hotkeys_basic.cpp
hotkey_grid_table.cpp
......
/*
* 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 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
*/
#include <fctsys.h>
#include <grid_tricks.h>
#include <wx/tokenzr.h>
#include <wx/arrstr.h>
#include <wx/clipbrd.h>
// It works for table data on clipboard for an Excell spreadsheet,
// why not us too for now.
#define COL_SEP wxT( '\t' )
#define ROW_SEP wxT( '\n' )
enum
{
MYID_FIRST = -1,
MYID_CUT,
MYID_COPY,
MYID_PASTE,
MYID_SELECT,
MYID_LAST,
};
GRID_TRICKS::GRID_TRICKS( wxGrid* aGrid ):
m_grid( aGrid )
{
aGrid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( GRID_TRICKS::onGridCellRightClick ), NULL, this );
aGrid->Connect( MYID_FIRST, MYID_LAST, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( GRID_TRICKS::onPopupSelection ), NULL, this );
aGrid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( GRID_TRICKS::onKeyDown ), NULL, this );
aGrid->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( GRID_TRICKS::onRightDown ), NULL, this );
}
void GRID_TRICKS::getSelectedArea()
{
wxGridCellCoordsArray topLeft = m_grid->GetSelectionBlockTopLeft();
wxGridCellCoordsArray botRight = m_grid->GetSelectionBlockBottomRight();
wxArrayInt cols = m_grid->GetSelectedCols();
wxArrayInt rows = m_grid->GetSelectedRows();
D(printf("topLeft.Count():%zd botRight:Count():%zd\n", topLeft.Count(), botRight.Count() );)
if( topLeft.Count() && botRight.Count() )
{
m_sel_row_start = topLeft[0].GetRow();
m_sel_col_start = topLeft[0].GetCol();
m_sel_row_count = botRight[0].GetRow() - m_sel_row_start + 1;
m_sel_col_count = botRight[0].GetCol() - m_sel_col_start + 1;
}
else if( cols.Count() )
{
m_sel_col_start = cols[0];
m_sel_col_count = cols.Count();
m_sel_row_start = 0;
m_sel_row_count = m_grid->GetNumberRows();
}
else if( rows.Count() )
{
m_sel_col_start = 0;
m_sel_col_count = m_grid->GetNumberCols();
m_sel_row_start = rows[0];
m_sel_row_count = rows.Count();
}
else
{
m_sel_row_start = -1;
m_sel_col_start = -1;
m_sel_row_count = 0;
m_sel_col_count = 0;
}
//D(printf("m_sel_row_start:%d m_sel_col_start:%d m_sel_row_count:%d m_sel_col_count:%d\n", m_sel_row_start, m_sel_col_start, m_sel_row_count, m_sel_col_count );)
}
void GRID_TRICKS::showPopupMenu()
{
wxMenu menu;
menu.Append( MYID_CUT, _( "Cut\tCTRL+X" ), _( "Clear selected cells pasting original contents to clipboard" ) );
menu.Append( MYID_COPY, _( "Copy\tCTRL+C" ), _( "Copy selected cells to clipboard" ) );
menu.Append( MYID_PASTE, _( "Paste\tCTRL+V" ), _( "Paste clipboard cells to matrix at current cell" ) );
menu.Append( MYID_SELECT, _( "Select All\tCTRL+A" ), _( "Select all cells" ) );
getSelectedArea();
// if nothing is selected, disable cut and copy.
if( !m_sel_row_count && !m_sel_col_count )
{
menu.Enable( MYID_CUT, false );
menu.Enable( MYID_COPY, false );
}
bool have_cb_text = false;
if( wxTheClipboard->Open() )
{
if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
have_cb_text = true;
wxTheClipboard->Close();
}
if( !have_cb_text )
{
// if nothing on clipboard, disable paste.
menu.Enable( MYID_PASTE, false );
}
m_grid->PopupMenu( &menu );
}
void GRID_TRICKS::onPopupSelection( wxCommandEvent& event )
{
int menu_id = event.GetId();
// assume getSelectedArea() was called by rightClickPopupMenu() and there's
// no way to have gotten here without that having been called.
switch( menu_id )
{
case MYID_CUT:
case MYID_COPY:
cutcopy( menu_id == MYID_CUT );
break;
case MYID_PASTE:
paste_clipboard();
break;
case MYID_SELECT:
m_grid->SelectAll();
break;
default:
;
}
}
void GRID_TRICKS::onKeyDown( wxKeyEvent& ev )
{
if( isCtl( 'A', ev ) )
{
m_grid->SelectAll();
}
else if( isCtl( 'C', ev ) )
{
getSelectedArea();
cutcopy( false );
}
else if( isCtl( 'V', ev ) )
{
getSelectedArea();
paste_clipboard();
}
else if( isCtl( 'X', ev ) )
{
getSelectedArea();
cutcopy( true );
}
else
ev.Skip();
}
void GRID_TRICKS::paste_clipboard()
{
if( wxTheClipboard->Open() )
{
if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
{
wxTextDataObject data;
wxTheClipboard->GetData( data );
wxString cb_text = data.GetText();
paste_text( cb_text );
}
wxTheClipboard->Close();
m_grid->ForceRefresh();
}
}
void GRID_TRICKS::paste_text( const wxString& cb_text )
{
wxGridTableBase* tbl = m_grid->GetTable();
const int cur_row = std::max( getCursorRow(), 0 ); // no -1
const int cur_col = std::max( getCursorCol(), 0 );
wxStringTokenizer rows( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
// if clipboard rows would extend past end of current table size...
if( int( rows.CountTokens() ) > tbl->GetNumberRows() - cur_row )
{
int newRowsNeeded = rows.CountTokens() - ( tbl->GetNumberRows() - cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int row = cur_row; rows.HasMoreTokens(); ++row )
{
wxString rowTxt = rows.GetNextToken();
wxStringTokenizer cols( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
for( int col = cur_col; cols.HasMoreTokens(); ++col )
{
wxString cellTxt = cols.GetNextToken();
tbl->SetValue( row, col, cellTxt );
}
}
m_grid->AutoSizeColumns( false );
}
void GRID_TRICKS::cutcopy( bool doCut )
{
if( wxTheClipboard->Open() )
{
wxGridTableBase* tbl = m_grid->GetTable();
wxString txt;
// fill txt with a format that is compatible with most spreadsheets
for( int row = m_sel_row_start; row < m_sel_row_start + m_sel_row_count; ++row )
{
for( int col = m_sel_col_start; col < m_sel_col_start + m_sel_col_count; ++col )
{
txt += tbl->GetValue( row, col );
if( col < m_sel_col_start + m_sel_col_count - 1 ) // that was not last column
txt += COL_SEP;
if( doCut )
tbl->SetValue( row, col, wxEmptyString );
}
txt += ROW_SEP;
}
wxTheClipboard->SetData( new wxTextDataObject( txt ) );
wxTheClipboard->Close();
if( doCut )
{
m_grid->AutoSizeColumns( false );
m_grid->ForceRefresh();
}
}
}
......@@ -315,6 +315,10 @@ public:
bool operator!=( const FP_LIB_TABLE& r ) const { return !( *this == r ); }
int GetCount() { return rows.size(); }
ROW& At( int aIndex ) { return rows[aIndex]; }
/**
* Function Parse
* fills this table fragment from information in the input stream \a aParser, which
......
/*
* 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 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
*/
#include <wx/grid.h>
#include <wx/event.h>
/**
* Class GRID_TRICKS
* is used to add cut, copy, and paste to an otherwise unmodied wxGrid instance.
*/
class GRID_TRICKS : public wxEvtHandler
{
public:
GRID_TRICKS( wxGrid* aGrid );
protected:
wxGrid* m_grid; ///< I don't own the grid, but he owns me
// row & col "selection" acquisition
// selected area by cell coordinate and count
int m_sel_row_start;
int m_sel_col_start;
int m_sel_row_count;
int m_sel_col_count;
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based column index.
int getCursorCol() const
{
return m_grid->GetGridCursorCol();
}
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based row index.
int getCursorRow() const
{
return m_grid->GetGridCursorRow();
}
/// Puts the selected area into a sensible rectangle of m_sel_{row,col}_{start,count} above.
void getSelectedArea();
static bool isCtl( int aChar, const wxKeyEvent& e )
{
return e.GetKeyCode() == aChar && e.ControlDown() && !e.AltDown() && !e.ShiftDown() && !e.MetaDown();
}
void onGridCellRightClick( wxGridEvent& event )
{
showPopupMenu();
}
void onRightDown( wxMouseEvent& event )
{
showPopupMenu();
}
virtual void showPopupMenu();
// the user clicked on a popup menu choice:
void onPopupSelection( wxCommandEvent& event );
void onKeyDown( wxKeyEvent& ev );
virtual void paste_clipboard();
virtual void paste_text( const wxString& cb_text );
virtual void cutcopy( bool doCut );
};
......@@ -2,6 +2,7 @@
* 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) 2013 CERN
* Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
......@@ -30,18 +31,15 @@
*/
#include <wx/grid.h>
#include <wx/clipbrd.h>
#include <wx/tokenzr.h>
#include <wx/arrstr.h>
#include <wx/regex.h>
#include <set>
#include <wx/regex.h>
#include <fctsys.h>
#include <dialog_fp_lib_table_base.h>
#include <fp_lib_table.h>
#include <fp_lib_table_lexer.h>
#include <invoke_pcb_dialog.h>
#include <grid_tricks.h>
/// grid column order is established by this sequence
......@@ -63,6 +61,8 @@ enum COL_ORDER
*/
class FP_TBL_MODEL : public wxGridTableBase, public FP_LIB_TABLE
{
friend class FP_GRID_TRICKS;
public:
/**
......@@ -120,9 +120,7 @@ public:
bool IsEmptyCell( int aRow, int aCol )
{
if( unsigned( aRow ) < rows.size() )
return false;
return true;
return !GetValue( aRow, aCol );
}
bool InsertRows( size_t aPos = 0, size_t aNumRows = 1 )
......@@ -212,169 +210,92 @@ public:
};
// It works for table data on clipboard for an Excell spreadsheet,
// why not us too for now.
#define COL_SEP wxT( '\t' )
#define ROW_SEP wxT( '\n' )
inline bool isCtl( int aChar, const wxKeyEvent& e )
class FP_GRID_TRICKS : public GRID_TRICKS
{
return e.GetKeyCode() == aChar && e.ControlDown() && !e.AltDown() && !e.ShiftDown() && !e.MetaDown();
}
/**
* 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
{
typedef FP_LIB_TABLE::ROW ROW;
enum
{
MYID_FIRST = -1,
MYID_CUT,
MYID_COPY,
MYID_PASTE,
MYID_SELECT,
MYID_LAST,
};
// row & col "selection" acquisition
// selected area by cell coordinate and count
int selRowStart;
int selColStart;
int selRowCount;
int selColCount;
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based column index.
int getCursorCol() const
public:
FP_GRID_TRICKS( wxGrid* aGrid ) :
GRID_TRICKS( aGrid )
{
return m_cur_grid->GetGridCursorCol();
}
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based row index.
int getCursorRow() const
{
return m_cur_grid->GetGridCursorRow();
}
protected:
/// Puts the selected area into a sensible rectangle of sel{Row,Col}{Start,Count} above.
void getSelectedArea()
/// handle specialized clipboard text, with leading "(fp_lib_table", OR
/// spreadsheet formatted text.
virtual void paste_text( const wxString& cb_text )
{
wxGridCellCoordsArray topLeft = m_cur_grid->GetSelectionBlockTopLeft();
wxGridCellCoordsArray botRight = m_cur_grid->GetSelectionBlockBottomRight();
FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) m_grid->GetTable();
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() );)
size_t ndx = cb_text.find( wxT( "(fp_lib_table" ) );
if( topLeft.Count() && botRight.Count() )
if( ndx != std::string::npos )
{
selRowStart = topLeft[0].GetRow();
selColStart = topLeft[0].GetCol();
// paste the ROWs of s-expression (fp_lib_table), starting
// at column 0 regardless of current cursor column.
selRowCount = botRight[0].GetRow() - selRowStart + 1;
selColCount = botRight[0].GetCol() - selColStart + 1;
}
else if( cols.Count() )
{
selColStart = cols[0];
selColCount = cols.Count();
selRowStart = 0;
selRowCount = m_cur_grid->GetNumberRows();
}
else if( rows.Count() )
STRING_LINE_READER slr( TO_UTF8( cb_text ), wxT( "Clipboard" ) );
FP_LIB_TABLE_LEXER lexer( &slr );
FP_LIB_TABLE tmp_tbl;
bool parsed = true;
try
{
selColStart = 0;
selColCount = m_cur_grid->GetNumberCols();
selRowStart = rows[0];
selRowCount = rows.Count();
tmp_tbl.Parse( &lexer );
}
else
catch( PARSE_ERROR& pe )
{
selRowStart = -1;
selColStart = -1;
selRowCount = 0;
selColCount = 0;
}
D(printf("selRowStart:%d selColStart:%d selRowCount:%d selColCount:%d\n", selRowStart, selColStart, selRowCount, selColCount );)
// @todo tell what line and offset
parsed = false;
}
void rightClickCellPopupMenu()
if( parsed )
{
wxMenu menu;
const int cur_row = std::max( getCursorRow(), 0 );
menu.Append( MYID_CUT, _( "Cut\tCTRL+X" ), _( "Clear selected cells pasting original contents to clipboard" ) );
menu.Append( MYID_COPY, _( "Copy\tCTRL+C" ), _( "Copy selected cells to clipboard" ) );
menu.Append( MYID_PASTE, _( "Paste\tCTRL+V" ), _( "Paste clipboard cells to matrix at current cell" ) );
menu.Append( MYID_SELECT, _( "Select All\tCTRL+A" ), _( "Select all cells" ) );
getSelectedArea();
// if nothing is selected, disable cut and copy.
if( !selRowCount && !selColCount )
// if clipboard rows would extend past end of current table size...
if( tmp_tbl.GetCount() > tbl->GetNumberRows() - cur_row )
{
menu.Enable( MYID_CUT, false );
menu.Enable( MYID_COPY, false );
int newRowsNeeded = tmp_tbl.GetCount() - ( tbl->GetNumberRows() - cur_row );
tbl->AppendRows( newRowsNeeded );
}
bool have_cb_text = false;
if( wxTheClipboard->Open() )
for( int i = 0; i < tmp_tbl.GetCount(); ++i )
{
if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
have_cb_text = true;
wxTheClipboard->Close();
tbl->At( cur_row+i ) = tmp_tbl.At( i );
}
if( !have_cb_text )
}
m_grid->AutoSizeColumns( false );
}
else
{
// if nothing on clipboard, disable paste.
menu.Enable( MYID_PASTE, false );
// paste spreadsheet formatted text.
GRID_TRICKS::paste_text( cb_text );
}
PopupMenu( &menu );
// passOnFocus();
}
};
void cutcopy( bool doCut );
void paste();
// 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.
/**
* 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
{
typedef FP_LIB_TABLE::ROW ROW;
switch( menuId )
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based column index.
int getCursorCol() const
{
case MYID_CUT:
case MYID_COPY:
cutcopy( menuId == MYID_CUT );
break;
case MYID_PASTE:
paste();
break;
case MYID_SELECT:
m_cur_grid->SelectAll();
break;
default:
;
return m_cur_grid->GetGridCursorCol();
}
/// If the cursor is not on a valid cell, because there are no rows at all, return -1,
/// else return a 0 based row index.
int getCursorRow() const
{
return m_cur_grid->GetGridCursorRow();
}
......@@ -479,27 +400,14 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
void onKeyDown( wxKeyEvent& ev )
{
if( isCtl( 'A', ev ) )
{
m_cur_grid->SelectAll();
}
else if( isCtl( 'C', ev ) )
{
getSelectedArea();
cutcopy( false );
}
else if( isCtl( 'V', ev ) )
{
getSelectedArea();
paste();
}
else if( isCtl( 'X', ev ) )
{
getSelectedArea();
cutcopy( true );
}
else
#if 0
// send the key to the current grid
((wxEvtHandler*)m_cur_grid)->ProcessEvent( ev );
#else
// or no:
// m_cur_grid has the focus most of the time anyways, so above not needed.
ev.Skip();
#endif
}
void pageChangedHandler( wxAuiNotebookEvent& event )
......@@ -646,26 +554,6 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
}
}
void onGridCmdSelectCell( wxGridEvent& event )
{
event.Skip();
}
void onGridCellLeftClick( wxGridEvent& event )
{
event.Skip();
}
void onGridCellLeftDClick( wxGridEvent& event )
{
event.Skip();
}
void onGridCellRightClick( wxGridEvent& event )
{
rightClickCellPopupMenu();
}
/// Populate the readonly environment variable table with names and values
/// by examining all the full_uri columns.
void populateEnvironReadOnlyTable()
......@@ -676,6 +564,7 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
std::set< wxString > unique;
typedef std::set<wxString>::const_iterator SET_CITER;
// clear the table
m_path_subs_grid->DeleteRows( 0, m_path_subs_grid->GetNumberRows() );
int gblRowCount = m_global_model.GetNumberRows();
......@@ -754,6 +643,10 @@ public:
m_global_grid->SetTable( (wxGridTableBase*) &m_global_model );
m_project_grid->SetTable( (wxGridTableBase*) &m_project_model );
// add Cut, Copy, and Paste to wxGrids
m_global_grid->PushEventHandler( new FP_GRID_TRICKS( m_global_grid ) );
m_project_grid->PushEventHandler( new FP_GRID_TRICKS( m_project_grid ) );
m_global_grid->AutoSizeColumns( false );
m_project_grid->AutoSizeColumns( false );
......@@ -779,11 +672,13 @@ public:
attr->SetEditor( new wxGridCellChoiceEditor( choices ) );
m_global_grid->SetColAttr( COL_TYPE, attr );
m_global_grid->AutoSizeColumns();
m_project_grid->AutoSizeColumns();
m_global_grid->AutoSizeColumns( false );
m_project_grid->AutoSizeColumns( false );
/*
Connect( MYID_FIRST, MYID_LAST, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );
*/
populateEnvironReadOnlyTable();
......@@ -801,8 +696,10 @@ public:
~DIALOG_FP_LIB_TABLE()
{
Disconnect( MYID_FIRST, MYID_LAST, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );
// Delete the GRID_TRICKS.
// Any additional event handlers should be popped before the window is deleted.
m_global_grid->PopEventHandler( true );
m_project_grid->PopEventHandler( true );
// ~wxGrid() examines its table, and the tables will have been destroyed before
// the wxGrids are, so remove the tables from the wxGrids' awareness.
......@@ -813,128 +710,6 @@ public:
};
void DIALOG_FP_LIB_TABLE::cutcopy( bool doCut )
{
// this format is compatible with most spreadsheets
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( doCut )
tbl->SetValue( row, col, wxEmptyString );
}
txt += ROW_SEP;
}
wxTheClipboard->SetData( new wxTextDataObject( txt ) );
wxTheClipboard->Close();
m_cur_grid->AutoSizeColumns();
m_cur_grid->ForceRefresh();
}
}
void DIALOG_FP_LIB_TABLE::paste()
{
// assume format came from a spreadsheet or us.
if( wxTheClipboard->Open() )
{
if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
{
wxTextDataObject data;
FP_TBL_MODEL* tbl = (FP_TBL_MODEL*) m_cur_grid->GetTable();
wxTheClipboard->GetData( data );
wxString cb_text = data.GetText();
size_t ndx = cb_text.find( wxT( "(fp_lib_table" ) );
if( ndx != std::string::npos )
{
// paste the ROWs of s-expression (fp_lib_table), starting
// at column 0 regardless of current cursor column.
STRING_LINE_READER slr( TO_UTF8( cb_text ), wxT( "Clipboard" ) );
FP_LIB_TABLE_LEXER lexer( &slr );
FP_LIB_TABLE tmp_tbl;
bool parsed = true;
try
{
tmp_tbl.Parse( &lexer );
}
catch( PARSE_ERROR& pe )
{
// @todo tell what line and offset
parsed = false;
}
if( parsed )
{
const int cur_row = getCursorRow();
// if clipboard rows would extend past end of current table size...
if( int( tmp_tbl.rows.size() ) > tbl->GetNumberRows() - cur_row )
{
int newRowsNeeded = tmp_tbl.rows.size() - ( tbl->GetNumberRows() - cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int i = 0; i < (int) tmp_tbl.rows.size(); ++i )
{
tbl->rows[cur_row+i] = tmp_tbl.rows[i];
}
}
m_cur_grid->AutoSizeColumns();
}
else
{
const int cur_row = std::max( getCursorRow(), 0 ); // no -1
const int cur_col = std::max( getCursorCol(), 0 );
wxStringTokenizer rows( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
// if clipboard rows would extend past end of current table size...
if( int( rows.CountTokens() ) > tbl->GetNumberRows() - cur_row )
{
int newRowsNeeded = rows.CountTokens() - ( tbl->GetNumberRows() - cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int row = cur_row; rows.HasMoreTokens(); ++row )
{
wxString rowTxt = rows.GetNextToken();
wxStringTokenizer cols( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
for( int col = cur_col; cols.HasMoreTokens(); ++col )
{
wxString cellTxt = cols.GetNextToken();
tbl->SetValue( row, col, cellTxt );
}
}
m_cur_grid->AutoSizeColumns();
}
}
wxTheClipboard->Close();
m_cur_grid->ForceRefresh();
}
}
int InvokePcbLibTableEditor( wxTopLevelWindow* aParent, FP_LIB_TABLE* aGlobal, FP_LIB_TABLE* aProject )
{
DIALOG_FP_LIB_TABLE dlg( aParent, aGlobal, aProject );
......
......@@ -193,16 +193,6 @@ DIALOG_FP_LIB_TABLE_BASE::DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FP_LIB_TABLE_BASE::onCancelButtonClick ) );
this->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ) );
m_auinotebook->Connect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( DIALOG_FP_LIB_TABLE_BASE::pageChangedHandler ), NULL, this );
m_global_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftClick ), NULL, this );
m_global_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftDClick ), NULL, this );
m_global_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellRightClick ), NULL, this );
m_global_grid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCmdSelectCell ), NULL, this );
m_global_grid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ), NULL, this );
m_project_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftClick ), NULL, this );
m_project_grid->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftDClick ), NULL, this );
m_project_grid->Connect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellRightClick ), NULL, this );
m_project_grid->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCmdSelectCell ), NULL, this );
m_project_grid->Connect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ), NULL, this );
m_append_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::appendRowHandler ), NULL, this );
m_delete_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::deleteRowHandler ), NULL, this );
m_move_up_button->Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveUpHandler ), NULL, this );
......@@ -218,16 +208,6 @@ DIALOG_FP_LIB_TABLE_BASE::~DIALOG_FP_LIB_TABLE_BASE()
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FP_LIB_TABLE_BASE::onCancelButtonClick ) );
this->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ) );
m_auinotebook->Disconnect( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, wxAuiNotebookEventHandler( DIALOG_FP_LIB_TABLE_BASE::pageChangedHandler ), NULL, this );
m_global_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftClick ), NULL, this );
m_global_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftDClick ), NULL, this );
m_global_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellRightClick ), NULL, this );
m_global_grid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCmdSelectCell ), NULL, this );
m_global_grid->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ), NULL, this );
m_project_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftClick ), NULL, this );
m_project_grid->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellLeftDClick ), NULL, this );
m_project_grid->Disconnect( wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCellRightClick ), NULL, this );
m_project_grid->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( DIALOG_FP_LIB_TABLE_BASE::onGridCmdSelectCell ), NULL, this );
m_project_grid->Disconnect( wxEVT_KEY_DOWN, wxKeyEventHandler( DIALOG_FP_LIB_TABLE_BASE::onKeyDown ), NULL, this );
m_append_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::appendRowHandler ), NULL, this );
m_delete_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::deleteRowHandler ), NULL, this );
m_move_up_button->Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( DIALOG_FP_LIB_TABLE_BASE::moveUpHandler ), NULL, this );
......
......@@ -30,7 +30,7 @@
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="context_menu">0</property>
<property name="enabled">1</property>
<property name="event_handler">decl_pure_virtual</property>
<property name="extra_style"></property>
......@@ -43,7 +43,7 @@
<property name="name">DIALOG_FP_LIB_TABLE_BASE</property>
<property name="pos"></property>
<property name="size">900,600</property>
<property name="style">wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER</property>
<property name="style">wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">PCB Library Tables</property>
<property name="tooltip"></property>
......@@ -123,7 +123,7 @@
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="context_menu">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
......@@ -212,7 +212,7 @@
<property name="center_pane">0</property>
<property name="close_button">0</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="context_menu">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
......@@ -365,9 +365,9 @@
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnGridCellChange"></event>
<event name="OnGridCellLeftClick">onGridCellLeftClick</event>
<event name="OnGridCellLeftDClick">onGridCellLeftDClick</event>
<event name="OnGridCellRightClick">onGridCellRightClick</event>
<event name="OnGridCellLeftClick"></event>
<event name="OnGridCellLeftDClick"></event>
<event name="OnGridCellRightClick"></event>
<event name="OnGridCellRightDClick"></event>
<event name="OnGridCmdCellChange"></event>
<event name="OnGridCmdCellLeftClick"></event>
......@@ -384,7 +384,7 @@
<event name="OnGridCmdLabelRightDClick"></event>
<event name="OnGridCmdRangeSelect"></event>
<event name="OnGridCmdRowSize"></event>
<event name="OnGridCmdSelectCell">onGridCmdSelectCell</event>
<event name="OnGridCmdSelectCell"></event>
<event name="OnGridColSize"></event>
<event name="OnGridEditorCreated"></event>
<event name="OnGridEditorHidden"></event>
......@@ -396,7 +396,7 @@
<event name="OnGridRangeSelect"></event>
<event name="OnGridRowSize"></event>
<event name="OnGridSelectCell"></event>
<event name="OnKeyDown">onKeyDown</event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
......@@ -441,7 +441,7 @@
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="context_menu">0</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
......@@ -594,9 +594,9 @@
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnGridCellChange"></event>
<event name="OnGridCellLeftClick">onGridCellLeftClick</event>
<event name="OnGridCellLeftDClick">onGridCellLeftDClick</event>
<event name="OnGridCellRightClick">onGridCellRightClick</event>
<event name="OnGridCellLeftClick"></event>
<event name="OnGridCellLeftDClick"></event>
<event name="OnGridCellRightClick"></event>
<event name="OnGridCellRightDClick"></event>
<event name="OnGridCmdCellChange"></event>
<event name="OnGridCmdCellLeftClick"></event>
......@@ -613,7 +613,7 @@
<event name="OnGridCmdLabelRightDClick"></event>
<event name="OnGridCmdRangeSelect"></event>
<event name="OnGridCmdRowSize"></event>
<event name="OnGridCmdSelectCell">onGridCmdSelectCell</event>
<event name="OnGridCmdSelectCell"></event>
<event name="OnGridColSize"></event>
<event name="OnGridEditorCreated"></event>
<event name="OnGridEditorHidden"></event>
......@@ -625,7 +625,7 @@
<event name="OnGridRangeSelect"></event>
<event name="OnGridRowSize"></event>
<event name="OnGridSelectCell"></event>
<event name="OnKeyDown">onKeyDown</event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
......
......@@ -60,10 +60,6 @@ class DIALOG_FP_LIB_TABLE_BASE : public DIALOG_SHIM
virtual void onCancelButtonClick( wxCloseEvent& event ) = 0;
virtual void onKeyDown( wxKeyEvent& event ) = 0;
virtual void pageChangedHandler( wxAuiNotebookEvent& event ) = 0;
virtual void onGridCellLeftClick( wxGridEvent& event ) = 0;
virtual void onGridCellLeftDClick( wxGridEvent& event ) = 0;
virtual void onGridCellRightClick( wxGridEvent& event ) = 0;
virtual void onGridCmdSelectCell( wxGridEvent& event ) = 0;
virtual void appendRowHandler( wxMouseEvent& event ) = 0;
virtual void deleteRowHandler( wxMouseEvent& event ) = 0;
virtual void moveUpHandler( wxMouseEvent& event ) = 0;
......@@ -75,7 +71,7 @@ class DIALOG_FP_LIB_TABLE_BASE : public DIALOG_SHIM
public:
DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("PCB Library Tables"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 900,600 ), long style = wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER );
DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("PCB Library Tables"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 900,600 ), long style = wxCAPTION|wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU );
~DIALOG_FP_LIB_TABLE_BASE();
};
......
......@@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 CERN
* Copyright (C) 2013 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
......@@ -26,6 +27,7 @@
#include <invoke_pcb_dialog.h>
#include <dialog_fp_plugin_options_base.h>
#include <fp_lib_table.h>
#include <grid_tricks.h>
class DIALOG_FP_PLUGIN_OPTIONS : public DIALOG_FP_PLUGIN_OPTIONS_BASE
......@@ -43,6 +45,19 @@ public:
_( "Options for Library '%s'" ), GetChars( aNickname ) );
SetTitle( title );
m_grid->AutoSizeColumns( false );
// add Cut, Copy, and Paste to wxGrids
m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
// initial focus on the grid please.
m_grid->SetFocus();
}
~DIALOG_FP_PLUGIN_OPTIONS()
{
m_grid->PopEventHandler( true );
}
......
......@@ -22,33 +22,33 @@ DIALOG_FP_PLUGIN_OPTIONS_BASE::DIALOG_FP_PLUGIN_OPTIONS_BASE( wxWindow* parent,
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Plugin Options:") ), wxVERTICAL );
m_grid1 = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_grid = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_grid1->CreateGrid( 5, 2 );
m_grid1->EnableEditing( true );
m_grid1->EnableGridLines( true );
m_grid1->EnableDragGridSize( false );
m_grid1->SetMargins( 0, 0 );
m_grid->CreateGrid( 5, 2 );
m_grid->EnableEditing( true );
m_grid->EnableGridLines( true );
m_grid->EnableDragGridSize( false );
m_grid->SetMargins( 0, 0 );
// Columns
m_grid1->EnableDragColMove( false );
m_grid1->EnableDragColSize( true );
m_grid1->SetColLabelSize( 30 );
m_grid1->SetColLabelValue( 0, _("Option") );
m_grid1->SetColLabelValue( 1, _("Value") );
m_grid1->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
m_grid->EnableDragColMove( false );
m_grid->EnableDragColSize( true );
m_grid->SetColLabelSize( 30 );
m_grid->SetColLabelValue( 0, _("Option") );
m_grid->SetColLabelValue( 1, _("Value") );
m_grid->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
// Rows
m_grid1->EnableDragRowSize( false );
m_grid1->SetRowLabelSize( 80 );
m_grid1->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
m_grid->EnableDragRowSize( false );
m_grid->SetRowLabelSize( 80 );
m_grid->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
// Label Appearance
// Cell Defaults
m_grid1->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
sbSizer1->Add( m_grid1, 1, wxEXPAND, 5 );
m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
sbSizer1->Add( m_grid, 1, wxEXPAND, 5 );
wxBoxSizer* bSizer6;
bSizer6 = new wxBoxSizer( wxHORIZONTAL );
......
......@@ -176,7 +176,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_grid1</property>
<property name="name">m_grid</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
......
......@@ -37,7 +37,7 @@ class DIALOG_FP_PLUGIN_OPTIONS_BASE : public DIALOG_SHIM
private:
protected:
wxGrid* m_grid1;
wxGrid* m_grid;
wxButton* m_add_row;
wxButton* m_delete_row;
wxButton* m_move_up;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment