mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[Escher] Add a Container that lets us run multiple apps
Change-Id: I674348ed0ff48934eb248dc48735f4ba13c34692
This commit is contained in:
@@ -2,6 +2,7 @@ include apps/graph/Makefile
|
||||
#include apps/picview/Makefile
|
||||
|
||||
app_objs += $(addprefix apps/,\
|
||||
apps_container.o\
|
||||
main.o\
|
||||
)
|
||||
|
||||
|
||||
34
apps/apps_container.cpp
Normal file
34
apps/apps_container.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "apps_container.h"
|
||||
|
||||
AppsContainer::AppsContainer() :
|
||||
Container()
|
||||
{
|
||||
}
|
||||
|
||||
bool AppsContainer::handleEvent(ion_event_t event) {
|
||||
if (event == F1) {
|
||||
#if USE_PIC_VIEW_APP
|
||||
if (activeApp() == &m_picViewApp) {
|
||||
Container::switchTo(&m_graphApp);
|
||||
} else {
|
||||
Container::switchTo(&m_picViewApp);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AppsContainer::switchTo(AppId appId) {
|
||||
Container::switchTo(appWithId(appId));
|
||||
}
|
||||
|
||||
App * AppsContainer::appWithId(AppId appId) {
|
||||
App * apps[] = {
|
||||
&m_graphApp
|
||||
#if USE_PIC_VIEW_APP
|
||||
, &m_picViewApp
|
||||
#endif
|
||||
};
|
||||
return apps[(int)appId];
|
||||
};
|
||||
27
apps/apps_container.h
Normal file
27
apps/apps_container.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef APPS_CONTAINER_H
|
||||
#define APPS_CONTAINER_H
|
||||
|
||||
#include "graph/graph_app.h"
|
||||
#define USE_PIC_VIEW_APP 0
|
||||
#if USE_PIC_VIEW_APP
|
||||
#include "picview/picview_app.h"
|
||||
#endif
|
||||
|
||||
class AppsContainer : public Container {
|
||||
public:
|
||||
AppsContainer();
|
||||
enum class AppId {
|
||||
Graph = 0,
|
||||
PicView = 1
|
||||
};
|
||||
void switchTo(AppId appId);
|
||||
bool handleEvent(ion_event_t event) override;
|
||||
private:
|
||||
App * appWithId(AppId appId);
|
||||
GraphApp m_graphApp;
|
||||
#if USE_PIC_VIEW_APP
|
||||
PicViewApp m_picViewApp;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,15 +1,7 @@
|
||||
#include "graph/graph_app.h"
|
||||
|
||||
#define USE_PIC_VIEW_APP 0
|
||||
#if USE_PIC_VIEW_APP
|
||||
#include "picview/picview_app.h"
|
||||
#endif
|
||||
#include "apps_container.h"
|
||||
|
||||
void ion_app() {
|
||||
#if USE_PIC_VIEW_APP
|
||||
PicViewApp picViewApp = PicViewApp();
|
||||
picViewApp.run();
|
||||
#endif
|
||||
GraphApp graphApp = GraphApp();
|
||||
graphApp.run();
|
||||
AppsContainer container;
|
||||
container.switchTo(AppsContainer::AppId::Graph);
|
||||
container.run();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
PicViewApp::PicViewApp() :
|
||||
App(),
|
||||
m_picViewController(PicViewController())
|
||||
m_picViewController(PicViewController(this))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "picview_controller.h"
|
||||
|
||||
PicViewController::PicViewController() :
|
||||
ViewController(),
|
||||
PicViewController::PicViewController(Responder * parentResponder) :
|
||||
ViewController(parentResponder),
|
||||
m_view(PicView())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
class PicViewController : public ViewController {
|
||||
public:
|
||||
PicViewController();
|
||||
PicViewController(Responder * parentResponder);
|
||||
View * view() override;
|
||||
private:
|
||||
PicView m_view;
|
||||
|
||||
@@ -3,6 +3,7 @@ SFLAGS += -Iescher/include
|
||||
objs += $(addprefix escher/src/,\
|
||||
app.o\
|
||||
childless_view.o\
|
||||
container.o\
|
||||
responder.o\
|
||||
scroll_view.o\
|
||||
scroll_view_indicator.o\
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define ESCHER_H
|
||||
|
||||
#include <escher/app.h>
|
||||
#include <escher/container.h>
|
||||
#include <escher/responder.h>
|
||||
#include <escher/scroll_view.h>
|
||||
#include <escher/scroll_view_indicator.h>
|
||||
|
||||
@@ -4,26 +4,25 @@
|
||||
#include <escher/responder.h>
|
||||
#include <escher/view_controller.h>
|
||||
|
||||
/* An app is fed events and outputs drawing calls.
|
||||
*
|
||||
* To achieve this, it uses a View hierarchy, and modifies it according to the
|
||||
* events received. The View hierarchy keeps a memory of the area that needs to
|
||||
* be redrawn depending on how it's been modified.
|
||||
*
|
||||
* Multiple App can exist at once.
|
||||
* */
|
||||
|
||||
class App : public Responder {
|
||||
public:
|
||||
App();
|
||||
void run();
|
||||
void setWindow(Window * window);
|
||||
void focus(Responder * responder);
|
||||
void processEvent(ion_event_t event);
|
||||
protected:
|
||||
virtual ViewController * rootViewController() = 0;
|
||||
private:
|
||||
void dispatchEvent(ion_event_t event);
|
||||
Responder * m_focusedResponder;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
void handleEvent(event) {
|
||||
// BACK: I want to do stuff!
|
||||
1/ Reset my text to what it was "before"
|
||||
2/ dismiss
|
||||
dismiss = app->focus(parentResponder());
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
32
escher/include/escher/container.h
Normal file
32
escher/include/escher/container.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef ESCHER_CONTAINER_H
|
||||
#define ESCHER_CONTAINER_H
|
||||
|
||||
/* Container is the entry point of a program using Escher.
|
||||
*
|
||||
* A container contains one or multiple App, and is responsible for running them
|
||||
* together. Currently Container displays a single App fullscreen, but can
|
||||
* switch to any other App.
|
||||
*
|
||||
* When writing an Escher program, you typically subclass Container, and your
|
||||
* subclass owns one or more App. You then call "run()" on your container. */
|
||||
|
||||
#include <escher/app.h>
|
||||
#include <escher/window.h>
|
||||
extern "C" {
|
||||
#include <ion.h>
|
||||
}
|
||||
|
||||
class Container {
|
||||
public:
|
||||
Container();
|
||||
void run();
|
||||
App * activeApp();
|
||||
virtual bool handleEvent(ion_event_t event);
|
||||
protected:
|
||||
void switchTo(App * app);
|
||||
private:
|
||||
App * m_activeApp;
|
||||
Window m_window;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -40,7 +40,7 @@ private:
|
||||
static constexpr uint8_t k_maxNumberOfChildren = 4;
|
||||
ViewController * m_children[k_maxNumberOfChildren];
|
||||
uint8_t m_numberOfChildren;
|
||||
uint8_t m_activeChildIndex;
|
||||
int8_t m_activeChildIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <escher/window.h>
|
||||
extern "C" {
|
||||
#include <ion.h>
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
App::App() :
|
||||
@@ -10,26 +11,21 @@ App::App() :
|
||||
{
|
||||
}
|
||||
|
||||
void App::run() {
|
||||
Window window;
|
||||
window.setFrame(KDRect(0, 0, ION_SCREEN_WIDTH, ION_SCREEN_HEIGHT));
|
||||
View * rootView = rootViewController()->view();
|
||||
|
||||
focus(rootViewController());
|
||||
|
||||
window.setContentView(rootView);
|
||||
rootView->setFrame(window.bounds());
|
||||
|
||||
window.redraw();
|
||||
|
||||
while (true) {
|
||||
ion_event_t event = ion_get_event(); // This is a blocking call
|
||||
dispatchEvent(event);
|
||||
window.redraw();
|
||||
void App::setWindow(Window * window) {
|
||||
ViewController * controller = rootViewController();
|
||||
View * view = controller->view();
|
||||
if (m_focusedResponder == nullptr) {
|
||||
focus(controller);
|
||||
}
|
||||
assert(controller->app() == this);
|
||||
|
||||
window->setContentView(view);
|
||||
view->setFrame(window->bounds());
|
||||
|
||||
window->redraw();
|
||||
}
|
||||
|
||||
void App::dispatchEvent(ion_event_t event) {
|
||||
void App::processEvent(ion_event_t event) {
|
||||
Responder * responder = m_focusedResponder;
|
||||
bool didHandleEvent = false;
|
||||
while (responder) {
|
||||
|
||||
37
escher/src/container.cpp
Normal file
37
escher/src/container.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <escher/container.h>
|
||||
extern "C" {
|
||||
#include <ion.h>
|
||||
}
|
||||
|
||||
Container::Container() :
|
||||
m_activeApp(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void Container::switchTo(App * app) {
|
||||
m_activeApp = app;
|
||||
m_activeApp->setWindow(&m_window);
|
||||
m_window.redraw();
|
||||
}
|
||||
|
||||
App * Container::activeApp() {
|
||||
return m_activeApp;
|
||||
}
|
||||
|
||||
bool Container::handleEvent(ion_event_t event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Container::run() {
|
||||
m_window.setFrame(KDRect(0, 0, ION_SCREEN_WIDTH, ION_SCREEN_HEIGHT));
|
||||
m_window.redraw();
|
||||
|
||||
while (true) {
|
||||
ion_event_t event = ion_get_event(); // This is a blocking call
|
||||
if (handleEvent(event)) {
|
||||
continue;
|
||||
}
|
||||
m_activeApp->processEvent(event);
|
||||
m_window.redraw();
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,9 @@ void TabViewController::setActiveTab(uint8_t i) {
|
||||
View * TabViewController::view() {
|
||||
// We're asked for a view!
|
||||
// Let's populate our tabview
|
||||
setActiveTab(0);
|
||||
if (m_activeChildIndex < 0) {
|
||||
setActiveTab(0);
|
||||
}
|
||||
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user