ESP8266_swiss_army_board/src/app/ScreenManager.cpp
2019-04-09 08:00:45 +02:00

358 lines
9.4 KiB
C++

#include "ScreenManager.h"
ScreenManager::ScreenManager(Adafruit_SSD1306 &display) : _displayRef(display), _displayColorInverted(false), _displayDimmed(false), _currentView(NO_CURRENT_VIEW), _error(OK)
, _viewNotFound{&(displayError), (ErrorInfo *)malloc(sizeof(ErrorInfo)), RESERVED_VIEW_UID, NULL}
, _viewFuncUndefined{&(displayError), (ErrorInfo *)malloc(sizeof(ErrorInfo)), RESERVED_VIEW_UID, NULL}
, _currentViewUndefined{&(displayError), (ErrorInfo *)malloc(sizeof(ErrorInfo)), RESERVED_VIEW_UID, NULL}
, _viewFunctionFailedToExecute{&(displayError), (ErrorInfo *)malloc(sizeof(ErrorInfo)), RESERVED_VIEW_UID, NULL}
{
_viewLinkedList = (ViewLinkedList) createEmptyList();
_displayRef.setRotation(OR_0);
_displayRef.setTextColor(WHITE);
}
boolean ScreenManager::addView(boolean (*viewLogicFunction)(Adafruit_SSD1306&, void*), void *pData, const unsigned char UID)
{
ViewLink viewLink ={viewLogicFunction, pData, UID, NULL};
addNewLinkAtTheEnd(&_viewLinkedList, viewLink);
}
void *ScreenManager::createEmptyList()
{
return NULL;
}
boolean ScreenManager::addNewLinkAtTheEnd(ViewLinkedList *viewLinkedList, ViewLink viewLink)
{
ViewLink *newViewLink = (ViewLink*) malloc(sizeof(ViewLink));
if(newViewLink == NULL)
{
_error = MALLOC_FAILED;
return false;
}
//Because of the const member
memcpy(newViewLink, &viewLink, sizeof(*newViewLink));
if(isListEmpty(*viewLinkedList))*viewLinkedList = newViewLink;
else
{
if((*viewLinkedList)->UID == newViewLink->UID)
{
ViewLink *link = *viewLinkedList;
*viewLinkedList = newViewLink;
newViewLink->next = link->next;
free(link);
return true;
}
ViewLinkedList cursor = *viewLinkedList;
while(cursor->next != NULL)
{
if(cursor->next->UID == newViewLink->UID)
{
ViewLink *link = cursor->next;
cursor->next = newViewLink;
newViewLink->next = link->next;
free(link);
return true;
}
cursor = cursor->next;
}
cursor->next = newViewLink;
}
return true;
}
boolean ScreenManager::removeView(const unsigned char UID)
{
return removeLinkByUID(&_viewLinkedList ,UID);
}
boolean ScreenManager::removeLinkByUID(ViewLinkedList *viewLinkedList, const unsigned char UID)
{
if(isListEmpty(*viewLinkedList))return false;
if((*viewLinkedList)->UID == UID)
{
ViewLink *tmp = *viewLinkedList;
*viewLinkedList = (*viewLinkedList)->next;
free(tmp);
return true;
}
ViewLinkedList cursor = *viewLinkedList;
while(!isListEmpty(cursor->next))
{
if(cursor->next->UID == UID)
{
ViewLink *tmp = cursor->next;
cursor->next = cursor->next->next;
free(tmp);
return true;
}
cursor = cursor->next;
}
return false;
}
boolean ScreenManager::isListEmpty(ViewLinkedList viewLinkedList)
{
return viewLinkedList == NULL;
}
ScreenManager::Error ScreenManager::getError() const
{
return _error;
}
void ScreenManager::iterateThroughList()
{
Serial.println("Lets go through");
ViewLinkedList temp = _viewLinkedList;
while(!isListEmpty(temp))
{
Serial.print("UID : ");Serial.println(temp->UID);
temp = temp->next;
}
}
ViewLink* ScreenManager::getLinkByUID(ViewLinkedList viewLinkedList, const unsigned char UID)
{
if(isListEmpty(viewLinkedList))
return NULL;
while(!isListEmpty(viewLinkedList))
{
if(viewLinkedList->UID == UID)return viewLinkedList;
viewLinkedList = viewLinkedList->next;
}
return NULL;
}
boolean ScreenManager::displayView(const int UID)
{
//Reset draw settings:
_displayRef.clearDisplay();
_displayRef.setCursor(0,0);
_displayRef.setTextSize(1);
if(UID == -1 && _currentView == NO_CURRENT_VIEW)
{
//We display an error message on the screen
((ErrorInfo *)_currentViewUndefined.pData)->errorMessage = F("Could not display current view");
((ErrorInfo *)_currentViewUndefined.pData)->viewUID = UID;
(*_currentViewUndefined.viewLogicFunction)(_displayRef, _currentViewUndefined.pData);
_displayRef.display();
_error = CURRENT_VIEW_UNDEFINED;
return false;
}
else if(UID == -1)
{
if(_currentView->viewLogicFunction == NULL)
{
//We display an error message on the screen
((ErrorInfo *)_viewFuncUndefined.pData)->errorMessage = F("View function is NULL");
((ErrorInfo *)_viewFuncUndefined.pData)->viewUID = _currentView->UID;
(*_viewFuncUndefined.viewLogicFunction)(_displayRef, _viewFuncUndefined.pData);
_displayRef.display();
_error = VIEW_FUNC_UNDEFINED;
return false;
}
else if(!(*_currentView->viewLogicFunction)(_displayRef, _currentView->pData))
{
//We display an error message on the screen
_displayRef.clearDisplay();
((ErrorInfo *)_viewFunctionFailedToExecute.pData)->errorMessage = F("View function failed\nto execute");
((ErrorInfo *)_viewFunctionFailedToExecute.pData)->viewUID = _currentView->UID;
(*_viewFunctionFailedToExecute.viewLogicFunction)(_displayRef, _viewFunctionFailedToExecute.pData);
_displayRef.display();
_error = VIEW_FAILED_TO_EXECUTE;
return false;
}
_error = OK;
_displayRef.display();
return true;
}
ViewLink *viewLink = getLinkByUID(_viewLinkedList, UID);
if(viewLink == NULL)
{
//We display an error message on the screen
((ErrorInfo *)_viewNotFound.pData)->errorMessage = F("View does not exist");
((ErrorInfo *)_viewNotFound.pData)->viewUID = UID;
(*_viewNotFound.viewLogicFunction)(_displayRef, _viewNotFound.pData);
_displayRef.display();
_error = VIEW_NOT_FOUND;
_currentView = &_viewNotFound;
return false;
}else if(viewLink->viewLogicFunction == NULL)
{
//We display an error message on the screen
((ErrorInfo *)_viewFuncUndefined.pData)->errorMessage = F("View function is NULL");
((ErrorInfo *)_viewFuncUndefined.pData)->viewUID = UID;
(*_viewFuncUndefined.viewLogicFunction)(_displayRef, _viewFuncUndefined.pData);
_displayRef.display();
_error = VIEW_FUNC_UNDEFINED;
_currentView = viewLink;
return false;
}
if(!(*viewLink->viewLogicFunction)(_displayRef, viewLink->pData))
{
//We display an error message on the screen
_displayRef.clearDisplay();
((ErrorInfo *)_viewFunctionFailedToExecute.pData)->errorMessage = F("View function failed\nto execute");
((ErrorInfo *)_viewFunctionFailedToExecute.pData)->viewUID = UID;
(*_viewFunctionFailedToExecute.viewLogicFunction)(_displayRef, _viewFunctionFailedToExecute.pData);
_displayRef.display();
_error = VIEW_FAILED_TO_EXECUTE;
_currentView = viewLink;
return false;
}
_displayRef.display();
_currentView = viewLink;
_error = OK;
return true;
}
boolean ScreenManager::displayNextView()
{
if(_currentView == NO_CURRENT_VIEW && !isListEmpty(_viewLinkedList))
{
_currentView = _viewLinkedList;
return displayView();
}
if(!isListEmpty(_currentView->next))
{
_currentView = _currentView->next;
return displayView();
}
_currentView = _viewLinkedList;
return displayView();
}
void ScreenManager::invertDisplayColor(const boolean inverted)
{
_displayRef.invertDisplay(inverted);
_displayColorInverted = inverted;
}
void ScreenManager::dimDisplay(const boolean dimmed)
{
_displayRef.dim(dimmed);
_displayDimmed = dimmed;
}
void ScreenManager::orientDisplay(const Orientation orientation)
{
_displayRef.setRotation(orientation);
}
boolean ScreenManager::isDisplayColorInverted() const
{
return _displayColorInverted;
}
Orientation ScreenManager::getDisplayOrientation() const
{
return (Orientation) _displayRef.getRotation();
}
boolean ScreenManager::isDisplayDimmed() const
{
return _displayDimmed;
}
void ScreenManager::clearDisplay(const boolean bufferOnly)
{
if(bufferOnly)
_displayRef.clearDisplay();
else
{
_displayRef.clearDisplay();
_displayRef.display();
}
}
unsigned char ScreenManager::getViewCount()
{
unsigned char counter = 0;
ViewLinkedList temp = _viewLinkedList;
while(!isListEmpty(temp))
{
counter++;
temp = temp->next;
}
return counter;
}
int ScreenManager::getCurrentViewUID() const
{
if(_currentView == NO_CURRENT_VIEW)
return -1;
return _currentView->UID < 0 ? -1 : _currentView->UID;
}
boolean ScreenManager::displayError(Adafruit_SSD1306 &display, void *pData)
{
const ErrorInfo *errorInfo = (ErrorInfo *) pData;
display.setTextSize(3);
display.setCursor(19,3);
display.drawRect(0,0,display.width(), 27, WHITE);
display.print(F("ERROR"));
display.setTextSize(1);
display.setCursor(0,29);
display.print(errorInfo->errorMessage);
//We then display the view UID that caused the probleme
if(errorInfo->viewUID >= 0)
{
display.setCursor(0,56);
char buff[30] = "";
sprintf(buff,"VIEW UID : %d" ,errorInfo->viewUID);
display.println(buff);
}
return true;
}
const char* ScreenManager::getErrorMessage()const
{
//NO_VIEW_ERROR, MALLOC_FAILED, VIEW_NOT_FOUND, VIEW_FUNC_UNDEFINED, VIEW_FAILED_TO_EXECUTE, CURRENT_VIEW_UNDEFINED
switch(_error)
{
case OK:
return "NO ERROR";
case MALLOC_FAILED:
return "MALLOC FAILED";
case VIEW_NOT_FOUND:
return "VIEW NOT FOUND";
case VIEW_FUNC_UNDEFINED:
return "VIEW FUNCTION UNDEFINED (NULL)";
case VIEW_FAILED_TO_EXECUTE:
return "VIEW FAILED TO EXECUTE (RETURNED FALSE)";
case CURRENT_VIEW_UNDEFINED:
return "CURRENT VIEW UNDEFINED";
default :
return "UNKNOWN ERROR";
}
}