| #pragma once |
| |
| #ifndef TCOLUMNSET_INCLUDED |
| #define TCOLUMNSET_INCLUDED |
| |
| #include "tsmartpointer.h" |
| |
| #undef DVAPI |
| #undef DVVAR |
| #ifdef TXSHEET_EXPORTS |
| #define DVAPI DV_EXPORT_API |
| #define DVVAR DV_EXPORT_VAR |
| #else |
| #define DVAPI DV_IMPORT_API |
| #define DVVAR DV_IMPORT_VAR |
| #endif |
| |
| |
| |
| class DVAPI TColumnHeader : public TSmartObject { |
| DECLARE_CLASS_CODE |
| |
| int m_index; |
| int m_pos; |
| int m_width; |
| |
| bool m_inColumnsSet; |
| |
| |
| public: |
| TColumnHeader(); |
| virtual ~TColumnHeader() {} |
| |
| int getIndex() const { return m_index; } |
| int getPos() const { return m_pos; } |
| int getX0() const { return m_pos; } |
| int getX1() const { return m_pos + m_width - 1; } |
| |
| void getCoords(int &x0, int &x1) const { |
| x0 = m_pos; |
| x1 = m_pos + m_width - 1; |
| } |
| |
| int getWidth() const { return m_width; } |
| |
| bool inColumnsSet() const { return m_inColumnsSet; } |
| |
| private: |
| template <class T> |
| friend class TColumnSetT; |
| }; |
| |
| |
| |
| #ifdef _WIN32 |
| template class DVAPI TSmartPointerT<TColumnHeader>; |
| #endif |
| |
| typedef TSmartPointerT<TColumnHeader> TColumnHeaderP; |
| |
| |
| |
| template <class T> |
| class TColumnSetT { |
| typedef TSmartPointerT<T> ColumnP; |
| |
| std::vector<ColumnP> m_columns; |
| int m_defaultWidth; |
| |
| static bool compareColumnPos(const int pos, const ColumnP &ch2) { |
| return pos <= ch2->getX1(); |
| } |
| |
| public: |
| TColumnSetT(int defaultWidth = 100) : m_defaultWidth(defaultWidth) {} |
| ~TColumnSetT() {} |
| |
| int getColumnCount() const { return m_columns.size(); } |
| |
| void clear() { m_columns.clear(); } |
| |
| |
| |
| void col2pos(int index, int &x0, int &x1) const { |
| assert(index >= 0); |
| int columnCount = (int)m_columns.size(); |
| if (index < columnCount) |
| m_columns[index]->getCoords(x0, x1); |
| else { |
| x0 = (columnCount > 0 ? m_columns.back()->getX1() + 1 : 0) + |
| (index - columnCount) * m_defaultWidth; |
| x1 = x0 + m_defaultWidth - 1; |
| } |
| } |
| |
| |
| |
| |
| int pos2col(int pos) const { |
| |
| int endPos = m_columns.empty() ? 0 : m_columns.back()->getX1() + 1; |
| if (pos >= endPos) |
| return m_columns.size() + (pos - endPos) / m_defaultWidth; |
| |
| typename std::vector<ColumnP>::const_iterator loc; |
| loc = std::upper_bound(m_columns.begin(), m_columns.end(), pos, |
| compareColumnPos); |
| return std::distance(m_columns.begin(), loc); |
| } |
| |
| |
| |
| const ColumnP &getColumn(int index) const { |
| static const ColumnP empty; |
| |
| if (index >= 0 && index < (int)m_columns.size()) return m_columns[index]; |
| |
| return empty; |
| } |
| |
| |
| |
| const ColumnP &touchColumn(int index, int type = 0) { |
| assert(index >= 0); |
| |
| const int count = m_columns.size(); |
| if (index < count) return m_columns[index]; |
| |
| for (int i = count; i <= index; ++i) { |
| int cType = (i != index) ? 0 : type; |
| ColumnP col = T::createEmpty(cType); |
| |
| m_columns.push_back(col); |
| } |
| |
| update(count); |
| |
| assert(index == (int)m_columns.size() - 1); |
| return m_columns[index]; |
| } |
| |
| |
| |
| const ColumnP &insertColumn(int index, const ColumnP &column) { |
| |
| assert(column && !column->m_inColumnsSet); |
| |
| if (index > 0) touchColumn(index - 1); |
| |
| m_columns.insert(m_columns.begin() + index, column); |
| update(index); |
| |
| return column; |
| } |
| |
| |
| |
| const ColumnP removeColumn(int index) { |
| assert(index >= 0); |
| |
| int columnCount = m_columns.size(); |
| if (index >= columnCount) |
| return ColumnP(); |
| |
| ColumnP column = m_columns[index]; |
| |
| |
| column->m_inColumnsSet = false; |
| |
| m_columns.erase(m_columns.begin() + index); |
| update(index); |
| |
| return column; |
| } |
| |
| |
| |
| void rollLeft(int index, int count) { |
| assert(index >= 0); |
| assert(count > 1); |
| |
| int columnCount = m_columns.size(); |
| if (index + count > columnCount) count = columnCount - index; |
| |
| if (count < 2) return; |
| |
| assert(0 <= index && index + count - 1 < columnCount); |
| assert(count > 0); |
| |
| int i = index, j = index + count - 1; |
| ColumnP tmp = m_columns[i]; |
| |
| for (int k = i; k < j; ++k) m_columns[k] = m_columns[k + 1]; |
| m_columns[j] = tmp; |
| |
| update(0); |
| } |
| |
| |
| |
| void rollRight(int index, int count) { |
| assert(index >= 0); |
| assert(count > 1); |
| |
| int columnCount = m_columns.size(); |
| if (index + count > columnCount) count = columnCount - index; |
| |
| if (count < 2) return; |
| |
| assert(0 <= index && index + count - 1 < columnCount); |
| assert(count > 0); |
| |
| int i = index, j = index + count - 1; |
| ColumnP tmp = m_columns[j]; |
| |
| for (int k = j; k > i; --k) m_columns[k] = m_columns[k - 1]; |
| m_columns[i] = tmp; |
| |
| update(0); |
| } |
| |
| |
| |
| void update(int fromIdx) { |
| int pos = 0, index = 0; |
| if (fromIdx > 0) { |
| assert(fromIdx <= (int)m_columns.size()); |
| |
| const ColumnP &left = m_columns[fromIdx - 1]; |
| |
| pos = left->getX1() + 1; |
| index = left->m_index + 1; |
| } |
| |
| int c, cCount = m_columns.size(); |
| for (c = fromIdx; c != cCount; ++c) { |
| const ColumnP &col = m_columns[c]; |
| |
| col->m_pos = pos; |
| col->m_index = index++; |
| pos += col->m_width; |
| |
| col->m_inColumnsSet = true; |
| } |
| } |
| |
| private: |
| |
| TColumnSetT(const TColumnSetT &); |
| TColumnSetT &operator=(const TColumnSetT &); |
| }; |
| |
| #endif |