Hello, I'm working on a simple (kinda simple, at least) class(es) that I can use to easily manage text on a TFT display. There will be a class that's initially initiated that you can pass the Adafruit_SSD1351 object to, as well as the default/initial settings (text color, bg color, size, etc etc), then after that you can create new TextBoxes and specify where to put them, and those settings will get saved to that specific text box. This will let me place textareas anywhere and update them without having to set the colors/sizes/fonts/locations, etc.
But it will be using two separate classes. One for the initial object that's given the GFX object and default settings, then it basically acts as a factory to the other class, where creating a new text area will create a new object from the "TextArea" class. (hopefully that was a summary enough).
Here's how I have it laid out currently (or at least the relevant parts), though there's something wrong with the factory bit.
Initial Class (ill call Factory):
Factory.hpp:
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include "TextArea.hpp"
class Factory {
public:
Factory(Adafruit_SSD1351 &GFXHandler);
void begin();
void begin( uint16_t fgColor );
void begin( uint16_t fgColor, uint16_t bgColor );
void setColor( uint16_t fgColor );
void setColor( uint16_t fgColor, uint16_t bgColor );
TextArea newTextArea( int x, int y );
// void print( char val );
private:
Adafruit_SSD1351 * GFXHandler;
void _begin();
//int _x, _y;
// DEFAULT fg/bg colors (can be changed on a TextArea basis);
uint16_t _defFgColor = 0x95e7;
uint16_t _defBgColor = 0x0000;
};
Factory.cpp:
#include "Factory.hpp"
Factory::Factory(Adafruit_SSD1351 &GFXHandler) : GFXHandler (&GFXHandler) {}
TextArea Factory::newTextArea( int x, int y ){
TextArea _txtArea( *GFXHandler );
// Do default stuff to this oled, using the settings
// provided when creating the Factory object..
return _txtArea;
}
void Factory::begin(){
_begin();
}
void Factory::begin( uint16_t fgColor , uint16_t bgColor ){
_defFgColor = fgColor;
_defBgColor = bgColor;
_begin();
}
void Factory::begin( uint16_t fgColor ){
_defFgColor = fgColor;
_begin();
}
void Factory::_begin(){
GFXHandler->begin();
GFXHandler->setFont();
GFXHandler->fillScreen(_defBgColor);
GFXHandler->setTextColor(_defFgColor);
GFXHandler->setTextSize(1);
}
void Factory::setColor( uint16_t fgColor ){
_defFgColor = fgColor;
}
void Factory::setColor( uint16_t fgColor, uint16_t bgColor ){
_defFgColor = fgColor;
_defBgColor = bgColor;
}
Now for the class that the Factory class will be interfacing with, lets call it TextArea.
TextArea.hpp:
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
class TextArea {
public:
TextArea(Adafruit_SSD1351 &GFXHandler);
// Set/update the print containers display value to a string, then display it
void print(char *charValue);
void setCursor( int x, int y );
void setColor( uint16_t fgColor );
void setColor( uint16_t fgColor, uint16_t bgColor );
// Function to re-print whatever value/type is saved (will be useful if the
// printed text needs to be "reloaded" for various reasons)
void print();
private:
Adafruit_SSD1351 * GFXHandler;
int _x = NULL, _y = NULL;
uint16_t _fgColor = NULL, _bgColor = NULL;
char _printerValPrev[MAX_CHAR_LENGTH];
char _printerVal[MAX_CHAR_LENGTH];
};
TextArea.cpp:
#include "TextArea.hpp"
TextArea::TextArea(Adafruit_SSD1351 &GFXHandler) : GFXHandler (&GFXHandler) {}
// If user were to set/change the printer to a CHAR...
void TextArea::print( char *charValue )
{
strcpy(_printerVal, charValue);
print();
}
void TextArea::setCursor( int x, int y ) {
_x = x;
_y = y;
}
void TextArea::setColor( uint16_t fgColor ){
_fgColor = fgColor;
print();
}
void TextArea::setColor( uint16_t fgColor, uint16_t bgColor ){
_fgColor = fgColor;
_bgColor = bgColor;
print();
}
// This would print the stored value in the specified area, but for this forum
// post, I'm just outputting the value to serial
void TextArea::print()
{
GFXHandler->setTextSize(1);
GFXHandler->setCursor( _x, _y );
GFXHandler->setTextColor( _fgColor, _bgColor );
GFXHandler->print( _printerVal );
}
And this is how I would prefer to be able to use it (or something like this)
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include "Factory.hpp"
Adafruit_SSD1351 oled(128, 128, &SPI, 10, 9, -1 );
// Create main object the simple factory
Factory UUI(oled);
// Then define two variables that can be used globally
TextArea timeDisplay;
TextArea milliseconds;
void setup() {
// Execute the "begin" function, providing default values..
UUI.begin(0x95e7, 0x0000);
// Create the timeDisplay textarea, and set the x/y location
TextArea timeDisplay = UUI.newTextArea(15, 10);
// Give it its own color
timeDisplay.setColor(0xc7a9);
// Create the milliseconds textarea, and set the x/y location
TextArea milliseconds = UUI.newTextArea(25, 30);
milliseconds.setColor(0xF800);
timeDisplay.print("<Time here>");
milliseconds.print("<Uptime here>");
}
void loop(){
// Update the milliseconds TextArea with the new time
milliseconds.print(millis());
timeDisplay.print(someFunctionThatMakesAFullTimeString());
}
You'll see all of the logic for setting the values/data for the textareas goes in the setup(), but since I want them to be global, I have to define the variables at the root. But evidently the TextArea timeDisplay; at the root isn't simply setting a variable that can be populated later and accessed globally, it's actually trying to initiate the object:
Compilation error: no matching function for call to 'TextArea::TextArea()'
So I guess my question is - What's the best way to handle this?
I was thinking the Factory object would literally just be there to hand off some default settings to the TextArea objects, but not have to store the object locally, but if I want to be able to create new TextArea objects (especially without having to define them in the root), i'll have to create an array in the Factory class itself to store the created TextArea objects in, and then access the TextArea via the Factory object for every call (instead of directly once it's been handed off from the Factory). Is that right? Or is there a way to make it work like I was planning to above?
Thanks in advance,
-J