Main Page   Class Hierarchy   Compound List   File List   Compound Members  

AddressGridTable.cpp

00001 /*
00002  * Purpose: Serializable wxGridTable
00003  * Author:  Frank Buß
00004  * Created: 2002
00005  */
00006 
00007 #include "AddressGridTable.h"
00008 
00009 #include "wx/arrimpl.cpp"
00010 WX_DEFINE_OBJARRAY(StringArray);
00011 WX_DEFINE_OBJARRAY(StringGrid);
00012 
00013 
00014 void wxGridTableBaseWithNotifyMethods::RequestViewGetValues()
00015 {
00016     wxGrid* pView = GetView();
00017     if (pView) {
00018         wxGridTableMessage msg(this, wxGRIDTABLE_REQUEST_VIEW_GET_VALUES);
00019         pView->ProcessTableMessage(msg);
00020     }
00021 }
00022 
00023 void wxGridTableBaseWithNotifyMethods::RequestViewSendValues()
00024 {
00025     wxGrid* pView = GetView();
00026     if (pView) {
00027         wxGridTableMessage msg(this, wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES);
00028         pView->ProcessTableMessage(msg);
00029     }
00030 }
00031 
00032 void wxGridTableBaseWithNotifyMethods::NotifyRowsInserted(int pos, int numRows)
00033 {
00034     wxGrid* pView = GetView();
00035     if (pView) {
00036         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_INSERTED, pos, numRows);
00037         pView->ProcessTableMessage(msg);
00038     }
00039 }
00040 
00041 void wxGridTableBaseWithNotifyMethods::NotifyRowsAppended(int numRows)
00042 {
00043     wxGrid* pView = GetView();
00044     if (pView) {
00045         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, numRows);
00046         pView->ProcessTableMessage(msg);
00047     }
00048 }
00049 
00050 void wxGridTableBaseWithNotifyMethods::NotifyRowsDeleted(int pos, int numRows)
00051 {
00052     wxGrid* pView = GetView();
00053     if (pView) {
00054         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED, pos, numRows);
00055         pView->ProcessTableMessage(msg);
00056     }
00057 }
00058 
00059 void wxGridTableBaseWithNotifyMethods::NotifyColsInserted(int pos, int numCols)
00060 {
00061     wxGrid* pView = GetView();
00062     if (pView) {
00063         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_INSERTED, pos, numCols);
00064         pView->ProcessTableMessage(msg);
00065     }
00066 }
00067 
00068 void wxGridTableBaseWithNotifyMethods::NotifyColsAppended(int numCols)
00069 {
00070     wxGrid* pView = GetView();
00071     if (pView) {
00072         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_APPENDED, numCols);
00073         pView->ProcessTableMessage(msg);
00074     }
00075 }
00076 
00077 void wxGridTableBaseWithNotifyMethods::NotifyColsDeleted(int pos, int numCols)
00078 {
00079     wxGrid* pView = GetView();
00080     if (pView) {
00081         wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_COLS_DELETED, pos, numCols);
00082         pView->ProcessTableMessage(msg);
00083     }
00084 }
00085 
00086 
00088 //
00089 // A basic grid table for string data. An object of this class will
00090 // created by wxGrid if you don't specify an alternative table class.
00091 //
00092 
00093 //WX_DEFINE_OBJARRAY(StringGrid)
00094 
00095 bool isEmpty(StringArray& row, size_t cols)
00096 {
00097     for (size_t j = 0; j < cols; j++) if (row[j].Length()) return false;
00098     return true;
00099 }
00100 
00101 void AddressGridTable::serialize(wxDataOutputStream& out)
00102 {
00103     // get number of cols and rows
00104     size_t cols = GetNumberCols();
00105     size_t rows = GetNumberRows();
00106 
00107     // count number of rows, where at least one cell has text
00108     size_t textRows = 0;
00109     size_t i;
00110     for (i = 0; i < rows; i++) {
00111         if (!isEmpty(m_data[i], cols)) textRows++;
00112     }
00113 
00114     // write number of cols and rows
00115     out.Write32(cols);
00116     out.Write32(textRows);
00117 
00118     // write column info
00119     wxGrid* pView = GetView();
00120     for (i = 0; i < cols; i++) {
00121         out.WriteString(GetColLabelValue(i));
00122         out.Write32(pView->GetColumnWidth(i));
00123     }
00124 
00125     // write all columns, where at least one cell has text
00126     for (i = 0; i < rows; i++) {
00127         if (!isEmpty(m_data[i], cols)) {
00128             for (size_t j = 0; j < cols; j++) out.WriteString(m_data[i][j]);
00129         }
00130     }
00131 }
00132 
00133 int AddressGridTable::GetNumberRows()
00134 {
00135     return m_data.GetCount();
00136 }
00137 
00138 int AddressGridTable::GetNumberCols()
00139 {
00140     return m_colLabels.GetCount();
00141 }
00142 
00143 wxString AddressGridTable::GetValue( int row, int col )
00144 {
00145     wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
00146                   _T("invalid row or column index in AddressGridTable") );
00147 
00148     return m_data[row][col];
00149 }
00150 
00151 void AddressGridTable::SetValue( int row, int col, const wxString& value )
00152 {
00153     wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
00154                   _T("invalid row or column index in AddressGridTable") );
00155 
00156     m_data[row][col] = value;
00157 }
00158 
00159 bool AddressGridTable::IsEmptyCell( int row, int col )
00160 {
00161     wxASSERT_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
00162                   _T("invalid row or column index in AddressGridTable") );
00163 
00164     return (m_data[row][col] == wxEmptyString);
00165 }
00166 
00167 void AddressGridTable::Clear()
00168 {
00169     int row, col;
00170     int numRows, numCols;
00171 
00172     numRows = m_data.GetCount();
00173     if ( numRows > 0 )
00174     {
00175         numCols = m_data[0].GetCount();
00176 
00177         for ( row = 0;  row < numRows;  row++ )
00178         {
00179             for ( col = 0;  col < numCols;  col++ )
00180             {
00181                 m_data[row][col] = wxEmptyString;
00182             }
00183         }
00184     }
00185 }
00186 
00187 
00188 bool AddressGridTable::InsertRows( size_t pos, size_t numRows )
00189 {
00190     size_t row, col;
00191 
00192     size_t curNumRows = m_data.GetCount();
00193     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
00194                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
00195 
00196     if ( pos >= curNumRows )
00197     {
00198         return AppendRows( numRows );
00199     }
00200 
00201     StringArray sa;
00202     sa.Alloc( curNumCols );
00203     for ( col = 0;  col < curNumCols;  col++ )
00204     {
00205         sa.Add( wxEmptyString );
00206     }
00207 
00208     for ( row = pos;  row < pos + numRows;  row++ )
00209     {
00210         m_data.Insert( sa, row );
00211     }
00212     NotifyRowsInserted(pos, numRows);
00213 
00214     return TRUE;
00215 }
00216 
00217 bool AddressGridTable::AppendRows( size_t numRows )
00218 {
00219     size_t row, col;
00220 
00221     size_t curNumRows = m_data.GetCount();
00222     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
00223                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
00224 
00225     StringArray sa;
00226     if ( curNumCols > 0 )
00227     {
00228         sa.Alloc( curNumCols );
00229         for ( col = 0;  col < curNumCols;  col++ )
00230         {
00231             sa.Add( wxEmptyString );
00232         }
00233     }
00234 
00235     for ( row = 0;  row < numRows;  row++ )
00236     {
00237         m_data.Add( sa );
00238     }
00239     NotifyRowsAppended(numRows);
00240 
00241     return TRUE;
00242 }
00243 
00244 bool AddressGridTable::DeleteRows( size_t pos, size_t numRows )
00245 {
00246     size_t n;
00247 
00248     size_t curNumRows = m_data.GetCount();
00249 
00250     if ( pos >= curNumRows )
00251     {
00252         wxString errmsg;
00253         errmsg.Printf(wxT("Called AddressGridTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"),
00254                       pos, numRows, curNumRows );
00255         wxFAIL_MSG( errmsg );
00256         return FALSE;
00257     }
00258 
00259     if ( numRows > curNumRows - pos )
00260     {
00261         numRows = curNumRows - pos;
00262     }
00263 
00264     if ( numRows >= curNumRows )
00265     {
00266         m_data.Empty();  // don't release memory just yet
00267     }
00268     else
00269     {
00270         for ( n = 0;  n < numRows;  n++ )
00271         {
00272             m_data.RemoveAt( pos );
00273         }
00274     }
00275     NotifyRowsDeleted(pos, numRows);
00276 
00277     return TRUE;
00278 }
00279 
00280 bool AddressGridTable::InsertCols( size_t pos, size_t numCols )
00281 {
00282     size_t row, col;
00283 
00284     size_t curNumRows = m_data.GetCount();
00285     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
00286                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
00287 
00288     if ( pos >= curNumCols )
00289     {
00290         return AppendCols( numCols );
00291     }
00292 
00293     for ( row = 0;  row < curNumRows;  row++ )
00294     {
00295         for ( col = pos;  col < pos + numCols;  col++ )
00296         {
00297             m_data[row].Insert( wxEmptyString, col );
00298         }
00299     }
00300     NotifyColsInserted(pos, numCols);
00301 
00302     return TRUE;
00303 }
00304 
00305 bool AddressGridTable::AppendCols( size_t numCols )
00306 {
00307     size_t row, n;
00308 
00309     size_t curNumRows = m_data.GetCount();
00310 
00311     for ( row = 0;  row < curNumRows;  row++ )
00312     {
00313         for ( n = 0;  n < numCols;  n++ )
00314         {
00315             m_data[row].Add( wxEmptyString );
00316         }
00317     }
00318     NotifyColsAppended(numCols);
00319 
00320     return TRUE;
00321 }
00322 
00323 bool AddressGridTable::DeleteCols( size_t pos, size_t numCols )
00324 {
00325     size_t row, n;
00326 
00327     size_t curNumRows = m_data.GetCount();
00328     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
00329                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
00330 
00331     if ( pos >= curNumCols )
00332     {
00333         wxString errmsg;
00334         errmsg.Printf( wxT("Called AddressGridTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"),
00335                         pos, numCols, curNumCols );
00336         wxFAIL_MSG( errmsg );
00337         return FALSE;
00338     }
00339 
00340     if ( numCols > curNumCols - pos )
00341     {
00342         numCols = curNumCols - pos;
00343     }
00344 
00345     for ( row = 0;  row < curNumRows;  row++ )
00346     {
00347         if ( numCols >= curNumCols )
00348         {
00349             m_data[row].Clear();
00350         }
00351         else
00352         {
00353             for ( n = 0;  n < numCols;  n++ )
00354             {
00355                 m_data[row].RemoveAt( pos );
00356             }
00357         }
00358     }
00359     NotifyColsDeleted(pos, numCols);
00360 
00361     return TRUE;
00362 }
00363 
00364 wxString AddressGridTable::GetColLabelValue( int col )
00365 {
00366     if ( col > (int)(m_colLabels.GetCount()) - 1 )
00367     {
00368         // using default label
00369         //
00370         return wxGridTableBase::GetColLabelValue( col );
00371     }
00372     else
00373     {
00374         return m_colLabels[ col ];
00375     }
00376 }
00377 
00378 void AddressGridTable::SetColLabelValue( int col, const wxString& value )
00379 {
00380     if ( col > (int)(m_colLabels.GetCount()) - 1 )
00381     {
00382         int n = m_colLabels.GetCount();
00383         int i;
00384         for ( i = n;  i <= col;  i++ )
00385         {
00386             m_colLabels.Add( wxGridTableBase::GetColLabelValue(i) );
00387         }
00388     }
00389 
00390     m_colLabels[col] = value;
00391 }
00392 
00393 void AddressGridTable::ClearAll()
00394 {
00395     int rows = m_data.GetCount();
00396     m_data = StringGrid();
00397     NotifyRowsDeleted(0, rows);
00398 
00399     int cols = m_colLabels.GetCount();
00400     m_colLabels = StringArray();
00401     NotifyColsDeleted(0, cols);
00402 }
00403 
00404 void AddressGridTable::Initialize()
00405 {
00406     ClearAll();
00407     m_colLabels.Add("eMail");
00408     m_colLabels.Add("Handy");
00409     m_colLabels.Add("SMS-Export");
00410     m_colLabels.Add("Fax");
00411     StringArray empty;
00412     empty.Add(wxEmptyString);
00413     empty.Add(wxEmptyString);
00414     empty.Add(wxEmptyString);
00415     empty.Add(wxEmptyString);
00416     m_data.Add(empty);
00417     NotifyColsAppended(4);
00418     NotifyRowsAppended(1);
00419 }
00420 
00421 
00422 void AddressGridTable::Initialize(wxDataInputStream& in)
00423 {
00424     ClearAll();
00425 
00426     // read number of cols and rows
00427     size_t cols = in.Read32();
00428     size_t rows = in.Read32();
00429 
00430     // add columns for setting the column labels
00431     NotifyColsAppended(cols);
00432 
00433     // read column labels and widths
00434     size_t i;
00435     wxGrid* pView = GetView();
00436     for (i = 0; i < cols; i++) {
00437         m_colLabels.Add(in.ReadString());
00438         pView->SetColumnWidth(i, in.Read32());
00439     }
00440 
00441     // read rows
00442     m_data.Alloc(rows + 1);
00443     for (i = 0; i < rows; i++) {
00444         StringArray row;
00445         row.Alloc(cols);
00446         for (size_t j = 0; j < cols; j++) {
00447             row.Add(in.ReadString());
00448         }
00449         m_data.Add(row);
00450     }
00451 
00452     // add empty row
00453     StringArray empty;
00454     empty.Alloc(cols);
00455     for (i = 0; i < cols; i++) empty.Add(wxEmptyString);
00456     m_data.Add(empty);
00457 
00458     // tell the view how many rows were added
00459     NotifyRowsAppended(rows + 1);
00460 }
00461 
00462 
00463 int gSortCol1;
00464 int gSortCol2;
00465 int gSortCol3;
00466 StringGrid* gSortGrid;
00467 wxUint32* gSortArray;
00468 
00469 int compare(const void *arg1, const void *arg2)
00470 {
00471     wxUint32 index1 = *((wxUint32*)arg1);
00472     wxUint32 index2 = *((wxUint32*)arg2);
00473     wxString& value1 = (*gSortGrid)[index1][gSortCol1];
00474     wxString& value2 = (*gSortGrid)[index2][gSortCol1];
00475     if (value1.Length() == 0) return 1;
00476     if (value2.Length() == 0) return -1;
00477     int cmp = value1.CmpNoCase(value2);
00478     if (cmp != 0) return cmp;
00479     if (gSortCol2 < 0) return cmp;
00480     wxString& value3 = (*gSortGrid)[index1][gSortCol2];
00481     wxString& value4 = (*gSortGrid)[index2][gSortCol2];
00482     if (value3.Length() == 0) return 1;
00483     if (value4.Length() == 0) return -1;
00484     cmp = value3.CmpNoCase(value4);
00485     if (cmp != 0) return cmp;
00486     if (gSortCol3 < 0) return cmp;
00487     wxString& value5 = (*gSortGrid)[index1][gSortCol3];
00488     wxString& value6 = (*gSortGrid)[index2][gSortCol3];
00489     if (value5.Length() == 0) return 1;
00490     if (value6.Length() == 0) return -1;
00491     return value5.CmpNoCase(value6);
00492 }
00493 
00494 void AddressGridTable::Sort(int col1, int col2, int col3)
00495 {
00496     gSortCol1 = col1;
00497     gSortCol2 = col2;
00498     gSortCol3 = col3;
00499 
00500     // create index array for sorting
00501     unsigned rowCount = GetNumberRows();
00502     gSortArray = new wxUint32[rowCount];
00503     size_t i;
00504     for (i = 0; i < rowCount; i++) gSortArray[i] = i;
00505 
00506     // sort array
00507     gSortGrid = &m_data;
00508     qsort((void *)gSortArray, rowCount, sizeof(wxUint32), compare);
00509 
00510     // copy in new grid
00511     unsigned colCount = GetNumberCols();
00512     unsigned newCount = 0;
00513     StringGrid newGrid = StringGrid();
00514     newGrid.Alloc(rowCount);
00515     for (i = 0; i < rowCount; i++)
00516     {
00517         unsigned len = 0;
00518         for (unsigned j = 0; j < colCount; j++) {
00519             wxString& value = m_data[gSortArray[i]][j];
00520             len += value.Length();
00521         }
00522         if (len > 0) {
00523             newGrid.Add(m_data[gSortArray[i]]);
00524             newCount++;
00525         }
00526     }
00527     delete [] gSortArray;
00528 
00529     // set new grid
00530     m_data = newGrid;
00531 
00532     // update view
00533     NotifyRowsDeleted(0, rowCount);
00534     NotifyRowsAppended(newCount);
00535 }
00536 
00537 
00538 void AddressGridTable::ChangeColumns(ColumnFieldArray& columns)
00539 {
00540     // get number of cols and rows
00541     size_t cols = columns.GetCount();
00542     size_t rows = GetNumberRows();
00543 
00544     // create new empty data grid
00545     StringGrid newGrid = StringGrid();
00546     StringArray newColLabels;
00547     newGrid.Alloc(rows);
00548     StringArray empty;
00549     empty.Alloc(cols);
00550     size_t i;
00551     for (i = 0; i < cols; i++) empty.Add(wxEmptyString);
00552     for (i = 0; i < rows; i++) newGrid.Add(empty);
00553 
00554     // fill with old values
00555     for (i = 0; i < cols; i++)
00556     {
00557         // create new column
00558         int oldIndex = columns[i].getOldIndex();
00559         newColLabels.Add(columns[i].getName());
00560 
00561         // copy old values, if it is not a new column
00562         if (!columns[i].isNew()) {
00563             for (size_t j = 0; j < rows; j++) {
00564                 newGrid[j][i] = m_data[j][oldIndex];
00565             }
00566         }
00567     }
00568 
00569     // set new grid
00570     ClearAll();
00571     m_data = newGrid;
00572     m_colLabels = newColLabels;
00573 
00574     // update view
00575     NotifyColsAppended(cols);
00576     NotifyRowsAppended(rows);
00577 
00578     // restore old column widths
00579     wxGrid* pView = GetView();
00580     for (i = 0; i < cols; i++)
00581     {
00582         if (!columns[i].isNew()) {
00583             pView->SetColumnWidth(i, columns[i].getOldWidth());
00584         }
00585     }
00586 }
00587 

Generated on Thu May 2 15:13:51 2002 for Wino by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001