Interesting thread, lots of good stuff in it.
I’ve also felt a need for a simple gui and started to work on my own. But before I go into that I’d just like to bring up an old topic and some thoughts that come up when reading this thread and writing the gui.
I’ve been pushing for it before, but reading threads like this and the manyMouse thread etc it’s becoming more and more apparent that OF would gain massively by settling on an event system (I advocate poco :). If not OF could end up with dozens of different callback and event approaches in addons, which potentially would be painful…
Wehn it comes to colors, I’m using a Color class that I think is quite handy instead of passing rgba floats around and I’m thinking that something similar could be nice for of.
I’ve also been thinking that push and pop drawing operations would be nice. I don’t now what the overhead would be for this but it would make it easier to isolate drawing more within classes, such as gui elements. Right now if you set a color you don’t know if it will affect something that’s drawn later on…
ofPushColor();
ofPopColor();
ofPushCircleResolution();
ofPopCircleResolution();
etc would take care of that…
and btw, what’s a networked gui object? sounds interesting…
Ok, back to the gui stuff I’m working on. I’m only interested in something for debugging and behind the scenes stuff, and don’t really want to spend time on it, so I’m trying to keep what I’m working on functional but without slick effects or graphics. Very much like controlP5 which I too dig… I have it pretty much planned out and _just_ need to fix some input field logic, put in some poco events and adjust the gui so it has nice contrast on top of any background and it will cover the gui stuff I usually need (though chris post got me thinking about a timeline). I think it might be nice to have something that can be used both for gui stuff and for other interactive elements though, just like DisplayObjects in Flash, which is another reason why I’m trying to stay a way from heavy gui-only things like xml styles, though that could be nice.
It’s going to be cleaned up and reworked a bit, but now that I found this thread I’ve committed some code to cppglue.googlecode.com, if you want to have a look at it (gui is in GUI and the base classes are in Graphics). Thoughts and suggestions are welcomed, I’d like to get the API as solid as possible before spending time on specific gui elements or optimizations…
It’s set up similar to DisplayObject and DisplayContainer in Flash but I call my base classes Widget and WidgetContainer (for uknown reasons, might change that). The idea is that you use a WidgetContainer to manage several widgets (or containers) at once, group them, translate them, making them behave like radio buttons etc. If you need a custom widget you just extend the base widget class and do your stuff within setup(), update(), draw(). A widget is very similar in structure to testApp except that they have access to some more gui logic and events and can be organized in containers. Just like with DisplayObjects in flash they could be used to render pretty much anything.
Right now the WidgetContainer stands in for a display list, it works but I’m thinking about complimenting it with a real display list so that all widgets would have globally unique id’s. In the more far away future I can imagine adding some more 3d support (z-indexes etc) and support for multiple inputs (like manyMouse)…
Anyway, the poco events aren’t there yet (but they should be quick to add in the base class), and I’ve been dreading the boring input field. But once that is done I’ll make an example and show how you could listen to events such as a widget being clicked on or the mouse entering over it etc…
For now let’s just say that it looks and works like controlP5 and here’s an example of how you could throw some stuff out on the screen:
void testApp::setup(){
// rootContainer is a WidgetContainer instance
Widget* w = rootContainer.addChild(0, new WidgetContainer(200,200)); //the new WidgetContainer is returned as a Widget pointer
((WidgetContainer*)w)->setRadioContainer(true); // casting to the correct widget (int this case a WidgetContainer) and setting a parameter on it
((WidgetContainer*)w)->addChild(1, new RectToggle(0,0,10,10, true)); // adding a widget to the WidgetContainer
((WidgetContainer*)w)->addChild(2, new RectToggle(0,20,10,10));
// adding some more widgets to the rootContainer…
w = rootContainer.addChild(1, new RectButton(100,100,30,30));
w->setDraggable(true); //no need to cast here since setDraggable is a Widget method
w=rootContainer.addChild(2, new TextLabel(350,50, “HELLO”));
w->setDraggable(true);
w=rootContainer.addChild(6, new InputField(350,90, 100, 18, “HELLO”));
w=rootContainer.addChild(3, new RectSlider(200,300,300,10));
w=rootContainer.addChild(4, new RectSlider(50,300,10,100, true));
w=rootContainer.addChild(5, new CircleKnob(400,400,50));
((CircleKnob*)w)->setValue(10);
rootContainer.setup();
}
//--------------------------------------------------------------
void testApp::update(){
rootContainer.update();
}
//--------------------------------------------------------------
void testApp::draw(){
rootContainer.draw();
rootContainer.drawInfo(); // shows all widgets positions etc
}
//--------------------------------------------------------------
void testApp::keyPressed(int key){
rootContainer.keyPressed(key);
}
//--------------------------------------------------------------
void testApp::keyReleased(int key){
rootContainer.keyReleased(key);
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
rootContainer.mouseMoved(x, y);
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
rootContainer.mouseDragged(x, y, button);
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
rootContainer.mousePressed(x, y, button);
}
//--------------------------------------------------------------
void testApp::mouseReleased(){
rootContainer.mouseReleased();
}
puh, that was a long post…