Commit e0a0f596 authored by Dick Hollenbeck's avatar Dick Hollenbeck

Add keyboard support to DIALOG_FP_LIB_TABLE grid interface:

CTL+X, CTL+V, CTL+A, CTL+C
parent bf26962f
......@@ -26,18 +26,13 @@
/* TODO:
*) Check for duplicate nicknames per table
*) Grab text from any pending ChoiceEditor when OK button pressed.
*) Test wxRE_ADVANCED on Windows.
*) Do environment variable substitution on lookup
*/
#include <fctsys.h>
#include <dialog_fp_lib_table_base.h>
#include <fp_lib_table.h>
......@@ -224,6 +219,12 @@ public:
#define ROW_SEP wxT( '\n' )
inline bool isCtl( int aChar, const wxKeyEvent& e )
{
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
......@@ -235,9 +236,11 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
enum
{
ID_CUT, // = wxID_HIGHEST + 1,
ID_COPY,
ID_PASTE,
MYID_CUT, // = wxID_HIGHEST + 1,
MYID_COPY,
MYID_PASTE,
MYID_SELECT,
MYID_SENTINEL,
};
// row & col "selection" acquisition
......@@ -295,17 +298,18 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
{
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" ) );
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 )
{
menu.Enable( ID_CUT, false );
menu.Enable( ID_COPY, false );
menu.Enable( MYID_CUT, false );
menu.Enable( MYID_COPY, false );
}
bool have_cb_text = false;
......@@ -320,137 +324,151 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
if( !have_cb_text )
{
// if nothing on clipboard, disable paste.
menu.Enable( ID_PASTE, false );
menu.Enable( MYID_PASTE, false );
}
// if there is no current cell cursor, disable paste.
else if( m_cur_row == -1 || m_cur_col == -1 )
menu.Enable( ID_PASTE, false );
menu.Enable( MYID_PASTE, false );
PopupMenu( &menu );
// passOnFocus();
}
// the user clicked on a popup menu choice:
void onPopupSelection( wxCommandEvent& event )
void cutcopy( bool doCut )
{
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 )
// this format is compatible with most spreadsheets
if( wxTheClipboard->Open() )
{
case ID_CUT:
case ID_COPY:
// this format is compatible with most spreadsheets
if( wxTheClipboard->Open() )
{
wxGridTableBase* tbl = m_cur_grid->GetTable();
wxString txt;
wxGridTableBase* tbl = m_cur_grid->GetTable();
wxString txt;
for( int row = selRowStart; row < selRowStart + selRowCount; ++row )
for( int row = selRowStart; row < selRowStart + selRowCount; ++row )
{
for( int col = selColStart; col < selColStart + selColCount; ++col )
{
for( int col = selColStart; col < selColStart + selColCount; ++col )
{
txt += tbl->GetValue( row, col );
txt += tbl->GetValue( row, col );
if( col < selColStart + selColCount - 1 ) // that was not last column
txt += COL_SEP;
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;
if( doCut )
tbl->SetValue( row, col, wxEmptyString );
}
wxTheClipboard->SetData( new wxTextDataObject( txt ) );
wxTheClipboard->Close();
m_cur_grid->ForceRefresh();
txt += ROW_SEP;
}
break;
case ID_PASTE:
D(printf( "paste\n" );)
// 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->SetData( new wxTextDataObject( txt ) );
wxTheClipboard->Close();
m_cur_grid->ForceRefresh();
}
}
wxTheClipboard->GetData( data );
void paste()
{
D(printf( "paste\n" );)
// 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();
wxString cb_text = data.GetText();
size_t ndx = cb_text.find_first_of( wxT( "(fp_lib_table " ) );
wxTheClipboard->GetData( data );
if( ndx != std::string::npos )
{
// paste the ROWs of s-expression (fp_lib_table), starting
// at column 0 regardless of current cursor column.
wxString cb_text = data.GetText();
size_t ndx = cb_text.find( wxT( "(fp_lib_table " ) );
STRING_LINE_READER slr( TO_UTF8( cb_text ), wxT( "Clipboard" ) );
FP_LIB_TABLE_LEXER lexer( &slr );
FP_LIB_TABLE tmp_tbl;
bool parsed = true;
if( ndx != std::string::npos )
{
// paste the ROWs of s-expression (fp_lib_table), starting
// at column 0 regardless of current cursor column.
try
{
tmp_tbl.Parse( &lexer );
}
catch( PARSE_ERROR& pe )
{
// @todo tell what line and offset
parsed = false;
}
STRING_LINE_READER slr( TO_UTF8( cb_text ), wxT( "Clipboard" ) );
FP_LIB_TABLE_LEXER lexer( &slr );
FP_LIB_TABLE tmp_tbl;
bool parsed = true;
if( parsed )
{
// if clipboard rows would extend past end of current table size...
if( int( tmp_tbl.rows.size() ) > tbl->GetNumberRows() - m_cur_row )
{
int newRowsNeeded = tmp_tbl.rows.size() - ( tbl->GetNumberRows() - m_cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int i = 0; i < (int) tmp_tbl.rows.size(); ++i )
{
tbl->rows[m_cur_row+i] = tmp_tbl.rows[i];
}
}
m_cur_grid->AutoSizeColumns();
try
{
tmp_tbl.Parse( &lexer );
}
else
catch( PARSE_ERROR& pe )
{
wxStringTokenizer rows( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
// @todo tell what line and offset
parsed = false;
}
if( parsed )
{
// if clipboard rows would extend past end of current table size...
if( int( rows.CountTokens() ) > tbl->GetNumberRows() - m_cur_row )
if( int( tmp_tbl.rows.size() ) > tbl->GetNumberRows() - m_cur_row )
{
int newRowsNeeded = rows.CountTokens() - ( tbl->GetNumberRows() - m_cur_row );
int newRowsNeeded = tmp_tbl.rows.size() - ( tbl->GetNumberRows() - m_cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int row = m_cur_row; rows.HasMoreTokens(); ++row )
for( int i = 0; i < (int) tmp_tbl.rows.size(); ++i )
{
wxString rowTxt = rows.GetNextToken();
tbl->rows[m_cur_row+i] = tmp_tbl.rows[i];
}
}
m_cur_grid->AutoSizeColumns();
}
else
{
wxStringTokenizer rows( cb_text, ROW_SEP, wxTOKEN_RET_EMPTY );
wxStringTokenizer cols( rowTxt, COL_SEP, wxTOKEN_RET_EMPTY );
// if clipboard rows would extend past end of current table size...
if( int( rows.CountTokens() ) > tbl->GetNumberRows() - m_cur_row )
{
int newRowsNeeded = rows.CountTokens() - ( tbl->GetNumberRows() - m_cur_row );
tbl->AppendRows( newRowsNeeded );
}
for( int col = m_cur_col; cols.HasMoreTokens(); ++col )
{
wxString cellTxt = cols.GetNextToken();
tbl->SetValue( row, col, cellTxt );
}
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();
}
wxTheClipboard->Close();
m_cur_grid->ForceRefresh();
}
}
// 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 MYID_CUT:
case MYID_COPY:
cutcopy( menuId == MYID_CUT );
break;
case MYID_PASTE:
paste();
break;
case MYID_SELECT:
m_cur_grid->SelectAll();
break;
}
}
......@@ -552,6 +570,31 @@ class DIALOG_FP_LIB_TABLE : public DIALOG_FP_LIB_TABLE_BASE
//-----<event handlers>----------------------------------
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
ev.Skip();
}
void pageChangedHandler( wxAuiNotebookEvent& event )
{
int pageNdx = m_auinotebook->GetSelection();
......@@ -822,7 +865,7 @@ public:
m_global_grid->AutoSizeColumns();
m_project_grid->AutoSizeColumns();
Connect( ID_CUT, ID_PASTE, wxEVT_COMMAND_MENU_SELECTED,
Connect( MYID_CUT, MYID_SENTINEL-1, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );
populateEnvironReadOnlyTable();
......@@ -834,11 +877,14 @@ public:
// fire pageChangedHandler() so m_cur_grid gets set
wxAuiNotebookEvent uneventful;
pageChangedHandler( uneventful );
// for ALT+A handling, we want the initial focus to be on the first selected grid.
m_cur_grid->SetFocus();
}
~DIALOG_FP_LIB_TABLE()
{
Disconnect( ID_CUT, ID_PASTE, wxEVT_COMMAND_MENU_SELECTED,
Disconnect( MYID_CUT, MYID_SENTINEL-1, wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler( DIALOG_FP_LIB_TABLE::onPopupSelection ), NULL, this );
// ~wxGrid() examines its table, and the tables will have been destroyed before
......
......@@ -194,16 +194,18 @@ DIALOG_FP_LIB_TABLE_BASE::DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FP_LIB_TABLE_BASE::onInitDialog ) );
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 );
......@@ -216,16 +218,18 @@ DIALOG_FP_LIB_TABLE_BASE::DIALOG_FP_LIB_TABLE_BASE( wxWindow* parent, wxWindowID
DIALOG_FP_LIB_TABLE_BASE::~DIALOG_FP_LIB_TABLE_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_FP_LIB_TABLE_BASE::onInitDialog ) );
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 );
......
......@@ -65,8 +65,8 @@
<event name="OnHibernate"></event>
<event name="OnIconize"></event>
<event name="OnIdle"></event>
<event name="OnInitDialog">onInitDialog</event>
<event name="OnKeyDown"></event>
<event name="OnInitDialog"></event>
<event name="OnKeyDown">onKeyDown</event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
......@@ -396,7 +396,7 @@
<event name="OnGridRangeSelect"></event>
<event name="OnGridRowSize"></event>
<event name="OnGridSelectCell"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyDown">onKeyDown</event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
......@@ -625,7 +625,7 @@
<event name="OnGridRangeSelect"></event>
<event name="OnGridRowSize"></event>
<event name="OnGridSelectCell"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyDown">onKeyDown</event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
......@@ -1105,11 +1105,11 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="1">
<object class="wxStaticBoxSizer" expanded="0">
<property name="id">wxID_ANY</property>
<property name="label">Path Substitutions</property>
<property name="minimum_size"></property>
......@@ -1262,11 +1262,11 @@
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<object class="wxBoxSizer" expanded="0">
<property name="minimum_size"></property>
<property name="name">m_bottom_sizer</property>
<property name="orient">wxVERTICAL</property>
......
......@@ -57,7 +57,7 @@ class DIALOG_FP_LIB_TABLE_BASE : public DIALOG_SHIM
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class
virtual void onInitDialog( wxInitDialogEvent& event ) { event.Skip(); }
virtual void onKeyDown( wxKeyEvent& event ) { event.Skip(); }
virtual void pageChangedHandler( wxAuiNotebookEvent& event ) { event.Skip(); }
virtual void onGridCellLeftClick( wxGridEvent& event ) { event.Skip(); }
virtual void onGridCellLeftDClick( wxGridEvent& event ) { event.Skip(); }
......
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