/* * $RCSfile: gkrellmlaunch.c,v $ * Revision: $Revision: 1.12 $ * Date: $Date: 2002/09/26 13:53:08 $ * * Copyright (C) 2001 Lee Webb * * Author: Lee Webb leewebb@users.sourceforge.net * Latest versions: http://gkrellmlaunch.sourceforge.net * * Contributions: * Bill Wilson http://bill.nalens.com/ GTK2 port * Etan Reisner GTK2 port * * This program is free software which I release under the GNU General Public * License. You may redistribute and/or modify this program under the terms * of that license as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Requires GKrellM 2 or better * * gcc -fPIC `pkg-config gtk+-2.0 --cflags` `pkg-config gtk+-2.0 --libs` -c gkrellmlaunch.c * gcc -shared -Wl -o gkrellmlaunch.so gkrellmlaunch.o * gkrellm -p gkrellmlaunch.so */ #include /* * Make sure we have a compatible version of GKrellM * (Version 2+ is required due to the use of GTK2) */ #if !defined(GKRELLM_VERSION_MAJOR) || GKRELLM_VERSION_MAJOR < 2 #error This plugin requires GKrellM version >= 2 #endif #define CONFIG_NAME "GKrellMLaunch" #define PLUGIN_PLACEMENT (MON_UPTIME | MON_INSERT_AFTER) #define PLUGIN_CONFIG_KEYWORD "gkrellmlaunch" #define STYLE_NAME "GKrellMLaunch" static gchar *GKrellMLaunchInfo[] = { "Usage\n\n", "Label: ", "This is the text that will appear on the button for the command.\n\n", "Command: ", "This is the binary name to run (e.g., mozilla).\n", "Visible: ", "Check box to allow buttons to be hidden if not used.\n\n", "Use the \"Add\" button to create a new button.\n", "Use the \"Replace\" button to update changes made for currently selected ", "list entry.\n", "Use the \"Delete\" button to delete the selected entry.\n", "Use the /\\ & \\/ buttons to move selected entry up & down in position.\n", }; static gchar GKrellMLaunchAbout[] = "GKrellMLaunch Version 0.5 (GKrellm2)\n"\ "GKrellM plugin to give one-click access to frequently used programs.\n\n"\ "Copyright (c) 2001-2002 by Lee Webb\n"\ "Release Date: 26/09/2002\n"\ "leewebb@users.sourceforge.net\n"\ "http://gkrellmlaunch.sourceforge.net\n\n"\ "Released under the GNU Public License.\n"; static GkrellmMonitor *monitor; typedef struct { gint visible; gchar *cmd; gchar *label; /* Each launcher has its own Panel & Decal */ GkrellmPanel *panel; GkrellmDecal *decal; } GLauncher; /* * We need a list to hold our series of GLaunchers. */ static GList *launcherList; /* * Unlike the array version of GKrellMLaunch, where buttons were always * kept in memory, regardless if they were used or not (due to the * limitations of fixed size arrays), the new list implementation zaps the * entire list & recreates it when apply_plugin_config is reached. Although * not necessarily a major problem, the graphical effect of GKrellM * deleting and (re)adding the Panels/Decals is not pretty. So we're going * to use a varible to keep track of modifications to the list & only zap * the list should something change. */ static gboolean listModified; static gint style_id; /* * Create Config tab widgets. */ static GtkWidget *cmdEntry; static GtkWidget *cmdEntryLabel; static GtkWidget *toggleButton; static GtkWidget *launcherVbox; /* * Listbox widget for the config tab. */ static GtkWidget *launcherCList; /* * Keep track of selected item in the Config listbox. */ static gint selectedRow; /* * Handle decal button presses */ static void buttonPress (GkrellmDecalbutton *button) { gchar *cmdRun = ""; gint i; gint selected; GLauncher *launcher; GList *list; /* * Perform the appropriate action acccording to the button pressed. * Note: we append the '&' for the user to ensure background execution. * * Bill has informed me that using system() can be iffy: * "Whenever a program execs a child, the child inherits all open * file descriptors and this could cause a problem because of plugins like * Volume which have the audio device open. So, for example, a user can * launch a program, then later after quitting gkrellm, can try to unload * a sound module. But this will fail if the child program launched from * gkrellm is still running because it has the audio device opened." * * Thus, use gkrellm_system() (a wrapper around system() that closes all * open files before doing the system()). * Unfortunately, such safety comes at a price: this call requires GKrellM * version 1.2.2. */ selected = (GPOINTER_TO_INT (button->data)); /* * Allocate space for cmd. * Note: We're adding 2 (not 1) to the length. * One for the '&' and one for the null. * No point having a variable just to hold a '&'. */ /* * Move to selected button in the list */ for (i = 0, list = launcherList; i < selected; i += 1, list = list->next); launcher = (GLauncher *) list->data; /* * g_spawn_command_line_async() replaces gkrellm_system as a built in GTK2 * call. Runs the specified command in the background so no need to append * '&' ourselves. */ cmdRun = g_strdup (launcher->cmd); g_spawn_command_line_async (cmdRun, NULL); /* * Cleanup as g_strdup doesn't automatically free() */ g_free (cmdRun); } static gint panel_expose_event (GtkWidget *widget, GdkEventExpose *ev) { GLauncher *launcher; GList *list; /* * O.K. This isn't particularly efficient, but in the interests of * maintainability, I'm going to keep this in. */ for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; if (widget == launcher->panel->drawing_area) { gdk_draw_pixmap (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], launcher->panel->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); } } return FALSE; } /* * Func called by create_plugin() & apply_config() to show/hide panels * at startup according to related config item. */ static void setVisibility () { GLauncher *launcher; GList *list; for (list = launcherList ; list ; list = list->next) { launcher = (GLauncher *) list->data; if (launcher->visible == 0) { gkrellm_panel_hide (launcher->panel); } else { gkrellm_panel_show (launcher->panel); } } } static void update_plugin () { GLauncher *launcher; GList *list; for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; gkrellm_draw_panel_layers (launcher->panel); } } /* * Configuration */ static void save_plugin_config (FILE *f) { GLauncher *launcher; GList *list; gchar *ptr; for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; /* * Since labels may have spaces, we need to convert those to * underscores: else sscanf won't work properly on load. */ for (ptr = launcher->label; *ptr; ptr++) { if (*ptr == ' ') { *ptr = '_'; } } fprintf (f, "%s visible=%d label=%s cmd=%s\n", PLUGIN_CONFIG_KEYWORD, launcher->visible, launcher->label, launcher->cmd); } } static void apply_plugin_config () { gchar *string; gint i; gint row; GLauncher *launcher; GList *list; GList *newList; GkrellmStyle *style; GkrellmTextstyle *ts; GkrellmTextstyle *ts_alt; if (listModified) { /* * Create a new list with the applied settings * Trash the old list. */ newList = NULL; /* * Read each row of the listbox & create a new launcher. * Append each launcher to the new list. */ for (row = 0; row < (GTK_CLIST (launcherCList)->rows); row += 1) { launcher = g_new0 (GLauncher, 1); newList = g_list_append (newList, launcher); gtk_clist_set_row_data (GTK_CLIST (launcherCList), row, launcher); /* * Fill the visible option. */ gtk_clist_get_text (GTK_CLIST (launcherCList), row, 0, &string); launcher->visible = (strcmp (string, "No") ? 1 : 0); /* * Fill the label option. */ gtk_clist_get_text (GTK_CLIST (launcherCList), row, 1, &string); gkrellm_dup_string (&launcher->label, string); /* * Fill the command option. */ gtk_clist_get_text (GTK_CLIST (launcherCList), row, 2, &string); gkrellm_dup_string (&launcher->cmd, string); } /* * Wipe out the old list. */ while (launcherList) { launcher = (GLauncher *) launcherList->data; gkrellm_panel_destroy (launcher->panel); launcherList = g_list_remove (launcherList, launcher); } /* * And then update to the new list. */ launcherList = newList; /* * Since we've destroyed the old list & the panels/decals with it, * we have to recreate those associated panels/decals. */ /* * First make sure we have the styles set up. */ style = gkrellm_meter_style (style_id); ts = gkrellm_meter_textstyle (style_id); ts_alt = gkrellm_meter_alt_textstyle (style_id); for (i = 0, list = launcherList; list; i += 1, list = list->next) { launcher = (GLauncher *) list->data; launcher->panel = gkrellm_panel_new0(); launcher->decal = gkrellm_create_decal_text (launcher->panel, launcher->label, ts_alt, style, -1, -1, -1); /* * Configure the panel to the created decal, and create it. */ gkrellm_panel_configure (launcher->panel, NULL, style); gkrellm_panel_create (launcherVbox, monitor, launcher->panel); /* * Panel's been created so convert the decal into a button. */ gkrellm_draw_decal_text (launcher->panel, launcher->decal, launcher->label, 1); gkrellm_put_decal_in_meter_button (launcher->panel, launcher->decal, buttonPress, GINT_TO_POINTER (i), NULL); /* * Connect our panel to the expose event to allow it to be drawn in * update_plugin(). */ gtk_signal_connect (GTK_OBJECT (launcher->panel->drawing_area), "expose_event", (GtkSignalFunc) panel_expose_event, NULL); } setVisibility (); /* * Reset the modification state. */ listModified = FALSE; } } static void load_plugin_config (gchar *arg) { gchar cmd[255]; gchar label[25]; gchar visible[2]; gchar *ptr; gint n; GLauncher *launcher; GList *list; n = sscanf (arg, "visible=%s label=%s cmd=%[^\n]", visible, label, cmd); if (n == 3) { launcher = g_new0 (GLauncher, 1); launcher->cmd = g_strdup (cmd); /* * Spaces in labels will have been converted to underscores in * save_plugin_config(). Convert them back to spaces. */ for (ptr = label; *ptr; ptr++) { if (*ptr == '_') { *ptr = ' '; } } launcher->label = g_strdup (label); launcher->visible = atoi (visible); launcherList = g_list_append (launcherList, launcher); } for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; } } static void cbMoveUp (GtkWidget *widget, gpointer drawer) { gint row; GtkWidget *clist; clist = launcherCList; row = selectedRow; /* * Only attempt a move if we're not on the first row. */ if (row > 0) { /* * Move the selected row up one position. * Note that we have to reselect it afterwards. */ gtk_clist_row_move (GTK_CLIST (clist), row, row - 1); gtk_clist_select_row (GTK_CLIST (clist), row - 1, -1); selectedRow = row - 1; listModified = TRUE; } } static void cbMoveDown (GtkWidget *widget, gpointer drawer) { gint row; GtkWidget *clist; clist = launcherCList; row = selectedRow; /* * Only attempt a row if we're not on the last row. * Note that we have to reselect it afterwards. */ if ((row >= 0) && (row < (GTK_CLIST (clist)->rows - 1))) { gtk_clist_row_move (GTK_CLIST (clist), row, row + 1); gtk_clist_select_row (GTK_CLIST (clist), row + 1, -1); selectedRow = row + 1; listModified = TRUE; } } static void cListSelected (GtkWidget *clist, gint row, gint column, GdkEventButton *bevent, gpointer data) { gchar *string; /* * Fill the entry widgets & check box accoring to the selected row's text */ gtk_clist_get_text (GTK_CLIST (launcherCList), row, 0, &string); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), strcmp (string, "No") ? TRUE : FALSE); gtk_clist_get_text (GTK_CLIST (launcherCList), row, 1, &string); gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), string); gtk_clist_get_text (GTK_CLIST (launcherCList), row, 2, &string); gtk_entry_set_text (GTK_ENTRY (cmdEntry), string); selectedRow = row; } static void cListUnSelected (GtkWidget *clist, gint row, gint column, GdkEventButton *bevent, gpointer data) { /* * Reset the entry widgets & check box */ gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), ""); gtk_entry_set_text (GTK_ENTRY (cmdEntry), ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), 0); selectedRow = -1; } static void cbAdd (GtkWidget *widget, gpointer data) { gchar *buffer[3]; buffer[0] = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggleButton)) == TRUE ? "0" : "1"); buffer[1] = gkrellm_gtk_entry_get_text (&cmdEntryLabel); buffer[2] = gkrellm_gtk_entry_get_text (&cmdEntry); /* * If either of the Label or Command entries are empty, forget it. */ if ((!strlen (buffer[1])) || (!strlen (buffer[2]))) { return; } buffer[0] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggleButton)) == TRUE ? "Yes" : "No"; gtk_clist_append (GTK_CLIST (launcherCList), buffer); listModified = TRUE; /* * Reset the entry widgets & check box */ gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), ""); gtk_entry_set_text (GTK_ENTRY (cmdEntry), ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), 0); } static void cbReplace (GtkWidget *widget, gpointer data) { gchar *buffer[3]; buffer[0] = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggleButton)) == TRUE ? "0" : "1"); buffer[1] = gkrellm_gtk_entry_get_text (&cmdEntryLabel); buffer[2] = gkrellm_gtk_entry_get_text (&cmdEntry); /* * If either of the Label or Command entries are empty, forget it. */ if ((!strlen (buffer[1])) || (!strlen (buffer[2]))) { return; } /* * If a row is selected, we're modifying an existing entry, */ if (selectedRow >= 0) { gtk_clist_set_text (GTK_CLIST (launcherCList), selectedRow, 1, buffer[1]); gtk_clist_set_text (GTK_CLIST (launcherCList), selectedRow, 2, buffer[2]); gtk_clist_set_text (GTK_CLIST (launcherCList), selectedRow, 0, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggleButton)) == TRUE ? "Yes" : "No"); gtk_clist_unselect_row (GTK_CLIST (launcherCList), selectedRow, 0); selectedRow = -1; listModified = TRUE; } /* * Reset the entry widgets & check box */ gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), ""); gtk_entry_set_text (GTK_ENTRY (cmdEntry), ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), 0); gtk_clist_unselect_row (GTK_CLIST (launcherCList), selectedRow, 0); } static void cbDelete (GtkWidget *widget, gpointer data) { /* * Reset the entry widgets & check box */ gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), ""); gtk_entry_set_text (GTK_ENTRY (cmdEntry), ""); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), 0); if (selectedRow >= 0) { gtk_clist_remove (GTK_CLIST (launcherCList), selectedRow); selectedRow = -1; listModified = TRUE; } } /* * Create a Config tab with: * 1. Checkbox to make panel visible/hidden * 2. Text entry widget for command to run * 3. Text entry widget for button label * 4. Listbox to show items * 5. Info tab */ static void create_plugin_tab (GtkWidget *tab_vbox) { gchar *titles[3] = {"Visible", "Label", "Command"}; gchar *buffer[3]; gchar visible[5]; gint i = 0; GLauncher *launcher; GList *list; GtkWidget *tabs; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *scrolled; GtkWidget *text; GtkWidget *label; GtkWidget *button; GtkWidget *aboutLabel; GtkWidget *aboutText; /* * Make a couple of tabs. One for Config and one for info. */ tabs = gtk_notebook_new (); gtk_notebook_set_tab_pos (GTK_NOTEBOOK (tabs), GTK_POS_TOP); gtk_box_pack_start (GTK_BOX (tab_vbox), tabs, TRUE, TRUE, 0); /* * Setup tab: give it some scroll bars to keep the config * window size compact. */ vbox = gkrellm_gtk_notebook_page (tabs, "Setup"); vbox = gkrellm_gtk_scrolled_vbox (vbox, NULL, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); /* * Dynamically create the options on the Config tab according to MAX_BUTTONS. */ /* * Create text boxes to put Labels and Commands in */ label = gtk_label_new ("Label: "); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); cmdEntryLabel = gtk_entry_new_with_max_length (255) ; gtk_entry_set_text (GTK_ENTRY (cmdEntryLabel), "") ; gtk_entry_set_editable (GTK_ENTRY (cmdEntryLabel), TRUE); gtk_box_pack_start (GTK_BOX (vbox), cmdEntryLabel, FALSE, FALSE, 0) ; label = gtk_label_new ("Command:"); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, i); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); gtk_misc_set_alignment (GTK_MISC (label), 0, 0); cmdEntry = gtk_entry_new_with_max_length (255) ; gtk_entry_set_text (GTK_ENTRY (cmdEntry), "") ; gtk_entry_set_editable (GTK_ENTRY (cmdEntry), TRUE) ; gtk_box_pack_start (GTK_BOX (vbox), cmdEntry, FALSE, FALSE, 0) ; toggleButton = gtk_check_button_new_with_label ("Visible?"); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggleButton), 0); gtk_box_pack_start (GTK_BOX (vbox), toggleButton, FALSE, TRUE, 0); /* * Add buttons into their own box * => Add Replace Delete /\ \/ */ hbox = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0); /* * Add "Add", "Replace" & "Delete" buttons */ button = gtk_button_new_with_label ("Add"); gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) cbAdd, NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_label ("Replace"); gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) cbReplace, NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_label ("Delete"); gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) cbDelete, NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); /* * Add reposition buttons */ button = gtk_button_new_with_label ("/\\"); gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) cbMoveUp, NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_label ("\\/"); gtk_signal_connect (GTK_OBJECT (button), "clicked", (GtkSignalFunc) cbMoveDown, NULL); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); /* * Create listbox to hold each item */ scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0); /* * Create the CList with 3 titles: * Label, Command, Visible */ launcherCList = gtk_clist_new_with_titles (3, titles); gtk_clist_set_shadow_type (GTK_CLIST (launcherCList), GTK_SHADOW_OUT); /* * Set the column widths */ /* Label */ gtk_clist_set_column_width (GTK_CLIST (launcherCList), 0, 30); /* Command */ gtk_clist_set_column_width (GTK_CLIST (launcherCList), 1, 100); /* Visible */ gtk_clist_set_column_width (GTK_CLIST (launcherCList), 2, 200); gtk_clist_set_column_justification (GTK_CLIST (launcherCList), 0, GTK_JUSTIFY_LEFT); gtk_clist_set_column_justification (GTK_CLIST (launcherCList), 1, GTK_JUSTIFY_LEFT); gtk_clist_set_column_justification (GTK_CLIST (launcherCList), 2, GTK_JUSTIFY_LEFT); /* * Add signals for selecting a row in the CList. */ gtk_signal_connect (GTK_OBJECT (launcherCList), "select_row", (GtkSignalFunc) cListSelected, NULL); /* * Add signal for deselecting a row in the CList. * If not, delselecting & attempting to create a new entry will overwrite * the previuosly selected row. */ gtk_signal_connect (GTK_OBJECT (launcherCList), "unselect_row", (GtkSignalFunc) cListUnSelected, NULL); /* * Add the CList to the scrolling window */ gtk_container_add (GTK_CONTAINER (scrolled), launcherCList); /* * Fill the CList with our commands etc. */ for (i = 0, list = launcherList; list; i += 1, list = list->next) { launcher = (GLauncher *) list->data; sprintf (visible, "%s", (launcher->visible == 1 ? "Yes" : "No")); buffer[0] = visible; buffer[1] = launcher->label; buffer[2] = launcher->cmd; gtk_clist_append (GTK_CLIST (launcherCList), buffer); gtk_clist_set_row_data (GTK_CLIST (launcherCList), i, launcher); } /* * Info tab */ vbox = gkrellm_gtk_notebook_page (tabs, "Info"); text = gkrellm_gtk_scrolled_text_view (vbox, NULL, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gkrellm_gtk_text_view_append_strings (text, GKrellMLaunchInfo, (sizeof (GKrellMLaunchInfo) / sizeof (gchar *))); /* * About tab */ aboutText = gtk_label_new (GKrellMLaunchAbout); aboutLabel = gtk_label_new ("About"); gtk_notebook_append_page (GTK_NOTEBOOK (tabs), aboutText, aboutLabel); } static void create_plugin (GtkWidget *vbox, gint first_create) { gint i; GLauncher *launcher; GList *list; GkrellmStyle *style; GkrellmTextstyle *ts; GkrellmTextstyle *ts_alt; launcherVbox = vbox; if (first_create) { for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; launcher->panel = gkrellm_panel_new0(); } } style = gkrellm_meter_style (style_id); /* * Each GkrellmStyle has two text styles. The theme designer has picked the * colors and font sizes, presumably based on knowledge of what you draw * on your panel. You just do the drawing. You probably could assume * the ts font is larger than the ts_alt font, but again you can be * overridden by the theme designer. */ ts = gkrellm_meter_textstyle (style_id); ts_alt = gkrellm_meter_alt_textstyle (style_id); /* * Create a text decal that will be converted to a button. * Make it the entire width of the panel. */ for (i = 0, list = launcherList; list; i += 1, list = list->next) { launcher = (GLauncher *) list->data; launcher->decal = gkrellm_create_decal_text (launcher->panel, launcher->label, ts_alt, style, -1, -1, -1); /* * Configure the panel to created decal, and create it. */ gkrellm_panel_configure (launcher->panel, NULL, style); gkrellm_panel_create (vbox, monitor, launcher->panel); /* * After the panel is created, the decal can be converted into a button. * First draw the initial text into the text decal button and then * put the text decal into a meter button. */ gkrellm_draw_decal_text (launcher->panel, launcher->decal, launcher->label,1); gkrellm_put_decal_in_meter_button (launcher->panel, launcher->decal, buttonPress, GINT_TO_POINTER (i), NULL); } /* * Note: all of the above gkrellm_draw_decal_XXX() calls will not * appear on the panel until a gkrellm_draw_panel_layers() call is * made. This will be done in update_plugin(), otherwise we would * make the call here and anytime the decals are changed. */ if (first_create) { for (list = launcherList; list; list = list->next) { launcher = (GLauncher *) list->data; gtk_signal_connect (GTK_OBJECT (launcher->panel->drawing_area), "expose_event", (GtkSignalFunc) panel_expose_event, NULL); } /* * Setup the initial visible status of each panel * according to the config item read in. */ setVisibility (); } } /* * The monitor structure tells GKrellM how to call the plugin routines. */ static GkrellmMonitor plugin_mon = { CONFIG_NAME, /* Name, for config tab. */ 0, /* Id, 0 if a plugin */ create_plugin, /* The create function */ update_plugin, /* The update function */ create_plugin_tab, /* The config tab create function */ apply_plugin_config, /* Apply the config function */ save_plugin_config, /* Save user config */ load_plugin_config, /* Load user config */ PLUGIN_CONFIG_KEYWORD, /* config keyword */ NULL, /* Undefined 2 */ NULL, /* Undefined 1 */ NULL, /* private */ PLUGIN_PLACEMENT, /* Insert plugin before this monitor */ NULL, /* Handle if a plugin, filled in by GKrellM */ NULL /* path if a plugin, filled in by GKrellM */ }; /* * All GKrellM plugins must have one global routine named gkrellm_init_plugin() * which returns a pointer to a filled in monitor structure. */ GkrellmMonitor* gkrellm_init_plugin () { /* * Don't want any row in the Config tab initially selected. */ selectedRow = -1; listModified = FALSE; style_id = gkrellm_add_meter_style (&plugin_mon, STYLE_NAME); monitor = &plugin_mon; return &plugin_mon; }