summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorthankyouverycool <66646555+thankyouverycool@users.noreply.github.com>2020-07-14 17:02:46 -0400
committerAndreas Kling <kling@serenityos.org>2020-07-15 13:19:44 +0200
commitb2783a234aa14e5c382d9bf225b4ec54d9b98852 (patch)
tree713a3d1d35e883b39b3ce19ac8c3649fcca3d329 /Libraries
parentdc716194c83bf308d6937cee021993bf82816e3c (diff)
downloadserenity-b2783a234aa14e5c382d9bf225b4ec54d9b98852.zip
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().
Diffstat (limited to 'Libraries')
-rw-r--r--Libraries/LibGUI/ComboBox.cpp2
-rw-r--r--Libraries/LibGUI/TextEditor.cpp71
-rw-r--r--Libraries/LibGUI/TextEditor.h27
3 files changed, 87 insertions, 13 deletions
diff --git a/Libraries/LibGUI/ComboBox.cpp b/Libraries/LibGUI/ComboBox.cpp
index 7516760261..42a0bdf61e 100644
--- a/Libraries/LibGUI/ComboBox.cpp
+++ b/Libraries/LibGUI/ComboBox.cpp
@@ -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()
diff --git a/Libraries/LibGUI/TextEditor.cpp b/Libraries/LibGUI/TextEditor.cpp
index 7eb199c732..7533f9a4e1 100644
--- a/Libraries/LibGUI/TextEditor.cpp
+++ b/Libraries/LibGUI/TextEditor.cpp
@@ -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_mode(const Mode mode)
+{
+ if (m_mode == mode)
+ return;
+ 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_readonly(bool readonly)
+void TextEditor::set_has_open_button(bool has_button)
{
- if (m_readonly == readonly)
+ if (m_has_open_button == has_button)
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_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());
diff --git a/Libraries/LibGUI/TextEditor.h b/Libraries/LibGUI/TextEditor.h
index 7d505a6b13..a3695090e5 100644
--- a/Libraries/LibGUI/TextEditor.h
+++ b/Libraries/LibGUI/TextEditor.h
@@ -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 };