/*
winnie - an experimental window system
Copyright (C) 2013 Eleni Maria Stea
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Author: Eleni Maria Stea
*/
#include
#include
#include
#include "sdl/gfx.h"
#include "window.h"
#include "wm.h"
Window::Window()
{
parent = 0;
title = 0;
rect.x = rect.y = 0;
rect.width = rect.height = 128;
memset(&callbacks, 0, sizeof callbacks);
dirty = true;
managed = true;
focusable = true;
state = STATE_NORMAL;
}
Window::~Window()
{
for (size_t i = 0; i < children.size(); i++) {
wm->remove_window(children[i]);
delete children[i];
}
delete[] title;
}
const Rect &
Window::get_rect() const
{
return rect;
}
Rect
Window::get_absolute_rect() const
{
if (!parent) {
return rect;
}
Rect absolute_rect;
absolute_rect = parent->get_absolute_rect();
absolute_rect.x += rect.x;
absolute_rect.y += rect.y;
absolute_rect.width = rect.width;
absolute_rect.height = rect.height;
return absolute_rect;
}
bool
Window::contains_point(int ptr_x, int ptr_y)
{
Rect abs_rect = get_absolute_rect();
return ptr_x >= abs_rect.x && ptr_x < abs_rect.x + abs_rect.width
&& ptr_y >= abs_rect.y && ptr_y < abs_rect.y + abs_rect.height;
}
void
Window::move(int x, int y)
{
invalidate(); // moved, should redraw, MUST BE CALLED FIRST
rect.x = x;
rect.y = y;
}
void
Window::resize(int x, int y)
{
invalidate(); // resized, should redraw, MUST BE CALLED FIRST
rect.width = x;
rect.height = y;
}
void
Window::set_title(const char *s)
{
delete[] title;
title = new char[strlen(s) + 1];
strcpy(title, s);
}
const char *
Window::get_title() const
{
return title;
}
void
Window::invalidate()
{
dirty = true;
Rect abs_rect = get_absolute_rect();
wm->invalidate_region(abs_rect);
}
void
Window::draw(Rect *dirty_region)
{
Rect abs_rect = get_absolute_rect();
Rect intersect = rect_intersection(abs_rect, *dirty_region);
if (intersect.width && intersect.height) {
Rect prev_clip = get_clipping_rect();
set_clipping_rect(abs_rect);
if (callbacks.display) {
callbacks.display(this);
}
dirty = false;
draw_children(abs_rect);
*dirty_region = rect_union(*dirty_region, abs_rect);
set_clipping_rect(prev_clip);
}
}
void
Window::draw_children(const Rect &dirty_region)
{
Rect drect = dirty_region;
for (size_t i = 0; i < children.size(); i++) {
children[i]->draw(&drect);
}
}
unsigned char *
Window::get_win_start_on_fb()
{
unsigned char *fb = get_framebuffer();
Rect abs_rect = get_absolute_rect();
return fb
+ get_color_depth() * (get_screen_size().x * abs_rect.y + abs_rect.x)
/ 8;
}
int
Window::get_scanline_width()
{
return get_screen_size().x;
}
void
Window::set_managed(bool managed)
{
this->managed = managed;
}
bool
Window::get_managed() const
{
return managed;
}
void
Window::set_focusable(bool focusable)
{
this->focusable = focusable;
}
bool
Window::get_focusable() const
{
return focusable;
}
bool
Window::get_dirty() const
{
return dirty;
}
void
Window::set_display_callback(DisplayFuncType func)
{
callbacks.display = func;
}
void
Window::set_keyboard_callback(KeyboardFuncType func)
{
callbacks.keyboard = func;
}
void
Window::set_mouse_button_callback(MouseButtonFuncType func)
{
callbacks.button = func;
}
void
Window::set_mouse_motion_callback(MouseMotionFuncType func)
{
callbacks.motion = func;
}
void
Window::set_timer_callback(TimerFuncType func)
{
callbacks.timer = func;
}
const DisplayFuncType
Window::get_display_callback() const
{
return callbacks.display;
}
const KeyboardFuncType
Window::get_keyboard_callback() const
{
return callbacks.keyboard;
}
const MouseButtonFuncType
Window::get_mouse_button_callback() const
{
return callbacks.button;
}
const MouseMotionFuncType
Window::get_mouse_motion_callback() const
{
return callbacks.motion;
}
const TimerFuncType
Window::get_timer_callback() const
{
return callbacks.timer;
}
void
Window::add_child(Window *win)
{
children.push_back(win);
if (win->parent) {
win->parent->remove_child(win);
}
win->parent = this;
}
void
Window::remove_child(Window *win)
{
std::vector::iterator it;
it = std::find(children.begin(), children.end(), win);
if (it != children.end()) {
children.erase(it);
win->parent = 0;
}
}
Window **
Window::get_children()
{
if (children.empty()) {
return 0;
}
return &children[0];
}
int
Window::get_children_count() const
{
return (int) children.size();
}
const Window *
Window::get_parent() const
{
return parent;
}
Window *
Window::get_parent()
{
return parent;
}
void
Window::set_state(State state)
{
this->state = state;
}
Window::State
Window::get_state() const
{
return state;
}