mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[escher] make simple table view data source inherit from table view
Change-Id: Ia3c64b643f633e4c7c6fd0f921fe6a79336a7b64
This commit is contained in:
@@ -12,7 +12,7 @@ objs += $(addprefix escher/src/,\
|
||||
responder.o\
|
||||
scroll_view.o\
|
||||
scroll_view_indicator.o\
|
||||
simple_table_view.o\
|
||||
simple_table_view_data_source.o\
|
||||
solid_color_view.o\
|
||||
stack_view.o\
|
||||
stack_view_controller.o\
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <escher/responder.h>
|
||||
#include <escher/scroll_view.h>
|
||||
#include <escher/scroll_view_indicator.h>
|
||||
#include <escher/simple_table_view.h>
|
||||
#include <escher/simple_table_view_data_source.h>
|
||||
#include <escher/solid_color_view.h>
|
||||
#include <escher/stack_view_controller.h>
|
||||
#include <escher/switch_view.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ESCHER_LIST_VIEW_H
|
||||
#define ESCHER_LIST_VIEW_H
|
||||
|
||||
#include <escher/simple_table_view.h>
|
||||
#include <escher/simple_table_view_data_source.h>
|
||||
|
||||
class ListViewDataSource : public SimpleTableViewDataSource{
|
||||
public:
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
virtual void willDisplayCellForIndex(View * cell, int index);
|
||||
};
|
||||
|
||||
class ListView : public SimpleTableView {
|
||||
class ListView : public TableView {
|
||||
public:
|
||||
ListView(ListViewDataSource * dataSource, KDCoordinate topMargin = 0, KDCoordinate rightMargin = 0,
|
||||
KDCoordinate bottomMargin = 0, KDCoordinate leftMargin = 0);
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
#ifndef ESCHER_SIMPLE_TABLE_VIEW_H
|
||||
#define ESCHER_SIMPLE_TABLE_VIEW_H
|
||||
|
||||
#include <escher/scroll_view.h>
|
||||
|
||||
class SimpleTableViewDataSource {
|
||||
public:
|
||||
virtual int numberOfRows() = 0;
|
||||
virtual int numberOfColumns() = 0;
|
||||
virtual void willDisplayCellAtLocation(View * cell, int x, int y);
|
||||
virtual KDCoordinate cellHeight() = 0;
|
||||
virtual KDCoordinate cellWidth() = 0;
|
||||
virtual View * reusableCell(int index) = 0;
|
||||
virtual int reusableCellCount() = 0;
|
||||
};
|
||||
|
||||
class SimpleTableView : public ScrollView {
|
||||
public:
|
||||
SimpleTableView(SimpleTableViewDataSource * dataSource, KDCoordinate topMargin = 0, KDCoordinate rightMargin = 0,
|
||||
KDCoordinate bottomMargin = 0, KDCoordinate leftMargin = 0);
|
||||
|
||||
void scrollToCell(int x, int y);
|
||||
View * cellAtLocation(int x, int y);
|
||||
protected:
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * className() const override;
|
||||
#endif
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(SimpleTableView * tableView, SimpleTableViewDataSource * dataSource);
|
||||
|
||||
KDCoordinate height() const;
|
||||
KDCoordinate width() const;
|
||||
void scrollToCell(int x, int y) const;
|
||||
View * cellAtLocation(int x, int y);
|
||||
protected:
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * className() const override;
|
||||
#endif
|
||||
private:
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
|
||||
/* realCellWidth enables to handle list view for which
|
||||
* TableViewDataSource->cellWidht = 0 */
|
||||
KDCoordinate realCellWidth() const;
|
||||
int numberOfFullyDisplayableRows() const;
|
||||
int numberOfFullyDisplayableColumns() const;
|
||||
int numberOfDisplayableRows() const;
|
||||
int numberOfDisplayableColumns() const;
|
||||
int rowsScrollingOffset() const;
|
||||
int columnsScrollingOffset() const;
|
||||
bool rowAtIndexIsBeforeFullyVisibleRange(int index) const;
|
||||
bool columnAtIndexIsBeforeFullyVisibleRange(int index) const;
|
||||
bool rowAtIndexIsAfterFullyVisibleRange(int index) const;
|
||||
bool columnAtIndexIsAfterFullyVisibleRange(int index) const;
|
||||
SimpleTableView * m_tableView;
|
||||
SimpleTableViewDataSource * m_dataSource;
|
||||
};
|
||||
|
||||
void layoutSubviews() override;
|
||||
|
||||
ContentView m_contentView;
|
||||
};
|
||||
|
||||
#endif
|
||||
23
escher/include/escher/simple_table_view_data_source.h
Normal file
23
escher/include/escher/simple_table_view_data_source.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef ESCHER_SIMPLE_TABLE_VIEW_DATA_SOURCE_H
|
||||
#define ESCHER_SIMPLE_TABLE_VIEW_DATA_SOURCE_H
|
||||
|
||||
#include <escher/table_view.h>
|
||||
|
||||
class SimpleTableViewDataSource : public TableViewDataSource {
|
||||
public:
|
||||
virtual KDCoordinate cellHeight() = 0;
|
||||
virtual KDCoordinate cellWidth() = 0;
|
||||
KDCoordinate columnWidth(int i) override;
|
||||
KDCoordinate rowHeight(int j) override;
|
||||
KDCoordinate cumulatedWidthFromIndex(int i) override;
|
||||
KDCoordinate cumulatedHeightFromIndex(int j) override;
|
||||
int indexFromCumulatedWidth(KDCoordinate offsetX) override;
|
||||
int indexFromCumulatedHeight(KDCoordinate offsetY) override;
|
||||
virtual View * reusableCell(int index) = 0;
|
||||
virtual int reusableCellCount() = 0;
|
||||
View * reusableCell(int index, int type) override;
|
||||
int reusableCellCount(int type) override;
|
||||
int typeAtLocation(int i, int j) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,8 +5,6 @@ extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
#define MIN(x,y) ((x)<(y) ? (x) : (y))
|
||||
|
||||
int ListViewDataSource::numberOfColumns() {
|
||||
return 1;
|
||||
}
|
||||
@@ -24,7 +22,7 @@ void ListViewDataSource::willDisplayCellForIndex(View * cell, int index) {
|
||||
|
||||
ListView::ListView(ListViewDataSource * dataSource, KDCoordinate topMargin, KDCoordinate rightMargin,
|
||||
KDCoordinate bottomMargin, KDCoordinate leftMargin) :
|
||||
SimpleTableView(dataSource, topMargin, rightMargin, bottomMargin, leftMargin)
|
||||
TableView(dataSource, topMargin, rightMargin, bottomMargin, leftMargin)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
#include <escher/simple_table_view.h>
|
||||
#include <escher/metric.h>
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
#define MIN(x,y) ((x)<(y) ? (x) : (y))
|
||||
|
||||
void SimpleTableViewDataSource::willDisplayCellAtLocation(View * cell, int x, int y) {
|
||||
}
|
||||
|
||||
|
||||
SimpleTableView::SimpleTableView(SimpleTableViewDataSource * dataSource, KDCoordinate topMargin, KDCoordinate rightMargin,
|
||||
KDCoordinate bottomMargin, KDCoordinate leftMargin) :
|
||||
ScrollView(&m_contentView, topMargin, rightMargin, bottomMargin, leftMargin),
|
||||
m_contentView(SimpleTableView::ContentView(this, dataSource))
|
||||
{
|
||||
}
|
||||
|
||||
// This method computes the minimal scrolling needed to properly display the
|
||||
// requested cell.
|
||||
void SimpleTableView::scrollToCell(int x, int y) {
|
||||
m_contentView.scrollToCell(x, y);
|
||||
}
|
||||
|
||||
View * SimpleTableView::cellAtLocation(int x, int y) {
|
||||
return m_contentView.cellAtLocation(x, y);
|
||||
}
|
||||
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * SimpleTableView::className() const {
|
||||
return "SimpleTableView";
|
||||
}
|
||||
#endif
|
||||
|
||||
void SimpleTableView::layoutSubviews() {
|
||||
// We only have to layout our contentView.
|
||||
// We will size it here, and ScrollView::layoutSubviews will position it.
|
||||
|
||||
KDRect contentViewFrame(0, 0, m_contentView.width(), m_contentView.height());
|
||||
m_contentView.setFrame(contentViewFrame);
|
||||
|
||||
ScrollView::layoutSubviews();
|
||||
}
|
||||
|
||||
/* SimpleTableView::ContentView */
|
||||
|
||||
SimpleTableView::ContentView::ContentView(SimpleTableView * tableView, SimpleTableViewDataSource * dataSource) :
|
||||
View(),
|
||||
m_tableView(tableView),
|
||||
m_dataSource(dataSource)
|
||||
{
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableView::ContentView::realCellWidth() const {
|
||||
int cellWidth = m_dataSource->cellWidth();
|
||||
cellWidth = cellWidth ? cellWidth : m_tableView->maxContentWidthDisplayableWithoutScrolling();
|
||||
return cellWidth;
|
||||
}
|
||||
|
||||
|
||||
KDCoordinate SimpleTableView::ContentView::height() const {
|
||||
return m_dataSource->numberOfRows() * m_dataSource->cellHeight();
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableView::ContentView::width() const {
|
||||
return m_dataSource->numberOfColumns() * realCellWidth();
|
||||
}
|
||||
|
||||
void SimpleTableView::ContentView::scrollToCell(int x, int y) const {
|
||||
KDCoordinate contentOffsetX = m_tableView->contentOffset().x();
|
||||
KDCoordinate contentOffsetY = m_tableView->contentOffset().y();
|
||||
if (columnAtIndexIsBeforeFullyVisibleRange(x)) {
|
||||
// Let's scroll the tableView to put that cell on the left (while keeping the left margin)
|
||||
contentOffsetX = x*realCellWidth();
|
||||
} else if (columnAtIndexIsAfterFullyVisibleRange(x)) {
|
||||
// Let's scroll the tableView to put that cell on the right (while keeping the right margin)
|
||||
contentOffsetX = (x+1)*realCellWidth() - m_tableView->maxContentWidthDisplayableWithoutScrolling();
|
||||
}
|
||||
if (rowAtIndexIsBeforeFullyVisibleRange(y)) {
|
||||
// Let's scroll the tableView to put that cell on the top (while keeping the top margin)
|
||||
contentOffsetY = y*m_dataSource->cellHeight();
|
||||
} else if (rowAtIndexIsAfterFullyVisibleRange(y)) {
|
||||
// Let's scroll the tableView to put that cell on the bottom (while keeping the bottom margin)
|
||||
contentOffsetY = (y+1)*m_dataSource->cellHeight() - m_tableView->maxContentHeightDisplayableWithoutScrolling();
|
||||
}
|
||||
m_tableView->setContentOffset(KDPoint(contentOffsetX, contentOffsetY));
|
||||
}
|
||||
|
||||
View * SimpleTableView::ContentView::cellAtLocation(int x, int y) {
|
||||
int relativeX = x-columnsScrollingOffset();
|
||||
int relativeY = y-rowsScrollingOffset();
|
||||
return m_dataSource->reusableCell(relativeY*numberOfDisplayableColumns()+relativeX);
|
||||
}
|
||||
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * SimpleTableView::ContentView::className() const {
|
||||
return "TableView::ContentView";
|
||||
}
|
||||
#endif
|
||||
|
||||
int SimpleTableView::ContentView::numberOfSubviews() const {
|
||||
int result = numberOfDisplayableRows() * numberOfDisplayableColumns();
|
||||
assert(result <= m_dataSource->reusableCellCount());
|
||||
return result;
|
||||
}
|
||||
|
||||
View * SimpleTableView::ContentView::subviewAtIndex(int index) {
|
||||
assert(index >= 0);
|
||||
assert(index < m_dataSource->reusableCellCount());
|
||||
return m_dataSource->reusableCell(index);
|
||||
}
|
||||
|
||||
void SimpleTableView::ContentView::layoutSubviews() {
|
||||
int rowOffset = rowsScrollingOffset();
|
||||
int columnOffset = columnsScrollingOffset();
|
||||
|
||||
for (int i=0; i<numberOfSubviews(); i++) {
|
||||
View * cell = subview(i);
|
||||
int columns = numberOfDisplayableColumns();
|
||||
int y = i / columns;
|
||||
/* "x = i % columns" but we avoid a call to modulo not to implement
|
||||
* "__aeabi_idivmod" */
|
||||
int x = i - y * columns;
|
||||
|
||||
KDCoordinate cellHeight = m_dataSource->cellHeight();
|
||||
KDCoordinate cellWidth = realCellWidth();
|
||||
KDRect cellFrame((columnOffset+x)*cellWidth, (rowOffset+y)*cellHeight,
|
||||
cellWidth, cellHeight);
|
||||
|
||||
cell->setFrame(cellFrame);
|
||||
|
||||
m_dataSource->willDisplayCellAtLocation(cell, columnOffset+x, rowOffset+y);
|
||||
}
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::numberOfFullyDisplayableRows() const {
|
||||
// The number of displayable rows taking into accounts margins
|
||||
return m_tableView->maxContentHeightDisplayableWithoutScrolling()/m_dataSource->cellHeight();
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::numberOfFullyDisplayableColumns() const {
|
||||
// The number of displayable columns taking into accounts margins
|
||||
return m_tableView->maxContentWidthDisplayableWithoutScrolling()/m_dataSource->cellHeight();
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::numberOfDisplayableRows() const {
|
||||
return MIN(
|
||||
m_dataSource->numberOfRows(),
|
||||
m_tableView->bounds().height() / m_dataSource->cellHeight() + 2
|
||||
);
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::numberOfDisplayableColumns() const {
|
||||
KDCoordinate width = realCellWidth();
|
||||
if (width == 0) {
|
||||
return 0;
|
||||
}
|
||||
return MIN(
|
||||
m_dataSource->numberOfColumns(),
|
||||
m_tableView->bounds().width() / width + 2
|
||||
);
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::rowsScrollingOffset() const {
|
||||
/* Here, we want to translate the offset at which our tableView is displaying
|
||||
* us into an integer offset we can use to ask cells to our data source. */
|
||||
KDCoordinate pixelScrollingOffset = -m_frame.y();
|
||||
return pixelScrollingOffset / m_dataSource->cellHeight();
|
||||
}
|
||||
|
||||
int SimpleTableView::ContentView::columnsScrollingOffset() const {
|
||||
/* Here, we want to translate the offset at which our tableView is displaying
|
||||
* us into an integer offset we can use to ask cells to our data source. */
|
||||
KDCoordinate width = realCellWidth();
|
||||
if (width == 0) {
|
||||
return 0;
|
||||
}
|
||||
KDCoordinate pixelScrollingOffset = -m_frame.x();
|
||||
return pixelScrollingOffset / width;
|
||||
}
|
||||
|
||||
bool SimpleTableView::ContentView::rowAtIndexIsBeforeFullyVisibleRange(int index) const {
|
||||
return index <= rowsScrollingOffset();
|
||||
}
|
||||
|
||||
bool SimpleTableView::ContentView::columnAtIndexIsBeforeFullyVisibleRange(int index) const {
|
||||
return index <= columnsScrollingOffset();
|
||||
}
|
||||
|
||||
bool SimpleTableView::ContentView::rowAtIndexIsAfterFullyVisibleRange(int index) const {
|
||||
int relativeIndex = index - rowsScrollingOffset();
|
||||
return (relativeIndex >= numberOfFullyDisplayableRows());
|
||||
}
|
||||
|
||||
bool SimpleTableView::ContentView::columnAtIndexIsAfterFullyVisibleRange(int index) const {
|
||||
int relativeIndex = index - columnsScrollingOffset();
|
||||
return (relativeIndex >= numberOfFullyDisplayableColumns());
|
||||
}
|
||||
52
escher/src/simple_table_view_data_source.cpp
Normal file
52
escher/src/simple_table_view_data_source.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <escher/simple_table_view_data_source.h>
|
||||
#include <escher/metric.h>
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableViewDataSource::columnWidth(int i) {
|
||||
return cellWidth();
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableViewDataSource::rowHeight(int j) {
|
||||
return cellHeight();
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableViewDataSource::cumulatedWidthFromIndex(int i) {
|
||||
return cellWidth() * i;
|
||||
}
|
||||
|
||||
KDCoordinate SimpleTableViewDataSource::cumulatedHeightFromIndex(int j) {
|
||||
return cellHeight() * j;
|
||||
}
|
||||
|
||||
int SimpleTableViewDataSource::indexFromCumulatedWidth(KDCoordinate offsetX) {
|
||||
KDCoordinate width = cellWidth();
|
||||
if (width == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (offsetX - 1) / width;
|
||||
}
|
||||
|
||||
int SimpleTableViewDataSource::indexFromCumulatedHeight(KDCoordinate offsetY) {
|
||||
KDCoordinate height = cellHeight();
|
||||
if (height == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (offsetY - 1) / height;
|
||||
}
|
||||
|
||||
View * SimpleTableViewDataSource::reusableCell(int index, int type) {
|
||||
assert(type == 0);
|
||||
return reusableCell(index);
|
||||
}
|
||||
|
||||
int SimpleTableViewDataSource::reusableCellCount(int type) {
|
||||
assert(type == 0);
|
||||
return reusableCellCount();
|
||||
}
|
||||
|
||||
int SimpleTableViewDataSource::typeAtLocation(int i, int j) {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user