Creating multiple classes inside another by variable AND Passing 2D array

My first post :grin:

I am attempting to create a main class that holds info on menu navigation. Inside that class are multiple sub-classes that have different array lengths depending values sent to them at compile time. It should also be able to send a pointer from a 2D array to the subclasses so that I can work with reading that 2D array inside the main class.

It works like this: in main I create a const char* array that has multiple strings which I believe is a pointer to program flash memory. I also create an instance of ‘DisplayControl’ and send it 5 and the array [2,5,3,5,1] which tells it to create 5 submenu classes, ‘DisplayMenu’, and initiate them with internal menu lengths of the array. Then I would call a link function which transfers the address of the 2D array in main to a pointer inside the submenu classes.

This link Class inside a class shows how to create a class inside a class but only if you know how many classes are being created (not by variable).

I have tried many different things to pass the reference inside just a single class but to no avail. Here is some code that I have come up with just to get the idea across but it is full of errors.

Main:

#include "DisplayControl.h"

DisplayControl MyDisplay(5, [2,5,3,5,1]);  //create a DisplayControl with 5 menus, each being 2,5,3,5, and 1 long

//Menu description to draw for menu 1
const char* LED_DescMatrix[] = {
                                "GoSteps:",  //menu item 1
                                "MS     :",  //menu item 2
                                "Stp/Deg:",  //menu item 3
                                "CurrPos:",  //menu item 4
                                "Degrees:"   //menu item 5
                                };

void setup()
{
  //supposed to push LED_DescMatrix to the pointer in MyMenu[1] so that I can work with it in the class
  MyDisplay.PushDescToMenu(1, LED_DescMatrix);
}

void loop()
{
  
}

The main class:

#ifndef DISPLAYCONTROL_H
#define DISPLAYCONTROL_H

#include "DisplayMenu.h"

class DisplayControl
{
  public:
    DisplayControl(byte NumberOfMenus, byte *MenuSizes[]);     //constructor
    
    void PushDescToMenu(byte WhichMenu, const char *DescPointer1);  //pushes pointer of desc to each MyMenu pointer
    
  private:  
    byte MenuHeight;                        //Limited display height of the screen
    byte ActiveMenu;                        //which menu is active -> in MyMenus[x]
    byte DescriptionLength;                 //how much of the description to show
    
    DisplayMenu MyMenus[];     //creating class within a class with size of variable input
};

#endif

cpp file
#include "DisplayControl.h"

DisplayControl::DisplayControl(byte NumberOfMenus, byte *MenuSizes[]) : //how to initialize variable 'MyMenu's here and pass 'MenuSizes[]' to each one?
{
  //DisplayMenu MyMenu[NumberOfMenus]
  
  //not going to work =(
  for (i=0; i<NumberOfMenus; i++)
  {
    DisplayMenu MyMenu(MenuSizes[i]); 
  }
}

void DisplayControl::PushDescToMenu(byte WhichMenu, const char *DescPointer1)
{
  MyMenu[WhichMenu].LinkDesc(DescPointer1);
}

The subclass:

#ifndef DISPLAYMENU_H
#define DISPLAYMENU_H

class DisplayMenu
{
    public:
      DisplayMenu(int MenuSize);    //constructor
            
      int CurrentIndex_X;           //menu x position
      int CurrentIndex_Y;           //menu y position
      int MenuStart;                //which global y position to start displaying menu
      
      //This should have an array size of 'MenuSize' from above... not working yet
      const char *MenuDescription[5];   //pointer to 2 dim array of menu description
  
      void LinkDesc(const char* DescPointer2);  //FUNC. takes pointer from main and stores it in Description

  private:  
    
};

#endif

cpp file
#include "DisplayMenu.h"

DisplayMenu::DisplayMenu(int MenuSize)
{
  CurrentIndex_X=0;
  CurrentIndex_Y=0;
  MenuStart=0;
}

void DisplayMenu::LinkDesc(const char* DescPointer2)
{
  MenuDescription = DescPointer2;
}

Any help would be appreciated. I have another way to do what I want but it requires a crap ton of index keeping and one big array.

Cheers!

Ok, I found out how to pass a constant 2D array to a pointer in a class. Here it is with new class files h and cpp that only passes a 2D array to the class pointer.

main:

#include "MenuControl.h"

const char* LED_DescMatrix[][8] = {
                          "GoSteps:",  //menu item 1
                          "MS     :",  //menu item 2
                          "Stp/Deg:",  //menu item 3
                          "CurrPos:",  //menu item 4
                          "Degrees:"   //menu item 5
                          };

                   

MenuControl MyMenu(2,10);

void setup()
{
  MyMenu.AssignMenuPointer((char**)LED_DescMatrix);
  
  Serial.begin(19200);

  Serial.println(MyMenu.MenuDesc[1]);  //spits out "MS     :"
}

void loop()
{
  
}

MenuControl.h

#ifndef MENUCONTROL_H
#define MENUCONTROL_H

class MenuControl
{
  public:
    MenuControl(int NumMenus, int TotalSize);
    
    void AssignMenuPointer(char** Pointer);
    char** MenuDesc;
  private:
    int NumberOfMenus;
    int MenuTotalSize;
    
 
};


#endif

MenuControl.cpp

#include "MenuControl.h"

MenuControl::MenuControl(int NumMenus, int TotalSize)
{
  
  
}

void MenuControl::AssignMenuPointer(char** Pointer)
{
  MenuDesc=Pointer;
}

Now I need to solve the multiple subclass problem…

This kind of approach is inclined to gobble up your available memory very quickly. In other environments your methods would be ideal, but on a micocontroller, you should strive to keep as much stuff OUT of memory as possible. Loading the bare essentials to get the job done. Having a whole menu structure sitting in ram is not a good idea.

You are absolutely right! Fixed it… now using

in main

const char Menu1_Item1[] PROGMEM = "GoSteps:";
const char Menu1_Item2[] PROGMEM = "MS     :";
const char Menu1_Item3[] PROGMEM = "Stp/Deg:";
const char Menu1_Item4[] PROGMEM = "CurrPos:";
const char Menu1_Item5[] PROGMEM = "Degrees:";

const char* LED_DescMatrix[] = {
                          Menu1_Item1,  //menu item 1
                          Menu1_Item2,  //menu item 2
                          Menu1_Item3,  //menu item 3
                          Menu1_Item4,  //menu item 4
                          Menu1_Item5   //menu item 5
                          };

before I print out

char chbuffer[8];
memcpy_P(chbuffer,LED_DescMatrix[0],8);  //copy from memory using a pointer, grab 8 spaces
Serial.println(chbuffer);

also used the freeMemory library and checked… it freed up 42 bytes :grin:

I’ll clean up the code and post it later for others.

The very first application I built using an arduino ran out of memory before I got around to writing the code to actually do something. All I had was a menu system along the lines you were going through here. :slight_smile: