Skip to content
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

Browser: Port browser to GML compilation #25399

Open
wants to merge 6 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
165 changes: 43 additions & 122 deletions Userland/Applications/Browser/BookmarksBarWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,116 +2,35 @@
* Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
* Copyright (c) 2022, networkException <networkexception@serenityos.org>
* Copyright (c) 2023, Cameron Youell <cameronyouell@gmail.com>
* Copyright (c) 2024, the SerenityOS developers
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <Applications/Browser/BookmarksBarWidget.h>
#include <Applications/Browser/Browser.h>
#include <Applications/Browser/EditBookmarkGML.h>
#include "BookmarksBarWidget.h"
#include "Browser.h"
#include "EditBookmarkDialog.h"
#include <LibGUI/Action.h>
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/Dialog.h>
#include <LibGUI/Event.h>
#include <LibGUI/JsonArrayModel.h>
#include <LibGUI/Menu.h>
#include <LibGUI/MessageBox.h>
#include <LibGUI/Model.h>
#include <LibGUI/TextBox.h>
#include <LibGUI/Widget.h>
#include <LibGUI/Window.h>
#include <LibGfx/Palette.h>

namespace Browser {

namespace {

enum class PerformEditOn {
NewBookmark,
ExistingBookmark
};

class BookmarkEditor final : public GUI::Dialog {
C_OBJECT(BookmarkEditor)

public:
static Vector<JsonValue>
edit_bookmark(Window* parent_window, StringView title, StringView url, PerformEditOn perform_edit_on)
{
auto editor = BookmarkEditor::construct(parent_window, title, url);
if (perform_edit_on == PerformEditOn::NewBookmark) {
editor->set_title("Add Bookmark");
} else {
editor->set_title("Edit Bookmark");
}
editor->set_icon(g_icon_bag.bookmark_filled);

if (editor->exec() == ExecResult::OK) {
return Vector<JsonValue> { editor->title(), editor->url() };
}

return {};
}

private:
BookmarkEditor(Window* parent_window, StringView title, StringView url)
: Dialog(parent_window)
{
auto widget = set_main_widget<GUI::Widget>();
widget->load_from_gml(edit_bookmark_gml).release_value_but_fixme_should_propagate_errors();

set_resizable(false);
resize(260, 85);

m_title_textbox = *widget->find_descendant_of_type_named<GUI::TextBox>("title_textbox");
m_title_textbox->set_text(title);
m_title_textbox->set_focus(true);
m_title_textbox->select_all();

auto& ok_button = *widget->find_descendant_of_type_named<GUI::Button>("ok_button");
ok_button.on_click = [this](auto) {
done(ExecResult::OK);
};
ok_button.set_default(true);

m_url_textbox = *widget->find_descendant_of_type_named<GUI::TextBox>("url_textbox");
m_url_textbox->set_text(url);
m_url_textbox->on_change = [this, &ok_button]() {
auto has_url = !m_url_textbox->text().is_empty();
ok_button.set_enabled(has_url);
};

auto& cancel_button = *widget->find_descendant_of_type_named<GUI::Button>("cancel_button");
cancel_button.on_click = [this](auto) {
done(ExecResult::Cancel);
};
}

ByteString title() const
{
return m_title_textbox->text();
}

ByteString url() const
{
return m_url_textbox->text();
}

RefPtr<GUI::TextBox> m_title_textbox;
RefPtr<GUI::TextBox> m_url_textbox;
};

}

static BookmarksBarWidget* s_the;

BookmarksBarWidget& BookmarksBarWidget::the()
{
return *s_the;
}

BookmarksBarWidget::BookmarksBarWidget(ByteString const& bookmarks_file, bool enabled)
BookmarksBarWidget::BookmarksBarWidget(ByteString const& bookmarks_file, bool const enabled)
{
s_the = this;
set_layout<GUI::HorizontalBoxLayout>(2, 0);
Expand Down Expand Up @@ -204,21 +123,21 @@ void BookmarksBarWidget::model_did_update(unsigned)

m_bookmarks.clear();

int width = 0;
int width { 0 };
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {

auto title = model()->index(item_index, 0).data().to_byte_string();
auto url = model()->index(item_index, 1).data().to_byte_string();

Gfx::IntRect rect { width, 0, font().width_rounded_up(title) + 32, height() };
Gfx::IntRect const rect { width, 0, font().width_rounded_up(title) + 32, height() };

auto& button = add<GUI::Button>();
m_bookmarks.append(button);

button.set_button_style(Gfx::ButtonStyle::Coolbar);
button.set_text(String::from_byte_string(title).release_value_but_fixme_should_propagate_errors());
button.set_icon(g_icon_bag.filetype_html);
button.set_fixed_size(font().width(title) + 32, 20);
button.set_fixed_size(static_cast<int>(font().width(title)) + 32, 20);
button.set_relative_rect(rect);
button.set_focus_policy(GUI::FocusPolicy::TabFocus);
button.set_tooltip(MUST(String::from_byte_string(url)));
Expand Down Expand Up @@ -251,13 +170,13 @@ void BookmarksBarWidget::model_did_update(unsigned)

void BookmarksBarWidget::update_content_size()
{
int x_position = 0;
int x_position { 0 };
m_last_visible_index = -1;

for (size_t i = 0; i < m_bookmarks.size(); ++i) {
auto& bookmark = m_bookmarks.at(i);
if (x_position + bookmark->width() + m_additional->width() > width()) {
m_last_visible_index = i;
m_last_visible_index = static_cast<int>(i);
break;
}
bookmark->set_x(x_position);
Expand All @@ -267,20 +186,21 @@ void BookmarksBarWidget::update_content_size()

if (m_last_visible_index < 0) {
m_additional->set_visible(false);
} else {
// hide all items > m_last_visible_index and create new bookmarks menu for them
m_additional->set_visible(true);
m_additional_menu = GUI::Menu::construct("Additional Bookmarks"_string);
m_additional->set_menu(m_additional_menu);
for (size_t i = m_last_visible_index; i < m_bookmarks.size(); ++i) {
auto& bookmark = m_bookmarks.at(i);
bookmark->set_visible(false);
m_additional_menu->add_action(GUI::Action::create(bookmark->text().to_byte_string(), g_icon_bag.filetype_html, [&](auto&) { bookmark->on_click(0); }));
}
return;
}

// hide all items > m_last_visible_index and create new bookmarks menu for them
m_additional->set_visible(true);
m_additional_menu = GUI::Menu::construct("Additional Bookmarks"_string);
m_additional->set_menu(m_additional_menu);
for (size_t i = m_last_visible_index; i < m_bookmarks.size(); ++i) {
auto& bookmark = m_bookmarks.at(i);
bookmark->set_visible(false);
m_additional_menu->add_action(GUI::Action::create(bookmark->text().to_byte_string(), g_icon_bag.filetype_html, [&](auto&) { bookmark->on_click(0); }));
}
}

bool BookmarksBarWidget::contains_bookmark(StringView url)
bool BookmarksBarWidget::contains_bookmark(StringView const url)
{
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {

Expand All @@ -292,11 +212,11 @@ bool BookmarksBarWidget::contains_bookmark(StringView url)
return false;
}

ErrorOr<void> BookmarksBarWidget::remove_bookmark(StringView url)
ErrorOr<void> BookmarksBarWidget::remove_bookmark(StringView const url)
{
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {

auto item_url = model()->index(item_index, 1).data().to_byte_string();
auto const item_url = model()->index(item_index, 1).data().to_byte_string();
if (item_url == url) {
auto& json_model = *static_cast<GUI::JsonArrayModel*>(model());

Expand Down Expand Up @@ -326,13 +246,13 @@ ErrorOr<void> BookmarksBarWidget::add_bookmark(StringView url, StringView title)
if (on_bookmark_change)
on_bookmark_change();

values = BookmarkEditor::edit_bookmark(window(), title, url, PerformEditOn::NewBookmark);
values = EditBookmarkDialog::edit_bookmark(window(), g_icon_bag.bookmark_filled, title, url, PerformEditOn::NewBookmark);
if (values.is_empty())
return remove_bookmark(url);

auto model_has_updated = false;
for (int item_index = 0; item_index < model()->row_count(); item_index++) {
auto item_url = model()->index(item_index, 1).data().to_byte_string();
bool model_has_updated { false };
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {
auto const item_url = model()->index(item_index, 1).data().to_byte_string();

if (item_url == url) {
TRY(update_model(values, [item_index](auto& model, auto&& values) {
Expand All @@ -352,26 +272,27 @@ ErrorOr<void> BookmarksBarWidget::add_bookmark(StringView url, StringView title)
return {};
}

ErrorOr<void> BookmarksBarWidget::edit_bookmark(StringView url)
ErrorOr<void> BookmarksBarWidget::edit_bookmark(StringView const url)
{
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {
auto item_title = model()->index(item_index, 0).data().to_byte_string();
auto item_url = model()->index(item_index, 1).data().to_byte_string();
auto const item_title = model()->index(item_index, 0).data().to_byte_string();
auto const item_url = model()->index(item_index, 1).data().to_byte_string();

if (item_url == url) {
auto values = BookmarkEditor::edit_bookmark(window(), item_title, item_url, PerformEditOn::ExistingBookmark);
if (values.is_empty())
return {};
if (item_url != url)
continue;

TRY(update_model(values, [item_index](auto& model, auto&& values) {
return model.set(item_index, move(values));
}));
auto values = EditBookmarkDialog::edit_bookmark(window(), g_icon_bag.bookmark_filled, item_title, item_url, PerformEditOn::ExistingBookmark);
if (values.is_empty())
return {};

if (on_bookmark_change)
on_bookmark_change();
TRY(update_model(values, [item_index](auto& model, auto&& values) {
return model.set(item_index, move(values));
}));

return {};
}
if (on_bookmark_change)
on_bookmark_change();

return {};
}

return Error::from_string_view("Bookmark not found"sv);
Expand Down
Loading