mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:37:34 +00:00
HackStudio: Add FindWidget
The find widget appears on Ctrl+F. It uses the GUI::TextEditor search API to search for text, which also takes care of highlighting the search results.
This commit is contained in:
parent
de902ab659
commit
d9d299f884
8 changed files with 186 additions and 4 deletions
|
@ -10,6 +10,7 @@ add_subdirectory(LanguageClients)
|
|||
|
||||
compile_gml(Dialogs/NewProjectDialog.gml Dialogs/NewProjectDialogGML.h new_project_dialog_gml)
|
||||
compile_gml(Dialogs/Git/GitCommitDialog.gml Dialogs/Git/GitCommitDialogGML.h git_commit_dialog_gml)
|
||||
compile_gml(FindWidget.gml FindWidgetGML.h find_widget_gml)
|
||||
|
||||
set(SOURCES
|
||||
CodeDocument.cpp
|
||||
|
@ -32,6 +33,8 @@ set(SOURCES
|
|||
Editor.cpp
|
||||
EditorWrapper.cpp
|
||||
FindInFilesWidget.cpp
|
||||
FindWidget.cpp
|
||||
FindWidgetGML.h
|
||||
Git/DiffViewer.cpp
|
||||
Git/GitFilesModel.cpp
|
||||
Git/GitFilesView.cpp
|
||||
|
|
|
@ -20,11 +20,13 @@ namespace HackStudio {
|
|||
EditorWrapper::EditorWrapper()
|
||||
{
|
||||
set_layout<GUI::VerticalBoxLayout>();
|
||||
|
||||
m_filename_title = untitled_label;
|
||||
|
||||
// FIXME: Propagate errors instead of giving up
|
||||
m_editor = MUST(try_add<Editor>());
|
||||
m_editor = MUST(Editor::try_create());
|
||||
m_find_widget = add<FindWidget>(*m_editor);
|
||||
|
||||
add_child(*m_editor);
|
||||
m_editor->set_ruler_visible(true);
|
||||
m_editor->set_automatic_indentation_enabled(true);
|
||||
|
||||
|
@ -115,4 +117,12 @@ void EditorWrapper::set_debug_mode(bool enabled)
|
|||
m_editor->set_debug_mode(enabled);
|
||||
}
|
||||
|
||||
void EditorWrapper::search_action()
|
||||
{
|
||||
if (m_find_widget->visible())
|
||||
m_find_widget->hide();
|
||||
else
|
||||
m_find_widget->show();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Debugger/BreakpointCallback.h"
|
||||
#include "FindWidget.h"
|
||||
#include "Git/GitRepo.h"
|
||||
#include "LanguageClient.h"
|
||||
#include <AK/Function.h>
|
||||
|
@ -52,6 +53,9 @@ public:
|
|||
Function<void()> on_change;
|
||||
Function<void(EditorWrapper&)> on_tab_close_request;
|
||||
|
||||
void search_action();
|
||||
FindWidget const& find_widget() const { return *m_find_widget; }
|
||||
|
||||
private:
|
||||
static constexpr auto untitled_label = "(Untitled)";
|
||||
|
||||
|
@ -62,6 +66,7 @@ private:
|
|||
String m_filename;
|
||||
String m_filename_title;
|
||||
RefPtr<Editor> m_editor;
|
||||
RefPtr<FindWidget> m_find_widget;
|
||||
|
||||
Optional<String> m_project_root;
|
||||
RefPtr<GitRepo> m_git_repo;
|
||||
|
|
83
Userland/DevTools/HackStudio/FindWidget.cpp
Normal file
83
Userland/DevTools/HackStudio/FindWidget.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Itamar S. <itamar8910@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "FindWidget.h"
|
||||
#include "Editor.h"
|
||||
#include <AK/QuickSort.h>
|
||||
#include <DevTools/HackStudio/FindWidgetGML.h>
|
||||
#include <LibGUI/BoxLayout.h>
|
||||
#include <LibGfx/Palette.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
FindWidget::FindWidget(NonnullRefPtr<Editor> editor)
|
||||
: m_editor(move(editor))
|
||||
{
|
||||
load_from_gml(find_widget_gml);
|
||||
set_fixed_height(widget_height);
|
||||
m_input_field = find_descendant_of_type_named<GUI::TextBox>("input_field");
|
||||
m_index_label = find_descendant_of_type_named<GUI::Label>("index_label");
|
||||
m_next = find_descendant_of_type_named<GUI::Button>("next");
|
||||
m_previous = find_descendant_of_type_named<GUI::Button>("previous");
|
||||
|
||||
VERIFY(m_input_field);
|
||||
VERIFY(m_next);
|
||||
VERIFY(m_previous);
|
||||
|
||||
m_next->on_click = [this](auto) {
|
||||
find_next(GUI::TextEditor::SearchDirection::Forward);
|
||||
};
|
||||
m_previous->on_click = [this](auto) {
|
||||
find_next(GUI::TextEditor::SearchDirection::Backward);
|
||||
};
|
||||
|
||||
m_input_field->on_change = [this]() {
|
||||
m_editor->reset_search_results();
|
||||
find_next(GUI::TextEditor::SearchDirection::Forward);
|
||||
};
|
||||
|
||||
m_input_field->on_return_pressed = [this]() {
|
||||
find_next(GUI::TextEditor::SearchDirection::Forward);
|
||||
};
|
||||
}
|
||||
|
||||
void FindWidget::show()
|
||||
{
|
||||
set_visible(true);
|
||||
set_focus(true);
|
||||
m_input_field->set_focus(true);
|
||||
// Adjust scroll value to smooth the appearance of the FindWidget.
|
||||
m_editor->vertical_scrollbar().set_value(m_editor->vertical_scrollbar().value() + widget_height, GUI::AllowCallback::Yes, GUI::Scrollbar::DoClamp::No);
|
||||
m_visible = !m_visible;
|
||||
}
|
||||
|
||||
void FindWidget::hide()
|
||||
{
|
||||
set_visible(false);
|
||||
set_focus(false);
|
||||
m_visible = !m_visible;
|
||||
m_editor->vertical_scrollbar().set_value(m_editor->vertical_scrollbar().value() - widget_height, GUI::AllowCallback::Yes, GUI::Scrollbar::DoClamp::No);
|
||||
m_editor->set_focus(true);
|
||||
m_editor->reset_search_results();
|
||||
}
|
||||
|
||||
void FindWidget::find_next(GUI::TextEditor::SearchDirection direction)
|
||||
{
|
||||
auto needle = m_input_field->text();
|
||||
if (needle.is_empty()) {
|
||||
m_editor->reset_search_results();
|
||||
m_index_label->set_text(String::empty());
|
||||
return;
|
||||
}
|
||||
auto result = m_editor->find_text(needle, direction, GUI::TextDocument::SearchShouldWrap::Yes, false, false);
|
||||
|
||||
if (result.is_valid())
|
||||
m_index_label->set_text(String::formatted("{}/{}", m_editor->search_result_index().value_or(0) + 1, m_editor->search_results().size()));
|
||||
else
|
||||
m_index_label->set_text(String::empty());
|
||||
}
|
||||
|
||||
}
|
32
Userland/DevTools/HackStudio/FindWidget.gml
Normal file
32
Userland/DevTools/HackStudio/FindWidget.gml
Normal file
|
@ -0,0 +1,32 @@
|
|||
@GUI::Widget {
|
||||
name: "find_widget"
|
||||
fill_with_background_color: true
|
||||
shrink_to_fit: true
|
||||
visible: false
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
margins: [0, 0]
|
||||
}
|
||||
|
||||
@GUI::TextBox {
|
||||
name: "input_field"
|
||||
max_width: 250
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "index_label"
|
||||
max_width: 30
|
||||
text: ""
|
||||
}
|
||||
|
||||
@GUI::Button {
|
||||
name: "next"
|
||||
icon: "/res/icons/16x16/go-down.png"
|
||||
max_width: 15
|
||||
}
|
||||
|
||||
@GUI::Button {
|
||||
name: "previous"
|
||||
icon: "/res/icons/16x16/go-up.png"
|
||||
max_width: 15
|
||||
}
|
||||
}
|
44
Userland/DevTools/HackStudio/FindWidget.h
Normal file
44
Userland/DevTools/HackStudio/FindWidget.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Itamar S. <itamar8910@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Editor.h"
|
||||
#include <LibGUI/Button.h>
|
||||
#include <LibGUI/TextBox.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
#include <LibGUI/Window.h>
|
||||
|
||||
namespace HackStudio {
|
||||
|
||||
class Editor;
|
||||
class EditorWrapper;
|
||||
|
||||
class FindWidget final : public GUI::Widget {
|
||||
C_OBJECT(FindWidget)
|
||||
public:
|
||||
~FindWidget() = default;
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
bool visible() const { return m_visible; }
|
||||
|
||||
private:
|
||||
FindWidget(NonnullRefPtr<Editor>);
|
||||
|
||||
void find_next(GUI::TextEditor::SearchDirection);
|
||||
|
||||
static constexpr auto widget_height = 25;
|
||||
|
||||
NonnullRefPtr<Editor> m_editor;
|
||||
RefPtr<GUI::TextBox> m_input_field;
|
||||
RefPtr<GUI::Label> m_index_label;
|
||||
RefPtr<GUI::Button> m_next;
|
||||
RefPtr<GUI::Button> m_previous;
|
||||
bool m_visible { false };
|
||||
};
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2022, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2022, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
@ -1445,6 +1445,11 @@ void HackStudioWidget::create_view_menu(GUI::Window& window)
|
|||
create_location_history_actions();
|
||||
view_menu.add_action(*m_locations_history_back_action);
|
||||
view_menu.add_action(*m_locations_history_forward_action);
|
||||
|
||||
auto search_action = GUI::Action::create("&Search", { Mod_Ctrl, Key_F }, [this](auto&) {
|
||||
current_editor_wrapper().search_action();
|
||||
});
|
||||
view_menu.add_action(search_action);
|
||||
}
|
||||
|
||||
void HackStudioWidget::create_help_menu(GUI::Window& window)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2022, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2021, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue