]> git.decadent.org.uk Git - ion3.git/blobdiff - mod_menu/menu.c
[svn-upgrade] Integrating new upstream version, ion3 (20070203)
[ion3.git] / mod_menu / menu.c
index b8ec9cfa446984102770562de2ba244c45ccd5eb..d891c230b6690a014b3cf1ec5810af78c450031b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ion/mod_menu/menu.c
  *
- * Copyright (c) Tuomo Valkonen 1999-2006
+ * Copyright (c) Tuomo Valkonen 1999-2007
  *
  * Ion is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by
@@ -28,6 +28,8 @@
 #include <ioncore/event.h>
 #include <ioncore/xwindow.h>
 #include <ioncore/names.h>
+#include <ioncore/gr.h>
+#include <ioncore/gr-util.h>
 #include "menu.h"
 #include "main.h"
 
@@ -85,22 +87,35 @@ static void get_inner_geom(WMenu *menu, WRectangle *geom)
 }
 
 
+GR_DEFATTR(active);
+GR_DEFATTR(inactive);
+GR_DEFATTR(selected);
+GR_DEFATTR(unselected);
+GR_DEFATTR(normal);
+GR_DEFATTR(submenu);
+
+
+static void init_attr()
+{
+    GR_ALLOCATTR_BEGIN;
+    GR_ALLOCATTR(active);
+    GR_ALLOCATTR(inactive);
+    GR_ALLOCATTR(selected);
+    GR_ALLOCATTR(unselected);
+    GR_ALLOCATTR(normal);
+    GR_ALLOCATTR(submenu);
+    GR_ALLOCATTR_END;
+}
+
+
 static void menu_draw_entry(WMenu *menu, int i, const WRectangle *igeom,
                             bool complete)
 {
     WRectangle geom;
-    int a;
-
-    static const char *attrs[]={
-        "active-selected-normal",
-        "active-selected-submenu",
-        "active-unselected-normal",
-        "active-unselected-submenu",
-        "inactive-selected-normal",
-        "inactive-selected-submenu",
-        "inactive-unselected-normal",
-        "inactive-unselected-submenu",
-    };
+    GrAttr sa, aa;
+
+    aa=(REGION_IS_ACTIVE(menu) ? GR_ATTR(active) : GR_ATTR(inactive));
+    sa=(menu->selected_entry==i ? GR_ATTR(selected) : GR_ATTR(unselected));
     
     if(menu->entry_brush==NULL)
         return;
@@ -109,14 +124,15 @@ static void menu_draw_entry(WMenu *menu, int i, const WRectangle *igeom,
     geom.h=menu->entry_h;
     geom.y+=(i-menu->first_entry)*(menu->entry_h+menu->entry_spacing);
     
-    a=((REGION_IS_ACTIVE(menu) ? 0 : 4)
-       |(menu->selected_entry==i ? 0 : 2)
-       |(menu->entries[i].flags&WMENUENTRY_SUBMENU ? 1 : 0));
-
-    grbrush_begin(menu->entry_brush, &geom, GRBRUSH_AMEND);
+    grbrush_begin(menu->entry_brush, &geom, GRBRUSH_AMEND|GRBRUSH_KEEP_ATTR);
+    
+    grbrush_init_attr(menu->entry_brush, &menu->entries[i].attr);
+    
+    grbrush_set_attr(menu->entry_brush, aa);
+    grbrush_set_attr(menu->entry_brush, sa);
 
     grbrush_draw_textbox(menu->entry_brush, &geom, menu->entries[i].title, 
-                         attrs[a], complete);
+                         complete);
     
     grbrush_end(menu->entry_brush);
 }
@@ -126,10 +142,10 @@ void menu_draw_entries(WMenu *menu, bool complete)
 {
     WRectangle igeom;
     int i, mx;
-
+    
     if(menu->entry_brush==NULL)
         return;
-    
+        
     get_inner_geom(menu, &igeom);
     
     mx=menu->first_entry+menu->vis_entries;
@@ -142,8 +158,8 @@ void menu_draw_entries(WMenu *menu, bool complete)
 
 void menu_draw(WMenu *menu, bool complete)
 {
+    GrAttr aa=(REGION_IS_ACTIVE(menu) ? GR_ATTR(active) : GR_ATTR(inactive));
     WRectangle geom;
-    const char *substyle=(REGION_IS_ACTIVE(menu) ? "active" : "inactive");
     
     if(menu->brush==NULL)
         return;
@@ -153,7 +169,9 @@ void menu_draw(WMenu *menu, bool complete)
     grbrush_begin(menu->brush, &geom, 
                   (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
     
-    grbrush_draw_border(menu->brush, &geom, substyle);
+    grbrush_set_attr(menu->brush, aa);
+    
+    grbrush_draw_border(menu->brush, &geom);
     
     menu_draw_entries(menu, FALSE);
     
@@ -491,9 +509,8 @@ static void menu_release_gr(WMenu *menu)
 
 static WMenuEntry *preprocess_menu(ExtlTab tab, int *n_entries)
 {
-    ExtlTab entry, sub;
-    ExtlFn fn;
     WMenuEntry *entries;
+    ExtlTab entry;
     int i, n;
     
     n=extl_table_get_n(tab);
@@ -506,17 +523,40 @@ static WMenuEntry *preprocess_menu(ExtlTab tab, int *n_entries)
     
     if(entries==NULL)
         return NULL;
-
+        
+    init_attr();
+    
     /* Initialise entries and check submenus */
     for(i=1; i<=n; i++){
-        entries[i-1].title=NULL;
-        entries[i-1].flags=0;
-        if(extl_table_getis(tab, i, "submenu_fn", 'f', &fn)){
-            entries[i-1].flags|=WMENUENTRY_SUBMENU;
-            extl_unref_fn(fn);
-        }else if(extl_table_getis(tab, i, "submenu", 't', &sub)){
-            entries[i-1].flags|=WMENUENTRY_SUBMENU;
-            extl_unref_table(sub);
+        WMenuEntry *ent=&entries[i-1];
+        
+        ent->title=NULL;
+        ent->flags=0;
+        
+        gr_stylespec_init(&ent->attr);
+        
+        if(extl_table_geti_t(tab, i, &entry)){
+            char *attr;
+            ExtlTab sub;
+            ExtlFn fn;
+            
+            if(extl_table_gets_s(entry, "attr", &attr)){
+                gr_stylespec_load_(&ent->attr, attr, TRUE);
+                free(attr);
+            }
+            
+            if(extl_table_gets_f(entry, "submenu_fn", &fn)){
+                ent->flags|=WMENUENTRY_SUBMENU;
+                extl_unref_fn(fn);
+            }else if(extl_table_gets_t(entry, "submenu", &sub)){
+                ent->flags|=WMENUENTRY_SUBMENU;
+                extl_unref_table(sub);
+            }
+            
+            if(ent->flags&WMENUENTRY_SUBMENU)
+                gr_stylespec_set(&ent->attr, GR_ATTR(submenu));
+            
+            extl_unref_table(entry);
         }
     }
     
@@ -524,6 +564,8 @@ static WMenuEntry *preprocess_menu(ExtlTab tab, int *n_entries)
 }
 
 
+static void deinit_entries(WMenu *menu);
+
 
 bool menu_init(WMenu *menu, WWindow *par, const WFitParams *fp,
                const WMenuCreateParams *params)
@@ -545,9 +587,9 @@ bool menu_init(WMenu *menu, WWindow *par, const WFitParams *fp,
 
     menu->last_fp=*fp;
     
-    if(params->pmenu_mode)
+    if(params->pmenu_mode){
         menu->selected_entry=-1;
-    else{
+    }else{
         menu->selected_entry=params->initial-1;
         if(menu->selected_entry<0)
            menu->selected_entry=0;
@@ -575,7 +617,9 @@ bool menu_init(WMenu *menu, WWindow *par, const WFitParams *fp,
     
     if(!menu_init_gr(menu, region_rootwin_of((WRegion*)par), win))
         goto fail2;
-
+        
+    init_attr();
+    
     menu_firstfit(menu, params->submenu_mode, &(params->refg));
     
     window_select_input(&(menu->win), IONCORE_EVENTMASK_NORMAL);
@@ -591,7 +635,7 @@ fail2:
 fail:
     extl_unref_table(menu->tab);
     extl_unref_fn(menu->handler);
-    free(menu->entries);
+    deinit_entries(menu);
     return FALSE;
 }
 
@@ -603,11 +647,22 @@ WMenu *create_menu(WWindow *par, const WFitParams *fp,
 }
 
 
-
-void menu_deinit(WMenu *menu)
+static void deinit_entries(WMenu *menu)
 {
     int i;
     
+    for(i=0; i<menu->n_entries; i++){
+        gr_stylespec_unalloc(&menu->entries[i].attr);
+        if(menu->entries[i].title!=NULL)
+            free(menu->entries[i].title);
+    }
+    
+    free(menu->entries);
+}
+
+
+void menu_deinit(WMenu *menu)
+{
     menu_typeahead_clear(menu);
     
     if(menu->submenu!=NULL)
@@ -616,11 +671,10 @@ void menu_deinit(WMenu *menu)
     extl_unref_table(menu->tab);
     extl_unref_fn(menu->handler);
     
-    for(i=0; i<menu->n_entries; i++)
-        free(menu->entries[i].title);
-    free(menu->entries);
+    deinit_entries(menu);
     
     menu_release_gr(menu);
+    
     window_deinit((WWindow*)menu);
 }
 
@@ -931,7 +985,7 @@ EXTL_EXPORT_MEMBER
 void menu_cancel(WMenu *menu)
 {
     if(region_manager_allows_destroying((WRegion*)menu))
-        mainloop_defer_destroy((Obj*)menu);
+        region_dispose_((WRegion*)menu);
 }