home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / dialog_handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  8.5 KB  |  353 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  * Copyright (C) 1999 Andy Thomas (alt@picnic.demon.co.uk)
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  */
  19. #define __DIALOG_HANDLER_C__ 1
  20.  
  21. #include <gtk/gtk.h>
  22.  
  23. #include <gmodule.h>
  24.  
  25. #include "apptypes.h"
  26. #include "cursorutil.h"
  27. #include "dialog_handler.h"
  28.  
  29. /*  State of individual dialogs  */
  30.  
  31. typedef enum
  32. {
  33.   INVISIBLE,
  34.   VISIBLE,
  35.   UNKNOWN
  36. } VisibilityState;
  37.  
  38. typedef struct _DialogState DialogState;
  39.  
  40. struct _DialogState
  41. {
  42.   GtkWidget       *dialog;
  43.   VisibilityState  saved_state;
  44. };
  45.  
  46. /*  This keeps track of the state the dialogs are in
  47.  *  ie how many times we have pressed the tab key
  48.  */
  49. typedef enum
  50. {
  51.   SHOW_ALL,
  52.   HIDE_ALL,
  53.   SHOW_TOOLBOX,
  54.   LAST_SHOW_STATE
  55. } ShowState;
  56.  
  57. /*  Start off with all dialogs showing  */
  58. static ShowState dialogs_showing = SHOW_ALL;
  59.  
  60. /*  Prevent multiple keypresses from unsetting me.  */
  61. static gboolean doing_update = FALSE;
  62.  
  63. /*  List of dialogs that have been created and are on screen
  64.  *  (may be hidden already).
  65.  */
  66. static GSList * active_dialogs = NULL;
  67.  
  68. /* Used as a placeholder when a member of active_dialogs is removed due to
  69.  * a detected error. 
  70.  */
  71. static GSList error_tmp_list = { NULL, NULL };
  72.  
  73. /*  Those have a special behaviour  */
  74. static DialogState * toolbox_shell  = NULL;
  75. static DialogState * fileload_shell = NULL;
  76.  
  77. /*  Private  */
  78.  
  79. /*  Hide all currently registered dialogs  */
  80.  
  81. static void
  82. dialog_hide_all (void)
  83. {
  84.   DialogState *dstate;
  85.   GSList *list;
  86.  
  87.   for (list = active_dialogs; list; list = g_slist_next (list))
  88.     {
  89.       dstate = (DialogState *) list->data;
  90.   
  91.       if (GTK_WIDGET_VISIBLE (dstate->dialog))
  92.     {
  93.       dstate->saved_state = VISIBLE;
  94.       gtk_widget_hide (dstate->dialog);
  95.     }
  96.       else
  97.     {
  98.       dstate->saved_state = INVISIBLE;
  99.     }
  100.     }
  101. }
  102.  
  103. /*  Show all currently registered dialogs  */
  104.  
  105. static void
  106. dialog_show_all (void)
  107. {
  108.   DialogState *dstate;
  109.   GSList *list;
  110.  
  111.   for (list = active_dialogs; list; list = g_slist_next (list))
  112.     {
  113.       dstate = (DialogState *) list->data;
  114.  
  115.       if (dstate->saved_state == VISIBLE && !GTK_WIDGET_VISIBLE (dstate->dialog))
  116.     gtk_widget_show(dstate->dialog);
  117.     }
  118. }
  119.  
  120. /*  Handle the tool box in a special way  */
  121.  
  122. static void
  123. dialog_hide_toolbox (void)
  124. {
  125.   if (toolbox_shell && GTK_WIDGET_VISIBLE (toolbox_shell->dialog))
  126.     {
  127.       gtk_widget_hide (toolbox_shell->dialog);
  128.       toolbox_shell->saved_state = VISIBLE;
  129.     }
  130. }
  131.  
  132. /*  public  */
  133.  
  134. void
  135. dialog_show_toolbox (void)
  136. {
  137.   if (toolbox_shell && 
  138.       toolbox_shell->saved_state == VISIBLE && 
  139.       !GTK_WIDGET_VISIBLE (toolbox_shell->dialog))
  140.     {
  141.       gtk_widget_show (toolbox_shell->dialog);
  142.     }
  143. }
  144.  
  145. /*  Set hourglass cursor on all currently registered dialogs  */
  146.  
  147. void
  148. dialog_idle_all (void)
  149. {
  150.   DialogState *dstate;
  151.   GSList *list;
  152.  
  153.   for (list = active_dialogs; list; list = g_slist_next (list))
  154.     {
  155.       dstate = (DialogState *) list->data;
  156.  
  157.       if(!GTK_IS_WIDGET(dstate->dialog) || 
  158.      (GTK_WIDGET_VISIBLE(dstate->dialog) && !dstate->dialog->window))
  159.     {
  160.       g_warning("%s discovered non-widget thing %p in list of "
  161.             "active_dialogs.  Calling dialog_unregister on it.\n",
  162.             G_GNUC_PRETTY_FUNCTION, dstate->dialog);
  163.  
  164.       error_tmp_list.next=list->next;
  165.       list=&error_tmp_list;
  166.       dialog_unregister(dstate->dialog);
  167.     }
  168.       else if(GTK_WIDGET_VISIBLE (dstate->dialog))
  169.     {
  170.       change_win_cursor (dstate->dialog->window, GDK_WATCH,
  171.                  TOOL_TYPE_NONE, CURSOR_MODIFIER_NONE, FALSE);
  172.     }
  173.     }
  174.  
  175.   if (toolbox_shell && GTK_WIDGET_VISIBLE (toolbox_shell->dialog))
  176.     {
  177.       change_win_cursor (toolbox_shell->dialog->window, GDK_WATCH,
  178.              TOOL_TYPE_NONE, CURSOR_MODIFIER_NONE, FALSE);
  179.     }
  180.  
  181.   if (fileload_shell && GTK_WIDGET_VISIBLE (fileload_shell->dialog))
  182.     {
  183.       change_win_cursor (fileload_shell->dialog->window, GDK_WATCH,
  184.              TOOL_TYPE_NONE, CURSOR_MODIFIER_NONE, FALSE);
  185.     }
  186. }
  187.  
  188. /*  And remove the hourglass again.  */
  189.  
  190. void
  191. dialog_unidle_all (void)
  192. {
  193.   DialogState *dstate;
  194.   GSList *list;
  195.  
  196.   for (list = active_dialogs; list; list = g_slist_next (list))
  197.     {
  198.       dstate = (DialogState *) list->data;
  199.  
  200.       if(!GTK_IS_WIDGET(dstate->dialog) || 
  201.      (GTK_WIDGET_VISIBLE(dstate->dialog) && !dstate->dialog->window))
  202.     {
  203.       g_warning("%s discovered non-widget thing %p in list of "
  204.             "active_dialogs.  Calling dialog_unregister on it.\n",
  205.             G_GNUC_PRETTY_FUNCTION, dstate->dialog);
  206.  
  207.       error_tmp_list.next=list->next;
  208.       list=&error_tmp_list;
  209.       dialog_unregister(dstate->dialog);
  210.     }
  211.       else if (GTK_WIDGET_VISIBLE (dstate->dialog))
  212.     {
  213.       unset_win_cursor (dstate->dialog->window);
  214.     }
  215.     }
  216.  
  217.   if (toolbox_shell && GTK_WIDGET_VISIBLE (toolbox_shell->dialog))
  218.     {
  219.       unset_win_cursor (toolbox_shell->dialog->window);
  220.     }
  221.  
  222.   if (fileload_shell && GTK_WIDGET_VISIBLE (fileload_shell->dialog))
  223.     {
  224.       unset_win_cursor (fileload_shell->dialog->window);
  225.     }
  226. }
  227.  
  228. /*  Register a dialog that we can handle  */
  229.  
  230. G_MODULE_EXPORT
  231. void
  232. dialog_register (GtkWidget *dialog)
  233. {
  234.   DialogState *dstate;
  235.  
  236.   dstate = g_new (DialogState, 1);
  237.  
  238.   dstate->dialog      = dialog;
  239.   dstate->saved_state = UNKNOWN;
  240.  
  241.   active_dialogs = g_slist_append (active_dialogs, dstate);
  242. }
  243.  
  244. void
  245. dialog_register_toolbox (GtkWidget *dialog)
  246. {
  247.   toolbox_shell = g_new (DialogState, 1);
  248.  
  249.   toolbox_shell->dialog      = dialog;
  250.   toolbox_shell->saved_state = UNKNOWN;
  251. }
  252.  
  253. void
  254. dialog_register_fileload (GtkWidget *dialog)
  255. {
  256.   fileload_shell = g_new (DialogState, 1);
  257.  
  258.   fileload_shell->dialog      = dialog;
  259.   fileload_shell->saved_state = UNKNOWN;
  260. }
  261.  
  262. /*  unregister dialog  */
  263.  
  264. G_MODULE_EXPORT
  265. void
  266. dialog_unregister (GtkWidget *dialog)
  267. {
  268.   DialogState *dstate = NULL;
  269.   GSList *list;
  270.  
  271.   for (list = active_dialogs; list; list = g_slist_next (list))
  272.     {
  273.       dstate = (DialogState *) list->data;
  274.  
  275.       if (dstate->dialog == dialog)
  276.     break;
  277.     }
  278.  
  279.   if (dstate != NULL)
  280.     {
  281.       active_dialogs = g_slist_remove (active_dialogs, dstate);
  282.       g_free (dstate);
  283.     }
  284. }
  285.  
  286. /*  Toggle showing of dialogs
  287.  *
  288.  *  States:-
  289.  *  SHOW_ALL -> HIDE_ALL -> SHOW_TOOLBOX -> SHOW_ALL ....
  290.  */
  291.  
  292. void 
  293. dialog_toggle (void)
  294. {
  295.   GSList *list;
  296.  
  297.   if (doing_update)
  298.     return;
  299.  
  300.   doing_update = TRUE;
  301.  
  302.   /* Paranoid error checking on our active_dialogs list, because
  303.      3rd party modules access this list through dialog_register 
  304.      and we don't want them wreaking havoc on our internal state.
  305.      Attempts to recover gracefully, but *is not bulletproof* since
  306.      GTK_IS_WIDGET *may* succeed, even if it's pointing to garbage,
  307.      if the garbage looks a little like a widget structure. */
  308.   for (list = active_dialogs; list; list = g_slist_next (list))
  309.     {
  310.       DialogState* dstate = (DialogState *) list->data;
  311.  
  312.       if(!GTK_IS_WIDGET(dstate->dialog))
  313.     {
  314.       g_warning("%s discovered non-widget thing %p in list of "
  315.             "active_dialogs.  Calling dialog_unregister on it.\n",
  316.             G_GNUC_PRETTY_FUNCTION, dstate->dialog);
  317.  
  318.       /* We must find the next list element before the current one
  319.          is destroyed by the call to unregister. */
  320.       error_tmp_list.next=list->next;
  321.       list=&error_tmp_list;
  322.       dialog_unregister(dstate->dialog);
  323.     }
  324.     }
  325.  
  326.   switch (dialogs_showing)
  327.     {
  328.     case SHOW_ALL:
  329.       dialogs_showing = HIDE_ALL;
  330.       dialog_hide_all ();
  331.       dialog_hide_toolbox ();
  332.       break;
  333.     case HIDE_ALL:
  334.       dialogs_showing = SHOW_TOOLBOX;
  335.       dialog_show_toolbox ();
  336.       break;
  337.     case SHOW_TOOLBOX:
  338.       dialogs_showing = SHOW_ALL;
  339.       dialog_show_all ();
  340.     default:
  341.       break;
  342.     }
  343.  
  344.   gdk_flush ();
  345.   while (gtk_events_pending ())
  346.     {
  347.       gtk_main_iteration ();
  348.       gdk_flush ();
  349.     }
  350.  
  351.   doing_update = FALSE;
  352. }
  353.