How do I make a GUI? - c++

I've made many different seperate parts of a GUI system for the Nintendo DS, like buttons and textboxes and select boxes, but I need a way of containing these classes in one Gui class, so that I can draw everything to the screen all at once, and check all the buttons at once to check if any are being pressed. My question is what is the best way organize all the classes (such as buttons and textboxes) into one GUI class?
Here's one way I thought of but it doesn't seem right:
Edit: I'm using C++.
class Gui {
public:
void update_all();
void draw_all() const;
int add_button(Button *button); // Returns button id
void remove_button(int button_id);
private:
Button *buttons[10];
int num_buttons;
}
This code has a few problems, but I just wanted to give you an idea of what I want.

This question is very similar to one I was going to post, only mine is for Sony PSP programming.
I've been toying with something for a while, I've consulted some books and VTMs, and so far this is a rough idea of a simple ui systems.
class uiElement()
{
...
virtual void Update() = 0;
virtual void Draw() = 0;
...
}
class uiButton() public : uiElement
{
...
virtual void Update();
virtual void Draw();
...
}
class uiTextbox() public : uiElement
{
...
virtual void Update();
virtual void Draw();
...
}
... // Other ui Elements
class uiWindow()
{
...
void Update();
void Draw();
void AddElement(uiElement *Element);
void RemoveElement(uiElement *Element);
std::list <uiElement*> Elements;
...
}
void uiWindow::Update()
{
...
for (list <uiElement*>::iterator it = Elements.begin(); it != Elements.end(); it++ )
it->Update();
...
}
void uiWindow::Draw()
{
...
for (list <uiElement*>::iterator it = Elements.begin(); it != Elements.end(); it++ )
it->Draw();
...
}
The princple is to create a window and attact ui Elements to it, and call the draw and update methods from the respective main functions.
I don't have anything working yet, as I have issues with drawing code. With different APIs on the PC and PSP, I'm looking at some wrapper code for OpenGL and psp gu.
Hope this helps.
thing2k

For anyone who's interested, here's my open source, BSD-licenced GUI toolkit for the DS:
http://www.sourceforge.net/projects/woopsi
thing2k's answer is pretty good, but I'd seriously recommend having code to contain child UI elements in the base uiElement class. This is the pattern I've followed in Woopsi.
If you don't support this in the base class, you'll run into major problems when you try to implement anything more complex than a textbox and a button. For example:
Tab bars can be modelled as multiple buttons grouped together into a single parent UI element that enforces mutual exclusiveness of selection;
Radio button groups (ditto);
Scroll bars can be represented as a slider/gutter element and up/down buttons;
Scrolling lists can be represented as a container and multiple option UI elements.
Also, it's worth remembering that the DS has a 66MHz CPU and 4MB of RAM, which is used both to store your program and execute it (DS ROMs are loaded into RAM before they are run). You should really be treating it as an embedded system, which means the STL is out. I removed the STL from Woopsi and managed to save 0.5MB. Not a lot by desktop standards, but that's 1/8th of the DS' total available memory consumed by STL junk.
I've detailed the entire process of writing the UI on my blog:
http://ant.simianzombie.com/blog
It includes descriptions of the two algorithms I came up with for redrawing the screen, which is the trickiest part of creating a GUI (one just splits rectangles up and remembers visible regions; the other uses BSP trees, which is much more efficient and easier to understand), tips for optimisation, etc.

One useful strategy to keep in mind might be the composite pattern. At a low level, it might allow you to treat all GUI objects (and collections of objects) more easily once built. But I have no idea what's involved in GUI framework design, so one place to find general inspiration is in the source code of an existing project. WxWidgets is a cross-platform GUI framework with source available. Good luck with your project!

I think looking at the way other GUI toolkits have done it would be an excellent place to start. For C++ examples, I hear lots of good things about Qt. I haven't used it personally though. And of course WxWidgets as Nick mentioned.

I've written a very simple GUI just like you propose. I have it running on Windows, Linux and Macintosh. It should port relatively easily to any system like the PSP or DS too.
It's open-source, LGPL and is here:
http://code.google.com/p/kgui/

Related

Too deep hierarchy of signals-slots in Qt

I am writing GUI applicaton in Qt. Currently I waste too much time on routine. It seems something wrong with my architecture. Please tell me how can I change my approach to improve code.
What I am doing:
My program can be decomposed as hierarchy of classes (not inheritance but composition). In example:
class D { /* something */ };
class C { /* something */ };
class B { C c1; C c2; D d1; };
class A { D d1; C c1; };
So, actually it is a tree hierarchy where leaf nodes (class C, class D) are "models" in Qt terminology which hold data. At the top of hierarchy MainWindow (class A) is placed, which holds first level of "views" (class D, i.e. subwidget) and leaf node with data (class C, i.e. text field).
To pass information down from main window to data I use function calls from mainwindow (pushbuttons) to leaf nodes. After that data changes and tells parents about it with signal slot mechanism. Parents continue to pass message up with signaling.
I am really bored by establishing all these communication. Now I have up to 5 levels, however it is not that much in usual code when using composition. Please tell me how can I change my approach. Due to complexity of these connections, development of the code extremely slow, almost stopped.
It is hard to give a concrete example, because there are a lot of code, but the idea of problem which is very difficult to solve is following:
There are two QTreeView, which differently shows data from own model inherited from QAbstractItemModel (tree inside model is not that tree in previous discussion, this tree is only single level of hierarchy). I want to select objects in one QTreeView and change by that selection in second QTreeView. There are total 2 QTreeView, 2 different QAbstractItemModel instances, 2 trees of own objects (for each QAbstractItemModel), and single data.
Sounds like you might have become a victim of going through too many examples. Examples tend to cram functionality where it doesn't belong, creating the possibility to develop bad programming habits.
In actual production things need to be more compartmentalized. The main window should not be the container of the "application logic", all it needs to concern itself with is holding together the main widgets.
But that doesn't seem to be your case, judging by the necessity to delegate things "from mainwindow (pushbuttons) to leaf nodes" as you put it.
On a grander scale, it is not advisable to mix application logic with UI at all, much less cram it all in the main window. The application logic should be its own layer, designed so that it can work without any GUI whatsoever, and then the GUI is another layer that simply hooks up to the logic core.
The logic core should not be monolith either, it should be made of individual components focusing on their particular task.
Your use case doesn't really require any crazy amount of connections, just some basic handlers for the UI elements, which should target the logic core API rather than GUI elements as you appear to be doing now.
Your clarification unfortunately makes absolutely no sense to me, it is still completely unclear what you exactly you want to do.
Let's assume your situation is something like this:
Tree 1 shows a folder structure.
Tree 2 shows the file content of the folder, selected in tree 1.
Data is an editor for the file, assuming a text file, selected in tree 2.
So, in pseudocode, presuming that app is your application core logic object:
Clicking an item in tree 1 says app.setFolder(tree1.selectedItem())
Clicking an item in tree 2 says app.setFile(tree2.selectedItem())
Clicking the editor "save" button says app.save(editorUI.dataField.text())
logic layer gui layer
app mainWindow
folder <-----------select----------- tree1
file <-----------select----------- tree2
save(newData) { editor
if (file) file.rewrite(newData) textField
} saveBtn: app.save(textField.text())
Since there is only a single data source, you could do the following:
Create a general model for that data source. The model should represent the data source generally, without consideration of what the views need.
Create two proxy viewmodels that adapt the general model to the needs of the views.
Couple the selection models of the views that display the viewmodels.
Given the selection models on top of the two proxy models that map to the same source, we can propagate the selection change between them. We leverage the selection mapping provided by the proxy. The QAbstractProxyModel has a functional implementation of mapSelectionxxxx.
void applySel(const QItemSelectionModel *src, const QItemSelection &sel,
const QItemSelection &desel, const QItemSelectionModel *dst) {
// Disallow reentrancy on the selection models
static QHash<QObject*> busySelectionModels;
if (busySelectionModels.contains(src) || busySelectionModels.contains(dst))
return;
busySelectionModels.insert(src);
busySelectionModels.insert(dst);
// The models must be proxies
auto *srcModel = qobject_cast<QAbstractProxyItemModel*>(src->model());
auto *dstModel = qobject_cast<QAbstractProxyItemModel*>(dst->model());
Q_ASSERT(srcModel && dstModel);
// The proxies must refer to the same source model
auto *srcSourceModel = srcModel->sourceModel();
auto *dstSourceModel = dstModel->sourceModel();
Q_ASSERT(srcSourceModel && (srcSourceModel == dstSourceModel));
// Convey the selection
auto const srcSel = srcModel->mapSelectionToSource(sel);
auto const srcDesel = srcModel->mapSelectionToSource(desel);
auto const dstSel = dstModel->mapSelectionFromSource(srcSel);
auto const dstDesel = dstModel->mapSelectionFromSource(srcDesel);
// we would re-enter in the select calls
dst->select(dstSel, QItemSelectionModel::Select);
dst->select(dstDesel, QItemSelectionModel::Deselect);
// Allow re-entrancy
busySelectionModels.remove(src);
busySelectionModels.remove(dst);
}
The above could be easily adapted for a list of destination item selection models, in case you had more than two views.
We can use this translation to couple the selection models of the views:
void coupleSelections(QAbstractItemView *view1, QAbstractItemView *view2) {
auto *sel1 = view1->selectionModel();
auto *sel2 = view2->selectionModel();
Q_ASSERT(sel1 && sel2);
connect(sel1, &QItemSelectionModel::selectionChanged,
[=](const QItemSelection &sel, const QItemSelection &desel){
applySel(sel1, sel, desel, sel2);
});
connect(sel2, &QItemSelectionModel::selectionChanged,
[=](const QItemSelection &sel, const QItemSelection &desel){
applySel(sel2, sel, desel, sel1);
});
}
The above is untested and written from memory, but hopefully will work without much ado.

Clarification on the Dependency Inversion Principle

Excuse me for cross-posting on Software Engineering, didn't know that it was frowned upon.
The answer I was got there was exactly what I was looking for, for those curious: https://softwareengineering.stackexchange.com/a/347143/269571
Original question
I'm reading the book "Agile Software Development, Principles, Patterns, and Practices" by Robert C. Martin.
When he talks about the Dependency Inversion Principle he gives the following example of a DIP violation:
This seems very clear to me, as the higher-level object Button is depending on a lower-level object Lamp.
The solution he comes with is:
He creates an interface so that way Button is no longer depending on the object Lamp.
The theory seems really clear to me, however I can't wrap my head around using the principle in real-life projects.
Who is going to determine what classes (that implement SwitchableDevice) need to be called?
Who tells Button what devices he need to turn on/off?
How do you tell an object that uses something abstract which concrete things it needs to use? (Please correct me if this question is completely wrong)
If anything is unclear about my question, please let me know, I'll be glad to clarify things for you.
The whole point of dependency injection (at least as I understood it) is that the Button does not need to know what concrete SwitchableDevice it is switching.
The abstract interface could look like this:
struct SwitchableDevice {
virtual void switchOn() = 0;
virtual void switchOff() = 0;
};
And the button could be implemented like this:
struct Button {
SwitchableDevice& dev;
bool state = false;
Button(SwitchableDevice& d) : dev(d) {}
void buttonPress(){
if (state) { dev.switchOff(); }
else { dev.switchOn(); }
state = !state;
}
};
For the button, thats it! Noone needs to tell the button what is the concrete implementation of the SwitchableDevice, in other words: The implementation of the Button and the SwitchableDevice are decoupled.
A possible implementation of a Lamp could look like this:
struct Lamp : SwitchableDevice {
void switchOn(){std::cout << "shine bright" << std::endl;}
void switchOff(){std::cout << "i am not afraid of the dark" << std::endl;}
};
And that could be used like this:
int main(){
Lamp lamp;
Button button(lamp);
button.buttonPress();
button.buttonPress();
}
Hope that helps...
The benifit is that now we can change the implementation of the Button and the Lamp individually, without having to change anything on the other part. For example a ButtonForManyDevices could look like this:
struct ButtonForManyDevices {
std::vector<SwitchableDevice*> devs;
bool state = false;
Button(std::vector<SwitchableDevice*> d) : devs(d) {}
void buttonPress(){
if (state) for (auto d: devs) { d.switchOff(); }
else for (auto d: devs) { d.switchOn(); }
state = !state;
}
};
And similarly you could change the behaviour of the Lamp completely (of course within the limits of SwitchableDevice without having to change anything on the button. The same ButtonForManyDevices could even be used to switch a Lamp, a VaccumCleaner and a MicroWaveOven.
He's saying that what a button controls should be more generalized than just a lamp. If you have button classes for each type of thing that a button can control, then you could wind up with a lot of button classes.
In the first example, one is describing a button on a lamp. It essentially is taking the lamp as the starting point and dividing it into components.
In the second example, he is dividing the parts and looking at a button more generally.
Who is going to determine what classes (that implement SwitchableDevice) need to be called?
There is going to have to be a link between the button and the interface.
Who tells Button what devices he need to turn on/off?
The Button class would need to implement a mechanism to tell what device it is connected to.
How do you tell an object that uses something abstract which concrete things it needs to use? (Please correct me if this question is completely wrong).
Because an object that derives from an abstract interface must fully implement the interface. A Lamp object must define a TurnOn and TurnOff method somewhere..

Clean OOP design when making a GUI

Say I have two main classes, Application and ApplicationGUI. Application does lots of things and can happily run without any knowledge that ApplicationGUI exists. ApplicationGUI is linked to Application in many ways, it has maybe 50 or 100 different knobs that can change Application's behavior.
ApplicationGUI is a hierarchical structure such that it has many instances of ControlGroup, each containing an arbitrary number of Buttons and Knobs, or even another ControlGroup.
Current design: Upon instantiation of the ApplicationGUI (Application was already running with some set of default parameters), I pass pointers of Application's parameters to various components of the GUI. For example:
my_gui.sound_controlgroup.knob.link_to_param(&(my_application.volume));
If I need to do something more complex, say call a member function of Application, my_application.update_something(), how is this done?
The easy answer is to pass a pointer to my_application to my_gui.sound_controlgroup.knob, but if I only ever need to call one of my_application's functions, it seems like I am giving my knob an option to change all kinds of things that it should even know about (my_application.update_something_unrelated(), for instance). What is the cleanest thing to do in this case?
Additionally, this either requires making all subcomponents of ApplicationGUI public or having a function at each stage of the hierarchy to forward that pointer to the bottom level. This leads to quite a lot of functions. Is this a necessary consequence of a UI with a lot of knobs?
Quick Short Answer
In order to implement interaction between your non GUI related Application object and your GUIApplication object I suggest apply the "Property and Method and Event Handler" paradigm.
Extended Complex Answer
G.U.I. development is one of the most practical implementation of the O.O.P. theory.
What is the "Property and Method and Event Handler" paradigm ?
That means build, both Non GUI Classes, and GUI Classes, should have:
Properties
Methods
Event handlers
"Events" (Handlers) are also called "Signals", and are implemented with functions pointers. Not sure, but, I think your "knob" (s) are like Event Handlers.
It's a technique to apply the my_application.update_something_unrelated(), you have in your question.
Since, C++, like Java, does not have property syntax, you may use "getter" and "setter" methods, or use a "property" template.
For example, if your application has a Close method, you may declare something like the following examples.
Note: They are not full programs, just an idea:
// Applications.hpp
public class BaseApplicationClass
{
// ...
};
public class BaseApplicationClientClass
{
// ...
};
typedef
void (BaseApplicationClientClass::*CloseFunctor)
(BaseApplicationClass App);
public class ApplicationClass: public BaseApplicationClass
{
// ...
public:
Vector<BaseApplicationClientClass::CloseFunctor>
BeforeCloseEventHandlers;
Vector<BaseApplicationClientClass::CloseFunctor>
AfterCloseEventHandlers;
protected:
void ConfirmedClose();
public:
virtual void Close();
} Application;
// Applications.cpp
void ApplicationClass::ConfirmedClose()
{
// do close app. without releasing from memory yet.
} // void ApplicationClass::ConfirmedClose()
void ApplicationClass::Close()
{
// Execute all handlers in "BeforeCloseEventaHandlers"
this.ConfirmedClose();
// Execute all handlers in "AfterCloseEventaHandlers"
} // void ApplicationClass::Close()
// AppShells.cpp
public class AppShell: public BaseApplicationClientClass
{
// ...
};
void AppShell::CloseHandler(ApplicationClass App)
{
// close GUI
} // void AppShell.CloseHandler(ApplicationClass App)
void AppShell::setApp(ApplicationClass App)
{
App->BeforeCloseEventHandlers->add(&this.CloseHandler);
} // void AppShell.setApp(ApplicationClass App)
void main (...)
{
ApplicationClass* AppKernel = new ApplicationClass();
ApplicationGUIClass* AppShell = new ApplicationGUIClass();
AppShell.setApp(App);
// this executes "App->Run();"
AppShell->Run();
free AppShell();
free AppKernel();
}
UPDATE: Fixed type declaration from global function pointer (a.k.a. "global functor") to object function pointer (a.k.a. "method functor").
Cheers.
Do you know about the model-view-controller (MVC) paradigm? Think of the Application class as the model, the entire hierarchy of GUI controls as the view, and the ApplicationGUI class as the controller. You don't want Application to know about the controls, and you don't want the controls to know about Application; they should both talk only to the controller, ApplicationGUI.
Using ApplicationGUI as the conduit for communication between controls and Application means that you can test either Application or controls by replacing the other with a mock object, for example. More importantly, you can change either the controls or Application without impacting the other. Individual controls don't need to know anything about Application -- they only need to know where to send their value when it changes. And Application shouldn't care whether an input comes from a knob or a slider or a text field. Keeping those two areas separate will simplify each of them.
Additionally, this either requires making all subcomponents of
ApplicationGUI public or having a function at each stage of the
hierarchy to forward that pointer to the bottom level. This leads to
quite a lot of functions. Is this a necessary consequence of a UI with
a lot of knobs?
A given control shouldn't care what value it manages. It doesn't need to know whether the value determines the number of alien invaders on the screen or the coolant level in a nuclear reactor. It does needs to know things like the minimum and maximum values, label to display, scale to use (linear, log, etc.), and other things that directly impact the way the control works. It also needs to know who to tell when something changes, and it might need some way to identify itself.
With that in mind, ApplicationGUI doesn't need to expose accessors for every possible parameter of Application. Instead, it should have a general method that lets controls send it updates. When a control changes, it should send a message to ApplicationGUI containing the new value(s) along with its identifier, and ApplicationGUI takes care of mapping that identifier to some particular parameter of Application. A control's identifier could be some identifying number that's given to it, or it could just be a pointer to the control.
Of course, sometimes communication has to go the other way, too... a GUI usually has both inputs and outputs, so you'll want some means for ApplicationGUI to get updates from Application and update the state of the GUI. For the same reasons described above, Application should send those updates to ApplicationGUI and let the latter find the actual UI components that need to be changed.

Simple acces of C++ object data from QML

I'm making a board game in Qt/C++ using qml. All the important game data is represented in a single class. My intention is to have the qml sheets access this one object and draw the game board depending on the data.
What is the simplest approach to exposing the C++ data members to QML?
Now I know the question has been asked, I've seen the answers and the Qt Documentation. I am, however, not satisfied. What I've seen, the way to do this seems to be to make Q_PROPERTY out of every single variable I want to access from QML. This looks to me tedious and unnecessary, not to mention it will stretch the code to 3x it's original length, making it significantly worse to read. Also, in most cases I won't need write function to the data members, for example.
And why bother with Q_PROPERTY overhead when I could just write Q_INVOKABLE getters for just the situations I need?
Here's an example of how simple I hoped it would be when I read in the Qt Project documentation: "This enables C++ data and functions to be accessible directly from QML, often with little or no modification."
class game : public QObject
{
Q_OBJECT
public:
explicit game(QObject *parent = 0);
colors NPC[3]; // colors being an enum declared elsewhere
player players[4]; // player is a non-QObject class containing player stats
}
...
game gMain;
QDeclarativeContext *context = viewer.rootContext();
context->setContextProperty("Game",&gMain);
QML in my ideal world:
Image {
id : Image1
source: { if (Game.NPC[0] === 0) {
if (Game.players[1].LifeCount > 0) {
return "pics/FigG.png"
}
else {
return "pics/StoneG.png"
}
}
Now how close to that can I actually get with QML and how do I go about it?
I'm especially interested in handling simple C++ style arrays and enums (have a lot of those in the game) - would I need to write helper functions, e.g. int Game.GetNPCAt(int i) instead of using just Game.NPC[i] ?
I realize that the way I DON'T want to do it is the tried and trusted, and for good reason... however in my situation (small one-man project) it seems like using a cannon to kill a fly (although the GUI building part in qml is amazingly simple and quite a joy to use) - also having to wrap around every data member including the simplest like an int seems... ridiculously excessive.
Maybe I have missed something somewhere, In which case I humbly apologize. Thank you for any thoughts on the matter.
In order:
Q_PROPERTY: When you look at the page that you quoted, they discuss using the Q_PROPERTY method to expose properties to QML. If you don't use Q_PROPERTY, it is my understanding that your variables won't be registered by QMLViewer (or what have you). The Q_PROPERTY needs a Q_INVOKABLE to get/set your variables. If you don't use Q_PROPERTY, though, your class properties will not appear in QML.
Setting the image source: If you may remember, QML is a forge between CSS and JavaScript. If you're just looking to make the image's source change depending on a condition outside of your Image element, you can just create a JavaScript function to achieve what you have quoted:
Image {
id: Image1
function getImage()
{
if (Game.NPC[0] === 0)
{
if (Game.players[1].LifeCount > 0) {
Image1.source="pics/FigG.png";
}
else {
Image1.source="pics/StoneG.png";
}
}
}
However, the function won't run by itself: you'll have to associate it with a signal, which I would create in your C++ class (put the function under a label named signals: (NOT within public -- see here on how to write signals)). Based on your example, I'm guessing that your C++ object is called Game.
Game {
id: gameKeeper //or whatever you want to name it
onUpdate: Image1.getImage() //replace onUpdate with your signal
}
Image {
id: Image1
function getImage()
{
if (gameKeeper.NPC[0] === 0)
{
if (gameKeeper.players[1].LifeCount > 0) {
Image1.source="pics/FigG.png";
}
else {
Image1.source="pics/StoneG.png";
}
}
}
In theory, you should be able to reference arrays this way with JavaScript (I'm not all that familiar with JS myself).
Array handling: On the C++ side, it looks like the best way to do it is through a QList. Fortunately, a QList iterates very similar to a normal array. I found this, which should help -- just ignore the second dimension.
Hope this helps.

Good design practice concerning MVC view interface

I don't often have to create GUI's but today I do so I was hoping for some design input.
Basically I have a backend which I intend to add a GUI too using the MVC pattern. The issue is I feel whatever class encapsulates the main GUI window is going to have A LOT of state (all of the sub elements); and on top of that it's going to have a lot of setters, and possibly getter, clear, colour, size, position and refresh functions too.
One option is to march ahead with this idea and have a very large public interface which deals with the types the GUI uses (std::string, std::vector<std::string>...) the more control I want over the UI the more public member function I am going to need.
The other option would be to pass the program state to the GUI and have it decide how it display it, I fear doing this would mean it would give me less fine detail control and would break down the separation of concerns and would mean any changes to the representation of the program state would require changes in the GUI too.
Any input on the matter would be of great help.
If it makes any difference this is a C++ gui using an ncurses abstraction.
It sounds like to me you've thought alot about the M and the V, but not much about the C. The pattern should really be called MCV because the whole idea is that the controller IS the bridge between your model (data) and view (GUI). It sounds like you need a controller with most of the functionality you've mentioned.
Simply put though, your model obviously should know nothing about display and your display (view) should not know how to access the model. You need a controller that reads the data (model) and gives instructions to the display (view). If you have user interaction within the view, the controller can interpret that and modify the model as necessary.
The idea is that you never have to change all 3, but if you change the model or the view, you almost always have to update the controller.
Hope that helps...
There is at least one alternative to the giant interface. Instead of having a function that handles each thing (size, font, color, what-to-display, etc...) have a singular function that accepts a "role" and data that represents the role. This requires some sort of wrapper that can contain multiple data types.
QT's QAbstractItemModel Class Reference has a good example:
QVariant QAbstractItemModel::data ( const QModelIndex & index, int
role = Qt::DisplayRole ) const [pure virtual]
What that function will do is return the QVariant that represents the role indicated at the index provided.
The downside of this approach, is you have to know what roles exist, and what they do. QT's default roles are shown here.
I like to have parts of the model able to instrument themselves:
class Model {
private:
int value;
public:
void instrument(Instrumenter& instrumenter);
};
The Instrumenter manages the creation of controls. The model will tell it how it can be controlled and give it access to the data.
void Model::instrument(Instrumenter& instrumenter) {
instrumenter.addRangeController(0, 100, 5, value);
}
Then for different input devices (e.g keyboard, touchscreen) you can create appropriate controls:
class KeyboardInstrumenter : public Instrumenter {
public:
void addRangeController(int min, int max, int increments, int& controlled) {
// create 3 widgets, up arrow, down arrow, and value
}
};
class TouchscreenInstrumenter : public Instrumenter {
public:
void addRangeController(int min, int max, int increments, int& controlled) {
// create slider with min, max and increments
}
};
Instead of passing in the int directly we could have wrapped it in a controlling object, to aid encapsulation.