[80] | 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 |
|
---|