mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:17:36 +00:00
Services: Convert WindowFrame button bitmaps to themable PNGs
Custom buttons can now be set using TitleButtonIcons under the Paths group in themes. WindowFrame recognizes window-close.png, window-minimize.png, window-maximize.png and window-restore.png filenames.
This commit is contained in:
parent
41aacdf815
commit
c815fa7f47
5 changed files with 75 additions and 92 deletions
|
@ -33,10 +33,9 @@
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
Button::Button(WindowFrame& frame, NonnullRefPtr<Gfx::CharacterBitmap>&& bitmap, Function<void(Button&)>&& on_click_handler)
|
Button::Button(WindowFrame& frame, Function<void(Button&)>&& on_click_handler)
|
||||||
: on_click(move(on_click_handler))
|
: on_click(move(on_click_handler))
|
||||||
, m_frame(frame)
|
, m_frame(frame)
|
||||||
, m_bitmap(move(bitmap))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +49,13 @@ void Button::paint(Gfx::Painter& painter)
|
||||||
Gfx::PainterStateSaver saver(painter);
|
Gfx::PainterStateSaver saver(painter);
|
||||||
painter.translate(relative_rect().location());
|
painter.translate(relative_rect().location());
|
||||||
Gfx::StylePainter::paint_button(painter, rect(), palette, Gfx::ButtonStyle::Normal, m_pressed, m_hovered);
|
Gfx::StylePainter::paint_button(painter, rect(), palette, Gfx::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_icon) {
|
||||||
if (m_pressed)
|
auto icon_location = rect().center().translated(-(m_icon->width() / 2), -(m_icon->height() / 2));
|
||||||
x_location.move_by(1, 1);
|
if (m_pressed)
|
||||||
painter.draw_bitmap(x_location, *m_bitmap, palette.button_text());
|
painter.translate(1, 1);
|
||||||
|
painter.blit(icon_location, *m_icon, m_icon->rect());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::on_mouse_event(const MouseEvent& event)
|
void Button::on_mouse_event(const MouseEvent& event)
|
||||||
|
|
|
@ -27,10 +27,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/NonnullRefPtr.h>
|
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
#include <LibGfx/Rect.h>
|
|
||||||
#include <LibGfx/Forward.h>
|
#include <LibGfx/Forward.h>
|
||||||
|
#include <LibGfx/Rect.h>
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ class WindowFrame;
|
||||||
|
|
||||||
class Button : public Weakable<Button> {
|
class Button : public Weakable<Button> {
|
||||||
public:
|
public:
|
||||||
Button(WindowFrame&, NonnullRefPtr<Gfx::CharacterBitmap>&&, Function<void(Button&)>&& on_click_handler);
|
Button(WindowFrame&, Function<void(Button&)>&& on_click_handler);
|
||||||
~Button();
|
~Button();
|
||||||
|
|
||||||
Gfx::IntRect relative_rect() const { return m_relative_rect; }
|
Gfx::IntRect relative_rect() const { return m_relative_rect; }
|
||||||
|
@ -56,12 +55,12 @@ public:
|
||||||
|
|
||||||
bool is_visible() const { return m_visible; }
|
bool is_visible() const { return m_visible; }
|
||||||
|
|
||||||
void set_bitmap(const Gfx::CharacterBitmap& bitmap) { m_bitmap = bitmap; }
|
void set_icon(const Gfx::Bitmap& icon) { m_icon = icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowFrame& m_frame;
|
WindowFrame& m_frame;
|
||||||
Gfx::IntRect m_relative_rect;
|
Gfx::IntRect m_relative_rect;
|
||||||
NonnullRefPtr<Gfx::CharacterBitmap> m_bitmap;
|
RefPtr<Gfx::Bitmap> m_icon;
|
||||||
bool m_pressed { false };
|
bool m_pressed { false };
|
||||||
bool m_visible { true };
|
bool m_visible { true };
|
||||||
bool m_hovered { false };
|
bool m_hovered { false };
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
|
|
||||||
#include "ClientConnection.h"
|
#include "ClientConnection.h"
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <LibGfx/CharacterBitmap.h>
|
|
||||||
#include <LibGfx/Font.h>
|
#include <LibGfx/Font.h>
|
||||||
#include <LibGfx/Painter.h>
|
#include <LibGfx/Painter.h>
|
||||||
#include <LibGfx/StylePainter.h>
|
#include <LibGfx/StylePainter.h>
|
||||||
|
@ -39,91 +38,24 @@
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
static const char* s_close_button_bitmap_data = {
|
static Gfx::Bitmap* s_minimize_icon;
|
||||||
"## ##"
|
static Gfx::Bitmap* s_maximize_icon;
|
||||||
"### ###"
|
static Gfx::Bitmap* s_restore_icon;
|
||||||
" ###### "
|
static Gfx::Bitmap* s_close_icon;
|
||||||
" #### "
|
|
||||||
" #### "
|
|
||||||
" ###### "
|
|
||||||
"### ###"
|
|
||||||
"## ##"
|
|
||||||
" "
|
|
||||||
};
|
|
||||||
|
|
||||||
static Gfx::CharacterBitmap* s_close_button_bitmap;
|
static String s_last_title_button_icons_path;
|
||||||
static const int s_close_button_bitmap_width = 8;
|
|
||||||
static const int s_close_button_bitmap_height = 9;
|
|
||||||
|
|
||||||
static const char* s_minimize_button_bitmap_data = {
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" ###### "
|
|
||||||
" #### "
|
|
||||||
" ## "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
};
|
|
||||||
|
|
||||||
static Gfx::CharacterBitmap* s_minimize_button_bitmap;
|
|
||||||
static const int s_minimize_button_bitmap_width = 8;
|
|
||||||
static const int s_minimize_button_bitmap_height = 9;
|
|
||||||
|
|
||||||
static const char* s_maximize_button_bitmap_data = {
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" ## "
|
|
||||||
" #### "
|
|
||||||
" ###### "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
" "
|
|
||||||
};
|
|
||||||
|
|
||||||
static Gfx::CharacterBitmap* s_maximize_button_bitmap;
|
|
||||||
static const int s_maximize_button_bitmap_width = 8;
|
|
||||||
static const int s_maximize_button_bitmap_height = 9;
|
|
||||||
|
|
||||||
static const char* s_unmaximize_button_bitmap_data = {
|
|
||||||
" "
|
|
||||||
" ## "
|
|
||||||
" #### "
|
|
||||||
" ###### "
|
|
||||||
" "
|
|
||||||
" ###### "
|
|
||||||
" #### "
|
|
||||||
" ## "
|
|
||||||
" "
|
|
||||||
};
|
|
||||||
|
|
||||||
static Gfx::CharacterBitmap* s_unmaximize_button_bitmap;
|
|
||||||
static const int s_unmaximize_button_bitmap_width = 8;
|
|
||||||
static const int s_unmaximize_button_bitmap_height = 9;
|
|
||||||
|
|
||||||
WindowFrame::WindowFrame(Window& window)
|
WindowFrame::WindowFrame(Window& window)
|
||||||
: m_window(window)
|
: m_window(window)
|
||||||
{
|
{
|
||||||
if (!s_close_button_bitmap)
|
auto button = make<Button>(*this, [this](auto&) {
|
||||||
s_close_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_close_button_bitmap_data, s_close_button_bitmap_width, s_close_button_bitmap_height).leak_ref();
|
|
||||||
|
|
||||||
if (!s_minimize_button_bitmap)
|
|
||||||
s_minimize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_minimize_button_bitmap_data, s_minimize_button_bitmap_width, s_minimize_button_bitmap_height).leak_ref();
|
|
||||||
|
|
||||||
if (!s_maximize_button_bitmap)
|
|
||||||
s_maximize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_maximize_button_bitmap_data, s_maximize_button_bitmap_width, s_maximize_button_bitmap_height).leak_ref();
|
|
||||||
|
|
||||||
if (!s_unmaximize_button_bitmap)
|
|
||||||
s_unmaximize_button_bitmap = &Gfx::CharacterBitmap::create_from_ascii(s_unmaximize_button_bitmap_data, s_unmaximize_button_bitmap_width, s_unmaximize_button_bitmap_height).leak_ref();
|
|
||||||
|
|
||||||
m_buttons.append(make<Button>(*this, *s_close_button_bitmap, [this](auto&) {
|
|
||||||
m_window.request_close();
|
m_window.request_close();
|
||||||
}));
|
});
|
||||||
|
m_close_button = button.ptr();
|
||||||
|
m_buttons.append(move(button));
|
||||||
|
|
||||||
if (window.is_resizable()) {
|
if (window.is_resizable()) {
|
||||||
auto button = make<Button>(*this, *s_maximize_button_bitmap, [this](auto&) {
|
auto button = make<Button>(*this, [this](auto&) {
|
||||||
m_window.set_maximized(!m_window.is_maximized());
|
m_window.set_maximized(!m_window.is_maximized());
|
||||||
});
|
});
|
||||||
m_maximize_button = button.ptr();
|
m_maximize_button = button.ptr();
|
||||||
|
@ -131,22 +63,70 @@ WindowFrame::WindowFrame(Window& window)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.is_minimizable()) {
|
if (window.is_minimizable()) {
|
||||||
auto button = make<Button>(*this, *s_minimize_button_bitmap, [this](auto&) {
|
auto button = make<Button>(*this, [this](auto&) {
|
||||||
m_window.set_minimized(true);
|
m_window.set_minimized(true);
|
||||||
});
|
});
|
||||||
m_minimize_button = button.ptr();
|
m_minimize_button = button.ptr();
|
||||||
m_buttons.append(move(button));
|
m_buttons.append(move(button));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_button_icons();
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowFrame::~WindowFrame()
|
WindowFrame::~WindowFrame()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowFrame::set_button_icons()
|
||||||
|
{
|
||||||
|
if (m_window.is_frameless())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String icons_path = WindowManager::the().palette().title_button_icons_path();
|
||||||
|
|
||||||
|
StringBuilder full_path;
|
||||||
|
if (!s_minimize_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
|
full_path.append(icons_path);
|
||||||
|
full_path.append("window-minimize.png");
|
||||||
|
if (!(s_minimize_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
|
||||||
|
s_minimize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-minimize.png").leak_ref();
|
||||||
|
full_path.clear();
|
||||||
|
}
|
||||||
|
if (!s_maximize_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
|
full_path.append(icons_path);
|
||||||
|
full_path.append("window-maximize.png");
|
||||||
|
if (!(s_maximize_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
|
||||||
|
s_maximize_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-maximize.png").leak_ref();
|
||||||
|
full_path.clear();
|
||||||
|
}
|
||||||
|
if (!s_restore_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
|
full_path.append(icons_path);
|
||||||
|
full_path.append("window-restore.png");
|
||||||
|
if (!(s_restore_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
|
||||||
|
s_restore_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-restore.png").leak_ref();
|
||||||
|
full_path.clear();
|
||||||
|
}
|
||||||
|
if (!s_close_icon || s_last_title_button_icons_path != icons_path) {
|
||||||
|
full_path.append(icons_path);
|
||||||
|
full_path.append("window-close.png");
|
||||||
|
if (!(s_close_icon = Gfx::Bitmap::load_from_file(full_path.to_string()).leak_ref()))
|
||||||
|
s_close_icon = Gfx::Bitmap::load_from_file("/res/icons/16x16/window-close.png").leak_ref();
|
||||||
|
full_path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_close_button->set_icon(*s_close_icon);
|
||||||
|
if (m_window.is_minimizable())
|
||||||
|
m_minimize_button->set_icon(*s_minimize_icon);
|
||||||
|
if (m_window.is_resizable())
|
||||||
|
m_maximize_button->set_icon(m_window.is_maximized() ? *s_restore_icon : *s_maximize_icon);
|
||||||
|
|
||||||
|
s_last_title_button_icons_path = icons_path;
|
||||||
|
}
|
||||||
|
|
||||||
void WindowFrame::did_set_maximized(Badge<Window>, bool maximized)
|
void WindowFrame::did_set_maximized(Badge<Window>, bool maximized)
|
||||||
{
|
{
|
||||||
ASSERT(m_maximize_button);
|
ASSERT(m_maximize_button);
|
||||||
m_maximize_button->set_bitmap(maximized ? *s_unmaximize_button_bitmap : *s_maximize_button_bitmap);
|
m_maximize_button->set_icon(maximized ? *s_restore_icon : *s_maximize_icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::IntRect WindowFrame::title_bar_rect() const
|
Gfx::IntRect WindowFrame::title_bar_rect() const
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
void did_set_maximized(Badge<Window>, bool);
|
void did_set_maximized(Badge<Window>, bool);
|
||||||
|
|
||||||
void layout_buttons();
|
void layout_buttons();
|
||||||
|
void set_button_icons();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paint_notification_frame(Gfx::Painter&);
|
void paint_notification_frame(Gfx::Painter&);
|
||||||
|
@ -69,6 +70,7 @@ private:
|
||||||
|
|
||||||
Window& m_window;
|
Window& m_window;
|
||||||
NonnullOwnPtrVector<Button> m_buttons;
|
NonnullOwnPtrVector<Button> m_buttons;
|
||||||
|
Button* m_close_button { nullptr };
|
||||||
Button* m_maximize_button { nullptr };
|
Button* m_maximize_button { nullptr };
|
||||||
Button* m_minimize_button { nullptr };
|
Button* m_minimize_button { nullptr };
|
||||||
};
|
};
|
||||||
|
|
|
@ -1392,6 +1392,7 @@ bool WindowManager::update_theme(String theme_path, String theme_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.frame().layout_buttons();
|
window.frame().layout_buttons();
|
||||||
|
window.frame().set_button_icons();
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
MenuManager::the().did_change_theme();
|
MenuManager::the().did_change_theme();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue