2015-11-11 16:54:08 +01:00
|
|
|
/*
|
|
|
|
* \brief Window decorator that can be styled - theme handling
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2015-11-12
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
2015-11-11 16:54:08 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2015-11-11 16:54:08 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <os/texture_rgb888.h>
|
2018-03-08 18:27:42 +01:00
|
|
|
#include <nitpicker_gfx/tff_font.h>
|
2015-11-11 16:54:08 +01:00
|
|
|
#include <util/xml_node.h>
|
|
|
|
#include <decorator/xml_utils.h>
|
|
|
|
|
|
|
|
/* gems includes */
|
|
|
|
#include <gems/file.h>
|
|
|
|
#include <gems/png_image.h>
|
|
|
|
|
|
|
|
/* demo includes */
|
|
|
|
#include <scout_gfx/icon_painter.h>
|
|
|
|
|
|
|
|
/* local includes */
|
|
|
|
#include "theme.h"
|
|
|
|
|
|
|
|
|
|
|
|
enum Texture_id { TEXTURE_ID_DEFAULT, TEXTURE_ID_CLOSER, TEXTURE_ID_MAXIMIZER };
|
|
|
|
|
|
|
|
|
|
|
|
struct Texture_from_png_file
|
|
|
|
{
|
|
|
|
typedef Genode::Texture<Genode::Pixel_rgb888> Texture;
|
|
|
|
|
|
|
|
File png_file;
|
2017-01-11 19:49:33 +01:00
|
|
|
Png_image png_image;
|
2015-11-11 16:54:08 +01:00
|
|
|
Texture &texture { *png_image.texture<Genode::Pixel_rgb888>() };
|
|
|
|
|
2019-01-21 15:46:48 +01:00
|
|
|
Texture_from_png_file(Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Allocator &alloc, char const *path)
|
2015-11-11 16:54:08 +01:00
|
|
|
:
|
2017-01-11 19:49:33 +01:00
|
|
|
png_file(path, alloc), png_image(ram, rm, alloc, png_file.data<void>())
|
2015-11-11 16:54:08 +01:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Genode::Texture<Genode::Pixel_rgb888> const &
|
2019-01-21 15:46:48 +01:00
|
|
|
texture_by_id(Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Allocator &alloc, Texture_id texture_id)
|
2015-11-11 16:54:08 +01:00
|
|
|
{
|
|
|
|
if (texture_id == TEXTURE_ID_DEFAULT) {
|
2017-01-11 19:49:33 +01:00
|
|
|
static Texture_from_png_file texture(ram, rm, alloc, "theme/default.png");
|
2015-11-11 16:54:08 +01:00
|
|
|
return texture.texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (texture_id == TEXTURE_ID_CLOSER) {
|
2017-01-11 19:49:33 +01:00
|
|
|
static Texture_from_png_file texture(ram, rm, alloc, "theme/closer.png");
|
2015-11-11 16:54:08 +01:00
|
|
|
return texture.texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (texture_id == TEXTURE_ID_MAXIMIZER) {
|
2017-01-11 19:49:33 +01:00
|
|
|
static Texture_from_png_file texture(ram, rm, alloc, "theme/maximizer.png");
|
2015-11-11 16:54:08 +01:00
|
|
|
return texture.texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Invalid_texture_id { };
|
|
|
|
throw Invalid_texture_id();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Genode::Texture<Genode::Pixel_rgb888> const &
|
2019-01-21 15:46:48 +01:00
|
|
|
texture_by_element_type(Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Allocator &alloc, Decorator::Theme::Element_type type)
|
2015-11-11 16:54:08 +01:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case Decorator::Theme::ELEMENT_TYPE_CLOSER:
|
2017-01-11 19:49:33 +01:00
|
|
|
return texture_by_id(ram, rm, alloc, TEXTURE_ID_CLOSER);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
case Decorator::Theme::ELEMENT_TYPE_MAXIMIZER:
|
2017-01-11 19:49:33 +01:00
|
|
|
return texture_by_id(ram, rm, alloc, TEXTURE_ID_MAXIMIZER);
|
2015-11-11 16:54:08 +01:00
|
|
|
}
|
|
|
|
struct Invalid_element_type { };
|
|
|
|
throw Invalid_element_type();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static Text_painter::Font const &title_font(Genode::Allocator &alloc)
|
|
|
|
{
|
|
|
|
static File tff_file("theme/font.tff", alloc);
|
2018-03-08 18:27:42 +01:00
|
|
|
static Tff_font::Allocated_glyph_buffer glyph_buffer(tff_file.data<char>(), alloc);
|
|
|
|
static Tff_font font(tff_file.data<char>(), glyph_buffer);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Genode::Xml_node metadata(Genode::Allocator &alloc)
|
|
|
|
{
|
|
|
|
static File file("theme/metadata", alloc);
|
|
|
|
|
|
|
|
return Genode::Xml_node(file.data<char>(), file.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Area Decorator::Theme::background_size() const
|
|
|
|
{
|
2015-12-04 12:30:47 +01:00
|
|
|
if (decor_margins().none() && aura_margins().none())
|
|
|
|
return Decorator::Area(0, 0);
|
|
|
|
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Texture<Pixel_rgb888> const &texture =
|
|
|
|
texture_by_id(_ram, _rm, _alloc, TEXTURE_ID_DEFAULT);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
return texture.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct Margins_from_metadata : Decorator::Theme::Margins
|
|
|
|
{
|
|
|
|
Margins_from_metadata(char const *sub_node, Genode::Allocator &alloc)
|
2018-12-12 09:49:20 +01:00
|
|
|
:
|
|
|
|
Decorator::Theme::Margins()
|
2015-11-11 16:54:08 +01:00
|
|
|
{
|
|
|
|
Genode::Xml_node aura = metadata(alloc).sub_node(sub_node);
|
|
|
|
top = aura.attribute_value("top", 0UL);
|
|
|
|
bottom = aura.attribute_value("bottom", 0UL);
|
|
|
|
left = aura.attribute_value("left", 0UL);
|
|
|
|
right = aura.attribute_value("right", 0UL);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Theme::Margins Decorator::Theme::aura_margins() const
|
|
|
|
{
|
|
|
|
static Margins_from_metadata aura("aura", _alloc);
|
|
|
|
return aura;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Theme::Margins Decorator::Theme::decor_margins() const
|
|
|
|
{
|
|
|
|
static Margins_from_metadata decor("decor", _alloc);
|
|
|
|
return decor;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Rect Decorator::Theme::title_geometry() const
|
|
|
|
{
|
2015-12-04 12:30:47 +01:00
|
|
|
static Genode::Xml_node node = metadata(_alloc);
|
|
|
|
static Rect rect = node.has_sub_node("title")
|
|
|
|
? rect_attribute(node.sub_node("title"))
|
|
|
|
: Rect(Point(0, 0), Area(0, 0));
|
2015-11-11 16:54:08 +01:00
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-04 12:30:47 +01:00
|
|
|
static Decorator::Rect
|
2019-01-21 15:46:48 +01:00
|
|
|
element_geometry(Genode::Ram_allocator &ram, Genode::Region_map &rm,
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Allocator &alloc, char const *sub_node_type,
|
2015-12-04 12:30:47 +01:00
|
|
|
Texture_id texture_id)
|
|
|
|
{
|
|
|
|
using namespace Decorator;
|
|
|
|
|
|
|
|
static Genode::Xml_node const node = metadata(alloc);
|
|
|
|
|
|
|
|
if (!node.has_sub_node(sub_node_type))
|
|
|
|
return Rect(Point(0, 0), Area(0, 0));
|
|
|
|
|
|
|
|
return Rect(point_attribute(node.sub_node(sub_node_type)),
|
2017-01-11 19:49:33 +01:00
|
|
|
texture_by_id(ram, rm, alloc, texture_id).size());
|
2015-12-04 12:30:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-11 16:54:08 +01:00
|
|
|
Decorator::Rect Decorator::Theme::element_geometry(Element_type type) const
|
|
|
|
{
|
|
|
|
|
2015-12-04 12:30:47 +01:00
|
|
|
if (type == ELEMENT_TYPE_CLOSER)
|
2017-01-11 19:49:33 +01:00
|
|
|
return ::element_geometry(_ram, _rm, _alloc, "closer", TEXTURE_ID_CLOSER);
|
2015-12-04 12:30:47 +01:00
|
|
|
|
|
|
|
if (type == ELEMENT_TYPE_MAXIMIZER)
|
2017-01-11 19:49:33 +01:00
|
|
|
return ::element_geometry(_ram, _rm, _alloc, "maximizer", TEXTURE_ID_MAXIMIZER);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
struct Invalid_element_type { };
|
|
|
|
throw Invalid_element_type();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
void Decorator::Theme::draw_background(Decorator::Pixel_surface &pixel_surface,
|
|
|
|
Decorator::Alpha_surface &alpha_surface,
|
2018-12-26 22:12:14 +01:00
|
|
|
Area const area, unsigned alpha) const
|
2015-11-11 16:54:08 +01:00
|
|
|
{
|
2015-12-04 12:30:47 +01:00
|
|
|
/*
|
|
|
|
* Back out early there is neither a decor nor an aura. In this case, we
|
|
|
|
* prevent accessing the 'default.png' file. So we can skip it from the
|
|
|
|
* theme.
|
|
|
|
*/
|
|
|
|
if (!background_size().valid())
|
|
|
|
return;
|
|
|
|
|
2017-01-11 19:49:33 +01:00
|
|
|
Genode::Texture<Pixel_rgb888> const &texture =
|
|
|
|
texture_by_id(_ram, _rm, _alloc, TEXTURE_ID_DEFAULT);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
typedef Genode::Surface_base::Point Point;
|
|
|
|
typedef Genode::Surface_base::Rect Rect;
|
|
|
|
|
|
|
|
unsigned const left = aura_margins().left + decor_margins().left;
|
|
|
|
unsigned const right = aura_margins().right + decor_margins().right;
|
|
|
|
|
2018-12-26 22:12:14 +01:00
|
|
|
unsigned const middle = left + right < area.w()
|
|
|
|
? area.w() - left - right
|
2015-11-11 16:54:08 +01:00
|
|
|
: 0;
|
|
|
|
|
|
|
|
Rect const orig_clip = pixel_surface.clip();
|
|
|
|
|
|
|
|
/* left */
|
|
|
|
if (left) {
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect curr_clip = Rect(Point(0, 0), Area(left, area.h()));
|
2015-11-11 16:54:08 +01:00
|
|
|
pixel_surface.clip(curr_clip);
|
|
|
|
alpha_surface.clip(curr_clip);
|
|
|
|
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect const rect(Point(0, 0), area);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
Icon_painter::paint(pixel_surface, rect, texture, alpha);
|
|
|
|
Icon_painter::paint(alpha_surface, rect, texture, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* middle */
|
|
|
|
if (middle) {
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect curr_clip = Rect(Point(left, 0), Area(middle, area.h()));
|
2015-11-11 16:54:08 +01:00
|
|
|
pixel_surface.clip(curr_clip);
|
|
|
|
alpha_surface.clip(curr_clip);
|
|
|
|
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect const rect(Point(0, 0), area);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
|
|
|
Icon_painter::paint(pixel_surface, rect, texture, alpha);
|
|
|
|
Icon_painter::paint(alpha_surface, rect, texture, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* right */
|
|
|
|
if (right) {
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect curr_clip = Rect(Point(left + middle, 0), Area(right, area.h()));
|
2015-11-11 16:54:08 +01:00
|
|
|
pixel_surface.clip(curr_clip);
|
|
|
|
alpha_surface.clip(curr_clip);
|
|
|
|
|
|
|
|
Point at(0, 0);
|
2018-12-26 22:12:14 +01:00
|
|
|
Area size = area;
|
2015-11-11 16:54:08 +01:00
|
|
|
|
2018-12-26 22:12:14 +01:00
|
|
|
if (texture.size().w() > area.w()) {
|
|
|
|
at = Point((int)area.w() - (int)texture.size().w(), 0);
|
2015-11-11 16:54:08 +01:00
|
|
|
size = Area(texture.size().w(), size.h());
|
|
|
|
}
|
|
|
|
|
|
|
|
Icon_painter::paint(pixel_surface, Rect(at, size), texture, alpha);
|
|
|
|
Icon_painter::paint(alpha_surface, Rect(at, size), texture, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
pixel_surface.clip(orig_clip);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
void Decorator::Theme::draw_title(Decorator::Pixel_surface &pixel_surface,
|
2018-12-12 09:49:20 +01:00
|
|
|
Decorator::Alpha_surface &,
|
2018-12-26 22:12:14 +01:00
|
|
|
Area const area, char const *title) const
|
2015-11-11 16:54:08 +01:00
|
|
|
{
|
2015-12-04 12:30:47 +01:00
|
|
|
/* skip title drawing if the metadata lacks a title declaration */
|
|
|
|
if (!title_geometry().area().valid())
|
|
|
|
return;
|
|
|
|
|
2015-11-11 16:54:08 +01:00
|
|
|
Text_painter::Font const &font = title_font(_alloc);
|
|
|
|
|
2018-03-08 18:27:42 +01:00
|
|
|
Area const label_area(font.string_width(title).decimal(),
|
|
|
|
font.bounding_box().h());
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect const target_rect(Point(0, 0), area);
|
|
|
|
Rect const title_rect = absolute(title_geometry(), target_rect);
|
2018-03-08 18:27:42 +01:00
|
|
|
Point const pos = title_rect.center(label_area) - Point(0, 1);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
2018-03-08 18:27:42 +01:00
|
|
|
Text_painter::paint(pixel_surface, Text_painter::Position(pos.x(), pos.y()),
|
|
|
|
font, Genode::Color(0, 0, 0), title);
|
2015-11-11 16:54:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
void Decorator::Theme::draw_element(Decorator::Pixel_surface &pixel_surface,
|
|
|
|
Decorator::Alpha_surface &alpha_surface,
|
2018-12-26 22:12:14 +01:00
|
|
|
Area area,
|
2015-11-11 16:54:08 +01:00
|
|
|
Element_type element_type,
|
|
|
|
unsigned alpha) const
|
|
|
|
{
|
2015-12-04 12:30:47 +01:00
|
|
|
if (!element_geometry(element_type).area().valid())
|
|
|
|
return;
|
|
|
|
|
2015-11-11 16:54:08 +01:00
|
|
|
Genode::Texture<Pixel_rgb888> const &texture =
|
2017-01-11 19:49:33 +01:00
|
|
|
texture_by_element_type(_ram, _rm, _alloc, element_type);
|
2015-11-11 16:54:08 +01:00
|
|
|
|
2018-12-26 22:12:14 +01:00
|
|
|
Rect const target_rect(Point(0, 0), area);
|
2015-11-11 16:54:08 +01:00
|
|
|
Rect const element_rect = element_geometry(element_type);
|
2018-12-26 22:12:14 +01:00
|
|
|
Point const pos = absolute(element_rect.p1(), target_rect);
|
2015-11-11 16:54:08 +01:00
|
|
|
Rect const rect(pos, element_rect.area());
|
|
|
|
|
|
|
|
Icon_painter::paint(pixel_surface, rect, texture, alpha);
|
|
|
|
Icon_painter::paint(alpha_surface, rect, texture, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Point Decorator::Theme::absolute(Decorator::Point pos,
|
|
|
|
Decorator::Rect win_rect) const
|
|
|
|
{
|
|
|
|
Area const theme_size = background_size();
|
|
|
|
|
|
|
|
int x = pos.x();
|
|
|
|
int y = pos.y();
|
|
|
|
|
|
|
|
if (x > (int)theme_size.w()/2) x = win_rect.w() - theme_size.w() + x;
|
|
|
|
if (y > (int)theme_size.h()/2) y = win_rect.h() - theme_size.h() + y;
|
|
|
|
|
|
|
|
return win_rect.p1() + Point(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Decorator::Rect Decorator::Theme::absolute(Decorator::Rect rect,
|
|
|
|
Decorator::Rect win_rect) const
|
|
|
|
{
|
|
|
|
return Rect(absolute(rect.p1(), win_rect), absolute(rect.p2(), win_rect));
|
|
|
|
}
|