#include "externals.hh" #include "window.hh" #include "imgui_impl_sdl.h" #include /*= 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 { #include "font-awesome.inl" static const ImWchar IconsRanges_[] = { ICON_MIN_FA , ICON_MAX_FA , 0 }; } // namespace T_Window::T_Window( ) { SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER , 1 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , 24 ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE , 8 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION , 2 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION , 2 ); SDL_DisplayMode current; SDL_GetCurrentDisplayMode( 0 , ¤t ); window = SDL_CreateWindow( "DEMO", SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , 1280 , 720 , SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); gl = SDL_GL_CreateContext( window ); glewInit( ); if ( !GLEW_VERSION_4_5 ) { fprintf( stderr , "OpenGL 4.5 required\n" ); exit( 1 ); } ImGui_ImplSdl_Init( window ); using namespace ImGui; StyleColorsDark( ); ImGuiIO& io{ GetIO( ) }; io.IniFilename = nullptr; { ImFontConfig cfg; cfg.SizePixels = 13.0f; defaultFont_ = io.Fonts->AddFontDefault( &cfg ); ImFontConfig icons; icons.MergeMode = true; icons.PixelSnapH = true; io.Fonts->AddFontFromMemoryCompressedBase85TTF( FontAwesome__compressed_data_base85 , 13.f , &icons , IconsRanges_ ); } { ImFontConfig cfg; cfg.SizePixels = 9.0f; smallFont_ = io.Fonts->AddFontDefault( &cfg ); ImFontConfig icons; icons.MergeMode = true; icons.PixelSnapH = true; icons.DstFont = smallFont_; io.Fonts->AddFontFromMemoryCompressedBase85TTF( FontAwesome__compressed_data_base85 , 9.f , &icons , IconsRanges_ ); } } T_Window::~T_Window( ) { ImGui_ImplSdl_Shutdown( ); SDL_GL_DeleteContext( gl ); SDL_DestroyWindow( window ); SDL_Quit( ); } void T_Window::startFrame( const bool capture , ImVec2 const& mouseInitial ) const { ImGui_ImplSdl_NewFrame( window , capture , mouseInitial ); } void T_Window::warpMouse( ImVec2 const& pos ) const { SDL_WarpMouseInWindow( window , pos.x , pos.y ); } void T_Window::swap( ) const { SDL_GL_SwapWindow( window ); } void T_Window::handleDialogs( ) noexcept { const auto nDialogs{ modals_.size( ) }; for ( auto i = 0u ; i < nDialogs ; i ++ ) { const bool keep{ modals_[ i ]->draw( ) }; assert( keep || i + 1 == nDialogs ); if ( !keep ) { modals_.removeLast( ); } } }