mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[escher] make an independent class alternate empty view to handle
empty store and add a delegate to the header view controller class Change-Id: I7c4e8342876e9273270772d4bad0db9424276a98
This commit is contained in:
@@ -8,12 +8,16 @@ App::App(Container * container, Context * context) :
|
||||
ExpressionTextFieldDelegate(),
|
||||
m_functionStore(FunctionStore()),
|
||||
m_evaluateContext(EvaluateContext(context)),
|
||||
m_listController(ListController(nullptr, &m_functionStore)),
|
||||
m_listStackViewController(StackViewController(&m_tabViewController, &m_listController)),
|
||||
m_graphController(GraphController(nullptr, &m_functionStore)),
|
||||
m_valuesController(nullptr, &m_functionStore),
|
||||
m_valuesStackViewController(StackViewController(&m_tabViewController, &m_valuesController)),
|
||||
m_tabViewController(&m_inputViewController, &m_listStackViewController, &m_graphController, &m_valuesStackViewController),
|
||||
m_listController(ListController(&m_listHeader, &m_functionStore, &m_listHeader)),
|
||||
m_listHeader(HeaderViewController(nullptr, &m_listController, &m_listController)),
|
||||
m_listStackViewController(StackViewController(&m_tabViewController, &m_listHeader)),
|
||||
m_graphController(GraphController(&m_graphHeader, &m_functionStore, &m_graphHeader)),
|
||||
m_graphHeader(HeaderViewController(nullptr, &m_graphController, &m_graphController)),
|
||||
m_valuesController(&m_valuesHeader, &m_functionStore, &m_valuesHeader),
|
||||
m_valuesHeader(HeaderViewController(&m_valuesAlternateEmptyViewController, &m_valuesController, &m_valuesController)),
|
||||
m_valuesAlternateEmptyViewController(AlternateEmptyViewController(nullptr, &m_valuesHeader, &m_valuesController)),
|
||||
m_valuesStackViewController(StackViewController(&m_tabViewController, &m_valuesAlternateEmptyViewController)),
|
||||
m_tabViewController(&m_inputViewController, &m_listStackViewController, &m_graphHeader, &m_valuesStackViewController),
|
||||
m_inputViewController(&m_modalViewController, &m_tabViewController, this)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -20,9 +20,13 @@ private:
|
||||
FunctionStore m_functionStore;
|
||||
EvaluateContext m_evaluateContext;
|
||||
ListController m_listController;
|
||||
HeaderViewController m_listHeader;
|
||||
StackViewController m_listStackViewController;
|
||||
GraphController m_graphController;
|
||||
HeaderViewController m_graphHeader;
|
||||
ValuesController m_valuesController;
|
||||
HeaderViewController m_valuesHeader;
|
||||
AlternateEmptyViewController m_valuesAlternateEmptyViewController;
|
||||
StackViewController m_valuesStackViewController;
|
||||
TabViewController m_tabViewController;
|
||||
InputViewController m_inputViewController;
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
GraphController::GraphController(Responder * parentResponder, FunctionStore * functionStore) :
|
||||
HeaderViewController(parentResponder, &m_view),
|
||||
GraphController::GraphController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header) :
|
||||
ViewController(parentResponder),
|
||||
HeaderViewDelegate(header),
|
||||
m_view(GraphView(functionStore)),
|
||||
m_headerSelected(false),
|
||||
m_windowButton(Button(this, "Fenetre", Invocation([](void * context, void * sender) {}, this))),
|
||||
@@ -18,7 +19,7 @@ View * GraphController::view() {
|
||||
App * graphApp = (Graph::App *)app();
|
||||
m_view.setContext(graphApp->evaluateContext());
|
||||
}
|
||||
return HeaderViewController::view();
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
const char * GraphController::title() const {
|
||||
@@ -26,7 +27,7 @@ const char * GraphController::title() const {
|
||||
}
|
||||
|
||||
Responder * GraphController::tabController() const{
|
||||
return (parentResponder());
|
||||
return (parentResponder()->parentResponder());
|
||||
}
|
||||
|
||||
int GraphController::numberOfButtons() const {
|
||||
@@ -52,22 +53,22 @@ void GraphController::didBecomeFirstResponder() {
|
||||
bool GraphController::handleEvent(Ion::Events::Event event) {
|
||||
if (m_headerSelected) {
|
||||
if (event == Ion::Events::Down) {
|
||||
setSelectedButton(-1);
|
||||
headerViewController()->setSelectedButton(-1);
|
||||
m_headerSelected = false;
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
setSelectedButton(-1);
|
||||
headerViewController()->setSelectedButton(-1);
|
||||
app()->setFirstResponder(tabController());
|
||||
}
|
||||
return HeaderViewController::handleEvent(event);
|
||||
return headerViewController()->handleEvent(event);
|
||||
} else {
|
||||
if (event == Ion::Events::OK) {
|
||||
m_view.moveCursorRight();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
setSelectedButton(0);
|
||||
headerViewController()->setSelectedButton(0);
|
||||
m_headerSelected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
#include "../function_store.h"
|
||||
|
||||
namespace Graph {
|
||||
class GraphController : public HeaderViewController {
|
||||
class GraphController : public ViewController, public HeaderViewDelegate {
|
||||
public:
|
||||
GraphController(Responder * parentResponder, FunctionStore * functionStore);
|
||||
GraphController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header);
|
||||
const char * title() const override;
|
||||
View * view() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
|
||||
@@ -4,21 +4,29 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
ListController::ListController(Responder * parentResponder, FunctionStore * functionStore) :
|
||||
HeaderViewController(parentResponder, &m_selectableTableView),
|
||||
ListController::ListController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header) :
|
||||
ViewController(parentResponder),
|
||||
HeaderViewDelegate(header),
|
||||
m_selectableTableView(SelectableTableView(this, this)),
|
||||
m_functionStore(functionStore),
|
||||
m_parameterController(ParameterController(this, functionStore))
|
||||
{
|
||||
setVisibleHeader(false);
|
||||
}
|
||||
|
||||
const char * ListController::title() const {
|
||||
return "Fonctions";
|
||||
}
|
||||
|
||||
View * ListController::view() {
|
||||
return &m_selectableTableView;
|
||||
}
|
||||
|
||||
Responder * ListController::tabController() const{
|
||||
return (parentResponder()->parentResponder());
|
||||
return (parentResponder()->parentResponder()->parentResponder());
|
||||
}
|
||||
|
||||
StackViewController * ListController::stackController() const{
|
||||
return (StackViewController *)(parentResponder()->parentResponder());
|
||||
}
|
||||
|
||||
int ListController::numberOfRows() {
|
||||
@@ -106,7 +114,7 @@ void ListController::didBecomeFirstResponder() {
|
||||
}
|
||||
|
||||
void ListController::configureFunction(Function * function) {
|
||||
StackViewController * stack = ((StackViewController *)parentResponder());
|
||||
StackViewController * stack = stackController();
|
||||
m_parameterController.setFunction(function);
|
||||
stack->push(&m_parameterController);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
class ListController : public HeaderViewController, public TableViewDataSource {
|
||||
class ListController : public ViewController, public HeaderViewDelegate, public TableViewDataSource {
|
||||
public:
|
||||
ListController(Responder * parentResponder, FunctionStore * functionStore);
|
||||
ListController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header);
|
||||
const char * title() const override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
bool handleEnter();
|
||||
void didBecomeFirstResponder() override;
|
||||
virtual View * view() override;
|
||||
|
||||
int numberOfRows() override;
|
||||
int numberOfColumns() override;
|
||||
@@ -38,6 +39,7 @@ private:
|
||||
static constexpr KDCoordinate k_functionNameWidth = 65;
|
||||
static constexpr KDCoordinate k_emptyRowHeight = 50;
|
||||
Responder * tabController() const;
|
||||
StackViewController * stackController() const;
|
||||
constexpr static int k_maxNumberOfRows = 6;
|
||||
// !!! CAUTION: The order here is important
|
||||
// The cells should be initialized *before* the TableView!
|
||||
|
||||
@@ -6,50 +6,9 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
/* Content View */
|
||||
|
||||
ValuesController::ContentView::ContentView(View * mainView) :
|
||||
m_noFunctionSelected(PointerTextView("Aucune fonction selectionnee", 0.5f, 0.5f, KDColorBlack, Palette::BackgroundColor)),
|
||||
m_mainView(mainView),
|
||||
m_tableState(TableState::Empty)
|
||||
{
|
||||
}
|
||||
|
||||
void ValuesController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
if (m_tableState == TableState::Empty) {
|
||||
ctx->fillRect(bounds(), Palette::BackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
int ValuesController::ContentView::numberOfSubviews() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
View * ValuesController::ContentView::subviewAtIndex(int index) {
|
||||
assert(index == 0);
|
||||
if (m_tableState == TableState::Empty) {
|
||||
return &m_noFunctionSelected;
|
||||
}
|
||||
return m_mainView;
|
||||
}
|
||||
|
||||
void ValuesController::ContentView::layoutSubviews() {
|
||||
m_noFunctionSelected.setFrame(bounds());
|
||||
m_mainView->setFrame(bounds());
|
||||
}
|
||||
|
||||
void ValuesController::ContentView::setTableState(TableState tableState) {
|
||||
m_tableState = tableState;
|
||||
}
|
||||
|
||||
ValuesController::ContentView::TableState ValuesController::ContentView::tableState() {
|
||||
return m_tableState;
|
||||
}
|
||||
|
||||
/* Value Controller */
|
||||
|
||||
ValuesController::ValuesController(Responder * parentResponder, FunctionStore * functionStore) :
|
||||
HeaderViewController(parentResponder, &m_contentView),
|
||||
ValuesController::ValuesController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header) :
|
||||
ViewController(parentResponder),
|
||||
HeaderViewDelegate(header),
|
||||
m_selectableTableView(SelectableTableView(this, this, k_topMargin, k_rightMargin, k_bottomMargin, k_leftMargin)),
|
||||
m_functionStore(functionStore),
|
||||
m_parameterController(ValuesParameterController(this, &m_interval)),
|
||||
@@ -58,20 +17,41 @@ ValuesController::ValuesController(Responder * parentResponder, FunctionStore *
|
||||
m_derivativeParameterController(DerivativeParameterController(this)),
|
||||
m_setIntervalButton(Button(this, "Regler l'intervalle",Invocation([](void * context, void * sender) {
|
||||
ValuesController * valuesController = (ValuesController *) context;
|
||||
StackViewController * stack = ((StackViewController *)valuesController->parentResponder());
|
||||
StackViewController * stack = ((StackViewController *)valuesController->stackController());
|
||||
stack->push(valuesController->parameterController());
|
||||
}, this))),
|
||||
m_contentView(&m_selectableTableView)
|
||||
}, this)))
|
||||
{
|
||||
m_interval.setStart(0);
|
||||
m_interval.setEnd(10);
|
||||
m_interval.setStep(1);
|
||||
}
|
||||
|
||||
View * ValuesController::view() {
|
||||
return &m_selectableTableView;
|
||||
}
|
||||
|
||||
const char * ValuesController::title() const {
|
||||
return "Valeurs";
|
||||
}
|
||||
|
||||
bool ValuesController::isEmpty() {
|
||||
if (m_functionStore->numberOfActiveFunctions() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * ValuesController::emptyMessage() {
|
||||
if (m_functionStore->numberOfDefinedFunctions() == 0) {
|
||||
return "Aucune fonction";
|
||||
}
|
||||
return "Aucune fonction selectionnee";
|
||||
}
|
||||
|
||||
Responder * ValuesController::defaultController() {
|
||||
return tabController();
|
||||
}
|
||||
|
||||
int ValuesController::numberOfButtons() const {
|
||||
return 1;
|
||||
}
|
||||
@@ -81,7 +61,11 @@ Button * ValuesController::buttonAtIndex(int index) {
|
||||
}
|
||||
|
||||
Responder * ValuesController::tabController() const {
|
||||
return (parentResponder()->parentResponder());
|
||||
return (parentResponder()->parentResponder()->parentResponder()->parentResponder());
|
||||
}
|
||||
|
||||
StackViewController * ValuesController::stackController() const {
|
||||
return (StackViewController *)(parentResponder()->parentResponder()->parentResponder());
|
||||
}
|
||||
|
||||
ViewController * ValuesController::parameterController() {
|
||||
@@ -165,12 +149,7 @@ ValueCell * ValuesController::abscisseCellAtRow(int rowIndex) {
|
||||
}
|
||||
|
||||
void ValuesController::didBecomeFirstResponder() {
|
||||
if (m_functionStore->numberOfDefinedFunctions() == 0 || m_functionStore->numberOfActiveFunctions() == 0) {
|
||||
m_contentView.setTableState(ValuesController::ContentView::TableState::Empty);
|
||||
return;
|
||||
}
|
||||
m_contentView.setTableState(ContentView::TableState::NonEmpty);
|
||||
setSelectedButton(-1);
|
||||
headerViewController()->setSelectedButton(-1);
|
||||
if (m_selectableTableView.selectedRow() == -1) {
|
||||
m_selectableTableView.selectCellAtLocation(0, 0);
|
||||
} else {
|
||||
@@ -184,17 +163,9 @@ void ValuesController::didBecomeFirstResponder() {
|
||||
}
|
||||
|
||||
bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
if (m_contentView.tableState() == ContentView::TableState::Empty) {
|
||||
if (event == Ion::Events::Up) {
|
||||
app()->setFirstResponder(tabController());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event == Ion::Events::Down) {
|
||||
if (activeRow() == -1) {
|
||||
setSelectedButton(-1);
|
||||
headerViewController()->setSelectedButton(-1);
|
||||
m_selectableTableView.selectCellAtLocation(0,0);
|
||||
app()->setFirstResponder(&m_selectableTableView);
|
||||
return true;
|
||||
@@ -204,18 +175,18 @@ bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
if (event == Ion::Events::Up) {
|
||||
if (activeRow() == -1) {
|
||||
setSelectedButton(-1);
|
||||
headerViewController()->setSelectedButton(-1);
|
||||
app()->setFirstResponder(tabController());
|
||||
return true;
|
||||
}
|
||||
m_selectableTableView.deselectTable();
|
||||
setSelectedButton(0);
|
||||
headerViewController()->setSelectedButton(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event == Ion::Events::OK) {
|
||||
if (activeRow() == -1) {
|
||||
return HeaderViewController::handleEvent(event);
|
||||
return headerViewController()->handleEvent(event);
|
||||
}
|
||||
if (activeRow() == 0) {
|
||||
if (activeColumn() == 0) {
|
||||
@@ -237,7 +208,7 @@ bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
}
|
||||
|
||||
if (activeRow() == -1) {
|
||||
return HeaderViewController::handleEvent(event);
|
||||
return headerViewController()->handleEvent(event);
|
||||
}
|
||||
if (event.hasText()) {
|
||||
if (activeColumn() == 0 && activeRow() > 0) {
|
||||
@@ -251,21 +222,21 @@ bool ValuesController::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
|
||||
void ValuesController::configureAbscissa() {
|
||||
StackViewController * stack = ((StackViewController *)parentResponder());
|
||||
StackViewController * stack = stackController();
|
||||
stack->push(&m_abscissaParameterController);
|
||||
}
|
||||
|
||||
void ValuesController::configureFunction() {
|
||||
Function * function = functionAtColumn(activeColumn());
|
||||
m_functionParameterController.setFunction(function);
|
||||
StackViewController * stack = ((StackViewController *)parentResponder());
|
||||
StackViewController * stack = stackController();
|
||||
stack->push(&m_functionParameterController);
|
||||
}
|
||||
|
||||
void ValuesController::configureDerivativeFunction() {
|
||||
Function * function = functionAtColumn(activeColumn());
|
||||
m_derivativeParameterController.setFunction(function);
|
||||
StackViewController * stack = ((StackViewController *)parentResponder());
|
||||
StackViewController * stack = stackController();
|
||||
stack->push(&m_derivativeParameterController);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
namespace Graph {
|
||||
|
||||
class ValuesController : public HeaderViewController, public TableViewDataSource {
|
||||
class ValuesController : public ViewController, public HeaderViewDelegate, public TableViewDataSource, public AlternateEmptyViewDelegate {
|
||||
public:
|
||||
ValuesController(Responder * parentResponder, FunctionStore * functionStore);
|
||||
ValuesController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header);
|
||||
|
||||
int activeRow();
|
||||
int activeColumn();
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
ValueCell * abscisseCellAtRow(int rowIndex);
|
||||
void editValue(const char * initialText = nullptr);
|
||||
|
||||
View * view() override;
|
||||
const char * title() const override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
@@ -44,6 +45,10 @@ public:
|
||||
int reusableCellCount(int type) override;
|
||||
int typeAtLocation(int i, int j) override;
|
||||
|
||||
bool isEmpty() override;
|
||||
const char * emptyMessage() override;
|
||||
Responder * defaultController() override;
|
||||
|
||||
static constexpr KDCoordinate k_topMargin = 10;
|
||||
static constexpr KDCoordinate k_bottomMargin = 5;
|
||||
static constexpr KDCoordinate k_leftMargin = 1;
|
||||
@@ -53,28 +58,10 @@ public:
|
||||
static constexpr KDCoordinate k_ordinateCellWidth = 100;
|
||||
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
enum class TableState {
|
||||
Empty,
|
||||
NonEmpty
|
||||
};
|
||||
ContentView(View * mainView);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setTableState(TableState tableState);
|
||||
TableState tableState();
|
||||
private:
|
||||
PointerTextView m_noFunctionSelected;
|
||||
View * m_mainView;
|
||||
TableState m_tableState;
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
};
|
||||
|
||||
Function * functionAtColumn(int i);
|
||||
bool isDerivativeColumn(int i);
|
||||
Responder * tabController() const;
|
||||
StackViewController * stackController() const;
|
||||
void configureAbscissa();
|
||||
void configureFunction();
|
||||
void configureDerivativeFunction();
|
||||
@@ -93,7 +80,6 @@ private:
|
||||
FunctionParameterController m_functionParameterController;
|
||||
DerivativeParameterController m_derivativeParameterController;
|
||||
Button m_setIntervalButton;
|
||||
ContentView m_contentView;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
SFLAGS += -Iescher/include
|
||||
|
||||
objs += $(addprefix escher/src/,\
|
||||
alternate_empty_view_controller.o\
|
||||
app.o\
|
||||
buffer_text_view.o\
|
||||
button.o\
|
||||
@@ -10,6 +11,7 @@ objs += $(addprefix escher/src/,\
|
||||
even_odd_cell.o\
|
||||
expression_view.o\
|
||||
header_view_controller.o\
|
||||
header_view_delegate.o\
|
||||
image_view.o\
|
||||
invocation.o\
|
||||
input_view_controller.o\
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ESCHER_H
|
||||
#define ESCHER_H
|
||||
|
||||
#include <escher/alternate_empty_view_controller.h>
|
||||
#include <escher/alternate_empty_view_delegate.h>
|
||||
#include <escher/app.h>
|
||||
#include <escher/buffer_text_view.h>
|
||||
#include <escher/button.h>
|
||||
@@ -10,6 +12,7 @@
|
||||
#include <escher/even_odd_cell.h>
|
||||
#include <escher/expression_view.h>
|
||||
#include <escher/header_view_controller.h>
|
||||
#include <escher/header_view_delegate.h>
|
||||
#include <escher/image.h>
|
||||
#include <escher/image_view.h>
|
||||
#include <escher/input_view_controller.h>
|
||||
|
||||
33
escher/include/escher/alternate_empty_view_controller.h
Normal file
33
escher/include/escher/alternate_empty_view_controller.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef ESCHER_ALTERNATE_EMPTY_VIEW_H
|
||||
#define ESCHER_ALTERNATE_EMPTY_VIEW_H
|
||||
|
||||
#include <escher/alternate_empty_view_delegate.h>
|
||||
#include <escher/pointer_text_view.h>
|
||||
#include <escher/view_controller.h>
|
||||
|
||||
class AlternateEmptyViewController : public ViewController {
|
||||
public:
|
||||
AlternateEmptyViewController(Responder * parentResponder, ViewController * mainViewController, AlternateEmptyViewDelegate * delegate);
|
||||
View * view() override;
|
||||
const char * title() const override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(ViewController * mainViewController, AlternateEmptyViewDelegate * delegate);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
ViewController * mainViewController() const;
|
||||
AlternateEmptyViewDelegate * alternateEmptyViewDelegate() const;
|
||||
private:
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
PointerTextView m_message;
|
||||
ViewController * m_mainViewController;
|
||||
AlternateEmptyViewDelegate * m_delegate;
|
||||
};
|
||||
ContentView m_contentView;
|
||||
};
|
||||
|
||||
#endif
|
||||
15
escher/include/escher/alternate_empty_view_delegate.h
Normal file
15
escher/include/escher/alternate_empty_view_delegate.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ESCHER_ALTERNATE_EMPTY_VIEW_DELEGATE_H
|
||||
#define ESCHER_ALTERNATE_EMPTY_VIEW_DELEGATE_H
|
||||
|
||||
#include <escher/view_controller.h>
|
||||
|
||||
class AlternateEmptyViewController;
|
||||
|
||||
class AlternateEmptyViewDelegate {
|
||||
public:
|
||||
virtual bool isEmpty() = 0;
|
||||
virtual const char * emptyMessage() = 0;
|
||||
virtual Responder * defaultController() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -6,42 +6,39 @@
|
||||
#include <escher/invocation.h>
|
||||
#include <escher/button.h>
|
||||
#include <escher/app.h>
|
||||
#include <escher/header_view_delegate.h>
|
||||
|
||||
class HeaderViewController : public ViewController {
|
||||
public:
|
||||
HeaderViewController(Responder * parentResponder, View * mainView);
|
||||
HeaderViewController(Responder * parentResponder, ViewController * mainViewController, HeaderViewDelegate * delegate);
|
||||
View * view() override;
|
||||
const char * title() const override;
|
||||
void didBecomeFirstResponder() override;
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
void setVisibleHeader(bool isVisibleHeader);
|
||||
virtual int numberOfButtons() const;
|
||||
virtual Button * buttonAtIndex(int index);
|
||||
protected:
|
||||
bool setSelectedButton(int selectedButton);
|
||||
private:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(View * subview, HeaderViewController * headerViewController);
|
||||
ContentView(ViewController * mainViewController, HeaderViewDelegate * delegate);
|
||||
int numberOfButtons() const;
|
||||
Button * buttonAtIndex(int index);
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setVisibleHeader(bool isVisibleHeader);
|
||||
bool setSelectedButton(int selectedButton, App * app);
|
||||
int selectedButton();
|
||||
ViewController * mainViewController() const;
|
||||
HeaderViewDelegate * headerViewDelegate() const;
|
||||
private:
|
||||
constexpr static KDCoordinate k_headerHeight = 20;
|
||||
constexpr static KDColor k_separatorHeaderColor = KDColor::RGB24(0xDEE0E2);
|
||||
constexpr static KDColor k_selectedBackgroundColor = KDColor::RGB24(0x426DA7);
|
||||
View * m_mainView;
|
||||
bool m_visibleHeader;
|
||||
ViewController * m_mainViewController;
|
||||
int m_selectedButton;
|
||||
HeaderViewController * m_headerViewController;
|
||||
HeaderViewDelegate * m_delegate;
|
||||
};
|
||||
ContentView m_contentView;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
18
escher/include/escher/header_view_delegate.h
Normal file
18
escher/include/escher/header_view_delegate.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef ESCHER_HEADER_VIEW_DELEGATE_H
|
||||
#define ESCHER_HEADER_VIEW_DELEGATE_H
|
||||
|
||||
#include <escher/button.h>
|
||||
|
||||
class HeaderViewController;
|
||||
|
||||
class HeaderViewDelegate {
|
||||
public:
|
||||
HeaderViewDelegate(HeaderViewController * headerViewController);
|
||||
virtual int numberOfButtons() const;
|
||||
virtual Button * buttonAtIndex(int index);
|
||||
HeaderViewController * headerViewController();
|
||||
private:
|
||||
HeaderViewController * m_headerViewController;
|
||||
};
|
||||
|
||||
#endif
|
||||
78
escher/src/alternate_empty_view_controller.cpp
Normal file
78
escher/src/alternate_empty_view_controller.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <escher/alternate_empty_view_controller.h>
|
||||
#include <escher/app.h>
|
||||
#include <escher/palette.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* ContentView */
|
||||
|
||||
AlternateEmptyViewController::ContentView::ContentView(ViewController * mainViewController, AlternateEmptyViewDelegate * delegate) :
|
||||
m_message(PointerTextView(nullptr, 0.5f, 0.5f, KDColorBlack, Palette::BackgroundColor)),
|
||||
m_mainViewController(mainViewController),
|
||||
m_delegate(delegate)
|
||||
{
|
||||
}
|
||||
|
||||
void AlternateEmptyViewController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
if (m_delegate->isEmpty()) {
|
||||
ctx->fillRect(bounds(), Palette::BackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
int AlternateEmptyViewController::ContentView::numberOfSubviews() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
View * AlternateEmptyViewController::ContentView::subviewAtIndex(int index) {
|
||||
assert(index == 0);
|
||||
if (m_delegate->isEmpty()) {
|
||||
m_message.setText(m_delegate->emptyMessage());
|
||||
return &m_message;
|
||||
}
|
||||
return m_mainViewController->view();
|
||||
}
|
||||
|
||||
void AlternateEmptyViewController::ContentView::layoutSubviews() {
|
||||
m_message.setFrame(bounds());
|
||||
m_mainViewController->view()->setFrame(bounds());
|
||||
}
|
||||
|
||||
ViewController * AlternateEmptyViewController::ContentView::mainViewController() const {
|
||||
return m_mainViewController;
|
||||
}
|
||||
|
||||
AlternateEmptyViewDelegate * AlternateEmptyViewController::ContentView::alternateEmptyViewDelegate() const {
|
||||
return m_delegate;
|
||||
}
|
||||
|
||||
/* AlternateEmptyViewController */
|
||||
|
||||
AlternateEmptyViewController::AlternateEmptyViewController(Responder * parentResponder, ViewController * mainViewController, AlternateEmptyViewDelegate * delegate) :
|
||||
ViewController(parentResponder),
|
||||
m_contentView(ContentView(mainViewController, delegate))
|
||||
{
|
||||
}
|
||||
|
||||
View * AlternateEmptyViewController::view() {
|
||||
return &m_contentView;
|
||||
}
|
||||
|
||||
const char * AlternateEmptyViewController::title() const {
|
||||
return m_contentView.mainViewController()->title();
|
||||
}
|
||||
|
||||
bool AlternateEmptyViewController::handleEvent(Ion::Events::Event event) {
|
||||
if (m_contentView.alternateEmptyViewDelegate()->isEmpty()) {
|
||||
if (event != Ion::Events::Home) {
|
||||
app()->setFirstResponder(m_contentView.alternateEmptyViewDelegate()->defaultController());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AlternateEmptyViewController::didBecomeFirstResponder() {
|
||||
if (!m_contentView.alternateEmptyViewDelegate()->isEmpty()) {
|
||||
app()->setFirstResponder(m_contentView.mainViewController());
|
||||
}
|
||||
}
|
||||
@@ -4,32 +4,29 @@
|
||||
constexpr KDColor HeaderViewController::ContentView::k_separatorHeaderColor;
|
||||
constexpr KDColor HeaderViewController::ContentView::k_selectedBackgroundColor;
|
||||
|
||||
HeaderViewController::ContentView::ContentView(View * subview, HeaderViewController * headerViewController) :
|
||||
HeaderViewController::ContentView::ContentView(ViewController * mainViewController, HeaderViewDelegate * delegate) :
|
||||
View(),
|
||||
m_mainView(subview),
|
||||
m_visibleHeader(true),
|
||||
m_mainViewController(mainViewController),
|
||||
m_selectedButton(-1),
|
||||
m_headerViewController(headerViewController)
|
||||
m_delegate(delegate)
|
||||
{
|
||||
}
|
||||
|
||||
int HeaderViewController::ContentView::numberOfButtons() const {
|
||||
return m_headerViewController->numberOfButtons();
|
||||
return m_delegate->numberOfButtons();
|
||||
}
|
||||
|
||||
Button * HeaderViewController::ContentView::buttonAtIndex(int index) {
|
||||
return m_headerViewController->buttonAtIndex(index);
|
||||
return m_delegate->buttonAtIndex(index);
|
||||
}
|
||||
|
||||
int HeaderViewController::ContentView::numberOfSubviews() const {
|
||||
if (m_visibleHeader) {
|
||||
return numberOfButtons() + 1;
|
||||
}
|
||||
return 1;
|
||||
return numberOfButtons() + 1;
|
||||
}
|
||||
|
||||
View * HeaderViewController::ContentView::subviewAtIndex(int index) {
|
||||
if (index == 0) {
|
||||
return m_mainView;
|
||||
return m_mainViewController->view();
|
||||
} else {
|
||||
return buttonAtIndex(index - 1);
|
||||
}
|
||||
@@ -38,11 +35,11 @@ View * HeaderViewController::ContentView::subviewAtIndex(int index) {
|
||||
void HeaderViewController::ContentView::layoutSubviews() {
|
||||
if (numberOfButtons() == 0) {
|
||||
KDRect mainViewFrame(0, 1, bounds().width(), bounds().height() - 1);
|
||||
m_mainView->setFrame(mainViewFrame);
|
||||
m_mainViewController->view()->setFrame(mainViewFrame);
|
||||
return;
|
||||
}
|
||||
KDRect mainViewFrame(0, k_headerHeight + 1, bounds().width(), bounds().height() - k_headerHeight - 1);
|
||||
m_mainView->setFrame(mainViewFrame);
|
||||
m_mainViewController->view()->setFrame(mainViewFrame);
|
||||
int currentXOrigin = 0;
|
||||
for (int i = 0; i < numberOfButtons(); i++) {
|
||||
Button * button = buttonAtIndex(i);
|
||||
@@ -54,7 +51,7 @@ void HeaderViewController::ContentView::layoutSubviews() {
|
||||
}
|
||||
|
||||
void HeaderViewController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
if (m_visibleHeader) {
|
||||
if (numberOfButtons() > 0) {
|
||||
ctx->fillRect(KDRect(0, 0, bounds().width(), k_headerHeight), KDColorWhite);
|
||||
ctx->fillRect(KDRect(0, k_headerHeight, bounds().width(), 1), k_separatorHeaderColor);
|
||||
} else {
|
||||
@@ -62,12 +59,6 @@ void HeaderViewController::ContentView::drawRect(KDContext * ctx, KDRect rect) c
|
||||
}
|
||||
}
|
||||
|
||||
void HeaderViewController::ContentView::setVisibleHeader(bool isVisibleHeader) {
|
||||
m_visibleHeader = isVisibleHeader;
|
||||
markRectAsDirty(KDRect(0, 0, bounds().width(), bounds().height()));
|
||||
layoutSubviews();
|
||||
}
|
||||
|
||||
bool HeaderViewController::ContentView::setSelectedButton(int selectedButton, App * application) {
|
||||
if (selectedButton < -1 || selectedButton >= numberOfButtons() || selectedButton == m_selectedButton) {
|
||||
return false;
|
||||
@@ -90,31 +81,30 @@ int HeaderViewController::ContentView::selectedButton() {
|
||||
return m_selectedButton;
|
||||
}
|
||||
|
||||
HeaderViewController::HeaderViewController(Responder * parentResponder, View * mainView) :
|
||||
ViewController * HeaderViewController::ContentView::mainViewController() const {
|
||||
return m_mainViewController;
|
||||
}
|
||||
|
||||
HeaderViewDelegate * HeaderViewController::ContentView::headerViewDelegate() const {
|
||||
return m_delegate;
|
||||
}
|
||||
|
||||
HeaderViewController::HeaderViewController(Responder * parentResponder, ViewController * mainViewController, HeaderViewDelegate * delegate) :
|
||||
ViewController(parentResponder),
|
||||
m_contentView(ContentView(mainView, this))
|
||||
m_contentView(ContentView(mainViewController, delegate))
|
||||
{
|
||||
}
|
||||
|
||||
int HeaderViewController::numberOfButtons() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Button * HeaderViewController::buttonAtIndex(int index) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
View * HeaderViewController::view() {
|
||||
return &m_contentView;
|
||||
}
|
||||
|
||||
const char * HeaderViewController::title() const {
|
||||
return "HeaderViewController";
|
||||
return m_contentView.mainViewController()->title();
|
||||
}
|
||||
|
||||
void HeaderViewController::setVisibleHeader(bool isVisibleHeader) {
|
||||
m_contentView.setVisibleHeader(isVisibleHeader);
|
||||
void HeaderViewController::didBecomeFirstResponder(){
|
||||
app()->setFirstResponder(m_contentView.mainViewController());
|
||||
}
|
||||
|
||||
bool HeaderViewController::setSelectedButton(int selectedButton) {
|
||||
|
||||
20
escher/src/header_view_delegate.cpp
Normal file
20
escher/src/header_view_delegate.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <escher/header_view_delegate.h>
|
||||
#include <assert.h>
|
||||
|
||||
HeaderViewDelegate::HeaderViewDelegate(HeaderViewController * headerViewController) :
|
||||
m_headerViewController(headerViewController)
|
||||
{
|
||||
}
|
||||
|
||||
int HeaderViewDelegate::numberOfButtons() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Button * HeaderViewDelegate::buttonAtIndex(int index) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HeaderViewController * HeaderViewDelegate::headerViewController() {
|
||||
return m_headerViewController;
|
||||
}
|
||||
Reference in New Issue
Block a user