matrix.h

Go to the documentation of this file.
00001 /*
00002   libwt - Vassilis Virvilis Toolkit - a widget library
00003   Copyright (C) 2006 Vassilis Virvilis <vasvir2@fastmail.fm>
00004  
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009   
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014   
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the
00017   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018   Boston, MA  02111-1307, SA.
00019 */
00020 
00021 #ifndef WT_MATRIX_H
00022 #define WT_MATRIX_H
00023 
00024 #include <vector>
00025 
00026 #include <sigc++/signal.h>
00027 
00028 namespace Wt {
00029 template<typename T>
00030 class Matrix : public std::vector< std::vector<T> > {
00031 public:
00032     typedef std::vector<T> Edge;
00033     typedef std::vector<Edge> MatrixBase;
00034 
00035     typedef T value_type;
00036 
00037     class iterator {
00038     public:
00039         iterator(Matrix* matrix_p = 0, int row = 0, int column = 0) :
00040                 m_(matrix_p),
00041                 row_(row),
00042         column_(column) {
00043             if (matrix_p) {
00044                 if (row_ >= m_->numRows())
00045                     row_ = -1;
00046                 if (column_ >= m_->numCols())
00047                     column_ = -1;
00048             }
00049         }
00050         bool operator==(const iterator& other) const {
00051             return (other.column_ == column_) && (other.row_ == row_);
00052         }
00053         bool operator!=(const iterator& other) const {
00054             return !(*this == other);
00055         }
00056         iterator& operator++() {
00057             const Matrix& matrix = *m_;
00058             if (column_ < matrix.numCols() - 1) {
00059                 ++column_;
00060             } else {
00061                 // end of column
00062                 if (row_ < matrix.numRows() - 1) {
00063                     // advance row
00064                     ++row_;
00065                     column_ = 0;
00066                 } else {
00067                     // end()
00068                     row_ = -1;
00069                     column_ = -1;
00070                 }
00071             }
00072             return *this;
00073         }
00074 
00075         T& operator*() const {
00076             Matrix& matrix = *m_;
00077             T& t = matrix[row_][column_];
00078             return t;
00079         }
00080         T *operator->() const {
00081             Matrix& matrix = *m_;
00082             T* t = &matrix[row_][column_];
00083             return t;
00084         }
00085 
00086         int row() const {
00087             return row_;
00088         }
00089 
00090         int column() const {
00091             return column_;
00092         }
00093 
00094     private:
00095         Matrix *m_;
00096         int row_;
00097         int column_;
00098     };
00099 
00100 class const_iterator : public iterator {
00101     public:
00102         const_iterator(const Matrix* matrix_p = 0,
00103                        int row = 0, int column = 0) :
00104         iterator(const_cast<Matrix*>(matrix_p), row, column) {}
00105 
00106         const_iterator(const iterator& other) :
00107         iterator(other) {}
00108     };
00109 
00110     Matrix() :
00111             rows_(0),
00112     columns_(0) {}
00113 
00114     int numRows() const {
00115         return rows_;
00116     }
00117 
00118     int numCols() const {
00119         return columns_;
00120     }
00121 
00122     bool empty() const {
00123         return !rows_ && !columns_;
00124     }
00125 
00126     iterator begin() {
00127         return iterator(this);
00128     }
00129 
00130     iterator end() {
00131         return iterator(this, -1, -1);
00132     }
00133 
00134     const_iterator begin() const {
00135         return const_iterator(this);
00136     }
00137 
00138     const_iterator end() const {
00139         return const_iterator(this, -1, -1);
00140     }
00141 
00142     T& operator()(int r, int c) {
00143         const int old_rows = rows_;
00144         const int old_cols = columns_;
00145         int i;
00146 
00147         if (r >= old_rows) {
00148             MatrixBase& m = *this;
00149             m.resize(r + 1);
00150             rows_ = r + 1;
00151         }
00152 
00153         const int new_columns = std::max(c + 1, columns_);
00154         for (i = 0; i < rows_; i++) {
00155             (*this)[i].resize(new_columns);
00156         }
00157 
00158         if (c >= columns_) {
00159             columns_ = c + 1;
00160         }
00161 
00162         if (rows_ != old_rows || columns_ != old_cols) {
00163             gridSizeChanged.emit(old_rows, old_cols, rows_, columns_);
00164         }
00165         Matrix& self = *this;
00166         return self[r][c];
00167     }
00168 
00169     void push_back(const T& t) {
00170         Matrix& self = *this;
00171         int r, c;
00172         if (!rows_) {
00173             // start the matrix
00174             r = 0;
00175             c = 0;
00176         } else if (rows_ == 1) {
00177             // in the first line we keep adding columns
00178             r = 0;
00179             c = columns_;
00180         } else {
00181             int j;
00182             // we try to find the first empty item after the last non empty
00183             // if we can't find it before the end of the row we open a new row
00184             for (j = 0; j < columns_ &&
00185                 self[rows_ - 1][columns_ - 1 - j] == T(); j++) {}
00186             if (j == 0) {
00187                 // this row is full, open new row
00188                 r = rows_;
00189                 c = 0;
00190             } else if (j == columns_) {
00191                 // this row is empty, go at at start;
00192                 r = rows_ - 1;
00193                 c = 0;
00194             } else {
00195                 r = rows_ - 1;
00196                 c = columns_ - j;
00197             }
00198         }
00199 
00200         self(r, c) = t;
00201     }
00202 
00203     iterator erase(iterator it) {
00204         *it = T();
00205         adjust();
00206         return ++it;
00207     }
00208 
00209     iterator find(iterator start, iterator finish, const T& t) const {
00210         iterator it = start;
00211         for (; it != finish; ++it) {
00212             if (t == *it)
00213                 break;
00214         }
00215         return (it != finish) ? it : end();
00216     }
00217 
00218     void remove
00219         (const T& t) {
00220         iterator it = begin();
00221         iterator e = end();
00222         while (it != e) {
00223             if (t == *it)
00224                 it = erase(it);
00225             else
00226                 ++it;
00227         }
00228     }
00229 
00230     sigc::signal4<void, int, int, int, int> gridSizeChanged;
00231 
00232 protected:
00233     bool isRowEmpty(int row) {
00234         bool empty = true;
00235 
00236         for (int c = 0; c < columns_; c++) {
00237             Matrix& self = *this;
00238             T empty_item;
00239             if (empty_item != self[row][c]) {
00240                 empty = false;
00241                 break;
00242             }
00243         }
00244         return empty;
00245     }
00246 
00247     bool isColumnEmpty(int column) {
00248         bool empty = true;
00249 
00250         for (int r = 0; r < rows_; r++) {
00251             Matrix& self = *this;
00252             T empty_item;
00253             if (empty_item != self[r][column]) {
00254                 empty = false;
00255                 break;
00256             }
00257         }
00258         return empty;
00259     }
00260 
00261     void adjust() {
00262         const int old_rows = rows_;
00263         const int old_cols = columns_;
00264         int row_max, col_max;
00265 
00266         //first find non empty row starting from end
00267         for (row_max = rows_ - 1; row_max >= 0 &&
00268             isRowEmpty(row_max); row_max--) {}
00269 
00270         //now the max column starting from end
00271         for (col_max = columns_ - 1; col_max >= 0 &&
00272             isColumnEmpty(col_max); col_max--) {}
00273 
00274         if (row_max < rows_ - 1 || col_max < columns_ - 1) {
00275             MatrixBase& m = *this;
00276             m.resize(row_max + 1);
00277             rows_ = row_max + 1;
00278 
00279             if (col_max < columns_ - 1) {
00280                 for (int r = 0; r < rows_; r++) {
00281                     (*this)[r].resize(col_max + 1);
00282                 }
00283             }
00284             columns_ = col_max + 1;
00285         }
00286         if (rows_ != old_rows || columns_ != old_cols) {
00287             gridSizeChanged.emit(old_rows, old_cols, rows_, columns_);
00288         }
00289     }
00290 
00291 private:
00292     int rows_;
00293     int columns_;
00294 };
00295 
00296 } // namespace
00297 
00298 #endif // WT_MATRIX_H

Generated Fri Jul 28 19:23:00 2006.
Copyright © 1998-2003 by the respective authors.

This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.