[Update] Epsilon 14

This commit is contained in:
Joachim LF
2020-07-09 15:33:21 +02:00
committed by Quentin Guidée
320 changed files with 6893 additions and 2610 deletions

View File

@@ -66,6 +66,7 @@ escher_src += $(addprefix escher/src/,\
message_text_view.cpp \
metric.cpp \
modal_view_controller.cpp \
modal_view_empty_controller.cpp \
nested_menu_controller.cpp \
palette.cpp \
pointer_text_view.cpp \

View File

@@ -87,11 +87,7 @@ private:
bool selectionIsEmpty() const;
void deleteSelection();
void invalidateInsertionCursor() { m_insertionCursor = Poincare::LayoutCursor(); }
void updateInsertionCursor() {
if (!m_insertionCursor.isDefined()) {
m_insertionCursor = m_cursor;
}
}
void updateInsertionCursor();
private:
int numberOfSubviews() const override { return 2; }

View File

@@ -13,8 +13,12 @@ public:
void setMessage(I18n::Message message);
virtual void setTextColor(KDColor color);
void setMessageFont(const KDFont * font);
void setBackgroundColor(KDColor color);
protected:
KDColor backgroundColor() const override { return m_backgroundColor; }
private:
MessageTextView m_messageTextView;
KDColor m_backgroundColor;
};
#endif

View File

@@ -10,7 +10,7 @@ public:
m_numberOfChildren(numberOfChildren)
{
};
virtual const MessageTree * children(int index) const = 0;
virtual const MessageTree * childAtIndex(int index) const = 0;
I18n::Message label() const { return m_label; }
int numberOfChildren() const { return m_numberOfChildren; }
bool isNull() const { return (m_label == (I18n::Message)0); }

View File

@@ -0,0 +1,37 @@
#ifndef ESCHER_EMPTY_MODAL_VIEW_EMPTY_CONTROLLER_H
#define ESCHER_EMPTY_MODAL_VIEW_EMPTY_CONTROLLER_H
#include <escher/bordered.h>
#include <escher/expression_view.h>
#include <escher/message_text_view.h>
#include <escher/view_controller.h>
class ModalViewEmptyController : public ViewController {
public:
ModalViewEmptyController() : ViewController(nullptr) {}
void setMessages(I18n::Message * messages);
// View Controller
DisplayParameter displayParameter() override { return DisplayParameter::DoNotShowOwnTitle; }
protected:
class ModalViewEmptyView : public View, public Bordered {
public:
constexpr static const KDFont * k_font = KDFont::SmallFont;
void initMessageViews();
void setMessages(I18n::Message * message);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
constexpr static int k_expressionViewRowIndex = 2;
constexpr static KDColor k_backgroundColor = Palette::WallScreen;
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews(bool force = false) override;
virtual int numberOfMessageTextViews() const = 0;
virtual MessageTextView * messageTextViewAtIndex(int index) = 0;
bool hasExpressionView() const {
return const_cast<ModalViewEmptyView *>(this)->expressionView() != nullptr;
}
virtual ExpressionView * expressionView() { return nullptr; }
};
};
#endif

View File

@@ -7,10 +7,11 @@
#include <escher/selectable_table_view.h>
#include <escher/stack_view_controller.h>
class NestedMenuController : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource {
class NestedMenuController : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource, public SelectableTableViewDelegate {
public:
NestedMenuController(Responder * parentResponder, I18n::Message title = (I18n::Message)0);
void setSender(InputEventHandler * sender) { m_sender = sender; }
void setTitle(I18n::Message title);
// StackViewController
bool handleEvent(Ion::Events::Event event) override;
@@ -48,6 +49,7 @@ protected:
public:
ListController(Responder * parentResponder, SelectableTableView * tableView, I18n::Message title);
const char * title() override;
void setTitle(I18n::Message title) { m_title = title; }
View * view() override;
void didBecomeFirstResponder() override;
void setFirstSelectedRow(int firstSelectedRow);

View File

@@ -0,0 +1,150 @@
#ifndef ESCHER_PALETTE_H
#define ESCHER_PALETTE_H
#include <kandinsky/color.h>
#include <stddef.h>
class Palette {
public:
constexpr static KDColor PrimaryText = KDColor::RGB24(0x000000);
constexpr static KDColor SecondaryText = KDColor::RGB24(0x6e6e6e);
constexpr static KDColor AccentText = KDColor::RGB24(0x00857f);
constexpr static KDColor ApproximateSignText = KDColor::RGB24(0x595959);
constexpr static KDColor ApproximateExpressionText = KDColor::RGB24(0x595959);
constexpr static KDColor BackgroundHard = KDColor::RGB24(0xffffff);
constexpr static KDColor BackgroundApps = KDColor::RGB24(0xfafafa);
constexpr static KDColor BackgroundAppsSecondary = KDColor::RGB24(0xf0f0f0);
constexpr static KDColor Toolbar = KDColor::RGB24(0xc03535);
constexpr static KDColor ToolbarText = KDColor::RGB24(0xffffff);
constexpr static KDColor ExpressionInputBackground = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor ExpressionInputBorder = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor GridPrimaryLine = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor GridSecondaryLine = KDColor::RGB24(0xf5f5f5);
constexpr static KDColor Battery = KDColor::RGB24(0xffffff);
constexpr static KDColor BatteryInCharge = KDColor::RGB24(0x179e1f);
constexpr static KDColor BatteryLow = KDColor::RGB24(0x992321);
constexpr static KDColor ScrollBarForeground = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor ScrollBarBackground = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor Control = KDColor::RGB24(0x00857f);
constexpr static KDColor ControlEnabled = KDColor::RGB24(0x00b2b0);
constexpr static KDColor ControlDisabled = KDColor::RGB24(0x9e9e9e);
constexpr static KDColor CalculationBackgroundOdd = KDColor::RGB24(0xfafafa);
constexpr static KDColor CalculationBackgroundEven = KDColor::RGB24(0xffffff);
constexpr static KDColor CalculationEmptyBox = KDColor::RGB24(0xc4c4c4);
constexpr static KDColor CalculationEmptyBoxNeeded = KDColor::RGB24(0x00857f);
constexpr static KDColor CalculationTrigoAndComplexForeground = KDColor::RGB24(0xff000c);
constexpr static KDColor CodeBackground = KDColor::RGB24(0xffffff);
constexpr static KDColor CodeBackgroundSelected = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor CodeText = KDColor::RGB24(0x000000);
constexpr static KDColor CodeComment = KDColor::RGB24(0x999988);
constexpr static KDColor CodeNumber = KDColor::RGB24(0x009999);
constexpr static KDColor CodeKeyword = KDColor::RGB24(0xff000c);
constexpr static KDColor CodeOperator = KDColor::RGB24(0xd73a49);
constexpr static KDColor CodeString = KDColor::RGB24(0x032f62);
constexpr static KDColor CodeGutterViewBackground = KDColor::RGB24(0xE4E6E7);
constexpr static KDColor ProbabilityCurve = KDColor::RGB24(0x00857f);
constexpr static KDColor ProbabilityCellBorder = KDColor::RGB24(0xececec);
constexpr static KDColor ProbabilityHistogramBar = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor StatisticsBox = KDColor::RGB24(0x00857f);
constexpr static KDColor StatisticsBoxVerticalLine = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor StatisticsSelected = KDColor::RGB24(0x00857f);
constexpr static KDColor StatisticsNotSelected = KDColor::RGB24(0xf5f5f5);
constexpr static KDColor GraphTangent = KDColor::RGB24(0x595959);
constexpr static KDColor SubMenuBackground = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor SubMenuBorder = KDColor::RGB24(0xfafafa);
constexpr static KDColor SubMenuText = KDColor::RGB24(0x000000);
constexpr static KDColor ToolboxHeaderBackground = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor ToolboxHeaderText = KDColor::RGB24(0xffffff);
constexpr static KDColor ToolboxHeaderBorder = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor ToolboxBackground = KDColor::RGB24(0x000000);
constexpr static KDColor ListCellBackground = KDColor::RGB24(0xffffff);
constexpr static KDColor ListCellBackgroundSelected = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor ListCellBorder = KDColor::RGB24(0xededef);
constexpr static KDColor ButtonBackground = KDColor::RGB24(0xe6e6e6);
constexpr static KDColor ButtonBackgroundSelected = KDColor::RGB24(0xc9c9c9);
constexpr static KDColor ButtonBackgroundSelectedHighContrast = KDColor::RGB24(0x00b2b0);
constexpr static KDColor ButtonBorder = KDColor::RGB24(0xadadad);
constexpr static KDColor ButtonRowBorder = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor ButtonBorderOut = KDColor::RGB24(0xf5f5f5);
constexpr static KDColor ButtonShadow = KDColor::RGB24(0x003833);
constexpr static KDColor ButtonText = KDColor::RGB24(0x000000);
constexpr static KDColor TabBackground = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor TabBackgroundSelected = KDColor::RGB24(0x757575);
constexpr static KDColor TabBackgroundActive = KDColor::RGB24(0xfafafa);
constexpr static KDColor TabBackgroundSelectedAndActive = KDColor::RGB24(0xe3e3e3);
constexpr static KDColor TabText = KDColor::RGB24(0xffffff);
constexpr static KDColor TabTextActive = KDColor::RGB24(0x000000);
constexpr static KDColor SubTabBackground = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor SubTabBackgroundSelected = KDColor::RGB24(0xd1d1d1);
constexpr static KDColor SubTabText = KDColor::RGB24(0x000000);
constexpr static KDColor BannerFirstBackground = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor BannerFirstBorder = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor BannerFirstText = KDColor::RGB24(0xffffff);
constexpr static KDColor BannerFirstVariantBackground = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor BannerFirstVariantBorder = KDColor::RGB24(0xfafafa);
constexpr static KDColor BannerFirstVariantText = KDColor::RGB24(0xffffff);
constexpr static KDColor BannerSecondBackground = KDColor::RGB24(0xe0e0e0);
constexpr static KDColor BannerSecondBorder = KDColor::RGB24(0xfafafa);
constexpr static KDColor BannerSecondText = KDColor::RGB24(0x000000);
constexpr static KDColor HomeBackground = KDColor::RGB24(0xffffff);
constexpr static KDColor HomeCellBackground = KDColor::RGB24(0xffffff);
constexpr static KDColor HomeCellBackgroundActive = KDColor::RGB24(0x4a4a4a);
constexpr static KDColor HomeCellText = KDColor::RGB24(0x000000);
constexpr static KDColor HomeCellTextActive = KDColor::RGB24(0xffffff);
constexpr static KDColor HomeCellTextExternal = KDColor::RGB24(0x008f87);
constexpr static KDColor HomeCellTextExternalActive = KDColor::RGB24(0x6fe6df);
constexpr static KDColor AtomUnknown = KDColor::RGB24(0xeeeeee);
constexpr static KDColor AtomText = KDColor::RGB24(0x000000);
constexpr static KDColor AtomAlkaliMetal = KDColor::RGB24(0xffaa00);
constexpr static KDColor AtomAlkaliEarthMetal = KDColor::RGB24(0xf6f200);
constexpr static KDColor AtomLanthanide = KDColor::RGB24(0xffaa8b);
constexpr static KDColor AtomActinide = KDColor::RGB24(0xdeaacd);
constexpr static KDColor AtomTransitionMetal = KDColor::RGB24(0xde999c);
constexpr static KDColor AtomPostTransitionMetal = KDColor::RGB24(0x9cbaac);
constexpr static KDColor AtomMetalloid = KDColor::RGB24(0x52ce8b);
constexpr static KDColor AtomHalogen = KDColor::RGB24(0x00debd);
constexpr static KDColor AtomReactiveNonmetal = KDColor::RGB24(0x00ee00);
constexpr static KDColor AtomNobleGas = KDColor::RGB24(0x8baaff);
constexpr static KDColor AtomTableLines = KDColor::RGB24(0x323532);
constexpr static KDColor YellowDark = KDColor::RGB24(0xffb734);
constexpr static KDColor YellowLight = KDColor::RGB24(0xffcc7b);
constexpr static KDColor PurpleBright = KDColor::RGB24(0x656975);
constexpr static KDColor PurpleDark = KDColor::RGB24(0x414147);
constexpr static KDColor GreyWhite = KDColor::RGB24(0xf5f5f5);
constexpr static KDColor GreyBright = KDColor::RGB24(0xececec);
constexpr static KDColor GreyMiddle = KDColor::RGB24(0xd9d9d9);
constexpr static KDColor GreyDark = KDColor::RGB24(0xa7a7a7);
constexpr static KDColor GreyVeryDark = KDColor::RGB24(0x8c8c8c);
constexpr static KDColor Select = KDColor::RGB24(0xd4d7e0);
constexpr static KDColor SelectDark = KDColor::RGB24(0xb0b8d8);
constexpr static KDColor WallScreen = KDColor::RGB24(0xf7f9fa);
constexpr static KDColor WallScreenDark = KDColor::RGB24(0xe0e6ed);
constexpr static KDColor SubTab = KDColor::RGB24(0xb8bbc5);
constexpr static KDColor LowBattery = KDColor::RGB24(0xf30211);
constexpr static KDColor Red = KDColor::RGB24(0xff000c);
constexpr static KDColor RedLight = KDColor::RGB24(0xfe6363);
constexpr static KDColor Magenta = KDColor::RGB24(0xff0588);
constexpr static KDColor Turquoise = KDColor::RGB24(0x60c1ec);
constexpr static KDColor Pink = KDColor::RGB24(0xffabb6);
constexpr static KDColor Blue = KDColor::RGB24(0x5075f2);
constexpr static KDColor BlueLight = KDColor::RGB24(0x718fee);
constexpr static KDColor Orange = KDColor::RGB24(0xfe871f);
constexpr static KDColor Green = KDColor::RGB24(0x50c102);
constexpr static KDColor GreenLight = KDColor::RGB24(0x52db8f);
constexpr static KDColor Brown = KDColor::RGB24(0x8d7350);
constexpr static KDColor Purple = KDColor::RGB24(0x6e2d79);
constexpr static KDColor BlueishGrey = KDColor::RGB24(0x919ea4);
constexpr static KDColor Cyan = KDColorBlue;
constexpr static KDColor DataColor[] = {Red, Blue, Green, YellowDark, Magenta, Turquoise, Pink, Orange};
constexpr static KDColor DataColorLight[] = {RedLight, BlueLight, GreenLight, YellowLight};
constexpr static KDColor AtomColor[] = {
AtomUnknown, AtomAlkaliMetal, AtomAlkaliEarthMetal, AtomLanthanide, AtomActinide, AtomTransitionMetal,
AtomPostTransitionMetal, AtomMetalloid, AtomHalogen, AtomReactiveNonmetal, AtomNobleGas
};
constexpr static size_t numberOfDataColors() { return sizeof(DataColor)/sizeof(KDColor); }
constexpr static size_t numberOfLightDataColors() { return sizeof(DataColorLight)/sizeof(KDColor); }
static KDColor nextDataColor(int * colorIndex);
};
#endif

View File

@@ -13,6 +13,7 @@ public:
* the previous selected cell. We might implement different course of action
* when the selection change is 'real' or within temporary selection. */
virtual void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) {}
virtual void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) {}
};
#endif

View File

@@ -16,8 +16,8 @@ public:
void push(ViewController * vc, KDColor textColor = Palette::SubMenuText, KDColor backgroundColor = Palette::SubMenuBackground, KDColor separatorColor = Palette::SubMenuBorder);
void pop();
int depth();
View * view() override;
int depth() const { return m_numberOfChildren; }
View * view() override { return &m_view; }
ViewController * topViewController();
const char * title() override;
bool handleEvent(Ion::Events::Event event) override;

View File

@@ -23,8 +23,9 @@ public:
virtual View * subAccessoryView() const;
void drawRect(KDContext * ctx, KDRect rect) const override;
protected:
virtual KDCoordinate labelMargin() const { return Metric::TableCellHorizontalMargin; }
virtual KDCoordinate accessoryMargin() const { return Metric::TableCellHorizontalMargin; }
virtual KDColor backgroundColor() const { return KDColorWhite; }
virtual KDCoordinate labelMargin() const { return k_horizontalMargin; }
virtual KDCoordinate accessoryMargin() const { return k_horizontalMargin; }
int numberOfSubviews() const override;
View * subviewAtIndex(int index) override;
void layoutSubviews(bool force = false) override;

View File

@@ -58,8 +58,6 @@ protected:
* coordinates that refer to the data source entire table */
int absoluteColumnNumberFromSubviewIndex(int index) const;
int absoluteRowNumberFromSubviewIndex(int index) const;
int numberOfFullyDisplayableRows() const;
int numberOfFullyDisplayableColumns() const;
int typeOfSubviewAtIndex(int index) const;
/* This method transform a index (of subview for instance) into an index
* refering to the set of cells of type "type". */

View File

@@ -117,11 +117,12 @@ protected:
const char * editedText() const override { return m_text.text(); }
size_t editedTextLength() const override { return m_text.textLength(); }
const Text * getText() const { return &m_text; }
bool insertTextAtLocation(const char * text, char * location) override;
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
void moveCursorGeo(int deltaX, int deltaY);
bool removePreviousGlyph() override;
bool removeEndOfLine() override;
bool removeStartOfLine();
size_t removeText(const char * start, const char * end);
size_t deleteSelection() override;
protected:
KDRect glyphFrameAtPosition(const char * text, const char * position) const override;

View File

@@ -74,7 +74,7 @@ protected:
/* If the text to be appended is too long to be added without overflowing the
* buffer, nothing is done (not even adding few letters from the text to reach
* the maximum buffer capacity) and false is returned. */
bool insertTextAtLocation(const char * text, char * location) override;
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
KDSize minimalSizeForOptimalDisplay() const override;
bool removePreviousGlyph() override;
bool removeEndOfLine() override;

View File

@@ -49,7 +49,7 @@ protected:
// Virtual text get/add/remove
virtual const char * text() const = 0;
virtual bool insertTextAtLocation(const char * text, char * location) = 0;
virtual bool insertTextAtLocation(const char * text, char * location, int textLength = -1) = 0;
virtual bool removePreviousGlyph() = 0;
virtual bool removeEndOfLine() = 0;

View File

@@ -24,7 +24,7 @@ public:
N,
true);
}
const MessageTree * children(int index) const override { return &m_children[index]; }
const MessageTree * childAtIndex(int index) const override { return &m_children[index]; }
I18n::Message text() const { return m_text; }
I18n::Message insertedText() const { return m_insertedText; }
bool stripInsertedText() const { return m_stripInsertedText; }

View File

@@ -18,13 +18,11 @@ ExpressionView::ExpressionView(float horizontalAlignment, float verticalAlignmen
}
bool ExpressionView::setLayout(Layout layoutR) {
/* TODO: this would avoid some useless redrawing. However, when we call
* setLayout after raising an Exception that led to erase all
* Poincare::TreePool, accessing m_layout will result in an ACCESS ERROR.
* How do we avoid that? */
/*if (m_layout.isIdenticalTo(layoutR)) {
if (!m_layout.wasErasedByException() && m_layout.isIdenticalTo(layoutR)) {
/* Check m_layout.wasErasedByException(), otherwise accessing m_layout would
* result in an ACCESS ERROR. */
return false;
}*/
}
m_layout = layoutR;
markRectAsDirty(bounds());
return true;

View File

@@ -5,10 +5,14 @@
#include <escher/metric.h>
bool InputEventHandler::handleBoxEvent(Ion::Events::Event event) {
if (m_inputEventHandlerDelegate == nullptr) {
return false;
}
NestedMenuController * box = nullptr;
if (m_inputEventHandlerDelegate) {
box = event == Ion::Events::Toolbox ? m_inputEventHandlerDelegate->toolboxForInputEventHandler(this) : box;
box = event == Ion::Events::Var ? m_inputEventHandlerDelegate->variableBoxForInputEventHandler(this) : box;
if (event == Ion::Events::Toolbox) {
box = m_inputEventHandlerDelegate->toolboxForInputEventHandler(this);
} else if (event == Ion::Events::Var) {
box = m_inputEventHandlerDelegate->variableBoxForInputEventHandler(this);
}
if (box) {
box->setSender(this);

View File

@@ -2,6 +2,7 @@
#include <escher/clipboard.h>
#include <escher/text_field.h>
#include <poincare/expression.h>
#include <poincare/empty_layout.h>
#include <poincare/horizontal_layout.h>
#include <assert.h>
#include <string.h>
@@ -42,13 +43,16 @@ bool LayoutField::ContentView::setEditing(bool isEditing) {
void LayoutField::ContentView::useInsertionCursor() {
if (m_insertionCursor.isDefined()) {
m_cursor.layout().removeGreySquaresFromAllMatrixAncestors();
m_cursor = m_insertionCursor;
m_cursor.layout().addGreySquaresToAllMatrixAncestors();
}
}
void LayoutField::ContentView::clearLayout() {
HorizontalLayout h = HorizontalLayout::Builder();
if (m_expressionView.setLayout(h)) {
resetSelection();
m_cursor.setLayout(h);
}
}
@@ -234,6 +238,17 @@ void LayoutField::ContentView::deleteSelection() {
resetSelection();
}
void LayoutField::ContentView::updateInsertionCursor() {
if (!m_insertionCursor.isDefined()) {
Layout l = m_cursor.layout();
if (l.type() == LayoutNode::Type::EmptyLayout && static_cast<EmptyLayout &>(l).color() == EmptyLayoutNode::Color::Grey) {
// Don't set m_insertionCursor pointing to a layout which might disappear
return;
}
m_insertionCursor = m_cursor;
}
}
View * LayoutField::ContentView::subviewAtIndex(int index) {
assert(0 <= index && index < numberOfSubviews());
View * m_views[] = {&m_expressionView, &m_cursorView};

View File

@@ -4,7 +4,8 @@
MessageTableCell::MessageTableCell(I18n::Message label, const KDFont * font, Layout layout) :
TableCell(layout),
m_messageTextView(font, label, 0, 0.5, Palette::PrimaryText, Palette::ListCellBackground)
m_messageTextView(font, label, 0, 0.5, Palette::PrimaryText, Palette::ListCellBackground),
m_backgroundColor(KDColorWhite)
{
}
@@ -31,3 +32,8 @@ void MessageTableCell::setMessageFont(const KDFont * font) {
m_messageTextView.setFont(font);
layoutSubviews();
}
void MessageTableCell::setBackgroundColor(KDColor color) {
m_backgroundColor = color;
m_messageTextView.setBackgroundColor(color);
}

View File

@@ -0,0 +1,81 @@
#include <escher/modal_view_empty_controller.h>
#include <apps/i18n.h>
#include <assert.h>
constexpr KDColor ModalViewEmptyController::ModalViewEmptyView::k_backgroundColor;
// ModalViewEmptyController::ModalViewEmptyView
void ModalViewEmptyController::ModalViewEmptyView::initMessageViews() {
const int numberOfMessageViews = numberOfMessageTextViews();
for (int i = 0; i < numberOfMessageViews; i++) {
MessageTextView * message = messageTextViewAtIndex(i);
message->setFont(k_font);
message->setBackgroundColor(k_backgroundColor);
float verticalAlignment = 0.5f;
if (i == 0) {
verticalAlignment = 1.0f;
} else if (i == numberOfMessageViews - 1) {
verticalAlignment = 0.0f;
}
message->setAlignment(0.5f, verticalAlignment);
}
}
void ModalViewEmptyController::ModalViewEmptyView::setMessages(I18n::Message * message) {
const int numberOfMessageViews = numberOfMessageTextViews();
for (int i = 0; i < numberOfMessageViews; i++) {
messageTextViewAtIndex(i)->setMessage(message[i]);
}
}
void ModalViewEmptyController::ModalViewEmptyView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), k_backgroundColor);
drawBorderOfRect(ctx, bounds(), Palette::GreyBright);
}
int ModalViewEmptyController::ModalViewEmptyView::numberOfSubviews() const {
return numberOfMessageTextViews() + hasExpressionView();
}
View * ModalViewEmptyController::ModalViewEmptyView::subviewAtIndex(int index) {
if (hasExpressionView()) {
if (index == k_expressionViewRowIndex) {
return expressionView();
}
return messageTextViewAtIndex(index + (index < k_expressionViewRowIndex ? 0 : -1));
}
return messageTextViewAtIndex(index);
}
void ModalViewEmptyController::ModalViewEmptyView::layoutSubviews(bool force) {
const int numberOfMessageViews = numberOfMessageTextViews();
const bool hasExpression = hasExpressionView();
KDCoordinate width = bounds().width() - 2 * k_separatorThickness;
KDCoordinate height = bounds().height() - 2 * k_separatorThickness;
KDCoordinate textHeight = k_font->glyphSize().height();
KDCoordinate layoutHeight = hasExpression ? expressionView()->minimalSizeForOptimalDisplay().height() : 0;
KDCoordinate margin = (height - numberOfMessageViews * textHeight - layoutHeight) / 2;
if (hasExpression) {
expressionView()->setFrame(KDRect(
k_separatorThickness,
k_separatorThickness + margin + k_expressionViewRowIndex * textHeight,
width,
layoutHeight),
force);
}
KDCoordinate currentHeight = k_separatorThickness;
for (uint8_t i = 0; i < numberOfMessageViews; i++) {
if (hasExpression && i == k_expressionViewRowIndex) {
currentHeight += layoutHeight;
}
KDCoordinate h = (i == 0 || i == numberOfMessageViews - 1) ? textHeight + margin : textHeight;
messageTextViewAtIndex(i)->setFrame(KDRect(k_separatorThickness, currentHeight, width, h), force);
currentHeight += h;
}
}
// ModalViewEmptyController
void ModalViewEmptyController::setMessages(I18n::Message * messages) {
static_cast<ModalViewEmptyView *>(view())->setMessages(messages);
}

View File

@@ -90,7 +90,7 @@ void NestedMenuController::ListController::setFirstSelectedRow(int firstSelected
NestedMenuController::NestedMenuController(Responder * parentResponder, I18n::Message title) :
StackViewController(parentResponder, &m_listController, Palette::ToolboxHeaderText, Palette::ToolboxHeaderBackground, Palette::ToolboxHeaderBorder),
m_selectableTableView(&m_listController, this, this),
m_selectableTableView(&m_listController, this, this, this),
m_listController(this, &m_selectableTableView, title),
m_sender(nullptr)
{
@@ -98,6 +98,10 @@ NestedMenuController::NestedMenuController(Responder * parentResponder, I18n::Me
m_selectableTableView.setDecoratorType(ScrollView::Decorator::Type::None);
}
void NestedMenuController::setTitle(I18n::Message title) {
m_listController.setTitle(title);
}
bool NestedMenuController::handleEvent(Ion::Events::Event event) {
return handleEventForRow(event, selectedRow());
}

View File

@@ -130,6 +130,8 @@ constexpr KDColor Palette::Green;
constexpr KDColor Palette::GreenLight;
constexpr KDColor Palette::Brown;
constexpr KDColor Palette::Purple;
constexpr KDColor Palette::Cyan; // TODO Palette change
constexpr KDColor Palette::BlueishGrey; // TODO Palette change
constexpr KDColor Palette::DataColor[];
constexpr KDColor Palette::DataColorLight[];

View File

@@ -53,9 +53,16 @@ void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) {
if (!allowOverscroll && !m_contentView->bounds().contains(p)) {
return;
}
KDRect visibleRect = visibleContentRect();
if (visibleRect.width() < 0 || visibleRect.height() < 0) {
return;
}
KDCoordinate offsetX = 0;
KDCoordinate offsetY = 0;
KDRect visibleRect = visibleContentRect();
if (visibleRect.left() > p.x()) {
offsetX = p.x() - visibleRect.left();
}
@@ -74,8 +81,16 @@ void ScrollView::scrollToContentPoint(KDPoint p, bool allowOverscroll) {
// Handle cases when the size of the view has decreased.
setContentOffset(KDPoint(
std::min(contentOffset().x(), std::max<KDCoordinate>(minimalSizeForOptimalDisplay().width() - bounds().width(), KDCoordinate{0})),
std::min(contentOffset().y(), std::max<KDCoordinate>(minimalSizeForOptimalDisplay().height() - bounds().height(), 0))));
std::min(
contentOffset().x(),
std::max<KDCoordinate>(
minimalSizeForOptimalDisplay().width() - bounds().width(),
KDCoordinate(0))),
std::min(
contentOffset().y(),
std::max<KDCoordinate>(
minimalSizeForOptimalDisplay().height() - bounds().height(),
KDCoordinate(0)))));
}
void ScrollView::scrollToContentRect(KDRect rect, bool allowOverscroll) {
@@ -83,7 +98,7 @@ void ScrollView::scrollToContentRect(KDRect rect, bool allowOverscroll) {
KDPoint br = rect.bottomRight();
KDRect visibleRect = visibleContentRect();
/* We first check that we can display the whole rect. If we can't, we focus
* the croll to the closest part of the rect. */
* the scroll to the closest part of the rect. */
if (visibleRect.height() < rect.height()) {
// The visible rect is too small to display 'rect'
if (rect.top() >= visibleRect.top()) {

View File

@@ -1,4 +1,5 @@
#include <escher/scroll_view_indicator.h>
#include <escher/metric.h>
#include <escher/palette.h>
extern "C" {
#include <assert.h>
@@ -8,7 +9,7 @@ extern "C" {
ScrollViewIndicator::ScrollViewIndicator() :
View(),
m_color(Palette::ScrollBarForeground),
m_margin(14)
m_margin(Metric::CommonTopMargin)
{
}

View File

@@ -71,6 +71,7 @@ void SelectableTableView::deselectTable(bool withinTemporarySelection) {
selectRow(-1);
if (m_delegate) {
m_delegate->tableViewDidChangeSelection(this, previousSelectedCellX, previousSelectedCellY, withinTemporarySelection);
m_delegate->tableViewDidChangeSelectionAndDidScroll(this, previousSelectedCellX, previousSelectedCellY, withinTemporarySelection);
}
}
@@ -87,21 +88,28 @@ bool SelectableTableView::selectCellAtLocation(int i, int j, bool setFirstRespon
selectColumn(i);
selectRow(j);
/* The delegate is notified:
* - after changing the selected cell but before scrolling: for instance,
* ExpressionModelListController needs to update its memoized cell before
* being able to scroll;
* - after scrolling: for instance, the calculation history table might
* change its cell content when selected (outup toggling, ellipsis toggling)
* and thus need to access the right used cell - which is defined only
* after scrolling.
*/
if (m_delegate) {
m_delegate->tableViewDidChangeSelection(this, previousX, previousY, withinTemporarySelection);
}
/* We need to scroll:
* - After notifying the delegate. For instance,
* ExpressionModelListController needs to update its memoized cell
* height values before any scroll.
* - Before setting the first responder. If the first responder is a view, it
* might change during the scroll. */
if (selectedRow() >= 0) {
scrollToCell(selectedColumn(), selectedRow());
}
if (m_delegate) {
m_delegate->tableViewDidChangeSelectionAndDidScroll(this, previousX, previousY, withinTemporarySelection);
}
HighlightCell * cell = selectedCell();
if (cell) {
// Update first responder

View File

@@ -129,10 +129,6 @@ void StackViewController::pop() {
vc->viewDidDisappear();
}
int StackViewController::depth() {
return m_numberOfChildren;
}
void StackViewController::pushModel(Frame frame) {
m_childrenFrame[m_numberOfChildren++] = frame;
}
@@ -160,10 +156,6 @@ bool StackViewController::handleEvent(Ion::Events::Event event) {
return false;
}
View * StackViewController::view() {
return &m_view;
}
void StackViewController::initView() {
m_childrenFrame[0].viewController()->initView();
}

View File

@@ -98,16 +98,16 @@ void TableCell::layoutSubviews(bool force) {
y += labelHeight + k_verticalMargin;
}
horizontalMargin = k_separatorThickness + k_horizontalMargin;
y = std::max<KDCoordinate>(y, height - k_separatorThickness - withMargin(accessorySize.height(), Metric::TableCellVerticalMargin) - withMargin(subAccessorySize.height(), 0));
y = std::max<KDCoordinate>(y, height - k_separatorThickness - withMargin(accessorySize.height(), k_verticalMargin) - withMargin(subAccessorySize.height(), 0));
if (subAccessory) {
KDCoordinate subAccessoryHeight = std::min<KDCoordinate>(subAccessorySize.height(), height - y - k_separatorThickness - Metric::TableCellVerticalMargin);
KDCoordinate subAccessoryHeight = std::min<KDCoordinate>(subAccessorySize.height(), height - y - k_separatorThickness - k_verticalMargin);
accessory->setFrame(KDRect(horizontalMargin, y, width - 2*horizontalMargin, subAccessoryHeight), force);
y += subAccessoryHeight;
}
horizontalMargin = k_separatorThickness + accessoryMargin();
y = std::max<KDCoordinate>(y, height - k_separatorThickness - withMargin(accessorySize.height(), Metric::TableCellVerticalMargin));
y = std::max<KDCoordinate>(y, height - k_separatorThickness - withMargin(accessorySize.height(), k_verticalMargin));
if (accessory) {
KDCoordinate accessoryHeight = std::min<KDCoordinate>(accessorySize.height(), height - y - k_separatorThickness - Metric::TableCellVerticalMargin);
KDCoordinate accessoryHeight = std::min<KDCoordinate>(accessorySize.height(), height - y - k_separatorThickness - k_verticalMargin);
accessory->setFrame(KDRect(horizontalMargin, y, width - 2*horizontalMargin, accessoryHeight), force);
}
} else {
@@ -164,7 +164,7 @@ void TableCell::layoutSubviews(bool force) {
}
void TableCell::drawRect(KDContext * ctx, KDRect rect) const {
KDColor backgroundColor = isHighlighted() ? Palette::ListCellBackgroundSelected : Palette::ListCellBackground;
drawInnerRect(ctx, bounds(), backgroundColor);
KDColor backColor = isHighlighted() ? Palette::ListCellBackgroundSelected : Palette::ListCellBackground;
drawInnerRect(ctx, bounds(), backColor);
drawBorderOfRect(ctx, bounds(), Palette::ListCellBorder);
}

View File

@@ -177,55 +177,28 @@ void TableView::ContentView::layoutSubviews(bool force) {
}
}
int TableView::ContentView::numberOfFullyDisplayableRows() const {
// The number of displayable rows taking into accounts margins
int rowOffsetWithMargin = m_dataSource->indexFromCumulatedHeight(m_tableView->contentOffset().y() +
m_tableView->topMargin());
int displayedHeightWithOffsetAndMargin = m_dataSource->indexFromCumulatedHeight(m_tableView->maxContentHeightDisplayableWithoutScrolling() +
m_tableView->contentOffset().y() + m_tableView->topMargin());
return displayedHeightWithOffsetAndMargin - rowOffsetWithMargin;
}
int TableView::ContentView::numberOfFullyDisplayableColumns() const {
// The number of displayable rows taking into accounts margins
int columnOffsetWithMargin = m_dataSource->indexFromCumulatedWidth(m_tableView->contentOffset().x() +
m_tableView->leftMargin());
int displayedWidthWithOffsetAndMargin = m_dataSource->indexFromCumulatedWidth(m_tableView->maxContentWidthDisplayableWithoutScrolling() +
m_tableView->contentOffset().x() + m_tableView->leftMargin());
return displayedWidthWithOffsetAndMargin - columnOffsetWithMargin;
}
int TableView::ContentView::numberOfDisplayableRows() const {
int rowOffset = rowsScrollingOffset();
int displayedHeightWithOffset = m_dataSource->indexFromCumulatedHeight(m_tableView->bounds().height() + m_tableView->contentOffset().y());
return std::min(
m_dataSource->numberOfRows(),
displayedHeightWithOffset + 1
) - rowOffset;
int displayedHeightWithOffset = m_dataSource->indexFromCumulatedHeight(m_tableView->bounds().height() + (m_tableView->contentOffset().y() - m_tableView->topMargin()));
return std::min(m_dataSource->numberOfRows(), displayedHeightWithOffset + 1) - rowOffset;
}
int TableView::ContentView::numberOfDisplayableColumns() const {
int columnOffset = columnsScrollingOffset();
int displayedWidthWithOffset = m_dataSource->indexFromCumulatedWidth(m_tableView->bounds().width() + m_tableView->contentOffset().x());
return std::min(
m_dataSource->numberOfColumns(),
displayedWidthWithOffset + 1
) - columnOffset;
int displayedWidthWithOffset = m_dataSource->indexFromCumulatedWidth(m_tableView->bounds().width() + m_tableView->contentOffset().x() - m_tableView->leftMargin());
return std::min(m_dataSource->numberOfColumns(), displayedWidthWithOffset + 1) - columnOffset;
}
int TableView::ContentView::rowsScrollingOffset() const {
/* Here, we want to translate the offset at which our tableView is displaying
* us into an integer offset we can use to ask cells to our data source. */
KDCoordinate invisibleHeight = m_tableView->contentOffset().y()-m_tableView->topMargin();
invisibleHeight = invisibleHeight < 0 ? 0 : invisibleHeight;
KDCoordinate invisibleHeight = std::max(m_tableView->contentOffset().y() - m_tableView->topMargin(), 0);
return m_dataSource->indexFromCumulatedHeight(invisibleHeight);
}
int TableView::ContentView::columnsScrollingOffset() const {
/* Here, we want to translate the offset at which our tableView is displaying
* us into an integer offset we can use to ask cells to our data source. */
KDCoordinate invisibleWidth = m_tableView->contentOffset().x()-m_tableView->leftMargin();
invisibleWidth = invisibleWidth < 0 ? 0 : invisibleWidth;
KDCoordinate invisibleWidth = std::max(m_tableView->contentOffset().x() - m_tableView->leftMargin(), 0);
return m_dataSource->indexFromCumulatedWidth(invisibleWidth);
}

View File

@@ -258,11 +258,16 @@ void TextArea::Text::insertText(const char * s, int textLength, char * location)
assert(m_buffer != nullptr);
assert(location >= m_buffer && location < m_buffer + m_bufferSize - 1);
assert(strlen(m_buffer) + textLength < m_bufferSize);
// assert the text to insert does not overlap the location where to insert
assert(s >= location || s + textLength < location);
/* The text to insert might be located after the insertion location, in which
* case we cannot simply do a memmove, as s will be shifted by the copy. */
bool noShift = (s + textLength < location) || (s > m_buffer + m_bufferSize);
size_t sizeToMove = strlen(location) + 1;
assert(location + textLength + sizeToMove <= m_buffer + m_bufferSize);
memmove(location + textLength, location, sizeToMove);
memmove(location, s, textLength);
memmove(location, s + (noShift ? 0 : textLength), textLength);
}
void TextArea::Text::insertSpacesAtLocation(int numberOfSpaces, char * location) {
@@ -479,26 +484,19 @@ void TextArea::ContentView::setText(char * textBuffer, size_t textBufferSize) {
m_cursorLocation = text();
}
bool TextArea::ContentView::insertTextAtLocation(const char * text, char * location) {
int textSize = strlen(text);
if (m_text.textLength() + textSize >= m_text.bufferSize() || textSize == 0) {
bool TextArea::ContentView::insertTextAtLocation(const char * text, char * location, int textLength) {
int textLen = textLength < 0 ? strlen(text) : textLength;
assert(textLen < 0 || textLen <= strlen(text));
if (m_text.textLength() + textLen >= m_text.bufferSize() || textLen == 0) {
return false;
}
bool lineBreak = false;
// Scan for \n and 0
const char * nullLocation = UTF8Helper::PerformAtCodePoints(
text, '\n',
[](int codePointOffset, void * lineBreak, int context1, int context2) {
*((bool *)lineBreak) = true;
},
[](int c1, void * c2, int c3, int c4) { },
&lineBreak, 0);
// Scan for \n
bool lineBreak = UTF8Helper::HasCodePoint(text, '\n', text + textLen);
assert(UTF8Helper::CodePointIs(nullLocation, 0));
m_text.insertText(text, nullLocation - text, location);
m_text.insertText(text, textLen, location);
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, nullLocation - text);
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, textLen);
reloadRectFromPosition(location, lineBreak);
return true;
}
@@ -542,9 +540,13 @@ bool TextArea::ContentView::removeStartOfLine() {
return false;
}
size_t TextArea::ContentView::removeText(const char * start, const char * end) {
return m_text.removeText(start, end);
}
size_t TextArea::ContentView::deleteSelection() {
assert(!selectionIsEmpty());
size_t removedLength = m_text.removeText(m_selectionStart, m_selectionEnd);
size_t removedLength = removeText(m_selectionStart, m_selectionEnd);
/* We cannot call resetSelection() because m_selectionStart and m_selectionEnd
* are invalid */
m_selectionStart = nullptr;

View File

@@ -119,10 +119,10 @@ void TextField::ContentView::reinitDraftTextBuffer() {
setCursorLocation(s_draftTextBuffer);
}
bool TextField::ContentView::insertTextAtLocation(const char * text, char * location) {
bool TextField::ContentView::insertTextAtLocation(const char * text, char * location, int textLen) {
assert(m_isEditing);
int textLength = strlen(text);
size_t textLength = textLen < 0 ? strlen(text) : (size_t)textLen;
if (m_currentDraftTextLength + textLength >= m_draftTextBufferSize || textLength == 0) {
return false;
}
@@ -130,12 +130,12 @@ bool TextField::ContentView::insertTextAtLocation(const char * text, char * loca
memmove(location + textLength, location, (s_draftTextBuffer + m_currentDraftTextLength + 1) - location);
// Caution! One byte will be overridden by the null-terminating char of strlcpy
char * overridenByteLocation = location + textLength;
size_t copySize = std::min(textLength + 1, static_cast<size_t>((s_draftTextBuffer + m_draftTextBufferSize) - location));
char * overridenByteLocation = location + copySize - 1;
char overridenByte = *overridenByteLocation;
strlcpy(location, text, (s_draftTextBuffer + m_draftTextBufferSize) - location);
assert(overridenByteLocation < s_draftTextBuffer + m_draftTextBufferSize);
strlcpy(location, text, copySize);
*overridenByteLocation = overridenByte;
m_currentDraftTextLength += textLength;
m_currentDraftTextLength += copySize-1; // Do no count the null-termination
reloadRectFromPosition(m_horizontalAlignment == 0.0f ? location : s_draftTextBuffer);
return true;

View File

@@ -25,7 +25,7 @@ int Toolbox::reusableCellCount(int type) {
}
void Toolbox::willDisplayCellForIndex(HighlightCell * cell, int index) {
ToolboxMessageTree * messageTree = (ToolboxMessageTree *)m_messageTreeModel->children(index);
ToolboxMessageTree * messageTree = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(index);
if (messageTree->numberOfChildren() == 0) {
MessageTableCellWithMessage * myCell = (MessageTableCellWithMessage *)cell;
myCell->setMessage(messageTree->label());
@@ -39,7 +39,7 @@ void Toolbox::willDisplayCellForIndex(HighlightCell * cell, int index) {
}
int Toolbox::typeAtLocation(int i, int j) {
MessageTree * messageTree = (MessageTree *)m_messageTreeModel->children(j);
MessageTree * messageTree = (MessageTree *)m_messageTreeModel->childAtIndex(j);
if (messageTree->numberOfChildren() == 0) {
return LeafCellType;
}
@@ -48,7 +48,7 @@ int Toolbox::typeAtLocation(int i, int j) {
bool Toolbox::selectSubMenu(int selectedRow) {
m_selectableTableView.deselectTable();
m_messageTreeModel = (ToolboxMessageTree *)m_messageTreeModel->children(selectedRow);
m_messageTreeModel = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
return NestedMenuController::selectSubMenu(selectedRow);
}
@@ -63,7 +63,7 @@ bool Toolbox::returnToPreviousMenu() {
ToolboxMessageTree * parentMessageTree = (ToolboxMessageTree *)rootModel();
Stack::State * previousState = m_stack.stateAtIndex(index++);
while (currentDepth-- > 1) {
parentMessageTree = (ToolboxMessageTree *)parentMessageTree->children(previousState->selectedRow());
parentMessageTree = (ToolboxMessageTree *)parentMessageTree->childAtIndex(previousState->selectedRow());
previousState = m_stack.stateAtIndex(index++);
}
m_messageTreeModel = parentMessageTree;