Skip to content

ListBox widget #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ set(
"${INCLUDE_PATH}/SFGUI/Frame.hpp"
"${INCLUDE_PATH}/SFGUI/Image.hpp"
"${INCLUDE_PATH}/SFGUI/Label.hpp"
"${INCLUDE_PATH}/SFGUI/ListBox.hpp"
"${INCLUDE_PATH}/SFGUI/Misc.hpp"
"${INCLUDE_PATH}/SFGUI/Notebook.hpp"
"${INCLUDE_PATH}/SFGUI/Object.hpp"
Expand Down Expand Up @@ -115,6 +116,7 @@ set(
"${SOURCE_PATH}/SFGUI/Engines/BREW/Frame.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/Image.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/Label.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/ListBox.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/Notebook.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/ProgressBar.cpp"
"${SOURCE_PATH}/SFGUI/Engines/BREW/Scale.cpp"
Expand All @@ -135,6 +137,7 @@ set(
"${SOURCE_PATH}/SFGUI/GLLoader.hpp"
"${SOURCE_PATH}/SFGUI/Image.cpp"
"${SOURCE_PATH}/SFGUI/Label.cpp"
"${SOURCE_PATH}/SFGUI/ListBox.cpp"
"${SOURCE_PATH}/SFGUI/Misc.cpp"
"${SOURCE_PATH}/SFGUI/Notebook.cpp"
"${SOURCE_PATH}/SFGUI/Object.cpp"
Expand Down Expand Up @@ -267,7 +270,7 @@ elseif( APPLE )
elseif( "${CMAKE_SYSTEM_NAME}" MATCHES "Linux" )
target_link_libraries( sfgui ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${OPENGL_gl_LIBRARY} ${X11_LIBRARIES} )
set( SHARE_PATH "${CMAKE_INSTALL_PREFIX}/share/SFGUI" )

if( LIB_SUFFIX )
set( LIB_PATH "lib${LIB_SUFFIX}" )
else()
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ build_example( "ProgressBar" "ProgressBar.cpp" )
build_example( "SpinButton" "SpinButton.cpp" )
build_example( "Canvas" "Canvas.cpp" )
build_example( "CustomWidget" "CustomWidget.cpp" )
build_example( "ListBox" "ListBox.cpp" )
build_example( "SFGUI-Test" "Test.cpp" )

# Copy data directory to build cache directory to be able to run examples from
Expand Down
130 changes: 130 additions & 0 deletions examples/ListBox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Always include the necessary header files.
// Including SFGUI/Widgets.hpp includes everything
// you can possibly need automatically.
#include <SFGUI/SFGUI.hpp>
#include <SFGUI/Widgets.hpp>

#include <SFML/Graphics.hpp>

int main() {
sfg::SFGUI sfgui;
sf::RenderWindow window(sf::VideoMode(800, 600), "ListBox Example");
window.setVerticalSyncEnabled(true);
window.setFramerateLimit(30);

sfg::Desktop desktop;

auto window1 = sfg::Window::Create();
window1->SetTitle( "ListBox with ItemTextPolicy::RESIZE_LISTBOX" );

auto box1 = sfg::Box::Create( sfg::Box::Orientation::VERTICAL );
box1->SetSpacing( 5.f );
box1->PackEnd( sfg::Label::Create( "The minimum width\nof this ListBox\ncorresponds to the largest\nitem's text width." ), false, true );

auto listbox1 = sfg::ListBox::Create();
listbox1->AppendItem( "This is the first item" );
listbox1->AppendItem( "Second item" );
listbox1->AppendItem( "Third item which is a bit large" );
listbox1->AppendItem( "Fourth item" );
listbox1->AppendItem( "Fifth item" );
listbox1->AppendItem( "Sixth item" );
listbox1->AppendItem( "Last one !" );
box1->PackEnd( listbox1 );

window1->Add( box1 );

auto window2 = sfg::Window::Create();
window2->SetTitle( "ListBox with ItemTextPolicy::SHRINK" );

auto box2 = sfg::Box::Create( sfg::Box::Orientation::VERTICAL );
box2->SetSpacing( 5.f );
auto label2 = sfg::Label::Create( "The items' texts\nare shrinked if the\nListBox is not big\nenough." );
box2->PackEnd( label2, false, true );

auto listbox2 = sfg::ListBox::Create();
listbox2->AppendItem( "This is the first item (long text)" );
listbox2->AppendItem( "Second item" );
listbox2->AppendItem( "Third item which is very long !" );
listbox2->AppendItem( "Fourth item" );
listbox2->AppendItem( "Fifth item" );
listbox2->AppendItem( "Sixth item, again it's too large !" );
listbox2->AppendItem( "Last one !" );
listbox2->SetItemTextPolicy( sfg::ListBox::ItemTextPolicy::SHRINK );
box2->PackEnd( listbox2 );

window2->Add( box2 );

auto window3 = sfg::Window::Create();
window3->SetTitle( "ListBox with ItemTextPolicy::SHRINK" );

auto box3 = sfg::Box::Create( sfg::Box::Orientation::VERTICAL );
box3->SetSpacing( 5.f );
auto label3 = sfg::Label::Create( "You can select multiple\nitems in this ListBox." );
box3->PackEnd( label3, false, true );

auto listbox3 = sfg::ListBox::Create();
listbox3->AppendItem( "First item" );
listbox3->AppendItem( "Second item" );
listbox3->AppendItem( "Third item" );
listbox3->AppendItem( "Fourth item" );
listbox3->AppendItem( "Fifth item" );
listbox3->AppendItem( "Sixth item" );
listbox3->AppendItem( "Last one !" );
listbox3->SetSelectionMode( sfg::ListBox::SelectionMode::MULTI_SELECTION );
listbox3->SetSelection( {1, 3, 4, 5} );
box3->PackEnd( listbox3 );

window3->Add( box3 );

desktop.Add( window1 );
desktop.Add( window2 );
desktop.Add( window3 );

sf::Vector2f windowSize( static_cast<float>( window.getSize().x ), static_cast<float>( window.getSize().y ) );

window2->SetPosition(sf::Vector2f(windowSize.x/2.f - window2->GetRequisition().x/2.f, windowSize.y/2.f - window2->GetRequisition().y/2.f));
window3->SetPosition(sf::Vector2f(windowSize.x - window3->GetRequisition().x - 100.f, windowSize.y - window3->GetRequisition().y - 100.f));

sf::Event event;
sf::Clock clock;

window.resetGLStates();

int i = 0;

while (window.isOpen())
{
while (window.pollEvent(event))
{
desktop.HandleEvent( event );
switch(event.type)
{
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyPressed:
if( event.key.code == sf::Keyboard::R ) {
listbox3->RemoveItem(2);
} else if( event.key.code == sf::Keyboard::I ) {
listbox3->InsertItem(3, "Inserted item #" + std::to_string(i));
++i;
} else if( event.key.code == sf::Keyboard::A) {
listbox3->AppendItem("Appended item #" + std::to_string(i));
++i;
} else if( event.key.code == sf::Keyboard::P) {
listbox3->PrependItem("Prepended item #" + std::to_string(i));
++i;
}
break;
default:
break;
}
}
desktop.Update( clock.restart().asSeconds() );
window.clear();
sfgui.Display( window );
window.display();
}

return 0;
}
7 changes: 7 additions & 0 deletions include/SFGUI/Engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Notebook;
class Spinner;
class ComboBox;
class SpinButton;
class ListBox;

class Selector;
class RenderQueue;
Expand Down Expand Up @@ -164,6 +165,12 @@ class SFGUI_API Engine {
*/
virtual std::unique_ptr<RenderQueue> CreateSpinButtonDrawable( std::shared_ptr<const SpinButton> spinbutton ) const = 0;

/** Create drawable for listbox widgets.
* @param listbox Widget.
* @return New drawable object (unmanaged memory!).
*/
virtual std::unique_ptr<RenderQueue> CreateListBoxDrawable( std::shared_ptr<const ListBox> listbox ) const = 0;

/** Get maximum line height.
* @param font Font.
* @param font_size Font size.
Expand Down
1 change: 1 addition & 0 deletions include/SFGUI/Engines/BREW.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class SFGUI_API BREW : public Engine {
std::unique_ptr<RenderQueue> CreateSpinnerDrawable( std::shared_ptr<const Spinner> spinner ) const override;
std::unique_ptr<RenderQueue> CreateComboBoxDrawable( std::shared_ptr<const ComboBox> combo_box ) const override;
std::unique_ptr<RenderQueue> CreateSpinButtonDrawable( std::shared_ptr<const SpinButton> spinbutton ) const override;
std::unique_ptr<RenderQueue> CreateListBoxDrawable( std::shared_ptr<const ListBox> listbox ) const override;

private:
static std::unique_ptr<RenderQueue> CreateBorder( const sf::FloatRect& rect, float border_width, const sf::Color& light_color, const sf::Color& dark_color );
Expand Down
136 changes: 136 additions & 0 deletions include/SFGUI/ListBox.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#pragma once

#include <SFGUI/Container.hpp>
#include <SFGUI/Scrollbar.hpp>

#include <SFML/System/String.hpp>

#include <initializer_list>
#include <memory>
#include <set>
#include <vector>

namespace sfg {

class SFGUI_API ListBox : public Container {
public:
typedef std::shared_ptr<ListBox> Ptr; //!< Shared pointer.
typedef std::shared_ptr<const ListBox> PtrConst; //!< Shared pointer.
typedef int IndexType;

static const IndexType NONE;

enum class SelectionMode : char {
NO_SELECTION,
SINGLE_SELECTION,
MULTI_SELECTION,
DEFAULT = SINGLE_SELECTION
};

enum class ScrollbarPolicy : char {
VERTICAL_ALWAYS,
VERTICAL_AUTOMATIC,
VERTICAL_NEVER,
DEFAULT = VERTICAL_AUTOMATIC
};

enum class ItemTextPolicy : char {
RESIZE_LISTBOX,
SHRINK,
DEFAULT = RESIZE_LISTBOX
};

/** Create listbox.
* @return ListBox.
*/
static Ptr Create( );

const std::string& GetName() const override;

void AppendItem( const sf::String& str );
void InsertItem( IndexType index, const sf::String& str );
void PrependItem( const sf::String& str );
void ChangeItem( IndexType index, const sf::String& str );
void RemoveItem( IndexType index );
void Clear();

IndexType GetItemsCount() const;
const sf::String& GetItemText( IndexType index ) const;
const sf::String& GetDisplayedItemText( IndexType index ) const;

IndexType GetHighlightedItem() const;

void SetSelection( IndexType index );
void SetSelection( std::initializer_list<IndexType> indices );
void AppendToSelection( IndexType index );
void RemoveFromSelection( IndexType index );
void ClearSelection();

bool IsItemSelected( IndexType index ) const;
IndexType GetSelectedItemsCount() const;
IndexType GetSelectedItemIndex( IndexType index = 0 ) const;
const sf::String& GetSelectedItemText( IndexType index = 0 ) const;

IndexType GetFirstDisplayedItemIndex() const;
IndexType GetDisplayedItemsCount() const;
IndexType GetMaxDisplayedItemsCount() const;

SelectionMode GetSelectionMode() const;
void SetSelectionMode( SelectionMode mode );

ScrollbarPolicy GetScrollbarPolicy() const;
void SetScrollbarPolicy( ScrollbarPolicy policy );

ItemTextPolicy GetItemTextPolicy() const;
void SetItemTextPolicy( ItemTextPolicy policy );

// Signals.
static Signal::SignalID OnSelect; //!< Fired when an entry is selected.

protected:
/** Ctor.
*/
ListBox();

std::unique_ptr<RenderQueue> InvalidateImpl() const override;
sf::Vector2f CalculateRequisition() override;

private:
void HandleMouseEnter( int x, int y ) override;
void HandleMouseLeave( int x, int y ) override;
void HandleMouseMoveEvent( int x, int y ) override;
void HandleMouseButtonEvent( sf::Mouse::Button button, bool press, int x, int y ) override;
void HandleSizeChange() override;
bool HandleAdd( Widget::Ptr ) override;
void HandleRemove( Widget::Ptr ) override;

IndexType GetItemAt( float y ) const;

bool IsScrollbarVisible() const;

void UpdateDisplayedItems();
void UpdateScrollbarAdjustment();
void UpdateScrollbarAllocation();

void UpdateDisplayedItemsText();

void OnScrollbarChanged();

std::vector<sf::String> m_items;

SelectionMode m_selection_mode;
std::set<IndexType> m_selected_items;

IndexType m_highlighted_item;

IndexType m_first_displayed_item;
IndexType m_max_displayed_items_count;

Scrollbar::Ptr m_vertical_scrollbar;
ScrollbarPolicy m_scrollbar_policy;

ItemTextPolicy m_item_text_policy;
std::vector<sf::String> m_displayed_items_texts;
};

}
1 change: 1 addition & 0 deletions include/SFGUI/Widgets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <SFGUI/Frame.hpp>
#include <SFGUI/Image.hpp>
#include <SFGUI/Label.hpp>
#include <SFGUI/ListBox.hpp>
#include <SFGUI/Notebook.hpp>
#include <SFGUI/ProgressBar.hpp>
#include <SFGUI/RadioButton.hpp>
Expand Down
6 changes: 6 additions & 0 deletions src/SFGUI/Engines/BREW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ void BREW::ResetProperties() {
SetProperty( "SpinButton", "StepperSpeed", 10.f );
SetProperty( "SpinButton", "StepperRepeatDelay", 500 );

// ListBox-specific.
SetProperty( "ListBox", "BackgroundColor", sf::Color( 0x5e, 0x5e, 0x5e ) );
SetProperty( "ListBox", "Color", sf::Color::White );
SetProperty( "ListBox", "HighlightedColor", sf::Color( 0x65, 0x67, 0x62 ) );
SetProperty( "ListBox", "SelectedColor", sf::Color( 0x5a, 0x6a, 0x50 ) );

// (Re)Enable automatic widget refreshing after we are done setting all these properties.
SetAutoRefresh( true );
}
Expand Down
Loading