Atrinik Client  4.0
menu.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
33 #include <global.h>
34 
37 {
38  widgetdata *tmp, *tmp2, *tmp3, *submenuwidget = NULL;
39  _menu *menu = NULL, *tmp_menu = NULL;
40  _menuitem *menuitem = NULL, *submenuitem = NULL;
41  int visible, create_submenu = 0, x = 0, y = 0;
42 
43  /* Sanity check. Make sure widget is a menu. */
44  if (!widget || widget->sub_type != MENU_ID) {
45  return;
46  }
47 
48  /* Check to see if the cursor is hovering over a menuitem or a widget inside
49  * it.
50  * We don't need to go recursive here, just scan the immediate children. */
51  for (tmp = widget->inv; tmp; tmp = tmp->next) {
52  visible = 0;
53 
54  /* Menuitem is being directly hovered over. Make the background visible
55  * for visual feedback. */
56  if (tmp == widget_mouse_event.owner) {
57  visible = 1;
58  } else if (tmp->inv) {
59  /* The cursor is hovering over something the menuitem contains. This
60  * only needs to search the direct children,
61  * as there should be nothing contained within the children. */
62 
63  for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->next) {
64  if (tmp2 == widget_mouse_event.owner) {
65  /* The cursor was hovering over something inside the
66  * menuitem. */
67  visible = 1;
68  break;
69  }
70  }
71  }
72 
73  /* Only do any real working if the state of the menuitem changed. */
74  if (tmp->hidden != visible) {
75  continue;
76  }
77 
78  menu = MENU(widget);
79  menuitem = MENUITEM(tmp);
80 
81  /* Cursor has just started to hover over the menuitem. */
82  if (visible) {
83  tmp->hidden = 0;
84 
85  /* If the highlighted menuitem is a submenu, we need to create a
86  * submenu next to the menuitem. */
87  if (menuitem->menu_type == MENU_SUBMENU) {
88  create_submenu = 1;
89  submenuitem = menuitem;
90  submenuwidget = tmp;
91  x = tmp->x + widget->w - 4;
92  y = tmp->y - (CONTAINER(widget))->outer_padding_top;
93  }
94  } else {
95  /* Cursor no longer hovers over the menuitem. */
96 
97  tmp->hidden = 1;
98 
99  /* Let's check if we need to remove the submenu.
100  * Don't remove it if the cursor is hovering over the submenu
101  * itself,
102  * or a submenu of the submenu, etc. */
103  if (menuitem->menu_type == MENU_SUBMENU && menu->submenu) {
104  /* This will for sure get the menu that the cursor is hovering
105  * over. */
107 
108  /* Just in case the 'for sure' part of the last comment turns
109  * out to be incorrect... */
110  if (tmp2 && tmp2->sub_type == MENU_ID) {
111  /* Loop through the submenus to see if we find a match for
112  * the menu the cursor is hovering over. */
113  for (tmp_menu = menu; tmp_menu->submenu && tmp_menu->submenu != tmp2; tmp_menu = MENU(tmp_menu->submenu)) {
114  }
115 
116  /* Remove any submenus related to menu if the menu
117  * underneath the cursor is not a submenu of menu. */
118  if (!tmp_menu->submenu) {
119  tmp2 = menu->submenu;
120 
121  while (tmp2) {
122  tmp3 = (MENU(tmp2))->submenu;
123  remove_widget_object(tmp2);
124  tmp2 = tmp3;
125  }
126 
127  menu->submenu = NULL;
128  } else {
129  /* Cursor is hovering over the submenu, so leave this
130  * menuitem highlighted. */
131  tmp->hidden = 0;
132  }
133  } else {
134  /* Cursor is not over a menu, so leave the menuitem containing
135  * the submenu highlighted.
136  * We want to keep the submenu open, which should reduce
137  * annoyance if the user is not precise with the mouse. */
138  tmp->hidden = 0;
139  }
140  }
141  }
142  }
143 
144  /* If a submenu needs to be created, create it now. Make sure there can be
145  * only one submenu open here. */
146  if (create_submenu && !menu->submenu) {
147  tmp_menu = MENU(widget);
148 
149  tmp_menu->submenu = create_menu(x, y, tmp_menu->owner);
150 
151  if (submenuitem->menu_func_ptr) {
152  submenuitem->menu_func_ptr(tmp_menu->owner, submenuwidget, NULL);
153  }
154 
155  menu_finalize(tmp_menu->submenu);
156  }
157 }
widgetdata * submenu
Definition: widget.h:255
void remove_widget_object(widgetdata *widget)
Definition: widget.c:460
int sub_type
Definition: widget.h:122
void menu_finalize(widgetdata *widget)
Definition: widget.c:2524
struct widgetdata * next
Definition: widget.h:86
int hidden
Definition: widget.h:140
struct widgetdata * inv
Definition: widget.h:92
int menu_type
Definition: widget.h:274
Definition: widget.h:252
widgetdata * get_outermost_container(widgetdata *widget)
Definition: widget.c:2047
int x
Definition: widget.h:48
widgetdata * create_menu(int x, int y, widgetdata *owner)
Definition: widget.c:2428
int w
Definition: widget.h:54
widgetdata * owner
Definition: widget.h:360
widgetevent widget_mouse_event
Definition: widget.c:82
void widget_highlight_menu(widgetdata *widget)
Definition: menu.c:36
int y
Definition: widget.h:51