diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index adb666104..776153935 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -146,6 +146,36 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { Ion::USB::clearEnumerationInterrupt(); } } else { + if (KDIonContext::sharedContext()->zoomEnabled) { + bool changedZoom = true; + + if (event == Ion::Events::ShiftOne) { + KDIonContext::sharedContext()->zoomPosition = 0; + } else if (event == Ion::Events::ShiftTwo) { + KDIonContext::sharedContext()->zoomPosition = 1; + } else if (event == Ion::Events::ShiftThree) { + KDIonContext::sharedContext()->zoomPosition = 2; + } else if (event == Ion::Events::ShiftFour) { + KDIonContext::sharedContext()->zoomPosition = 3; + } else if (event == Ion::Events::ShiftFive) { + KDIonContext::sharedContext()->zoomPosition = 4; + } else if (event == Ion::Events::ShiftSix) { + KDIonContext::sharedContext()->zoomPosition = 5; + } else if (event == Ion::Events::ShiftSeven) { + KDIonContext::sharedContext()->zoomPosition = 6; + } else if (event == Ion::Events::ShiftEight) { + KDIonContext::sharedContext()->zoomPosition = 7; + } else if (event == Ion::Events::ShiftNine) { + KDIonContext::sharedContext()->zoomPosition = 8; + } else { + changedZoom = false; + } + if (changedZoom) { + KDIonContext::sharedContext()->updatePostProcessingEffects(); + redrawWindow(true); + return true; + } + } didProcessEvent = Container::dispatchEvent(event); } @@ -312,8 +342,8 @@ OnBoarding::PopUpController * AppsContainer::promptController() { return &m_promptController; } -void AppsContainer::redrawWindow() { - m_window.redraw(); +void AppsContainer::redrawWindow(bool force) { + m_window.redraw(force); } void AppsContainer::examDeactivatingPopUpIsDismissed() { diff --git a/apps/apps_container.h b/apps/apps_container.h index bd0c8fb2c..87c0adea6 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -45,7 +45,7 @@ public: void shutdownDueToLowBattery(); void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); OnBoarding::PopUpController * promptController(); - void redrawWindow(); + void redrawWindow(bool force = false); // Exam pop-up controller delegate void examDeactivatingPopUpIsDismissed() override; // Ion::StorageDelegate diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index c59612d7a..42a657398 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -1,6 +1,7 @@ #include "controller.h" #include "app.h" #include "../apps_container.h" +#include "../global_preferences.h" extern "C" { #include } @@ -85,6 +86,13 @@ void Controller::didBecomeFirstResponder() { } void Controller::viewWillAppear() { + KDIonContext::sharedContext()->zoomInhibit = true; + KDIonContext::sharedContext()->updatePostProcessingEffects(); +} + +void Controller::viewDidDisappear() { + KDIonContext::sharedContext()->zoomInhibit = false; + KDIonContext::sharedContext()->updatePostProcessingEffects(); } View * Controller::view() { diff --git a/apps/home/controller.h b/apps/home/controller.h index 4c354bfb5..b30bf89d1 100644 --- a/apps/home/controller.h +++ b/apps/home/controller.h @@ -15,6 +15,7 @@ public: bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; void viewWillAppear() override; + void viewDidDisappear() override; virtual int numberOfRows() const override; virtual int numberOfColumns() const override; diff --git a/apps/settings/Makefile b/apps/settings/Makefile index d3d82d539..c60b78c21 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -6,6 +6,7 @@ app_settings_src = $(addprefix apps/settings/,\ main_controller.cpp \ settings_message_tree.cpp \ sub_menu/about_controller.cpp \ + sub_menu/accessibility_controller.cpp \ sub_menu/display_mode_controller.cpp \ sub_menu/exam_mode_controller.cpp \ sub_menu/generic_sub_controller.cpp \ diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 85cb99187..a88d9b97a 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -32,3 +32,10 @@ ColorBlue = "Blau " ColorGreen = "Grün " ColorYellow = "Gelb " Contributors = "Beiträger" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index b44ee12cf..96455df9e 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -32,3 +32,10 @@ ColorBlue = "Blue " ColorGreen = "Green " ColorYellow = "Yellow " Contributors = "Contributors" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index e85cfde3b..e67cf1834 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -32,3 +32,10 @@ ColorBlue = "Azul " ColorGreen = "Verde " ColorYellow = "Amarillo " Contributors = "Contribuyentes" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index f846c1a36..e513f86da 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -32,3 +32,10 @@ ColorBlue = "Bleu " ColorGreen = "Vert " ColorYellow = "Jaune " Contributors = "Contributeurs" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Inverser couleurs" +AccessibilityMagnify = "Loupe" +AccessibilityGamma = "Correction gamma" +AccessibilityGammaRed = "Gamma rouge" +AccessibilityGammaGreen = "Gamma vert" +AccessibilityGammaBlue = "Gamma bleu" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index c922c0559..a39c61a3c 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -32,3 +32,10 @@ ColorBlue = "Azul " ColorGreen = "Verde " ColorYellow = "Amarelo " Contributors = "Contribuidores" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index d05289721..22bd8ba47 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -15,6 +15,7 @@ MainController::MainController(Responder * parentResponder, InputEventHandlerDel m_preferencesController(this), m_displayModeController(this, inputEventHandlerDelegate), m_languageController(this, 13), + m_accessibilityController(this), m_examModeController(this), m_aboutController(this), m_contributorsController(this) @@ -76,6 +77,8 @@ bool MainController::handleEvent(Ion::Events::Event event) { } else if (rowIndex == 7 + hasPrompt()) { subController = &m_aboutController; } else if (rowIndex == 9 + hasPrompt()) { + subController = &m_accessibilityController; + } else if (rowIndex == 10 + hasPrompt()) { subController = &m_contributorsController; } else { subController = &m_preferencesController; diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index b26ff79c6..c5a75f9e9 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -4,6 +4,7 @@ #include #include "settings_message_tree.h" #include "sub_menu/about_controller.h" +#include "sub_menu/accessibility_controller.h" #include "sub_menu/display_mode_controller.h" #include "sub_menu/exam_mode_controller.h" #include "sub_menu/language_controller.h" @@ -40,6 +41,7 @@ private: PreferencesController m_preferencesController; DisplayModeController m_displayModeController; LanguageController m_languageController; + AccessibilityController m_accessibilityController; ExamModeController m_examModeController; AboutController m_aboutController; ContributorsController m_contributorsController; diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index 599d12576..62ef395fd 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -10,6 +10,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::BetaPopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 12); I18n::Message MainController::promptMessage() const { return I18n::Message::BetaPopUp; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index 8a59de5de..87ffd9eb6 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -11,6 +11,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 1), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 10); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); I18n::Message MainController::promptMessage() const { return I18n::Message::Default; diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index c9b41b540..d3c8fff49 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -10,6 +10,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::UpdatePopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 12); I18n::Message MainController::promptMessage() const { return I18n::Message::UpdatePopUp; diff --git a/apps/settings/sub_menu/accessibility_controller.cpp b/apps/settings/sub_menu/accessibility_controller.cpp new file mode 100644 index 000000000..1df981f37 --- /dev/null +++ b/apps/settings/sub_menu/accessibility_controller.cpp @@ -0,0 +1,141 @@ +#include "accessibility_controller.h" +#include "../../global_preferences.h" +#include "../../apps_container.h" +#include + +using namespace Shared; + +namespace Settings { + +AccessibilityController::AccessibilityController(Responder * parentResponder) : + GenericSubController(parentResponder) +{ + for (int i = 0; i < k_totalNumberOfSwitchCells; i++) { + m_switchCells[i].setMessageFont(KDFont::LargeFont); + } + for (int i = 0; i < k_totalNumberOfGaugeCells; i++) { + m_gaugeCells[i].setMessageFont(KDFont::LargeFont); + } +} + +bool AccessibilityController::handleEvent(Ion::Events::Event event) { + bool invertEnabled = KDIonContext::sharedContext()->invertEnabled; + bool zoomEnabled = KDIonContext::sharedContext()->zoomEnabled; + bool gammaEnabled = KDIonContext::sharedContext()->gammaEnabled; + int redGamma, greenGamma, blueGamma; + KDIonContext::sharedContext()->gamma.gamma(redGamma, greenGamma, blueGamma); + + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (selectedRow() == 0) { + invertEnabled = !invertEnabled; + } + else if (selectedRow() == 1) { + zoomEnabled = !zoomEnabled; + } + else if (selectedRow() == 2) { + gammaEnabled = !gammaEnabled; + } + else { + GenericSubController::handleEvent(event); + } + } + else if (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus) { + int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? 1 : -1; + if (selectedRow() == 3) { + redGamma += direction; + } + else if (selectedRow() == 4) { + greenGamma += direction; + } + else if (selectedRow() == 5) { + blueGamma += direction; + } + else { + return GenericSubController::handleEvent(event); + } + } + else { + return GenericSubController::handleEvent(event); + } + KDIonContext::sharedContext()->invertEnabled = invertEnabled; + KDIonContext::sharedContext()->zoomEnabled = zoomEnabled; + KDIonContext::sharedContext()->gammaEnabled = gammaEnabled; + KDIonContext::sharedContext()->gamma.setGamma(redGamma, greenGamma, blueGamma); + KDIonContext::sharedContext()->updatePostProcessingEffects(); + m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + AppsContainer::sharedAppsContainer()->redrawWindow(true); + return true; +} + +HighlightCell * AccessibilityController::reusableCell(int index, int type) { + assert(type == 1 || type == 2); + if (type == 2) { + assert(index >= 0 && index < k_totalNumberOfSwitchCells); + return &m_switchCells[index]; + } + else if (type == 1) { + assert(index >= 0 && index < k_totalNumberOfGaugeCells); + return &m_gaugeCells[index]; + } + return nullptr; +} + +int AccessibilityController::reusableCellCount(int type) { + assert(type == 1 || type == 2); + if (type == 2) { + return k_totalNumberOfSwitchCells; + } + else if (type == 1) { + return k_totalNumberOfGaugeCells; + } + return 0; +} + +void AccessibilityController::willDisplayCellForIndex(HighlightCell * cell, int index) { + GenericSubController::willDisplayCellForIndex(cell, index); + + MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; + + if (index == 0) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->invertEnabled); + } + else if (index == 1) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->zoomEnabled); + } + else if (index == 2) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->gammaEnabled); + } + else { + MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell; + GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView(); + + float redGamma, greenGamma, blueGamma, level; + KDIonContext::sharedContext()->gamma.gamma(redGamma, greenGamma, blueGamma); + if (index == 3) { + level = redGamma; + } + else if (index == 4) { + level = greenGamma; + } + else { + level = blueGamma; + } + myGauge->setLevel(level); + } +} + +int AccessibilityController::typeAtLocation(int i, int j) { + switch (j) { + case 0: + case 1: + case 2: + return 2; + default: + return 1; + } +} + +} diff --git a/apps/settings/sub_menu/accessibility_controller.h b/apps/settings/sub_menu/accessibility_controller.h new file mode 100644 index 000000000..1d42ff6c3 --- /dev/null +++ b/apps/settings/sub_menu/accessibility_controller.h @@ -0,0 +1,26 @@ +#ifndef SETTINGS_ACCESSIBILITY_CONTROLLER_H +#define SETTINGS_ACCESSIBILITY_CONTROLLER_H + +#include "generic_sub_controller.h" +#include "../../hardware_test/pop_up_controller.h" + +namespace Settings { + +class AccessibilityController : public GenericSubController { +public: + AccessibilityController(Responder * parentResponder); + bool handleEvent(Ion::Events::Event event) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + int typeAtLocation(int i, int j) override; +private: + constexpr static int k_totalNumberOfSwitchCells = 3; + constexpr static int k_totalNumberOfGaugeCells = 3; + MessageTableCellWithGauge m_gaugeCells[k_totalNumberOfGaugeCells]; + MessageTableCellWithSwitch m_switchCells[k_totalNumberOfSwitchCells]; +}; + +} + +#endif diff --git a/apps/settings/sub_menu/generic_sub_controller.h b/apps/settings/sub_menu/generic_sub_controller.h index 132cc1773..039d25ede 100644 --- a/apps/settings/sub_menu/generic_sub_controller.h +++ b/apps/settings/sub_menu/generic_sub_controller.h @@ -17,7 +17,7 @@ public: KDCoordinate rowHeight(int j) override; KDCoordinate cumulatedHeightFromIndex(int j) override; int indexFromCumulatedHeight(KDCoordinate offsetY) override; - int typeAtLocation(int i, int j) override; + virtual int typeAtLocation(int i, int j) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; void setMessageTreeModel(const MessageTree * messageTreeModel); void viewWillAppear() override;