summaryrefslogtreecommitdiff
path: root/common/grid_tricks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/grid_tricks.cpp')
-rw-r--r--common/grid_tricks.cpp289
1 files changed, 289 insertions, 0 deletions
diff --git a/common/grid_tricks.cpp b/common/grid_tricks.cpp
new file mode 100644
index 0000000..c854411
--- /dev/null
+++ b/common/grid_tricks.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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 )
+{
+ m_sel_row_start = 0;
+ m_sel_col_start = 0;
+ m_sel_row_count = 0;
+ m_sel_col_count = 0;
+
+ 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();
+
+ DBG(printf("topLeft.Count():%d botRight:Count():%d\n", int( topLeft.Count() ), int( 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;
+ }
+
+ //DBG(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( true );
+ }
+}
+
+
+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();
+ }
+ }
+}
+