Browse Source

LibGUI: Let GTextEditor deal with its horizontal padding internally.

I originally wanted to have the padding concept in GScrollableWidget
but it's really finicky with the ruler and everything.
Andreas Kling 6 years ago
parent
commit
ec8bffb06d
4 changed files with 24 additions and 30 deletions
  1. 4 12
      LibGUI/GScrollableWidget.cpp
  2. 4 8
      LibGUI/GScrollableWidget.h
  3. 14 9
      LibGUI/GTextEditor.cpp
  4. 2 1
      LibGUI/GTextEditor.h

+ 4 - 12
LibGUI/GScrollableWidget.cpp

@@ -42,11 +42,11 @@ void GScrollableWidget::resize_event(GResizeEvent& event)
 void GScrollableWidget::update_scrollbar_ranges()
 void GScrollableWidget::update_scrollbar_ranges()
 {
 {
     int available_height = height() - m_size_occupied_by_fixed_elements.height() - height_occupied_by_horizontal_scrollbar();
     int available_height = height() - m_size_occupied_by_fixed_elements.height() - height_occupied_by_horizontal_scrollbar();
-    int excess_height = max(0, (m_content_size.height() + m_padding.height() * 2) - available_height);
+    int excess_height = max(0, m_content_size.height() - available_height);
     m_vertical_scrollbar->set_range(0, excess_height);
     m_vertical_scrollbar->set_range(0, excess_height);
 
 
     int available_width = width() - m_size_occupied_by_fixed_elements.width() - width_occupied_by_vertical_scrollbar();
     int available_width = width() - m_size_occupied_by_fixed_elements.width() - width_occupied_by_vertical_scrollbar();
-    int excess_width = max(0, (m_content_size.width() + m_padding.height() * 2) - available_width);
+    int excess_width = max(0, m_content_size.width() - available_width);
     m_horizontal_scrollbar->set_range(0, excess_width);
     m_horizontal_scrollbar->set_range(0, excess_width);
 
 
     m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
     m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
@@ -68,14 +68,6 @@ void GScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
     update_scrollbar_ranges();
     update_scrollbar_ranges();
 }
 }
 
 
-void GScrollableWidget::set_padding(const Size& size)
-{
-    if (m_padding == size)
-        return;
-    m_padding = size;
-    update_scrollbar_ranges();
-}
-
 int GScrollableWidget::height_occupied_by_horizontal_scrollbar() const
 int GScrollableWidget::height_occupied_by_horizontal_scrollbar() const
 {
 {
     return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0;
     return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0;
@@ -91,8 +83,8 @@ Rect GScrollableWidget::visible_content_rect() const
     return {
     return {
         m_horizontal_scrollbar->value(),
         m_horizontal_scrollbar->value(),
         m_vertical_scrollbar->value(),
         m_vertical_scrollbar->value(),
-        width() - width_occupied_by_vertical_scrollbar() - padding().width() * 2 - m_size_occupied_by_fixed_elements.width(),
-        height() - height_occupied_by_horizontal_scrollbar() - padding().height() * 2 - m_size_occupied_by_fixed_elements.height()
+        width() - width_occupied_by_vertical_scrollbar() - m_size_occupied_by_fixed_elements.width(),
+        height() - height_occupied_by_horizontal_scrollbar() - m_size_occupied_by_fixed_elements.height()
     };
     };
 }
 }
 
 

+ 4 - 8
LibGUI/GScrollableWidget.h

@@ -8,19 +8,18 @@ class GScrollableWidget : public GWidget {
 public:
 public:
     virtual ~GScrollableWidget() override;
     virtual ~GScrollableWidget() override;
 
 
-    virtual const char* class_name() const override { return "GScrollableWidget"; }
-
     Size content_size() const { return m_content_size; }
     Size content_size() const { return m_content_size; }
     int content_width() const { return m_content_size.width(); }
     int content_width() const { return m_content_size.width(); }
     int content_height() const { return m_content_size.height(); }
     int content_height() const { return m_content_size.height(); }
 
 
-    Size padding() const { return m_padding; }
-
     Rect visible_content_rect() const;
     Rect visible_content_rect() const;
 
 
     void scroll_into_view(const Rect&, Orientation);
     void scroll_into_view(const Rect&, Orientation);
     void scroll_into_view(const Rect&, bool scroll_horizontally, bool scroll_vertically);
     void scroll_into_view(const Rect&, bool scroll_horizontally, bool scroll_vertically);
 
 
+    void set_scrollbars_enabled(bool);
+    bool is_scrollbars_enabled() const { return m_scrollbars_enabled; }
+
     GScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; }
     GScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; }
     const GScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; }
     const GScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; }
     GScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; }
     GScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; }
@@ -28,15 +27,13 @@ public:
     GWidget& corner_widget() { return *m_corner_widget; }
     GWidget& corner_widget() { return *m_corner_widget; }
     const GWidget& corner_widget() const { return *m_corner_widget; }
     const GWidget& corner_widget() const { return *m_corner_widget; }
 
 
-    void set_scrollbars_enabled(bool);
-    bool is_scrollbars_enabled() const { return m_scrollbars_enabled; }
+    virtual const char* class_name() const override { return "GScrollableWidget"; }
 
 
 protected:
 protected:
     explicit GScrollableWidget(GWidget* parent);
     explicit GScrollableWidget(GWidget* parent);
     virtual void resize_event(GResizeEvent&) override;
     virtual void resize_event(GResizeEvent&) override;
     void set_content_size(const Size&);
     void set_content_size(const Size&);
     void set_size_occupied_by_fixed_elements(const Size&);
     void set_size_occupied_by_fixed_elements(const Size&);
-    void set_padding(const Size&);
 
 
     int width_occupied_by_vertical_scrollbar() const;
     int width_occupied_by_vertical_scrollbar() const;
     int height_occupied_by_horizontal_scrollbar() const;
     int height_occupied_by_horizontal_scrollbar() const;
@@ -49,6 +46,5 @@ private:
     GWidget* m_corner_widget { nullptr };
     GWidget* m_corner_widget { nullptr };
     Size m_content_size;
     Size m_content_size;
     Size m_size_occupied_by_fixed_elements;
     Size m_size_occupied_by_fixed_elements;
-    Size m_padding;
     bool m_scrollbars_enabled { true };
     bool m_scrollbars_enabled { true };
 };
 };

+ 14 - 9
LibGUI/GTextEditor.cpp

@@ -13,7 +13,6 @@ GTextEditor::GTextEditor(Type type, GWidget* parent)
     : GScrollableWidget(parent)
     : GScrollableWidget(parent)
     , m_type(type)
     , m_type(type)
 {
 {
-    set_padding({ 3, 3 });
     set_scrollbars_enabled(is_multi_line());
     set_scrollbars_enabled(is_multi_line());
     m_ruler_visible = is_multi_line();
     m_ruler_visible = is_multi_line();
     set_font(GFontDatabase::the().get_by_name("Csilla Thin"));
     set_font(GFontDatabase::the().get_by_name("Csilla Thin"));
@@ -53,6 +52,7 @@ void GTextEditor::update_content_size()
     int content_width = 0;
     int content_width = 0;
     for (auto& line : m_lines)
     for (auto& line : m_lines)
         content_width = max(line->width(font()), content_width);
         content_width = max(line->width(font()), content_width);
+    content_width += m_horizontal_content_padding * 2;
     int content_height = line_count() * line_height();
     int content_height = line_count() * line_height();
     set_content_size({ content_width, content_height });
     set_content_size({ content_width, content_height });
     set_size_occupied_by_fixed_elements({ ruler_width(), 0 });
     set_size_occupied_by_fixed_elements({ ruler_width(), 0 });
@@ -62,7 +62,7 @@ GTextPosition GTextEditor::text_position_at(const Point& a_position) const
 {
 {
     auto position = a_position;
     auto position = a_position;
     position.move_by(horizontal_scrollbar().value(), vertical_scrollbar().value());
     position.move_by(horizontal_scrollbar().value(), vertical_scrollbar().value());
-    position.move_by(-(padding().width() + ruler_width()), -padding().height());
+    position.move_by(-(m_horizontal_content_padding + ruler_width()), 0);
     int line_index = position.y() / line_height();
     int line_index = position.y() / line_height();
     int column_index = position.x() / glyph_width();
     int column_index = position.x() / glyph_width();
     line_index = max(0, min(line_index, line_count() - 1));
     line_index = max(0, min(line_index, line_count() - 1));
@@ -133,7 +133,7 @@ Rect GTextEditor::ruler_content_rect(int line_index) const
     if (!m_ruler_visible)
     if (!m_ruler_visible)
         return { };
         return { };
     return {
     return {
-        0 - ruler_width() - padding().width() + horizontal_scrollbar().value(),
+        0 - ruler_width() + horizontal_scrollbar().value(),
         line_index * line_height(),
         line_index * line_height(),
         ruler_width(),
         ruler_width(),
         line_height()
         line_height()
@@ -158,7 +158,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
     painter.save();
     painter.save();
 
 
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
     painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
-    painter.translate(padding().width() + ruler_width(), padding().height());
+    painter.translate(ruler_width(), 0);
     int exposed_width = max(content_width(), width());
     int exposed_width = max(content_width(), width());
 
 
     int first_visible_line = text_position_at(event.rect().top_left()).line();
     int first_visible_line = text_position_at(event.rect().top_left()).line();
@@ -194,7 +194,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
         if (line_has_selection) {
         if (line_has_selection) {
             int selection_start_column_on_line = selection.start().line() == i ? selection.start().column() : 0;
             int selection_start_column_on_line = selection.start().line() == i ? selection.start().column() : 0;
             int selection_end_column_on_line = selection.end().line() == i ? selection.end().column() : line.length();
             int selection_end_column_on_line = selection.end().line() == i ? selection.end().column() : line.length();
-            int selection_left = selection_start_column_on_line * font().glyph_width('x');
+            int selection_left = m_horizontal_content_padding + selection_start_column_on_line * font().glyph_width('x');
             int selection_right = line_rect.left() + selection_end_column_on_line * font().glyph_width('x');
             int selection_right = line_rect.left() + selection_end_column_on_line * font().glyph_width('x');
             Rect selection_rect { selection_left, line_rect.y(), selection_right - selection_left, line_rect.height() };
             Rect selection_rect { selection_left, line_rect.y(), selection_right - selection_left, line_rect.height() };
             painter.fill_rect(selection_rect, Color::from_rgb(0x955233));
             painter.fill_rect(selection_rect, Color::from_rgb(0x955233));
@@ -457,13 +457,13 @@ Rect GTextEditor::cursor_content_rect() const
         return { };
         return { };
     ASSERT(!m_lines.is_empty());
     ASSERT(!m_lines.is_empty());
     ASSERT(m_cursor.column() <= (current_line().length() + 1));
     ASSERT(m_cursor.column() <= (current_line().length() + 1));
-    return { m_cursor.column() * glyph_width(), m_cursor.line() * line_height(), 1, line_height() };
+    return { m_horizontal_content_padding + m_cursor.column() * glyph_width(), m_cursor.line() * line_height(), 1, line_height() };
 }
 }
 
 
 Rect GTextEditor::line_widget_rect(int line_index) const
 Rect GTextEditor::line_widget_rect(int line_index) const
 {
 {
     auto rect = line_content_rect(line_index);
     auto rect = line_content_rect(line_index);
-    rect.move_by(-(horizontal_scrollbar().value() - padding().width()), -(vertical_scrollbar().value() - padding().height()));
+    rect.move_by(-(horizontal_scrollbar().value() - m_horizontal_content_padding), -(vertical_scrollbar().value()));
     rect.set_width(rect.width() + 1); // Add 1 pixel for when the cursor is on the end.
     rect.set_width(rect.width() + 1); // Add 1 pixel for when the cursor is on the end.
     rect.intersect(this->rect());
     rect.intersect(this->rect());
     // This feels rather hackish, but extend the rect to the edge of the content view:
     // This feels rather hackish, but extend the rect to the edge of the content view:
@@ -473,13 +473,18 @@ Rect GTextEditor::line_widget_rect(int line_index) const
 
 
 void GTextEditor::scroll_cursor_into_view()
 void GTextEditor::scroll_cursor_into_view()
 {
 {
-    scroll_into_view(cursor_content_rect(), true, true);
+    auto rect = cursor_content_rect();
+    if (m_cursor.column() == 0)
+        rect.set_x(0);
+    else if (m_cursor.column() >= m_lines[m_cursor.line()]->length())
+        rect.set_x(m_lines[m_cursor.line()]->width(font()) + m_horizontal_content_padding * 2);
+    scroll_into_view(rect, true, true);
 }
 }
 
 
 Rect GTextEditor::line_content_rect(int line_index) const
 Rect GTextEditor::line_content_rect(int line_index) const
 {
 {
     return {
     return {
-        0,
+        m_horizontal_content_padding,
         line_index * line_height(),
         line_index * line_height(),
         content_width(),
         content_width(),
         line_height()
         line_height()

+ 2 - 1
LibGUI/GTextEditor.h

@@ -157,7 +157,8 @@ private:
     bool m_cursor_state { true };
     bool m_cursor_state { true };
     bool m_in_drag_select { false };
     bool m_in_drag_select { false };
     bool m_ruler_visible { true };
     bool m_ruler_visible { true };
-    int m_line_spacing { 2 };
+    int m_line_spacing { 4 };
     int m_soft_tab_width { 4 };
     int m_soft_tab_width { 4 };
+    int m_horizontal_content_padding { 2 };
     GTextRange m_selection;
     GTextRange m_selection;
 };
 };