mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:18:12 +00:00
LibGUI: Use enum for TextEditor modes & add new DisplayOnly mode
Adds a new, more restrictive read-only state to TextEditor which forbids copying, selecting, editor cursors, and context menus. Provides a unique appearance on focus which accomodates ComboBox widgets. All TextEditor modes are now accessed by enum and set_mode() which sets the editor to Editable, ReadOnly or DisplayOnly. Updates applications still using set_readonly().
This commit is contained in:
parent
dc716194c8
commit
b2783a234a
6 changed files with 92 additions and 18 deletions
|
@ -261,7 +261,7 @@ Tab::Tab(Type type)
|
|||
auto window = GUI::Window::construct();
|
||||
auto& editor = window->set_main_widget<GUI::TextEditor>();
|
||||
editor.set_text(source);
|
||||
editor.set_readonly(true);
|
||||
editor.set_mode(GUI::TextEditor::ReadOnly);
|
||||
editor.set_ruler_visible(true);
|
||||
window->set_rect(150, 150, 640, 480);
|
||||
window->set_title(url);
|
||||
|
|
|
@ -35,7 +35,7 @@ ProcessStacksWidget::ProcessStacksWidget()
|
|||
set_layout<GUI::VerticalBoxLayout>();
|
||||
layout()->set_margins({ 4, 4, 4, 4 });
|
||||
m_stacks_editor = add<GUI::TextEditor>();
|
||||
m_stacks_editor->set_readonly(true);
|
||||
m_stacks_editor->set_mode(GUI::TextEditor::ReadOnly);
|
||||
|
||||
m_timer = add<Core::Timer>(1000, [this] { refresh(); });
|
||||
}
|
||||
|
|
|
@ -734,11 +734,11 @@ void open_file(const String& filename)
|
|||
auto project_file = g_project->get_file(filename);
|
||||
if (project_file) {
|
||||
current_editor().set_document(const_cast<GUI::TextDocument&>(project_file->document()));
|
||||
current_editor().set_readonly(false);
|
||||
current_editor().set_mode(GUI::TextEditor::Editable);
|
||||
} else {
|
||||
auto external_file = ProjectFile::construct_with_name(filename);
|
||||
current_editor().set_document(const_cast<GUI::TextDocument&>(external_file->document()));
|
||||
current_editor().set_readonly(true);
|
||||
current_editor().set_mode(GUI::TextEditor::ReadOnly);
|
||||
}
|
||||
|
||||
if (filename.ends_with(".cpp") || filename.ends_with(".h"))
|
||||
|
|
|
@ -177,7 +177,7 @@ void ComboBox::set_only_allow_values_from_model(bool b)
|
|||
if (m_only_allow_values_from_model == b)
|
||||
return;
|
||||
m_only_allow_values_from_model = b;
|
||||
m_editor->set_readonly(m_only_allow_values_from_model);
|
||||
m_editor->set_mode(m_only_allow_values_from_model ? TextEditor::DisplayOnly : TextEditor::Editable);
|
||||
}
|
||||
|
||||
Model* ComboBox::model()
|
||||
|
|
|
@ -201,6 +201,9 @@ void TextEditor::doubleclick_event(MouseEvent& event)
|
|||
if (event.button() != MouseButton::Left)
|
||||
return;
|
||||
|
||||
if (is_displayonly())
|
||||
return;
|
||||
|
||||
// NOTE: This ensures that spans are updated before we look at them.
|
||||
flush_pending_change_notification_if_needed();
|
||||
|
||||
|
@ -236,6 +239,12 @@ void TextEditor::mousedown_event(MouseEvent& event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (on_mousedown)
|
||||
on_mousedown();
|
||||
|
||||
if (is_displayonly())
|
||||
return;
|
||||
|
||||
if (m_triple_click_timer.is_valid() && m_triple_click_timer.elapsed() < 250) {
|
||||
m_triple_click_timer = Core::ElapsedTimer();
|
||||
|
||||
|
@ -364,6 +373,19 @@ void TextEditor::paint_event(PaintEvent& event)
|
|||
painter.add_clip_rect(event.rect());
|
||||
painter.fill_rect(event.rect(), widget_background_color);
|
||||
|
||||
if (is_displayonly() && (is_focused() || has_visible_list())) {
|
||||
widget_background_color = palette().selection();
|
||||
Gfx::IntRect display_rect {
|
||||
widget_inner_rect().x() + 1,
|
||||
widget_inner_rect().y() + 1,
|
||||
widget_inner_rect().width() - button_padding(),
|
||||
widget_inner_rect().height() - 2
|
||||
};
|
||||
painter.add_clip_rect(display_rect);
|
||||
painter.add_clip_rect(event.rect());
|
||||
painter.fill_rect(event.rect(), widget_background_color);
|
||||
}
|
||||
|
||||
painter.translate(frame_thickness(), frame_thickness());
|
||||
|
||||
auto ruler_rect = ruler_rect_in_inner_coordinates();
|
||||
|
@ -438,6 +460,8 @@ void TextEditor::paint_event(PaintEvent& event)
|
|||
if (!document().has_spans()) {
|
||||
// Fast-path for plain text
|
||||
auto color = palette().color(is_enabled() ? foreground_role() : Gfx::ColorRole::DisabledText);
|
||||
if (is_displayonly() && (is_focused() || has_visible_list()))
|
||||
color = palette().color(is_enabled() ? Gfx::ColorRole::SelectionText : Gfx::ColorRole::DisabledText);
|
||||
painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, color);
|
||||
} else {
|
||||
Gfx::IntRect character_rect = { visual_line_rect.location(), { 0, line_height() } };
|
||||
|
@ -521,7 +545,7 @@ void TextEditor::paint_event(PaintEvent& event)
|
|||
painter.draw_scaled_bitmap(icon_rect, *m_icon, m_icon->rect());
|
||||
}
|
||||
|
||||
if (is_focused() && m_cursor_state)
|
||||
if (is_focused() && m_cursor_state && !is_displayonly())
|
||||
painter.fill_rect(cursor_content_rect(), palette().text_cursor());
|
||||
}
|
||||
|
||||
|
@ -1269,7 +1293,8 @@ void TextEditor::undefer_reflow()
|
|||
void TextEditor::enter_event(Core::Event&)
|
||||
{
|
||||
ASSERT(window());
|
||||
window()->set_override_cursor(StandardCursor::IBeam);
|
||||
if (!is_displayonly())
|
||||
window()->set_override_cursor(StandardCursor::IBeam);
|
||||
|
||||
m_automatic_selection_scroll_timer->stop();
|
||||
}
|
||||
|
@ -1302,15 +1327,42 @@ void TextEditor::did_change()
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::set_readonly(bool readonly)
|
||||
void TextEditor::set_mode(const Mode mode)
|
||||
{
|
||||
if (m_readonly == readonly)
|
||||
if (m_mode == mode)
|
||||
return;
|
||||
m_readonly = readonly;
|
||||
m_cut_action->set_enabled(!is_readonly() && has_selection());
|
||||
m_delete_action->set_enabled(!is_readonly());
|
||||
m_paste_action->set_enabled(!is_readonly());
|
||||
m_mode = mode;
|
||||
switch (mode) {
|
||||
case Editable:
|
||||
m_cut_action->set_enabled(true && has_selection());
|
||||
m_delete_action->set_enabled(true);
|
||||
m_paste_action->set_enabled(true);
|
||||
set_accepts_emoji_input(true);
|
||||
break;
|
||||
case ReadOnly:
|
||||
case DisplayOnly:
|
||||
m_cut_action->set_enabled(false && has_selection());
|
||||
m_delete_action->set_enabled(false);
|
||||
m_paste_action->set_enabled(false);
|
||||
set_accepts_emoji_input(false);
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::set_has_open_button(bool has_button)
|
||||
{
|
||||
if (m_has_open_button == has_button)
|
||||
return;
|
||||
m_has_open_button = has_button;
|
||||
}
|
||||
|
||||
void TextEditor::set_has_visible_list(bool visible)
|
||||
{
|
||||
if (m_has_visible_list == visible)
|
||||
return;
|
||||
m_has_visible_list = visible;
|
||||
}
|
||||
|
||||
void TextEditor::did_update_selection()
|
||||
|
@ -1327,6 +1379,9 @@ void TextEditor::did_update_selection()
|
|||
|
||||
void TextEditor::context_menu_event(ContextMenuEvent& event)
|
||||
{
|
||||
if (is_displayonly())
|
||||
return;
|
||||
|
||||
if (!m_context_menu) {
|
||||
m_context_menu = Menu::construct();
|
||||
m_context_menu->add_action(undo_action());
|
||||
|
|
|
@ -46,6 +46,13 @@ public:
|
|||
MultiLine,
|
||||
SingleLine
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
Editable,
|
||||
ReadOnly,
|
||||
DisplayOnly
|
||||
};
|
||||
|
||||
virtual ~TextEditor() override;
|
||||
|
||||
const TextDocument& document() const { return *m_document; }
|
||||
|
@ -53,8 +60,10 @@ public:
|
|||
|
||||
void set_document(TextDocument&);
|
||||
|
||||
bool is_readonly() const { return m_readonly; }
|
||||
void set_readonly(bool);
|
||||
bool has_visible_list() const { return m_has_visible_list; }
|
||||
void set_has_visible_list(bool);
|
||||
bool has_open_button() const { return m_has_open_button; }
|
||||
void set_has_open_button(bool);
|
||||
|
||||
virtual bool is_automatic_indentation_enabled() const final { return m_automatic_indentation_enabled; }
|
||||
void set_automatic_indentation_enabled(bool enabled) { m_automatic_indentation_enabled = enabled; }
|
||||
|
@ -71,6 +80,12 @@ public:
|
|||
bool is_single_line() const { return m_type == SingleLine; }
|
||||
bool is_multi_line() const { return m_type == MultiLine; }
|
||||
|
||||
Mode mode() const { return m_mode; }
|
||||
bool is_editable() const { return m_mode == Editable; }
|
||||
bool is_readonly() const { return m_mode == ReadOnly; }
|
||||
bool is_displayonly() const { return m_mode == DisplayOnly; }
|
||||
void set_mode(const Mode);
|
||||
|
||||
bool is_ruler_visible() const { return m_ruler_visible; }
|
||||
void set_ruler_visible(bool b) { m_ruler_visible = b; }
|
||||
|
||||
|
@ -153,7 +168,7 @@ protected:
|
|||
virtual void context_menu_event(ContextMenuEvent&) override;
|
||||
virtual void resize_event(ResizeEvent&) override;
|
||||
virtual void theme_change_event(ThemeChangeEvent&) override;
|
||||
virtual void cursor_did_change() {}
|
||||
virtual void cursor_did_change() { }
|
||||
Gfx::IntRect ruler_content_rect(size_t line) const;
|
||||
|
||||
TextPosition text_position_at(const Gfx::IntPoint&) const;
|
||||
|
@ -182,6 +197,7 @@ private:
|
|||
|
||||
int icon_size() const { return 16; }
|
||||
int icon_padding() const { return 2; }
|
||||
int button_padding() const { return m_has_open_button ? 17 : 2; }
|
||||
|
||||
class ReflowDeferrer {
|
||||
public:
|
||||
|
@ -194,6 +210,7 @@ private:
|
|||
{
|
||||
m_editor.undefer_reflow();
|
||||
}
|
||||
|
||||
private:
|
||||
TextEditor& m_editor;
|
||||
};
|
||||
|
@ -238,6 +255,7 @@ private:
|
|||
}
|
||||
|
||||
Type m_type { MultiLine };
|
||||
Mode m_mode { Editable };
|
||||
|
||||
TextPosition m_cursor;
|
||||
Gfx::TextAlignment m_text_alignment { Gfx::TextAlignment::CenterLeft };
|
||||
|
@ -247,7 +265,8 @@ private:
|
|||
bool m_has_pending_change_notification { false };
|
||||
bool m_automatic_indentation_enabled { false };
|
||||
bool m_line_wrapping_enabled { false };
|
||||
bool m_readonly { false };
|
||||
bool m_has_visible_list { false };
|
||||
bool m_has_open_button { false };
|
||||
int m_line_spacing { 4 };
|
||||
size_t m_soft_tab_width { 4 };
|
||||
int m_horizontal_content_padding { 3 };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue