| 65 | } |
| 66 | |
| 67 | int main() { |
| 68 | sf::RenderWindow app_window( sf::VideoMode( { 800, 600 } ), "SFGUI Button Example", sf::Style::Titlebar | sf::Style::Close ); |
| 69 | |
| 70 | // Create an SFGUI. This is required before doing anything with SFGUI. |
| 71 | sfg::SFGUI sfgui; |
| 72 | |
| 73 | // We have to do this because we don't use SFML to draw. |
| 74 | app_window.resetGLStates(); |
| 75 | |
| 76 | window = sfg::Window::Create(); |
| 77 | window->SetTitle( "Title" ); |
| 78 | |
| 79 | auto box = sfg::Box::Create( sfg::Box::Orientation::VERTICAL ); |
| 80 | window->Add( box ); |
| 81 | |
| 82 | // Possibility 1, normal function |
| 83 | auto button1 = sfg::Button::Create(); |
| 84 | button1->SetLabel( "Clicky 1" ); |
| 85 | button1->GetSignal( sfg::Widget::OnLeftClick ).Connect( &Foo ); |
| 86 | box->Pack( button1, false ); |
| 87 | |
| 88 | // Possibility 2, lambda function |
| 89 | auto button2 = sfg::Button::Create(); |
| 90 | button2->SetLabel( "Clicky 2" ); |
| 91 | button2->GetSignal( sfg::Widget::OnLeftClick ).Connect( [] { window->SetTitle( "Bar" ); } ); |
| 92 | box->Pack( button2, false ); |
| 93 | |
| 94 | // Possibility 3, objects |
| 95 | BazClass baz_array[3] = { BazClass( 1 ), BazClass( 2 ), BazClass( 3 ) }; |
| 96 | |
| 97 | for( int i = 0; i < 3; i++ ) { |
| 98 | std::stringstream sstr; |
| 99 | sstr << "Clicky " << i + 3; |
| 100 | auto button = sfg::Button::Create(); |
| 101 | button->SetLabel( sstr.str() ); |
| 102 | // This is just a more complicated way of passing a pointer to a |
| 103 | // BazClass to Connect() when the BazClass object is part of an array. |
| 104 | // Passing normal pointers such as &baz1 would also work. |
| 105 | button->GetSignal( sfg::Widget::OnLeftClick ).Connect( [&baz_array, i] { baz_array[i].Baz(); } ); |
| 106 | box->Pack( button, false ); |
| 107 | } |
| 108 | |
| 109 | // Notice that with possibility 3 you can do very advanced things. The tricky |
| 110 | // part of implementing it this way is that the method address has to be |
| 111 | // known at compile time, which means that only the instanciated object itself |
| 112 | // is able to pick how it will behave when that method is called on it. This |
| 113 | // way you can also connect signals to dynamically determined behavior. |
| 114 | |
| 115 | // For further reading on this topic refer to Design Patterns and as |
| 116 | // specialized cases similar to the one in this example the |
| 117 | // Factory Method Pattern and Abstract Factory Pattern. |
| 118 | |
| 119 | while ( app_window.isOpen() ) { |
| 120 | while ( const std::optional event = app_window.pollEvent() ) { |
| 121 | window->HandleEvent( *event ); |
| 122 | |
| 123 | if ( event->is<sf::Event::Closed>() ) { |
| 124 | return EXIT_SUCCESS; |
nothing calls this directly
no test coverage detected