Numworks Epsilon  1.4.1
Graphing Calculator Operating System
stack_view_controller.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <assert.h>
3 }
5 #include <escher/app.h>
6 #include <escher/metric.h>
7 
8 StackViewController::ControllerView::ControllerView() :
9  View(),
10  m_contentView(nullptr),
11  m_numberOfStacks(0),
12  m_displayStackHeaders(true)
13 {
14 }
15 
16 void StackViewController::ControllerView::shouldDisplayStackHearders(bool shouldDisplay) {
17  m_displayStackHeaders = shouldDisplay;
18 }
19 
20 void StackViewController::ControllerView::setContentView(View * view) {
21  m_contentView = view;
22  layoutSubviews();
23  markRectAsDirty(bounds());
24 }
25 
26 void StackViewController::ControllerView::pushStack(Frame frame) {
27  m_stackViews[m_numberOfStacks].setNamedController(frame.viewController());
28  m_stackViews[m_numberOfStacks].setTextColor(frame.textColor());
29  m_stackViews[m_numberOfStacks].setBackgroundColor(frame.backgroundColor());
30  m_stackViews[m_numberOfStacks].setSeparatorColor(frame.separatorColor());
31  m_numberOfStacks++;
32 }
33 
34 void StackViewController::ControllerView::popStack() {
35  assert(m_numberOfStacks > 0);
36  m_numberOfStacks--;
37 }
38 
39 void StackViewController::ControllerView::layoutSubviews() {
40  KDCoordinate width = m_frame.width();
41  if (m_displayStackHeaders) {
42  for (int i=0; i<m_numberOfStacks; i++) {
43  m_stackViews[i].setFrame(KDRect(0, Metric::StackTitleHeight*i, width, Metric::StackTitleHeight + 1));
44  }
45  }
46  if (m_contentView) {
47  KDCoordinate separatorHeight = m_numberOfStacks > 0 ? 1 : 0;
48  KDRect contentViewFrame = KDRect( 0,
49  m_displayStackHeaders * (m_numberOfStacks * Metric::StackTitleHeight + separatorHeight),
50  width,
51  m_frame.height() - m_displayStackHeaders * m_numberOfStacks * Metric::StackTitleHeight);
52  m_contentView->setFrame(contentViewFrame);
53  }
54 }
55 
56 int StackViewController::ControllerView::numberOfSubviews() const {
57  return (m_displayStackHeaders ? m_numberOfStacks : 0) + (m_contentView == nullptr ? 0 : 1);
58 }
59 
60 View * StackViewController::ControllerView::subviewAtIndex(int index) {
61  if (!m_displayStackHeaders) {
62  assert(index == 0);
63  return m_contentView;
64  }
65  if (index < m_numberOfStacks) {
66  assert(index >= 0);
67  return &m_stackViews[index];
68  } else {
69  assert(index == m_numberOfStacks);
70  return m_contentView;
71  }
72 }
73 
74 #if ESCHER_VIEW_LOGGING
75 const char * StackViewController::ControllerView::className() const {
76  return "StackViewController::ControllerView";
77 }
78 #endif
79 
80 StackViewController::StackViewController(Responder * parentResponder, ViewController * rootViewController, KDColor textColor, KDColor backgroundColor, KDColor separatorColor) :
81  ViewController(parentResponder),
82  m_view(),
83  m_numberOfChildren(0),
84  m_isVisible(false)
85 {
86  pushModel(Frame(rootViewController, textColor, backgroundColor, separatorColor));
87  rootViewController->setParentResponder(this);
88 }
89 
91  ViewController * vc = m_childrenFrame[0].viewController();
92  return vc->title();
93 }
94 
95 void StackViewController::push(ViewController * vc, KDColor textColor, KDColor backgroundColor, KDColor separatorColor) {
96  Frame frame = Frame(vc, textColor, backgroundColor, separatorColor);
97  /* Add the frame to the model */
98  pushModel(frame);
99  if (!m_isVisible) {
100  return;
101  }
102  /* Load stack view if the View Controller has a title. */
104  m_view.pushStack(frame);
105  }
106  setupActiveViewController();
107  if (m_numberOfChildren > 1) {
108  m_childrenFrame[m_numberOfChildren-2].viewController()->viewDidDisappear();
109  }
110 }
111 
113  assert(m_numberOfChildren > 0);
114  ViewController * vc = m_childrenFrame[m_numberOfChildren-1].viewController();
116  m_view.popStack();
117  }
118  m_numberOfChildren--;
119  setupActiveViewController();
120  vc->setParentResponder(nullptr);
121  vc->viewDidDisappear();
122 }
123 
125  return m_numberOfChildren;
126 }
127 
128 void StackViewController::pushModel(Frame frame) {
129  m_childrenFrame[m_numberOfChildren++] = frame;
130 }
131 
132 void StackViewController::setupActiveViewController() {
133  ViewController * vc = m_childrenFrame[m_numberOfChildren-1].viewController();
134  vc->setParentResponder(this);
135  m_view.shouldDisplayStackHearders(vc->displayParameter() != ViewController::DisplayParameter::WantsMaximumSpace);
136  m_view.setContentView(vc->view());
137  vc->viewWillAppear();
138  vc->setParentResponder(this);
139  app()->setFirstResponder(vc);
140 }
141 
143  ViewController * vc = m_childrenFrame[m_numberOfChildren-1].viewController();
144  app()->setFirstResponder(vc);
145 }
146 
148  if (event == Ion::Events::Back && m_numberOfChildren > 1) {
149  pop();
150  return true;
151  }
152  return false;
153 }
154 
156  return &m_view;
157 }
158 
160  /* Load the stack view */
161  for (int i = 0; i < m_numberOfChildren; i++) {
162  ViewController * childrenVC = m_childrenFrame[i].viewController();
163  if (childrenVC->title() != nullptr && childrenVC->displayParameter() != ViewController::DisplayParameter::DoNotShowOwnTitle) {
164  m_view.pushStack(m_childrenFrame[i]);
165  }
166  }
167  /* Load the visible controller view */
168  ViewController * vc = m_childrenFrame[m_numberOfChildren-1].viewController();
169  if (m_numberOfChildren > 0 && vc) {
170  m_view.setContentView(vc->view());
171  m_view.shouldDisplayStackHearders(vc->displayParameter() != ViewController::DisplayParameter::WantsMaximumSpace);
172  vc->viewWillAppear();
173  }
174  m_isVisible = true;
175 }
176 
178  ViewController * vc = m_childrenFrame[m_numberOfChildren-1].viewController();
179  if (m_numberOfChildren > 0 && vc) {
180  vc->viewDidDisappear();
181  }
182  for (int i = 0; i < m_view.numberOfStacks(); i++) {
183  m_view.popStack();
184  }
185  m_isVisible = false;
186 }
#define assert(e)
Definition: assert.h:9
static constexpr KDCoordinate StackTitleHeight
Definition: metric.h:28
int16_t KDCoordinate
Definition: coordinate.h:6
StackViewController(Responder *parentResponder, ViewController *rootViewController, KDColor textColor=Palette::SubTab, KDColor backgroundColor=KDColorWhite, KDColor separatorColor=Palette::GreyBright)
void push(ViewController *vc, KDColor textColor=Palette::SubTab, KDColor backgroundColor=KDColorWhite, KDColor separatorColor=Palette::GreyBright)
const char * title() override
virtual View * view()=0
constexpr Event Back
Definition: events.h:66
void viewDidDisappear() override
void setParentResponder(Responder *responder)
Definition: responder.cpp:16
bool handleEvent(Ion::Events::Event event) override
virtual void viewWillAppear()
#define false
Definition: stdbool.h:9
Definition: rect.h:26
Definition: color.h:6
void didBecomeFirstResponder() override
virtual const char * title()
void setFirstResponder(Responder *responder)
Definition: app.cpp:62
Definition: view.h:23
virtual void viewDidDisappear()
App * app()
Definition: responder.cpp:77
virtual DisplayParameter displayParameter()
#define true
Definition: stdbool.h:8