Index: launcher-dialog.c =================================================================== --- launcher-dialog.c (Revision 27883) +++ launcher-dialog.c (Arbeitskopie) @@ -80,6 +80,17 @@ #ifdef HAVE_LIBSTARTUP_NOTIFICATION GtkWidget *entry_startup; #endif + + /* extension by FN to get the normal sort order back as in 4.4 */ + GtkWidget *entry_invert; + + /* FN: separator item extension */ + GtkWidget *radio_type_image; + GtkWidget *radio_type_separator; + + /* extension by FN to easily add the icons by typing in their icon + * name */ + GtkWidget *entry_iconName; }; @@ -111,7 +122,8 @@ LauncherDialog *ld); static void launcher_dialog_save_button (GtkWidget *button, LauncherDialog *ld); -static void launcher_dialog_update_entries (LauncherDialog *ld); +static void launcher_dialog_update_entries (LauncherDialog *ld, + gboolean toggle_type_buttons); static void launcher_dialog_update_icon (LauncherDialog *ld); static void launcher_dialog_folder_chooser (LauncherDialog *ld); static void launcher_dialog_command_chooser (LauncherDialog *ld); @@ -188,7 +200,8 @@ value = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); if (G_LIKELY (value != NULL)) { - g_free (entry->icon); + if (strlen(entry->icon)>0) + g_free (entry->icon); /* get rid of extensions in non-absolute names */ if (G_UNLIKELY (g_path_is_absolute (value) == FALSE) && @@ -292,6 +305,16 @@ break; } + if (position==0) + { + // swap ancient first and new item so that ancient first will be after separator + } + else if (position==1) + { + // move to position 2 + position++; + } + /* we need to update the button icon afterwards */ if (i == 0) update_icon = TRUE; @@ -398,7 +421,7 @@ if (G_LIKELY (launcher_dialog_read_desktop_file (file, ld->entry) == TRUE)) { /* update the widgets */ - launcher_dialog_update_entries (ld); + launcher_dialog_update_entries (ld, TRUE); /* update the tree */ launcher_dialog_tree_update_row (ld, COLUMN_NAME); @@ -446,9 +469,15 @@ if (G_UNLIKELY (text == NULL || *text == '\0')) text = NULL; - /* save new value */ - if (entry == ld->entry_name) + /* save new value if not a separator entry. + * for a separator entry, we prefer keeping this value to gain it back */ + /* FN: might want to change that to gtk_toggl_button_get_active(ld->separator_button) */ + if (ld->entry->type==SEPARATOR_ENTRY) { + // do nothing then + } + else if (entry == ld->entry_name) + { g_free (ld->entry->name); ld->entry->name = g_strdup (text); @@ -470,6 +499,7 @@ g_free (ld->entry->path); ld->entry->path = text ? xfce_expand_variables (text, NULL) : NULL; } + /* FN: do not handel entry_iconname as this one is handled separately */ /* update panel */ launcher_plugin_rebuild (ld->launcher, FALSE); @@ -501,44 +531,158 @@ #ifdef HAVE_LIBSTARTUP_NOTIFICATION else if (button == ld->entry_startup) ld->entry->startup = active; + else if (button == ld->entry_invert) + ld->launcher->invert = active; + else + g_assert(FALSE); #endif } +/* FN: Separator menu item extension */ +static void +launcher_dialog_type_button_toggled (GtkWidget *w, + LauncherDialog *ld) +{ + g_assert (ld->entry != NULL); + /* if (strcmp(gtk_button_get_label(GTK_BUTTON(w)), _("_Separator item"))==0) */ + + if ( ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) + return; + + if (w == ld->radio_type_separator && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) + { + /* g_printf(" Separator\n"); */ + ld->entry->type = SEPARATOR_ENTRY; + /* if (ld->entry->icon==NULL) ld->entry->icon = ""; ??? */ + } + else + { + /* g_printf(" Image\n"); */ + ld->entry->type = IMAGE_ENTRY; + } + /* update the tree */ + launcher_dialog_tree_update_row (ld, COLUMN_NAME); + launcher_dialog_tree_update_row (ld, COLUMN_ICON); + + launcher_dialog_update_entries (ld, FALSE); +} + +/* FN: want to use function overrinding actually with the second argument set to TRUE by default. */ static void -launcher_dialog_update_entries (LauncherDialog *ld) +launcher_dialog_update_entries (LauncherDialog *ld, gboolean toggle_type_buttons) { /* quit if locked or no active entry set */ - if (G_UNLIKELY (ld->updating == TRUE || ld->entry == NULL)) + if (G_UNLIKELY (ld->updating == TRUE)) return; + /* FN: Separator item extension */ + else if (ld->entry == NULL || ld->entry->type == SEPARATOR_ENTRY) + { + ld->updating = TRUE; - /* lock the save functions */ - ld->updating = TRUE; + /* clear fields */ + gtk_entry_set_text (GTK_ENTRY (ld->entry_name), ""); + gtk_entry_set_text (GTK_ENTRY (ld->entry_comment), ""); + gtk_entry_set_text (GTK_ENTRY (ld->entry_iconName), ""); + gtk_entry_set_text (GTK_ENTRY (ld->entry_exec),""); + gtk_entry_set_text (GTK_ENTRY (ld->entry_path), ""); - /* set new entry values */ - gtk_entry_set_text (GTK_ENTRY (ld->entry_name), - (ld->entry->name != NULL) ? ld->entry->name : ""); + /* remove icon */ + //launcher_dialog_update_icon (ld); - gtk_entry_set_text (GTK_ENTRY (ld->entry_comment), - (ld->entry->comment != NULL) ? ld->entry->comment : ""); + /* make all widgets insensitive */ + gtk_widget_set_sensitive (ld->entry_name, FALSE); + gtk_widget_set_sensitive (ld->entry_comment, FALSE); + gtk_widget_set_sensitive (ld->entry_exec, FALSE); + gtk_widget_set_sensitive (ld->entry_iconName, FALSE); + gtk_widget_set_sensitive (ld->entry_path, FALSE); + gtk_widget_set_sensitive (ld->entry_terminal, FALSE); + gtk_widget_set_sensitive (ld->entry_startup, FALSE); + gtk_widget_set_sensitive (ld->entry_icon, FALSE); - gtk_entry_set_text (GTK_ENTRY (ld->entry_exec), - (ld->entry->exec != NULL) ? ld->entry->exec : ""); + if (toggle_type_buttons) + { + if (!ld->entry) + { + gtk_widget_set_sensitive (ld->radio_type_separator, FALSE); + gtk_widget_set_sensitive (ld->radio_type_image, FALSE); + } + else + { + gtk_widget_set_sensitive (ld->radio_type_separator, TRUE); + gtk_widget_set_sensitive (ld->radio_type_image, TRUE); - gtk_entry_set_text (GTK_ENTRY (ld->entry_path), - (ld->entry->path != NULL) ? ld->entry->path : ""); + /* if (ld->entry->type == SEPARATOR_ENTRY) + { */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_separator), TRUE); + /* } + else + { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_image), TRUE); + } */ + } + } - /* set toggle buttons */ - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_terminal), - ld->entry->terminal); -#ifdef HAVE_LIBSTARTUP_NOTIFICATION - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_startup), - ld->entry->startup); + /* and finally, return in order to not have ugly "else" paths */ + /* return; */ + } + else + { + gtk_widget_set_sensitive (ld->entry_name, TRUE); + gtk_widget_set_sensitive (ld->entry_comment, TRUE); + gtk_widget_set_sensitive (ld->entry_exec, TRUE); + gtk_widget_set_sensitive (ld->entry_iconName, TRUE); + gtk_widget_set_sensitive (ld->entry_path, TRUE); + gtk_widget_set_sensitive (ld->entry_terminal, TRUE); + gtk_widget_set_sensitive (ld->entry_startup, TRUE); + gtk_widget_set_sensitive (ld->radio_type_separator, TRUE); + gtk_widget_set_sensitive (ld->radio_type_image, TRUE); + gtk_widget_set_sensitive (ld->entry_icon, TRUE); - gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal); -#endif + /* lock the save functions */ + ld->updating = TRUE; + /* set new entry values */ + gtk_entry_set_text (GTK_ENTRY (ld->entry_name), + (ld->entry->name != NULL) ? ld->entry->name : ""); + + gtk_entry_set_text (GTK_ENTRY (ld->entry_comment), + (ld->entry->comment != NULL) ? ld->entry->comment : ""); + + gtk_entry_set_text (GTK_ENTRY (ld->entry_exec), + (ld->entry->exec != NULL) ? ld->entry->exec : ""); + + gtk_entry_set_text (GTK_ENTRY (ld->entry_iconName), + (ld->entry->icon != NULL) ? ld->entry->icon : ""); + + gtk_entry_set_text (GTK_ENTRY (ld->entry_path), + (ld->entry->path != NULL) ? ld->entry->path : ""); + + /* set toggle buttons */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_terminal), + ld->entry->terminal); + + #ifdef HAVE_LIBSTARTUP_NOTIFICATION + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_startup), + ld->entry->startup); + + gtk_widget_set_sensitive (ld->entry_startup, !ld->entry->terminal); + #endif + + /* extension by FN to get the normal sort order back as in 4.4 */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->entry_invert), + ld->launcher->invert); + + /* FN: Separator item extension */ + /* but do not set them again; they are set on their own and aove! */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->radio_type_image), + ld->entry->type==IMAGE_ENTRY); + /* gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ld->radio_type_separator), + ld->entry->type==SEPARATOR_ENTRY); */ + + } + /* update icon button */ launcher_dialog_update_icon (ld); @@ -558,9 +702,25 @@ if (GTK_BIN (ld->entry_icon)->child != NULL) gtk_widget_destroy (GTK_BIN (ld->entry_icon)->child); - if (G_LIKELY (ld->entry->icon)) + /* FN: make it more secure, as it might be called when ld->entry is NULL! */ + if (ld->entry && G_LIKELY (ld->entry->icon) && ld->entry->type==IMAGE_ENTRY) + { icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->entry_icon), ld->entry->icon, LAUNCHER_CHOOSER_ICON_SIZE); + /* FN: FIXME: this belongs elsewhere, but not here */ + /* gtk_widget_set_sensitive(ld->entry_icon, TRUE); */ + } + else if (ld->entry && G_LIKELY (ld->entry->icon) && ld->entry->type!=IMAGE_ENTRY) + { + // icon = NULL; + } + else if (!ld->entry) /* FN: make button unclickable */ + { + /* FN: FIXME: this belongs elsewhere, but not here */ + /* gtk_widget_set_sensitive(ld->entry_icon, FALSE); */ + /* return; */ /* bottom part handles that, how nice. */ + } + /* create icon button */ if (G_LIKELY (icon != NULL)) { @@ -772,7 +932,9 @@ /* set the current icon, if there is any */ if (G_LIKELY (ld->entry->icon)) + { exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), ld->entry->icon); + } /* run the icon chooser dialog */ if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT) @@ -784,6 +946,10 @@ /* set new icon */ ld->entry->icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser)); + /* FN: get string into our good, old, old-fashioned style, plain entry + * field */ + gtk_entry_set_text(GTK_ENTRY(ld->entry_iconName), ld->entry->icon); + /* update the icon button */ launcher_dialog_update_icon (ld); @@ -815,6 +981,7 @@ GtkTreeIter iter; GdkPixbuf *icon = NULL; const gchar *name; + char *tmpicon; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ld->treeview)); @@ -824,8 +991,15 @@ { case COLUMN_ICON: /* load entry icon */ - icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), ld->entry->icon, LAUNCHER_TREE_ICON_SIZE); + /* g_assert (ld->entry->icon!=NULL); */ /* this fails sometimes */ + /* if (ld->entry->icon==NULL) ld->entry->icon==""; ??? */ + if (ld->entry->type==IMAGE_ENTRY) + tmpicon = ld->entry->icon; + else + tmpicon = ""; + icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), tmpicon, LAUNCHER_TREE_ICON_SIZE); + /* set new icon */ gtk_list_store_set (ld->store, &iter, COLUMN_ICON, icon, @@ -839,8 +1013,11 @@ case COLUMN_NAME: /* build name */ - name = ld->entry->name ? ld->entry->name : _("Unnamed"); - + if (ld->entry->type==IMAGE_ENTRY) + name = ld->entry->name ? ld->entry->name : _("Unnamed"); + else + name = _("--- Separator ---"); /* FN: better use g_strdup()? */ + /* set new name */ gtk_list_store_set (ld->store, &iter, COLUMN_NAME, name, @@ -880,11 +1057,25 @@ /* get position */ position = gtk_tree_path_get_indices (path)[0]; - /* set new active entry */ - ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data; + /* extension by FN to add separation bar */ + if (position==1) + { + /* set no active entry */ + ld->entry = NULL; + selected = FALSE; + } + else + { + /* set new active entry */ + if (position>1) + position--; + + ld->entry = (LauncherEntry *) g_list_nth (ld->launcher->entries, position)->data; + } + /* update fields */ - launcher_dialog_update_entries (ld); + launcher_dialog_update_entries (ld, TRUE); /* scroll new item to center of window */ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ld->treeview), path, NULL, @@ -899,8 +1090,8 @@ /* change sensitivity of buttons */ gtk_widget_set_sensitive (ld->up, selected && (position > 0)); - gtk_widget_set_sensitive (ld->down, selected && (position < items - 1)); - gtk_widget_set_sensitive (ld->remove, selected && (items > 1)); + gtk_widget_set_sensitive (ld->down, selected && (position < items-2)); /* FN: items - 1, when we didn't have a separator */ + gtk_widget_set_sensitive (ld->remove, selected && (items > 2)); } @@ -937,9 +1128,19 @@ /* position of the item in the list */ position = gtk_tree_path_get_indices (path)[0]; + /* cant have position one, because we're moving upwards; + * and can't have position 1, because that would be a separator */ + g_assert(position>1); + /* check if we need to update the icon button image */ - if (position == 1) + /* FN: position == 1, when there was no separator */ + if (position == 2) + { + /* need to get even one earlier item lateron; + * thus decrease path counter already here by one */ + gtk_tree_path_prev (path); update_icon = TRUE; + } /* get previous path */ if (G_LIKELY (gtk_tree_path_prev (path))) @@ -951,7 +1152,8 @@ gtk_list_store_swap (ld->store, &iter_a, &iter_b); /* swap items in the list */ - li = g_list_nth (ld->launcher->entries, position); + /* FN: need to decrease position by 1, because tree has one more entry */ + li = g_list_nth (ld->launcher->entries, position-1); launcher_dialog_g_list_swap (li, li->prev); } @@ -970,8 +1172,14 @@ position = gtk_tree_path_get_indices (path)[0]; /* check if we need to update the icon button image*/ + /* FN: same game again; need to advance tree by one more item! */ if (position == 0) + { + gtk_tree_path_next (path); update_icon = TRUE; + } + else + position--; /* need to increase position for all other items */ /* get next item in the list */ gtk_tree_path_next (path); @@ -983,6 +1191,7 @@ gtk_list_store_swap (ld->store, &iter_a, &iter_b); /* swap items in the list */ + /* FN: same game again, need a lower position. but that's done above when position!=0 */ li = g_list_nth (ld->launcher->entries, position); launcher_dialog_g_list_swap (li, li->next); } @@ -1001,7 +1210,15 @@ /* load new launcher icon */ icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE); - /* append new entry */ + /* FN: check that we insert _after_ the separator */ + path = gtk_tree_model_get_path (model, &iter_a); + + if (gtk_tree_path_get_indices (path)[0] == 0) + gtk_tree_model_iter_next (model, &iter_a); + + /* g_assert (gtk_tree_path_get_indices (path)[0] > 0); */ + + /* append new entry - now after the separator */ gtk_list_store_insert_after (ld->store, &iter_b, &iter_a); gtk_list_store_set (ld->store, &iter_b, COLUMN_ICON, icon, @@ -1019,8 +1236,10 @@ position = gtk_tree_path_get_indices (path)[0]; /* insert in list */ + /* FN: need to decrease position by one to handle shorter launcher + * list */ ld->launcher->entries = g_list_insert (ld->launcher->entries, - entry, position); + entry, position-1); /* select the new item (also updates treeview buttons) */ gtk_tree_view_set_cursor (GTK_TREE_VIEW (ld->treeview), path, NULL, FALSE); @@ -1040,6 +1259,9 @@ /* get position of the item to remove */ position = gtk_tree_path_get_indices (path)[0]; + /* FN: check for valid position */ + g_assert (position!=1); + /* check if we need to update the icon button image*/ if (position == 0) update_icon = TRUE; @@ -1054,6 +1276,18 @@ /* remove row from store */ gtk_list_store_remove (ld->store, &iter_a); + /* FN: need to take care that wehen removing the first item, the + * separator and second item be swapped! */ + if (position == 0) + { + /* swap separator now at pos 0 and next item at pos 1 */ + gtk_tree_model_get_iter_first(model, &iter_a); + path = gtk_tree_model_get_path (model, &iter_a); + gtk_tree_path_next (path); + gtk_tree_model_get_iter (model, &iter_b, path); + gtk_list_store_swap (ld->store, &iter_a, &iter_b); + } + /* unlock */ ld->updating = FALSE; @@ -1061,7 +1295,9 @@ list_length = g_list_length (ld->launcher->entries); /* select previous item, if last item was removed */ - if (position >= (guint) list_length) + /* FN: need to increase list_length because its one shorter due to + * separator */ + if (position >= (guint) list_length+1) gtk_tree_path_prev (path); /* select the new item (also updates treeview buttons) */ @@ -1083,7 +1319,6 @@ } - static void launcher_dialog_arrow_position_changed (GtkComboBox *combo, LauncherDialog *ld) @@ -1094,7 +1329,56 @@ } +/* FN: Function to save toggled value. */ +static void +launcher_dialog_entry_invert_toggled (GtkToggleButton *tb, + LauncherDialog *ld) +{ + ld->launcher->invert = gtk_toggle_button_get_active(tb); +} + +/* FN: New function handle when a new icon name has been entered manually + */ +static void +launcher_dialog_update_icon_from_entry (GtkWidget *entry, + LauncherDialog *ld) +{ + gchar *tmp; + gboolean update_icon = FALSE; + + TRACE ("launcher_dialog_update_icon_from_entry entered."); + + g_assert (entry); + + if (!ld->entry) + { + return; + } + + if (ld->entry->type==IMAGE_ENTRY) + { + tmp = (gchar *) gtk_entry_get_text(GTK_ENTRY(entry)); + ld->entry->icon = g_strdup(tmp); /* const gchar* returned from gtk_entry_get_text that cannto be freed safely!!! */ + } + + launcher_dialog_update_icon(ld); + + /* The following is just the same code as above in + * launcher_dialog_icon_chooser. Might want to extract it + * into a separate function. */ + /* update the icon column in the tree */ + launcher_dialog_tree_update_row (ld, COLUMN_ICON); + + /* check if we need to update the icon button image */ + if (g_list_index (ld->launcher->entries, ld->entry) == 0) + update_icon = TRUE; + + /* update the panel widgets */ + launcher_plugin_rebuild (ld->launcher, update_icon); +} + + /** * Launcher dialog widgets **/ @@ -1113,6 +1397,23 @@ sg = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + /* FN: type chooser radio buttons */ + hbox = gtk_hbox_new (FALSE, BORDER); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + ld->radio_type_image = gtk_radio_button_new_with_mnemonic(NULL, _("_Image menu item")); + gtk_box_pack_start (GTK_BOX (hbox), ld->radio_type_image, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->radio_type_image), TRUE); + + g_signal_connect (G_OBJECT (ld->radio_type_image), "toggled", + G_CALLBACK (launcher_dialog_type_button_toggled), ld); + + ld->radio_type_separator = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(ld->radio_type_image), _("_Separator item")); + gtk_box_pack_start (GTK_BOX (hbox), ld->radio_type_separator, FALSE, FALSE, 0); + + g_signal_connect (G_OBJECT (ld->radio_type_separator), "toggled", + G_CALLBACK (launcher_dialog_type_button_toggled), ld); + /* entry name field */ hbox = gtk_hbox_new (FALSE, BORDER); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); @@ -1160,6 +1461,12 @@ gtk_size_group_add_widget (sg, label); + /* FN: old handling of icon names */ + ld->entry_iconName = gtk_entry_new(); + gtk_box_pack_start (GTK_BOX (hbox), ld->entry_iconName , FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (ld->entry_iconName), "changed", + G_CALLBACK (launcher_dialog_update_icon_from_entry), ld); + ld->entry_icon = gtk_button_new (); gtk_box_pack_start (GTK_BOX (hbox), ld->entry_icon, FALSE, FALSE, 0); @@ -1281,8 +1588,9 @@ GtkTreeIter iter; GList *li; LauncherEntry *entry; - GdkPixbuf *icon; + GdkPixbuf *icon = NULL; const gchar *name; + gint count; /* scrolled window */ scroll = gtk_scrolled_window_new (NULL, NULL); @@ -1328,18 +1636,28 @@ G_CALLBACK (launcher_dialog_tree_selection_changed), ld); /* append current items */ - for (li = ld->launcher->entries; li != NULL; li = li->next) + count = 0; + for (li = ld->launcher->entries; li != NULL; li = li->next, count++) { entry = li->data; if (G_LIKELY (entry)) { - /* load icon */ - icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE); - - /* build name */ - name = entry->name ? entry->name : _("Unnamed"); + if (entry->type==IMAGE_ENTRY) + { + /* build name */ + name = entry->name ? entry->name : _("Unnamed"); + + /* load icon */ + icon = launcher_utility_load_pixbuf (gtk_widget_get_screen (ld->treeview), entry->icon, LAUNCHER_TREE_ICON_SIZE); + } + else /* SEPARATOR_ENTRY */ + { + /* build name */ + name = _("--- Separator ---"); /* FN: better use g_strdup()? */ + } + /* create new row and add the data */ gtk_list_store_append (ld->store, &iter); gtk_list_store_set (ld->store, &iter, @@ -1350,6 +1668,15 @@ if (G_LIKELY (icon)) g_object_unref (G_OBJECT (icon)); } + + /* FN: extension to insert separator */ + if (count==0) + { + gtk_list_store_append (ld->store, &iter); + name = g_strdup(_("--- Menu content below ---")); + gtk_list_store_set (ld->store, &iter, + COLUMN_NAME, name, -1); + } } /* dnd support */ @@ -1542,9 +1869,9 @@ gtk_container_set_border_width (GTK_CONTAINER (paned), BORDER - 2); vbox = gtk_vbox_new (FALSE, BORDER); - gtk_paned_pack1 (GTK_PANED (paned), vbox, FALSE, FALSE); + gtk_paned_pack1 (GTK_PANED (paned), vbox, TRUE, TRUE); /* FALSE, FALSE */ - /* arrow button position */ + /* arrow button position in combo box */ hbox = gtk_hbox_new (FALSE, BORDER); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); @@ -1565,9 +1892,15 @@ g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (launcher_dialog_arrow_position_changed), ld); gtk_widget_show (combo); + /* FN: checkbox for selecting Nick's inverted sort order */ + ld->entry_invert = gtk_check_button_new_with_mnemonic(_("_Invert menu sort order")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ld->entry_invert), ld->launcher->invert); + g_signal_connect (G_OBJECT (ld->entry_invert), "toggled", G_CALLBACK (launcher_dialog_entry_invert_toggled), ld); + gtk_box_pack_start (GTK_BOX (vbox), ld->entry_invert, FALSE, FALSE, 0); + /* add the entries list */ widget = launcher_dialog_add_tree (ld); - gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0); /* TRUE, FALSE */ /* add the tree navigation buttons */ widget = launcher_dialog_add_tree_buttons (ld); @@ -1575,7 +1908,7 @@ /* add the entry widgets */ widget = launcher_dialog_add_properties (ld); - gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, FALSE); + gtk_paned_pack2 (GTK_PANED (paned), widget, TRUE, TRUE); /* show all widgets inside dialog */ gtk_widget_show_all (dialog_vbox); Index: launcher.c =================================================================== --- launcher.c (Revision 27883) +++ launcher.c (Arbeitskopie) @@ -569,6 +569,9 @@ /* get the item number */ i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (mi), I_("entry-number"))); + if (!launcher->invert) + i = g_list_length(launcher->entries) - i - 1; + /* get the entry from the list */ entry = g_list_nth_data (launcher->entries, i); @@ -631,7 +634,7 @@ /* popup menu */ gtk_menu_popup (GTK_MENU (launcher->menu), NULL, NULL, xfce_panel_plugin_position_menu, - launcher->panel_plugin, + launcher->panel_plugin, 1, gtk_get_current_event_time ()); GDK_THREADS_LEAVE (); @@ -675,8 +678,17 @@ } } +/* +static void +launcher_menu_tearoff_pressed (GtkWidget *w, + LauncherPlugin *launcher) +{ + gtk_menu_set_tearoff_state (GTK_MENU(launcher->menu), TRUE); + gtk_window_set_default_size(GTK_WINDOW(launcher->menu)) ; +} */ + static void launcher_menu_rebuild (LauncherPlugin *launcher) { @@ -701,57 +713,110 @@ gtk_menu_set_screen (GTK_MENU (launcher->menu), screen); /* walk through the entries */ - for (li = launcher->entries; li != NULL; li = li->next, n++) + + if (launcher->invert) + li = launcher->entries; + else + li = g_list_last(launcher->entries); + + while (li) { - /* skip the first entry when the arrow is visible */ - if (n == 0 && launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON) - continue; + /*for (li = launcher->entries; li != NULL; li = li->next, n++) + { */ + /* skip the first entry when the arrow is visible */ + /* FN: Note that this vast amount of checks should be superfluous as + * arrow_position is LAUNCHER_ARROW_INSIDE_BUTTON iff there is only + * one item. */ + if (launcher->arrow_position != LAUNCHER_ARROW_INSIDE_BUTTON) + { + if ((n == 0 && launcher->invert) || (n == (g_list_length(launcher->entries)-1) && !launcher->invert)) + { + if (launcher->invert) + li = g_list_next(li); + else + li = g_list_previous(li); - entry = li->data; + n++; + continue; + } + } - /* create menu item */ - mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item")); - gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi); - gtk_widget_show (mi); + entry = li->data; - /* try to set an image */ - if (G_LIKELY (entry->icon)) - { - /* load pixbuf */ - pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, LAUNCHER_MENU_SIZE); + if (entry->type==SEPARATOR_ENTRY) + { + mi = gtk_separator_menu_item_new(); + gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi); + gtk_widget_show (mi); + /*n++; + continue; */ + } - if (G_LIKELY (pixbuf)) + else if (entry->type==IMAGE_ENTRY) { - /* set image */ - image = gtk_image_new_from_pixbuf (pixbuf); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); - gtk_widget_show (image); + /* create menu item */ + mi = gtk_image_menu_item_new_with_label (entry->name ? entry->name : _("New Item")); + gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi); + gtk_widget_show (mi); - /* release reference */ - g_object_unref (G_OBJECT (pixbuf)); + /* try to set an image */ + if (G_LIKELY (entry->icon)) + { + /* load pixbuf */ + pixbuf = launcher_utility_load_pixbuf (screen, entry->icon, LAUNCHER_MENU_SIZE); + + if (G_LIKELY (pixbuf)) + { + /* set image */ + image = gtk_image_new_from_pixbuf (pixbuf); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); + gtk_widget_show (image); + + /* release reference */ + g_object_unref (G_OBJECT (pixbuf)); + } + } } - } - /* set entries list number */ - g_object_set_data (G_OBJECT (mi), I_("entry-number"), GINT_TO_POINTER (n)); - /* connect signals */ - g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK (launcher_menu_item_released), launcher); -#if LAUNCHER_NEW_TOOLTIP_API - g_object_set (G_OBJECT (mi), "has-tooltip", TRUE, NULL); - g_signal_connect (G_OBJECT (mi), "query-tooltip", G_CALLBACK (launcher_utility_query_tooltip), entry); -#endif + /* set entries list number */ + g_object_set_data (G_OBJECT (mi), I_("entry-number"), GINT_TO_POINTER (n)); - /* dnd support */ - gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY); + /* connect signals */ + g_signal_connect (G_OBJECT (mi), "button-release-event", G_CALLBACK (launcher_menu_item_released), launcher); + #if LAUNCHER_NEW_TOOLTIP_API + if (entry->type==IMAGE_ENTRY) + { + g_object_set (G_OBJECT (mi), "has-tooltip", TRUE, NULL); + g_signal_connect (G_OBJECT (mi), "query-tooltip", G_CALLBACK (launcher_utility_query_tooltip), entry); + } + #endif -#if !LAUNCHER_NEW_TOOLTIP_API - /* set tooltip */ - if (entry->comment) - gtk_tooltips_set_tip (launcher->tips, mi, entry->comment, NULL); -#endif - } + /* dnd support */ + gtk_drag_dest_set (mi, GTK_DEST_DEFAULT_ALL, drop_targets, G_N_ELEMENTS (drop_targets), GDK_ACTION_COPY); + #if !LAUNCHER_NEW_TOOLTIP_API + /* set tooltip */ + /* FN: extend to not show anything for separators */ + if (entry->comment && entry->type==IMAGE_ENTRY) + gtk_tooltips_set_tip (launcher->tips, mi, entry->comment, NULL); + #endif + /*} */ /* end for all items */ + + if (launcher->invert) + li = g_list_next(li); + else + li = g_list_previous(li); + + n++; + } /* end while */ + + + mi = gtk_tearoff_menu_item_new(); + gtk_menu_shell_prepend (GTK_MENU_SHELL (launcher->menu), mi); + gtk_widget_show (mi); + + /* connect deactivate signal */ g_signal_connect_swapped (G_OBJECT (launcher->menu), "deactivate", G_CALLBACK (launcher_menu_deactivated), launcher); } @@ -1035,6 +1100,9 @@ launcher->move_first = xfce_rc_read_bool_entry (rc, "MoveFirst", FALSE); launcher->arrow_position = xfce_rc_read_int_entry (rc, "ArrowPosition", 0); + /* FN: Read our preferred sort order */ + launcher->invert = xfce_rc_read_bool_entry (rc, "InvertSortOrder", FALSE); + for (i = 0; i < 100 /* arbitrary */; ++i) { /* create group name */ @@ -1056,6 +1124,7 @@ entry->icon = launcher_plugin_read_entry (rc, "Icon"); entry->exec = launcher_plugin_read_entry (rc, "Exec"); entry->path = launcher_plugin_read_entry (rc, "Path"); + entry->type = (entry_type) xfce_rc_read_int_entry (rc, "Type", 0); entry->terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE); #ifdef HAVE_LIBSTARTUP_NOTIFICATION @@ -1120,6 +1189,9 @@ xfce_rc_write_bool_entry (rc, "MoveFirst", launcher->move_first); xfce_rc_write_int_entry (rc, "ArrowPosition", launcher->arrow_position); + /* FN: Need to take care of saving our desired sort order */ + xfce_rc_write_bool_entry (rc, "InvertSortOrder", launcher->invert); + /* save all the entries */ for (li = launcher->entries, i = 0; li != NULL; li = li->next, i++) { @@ -1142,6 +1214,9 @@ xfce_rc_write_entry (rc, "Exec", entry->exec); if (G_LIKELY (entry->path)) xfce_rc_write_entry (rc, "Path", entry->path); + /* FN: separator extension */ + xfce_rc_write_int_entry (rc, "Type", entry->type); + xfce_rc_write_bool_entry (rc, "Terminal", entry->terminal); #ifdef HAVE_LIBSTARTUP_NOTIFICATION xfce_rc_write_bool_entry (rc, "StartupNotify", entry->startup); Index: launcher-exec.c =================================================================== --- launcher-exec.c (Revision 27883) +++ launcher-exec.c (Arbeitskopie) @@ -560,6 +560,10 @@ /* maybe no command have been filed yet */ if (G_UNLIKELY (entry->exec == NULL || *entry->exec == '\0')) return; + + /* separator items cannot be executed! */ + if (entry->type == SEPARATOR_ENTRY) + return; /* check if the launcher supports (and needs) multiple instances */ if (file_list != NULL && Index: launcher.h =================================================================== --- launcher.h (Revision 27883) +++ launcher.h (Arbeitskopie) @@ -30,7 +30,7 @@ #define LAUNCHER_ARROW_SIZE (16) #define LAUNCHER_POPUP_DELAY (225) #define LAUNCHER_TOOLTIP_SIZE (32) -#define LAUNCHER_MENU_SIZE (24) +#define LAUNCHER_MENU_SIZE (24) #define LAUNCHER_STARTUP_TIMEOUT (30 * 1000) #define LAUNCHER_TREE_ICON_SIZE (24) #define LAUNCHER_CHOOSER_ICON_SIZE (48) @@ -46,6 +46,12 @@ typedef struct _LauncherEntry LauncherEntry; typedef struct _LauncherPlugin LauncherPlugin; +typedef enum entry_type_e +{ + IMAGE_ENTRY = 0, + SEPARATOR_ENTRY +} entry_type; + struct _LauncherEntry { gchar *name; @@ -54,6 +60,8 @@ gchar *path; gchar *icon; + entry_type type; + guint terminal : 1; #ifdef HAVE_LIBSTARTUP_NOTIFICATION guint startup : 1; @@ -89,6 +97,9 @@ /* settings */ guint move_first : 1; guint arrow_position; + /* inverts the sort order as in Xfce 4.4 and as discussed extensively + * by JH and FN somewhere between 2005 and 2006 */ + gboolean invert; }; enum