2015-12-15 21:53:15 +00:00
|
|
|
#include "Specter/Table.hpp"
|
2015-12-23 00:25:46 +00:00
|
|
|
#include "Specter/ViewResources.hpp"
|
2015-12-29 02:02:43 +00:00
|
|
|
#include "Specter/RootView.hpp"
|
2015-12-15 21:53:15 +00:00
|
|
|
|
|
|
|
namespace Specter
|
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
static LogVisor::LogModule Log("Specter::Table");
|
2015-12-29 02:02:43 +00:00
|
|
|
#define ROW_HEIGHT 18
|
2015-12-30 02:20:24 +00:00
|
|
|
#define CELL_MARGIN 1
|
2015-12-15 21:53:15 +00:00
|
|
|
|
2015-12-31 20:26:04 +00:00
|
|
|
Table::Table(ViewResources& res, View& parentView, ITableDataBinding* data, ITableStateBinding* state, size_t maxColumns)
|
2016-01-01 00:12:19 +00:00
|
|
|
: View(res, parentView), m_data(data), m_state(state), m_maxColumns(maxColumns),
|
|
|
|
m_hVerts(new SolidShaderVert[maxColumns * 6]), m_rowsView(*this, res)
|
2015-12-29 22:58:09 +00:00
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
if (!maxColumns)
|
|
|
|
Log.report(LogVisor::FatalError, "0-column tables not supported");
|
|
|
|
|
|
|
|
m_hVertsBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SolidShaderVert), maxColumns * 6);
|
|
|
|
|
|
|
|
if (!res.m_viewRes.m_texVtxFmt)
|
|
|
|
{
|
|
|
|
boo::VertexElementDescriptor vdescs[] =
|
|
|
|
{
|
|
|
|
{m_hVertsBuf, nullptr, boo::VertexSemantic::Position4},
|
|
|
|
{m_hVertsBuf, nullptr, boo::VertexSemantic::Color}
|
|
|
|
};
|
|
|
|
m_hVtxFmt = res.m_factory->newVertexFormat(2, vdescs);
|
|
|
|
boo::IGraphicsBuffer* bufs[] = {m_viewVertBlockBuf};
|
|
|
|
m_hShaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
|
|
|
m_hVtxFmt, m_hVertsBuf, nullptr,
|
|
|
|
nullptr, 1, bufs, 0, nullptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
boo::IGraphicsBuffer* bufs[] = {m_viewVertBlockBuf};
|
|
|
|
m_hShaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
|
|
|
res.m_viewRes.m_texVtxFmt,
|
|
|
|
m_hVertsBuf, nullptr,
|
|
|
|
nullptr, 1, bufs, 0, nullptr);
|
|
|
|
}
|
2015-12-29 22:58:09 +00:00
|
|
|
commitResources(res);
|
|
|
|
|
2015-12-30 02:20:24 +00:00
|
|
|
m_scroll.m_view.reset(new ScrollView(res, *this, ScrollView::Style::ThinIndicator));
|
2015-12-29 22:58:09 +00:00
|
|
|
m_scroll.m_view->setContentView(&m_rowsView);
|
|
|
|
updateData();
|
|
|
|
}
|
|
|
|
|
|
|
|
Table::RowsView::RowsView(Table& t, ViewResources& res)
|
2015-12-31 20:26:04 +00:00
|
|
|
: View(res, t), m_t(t), m_verts(new SolidShaderVert[SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6])
|
2015-12-15 21:53:15 +00:00
|
|
|
{
|
2015-12-23 00:25:46 +00:00
|
|
|
m_vertsBuf = res.m_factory->newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SolidShaderVert),
|
2015-12-31 20:26:04 +00:00
|
|
|
SPECTER_TABLE_MAX_ROWS * t.m_maxColumns * 6);
|
2015-12-23 00:25:46 +00:00
|
|
|
|
|
|
|
if (!res.m_viewRes.m_texVtxFmt)
|
|
|
|
{
|
|
|
|
boo::VertexElementDescriptor vdescs[] =
|
|
|
|
{
|
|
|
|
{m_vertsBuf, nullptr, boo::VertexSemantic::Position4},
|
|
|
|
{m_vertsBuf, nullptr, boo::VertexSemantic::Color}
|
|
|
|
};
|
|
|
|
m_vtxFmt = res.m_factory->newVertexFormat(2, vdescs);
|
|
|
|
boo::IGraphicsBuffer* bufs[] = {m_viewVertBlockBuf};
|
|
|
|
m_shaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
|
|
|
m_vtxFmt, m_vertsBuf, nullptr,
|
|
|
|
nullptr, 1, bufs, 0, nullptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
boo::IGraphicsBuffer* bufs[] = {m_viewVertBlockBuf};
|
|
|
|
m_shaderBinding = res.m_factory->newShaderDataBinding(res.m_viewRes.m_solidShader,
|
|
|
|
res.m_viewRes.m_texVtxFmt,
|
|
|
|
m_vertsBuf, nullptr,
|
|
|
|
nullptr, 1, bufs, 0, nullptr);
|
|
|
|
}
|
2015-12-22 01:33:27 +00:00
|
|
|
commitResources(res);
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
|
2016-01-01 00:12:19 +00:00
|
|
|
Table::CellView::CellView(Table& t, ViewResources& res, size_t c, size_t r)
|
|
|
|
: View(res, t), m_t(t), m_text(new TextView(res, *this, res.m_mainFont)), m_c(c), m_r(r) {}
|
|
|
|
|
|
|
|
void Table::_setHeaderVerts(const boo::SWindowRect& sub)
|
|
|
|
{;
|
|
|
|
if (m_headerViews.empty())
|
|
|
|
return;
|
|
|
|
SolidShaderVert* v = m_hVerts.get();
|
|
|
|
const ThemeData& theme = rootView().themeData();
|
|
|
|
|
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
|
|
|
int div = sub.size[0] / m_headerViews.size();
|
|
|
|
int margin = CELL_MARGIN * pf;
|
|
|
|
int rowHeight = ROW_HEIGHT * pf;
|
|
|
|
int xOff = 0;
|
|
|
|
int yOff = sub.size[1];
|
|
|
|
size_t c;
|
|
|
|
auto it = m_headerViews.cbegin();
|
|
|
|
|
|
|
|
size_t sCol = -1;
|
|
|
|
SortDirection sDir = SortDirection::None;
|
|
|
|
if (m_state)
|
|
|
|
sDir = m_state->getSort(sCol);
|
|
|
|
|
|
|
|
for (c=0 ; c<std::min(m_maxColumns, m_columns) ; ++c)
|
|
|
|
{
|
|
|
|
const ViewChild<std::unique_ptr<CellView>>& hv = *it;
|
|
|
|
const Zeus::CColor* c1 = &theme.button1Inactive();
|
|
|
|
const Zeus::CColor* c2 = &theme.button2Inactive();
|
|
|
|
if (hv.m_mouseDown && hv.m_mouseIn)
|
|
|
|
{
|
|
|
|
c1 = &theme.button1Press();
|
|
|
|
c2 = &theme.button2Press();
|
|
|
|
}
|
|
|
|
else if (hv.m_mouseIn)
|
|
|
|
{
|
|
|
|
c1 = &theme.button1Hover();
|
|
|
|
c2 = &theme.button2Hover();
|
|
|
|
}
|
|
|
|
|
|
|
|
Zeus::CColor cm1 = *c1;
|
|
|
|
Zeus::CColor cm2 = *c2;
|
|
|
|
if (sCol == c)
|
|
|
|
{
|
|
|
|
if (sDir == SortDirection::Ascending)
|
|
|
|
{
|
|
|
|
cm1 *= Zeus::CColor::skGreen;
|
|
|
|
cm2 *= Zeus::CColor::skGreen;
|
|
|
|
}
|
|
|
|
else if (sDir == SortDirection::Descending)
|
|
|
|
{
|
|
|
|
cm1 *= Zeus::CColor::skRed;
|
|
|
|
cm2 *= Zeus::CColor::skRed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v[0].m_pos.assign(xOff + margin, yOff - margin, 0);
|
|
|
|
v[0].m_color = cm1;
|
|
|
|
v[1] = v[0];
|
|
|
|
v[2].m_pos.assign(xOff + margin, yOff - margin - rowHeight, 0);
|
|
|
|
v[2].m_color = cm2;
|
|
|
|
v[3].m_pos.assign(xOff + div - margin, yOff - margin, 0);
|
|
|
|
v[3].m_color = cm1;
|
|
|
|
v[4].m_pos.assign(xOff + div - margin, yOff - margin - rowHeight, 0);
|
|
|
|
v[4].m_color = cm2;
|
|
|
|
v[5] = v[4];
|
|
|
|
v += 6;
|
|
|
|
xOff += div;
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
m_hVertsBuf->load(m_hVerts.get(), sizeof(SolidShaderVert) * 6 * c);
|
|
|
|
|
|
|
|
m_headerNeedsUpdate = false;
|
|
|
|
}
|
2015-12-29 02:02:43 +00:00
|
|
|
|
2015-12-29 22:58:09 +00:00
|
|
|
void Table::RowsView::_setRowVerts(const boo::SWindowRect& sub, const boo::SWindowRect& scissor)
|
2015-12-29 02:02:43 +00:00
|
|
|
{
|
2015-12-31 20:26:04 +00:00
|
|
|
SolidShaderVert* v = m_verts.get();
|
2015-12-29 02:02:43 +00:00
|
|
|
const ThemeData& theme = rootView().themeData();
|
2015-12-29 22:58:09 +00:00
|
|
|
|
|
|
|
if (m_t.m_cellViews.empty())
|
|
|
|
return;
|
|
|
|
|
2015-12-29 02:02:43 +00:00
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
2015-12-29 22:58:09 +00:00
|
|
|
int div = sub.size[0] / m_t.m_cellViews.size();
|
2015-12-30 02:20:24 +00:00
|
|
|
int spacing = (ROW_HEIGHT + CELL_MARGIN * 2) * pf;
|
|
|
|
int margin = CELL_MARGIN * pf;
|
2015-12-29 02:02:43 +00:00
|
|
|
int rowHeight = ROW_HEIGHT * pf;
|
2015-12-29 22:58:09 +00:00
|
|
|
int yOff = 0;
|
|
|
|
int idx = 0;
|
|
|
|
while (sub.location[1] + yOff < scissor.location[1] + scissor.size[1] || (idx & 1) != 0)
|
|
|
|
{
|
|
|
|
yOff += spacing;
|
|
|
|
++idx;
|
|
|
|
}
|
2016-01-01 00:12:19 +00:00
|
|
|
int startIdx = int(m_t.m_rows) - idx;
|
2015-12-29 22:58:09 +00:00
|
|
|
|
2015-12-30 02:20:24 +00:00
|
|
|
size_t r, c;
|
2015-12-31 06:37:32 +00:00
|
|
|
for (r=0, c=0 ; r<SPECTER_TABLE_MAX_ROWS && (sub.location[1] + yOff + spacing) >= scissor.location[1] ; ++r)
|
2015-12-29 02:02:43 +00:00
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
const Zeus::CColor& color = (startIdx+r==m_t.m_selectedRow) ? theme.tableCellBgSelected() :
|
|
|
|
((r&1) ? theme.tableCellBg1() : theme.tableCellBg2());
|
2015-12-30 02:20:24 +00:00
|
|
|
int xOff = 0;
|
2015-12-31 20:26:04 +00:00
|
|
|
for (c=0 ; c<std::min(m_t.m_maxColumns, m_t.m_columns) ; ++c)
|
2015-12-30 02:20:24 +00:00
|
|
|
{
|
|
|
|
v[0].m_pos.assign(xOff + margin, yOff - margin, 0);
|
|
|
|
v[0].m_color = color;
|
|
|
|
v[1] = v[0];
|
|
|
|
v[2].m_pos.assign(xOff + margin, yOff - margin - rowHeight, 0);
|
|
|
|
v[2].m_color = color;
|
|
|
|
v[3].m_pos.assign(xOff + div - margin, yOff - margin, 0);
|
|
|
|
v[3].m_color = color;
|
|
|
|
v[4].m_pos.assign(xOff + div - margin, yOff - margin - rowHeight, 0);
|
|
|
|
v[4].m_color = color;
|
|
|
|
v[5] = v[4];
|
|
|
|
v += 6;
|
|
|
|
xOff += div;
|
|
|
|
}
|
2015-12-29 22:58:09 +00:00
|
|
|
yOff -= spacing;
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
2016-01-01 00:12:19 +00:00
|
|
|
m_visibleStart = std::max(0, startIdx);
|
2015-12-30 02:20:24 +00:00
|
|
|
m_visibleRows = r;
|
2015-12-31 06:37:32 +00:00
|
|
|
if (r * c)
|
2016-01-01 00:12:19 +00:00
|
|
|
m_vertsBuf->load(m_verts.get(), sizeof(SolidShaderVert) * 6 * r * c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::cycleSortColumn(size_t c)
|
|
|
|
{
|
|
|
|
if (c >= m_columns)
|
|
|
|
Log.report(LogVisor::FatalError, "cycleSortColumn out of bounds (%" PRISize ", %" PRISize ")",
|
|
|
|
c, m_columns);
|
|
|
|
if (m_state)
|
|
|
|
{
|
|
|
|
size_t cIdx;
|
|
|
|
SortDirection dir = m_state->getSort(cIdx);
|
|
|
|
if (dir == SortDirection::None || cIdx != c)
|
|
|
|
m_state->setSort(c, SortDirection::Ascending);
|
|
|
|
else if (dir == SortDirection::Ascending)
|
|
|
|
m_state->setSort(c, SortDirection::Descending);
|
|
|
|
else if (dir == SortDirection::Descending)
|
|
|
|
m_state->setSort(c, SortDirection::Ascending);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::selectRow(size_t r)
|
|
|
|
{
|
|
|
|
if (r >= m_rows && r != -1)
|
|
|
|
Log.report(LogVisor::FatalError, "selectRow out of bounds (%" PRISize ", %" PRISize ")",
|
|
|
|
r, m_rows);
|
|
|
|
if (r == m_selectedRow)
|
|
|
|
return;
|
|
|
|
if (m_selectedRow != -1)
|
|
|
|
for (auto& col : m_cellViews)
|
|
|
|
{
|
|
|
|
ViewChild<std::unique_ptr<CellView>>& cv = col.at(m_selectedRow);
|
|
|
|
if (cv.m_view)
|
|
|
|
cv.m_view->deselect();
|
|
|
|
}
|
|
|
|
m_selectedRow = r;
|
|
|
|
if (m_selectedRow != -1)
|
|
|
|
for (auto& col : m_cellViews)
|
|
|
|
{
|
|
|
|
ViewChild<std::unique_ptr<CellView>>& cv = col.at(m_selectedRow);
|
|
|
|
if (cv.m_view)
|
|
|
|
cv.m_view->select();
|
|
|
|
}
|
|
|
|
updateSize();
|
|
|
|
if (m_state)
|
|
|
|
m_state->setSelectedRow(r);
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::setMultiplyColor(const Zeus::CColor& color)
|
|
|
|
{
|
|
|
|
View::setMultiplyColor(color);
|
2015-12-30 02:20:24 +00:00
|
|
|
if (m_scroll.m_view)
|
|
|
|
m_scroll.m_view->setMultiplyColor(color);
|
2016-01-01 00:12:19 +00:00
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews)
|
|
|
|
if (hv.m_view)
|
|
|
|
hv.m_view->m_text->setMultiplyColor(color);
|
2015-12-29 02:02:43 +00:00
|
|
|
for (auto& col : m_cellViews)
|
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
|
|
|
if (cv.m_view)
|
|
|
|
cv.m_view->m_text->setMultiplyColor(color);
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
2016-01-01 00:12:19 +00:00
|
|
|
void Table::CellView::select()
|
|
|
|
{
|
|
|
|
m_selected = true;
|
|
|
|
m_text->colorGlyphs(rootView().themeData().fieldText());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::deselect()
|
|
|
|
{
|
|
|
|
m_selected = false;
|
|
|
|
m_text->colorGlyphs(rootView().themeData().uiText());
|
|
|
|
}
|
|
|
|
|
2015-12-23 00:25:46 +00:00
|
|
|
void Table::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
m_scroll.mouseDown(coord, button, mod);
|
2016-01-01 00:12:19 +00:00
|
|
|
if (m_headerNeedsUpdate)
|
|
|
|
_setHeaderVerts(subRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Table::RowsView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
|
|
|
|
if (hv.mouseDown(coord, button, mod))
|
|
|
|
return; /* Trap header event */
|
|
|
|
for (std::vector<ViewChild<std::unique_ptr<CellView>>>& col : m_t.m_cellViews)
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
|
|
|
cv.mouseDown(coord, button, mod);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
if (m_r != -1)
|
|
|
|
{
|
|
|
|
m_t.selectRow(m_r);
|
|
|
|
if (m_t.m_clickFrames < 15 && m_t.m_state)
|
|
|
|
m_t.m_state->rowActivated(m_r);
|
|
|
|
else
|
|
|
|
m_t.m_clickFrames = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_t.m_headerNeedsUpdate = true;
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
m_scroll.mouseUp(coord, button, mod);
|
2016-01-01 00:12:19 +00:00
|
|
|
if (m_headerNeedsUpdate)
|
|
|
|
_setHeaderVerts(subRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::RowsView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
size_t idx = 0;
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
|
|
|
|
{
|
|
|
|
if (hv.m_mouseDown && hv.m_mouseIn)
|
|
|
|
m_t.cycleSortColumn(idx);
|
|
|
|
hv.mouseUp(coord, button, mod);
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
for (std::vector<ViewChild<std::unique_ptr<CellView>>>& col : m_t.m_cellViews)
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
|
|
|
cv.mouseUp(coord, button, mod);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod)
|
|
|
|
{
|
|
|
|
if (m_r == -1)
|
|
|
|
m_t.m_headerNeedsUpdate = true;
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-12-29 02:02:43 +00:00
|
|
|
void Table::mouseMove(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
m_scroll.mouseMove(coord);
|
2016-01-01 00:12:19 +00:00
|
|
|
if (m_headerNeedsUpdate)
|
|
|
|
_setHeaderVerts(subRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::RowsView::mouseMove(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
|
|
|
|
hv.mouseMove(coord);
|
|
|
|
for (std::vector<ViewChild<std::unique_ptr<CellView>>>& col : m_t.m_cellViews)
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
|
|
|
cv.mouseMove(coord);
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
|
2015-12-23 00:25:46 +00:00
|
|
|
void Table::mouseEnter(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
m_scroll.mouseEnter(coord);
|
2016-01-01 00:12:19 +00:00
|
|
|
if (m_headerNeedsUpdate)
|
|
|
|
_setHeaderVerts(subRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::mouseEnter(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
if (m_r == -1)
|
|
|
|
m_t.m_headerNeedsUpdate = true;
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::mouseLeave(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
m_scroll.mouseLeave(coord);
|
2016-01-01 00:12:19 +00:00
|
|
|
if (m_headerNeedsUpdate)
|
|
|
|
_setHeaderVerts(subRect());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::RowsView::mouseLeave(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
|
|
|
|
hv.mouseLeave(coord);
|
|
|
|
for (std::vector<ViewChild<std::unique_ptr<CellView>>>& col : m_t.m_cellViews)
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
|
|
|
cv.mouseLeave(coord);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::mouseLeave(const boo::SWindowCoord& coord)
|
|
|
|
{
|
|
|
|
if (m_r == -1)
|
|
|
|
m_t.m_headerNeedsUpdate = true;
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll)
|
|
|
|
{
|
|
|
|
m_scroll.scroll(coord, scroll);
|
|
|
|
}
|
|
|
|
|
2015-12-29 22:58:09 +00:00
|
|
|
void Table::think()
|
|
|
|
{
|
|
|
|
if (m_scroll.m_view)
|
|
|
|
m_scroll.m_view->think();
|
2016-01-01 00:12:19 +00:00
|
|
|
++m_clickFrames;
|
2015-12-29 22:58:09 +00:00
|
|
|
}
|
|
|
|
|
2015-12-29 02:02:43 +00:00
|
|
|
void Table::updateData()
|
|
|
|
{
|
|
|
|
m_header = false;
|
2016-01-01 00:12:19 +00:00
|
|
|
bool newViewChildren = false;
|
|
|
|
if (m_columns != m_data->columnCount())
|
|
|
|
newViewChildren = true;
|
|
|
|
|
2015-12-29 02:02:43 +00:00
|
|
|
m_rows = m_data->rowCount();
|
|
|
|
m_columns = m_data->columnCount();
|
|
|
|
if (!m_columns)
|
|
|
|
return;
|
|
|
|
|
2016-01-01 00:12:19 +00:00
|
|
|
if (newViewChildren)
|
|
|
|
{
|
|
|
|
m_headerViews.clear();
|
|
|
|
m_cellViews.clear();
|
|
|
|
m_headerViews.reserve(m_columns);
|
|
|
|
m_cellViews.reserve(m_columns);
|
|
|
|
for (size_t c=0 ; c<m_columns ; ++c)
|
|
|
|
{
|
|
|
|
m_headerViews.emplace_back();
|
|
|
|
m_cellViews.emplace_back();
|
|
|
|
}
|
|
|
|
}
|
2015-12-29 02:02:43 +00:00
|
|
|
|
|
|
|
ViewResources& res = rootView().viewRes();
|
|
|
|
const Zeus::CColor& textColor = rootView().themeData().uiText();
|
|
|
|
for (size_t c=0 ; c<m_columns ; ++c)
|
|
|
|
{
|
|
|
|
const std::string* headerText = m_data->header(c);
|
|
|
|
if (headerText)
|
|
|
|
{
|
|
|
|
m_header = true;
|
2016-01-01 00:12:19 +00:00
|
|
|
CellView* cv = new CellView(*this, res, c, -1);
|
|
|
|
m_headerViews[c].m_view.reset(cv);
|
2015-12-29 02:02:43 +00:00
|
|
|
cv->m_text->typesetGlyphs(*headerText, textColor);
|
|
|
|
}
|
|
|
|
else
|
2016-01-01 00:12:19 +00:00
|
|
|
m_headerViews[c].m_view.reset();
|
2015-12-29 02:02:43 +00:00
|
|
|
|
2016-01-01 00:12:19 +00:00
|
|
|
std::vector<ViewChild<std::unique_ptr<CellView>>>& col = m_cellViews[c];
|
|
|
|
col.clear();
|
2015-12-29 02:02:43 +00:00
|
|
|
col.reserve(m_rows);
|
|
|
|
for (size_t r=0 ; r<m_rows ; ++r)
|
|
|
|
{
|
|
|
|
const std::string* cellText = m_data->cell(c, r);
|
|
|
|
if (cellText)
|
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
CellView* cv = new CellView(*this, res, c, r);
|
|
|
|
col.emplace_back();
|
|
|
|
col.back().m_view.reset(cv);
|
2015-12-29 02:02:43 +00:00
|
|
|
cv->m_text->typesetGlyphs(*cellText, textColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
col.emplace_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSize();
|
|
|
|
}
|
|
|
|
|
2015-12-23 00:25:46 +00:00
|
|
|
void Table::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
|
|
|
{
|
2015-12-29 02:02:43 +00:00
|
|
|
View::resized(root, sub);
|
|
|
|
if (m_scroll.m_view)
|
|
|
|
m_scroll.m_view->resized(root, sub);
|
|
|
|
|
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
|
|
|
boo::SWindowRect cell = sub;
|
|
|
|
cell.size[1] = ROW_HEIGHT * pf;
|
|
|
|
cell.location[1] += sub.size[1] - cell.size[1];
|
|
|
|
int div = sub.size[0] / m_cellViews.size();
|
2016-01-01 00:12:19 +00:00
|
|
|
cell.size[0] = div;
|
2015-12-29 02:02:43 +00:00
|
|
|
|
2016-01-01 00:12:19 +00:00
|
|
|
_setHeaderVerts(sub);
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_headerViews)
|
2015-12-29 02:02:43 +00:00
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
if (hv.m_view)
|
|
|
|
hv.m_view->resized(root, cell);
|
2015-12-29 02:02:43 +00:00
|
|
|
cell.location[0] += div;
|
|
|
|
}
|
2015-12-29 22:58:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Table::RowsView::nominalHeight() const
|
|
|
|
{
|
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
2015-12-30 02:20:24 +00:00
|
|
|
int rows = m_t.m_rows;
|
|
|
|
if (m_t.m_header)
|
|
|
|
rows += 1;
|
|
|
|
return rows * (ROW_HEIGHT + CELL_MARGIN * 2) * pf;
|
2015-12-29 22:58:09 +00:00
|
|
|
}
|
2015-12-29 02:02:43 +00:00
|
|
|
|
2015-12-29 22:58:09 +00:00
|
|
|
void Table::RowsView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub,
|
|
|
|
const boo::SWindowRect& scissor)
|
|
|
|
{
|
|
|
|
View::resized(root, sub);
|
|
|
|
_setRowVerts(sub, scissor);
|
|
|
|
|
|
|
|
if (m_t.m_cellViews.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
|
|
|
int div = sub.size[0] / m_t.m_cellViews.size();
|
|
|
|
boo::SWindowRect cell = sub;
|
2016-01-01 00:12:19 +00:00
|
|
|
cell.size[0] = div;
|
2015-12-29 22:58:09 +00:00
|
|
|
cell.size[1] = ROW_HEIGHT * pf;
|
|
|
|
cell.location[1] += sub.size[1] - cell.size[1];
|
2015-12-30 02:20:24 +00:00
|
|
|
int spacing = (ROW_HEIGHT + CELL_MARGIN * 2) * pf;
|
2015-12-29 02:02:43 +00:00
|
|
|
int hStart = cell.location[1];
|
2015-12-29 22:58:09 +00:00
|
|
|
for (auto& col : m_t.m_cellViews)
|
2015-12-29 02:02:43 +00:00
|
|
|
{
|
|
|
|
cell.location[1] = hStart;
|
2016-01-01 00:12:19 +00:00
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
2015-12-29 02:02:43 +00:00
|
|
|
{
|
|
|
|
cell.location[1] -= spacing;
|
2016-01-01 00:12:19 +00:00
|
|
|
if (cv.m_view)
|
|
|
|
cv.m_view->resized(root, cell);
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
cell.location[0] += div;
|
|
|
|
}
|
|
|
|
|
2015-12-29 22:58:09 +00:00
|
|
|
m_scissorRect = scissor;
|
|
|
|
m_scissorRect.size[1] -= spacing;
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
2015-12-29 02:02:43 +00:00
|
|
|
void Table::CellView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
|
2015-12-23 00:25:46 +00:00
|
|
|
{
|
2015-12-29 02:02:43 +00:00
|
|
|
View::resized(root, sub);
|
|
|
|
boo::SWindowRect textRect = sub;
|
|
|
|
float pf = rootView().viewRes().pixelFactor();
|
|
|
|
textRect.location[0] += 5 * pf;
|
2015-12-30 02:20:24 +00:00
|
|
|
textRect.location[1] += 5 * pf;
|
2015-12-29 02:02:43 +00:00
|
|
|
m_text->resized(root, textRect);
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::draw(boo::IGraphicsCommandQueue* gfxQ)
|
|
|
|
{
|
2015-12-29 02:02:43 +00:00
|
|
|
if (m_scroll.m_view)
|
|
|
|
m_scroll.m_view->draw(gfxQ);
|
2015-12-23 00:25:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::RowsView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
|
|
|
{
|
2015-12-29 22:58:09 +00:00
|
|
|
gfxQ->setShaderDataBinding(m_shaderBinding);
|
2015-12-29 02:02:43 +00:00
|
|
|
gfxQ->setDrawPrimitive(boo::Primitive::TriStrips);
|
2015-12-29 22:58:09 +00:00
|
|
|
|
|
|
|
gfxQ->setScissor(m_scissorRect);
|
2015-12-30 22:04:58 +00:00
|
|
|
gfxQ->draw(1, m_visibleRows * m_t.m_columns * 6 - 2);
|
2015-12-29 02:02:43 +00:00
|
|
|
for (auto& col : m_t.m_cellViews)
|
|
|
|
{
|
2015-12-29 22:58:09 +00:00
|
|
|
size_t idx = 0;
|
2016-01-01 00:12:19 +00:00
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& cv : col)
|
2015-12-29 22:58:09 +00:00
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
if (cv.m_view && idx >= m_visibleStart && idx < m_visibleStart + m_visibleRows)
|
|
|
|
cv.m_view->draw(gfxQ);
|
2015-12-29 22:58:09 +00:00
|
|
|
++idx;
|
|
|
|
}
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
gfxQ->setScissor(rootView().subRect());
|
2015-12-29 22:58:09 +00:00
|
|
|
|
2015-12-30 22:04:58 +00:00
|
|
|
if (m_t.m_header)
|
|
|
|
{
|
2016-01-01 00:12:19 +00:00
|
|
|
gfxQ->setShaderDataBinding(m_t.m_hShaderBinding);
|
|
|
|
gfxQ->setDrawPrimitive(boo::Primitive::TriStrips);
|
|
|
|
gfxQ->draw(1, m_t.m_columns * 6 - 2);
|
|
|
|
for (ViewChild<std::unique_ptr<CellView>>& hv : m_t.m_headerViews)
|
|
|
|
if (hv.m_view)
|
|
|
|
hv.m_view->draw(gfxQ);
|
2015-12-30 22:04:58 +00:00
|
|
|
}
|
2015-12-29 02:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Table::CellView::draw(boo::IGraphicsCommandQueue* gfxQ)
|
|
|
|
{
|
|
|
|
m_text->draw(gfxQ);
|
2015-12-15 21:53:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|