minimenu fixes so icon-wrap is better handled in edge cases -- pushing right, on...
[pandora-libraries.git] / minimenu / mmui.c
index 248846b..90288e8 100644 (file)
@@ -11,6 +11,8 @@
 #include "SDL_gfxPrimitives.h"
 #include "SDL_rotozoom.h"
 #include "SDL_thread.h"
+#include <sys/types.h>
+#include <dirent.h>
 
 #include "pnd_conf.h"
 #include "pnd_logger.h"
@@ -19,6 +21,8 @@
 #include "pnd_discovery.h"
 #include "pnd_apps.h"
 #include "pnd_device.h"
+#include "../lib/pnd_pathiter.h"
+#include "pnd_utility.h"
 
 #include "mmenu.h"
 #include "mmcat.h"
@@ -155,11 +159,11 @@ unsigned char ui_setup ( void ) {
   }
 
   // grid font
-  sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, MMENU_GRID_FONT ) );
-  g_grid_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, MMENU_GRID_FONTSIZE, 10 ) );
+  sprintf ( fullpath, "%s/%s", g_skinpath, pnd_conf_get_as_char ( g_conf, "grid.font" ) );
+  g_grid_font = TTF_OpenFont ( fullpath, pnd_conf_get_as_int_d ( g_conf, "grid.font_ptsize", 10 ) );
   if ( ! g_grid_font ) {
     pnd_log ( pndn_error, "ERROR: Couldn't load font '%s' for size %u\n",
-             pnd_conf_get_as_char ( g_conf, MMENU_GRID_FONT ), pnd_conf_get_as_int_d ( g_conf, MMENU_GRID_FONTSIZE, 10 ) );
+             pnd_conf_get_as_char ( g_conf, "grid.font" ), pnd_conf_get_as_int_d ( g_conf, "grid.font_ptsize", 10 ) );
     return ( 0 ); // couldn't set up SDL TTF
   }
 
@@ -246,7 +250,6 @@ unsigned char ui_imagecache ( char *basepath ) {
   //
 
   // scale icons
-  g_imagecache [ IMG_SELECTED_ALPHAMASK ].i = ui_scale_image ( g_imagecache [ IMG_SELECTED_ALPHAMASK ].i, pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_width", 50 ), -1 );
   g_imagecache [ IMG_ICON_MISSING ].i = ui_scale_image ( g_imagecache [ IMG_ICON_MISSING ].i, pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_width", 50 ), -1 );
   // scale text hilight
   g_imagecache [ IMG_SELECTED_HILITE ].i = ui_scale_image ( g_imagecache [ IMG_SELECTED_HILITE ].i, pnd_conf_get_as_int_d ( g_conf, "grid.text_width", 50 ), -1 );
@@ -309,8 +312,8 @@ void ui_render ( void ) {
 
   unsigned int screen_width = pnd_conf_get_as_int_d ( g_conf, "display.screen_width", 800 );
 
-  unsigned char row_max = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_ROWMAX, 4 );
-  unsigned char col_max = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_COLMAX, 5 );
+  unsigned char row_max = pnd_conf_get_as_int_d ( g_conf, "grid.row_max", 4 );
+  unsigned char col_max = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 );
 
   unsigned int font_rgba_r = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_r", 200 );
   unsigned int font_rgba_g = pnd_conf_get_as_int_d ( g_conf, "display.font_rgba_g", 200 );
@@ -324,6 +327,8 @@ void ui_render ( void ) {
   unsigned int icon_offset_y = pnd_conf_get_as_int ( g_conf, "grid.icon_offset_y" );
   unsigned int icon_max_width = pnd_conf_get_as_int ( g_conf, "grid.icon_max_width" );
   unsigned int icon_max_height = pnd_conf_get_as_int ( g_conf, "grid.icon_max_height" );
+  unsigned int sel_icon_offset_x = pnd_conf_get_as_int_d ( g_conf, "grid.sel_offoffset_x", 0 );
+  unsigned int sel_icon_offset_y = pnd_conf_get_as_int_d ( g_conf, "grid.sel_offoffset_y", 0 );
 
   unsigned int text_width = pnd_conf_get_as_int ( g_conf, "grid.text_width" );
   unsigned int text_clip_x = pnd_conf_get_as_int ( g_conf, "grid.text_clip_x" );
@@ -356,7 +361,7 @@ void ui_render ( void ) {
     int topleft = col_max * ui_rows_scrolled_down;
     int botright = ( col_max * ( ui_rows_scrolled_down + row_max ) - 1 );
 
-    //pnd_log ( PND_LOG_DEFAULT, "index %u tl %u br %u\n", index, topleft, botright );
+    pnd_log ( PND_LOG_DEFAULT, "index %u tl %u br %u\n", index, topleft, botright );
 
     if ( index < topleft ) {
       ui_rows_scrolled_down -= pnd_conf_get_as_int_d ( g_conf, "grid.scroll_increment", 1 );
@@ -427,12 +432,17 @@ void ui_render ( void ) {
       // draw tab
       src.x = 0;
       src.y = 0;
+#if 0
       src.w = tab_width;
       if ( col == ui_category ) {
        src.h = tab_selheight;
       } else {
        src.h = tab_height;
       }
+#else
+      src.w = s -> w;
+      src.h = s -> h;
+#endif
       dest -> x = tab_offset_x + ( (col-ui_catshift) * tab_width );
       dest -> y = tab_offset_y;
 
@@ -577,12 +587,12 @@ void ui_render ( void ) {
     if ( ! ( render_jobs_b & R_BG ) ) {
       if ( g_imagecache [ IMG_BACKGROUND_800480 ].i ) {
        src.x = grid_offset_x;
-       src.y = grid_offset_y;
+       src.y = grid_offset_y + sel_icon_offset_y;
        src.w = col_max * cell_width;
        src.h = row_max * cell_height;
 
        dest -> x = grid_offset_x;
-       dest -> y = grid_offset_y;
+       dest -> y = grid_offset_y + sel_icon_offset_y;
 
        SDL_BlitSurface ( g_imagecache [ IMG_BACKGROUND_800480 ].i, &src, sdl_realscreen, dest );
        dest++;
@@ -606,10 +616,13 @@ void ui_render ( void ) {
 
            // selected? show hilights
            if ( appiter == ui_selected ) {
+             SDL_Surface *s = g_imagecache [ IMG_SELECTED_ALPHAMASK ].i;
              // icon
-             dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x;
-             dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y;
-             SDL_BlitSurface ( g_imagecache [ IMG_SELECTED_ALPHAMASK ].i, NULL /* all */, sdl_realscreen, dest );
+             //dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x + ( ( icon_max_width - s -> w ) / 2 );
+             dest -> x = grid_offset_x + ( col * cell_width ) + icon_offset_x + sel_icon_offset_x;
+             //dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y + ( ( icon_max_height - s -> h ) / 2 );
+             dest -> y = grid_offset_y + ( displayrow * cell_height ) + icon_offset_y + sel_icon_offset_y;
+             SDL_BlitSurface ( s, NULL /* all */, sdl_realscreen, dest );
              dest++;
              // text
              dest -> x = grid_offset_x + ( col * cell_width ) + text_clip_x;
@@ -722,6 +735,7 @@ void ui_render ( void ) {
     }
 
     // category
+#if 0
     if ( ui_selected -> ref -> main_category ) {
 
       sprintf ( buffer, "Category: %s", ui_selected -> ref -> main_category );
@@ -740,6 +754,7 @@ void ui_render ( void ) {
       dest++;
       desty += src.h;
     }
+#endif
 
     // clock
     if ( ui_selected -> ref -> clockspeed ) {
@@ -777,7 +792,8 @@ void ui_render ( void ) {
     }
 
     // info hint
-    if ( ui_selected -> ref -> clockspeed && ui_selected -> ref -> info_filename ) {
+#if 0 // merged into hint-line
+    if ( ui_selected -> ref -> info_filename ) {
 
       sprintf ( buffer, "Documentation - hit Y" );
 
@@ -795,6 +811,38 @@ void ui_render ( void ) {
       dest++;
       desty += src.h;
     }
+#endif
+
+    // notes
+    if ( ui_selected -> ovrh ) {
+      char *n;
+      unsigned char i;
+      char buffer [ 50 ];
+
+      desty += 5; // a touch of spacing can't hurt
+
+      for ( i = 1; i < 4; i++ ) {
+       sprintf ( buffer, "Application-%u.note-%u", ui_selected -> ref -> subapp_number, i );
+       n = pnd_conf_get_as_char ( ui_selected -> ovrh, buffer );
+
+       if ( n ) {
+         SDL_Surface *rtext;
+         SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
+         rtext = TTF_RenderText_Blended ( g_detailtext_font, n, tmpfontcolor );
+         src.x = 0;
+         src.y = 0;
+         src.w = rtext -> w < cell_width ? rtext -> w : cell_width;
+         src.h = rtext -> h;
+         dest -> x = cell_offset_x;
+         dest -> y = desty;
+         SDL_BlitSurface ( rtext, &src, sdl_realscreen, dest );
+         SDL_FreeSurface ( rtext );
+         dest++;
+         desty += rtext -> h;
+       }
+      } // for
+
+    } // r_detail -> notes
 
     // preview pic
     mm_cache_t *ic = cache_query_preview ( ui_selected -> ref -> unique_id );
@@ -814,13 +862,13 @@ void ui_render ( void ) {
       dest++;
     }
 
-  } // selected?
+  } // r_detail && selected?
 
   // extras
   //
 
   // battery
-  if ( 1 ) {
+  if ( render_jobs_b & R_BG ) {
     static int last_battlevel = 0;
     static unsigned char batterylevel = 0;
     char buffer [ 100 ];
@@ -844,19 +892,47 @@ void ui_render ( void ) {
 
   // hints
   if ( pnd_conf_get_as_char ( g_conf, "display.hintline" ) ) {
-    char *buffer = pnd_conf_get_as_char ( g_conf, "display.hintline" );
+    char *buffer;
+    unsigned int hintx, hinty;
+    hintx = pnd_conf_get_as_int_d ( g_conf, "display.hint_x", 40 );
+    hinty = pnd_conf_get_as_int_d ( g_conf, "display.hint_y", 450 );
+    static unsigned int lastwidth = 3000;
+
+    if ( ui_selected && ui_selected -> ref -> info_filename ) {
+      buffer = "Documentation - hit Y";
+    } else {
+      buffer = pnd_conf_get_as_char ( g_conf, "display.hintline" );
+    }
+
     SDL_Surface *rtext;
     SDL_Color tmpfontcolor = { font_rgba_r, font_rgba_g, font_rgba_b, font_rgba_a };
     rtext = TTF_RenderText_Blended ( g_grid_font, buffer, tmpfontcolor );
-    dest -> x = pnd_conf_get_as_int_d ( g_conf, "display.hint_x", 40 );
-    dest -> y = pnd_conf_get_as_int_d ( g_conf, "display.hint_y", 450 );
+
+    // clear bg
+    if ( ! ( render_jobs_b & R_BG ) ) {
+      src.x = hintx;
+      src.y = hinty;
+      src.w = lastwidth;
+      src.h = rtext -> h;
+      dest -> x = hintx;
+      dest -> y = hinty;
+      SDL_BlitSurface ( g_imagecache [ IMG_BACKGROUND_TABMASK ].i, &src, sdl_realscreen, dest );
+      dest++;
+      lastwidth = rtext -> w;
+    }
+
+    // now render text
+    dest -> x = hintx;
+    dest -> y = hinty;
     SDL_BlitSurface ( rtext, NULL /* all */, sdl_realscreen, dest );
     SDL_FreeSurface ( rtext );
     dest++;
   }
 
-  // hints
-  if ( pnd_conf_get_as_int_d ( g_conf, "display.clock_x", -1 ) != -1 ) {
+  // clock time
+  if ( render_jobs_b & R_BG &&
+       pnd_conf_get_as_int_d ( g_conf, "display.clock_x", -1 ) != -1 )
+  {
     char buffer [ 50 ];
 
     time_t t = time ( NULL );
@@ -874,6 +950,8 @@ void ui_render ( void ) {
   }
 
   // update all the rects and send it all to sdl
+  // - at this point, we could probably just do 1 rect, of the
+  //   whole screen, and be faster :/
   SDL_UpdateRects ( sdl_realscreen, dest - rects, rects );
 
 } // ui_render
@@ -1090,9 +1168,10 @@ void ui_process_input ( unsigned char block_p ) {
          "Exit and run xfce4",
          "Exit and run pmenu",
          "Quit (<- beware)",
+         "Select a Minimenu skin",
          "About Minimenu"
        };
-       int sel = ui_modal_single_menu ( opts, 9, "Minimenu", "Enter to select; other to return." );
+       int sel = ui_modal_single_menu ( opts, 11, "Minimenu", "Enter to select; other to return." );
 
        char buffer [ 100 ];
        if ( sel == 0 ) {
@@ -1152,6 +1231,7 @@ void ui_process_input ( unsigned char block_p ) {
          // set env to xfce
          sprintf ( buffer, "echo startxfce4 > /tmp/gui.load" );
          system ( buffer );
+         emit_and_quit ( buffer );
          //sprintf ( buffer, "sudo poweroff" );
          //system ( buffer );
          exit ( 0 );
@@ -1159,12 +1239,18 @@ void ui_process_input ( unsigned char block_p ) {
          // set env to pmenu
          sprintf ( buffer, "echo pmenu > /tmp/gui.load" );
          system ( buffer );
+         emit_and_quit ( buffer );
          //sprintf ( buffer, "sudo poweroff" );
          //system ( buffer );
          exit ( 0 );
        } else if ( sel == 8 ) {
          emit_and_quit ( MM_QUIT );
        } else if ( sel == 9 ) {
+         // select skin
+         if ( ui_pick_skin() ) {
+           emit_and_quit ( MM_RESTART );
+         }
+       } else if ( sel == 10 ) {
          // about
        }
 
@@ -1222,13 +1308,13 @@ void ui_push_left ( unsigned char forcecoil ) {
   // what column we in?
   unsigned int col = ui_determine_screen_col ( ui_selected );
 
-  // are we alreadt at first item?
+  // are we already at first item?
   if ( forcecoil == 0 &&
        pnd_conf_get_as_int_d ( g_conf, "grid.wrap_horiz_samerow", 0 ) &&
        col == 0 )
   {
     unsigned int i = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1;
-    while ( i ) {
+    while ( i && ui_selected -> next ) {
       ui_push_right ( 0 );
       i--;
     }
@@ -1263,13 +1349,16 @@ void ui_push_right ( unsigned char forcecoil ) {
     // wrap same or no?
     if ( forcecoil == 0 &&
         pnd_conf_get_as_int_d ( g_conf, "grid.wrap_horiz_samerow", 0 ) &&
-        col == pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1 )
+        // and selected is far-right, or last icon in category (might not be far right)
+        ( ( col == pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1 ) ||
+          ( ui_selected -> next == NULL ) )
+       )
     {
       // same wrap
-      unsigned int i = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1;
-      while ( i ) {
+      //unsigned int i = pnd_conf_get_as_int_d ( g_conf, "grid.col_max", 5 ) - 1;
+      while ( col /*i*/ ) {
        ui_push_left ( 0 );
-       i--;
+       col--; //i--;
       }
 
     } else {
@@ -1291,7 +1380,7 @@ void ui_push_right ( unsigned char forcecoil ) {
 }
 
 void ui_push_up ( void ) {
-  unsigned char col_max = pnd_conf_get_as_int ( g_conf, MMENU_DISP_COLMAX );
+  unsigned char col_max = pnd_conf_get_as_int ( g_conf, "grid.col_max" );
 
   if ( ! ui_selected ) {
     return;
@@ -1325,7 +1414,7 @@ void ui_push_up ( void ) {
 
     // scroll down to show it
     int r = ui_determine_row ( ui_selected ) - 1;
-    if ( r - pnd_conf_get_as_int ( g_conf, MMENU_DISP_ROWMAX ) > 0 ) {
+    if ( r - pnd_conf_get_as_int ( g_conf, "grid.row_max" ) > 0 ) {
       ui_rows_scrolled_down = (unsigned int) r;
     }
 
@@ -1343,7 +1432,7 @@ void ui_push_up ( void ) {
 }
 
 void ui_push_down ( void ) {
-  unsigned char col_max = pnd_conf_get_as_int ( g_conf, MMENU_DISP_COLMAX );
+  unsigned char col_max = pnd_conf_get_as_int ( g_conf, "grid.col_max" );
 
   if ( ui_selected ) {
 
@@ -1372,6 +1461,8 @@ void ui_push_down ( void ) {
 
       ui_rows_scrolled_down = 0;
 
+      render_mask |= CHANGED_EVERYTHING;
+
     } else {
 
       while ( col_max ) {
@@ -1391,16 +1482,8 @@ void ui_push_down ( void ) {
 void ui_push_exec ( void ) {
 
   if ( ui_selected ) {
+    pnd_apps_exec_disco ( pnd_run_script, ui_selected -> ref, PND_EXEC_OPTION_NORUN, NULL );
     char buffer [ PATH_MAX ];
-    sprintf ( buffer, "%s/%s", ui_selected -> ref -> object_path, ui_selected -> ref -> object_filename );
-    pnd_apps_exec ( pnd_run_script,
-                   buffer,
-                   ui_selected -> ref -> unique_id,
-                   ui_selected -> ref -> exec,
-                   ui_selected -> ref -> startdir,
-                   ui_selected -> ref -> execargs,
-                   ui_selected -> ref -> clockspeed ? atoi ( ui_selected -> ref -> clockspeed ) : 0,
-                   PND_EXEC_OPTION_NORUN );
     sprintf ( buffer, "%s %s\n", MM_RUN, pnd_apps_exec_runline() );
     emit_and_quit ( buffer );
   }
@@ -2104,8 +2187,8 @@ unsigned char ui_threaded_defered_icon ( void *p ) {
   pnd_box_handle h = g_active_apps;
 
   unsigned char maxwidth, maxheight;
-  maxwidth = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_ICON_MAX_WIDTH, 50 );
-  maxheight = pnd_conf_get_as_int_d ( g_conf, MMENU_DISP_ICON_MAX_HEIGHT, 50 );
+  maxwidth = pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_width", 50 );
+  maxheight = pnd_conf_get_as_int_d ( g_conf, "grid.icon_max_height", 50 );
 
   pnd_disco_t *iter = pnd_box_get_head ( h );
 
@@ -2153,3 +2236,65 @@ void ui_show_hourglass ( unsigned char updaterect ) {
 
   return;
 }
+
+unsigned char ui_pick_skin ( void ) {
+#define MAXSKINS 10
+  char *skins [ MAXSKINS ];
+  unsigned char iter;
+
+  char *searchpath = pnd_conf_get_as_char ( g_conf, "minimenu.skin_searchpath" );
+  char tempname [ 100 ];
+
+  iter = 0;
+
+  skins [ iter++ ] = "No skin change";
+
+  SEARCHPATH_PRE
+  {
+    DIR *d = opendir ( buffer );
+
+    if ( d ) {
+      struct dirent *dd;
+
+      while ( ( dd = readdir ( d ) ) ) {
+
+       if ( dd -> d_name [ 0 ] == '.' ) {
+         // ignore
+       } else if ( ( dd -> d_type == DT_DIR || dd -> d_type == DT_UNKNOWN ) &&
+                   iter < MAXSKINS )
+       {
+         snprintf ( tempname, 100, "Skin: %s", dd -> d_name );
+         skins [ iter++ ] = strdup ( tempname );
+       }
+
+      }
+
+      closedir ( d );
+    }
+
+  }
+  SEARCHPATH_POST
+
+  int sel = ui_modal_single_menu ( skins, iter, "Skins", "Enter to select; other to return." );
+
+  // did they pick one?
+  if ( sel > 0 ) {
+    FILE *f;
+
+    char *s = strdup ( pnd_conf_get_as_char ( g_conf, "minimenu.skin_selected" ) );
+    s = pnd_expand_tilde ( s );
+
+    f = fopen ( s, "w" );
+
+    free ( s );
+
+    if ( f ) {
+      fprintf ( f, "%s\n", skins [ sel ] + 6 );
+      fclose ( f );
+    }
+
+    return ( 1 );
+  }
+
+  return ( 0 );
+}