Skip to content

Commit cb296ff

Browse files
committed
LibGUI: Add a GFrame class that can be inherited by framey widgets.
This will gather the code for painting sunken/raised frames etc in a single place and make it easier add a bit of pleasant shading to UI's. :^)
1 parent b6c5bd3 commit cb296ff

File tree

7 files changed

+110
-12
lines changed

7 files changed

+110
-12
lines changed

LibGUI/GFrame.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <LibGUI/GFrame.h>
2+
#include <LibGUI/GStyle.h>
3+
#include <SharedGraphics/Painter.h>
4+
5+
GFrame::GFrame(GWidget* parent)
6+
: GWidget(parent)
7+
{
8+
}
9+
10+
GFrame::~GFrame()
11+
{
12+
}
13+
14+
void GFrame::paint_event(GPaintEvent& event)
15+
{
16+
if (m_shape == Shape::NoFrame)
17+
return;
18+
19+
Painter painter(*this);
20+
painter.set_clip_rect(event.rect());
21+
22+
auto rect = this->rect();
23+
24+
Color top_left_color;
25+
Color bottom_right_color;
26+
27+
if (m_shadow == Shadow::Raised) {
28+
top_left_color = Color::White;
29+
bottom_right_color = Color::MidGray;
30+
} else if (m_shadow == Shadow::Sunken) {
31+
top_left_color = Color::MidGray;
32+
bottom_right_color = Color::White;
33+
} else if (m_shadow == Shadow::Plain) {
34+
top_left_color = Color::MidGray;
35+
bottom_right_color = Color::MidGray;
36+
}
37+
38+
painter.draw_line(rect.top_left(), rect.top_right(), top_left_color);
39+
painter.draw_line(rect.bottom_left(), rect.bottom_right(), bottom_right_color);
40+
41+
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), top_left_color);
42+
painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), bottom_right_color);
43+
}

LibGUI/GFrame.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include <LibGUI/GWidget.h>
4+
5+
class GFrame : public GWidget {
6+
public:
7+
explicit GFrame(GWidget* parent);
8+
virtual ~GFrame() override;
9+
10+
enum Shadow { Plain, Raised, Sunken };
11+
enum Shape { NoFrame, Box, Panel, VerticalLine, HorizontalLine };
12+
13+
int frame_thickness() const { return m_thickness; }
14+
void set_frame_thickness(int thickness) { m_thickness = thickness; }
15+
16+
Shadow frame_shadow() const { return m_shadow; }
17+
void set_frame_shadow(Shadow shadow) { m_shadow = shadow; }
18+
19+
Shape frame_shape() const { return m_shape; }
20+
void set_frame_shape(Shape shape) { m_shape = shape; }
21+
22+
Rect frame_inner_rect() const { return rect().shrunken(m_thickness * 2, m_thickness * 2); }
23+
24+
virtual const char* class_name() const override { return "GFrame"; }
25+
26+
protected:
27+
void paint_event(GPaintEvent&) override;
28+
29+
private:
30+
int m_thickness { 0 };
31+
Shadow m_shadow { Plain };
32+
Shape m_shape { NoFrame };
33+
};

LibGUI/GLabel.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
#include <SharedGraphics/GraphicsBitmap.h>
44

55
GLabel::GLabel(GWidget* parent)
6-
: GWidget(parent)
6+
: GFrame(parent)
77
{
88
}
99

1010
GLabel::GLabel(const String& text, GWidget* parent)
11-
: GWidget(parent)
11+
: GFrame(parent)
1212
, m_text(text)
1313
{
1414
}
@@ -32,21 +32,28 @@ void GLabel::set_text(const String& text)
3232

3333
void GLabel::paint_event(GPaintEvent& event)
3434
{
35+
GFrame::paint_event(event);
36+
3537
Painter painter(*this);
3638
painter.set_clip_rect(event.rect());
3739

38-
if (fill_with_background_color())
39-
painter.fill_rect({ 0, 0, width(), height() }, background_color());
4040
if (m_icon) {
4141
if (m_should_stretch_icon) {
42-
painter.draw_scaled_bitmap(rect(), *m_icon, m_icon->rect());
42+
painter.draw_scaled_bitmap(frame_inner_rect(), *m_icon, m_icon->rect());
4343
} else {
44-
auto icon_location = rect().center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2));
44+
auto icon_location = frame_inner_rect().center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2));
4545
painter.blit(icon_location, *m_icon, m_icon->rect());
4646
}
4747
}
48-
if (!text().is_empty())
49-
painter.draw_text({ 0, 0, width(), height() }, text(), m_text_alignment, foreground_color());
48+
if (!text().is_empty()) {
49+
int indent = 0;
50+
if (frame_thickness() > 0)
51+
indent = font().glyph_width('x') / 2;
52+
auto text_rect = frame_inner_rect();
53+
text_rect.move_by(indent, 0);
54+
text_rect.set_width(text_rect.width() - indent * 2);
55+
painter.draw_text(text_rect, text(), m_text_alignment, foreground_color());
56+
}
5057
}
5158

5259
void GLabel::size_to_fit()

LibGUI/GLabel.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
#pragma once
22

3-
#include "GWidget.h"
4-
#include <AK/AKString.h>
5-
#include <SharedGraphics/Painter.h>
3+
#include <LibGUI/GFrame.h>
4+
#include <SharedGraphics/TextAlignment.h>
65

76
class GraphicsBitmap;
87

9-
class GLabel final : public GWidget {
8+
class GLabel final : public GFrame {
109
public:
1110
explicit GLabel(GWidget* parent);
1211
GLabel(const String& text, GWidget* parent);

LibGUI/GStatusBar.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ GStatusBar::GStatusBar(GWidget* parent)
1212
set_layout(make<GBoxLayout>(Orientation::Horizontal));
1313
layout()->set_margins({ 4, 2, 4, 2 });
1414
m_label = new GLabel(this);
15+
m_label->set_frame_shadow(GFrame::Shadow::Sunken);
16+
m_label->set_frame_shape(GFrame::Shape::Panel);
17+
m_label->set_frame_thickness(1);
1518
m_label->set_text_alignment(TextAlignment::CenterLeft);
1619
}
1720

LibGUI/GTextEditor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,11 @@ Rect GTextEditor::cursor_content_rect() const
492492
return { };
493493
ASSERT(!m_lines.is_empty());
494494
ASSERT(m_cursor.column() <= (current_line().length() + 1));
495+
if (is_single_line()) {
496+
Rect cursor_rect = { m_horizontal_content_padding + m_cursor.column() * glyph_width(), 0, 1, line_height() };
497+
cursor_rect.center_vertically_within(rect());
498+
return cursor_rect;
499+
}
495500
return { m_horizontal_content_padding + m_cursor.column() * glyph_width(), m_cursor.line() * line_height(), 1, line_height() };
496501
}
497502

@@ -518,6 +523,13 @@ void GTextEditor::scroll_cursor_into_view()
518523

519524
Rect GTextEditor::line_content_rect(int line_index) const
520525
{
526+
if (is_single_line()) {
527+
Rect line_rect = { m_horizontal_content_padding, 0, content_width(), font().glyph_height() };
528+
line_rect.center_vertically_within(rect());
529+
// FIXME: This would not be necessary if we knew more about the font and could center it based on baseline and x-height.
530+
line_rect.move_by(0, 1);
531+
return line_rect;
532+
}
521533
return {
522534
m_horizontal_content_padding,
523535
line_index * line_height(),

LibGUI/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ LIBGUI_OBJS = \
5252
GItemView.o \
5353
GIcon.o \
5454
GElapsedTimer.o \
55+
GFrame.o \
5556
GWindow.o
5657

5758
OBJS = $(SHAREDGRAPHICS_OBJS) $(LIBGUI_OBJS)

0 commit comments

Comments
 (0)