[apps/calculation] EditableExpressionView in calculation app.

Change-Id: I8b67353682652695f7296f0222939930f4b21794
This commit is contained in:
Léa Saviot
2018-01-16 14:47:21 +01:00
parent 47ab766549
commit 91c05b3bb7
13 changed files with 246 additions and 42 deletions

View File

@@ -43,7 +43,7 @@ void App::Snapshot::tidy() {
}
App::App(Container * container, Snapshot * snapshot) :
TextFieldDelegateApp(container, snapshot, &m_editExpressionController),
TextFieldAndEditableExpressionViewDelegateApp(container, snapshot, &m_editExpressionController),
m_localContext((GlobalContext *)((AppsContainer *)container)->globalContext(), snapshot->calculationStore()),
m_historyController(&m_editExpressionController, snapshot->calculationStore()),
m_editExpressionController(&m_modalViewController, &m_historyController, snapshot->calculationStore())
@@ -80,6 +80,36 @@ bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event e
return false;
}
bool App::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) {
if ((event == Ion::Events::Var || event == Ion::Events::XNT) && TextFieldAndEditableExpressionViewDelegateApp::editableExpressionViewDidReceiveEvent(editableExpressionView, event)) {
return true;
}
/* Here, we check that the expression entered by the user can be printed with
* less than k_printedExpressionLength characters. Otherwise, we prevent the
* user from adding this expression to the calculation store. */
if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event)) {
int bufferLength = TextField::maxBufferSize();
char bufferForParsing[bufferLength];
Poincare::ExpressionLayout * expressionLayout = editableExpressionView->expressionViewWithCursor()->expressionView()->expressionLayout();
expressionLayout->writeTextInBuffer(bufferForParsing, bufferLength);
Expression * exp = Expression::parse(bufferForParsing);
if (exp == nullptr) {
editableExpressionView->app()->displayWarning(I18n::Message::SyntaxError);
return true;
}
char buffer[Calculation::k_printedExpressionSize];
int length = exp->writeTextInBuffer(buffer, sizeof(buffer));
delete exp;
/* if the buffer is totally full, it is VERY likely that writeTextInBuffer
* escaped before printing utterly the expression. */
if (length >= Calculation::k_printedExpressionSize-1) {
displayWarning(I18n::Message::SyntaxError);
return true;
}
}
return false;
}
const char * App::XNT() {
return "x";
}

View File

@@ -10,7 +10,7 @@
namespace Calculation {
class App : public Shared::TextFieldDelegateApp {
class App : public Shared::TextFieldAndEditableExpressionViewDelegateApp {
public:
class Descriptor : public ::App::Descriptor {
public:
@@ -30,6 +30,7 @@ public:
};
Poincare::Context * localContext() override;
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
bool editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) override;
const char * XNT() override;
private:
App(Container * container, Snapshot * snapshot);

View File

@@ -1,5 +1,6 @@
#include "edit_expression_controller.h"
#include "../apps_container.h"
#include "ion/display.h"
#include "app.h"
#include <assert.h>
@@ -7,10 +8,11 @@ using namespace Shared;
namespace Calculation {
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate) :
EditExpressionController::ContentView::ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate) :
View(),
m_mainView(subview),
m_textField(parentResponder, m_textBody, TextField::maxBufferSize(), textFieldDelegate)
m_textField(parentResponder, m_textBody, TextField::maxBufferSize(), textFieldDelegate),
m_editableExpressionView(parentResponder, new Poincare::HorizontalLayout(), editableExpressionViewDelegate)
{
m_textBody[0] = 0;
}
@@ -20,30 +22,55 @@ int EditExpressionController::ContentView::numberOfSubviews() const {
}
View * EditExpressionController::ContentView::subviewAtIndex(int index) {
View * views[2] = {m_mainView, &m_textField};
return views[index];
assert(index >= 0 && index < numberOfSubviews());
if (index == 0) {
return m_mainView;
}
assert(index == 1);
if (editionIsInTextField()) {
return &m_textField;
}
return &m_editableExpressionView;
}
void EditExpressionController::ContentView::layoutSubviews() {
KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - k_textFieldHeight-k_separatorThickness);
KDCoordinate inputViewFrameHeight = inputViewHeight();
KDRect mainViewFrame(0, 0, bounds().width(), bounds().height() - inputViewFrameHeight-k_separatorThickness);
m_mainView->setFrame(mainViewFrame);
KDRect inputViewFrame(k_textMargin, bounds().height() - k_textFieldHeight, bounds().width()-k_textMargin, k_textFieldHeight);
m_textField.setFrame(inputViewFrame);
if (editionIsInTextField()) {
KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight + k_verticalMargin, bounds().width()-k_leftMargin, k_textFieldHeight - k_verticalMargin);
m_textField.setFrame(inputViewFrame);
m_editableExpressionView.setFrame(KDRectZero);
return;
}
KDRect inputViewFrame(k_leftMargin, bounds().height() - inputViewFrameHeight, bounds().width() - k_leftMargin, inputViewFrameHeight);
m_editableExpressionView.setFrame(inputViewFrame);
m_textField.setFrame(KDRectZero);
}
void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
void EditExpressionController::ContentView::reload() {
layoutSubviews();
markRectAsDirty(bounds());
}
void EditExpressionController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
KDCoordinate inputViewFrameHeight = inputViewHeight();
// Draw the separator
ctx->fillRect(KDRect(0, bounds().height() -k_textFieldHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle);
// Color the margin
ctx->fillRect(KDRect(0, bounds().height() -k_textFieldHeight, k_textMargin, k_textFieldHeight), m_textField.backgroundColor());
ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight-k_separatorThickness, bounds().width(), k_separatorThickness), Palette::GreyMiddle);
// Color the left margin
ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, k_leftMargin, k_textFieldHeight), m_textField.backgroundColor());
if (!editionIsInTextField()) {
// Color the upper margin
ctx->fillRect(KDRect(0, bounds().height() -inputViewFrameHeight, bounds().width(), k_verticalMargin), m_textField.backgroundColor());
}
}
TextField * EditExpressionController::ContentView::textField() {
return &m_textField;
KDCoordinate EditExpressionController::ContentView::inputViewHeight() const {
return k_verticalMargin + (editionIsInTextField() ? k_textFieldHeight : editableExpressionViewHeight());
}
TableView * EditExpressionController::ContentView::mainView() {
return m_mainView;
KDCoordinate EditExpressionController::ContentView::editableExpressionViewHeight() const {
return KDCoordinate(min(0.6*Ion::Display::Height, max(k_textFieldHeight, m_editableExpressionView.minimalSizeForOptimalDisplay().height()+k_verticalMargin)));
}
EditExpressionController::EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore) :
@@ -67,7 +94,11 @@ void EditExpressionController::insertTextBody(const char * text) {
bool EditExpressionController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::Up) {
if (m_calculationStore->numberOfCalculations() > 0) {
((ContentView *)view())->textField()->setEditing(false, false);
if (((ContentView *)view())->editionIsInTextField()) {
((ContentView *)view())->textField()->setEditing(false, false);
} else {
((ContentView *)view())->editableExpressionView()->setEditing(false);
}
app()->setFirstResponder(m_historyController);
}
return true;
@@ -78,8 +109,13 @@ bool EditExpressionController::handleEvent(Ion::Events::Event event) {
void EditExpressionController::didBecomeFirstResponder() {
int lastRow = m_calculationStore->numberOfCalculations() > 0 ? m_calculationStore->numberOfCalculations()-1 : 0;
m_historyController->scrollToCell(0, lastRow);
((ContentView *)view())->textField()->setEditing(true, false);
app()->setFirstResponder(((ContentView *)view())->textField());
if (((ContentView *)view())->editionIsInTextField()) {
((ContentView *)view())->textField()->setEditing(true, false);
app()->setFirstResponder(((ContentView *)view())->textField());
return;
}
((ContentView *)view())->editableExpressionView()->setEditing(true);
app()->setFirstResponder(((ContentView *)view())->editableExpressionView());
}
bool EditExpressionController::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) {
@@ -110,21 +146,71 @@ bool EditExpressionController::textFieldDidAbortEditing(::TextField * textField,
return false;
}
bool EditExpressionController::editableExpressionViewDidReceiveEvent(::EditableExpressionView * editableExpressionView, Ion::Events::Event event) {
bool layoutIsEmpty = expressionLayout()->isHorizontal() && expressionLayout()->numberOfChildren() == 0;
if (editableExpressionView->isEditing() && editableExpressionView->editableExpressionViewShouldFinishEditing(event) && layoutIsEmpty && m_calculationStore->numberOfCalculations() > 0) {
App * calculationApp = (App *)app();
const char * lastTextBody = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1)->inputText();
m_calculationStore->push(lastTextBody, calculationApp->localContext());
m_historyController->reload();
((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
return true;
}
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event);
}
bool EditExpressionController::editableExpressionViewDidFinishEditing(::EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) {
App * calculationApp = (App *)app();
expressionLayout()->writeTextInBuffer(const_cast<char *>(textBody()), ContentView::k_bufferLength);
m_calculationStore->push(textBody(), calculationApp->localContext());
(const_cast<ExpressionView *>(((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()))->setExpressionLayout(new Poincare::HorizontalLayout());
reloadView();
((ContentView *)view())->editableExpressionView()->setEditing(true);
return true;
}
bool EditExpressionController::editableExpressionViewDidAbortEditing(::EditableExpressionView * editableExpressionView, const char * text) {
((ContentView *)view())->editableExpressionView()->setEditing(true);
//TODO ((ContentView *)view())->editableExpressionView()->editableExpressionView()->expressionViewWithCursor()->expressionView()->setLayout(;
return false;
}
void EditExpressionController::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) {
assert(editableExpressionView == ((ContentView *)view())->editableExpressionView());
reloadView();
}
TextFieldDelegateApp * EditExpressionController::textFieldDelegateApp() {
return (App *)app();
}
TextFieldAndEditableExpressionViewDelegateApp * EditExpressionController::textFieldAndEditableExpressionViewDelegateApp() {
return (App *)app();
}
View * EditExpressionController::loadView() {
return new ContentView(this, (TableView *)m_historyController->view(), this);
return new ContentView(this, (TableView *)m_historyController->view(), this, this);
}
void EditExpressionController::unloadView(View * view) {
delete view;
}
void EditExpressionController::reloadView() {
((ContentView *)view())->reload();
m_historyController->reload();
if (m_historyController->numberOfRows() > 0) {
((ContentView *)view())->mainView()->scrollToCell(0, m_historyController->numberOfRows()-1);
}
}
void EditExpressionController::viewDidDisappear() {
DynamicViewController::viewDidDisappear();
m_historyController->viewDidDisappear();
}
Poincare::ExpressionLayout * EditExpressionController::expressionLayout() {
return ((ContentView *)view())->editableExpressionView()->expressionViewWithCursor()->expressionView()->expressionLayout();
}
}

View File

@@ -3,6 +3,7 @@
#include <escher.h>
#include "../shared/text_field_delegate.h"
#include "../shared/editable_expression_view_delegate.h"
#include "history_controller.h"
#include "calculation_store.h"
#include "text_field.h"
@@ -11,7 +12,7 @@ namespace Calculation {
class HistoryController;
/* TODO: implement a split view */
class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate {
class EditExpressionController : public DynamicViewController, public Shared::TextFieldDelegate, public Shared::EditableExpressionViewDelegate {
public:
EditExpressionController(Responder * parentResponder, HistoryController * historyController, CalculationStore * calculationStore);
void didBecomeFirstResponder() override;
@@ -19,30 +20,50 @@ public:
bool handleEvent(Ion::Events::Event event) override;
const char * textBody();
void insertTextBody(const char * text);
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
/* TextFieldDelegate */
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(::TextField * textField, const char * text, Ion::Events::Event event) override;
bool textFieldDidAbortEditing(::TextField * textField, const char * text) override;
/* EditableExpressionViewDelegate */
bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override;
bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override;
bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override;
void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override;
private:
class ContentView : public View {
public:
ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate);
ContentView(Responder * parentResponder, TableView * subview, TextFieldDelegate * textFieldDelegate, EditableExpressionViewDelegate * editableExpressionViewDelegate);
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews() override;
TextField * textField();
TableView * mainView();
void reload();
TextField * textField() { return &m_textField; }
EditableExpressionView * editableExpressionView() { return &m_editableExpressionView; }
TableView * mainView() { return m_mainView; }
void drawRect(KDContext * ctx, KDRect rect) const override;
bool editionIsInTextField() const { return true; } //TODO
static constexpr int k_bufferLength = TextField::maxBufferSize();
private:
static constexpr KDCoordinate k_textFieldHeight = 37;
static constexpr KDCoordinate k_textMargin= 5;
static constexpr KDCoordinate k_textFieldHeight = 32; //37
static constexpr KDCoordinate k_leftMargin = 5;
static constexpr KDCoordinate k_verticalMargin = 9;
constexpr static int k_separatorThickness = 1;
KDCoordinate inputViewHeight() const;
KDCoordinate editableExpressionViewHeight() const;
TableView * m_mainView;
TextField m_textField;
char m_textBody[TextField::maxBufferSize()];
EditableExpressionView m_editableExpressionView;
char m_textBody[k_bufferLength];
};
View * loadView() override;
void unloadView(View * view) override;
void reloadView();
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
Shared::TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() override;
Poincare::ExpressionLayout * expressionLayout();
HistoryController * m_historyController;
CalculationStore * m_calculationStore;
};

View File

@@ -12,6 +12,22 @@ bool EditableExpressionViewDelegate::editableExpressionViewDidReceiveEvent(::Edi
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidReceiveEvent(editableExpressionView, event);
}
bool EditableExpressionViewDelegate::editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) {
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidFinishEditing(editableExpressionView, text, event);
}
bool EditableExpressionViewDelegate::editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) {
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidAbortEditing(editableExpressionView, text);
}
bool EditableExpressionViewDelegate::editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) {
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidHandleEvent(editableExpressionView, event, returnValue, expressionHasChanged);
}
void EditableExpressionViewDelegate::editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) {
return textFieldAndEditableExpressionViewDelegateApp()->editableExpressionViewDidChangeSize(editableExpressionView);
}
Toolbox * EditableExpressionViewDelegate::toolboxForEditableExpressionView(::EditableExpressionView * editableExpressionView) {
return textFieldAndEditableExpressionViewDelegateApp()->toolboxForEditableExpressionView(editableExpressionView);
}

View File

@@ -10,6 +10,10 @@ class EditableExpressionViewDelegate : public ::EditableExpressionViewDelegate {
public:
bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override;
bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) override;
bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) override;
bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) override;
bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) override;
void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) override;
Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) override;
private:
virtual TextFieldAndEditableExpressionViewDelegateApp * textFieldAndEditableExpressionViewDelegateApp() = 0;

View File

@@ -14,6 +14,7 @@ public:
bool isEditing() const;
void setEditing(bool isEditing);
void scrollToCursor();
void reload();
/* Responder */
Toolbox * toolbox() override;
@@ -29,7 +30,6 @@ public:
private:
bool privateHandleEvent(Ion::Events::Event event);
void cursorOrLayoutChanged();
ExpressionViewWithCursor m_expressionViewWithCursor;
EditableExpressionViewDelegate * m_delegate;
};

View File

@@ -10,9 +10,10 @@ class EditableExpressionViewDelegate {
public:
virtual bool editableExpressionViewShouldFinishEditing(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0;
virtual bool editableExpressionViewDidReceiveEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event) = 0;
/*virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; };
virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) {return false;};
virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool textHasChanged) { return returnValue; };*/ // TODO?
virtual bool editableExpressionViewDidFinishEditing(EditableExpressionView * editableExpressionView, const char * text, Ion::Events::Event event) { return false; }
virtual bool editableExpressionViewDidAbortEditing(EditableExpressionView * editableExpressionView, const char * text) { return false; }
virtual bool editableExpressionViewDidHandleEvent(EditableExpressionView * editableExpressionView, Ion::Events::Event event, bool returnValue, bool expressionHasChanged) { return returnValue; }
virtual void editableExpressionViewDidChangeSize(EditableExpressionView * editableExpressionView) {}
virtual Toolbox * toolboxForEditableExpressionView(EditableExpressionView * editableExpressionView) = 0;
};

View File

@@ -23,6 +23,7 @@ public:
void setAlignment(float horizontalAlignment, float verticalAlignment);
KDSize minimalSizeForOptimalDisplay() const override;
KDPoint drawingOrigin() const;
KDPoint absoluteDrawingOrigin() const;
private:
/* Warning: we do not need to delete the previous expression layout when
* deleting object or setting a new expression layout. Indeed, the expression

View File

@@ -10,12 +10,12 @@
class ExpressionViewWithCursor : public View {
public:
ExpressionViewWithCursor(Poincare::ExpressionLayout * expressionLayout);
Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; }
bool isEditing() const { return m_isEditing; }
void setEditing(bool isEditing) { m_isEditing = isEditing; }
void cursorPositionChanged();
KDRect cursorRect();
const ExpressionView * expressionView() const { return &m_expressionView; }
Poincare::ExpressionLayoutCursor * cursor() { return &m_cursor; }
ExpressionView * expressionView() { return &m_expressionView; }
/* View */
KDSize minimalSizeForOptimalDisplay() const override;
private:

View File

@@ -1,4 +1,5 @@
#include <escher/editable_expression_view.h>
#include <escher/text_field.h>
#include <assert.h>
EditableExpressionView::EditableExpressionView(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, EditableExpressionViewDelegate * delegate) :
@@ -28,8 +29,13 @@ Toolbox * EditableExpressionView::toolbox() {
}
bool EditableExpressionView::handleEvent(Ion::Events::Event event) {
KDSize previousSize = minimalSizeForOptimalDisplay();
if (privateHandleEvent(event)) {
cursorOrLayoutChanged();
reload();
KDSize newSize = minimalSizeForOptimalDisplay();
if (m_delegate && previousSize.height() != newSize.height()) {
m_delegate->editableExpressionViewDidChangeSize(this);
}
return true;
}
return false;
@@ -44,6 +50,30 @@ KDSize EditableExpressionView::minimalSizeForOptimalDisplay() const {
}
bool EditableExpressionView::privateHandleEvent(Ion::Events::Event event) {
if (m_delegate && m_delegate->editableExpressionViewDidReceiveEvent(this, event)) {
return true;
}
if (Responder::handleEvent(event)) {
/* The only event Responder handles is 'Toolbox' displaying. In that case,
* the EditableExpressionView is forced into editing mode. */
if (!isEditing()) {
setEditing(true);
}
return true;
}
if (isEditing() && editableExpressionViewShouldFinishEditing(event)) {
setEditing(false);
int bufferSize = TextField::maxBufferSize();
char buffer[bufferSize];
m_expressionViewWithCursor.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferSize);
if (m_delegate->editableExpressionViewDidFinishEditing(this, buffer, event)) {
delete m_expressionViewWithCursor.expressionView()->expressionLayout();
Poincare::ExpressionLayout * newLayout = new Poincare::HorizontalLayout();
m_expressionViewWithCursor.expressionView()->setExpressionLayout(newLayout);
m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(newLayout);
}
return true;
}
if (event == Ion::Events::Left) {
return m_expressionViewWithCursor.cursor()->moveLeft();
}
@@ -121,14 +151,22 @@ void EditableExpressionView::insertLayoutAtCursor(Poincare::ExpressionLayout * l
if (layout == nullptr) {
return;
}
KDSize previousSize = minimalSizeForOptimalDisplay();
m_expressionViewWithCursor.cursor()->addLayout(layout);
m_expressionViewWithCursor.cursor()->setPointedExpressionLayout(pointedLayout);
m_expressionViewWithCursor.cursor()->setPosition(Poincare::ExpressionLayoutCursor::Position::Right);
m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines();
cursorOrLayoutChanged();
KDSize newSize = minimalSizeForOptimalDisplay();
reload();
if (m_delegate && previousSize.height() != newSize.height()) {
m_delegate->editableExpressionViewDidChangeSize(this);
}
}
void EditableExpressionView::cursorOrLayoutChanged() {
void EditableExpressionView::reload() {
m_expressionViewWithCursor.expressionView()->expressionLayout()->invalidAllSizesPositionsAndBaselines();
m_expressionViewWithCursor.cursorPositionChanged();
layoutSubviews();
scrollToCursor();
markRectAsDirty(bounds());
}

View File

@@ -49,8 +49,11 @@ KDSize ExpressionView::minimalSizeForOptimalDisplay() const {
KDPoint ExpressionView::drawingOrigin() const {
KDSize expressionSize = m_expressionLayout->size();
return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()),
0.5f*(m_frame.height() - expressionSize.height()));
return KDPoint(m_horizontalAlignment*(m_frame.width() - expressionSize.width()), 0.5f*(m_frame.height() - expressionSize.height()));
}
KDPoint ExpressionView::absoluteDrawingOrigin() const {
return drawingOrigin().translatedBy(m_frame.topLeft());
}
void ExpressionView::drawRect(KDContext * ctx, KDRect rect) const {

View File

@@ -25,7 +25,10 @@ KDRect ExpressionViewWithCursor::cursorRect() {
KDSize ExpressionViewWithCursor::minimalSizeForOptimalDisplay() const {
KDSize expressionViewSize = m_expressionView.minimalSizeForOptimalDisplay();
return KDSize(expressionViewSize.width()+1, m_expressionView.minimalSizeForOptimalDisplay().height()); // +1 for the cursor
KDSize cursorSize = isEditing() ? m_cursorView.minimalSizeForOptimalDisplay() : KDSizeZero;
KDCoordinate resultWidth = expressionViewSize.width() + cursorSize.width();
KDCoordinate resultHeight = expressionViewSize.height() + cursorSize.height()/2;
return KDSize(resultWidth, resultHeight);
}
View * ExpressionViewWithCursor::subviewAtIndex(int index) {
@@ -40,7 +43,7 @@ void ExpressionViewWithCursor::layoutSubviews() {
}
void ExpressionViewWithCursor::layoutCursorSubview() {
KDPoint expressionViewOrigin = m_expressionView.drawingOrigin();
KDPoint expressionViewOrigin = m_expressionView.absoluteDrawingOrigin();
KDPoint cursoredExpressionViewOrigin = m_cursor.pointedExpressionLayout()->absoluteOrigin();
KDCoordinate cursorX = expressionViewOrigin.x() + cursoredExpressionViewOrigin.x();
if (m_cursor.position() == ExpressionLayoutCursor::Position::Right) {