mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 01:59:14 +03:00
ModelGallery: Add the new Model Gallery application :^)
This is an application analogous to WidgetGallery, in that it tests various capabilities of LibGUI models. Right now it is pretty bare, but as more work towards LibGUI models is done regarding persistent model indices, more demos will be added.
This commit is contained in:
parent
a8967388d3
commit
b30b7de2d2
Notes:
sideshowbarker
2024-07-18 05:21:07 +09:00
Author: https://github.com/sin-ack Commit: https://github.com/SerenityOS/serenity/commit/b30b7de2d2d Pull-request: https://github.com/SerenityOS/serenity/pull/9503 Reviewed-by: https://github.com/awesomekling
4
Base/res/apps/ModelGallery.af
Normal file
4
Base/res/apps/ModelGallery.af
Normal file
@ -0,0 +1,4 @@
|
||||
[App]
|
||||
Name=Model Gallery
|
||||
Executable=/bin/ModelGallery
|
||||
Category=Demos
|
BIN
Base/res/icons/16x16/app-model-gallery.png
Normal file
BIN
Base/res/icons/16x16/app-model-gallery.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 694 B |
BIN
Base/res/icons/32x32/app-model-gallery.png
Normal file
BIN
Base/res/icons/32x32/app-model-gallery.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 740 B |
@ -5,6 +5,7 @@ add_subdirectory(Fire)
|
||||
add_subdirectory(LibGfxDemo)
|
||||
add_subdirectory(LibGfxScaleDemo)
|
||||
add_subdirectory(Mandelbrot)
|
||||
add_subdirectory(ModelGallery)
|
||||
add_subdirectory(Mouse)
|
||||
add_subdirectory(Screensaver)
|
||||
add_subdirectory(Starfield)
|
||||
|
68
Userland/Demos/ModelGallery/BasicModel.cpp
Normal file
68
Userland/Demos/ModelGallery/BasicModel.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "BasicModel.h"
|
||||
|
||||
GUI::Variant BasicModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const
|
||||
{
|
||||
if (role != GUI::ModelRole::Display)
|
||||
return {};
|
||||
if (!is_within_range(index))
|
||||
return {};
|
||||
|
||||
return m_items.at(index.row());
|
||||
}
|
||||
|
||||
TriState BasicModel::data_matches(GUI::ModelIndex const& index, GUI::Variant const& data) const
|
||||
{
|
||||
if (!is_within_range(index))
|
||||
return TriState::False;
|
||||
if (!data.is_string())
|
||||
return TriState::False;
|
||||
|
||||
auto& value = m_items.at(index.row());
|
||||
return value.contains(data.as_string()) ? TriState::True : TriState::False;
|
||||
}
|
||||
|
||||
void BasicModel::invalidate()
|
||||
{
|
||||
Model::invalidate();
|
||||
if (on_invalidate)
|
||||
on_invalidate();
|
||||
}
|
||||
|
||||
GUI::ModelIndex BasicModel::index(int row, int column, GUI::ModelIndex const& parent) const
|
||||
{
|
||||
if (column != 0)
|
||||
return {};
|
||||
if (parent.is_valid())
|
||||
return {};
|
||||
if (row < 0 || row >= static_cast<int>(m_items.size()))
|
||||
return {};
|
||||
|
||||
return create_index(row, column);
|
||||
}
|
||||
|
||||
void BasicModel::add_item(String const& item)
|
||||
{
|
||||
begin_insert_rows({}, m_items.size(), m_items.size());
|
||||
m_items.append(item);
|
||||
end_insert_rows();
|
||||
|
||||
did_update(UpdateFlag::DontInvalidateIndices);
|
||||
}
|
||||
|
||||
void BasicModel::remove_item(GUI::ModelIndex const& index)
|
||||
{
|
||||
if (!index.is_valid() || !is_within_range(index))
|
||||
return;
|
||||
|
||||
begin_delete_rows({}, index.row(), index.row());
|
||||
m_items.remove(index.row());
|
||||
end_delete_rows();
|
||||
|
||||
did_update(UpdateFlag::DontInvalidateIndices);
|
||||
}
|
41
Userland/Demos/ModelGallery/BasicModel.h
Normal file
41
Userland/Demos/ModelGallery/BasicModel.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGUI/Model.h>
|
||||
|
||||
class BasicModel final : public GUI::Model {
|
||||
public:
|
||||
static NonnullRefPtr<BasicModel> create()
|
||||
{
|
||||
return adopt_ref(*new BasicModel());
|
||||
}
|
||||
|
||||
virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_items.size(); }
|
||||
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return 1; }
|
||||
virtual String column_name(int) const override { return "Item"; }
|
||||
|
||||
virtual GUI::Variant data(GUI::ModelIndex const&, GUI::ModelRole = GUI::ModelRole::Display) const override;
|
||||
virtual TriState data_matches(GUI::ModelIndex const&, GUI::Variant const&) const override;
|
||||
virtual void invalidate() override;
|
||||
virtual GUI::ModelIndex index(int row, int column = 0, GUI::ModelIndex const& parent = GUI::ModelIndex()) const override;
|
||||
|
||||
Function<void()> on_invalidate;
|
||||
|
||||
void add_item(String const& item);
|
||||
void remove_item(GUI::ModelIndex const&);
|
||||
|
||||
private:
|
||||
BasicModel()
|
||||
{
|
||||
}
|
||||
|
||||
Vector<String> m_items;
|
||||
};
|
44
Userland/Demos/ModelGallery/BasicModelTab.gml
Normal file
44
Userland/Demos/ModelGallery/BasicModelTab.gml
Normal file
@ -0,0 +1,44 @@
|
||||
@GUI::Widget {
|
||||
name: "basic_model_tab"
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [4]
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Here is a basic model, displayed on a table widget. Its clients are updated via granular updates. You can add or remove items with the widgets below."
|
||||
text_alignment: "CenterLeft"
|
||||
|
||||
thickness: 2
|
||||
fixed_height: 34
|
||||
}
|
||||
|
||||
@GUI::TableView {
|
||||
name: "model_table"
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
}
|
||||
|
||||
fixed_height: 30
|
||||
|
||||
@GUI::TextBox {
|
||||
name: "new_item_name"
|
||||
placeholder: "Enter some text to be added..."
|
||||
}
|
||||
|
||||
@GUI::Button {
|
||||
name: "add_new_item"
|
||||
fixed_width: 22
|
||||
fixed_height: 22
|
||||
tooltip: "Add the text as an item to the model"
|
||||
}
|
||||
|
||||
@GUI::Button {
|
||||
name: "remove_selected_item"
|
||||
fixed_width: 22
|
||||
fixed_height: 22
|
||||
tooltip: "Remove the selected item from the model"
|
||||
}
|
||||
}
|
||||
}
|
17
Userland/Demos/ModelGallery/CMakeLists.txt
Normal file
17
Userland/Demos/ModelGallery/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
serenity_component(
|
||||
ModelGallery
|
||||
TARGETS ModelGallery
|
||||
)
|
||||
|
||||
compile_gml(./BasicModelTab.gml BasicModelTabGML.h basic_model_tab_gml)
|
||||
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
GalleryWidget.cpp
|
||||
BasicModel.cpp
|
||||
BasicModelTabGML.h
|
||||
)
|
||||
|
||||
serenity_app(ModelGallery ICON app-model-gallery)
|
||||
|
||||
target_link_libraries(ModelGallery LibGUI LibGfx)
|
75
Userland/Demos/ModelGallery/GalleryWidget.cpp
Normal file
75
Userland/Demos/ModelGallery/GalleryWidget.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "GalleryWidget.h"
|
||||
#include <Demos/ModelGallery/BasicModelTabGML.h>
|
||||
|
||||
GalleryWidget::GalleryWidget()
|
||||
{
|
||||
set_fill_with_background_color(true);
|
||||
set_layout<GUI::VerticalBoxLayout>();
|
||||
|
||||
auto& inner_widget = add<GUI::Widget>();
|
||||
auto& inner_layout = inner_widget.set_layout<GUI::VerticalBoxLayout>();
|
||||
inner_layout.set_margins({ 4 });
|
||||
|
||||
m_tab_widget = inner_widget.add<GUI::TabWidget>();
|
||||
m_statusbar = add<GUI::Statusbar>();
|
||||
|
||||
load_basic_model_tab();
|
||||
load_sorting_filtering_tab();
|
||||
}
|
||||
|
||||
void GalleryWidget::load_basic_model_tab()
|
||||
{
|
||||
auto& tab = m_tab_widget->add_tab<GUI::Widget>("Basic Model");
|
||||
tab.load_from_gml(basic_model_tab_gml);
|
||||
|
||||
m_basic_model = BasicModel::create();
|
||||
m_basic_model_table = *tab.find_descendant_of_type_named<GUI::TableView>("model_table");
|
||||
m_basic_model_table->set_model(m_basic_model);
|
||||
|
||||
m_basic_model->on_invalidate = [&] {
|
||||
m_invalidation_count++;
|
||||
m_statusbar->set_text(String::formatted("Times invalidated: {}", m_invalidation_count));
|
||||
};
|
||||
|
||||
m_statusbar->set_text(String::formatted("Times invalidated: {}", m_invalidation_count));
|
||||
|
||||
m_basic_model->add_item("Well...");
|
||||
m_basic_model->add_item("...hello...");
|
||||
m_basic_model->add_item("...friends! :^)");
|
||||
|
||||
m_new_item_name = *tab.find_descendant_of_type_named<GUI::TextBox>("new_item_name");
|
||||
m_add_new_item = *tab.find_descendant_of_type_named<GUI::Button>("add_new_item");
|
||||
m_remove_selected_item = *tab.find_descendant_of_type_named<GUI::Button>("remove_selected_item");
|
||||
|
||||
m_add_new_item->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/plus.png"));
|
||||
m_remove_selected_item->set_icon(Gfx::Bitmap::try_load_from_file("/res/icons/16x16/minus.png"));
|
||||
|
||||
m_new_item_name->on_return_pressed = [&] { add_textbox_contents_to_basic_model(); };
|
||||
m_add_new_item->on_click = [&](auto) { add_textbox_contents_to_basic_model(); };
|
||||
|
||||
m_remove_selected_item->on_click = [&](auto) {
|
||||
auto index = m_basic_model_table->cursor_index();
|
||||
if (index.is_valid()) {
|
||||
m_basic_model->remove_item(index);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void GalleryWidget::load_sorting_filtering_tab()
|
||||
{
|
||||
// TODO: Add the SortingFilteringProxyModel here.
|
||||
}
|
||||
|
||||
void GalleryWidget::add_textbox_contents_to_basic_model()
|
||||
{
|
||||
if (!m_new_item_name->current_line().is_empty()) {
|
||||
m_basic_model->add_item(m_new_item_name->current_line().to_utf8());
|
||||
m_new_item_name->set_text("");
|
||||
}
|
||||
}
|
38
Userland/Demos/ModelGallery/GalleryWidget.h
Normal file
38
Userland/Demos/ModelGallery/GalleryWidget.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BasicModel.h"
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGUI/Button.h>
|
||||
#include <LibGUI/Statusbar.h>
|
||||
#include <LibGUI/TabWidget.h>
|
||||
#include <LibGUI/TableView.h>
|
||||
#include <LibGUI/TextBox.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
class GalleryWidget final : public GUI::Widget {
|
||||
C_OBJECT(GalleryWidget)
|
||||
|
||||
private:
|
||||
GalleryWidget();
|
||||
|
||||
void load_basic_model_tab();
|
||||
void load_sorting_filtering_tab();
|
||||
|
||||
void add_textbox_contents_to_basic_model();
|
||||
|
||||
RefPtr<GUI::TabWidget> m_tab_widget;
|
||||
RefPtr<GUI::Statusbar> m_statusbar;
|
||||
|
||||
size_t m_invalidation_count { 0 };
|
||||
RefPtr<BasicModel> m_basic_model;
|
||||
RefPtr<GUI::TableView> m_basic_model_table;
|
||||
RefPtr<GUI::TextBox> m_new_item_name;
|
||||
RefPtr<GUI::Button> m_add_new_item;
|
||||
RefPtr<GUI::Button> m_remove_selected_item;
|
||||
};
|
39
Userland/Demos/ModelGallery/main.cpp
Normal file
39
Userland/Demos/ModelGallery/main.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "GalleryWidget.h"
|
||||
#include <LibGUI/Application.h>
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGUI/Button.h>
|
||||
#include <LibGUI/Frame.h>
|
||||
#include <LibGUI/MessageBox.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (pledge("stdio recvfd sendfd rpath wpath cpath unix", nullptr) < 0) {
|
||||
perror("pledge");
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto app = GUI::Application::construct(argc, argv);
|
||||
|
||||
if (pledge("stdio recvfd sendfd rpath", nullptr) < 0) {
|
||||
perror("pledge");
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto app_icon = GUI::Icon::default_icon("app-model-gallery");
|
||||
|
||||
auto window = GUI::Window::construct();
|
||||
window->set_title("Model Gallery");
|
||||
window->set_icon(app_icon.bitmap_for_size(16));
|
||||
window->resize(430, 480);
|
||||
window->set_main_widget<GalleryWidget>();
|
||||
|
||||
window->show();
|
||||
return app->exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user