Files
Andrew Kaster f4773b0c36 Userland: Convert bitmap resource loads to load from resource URIs
Any bitmap load of the style load_from_file("/res/foo") has been
converted to the new pattern load_from_uri("resource://foo").

This will allow for porting more apps to non-serenity targets, as well
as add some flexibility if we want to experiment with other resource
storage formats in the future.
2026-07-12 14:42:21 -04:00

136 lines
4.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2026, Fırat Kızılboğa <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "FindInPageWidget.h"
#include <Applications/Browser/FindInPageWidgetGML.h>
#include <LibGUI/Button.h>
#include <LibGUI/CheckBox.h>
#include <LibGUI/Label.h>
#include <LibGUI/TextBox.h>
#include <LibGfx/Bitmap.h>
REGISTER_WIDGET(Browser, FindInPageWidget)
namespace Browser {
FindInPageWidget::FindInPageWidget()
{
load_from_gml(find_in_page_widget_gml).release_value_but_fixme_should_propagate_errors();
m_close_button = find_descendant_of_type_named<GUI::Button>("close_button");
m_previous_button = find_descendant_of_type_named<GUI::Button>("previous_button");
m_next_button = find_descendant_of_type_named<GUI::Button>("next_button");
m_search_textbox = find_descendant_of_type_named<GUI::TextBox>("search_textbox");
m_match_case_checkbox = find_descendant_of_type_named<GUI::CheckBox>("match_case_checkbox");
m_result_label = find_descendant_of_type_named<GUI::Label>("result_label");
m_close_button->set_icon(MUST(Gfx::Bitmap::load_from_uri("resource://icons/16x16/window-close.png"sv)));
m_previous_button->set_icon(MUST(Gfx::Bitmap::load_from_uri("resource://icons/16x16/go-up.png"sv)));
m_next_button->set_icon(MUST(Gfx::Bitmap::load_from_uri("resource://icons/16x16/go-down.png"sv)));
}
void FindInPageWidget::initialize(WebView::OutOfProcessWebView& web_view)
{
m_web_content_view = web_view;
m_search_textbox->on_change = [this] {
find_text_changed();
notify_search_text_changed();
};
m_search_textbox->on_return_pressed = [this] {
m_web_content_view->find_in_page_next_match();
notify_search_text_changed();
};
m_search_textbox->on_shift_return_pressed = [this] {
m_web_content_view->find_in_page_previous_match();
notify_search_text_changed();
};
m_next_button->on_click = [this](auto) {
m_web_content_view->find_in_page_next_match();
notify_search_text_changed();
};
m_previous_button->on_click = [this](auto) {
m_web_content_view->find_in_page_previous_match();
notify_search_text_changed();
};
m_close_button->on_click = [this](auto) {
set_visible(false);
};
m_match_case_checkbox->on_checked = [this](bool) {
if (!m_search_textbox->text().is_empty())
find_text_changed();
};
m_web_content_view->on_find_in_page = [this](size_t current_match_index, Optional<size_t> const& total_match_count) {
update_result_label(current_match_index, total_match_count);
};
}
void FindInPageWidget::find_text_changed()
{
auto query = MUST(String::from_byte_string(m_search_textbox->text()));
auto case_sensitive = m_match_case_checkbox->is_checked() ? CaseSensitivity::CaseSensitive : CaseSensitivity::CaseInsensitive;
m_web_content_view->find_in_page(query, case_sensitive);
}
void FindInPageWidget::update_result_label(size_t current_match_index, Optional<size_t> const& total_match_count)
{
if (total_match_count.has_value()) {
if (*total_match_count > 0) {
m_result_label->set_text(MUST(String::formatted("{} of {} matches", current_match_index + 1, *total_match_count)));
} else {
m_result_label->set_text("Phrase not found"_string);
}
m_result_label->set_visible(true);
} else {
m_result_label->set_visible(false);
}
}
void FindInPageWidget::notify_search_text_changed()
{
if (on_search_text_change) {
auto text = MUST(String::from_byte_string(m_search_textbox->text()));
on_search_text_change(text);
}
}
void FindInPageWidget::show(String const& global_term)
{
// Priority 1: If there's a selection on the page, use that
if (auto selection = m_web_content_view->selected_text_with_whitespace_collapsed(); selection.has_value() && !selection->is_empty()) {
m_search_textbox->set_text(*selection);
notify_search_text_changed();
}
// Priority 2: If the textbox is empty, use the global term
else if (m_search_textbox->text().is_empty() && !global_term.is_empty()) {
m_search_textbox->set_text(global_term);
}
// Priority 3: Keep existing text (do nothing)
m_search_textbox->select_all();
m_search_textbox->set_focus(true);
set_visible(true);
}
void FindInPageWidget::keydown_event(GUI::KeyEvent& event)
{
if (event.key() == KeyCode::Key_Escape) {
set_visible(false);
event.accept();
return;
}
Widget::keydown_event(event);
}
}