Numworks Epsilon  1.4.1
Graphing Calculator Operating System
modal_view_controller.cpp
Go to the documentation of this file.
2 #include <escher/app.h>
3 #include <assert.h>
4 
5 ModalViewController::ContentView::ContentView() :
6  View(),
7  m_regularView(nullptr),
8  m_currentModalView(nullptr),
9  m_isDisplayingModal(false),
10  m_verticalAlignment(0.0f),
11  m_horizontalAlignment(0.0f),
12  m_topMargin(0),
13  m_leftMargin(0),
14  m_bottomMargin(0),
15  m_rightMargin(0)
16 {
17 }
18 
19 void ModalViewController::ContentView::setMainView(View * regularView) {
20  if (m_regularView != regularView) {
21  m_regularView = regularView;
22  }
23 }
24 
25 int ModalViewController::ContentView::numberOfSubviews() const {
26  KDRect regularFrame = bounds();
27  KDRect modalFrame = frame();
28  bool shouldDrawTheRegularViewBehind = !modalFrame.contains(regularFrame.topLeft()) || !modalFrame.contains(regularFrame.bottomRight());
29  return 1 + (m_isDisplayingModal && shouldDrawTheRegularViewBehind);
30 }
31 
32 View * ModalViewController::ContentView::subviewAtIndex(int index) {
33  switch (index) {
34  case 0:
35  if (m_isDisplayingModal && numberOfSubviews() == 1) {
36  return m_currentModalView;
37  }
38  return m_regularView;
39  case 1:
40  if (numberOfSubviews() == 2) {
41  return m_currentModalView;
42  } else {
43  assert(false);
44  return nullptr;
45  }
46  default:
47  assert(false);
48  return nullptr;
49  }
50 }
51 
52 KDRect ModalViewController::ContentView::frame() const {
53  KDSize modalSize = m_isDisplayingModal ? m_currentModalView->minimalSizeForOptimalDisplay() : KDSize(0,0);
54  KDCoordinate modalHeight = modalSize.height();
55  modalHeight = modalHeight == 0 ? bounds().height()-m_topMargin-m_bottomMargin : modalHeight;
56  KDCoordinate modalWidth = modalSize.width();
57  modalWidth = modalWidth == 0 ? bounds().width()-m_leftMargin-m_rightMargin : modalWidth;
58  KDRect modalViewFrame(m_leftMargin + m_horizontalAlignment*(bounds().width()-m_leftMargin-m_rightMargin-modalWidth),
59  m_topMargin+m_verticalAlignment*(bounds().height()-m_topMargin-m_bottomMargin-modalHeight), modalWidth, modalHeight);
60  return modalViewFrame;
61 }
62 
63 void ModalViewController::ContentView::layoutSubviews() {
64  assert(m_regularView != nullptr);
65  m_regularView->setFrame(bounds());
66  if (m_isDisplayingModal) {
67  assert(m_currentModalView != nullptr);
68  m_currentModalView->setFrame(frame());
69  }
70 }
71 
72 void ModalViewController::ContentView::presentModalView(View * modalView, float verticalAlignment, float horizontalAlignment,
73  KDCoordinate topMargin, KDCoordinate leftMargin, KDCoordinate bottomMargin, KDCoordinate rightMargin) {
74  m_isDisplayingModal = true;
75  m_currentModalView = modalView;
76  m_horizontalAlignment = horizontalAlignment;
77  m_verticalAlignment = verticalAlignment;
78  m_topMargin = topMargin;
79  m_leftMargin = leftMargin;
80  m_bottomMargin = bottomMargin;
81  m_rightMargin = rightMargin;
82  markRectAsDirty(frame());
83  layoutSubviews();
84 }
85 
86 void ModalViewController::ContentView::dismissModalView() {
87  m_isDisplayingModal = false;
88  markRectAsDirty(frame());
89  m_currentModalView->resetSuperview();
90  m_currentModalView = nullptr;
91  layoutSubviews();
92 }
93 
94 bool ModalViewController::ContentView::isDisplayingModal() const {
95  return m_isDisplayingModal;
96 }
97 
99  ViewController(parentResponder),
100  m_contentView(),
101  m_previousResponder(child),
102  m_currentModalViewController(nullptr),
103  m_regularViewController(child)
104 {
105 }
106 
108  return &m_contentView;
109 }
110 
112  return m_contentView.isDisplayingModal();
113 }
114 
115 void ModalViewController::displayModalViewController(ViewController * vc, float verticalAlignment, float horizontalAlignment,
116  KDCoordinate topMargin, KDCoordinate leftMargin, KDCoordinate bottomMargin, KDCoordinate rightMargin) {
117  m_currentModalViewController = vc;
118  vc->setParentResponder(this);
119  m_previousResponder = app()->firstResponder();
120  m_contentView.presentModalView(vc->view(), verticalAlignment, horizontalAlignment, topMargin, leftMargin, bottomMargin, rightMargin);
121  m_currentModalViewController->viewWillAppear();
122  app()->setFirstResponder(vc);
123 }
124 
126  m_currentModalViewController->viewDidDisappear();
127  app()->setFirstResponder(m_previousResponder);
128  m_contentView.dismissModalView();
129  m_currentModalViewController = nullptr;
130 }
131 
133  if (m_contentView.isDisplayingModal()) {
134  app()->setFirstResponder(m_currentModalViewController);
135  }
136  app()->setFirstResponder(m_regularViewController);
137 }
138 
140  if (!m_contentView.isDisplayingModal()) {
141  return false;
142  }
143  if (event == Ion::Events::Back) {
145  return true;
146  }
147  return false;
148 }
149 
151  m_contentView.setMainView(m_regularViewController->view());
152  m_contentView.layoutSubviews();
153  if (m_contentView.isDisplayingModal()) {
154  m_currentModalViewController->viewWillAppear();
155  }
156  m_regularViewController->viewWillAppear();
157 }
158 
160  if (m_contentView.isDisplayingModal()) {
161  m_currentModalViewController->viewDidDisappear();
162  }
163  m_regularViewController->viewDidDisappear();
164 }
bool handleEvent(Ion::Events::Event event) override
#define assert(e)
Definition: assert.h:9
bool contains(KDPoint p) const
Definition: rect.cpp:104
KDPoint bottomRight() const
Definition: rect.h:48
int16_t KDCoordinate
Definition: coordinate.h:6
constexpr KDCoordinate width() const
Definition: size.h:10
virtual View * view()=0
constexpr Event Back
Definition: events.h:66
Definition: size.h:6
void viewDidDisappear() override
ModalViewController(Responder *parentResponder, ViewController *child)
void didBecomeFirstResponder() override
void setParentResponder(Responder *responder)
Definition: responder.cpp:16
virtual void viewWillAppear()
#define false
Definition: stdbool.h:9
Responder * firstResponder()
Definition: app.cpp:58
Definition: rect.h:26
KDPoint topLeft() const
Definition: rect.h:47
void displayModalViewController(ViewController *vc, float verticalAlignment, float horizontalAlignment, KDCoordinate topMargin=0, KDCoordinate leftMargin=0, KDCoordinate bottomMargin=0, KDCoordinate rightMargin=0)
void setFirstResponder(Responder *responder)
Definition: app.cpp:62
Definition: view.h:23
virtual void viewDidDisappear()
App * app()
Definition: responder.cpp:77
constexpr KDCoordinate height() const
Definition: size.h:11