added clipping rectangles
[winnie] / src / window.cc
1 #include <algorithm>
2 #include <stdio.h> //TODO
3 #include <string.h>
4
5 #include "gfx.h"
6 #include "window.h"
7 #include "wm.h"
8
9 Window::Window()
10 {
11         parent = 0;
12         title = 0;
13         rect.x = rect.y = 0;
14         rect.width = rect.height = 128;
15         memset(&callbacks, 0, sizeof callbacks);
16         dirty = true;
17         managed = true;
18         focusable = true;
19 }
20
21 Window::~Window()
22 {
23         for(size_t i=0; i<children.size(); i++) {
24                 wm->remove_window(children[i]);
25                 delete children[i];
26         }
27
28         delete [] title;
29 }
30
31 const Rect &Window::get_rect() const
32 {
33         return rect;
34 }
35
36 Rect Window::get_absolute_rect() const
37 {
38         if(!parent) {
39                 return rect;
40         }
41
42         Rect absolute_rect;
43         absolute_rect = parent->get_absolute_rect();
44
45         absolute_rect.x += rect.x;
46         absolute_rect.y += rect.y;
47         absolute_rect.width = rect.width;
48         absolute_rect.height = rect.height;
49
50         return absolute_rect;
51 }
52
53 bool Window::contains_point(int ptr_x, int ptr_y)
54 {
55         Rect abs_rect = get_absolute_rect();
56         return ptr_x >= abs_rect.x && ptr_x < abs_rect.x + abs_rect.width &&
57                         ptr_y >= abs_rect.y && ptr_y < abs_rect.y + abs_rect.height;
58 }
59
60 void Window::move(int x, int y)
61 {
62         invalidate();   // moved, should redraw, MUST BE CALLED FIRST
63         rect.x = x;
64         rect.y = y;
65 }
66
67 void Window::resize(int x, int y)
68 {
69         invalidate();   // resized, should redraw, MUST BE CALLED FIRST
70         rect.width = x;
71         rect.height = y;
72 }
73
74 void Window::set_title(const char *s)
75 {
76         delete [] title;
77
78         title = new char[strlen(s) + 1];
79         strcpy(title, s);
80 }
81
82 const char *Window::get_title() const
83 {
84         return title;
85 }
86
87 void Window::invalidate()
88 {
89         dirty = true;
90         Rect abs_rect = get_absolute_rect();
91         wm->invalidate_region(abs_rect);
92 }
93
94 void Window::draw(Rect *dirty_region)
95 {
96         Rect abs_rect = get_absolute_rect();
97         Rect intersect = rect_intersection(abs_rect, *dirty_region);
98         if(intersect.width && intersect.height) {
99                 Rect prev_clip = get_clipping_rect();
100                 set_clipping_rect(abs_rect);
101                 
102                 if(callbacks.display) {
103                         callbacks.display(this);
104                 }
105                 dirty = false;
106
107                 draw_children(abs_rect);
108                 
109                 *dirty_region = rect_union(*dirty_region, abs_rect);
110                 set_clipping_rect(prev_clip);
111         }
112 }
113
114 void Window::draw_children(const Rect &dirty_region)
115 {
116         Rect drect = dirty_region;
117         for(size_t i=0; i<children.size(); i++) {
118                 children[i]->draw(&drect);
119         }
120 }
121
122 unsigned char *Window::get_win_start_on_fb()
123 {
124         unsigned char *fb = get_framebuffer();
125         Rect abs_rect = get_absolute_rect();
126         return fb + get_color_depth() * (get_screen_size().x * abs_rect.y + abs_rect.x) / 8;
127 }
128
129 int Window::get_scanline_width()
130 {
131         return get_screen_size().x;
132 }
133
134 void Window::set_managed(bool managed)
135 {
136         this->managed = managed;
137 }
138
139 bool Window::get_managed() const
140 {
141         return managed;
142 }
143
144 void Window::set_focusable(bool focusable)
145 {
146         this->focusable = focusable;
147 }
148
149 bool Window::get_focusable() const
150 {
151         return focusable;
152 }
153
154 bool Window::get_dirty() const
155 {
156         return dirty;
157 }
158
159 void Window::set_display_callback(DisplayFuncType func)
160 {
161         callbacks.display = func;
162 }
163
164 void Window::set_keyboard_callback(KeyboardFuncType func)
165 {
166         callbacks.keyboard = func;
167 }
168
169 void Window::set_mouse_button_callback(MouseButtonFuncType func)
170 {
171         callbacks.button = func;
172 }
173
174 void Window::set_mouse_motion_callback(MouseMotionFuncType func)
175 {
176         callbacks.motion = func;
177 }
178
179 const DisplayFuncType Window::get_display_callback() const
180 {
181         return callbacks.display;
182 }
183
184 const KeyboardFuncType Window::get_keyboard_callback() const
185 {
186         return callbacks.keyboard;
187 }
188
189 const MouseButtonFuncType Window::get_mouse_button_callback() const
190 {
191         return callbacks.button;
192 }
193
194 const MouseMotionFuncType Window::get_mouse_motion_callback() const
195 {
196         return callbacks.motion;
197 }
198
199 void Window::add_child(Window *win)
200 {
201         children.push_back(win);
202         if(win->parent) {
203                 win->parent->remove_child(win);
204         }
205         win->parent = this;
206 }
207
208 void Window::remove_child(Window *win)
209 {
210         std::vector<Window*>::iterator it;
211         it = std::find(children.begin(), children.end(), win);
212         if(it != children.end()) {
213                 children.erase(it);
214                 win->parent = 0;
215         }
216 }
217
218 Window **Window::get_children()
219 {
220         if(children.empty()) {
221                 return 0;
222         }
223         return &children[0];
224 }
225
226 int Window::get_children_count() const
227 {
228         return (int)children.size();
229 }
230
231 const Window *Window::get_parent() const
232 {
233         return parent;
234 }
235
236 Window *Window::get_parent()
237 {
238         return parent;
239 }