[poincare] Continue removing layouts

This commit is contained in:
Léa Saviot
2018-07-03 18:09:43 +02:00
parent f579e95815
commit 880c3e59de
32 changed files with 190 additions and 698 deletions

View File

@@ -65,18 +65,18 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e
return false;
}
bool App::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event)) {
bool App::layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) {
if ((event == Ion::Events::Var || event == Ion::Events::XNT) && ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(layoutField, event)) {
return true;
}
if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) {
if (!expressionLayoutField->hasText()) {
if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event)) {
if (!layoutField->hasText()) {
return true;
}
int bufferLength = Calculation::k_printedExpressionSize;
char bufferForParsing[bufferLength];
expressionLayoutField->writeTextInBuffer(bufferForParsing, bufferLength);
layoutField->writeTextInBuffer(bufferForParsing, bufferLength);
if (!textInputIsCorrect(bufferForParsing)) {
displayWarning(I18n::Message::SyntaxError);

View File

@@ -29,7 +29,7 @@ public:
};
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
bool textInputIsCorrect(const char * text);
bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override;
const char * XNT() override;
private:
App(Container * container, Snapshot * snapshot);

View File

@@ -10,19 +10,15 @@ using namespace Poincare;
namespace Calculation {
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) :
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
View(),
m_mainView(subview),
m_layout(new Poincare::HorizontalLayout()),
m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate)
m_layoutR(Poincare::HorizontalLayoutRef()),
m_expressionField(parentResponder, m_textBody, k_bufferLength, m_layoutR, textFieldDelegate, layoutFieldDelegate)
{
m_textBody[0] = 0;
}
EditExpressionController::ContentView::~ContentView() {
delete m_layout;
}
View * EditExpressionController::ContentView::subviewAtIndex(int index) {
assert(index >= 0 && index < numberOfSubviews());
if (index == 0) {
@@ -92,22 +88,22 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField)
return inputViewDidAbortEditing(textField->text());
}
bool EditExpressionController::expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event) && !expressionLayoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) {
bool EditExpressionController::layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) {
if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event) && !layoutField->hasText() && m_calculationStore->numberOfCalculations() > 0) {
return inputViewDidReceiveEvent(event);
}
return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event);
return expressionFieldDelegateApp()->layoutFieldDidReceiveEvent(layoutField, event);
}
bool EditExpressionController::expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, ExpressionLayout * layout, Ion::Events::Event event) {
return inputViewDidFinishEditing(nullptr, layout);
bool EditExpressionController::layoutFieldDidFinishEditing(::LayoutField * layoutField, LayoutRef layoutR, Ion::Events::Event event) {
return inputViewDidFinishEditing(nullptr, layoutR);
}
bool EditExpressionController::expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) {
bool EditExpressionController::layoutFieldDidAbortEditing(::LayoutField * layoutField) {
return inputViewDidAbortEditing(nullptr);
}
void EditExpressionController::expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) {
void EditExpressionController::layoutFieldDidChangeSize(::LayoutField * layoutField) {
/* Reload the view only if the ExpressionField height actually changes, i.e.
* not if the height is already maximal and stays maximal. */
if (view()) {
@@ -157,14 +153,14 @@ bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event
}
bool EditExpressionController::inputViewDidFinishEditing(const char * text, ExpressionLayout * layout) {
bool EditExpressionController::inputViewDidFinishEditing(const char * text, LayoutRef layoutR) {
App * calculationApp = (App *)app();
if (layout == nullptr) {
if (!layoutR.isDefined()) {
assert(text);
strlcpy(m_cacheBuffer, text, Calculation::k_printedExpressionSize);
} else {
assert(layout);
layout->writeTextInBuffer(m_cacheBuffer, Calculation::k_printedExpressionSize);
assert(layoutR.isDefined());
layoutR.writeTextInBuffer(m_cacheBuffer, Calculation::k_printedExpressionSize);
}
m_calculationStore->push(m_cacheBuffer, calculationApp->localContext());
m_historyController->reload();

View File

@@ -2,10 +2,10 @@
#define CALCULATION_EDIT_EXPRESSION_CONTROLLER_H
#include <escher.h>
#include <poincare/expression_layout.h>
#include <poincare/layout_reference.h>
#include "expression_field.h"
#include "../shared/text_field_delegate.h"
#include "../shared/expression_layout_field_delegate.h"
#include "../shared/layout_field_delegate.h"
#include "history_controller.h"
#include "calculation_store.h"
@@ -13,7 +13,7 @@ namespace Calculation {
class HistoryController;
/* TODO: implement a split view */
class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::ExpressionLayoutFieldDelegate {
class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::LayoutFieldDelegate {
public:
EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore);
void didBecomeFirstResponder() override;
@@ -26,21 +26,16 @@ public:
bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override;
bool textFieldDidAbortEditing(::TextField * textField) override;
/* ExpressionLayoutFieldDelegate */
bool expressionLayoutFieldDidReceiveEvent(::ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool expressionLayoutFieldDidFinishEditing(::ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override;
bool expressionLayoutFieldDidAbortEditing(::ExpressionLayoutField * expressionLayoutField) override;
void expressionLayoutFieldDidChangeSize(::ExpressionLayoutField * expressionLayoutField) override;
/* LayoutFieldDelegate */
bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override;
bool layoutFieldDidFinishEditing(::LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override;
bool layoutFieldDidAbortEditing(::LayoutField * layoutField) override;
void layoutFieldDidChangeSize(::LayoutField * layoutField) override;
private:
class ContentView : public View {
public:
ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate);
~ContentView();
ContentView(const ContentView& other) = delete;
ContentView(ContentView&& other) = delete;
ContentView& operator=(const ContentView& other) = delete;
ContentView& operator=(ContentView&& other) = delete;
ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate);
void reload();
TableView * mainView() { return m_mainView; }
ExpressionField * expressionField() { return &m_expressionField; }
@@ -52,14 +47,14 @@ private:
static constexpr int k_bufferLength = TextField::maxBufferSize();
TableView * m_mainView;
char m_textBody[k_bufferLength];
Poincare::ExpressionLayout * m_layout;
Poincare::LayoutRef m_layoutR;
ExpressionField m_expressionField;
};
View * loadView() override;
void unloadView(View * view) override;
void reloadView();
bool inputViewDidReceiveEvent(Ion::Events::Event event);
bool inputViewDidFinishEditing(const char * text, Poincare::ExpressionLayout * layout);
bool inputViewDidFinishEditing(const char * text, Poincare::LayoutRef layoutR);
bool inputViewDidAbortEditing(const char * text);
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override;

View File

@@ -10,7 +10,6 @@ app_objs += $(addprefix apps/shared/,\
double_pair_store.o\
editable_cell_table_view_controller.o\
expression_field_delegate_app.o\
expression_layout_field_delegate.o\
expression_model.o\
expression_model_list_controller.o\
expression_model_store.o\
@@ -36,6 +35,7 @@ app_objs += $(addprefix apps/shared/,\
interval.o\
interval_parameter_controller.o\
language_controller.o\
layout_field_delegate.o\
list_parameter_controller.o\
margin_even_odd_message_text_cell.o\
memoized_curve_view_range.o\

View File

@@ -9,31 +9,31 @@ namespace Shared {
ExpressionFieldDelegateApp::ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController) :
TextFieldDelegateApp(container, snapshot, rootViewController),
ExpressionLayoutFieldDelegate()
LayoutFieldDelegate()
{
}
char ExpressionFieldDelegateApp::privateXNT(ExpressionLayoutField * expressionLayoutField) {
char xntCharFromLayout = expressionLayoutField->XNTChar();
char ExpressionFieldDelegateApp::privateXNT(LayoutField * layoutField) {
char xntCharFromLayout = layoutField->XNTChar();
if (xntCharFromLayout != Ion::Charset::Empty) {
return xntCharFromLayout;
}
return XNT()[0];
}
bool ExpressionFieldDelegateApp::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
bool ExpressionFieldDelegateApp::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) {
return event == Ion::Events::OK || event == Ion::Events::EXE;
}
bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
if (expressionLayoutField->isEditing() && expressionLayoutField->expressionLayoutFieldShouldFinishEditing(event)) {
if (!expressionLayoutField->hasText()) {
expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError);
bool ExpressionFieldDelegateApp::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) {
if (layoutField->isEditing() && layoutField->layoutFieldShouldFinishEditing(event)) {
if (!layoutField->hasText()) {
layoutField->app()->displayWarning(I18n::Message::SyntaxError);
return true;
}
char buffer[TextField::maxBufferSize()];
int bufferSize = TextField::maxBufferSize();
int length = expressionLayoutField->writeTextInBuffer(buffer, bufferSize);
int length = layoutField->writeTextInBuffer(buffer, bufferSize);
Expression * exp = Expression::parse(buffer);
if (exp != nullptr) {
delete exp;
@@ -45,33 +45,33 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression
return true;
}
if (exp == nullptr) {
expressionLayoutField->app()->displayWarning(I18n::Message::SyntaxError);
layoutField->app()->displayWarning(I18n::Message::SyntaxError);
return true;
}
}
if (event == Ion::Events::Var) {
if (!expressionLayoutField->isEditing()) {
expressionLayoutField->setEditing(true);
if (!layoutField->isEditing()) {
layoutField->setEditing(true);
}
AppsContainer * appsContainer = (AppsContainer *)expressionLayoutField->app()->container();
AppsContainer * appsContainer = (AppsContainer *)layoutField->app()->container();
VariableBoxController * variableBoxController = appsContainer->variableBoxController();
variableBoxController->setSender(expressionLayoutField);
expressionLayoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
variableBoxController->setSender(layoutField);
layoutField->app()->displayModalViewController(variableBoxController, 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
return true;
}
if (event == Ion::Events::XNT) {
if (!expressionLayoutField->isEditing()) {
expressionLayoutField->setEditing(true);
if (!layoutField->isEditing()) {
layoutField->setEditing(true);
}
const char xnt[2] = {privateXNT(expressionLayoutField), 0};
return expressionLayoutField->handleEventWithText(xnt);
const char xnt[2] = {privateXNT(layoutField), 0};
return layoutField->handleEventWithText(xnt);
}
return false;
}
Toolbox * ExpressionFieldDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) {
Toolbox * ExpressionFieldDelegateApp::toolboxForLayoutField(LayoutField * layoutField) {
Toolbox * toolbox = container()->mathToolbox();
toolbox->setSender(expressionLayoutField);
toolbox->setSender(layoutField);
return toolbox;
}

View File

@@ -2,18 +2,18 @@
#define SHARED_EXPRESSION_FIELD_DELEGATE_APP_H
#include "text_field_delegate_app.h"
#include <escher/expression_layout_field_delegate.h>
#include <escher/layout_field_delegate.h>
namespace Shared {
class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public ExpressionLayoutFieldDelegate {
class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public LayoutFieldDelegate {
public:
virtual ~ExpressionFieldDelegateApp() = default;
bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override;
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
virtual bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
Toolbox * toolboxForLayoutField(LayoutField * layoutField) override;
protected:
char privateXNT(ExpressionLayoutField * expressionLayoutField);
char privateXNT(LayoutField * layoutField);
ExpressionFieldDelegateApp(Container * container, Snapshot * snapshot, ViewController * rootViewController);
};

View File

@@ -1,31 +0,0 @@
#include "expression_layout_field_delegate.h"
using namespace Poincare;
namespace Shared {
bool ExpressionLayoutFieldDelegate::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
return expressionFieldDelegateApp()->expressionLayoutFieldShouldFinishEditing(expressionLayoutField, event);
}
bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
return expressionFieldDelegateApp()->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event);
}
bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, ExpressionLayout * layout, Ion::Events::Event event) {
return expressionFieldDelegateApp()->expressionLayoutFieldDidFinishEditing(expressionLayoutField, layout, event);
}
bool ExpressionLayoutFieldDelegate::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) {
return expressionFieldDelegateApp()->expressionLayoutFieldDidAbortEditing(expressionLayoutField);
}
void ExpressionLayoutFieldDelegate::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) {
return expressionFieldDelegateApp()->expressionLayoutFieldDidChangeSize(expressionLayoutField);
}
Toolbox * ExpressionLayoutFieldDelegate::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) {
return expressionFieldDelegateApp()->toolboxForExpressionLayoutField(expressionLayoutField);
}
}

View File

@@ -1,23 +0,0 @@
#ifndef SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H
#define SHARED_EXPRESSION_LAYOUT_FIELD_DELEGATE_H
#include <escher/expression_layout_field_delegate.h>
#include "expression_field_delegate_app.h"
namespace Shared {
class ExpressionLayoutFieldDelegate : public ::ExpressionLayoutFieldDelegate {
public:
bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override;
bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override;
void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override;
Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override;
private:
virtual ExpressionFieldDelegateApp * expressionFieldDelegateApp() = 0;
};
}
#endif

View File

@@ -33,8 +33,7 @@ KDCoordinate ExpressionModelListController::expressionRowHeight(int j) {
void ExpressionModelListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) {
EvenOddExpressionCell * myCell = (EvenOddExpressionCell *)cell;
ExpressionModel * m = modelStore()->modelAtIndex(j);
myCell->setExpressionLayout(nullptr); //TODO
//myCell->setExpressionLayout(m->layout());
myCell->setLayoutRef(m->layoutRef());
}
/* Responder */

View File

@@ -0,0 +1,31 @@
#include "layout_field_delegate.h"
using namespace Poincare;
namespace Shared {
bool LayoutFieldDelegate::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) {
return expressionFieldDelegateApp()->layoutFieldShouldFinishEditing(layoutField, event);
}
bool LayoutFieldDelegate::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) {
return expressionFieldDelegateApp()->layoutFieldDidReceiveEvent(layoutField, event);
}
bool LayoutFieldDelegate::layoutFieldDidFinishEditing(LayoutField * layoutField, LayoutRef layoutR, Ion::Events::Event event) {
return expressionFieldDelegateApp()->layoutFieldDidFinishEditing(layoutField, layoutR, event);
}
bool LayoutFieldDelegate::layoutFieldDidAbortEditing(LayoutField * layoutField) {
return expressionFieldDelegateApp()->layoutFieldDidAbortEditing(layoutField);
}
void LayoutFieldDelegate::layoutFieldDidChangeSize(LayoutField * layoutField) {
return expressionFieldDelegateApp()->layoutFieldDidChangeSize(layoutField);
}
Toolbox * LayoutFieldDelegate::toolboxForLayoutField(LayoutField * layoutField) {
return expressionFieldDelegateApp()->toolboxForLayoutField(layoutField);
}
}

View File

@@ -0,0 +1,23 @@
#ifndef SHARED_LAYOUT_FIELD_DELEGATE_H
#define SHARED_LAYOUT_FIELD_DELEGATE_H
#include <escher/layout_field_delegate.h>
#include "expression_field_delegate_app.h"
namespace Shared {
class LayoutFieldDelegate : public ::LayoutFieldDelegate {
public:
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override;
bool layoutFieldDidAbortEditing(LayoutField * layoutField) override;
void layoutFieldDidChangeSize(LayoutField * layoutField) override;
Toolbox * toolboxForLayoutField(LayoutField * layoutField) override;
private:
virtual ExpressionFieldDelegateApp * expressionFieldDelegateApp() = 0;
};
}
#endif

View File

@@ -30,7 +30,6 @@ objs += $(addprefix escher/src/,\
input_view_controller.o\
key_view.o\
layout_field.o\
layout_field_content_view.o\
list_view_data_source.o\
message_table_cell.o\
message_table_cell_with_buffer.o\
@@ -52,8 +51,6 @@ objs += $(addprefix escher/src/,\
scroll_view_data_source.o\
scroll_view_indicator.o\
scrollable_view.o\
expression_layout_field.o\
expression_layout_field_content_view.o\
selectable_table_view.o\
selectable_table_view_data_source.o\
selectable_table_view_delegate.o\

View File

@@ -32,6 +32,8 @@
#include <escher/invocation.h>
#include <escher/i18n.h>
#include <escher/key_view.h>
#include <escher/layout_field.h>
#include <escher/layout_field_delegate.h>
#include <escher/list_view_data_source.h>
#include <escher/message_table_cell.h>
#include <escher/message_table_cell_with_buffer.h>
@@ -53,8 +55,6 @@
#include <escher/scroll_view_data_source.h>
#include <escher/scroll_view_indicator.h>
#include <escher/scrollable_view.h>
#include <escher/expression_layout_field.h>
#include <escher/expression_layout_field_delegate.h>
#include <escher/selectable_table_view.h>
#include <escher/selectable_table_view_data_source.h>
#include <escher/selectable_table_view_delegate.h>

View File

@@ -10,7 +10,7 @@ public:
KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite);
void setEven(bool even) override;
void setHighlighted(bool highlight) override;
void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout);
void setLayoutRef(Poincare::LayoutRef layoutRef);
void setBackgroundColor(KDColor backgroundColor);
void setTextColor(KDColor textColor);
KDSize minimalSizeForOptimalDisplay() const override;

View File

@@ -1,15 +1,15 @@
#ifndef ESCHER_EXPRESSION_FIELD_H
#define ESCHER_EXPRESSION_FIELD_H
#include <escher/expression_layout_field.h>
#include <escher/expression_layout_field_delegate.h>
#include <escher/layout_field.h>
#include <escher/layout_field_delegate.h>
#include <escher/text_field.h>
#include <escher/text_field_delegate.h>
#include <poincare/expression_layout.h>
#include <poincare/layout_reference.h>
class ExpressionField : public Responder, public View {
public:
ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate);
ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::LayoutRef layout, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate);
void setEditing(bool isEditing, bool reinitDraftBuffer = true);
bool isEditing() const;
@@ -44,7 +44,7 @@ private:
KDCoordinate inputViewHeight() const;
KDCoordinate maximalHeight() const;
TextField m_textField;
ExpressionLayoutField m_expressionLayoutField;
LayoutField m_layoutField;
char * m_textBuffer;
int m_textBufferLength;
};

View File

@@ -1,81 +0,0 @@
#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_H
#define ESCHER_EXPRESSION_LAYOUT_FIELD_H
#include <escher/expression_view.h>
#include <escher/expression_layout_field_delegate.h>
#include <escher/scrollable_view.h>
#include <escher/text_cursor_view.h>
#include <escher/text_field.h>
#include <kandinsky/point.h>
#include <poincare/expression_layout.h>
#include <poincare/expression_layout_cursor.h>
class ExpressionLayoutField : public ScrollableView, public ScrollViewDataSource {
public:
ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate = nullptr);
void setDelegate(ExpressionLayoutFieldDelegate * delegate) { m_delegate = delegate; }
bool isEditing() const;
void setEditing(bool isEditing);
void clearLayout();
void scrollToCursor();
void reload();
bool hasText() const;
int writeTextInBuffer(char * buffer, int bufferLength);
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
Poincare::ExpressionLayout * expressionLayout() const;
char XNTChar();
void setBackgroundColor(KDColor c) override;
/* Responder */
Toolbox * toolbox() override;
bool handleEvent(Ion::Events::Event event) override;
bool expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event);
/* View */
KDSize minimalSizeForOptimalDisplay() const override;
protected:
virtual bool privateHandleEvent(Ion::Events::Event event);
bool privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout);
private:
constexpr static int k_maxNumberOfLayouts = 152;
static_assert(k_maxNumberOfLayouts == TextField::maxBufferSize(), "Maximal number of layouts in a layout field should be equal to max number of char in text field");
void scrollRightOfLayout(Poincare::ExpressionLayout * layout);
void scrollToBaselinedRect(KDRect rect, KDCoordinate baseline);
void insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout, bool forceCursorRightOfLayout = false);
class ContentView : public View {
public:
ContentView(Poincare::ExpressionLayout * expressionLayout);
bool isEditing() const { return m_isEditing; }
void setEditing(bool isEditing);
void setBackgroundColor(KDColor c);
void setCursor(Poincare::ExpressionLayoutCursor cursor) { m_cursor = cursor; }
void cursorPositionChanged();
KDRect cursorRect();
Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; }
const ExpressionView * expressionView() const { return &m_expressionView; }
ExpressionView * editableExpressionView() { return &m_expressionView; }
void clearLayout();
/* View */
KDSize minimalSizeForOptimalDisplay() const override;
private:
enum class Position {
Top,
Bottom
};
int numberOfSubviews() const override { return 2; }
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
void layoutCursorSubview();
Poincare::ExpressionLayoutCursor m_cursor;
ExpressionView m_expressionView;
TextCursorView m_cursorView;
bool m_isEditing;
};
ContentView m_contentView;
ExpressionLayoutFieldDelegate * m_delegate;
};
#endif

View File

@@ -1,19 +0,0 @@
#ifndef ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H
#define ESCHER_EXPRESSION_LAYOUT_FIELD_DELEGATE_H
#include <escher/toolbox.h>
#include <ion/events.h>
class ExpressionLayoutField;
class ExpressionLayoutFieldDelegate {
public:
virtual bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0;
virtual bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) = 0;
virtual bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) { return false; }
virtual bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) { return false; }
virtual void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) {}
virtual Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) = 0;
};
#endif

View File

@@ -9,7 +9,7 @@ public:
ExpressionTableCell(Layout layout = Layout::Horizontal);
View * labelView() const override;
void setHighlighted(bool highlight) override;
void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout);
void setLayoutRef(Poincare::LayoutRef layoutR);
Poincare::LayoutRef layoutRef() const override { return m_labelExpressionView.layoutRef(); }
private:
ExpressionView m_labelExpressionView;

View File

@@ -16,13 +16,8 @@ class ExpressionView : public View {
public:
ExpressionView(float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f,
KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite);
Poincare::ExpressionLayout * expressionLayout() const;
void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout);
Poincare::LayoutRef layoutRef() const { return m_layoutRef; }
void setLayoutRef(Poincare::LayoutRef layoutRef);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setBackgroundColor(KDColor backgroundColor);
void setTextColor(KDColor textColor);
@@ -37,8 +32,7 @@ private:
* layout is always possessed by a controller which only gives a pointer to
* the expression view (without cloning it). The named controller is then
* responsible for freeing the expression layout when required. */
Poincare::ExpressionLayout * m_expressionLayout;
Poincare::LayoutRef m_layoutRef;
mutable Poincare::LayoutRef m_layoutRef; // TODO find better way to have minimalSizeForOptimalDisplay const
float m_horizontalAlignment;
float m_verticalAlignment;
KDColor m_textColor;

View File

@@ -2,7 +2,7 @@
#define ESCHER_INPUT_VIEW_CONTROLLER_H
#include <escher/expression_field.h>
#include <escher/expression_layout_field_delegate.h>
#include <escher/layout_field_delegate.h>
#include <escher/modal_view_controller.h>
#include <escher/invocation.h>
#include <escher/text_field.h>
@@ -12,9 +12,9 @@
/* TODO Implement a split view. Because we use a modal view, the main view is
* redrawn underneath the modal view, which is visible and ugly. */
class InputViewController : public ModalViewController, TextFieldDelegate, ExpressionLayoutFieldDelegate {
class InputViewController : public ModalViewController, TextFieldDelegate, LayoutFieldDelegate {
public:
InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate);
InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate);
void edit(Responder * caller, Ion::Events::Event event, void * context, const char * initialText, Invocation::Action successAction, Invocation::Action failureAction);
const char * textBody();
void abortEditionAndDismiss();
@@ -26,19 +26,18 @@ public:
bool textFieldDidAbortEditing(TextField * textField) override;
Toolbox * toolboxForTextInput(TextInput * textInput) override;
/* ExpressionLayoutFieldDelegate */
bool expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) override;
bool expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) override;
bool expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) override;
void expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) override;
Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override;
/* LayoutFieldDelegate */
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) override;
bool layoutFieldDidAbortEditing(LayoutField * layoutField) override;
void layoutFieldDidChangeSize(LayoutField * layoutField) override;
Toolbox * toolboxForLayoutField(LayoutField * layoutField) override;
private:
class ExpressionFieldController : public ViewController {
public:
ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate);
~ExpressionFieldController();
ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate);
ExpressionFieldController(const ExpressionFieldController& other) = delete;
ExpressionFieldController(ExpressionFieldController&& other) = delete;
ExpressionFieldController& operator=(const ExpressionFieldController& other) = delete;
@@ -48,7 +47,7 @@ private:
ExpressionField * expressionField() { return &m_expressionField; }
private:
static constexpr int k_bufferLength = TextField::maxBufferSize();
Poincare::ExpressionLayout * m_layout;
Poincare::LayoutRef m_layout;
char m_textBuffer[k_bufferLength];
ExpressionField m_expressionField;
};
@@ -58,7 +57,7 @@ private:
Invocation m_successAction;
Invocation m_failureAction;
TextFieldDelegate * m_textFieldDelegate;
ExpressionLayoutFieldDelegate * m_expressionLayoutFieldDelegate;
LayoutFieldDelegate * m_layoutFieldDelegate;
bool m_inputViewHeightIsMaximal;
};

View File

@@ -9,7 +9,7 @@ public:
MessageTableCellWithChevronAndExpression(I18n::Message message = (I18n::Message)0, KDText::FontSize size = KDText::FontSize::Small);
View * subAccessoryView() const override;
void setHighlighted(bool highlight) override;
void setExpressionLayout(Poincare::ExpressionLayout * expressionLayout);
void setLayoutRef(Poincare::LayoutRef layoutR);
private:
ExpressionView m_subtitleView;
};

View File

@@ -23,8 +23,8 @@ void EvenOddExpressionCell::setEven(bool even) {
m_expressionView.setBackgroundColor(backgroundColor());
}
void EvenOddExpressionCell::setExpressionLayout(ExpressionLayout * expressionLayout) {
m_expressionView.setExpressionLayout(expressionLayout);
void EvenOddExpressionCell::setLayoutRef(LayoutRef layoutR) {
m_expressionView.setLayoutRef(layoutR);
}
void EvenOddExpressionCell::setBackgroundColor(KDColor backgroundColor) {

View File

@@ -2,11 +2,11 @@
#include <poincare/preferences.h>
#include <assert.h>
ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) :
ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::LayoutRef layout, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
Responder(parentResponder),
View(),
m_textField(parentResponder, textBuffer, textBuffer, textBufferLength, textFieldDelegate, false, KDText::FontSize::Large, 0.0f, 0.5f, KDColorBlack, KDColorWhite),
m_expressionLayoutField(parentResponder, layout, expressionLayoutFieldDelegate),
m_layoutField(parentResponder, layout, layoutFieldDelegate),
m_textBuffer(textBuffer),
m_textBufferLength(textBufferLength)
{
@@ -15,9 +15,9 @@ ExpressionField::ExpressionField(Responder * parentResponder, char * textBuffer,
m_textField.setBackgroundColor(KDColorWhite);
m_textField.setColorsBackground(true);
// Initialize layout field
m_expressionLayoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin);
m_expressionLayoutField.setBackgroundColor(KDColorWhite);
m_expressionLayoutField.setColorsBackground(true);
m_layoutField.setMargins(k_verticalMargin, k_horizontalMargin, k_verticalMargin, k_horizontalMargin);
m_layoutField.setBackgroundColor(KDColorWhite);
m_layoutField.setColorsBackground(true);
}
void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) {
@@ -25,19 +25,19 @@ void ExpressionField::setEditing(bool isEditing, bool reinitDraftBuffer) {
m_textField.setEditing(isEditing, reinitDraftBuffer);
} else {
if (reinitDraftBuffer) {
m_expressionLayoutField.clearLayout();
m_layoutField.clearLayout();
}
m_expressionLayoutField.setEditing(isEditing);
m_layoutField.setEditing(isEditing);
}
}
bool ExpressionField::isEditing() const {
return editionIsInTextField() ? m_textField.isEditing() : m_expressionLayoutField.isEditing();
return editionIsInTextField() ? m_textField.isEditing() : m_layoutField.isEditing();
}
const char * ExpressionField::text() {
if (!editionIsInTextField()) {
m_expressionLayoutField.writeTextInBuffer(m_textBuffer, m_textBufferLength);
m_layoutField.writeTextInBuffer(m_textBuffer, m_textBufferLength);
}
return m_textBuffer;
}
@@ -46,8 +46,8 @@ void ExpressionField::setText(const char * text) {
if (editionIsInTextField()) {
m_textField.setText(text);
} else {
m_expressionLayoutField.clearLayout();
m_expressionLayoutField.handleEventWithText(text, false, true);
m_layoutField.clearLayout();
m_layoutField.handleEventWithText(text, false, true);
}
}
@@ -56,17 +56,17 @@ View * ExpressionField::subviewAtIndex(int index) {
if (editionIsInTextField()) {
return &m_textField;
}
return &m_expressionLayoutField;
return &m_layoutField;
}
void ExpressionField::layoutSubviews() {
KDRect inputViewFrame(0, k_separatorThickness, bounds().width(), bounds().height() - k_separatorThickness);
if (editionIsInTextField()) {
m_textField.setFrame(inputViewFrame);
m_expressionLayoutField.setFrame(KDRectZero);
m_layoutField.setFrame(KDRectZero);
return;
}
m_expressionLayoutField.setFrame(inputViewFrame);
m_layoutField.setFrame(inputViewFrame);
m_textField.setFrame(KDRectZero);
}
@@ -81,7 +81,7 @@ void ExpressionField::drawRect(KDContext * ctx, KDRect rect) const {
}
bool ExpressionField::handleEvent(Ion::Events::Event event) {
return editionIsInTextField() ? m_textField.handleEvent(event) : m_expressionLayoutField.handleEvent(event);
return editionIsInTextField() ? m_textField.handleEvent(event) : m_layoutField.handleEvent(event);
}
KDSize ExpressionField::minimalSizeForOptimalDisplay() const {
@@ -93,7 +93,7 @@ bool ExpressionField::editionIsInTextField() const {
}
bool ExpressionField::isEmpty() const {
return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_expressionLayoutField.hasText();
return editionIsInTextField() ? (m_textField.draftTextLength() == 0) : !m_layoutField.hasText();
}
bool ExpressionField::heightIsMaximal() const {
@@ -104,7 +104,7 @@ bool ExpressionField::handleEventWithText(const char * text, bool indentation, b
if (editionIsInTextField()) {
return m_textField.handleEventWithText(text, indentation, forceCursorRightOfText);
} else {
return m_expressionLayoutField.handleEventWithText(text, indentation, forceCursorRightOfText);
return m_layoutField.handleEventWithText(text, indentation, forceCursorRightOfText);
}
}
@@ -112,7 +112,7 @@ KDCoordinate ExpressionField::inputViewHeight() const {
return k_separatorThickness
+ (editionIsInTextField() ? k_textFieldHeight :
min(maximalHeight(),
max(k_textFieldHeight, m_expressionLayoutField.minimalSizeForOptimalDisplay().height() + 2*k_verticalMargin )));
max(k_textFieldHeight, m_layoutField.minimalSizeForOptimalDisplay().height() + 2*k_verticalMargin )));
}
KDCoordinate ExpressionField::maximalHeight() const {

View File

@@ -1,303 +0,0 @@
#include <escher/expression_layout_field.h>
#include <apps/i18n.h>
#include <escher/clipboard.h>
#include <escher/text_field.h>
#include <poincare/expression.h>
#include <poincare/expression_layout_cursor.h>
#include <poincare/src/layout/matrix_layout.h>
#include <assert.h>
#include <string.h>
ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) :
ScrollableView(parentResponder, &m_contentView, this),
m_contentView(expressionLayout),
m_delegate(delegate)
{
}
bool ExpressionLayoutField::isEditing() const {
return m_contentView.isEditing();
}
void ExpressionLayoutField::setEditing(bool isEditing) {
m_contentView.setEditing(isEditing);
}
void ExpressionLayoutField::clearLayout() {
m_contentView.clearLayout();
}
void ExpressionLayoutField::scrollToCursor() {
scrollToBaselinedRect(m_contentView.cursorRect(), m_contentView.cursor()->baseline());
}
Toolbox * ExpressionLayoutField::toolbox() {
if (m_delegate) {
return m_delegate->toolboxForExpressionLayoutField(this);
}
return nullptr;
}
bool ExpressionLayoutField::handleEvent(Ion::Events::Event event) {
bool didHandleEvent = false;
bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded();
bool moveEventChangedLayout = false;
if (privateHandleMoveEvent(event, &moveEventChangedLayout)) {
if (!isEditing()) {
setEditing(true);
}
shouldRecomputeLayout = shouldRecomputeLayout || moveEventChangedLayout;
didHandleEvent = true;
} else if (privateHandleEvent(event)) {
shouldRecomputeLayout = true;
didHandleEvent = true;
}
if (didHandleEvent) {
shouldRecomputeLayout = m_contentView.cursor()->hideEmptyLayoutIfNeeded() || shouldRecomputeLayout;
if (!shouldRecomputeLayout) {
m_contentView.cursorPositionChanged();
scrollToCursor();
} else {
reload();
}
return true;
}
m_contentView.cursor()->hideEmptyLayoutIfNeeded();
return false;
}
bool ExpressionLayoutField::expressionLayoutFieldShouldFinishEditing(Ion::Events::Event event) {
return m_delegate->expressionLayoutFieldShouldFinishEditing(this, event);
}
KDSize ExpressionLayoutField::minimalSizeForOptimalDisplay() const {
KDSize contentViewSize = m_contentView.minimalSizeForOptimalDisplay();
return KDSize(contentViewSize.width(), contentViewSize.height());
}
bool ExpressionLayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) {
Poincare::ExpressionLayoutCursor result;
if (event == Ion::Events::Left) {
result = m_contentView.cursor()->cursorOnLeft(shouldRecomputeLayout);
} else if (event == Ion::Events::Right) {
result = m_contentView.cursor()->cursorOnRight(shouldRecomputeLayout);
} else if (event == Ion::Events::Up) {
result = m_contentView.cursor()->cursorAbove(shouldRecomputeLayout);
} else if (event == Ion::Events::Down) {
result = m_contentView.cursor()->cursorUnder(shouldRecomputeLayout);
} else if (event == Ion::Events::ShiftLeft) {
*shouldRecomputeLayout = true;
if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) {
*shouldRecomputeLayout = true;
}
result.setPointedExpressionLayout(expressionLayout());
result.setPosition(Poincare::ExpressionLayoutCursor::Position::Left);
} else if (event == Ion::Events::ShiftRight) {
if (m_contentView.cursor()->pointedExpressionLayout()->removeGreySquaresFromAllMatrixAncestors()) {
*shouldRecomputeLayout = true;
}
result.setPointedExpressionLayout(expressionLayout());
result.setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
}
if (result.isDefined()) {
m_contentView.setCursor(result);
return true;
}
return false;
}
bool ExpressionLayoutField::privateHandleEvent(Ion::Events::Event event) {
if (m_delegate && m_delegate->expressionLayoutFieldDidReceiveEvent(this, event)) {
return true;
}
if (Responder::handleEvent(event)) {
/* The only event Responder handles is 'Toolbox' displaying. In that case,
* the ExpressionLayoutField is forced into editing mode. */
if (!isEditing()) {
setEditing(true);
}
return true;
}
if (isEditing() && expressionLayoutFieldShouldFinishEditing(event)) {
setEditing(false);
if (m_delegate->expressionLayoutFieldDidFinishEditing(this, expressionLayout(), event)) {
clearLayout();
}
return true;
}
if ((event == Ion::Events::OK || event == Ion::Events::EXE) && !isEditing()) {
setEditing(true);
m_contentView.cursor()->setPointedExpressionLayout(expressionLayout());
m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
return true;
}
if (event == Ion::Events::Back && isEditing()) {
clearLayout();
setEditing(false);
m_delegate->expressionLayoutFieldDidAbortEditing(this);
return true;
}
if (event.hasText() || event == Ion::Events::Paste || event == Ion::Events::Backspace) {
if (!isEditing()) {
setEditing(true);
}
if (event.hasText()) {
handleEventWithText(event.text());
} else if (event == Ion::Events::Paste) {
handleEventWithText(Clipboard::sharedClipboard()->storedText(), false, true);
} else {
assert(event == Ion::Events::Backspace);
m_contentView.cursor()->performBackspace();
}
return true;
}
if (event == Ion::Events::Clear && isEditing()) {
clearLayout();
return true;
}
return false;
}
void ExpressionLayoutField::reload() {
KDSize previousSize = minimalSizeForOptimalDisplay();
expressionLayout()->invalidAllSizesPositionsAndBaselines();
KDSize newSize = minimalSizeForOptimalDisplay();
if (m_delegate && previousSize.height() != newSize.height()) {
m_delegate->expressionLayoutFieldDidChangeSize(this);
}
m_contentView.cursorPositionChanged();
scrollToCursor();
markRectAsDirty(bounds());
}
bool ExpressionLayoutField::hasText() const {
return expressionLayout()->hasText();
}
int ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) {
return expressionLayout()->writeTextInBuffer(buffer, bufferLength);
}
bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
if (text[0] == 0) {
// The text is empty
return true;
}
int currentNumberOfLayouts = m_contentView.expressionView()->numberOfLayouts();
if (currentNumberOfLayouts >= k_maxNumberOfLayouts - 6) {
/* We add -6 because in some cases (Ion::Events::Division,
* Ion::Events::Exp...) we let the layout cursor handle the layout insertion
* and these events may add at most 6 layouts (e.g *10^•). */
return true;
}
// Handle special cases
if (strcmp(text, Ion::Events::Division.text()) == 0) {
m_contentView.cursor()->addFractionLayoutAndCollapseSiblings();
} else if (strcmp(text, Ion::Events::Exp.text()) == 0) {
m_contentView.cursor()->addEmptyExponentialLayout();
} else if (strcmp(text, Ion::Events::Power.text()) == 0) {
m_contentView.cursor()->addEmptyPowerLayout();
} else if (strcmp(text, Ion::Events::Sqrt.text()) == 0) {
m_contentView.cursor()->addEmptySquareRootLayout();
} else if (strcmp(text, Ion::Events::Square.text()) == 0) {
m_contentView.cursor()->addEmptySquarePowerLayout();
} else if (strcmp(text, Ion::Events::EE.text()) == 0) {
m_contentView.cursor()->addEmptyTenPowerLayout();
} else if ((strcmp(text, "[") == 0) || (strcmp(text, "]") == 0)) {
m_contentView.cursor()->addEmptyMatrixLayout();
} else {
Poincare::Expression * resultExpression = Poincare::Expression::parse(text);
if (resultExpression == nullptr) {
m_contentView.cursor()->insertText(text);
return true;
}
Poincare::ExpressionLayout * resultLayout = resultExpression->createLayout();
delete resultExpression;
if (currentNumberOfLayouts + resultLayout->numberOfDescendants(true) >= k_maxNumberOfLayouts) {
delete resultLayout;
return true;
}
// Find the pointed layout.
Poincare::ExpressionLayout * pointedLayout = nullptr;
if (strcmp(text, I18n::translate(I18n::Message::RandomCommandWithArg)) == 0) {
/* Special case: if the text is "random()", the cursor should not be set
* inside the parentheses. */
pointedLayout = resultLayout;
} else if (resultLayout->isHorizontal()) {
/* If the layout is horizontal, pick the first open parenthesis. For now,
* all horizontal layouts in MathToolbox have parentheses. */
for (int i = 0; i < resultLayout->numberOfChildren(); i++) {
if (resultLayout->editableChild(i)->isLeftParenthesis()) {
pointedLayout = resultLayout->editableChild(i);
break;
}
}
}
/* Insert the layout. If pointedLayout is nullptr, the cursor will be on the
* right of the inserted layout. */
insertLayoutAtCursor(resultLayout, pointedLayout, forceCursorRightOfText);
}
return true;
}
Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() const {
return m_contentView.expressionView()->expressionLayout();
}
char ExpressionLayoutField::XNTChar() {
return m_contentView.cursor()->pointedExpressionLayout()->XNTChar();
}
void ExpressionLayoutField::setBackgroundColor(KDColor c) {
ScrollableView::setBackgroundColor(c);
m_contentView.setBackgroundColor(c);
}
void ExpressionLayoutField::scrollRightOfLayout(Poincare::ExpressionLayout * layout) {
KDRect layoutRect(layout->absoluteOrigin().translatedBy(m_contentView.expressionView()->drawingOrigin()), layout->size());
scrollToBaselinedRect(layoutRect, layout->baseline());
}
void ExpressionLayoutField::scrollToBaselinedRect(KDRect rect, KDCoordinate baseline) {
scrollToContentRect(rect, true);
// Show the rect area around its baseline
KDCoordinate underBaseline = rect.height() - baseline;
KDCoordinate minAroundBaseline = min(baseline, underBaseline);
minAroundBaseline = min(minAroundBaseline, bounds().height() / 2);
KDRect balancedRect(rect.x(), rect.y() + baseline - minAroundBaseline, rect.width(), 2 * minAroundBaseline);
scrollToContentRect(balancedRect, true);
}
void ExpressionLayoutField::insertLayoutAtCursor(Poincare::ExpressionLayout * layout, Poincare::ExpressionLayout * pointedLayout, bool forceCursorRightOfLayout) {
if (layout == nullptr) {
return;
}
m_contentView.cursor()->showEmptyLayoutIfNeeded();
bool layoutWillBeMerged = layout->isHorizontal();
Poincare::ExpressionLayout * lastMergedLayoutChild = layoutWillBeMerged ? layout->editableChild(layout->numberOfChildren()-1) : nullptr;
m_contentView.cursor()->addLayoutAndMoveCursor(layout);
if (!forceCursorRightOfLayout) {
if (pointedLayout != nullptr && (pointedLayout != layout || !layoutWillBeMerged)) {
m_contentView.cursor()->setPointedExpressionLayout(pointedLayout);
m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
} else if (!layoutWillBeMerged) {
m_contentView.cursor()->setPointedExpressionLayout(layout->layoutToPointWhenInserting());
m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
}
} else if (!layoutWillBeMerged) {
m_contentView.cursor()->setPointedExpressionLayout(layout);
m_contentView.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
}
m_contentView.cursor()->pointedExpressionLayout()->addGreySquaresToAllMatrixAncestors();
m_contentView.cursor()->hideEmptyLayoutIfNeeded();
reload();
if (!layoutWillBeMerged) {
scrollRightOfLayout(layout);
} else {
assert(lastMergedLayoutChild != nullptr);
scrollRightOfLayout(lastMergedLayoutChild);
}
scrollToCursor();
}

View File

@@ -1,74 +0,0 @@
#include <escher/expression_layout_field.h>
#include <kandinsky/rect.h>
#include <assert.h>
using namespace Poincare;
ExpressionLayoutField::ContentView::ContentView(ExpressionLayout * expressionLayout) :
m_cursor(expressionLayout, ExpressionLayoutCursor::Position::Right),
m_expressionView(0.0f, 0.5f, KDColorBlack, KDColorWhite),
m_cursorView(),
m_isEditing(false)
{
m_expressionView.setExpressionLayout(expressionLayout);
}
void ExpressionLayoutField::ContentView::setEditing(bool isEditing) {
m_isEditing = isEditing;
markRectAsDirty(bounds());
layoutSubviews();
}
void ExpressionLayoutField::ContentView::setBackgroundColor(KDColor c) {
m_expressionView.setBackgroundColor(c);
}
void ExpressionLayoutField::ContentView::cursorPositionChanged() {
layoutCursorSubview();
}
KDRect ExpressionLayoutField::ContentView::cursorRect() {
return m_cursorView.frame();
}
void ExpressionLayoutField::ContentView::clearLayout() {
m_cursor.clearLayout();
}
KDSize ExpressionLayoutField::ContentView::minimalSizeForOptimalDisplay() const {
KDSize evSize = m_expressionView.minimalSizeForOptimalDisplay();
return KDSize(evSize.width() + ExpressionLayoutCursor::k_cursorWidth, evSize.height());
}
View * ExpressionLayoutField::ContentView::subviewAtIndex(int index) {
assert(index >= 0 && index < 2);
View * m_views[] = {&m_expressionView, &m_cursorView};
return m_views[index];
}
void ExpressionLayoutField::ContentView::layoutSubviews() {
m_expressionView.setFrame(bounds());
layoutCursorSubview();
}
void ExpressionLayoutField::ContentView::layoutCursorSubview() {
if (!m_isEditing) {
m_cursorView.setFrame(KDRectZero);
return;
}
KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin();
ExpressionLayout * pointedLayout = m_cursor.pointedExpressionLayout();
ExpressionLayoutCursor::Position cursorPosition = m_cursor.position();
ExpressionLayoutCursor eqCursor = pointedLayout->equivalentCursor(m_cursor);
if (pointedLayout->hasChild(eqCursor.pointedExpressionLayout())) {
pointedLayout = eqCursor.pointedExpressionLayout();
cursorPosition = eqCursor.position();
}
KDPoint cursoredExpressionViewOrigin = pointedLayout->absoluteOrigin();
KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x();
if (cursorPosition == ExpressionLayoutCursor::Position::Right) {
cursorX += pointedLayout->size().width();
}
KDPoint cursorTopLeftPosition(cursorX, expressionViewOrigin.y() + cursoredExpressionViewOrigin.y() + pointedLayout->baseline() - m_cursor.baseline());
m_cursorView.setFrame(KDRect(cursorTopLeftPosition, ExpressionLayoutCursor::k_cursorWidth, m_cursor.cursorHeight()));
}

View File

@@ -18,7 +18,7 @@ void ExpressionTableCell::setHighlighted(bool highlight) {
m_labelExpressionView.setBackgroundColor(backgroundColor);
}
void ExpressionTableCell::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) {
m_labelExpressionView.setExpressionLayout(expressionLayout);
void ExpressionTableCell::setLayoutRef(Poincare::LayoutRef layoutR) {
m_labelExpressionView.setLayoutRef(layoutR);
layoutSubviews();
}

View File

@@ -3,7 +3,6 @@ using namespace Poincare;
ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignment,
KDColor textColor, KDColor backgroundColor) :
m_expressionLayout(nullptr),
m_layoutRef(nullptr),
m_horizontalAlignment(horizontalAlignment),
m_verticalAlignment(verticalAlignment),
@@ -12,16 +11,6 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen
{
}
//TODO remove
ExpressionLayout * ExpressionView::expressionLayout() const {
return m_expressionLayout;
}
void ExpressionView::setExpressionLayout(ExpressionLayout * expressionLayout) {
m_expressionLayout = expressionLayout;
markRectAsDirty(bounds());
}
void ExpressionView::setLayoutRef(LayoutRef layoutR) {
m_layoutRef = layoutR;
markRectAsDirty(bounds());
@@ -48,18 +37,18 @@ void ExpressionView::setAlignment(float horizontalAlignment, float verticalAlign
}
int ExpressionView::numberOfLayouts() const {
return m_expressionLayout->numberOfDescendants(true);
return m_layoutRef.numberOfDescendants(true);
}
KDSize ExpressionView::minimalSizeForOptimalDisplay() const {
if (m_expressionLayout == nullptr) {
if (!m_layoutRef.isDefined()) {
return KDSizeZero;
}
return m_expressionLayout->size();
return m_layoutRef.layoutSize();
}
KDPoint ExpressionView::drawingOrigin() const {
KDSize expressionSize = m_expressionLayout->size();
KDSize expressionSize = m_layoutRef.layoutSize();
return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), max(0, (m_frame.height() - expressionSize.height())/2));
}
@@ -69,7 +58,7 @@ KDPoint ExpressionView::absoluteDrawingOrigin() const {
void ExpressionView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(rect, m_backgroundColor);
if (m_expressionLayout != nullptr) {
m_expressionLayout->draw(ctx, drawingOrigin(), m_textColor, m_backgroundColor);
if (m_layoutRef.isDefined()) {
m_layoutRef.draw(ctx, drawingOrigin(), m_textColor, m_backgroundColor);
}
}

View File

@@ -1,32 +1,28 @@
#include <escher/input_view_controller.h>
#include <escher/app.h>
#include <escher/palette.h>
#include <poincare/src/layout/horizontal_layout.h>
#include <poincare/horizontal_layout_node.h>
#include <assert.h>
InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) :
InputViewController::ExpressionFieldController::ExpressionFieldController(Responder * parentResponder, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
ViewController(parentResponder),
m_layout(new Poincare::HorizontalLayout()),
m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, expressionLayoutFieldDelegate)
m_layout(Poincare::HorizontalLayoutRef()),
m_expressionField(this, m_textBuffer, k_bufferLength, m_layout, textFieldDelegate, layoutFieldDelegate)
{
m_textBuffer[0] = 0;
}
InputViewController::ExpressionFieldController::~ExpressionFieldController() {
delete m_layout;
}
void InputViewController::ExpressionFieldController::didBecomeFirstResponder() {
app()->setFirstResponder(&m_expressionField);
}
InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate) :
InputViewController::InputViewController(Responder * parentResponder, ViewController * child, TextFieldDelegate * textFieldDelegate, LayoutFieldDelegate * layoutFieldDelegate) :
ModalViewController(parentResponder, child),
m_expressionFieldController(this, this, this),
m_successAction(Invocation(nullptr, nullptr)),
m_failureAction(Invocation(nullptr, nullptr)),
m_textFieldDelegate(textFieldDelegate),
m_expressionLayoutFieldDelegate(expressionLayoutFieldDelegate),
m_layoutFieldDelegate(layoutFieldDelegate),
m_inputViewHeightIsMaximal(false)
{
}
@@ -74,27 +70,27 @@ Toolbox * InputViewController::toolboxForTextInput(TextInput * input) {
return m_textFieldDelegate->toolboxForTextInput(input);
}
bool InputViewController::expressionLayoutFieldShouldFinishEditing(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
bool InputViewController::layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) {
return event == Ion::Events::OK || event == Ion::Events::EXE;
}
bool InputViewController::expressionLayoutFieldDidReceiveEvent(ExpressionLayoutField * expressionLayoutField, Ion::Events::Event event) {
return m_expressionLayoutFieldDelegate->expressionLayoutFieldDidReceiveEvent(expressionLayoutField, event);
bool InputViewController::layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) {
return m_layoutFieldDelegate->layoutFieldDidReceiveEvent(layoutField, event);
}
bool InputViewController::expressionLayoutFieldDidFinishEditing(ExpressionLayoutField * expressionLayoutField, Poincare::ExpressionLayout * layout, Ion::Events::Event event) {
bool InputViewController::layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::LayoutRef layoutR, Ion::Events::Event event) {
inputViewDidFinishEditing();
m_expressionLayoutFieldDelegate->expressionLayoutFieldDidFinishEditing(expressionLayoutField, layout, event);
m_layoutFieldDelegate->layoutFieldDidFinishEditing(layoutField, layoutR, event);
return true;
}
bool InputViewController::expressionLayoutFieldDidAbortEditing(ExpressionLayoutField * expressionLayoutField) {
bool InputViewController::layoutFieldDidAbortEditing(LayoutField * layoutField) {
inputViewDidAbortEditing();
m_expressionLayoutFieldDelegate->expressionLayoutFieldDidAbortEditing(expressionLayoutField);
m_layoutFieldDelegate->layoutFieldDidAbortEditing(layoutField);
return true;
}
void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutField * expressionLayoutField) {
void InputViewController::layoutFieldDidChangeSize(LayoutField * layoutField) {
/* Reload the view only if the ExpressionField height actually changes, i.e.
* not if the height is already maximal and stays maximal. */
bool newInputViewHeightIsMaximal = m_expressionFieldController.expressionField()->heightIsMaximal();
@@ -104,8 +100,8 @@ void InputViewController::expressionLayoutFieldDidChangeSize(ExpressionLayoutFie
}
}
Toolbox * InputViewController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) {
return m_expressionLayoutFieldDelegate->toolboxForExpressionLayoutField(expressionLayoutField);
Toolbox * InputViewController::toolboxForLayoutField(LayoutField * layoutField) {
return m_layoutFieldDelegate->toolboxForLayoutField(layoutField);
}
void InputViewController::inputViewDidFinishEditing() {

View File

@@ -17,8 +17,8 @@ void MessageTableCellWithChevronAndExpression::setHighlighted(bool highlight) {
m_subtitleView.setBackgroundColor(backgroundColor);
}
void MessageTableCellWithChevronAndExpression::setExpressionLayout(Poincare::ExpressionLayout * expressionLayout) {
m_subtitleView.setExpressionLayout(expressionLayout);
void MessageTableCellWithChevronAndExpression::setLayoutRef(Poincare::LayoutRef layoutR) {
m_subtitleView.setLayoutRef(layoutR);
reloadCell();
layoutSubviews();
}

View File

@@ -43,6 +43,10 @@ public:
TreeReference<T>::replaceChildAtIndex(oldChildIndex, newChild);
}
void draw(KDContext * ctx, KDPoint p, KDColor expressionColor = KDColorBlack, KDColor backgroundColor = KDColorWhite) {
return this->typedNode()->draw(ctx, p, expressionColor, backgroundColor);
}
bool isHorizontal() const { return this->typedNode()->isHorizontal(); }
bool isLeftParenthesis() const { return this->typedNode()->isLeftParenthesis(); }
bool hasText() { return this->typedNode()->hasText(); }

View File

@@ -222,7 +222,7 @@ LayoutRef Decimal::privateCreateLayout(PrintFloat::Mode floatDisplayMode, Comple
return CharLayoutRef('a'); //TODO
/*char buffer[k_maxBufferSize];
int numberOfChars = convertToText(buffer, k_maxBufferSize, floatDisplayMode, PrintFloat::k_numberOfStoredSignificantDigits);
return LayoutEngine::createStringLayout(buffer, numberOfChars);
return LayoutEngine::createStringLayout(buffer, numberOfChars);*/
}
Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) {
@@ -243,7 +243,7 @@ Expression * Decimal::shallowReduce(Context& context, AngleUnit angleUnit) {
} else {
denominator = Integer::Power(Integer(10), Integer(numberOfDigits-1-m_exponent));
}
return replaceWith(new Rational(numerator, denominator), true);*/
return replaceWith(new Rational(numerator, denominator), true);
}
Expression * Decimal::shallowBeautify(Context & context, AngleUnit angleUnit) {