It had just about every control imaginable. So with that experience, I know that that is not the road I want to go down. Instead I want to explore a new fad called an Immediate Mode gui. That other kind, with it's hierarchy of controls, is called Retained Mode, because the state is retained in the controls. The controls are actually objects that continue to exist, and to change the gui, you manipulate this set of objects. The biggest difference in an Immediate Mode gui is that there are no controls.
Some of the advantages an Immediate Mode gui has over the other way of doing things are, in a large app with a complicated gui like a map editor or Word, nothing at all. For these big complicated maps, the Retained Mode methodology of using nested controls and event callbacks works very well and there's no need to shake things up. Immediate Mode guis do not scale well to more complex projects. They can't hide the complexity.
That's enough rambling about theory. There's plenty of that on the internet already. Most of the things that made the retained mode libraries I examined so complex no longer matter. I don't need fancy controls (I might only need buttons), I don't need floating windows that the user can drag and drop. I don't even need to be able to skin it, instead I just draw it. What's seriously lacking on the internet is implementations, and since I need so little, the implementation is simple, too.
I'm going to start with a simple main menu. It has a bunch of buttons on the left. Clicking a button changes the panel on the right (Opening the options screen, for example). I don't know how to present this besides dumping some code. So here is some code.
var Imgui = new Gui.Driver(prevMouseState, mouseState);
var BorderLayout = new Gui.BorderLayout(Graphics.Viewport.Bounds, 20);
Imgui.Button(BorderLayout.PositionItem(Gui.BorderLayout.Sides.West, 276), (A, B) =>
{
spriteBatch.DrawBorder(background, A, new Rectangle(33, 33, 190, 9), Color.White);
var Layout = new Gui.FlowLayout(A, 10);
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => {
//Draw the button.
spriteBatch.Draw(buttonPlayAlone, C, D ? Color.Plum : Color.White); },
() => { /* Do Stuff if the button is clicked */ });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonHostOnline, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Host; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonJoinOnline, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Connect; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonOptions, C, D ? Color.Plum : Color.White); },
() => { SelectedWindow = Windows.Options; });
Layout.ForceNewLine();
Imgui.Button(Layout.PositionItem(256, 77),
(C, D) => { spriteBatch.Draw(buttonQuit, C, D ? Color.Plum : Color.White); },
() => { Quit(); });
},
() => { });
I'm using XNA for rendering (obviously), and lots of lambdas. The result of this is
All of the types involved (FlowLayout, BorderLayout, Driver) operate independently. They can be used individually, but together they allow complex arrangements. Unique to my technique is, I believe, the lack of an 'item id'. It still exists, in a sense, in the form of the 'SelectedWindow', but instead of assigning an id to every item, I require the client code to deal with it when it's appropriate.
What I want to know is, what do you want to be able to do with an immediate mode gui? If you've reviewed the material available on the internet, what don't you understand about how they work?