tahoma2d/toonz/sources/include/tcolumnset.h

254 lines
6.5 KiB
C
Raw Normal View History

2016-05-17 03:04:11 +12:00
#pragma once
2016-03-19 06:57:51 +13:00
#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
//=============================================================================
2016-06-15 18:43:10 +12:00
class DVAPI TColumnHeader : public TSmartObject {
DECLARE_CLASS_CODE
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int m_index; //!< The header's index in a columns set
int m_pos; //!< The header's screen X pos in a columns viewer
int m_width; //!< The header's width in a columns viewer
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool m_inColumnsSet; //!< (TO BE REMOVED ASAP) Whether the header
//!< belongs to a columns set. Should be
//!< redirected to a negative m_index.
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
TColumnHeader();
virtual ~TColumnHeader() {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
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; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void getCoords(int &x0, int &x1) const {
x0 = m_pos;
x1 = m_pos + m_width - 1;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int getWidth() const { return m_width; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool inColumnsSet() const { return m_inColumnsSet; }
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
template <class T>
friend class TColumnSetT;
2016-03-19 06:57:51 +13:00
};
//---------------------------------------------------------
2016-04-15 17:11:23 +12:00
#ifdef _WIN32
2016-03-19 06:57:51 +13:00
template class DVAPI TSmartPointerT<TColumnHeader>;
#endif
typedef TSmartPointerT<TColumnHeader> TColumnHeaderP;
//=============================================================================
template <class T>
2016-06-15 18:43:10 +12:00
class TColumnSetT {
typedef TSmartPointerT<T> ColumnP;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
std::vector<ColumnP> m_columns;
int m_defaultWidth;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
static bool compareColumnPos(const int pos, const ColumnP &ch2) {
return pos <= ch2->getX1();
}
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
TColumnSetT(int defaultWidth = 100) : m_defaultWidth(defaultWidth) {}
~TColumnSetT() {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int getColumnCount() const { return m_columns.size(); }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void clear() { m_columns.clear(); }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
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;
}
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
// versione con upper_bound
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int pos2col(int pos) const {
// n.b. endPos e' la coordinata del primo pixel non occupato da colonne
int endPos = m_columns.empty() ? 0 : m_columns.back()->getX1() + 1;
if (pos >= endPos)
return m_columns.size() + (pos - endPos) / m_defaultWidth;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
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);
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const ColumnP &getColumn(int index) const {
static const ColumnP empty;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (index >= 0 && index < (int)m_columns.size()) return m_columns[index];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return empty;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const ColumnP &touchColumn(int index, int type = 0) {
assert(index >= 0);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const int count = m_columns.size();
if (index < count) return m_columns[index];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
for (int i = count; i <= index; ++i) {
int cType = (i != index) ? 0 : type;
ColumnP col = T::createEmpty(cType);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_columns.push_back(col);
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
update(count);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
assert(index == (int)m_columns.size() - 1);
return m_columns[index];
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const ColumnP &insertColumn(int index, const ColumnP &column) {
// assert(column && column->m_index < 0);
assert(column && !column->m_inColumnsSet);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (index > 0) touchColumn(index - 1);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_columns.insert(m_columns.begin() + index, column);
update(index);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return column;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const ColumnP removeColumn(int index) {
assert(index >= 0);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int columnCount = m_columns.size();
if (index >= columnCount) // Shouldn't be asserted instead ?
return ColumnP();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
ColumnP column = m_columns[index];
// column->m_index = -1; // We should enforce
// this. Unfortunately, must be tested extensively.
column->m_inColumnsSet = false;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
m_columns.erase(m_columns.begin() + index);
update(index);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
return column;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void rollLeft(int index, int count) {
assert(index >= 0);
assert(count > 1);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int columnCount = m_columns.size();
if (index + count > columnCount) count = columnCount - index;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (count < 2) return;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
assert(0 <= index && index + count - 1 < columnCount);
assert(count > 0);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int i = index, j = index + count - 1;
ColumnP tmp = m_columns[i];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
for (int k = i; k < j; ++k) m_columns[k] = m_columns[k + 1];
m_columns[j] = tmp;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
update(0);
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void rollRight(int index, int count) {
assert(index >= 0);
assert(count > 1);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int columnCount = m_columns.size();
if (index + count > columnCount) count = columnCount - index;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
if (count < 2) return;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
assert(0 <= index && index + count - 1 < columnCount);
assert(count > 0);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int i = index, j = index + count - 1;
ColumnP tmp = m_columns[j];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
for (int k = j; k > i; --k) m_columns[k] = m_columns[k - 1];
m_columns[i] = tmp;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
update(0);
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
//---------------------------------------------------------
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void update(int fromIdx) {
int pos = 0, index = 0;
if (fromIdx > 0) {
assert(fromIdx <= (int)m_columns.size());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const ColumnP &left = m_columns[fromIdx - 1];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
pos = left->getX1() + 1;
index = left->m_index + 1;
}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int c, cCount = m_columns.size();
for (c = fromIdx; c != cCount; ++c) {
const ColumnP &col = m_columns[c];
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
col->m_pos = pos;
col->m_index = index++;
pos += col->m_width;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
col->m_inColumnsSet = true;
}
}
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
// Not copyable
TColumnSetT(const TColumnSetT &);
TColumnSetT &operator=(const TColumnSetT &);
2016-03-19 06:57:51 +13:00
};
2016-06-15 18:43:10 +12:00
#endif // TCOLUMNSET_INCLUDED