UI - Some refactoring

Basically trying to separate stuff from window.hh
This commit is contained in:
Emmanuel BENOîT 2017-11-23 12:46:48 +01:00
parent da570c14bf
commit 89d125761a
9 changed files with 303 additions and 285 deletions

View file

@ -25,6 +25,7 @@ COMMON = \
\
filewatcher.cc \
window.cc \
dialogs.cc \
globals.cc \
profiling.cc \
shaders.cc \

View file

@ -1,5 +1,5 @@
#pragma once
#include "imousectrl.hh"
#include "mousectrl.hh"
/*= T_Camera =================================================================*/

170
dialogs.cc Normal file
View file

@ -0,0 +1,170 @@
#include "externals.hh"
#include "dialogs.hh"
#include <imgui_internal.h>
/*= A_ModalDialog ============================================================*/
A_ModalDialog::A_ModalDialog(
char const* const id ) noexcept
: id_{ id , uint32_t( strlen( id ) + 1 ) }
{}
A_ModalDialog::A_ModalDialog(
T_String const& id ) noexcept
{
if ( id && id[ id.length( ) - 1 ] == 0 ) {
id_ = ebcl::T_Buffer< char >{ id.data( ) , id.size( ) };
} else {
id_ = id.toOSString( );
}
}
A_ModalDialog::~A_ModalDialog( )
{ }
uint8_t A_ModalDialog::addButton(
char const* name ) noexcept
{
buttons_.addNew( name , strlen( name ) + 1 );
return buttons_.size( ) - 1;
}
uint8_t A_ModalDialog::addButton(
T_String const& name ) noexcept
{
if ( name && name[ name.length( ) - 1 ] == 0 ) {
buttons_.addNew( name.data( ) , name.size( ) );
} else {
buttons_.add( name.toOSString( ) );
}
return buttons_.size( );
}
void A_ModalDialog::initDialog( ) noexcept
{}
bool A_ModalDialog::draw( ) noexcept
{
using namespace ImGui;
if ( !open_ ) {
assert( buttons_.size( ) );
OpenPopup( &id_[ 0 ] );
open_ = true;
}
initDialog( );
if ( initialSize_ ) {
SetNextWindowSize( *initialSize_ , ImGuiCond_Appearing );
}
BeginPopupModal( &id_[ 0 ] , nullptr , ImGuiWindowFlags_NoResize );
const auto btMask{ drawDialog( ) };
assert( btMask != 0 );
const ImVec2 ws( GetWindowContentRegionMax( ) );
auto const& style( GetStyle( ) );
const float innerWidth{ ws.x - 2 * style.FramePadding.x };
const auto nButtons{ buttons_.size( ) };
const ImVec2 buttonSize{
std::max( 40.f , ( innerWidth - nButtons * style.FramePadding.x ) / nButtons ) ,
0.f
};
int32_t clicked{ -1 };
for ( auto i = 0u ; i < buttons_.size( ) ; i ++ ) {
const auto m{ 1 << i };
const bool d{ ( btMask & m ) == 0 };
if ( i ) {
SameLine( 0 );
}
if ( d ) {
PushItemFlag( ImGuiItemFlags_Disabled , true );
PushStyleVar( ImGuiStyleVar_Alpha ,
GetStyle( ).Alpha * .5f );
}
if ( Button( &buttons_[ i ][ 0 ] , buttonSize ) ) {
assert( clicked == -1 );
clicked = i;
}
if ( d ) {
PopItemFlag( );
PopStyleVar( );
}
}
const bool close( clicked != -1 && onButton( clicked ) );
if ( close ) {
CloseCurrentPopup( );
}
EndPopup( );
return !close;
}
/*= T_MessageBox =============================================================*/
void T_MessageBox::setButtons(
const T_Buttons buttons ) noexcept
{
assert( buttons );
for ( auto i = 0u , nb = 0u ; i < 4 ; i ++ ) {
const E_Button b{ (E_Button) i };
const bool hasButton{ buttons & T_Buttons{ b } };
if ( !hasButton ) {
continue;
}
buttonMask_ |= ( 1 << nb );
nb ++;
buttons_.add( b );
switch ( b ) {
case BT_OK: addButton( "OK" ); break;
case BT_CANCEL: addButton( "Cancel" ); break;
case BT_YES: addButton( "Yes" ); break;
case BT_NO: addButton( "No" ); break;
}
}
}
T_MessageBox::T_MessageBox(
char const* const title ,
char const* const text ,
F_Handler handler ,
const T_Buttons buttons ) noexcept
: A_ModalDialog( title ) , text_{ text , strlen( text ) + 1 } ,
handler_{ std::move( handler ) }
{
setButtons( buttons );
setInitialSize( 300.f , 100.f );
}
T_MessageBox::T_MessageBox(
T_String const& title ,
T_String const& text ,
F_Handler handler ,
const T_Buttons buttons ) noexcept
: A_ModalDialog( title ) , handler_{ std::move( handler ) }
{
if ( text && text[ text.length( ) - 1 ] == 0 ) {
text_ = ebcl::T_Buffer< char >{ text.data( ) , text.size( ) };
} else {
text_ = text.toOSString( );
}
setButtons( buttons );
setInitialSize( 300.f , 100.f );
}
uint8_t T_MessageBox::drawDialog( ) noexcept
{
ImGui::TextWrapped( "%s" , &text_[ 0 ] );
return buttonMask_;
}
bool T_MessageBox::onButton(
uint8_t button ) noexcept
{
assert( button < buttons_.size( ) );
if ( handler_ ) {
handler_( buttons_[ button ] );
}
return true;
}

91
dialogs.hh Normal file
View file

@ -0,0 +1,91 @@
#pragma once
#ifndef REAL_BUILD
# include "externals.hh"
#endif
/*= DIALOGS ==================================================================*/
// Base class for a modal dialog that can be pushed to the window's modal
// stack.
class A_ModalDialog
{
private:
ebcl::T_Buffer< char > id_;
bool open_{ false };
T_Optional< ImVec2 > initialSize_;
T_StaticArray< ebcl::T_Buffer< char > , 4 > buttons_;
protected:
A_ModalDialog( char const* id ) noexcept;
A_ModalDialog( T_String const& id ) noexcept;
void setInitialSize( const float width ,
const float height ) noexcept
{ initialSize_.setNew( width , height ); }
// Add a button w/ the specified name, return its identifier
uint8_t addButton( char const* name ) noexcept;
uint8_t addButton( T_String const& name ) noexcept;
// Initialisation, called right before the window is opened.
// Does nothing by default.
virtual void initDialog( ) noexcept;
// Draw the dialog box's contents, returns a mask that determines
// which buttons should be enabled.
virtual uint8_t drawDialog( ) noexcept = 0;
// Button click handler. Returns true if the dialog should be
// closed.
virtual bool onButton( uint8_t button ) noexcept = 0;
public:
NO_COPY( A_ModalDialog );
NO_MOVE( A_ModalDialog );
virtual ~A_ModalDialog( );
// Draw and handle the dialog box. Returns true if it must be kept,
// or false if it must be removed from the stack.
bool draw( ) noexcept;
};
using P_ModalDialog = T_OwnPtr< A_ModalDialog >;
// Simple modal message box with configurable buttons
class T_MessageBox : public A_ModalDialog
{
public:
enum E_Button {
BT_OK ,
BT_CANCEL ,
BT_YES ,
BT_NO ,
};
using T_Buttons = T_Flags< E_Button >;
// Result handler
using F_Handler = std::function< void( E_Button ) >;
private:
ebcl::T_Buffer< char > text_;
F_Handler handler_;
uint8_t buttonMask_{ 0 };
T_StaticArray< E_Button , 4 > buttons_;
void setButtons( T_Buttons buttons ) noexcept;
protected:
uint8_t drawDialog( ) noexcept override;
bool onButton( uint8_t button ) noexcept override;
public:
T_MessageBox( char const* title ,
char const* text ,
F_Handler handler = { } ,
T_Buttons buttons = BT_OK ) noexcept;
T_MessageBox( T_String const& title ,
T_String const& text ,
F_Handler handler = { } ,
T_Buttons buttons = BT_OK ) noexcept;
};

View file

@ -1,30 +1,9 @@
#pragma once
#ifndef REAL_BUILD
# include "externals.hh"
#endif
#include "ui-input.hh"
/*= MOUSE CONTROLS INTERFACE ===================================================*/
enum class E_MouseButton {
LEFT ,
MIDDLE ,
RIGHT ,
};
using T_MouseButtons = T_Flags< E_MouseButton >;
/*------------------------------------------------------------------------------*/
enum class E_KeyboardModifier
{
CTRL ,
SHIFT ,
ALT ,
};
using T_KeyboardModifiers = T_Flags< E_KeyboardModifier >;
/*------------------------------------------------------------------------------*/
class A_MouseCtrl
{
public:

View file

@ -1,7 +1,7 @@
#pragma once
#include "filewatcher.hh"
#include "utilities.hh"
#include "imousectrl.hh"
#include "mousectrl.hh"
#include <ebcl/SRDParserConfig.hh>
#include <ebcl/Sets.hh>

22
ui-input.hh Normal file
View file

@ -0,0 +1,22 @@
#pragma once
#ifndef REAL_BUILD
# include "externals.hh"
#endif
enum class E_MouseButton {
LEFT ,
MIDDLE ,
RIGHT ,
};
using T_MouseButtons = T_Flags< E_MouseButton >;
/*------------------------------------------------------------------------------*/
enum class E_KeyboardModifier
{
CTRL ,
SHIFT ,
ALT ,
};
using T_KeyboardModifiers = T_Flags< E_KeyboardModifier >;

167
window.cc
View file

@ -4,173 +4,6 @@
#include <imgui_internal.h>
/*= A_ModalDialog ============================================================*/
A_ModalDialog::A_ModalDialog(
char const* const id ) noexcept
: id_{ id , uint32_t( strlen( id ) + 1 ) }
{}
A_ModalDialog::A_ModalDialog(
T_String const& id ) noexcept
{
if ( id && id[ id.length( ) - 1 ] == 0 ) {
id_ = ebcl::T_Buffer< char >{ id.data( ) , id.size( ) };
} else {
id_ = id.toOSString( );
}
}
A_ModalDialog::~A_ModalDialog( )
{ }
uint8_t A_ModalDialog::addButton(
char const* name ) noexcept
{
buttons_.addNew( name , strlen( name ) + 1 );
return buttons_.size( ) - 1;
}
uint8_t A_ModalDialog::addButton(
T_String const& name ) noexcept
{
if ( name && name[ name.length( ) - 1 ] == 0 ) {
buttons_.addNew( name.data( ) , name.size( ) );
} else {
buttons_.add( name.toOSString( ) );
}
return buttons_.size( );
}
void A_ModalDialog::initDialog( ) noexcept
{}
bool A_ModalDialog::draw( ) noexcept
{
using namespace ImGui;
if ( !open_ ) {
assert( buttons_.size( ) );
OpenPopup( &id_[ 0 ] );
open_ = true;
}
initDialog( );
if ( initialSize_ ) {
SetNextWindowSize( *initialSize_ , ImGuiCond_Appearing );
}
BeginPopupModal( &id_[ 0 ] , nullptr , ImGuiWindowFlags_NoResize );
const auto btMask{ drawDialog( ) };
assert( btMask != 0 );
const ImVec2 ws( GetWindowContentRegionMax( ) );
auto const& style( GetStyle( ) );
const float innerWidth{ ws.x - 2 * style.FramePadding.x };
const auto nButtons{ buttons_.size( ) };
const ImVec2 buttonSize{
std::max( 40.f , ( innerWidth - nButtons * style.FramePadding.x ) / nButtons ) ,
0.f
};
int32_t clicked{ -1 };
for ( auto i = 0u ; i < buttons_.size( ) ; i ++ ) {
const auto m{ 1 << i };
const bool d{ ( btMask & m ) == 0 };
if ( i ) {
SameLine( 0 );
}
if ( d ) {
PushItemFlag( ImGuiItemFlags_Disabled , true );
PushStyleVar( ImGuiStyleVar_Alpha ,
GetStyle( ).Alpha * .5f );
}
if ( Button( &buttons_[ i ][ 0 ] , buttonSize ) ) {
assert( clicked == -1 );
clicked = i;
}
if ( d ) {
PopItemFlag( );
PopStyleVar( );
}
}
const bool close( clicked != -1 && onButton( clicked ) );
if ( close ) {
CloseCurrentPopup( );
}
EndPopup( );
return !close;
}
/*= T_MessageBox =============================================================*/
void T_MessageBox::setButtons(
const T_Buttons buttons ) noexcept
{
assert( buttons );
for ( auto i = 0u , nb = 0u ; i < 4 ; i ++ ) {
const E_Button b{ (E_Button) i };
const bool hasButton{ buttons & T_Buttons{ b } };
if ( !hasButton ) {
continue;
}
buttonMask_ |= ( 1 << nb );
nb ++;
buttons_.add( b );
switch ( b ) {
case BT_OK: addButton( "OK" ); break;
case BT_CANCEL: addButton( "Cancel" ); break;
case BT_YES: addButton( "Yes" ); break;
case BT_NO: addButton( "No" ); break;
}
}
}
T_MessageBox::T_MessageBox(
char const* const title ,
char const* const text ,
F_Handler handler ,
const T_Buttons buttons ) noexcept
: A_ModalDialog( title ) , text_{ text , strlen( text ) + 1 } ,
handler_{ std::move( handler ) }
{
setButtons( buttons );
setInitialSize( 300.f , 100.f );
}
T_MessageBox::T_MessageBox(
T_String const& title ,
T_String const& text ,
F_Handler handler ,
const T_Buttons buttons ) noexcept
: A_ModalDialog( title ) , handler_{ std::move( handler ) }
{
if ( text && text[ text.length( ) - 1 ] == 0 ) {
text_ = ebcl::T_Buffer< char >{ text.data( ) , text.size( ) };
} else {
text_ = text.toOSString( );
}
setButtons( buttons );
setInitialSize( 300.f , 100.f );
}
uint8_t T_MessageBox::drawDialog( ) noexcept
{
ImGui::TextWrapped( "%s" , &text_[ 0 ] );
return buttonMask_;
}
bool T_MessageBox::onButton(
uint8_t button ) noexcept
{
assert( button < buttons_.size( ) );
if ( handler_ ) {
handler_( buttons_[ button ] );
}
return true;
}
/*= T_Window =================================================================*/
namespace {

110
window.hh
View file

@ -1,103 +1,16 @@
#pragma once
#ifndef REAL_BUILD
# include "externals.hh"
#endif
#include "dialogs.hh"
#include "mousectrl.hh"
// Base class for a modal dialog that can be pushed to the window's modal
// stack.
class A_ModalDialog
{
private:
ebcl::T_Buffer< char > id_;
bool open_{ false };
T_Optional< ImVec2 > initialSize_;
T_StaticArray< ebcl::T_Buffer< char > , 4 > buttons_;
protected:
A_ModalDialog( char const* id ) noexcept;
A_ModalDialog( T_String const& id ) noexcept;
void setInitialSize( const float width ,
const float height ) noexcept
{ initialSize_.setNew( width , height ); }
// Add a button w/ the specified name, return its identifier
uint8_t addButton( char const* name ) noexcept;
uint8_t addButton( T_String const& name ) noexcept;
// Initialisation, called right before the window is opened.
// Does nothing by default.
virtual void initDialog( ) noexcept;
// Draw the dialog box's contents, returns a mask that determines
// which buttons should be enabled.
virtual uint8_t drawDialog( ) noexcept = 0;
// Button click handler. Returns true if the dialog should be
// closed.
virtual bool onButton( uint8_t button ) noexcept = 0;
public:
NO_COPY( A_ModalDialog );
NO_MOVE( A_ModalDialog );
virtual ~A_ModalDialog( );
// Draw and handle the dialog box. Returns true if it must be kept,
// or false if it must be removed from the stack.
bool draw( ) noexcept;
};
using P_ModalDialog = T_OwnPtr< A_ModalDialog >;
class T_MessageBox : public A_ModalDialog
{
public:
enum E_Button {
BT_OK ,
BT_CANCEL ,
BT_YES ,
BT_NO ,
};
using T_Buttons = T_Flags< E_Button >;
// Result handler
using F_Handler = std::function< void( E_Button ) >;
private:
ebcl::T_Buffer< char > text_;
F_Handler handler_;
uint8_t buttonMask_{ 0 };
T_StaticArray< E_Button , 4 > buttons_;
void setButtons( T_Buttons buttons ) noexcept;
protected:
uint8_t drawDialog( ) noexcept override;
bool onButton( uint8_t button ) noexcept override;
public:
T_MessageBox( char const* title ,
char const* text ,
F_Handler handler = { } ,
T_Buttons buttons = BT_OK ) noexcept;
T_MessageBox( T_String const& title ,
T_String const& text ,
F_Handler handler = { } ,
T_Buttons buttons = BT_OK ) noexcept;
};
/*= WINDOW MANAGEMENT ========================================================*/
struct T_Window
{
T_Window( );
~T_Window( );
void startFrame( const bool capture ,
ImVec2 const& mouseInitial ) const;
void warpMouse( ImVec2 const& pos ) const;
void swap( ) const;
//----------------------------------------------------------------------
void pushDialog( P_ModalDialog dialog ) noexcept
{ modals_.add( std::move( dialog ) ); }
@ -106,20 +19,29 @@ struct T_Window
char const* text ,
T_MessageBox::F_Handler handler = { } ,
T_MessageBox::T_Buttons buttons = T_MessageBox::BT_OK )
{ modals_.add( NewOwned< T_MessageBox >( title , text , handler , buttons ) ); }
{ pushDialog( NewOwned< T_MessageBox >( title , text , handler , buttons ) ); }
void msgbox( T_String const& title ,
T_String const& text ,
T_MessageBox::F_Handler handler = { } ,
T_MessageBox::T_Buttons buttons = T_MessageBox::BT_OK )
{ modals_.add( NewOwned< T_MessageBox >( title , text , handler , buttons ) ); }
{ pushDialog( NewOwned< T_MessageBox >( title , text , handler , buttons ) ); }
void handleDialogs( ) noexcept;
//----------------------------------------------------------------------
ImFont* defaultFont( ) const noexcept
{ return defaultFont_; }
ImFont* smallFont( ) const noexcept
{ return smallFont_; }
//----------------------------------------------------------------------
void startFrame( const bool capture ,
ImVec2 const& mouseInitial ) const;
void warpMouse( ImVec2 const& pos ) const;
void swap( ) const;
void handleDialogs( ) noexcept;
private:
SDL_Window * window;
SDL_GLContext gl;