I made some code because I needed a way to keep track of open windows, switch to another mode where other windows should be visible, and switch back again.
I've made a "windowStack" which can keep track of several groups of windows and show or hide them when you switch to another context. It's just a few Meml's with pointers to Window elements.
Then I added a new struct "stackWindow" which extends the normal window, but registers itself with the windowStack on fadeIn, and removes itself on fadeOut.
With the function switchToStack(W_STACK stack) you can easily switch between several contexts and show only the windows that are linked to that context.
A nice extra is a function escapePressed() which closes the last added window of the current context. Like the name says, it can be interesting if you want to close windows on pressing escape. (Before this code, I had to check all windows for that.)
Using these structures is as easy as:
PHP Code:
struct chat {
GuiObjs obj;
parts::stackWindow * window;
//etc...
void gui::chat::create() {
obj.replaceWindow<parts::stackWindow>();
if (obj.load("gui/obj/chat.gobj")) {
window = (parts::stackWindow *)&obj.getWindow("window");
// if you want it on another windowStack, just do
window->stack = gui::WS_QUEST;
// or if you don't want this window to close when pressing escape, use:
window->keepOnEsc = true;
//etc...
So not much more work than a standard gui object.
Here's the code for the windowStack and stackWindow structures, in case someone can use it. I used two contexts here: MAIN and QUEST. But you can very easily extend it to more.
windowStack.h
PHP Code:
#pragma once
namespace gui {
enum W_STACK {
WS_MAIN ,
WS_QUEST ,
WS_CURRENT,
};
struct pWindow {
Window * window ;
Bool keepOnEsc;
};
struct windowStack {
Meml<pWindow> main ;
Meml<pWindow> quest ;
Meml<pWindow> * current ;
windowStack();
void switchToStack(W_STACK stack);
void add (Window * window, Bool keepVisible = false, W_STACK stack = WS_CURRENT);
void remove (Window * window); // remove if in current stack
Bool escapePressed( ); // closes the last opened window on the current stack, returns false if nothing was closed
};
extern windowStack WindowStack;
} // end namespace
windowStack.cpp
PHP Code:
#include "stdafx.h"
#include "windowStack.h"
gui::windowStack gui::WindowStack;
gui::windowStack::windowStack() {
current = &main;
}
void gui::windowStack::switchToStack(W_STACK stack) {
switch (stack) {
case WS_MAIN: {
current = &main;
FREPA (quest) quest[i].window->fadeOut();
FREPA (main ) main [i].window->fadeIn ();
break;
}
case WS_QUEST: {
current = ?
FREPA (main ) main [i].window->fadeOut();
FREPA (quest) quest[i].window->fadeIn ();
break;
}
}
}
void gui::windowStack::add(Window * window, Bool keepOnEsc, W_STACK stack) {
pWindow * p = NULL;
if (stack == WS_CURRENT) {
MFREP(*current) if ( (*current)[i].window == window) return;
p = ¤t->New();
} else if (stack == WS_MAIN) {
MFREP(main) if (main[i].window == window) return;
p = &main.New();
} else if (stack == WS_QUEST) {
MFREP(quest) if (quest[i].window == window) return;
p = &quest.New();
}
if (p != NULL) {
p->window = window ;
p->keepOnEsc = keepOnEsc ;
}
}
void gui::windowStack::remove(Window * window) {
SMFREP(*current) {
if ( (*current)[i].window == window) {
current->remove(i);
return;
}
}
}
Bool gui::windowStack::escapePressed() {
SMREP(*current) {
if (! (*current)[i].keepOnEsc ) {
(*current)[i].window->fadeOut();
current->remove(i);
return true;
}
}
return false;
}
stackWindow.h
PHP Code:
#pragma once
#include "..\windowStack.h"
namespace gui {
namespace parts {
struct stackWindow : Window {
::gui::W_STACK stack;
Bool keepOnEsc;
stackWindow();
stackWindow& del(); // just to be safe
stackWindow& fadeIn ( );
stackWindow& fadeOut ( );
stackWindow& fadeToggle ( );
stackWindow& fade (Bool in);
};
}
}
stackWindow.cpp
PHP Code:
#include "stdafx.h"
#include "stackWindow.h"
using namespace gui::parts;
stackWindow& stackWindow::del() {
::gui::WindowStack.remove(this);
super::del();
return T;
}
stackWindow::stackWindow() {
stack = ::gui::WS_MAIN;
keepOnEsc = false;
}
stackWindow& stackWindow::fadeIn() {
::gui::WindowStack.add(this, keepOnEsc, stack);
super::fadeIn();
return T;
}
stackWindow& stackWindow::fadeOut() {
::gui::WindowStack.remove(this);
super::fadeOut();
return T;
}
stackWindow& stackWindow::fadeToggle() {
if (T.hiding()) ::gui::WindowStack.add(this, keepOnEsc, stack);
else ::gui::WindowStack.remove(this);
super::fadeToggle();
return T;
}
stackWindow& stackWindow::fade(Bool in) {
if (in) ::gui::WindowStack.add(this, keepOnEsc, stack);
else ::gui::WindowStack.remove(this);
super::fade(in);
return T;
}
oh, and I know it's not really a stack
I just called it that because I had that ESC functionality in my head.