📄 gui-dial.c
字号:
/* $Header: /home/jcb/newmj/RCS/gui-dial.c,v 11.63 2003/09/27 12:09:25 jcb Rel $ * gui-dial.c * dialog box functions. *//****************** COPYRIGHT STATEMENT ********************** * This file is Copyright (c) 2000 by J. C. Bradfield. * * Distribution and use is governed by the LICENCE file that * * accompanies this file. * * The moral rights of the author are asserted. * * * ***************** DISCLAIMER OF WARRANTY ******************** * This code is not warranted fit for any purpose. See the * * LICENCE file for further information. * * * *************************************************************/#include "gui.h"static const char rcs_id[] = "$Header: /home/jcb/newmj/RCS/gui-dial.c,v 11.63 2003/09/27 12:09:25 jcb Rel $";static void continue_callback(GtkWidget *w, gpointer data);static void turn_callback(GtkWidget *w, gpointer data);/* check box to keep keyboard focus in message window */static GtkWidget *mfocus;/* This grabs focus, unless the chat window is in the main window and has focus. This stops focus being lost from the chat entry box every time a dialog pops up. (Requested by users, to avoid accidental discards. Moreover, if the appropriate checkbox is set, it keeps the focus in the message window.*/static void grab_focus_if_appropriate(GtkWidget *w);/* Used sordidly and internally */static GtkRequisition discard_req = { 0, 0};/* Why an array? So I can pass pointers around */DiscardDialog discard_dialog[1];/* dialog box for specifying chows */GtkWidget *chow_dialog;/* Stores the three TileSetBoxes */static TileSetBox chowtsbs[3];/* and the three buttons */static GtkWidget *chowbuttons[3];/* dialog box for declaring specials */GtkWidget *ds_dialog;/* dialog box for continuing with next hand */GtkWidget *continue_dialog;/* dialog for opening connection */GtkWidget *open_dialog;GtkWidget *openmenuentry, *newgamemenuentry, *resumegamemenuentry, *savemenuentry, *saveasmenuentry, *closemenuentry, *gameoptionsmenuentry;/* entry for showing warnings window */static GtkWidget *warningentry;/* dialog box for action when it's our turn. Actions: Discard Kong Add to Pung Mah Jong*/GtkWidget *turn_dialog;GtkWidget *turn_dialog_label; /* used to display number of tiles left *//* dialog box for closed sets when scoring. Actions: Eyes Chow Pung Done*/GtkWidget *scoring_dialog;/* window for game status display */GtkWidget *status_window;/* window for "about" information */GtkWidget *about_window;/* window to nag for donations */GtkWidget *nag_window;/* an array of text widgets for displaying scores etc. Element 4 is for settlements. The others are for each player: currently, I think these should be table relative.*/GtkWidget *scoring_notebook;GtkWidget *textpages[5];GtkWidget *textlabels[5]; /* labels for the pages */GtkWidget *textwindow; /* and the window for it *//* The window for messages, and the display text widget */GtkWidget *messagewindow, *messagetext;/* Warning window */GtkWidget *warningwindow, *warningtext;/* The Save As.. dialog */GtkWidget *save_window;/* and its text entry widget */GtkWidget *save_text;/* The window for display options */GtkWidget *display_option_dialog = NULL;/* the window for updating the game options */GtkWidget *game_option_dialog = NULL;GtkWidget *game_option_panel = NULL;/* and some of its buttons */GtkWidget *game_option_apply_button = NULL;GtkWidget *game_option_prefs_button = NULL;/* and a very similar one for option preferences */GtkWidget *game_prefs_dialog = NULL;GtkWidget *game_prefs_panel = NULL;/* and one for playing preferences */GtkWidget *playing_prefs_dialog = NULL;/* message entry widget */static GtkWidget *message_entry = NULL;/* time at which progress bar was started */static struct timeval pstart;static int pinterval = 25; /* timeout interval in ms */static int pbar_timeout_instance = 0; /* track dead timeouts */static GtkWidget *pbar;/* timeout handler for the dialog progress bar */static int pbar_timeout(gpointer instance) { int timeleft; struct timeval timenow; if ( pbar_timeout_instance != (int) instance ) return FALSE; /* dead timeout */ if ( ! GTK_WIDGET_VISIBLE(discard_dialog->widget) ) return FALSE; gettimeofday(&timenow,NULL); timeleft = ptimeout-(1000*(timenow.tv_sec-pstart.tv_sec) +(timenow.tv_usec-pstart.tv_usec)/1000); if ( timeleft <= 0 ) { /* we should not hide the claim dialog: the timeout is really controlled by the server, not us */ /* However, if we are supposed to be handling timeouts locally, we'd better send a noclaim! */ if ( local_timeouts ) { disc_callback(NULL,(gpointer)NoClaim); } return FALSE; } gtk_progress_bar_update(GTK_PROGRESS_BAR(pbar),1.0-(timeleft+0.0)/(ptimeout+0.0)); return TRUE;}/* popup the discard dialog. Arguments: Tile, player whence it came (as an ori), mode = 0 (normal), 1 (claiming tile for mah jong), 2 (claiming from kong) */void discard_dialog_popup(Tile t, int ori, int mode) { gint x,y,w,h; int i; char buf[128]; static Tile lastt; static int lastori, lastmode; static int positioned = 0; /* So that we don't work if it's already popped up: */ if ( GTK_WIDGET_VISIBLE(discard_dialog->widget) && t == lastt && lastori == ori && lastmode == mode ) return; lastt = t; lastori = ori; lastmode = mode; if ( mode != discard_dialog->mode ) { discard_dialog->mode = mode; if ( mode == 0 ) { gtk_widget_show(discard_dialog->noclaim); gtk_widget_hide(discard_dialog->eyes); gtk_widget_show(discard_dialog->chow); gtk_widget_show(discard_dialog->pung); gtk_widget_hide(discard_dialog->special); gtk_widget_show(discard_dialog->kong); gtk_widget_show(discard_dialog->mahjong); gtk_widget_hide(discard_dialog->robkong); } else if ( mode == 1 ) { gtk_widget_hide(discard_dialog->noclaim); gtk_widget_show(discard_dialog->eyes); gtk_widget_show(discard_dialog->chow); gtk_widget_show(discard_dialog->pung); gtk_widget_show(discard_dialog->special); gtk_widget_hide(discard_dialog->kong); gtk_widget_hide(discard_dialog->mahjong); gtk_widget_hide(discard_dialog->robkong); } else { gtk_widget_show(discard_dialog->noclaim); gtk_widget_hide(discard_dialog->eyes); gtk_widget_hide(discard_dialog->chow); gtk_widget_hide(discard_dialog->pung); gtk_widget_hide(discard_dialog->special); gtk_widget_hide(discard_dialog->kong); gtk_widget_hide(discard_dialog->mahjong); gtk_widget_show(discard_dialog->robkong); } } if ( mode == 0 ) grab_focus_if_appropriate(discard_dialog->noclaim); /* center the dialog on the main window */ /* Oh. I'd like to tell the window manager not to shift it when it puts the border round it. I wonder how I do that? */ /* Note that the size has been fixed in the init routine. The reason we do this statically is so that we can force the bloody thing to have the right size: we want to hide buttons before showing it, but then it would have a different size on being shown. Also, we want it to have a fixed size so we can put the turn dialog to coincide with this one's bottom left. */ switch ( dialogs_position ) { case DialogsCentral: case DialogsUnspecified: /* dialog is child of discard area */ w = discard_area_alloc.width; h = discard_area_alloc.height; x = y = 0; gtk_widget_set_uposition(discard_dialog->widget, x + w/2 - discard_req.width/2, y + h/2 - discard_req.height/2); break; case DialogsPopup: /* only do this the first time; we should let the user position them */ if ( ! positioned++ ) { gdk_window_get_size(topwindow->window,&w,&h); gdk_window_get_deskrelative_origin(topwindow->window,&x,&y); gtk_widget_set_uposition(discard_dialog->widget, x + w/2 - discard_req.width/2, y + h/2 - discard_req.height/2); } break; case DialogsBelow: ; } /* set the appropriate tile */ for ( i=1 ; i < 4 ; i++ ) { if ( i == ori ) { button_set_tile(discard_dialog->tiles[i],t,i); gtk_widget_show(discard_dialog->tiles[i]); } else { gtk_widget_hide(discard_dialog->tiles[i]); } } gtk_widget_hide(discard_dialog->tilename); if ( mode == 1 ) { gtk_label_set_text(GTK_LABEL(discard_dialog->tilename), "Claim discard for:"); } else { /* if not showing wall, say how many tiles left */ if ( ! showwall ) { if ( ori == 1 ) sprintf(buf,"(%d tiles left) %s", the_game->wall.live_end-the_game->wall.live_used, tile_name(the_game->tile)); else sprintf(buf,"%s (%d tiles left)", tile_name(the_game->tile), the_game->wall.live_end-the_game->wall.live_used); } else { strcpy(buf,tile_name(the_game->tile)); } gtk_label_set_text(GTK_LABEL(discard_dialog->tilename),buf); } if ( mode == 0 ) { static const gfloat xal[] = { 0.5,1.0,0.5,0.0 }; gtk_misc_set_alignment(GTK_MISC(discard_dialog->tilename), xal[ori],0.5); } else { gtk_misc_set_alignment(GTK_MISC(discard_dialog->tilename), 0.5,0.5); } gtk_widget_show(discard_dialog->widget); gtk_widget_show(discard_dialog->tilename); /* and start the progress bar timeout if appropriate */ if ( the_game->state != MahJonging && ptimeout > 0 ) { gtk_widget_show(pbar); gettimeofday(&pstart,NULL); /* we may as well calculate an appropriate value of pbar_timeout each time... we want it to update every half pixel, or 40 times a second, whichever is slower */ if ( pbar->allocation.width > 1 ) { /* in case it isn't realized yet */ pinterval = ptimeout/(2*pbar->allocation.width); } if ( pinterval < 25 ) pinterval = 25; gtk_timeout_add(pinterval,pbar_timeout,(gpointer) ++pbar_timeout_instance); } else { gtk_widget_hide(pbar); }}/* an accelerator group for the discard dialog */static GtkAccelGroup *discard_accel;/* this little function is used to install or remove the discard accelerators */static void add_or_remove_discard_accels(GtkWidget *w UNUSED, gpointer data){ if ( discard_accel == NULL ) return; if ( data ) { gtk_window_add_accel_group(GTK_WINDOW(topwindow),discard_accel); } else { gtk_window_remove_accel_group(GTK_WINDOW(topwindow),discard_accel); }}/* initialize it *//* Structure: If the dialog is in the middle: lefttile opptile righttile tile name progress bar Pass/Draw Chow Pung Kong MahJong otherwise: tilename progress bar buttons*/void discard_dialog_init(void) { GtkWidget *box, *tilebox, *left, *opp, *right, *lbl, *butbox, *but, *pixm; DiscardDialog *dd = &discard_dialog[0]; if ( dd->widget ) { gtk_widget_destroy(dd->widget); dd->widget = NULL; } switch ( dialogs_position ) { case DialogsCentral: case DialogsUnspecified: /* event box so there's a window to have background */ dd->widget = gtk_event_box_new(); gtk_fixed_put(GTK_FIXED(discard_area),dd->widget,0,0); /* it'll be moved later */ break; case DialogsBelow: dd->widget = gtk_event_box_new(); gtk_box_pack_start(GTK_BOX(dialoglowerbox),dd->widget,1,0,0); /* show it, so that the top window includes it when first mapped */ gtk_widget_show(dd->widget); break; case DialogsPopup: dd->widget = gtk_window_new(GTK_WINDOW_DIALOG); gtk_signal_connect (GTK_OBJECT (dd->widget), "delete_event", GTK_SIGNAL_FUNC (gtk_widget_hide), NULL); } box = gtk_vbox_new(0,dialog_vert_spacing); gtk_widget_show(box); gtk_container_add(GTK_CONTAINER(dd->widget),box); dd->mode = -1; /* so that personality will be set */ gtk_container_set_border_width(GTK_CONTAINER(box), dialog_border_width); tilebox = gtk_hbox_new(0,0); if ( dialogs_position != DialogsBelow ) gtk_widget_show(tilebox); left = gtk_button_new(); GTK_WIDGET_UNSET_FLAGS(left,GTK_CAN_FOCUS); gtk_widget_show(left); pixm = gtk_pixmap_new(tilepixmaps[3][HiddenTile],NULL); gtk_widget_show(pixm); gtk_container_add(GTK_CONTAINER(left),pixm); opp = gtk_button_new(); GTK_WIDGET_UNSET_FLAGS(opp,GTK_CAN_FOCUS); gtk_widget_show(opp); pixm = gtk_pixmap_new(tilepixmaps[2][HiddenTile],NULL); gtk_widget_show(pixm); gtk_container_add(GTK_CONTAINER(opp),pixm); right = gtk_button_new(); GTK_WIDGET_UNSET_FLAGS(right,GTK_CAN_FOCUS); gtk_widget_show(right); pixm = gtk_pixmap_new(tilepixmaps[1][HiddenTile],NULL); gtk_widget_show(pixm); gtk_container_add(GTK_CONTAINER(right),pixm); gtk_box_pack_start(GTK_BOX(tilebox),left,0,0,0); gtk_box_pack_start(GTK_BOX(tilebox),opp,1,0,0); gtk_box_pack_end(GTK_BOX(tilebox),right,0,0,0); dd->tiles[1] = right; dd->tiles[2] = opp; dd->tiles[3] = left; lbl = gtk_label_new("name of tile"); gtk_widget_show(lbl); dd->tilename = lbl; butbox = gtk_hbox_new(1,dialog_button_spacing); /* homogeneous, spaced */ gtk_widget_show(butbox);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -