Global variables in a GUI? - c++

I am designing an immediate gui using C++ and SDL2. As I was starting to design my framework, I noticed that basically everything needs a renderer or some sort of event or other relevant information (Fonts, Themes, etc.). Does it make sense to put these is global static object that only the gui functions have access to, or just keep passing everything in.
Would this be ok?
This could be the header:
struct GuiForm {
GuiId active_id;
GuiId hot_id;
std::vector<Window> windows;
Renderer* renderer;
};
Then this could be the .cpp file:
static GuiForm* gui_form;
void SomeGuiWidget() {
GuiId current_hot_id = gui_form.hot_id;
/* Whatever the widget is going to do */
}

Related

How to structure this without introducing circular includes?

I am trying to figure out how to structure my game. I want to pass my "managers" down the hiearchy instead of making them global. But I ran into a problem. One of my managers updates scenes. It needs to pass Application reference to scenes, as application contains quit method. But my Application holds and updates this SceneManager. So my Application now includes SceneManager as it needs to update it, and my SceneManager includes Application as it needs to pass Application reference to scenes.
Basically Application holds all managers, SceneManager passes Application reference to Scenes, Scenes use managers obtained from Application reference.
// In application
sceneManager.updateScenes(*this);
// In SceneManager
currentScene.update(application)
// In scene
application.getSceneManager().doSomething()
Could anyone suggest me how to elegantly structure this part of my game? I know about forward declarations, but I would like to know if there is a solution without the need to make forward declarations.
I could use globals, but I would rather not.
One common (but not the only) solution to this problem is to have Scene communicate with Application through an interface which Application implements, rather than by direct reference.
This has the additional benefit of more clearly expressing what exactly Scene (and other dependencies) need to call out to.
For example:
interface ISceneHandler {
void Quit(); // Request that we quit the game.
}
class Application : ISceneHandler {
private SceneManager sceneManager;
public Application() {
// Pass ourself as the handler.
sceneManager = new SceneManager(this);
}
public void Quit() { ... }
}
class SceneManager {
private ISceneHandler handler;
public SceneManager(ISceneHandler handler) {
this.handler = handler;
}
public void SomeEvent() {
this.handler.Quit();
}
}

How to remove this circular dependency? [duplicate]

This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 3 years ago.
What am I trying to do?
I am trying to make game. Instead of having global "managers"
, I decided that I could pass all managers down the hiearchy. My plan was to make "Application" class, that would hold all "manager" objects, like Window, Asset Manager, etc... Application would then pass it's reference to SceneManager, SceneManager would pass Application reference to Scene and Scene whould then pass it to GameObjects, so it would be possible to call any manager from any level of hiearchy.
The problem is, my Application holds SceneManager. And SceneManager needs to pass Application reference to Scene.
Diagram:
Code: (Simplified)
Application:
Application relies on SceneManager, because it needs to hold it and update it.
#include "SceneManager"
class Application {
public:
SceneManager& getSceneManager();
void update();
void quit();
enter code here
private:
SceneManager sceneManager;
// Input, Window, Asset loaders etc
};
SceneManager:
SceneManager relies on Application, because it needs to pass Application reference to the current Scene.
#include "Application"
class SceneManager {
public:
void updateCurrentScene(Application& application);
// Handling scene switching etc.
enter code here
private:
Scene currentScene;
};
In scene it would be then possible to:
void onUpdate(Application& application) {
application.getSceneManager().doSomething();
}
Is it possible to remove circular reference and still have this "passing the managers down"?
How would you do it?
You can “forward declare” the classes in the header files.
class Application;
Instead of the full #include.
You will need the #include in the cpp file (or really before you do anything with the forward declared class).

C++ GTKMM gui circular dependencies

I have been attempting to write a GTKMM gui application in C++. In my earlier projects in Java I started by making so-called 'Screen' objects which would each contain the layout of, and objects in, different screens. So I tried that in C++ as well, I derived these different Screen objects from the Gtk::Box so that I could easily append them to a Gtk::Notebook.
However I found out that this approach results in circular dependencies, and after a lot of browsing I couldn't find people with other approaches. I currently have a screen to display data retrieved from a database, and wanted to add filters to that.
I managed to allow the swapping of screens by giving each screen a pointer to the Gtk::Notebook they are in, but I hit a roadblock when I couldn't figure out how to make two screens interact with each other (eg. filter the data in another screen).
The general problem appears like this:
Gui.h:
class Gui {
protected:
// Child object pointers.
Gtk::Notebook *m_screens;
DbConnector *m_db;
// Screen object pointers.
MainScreen *m_mainScreen;
FilterScreen *m_filterScreen;
public:
// Constructors & destructor.
Gui();
virtual ~Gui();
};
Gui.cpp:
Gui::Gui() {
// Create application.
auto app = Gtk::Application::create();
// Db connector
m_db = new DbConnector();
// Create & configure window.
Gtk::Window m_window;
// Window configs.....
// Create notebook & screen objects.
m_screens = new Gtk::Notebook();
m_screens->set_show_tabs(false);
m_mainScreen = new MainScreen(*m_screens);
m_filterScreen = new FilterScreen(*m_screens);
// Add notebook to window.
m_window.add(*m_screens);
//Insert pages.
m_screens->append_page(*m_mainScreen);
m_screens->append_page(*m_filterScreen);
// Show all children & run app.
m_window.show_all_children();
app->run(m_window);
}
MainScreen.h:
class MainScreen : public Gtk::Box {
protected:
// Parent notebook pointer.
Gtk::Notebook* parent;
// Child widgets.
Gtk::Button m_toFilterScreenButton = Gtk::Button("To Filter Screen");
// Constructors & desctructor.
MainScreen(Gtk::Notebook& par);
virtual ~MainScreen();
// Methods.
void addFilter(std::string filterText);
void toFilterScreen();
};
MainScreen.cpp:
MainScreen::MainScreen(Gtk::Notebook& par) : parent(&par) {
// Build screen.
// Packing contents.....
// Configure widgets.
// Things like widget border width.....
// Signal handlers.
m_toFilterScreenButton.signal_clicked().connect(sigc::mem_fun(*this, &MainScreen::toFilterScreen));
}
void MainScreen::addFilter(std::string filterText) {
// Add filter
}
void MainScreen::toFilterScreen() {
notebook->set_current_screen(pagenum_of_filterscreen);
}
The problem I ran into now is when the FilterScreen is up, a filter is selected, and that filter should be applied to the MainScreen. The FilterScreen can't reach the MainScreen via the Gui object because that would require the screens to include Gui.h, which would result in a circular dependency. Trying to retrieve the MainScreen from the Gtk::Notebook returns a Widget&, which will tell you a Gtk::Widget has no function called addFilter(std::string filterText);.
Is anybody aware of a pattern I could use that would allow this type of behavior? So far the only option I can think of is one giant class that sets the screens using functions instead of premade objects, which would be far from optimal...
With the advice given by Sam Varshavchik in the comments I made a tiny example app that can handle multiple screens and switch easily. For those interested: source can be found here: ExampleApp

Scoping Issues With GLFW

I'm writing a library that wraps around GLFW, among a few other libraries. I have a class that needs to be aware of user interface events, but GLFW uses a callback system where I have to specify a function that GLFW will automatically call when an event happens. This causes issues, because those functions that I have to supply GLFW have no way of being associated with an object of my class, so far as I can tell. For instance:
class MyClass {
MyClass() {
// Initialize GLFW
glfwSetKeyCallback(window, keyboardEventFunction);
}
// other content
}
void keyboardEventFunction(GLFWwindow *window, int b, int a, int m) {
// I want to notify the MyClass object, but it's out of scope
}
I am aware that GLFW has some non-callback functions to retrieve input data, but if I use those, there's no guarantee that I won't miss something simply because my program didn't happen to check at the exact moment a user provides input. I also lose the ability to check window focus and cursor enter-exit events. How can I get around this issue?

Passing application objects into lower level classes

I wasn't really sure how to search for this question.
I'm doing an embedded system design with the following scenario.
I have a main application class that needs to create a bunch of hardware interfaces such as a keypad, display, communication ports, etc... a whole slew of stuff
Now I have all these objets in the main application that I can use which is great
The application class contains a few sub classes that it can go into and stay for a while. One example is a menu class that it enters and runs inside that class until the menu is closed
I need the menu class to also interact with a lot of a hardware objects that were created at the application level
What is the best way to go about this without using global variables? Is there a good solution to this problem?
I could pass each object into the menu class, but I don't want to create a constructor with 20 arguments. My current solution is to put all the objects into a structure and pass that structure into the sub-class constructor. That way they also have access.
The part that bugs me about this approach is that I have to define the structure outside of the application which I don't really like. Something just keeps telling me it's not the best solution.
Open to any suggestions.
Presumably, there is ONE keypad - thus only one "Keypad Interface Object", right? Similarly with Display [ok, there may be two displays, but still].
So my suggestion would be to have a registration and a "container" that holds the registered interfaces something like this:
class KeyPad
{
public:
int getKeyPressed();
};
class Display
{
public:
OutputText(std::string msg);
};
... bunch of other stuff ...
class HardwareRegistry
{
priviate:
Keypad *keypad;
Display *display;
static HardwareRegistry *myself;
public:
Keypad* GetKeypad() { return keypad; }
Display* GetDisplay() { return display; }
void RegisterKeypad(Keypad *akeypad) { keypad = akeypad; }
void RegisterDisplay(Display *adisplay) { display = adisplay; }
static HardwareRegistry* GetHwRegistry()
{
if (!myself) myself = new HardwareRegistry;
ASSERT(myself); // If we don't have a pointer now, panic!
return myself;
}
};
Then you just have a Singleton Pattern to provide your HardwareRegistry, and register the devices as you create them during hardware initialization.
Of course, if you support different kinds of Keypads, Displays, etc, then you would implement those with a "interface baseclass", and the registry returns the KeypadBase type, for example.