LibGUI+LibDraw: Add "Palette" concept for scoped color theming

GApplication now has a palette. This palette contains all the system
theme colors by default, and is inherited by a new top-level GWidget.
New child widgets inherit their parents palette.

It is possible to override the GApplication palette, and the palette
of any GWidget.

The Palette object contains a bunch of colors, each corresponding to
a ColorRole. Each role has a convenience getter as well.

Each GWidget now has a background_role() and foreground_role(), which
are then looked up in their current palette when painting. This means
that you no longer alter the background color of a widget by setting
it directly, rather you alter either its background role, or the
widget's palette.
This commit is contained in:
Andreas Kling 2019-12-24 20:57:54 +01:00
parent cb4e51a7a5
commit a79bac428b
62 changed files with 448 additions and 410 deletions

View file

@ -1,4 +1,5 @@
#include "GlyphMapWidget.h"
#include <LibDraw/Palette.h>
#include <LibGUI/GPainter.h>
GlyphMapWidget::GlyphMapWidget(Font& mutable_font, GWidget* parent)
@ -74,7 +75,7 @@ void GlyphMapWidget::paint_event(GPaintEvent& event)
font().max_glyph_width(),
font().glyph_height());
if (glyph == m_selected_glyph) {
painter.fill_rect(outer_rect, SystemColor::Selection);
painter.fill_rect(outer_rect, palette().selection());
painter.draw_glyph(inner_rect.location(), glyph, Color::White);
} else {
painter.draw_glyph(inner_rect.location(), glyph, Color::Black);

View file

@ -1,6 +1,7 @@
#include "HexEditor.h"
#include <AK/StringBuilder.h>
#include <Kernel/KeyCode.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GClipboard.h>
#include <LibGUI/GFontDatabase.h>
@ -492,7 +493,7 @@ void HexEditor::paint_event(GPaintEvent& event)
text_color = Color::Red;
}
Color highlight_color = SystemColor::Selection;
Color highlight_color = palette().selection();
auto highlight_flag = false;
if (m_selection_start > -1 && m_selection_end > -1) {
if (byte_position >= m_selection_start && byte_position <= m_selection_end) {

View file

@ -156,7 +156,6 @@ void IRCAppWindow::setup_widgets()
auto widget = GWidget::construct();
set_main_widget(widget);
widget->set_fill_with_background_color(true);
widget->set_background_color(SystemColor::Window);
widget->set_layout(make<GBoxLayout>(Orientation::Vertical));
widget->layout()->set_spacing(0);

View file

@ -51,7 +51,6 @@ PaletteWidget::PaletteWidget(PaintableWidget& paintable_widget, GWidget* parent)
set_frame_shadow(FrameShadow::Raised);
set_frame_thickness(0);
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
set_preferred_size(0, 34);

View file

@ -35,7 +35,6 @@ private:
ToolboxWidget::ToolboxWidget(GWidget* parent)
: GFrame(parent)
{
set_background_color(SystemColor::Window);
set_fill_with_background_color(true);
set_frame_thickness(1);

View file

@ -11,7 +11,6 @@ NetworkStatisticsWidget::NetworkStatisticsWidget(GWidget* parent)
set_layout(make<GBoxLayout>(Orientation::Vertical));
layout()->set_margins({ 4, 4, 4, 4 });
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
auto adapters_group_box = GGroupBox::construct("Adapters", this);
adapters_group_box->set_layout(make<GBoxLayout>(Orientation::Vertical));

View file

@ -53,7 +53,6 @@ int main(int argc, char** argv)
auto keeper = GWidget::construct();
keeper->set_layout(make<GBoxLayout>(Orientation::Vertical));
keeper->set_fill_with_background_color(true);
keeper->set_background_color(SystemColor::Window);
keeper->layout()->set_margins({ 4, 4, 4, 4 });
auto tabwidget = GTabWidget::construct(keeper);
@ -192,7 +191,7 @@ class ProgressBarPaintingDelegate final : public GTableCellPaintingDelegate {
public:
virtual ~ProgressBarPaintingDelegate() override {}
virtual void paint(GPainter& painter, const Rect& a_rect, const GModel& model, const GModelIndex& index) override
virtual void paint(GPainter& painter, const Rect& a_rect, const Palette& palette, const GModel& model, const GModelIndex& index) override
{
auto rect = a_rect.shrunken(2, 2);
auto percentage = model.data(index, GModel::Role::Custom).to_int();
@ -201,7 +200,7 @@ public:
String text;
if (data.is_string())
text = data.as_string();
StylePainter::paint_progress_bar(painter, rect, 0, 100, percentage, text);
StylePainter::paint_progress_bar(painter, rect, palette, 0, 100, percentage, text);
painter.draw_rect(rect, Color::Black);
}
};
@ -355,7 +354,7 @@ NonnullRefPtr<GWidget> build_graphs_tab()
graphs_container->on_first_show = [](auto& self) {
self.set_fill_with_background_color(true);
self.set_background_color(SystemColor::Window);
self.set_background_role(ColorRole::Button);
self.set_layout(make<GBoxLayout>(Orientation::Vertical));
self.layout()->set_margins({ 4, 4, 4, 4 });

View file

@ -98,13 +98,13 @@ RefPtr<GWindow> create_settings_window(TerminalWidget& terminal, RefPtr<CConfigF
auto settings = GWidget::construct();
window->set_main_widget(settings);
settings->set_fill_with_background_color(true);
settings->set_background_role(ColorRole::Button);
settings->set_layout(make<GBoxLayout>(Orientation::Vertical));
settings->layout()->set_margins({ 4, 4, 4, 4 });
auto radio_container = GGroupBox::construct("Bell Mode", settings);
radio_container->set_layout(make<GBoxLayout>(Orientation::Vertical));
radio_container->layout()->set_margins({ 6, 16, 6, 6 });
radio_container->set_fill_with_background_color(true);
radio_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
radio_container->set_preferred_size(100, 70);
@ -119,12 +119,9 @@ RefPtr<GWindow> create_settings_window(TerminalWidget& terminal, RefPtr<CConfigF
auto slider_container = GGroupBox::construct("Background Opacity", settings);
slider_container->set_layout(make<GBoxLayout>(Orientation::Vertical));
slider_container->layout()->set_margins({ 6, 16, 6, 6 });
slider_container->set_fill_with_background_color(true);
slider_container->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed);
slider_container->set_preferred_size(100, 50);
auto slider = GSlider::construct(Orientation::Horizontal, slider_container);
slider->set_fill_with_background_color(true);
slider->set_background_color(SystemColor::Window);
slider->on_value_changed = [&terminal, &config](int value) {
terminal.set_opacity(value);

View file

@ -1,10 +1,10 @@
#include "TextWidget.h"
#include <AK/String.h>
#include <AK/StringBuilder.h>
#include <AK/Vector.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GPainter.h>
#include "TextWidget.h"
TextWidget::TextWidget(GWidget* parent)
: GFrame(parent)
{
@ -49,7 +49,7 @@ void TextWidget::paint_event(GPaintEvent& event)
text_rect.set_width(text_rect.width() - indent * 2);
if (is_enabled()) {
painter.draw_text(text_rect, line, m_text_alignment, foreground_color(), TextElision::None);
painter.draw_text(text_rect, line, m_text_alignment, palette().color(foreground_role()), TextElision::None);
} else {
painter.draw_text(text_rect.translated(1, 1), line, font(), text_alignment(), Color::White, TextElision::Right);
painter.draw_text(text_rect, line, font(), text_alignment(), Color::from_rgb(0x808080), TextElision::Right);

View file

@ -31,7 +31,7 @@
#define FIRE_HEIGHT 168
#define FIRE_MAX 29
const Color palette[] = {
static const Color s_palette[] = {
Color(0x07, 0x07, 0x07), Color(0x1F, 0x07, 0x07), Color(0x2F, 0x0F, 0x07),
Color(0x47, 0x0F, 0x07), Color(0x57, 0x17, 0x07), Color(0x67, 0x1F, 0x07),
Color(0x77, 0x1F, 0x07), Color(0x9F, 0x2F, 0x07), Color(0xAF, 0x3F, 0x07),
@ -93,7 +93,7 @@ Fire::Fire(GWidget* parent)
/* Initialize fire palette */
for (int i = 0; i < 30; i++)
bitmap->set_palette_color(i, palette[i]);
bitmap->set_palette_color(i, s_palette[i]);
/* Set remaining entries to white */
for (int i = 30; i < 256; i++)

View file

@ -68,7 +68,7 @@ void Editor::paint_event(GPaintEvent& event)
rect.set_width(rect.width() - vertical_scrollbar().width());
if (horizontal_scrollbar().is_visible())
rect.set_height(rect.height() - horizontal_scrollbar().height());
painter.draw_rect(rect, SystemColor::Selection);
painter.draw_rect(rect, palette().selection());
}
}

View file

@ -7,7 +7,6 @@ FormWidget::FormWidget(FormEditorWidget& parent)
: GWidget(&parent)
{
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
set_relative_rect(5, 5, 400, 300);
set_greedy_for_hits(true);

View file

@ -25,7 +25,6 @@ VBForm::VBForm(const String& name, GWidget* parent)
{
s_current = this;
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
set_greedy_for_hits(true);
m_context_menu = GMenu::construct();

View file

@ -121,7 +121,6 @@ Field::Field(GLabel& flag_label, GLabel& time_label, GButton& face_button, GWidg
m_number_bitmap[i] = GraphicsBitmap::load_from_file(String::format("/res/icons/minesweeper/%u.png", i + 1));
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
reset();
m_face_button.on_click = [this](auto&) { reset(); };

View file

@ -4,94 +4,6 @@
#include <ctype.h>
#include <stdio.h>
Color::Color(SystemColor system_color)
{
auto& theme = current_system_theme();
switch (system_color) {
case SystemColor::Window:
m_value = theme.window.value();
break;
case SystemColor::WindowText:
m_value = theme.window_text.value();
break;
case SystemColor::Base:
m_value = theme.base.value();
break;
case SystemColor::ThreedShadow1:
m_value = theme.threed_shadow1.value();
break;
case SystemColor::ThreedShadow2:
m_value = theme.threed_shadow2.value();
break;
case SystemColor::ThreedHighlight:
m_value = theme.threed_highlight.value();
break;
case SystemColor::Button:
m_value = theme.button.value();
break;
case SystemColor::ButtonText:
m_value = theme.button_text.value();
break;
case SystemColor::HoverHighlight:
m_value = theme.hover_highlight.value();
break;
case SystemColor::Selection:
m_value = theme.selection.value();
break;
case SystemColor::SelectionText:
m_value = theme.selection_text.value();
break;
case SystemColor::DesktopBackground:
m_value = theme.desktop_background.value();
break;
case SystemColor::ActiveWindowBorder1:
m_value = theme.active_window_border1.value();
break;
case SystemColor::ActiveWindowBorder2:
m_value = theme.active_window_border2.value();
break;
case SystemColor::ActiveWindowTitle:
m_value = theme.active_window_title.value();
break;
case SystemColor::InactiveWindowBorder1:
m_value = theme.inactive_window_border1.value();
break;
case SystemColor::InactiveWindowBorder2:
m_value = theme.inactive_window_border2.value();
break;
case SystemColor::InactiveWindowTitle:
m_value = theme.inactive_window_title.value();
break;
case SystemColor::MovingWindowBorder1:
m_value = theme.moving_window_border1.value();
break;
case SystemColor::MovingWindowBorder2:
m_value = theme.moving_window_border2.value();
break;
case SystemColor::MovingWindowTitle:
m_value = theme.moving_window_title.value();
break;
case SystemColor::HighlightWindowBorder1:
m_value = theme.highlight_window_border1.value();
break;
case SystemColor::HighlightWindowBorder2:
m_value = theme.highlight_window_border2.value();
break;
case SystemColor::HighlightWindowTitle:
m_value = theme.highlight_window_title.value();
break;
case SystemColor::MenuStripe:
m_value = theme.menu_stripe.value();
break;
case SystemColor::MenuBase:
m_value = theme.menu_base.value();
break;
case SystemColor::MenuSelection:
m_value = theme.menu_selection.value();
break;
}
}
Color::Color(NamedColor named)
{
struct {

View file

@ -4,6 +4,7 @@
#include <AK/String.h>
#include <AK/Types.h>
enum class ColorRole;
typedef u32 RGBA32;
inline constexpr u32 make_rgb(u8 r, u8 g, u8 b)
@ -11,38 +12,6 @@ inline constexpr u32 make_rgb(u8 r, u8 g, u8 b)
return ((r << 16) | (g << 8) | b);
}
enum class SystemColor {
DesktopBackground,
ActiveWindowBorder1,
ActiveWindowBorder2,
ActiveWindowTitle,
InactiveWindowBorder1,
InactiveWindowBorder2,
InactiveWindowTitle,
MovingWindowBorder1,
MovingWindowBorder2,
MovingWindowTitle,
HighlightWindowBorder1,
HighlightWindowBorder2,
HighlightWindowTitle,
MenuStripe,
MenuBase,
MenuSelection,
Window,
WindowText,
Button,
ButtonText,
Base,
ThreedHighlight,
ThreedShadow1,
ThreedShadow2,
HoverHighlight,
Selection,
SelectionText,
DisabledText = ThreedShadow1,
};
class Color {
public:
enum NamedColor {
@ -71,7 +40,6 @@ public:
Color() {}
Color(NamedColor);
Color(SystemColor);
Color(u8 r, u8 g, u8 b)
: m_value(0xff000000 | (r << 16) | (g << 8) | b)
{

View file

@ -11,6 +11,7 @@ OBJS = \
Rect.o \
StylePainter.o \
SystemTheme.o \
Palette.o \
Emoji.o
LIBRARY = libdraw.a

View file

@ -0,0 +1,26 @@
#include <LibDraw/Palette.h>
NonnullRefPtr<Palette> Palette::create_with_shared_buffer(SharedBuffer& buffer)
{
return adopt(*new Palette(buffer));
}
Palette::Palette(SharedBuffer& buffer)
: m_theme_buffer(buffer)
{
}
Palette::~Palette()
{
}
const SystemTheme& Palette::theme() const
{
return *(const SystemTheme*)m_theme_buffer->data();
}
Color Palette::color(ColorRole role) const
{
ASSERT((int)role < (int)ColorRole::__Count);
return theme().color[(int)role];
}

View file

@ -0,0 +1,51 @@
#pragma once
#include <AK/Badge.h>
#include <LibDraw/SystemTheme.h>
class GApplication;
class Palette : public RefCounted<Palette> {
public:
static NonnullRefPtr<Palette> create_with_shared_buffer(SharedBuffer&);
~Palette();
Color window() const { return color(ColorRole::Window); }
Color window_text() const { return color(ColorRole::WindowText); }
Color selection() const { return color(ColorRole::Selection); }
Color selection_text() const { return color(ColorRole::SelectionText); }
Color desktop_background() const { return color(ColorRole::DesktopBackground); }
Color active_window_border1() const { return color(ColorRole::ActiveWindowBorder1); }
Color active_window_border2() const { return color(ColorRole::ActiveWindowBorder2); }
Color active_window_title() const { return color(ColorRole::ActiveWindowTitle); }
Color inactive_window_border1() const { return color(ColorRole::InactiveWindowBorder1); }
Color inactive_window_border2() const { return color(ColorRole::InactiveWindowBorder2); }
Color inactive_window_title() const { return color(ColorRole::InactiveWindowTitle); }
Color moving_window_border1() const { return color(ColorRole::MovingWindowBorder1); }
Color moving_window_border2() const { return color(ColorRole::MovingWindowBorder2); }
Color moving_window_title() const { return color(ColorRole::MovingWindowTitle); }
Color highlight_window_border1() const { return color(ColorRole::HighlightWindowBorder1); }
Color highlight_window_border2() const { return color(ColorRole::HighlightWindowBorder2); }
Color highlight_window_title() const { return color(ColorRole::HighlightWindowTitle); }
Color menu_stripe() const { return color(ColorRole::MenuStripe); }
Color menu_base() const { return color(ColorRole::MenuBase); }
Color menu_selection() const { return color(ColorRole::MenuSelection); }
Color base() const { return color(ColorRole::Base); }
Color button() const { return color(ColorRole::Button); }
Color button_text() const { return color(ColorRole::ButtonText); }
Color threed_highlight() const { return color(ColorRole::ThreedHighlight); }
Color threed_shadow1() const { return color(ColorRole::ThreedShadow1); }
Color threed_shadow2() const { return color(ColorRole::ThreedShadow2); }
Color hover_highlight() const { return color(ColorRole::ThreedHighlight); }
Color color(ColorRole) const;
const SystemTheme& theme() const;
void replace_internal_buffer(Badge<GApplication>, SharedBuffer& buffer) { m_theme_buffer = buffer; }
private:
explicit Palette(SharedBuffer&);
RefPtr<SharedBuffer> m_theme_buffer;
};

View file

@ -1,15 +1,16 @@
#include <LibDraw/Painter.h>
#include <LibDraw/Palette.h>
#include <LibDraw/StylePainter.h>
void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool active, bool hovered, bool enabled)
void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, const Palette& palette, bool active, bool hovered, bool enabled)
{
Color base_color = SystemColor::Button;
Color highlight_color2 = SystemColor::ThreedHighlight;
Color shadow_color1 = SystemColor::ThreedShadow1;
Color shadow_color2 = SystemColor::ThreedShadow2;
Color base_color = palette.button();
Color highlight_color2 = palette.threed_highlight();
Color shadow_color1 = palette.threed_shadow1();
Color shadow_color2 = palette.threed_shadow2();
if (hovered && enabled && !active)
base_color = StylePainter::hover_highlight_color();
base_color = palette.hover_highlight();
PainterStateSaver saver(painter);
painter.translate(rect.location());
@ -42,20 +43,20 @@ void StylePainter::paint_tab_button(Painter& painter, const Rect& rect, bool act
shadow_color2);
}
static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, bool checked, bool hovered, bool enabled)
static void paint_button_new(Painter& painter, const Rect& rect, const Palette& palette, bool pressed, bool checked, bool hovered, bool enabled)
{
Color button_color = SystemColor::Button;
Color highlight_color2 = SystemColor::ThreedHighlight;
Color shadow_color1 = SystemColor::ThreedShadow1;
Color shadow_color2 = SystemColor::ThreedShadow2;
Color button_color = palette.button();
Color highlight_color2 = palette.threed_highlight();
Color shadow_color1 = palette.threed_shadow1();
Color shadow_color2 = palette.threed_shadow2();
if (checked && enabled) {
if (hovered)
button_color = SystemColor::HoverHighlight;
button_color = palette.hover_highlight();
else
button_color = SystemColor::Button;
button_color = palette.button();
} else if (hovered && enabled)
button_color = StylePainter::hover_highlight_color();
button_color = palette.hover_highlight();
PainterStateSaver saver(painter);
painter.translate(rect.location());
@ -87,14 +88,14 @@ static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, b
}
}
void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled)
void StylePainter::paint_button(Painter& painter, const Rect& rect, const Palette& palette, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled)
{
if (button_style == ButtonStyle::Normal)
return paint_button_new(painter, rect, pressed, checked, hovered, enabled);
return paint_button_new(painter, rect, palette, pressed, checked, hovered, enabled);
Color button_color = SystemColor::Button;
Color highlight_color = SystemColor::ThreedHighlight;
Color shadow_color = Color(96, 96, 96);
Color button_color = palette.button();
Color highlight_color = palette.threed_highlight();
Color shadow_color = palette.threed_shadow1();
if (button_style == ButtonStyle::CoolBar && !enabled)
return;
@ -127,27 +128,27 @@ void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle
}
}
void StylePainter::paint_surface(Painter& painter, const Rect& rect, bool paint_vertical_lines, bool paint_top_line)
void StylePainter::paint_surface(Painter& painter, const Rect& rect, const Palette& palette, bool paint_vertical_lines, bool paint_top_line)
{
painter.fill_rect({ rect.x(), rect.y() + 1, rect.width(), rect.height() - 2 }, SystemColor::Button);
painter.draw_line(rect.top_left(), rect.top_right(), paint_top_line ? SystemColor::ThreedHighlight : SystemColor::Button);
painter.draw_line(rect.bottom_left(), rect.bottom_right(), SystemColor::ThreedShadow1);
painter.fill_rect({ rect.x(), rect.y() + 1, rect.width(), rect.height() - 2 }, palette.button());
painter.draw_line(rect.top_left(), rect.top_right(), paint_top_line ? palette.threed_highlight() : palette.button());
painter.draw_line(rect.bottom_left(), rect.bottom_right(), palette.threed_shadow1());
if (paint_vertical_lines) {
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), SystemColor::ThreedHighlight);
painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), SystemColor::ThreedShadow1);
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), palette.threed_highlight());
painter.draw_line(rect.top_right(), rect.bottom_right().translated(0, -1), palette.threed_shadow1());
}
}
void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape shape, FrameShadow shadow, int thickness, bool skip_vertical_lines)
void StylePainter::paint_frame(Painter& painter, const Rect& rect, const Palette& palette, FrameShape shape, FrameShadow shadow, int thickness, bool skip_vertical_lines)
{
Color top_left_color;
Color bottom_right_color;
Color dark_shade = SystemColor::ThreedShadow1;
Color light_shade = SystemColor::ThreedHighlight;
Color dark_shade = palette.threed_shadow1();
Color light_shade = palette.threed_highlight();
if (shape == FrameShape::Container && thickness >= 2) {
if (shadow == FrameShadow::Raised) {
dark_shade = SystemColor::ThreedShadow2;
dark_shade = palette.threed_shadow2();
}
}
@ -175,10 +176,10 @@ void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape sh
if (shape == FrameShape::Container && thickness >= 2) {
Color top_left_color;
Color bottom_right_color;
Color dark_shade = SystemColor::ThreedShadow2;
Color light_shade = SystemColor::Button;
Color dark_shade = palette.threed_shadow2();
Color light_shade = palette.button();
if (shadow == FrameShadow::Raised) {
dark_shade = SystemColor::ThreedShadow1;
dark_shade = palette.threed_shadow1();
top_left_color = light_shade;
bottom_right_color = dark_shade;
} else if (shadow == FrameShadow::Sunken) {
@ -205,12 +206,12 @@ void StylePainter::paint_frame(Painter& painter, const Rect& rect, FrameShape sh
}
}
void StylePainter::paint_window_frame(Painter& painter, const Rect& rect)
void StylePainter::paint_window_frame(Painter& painter, const Rect& rect, const Palette& palette)
{
Color base_color = SystemColor::Button;
Color dark_shade = SystemColor::ThreedShadow2;
Color mid_shade = SystemColor::ThreedShadow1;
Color light_shade = SystemColor::ThreedHighlight;
Color base_color = palette.button();
Color dark_shade = palette.threed_shadow2();
Color mid_shade = palette.threed_shadow1();
Color light_shade = palette.threed_highlight();
painter.draw_line(rect.top_left(), rect.top_right(), base_color);
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left(), base_color);
@ -227,7 +228,7 @@ void StylePainter::paint_window_frame(Painter& painter, const Rect& rect)
painter.draw_line(rect.bottom_left().translated(2, -2), rect.bottom_right().translated(-2, -2), base_color);
}
void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, int min, int max, int value, const StringView& text)
void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, const Palette& palette, int min, int max, int value, const StringView& text)
{
// First we fill the entire widget with the gradient. This incurs a bit of
// overdraw but ensures a consistent look throughout the progression.
@ -249,7 +250,7 @@ void StylePainter::paint_progress_bar(Painter& painter, const Rect& rect, int mi
Rect hole_rect { (int)progress_width, 0, (int)(rect.width() - progress_width), rect.height() };
hole_rect.move_by(rect.location());
PainterStateSaver saver(painter);
painter.fill_rect(hole_rect, Color::White);
painter.fill_rect(hole_rect, palette.base());
painter.add_clip_rect(hole_rect);
if (!text.is_null())

View file

@ -3,6 +3,7 @@
#include <LibDraw/Color.h>
class Painter;
class Palette;
class Rect;
enum class ButtonStyle {
@ -25,12 +26,10 @@ enum class FrameShape {
class StylePainter {
public:
static void paint_button(Painter&, const Rect&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true);
static void paint_tab_button(Painter&, const Rect&, bool active, bool hovered, bool enabled);
static void paint_surface(Painter&, const Rect&, bool paint_vertical_lines = true, bool paint_top_line = true);
static void paint_frame(Painter&, const Rect&, FrameShape, FrameShadow, int thickness, bool skip_vertical_lines = false);
static void paint_window_frame(Painter&, const Rect&);
static void paint_progress_bar(Painter&, const Rect&, int min, int max, int value, const StringView& text = {});
static Color hover_highlight_color() { return SystemColor::HoverHighlight; }
static void paint_button(Painter&, const Rect&, const Palette&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true);
static void paint_tab_button(Painter&, const Rect&, const Palette&, bool active, bool hovered, bool enabled);
static void paint_surface(Painter&, const Rect&, const Palette&, bool paint_vertical_lines = true, bool paint_top_line = true);
static void paint_frame(Painter&, const Rect&, const Palette&, FrameShape, FrameShadow, int thickness, bool skip_vertical_lines = false);
static void paint_window_frame(Painter&, const Rect&, const Palette&);
static void paint_progress_bar(Painter&, const Rect&, const Palette&, int min, int max, int value, const StringView& text = {});
};

View file

@ -41,34 +41,37 @@ RefPtr<SharedBuffer> load_system_theme(const String& path)
return color.value();
};
data->desktop_background = get("DesktopBackground");
data->threed_highlight = get("ThreedHighlight");
data->threed_shadow1 = get("ThreedShadow1");
data->threed_shadow2 = get("ThreedShadow2");
data->hover_highlight = get("HoverHighlight");
data->selection = get("Selection");
data->selection_text = get("SelectionText");
data->window = get("Window");
data->window_text = get("WindowText");
data->base = get("Base");
data->button = get("Button");
data->button_text = get("ButtonText");
data->desktop_background = get("DesktopBackground");
data->active_window_border1 = get("ActiveWindowBorder1");
data->active_window_border2 = get("ActiveWindowBorder2");
data->active_window_title = get("ActiveWindowTitle");
data->inactive_window_border1 = get("InactiveWindowBorder1");
data->inactive_window_border2 = get("InactiveWindowBorder2");
data->inactive_window_title = get("InactiveWindowTitle");
data->moving_window_border1 = get("MovingWindowBorder1");
data->moving_window_border2 = get("MovingWindowBorder2");
data->moving_window_title = get("MovingWindowTitle");
data->highlight_window_border1 = get("HighlightWindowBorder1");
data->highlight_window_border2 = get("HighlightWindowBorder2");
data->highlight_window_title = get("HighlightWindowTitle");
data->menu_stripe = get("MenuStripe");
data->menu_base = get("MenuBase");
data->menu_selection = get("MenuSelection");
#define DO_COLOR(x) \
data->color[(int)ColorRole::x] = get(#x)
DO_COLOR(DesktopBackground);
DO_COLOR(ThreedHighlight);
DO_COLOR(ThreedShadow1);
DO_COLOR(ThreedShadow2);
DO_COLOR(HoverHighlight);
DO_COLOR(Selection);
DO_COLOR(SelectionText);
DO_COLOR(Window);
DO_COLOR(WindowText);
DO_COLOR(Base);
DO_COLOR(Button);
DO_COLOR(ButtonText);
DO_COLOR(DesktopBackground);
DO_COLOR(ActiveWindowBorder1);
DO_COLOR(ActiveWindowBorder2);
DO_COLOR(ActiveWindowTitle);
DO_COLOR(InactiveWindowBorder1);
DO_COLOR(InactiveWindowBorder2);
DO_COLOR(InactiveWindowTitle);
DO_COLOR(MovingWindowBorder1);
DO_COLOR(MovingWindowBorder2);
DO_COLOR(MovingWindowTitle);
DO_COLOR(HighlightWindowBorder1);
DO_COLOR(HighlightWindowBorder2);
DO_COLOR(HighlightWindowTitle);
DO_COLOR(MenuStripe);
DO_COLOR(MenuBase);
DO_COLOR(MenuSelection);
buffer->seal();
buffer->share_globally();

View file

@ -4,43 +4,43 @@
#include <LibC/SharedBuffer.h>
#include <LibDraw/Color.h>
enum class ColorRole {
NoRole,
DesktopBackground,
ActiveWindowBorder1,
ActiveWindowBorder2,
ActiveWindowTitle,
InactiveWindowBorder1,
InactiveWindowBorder2,
InactiveWindowTitle,
MovingWindowBorder1,
MovingWindowBorder2,
MovingWindowTitle,
HighlightWindowBorder1,
HighlightWindowBorder2,
HighlightWindowTitle,
MenuStripe,
MenuBase,
MenuSelection,
Window,
WindowText,
Button,
ButtonText,
Base,
ThreedHighlight,
ThreedShadow1,
ThreedShadow2,
HoverHighlight,
Selection,
SelectionText,
__Count,
DisabledText = ThreedShadow1,
};
struct SystemTheme {
Color desktop_background;
Color active_window_border1;
Color active_window_border2;
Color active_window_title;
Color inactive_window_border1;
Color inactive_window_border2;
Color inactive_window_title;
Color moving_window_border1;
Color moving_window_border2;
Color moving_window_title;
Color highlight_window_border1;
Color highlight_window_border2;
Color highlight_window_title;
Color menu_stripe;
Color menu_base;
Color menu_selection;
Color window;
Color window_text;
Color base;
Color button;
Color button_text;
Color threed_highlight;
Color threed_shadow1;
Color threed_shadow2;
Color hover_highlight;
Color selection;
Color selection_text;
Color color[(int)ColorRole::__Count];
};
const SystemTheme& current_system_theme();

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibGUI/GAbstractButton.h>
#include <LibGUI/GPainter.h>
@ -154,7 +155,7 @@ void GAbstractButton::paint_text(GPainter& painter, const Rect& rect, const Font
if (text().is_empty())
return;
painter.draw_text(clipped_rect, text(), font, text_alignment, SystemColor::ButtonText, TextElision::Right);
painter.draw_text(clipped_rect, text(), font, text_alignment, palette().button_text(), TextElision::Right);
if (is_focused())
painter.draw_rect(clipped_rect.inflated(6, 4), Color(140, 140, 140));
}

View file

@ -1,4 +1,5 @@
#include <AK/StringBuilder.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GAbstractColumnView.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GMenu.h>
@ -99,9 +100,9 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
if (!headers_visible())
return;
int exposed_width = max(content_size().width(), width());
painter.fill_rect({ 0, 0, exposed_width, header_height() }, SystemColor::Window);
painter.draw_line({ 0, 0 }, { exposed_width - 1, 0 }, SystemColor::ThreedHighlight);
painter.draw_line({ 0, header_height() - 1 }, { exposed_width - 1, header_height() - 1 }, SystemColor::ThreedShadow1);
painter.fill_rect({ 0, 0, exposed_width, header_height() }, palette().button());
painter.draw_line({ 0, 0 }, { exposed_width - 1, 0 }, palette().threed_highlight());
painter.draw_line({ 0, header_height() - 1 }, { exposed_width - 1, header_height() - 1 }, palette().threed_shadow1());
int x_offset = 0;
int column_count = model()->column_count();
for (int column_index = 0; column_index < column_count; ++column_index) {
@ -112,7 +113,7 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
Rect cell_rect(x_offset, 0, column_width + horizontal_padding() * 2, header_height());
bool pressed = column_index == m_pressed_column_header_index && m_pressed_column_header_is_pressed;
bool hovered = column_index == m_hovered_column_header_index && model()->column_metadata(column_index).sortable == GModel::ColumnMetadata::Sortable::True;
StylePainter::paint_button(painter, cell_rect, ButtonStyle::Normal, pressed, hovered);
StylePainter::paint_button(painter, cell_rect, palette(), ButtonStyle::Normal, pressed, hovered);
String text;
if (is_key_column) {
StringBuilder builder;
@ -129,7 +130,7 @@ void GAbstractColumnView::paint_headers(GPainter& painter)
auto text_rect = cell_rect.translated(horizontal_padding(), 0);
if (pressed)
text_rect.move_by(1, 1);
painter.draw_text(text_rect, text, header_font(), TextAlignment::CenterLeft, SystemColor::ButtonText);
painter.draw_text(text_rect, text, header_font(), TextAlignment::CenterLeft, palette().button_text());
x_offset += column_width + horizontal_padding() * 2;
}
}

View file

@ -9,7 +9,7 @@ class GTableCellPaintingDelegate {
public:
virtual ~GTableCellPaintingDelegate() {}
virtual void paint(GPainter&, const Rect&, const GModel&, const GModelIndex&) = 0;
virtual void paint(GPainter&, const Rect&, const Palette&, const GModel&, const GModelIndex&) = 0;
};
class GAbstractColumnView : public GAbstractView {

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
#include <LibGUI/GDesktop.h>
@ -142,3 +143,19 @@ void GApplication::did_delete_last_window(Badge<GWindow>)
if (m_quit_when_last_window_deleted)
m_event_loop->quit(0);
}
void GApplication::set_system_palette(SharedBuffer& buffer)
{
if (!m_system_palette)
m_system_palette = Palette::create_with_shared_buffer(buffer);
else
m_system_palette->replace_internal_buffer({}, buffer);
if (!m_palette)
m_palette = m_system_palette;
}
void GApplication::set_palette(const Palette& palette)
{
m_palette = palette;
}

View file

@ -10,7 +10,10 @@ class GAction;
class GKeyEvent;
class GMenuBar;
class GWindow;
class GWindowServerConnection;
class Palette;
class Point;
class SharedBuffer;
class GApplication {
public:
@ -39,9 +42,16 @@ public:
const String& invoked_as() const { return m_invoked_as; }
const Vector<String>& args() const { return m_args; }
const Palette& palette() const { return *m_palette; }
void set_palette(const Palette&);
void set_system_palette(SharedBuffer&);
private:
OwnPtr<CEventLoop> m_event_loop;
OwnPtr<GMenuBar> m_menubar;
RefPtr<Palette> m_palette;
RefPtr<Palette> m_system_palette;
HashMap<GShortcut, GAction*> m_global_shortcut_actions;
class TooltipWindow;
TooltipWindow* m_tooltip_window { nullptr };

View file

@ -27,7 +27,7 @@ void GButton::paint_event(GPaintEvent& event)
GPainter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_button(painter, rect(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled());
StylePainter::paint_button(painter, rect(), palette(), m_button_style, is_being_pressed(), is_hovered(), is_checked(), is_enabled());
if (text().is_empty() && !m_icon)
return;

View file

@ -1,8 +1,9 @@
#include <Kernel/KeyCode.h>
#include <LibDraw/CharacterBitmap.h>
#include <LibDraw/Palette.h>
#include <LibDraw/StylePainter.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GPainter.h>
#include <LibDraw/CharacterBitmap.h>
#include <LibDraw/StylePainter.h>
static const char* s_checked_bitmap_data = {
" "
@ -48,14 +49,14 @@ void GCheckBox::paint_event(GPaintEvent& event)
text_rect.set_height(font().glyph_height());
if (fill_with_background_color())
painter.fill_rect(rect(), background_color());
painter.fill_rect(rect(), palette().window());
Rect box_rect {
0, height() / 2 - s_box_height / 2 - 1,
s_box_width, s_box_height
};
painter.fill_rect(box_rect, SystemColor::Base);
StylePainter::paint_frame(painter, box_rect, FrameShape::Container, FrameShadow::Sunken, 2);
painter.fill_rect(box_rect, palette().base());
StylePainter::paint_frame(painter, box_rect, palette(), FrameShape::Container, FrameShadow::Sunken, 2);
if (is_being_pressed())
painter.draw_rect(box_rect.shrunken(4, 4), Color::MidGray);
@ -63,7 +64,7 @@ void GCheckBox::paint_event(GPaintEvent& event)
if (is_checked()) {
if (!s_checked_bitmap)
s_checked_bitmap = &CharacterBitmap::create_from_ascii(s_checked_bitmap_data, s_checked_bitmap_width, s_checked_bitmap_height).leak_ref();
painter.draw_bitmap(box_rect.shrunken(4, 4).location(), *s_checked_bitmap, SystemColor::ButtonText);
painter.draw_bitmap(box_rect.shrunken(4, 4).location(), *s_checked_bitmap, palette().button_text());
}
paint_text(painter, text_rect, font(), TextAlignment::TopLeft);

View file

@ -58,7 +58,6 @@ GFilePicker::GFilePicker(Mode mode, const StringView& file_name, const StringVie
horizontal_container->set_layout(make<GBoxLayout>(Orientation::Horizontal));
horizontal_container->layout()->set_margins({ 4, 4, 4, 4 });
horizontal_container->set_fill_with_background_color(true);
horizontal_container->set_background_color(SystemColor::Window);
auto vertical_container = GWidget::construct(horizontal_container.ptr());
vertical_container->set_layout(make<GBoxLayout>(Orientation::Vertical));

View file

@ -18,5 +18,5 @@ void GFrame::paint_event(GPaintEvent& event)
GPainter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_frame(painter, rect(), m_shape, m_shadow, m_thickness, spans_entire_window_horizontally());
StylePainter::paint_frame(painter, rect(), palette(), m_shape, m_shadow, m_thickness, spans_entire_window_horizontally());
}

View file

@ -1,6 +1,7 @@
#include <LibDraw/Palette.h>
#include <LibDraw/StylePainter.h>
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GPainter.h>
#include <LibDraw/StylePainter.h>
GGroupBox::GGroupBox(GWidget* parent)
: GGroupBox({}, parent)
@ -11,8 +12,6 @@ GGroupBox::GGroupBox(const StringView& title, GWidget* parent)
: GWidget(parent)
, m_title(title)
{
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
}
GGroupBox::~GGroupBox()
@ -28,11 +27,11 @@ void GGroupBox::paint_event(GPaintEvent& event)
0, font().glyph_height() / 2,
width(), height() - font().glyph_height() / 2
};
StylePainter::paint_frame(painter, frame_rect, FrameShape::Box, FrameShadow::Sunken, 2);
StylePainter::paint_frame(painter, frame_rect, palette(), FrameShape::Box, FrameShadow::Sunken, 2);
Rect text_rect { 4, 0, font().width(m_title) + 6, font().glyph_height() };
painter.fill_rect(text_rect, background_color());
painter.draw_text(text_rect, m_title, TextAlignment::Center, foreground_color());
painter.fill_rect(text_rect, palette().button());
painter.draw_text(text_rect, m_title, TextAlignment::Center, palette().button_text());
}
void GGroupBox::set_title(const StringView& title)

View file

@ -1,5 +1,6 @@
#include <AK/StringBuilder.h>
#include <Kernel/KeyCode.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GDragOperation.h>
#include <LibGUI/GItemView.h>
#include <LibGUI/GModel.h>
@ -186,12 +187,13 @@ void GItemView::doubleclick_event(GMouseEvent& event)
void GItemView::paint_event(GPaintEvent& event)
{
Color widget_background_color = palette().color(background_role());
GFrame::paint_event(event);
GPainter painter(*this);
painter.add_clip_rect(widget_inner_rect());
painter.add_clip_rect(event.rect());
painter.fill_rect(event.rect(), SystemColor::Base);
painter.fill_rect(event.rect(), widget_background_color);
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
auto column_metadata = model()->column_metadata(m_model_column);
@ -201,9 +203,9 @@ void GItemView::paint_event(GPaintEvent& event)
bool is_selected_item = selection().contains(model()->index(item_index, m_model_column));
Color background_color;
if (is_selected_item) {
background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
} else {
background_color = SystemColor::Base;
background_color = widget_background_color;
}
Rect item_rect = this->item_rect(item_index);
@ -228,9 +230,9 @@ void GItemView::paint_event(GPaintEvent& event)
Color text_color;
if (is_selected_item)
text_color = SystemColor::SelectionText;
text_color = palette().selection_text();
else
text_color = model()->data(model_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
text_color = model()->data(model_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
painter.fill_rect(text_rect, background_color);
painter.draw_text(text_rect, item_text.to_string(), font, TextAlignment::Center, text_color, TextElision::Right);
};

View file

@ -1,6 +1,7 @@
#include "GLabel.h"
#include <LibGUI/GPainter.h>
#include <LibDraw/GraphicsBitmap.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GLabel.h>
#include <LibGUI/GPainter.h>
GLabel::GLabel(GWidget* parent)
: GFrame(parent)
@ -58,7 +59,7 @@ void GLabel::paint_event(GPaintEvent& event)
text_rect.set_width(text_rect.width() - indent * 2);
if (is_enabled()) {
painter.draw_text(text_rect, text(), m_text_alignment, foreground_color(), TextElision::Right);
painter.draw_text(text_rect, text(), m_text_alignment, palette().window_text(), TextElision::Right);
} else {
painter.draw_text(text_rect.translated(1, 1), text(), font(), text_alignment(), Color::White, TextElision::Right);
painter.draw_text(text_rect, text(), font(), text_alignment(), Color::from_rgb(0x808080), TextElision::Right);

View file

@ -1,4 +1,5 @@
#include <Kernel/KeyCode.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GListView.h>
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
@ -6,6 +7,7 @@
GListView::GListView(GWidget* parent)
: GAbstractView(parent)
{
set_background_role(ColorRole::Base);
set_frame_shape(FrameShape::Container);
set_frame_shadow(FrameShadow::Sunken);
set_frame_thickness(2);
@ -104,12 +106,12 @@ void GListView::paint_event(GPaintEvent& event)
Color background_color;
if (is_selected_row) {
background_color = is_focused() ? Color(SystemColor::SelectionText) : Color::from_rgb(0x606060);
background_color = is_focused() ? palette().selection_text() : Color::from_rgb(0x606060);
} else {
if (alternating_row_colors() && (painted_item_index % 2))
background_color = Color(210, 210, 210);
else
background_color = SystemColor::Base;
background_color = palette().color(background_role());
}
auto column_metadata = model()->column_metadata(m_model_column);
@ -129,7 +131,7 @@ void GListView::paint_event(GPaintEvent& event)
if (is_selected_row)
text_color = Color::White;
else
text_color = model()->data(index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
text_color = model()->data(index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
auto text_rect = row_rect;
text_rect.move_by(horizontal_padding(), 0);
text_rect.set_width(text_rect.width() - horizontal_padding() * 2);
@ -140,7 +142,7 @@ void GListView::paint_event(GPaintEvent& event)
};
Rect unpainted_rect(0, painted_item_index * item_height(), exposed_width, height());
painter.fill_rect(unpainted_rect, SystemColor::Base);
painter.fill_rect(unpainted_rect, palette().color(background_role()));
}
int GListView::item_count() const

View file

@ -58,5 +58,5 @@ void GProgressBar::paint_event(GPaintEvent& event)
progress_text = builder.to_string();
}
StylePainter::paint_progress_bar(painter, rect, m_min, m_max, m_value, progress_text);
StylePainter::paint_progress_bar(painter, rect, palette(), m_min, m_max, m_value, progress_text);
}

View file

@ -1,11 +1,13 @@
#include <LibDraw/GraphicsBitmap.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GPainter.h>
#include <LibGUI/GResizeCorner.h>
#include <LibGUI/GWindow.h>
#include <LibDraw/GraphicsBitmap.h>
GResizeCorner::GResizeCorner(GWidget* parent)
: GWidget(parent)
{
set_background_role(ColorRole::Button);
set_size_policy(SizePolicy::Fixed, SizePolicy::Fixed);
set_preferred_size(16, 16);
m_bitmap = GraphicsBitmap::load_from_file("/res/icons/resize-corner.png");
@ -20,7 +22,7 @@ void GResizeCorner::paint_event(GPaintEvent& event)
{
GPainter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(rect(), SystemColor::Button);
painter.fill_rect(rect(), palette().color(background_role()));
painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
GWidget::paint_event(event);
}

View file

@ -1,5 +1,6 @@
#include <LibDraw/CharacterBitmap.h>
#include <LibDraw/GraphicsBitmap.h>
#include <LibDraw/Palette.h>
#include <LibDraw/StylePainter.h>
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
@ -203,18 +204,18 @@ void GScrollBar::paint_event(GPaintEvent& event)
GPainter painter(*this);
painter.add_clip_rect(event.rect());
painter.fill_rect(rect(), Color(SystemColor::Button).lightened());
painter.fill_rect(rect(), palette().button().lightened());
StylePainter::paint_button(painter, decrement_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton);
StylePainter::paint_button(painter, increment_button_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton);
StylePainter::paint_button(painter, decrement_button_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::DecrementButton);
StylePainter::paint_button(painter, increment_button_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::IncrementButton);
if (length(orientation()) > default_button_size()) {
painter.draw_bitmap(decrement_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? SystemColor::ButtonText : SystemColor::DisabledText);
painter.draw_bitmap(increment_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? SystemColor::ButtonText : SystemColor::DisabledText);
painter.draw_bitmap(decrement_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_up_arrow_bitmap : *s_left_arrow_bitmap, has_scrubber() ? palette().button_text() : palette().threed_shadow1());
painter.draw_bitmap(increment_button_rect().location().translated(3, 3), orientation() == Orientation::Vertical ? *s_down_arrow_bitmap : *s_right_arrow_bitmap, has_scrubber() ? palette().button_text() : palette().threed_shadow1());
}
if (has_scrubber())
StylePainter::paint_button(painter, scrubber_rect(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber || m_scrubber_in_use);
StylePainter::paint_button(painter, scrubber_rect(), palette(), ButtonStyle::Normal, false, m_hovered_component == Component::Scrubber || m_scrubber_in_use);
}
void GScrollBar::on_automatic_scrolling_timer_fired()

View file

@ -62,8 +62,8 @@ void GSlider::paint_event(GPaintEvent& event)
track_rect.center_horizontally_within(inner_rect());
}
StylePainter::paint_frame(painter, track_rect, FrameShape::Panel, FrameShadow::Sunken, 1);
StylePainter::paint_button(painter, knob_rect(), ButtonStyle::Normal, false, m_knob_hovered);
StylePainter::paint_frame(painter, track_rect, palette(), FrameShape::Panel, FrameShadow::Sunken, 1);
StylePainter::paint_button(painter, knob_rect(), palette(), ButtonStyle::Normal, false, m_knob_hovered);
}
Rect GSlider::knob_rect() const

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GSplitter.h>
#include <LibGUI/GWindow.h>
@ -6,9 +7,9 @@ GSplitter::GSplitter(Orientation orientation, GWidget* parent)
: GFrame(parent)
, m_orientation(orientation)
{
set_background_role(ColorRole::Button);
set_layout(make<GBoxLayout>(orientation));
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
layout()->set_spacing(3);
}
@ -18,14 +19,14 @@ GSplitter::~GSplitter()
void GSplitter::enter_event(CEvent&)
{
set_background_color(StylePainter::hover_highlight_color());
set_background_role(ColorRole::HoverHighlight);
window()->set_override_cursor(m_orientation == Orientation::Horizontal ? GStandardCursor::ResizeHorizontal : GStandardCursor::ResizeVertical);
update();
}
void GSplitter::leave_event(CEvent&)
{
set_background_color(SystemColor::Window);
set_background_role(ColorRole::Button);
if (!m_resizing)
window()->set_override_cursor(GStandardCursor::None);
update();

View file

@ -66,5 +66,5 @@ void GStatusBar::paint_event(GPaintEvent& event)
{
GPainter painter(*this);
painter.add_clip_rect(event.rect());
StylePainter::paint_surface(painter, rect(), !spans_entire_window_horizontally());
StylePainter::paint_surface(painter, rect(), palette(), !spans_entire_window_horizontally());
}

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibDraw/StylePainter.h>
#include <LibGUI/GBoxLayout.h>
#include <LibGUI/GPainter.h>
@ -6,8 +7,6 @@
GTabWidget::GTabWidget(GWidget* parent)
: GWidget(parent)
{
set_fill_with_background_color(true);
set_background_color(SystemColor::Window);
}
GTabWidget::~GTabWidget()
@ -112,19 +111,19 @@ void GTabWidget::paint_event(GPaintEvent& event)
auto container_rect = this->container_rect();
auto padding_rect = container_rect;
for (int i = 0; i < container_padding(); ++i) {
painter.draw_rect(padding_rect, background_color());
painter.draw_rect(padding_rect, palette().button());
padding_rect.shrink(2, 2);
}
StylePainter::paint_frame(painter, container_rect, FrameShape::Container, FrameShadow::Raised, 2);
StylePainter::paint_frame(painter, container_rect, palette(), FrameShape::Container, FrameShadow::Raised, 2);
for (int i = 0; i < m_tabs.size(); ++i) {
if (m_tabs[i].widget == m_active_widget)
continue;
bool hovered = i == m_hovered_tab_index;
auto button_rect = this->button_rect(i);
StylePainter::paint_tab_button(painter, button_rect, false, hovered, m_tabs[i].widget->is_enabled());
painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, SystemColor::ButtonText);
StylePainter::paint_tab_button(painter, button_rect, palette(), false, hovered, m_tabs[i].widget->is_enabled());
painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, palette().button_text());
}
for (int i = 0; i < m_tabs.size(); ++i) {
@ -132,9 +131,9 @@ void GTabWidget::paint_event(GPaintEvent& event)
continue;
bool hovered = i == m_hovered_tab_index;
auto button_rect = this->button_rect(i);
StylePainter::paint_tab_button(painter, button_rect, true, hovered, m_tabs[i].widget->is_enabled());
painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, SystemColor::ButtonText);
painter.draw_line(button_rect.bottom_left().translated(1, 1), button_rect.bottom_right().translated(-1, 1), SystemColor::Button);
StylePainter::paint_tab_button(painter, button_rect, palette(), true, hovered, m_tabs[i].widget->is_enabled());
painter.draw_text(button_rect.translated(0, 1), m_tabs[i].title, TextAlignment::Center, palette().button_text());
painter.draw_line(button_rect.bottom_left().translated(1, 1), button_rect.bottom_right().translated(-1, 1), palette().button());
break;
}
}

View file

@ -1,5 +1,6 @@
#include <AK/StringBuilder.h>
#include <Kernel/KeyCode.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GMenu.h>
#include <LibGUI/GModel.h>
@ -12,6 +13,7 @@
GTableView::GTableView(GWidget* parent)
: GAbstractColumnView(parent)
{
set_background_role(ColorRole::Base);
}
GTableView::~GTableView()
@ -20,12 +22,13 @@ GTableView::~GTableView()
void GTableView::paint_event(GPaintEvent& event)
{
Color widget_background_color = palette().color(background_role());
GFrame::paint_event(event);
GPainter painter(*this);
painter.add_clip_rect(frame_inner_rect());
painter.add_clip_rect(event.rect());
painter.fill_rect(event.rect(), SystemColor::Base);
painter.fill_rect(event.rect(), widget_background_color);
painter.translate(frame_thickness(), frame_thickness());
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
@ -53,15 +56,15 @@ void GTableView::paint_event(GPaintEvent& event)
Color background_color;
Color key_column_background_color;
if (is_selected_row) {
background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
key_column_background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
key_column_background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
} else {
if (alternating_row_colors() && (painted_item_index % 2)) {
background_color = Color(SystemColor::Base).darkened(0.8f);
key_column_background_color = Color(SystemColor::Base).darkened(0.7f);
background_color = widget_background_color.darkened(0.8f);
key_column_background_color = widget_background_color.darkened(0.7f);
} else {
background_color = SystemColor::Base;
key_column_background_color = Color(SystemColor::Base).darkened(0.9f);
background_color = widget_background_color;
key_column_background_color = widget_background_color.darkened(0.9f);
}
}
painter.fill_rect(row_rect(painted_item_index), background_color);
@ -82,7 +85,7 @@ void GTableView::paint_event(GPaintEvent& event)
auto cell_index = model()->index(row_index, column_index);
if (auto* delegate = column_data(column_index).cell_painting_delegate.ptr()) {
delegate->paint(painter, cell_rect, *model(), cell_index);
delegate->paint(painter, cell_rect, palette(), *model(), cell_index);
} else {
auto data = model()->data(cell_index);
if (data.is_bitmap()) {
@ -93,9 +96,9 @@ void GTableView::paint_event(GPaintEvent& event)
} else {
Color text_color;
if (is_selected_row)
text_color = SystemColor::SelectionText;
text_color = palette().selection_text();
else
text_color = model()->data(cell_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
text_color = model()->data(cell_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
painter.draw_text(cell_rect, data.to_string(), font, column_metadata.text_alignment, text_color, TextElision::Right);
}
}
@ -105,7 +108,7 @@ void GTableView::paint_event(GPaintEvent& event)
};
Rect unpainted_rect(0, header_height() + painted_item_index * item_height(), exposed_width, height());
painter.fill_rect(unpainted_rect, SystemColor::Base);
painter.fill_rect(unpainted_rect, widget_background_color);
// Untranslate the painter vertically and do the column headers.
painter.translate(0, vertical_scrollbar().value());

View file

@ -1,6 +1,7 @@
#include <AK/QuickSort.h>
#include <AK/StringBuilder.h>
#include <Kernel/KeyCode.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GClipboard.h>
#include <LibGUI/GFontDatabase.h>
@ -295,6 +296,7 @@ Rect GTextEditor::visible_text_rect_in_inner_coordinates() const
void GTextEditor::paint_event(GPaintEvent& event)
{
Color widget_background_color = palette().color(background_role());
// NOTE: This ensures that spans are updated before we look at them.
flush_pending_change_notification_if_needed();
@ -303,15 +305,15 @@ void GTextEditor::paint_event(GPaintEvent& event)
GPainter painter(*this);
painter.add_clip_rect(widget_inner_rect());
painter.add_clip_rect(event.rect());
painter.fill_rect(event.rect(), SystemColor::Base);
painter.fill_rect(event.rect(), widget_background_color);
painter.translate(frame_thickness(), frame_thickness());
auto ruler_rect = ruler_rect_in_inner_coordinates();
if (m_ruler_visible) {
painter.fill_rect(ruler_rect, Color(SystemColor::Base).darkened(0.85f));
painter.draw_line(ruler_rect.top_right(), ruler_rect.bottom_right(), Color(SystemColor::Base).darkened(0.5f));
painter.fill_rect(ruler_rect, widget_background_color.darkened(0.85f));
painter.draw_line(ruler_rect.top_right(), ruler_rect.bottom_right(), widget_background_color.darkened(0.5f));
}
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
@ -333,7 +335,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
String::number(i + 1),
is_current_line ? Font::default_bold_font() : font(),
TextAlignment::TopRight,
is_current_line ? Color(SystemColor::Base).darkened(0.6f) : Color(SystemColor::Base).darkened(0.7f));
is_current_line ? widget_background_color.darkened(0.6f) : widget_background_color.darkened(0.7f));
}
}
@ -369,13 +371,13 @@ void GTextEditor::paint_event(GPaintEvent& event)
size_t visual_line_index = 0;
for_each_visual_line(line_index, [&](const Rect& visual_line_rect, const StringView& visual_line_text, size_t start_of_visual_line) {
if (is_multi_line() && line_index == m_cursor.line())
painter.fill_rect(visual_line_rect, Color(SystemColor::Base).darkened(0.9f));
painter.fill_rect(visual_line_rect, widget_background_color.darkened(0.9f));
#ifdef DEBUG_GTEXTEDITOR
painter.draw_rect(visual_line_rect, Color::Cyan);
#endif
if (!document().has_spans()) {
// Fast-path for plain text
painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, SystemColor::WindowText);
painter.draw_text(visual_line_rect, visual_line_text, m_text_alignment, palette().color(foreground_role()));
} else {
int advance = font().glyph_width(' ') + font().glyph_spacing();
Rect character_rect = { visual_line_rect.location(), { font().glyph_width(' '), line_height() } };
@ -424,7 +426,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
visual_line_rect.height()
};
painter.fill_rect(selection_rect, SystemColor::Selection);
painter.fill_rect(selection_rect, palette().selection());
size_t start_of_selection_within_visual_line = (size_t)max(0, (int)selection_start_column_within_line - (int)start_of_visual_line);
size_t end_of_selection_within_visual_line = selection_end_column_within_line - start_of_visual_line;
@ -434,7 +436,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
end_of_selection_within_visual_line - start_of_selection_within_visual_line
};
painter.draw_text(selection_rect, visual_selected_text, TextAlignment::CenterLeft, SystemColor::SelectionText);
painter.draw_text(selection_rect, visual_selected_text, TextAlignment::CenterLeft, palette().selection_text());
}
}
++visual_line_index;

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GActionGroup.h>
#include <LibGUI/GBoxLayout.h>
@ -71,8 +72,8 @@ public:
GPainter painter(*this);
painter.add_clip_rect(event.rect());
painter.translate(rect().center().x() - 1, 0);
painter.draw_line({ 0, 0 }, { 0, rect().bottom() }, SystemColor::ThreedShadow1);
painter.draw_line({ 1, 0 }, { 1, rect().bottom() }, SystemColor::ThreedHighlight);
painter.draw_line({ 0, 0 }, { 0, rect().bottom() }, palette().threed_shadow1());
painter.draw_line({ 1, 0 }, { 1, rect().bottom() }, palette().threed_highlight());
}
};
@ -90,7 +91,7 @@ void GToolBar::paint_event(GPaintEvent& event)
painter.add_clip_rect(event.rect());
if (m_has_frame)
StylePainter::paint_surface(painter, rect(), x() != 0, y() != 0);
StylePainter::paint_surface(painter, rect(), palette(), x() != 0, y() != 0);
else
painter.fill_rect(event.rect(), background_color());
painter.fill_rect(event.rect(), palette().button());
}

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibGUI/GPainter.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GTreeView.h>
@ -23,6 +24,7 @@ GTreeView::MetadataForIndex& GTreeView::ensure_metadata_for_index(const GModelIn
GTreeView::GTreeView(GWidget* parent)
: GAbstractColumnView(parent)
{
set_background_role(ColorRole::Base);
set_size_columns_to_fit_content(true);
set_headers_visible(false);
m_expand_bitmap = GraphicsBitmap::load_from_file("/res/icons/treeview-expand.png");
@ -146,7 +148,7 @@ void GTreeView::paint_event(GPaintEvent& event)
GPainter painter(*this);
painter.add_clip_rect(frame_inner_rect());
painter.add_clip_rect(event.rect());
painter.fill_rect(event.rect(), SystemColor::Base);
painter.fill_rect(event.rect(), palette().color(background_role()));
if (!model())
return;
@ -178,21 +180,21 @@ void GTreeView::paint_event(GPaintEvent& event)
bool is_selected_row = selection().contains(index);
Color text_color = SystemColor::WindowText;
Color text_color = palette().color(foreground_role());
if (is_selected_row)
text_color = Color::White;
Color background_color;
Color key_column_background_color;
if (is_selected_row) {
background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
key_column_background_color = is_focused() ? Color(SystemColor::Selection) : Color::from_rgb(0x606060);
background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
key_column_background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
} else {
if (alternating_row_colors() && (painted_row_index % 2)) {
background_color = Color(220, 220, 220);
key_column_background_color = Color(200, 200, 200);
} else {
background_color = SystemColor::Base;
background_color = palette().color(background_role());
key_column_background_color = Color(220, 220, 220);
}
}
@ -215,7 +217,7 @@ void GTreeView::paint_event(GPaintEvent& event)
auto cell_index = model.sibling(index.row(), column_index, index.parent());
if (auto* delegate = column_data(column_index).cell_painting_delegate.ptr()) {
delegate->paint(painter, cell_rect, model, cell_index);
delegate->paint(painter, cell_rect, palette(), model, cell_index);
} else {
auto data = model.data(cell_index);
@ -226,7 +228,7 @@ void GTreeView::paint_event(GPaintEvent& event)
painter.blit(cell_rect.location(), *bitmap, bitmap->rect());
} else {
if (!is_selected_row)
text_color = model.data(cell_index, GModel::Role::ForegroundColor).to_color(SystemColor::WindowText);
text_color = model.data(cell_index, GModel::Role::ForegroundColor).to_color(palette().color(foreground_role()));
painter.draw_text(cell_rect, data.to_string(), font, column_metadata.text_alignment, text_color, TextElision::Right);
}
}

View file

@ -1,26 +1,26 @@
#include <AK/Assertions.h>
#include <AK/JsonObject.h>
#include <LibDraw/GraphicsBitmap.h>
#include <LibDraw/Palette.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GEvent.h>
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GLabel.h>
#include <LibGUI/GLayout.h>
#include <LibGUI/GMenu.h>
#include <LibGUI/GPainter.h>
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
#include <LibGUI/GWindowServerConnection.h>
#include <unistd.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GLabel.h>
#include <LibGUI/GRadioButton.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GSlider.h>
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GTextBox.h>
#include <LibGUI/GWidget.h>
#include <LibGUI/GWindow.h>
#include <LibGUI/GWindowServerConnection.h>
#include <unistd.h>
REGISTER_GWIDGET(GButton)
REGISTER_GWIDGET(GCheckBox)
@ -67,9 +67,8 @@ const GWidgetClassRegistration* GWidgetClassRegistration::find(const String& cla
GWidget::GWidget(GWidget* parent)
: CObject(parent, true)
, m_font(Font::default_font())
, m_palette(GApplication::the().palette())
{
m_background_color = SystemColor::Window;
m_foreground_color = SystemColor::WindowText;
}
GWidget::~GWidget()
@ -173,7 +172,7 @@ void GWidget::handle_paint_event(GPaintEvent& event)
ASSERT(is_visible());
if (fill_with_background_color()) {
GPainter painter(*this);
painter.fill_rect(event.rect(), background_color());
painter.fill_rect(event.rect(), palette().color(background_role()));
} else {
#ifdef DEBUG_WIDGET_UNDERDRAW
// FIXME: This is a bit broken.
@ -693,3 +692,8 @@ Vector<GWidget*> GWidget::child_widgets() const
}
return widgets;
}
void GWidget::set_palette(const Palette& palette)
{
m_palette = palette;
}

View file

@ -9,6 +9,7 @@
#include <LibDraw/Font.h>
#include <LibDraw/Orientation.h>
#include <LibDraw/Rect.h>
#include <LibDraw/SystemTheme.h>
#include <LibGUI/GEvent.h>
#include <LibGUI/GShortcut.h>
@ -16,11 +17,12 @@
extern GWidgetClassRegistration registration_##class_name; \
GWidgetClassRegistration registration_##class_name(#class_name, [](GWidget* parent) { return class_name::construct(parent); });
class GraphicsBitmap;
class GAction;
class GLayout;
class GMenu;
class GWindow;
class GraphicsBitmap;
class Palette;
enum class SizePolicy {
Fixed,
@ -149,6 +151,12 @@ public:
void move_by(int x, int y) { move_by({ x, y }); }
void move_by(const Point& delta) { set_relative_rect({ relative_position().translated(delta), size() }); }
ColorRole background_role() const { return m_background_role; }
void set_background_role(ColorRole role) { m_background_role = role; }
ColorRole foreground_role() const { return m_foreground_role; }
void set_foreground_role(ColorRole role) { m_foreground_role = role; }
Color background_color() const { return m_background_color; }
Color foreground_color() const { return m_foreground_color; }
@ -230,6 +238,9 @@ public:
void do_layout();
const Palette& palette() const { return *m_palette; }
void set_palette(const Palette&);
protected:
explicit GWidget(GWidget* parent = nullptr);
@ -271,6 +282,8 @@ private:
OwnPtr<GLayout> m_layout;
Rect m_relative_rect;
ColorRole m_background_role { ColorRole::Window };
ColorRole m_foreground_role { ColorRole::WindowText };
Color m_background_color;
Color m_foreground_color;
NonnullRefPtr<Font> m_font;
@ -288,6 +301,8 @@ private:
bool m_updates_enabled { true };
HashMap<GShortcut, GAction*> m_local_shortcut_actions;
NonnullRefPtr<Palette> m_palette;
};
template<>

View file

@ -1,3 +1,4 @@
#include <LibDraw/Palette.h>
#include <LibDraw/SystemTheme.h>
#include <LibGUI/GAction.h>
#include <LibGUI/GApplication.h>
@ -25,6 +26,7 @@ static void set_system_theme_from_shared_buffer_id(int id)
auto system_theme = SharedBuffer::create_from_shared_buffer_id(id);
ASSERT(system_theme);
set_system_theme(*system_theme);
GApplication::the().set_system_palette(*system_theme);
}
void GWindowServerConnection::handshake()

View file

@ -118,7 +118,7 @@ void HtmlView::paint_event(GPaintEvent& event)
painter.add_clip_rect(event.rect());
if (!layout_root()) {
painter.fill_rect(event.rect(), background_color());
painter.fill_rect(event.rect(), palette().color(background_role()));
return;
}
@ -131,7 +131,7 @@ void HtmlView::paint_event(GPaintEvent& event)
painter.translate(frame_thickness(), frame_thickness());
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
RenderingContext context { painter };
RenderingContext context(painter, palette());
context.set_should_show_line_box_borders(m_should_show_line_box_borders);
context.set_viewport_rect(visible_content_rect());
layout_root()->render(context);

View file

@ -43,7 +43,7 @@ void LayoutImage::render(RenderingContext& context)
if (renders_as_alt_text()) {
context.painter().set_font(Font::default_font());
StylePainter::paint_frame(context.painter(), enclosing_int_rect(rect()), FrameShape::Container, FrameShadow::Sunken, 2);
StylePainter::paint_frame(context.painter(), enclosing_int_rect(rect()), context.palette(), FrameShape::Container, FrameShadow::Sunken, 2);
auto alt = node().alt();
if (alt.is_empty())
alt = node().src();

View file

@ -1,17 +1,20 @@
#pragma once
#include <LibDraw/Palette.h>
#include <LibDraw/Rect.h>
class GPainter;
class RenderingContext {
public:
explicit RenderingContext(GPainter& painter)
explicit RenderingContext(GPainter& painter, const Palette& palette)
: m_painter(painter)
, m_palette(palette)
{
}
GPainter& painter() const { return m_painter; }
const Palette& palette() const { return m_palette; }
bool should_show_line_box_borders() const { return m_should_show_line_box_borders; }
void set_should_show_line_box_borders(bool value) { m_should_show_line_box_borders = value; }
@ -21,6 +24,7 @@ public:
private:
GPainter& m_painter;
const Palette& m_palette;
Rect m_viewport_rect;
bool m_should_show_line_box_borders { false };
};

View file

@ -18,14 +18,15 @@ WSButton::~WSButton()
void WSButton::paint(Painter& painter)
{
auto& palette = WSWindowManager::the().palette();
PainterStateSaver saver(painter);
painter.translate(relative_rect().location());
StylePainter::paint_button(painter, rect(), ButtonStyle::Normal, m_pressed, m_hovered);
StylePainter::paint_button(painter, rect(), palette, ButtonStyle::Normal, m_pressed, m_hovered);
auto x_location = rect().center();
x_location.move_by(-(m_bitmap->width() / 2), -(m_bitmap->height() / 2));
if (m_pressed)
x_location.move_by(1, 1);
painter.draw_bitmap(x_location, *m_bitmap, SystemColor::ButtonText);
painter.draw_bitmap(x_location, *m_bitmap, palette.button_text());
}
void WSButton::on_mouse_event(const WSMouseEvent& event)

View file

@ -113,7 +113,7 @@ void WSCompositor::compose()
if (wm.any_opaque_window_contains_rect(dirty_rect))
continue;
// FIXME: If the wallpaper is opaque, no need to fill with color!
m_back_painter->fill_rect(dirty_rect, SystemColor::DesktopBackground);
m_back_painter->fill_rect(dirty_rect, wm.palette().desktop_background());
if (m_wallpaper) {
if (m_wallpaper_mode == WallpaperMode::Simple) {
m_back_painter->blit(dirty_rect.location(), *m_wallpaper, dirty_rect);

View file

@ -126,6 +126,7 @@ WSWindow& WSMenu::ensure_menu_window()
void WSMenu::draw()
{
auto& palette = WSWindowManager::the().palette();
m_theme_index_at_last_paint = WSWindowManager::the().theme_index();
ASSERT(menu_window());
@ -133,8 +134,8 @@ void WSMenu::draw()
Painter painter(*menu_window()->backing_store());
Rect rect { {}, menu_window()->size() };
painter.fill_rect(rect.shrunken(6, 6), SystemColor::MenuBase);
StylePainter::paint_window_frame(painter, rect);
painter.fill_rect(rect.shrunken(6, 6), palette.menu_base());
StylePainter::paint_window_frame(painter, rect, palette);
int width = this->width();
if (!s_checked_bitmap)
@ -148,15 +149,15 @@ void WSMenu::draw()
}
Rect stripe_rect { frame_thickness(), frame_thickness(), s_stripe_width, height() - frame_thickness() * 2 };
painter.fill_rect(stripe_rect, SystemColor::MenuStripe);
painter.draw_line(stripe_rect.top_right(), stripe_rect.bottom_right(), Color(SystemColor::MenuStripe).darkened());
painter.fill_rect(stripe_rect, palette.menu_stripe());
painter.draw_line(stripe_rect.top_right(), stripe_rect.bottom_right(), palette.menu_stripe().darkened());
for (auto& item : m_items) {
if (item.type() == WSMenuItem::Text) {
Color text_color = SystemColor::WindowText;
Color text_color = palette.window_text();
if (&item == m_hovered_item && item.is_enabled()) {
painter.fill_rect(item.rect(), SystemColor::MenuSelection);
painter.draw_rect(item.rect(), Color(SystemColor::MenuSelection).darkened());
painter.fill_rect(item.rect(), palette.menu_selection());
painter.draw_rect(item.rect(), palette.menu_selection().darkened());
text_color = Color::White;
} else if (!item.is_enabled()) {
text_color = Color::MidGray;
@ -166,10 +167,10 @@ void WSMenu::draw()
Rect checkmark_rect { item.rect().x() + 7, 0, s_checked_bitmap_width, s_checked_bitmap_height };
checkmark_rect.center_vertically_within(text_rect);
Rect checkbox_rect = checkmark_rect.inflated(4, 4);
painter.fill_rect(checkbox_rect, SystemColor::Base);
StylePainter::paint_frame(painter, checkbox_rect, FrameShape::Container, FrameShadow::Sunken, 2);
painter.fill_rect(checkbox_rect, palette.base());
StylePainter::paint_frame(painter, checkbox_rect, palette, FrameShape::Container, FrameShadow::Sunken, 2);
if (item.is_checked()) {
painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, SystemColor::ButtonText);
painter.draw_bitmap(checkmark_rect.location(), *s_checked_bitmap, palette.button_text());
}
} else if (item.icon()) {
Rect icon_rect { item.rect().x() + 3, 0, s_item_icon_width, s_item_icon_width };
@ -189,13 +190,13 @@ void WSMenu::draw()
s_submenu_arrow_bitmap_height
};
submenu_arrow_rect.center_vertically_within(item.rect());
painter.draw_bitmap(submenu_arrow_rect.location(), submenu_arrow_bitmap, SystemColor::WindowText);
painter.draw_bitmap(submenu_arrow_rect.location(), submenu_arrow_bitmap, palette.window_text());
}
} else if (item.type() == WSMenuItem::Separator) {
Point p1(item.rect().translated(stripe_rect.width() + 4, 0).x(), item.rect().center().y() - 1);
Point p2(width - 7, item.rect().center().y() - 1);
painter.draw_line(p1, p2, SystemColor::ThreedShadow1);
painter.draw_line(p1.translated(0, 1), p2.translated(0, 1), SystemColor::ThreedHighlight);
painter.draw_line(p1, p2, palette.threed_shadow1());
painter.draw_line(p1.translated(0, 1), p2.translated(0, 1), palette.threed_highlight());
}
}
}

View file

@ -44,6 +44,7 @@ bool WSMenuManager::is_open(const WSMenu& menu) const
void WSMenuManager::draw()
{
auto& wm = WSWindowManager::the();
auto& palette = wm.palette();
auto menubar_rect = this->menubar_rect();
if (m_needs_window_resize) {
@ -83,14 +84,14 @@ void WSMenuManager::draw()
Painter painter(*window().backing_store());
painter.fill_rect(menubar_rect, SystemColor::Window);
painter.draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, SystemColor::ThreedShadow1);
painter.fill_rect(menubar_rect, palette.window());
painter.draw_line({ 0, menubar_rect.bottom() }, { menubar_rect.right(), menubar_rect.bottom() }, palette.threed_shadow1());
int index = 0;
wm.for_each_active_menubar_menu([&](WSMenu& menu) {
Color text_color = SystemColor::WindowText;
Color text_color = palette.window_text();
if (is_open(menu)) {
painter.fill_rect(menu.rect_in_menubar(), SystemColor::MenuSelection);
painter.draw_rect(menu.rect_in_menubar(), Color(SystemColor::MenuSelection).darkened());
painter.fill_rect(menu.rect_in_menubar(), palette.menu_selection());
painter.draw_rect(menu.rect_in_menubar(), palette.menu_selection().darkened());
text_color = Color::White;
}
painter.draw_text(
@ -103,7 +104,7 @@ void WSMenuManager::draw()
return IterationDecision::Continue;
});
painter.draw_text(m_username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, SystemColor::WindowText);
painter.draw_text(m_username_rect, m_username, Font::default_bold_font(), TextAlignment::CenterRight, palette.window_text());
time_t now = time(nullptr);
auto* tm = localtime(&now);
@ -115,7 +116,7 @@ void WSMenuManager::draw()
tm->tm_min,
tm->tm_sec);
painter.draw_text(m_time_rect, time_text, wm.font(), TextAlignment::CenterRight, SystemColor::WindowText);
painter.draw_text(m_time_rect, time_text, wm.font(), TextAlignment::CenterRight, palette.window_text());
for (auto& applet : m_applets) {
if (!applet)

View file

@ -153,6 +153,7 @@ void WSWindowFrame::paint(Painter& painter)
if (m_window.type() != WSWindowType::Normal)
return;
auto& palette = WSWindowManager::the().palette();
auto& window = m_window;
auto titlebar_rect = title_bar_rect();
@ -170,29 +171,29 @@ void WSWindowFrame::paint(Painter& painter)
auto& wm = WSWindowManager::the();
if (&window == wm.m_highlight_window) {
border_color = SystemColor::HighlightWindowBorder1;
border_color2 = SystemColor::HighlightWindowBorder2;
title_color = SystemColor::HighlightWindowTitle;
border_color = palette.highlight_window_border1();
border_color2 = palette.highlight_window_border2();
title_color = palette.highlight_window_title();
} else if (&window == wm.m_move_window) {
border_color = SystemColor::MovingWindowBorder1;
border_color2 = SystemColor::MovingWindowBorder2;
title_color = SystemColor::MovingWindowTitle;
border_color = palette.moving_window_border1();
border_color2 = palette.moving_window_border2();
title_color = palette.moving_window_title();
} else if (&window == wm.m_active_window) {
border_color = SystemColor::ActiveWindowBorder1;
border_color2 = SystemColor::ActiveWindowBorder2;
title_color = SystemColor::ActiveWindowTitle;
border_color = palette.active_window_border1();
border_color2 = palette.active_window_border2();
title_color = palette.active_window_title();
} else {
border_color = SystemColor::InactiveWindowBorder1;
border_color2 = SystemColor::InactiveWindowBorder2;
title_color = SystemColor::InactiveWindowTitle;
border_color = palette.inactive_window_border1();
border_color2 = palette.inactive_window_border2();
title_color = palette.inactive_window_title();
}
StylePainter::paint_window_frame(painter, outer_rect);
StylePainter::paint_window_frame(painter, outer_rect, palette);
if (!window.show_titlebar())
return;
painter.draw_line(titlebar_rect.bottom_left().translated(0, 1), titlebar_rect.bottom_right().translated(0, 1), SystemColor::Button);
painter.draw_line(titlebar_rect.bottom_left().translated(0, 1), titlebar_rect.bottom_right().translated(0, 1), palette.button());
auto leftmost_button_rect = m_buttons.is_empty() ? Rect() : m_buttons.last().relative_rect();

View file

@ -42,7 +42,8 @@ WSWindowManager& WSWindowManager::the()
return *s_the;
}
WSWindowManager::WSWindowManager()
WSWindowManager::WSWindowManager(const Palette& palette)
: m_palette(palette)
{
s_the = this;
@ -132,6 +133,7 @@ WSWindowManager::WSWindowManager()
auto new_theme = load_system_theme(theme.path);
ASSERT(new_theme);
set_system_theme(*new_theme);
m_palette = Palette::create_with_shared_buffer(*new_theme);
HashTable<WSClientConnection*> notified_clients;
for_each_window([&](WSWindow& window) {
if (window.client()) {

View file

@ -9,6 +9,7 @@
#include <LibDraw/Color.h>
#include <LibDraw/DisjointRectSet.h>
#include <LibDraw/Painter.h>
#include <LibDraw/Palette.h>
#include <LibDraw/Rect.h>
#include <WindowServer/WSCursor.h>
#include <WindowServer/WSEvent.h>
@ -50,10 +51,15 @@ class WSWindowManager : public CObject {
public:
static WSWindowManager& the();
WSWindowManager();
explicit WSWindowManager(const Palette&);
virtual ~WSWindowManager() override;
RefPtr<CConfigFile> wm_config() const { return m_wm_config; }
const Palette& palette() const { return *m_palette; }
RefPtr<CConfigFile> wm_config() const
{
return m_wm_config;
}
void reload_config(bool);
void add_window(WSWindow&);
@ -276,6 +282,8 @@ private:
WeakPtr<WSButton> m_cursor_tracking_button;
WeakPtr<WSButton> m_hovered_button;
NonnullRefPtr<Palette> m_palette;
RefPtr<CConfigFile> m_wm_config;
struct AppMetadata {

View file

@ -70,9 +70,10 @@ void WSWindowSwitcher::on_key_event(const WSKeyEvent& event)
void WSWindowSwitcher::draw()
{
auto& palette = WSWindowManager::the().palette();
Painter painter(*m_switcher_window->backing_store());
painter.fill_rect({ {}, m_rect.size() }, SystemColor::Window);
painter.draw_rect({ {}, m_rect.size() }, SystemColor::ThreedShadow2);
painter.fill_rect({ {}, m_rect.size() }, palette.window());
painter.draw_rect({ {}, m_rect.size() }, palette.threed_shadow2());
for (int index = 0; index < m_windows.size(); ++index) {
auto& window = *m_windows.at(index);
Rect item_rect {
@ -84,21 +85,21 @@ void WSWindowSwitcher::draw()
Color text_color;
Color rect_text_color;
if (index == m_selected_index) {
painter.fill_rect(item_rect, SystemColor::Selection);
text_color = SystemColor::SelectionText;
rect_text_color = SystemColor::ThreedShadow1;
painter.fill_rect(item_rect, palette.selection());
text_color = palette.selection_text();
rect_text_color = palette.threed_shadow1();
} else {
text_color = SystemColor::WindowText;
rect_text_color = SystemColor::ThreedShadow2;
text_color = palette.window_text();
rect_text_color = palette.threed_shadow2();
}
item_rect.shrink(item_padding(), 0);
Rect thumbnail_rect = { item_rect.location().translated(0, 5), { thumbnail_width(), thumbnail_height() } };
if (window.backing_store()) {
painter.draw_scaled_bitmap(thumbnail_rect, *window.backing_store(), window.backing_store()->rect());
StylePainter::paint_frame(painter, thumbnail_rect.inflated(4, 4), FrameShape::Container, FrameShadow::Sunken, 2);
StylePainter::paint_frame(painter, thumbnail_rect.inflated(4, 4), palette, FrameShape::Container, FrameShadow::Sunken, 2);
}
Rect icon_rect = { thumbnail_rect.bottom_right().translated(-window.icon().width(), -window.icon().height()), { window.icon().width(), window.icon().height() } };
painter.fill_rect(icon_rect, SystemColor::Window);
painter.fill_rect(icon_rect, palette.window());
painter.blit(icon_rect.location(), window.icon(), window.icon().rect());
painter.draw_text(item_rect.translated(thumbnail_width() + 12, 0), window.title(), WSWindowManager::the().window_title_font(), TextAlignment::CenterLeft, text_color);
painter.draw_text(item_rect, window.rect().to_string(), TextAlignment::CenterRight, rect_text_color);

View file

@ -1,4 +1,5 @@
#include <LibCore/CConfigFile.h>
#include <LibDraw/Palette.h>
#include <LibDraw/SystemTheme.h>
#include <WindowServer/WSCompositor.h>
#include <WindowServer/WSEventLoop.h>
@ -25,13 +26,14 @@ int main(int, char**)
auto theme = load_system_theme(String::format("/res/themes/%s.ini", theme_name.characters()));
ASSERT(theme);
set_system_theme(*theme);
auto palette = Palette::create_with_shared_buffer(*theme);
WSEventLoop loop;
WSScreen screen(wm_config->read_num_entry("Screen", "Width", 1024),
wm_config->read_num_entry("Screen", "Height", 768));
WSCompositor::the();
auto wm = WSWindowManager::construct();
auto wm = WSWindowManager::construct(*palette);
dbgprintf("Entering WindowServer main loop.\n");
loop.exec();