Beispiel #1
0
/* Function: al_popup_menu
 */
bool al_popup_menu(ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display)
{
   bool ret;
   ASSERT(popup);

   if (!popup->is_popup_menu || popup->parent)
      return false;

   if (!display)
      display = al_get_current_display();

   /* Set the entire menu tree as owned by the display */
   _al_walk_over_menu(popup, set_menu_display_r, display);

   ret = _al_show_popup_menu(display, popup);

   if (!ret) {
      _al_walk_over_menu(popup, set_menu_display_r, NULL);
   }
   return ret;
}
Beispiel #2
0
/* [user thread] */
bool _al_destroy_menu(ALLEGRO_MENU *menu)
{
   ARGS *args;
   
   if (!menu->extra1)
      return true;
   
   args = create_args();
   args->menu = menu;
   
   wait_for_args(do_destroy_menu, args);
   /* TODO: decrease_window_counter(); ... but only if this is a top level menu */
   _al_walk_over_menu(menu, clear_menu_extras, NULL);
   
   return true;
}
Beispiel #3
0
/* [user thread] */
bool _al_destroy_menu_item_at(ALLEGRO_MENU_ITEM *item, int i)
{
   if (item->extra1) {
      ARGS *args = make_menu_item_args(item, i);
      if (!args)
         return false;
         
      wait_for_args(do_destroy_menu_item_at, args);
      
      if (item->popup) {
         /* if this has a submenu, then deleting this item will have automatically
            deleted all of its GTK widgets */
         _al_walk_over_menu(item->popup, clear_menu_extras, NULL);
      }
   }
   return true;
}
Beispiel #4
0
/* [user thread] */
bool _al_destroy_menu(ALLEGRO_MENU *menu)
{
   ARGS args;

   if (!menu->extra1)
      return true;
   
   if (!_al_gtk_init_args(&args, sizeof(args)))
      return false;

   args.menu = menu;
   _al_gtk_wait_for_args(do_destroy_menu, &args);

   _al_walk_over_menu(menu, clear_menu_extras, NULL);
   
   return true;
}
Beispiel #5
0
/* [user thread] */
bool _al_hide_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
{
   GtkWidget *gtk_window;
   ARGS args;

   if (!(gtk_window = _al_gtk_get_window(display)))
      return false;
   
   if (!_al_gtk_init_args(&args, sizeof(args)))
      return false;
   
   args.gtk_window = gtk_window;
   args.menu = menu;
   _al_gtk_wait_for_args(do_hide_display_menu, &args);
   _al_walk_over_menu(menu, clear_menu_extras, NULL);
   
   return true;
}
Beispiel #6
0
/* Recursively walks over the entire menu structure, calling the user proc once per menu item,
 * and once per menu. The deepest menu is called first. If the proc returns true, then the
 * process terminates. It is not safe for the proc to modify the structure (add/remove items).
 */
bool _al_walk_over_menu(ALLEGRO_MENU *menu,
   bool (*proc)(ALLEGRO_MENU *menu, ALLEGRO_MENU_ITEM *item, int index, void *extra), void *extra)
{
   ALLEGRO_MENU_ITEM **slot;
   size_t i;
   ASSERT(menu);
   ASSERT(proc);

   for (i = 0; i < _al_vector_size(&menu->items); ++i) {
      slot = _al_vector_ref(&menu->items, i);
      
      if ((*slot)->popup && _al_walk_over_menu((*slot)->popup, proc, extra))
         return true;
 
      if (proc(menu, *slot, i, extra))
         return true;
   }

   return proc(menu, NULL, -1, extra);
}
Beispiel #7
0
/* [user thread] */
bool _al_hide_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
{
#ifdef CREATE_WINDOW_FOR_MENU
   ARGS *args;
   
   if (!(args = create_args()))
      return false;
   
   args->display = display;
   args->menu = menu;      
   wait_for_args(do_hide_display_menu, args);   
   _al_walk_over_menu(menu, clear_menu_extras, NULL);
   
   return true;
#else
   (void) display;
   (void) menu;
   
   return false;
#endif
}
Beispiel #8
0
/* Function: al_find_menu_item
 */
bool al_find_menu_item(ALLEGRO_MENU *haystack, uint16_t id, ALLEGRO_MENU **menu,
   int *index)
{
   ALLEGRO_MENU_ITEM item; 

   ASSERT(haystack);

   /* Abuse the ALLEGRO_MENU_ITEM struct as a container for the _al_walk_over_menu callback.
    * If found, it will return true, and the "parent" field will be the menu that and
    * the "id" will be the index.
    */
   item.id = id;

   if (!_al_walk_over_menu(haystack, find_menu_item_r, &item))
      return false;

   if (menu)
      *menu = item.parent;
   
   if (index)
      *index = item.id;

   return true;
}
Beispiel #9
0
/* Function: al_set_display_menu
 */
bool al_set_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
{
   DISPLAY_MENU *dm = NULL;
   size_t i;
   int menu_height = _al_get_menu_display_height();
   bool automatic_menu_display_resize = true;
   const char* automatic_menu_display_resize_value =
      al_get_config_value(al_get_system_config(), "compatibility", "automatic_menu_display_resize");
   if (automatic_menu_display_resize_value && strcmp(automatic_menu_display_resize_value, "false") == 0)
      automatic_menu_display_resize = false; 

   ASSERT(display);

   /* Check if this display has a menu associated with it */
   for (i = 0; i < _al_vector_size(&display_menus); ++i) {
      dm = (DISPLAY_MENU *) _al_vector_ref(&display_menus, i);
      if (dm->display == display)
         break;
   }

   /* If no display was found, reset dm to NULL */
   if (i == _al_vector_size(&display_menus))
      dm = NULL;

   if (!menu) {
      /* Removing the menu */

      if (!dm)
         return false;

      _al_hide_display_menu(display, dm->menu);
      _al_walk_over_menu(dm->menu, set_menu_display_r, NULL);
      _al_vector_delete_at(&display_menus, i);

      if (automatic_menu_display_resize && menu_height > 0) {
         display->extra_resize_height = 0;
         al_resize_display(display, al_get_display_width(display), al_get_display_height(display));
      }
   }
   else {
      /* Setting the menu. It must not currently be attached to any 
       * display, and it cannot have a parent menu. */
      if (menu->display || menu->parent)
         return false;

      if (dm) {
         /* hide the existing menu */
         _al_hide_display_menu(display, dm->menu);
         _al_walk_over_menu(dm->menu, set_menu_display_r, NULL);
      }

      if (!_al_show_display_menu(display, menu)) {
         /* Unable to set the new menu, but already have hidden the 
          * previous one, so delete the display_menus slot. */
         if (dm) 
            _al_vector_delete_at(&display_menus, i);
         return false;
      }

      /* Set the entire menu tree as owned by the display */
      _al_walk_over_menu(menu, set_menu_display_r, display);

      if (!dm)
         dm = _al_vector_alloc_back(&display_menus);

      if (automatic_menu_display_resize && menu_height > 0) {
         /* Temporarily disable the constraints so we don't send a RESIZE_EVENT. */
         bool old_constraints = display->use_constraints;
         display->use_constraints = false;
         display->extra_resize_height = menu_height;
         al_resize_display(display, al_get_display_width(display), al_get_display_height(display));
         display->use_constraints = old_constraints;
      }

      dm->display = display;
      dm->menu = menu;
   }

   return true;
}
Beispiel #10
0
/* Function: al_insert_menu_item
 */
int al_insert_menu_item(ALLEGRO_MENU *parent, int pos, char const *title,
   uint16_t id, int flags, ALLEGRO_BITMAP *icon, ALLEGRO_MENU *submenu)
{
   ALLEGRO_MENU_ITEM *item;
   ALLEGRO_MENU_ITEM **slot;
   _AL_MENU_ID *menu_id;
   size_t i;

   ASSERT(parent);

   /* If not found, then treat as an append. */
   if (!interpret_menu_id_param(&parent, &pos))
      pos = _al_vector_size(&parent->items);

   /* At this point pos == the _index_ of where to insert */

   /* The sub-menu must not already be in use. */
   if (submenu && (submenu->display || submenu->parent || submenu->is_popup_menu))
      return -1;

   item = create_menu_item(title, id, flags, submenu);
   if (!item)
      return -1;
   item->parent = parent;
   
   set_item_icon(item, icon);

   i = (size_t) pos;

   if (i >= _al_vector_size(&parent->items)) {
      /* Append */
      i = _al_vector_size(&parent->items);
      slot = _al_vector_alloc_back(&parent->items);
   }
   else {
      /* Insert */
      slot = _al_vector_alloc_mid(&parent->items, i);
   }  

   if (!slot) {
      destroy_menu_item(item);
      return -1;
   }
   *slot = item;

   if (submenu) {
      submenu->parent = item;

      if (parent->display)
         _al_walk_over_menu(submenu, set_menu_display_r, parent->display);
   }

   _al_insert_menu_item_at(item, (int) i);

   if (id) {
      /* Append the menu's ID to the search vector */
      menu_id = (_AL_MENU_ID *) _al_vector_alloc_back(&menu_ids);
      menu_id->unique_id = item->unique_id;
      menu_id->id = id;
      menu_id->menu = parent;
   }

   return (int) i;
}