Numworks Epsilon  1.4.1
Graphing Calculator Operating System
table_view.cpp
Go to the documentation of this file.
1 #include <escher/table_view.h>
2 #include <escher/metric.h>
3 
4 extern "C" {
5 #include <assert.h>
6 }
7 
8 #define MIN(x,y) ((x)<(y) ? (x) : (y))
9 
11  ScrollView(&m_contentView, scrollDataSource),
12  m_contentView(this, dataSource, 0, 1)
13 {
14 }
15 
18 }
19 
21  return m_contentView.dataSource();
22 }
23 
24 // This method computes the minimal scrolling needed to properly display the
25 // requested cell.
26 void TableView::scrollToCell(int i, int j) {
28 }
29 
31  return m_contentView.cellAtLocation(i, j);
32 }
33 
34 #if ESCHER_VIEW_LOGGING
35 const char * TableView::className() const {
36  return "TableView";
37 }
38 #endif
39 
41  // We only have to layout our contentView.
42  // We will size it here, and ScrollView::layoutSubviews will position it.
43 
45 
47 }
48 
49 void TableView::reloadCellAtLocation(int i, int j) {
51 }
52 
53 /* TableView::ContentView */
54 
55 TableView::ContentView::ContentView(TableView * tableView, TableViewDataSource * dataSource, KDCoordinate horizontalCellOverlap, KDCoordinate verticalCellOverlap) :
56  View(),
57  m_tableView(tableView),
58  m_dataSource(dataSource),
59  m_horizontalCellOverlap(horizontalCellOverlap),
60  m_verticalCellOverlap(verticalCellOverlap)
61 {
62 }
63 
65  return KDSize(width(), height());
66 }
67 
69  return m_dataSource;
70 }
71 
72 KDCoordinate TableView::ContentView::columnWidth(int i) const {
73  int columnWidth = m_dataSource->columnWidth(i);
74  columnWidth = columnWidth ? columnWidth : m_tableView->maxContentWidthDisplayableWithoutScrolling();
75  return columnWidth;
76 }
77 
80  setSize(KDSize(width(), height()));
81 }
82 
83 KDCoordinate TableView::ContentView::height() const {
84  return m_dataSource->cumulatedHeightFromIndex(m_dataSource->numberOfRows())+m_verticalCellOverlap;
85 }
86 
87 KDCoordinate TableView::ContentView::width() const {
88  int result = m_dataSource->cumulatedWidthFromIndex(m_dataSource->numberOfColumns())+m_horizontalCellOverlap;
89  // handle the case of list: cumulatedWidthFromIndex() = 0
90  return result ? result : m_tableView->maxContentWidthDisplayableWithoutScrolling();
91 }
92 
93 void TableView::ContentView::scrollToCell(int x, int y) const {
94  KDRect cellRect = KDRect(m_dataSource->cumulatedWidthFromIndex(x), m_dataSource->cumulatedHeightFromIndex(y), columnWidth(x), m_dataSource->rowHeight(y));
95  m_tableView->scrollToContentRect(cellRect, true);
96 }
97 
99  m_dataSource->willDisplayCellAtLocation(cellAtLocation(i, j), i, j);
100 }
101 
102 int TableView::ContentView::typeOfSubviewAtIndex(int index) const {
103  assert(index >= 0);
104  int i = absoluteColumnNumberFromSubviewIndex(index);
105  int j = absoluteRowNumberFromSubviewIndex(index);
106  int type = m_dataSource->typeAtLocation(i, j);
107  return type;
108 }
109 
110 int TableView::ContentView::typeIndexFromSubviewIndex(int index, int type) const {
111  int typeIndex = 0;
112  for (int k = 0; k < index; k++) {
113  if (typeOfSubviewAtIndex(k) == type) {
114  typeIndex++;
115  }
116  }
117  assert(typeIndex < m_dataSource->reusableCellCount(type));
118  return typeIndex;
119 }
120 
122  int relativeX = x-columnsScrollingOffset();
123  int relativeY = y-rowsScrollingOffset();
124  int type = m_dataSource->typeAtLocation(x, y);
125  int index = relativeY*numberOfDisplayableColumns()+relativeX;
126  int typeIndex = typeIndexFromSubviewIndex(index, type);
127  return m_dataSource->reusableCell(typeIndex, type);
128 }
129 
130 #if ESCHER_VIEW_LOGGING
131 const char * TableView::ContentView::className() const {
132  return "TableView::ContentView";
133 }
134 #endif
135 
136 int TableView::ContentView::numberOfSubviews() const {
137  int result = numberOfDisplayableRows() * numberOfDisplayableColumns();
138  return result;
139 }
140 
141 int TableView::ContentView::absoluteColumnNumberFromSubviewIndex(int index) const {
142  /* "x = i % columns" but we avoid a call to modulo not to implement
143  * "__aeabi_idivmod" */
144  int j = index / numberOfDisplayableColumns();
145  int i = index - j * numberOfDisplayableColumns();
146  int columnOffset = columnsScrollingOffset();
147  return i + columnOffset;
148 }
149 
150 int TableView::ContentView::absoluteRowNumberFromSubviewIndex(int index) const {
151  int j = index / numberOfDisplayableColumns();
152  int rowOffset = rowsScrollingOffset();
153  return j + rowOffset;
154 }
155 
156 View * TableView::ContentView::subviewAtIndex(int index) {
157  int type = typeOfSubviewAtIndex(index);
158  int typeIndex = typeIndexFromSubviewIndex(index, type);
159  return m_dataSource->reusableCell(typeIndex, type);
160 }
161 
162 void TableView::ContentView::layoutSubviews() {
163  for (int index=0; index<numberOfSubviews(); index++) {
164  View * cell = subview(index);
165  int i = absoluteColumnNumberFromSubviewIndex(index);
166  int j = absoluteRowNumberFromSubviewIndex(index);
167  m_dataSource->willDisplayCellAtLocation((HighlightCell *)cell, i, j);
168 
169  KDCoordinate rowHeight = m_dataSource->rowHeight(j);
170  KDCoordinate columnWidth = this->columnWidth(i);
171  KDCoordinate verticalOffset = m_dataSource->cumulatedHeightFromIndex(j);
172  KDCoordinate horizontalOffset = m_dataSource->cumulatedWidthFromIndex(i);
173  KDRect cellFrame(horizontalOffset, verticalOffset,
174  columnWidth+m_horizontalCellOverlap, rowHeight+m_verticalCellOverlap);
175  cell->setFrame(cellFrame);
176  }
177 }
178 
179 
180 int TableView::ContentView::numberOfFullyDisplayableRows() const {
181  // The number of displayable rows taking into accounts margins
182  int rowOffsetWithMargin = m_dataSource->indexFromCumulatedHeight(m_tableView->contentOffset().y() +
183  m_tableView->topMargin());
184  int displayedHeightWithOffsetAndMargin = m_dataSource->indexFromCumulatedHeight(m_tableView->maxContentHeightDisplayableWithoutScrolling() +
185  m_tableView->contentOffset().y() + m_tableView->topMargin());
186  return displayedHeightWithOffsetAndMargin - rowOffsetWithMargin;
187 }
188 
189 int TableView::ContentView::numberOfFullyDisplayableColumns() const {
190  // The number of displayable rows taking into accounts margins
191  int columnOffsetWithMargin = m_dataSource->indexFromCumulatedWidth(m_tableView->contentOffset().x() +
192  m_tableView->leftMargin());
193  int displayedWidthWithOffsetAndMargin = m_dataSource->indexFromCumulatedWidth(m_tableView->maxContentWidthDisplayableWithoutScrolling() +
194  m_tableView->contentOffset().x() + m_tableView->leftMargin());
195  return displayedWidthWithOffsetAndMargin - columnOffsetWithMargin;
196 }
197 
198 int TableView::ContentView::numberOfDisplayableRows() const {
199  int rowOffset = rowsScrollingOffset();
200  int displayedHeightWithOffset = m_dataSource->indexFromCumulatedHeight(m_tableView->bounds().height() + m_tableView->contentOffset().y());
201  return MIN(
202  m_dataSource->numberOfRows(),
203  displayedHeightWithOffset + 1
204  ) - rowOffset;
205 }
206 
207 int TableView::ContentView::numberOfDisplayableColumns() const {
208  int columnOffset = columnsScrollingOffset();
209  int displayedWidthWithOffset = m_dataSource->indexFromCumulatedWidth(m_tableView->bounds().width() + m_tableView->contentOffset().x());
210  return MIN(
211  m_dataSource->numberOfColumns(),
212  displayedWidthWithOffset + 1
213  ) - columnOffset;
214 }
215 
216 int TableView::ContentView::rowsScrollingOffset() const {
217  /* Here, we want to translate the offset at which our tableView is displaying
218  * us into an integer offset we can use to ask cells to our data source. */
219  KDCoordinate invisibleHeight = m_tableView->contentOffset().y()-m_tableView->topMargin();
220  invisibleHeight = invisibleHeight < 0 ? 0 : invisibleHeight;
221  return m_dataSource->indexFromCumulatedHeight(invisibleHeight);
222 }
223 
224 int TableView::ContentView::columnsScrollingOffset() const {
225  /* Here, we want to translate the offset at which our tableView is displaying
226  * us into an integer offset we can use to ask cells to our data source. */
227  KDCoordinate invisibleWidth = m_tableView->contentOffset().x()-m_tableView->leftMargin();
228  invisibleWidth = invisibleWidth < 0 ? 0 : invisibleWidth;
229  return m_dataSource->indexFromCumulatedWidth(invisibleWidth);
230 }
#define assert(e)
Definition: assert.h:9
#define MIN(x, y)
Definition: table_view.cpp:8
void setFrame(KDRect frame)
Definition: view.cpp:125
int16_t KDCoordinate
Definition: coordinate.h:6
ContentView(TableView *tableView, TableViewDataSource *dataSource, KDCoordinate horizontalCellOverlap, KDCoordinate verticalCellOverlap)
Definition: table_view.cpp:55
void layoutSubviews() override
Definition: table_view.cpp:40
virtual void scrollToCell(int i, int j)
Definition: table_view.cpp:26
KDSize minimalSizeForOptimalDisplay() const override
Definition: table_view.cpp:64
HighlightCell * cellAtLocation(int i, int j)
Definition: table_view.cpp:30
void layoutSubviews() override
void scrollToCell(int i, int j) const
Definition: table_view.cpp:93
TableViewDataSource * dataSource()
Definition: table_view.cpp:20
void setSize(KDSize size)
Definition: view.cpp:120
Definition: size.h:6
void reloadCellAtLocation(int i, int j)
Definition: table_view.cpp:49
KDSize minimalSizeForOptimalDisplay() const override
Definition: table_view.cpp:16
Definition: rect.h:26
Definition: view.h:23
TableViewDataSource * dataSource()
Definition: table_view.cpp:68
ContentView m_contentView
Definition: table_view.h:73
HighlightCell * cellAtLocation(int i, int j)
Definition: table_view.cpp:121
void reloadCellAtLocation(int i, int j)
Definition: table_view.cpp:98
TableView(TableViewDataSource *dataSource, ScrollViewDataSource *scrollDataSource)
Definition: table_view.cpp:10
View * subview(int index)
Definition: view.cpp:111