diff --git a/apps/banner_view.cpp b/apps/banner_view.cpp index 0940b8004..f7c388422 100644 --- a/apps/banner_view.cpp +++ b/apps/banner_view.cpp @@ -1,5 +1,79 @@ #include "banner_view.h" +#include +#include void BannerView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(bounds(), KDColorWhite); } + +void BannerView::setLegendAtIndex(char * text, int index) { + TextView * textView = textViewAtIndex(index); + textView->setText(text); +} + +KDSize BannerView::minimalSizeForOptimalDisplay() { + return KDSize(0, KDText::stringSize(" ").height()*numberOfLines()); +} + +int BannerView::numberOfSubviews() const { + return 0; +} + +void BannerView::layoutSubviews() { + /* We iterate on subviews, adding their width until we exceed the view bound. + * The last subview that exceeds the bound is recorded as the first subview of + * the next line. For the current line, we scan again the subviews and frame + * them by equally distributing the remaining width. We then jump to the next + * line and iterate the process. */ + KDCoordinate totalWidth = bounds().width(); + KDCoordinate lineWidth = 0; + TextView * textViewPreviousLine = textViewAtIndex(0); + int indexOfFirstViewOfCurrentLine = 0; + KDCoordinate y = 0; + /* We do a last iteration of the loop to layout the last line. */ + for (int i = 0; i <= numberOfSubviews(); i++) { + TextView * textView = nullptr; + KDCoordinate currentViewWidth = totalWidth; + if (i < numberOfSubviews()) { + textView = textViewAtIndex(i); + currentViewWidth = textView->minimalSizeForOptimalDisplay().width(); + } + // The subview exceed the total width + if (lineWidth + currentViewWidth > totalWidth) { + KDCoordinate x = 0; + for (int j = indexOfFirstViewOfCurrentLine; j < i; j++) { + textViewPreviousLine = textViewAtIndex(j); + KDCoordinate textWidth = textViewPreviousLine->minimalSizeForOptimalDisplay().width() + (totalWidth - lineWidth)/(i-indexOfFirstViewOfCurrentLine); + KDCoordinate textHeight = textViewPreviousLine->minimalSizeForOptimalDisplay().height(); + textViewPreviousLine->setFrame(KDRect(x, y, textWidth, textHeight)); + x += textWidth; + } + // Next line + y += textViewPreviousLine->minimalSizeForOptimalDisplay().height(); + lineWidth = 0; + indexOfFirstViewOfCurrentLine = i; + } + lineWidth += currentViewWidth; + } +} + +View * BannerView::subviewAtIndex(int index) { + assert(index >= 0 && index < numberOfSubviews()); + return textViewAtIndex(index); +} + +int BannerView::numberOfLines() { + KDCoordinate width = bounds().width(); + KDCoordinate usedWidth = 0; + KDCoordinate lineNumber = 0; + for (int i = 0; i < numberOfSubviews(); i++) { + KDCoordinate textWidth = KDText::stringSize(textViewAtIndex(i)->text()).width(); + if (usedWidth+textWidth > width) { + usedWidth = textWidth; + lineNumber++; + } else { + usedWidth += textWidth; + } + } + return lineNumber+1; +} diff --git a/apps/banner_view.h b/apps/banner_view.h index 151cf1b7c..c857e12b4 100644 --- a/apps/banner_view.h +++ b/apps/banner_view.h @@ -5,8 +5,15 @@ class BannerView : public View { public: - virtual void reload() = 0; void drawRect(KDContext * ctx, KDRect rect) const override; + void setLegendAtIndex(char * text, int index); + KDSize minimalSizeForOptimalDisplay() override; + void layoutSubviews() override; +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + int numberOfLines(); + virtual TextView * textViewAtIndex(int i) = 0; }; #endif diff --git a/apps/curve_view_with_banner.cpp b/apps/curve_view_with_banner.cpp index f03303b4b..04a499eac 100644 --- a/apps/curve_view_with_banner.cpp +++ b/apps/curve_view_with_banner.cpp @@ -2,17 +2,17 @@ #include #include -CurveViewWithBanner::CurveViewWithBanner(CurveViewWindow * curveViewWindow, float topMarginFactor, - float rightMarginFactor, float bottomMarginFactor, float leftMarginFactor) : +CurveViewWithBanner::CurveViewWithBanner(CurveViewWindow * curveViewWindow, BannerView * bannerView, + float topMarginFactor, float rightMarginFactor, float bottomMarginFactor, float leftMarginFactor) : CurveView(curveViewWindow, topMarginFactor, rightMarginFactor, bottomMarginFactor, leftMarginFactor), - m_mainViewSelected(true) + m_mainViewSelected(true), + m_bannerView(bannerView) { } void CurveViewWithBanner::reload() { markRectAsDirty(bounds()); computeLabels(Axis::Horizontal); - bannerView()->reload(); } bool CurveViewWithBanner::isMainViewSelected() { @@ -33,13 +33,15 @@ int CurveViewWithBanner::numberOfSubviews() const { View * CurveViewWithBanner::subviewAtIndex(int index) { assert(index == 0); - return bannerView(); + return m_bannerView; } void CurveViewWithBanner::layoutSubviews() { - KDRect bannerFrame(KDRect(0, bounds().height()- k_bannerHeight, bounds().width(), k_bannerHeight)); + m_bannerView->setFrame(bounds()); + KDCoordinate bannerHeight = m_bannerView->minimalSizeForOptimalDisplay().height(); + KDRect bannerFrame(KDRect(0, bounds().height()- bannerHeight, bounds().width(), bannerHeight)); if (!m_mainViewSelected) { bannerFrame = KDRectZero; } - bannerView()->setFrame(bannerFrame); + m_bannerView->setFrame(bannerFrame); } diff --git a/apps/curve_view_with_banner.h b/apps/curve_view_with_banner.h index f982aa7c3..0418ca05b 100644 --- a/apps/curve_view_with_banner.h +++ b/apps/curve_view_with_banner.h @@ -7,8 +7,8 @@ class CurveViewWithBanner : public CurveView { public: - CurveViewWithBanner(CurveViewWindow * curveViewWindow = nullptr, float topMarginFactor = 0.0f, - float rightMarginFactor = 0.0f, float bottomMarginFactor = 0.0f, float leftMarginFactor = 0.0f); + CurveViewWithBanner(CurveViewWindow * curveViewWindow = nullptr, BannerView * bannerView = nullptr, + float topMarginFactor = 0.0f, float rightMarginFactor = 0.0f, float bottomMarginFactor = 0.0f, float leftMarginFactor = 0.0f); virtual void reloadSelection() = 0; void reload() override; bool isMainViewSelected(); @@ -16,9 +16,8 @@ public: protected: void layoutSubviews() override; bool m_mainViewSelected; - virtual BannerView * bannerView() = 0; + BannerView * m_bannerView; private: - constexpr static KDCoordinate k_bannerHeight = 30; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; }; diff --git a/apps/curve_view_with_banner_and_cursor.cpp b/apps/curve_view_with_banner_and_cursor.cpp index 15bb09277..33783b4c5 100644 --- a/apps/curve_view_with_banner_and_cursor.cpp +++ b/apps/curve_view_with_banner_and_cursor.cpp @@ -3,10 +3,10 @@ constexpr KDColor CurveViewWithBannerAndCursor::k_gridColor; -CurveViewWithBannerAndCursor::CurveViewWithBannerAndCursor(CurveViewWindowWithCursor * curveViewWindowWithCursor, float topMarginFactor, - float rightMarginFactor, float bottomMarginFactor, float leftMarginFactor) : - CurveViewWithBanner(curveViewWindowWithCursor, topMarginFactor, rightMarginFactor, bottomMarginFactor, leftMarginFactor), - m_cursorView(CursorView()), +CurveViewWithBannerAndCursor::CurveViewWithBannerAndCursor(CurveViewWindowWithCursor * curveViewWindowWithCursor, + BannerView * bannerView, CursorView * cursorView, float topMarginFactor, float rightMarginFactor, float bottomMarginFactor, float leftMarginFactor) : + CurveViewWithBanner(curveViewWindowWithCursor, bannerView, topMarginFactor, rightMarginFactor, bottomMarginFactor, leftMarginFactor), + m_cursorView(cursorView), m_curveViewWindowWithCursor(curveViewWindowWithCursor) { } @@ -16,7 +16,6 @@ void CurveViewWithBannerAndCursor::reload() { computeLabels(Axis::Horizontal); computeLabels(Axis::Vertical); layoutSubviews(); - bannerView()->reload(); } void CurveViewWithBannerAndCursor::reloadSelection() { @@ -25,7 +24,6 @@ void CurveViewWithBannerAndCursor::reloadSelection() { KDRect dirtyZone(KDRect(pixelXSelection - k_cursorSize/2, pixelYSelection - k_cursorSize/2, k_cursorSize, k_cursorSize)); markRectAsDirty(dirtyZone); layoutSubviews(); - bannerView()->reload(); } void CurveViewWithBannerAndCursor::drawGrid(KDContext * ctx, KDRect rect) const { @@ -40,7 +38,7 @@ void CurveViewWithBannerAndCursor::layoutSubviews() { if (!m_mainViewSelected) { cursorFrame = KDRectZero; } - m_cursorView.setFrame(cursorFrame); + m_cursorView->setFrame(cursorFrame); CurveViewWithBanner::layoutSubviews(); } @@ -51,7 +49,7 @@ int CurveViewWithBannerAndCursor::numberOfSubviews() const { View * CurveViewWithBannerAndCursor::subviewAtIndex(int index) { assert(index >= 0 && index < 2); if (index == 0) { - return &m_cursorView; + return m_cursorView; } - return bannerView(); + return m_bannerView; } diff --git a/apps/curve_view_with_banner_and_cursor.h b/apps/curve_view_with_banner_and_cursor.h index 99393d303..802538295 100644 --- a/apps/curve_view_with_banner_and_cursor.h +++ b/apps/curve_view_with_banner_and_cursor.h @@ -8,8 +8,8 @@ class CurveViewWithBannerAndCursor : public CurveViewWithBanner { public: - CurveViewWithBannerAndCursor(CurveViewWindowWithCursor * curveViewWindowWithCursor = nullptr, float topMarginFactor = 0.0f, - float rightMarginFactor = 0.0f, float bottomMarginFactor = 0.0f, float leftMarginFactor = 0.0f); + CurveViewWithBannerAndCursor(CurveViewWindowWithCursor * curveViewWindowWithCursor = nullptr, BannerView * bannerView = nullptr, + CursorView * cursorView = nullptr, float topMarginFactor = 0.0f, float rightMarginFactor = 0.0f, float bottomMarginFactor = 0.0f, float leftMarginFactor = 0.0f); void reload() override; void reloadSelection() override; void drawGrid(KDContext * ctx, KDRect rect) const; @@ -20,7 +20,7 @@ protected: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; - CursorView m_cursorView; + CursorView * m_cursorView; CurveViewWindowWithCursor * m_curveViewWindowWithCursor; }; diff --git a/apps/curve_view_with_banner_and_cursor_controller.cpp b/apps/curve_view_with_banner_and_cursor_controller.cpp index 4c1b9f4fc..8527b51c8 100644 --- a/apps/curve_view_with_banner_and_cursor_controller.cpp +++ b/apps/curve_view_with_banner_and_cursor_controller.cpp @@ -24,7 +24,8 @@ CurveViewWindowWithBannerAndCursorController::CurveViewWindowWithBannerAndCursor CurveViewWindowWithBannerAndCursorController * graphController = (CurveViewWindowWithBannerAndCursorController *) context; StackViewController * stack = graphController->stackController(); stack->push(graphController->initialisationParameterController()); - }, this)) + }, this)), + m_cursorView(CursorView()) { } @@ -42,6 +43,7 @@ bool CurveViewWindowWithBannerAndCursorController::handleEvent(Ion::Events::Even headerViewController()->setSelectedButton(-1); m_graphView->selectMainView(true); m_graphView->reloadSelection(); + reloadBannerView(); return true; } if (event == Ion::Events::Up) { @@ -54,11 +56,13 @@ bool CurveViewWindowWithBannerAndCursorController::handleEvent(Ion::Events::Even if (event == Ion::Events::Plus) { m_graphWindow->zoom(1.0f/3.0f); m_graphView->reload(); + reloadBannerView(); return true; } if (event == Ion::Events::Minus) { m_graphWindow->zoom(3.0f/4.0f); m_graphView->reload(); + reloadBannerView(); return true; } if (event == Ion::Events::Left || event == Ion::Events::Right) { @@ -70,6 +74,7 @@ bool CurveViewWindowWithBannerAndCursorController::handleEvent(Ion::Events::Even } else { m_graphView->reload(); } + reloadBannerView(); return (didMoveCursor >= 0); } if (event == Ion::Events::Down || event == Ion::Events::Up) { @@ -90,6 +95,7 @@ bool CurveViewWindowWithBannerAndCursorController::handleEvent(Ion::Events::Even if (didMoveCursor == 1) { m_graphView->reload(); } + reloadBannerView(); return true; } if (event == Ion::Events::OK) { @@ -105,6 +111,7 @@ void CurveViewWindowWithBannerAndCursorController::didBecomeFirstResponder() { headerViewController()->layoutView(); // Reload graph view m_graphView->reload(); + reloadBannerView(); } ViewController * CurveViewWindowWithBannerAndCursorController::windowParameterController() { diff --git a/apps/curve_view_with_banner_and_cursor_controller.h b/apps/curve_view_with_banner_and_cursor_controller.h index 53aa51920..8dbace239 100644 --- a/apps/curve_view_with_banner_and_cursor_controller.h +++ b/apps/curve_view_with_banner_and_cursor_controller.h @@ -27,6 +27,7 @@ protected: virtual bool handleEnter() = 0; Responder * tabController() const; StackViewController * stackController() const; + virtual void reloadBannerView() = 0; CurveViewWindowWithCursor * m_graphWindow; CurveViewWithBannerAndCursor * m_graphView; WindowParameterController m_windowParameterController; @@ -34,6 +35,7 @@ protected: Button m_windowButton; Button m_zoomButton; Button m_defaultInitialisationButton; + CursorView m_cursorView; }; #endif diff --git a/apps/graph/graph/banner_view.cpp b/apps/graph/graph/banner_view.cpp index 04f363b39..3f214f8e5 100644 --- a/apps/graph/graph/banner_view.cpp +++ b/apps/graph/graph/banner_view.cpp @@ -1,38 +1,15 @@ #include "banner_view.h" -#include -#include -#include "../../constant.h" namespace Graph { -BannerView::BannerView(GraphWindow * graphWindow) : - m_abscissaView(0.0f, 0.5f), +BannerView::BannerView() : + m_abscissaView(0.5f, 0.5f), m_functionView(0.5f, 0.5f), - m_derivativeView(1.0f, 0.5f), - m_displayDerivative(false), - m_graphWindow(graphWindow) + m_derivativeView(0.5f, 0.5f), + m_displayDerivative(false) { } -void BannerView::reload() { - markRectAsDirty(bounds()); - char buffer[k_maxNumberOfCharacters+Constant::FloatBufferSizeInScientificMode] = {'x', ' ', '=', ' ',0}; - Float(m_graphWindow->xCursorPosition()).convertFloatToText(buffer+4, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_abscissaView.setText(buffer); - - strlcpy(buffer, "00(x) = ", k_maxNumberOfCharacters+1); - buffer[1] = m_graphWindow->functionSelectedByCursor()->name()[0]; - Float(m_graphWindow->yCursorPosition()).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_functionView.setText(buffer+1); - - if (m_displayDerivative) { - buffer[0] = m_graphWindow->functionSelectedByCursor()->name()[0]; - buffer[1] = '\''; - Float(m_graphWindow->derivativeAtCursorPosition()).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaForDerivativeNumberInScientificMode); - m_derivativeView.setText(buffer); - } -} - void BannerView::setDisplayDerivative(bool displayDerivative) { m_displayDerivative = displayDerivative; } @@ -48,21 +25,9 @@ int BannerView::numberOfSubviews() const { return 2; } -View * BannerView::subviewAtIndex(int index) { - assert(index >= 0); - if (index == 0) { - return &m_abscissaView; - } - if (index == 1) { - return &m_functionView; - } - return &m_derivativeView; -} - -void BannerView::layoutSubviews() { - m_abscissaView.setFrame(bounds()); - m_functionView.setFrame(bounds()); - m_derivativeView.setFrame(bounds()); +TextView * BannerView::textViewAtIndex(int i) { + TextView * textViews[3] = {&m_abscissaView, &m_functionView, &m_derivativeView}; + return textViews[i]; } } diff --git a/apps/graph/graph/banner_view.h b/apps/graph/graph/banner_view.h index 6dfd2170b..a861a8d3a 100644 --- a/apps/graph/graph/banner_view.h +++ b/apps/graph/graph/banner_view.h @@ -2,27 +2,22 @@ #define GRAPH_BANNER_VIEW_H #include -#include "graph_window.h" #include "../../banner_view.h" namespace Graph { class BannerView : public ::BannerView { public: - BannerView(GraphWindow * graphWindow); - void reload() override; + BannerView(); void setDisplayDerivative(bool displayDerivative); bool displayDerivative(); private: - constexpr static int k_maxNumberOfCharacters = 8; int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; + TextView * textViewAtIndex(int i) override; BufferTextView m_abscissaView; BufferTextView m_functionView; BufferTextView m_derivativeView; bool m_displayDerivative; - GraphWindow * m_graphWindow; }; } diff --git a/apps/graph/graph/curve_parameter_controller.cpp b/apps/graph/graph/curve_parameter_controller.cpp index 60b2b265e..bee2e0c4f 100644 --- a/apps/graph/graph/curve_parameter_controller.cpp +++ b/apps/graph/graph/curve_parameter_controller.cpp @@ -3,9 +3,9 @@ namespace Graph { -CurveParameterController::CurveParameterController(GraphView * graphView, GraphWindow * graphWindow) : +CurveParameterController::CurveParameterController(GraphWindow * graphWindow, BannerView * bannerView) : ViewController(nullptr), - m_graphView(graphView), + m_bannerView(bannerView), m_function(nullptr), m_calculationCell(ChevronMenuListCell((char*)"Calculer")), m_goToCell(ChevronMenuListCell((char*)"Aller a")), @@ -32,7 +32,7 @@ void CurveParameterController::didBecomeFirstResponder() { void CurveParameterController::willDisplayCellForIndex(TableViewCell * cell, int index) { if (cell == &m_derivativeCell) { SwitchView * switchView = (SwitchView *)m_derivativeCell.accessoryView(); - switchView->setState(m_graphView->bannerView()->displayDerivative()); + switchView->setState(m_bannerView->displayDerivative()); } } @@ -50,8 +50,7 @@ bool CurveParameterController::handleEvent(Ion::Events::Event event) { } case 2: { - BannerView * bannerView = (BannerView *)m_graphView->bannerView(); - bannerView->setDisplayDerivative(!bannerView->displayDerivative()); + m_bannerView->setDisplayDerivative(!m_bannerView->displayDerivative()); m_selectableTableView.reloadData(); return true; } diff --git a/apps/graph/graph/curve_parameter_controller.h b/apps/graph/graph/curve_parameter_controller.h index a6c6bb8f5..b18c51d42 100644 --- a/apps/graph/graph/curve_parameter_controller.h +++ b/apps/graph/graph/curve_parameter_controller.h @@ -3,13 +3,14 @@ #include #include "goto_parameter_controller.h" +#include "banner_view.h" #include "../function.h" namespace Graph { class CurveParameterController : public ViewController, public SimpleListViewDataSource { public: - CurveParameterController(GraphView * graphView, GraphWindow * graphWindow); + CurveParameterController(GraphWindow * graphWindow, BannerView * bannerView); View * view() override; const char * title() const override; @@ -22,7 +23,7 @@ public: void willDisplayCellForIndex(TableViewCell * cell, int index) override; void setFunction(Function * function); private: - GraphView * m_graphView; + BannerView * m_bannerView; Function * m_function; constexpr static int k_totalNumberOfCells = 3; ChevronMenuListCell m_calculationCell; diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 5df46f05b..24ab0701a 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -7,10 +7,11 @@ namespace Graph { GraphController::GraphController(Responder * parentResponder, FunctionStore * functionStore, HeaderViewController * header) : CurveViewWindowWithBannerAndCursorController(parentResponder, header, &m_graphWindow, &m_view), - m_view(GraphView(functionStore, &m_graphWindow)), + m_bannerView(BannerView()), + m_view(GraphView(functionStore, &m_graphWindow, &m_bannerView, &m_cursorView)), m_graphWindow(functionStore), m_initialisationParameterController(InitialisationParameterController(this, &m_graphWindow)), - m_curveParameterController(CurveParameterController(&m_view, &m_graphWindow)), + m_curveParameterController(CurveParameterController(&m_graphWindow, &m_bannerView)), m_functionStore(functionStore) { } @@ -64,4 +65,23 @@ bool GraphController::handleEnter() { return true; } +void GraphController::reloadBannerView() { + char buffer[k_maxNumberOfCharacters+Constant::FloatBufferSizeInScientificMode] = {'x', ' ', '=', ' ',0}; + Float(m_graphWindow.xCursorPosition()).convertFloatToText(buffer+4, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 0); + + strlcpy(buffer, "00(x) = ", k_maxNumberOfCharacters+1); + buffer[1] = m_graphWindow.functionSelectedByCursor()->name()[0]; + Float(m_graphWindow.yCursorPosition()).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer+1, 1); + + if (m_bannerView.displayDerivative()) { + buffer[0] = m_graphWindow.functionSelectedByCursor()->name()[0]; + buffer[1] = '\''; + Float(m_graphWindow.derivativeAtCursorPosition()).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaForDerivativeNumberInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 2); + } + m_bannerView.layoutSubviews(); +} + } diff --git a/apps/graph/graph/graph_controller.h b/apps/graph/graph/graph_controller.h index ac2e1b858..d92c6f045 100644 --- a/apps/graph/graph/graph_controller.h +++ b/apps/graph/graph/graph_controller.h @@ -4,6 +4,7 @@ #include #include "graph_view.h" #include "graph_window.h" +#include "banner_view.h" #include "curve_parameter_controller.h" #include "initialisation_parameter_controller.h" #include "../../curve_view_with_banner_and_cursor_controller.h" @@ -21,7 +22,10 @@ public: const char * emptyMessage() override; private: + constexpr static int k_maxNumberOfCharacters = 8; bool handleEnter() override; + void reloadBannerView() override; + BannerView m_bannerView; GraphView m_view; GraphWindow m_graphWindow; InitialisationParameterController m_initialisationParameterController; diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index 57cc0a001..6813b1257 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -5,18 +5,13 @@ namespace Graph { -GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow) : - CurveViewWithBannerAndCursor(graphWindow, 0.0f, 0.0f, 0.2f, 0.0f), - m_bannerView(BannerView(graphWindow)), +GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow, BannerView * bannerView, CursorView * cursorView) : + CurveViewWithBannerAndCursor(graphWindow, bannerView, cursorView, 0.0f, 0.0f, 0.2f, 0.0f), m_functionStore(functionStore), m_context(nullptr) { } -BannerView * GraphView::bannerView() { - return &m_bannerView; -} - void GraphView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(rect, KDColorWhite); drawGrid(ctx, rect); diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index 063c04f7b..03b96050c 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -2,8 +2,6 @@ #define GRAPH_GRAPH_VIEW_H #include -#include "banner_view.h" -#include "../../cursor_view.h" #include "graph_window.h" #include "../../curve_view_with_banner_and_cursor.h" #include "../../constant.h" @@ -14,15 +12,13 @@ namespace Graph { class GraphView : public CurveViewWithBannerAndCursor { public: - GraphView(FunctionStore * functionStore, GraphWindow * graphWindow); - BannerView * bannerView() override; + GraphView(FunctionStore * functionStore, GraphWindow * graphWindow, BannerView * bannerView, CursorView * cursorView); void drawRect(KDContext * ctx, KDRect rect) const override; void setContext(Context * context); Context * context() const; private: char * label(Axis axis, int index) const override; float evaluateModelWithParameter(Model * expression, float abscissa) const override; - BannerView m_bannerView; char m_xLabels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; char m_yLabels[k_maxNumberOfYLabels][Constant::FloatBufferSizeInScientificMode]; FunctionStore * m_functionStore; diff --git a/apps/regression/banner_view.cpp b/apps/regression/banner_view.cpp index ae812e835..b3ee8ba87 100644 --- a/apps/regression/banner_view.cpp +++ b/apps/regression/banner_view.cpp @@ -1,93 +1,23 @@ #include "banner_view.h" -#include "../constant.h" -#include -#include namespace Regression { -BannerView::BannerView(Store * store) : +BannerView::BannerView() : m_regressionTypeView(nullptr, 0.5f, 0.5f), m_slopeView(0.5f, 0.5f), m_yInterceptView(0.5f, 0.5f), m_xView(0.5f, 0.5f), - m_yView(0.5f, 0.5f), - m_store(store) + m_yView(0.5f, 0.5f) { } -void BannerView::reload() { - markRectAsDirty(bounds()); - m_regressionTypeView.setText("y = ax+b"); - char buffer[k_maxNumberOfCharacters]; - const char * legend = "a = "; - float slope = m_store->slope(); - int legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - Float(slope).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_slopeView.setText(buffer); - - legend = "b = "; - float yIntercept = m_store->yIntercept(); - legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - Float(yIntercept).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_yInterceptView.setText(buffer); - - legend = "x = "; - float x = m_store->xCursorPosition(); - // Display a specific legend if the mean dot is selected - if (m_store->selectedDotIndex() == m_store->numberOfPairs()) { - legend = "x^ = "; - x = m_store->meanOfColumn(0); - } - legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - Float(x).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_xView.setText(buffer); - - legend = "y = "; - float y = m_store->yCursorPosition(); - if (m_store->selectedDotIndex() == m_store->numberOfPairs()) { - legend = "y^ = "; - y = m_store->meanOfColumn(1); - } - legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - Float(y).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_yView.setText(buffer); -} - int BannerView::numberOfSubviews() const { return 5; } -View * BannerView::subviewAtIndex(int index) { - assert(index >= 0); - switch (index) { - case 0: - return &m_regressionTypeView; - case 1: - return &m_slopeView; - case 2: - return &m_yInterceptView; - case 3: - return &m_xView; - case 4: - return &m_yView; - default: - assert(false); - return nullptr; - } -} - -void BannerView::layoutSubviews() { - KDCoordinate height = bounds().height(); - KDCoordinate width = bounds().width(); - m_regressionTypeView.setFrame(KDRect(0, 0, width/3, height/2)); - m_slopeView.setFrame(KDRect(width/3, 0, width/3, height/2)); - m_yInterceptView.setFrame(KDRect(2*width/3, 0, width/3, height/2)); - m_xView.setFrame(KDRect(0, height/2, width/3, height/2)); - m_yView.setFrame(KDRect(width/3, height/2, width/3, height/2)); +TextView * BannerView::textViewAtIndex(int i) { + TextView * textViews[5] = {&m_regressionTypeView, &m_slopeView, &m_yInterceptView, &m_xView, &m_yView}; + return textViews[i]; } } diff --git a/apps/regression/banner_view.h b/apps/regression/banner_view.h index 41f850b7d..eb3e33739 100644 --- a/apps/regression/banner_view.h +++ b/apps/regression/banner_view.h @@ -2,26 +2,21 @@ #define REGRESSION_BANNER_VIEW_H #include -#include "store.h" #include "../banner_view.h" namespace Regression { class BannerView : public ::BannerView { public: - BannerView(Store * store); - void reload() override; + BannerView(); private: - constexpr static int k_maxNumberOfCharacters = 50; int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; + TextView * textViewAtIndex(int i) override; PointerTextView m_regressionTypeView; BufferTextView m_slopeView; BufferTextView m_yInterceptView; BufferTextView m_xView; BufferTextView m_yView; - Store * m_store; }; } diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 0ca42c06d..06ee3f6ab 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -4,7 +4,7 @@ namespace Regression { GraphController::GraphController(Responder * parentResponder, HeaderViewController * headerViewController, Store * store) : CurveViewWindowWithBannerAndCursorController(parentResponder, headerViewController, store, &m_view), - m_view(GraphView(store)), + m_view(GraphView(store, &m_bannerView, &m_cursorView)), m_store(store), m_initialisationParameterController(InitialisationParameterController(this, m_store)), m_predictionParameterController(PredictionParameterController(this, m_store)) @@ -48,4 +48,47 @@ bool GraphController::handleEnter() { return false; } +void GraphController::reloadBannerView() { + m_bannerView.setLegendAtIndex((char *)"y = ax+b", 0); + char buffer[k_maxNumberOfCharacters + Constant::FloatBufferSizeInScientificMode]; + const char * legend = "a = "; + float slope = m_store->slope(); + int legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + Float(slope).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 1); + + legend = "b = "; + float yIntercept = m_store->yIntercept(); + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + Float(yIntercept).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 2); + + legend = "x = "; + float x = m_store->xCursorPosition(); + // Display a specific legend if the mean dot is selected + if (m_store->selectedDotIndex() == m_store->numberOfPairs()) { + legend = "x^ = "; + x = m_store->meanOfColumn(0); + } + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + Float(x).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 3); + + legend = "y = "; + float y = m_store->yCursorPosition(); + if (m_store->selectedDotIndex() == m_store->numberOfPairs()) { + legend = "y^ = "; + y = m_store->meanOfColumn(1); + } + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + Float(y).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 4); + + m_bannerView.layoutSubviews(); +} + } diff --git a/apps/regression/graph_controller.h b/apps/regression/graph_controller.h index 5c1ca5176..773c9b942 100644 --- a/apps/regression/graph_controller.h +++ b/apps/regression/graph_controller.h @@ -2,6 +2,7 @@ #define REGRESSION_GRAPH_CONTROLLER_H #include +#include "banner_view.h" #include "store.h" #include "graph_view.h" #include "initialisation_parameter_controller.h" @@ -19,7 +20,10 @@ public: bool isEmpty() override; const char * emptyMessage() override; private: + constexpr static int k_maxNumberOfCharacters = 8; bool handleEnter() override; + void reloadBannerView() override; + BannerView m_bannerView; GraphView m_view; Store * m_store; uint32_t m_storeVersion; diff --git a/apps/regression/graph_view.cpp b/apps/regression/graph_view.cpp index 8b4e872b3..f01fdf091 100644 --- a/apps/regression/graph_view.cpp +++ b/apps/regression/graph_view.cpp @@ -4,10 +4,9 @@ namespace Regression { -GraphView::GraphView(Store * store) : - CurveViewWithBannerAndCursor(store, 0.05f, 0.05f, 0.25f, 0.05f), - m_store(store), - m_bannerView(BannerView(store)) +GraphView::GraphView(Store * store, BannerView * bannerView, CursorView * cursorView) : + CurveViewWithBannerAndCursor(store, bannerView, cursorView, 0.05f, 0.05f, 0.25f, 0.05f), + m_store(store) { } @@ -32,10 +31,6 @@ char * GraphView::label(Axis axis, int index) const { return (char *)m_xLabels[index]; } -BannerView * GraphView::bannerView() { - return &m_bannerView; -} - float GraphView::evaluateModelWithParameter(Model * curve, float t) const { return m_store->yValueForXValue(t); } diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index 1bd25b1d9..c723bc994 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -3,7 +3,6 @@ #include #include "store.h" -#include "banner_view.h" #include "../constant.h" #include "../cursor_view.h" #include "../curve_view_with_banner_and_cursor.h" @@ -12,17 +11,15 @@ namespace Regression { class GraphView : public CurveViewWithBannerAndCursor { public: - GraphView(Store * store); + GraphView(Store * store, ::BannerView * bannerView, CursorView * cursorView); void drawRect(KDContext * ctx, KDRect rect) const override; private: constexpr static KDCoordinate k_dotSize = 5; char * label(Axis axis, int index) const override; - BannerView * bannerView() override; float evaluateModelWithParameter(Model * curve, float t) const override; Store * m_store; char m_xLabels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; char m_yLabels[k_maxNumberOfYLabels][Constant::FloatBufferSizeInScientificMode]; - BannerView m_bannerView; }; } diff --git a/apps/statistics/box_banner_view.cpp b/apps/statistics/box_banner_view.cpp index d470c8913..1e5a3a0f6 100644 --- a/apps/statistics/box_banner_view.cpp +++ b/apps/statistics/box_banner_view.cpp @@ -1,64 +1,20 @@ #include "box_banner_view.h" -#include "box_view.h" -#include "../constant.h" -#include -#include namespace Statistics { -BoxBannerView::BoxBannerView(Store * store, BoxView * boxView) : +BoxBannerView::BoxBannerView() : m_calculationName(nullptr, 0.0f, 0.5f), - m_calculationValue(1.0f, 0.5f), - m_store(store), - m_boxView(boxView) + m_calculationValue(1.0f, 0.5f) { } -void BoxBannerView::reload() { - markRectAsDirty(bounds()); - const char * calculationName[5] = {"Minimum", "Premier quartile", "Mediane", "Troisieme quartile", "Maximum"}; - m_calculationName.setText(calculationName[m_boxView->selectedQuantile()]); - - char buffer[Constant::FloatBufferSizeInScientificMode]; - float calculation = 0.0f; - switch(m_boxView->selectedQuantile()) { - case 0: - calculation = m_store->minValue(); - break; - case 1: - calculation = m_store->firstQuartile(); - break; - case 2: - calculation = m_store->median(); - break; - case 3: - calculation = m_store->thirdQuartile(); - break; - case 4: - calculation = m_store->maxValue(); - break; - } - Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_calculationValue.setText(buffer); -} - int BoxBannerView::numberOfSubviews() const { return 2; } -View * BoxBannerView::subviewAtIndex(int index) { - assert(index == 0 || index == 1); - if (index == 0) { - return &m_calculationName; - } - return &m_calculationValue; -} - -void BoxBannerView::layoutSubviews() { - KDCoordinate height = bounds().height(); - KDCoordinate width = bounds().width(); - m_calculationName.setFrame(KDRect(0, 0, width/2, height)); - m_calculationValue.setFrame(KDRect(width/2, 0, width/2, height)); +TextView * BoxBannerView::textViewAtIndex(int index) { + TextView * textViews[2] = {&m_calculationName, &m_calculationValue}; + return textViews[index]; } } diff --git a/apps/statistics/box_banner_view.h b/apps/statistics/box_banner_view.h index 6983368d6..c47b9c6b9 100644 --- a/apps/statistics/box_banner_view.h +++ b/apps/statistics/box_banner_view.h @@ -2,26 +2,18 @@ #define STATISTICS_BOX_BANNER_VIEW_H #include -#include "store.h" #include "../banner_view.h" namespace Statistics { -class BoxView; - class BoxBannerView : public ::BannerView { public: - BoxBannerView(Store * store, BoxView * boxView); - void reload() override; + BoxBannerView(); private: - constexpr static int k_maxNumberOfCharacters = 50; int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; + TextView * textViewAtIndex(int i) override; PointerTextView m_calculationName; BufferTextView m_calculationValue; - Store * m_store; - BoxView * m_boxView; }; } diff --git a/apps/statistics/box_controller.cpp b/apps/statistics/box_controller.cpp index 289a4b03c..5ce49bf19 100644 --- a/apps/statistics/box_controller.cpp +++ b/apps/statistics/box_controller.cpp @@ -5,7 +5,8 @@ namespace Statistics { BoxController::BoxController(Responder * parentResponder, Store * store) : ViewController(parentResponder), - m_view(BoxView(store)), + m_boxBannerView(BoxBannerView()), + m_view(BoxView(store, &m_boxBannerView)), m_store(store) { } @@ -26,7 +27,11 @@ bool BoxController::handleEvent(Ion::Events::Event event) { } if (event == Ion::Events::Left || event == Ion::Events::Right) { int nextSelectedQuantile = event == Ion::Events::Left ? m_view.selectedQuantile()-1 : m_view.selectedQuantile()+1; - return m_view.selectQuantile(nextSelectedQuantile); + if (m_view.selectQuantile(nextSelectedQuantile)) { + reloadBannerView(); + return true; + } + return false; } return false; } @@ -40,6 +45,7 @@ void BoxController::didBecomeFirstResponder() { } m_view.selectMainView(true); m_view.reload(); + reloadBannerView(); } bool BoxController::isEmpty() { @@ -60,4 +66,32 @@ Responder * BoxController::tabController() const { return (parentResponder()->parentResponder()->parentResponder()); } +void BoxController::reloadBannerView() { + const char * calculationName[5] = {"Minimum", "Premier quartile", "Mediane", "Troisieme quartile", "Maximum"}; + m_boxBannerView.setLegendAtIndex((char *)calculationName[m_view.selectedQuantile()], 0); + + char buffer[Constant::FloatBufferSizeInScientificMode]; + float calculation = 0.0f; + switch(m_view.selectedQuantile()) { + case 0: + calculation = m_store->minValue(); + break; + case 1: + calculation = m_store->firstQuartile(); + break; + case 2: + calculation = m_store->median(); + break; + case 3: + calculation = m_store->thirdQuartile(); + break; + case 4: + calculation = m_store->maxValue(); + break; + } + Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_boxBannerView.setLegendAtIndex(buffer, 1); + m_boxBannerView.layoutSubviews(); +} + } diff --git a/apps/statistics/box_controller.h b/apps/statistics/box_controller.h index 6139ede7a..a22b1204c 100644 --- a/apps/statistics/box_controller.h +++ b/apps/statistics/box_controller.h @@ -4,6 +4,7 @@ #include #include "store.h" #include "box_view.h" +#include "box_banner_view.h" namespace Statistics { @@ -20,6 +21,8 @@ public: Responder * defaultController() override; private: Responder * tabController() const; + void reloadBannerView(); + BoxBannerView m_boxBannerView; BoxView m_view; Store * m_store; uint32_t m_storeVersion; diff --git a/apps/statistics/box_view.cpp b/apps/statistics/box_view.cpp index 0b80a51bb..4f3d54d80 100644 --- a/apps/statistics/box_view.cpp +++ b/apps/statistics/box_view.cpp @@ -4,12 +4,11 @@ namespace Statistics { -BoxView::BoxView(Store * store) : - CurveViewWithBanner(&m_boxWindow, 0.0f, 0.2f, 0.4f, 0.2f), +BoxView::BoxView(Store * store, BannerView * bannerView) : + CurveViewWithBanner(&m_boxWindow, bannerView, 0.0f, 0.2f, 0.4f, 0.2f), m_store(store), m_boxWindow(BoxWindow(store)), - m_selectedQuantile(0), - m_bannerView(BoxBannerView(store, this)) + m_selectedQuantile(0) { } @@ -20,7 +19,6 @@ void BoxView::reloadSelection() { float selectedValueInPixels = floatToPixel(Axis::Horizontal, calculations[m_selectedQuantile]); KDRect dirtyZone(KDRect(selectedValueInPixels-1, pixelLowerBound, 2, pixelUpperBound - pixelLowerBound)); markRectAsDirty(dirtyZone); - m_bannerView.reload(); } int BoxView::selectedQuantile() { @@ -65,8 +63,4 @@ char * BoxView::label(Axis axis, int index) const { return (char *)m_labels[index]; } -BannerView * BoxView::bannerView() { - return &m_bannerView; -} - } diff --git a/apps/statistics/box_view.h b/apps/statistics/box_view.h index 1cffb57fd..348855ea7 100644 --- a/apps/statistics/box_view.h +++ b/apps/statistics/box_view.h @@ -3,7 +3,6 @@ #include #include "store.h" -#include "box_banner_view.h" #include "box_window.h" #include "../constant.h" #include "../curve_view_with_banner.h" @@ -12,20 +11,18 @@ namespace Statistics { class BoxView : public CurveViewWithBanner { public: - BoxView(Store * store); + BoxView(Store * store, BannerView * bannerView); void reloadSelection() override; int selectedQuantile(); bool selectQuantile(int selectedQuantile); void drawRect(KDContext * ctx, KDRect rect) const override; private: char * label(Axis axis, int index) const override; - BannerView * bannerView() override; Store * m_store; BoxWindow m_boxWindow; char m_labels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; // -1->Unselect 0->min 1->first quartile 2->median 3->third quartile 4->max int m_selectedQuantile; - BoxBannerView m_bannerView; }; } diff --git a/apps/statistics/histogram_banner_view.cpp b/apps/statistics/histogram_banner_view.cpp index a521f1d5d..787d782b2 100644 --- a/apps/statistics/histogram_banner_view.cpp +++ b/apps/statistics/histogram_banner_view.cpp @@ -5,65 +5,20 @@ namespace Statistics { -HistogramBannerView::HistogramBannerView(Store * store) : - m_intervalView(0.0f, 0.5f), - m_sizeView(0.0f, 0.5f), - m_frequencyView(1.0f, 0.5f), - m_store(store) +HistogramBannerView::HistogramBannerView() : + m_intervalView(0.5f, 0.5f), + m_sizeView(0.5f, 0.5f), + m_frequencyView(0.5f, 0.5f) { } -void HistogramBannerView::reload() { - markRectAsDirty(bounds()); - char buffer[k_maxNumberOfCharacters]; - const char * legend = "Interval ["; - int legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - float lowerBound = m_store->selectedBar() - m_store->barWidth()/2; - int lowerBoundNumberOfChar = Float(lowerBound).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - buffer[legendLength+lowerBoundNumberOfChar] = ';'; - float upperBound = m_store->selectedBar() + m_store->barWidth()/2; - int upperBoundNumberOfChar = Float(upperBound).convertFloatToText(buffer+legendLength+lowerBoundNumberOfChar+1, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+1] = '['; - buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+2] = 0; - m_intervalView.setText(buffer); - - legend = "Effectif: "; - legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - float size = m_store->heightForBarAtValue(m_store->selectedBar()); - Float(size).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_sizeView.setText(buffer); - - legend = "Frequence: "; - legendLength = strlen(legend); - strlcpy(buffer, legend, legendLength+1); - float frequency = size/m_store->sumOfColumn(1); - Float(frequency).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); - m_frequencyView.setText(buffer); -} - int HistogramBannerView::numberOfSubviews() const { return 3; } -View * HistogramBannerView::subviewAtIndex(int index) { - assert(index >= 0); - if (index == 0) { - return &m_intervalView; - } - if (index == 1) { - return &m_sizeView; - } - return &m_frequencyView; -} - -void HistogramBannerView::layoutSubviews() { - KDCoordinate height = bounds().height(); - KDCoordinate width = bounds().width(); - m_intervalView.setFrame(KDRect(0, 0, width, height/2)); - m_sizeView.setFrame(KDRect(0, height/2, width, height/2)); - m_frequencyView.setFrame(KDRect(0, height/2, width, height/2)); +TextView * HistogramBannerView::textViewAtIndex(int i) { + TextView * textViews[3] = {&m_intervalView, &m_sizeView, &m_frequencyView}; + return textViews[i]; } } diff --git a/apps/statistics/histogram_banner_view.h b/apps/statistics/histogram_banner_view.h index b1caa9097..5dc3306c4 100644 --- a/apps/statistics/histogram_banner_view.h +++ b/apps/statistics/histogram_banner_view.h @@ -2,24 +2,19 @@ #define STATISTICS_HISTOGRAM_BANNER_VIEW_H #include -#include "store.h" #include "../banner_view.h" namespace Statistics { class HistogramBannerView : public ::BannerView { public: - HistogramBannerView(Store * store); - void reload() override; + HistogramBannerView(); private: - constexpr static int k_maxNumberOfCharacters = 50; int numberOfSubviews() const override; - View * subviewAtIndex(int index) override; - void layoutSubviews() override; + TextView * textViewAtIndex(int i) override; BufferTextView m_intervalView; BufferTextView m_sizeView; BufferTextView m_frequencyView; - Store * m_store; }; } diff --git a/apps/statistics/histogram_controller.cpp b/apps/statistics/histogram_controller.cpp index 5d11c1a93..c95970a21 100644 --- a/apps/statistics/histogram_controller.cpp +++ b/apps/statistics/histogram_controller.cpp @@ -7,7 +7,8 @@ namespace Statistics { HistogramController::HistogramController(Responder * parentResponder, HeaderViewController * headerViewController, Store * store) : ViewController(parentResponder), HeaderViewDelegate(headerViewController), - m_view(HistogramView(store)), + m_bannerView(HistogramBannerView()), + m_view(HistogramView(store, &m_bannerView)), m_settingButton(Button(this, "Reglages de l'histogramme",Invocation([](void * context, void * sender) { HistogramController * histogramController = (HistogramController *) context; StackViewController * stack = ((StackViewController *)histogramController->stackController()); @@ -41,6 +42,7 @@ bool HistogramController::handleEvent(Ion::Events::Event event) { headerViewController()->setSelectedButton(-1); m_view.selectMainView(true); m_view.reloadSelection(); + reloadBannerView(); return true; } return false; @@ -63,6 +65,7 @@ bool HistogramController::handleEvent(Ion::Events::Event event) { } else { m_view.reloadSelection(); } + reloadBannerView(); return true; } return false; @@ -78,6 +81,7 @@ void HistogramController::didBecomeFirstResponder() { headerViewController()->setSelectedButton(-1); m_view.selectMainView(true); m_view.reload(); + reloadBannerView(); } int HistogramController::numberOfButtons() const { @@ -106,4 +110,34 @@ Responder * HistogramController::tabController() const { return (parentResponder()->parentResponder()->parentResponder()->parentResponder()); } +void HistogramController::reloadBannerView() { + char buffer[k_maxNumberOfCharacters+ Constant::FloatBufferSizeInScientificMode*2]; + const char * legend = "Interval ["; + int legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + float lowerBound = m_store->selectedBar() - m_store->barWidth()/2; + int lowerBoundNumberOfChar = Float(lowerBound).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + buffer[legendLength+lowerBoundNumberOfChar] = ';'; + float upperBound = m_store->selectedBar() + m_store->barWidth()/2; + int upperBoundNumberOfChar = Float(upperBound).convertFloatToText(buffer+legendLength+lowerBoundNumberOfChar+1, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+1] = '['; + buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+2] = 0; + m_bannerView.setLegendAtIndex(buffer, 0); + + legend = "Effectif: "; + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + float size = m_store->heightForBarAtValue(m_store->selectedBar()); + Float(size).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 1); + + legend = "Frequence: "; + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + float frequency = size/m_store->sumOfColumn(1); + Float(frequency).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_bannerView.setLegendAtIndex(buffer, 2); + m_bannerView.layoutSubviews(); +} + } diff --git a/apps/statistics/histogram_controller.h b/apps/statistics/histogram_controller.h index e90d76466..0ec5e1568 100644 --- a/apps/statistics/histogram_controller.h +++ b/apps/statistics/histogram_controller.h @@ -4,6 +4,7 @@ #include #include "store.h" #include "histogram_view.h" +#include "histogram_banner_view.h" #include "histogram_parameter_controller.h" #include "../curve_view.h" @@ -27,7 +28,10 @@ public: const char * emptyMessage() override; Responder * defaultController() override; private: + constexpr static int k_maxNumberOfCharacters = 12; Responder * tabController() const; + void reloadBannerView(); + HistogramBannerView m_bannerView; HistogramView m_view; Button m_settingButton; Store * m_store; diff --git a/apps/statistics/histogram_view.cpp b/apps/statistics/histogram_view.cpp index a58bfc2d3..8ee0e5807 100644 --- a/apps/statistics/histogram_view.cpp +++ b/apps/statistics/histogram_view.cpp @@ -4,10 +4,9 @@ namespace Statistics { -HistogramView::HistogramView(Store * store) : - CurveViewWithBanner(store, 0.2f, 0.1f, 0.4f, 0.1f), - m_store(store), - m_bannerView(HistogramBannerView(store)) +HistogramView::HistogramView(Store * store, BannerView * bannerView) : + CurveViewWithBanner(store, bannerView, 0.2f, 0.1f, 0.4f, 0.1f), + m_store(store) { } @@ -19,7 +18,6 @@ void HistogramView::reloadSelection() { KDRect dirtyZone(KDRect(pixelLowerBound, selectedValueInPixels, pixelUpperBound-pixelLowerBound, horizontalAxisInPixels - selectedValueInPixels)); markRectAsDirty(dirtyZone); - m_bannerView.reload(); } void HistogramView::drawRect(KDContext * ctx, KDRect rect) const { @@ -41,10 +39,6 @@ char * HistogramView::label(Axis axis, int index) const { return (char *)m_labels[index]; } -BannerView * HistogramView::bannerView() { - return &m_bannerView; -} - float HistogramView::evaluateModelWithParameter(Model * curve, float t) const { return (float)m_store->heightForBarAtValue(t)/m_store->sumOfColumn(1); } diff --git a/apps/statistics/histogram_view.h b/apps/statistics/histogram_view.h index 69c44051a..80f6e5b4b 100644 --- a/apps/statistics/histogram_view.h +++ b/apps/statistics/histogram_view.h @@ -3,7 +3,6 @@ #include #include "store.h" -#include "histogram_banner_view.h" #include "../constant.h" #include "../curve_view_with_banner.h" @@ -11,16 +10,14 @@ namespace Statistics { class HistogramView : public CurveViewWithBanner { public: - HistogramView(Store * store); + HistogramView(Store * store, BannerView * bannerView); void reloadSelection() override; void drawRect(KDContext * ctx, KDRect rect) const override; private: char * label(Axis axis, int index) const override; - BannerView * bannerView() override; float evaluateModelWithParameter(Model * curve, float t) const override; Store * m_store; char m_labels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; - HistogramBannerView m_bannerView; }; } diff --git a/escher/include/escher/buffer_text_view.h b/escher/include/escher/buffer_text_view.h index c7dae76b4..0c095c956 100644 --- a/escher/include/escher/buffer_text_view.h +++ b/escher/include/escher/buffer_text_view.h @@ -7,7 +7,7 @@ class BufferTextView : public TextView { public: BufferTextView(float horizontalAlignment = 0.5f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); - void setText(const char * text); + void setText(const char * text) override; const char * text() const override; private: static constexpr int k_maxNumberOfChar = 256; diff --git a/escher/include/escher/pointer_text_view.h b/escher/include/escher/pointer_text_view.h index 8b47e986d..d3675d201 100644 --- a/escher/include/escher/pointer_text_view.h +++ b/escher/include/escher/pointer_text_view.h @@ -7,7 +7,7 @@ class PointerTextView : public TextView { public: PointerTextView(const char * text = nullptr, float horizontalAlignment = 0.0f, float verticalAlignment = 0.0f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); - void setText(const char * text); + void setText(const char * text) override; protected: const char * text() const override; private: diff --git a/escher/include/escher/text_view.h b/escher/include/escher/text_view.h index f71f6fa78..9a5adca65 100644 --- a/escher/include/escher/text_view.h +++ b/escher/include/escher/text_view.h @@ -16,8 +16,9 @@ public: void setTextColor(KDColor textColor); void setAlignment(float horizontalAlignment, float verticalAlignment); KDSize minimalSizeForOptimalDisplay() override; -protected: virtual const char * text() const = 0; + virtual void setText(const char * text) = 0; +protected: #if ESCHER_VIEW_LOGGING const char * className() const override; #endif