/* view.h console view object Copyright (C) 2003 Bill Currie Author: Bill Currie Date: 2003/5/5 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 2 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, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifndef __QF_ui_view_h #define __QF_ui_view_h #include "QF/ecs/component.h" #include "QF/ecs/hierarchy.h" /** \defgroup console_view Console View Objects \ingroup console */ ///@{ /** Control the positioning of a view within its parent. The directions are the standard compass rose (north, east, south, west in clockwise order) with north at the top. The origin of the view is taken to be the corresponding point on the edge of the view (eg, southeast is bottom right), or the view's center for center gravity. When the relative coordinates of the view are (0,0), the view's origin is placed on the parent view's gravity point using the view's gravity (\em not the parent view's gravity). That is, the parent view's gravity has no effect on the view's position within the parent view. The gravity also affects the direction the view moves as the relative coordinates of the view change. No checking is done to ensure the view stays within the parent, or that the view is smaller than the parent. This is by design. It is up to the drawing callbacks to do any necessary clipping. */ typedef enum { grav_center, ///< +ve X right, +ve Y down, -X left, -ve Y up grav_north, ///< +ve X right, +ve Y down, -X left, -ve Y up grav_northeast, ///< +ve X left, +ve Y down, -X right, -ve Y up grav_east, ///< +ve X left, +ve Y down, -X right, -ve Y up grav_southeast, ///< +ve X left, +ve Y up, -X right, -ve Y down grav_south, ///< +ve X right, +ve Y up, -X left, -ve Y down grav_southwest, ///< +ve X right, +ve Y up, -X left, -ve Y down grav_west, ///< +ve X right, +ve Y down, -X left, -ve Y up grav_northwest, ///< +ve X right, +ve Y down, -X left, -ve Y up grav_flow, ///< controlled by view_flow } grav_t; extern struct exprtype_s grav_t_type; typedef struct view_pos_s { int x; int y; } view_pos_t; typedef struct viewcont_s { grav_t gravity; ///< The gravity of the view. unsigned visible:1; ///< If false, view_draw() skips this view. unsigned resize_x:1; ///< If true, view's width follows parent's. unsigned resize_y:1; ///< If true, view's height follows parent's. unsigned bol_suppress:1; ///< If true, view_flow skips at start of line. unsigned flow_size:1; ///< If true, view's size is adjusted to flow. } viewcont_t; enum { /// Coordinates of view's origin relative to parent's gravity point. view_pos, /// Size of the view. view_len, /** Absolute coordinates of the top left (northwest) corner of the view. Set interally. */ view_abs, /** Coordinates of the top left (northwest) corner of the view relative to the parent view's top left corner. Set internally. */ view_rel, view_oldlen, view_control, view_modified, view_onresize, view_onmove, view_type_count }; /** The view object. */ typedef struct view_s { ecs_registry_t *reg; uint32_t id; uint32_t comp; } view_t; #define nullview ((view_t) {}) typedef void (*view_resize_f) (view_t view, view_pos_t len); typedef void (*view_move_f) (view_t view, view_pos_t abs); #define VIEWINLINE GNU89INLINE inline view_t View_New (ecs_registry_t *reg, view_t parent); VIEWINLINE void View_Delete (view_t view); void View_SetParent (view_t view, view_t parent); void View_UpdateHierarchy (view_t view); void view_flow_right_down (view_t view, view_pos_t len); void view_flow_right_up (view_t view, view_pos_t len); void view_flow_left_down (view_t view, view_pos_t len); void view_flow_left_up (view_t view, view_pos_t len); void view_flow_down_right (view_t view, view_pos_t len); void view_flow_up_right (view_t view, view_pos_t len); void view_flow_down_left (view_t view, view_pos_t len); void view_flow_up_left (view_t view, view_pos_t len); VIEWINLINE hierref_t *View_GetRef (view_t view); VIEWINLINE int View_Valid (view_t view); VIEWINLINE view_t View_GetParent (view_t view); VIEWINLINE uint32_t View_ChildCount (view_t view); VIEWINLINE view_t View_GetChild (view_t view, uint32_t index); VIEWINLINE void View_SetPos (view_t view, int x, int y); VIEWINLINE view_pos_t View_GetPos (view_t view); VIEWINLINE view_pos_t View_GetAbs (view_t view); VIEWINLINE view_pos_t View_GetRel (view_t view); VIEWINLINE void View_SetLen (view_t view, int x, int y); VIEWINLINE view_pos_t View_GetLen (view_t view); VIEWINLINE viewcont_t* View_Control (view_t view); VIEWINLINE void View_SetGravity (view_t view, grav_t grav); VIEWINLINE grav_t View_GetGravity (view_t view); VIEWINLINE void View_SetVisible (view_t view, int visible); VIEWINLINE int View_GetVisible (view_t view); VIEWINLINE void View_SetResize (view_t view, int resize_x, int resize_y); VIEWINLINE void View_SetOnResize (view_t view, view_resize_f onresize); VIEWINLINE void View_SetOnMove (view_t view, view_move_f onmove); #undef VIEWINLINE #ifndef IMPLEMENT_VIEW_Funcs #define VIEWINLINE GNU89INLINE inline #else #define VIEWINLINE VISIBLE #endif VIEWINLINE hierref_t * View_GetRef (view_t view) { return Ent_GetComponent (view.id, view.comp, view.reg); } VIEWINLINE int View_Valid (view_t view) { return view.reg && ECS_EntValid (view.id, view.reg); } VIEWINLINE void View_Delete (view_t view) { __auto_type ref = *View_GetRef (view); Hierarchy_RemoveHierarchy (ref.hierarchy, ref.index, 1); if (!ref.hierarchy->num_objects) { Hierarchy_Delete (ref.hierarchy); } } VIEWINLINE view_t View_GetParent (view_t view) { __auto_type ref = View_GetRef (view); if (ref->index == 0) { return nullview; } hierarchy_t *h = ref->hierarchy; return (view_t) { .reg = view.reg, .id = h->ent[h->parentIndex[ref->index]], .comp = view.comp, }; } VIEWINLINE uint32_t View_ChildCount (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; return h->childCount[ref->index]; } VIEWINLINE view_t View_GetChild (view_t view, uint32_t childIndex) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; if (childIndex >= h->childCount[ref->index]) { return nullview; } return (view_t) { .reg = view.reg, .id = h->ent[h->childIndex[ref->index] + childIndex], .comp = view.comp, }; } VIEWINLINE void View_SetPos (view_t view, int x, int y) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *pos = h->components[view_pos]; byte *modified = h->components[view_modified]; pos[ref->index] = (view_pos_t) { x, y }; modified[ref->index] |= 1; } VIEWINLINE view_pos_t View_GetPos (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *pos = h->components[view_pos]; return pos[ref->index]; } VIEWINLINE view_pos_t View_GetAbs (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *abs = h->components[view_abs]; return abs[ref->index]; } VIEWINLINE view_pos_t View_GetRel (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *rel = h->components[view_rel]; return rel[ref->index]; } VIEWINLINE void View_SetLen (view_t view, int x, int y) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *len = h->components[view_len]; view_pos_t *oldlen = h->components[view_oldlen]; byte *modified = h->components[view_modified]; if (!(modified[ref->index] & 2)) { oldlen[ref->index] = len[ref->index]; } len[ref->index] = (view_pos_t) { x, y }; modified[ref->index] |= 2; } VIEWINLINE view_pos_t View_GetLen (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_pos_t *len = h->components[view_len]; return len[ref->index]; } VIEWINLINE viewcont_t * View_Control (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; return &cont[ref->index]; } VIEWINLINE void View_SetGravity (view_t view, grav_t grav) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; byte *modified = h->components[view_modified]; cont[ref->index].gravity = grav; modified[ref->index] |= 1; } VIEWINLINE grav_t View_GetGravity (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; return cont[ref->index].gravity; } VIEWINLINE void View_SetVisible (view_t view, int visible) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; cont[ref->index].visible = !!visible; } VIEWINLINE int View_GetVisible (view_t view) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; return cont[ref->index].visible; } VIEWINLINE void View_SetResize (view_t view, int resize_x, int resize_y) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; viewcont_t *cont = h->components[view_control]; cont[ref->index].resize_x = resize_x; cont[ref->index].resize_y = resize_y; } VIEWINLINE void View_SetOnResize (view_t view, view_resize_f onresize) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_resize_f *resize = h->components[view_onresize]; resize[ref->index] = onresize; } VIEWINLINE void View_SetOnMove (view_t view, view_move_f onmove) { __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; view_move_f *move = h->components[view_onmove]; move[ref->index] = onmove; } ///@} #endif//__QF_ui_view_h