[app/external] External apps on home menu.

This commit is contained in:
M4x1m3
2020-05-04 14:17:19 +02:00
parent bb9f52b355
commit becada912a
12 changed files with 156 additions and 8 deletions

View File

@@ -22,6 +22,14 @@ ifdef FORCE_EXTERNAL
apps_list = ${EPSILON_APPS}
endif
ifdef HOME_DISPLAY_EXTERNALS
ifneq ($(filter external,$(apps_list)),)
SFLAGS += -DHOME_DISPLAY_EXTERNALS
else
$(warning HOME_DISPLAY_EXTERNALS is set but external isn't included, ignoring flag.)
endif
endif
.PHONY: info
info:
@echo "EPSILON_VERSION = $(EPSILON_VERSION)"

View File

@@ -1,3 +1,12 @@
ifdef HOME_DISPLAY_EXTERNALS
app_external_src = $(addprefix apps/external/,\
extapp_api.cpp \
archive.cpp \
)
else
apps += External::App
app_headers += apps/external/app.h
@@ -9,6 +18,10 @@ app_external_src = $(addprefix apps/external/,\
pointer_text_table_cell.cpp \
)
$(eval $(call depends_on_image,apps/external/app.cpp,apps/external/external_icon.png))
endif
SFLAGS += -Iapps/external/
EXTAPP_PATH ?= apps/external/app/
@@ -34,4 +47,3 @@ i18n_files += $(addprefix apps/external/,\
base.universal.i18n\
)
$(eval $(call depends_on_image,apps/external/app.cpp,apps/external/external_icon.png))

View File

@@ -115,9 +115,44 @@ size_t numberOfFiles() {
return count;
}
bool executableAtIndex(size_t index, File &entry) {
File dummy;
size_t count;
size_t final_count = 0;
for (count = 0; fileAtIndex(count, dummy); count++) {
if (dummy.isExecutable) {
if (final_count == index) {
entry = dummy;
return true;
}
final_count++;
}
}
return false;
}
size_t numberOfExecutables() {
File dummy;
size_t count;
size_t final_count = 0;
for (count = 0; fileAtIndex(count, dummy); count++)
if (dummy.isExecutable)
final_count++;
return final_count;
}
#else
bool fileAtIndex(size_t index, File &entry) {
if (index != 0)
return false;
entry.name = "Built-in";
entry.data = NULL;
entry.dataLength = 0;
@@ -125,6 +160,14 @@ bool fileAtIndex(size_t index, File &entry) {
return true;
}
bool executableAtIndex(size_t index, File &entry) {
return fileAtIndex(index, entry);
}
size_t numberOfExecutables() {
return 1;
}
extern "C" void extapp_main(void);
uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) {

View File

@@ -19,6 +19,8 @@ struct File {
bool fileAtIndex(size_t index, File &entry);
int indexFromName(const char *name);
size_t numberOfFiles();
size_t numberOfExecutables();
bool executableAtIndex(size_t index, File &entry);
uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize);
}

View File

@@ -24,9 +24,18 @@ App::Descriptor * App::Snapshot::descriptor() {
return &descriptor;
}
void App::didBecomeActive(Window * window) {
::App::didBecomeActive(window);
m_window = window;
}
void App::redraw() {
m_window->redraw(true);
}
App::App(Snapshot * snapshot) :
::App(snapshot, &m_controller, I18n::Message::Warning),
m_controller(&m_modalViewController, snapshot)
m_controller(&m_modalViewController, snapshot, this)
{
}

View File

@@ -18,6 +18,8 @@ public:
App * unpack(Container * container) override;
Descriptor * descriptor() override;
};
void redraw();
virtual void didBecomeActive(Window * window);
static App * app() {
return static_cast<App *>(Container::activeApp());
}
@@ -25,9 +27,18 @@ public:
return static_cast<Snapshot *>(::App::snapshot());
}
TELEMETRY_ID("Home");
#if HOME_DISPLAY_EXTERNALS
int heapSize() { return k_externalHeapSize; }
char * heap() { return m_externalHeap; }
#endif
private:
App(Snapshot * snapshot);
Controller m_controller;
#if HOME_DISPLAY_EXTERNALS
static constexpr int k_externalHeapSize = 80000;
char m_externalHeap[k_externalHeapSize];
#endif
Window * m_window;
};
}

View File

@@ -31,6 +31,12 @@ void AppCell::layoutSubviews(bool force) {
m_nameView.setFrame(KDRect((bounds().width()-nameSize.width())/2-k_nameWidthMargin, bounds().height()-nameSize.height() - 2*k_nameHeightMargin, nameSize.width()+2*k_nameWidthMargin, nameSize.height()+2*k_nameHeightMargin), force);
}
void AppCell::setExtAppDescriptor(const char* name) {
// m_iconView.setImage(descriptor->icon());
m_nameView.setText(name);
layoutSubviews();
}
void AppCell::setAppDescriptor(::App::Descriptor * descriptor) {
m_iconView.setImage(descriptor->icon());
m_nameView.setMessage(descriptor->name());

View File

@@ -17,6 +17,7 @@ public:
void setVisible(bool visible);
void reloadCell() override;
void setAppDescriptor(::App::Descriptor * appDescriptor);
void setExtAppDescriptor(const char* name);
private:
static constexpr KDCoordinate k_iconMargin = 22;
static constexpr KDCoordinate k_iconWidth = 55;

View File

@@ -6,6 +6,10 @@ extern "C" {
#include <assert.h>
}
#ifdef HOME_DISPLAY_EXTERNALS
#include "../external/archive.h"
#endif
namespace Home {
Controller::ContentView::ContentView(Controller * controller, SelectableTableViewDataSource * selectionDataSource) :
@@ -49,16 +53,45 @@ void Controller::ContentView::layoutSubviews(bool force) {
m_selectableTableView.setFrame(bounds(), force);
}
Controller::Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource) :
Controller::Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource, ::App * app) :
ViewController(parentResponder),
m_view(this, selectionDataSource)
{
m_app = app;
}
bool Controller::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
AppsContainer * container = AppsContainer::sharedAppsContainer();
::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1);
int index = selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1;
#ifdef HOME_DISPLAY_EXTERNALS
if (index >= container->numberOfApps()) {
External::Archive::File executable;
if (External::Archive::executableAtIndex(index - container->numberOfApps(), executable)) {
uint32_t res = External::Archive::executeFile(executable.name, ((App *)m_app)->heap(), ((App *)m_app)->heapSize());
((App*)m_app)->redraw();
switch(res) {
case 0:
break;
case 1:
Container::activeApp()->displayWarning(I18n::Message::ExternalAppApiMismatch);
break;
case 2:
Container::activeApp()->displayWarning(I18n::Message::StorageMemoryFull1);
break;
default:
Container::activeApp()->displayWarning(I18n::Message::ExternalAppExecError);
break;
}
return true;
}
} else {
#endif
::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(index);
if (((GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch || GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::NoSymNoText) && selectedSnapshot->descriptor()->examinationLevel() < 2) ||
((GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Standard || GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::NoSym) && selectedSnapshot->descriptor()->examinationLevel() < 1)) {
App::app()->displayWarning(I18n::Message::ForbidenAppInExamMode1, I18n::Message::ForbidenAppInExamMode2);
@@ -67,6 +100,9 @@ bool Controller::handleEvent(Ion::Events::Event event) {
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
}
#ifdef HOME_DISPLAY_EXTERNALS
}
#endif
return true;
}
@@ -134,7 +170,19 @@ void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
AppsContainer * container = AppsContainer::sharedAppsContainer();
int appIndex = (j*k_numberOfColumns+i)+1;
if (appIndex >= container->numberOfApps()) {
#ifdef HOME_DISPLAY_EXTERNALS
External::Archive::File app_file;
if (External::Archive::executableAtIndex(appIndex - container->numberOfApps(), app_file)) {
appCell->setExtAppDescriptor(app_file.name);
appCell->setVisible(true);
} else {
appCell->setVisible(false);
}
#else
appCell->setVisible(false);
#endif
} else {
appCell->setVisible(true);
::App::Descriptor * descriptor = container->appSnapshotAtIndex(appIndex)->descriptor();
@@ -145,7 +193,11 @@ void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
int Controller::numberOfIcons() const {
AppsContainer * container = AppsContainer::sharedAppsContainer();
assert(container->numberOfApps() > 0);
#ifdef HOME_DISPLAY_EXTERNALS
return container->numberOfApps() - 1 + External::Archive::numberOfExecutables();
#else
return container->numberOfApps() - 1;
#endif
}
void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection) {
@@ -162,7 +214,7 @@ void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previo
* background complete redrawing but the code is a bit
* clumsy. */
if (t->selectedRow() == numberOfRows()-1) {
m_view.reloadBottomRow(this, container->numberOfApps()-1, k_numberOfColumns);
m_view.reloadBottomRow(this, this->numberOfIcons(), k_numberOfColumns);
}
/* To prevent the selectable table view to select cells that are unvisible,
* we reselect the previous selected cell as soon as the selected cell is
@@ -170,7 +222,7 @@ void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previo
* stay on a unvisible cell and to initialize the first cell on a visible one
* (so the previous one is always visible). */
int appIndex = (t->selectedColumn()+t->selectedRow()*k_numberOfColumns)+1;
if (appIndex >= container->numberOfApps()) {
if (appIndex >= this->numberOfIcons() + 1) {
t->selectCellAtLocation(previousSelectedCellX, previousSelectedCellY);
}
}

View File

@@ -8,7 +8,7 @@ namespace Home {
class Controller : public ViewController, public SimpleTableViewDataSource, public SelectableTableViewDelegate {
public:
Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource);
Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource, App * app);
View * view() override;
@@ -49,6 +49,7 @@ private:
static constexpr int k_cellWidth = 104;
ContentView m_view;
AppCell m_cells[k_maxNumberOfCells];
App * m_app;
};
}

View File

@@ -15,6 +15,7 @@ public:
KDSize minimalSizeForOptimalDisplay() const override;
private:
I18n::Message m_message;
const char* m_text = 0;
};
#endif

View File

@@ -9,11 +9,13 @@ MessageTextView::MessageTextView(const KDFont * font, I18n::Message message, flo
}
const char * MessageTextView::text() const {
if (m_text)
return m_text;
return I18n::translate(m_message);
}
void MessageTextView::setText(const char * text) {
assert(false);
m_text = text;
}
void MessageTextView::setMessage(I18n::Message message) {