1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #ifndef __I4_WINDOW_HPP_
|
---|
10 | #define __I4_WINDOW_HPP_
|
---|
11 |
|
---|
12 | class i4_image_class;
|
---|
13 | class i4_cursor_class;
|
---|
14 |
|
---|
15 | #include "area/rectlist.hh"
|
---|
16 | #include "device/device.hh"
|
---|
17 | #include "area/rectlist.hh"
|
---|
18 | #include "device/event.hh"
|
---|
19 | #include "isllist.hh"
|
---|
20 | #include "image/context.hh"
|
---|
21 |
|
---|
22 | // Brief summary :
|
---|
23 | //
|
---|
24 | // 2 Main classes are defined here :
|
---|
25 | // i4_window_class :
|
---|
26 | // base object for most everything graphical.
|
---|
27 | // An i4_window_class should only draw (using local_image) during draw().
|
---|
28 | // During draw(), proper clipping is setup.
|
---|
29 | // local_image will transform local coordinates to global space for you.
|
---|
30 | // because a window is derived from i4_event_handler_class,
|
---|
31 | // it can receive events through receive_event (see device/device.hh
|
---|
32 | // for more info on this. A the base window class does not process any events.
|
---|
33 | //
|
---|
34 | // i4_parent_window_class :
|
---|
35 | // parent windows have a list of children window.
|
---|
36 | // The draw order for children is painter's algorithm. So the last
|
---|
37 | // child in the list gets drawn on top. parent windows also
|
---|
38 | // maintain a dirty_area list so that redraw can be done
|
---|
39 | // more efficiently than redrawing themselves & their children completely.
|
---|
40 | // parent windows have a default behavior for responding to a
|
---|
41 | // number of events. parent windows keep a mouse & keyboard
|
---|
42 | // focus. The mouse focus is set automically through mouse_move events.
|
---|
43 | // The key focus is not implemented yet.
|
---|
44 | //
|
---|
45 |
|
---|
46 | class i4_parent_window_class;
|
---|
47 |
|
---|
48 | class i4_window_class : public i4_event_handler_class
|
---|
49 | {
|
---|
50 | protected:
|
---|
51 |
|
---|
52 | // Data members you need not worry about
|
---|
53 | i4_image_class *global_image; // pointer to the image associated with the display we draw on
|
---|
54 |
|
---|
55 | i4_coord global_x,global_y, // returned by x() & y()
|
---|
56 | mouse_x, mouse_y;
|
---|
57 | w16 w,h;
|
---|
58 | i4_bool redraw_flag;
|
---|
59 |
|
---|
60 |
|
---|
61 | i4_image_class *local_image; /* this will transform all drawing coordinates
|
---|
62 | from local-space to glabal space
|
---|
63 | plus when drawing is done from draw()
|
---|
64 | proper clipping for you window is setup beforehand */
|
---|
65 | i4_parent_window_class *parent; // this may be 0
|
---|
66 | i4_cursor_class *cursor;
|
---|
67 |
|
---|
68 | public:
|
---|
69 |
|
---|
70 | // next pointer is used by i4_parent_window_class's isl_list
|
---|
71 | i4_window_class *next;
|
---|
72 |
|
---|
73 | virtual void receive_event(i4_event *ev);
|
---|
74 |
|
---|
75 | // initially when a window is created it has no parent
|
---|
76 | i4_window_class(w16 w, w16 h);
|
---|
77 |
|
---|
78 | i4_coord x() { return global_x; }
|
---|
79 | i4_coord y() { return global_y; }
|
---|
80 | w16 width() { return w; }
|
---|
81 | w16 height() { return h; }
|
---|
82 |
|
---|
83 | i4_coord last_mouse_x() { return mouse_x; } // last position in the window mouse was at
|
---|
84 | i4_coord last_mouse_y() { return mouse_y; }
|
---|
85 |
|
---|
86 |
|
---|
87 | // forget redraw is called by a parent if the child had ask for a redraw but
|
---|
88 | // when the parent got around to doing the redraw, the child was clipped away
|
---|
89 | virtual void forget_redraw() { redraw_flag=i4_F; }
|
---|
90 |
|
---|
91 | // request draw should be called in the calculating part of a windows processing
|
---|
92 | // the windows draw() function will then be called later with the correct clip list
|
---|
93 | // 2 versions of request_redraw exist, one redraws
|
---|
94 | // everything, and one tells of a specific area to redraw
|
---|
95 | // a window may call request_redraw() within it's draw() to display continual animations
|
---|
96 |
|
---|
97 | virtual void request_redraw(i4_bool for_a_child=i4_F);
|
---|
98 |
|
---|
99 | // x1, y1, x2, y2 are in local-space coordinates
|
---|
100 | // this used to be called request_redraw, but it got confused with regular request_redraw
|
---|
101 | // this is called whan a window's area becomes visible when it wasn't before
|
---|
102 | virtual void note_undrawn(i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
|
---|
103 | i4_bool propogate_to_children=i4_T);
|
---|
104 |
|
---|
105 | // a parent uses this to determine that you need to have your draw() function called
|
---|
106 | virtual i4_bool need_redraw() { return redraw_flag; }
|
---|
107 |
|
---|
108 | // draw is called by parent sometime after request_draw() is called
|
---|
109 | // this draw may not occur if window is clipped away, in which case forget_redraw() is called
|
---|
110 | virtual void draw(i4_draw_context_class &context);
|
---|
111 |
|
---|
112 | // move can be used to a change window's position
|
---|
113 | // within a window, to give a window a draw_area and parent or both
|
---|
114 | // move will also send a notify_move event to it's parent
|
---|
115 | // (if it has one), whereas private_move will not
|
---|
116 | // if draw_under is false the parent will not draw under
|
---|
117 | //the dirty area the window's movement created
|
---|
118 | virtual void move(i4_coord x_offset, i4_coord y_offset, i4_bool draw_under=i4_T);
|
---|
119 |
|
---|
120 | // private move will not notify it's parent, and should
|
---|
121 | // probably only be called by the parent.
|
---|
122 | virtual void private_move(i4_coord new_x, i4_coord new_y);
|
---|
123 |
|
---|
124 | // private resize will not notify it's parent, and
|
---|
125 | // should probably only be called by your parent
|
---|
126 | virtual void private_resize(w16 new_width, w16 new_height);
|
---|
127 |
|
---|
128 | virtual void reparent(i4_image_class *draw_area, i4_parent_window_class *parent);
|
---|
129 |
|
---|
130 | // resize will change the width and height of our window and notify our parent of the change
|
---|
131 | virtual void resize(w16 new_width, w16 new_height);
|
---|
132 |
|
---|
133 |
|
---|
134 | // this sets the mouse image to displayed when the cursor
|
---|
135 | // enters this window. The actual act of changing the cursor
|
---|
136 | // is done by i4_window_class::receive_event() on GOT & LOST mouse
|
---|
137 | // focus events. So a derived window must remember to call
|
---|
138 | // the shadowed receive_event or the cursor will not change.
|
---|
139 | // If cursor is 0, then the cursor will not change
|
---|
140 | // shape when it enters this window.
|
---|
141 | virtual void set_cursor(i4_cursor_class *cursor);
|
---|
142 |
|
---|
143 |
|
---|
144 | virtual ~i4_window_class();
|
---|
145 | void show_context(i4_draw_context_class &context);
|
---|
146 |
|
---|
147 | i4_bool isa_parent(i4_window_class *who);
|
---|
148 | virtual i4_parent_window_class *root_window();
|
---|
149 |
|
---|
150 | // if this is true, then parent will not clip you out when it draws
|
---|
151 | virtual i4_bool transparent() { return i4_F; }
|
---|
152 |
|
---|
153 | i4_parent_window_class *get_parent() { return parent; }
|
---|
154 | #ifndef I4_RETAIL
|
---|
155 | void debug_show();
|
---|
156 | #endif
|
---|
157 | };
|
---|
158 |
|
---|
159 |
|
---|
160 | class i4_parent_window_class : public i4_window_class
|
---|
161 | {
|
---|
162 | private:
|
---|
163 | i4_bool mouse_focus_grabbed, have_mouse_focus;
|
---|
164 | i4_bool child_rerequested_redraw;
|
---|
165 | void send_event_to_child(i4_window_class *w, i4_event *ev);
|
---|
166 |
|
---|
167 | protected:
|
---|
168 | i4_bool child_need_redraw;
|
---|
169 |
|
---|
170 | virtual void private_move(i4_coord x_offset, i4_coord y_offset);
|
---|
171 |
|
---|
172 |
|
---|
173 | typedef i4_isl_list<i4_window_class> win_list;
|
---|
174 | typedef i4_isl_list<i4_window_class>::iterator win_iter;
|
---|
175 |
|
---|
176 | win_list children;
|
---|
177 | win_iter key_focus, mouse_focus, drag_drop_focus;
|
---|
178 |
|
---|
179 |
|
---|
180 | // Note:
|
---|
181 | // so a parent can refresh itself and children more efficiently it keeps a list of dirty area.
|
---|
182 | // this is kept in global coordinates for several reasons. It is important to note that
|
---|
183 | // request_redraw(x1,y1,x2,y2) takes coordinates in local_space, but transforms them to
|
---|
184 | // local space when adding to dirty_area
|
---|
185 | i4_rect_list_class undrawn_area;
|
---|
186 |
|
---|
187 |
|
---|
188 | // These functions shouldn't really be needed by derived classes
|
---|
189 | void change_key_focus(i4_window_class *new_focus);
|
---|
190 | void change_mouse_focus(i4_window_class *new_focus);
|
---|
191 | void redraw_area(i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2); // in local coordinates
|
---|
192 | win_iter find_window(i4_coord mouse_x, i4_coord mouse_y);
|
---|
193 |
|
---|
194 | void drag_drop_move(i4_event *ev);
|
---|
195 | void mouse_move(i4_event *ev);
|
---|
196 |
|
---|
197 | public:
|
---|
198 | i4_bool has_mouse_focus() { return have_mouse_focus; }
|
---|
199 | virtual i4_bool find_new_mouse_focus(); // return true if focus changed
|
---|
200 |
|
---|
201 | virtual i4_parent_window_class *root_window();
|
---|
202 |
|
---|
203 | virtual void resize(w16 new_width, w16 new_height);
|
---|
204 | virtual void reparent(i4_image_class *draw_area, i4_parent_window_class *parent);
|
---|
205 |
|
---|
206 | // these functions are called when REQUEST_NEXT_FOCUS, etc. events are recieved
|
---|
207 | // so that you can over-ride these event functionalities if you want
|
---|
208 | virtual void next_key_focus();
|
---|
209 | virtual void left_key_focus();
|
---|
210 | virtual void right_key_focus();
|
---|
211 | virtual void up_key_focus();
|
---|
212 | virtual void down_key_focus();
|
---|
213 |
|
---|
214 | // Because a parent window needs to tells it's children
|
---|
215 | // to draw() as well and setup proper clipping for itself
|
---|
216 | // a parent_draw() function is supplied which is called by draw() which is where all drawing
|
---|
217 | // done by a derived class of i4_window_class should go. parent_draw() will have the correct clipping
|
---|
218 | // list (including the exclusion of it's children.
|
---|
219 | virtual void draw(i4_draw_context_class &context);
|
---|
220 |
|
---|
221 | // see comment's above draw(), this function should be used by derived class instead of draw()
|
---|
222 | virtual void parent_draw(i4_draw_context_class &context);
|
---|
223 |
|
---|
224 | // receive_event is a general event notification routine.
|
---|
225 | // If you get a event and note that you cannot handle it, you should
|
---|
226 | // pass it on down to you derived parent so that functionality still works
|
---|
227 | // example receive_event :
|
---|
228 | // void receive_event(i4_event *ev)
|
---|
229 | // {
|
---|
230 | // if (ev->type==i4_event::MOUSE_MOVE)
|
---|
231 | // {
|
---|
232 | // do something
|
---|
233 | // } else i4_parent_window_class::receive_event(ev);
|
---|
234 | // }
|
---|
235 | virtual void receive_event(i4_event *ev);
|
---|
236 |
|
---|
237 | // forget redraw is called by a parent if the child had ask for a redraw but
|
---|
238 | // when the parent got around to doing the redraw, the child was clipped away
|
---|
239 | // for the parent window case, undrawn_area is discarded and all
|
---|
240 | // children's forget_redraw are called
|
---|
241 | virtual void forget_redraw();
|
---|
242 |
|
---|
243 | i4_parent_window_class(w16 w, w16 h);
|
---|
244 |
|
---|
245 | // x & y are relative to parent x,y (added to end of window list)
|
---|
246 | virtual void add_child(i4_coord x, i4_coord y, i4_window_class *child);
|
---|
247 |
|
---|
248 | // x & y are relative to parent x,y (added to front of window list)
|
---|
249 | virtual void add_child_front(i4_coord x, i4_coord y, i4_window_class *child);
|
---|
250 |
|
---|
251 | // does not delete the child, simply removes and request redraw under its area
|
---|
252 | virtual void remove_child(i4_window_class *child);
|
---|
253 |
|
---|
254 | // removes all children from self and addes them into other_parent
|
---|
255 | void transfer_children(i4_parent_window_class *other_parent,
|
---|
256 | i4_coord x_offset, i4_coord y_offset);
|
---|
257 |
|
---|
258 | // arranges child windows from left to right then down
|
---|
259 | virtual void arrange_right_down();
|
---|
260 |
|
---|
261 | // arranges child windows from top to bottom then right
|
---|
262 | virtual void arrange_down_right();
|
---|
263 |
|
---|
264 | // makes the window the minimum size needed to fit all children
|
---|
265 | virtual void resize_to_fit_children();
|
---|
266 |
|
---|
267 | // adds all local area to undrawn_area
|
---|
268 | virtual void request_redraw(i4_bool for_a_child=i4_F);
|
---|
269 |
|
---|
270 | // adds this area to undrawn_area (in local coordinates)
|
---|
271 | virtual void note_undrawn(i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
|
---|
272 | i4_bool propogate_to_children=i4_T);
|
---|
273 |
|
---|
274 |
|
---|
275 | virtual i4_bool need_redraw()
|
---|
276 | // returns true if we have any dirty area or childen report they need redrawing
|
---|
277 | { return (i4_bool)(!undrawn_area.empty()|
|
---|
278 | child_need_redraw |
|
---|
279 | i4_window_class::need_redraw()); }
|
---|
280 |
|
---|
281 | virtual i4_window_class *get_nth_window(w32 win_num);
|
---|
282 |
|
---|
283 | i4_bool isa_child(i4_window_class *w);
|
---|
284 |
|
---|
285 | virtual ~i4_parent_window_class();
|
---|
286 | };
|
---|
287 |
|
---|
288 | #endif
|
---|
289 |
|
---|