Difference between revisions of "Dialog System"

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Jump to: navigation, search
 
Line 1: Line 1:
 
The default CEGUI implementation stores the currently specified values of the widgets such that closing and then reopening a window will redisplay those values.  Presented here is a different approach, to allow values to be saved or cancelled.
 
The default CEGUI implementation stores the currently specified values of the widgets such that closing and then reopening a window will redisplay those values.  Presented here is a different approach, to allow values to be saved or cancelled.
  
[[WindowingSystem.layout]]
+
==== WindowSystem.h ====
 +
<pre>
 +
#ifndef _WindowSystem_h_
 +
#define _WindowSystem_h_
 +
 
 +
#include "CEGUI.h"
 +
#include "vector"
 +
 
 +
class WindowSystem
 +
{
 +
public:
 +
WindowSystem();
 +
enum WindowSystemEvents { open, ok, cancel, escape, apply, modified };
 +
bool isModified(); // Return whether data within the window is modified
 +
 
 +
// Actions
 +
virtual bool doOpen(); // Open the window
 +
virtual bool doLoad(); // Assign the data into the widgets
 +
virtual bool doSave(); // Assign the widgets into the data
 +
virtual bool doClose(); // Close the window
 +
void initialise(const CEGUI::String& window, bool visible, const CEGUI::String& parent = ""); // Initialise the window system
 +
void bindEvent(const CEGUI::String& widget, const CEGUI::String& event, WindowSystem::WindowSystemEvents action); // Subscribe to window events
 +
private:
 +
// Events
 +
bool onOpen(const CEGUI::EventArgs& e); // Open the window
 +
bool onOk(const CEGUI::EventArgs& e); // Save the data and close the window
 +
bool onCancel(const CEGUI::EventArgs& e); // Close the window
 +
bool onEscape(const CEGUI::EventArgs& e); // Close the window
 +
bool onApply(const CEGUI::EventArgs& e); // Save the data
 +
bool onModified(const CEGUI::EventArgs& e); // A widget in the window has been modified
 +
 
 +
CEGUI::String m_parent; // Handle to the parent
 +
CEGUI::String m_window; // Handle to the window
 +
CEGUI::String m_apply;  // Handle of the apply button
 +
bool m_modal; // Whether the window is modal
 +
bool m_modified; // Whether data within the window is modified
 +
};
 +
 
 +
#endif // _WindowSystem_h_
 +
</pre>
 +
 
 +
 
 +
==== WindowSystem.cpp ====
 +
<pre>
 +
#include "WindowSystem.h"
 +
#include "assert.h"
 +
 
 +
WindowSystem::WindowSystem()
 +
{
 +
m_modal  = false;
 +
}
 +
 
 +
bool WindowSystem::isModified()
 +
{
 +
// Return whether data within the window is modified
 +
assert(!m_apply.empty() && "The isModified() function requires that you specify an \"Apply\" button");
 +
return !CEGUI::WindowManager::getSingleton().getWindow(m_apply)->isDisabled();
 +
}
 +
 
 +
bool WindowSystem::doOpen()
 +
{
 +
// Open the window
 +
assert(!m_window.empty() && "You have forgotten to call initialise()");
 +
if(m_modal)
 +
{
 +
// Displaying a modal window disables its parent
 +
assert(!m_parent.empty() && "The value of m_modal or m_parent has become corrupted");
 +
CEGUI::WindowManager::getSingleton().getWindow(m_parent)->setEnabled(false);
 +
}
 +
 
 +
// Display the window
 +
CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(true);
 +
 
 +
// Load the data into the widgets
 +
return doLoad();
 +
}
 +
 
 +
bool WindowSystem::doLoad()
 +
{
 +
// Populate the window widgets with data
 +
// Note that this can also be used to simulate an undo for every widget
 +
// present in the window
 +
 
 +
// Disable the apply button since there are no modifications
 +
if(!m_apply.empty())
 +
CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(false);
 +
return true;
 +
}
 +
 
 +
bool WindowSystem::doSave()
 +
{
 +
// Update the data with the inputs from the widgets
 +
 
 +
// Disable the apply button since there are no modifications
 +
if(!m_apply.empty())
 +
CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(false);
 +
 
 +
return true;
 +
}
 +
 
 +
bool WindowSystem::doClose()
 +
{
 +
// Close the window
 +
assert(!m_window.empty() && "You have forgotten to call initialise()");
 +
 
 +
if(m_modal)
 +
{
 +
// Closing a modal window enables its parent
 +
assert(!m_parent.empty() && "The value of m_modal or m_parent has become corrupted");
 +
CEGUI::WindowManager::getSingleton().getWindow(m_parent)->setEnabled(true);
 +
}
 +
 
 +
CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(false);
 +
return true;
 +
}
 +
 
 +
void WindowSystem::initialise(const CEGUI::String& window, bool visible, const CEGUI::String& parent)
 +
{
 +
// Initialise the window system
 +
// Specifying a parent makes this window modal
 +
m_window = window;
 +
CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(visible);
 +
m_parent = parent;
 +
m_modal  = !m_parent.empty();
 +
}
 +
 
 +
 
 +
void WindowSystem::bindEvent(const CEGUI::String& widget, const CEGUI::String& widgetEvent, WindowSystemEvents action)
 +
{
 +
// Subscribe to events
 +
CEGUI::Window* widgetHandle = CEGUI::WindowManager::getSingleton().getWindow(widget);
 +
switch(action)
 +
{
 +
case open:
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onOpen, this));
 +
break;
 +
case ok:
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onOk, this));
 +
break;
 +
case cancel:
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onCancel, this));
 +
break;
 +
case escape:
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onEscape, this));
 +
break;
 +
case apply:
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onApply, this));
 +
m_apply = widget;
 +
break;
 +
case modified:
 +
if(!m_apply.empty())
 +
widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onModified, this));
 +
break;
 +
}
 +
}
 +
 
 +
bool WindowSystem::onOpen(const CEGUI::EventArgs& e)
 +
{
 +
// Open the window
 +
return doOpen();
 +
}
 +
 
 +
bool WindowSystem::onOk(const CEGUI::EventArgs& e)
 +
{
 +
// The 'ok' button was pressed
 +
// Respond by saving the data and closing the window
 +
return doSave() && doClose();
 +
}
 +
 
 +
bool WindowSystem::onCancel(const CEGUI::EventArgs& e)
 +
{
 +
// The 'cancel' button was pressed
 +
// Respond by closing the window without saving the data
 +
return doClose();
 +
}
 +
 
 +
bool WindowSystem::onEscape(const CEGUI::EventArgs& e)
 +
{
 +
// The 'escape' key was pressed
 +
// Respond by closing the dialog without saving the data
 +
// Note that Win32AppHelper::doDirectInputEvents() intercepts this key
 +
// This means that the escape key will NOT reach here
 +
    const CEGUI::KeyEventArgs& keyArgs = static_cast<const CEGUI::KeyEventArgs&>(e);
 +
if(keyArgs.scancode == CEGUI::Key::Escape)
 +
{
 +
return doClose();
 +
}
 +
else
 +
return false;
 +
}
 +
 
 +
bool WindowSystem::onApply(const CEGUI::EventArgs& e)
 +
{
 +
// The 'apply' button was pressed
 +
// Respond by saving the data without closing the window
 +
return doSave();
 +
}
 +
 
 +
bool WindowSystem::onModified(const CEGUI::EventArgs& e)
 +
{
 +
// A widget within the window was modified
 +
// Respond by enabling the 'apply' button
 +
CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(true);
 +
return true;
 +
}
 +
</pre>
 +
 
 +
==== WindowingSystemDemo.h ====
 +
<pre>
 +
#ifndef _WindowingSystemDemo_h_
 +
#define _WindowingSystemDemo_h_
 +
 
 +
#include "CEGuiSample.h"
 +
#include "CEGUI.h"
 +
#include "DemoUtils.h"
 +
#include "WindowSystem.h"
 +
 
 +
class SimpleWindow : public WindowSystem
 +
{
 +
public:
 +
void initWindow()
 +
{
 +
// Initialise the window
 +
using namespace CEGUI;
 +
 
 +
// Initialise the windowing system
 +
WindowSystem::initialise("winSimpleWindow", // The handle of this window
 +
false); // Initially invisible
 +
// A modeless window does not have a parent
 +
 
 +
// Subscribe to widget events
 +
// Note that the "close" button is set to behave as an "ok" button
 +
WindowSystem::bindEvent( "Toolbar_btnSimpleWindow", PushButton::EventClicked, WindowSystem::open);
 +
WindowSystem::bindEvent( "SimpleWindow_btnClose", PushButton::EventClicked, WindowSystem::ok);
 +
 
 +
// Subscribe to window events
 +
WindowSystem::bindEvent("winSimpleWindow", FrameWindow::EventCloseClicked, WindowSystem::cancel); // The 'X' button was clicked
 +
WindowSystem::bindEvent("winSimpleWindow", FrameWindow::EventKeyDown, WindowSystem::escape); // The 'escape' key was pressed
 +
}
 +
protected:
 +
bool doLoad()
 +
{
 +
// Handle the load action by placing data into widgets
 +
CEGUI::WindowManager::getSingleton().getWindow("SimpleWindow_edtValue")->setText(dataString);
 +
return WindowSystem::doLoad();
 +
}
 +
bool doSave()
 +
{
 +
// Handle the save action by moving widget data into variables
 +
dataString = CEGUI::WindowManager::getSingleton().getWindow("SimpleWindow_edtValue")->getText();
 +
return WindowSystem::doSave();
 +
}
 +
private:
 +
CEGUI::String dataString; // Variable associated with the Editbox
 +
};
 +
 
 +
//////////////////////////////////////////////
 +
 
 +
class SimpleDialog : public WindowSystem
 +
{
 +
public:
 +
void initWindow()
 +
{
 +
// Initialise the dialog
 +
using namespace CEGUI;
 +
WindowManager& winMgr = WindowManager::getSingleton();
 +
 
 +
// Initialise the windowing system
 +
WindowSystem::initialise("dlgSimpleDialog", // The handle of this window
 +
false, // Initially invisible
 +
"winToolbar"); // The handle of its parent, making it a modal dialog
 +
 
 +
// Subscribe to widget events
 +
WindowSystem::bindEvent( "Toolbar_btnSimpleDialog", PushButton::EventClicked, WindowSystem::open);
 +
WindowSystem::bindEvent( "SimpleDialog_btnOk", PushButton::EventClicked, WindowSystem::ok);
 +
WindowSystem::bindEvent( "SimpleDialog_btnCancel", PushButton::EventClicked, WindowSystem::cancel);
 +
WindowSystem::bindEvent( "SimpleDialog_btnApply", PushButton::EventClicked, WindowSystem::apply);
 +
 
 +
// These events trigger a 'modified' event, activating the 'apply' button
 +
WindowSystem::bindEvent( "SimpleDialog_edtValue", Editbox::EventTextChanged, WindowSystem::modified);
 +
 
 +
// Subscribe to window events
 +
// Pressing the 'X' button will behave as a cancel
 +
WindowSystem::bindEvent( "dlgSimpleDialog", FrameWindow::EventCloseClicked, WindowSystem::cancel); // The 'X' button was clicked
 +
WindowSystem::bindEvent( "dlgSimpleDialog", FrameWindow::EventKeyDown, WindowSystem::escape); // The 'escape' key was pressed
 +
}
 +
protected:
 +
bool doLoad()
 +
{
 +
// Handle the load action by placing data into widgets
 +
CEGUI::WindowManager::getSingleton().getWindow("SimpleDialog_edtValue")->setText(dataString);
 +
return WindowSystem::doLoad();
 +
}
 +
bool doSave()
 +
{
 +
// Handle the save action by moving widget data into variables
 +
dataString = CEGUI::WindowManager::getSingleton().getWindow("SimpleDialog_edtValue")->getText();
 +
return WindowSystem::doSave();
 +
}
 +
private:
 +
CEGUI::String dataString;
 +
};
 +
 
 +
//////////////////////////////////////////
 +
 
 +
class DemoSample : public CEGuiSample
 +
{
 +
public:
 +
    bool initialiseSample()
 +
{
 +
using namespace CEGUI;
 +
try
 +
{
 +
initDemo("../datafiles/layouts/WindowingSystem.layout");
 +
 
 +
// Initialise the Simple Window and the Simple Dialog
 +
simpleWindow.initWindow();
 +
simpleDialog.initWindow();
 +
}
 +
catch(Exception &e)
 +
{
 +
ErrorMessage(e.getMessage().c_str(), "Error initializing the demo");
 +
}
 +
 
 +
return true;
 +
}
 +
 
 +
    void cleanupSample(void)
 +
{
 +
}
 +
private:
 +
SimpleWindow simpleWindow;
 +
SimpleDialog simpleDialog;
 +
};
 +
 
 +
#endif // _WindowingSystemDemo_h_
 +
</pre>
 +
 
 +
 
 +
==== main.cpp ====
 +
<pre>
 +
#if defined( __WIN32__ ) || defined( _WIN32 )
 +
#define WIN32_LEAN_AND_MEAN
 +
#define NOMINMAX
 +
#include "windows.h"
 +
#endif
 +
 
 +
#include "WindowingSystemDemo.h"
 +
 
 +
 
 +
#if defined( __WIN32__ ) || defined( _WIN32 )
 +
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
 +
#else
 +
int main(int argc, char *argv[])
 +
#endif
 +
{
 +
    DemoSample app;
 +
    return app.run();
 +
}
 +
</pre>
 +
 
 +
==== WindowingSystem.layout ====
 +
<pre>
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<GUILayout>
 +
<Window Type="DefaultWindow" Name="Root" >
 +
<Property Name="UnifiedAreaRect" Value="{{0.000000,0.000000},{0.000000,0.000000},{1.000000,0.000000},{1.000000,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
<Window Type="TaharezLook/FrameWindow" Name="winToolbar" >
 +
<Property Name="AlwaysOnTop" Value="True" />
 +
<Property Name="CaptionColour" Value="00FFFFFF" />
 +
<Property Name="CloseButtonEnabled" Value="False" />
 +
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
 +
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
 +
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
 +
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
 +
<Property Name="Text" Value="Toolbar" />
 +
<Property Name="TitlebarEnabled" Value="False" />
 +
<Property Name="TitlebarFont" Value="Commonwealth-10" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.248750,0.000000},{0.010001,0.000000},{0.568749,0.000000},{0.081667,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
<Window Type="TaharezLook/Button" Name="Toolbar_btnSimpleWindow" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Simple Window" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.065103,0.000000},{0.227595,0.000000},{0.475554,0.000000},{0.686899,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/Button" Name="Toolbar_btnSimpleDialog" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Simple Dialog" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.538253,0.000000},{0.227595,0.000000},{0.948703,0.000000},{0.686899,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
</Window>
 +
<Window Type="TaharezLook/FrameWindow" Name="winSimpleWindow" >
 +
<Property Name="CaptionColour" Value="00FFFFFF" />
 +
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
 +
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
 +
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
 +
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
 +
<Property Name="Text" Value="Simple Window" />
 +
<Property Name="TitlebarEnabled" Value="True" />
 +
<Property Name="TitlebarFont" Value="Commonwealth-10" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.005000,0.000000},{0.168333,0.000000},{0.420000,0.000000},{0.511666,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
<Window Type="TaharezLook/Button" Name="SimpleWindow_btnClose" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Close" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.688554,0.000000},{0.804855,0.000000},{0.938554,0.000000},{0.943204,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/StaticText" Name="SimpleWindow_lblValue" >
 +
<Property Name="BackgroundImage" Value="set:TaharezLook image:StaticBackdrop" />
 +
<Property Name="BottomFrameImage" Value="set:TaharezLook image:StaticBottom" />
 +
<Property Name="BottomLeftFrameImage" Value="set:TaharezLook image:StaticBottomLeft" />
 +
<Property Name="BottomRightFrameImage" Value="set:TaharezLook image:StaticBottomRight" />
 +
<Property Name="Font" Value="Commonwealth-10" />
 +
<Property Name="LeftFrameImage" Value="set:TaharezLook image:StaticLeft" />
 +
<Property Name="RightFrameImage" Value="set:TaharezLook image:StaticRight" />
 +
<Property Name="Text" Value="Value:" />
 +
<Property Name="TopFrameImage" Value="set:TaharezLook image:StaticTop" />
 +
<Property Name="TopLeftFrameImage" Value="set:TaharezLook image:StaticTopLeft" />
 +
<Property Name="TopRightFrameImage" Value="set:TaharezLook image:StaticTopRight" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.455591,0.000000},{0.430746,0.000000},{0.606068,0.000000},{0.569095,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/Editbox" Name="SimpleWindow_edtValue" >
 +
<Property Name="Font" Value="Commonwealth-10" />
 +
<Property Name="MaxTextLength" Value="1073741823" />
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTextBar" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.618241,0.000000},{0.430746,0.000000},{0.970525,0.000000},{0.569095,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
</Window>
 +
<Window Type="TaharezLook/FrameWindow" Name="dlgSimpleDialog" >
 +
<Property Name="CaptionColour" Value="00FFFFFF" />
 +
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
 +
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
 +
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
 +
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
 +
<Property Name="Text" Value="Simple Dialog" />
 +
<Property Name="TitlebarEnabled" Value="True" />
 +
<Property Name="TitlebarFont" Value="Commonwealth-10" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.436250,0.000000},{0.165000,0.000000},{0.916249,0.000000},{0.508333,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnOk" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Ok" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.173754,0.000000},{0.804855,0.000000},{0.423754,0.000000},{0.943204,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnCancel" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Cancel" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.451828,0.000000},{0.804855,0.000000},{0.701828,0.000000},{0.943204,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnApply" >
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
 +
<Property Name="Text" Value="Apply" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.731230,0.000000},{0.804855,0.000000},{0.981230,0.000000},{0.943204,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/Editbox" Name="SimpleDialog_edtValue" >
 +
<Property Name="Font" Value="Commonwealth-10" />
 +
<Property Name="MaxTextLength" Value="1073741823" />
 +
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTextBar" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.626093,0.000000},{0.418446,0.000000},{0.971449,0.000000},{0.556795,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
<Window Type="TaharezLook/StaticText" Name="SimpleDialog_lblValue" >
 +
<Property Name="BackgroundImage" Value="set:TaharezLook image:StaticBackdrop" />
 +
<Property Name="BottomFrameImage" Value="set:TaharezLook image:StaticBottom" />
 +
<Property Name="BottomLeftFrameImage" Value="set:TaharezLook image:StaticBottomLeft" />
 +
<Property Name="BottomRightFrameImage" Value="set:TaharezLook image:StaticBottomRight" />
 +
<Property Name="LeftFrameImage" Value="set:TaharezLook image:StaticLeft" />
 +
<Property Name="RightFrameImage" Value="set:TaharezLook image:StaticRight" />
 +
<Property Name="Text" Value="Value:" />
 +
<Property Name="TopFrameImage" Value="set:TaharezLook image:StaticTop" />
 +
<Property Name="TopLeftFrameImage" Value="set:TaharezLook image:StaticTopLeft" />
 +
<Property Name="TopRightFrameImage" Value="set:TaharezLook image:StaticTopRight" />
 +
<Property Name="UnifiedAreaRect" Value="{{0.482291,0.000000},{0.418446,0.000000},{0.617709,0.000000},{0.556795,0.000000}}" />
 +
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
 +
</Window>
 +
</Window>
 +
</Window>
 +
</GUILayout>
 +
</pre>

Revision as of 07:08, 1 May 2006

The default CEGUI implementation stores the currently specified values of the widgets such that closing and then reopening a window will redisplay those values. Presented here is a different approach, to allow values to be saved or cancelled.

WindowSystem.h

#ifndef _WindowSystem_h_
#define _WindowSystem_h_

#include "CEGUI.h"
#include "vector"

class WindowSystem
{
public:
	WindowSystem();
	enum WindowSystemEvents { open, ok, cancel, escape, apply, modified };
	bool isModified(); // Return whether data within the window is modified

	// Actions
	virtual bool doOpen(); // Open the window
	virtual bool doLoad(); // Assign the data into the widgets
	virtual bool doSave(); // Assign the widgets into the data
	virtual bool doClose(); // Close the window
	void initialise(const CEGUI::String& window, bool visible, const CEGUI::String& parent = ""); // Initialise the window system
	void bindEvent(const CEGUI::String& widget, const CEGUI::String& event, WindowSystem::WindowSystemEvents action); // Subscribe to window events
private:
	// Events
	bool onOpen(const CEGUI::EventArgs& e); // Open the window
	bool onOk(const CEGUI::EventArgs& e); // Save the data and close the window
	bool onCancel(const CEGUI::EventArgs& e); // Close the window
	bool onEscape(const CEGUI::EventArgs& e); // Close the window
	bool onApply(const CEGUI::EventArgs& e); // Save the data
	bool onModified(const CEGUI::EventArgs& e); // A widget in the window has been modified

	CEGUI::String m_parent; // Handle to the parent
	CEGUI::String m_window; // Handle to the window
	CEGUI::String m_apply;  // Handle of the apply button
	bool m_modal; // Whether the window is modal
	bool m_modified; // Whether data within the window is modified
};

#endif // _WindowSystem_h_


WindowSystem.cpp

#include "WindowSystem.h"
#include "assert.h"

WindowSystem::WindowSystem()
{
	m_modal  = false;
}

bool WindowSystem::isModified()
{
	// Return whether data within the window is modified
	assert(!m_apply.empty() && "The isModified() function requires that you specify an \"Apply\" button");
	return !CEGUI::WindowManager::getSingleton().getWindow(m_apply)->isDisabled();
}

bool WindowSystem::doOpen()
{
	// Open the window
	assert(!m_window.empty() && "You have forgotten to call initialise()");
	if(m_modal)
	{
		// Displaying a modal window disables its parent
		assert(!m_parent.empty() && "The value of m_modal or m_parent has become corrupted");
		CEGUI::WindowManager::getSingleton().getWindow(m_parent)->setEnabled(false);
	}

	// Display the window
	CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(true);

	// Load the data into the widgets
	return doLoad();
}

bool WindowSystem::doLoad()
{
	// Populate the window widgets with data
	// Note that this can also be used to simulate an undo for every widget
	// present in the window

	// Disable the apply button since there are no modifications
	if(!m_apply.empty())
		CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(false);
	return true;
}

bool WindowSystem::doSave()
{
	// Update the data with the inputs from the widgets

	// Disable the apply button since there are no modifications
	if(!m_apply.empty())
		CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(false);

	return true;
}

bool WindowSystem::doClose()
{
	// Close the window
	assert(!m_window.empty() && "You have forgotten to call initialise()");

	if(m_modal)
	{
		// Closing a modal window enables its parent
		assert(!m_parent.empty() && "The value of m_modal or m_parent has become corrupted");
		CEGUI::WindowManager::getSingleton().getWindow(m_parent)->setEnabled(true);
	}

	CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(false);
	return true;
}

void WindowSystem::initialise(const CEGUI::String& window, bool visible, const CEGUI::String& parent)
{
	// Initialise the window system
	// Specifying a parent makes this window modal
	m_window = window;
	CEGUI::WindowManager::getSingleton().getWindow(m_window)->setVisible(visible);
	m_parent = parent;
	m_modal  = !m_parent.empty();
}


void WindowSystem::bindEvent(const CEGUI::String& widget, const CEGUI::String& widgetEvent, WindowSystemEvents action)
{
	// Subscribe to events
	CEGUI::Window* widgetHandle = CEGUI::WindowManager::getSingleton().getWindow(widget);
	switch(action)
	{
	case open:
		widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onOpen, this));
		break;
	case ok:
		widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onOk, this));
		break;
	case cancel:
		widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onCancel, this));
		break;
	case escape:
		widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onEscape, this));
		break;
	case apply:
		widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onApply, this));
		m_apply = widget;
		break;
	case modified:
		if(!m_apply.empty())
			widgetHandle->subscribeEvent(widgetEvent, CEGUI::Event::Subscriber(&WindowSystem::onModified, this));
		break;
	}
}

bool WindowSystem::onOpen(const CEGUI::EventArgs& e)
{
	// Open the window
	return doOpen();
}

bool WindowSystem::onOk(const CEGUI::EventArgs& e)
{
	// The 'ok' button was pressed
	// Respond by saving the data and closing the window
	return doSave() && doClose();
}

bool WindowSystem::onCancel(const CEGUI::EventArgs& e)
{
	// The 'cancel' button was pressed
	// Respond by closing the window without saving the data
	return doClose();
}

bool WindowSystem::onEscape(const CEGUI::EventArgs& e)
{
	// The 'escape' key was pressed
	// Respond by closing the dialog without saving the data
	// Note that Win32AppHelper::doDirectInputEvents() intercepts this key
	// This means that the escape key will NOT reach here
    const CEGUI::KeyEventArgs& keyArgs = static_cast<const CEGUI::KeyEventArgs&>(e);
	if(keyArgs.scancode == CEGUI::Key::Escape)
	{
		return doClose();
	}
	else
		return false;
}

bool WindowSystem::onApply(const CEGUI::EventArgs& e)
{
	// The 'apply' button was pressed
	// Respond by saving the data without closing the window
	return doSave();
}

bool WindowSystem::onModified(const CEGUI::EventArgs& e)
{
	// A widget within the window was modified
	// Respond by enabling the 'apply' button
	CEGUI::WindowManager::getSingleton().getWindow(m_apply)->setEnabled(true);
	return true;
}

WindowingSystemDemo.h

#ifndef _WindowingSystemDemo_h_
#define _WindowingSystemDemo_h_

#include "CEGuiSample.h"
#include "CEGUI.h"
#include "DemoUtils.h"
#include "WindowSystem.h"

class SimpleWindow : public WindowSystem
{
public:
	void initWindow()
	{
		// Initialise the window
		using namespace CEGUI;

		// Initialise the windowing system
		WindowSystem::initialise("winSimpleWindow",	// The handle of this window
									false);			// Initially invisible
													// A modeless window does not have a parent

		// Subscribe to widget events
		// Note that the "close" button is set to behave as an "ok" button
		WindowSystem::bindEvent( "Toolbar_btnSimpleWindow",	PushButton::EventClicked, WindowSystem::open);
		WindowSystem::bindEvent( "SimpleWindow_btnClose",	PushButton::EventClicked, WindowSystem::ok);

		// Subscribe to window events
		WindowSystem::bindEvent("winSimpleWindow", FrameWindow::EventCloseClicked,	WindowSystem::cancel); // The 'X' button was clicked
		WindowSystem::bindEvent("winSimpleWindow", FrameWindow::EventKeyDown,		WindowSystem::escape); // The 'escape' key was pressed
	}
protected:
	bool doLoad()
	{
		// Handle the load action by placing data into widgets
		CEGUI::WindowManager::getSingleton().getWindow("SimpleWindow_edtValue")->setText(dataString);
		return WindowSystem::doLoad(); 
	}
	bool doSave()
	{
		// Handle the save action by moving widget data into variables
		dataString = CEGUI::WindowManager::getSingleton().getWindow("SimpleWindow_edtValue")->getText();
		return WindowSystem::doSave(); 
	}
private:
	CEGUI::String dataString; // Variable associated with the Editbox
};

//////////////////////////////////////////////

class SimpleDialog : public WindowSystem
{
public:
	void initWindow()
	{
		// Initialise the dialog
		using namespace CEGUI;
		WindowManager& winMgr = WindowManager::getSingleton();

		// Initialise the windowing system
		WindowSystem::initialise("dlgSimpleDialog",	// The handle of this window
									false,			// Initially invisible
									"winToolbar");	// The handle of its parent, making it a modal dialog

		// Subscribe to widget events
		WindowSystem::bindEvent( "Toolbar_btnSimpleDialog",	PushButton::EventClicked,	WindowSystem::open);
		WindowSystem::bindEvent( "SimpleDialog_btnOk",		PushButton::EventClicked,	WindowSystem::ok);
		WindowSystem::bindEvent( "SimpleDialog_btnCancel",	PushButton::EventClicked,	WindowSystem::cancel);
		WindowSystem::bindEvent( "SimpleDialog_btnApply",	PushButton::EventClicked,	WindowSystem::apply);

		// These events trigger a 'modified' event, activating the 'apply' button
		WindowSystem::bindEvent( "SimpleDialog_edtValue",		Editbox::EventTextChanged,	WindowSystem::modified);

		// Subscribe to window events
		// Pressing the 'X' button will behave as a cancel
		WindowSystem::bindEvent( "dlgSimpleDialog", FrameWindow::EventCloseClicked,	WindowSystem::cancel); // The 'X' button was clicked
		WindowSystem::bindEvent( "dlgSimpleDialog", FrameWindow::EventKeyDown,		WindowSystem::escape); // The 'escape' key was pressed
	}
protected:
	bool doLoad()
	{
		// Handle the load action by placing data into widgets
		CEGUI::WindowManager::getSingleton().getWindow("SimpleDialog_edtValue")->setText(dataString);
		return WindowSystem::doLoad(); 
	}
	bool doSave()
	{
		// Handle the save action by moving widget data into variables
		dataString = CEGUI::WindowManager::getSingleton().getWindow("SimpleDialog_edtValue")->getText();
		return WindowSystem::doSave(); 
	}
private:
	CEGUI::String dataString;
};

//////////////////////////////////////////

class DemoSample : public CEGuiSample
{
public:
    bool initialiseSample()
	{
		using namespace CEGUI;
		try
		{
			initDemo("../datafiles/layouts/WindowingSystem.layout");

			// Initialise the Simple Window and the Simple Dialog
			simpleWindow.initWindow();
			simpleDialog.initWindow();
		}
		catch(Exception &e)
		{
			ErrorMessage(e.getMessage().c_str(), "Error initializing the demo");
		}

		return true;
	}

    void cleanupSample(void)
	{
	}
private:
	SimpleWindow simpleWindow;
	SimpleDialog simpleDialog;
};

#endif // _WindowingSystemDemo_h_


main.cpp

#if defined( __WIN32__ ) || defined( _WIN32 )
	#define WIN32_LEAN_AND_MEAN
	#define NOMINMAX
	#include "windows.h"
#endif

#include "WindowingSystemDemo.h"


#if defined( __WIN32__ ) || defined( _WIN32 )
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow)
#else
int main(int argc, char *argv[])
#endif
{
    DemoSample app;
    return app.run();
}

WindowingSystem.layout

<?xml version="1.0" encoding="UTF-8"?>
<GUILayout>
<Window Type="DefaultWindow" Name="Root" >
<Property Name="UnifiedAreaRect" Value="{{0.000000,0.000000},{0.000000,0.000000},{1.000000,0.000000},{1.000000,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
<Window Type="TaharezLook/FrameWindow" Name="winToolbar" >
<Property Name="AlwaysOnTop" Value="True" />
<Property Name="CaptionColour" Value="00FFFFFF" />
<Property Name="CloseButtonEnabled" Value="False" />
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
<Property Name="Text" Value="Toolbar" />
<Property Name="TitlebarEnabled" Value="False" />
<Property Name="TitlebarFont" Value="Commonwealth-10" />
<Property Name="UnifiedAreaRect" Value="{{0.248750,0.000000},{0.010001,0.000000},{0.568749,0.000000},{0.081667,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
<Window Type="TaharezLook/Button" Name="Toolbar_btnSimpleWindow" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Simple Window" />
<Property Name="UnifiedAreaRect" Value="{{0.065103,0.000000},{0.227595,0.000000},{0.475554,0.000000},{0.686899,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/Button" Name="Toolbar_btnSimpleDialog" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Simple Dialog" />
<Property Name="UnifiedAreaRect" Value="{{0.538253,0.000000},{0.227595,0.000000},{0.948703,0.000000},{0.686899,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
</Window>
<Window Type="TaharezLook/FrameWindow" Name="winSimpleWindow" >
<Property Name="CaptionColour" Value="00FFFFFF" />
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
<Property Name="Text" Value="Simple Window" />
<Property Name="TitlebarEnabled" Value="True" />
<Property Name="TitlebarFont" Value="Commonwealth-10" />
<Property Name="UnifiedAreaRect" Value="{{0.005000,0.000000},{0.168333,0.000000},{0.420000,0.000000},{0.511666,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
<Window Type="TaharezLook/Button" Name="SimpleWindow_btnClose" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Close" />
<Property Name="UnifiedAreaRect" Value="{{0.688554,0.000000},{0.804855,0.000000},{0.938554,0.000000},{0.943204,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/StaticText" Name="SimpleWindow_lblValue" >
<Property Name="BackgroundImage" Value="set:TaharezLook image:StaticBackdrop" />
<Property Name="BottomFrameImage" Value="set:TaharezLook image:StaticBottom" />
<Property Name="BottomLeftFrameImage" Value="set:TaharezLook image:StaticBottomLeft" />
<Property Name="BottomRightFrameImage" Value="set:TaharezLook image:StaticBottomRight" />
<Property Name="Font" Value="Commonwealth-10" />
<Property Name="LeftFrameImage" Value="set:TaharezLook image:StaticLeft" />
<Property Name="RightFrameImage" Value="set:TaharezLook image:StaticRight" />
<Property Name="Text" Value="Value:" />
<Property Name="TopFrameImage" Value="set:TaharezLook image:StaticTop" />
<Property Name="TopLeftFrameImage" Value="set:TaharezLook image:StaticTopLeft" />
<Property Name="TopRightFrameImage" Value="set:TaharezLook image:StaticTopRight" />
<Property Name="UnifiedAreaRect" Value="{{0.455591,0.000000},{0.430746,0.000000},{0.606068,0.000000},{0.569095,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/Editbox" Name="SimpleWindow_edtValue" >
<Property Name="Font" Value="Commonwealth-10" />
<Property Name="MaxTextLength" Value="1073741823" />
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTextBar" />
<Property Name="UnifiedAreaRect" Value="{{0.618241,0.000000},{0.430746,0.000000},{0.970525,0.000000},{0.569095,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
</Window>
<Window Type="TaharezLook/FrameWindow" Name="dlgSimpleDialog" >
<Property Name="CaptionColour" Value="00FFFFFF" />
<Property Name="EWSizingCursorImage" Value="set:TaharezLook image:MouseEsWeCursor" />
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTarget" />
<Property Name="NESWSizingCursorImage" Value="set:TaharezLook image:MouseNeSwCursor" />
<Property Name="NSSizingCursorImage" Value="set:TaharezLook image:MouseNoSoCursor" />
<Property Name="NWSESizingCursorImage" Value="set:TaharezLook image:MouseNwSeCursor" />
<Property Name="Text" Value="Simple Dialog" />
<Property Name="TitlebarEnabled" Value="True" />
<Property Name="TitlebarFont" Value="Commonwealth-10" />
<Property Name="UnifiedAreaRect" Value="{{0.436250,0.000000},{0.165000,0.000000},{0.916249,0.000000},{0.508333,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnOk" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Ok" />
<Property Name="UnifiedAreaRect" Value="{{0.173754,0.000000},{0.804855,0.000000},{0.423754,0.000000},{0.943204,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnCancel" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Cancel" />
<Property Name="UnifiedAreaRect" Value="{{0.451828,0.000000},{0.804855,0.000000},{0.701828,0.000000},{0.943204,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/Button" Name="SimpleDialog_btnApply" >
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseArrow" />
<Property Name="Text" Value="Apply" />
<Property Name="UnifiedAreaRect" Value="{{0.731230,0.000000},{0.804855,0.000000},{0.981230,0.000000},{0.943204,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/Editbox" Name="SimpleDialog_edtValue" >
<Property Name="Font" Value="Commonwealth-10" />
<Property Name="MaxTextLength" Value="1073741823" />
<Property Name="MouseCursorImage" Value="set:TaharezLook image:MouseTextBar" />
<Property Name="UnifiedAreaRect" Value="{{0.626093,0.000000},{0.418446,0.000000},{0.971449,0.000000},{0.556795,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
<Window Type="TaharezLook/StaticText" Name="SimpleDialog_lblValue" >
<Property Name="BackgroundImage" Value="set:TaharezLook image:StaticBackdrop" />
<Property Name="BottomFrameImage" Value="set:TaharezLook image:StaticBottom" />
<Property Name="BottomLeftFrameImage" Value="set:TaharezLook image:StaticBottomLeft" />
<Property Name="BottomRightFrameImage" Value="set:TaharezLook image:StaticBottomRight" />
<Property Name="LeftFrameImage" Value="set:TaharezLook image:StaticLeft" />
<Property Name="RightFrameImage" Value="set:TaharezLook image:StaticRight" />
<Property Name="Text" Value="Value:" />
<Property Name="TopFrameImage" Value="set:TaharezLook image:StaticTop" />
<Property Name="TopLeftFrameImage" Value="set:TaharezLook image:StaticTopLeft" />
<Property Name="TopRightFrameImage" Value="set:TaharezLook image:StaticTopRight" />
<Property Name="UnifiedAreaRect" Value="{{0.482291,0.000000},{0.418446,0.000000},{0.617709,0.000000},{0.556795,0.000000}}" />
<Property Name="UnifiedMaxSize" Value="{{1.000000,0.000000},{1.000000,0.000000}}" />
</Window>
</Window>
</Window>
</GUILayout>