Example #1
0
static void create_hand_widgets (window_board_t *win)
{
	static const char *alignment_a[] = {"alignment_w", "alignment_n", "alignment_e", "alignment_s"};
	static int dir[] = { 1, 2, 3, 4 };
	int h;
	GtkSizeGroup *sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);

	for (h = 0; h < 4; h++) {
		GtkWidget *alignment = get_widget (alignment_a[h]);
		GtkWidget *hand = hand_display_new(HAND_DISPLAY_MODE_HAND);
		gtk_container_add(GTK_CONTAINER(alignment), hand);
		gtk_widget_show(hand);
		g_signal_connect (hand, "card-clicked", G_CALLBACK (card_clicked), dir + h);
		g_signal_connect (hand, "card-enter", G_CALLBACK (card_enter), dir + h);
		g_signal_connect (hand, "card-leave", G_CALLBACK (card_leave), dir + h);
		g_signal_connect (hand, "card-drag-drop", G_CALLBACK (card_drag_drop), dir + h);
		win->handdisp[h] = HAND_DISPLAY(hand);
		hand_display_set_drag (HAND_DISPLAY (hand), 1);
		gtk_size_group_add_widget (sizegroup, hand);
	}
	g_object_unref (sizegroup);

	/* trick display */
	GtkWidget *grid = get_widget ("table1");
	GtkWidget *table = hand_display_new (HAND_DISPLAY_MODE_TABLE);
	gtk_table_attach_defaults (GTK_TABLE (grid), table, 1, 2, 1, 2);
	gtk_widget_show (table);
	win->table = HAND_DISPLAY (table);
}
Example #2
0
static void
hand_display_size_request (GtkWidget *hand, GtkRequisition *requisition)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	requisition->width = handdisp->want_width;
	requisition->height = handdisp->mode != HAND_DISPLAY_MODE_CARD ? 90 : 10;
}
Example #3
0
static gboolean
hand_display_button_press (GtkWidget *hand, GdkEventButton *event)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	int card = which_card(handdisp, event->x, event->y);

	if (event->type != GDK_BUTTON_RELEASE) /* don't trigger after dnd */
		handdisp->cur_focus = card;
	if (event->type == GDK_BUTTON_PRESS) {
		handdisp->cur_click = card;
		if (handdisp->drag) {
			handdisp->drag_x = event->x;
			handdisp->drag_y = event->y;
		}
	}
	if (handdisp->cur_focus == -1)
		return FALSE;
	redraw_card (hand, card);

	if (event->type == GDK_BUTTON_RELEASE) {
		if (handdisp->cur_click == card)
			g_signal_emit_by_name (handdisp, "card-clicked", card);
		handdisp->cur_click = -1;
	}
	return FALSE;
}
Example #4
0
static gboolean
hand_display_motion (GtkWidget *hand, GdkEventMotion *event)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	int card = which_card(handdisp, event->x, event->y);
	if (handdisp->drag && handdisp->cur_click >= 0 && handdisp->cur_click < 52 &&
		gtk_drag_check_threshold (hand, handdisp->drag_x, handdisp->drag_y, event->x, event->y))
	{
		if (! target_list)
			target_list = gtk_target_list_new (target_entry, 1);
		handdisp->cur_drag = handdisp->cur_click;
		gtk_drag_begin (hand, target_list, GDK_ACTION_COPY, 1, (GdkEvent *) event);
	}
	if (handdisp->cur_focus != card) {
		if (handdisp->cur_focus != -1) {
			redraw_card (hand, handdisp->cur_focus);
			g_signal_emit_by_name (handdisp, "card-leave", handdisp->cur_focus);
		}
		handdisp->cur_focus = card;
		if (card != -1) {
			redraw_card (hand, card);
			g_signal_emit_by_name (handdisp, "card-enter", card);
		}
	}
	gdk_window_get_pointer(gtk_widget_get_window (hand), NULL, NULL, NULL); /* request more pointer hints */
	return FALSE;
}
Example #5
0
static void
hand_display_drag_leave (GtkWidget *hand, GdkDragContext *dc, gpointer data)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	if (handdisp->cur_focus != -1) {
		redraw_card (hand, handdisp->cur_focus);
		g_signal_emit_by_name (handdisp, "card-drag-leave", handdisp->cur_focus);
		handdisp->cur_focus = -1;
	}
}
Example #6
0
static void
hand_display_drag_data_get (GtkWidget *hand, GdkDragContext *dc,
        GtkSelectionData *selection_data, guint targettype, guint t, gpointer data)
{
	HandDisplay *handdisp = HAND_DISPLAY (hand);
	if (handdisp->cur_drag < 0)
		return;
	assert (targettype == 0);
	gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data),
			32, (guchar *) &(handdisp->cur_drag), sizeof (int));
}
Example #7
0
static gboolean
hand_display_leave (GtkWidget *hand, GdkEventCrossing *event)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	if (handdisp->cur_focus != -1) {
		redraw_card (hand, handdisp->cur_focus);
		g_signal_emit_by_name (handdisp, "card-leave", handdisp->cur_focus);
		handdisp->cur_focus = -1;
	}
	return FALSE;
}
Example #8
0
static void
redraw_card (GtkWidget *hand, int card)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	GdkRectangle rect;
	rect.x = handdisp->l[card] - 2;
	rect.y = handdisp->t[card] - 7;
	rect.width = handdisp->r[card] - handdisp->l[card] + 4;
	rect.height = handdisp->b[card] - handdisp->t[card] + 8;
	gdk_window_invalidate_rect (gtk_widget_get_window (hand), &rect, FALSE);
}
Example #9
0
static void
hand_display_drag_end (GtkWidget *hand, GdkDragContext *dc, gpointer data)
{
	HandDisplay *handdisp = HAND_DISPLAY (hand);
	if (handdisp->cur_drag >= 0) {
		handdisp->cards[handdisp->cur_drag] &= ~HAND_DISPLAY_INVISIBLE_CARD;
		redraw_card (hand, handdisp->cur_drag);
	}
	handdisp->cur_drag = -1;
	gtk_widget_destroy (drag_win);
	drag_win = NULL;
}
Example #10
0
static void
hand_display_drag_begin (GtkWidget *hand, GdkDragContext *dc, gpointer data /* unused */)
{
	HandDisplay *handdisp = HAND_DISPLAY (hand);
	assert (handdisp->cur_drag >= 0 && handdisp->cur_drag < 52);
	handdisp->cards[handdisp->cur_drag] |= HAND_DISPLAY_INVISIBLE_CARD;
	handdisp->cur_click = -1;
	redraw_card (hand, handdisp->cur_drag);

	/* create drag widget */
	if (drag_win) { /* should be NULL, but happens sometimes */
		gtk_widget_destroy (drag_win);
		drag_win = NULL;
	}
	drag_win = gtk_window_new (GTK_WINDOW_POPUP);
	GtkWidget *card = hand_display_new (HAND_DISPLAY_MODE_CARD);
	hand_display_set_style (HAND_DISPLAY (card), handdisp->style);
	hand_display_card_set_card (HAND_DISPLAY (card), handdisp->cur_drag);
	gtk_container_add (GTK_CONTAINER (drag_win), card);
	gtk_drag_set_icon_widget (dc, drag_win, 0, 0);
	gtk_widget_show_all (drag_win);
}
Example #11
0
static void
hand_display_drag_data_received (GtkWidget *hand, GdkDragContext *dc,
        gint x, gint y, GtkSelectionData *selection_data,
        guint targettype, guint t, gpointer data)
{
	HandDisplay *handdisp = HAND_DISPLAY (hand);
	int *card = (int *) gtk_selection_data_get_data (selection_data);
	int on_card = which_card(handdisp, x, y);
	/*
	if (*card == on_card) {
		gtk_drag_finish (dc, FALSE, FALSE, t);
		return;
	}
	*/
	g_signal_emit_by_name (handdisp, "card-drag-drop", *card, on_card);
	gtk_drag_finish (dc, TRUE, FALSE, t);
}
Example #12
0
static gboolean
hand_display_drag_motion (GtkWidget *hand, GdkDragContext *dc,
        gint x, gint y, guint t, gpointer data)
{
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	int card = which_card(handdisp, x, y);
	if (handdisp->cur_focus != card) {
		if (handdisp->cur_focus != -1) {
			redraw_card (hand, handdisp->cur_focus);
			g_signal_emit_by_name (handdisp, "card-drag-leave", handdisp->cur_focus);
		}
		handdisp->cur_focus = card;
		if (card != -1) {
			redraw_card (hand, card);
			g_signal_emit_by_name (handdisp, "card-drag-enter", card);
		}
	}
	return FALSE;
}
Example #13
0
static void
draw (GtkWidget *hand, cairo_t *cr)
{
	int x, y;
	HandDisplay *handdisp = HAND_DISPLAY(hand);
	cairo_text_extents_t extents;
	cairo_font_extents_t fextents;
	GtkAllocation allocation;
	gtk_widget_get_allocation (hand, &allocation);

	cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);

	/* "card" mode for drap&drop icon */
	if (handdisp->mode == HAND_DISPLAY_MODE_CARD) {
		if (handdisp->style == HAND_DISPLAY_STYLE_CARDS) {
			if (card_width != handdisp->want_width) { /* adjust window */
				handdisp->want_width = card_width;
				gdk_window_resize (gtk_widget_get_parent_window (hand),
						card_width, card_height);

				/* shaped drag icon
				 * credits to Mirco "MacSlow" Mueller <*****@*****.**>
				 * http://macslow.thepimp.net/?p=26 */
				GdkBitmap *pShapeBitmap = (GdkBitmap*) gdk_pixmap_new (NULL, card_width, card_height, 1);
				assert (pShapeBitmap);
				cairo_t *pCairoContext = gdk_cairo_create (pShapeBitmap);
				assert (cairo_status (pCairoContext) == CAIRO_STATUS_SUCCESS);
				render_card (pCairoContext, 0, 0, handdisp->table_card[0], HAND_DISPLAY_CARD);
				cairo_destroy (pCairoContext);
				gdk_window_shape_combine_mask (gtk_widget_get_parent_window (hand), pShapeBitmap, 0, 0);
				g_object_unref ((gpointer) pShapeBitmap);
			}
			render_card (cr, 0, 0, handdisp->table_card[0], HAND_DISPLAY_CARD);
			return;
		}

		char cs[6];
		int c = handdisp->table_card[0];
		int suit = c / 13;
		int rank = c % 13;

		snprintf (cs, 6, "%s%s", suit_str[suit], rank_str[rank]);
		cairo_set_font_size (cr, 20);
		cairo_text_extents (cr, cs, &extents);
#define XPAD 4
#define YPAD 2
		int w = extents.width + 2 * XPAD + 5;
		int h = extents.height + 2 * YPAD;

		cairo_set_source_rgb (cr, HAND_DISPLAY_FOCUS_BG);
		cairo_rectangle (cr, 1, 1, w, h);
		cairo_fill (cr);
		cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
		cairo_rectangle (cr, 1, 1, w, h);
		cairo_stroke (cr);

		cairo_move_to (cr, XPAD - extents.x_bearing + 1, YPAD - extents.y_bearing + 2);
		cairo_set_source_rgb (cr, suit_color[suit][0],
			suit_color[suit][1], suit_color[suit][2]);
		cairo_show_text (cr, suit_str[suit]);
		cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
		cairo_show_text (cr, rank_str[rank]);

		if (w + 2 != handdisp->want_width) { /* adjust window */
			handdisp->want_width = w + 2;
			gdk_window_resize (gtk_widget_get_parent_window (hand), w + 2, h + 2);
		}

		return;
	}

	cairo_set_source_rgb (cr, HAND_DISPLAY_TABLE_BG);
	cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
	cairo_fill (cr);

	/* "table" mode for displaying the already played cards in the middle of the screen */

	if (handdisp->mode == HAND_DISPLAY_MODE_TABLE &&
	    handdisp->style == HAND_DISPLAY_STYLE_CARDS) {
		int i;
		for (i = 0; i < 4; i++) {
			switch (handdisp->table_seat[i]) {
				case 1: x = allocation.width / 2 - card_width + 5;
				/*W*/	y = (allocation.height - card_height) / 2 + 5;
					break;
				case 2: x = (allocation.width - card_width) / 2 - 2;
				/*N*/	y = MAX (allocation.height / 2 - card_height + 10, 0);
					break;
				case 3: x = allocation.width / 2 - 5;
				/*E*/	y = (allocation.height - card_height) / 2 - 5;
					break;
				case 4: x = (allocation.width - card_width) / 2 + 2;
				/*S*/	y = MIN (allocation.height / 2 - 10, allocation.height - card_height);
					break;
				default:
					return; /* stop here */
			}

			render_card (cr, x, y, handdisp->table_card[i], HAND_DISPLAY_CARD);

		}
		return;
	}

	if (handdisp->mode == HAND_DISPLAY_MODE_TABLE) { /* text */
		cairo_set_font_size (cr, 20);

		int i;
		for (i = 0; i < 4; i++) {
			char cs[6];
			if (!handdisp->table_seat[i])
				return;
			int c = handdisp->table_card[i];
			int suit = c / 13;
			int rank = c % 13;
			snprintf (cs, 6, "%s%s", suit_str[suit], rank_str[rank]);
			cairo_text_extents (cr, cs, &extents);

#define XOFF 38
#define YOFF 23
#define WIDTH 52
#define HEIGHT 28
#define RAD 5
			switch (handdisp->table_seat[i]) { /* middle point */
				case 1: x = allocation.width / 2 - XOFF;
				/*W*/	y = allocation.height / 2;
					break;
				case 2: x = allocation.width / 2;
				/*N*/	y = allocation.height / 2 - YOFF;
					break;
				case 3: x = allocation.width / 2 + XOFF;
				/*E*/	y = allocation.height / 2;
					break;
				case 4: x = allocation.width / 2;
				/*S*/	y = allocation.height / 2 + YOFF;
					break;
				default:
					return; /* stop here */
			}

			cairo_new_path (cr);
			cairo_arc_negative (cr, x-WIDTH/2+RAD, y+HEIGHT/2 - RAD, RAD, M_PI, M_PI_2);
			cairo_arc_negative (cr, x+WIDTH/2-RAD, y+HEIGHT/2 - RAD, RAD, M_PI_2, 0.0);
			cairo_arc_negative (cr, x+WIDTH/2-RAD, y-HEIGHT/2 + RAD, RAD, 0.0, -M_PI_2);
			cairo_arc_negative (cr, x-WIDTH/2+RAD, y-HEIGHT/2 + RAD, RAD, -M_PI_2, M_PI);
			cairo_close_path (cr);
			cairo_set_source_rgb (cr, HAND_DISPLAY_FOCUS_BG);
			cairo_fill_preserve (cr);
			cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
			cairo_stroke (cr);

			cairo_move_to (cr, x - extents.width / 2 - 3,
					y + extents.height / 2 - 3);
			cairo_set_source_rgb (cr, suit_color[suit][0],
				suit_color[suit][1], suit_color[suit][2]);
			cairo_show_text (cr, suit_str[suit]);
			cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
			cairo_show_text (cr, rank_str[rank]);
		}
		return;
	}

	/* normal hands display */

	/* compute cached best card score for this hand */
	if (handdisp->best_card_score == HAND_DISPLAY_NO_SCORE) {
		int c;
		handdisp->best_card_score = handdisp->card_score_neg ? 14 : -14;
		for (c = 0; c < 52; c++) {
			if (handdisp->card_score_neg ?
				(handdisp->card_score[c] < handdisp->best_card_score) :
				(handdisp->card_score[c] > handdisp->best_card_score))
					handdisp->best_card_score = handdisp->card_score[c];
		}
	}

	/* "cards" style */

	if (handdisp->style == HAND_DISPLAY_STYLE_CARDS && handdisp->mode != HAND_DISPLAY_MODE_HAND_X) {
		/* we do not support MODE_X here, yet we still allow setting
		 * STYLE_CARDS there to have the right drag icon */
		y = MAX (allocation.height - card_height - 5, 15);
		int n = 0;
		int suit;
		for (suit = 0; suit < 4; suit++) {
			int c;
			for (c = 13 * (handdisp->suits[suit] + 1) - 1; c >= 13 * handdisp->suits[suit]; c--) {
				if (handdisp->cards[c]) {
					x = floor (n++ * (allocation.width - card_width) / 12.0);

					int sc = handdisp->card_score[c];
					int yy = c == handdisp->cur_focus ? y - 15 :
						(sc != HAND_DISPLAY_NO_SCORE &&
						 handdisp->best_card_score == sc ? y - 5 : y);
					yy = MAX (yy, 0);
					handdisp->l[c] = x;
					handdisp->r[c] = x + card_width;
					handdisp->t[c] = y - 15;
					handdisp->b[c] = y + card_height;

					if (handdisp->cards[c] & HAND_DISPLAY_INVISIBLE_CARD)
						continue;

					render_card (cr, x, yy, c, handdisp->cards[c]);

					if (handdisp->cards[c] == HAND_DISPLAY_HILIGHT_CARD) { /* draw triangular arrow */
						cairo_set_source_rgb (cr, HAND_DISPLAY_HILIGHT_FONT);
						cairo_move_to (cr, x + 3 + (allocation.width - card_width - 10) / 24.0, yy);
						cairo_rel_line_to (cr, -5, -5);
						cairo_rel_line_to (cr, 10, 0);
						cairo_fill (cr);
					}

					/* show card score */
					if (handdisp->card_score[c] == HAND_DISPLAY_NO_SCORE)
						continue;
					char *buf = overtricks (handdisp->card_score[c]);
					static int text_h = 0;
					if (!text_h) {
						cairo_font_extents (cr, &fextents);
						text_h = fextents.ascent;
					}
					cairo_text_extents (cr, buf, &extents);
					cairo_move_to (cr, x + 1 + text_h,
							yy + 30 + extents.width);
					cairo_set_source_rgb (cr, HAND_DISPLAY_DD_FONT);
					cairo_save (cr);
					cairo_rotate (cr, -G_PI_2);
					cairo_show_text (cr, buf);
					cairo_restore (cr);
				}
			}
		}

		return;
	}

	/* "text" style */

	/* draw suit symbols */
	cairo_set_font_size (cr, 20);
	int suit_width = 0;
	int suit;
	for (suit = 0; suit < 4; suit++) {
		x = 0;
		y = floor ((double) allocation.height * (3.8 - suit) / 4.0);
		cairo_move_to (cr, x, y);
		cairo_text_extents (cr, suit_str[suit], &extents);
		if (extents.x_advance > suit_width)
			suit_width = extents.x_advance;
		cairo_set_source_rgb (cr, suit_color[suit][0], suit_color[suit][1], suit_color[suit][2]);
		cairo_show_text (cr, suit_str[suit]);
	}

	/* draw cards */
	for (suit = 0; suit < 4; suit++) {
		x = 4 + suit_width;
		y = floor ((double) allocation.height * (3.8 - suit) / 4.0);
		cairo_move_to (cr, x, y);

		int c;
		for (c = 13 * suit + 12; c >= 13 * suit; c--) {
			if (handdisp->cards[c]) {
				cairo_text_extents (cr, rank_str[c % 13], &extents);
				handdisp->l[c] = x + extents.x_bearing;
				handdisp->r[c] = x + extents.x_bearing + extents.width;
				handdisp->t[c] = y + extents.y_bearing;
				handdisp->b[c] = y + extents.y_bearing + extents.height;
				if (!(handdisp->cards[c] & HAND_DISPLAY_INVISIBLE_CARD)) {
					if (c == handdisp->cur_focus) {
						cairo_set_source_rgb (cr, HAND_DISPLAY_FOCUS_BG);
						cairo_rectangle (cr, handdisp->l[c] - 1, handdisp->t[c] - 1,
							extents.width + 2, extents.height + 2);
						cairo_fill (cr);
					}
					if (handdisp->card_score[c] == HAND_DISPLAY_NO_SCORE) {
						if (handdisp->cards[c] == HAND_DISPLAY_CARD)
							cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
						else if (handdisp->cards[c] == HAND_DISPLAY_GREY_CARD)
							cairo_set_source_rgb (cr, HAND_DISPLAY_GREY_FONT);
						else if (handdisp->cards[c] == HAND_DISPLAY_OLD_CARD)
							cairo_set_source_rgb (cr, HAND_DISPLAY_OLD_FONT);
						else if (handdisp->cards[c] == HAND_DISPLAY_HILIGHT_CARD)
							cairo_set_source_rgb (cr, HAND_DISPLAY_HILIGHT_FONT);
					} else {
						/* invert colors if the score is for the opps */
						if (handdisp->card_score_neg ^ (handdisp->card_score[c] >= 0))
							if (handdisp->best_card_score == handdisp->card_score[c])
								cairo_set_source_rgb (cr, HAND_DISPLAY_BEST_POS_FONT);
							else
								cairo_set_source_rgb (cr, HAND_DISPLAY_POS_FONT);
						else
							if (handdisp->best_card_score == handdisp->card_score[c])
								cairo_set_source_rgb (cr, HAND_DISPLAY_BEST_NEG_FONT);
							else
								cairo_set_source_rgb (cr, HAND_DISPLAY_NEG_FONT);
					}
					cairo_move_to (cr, x, y);
					cairo_show_text (cr, rank_str[c % 13]);
				}
				x += extents.x_advance; y += extents.y_advance;
			} else {
				handdisp->l[c] = handdisp->r[c] = handdisp->t[c] = handdisp->b[c] = 0;
			}
		}

		/* MODE_X */
		if (handdisp->mode == HAND_DISPLAY_MODE_HAND_X) {
			c = 52 + suit;
			x += 3;
			cairo_text_extents (cr, "x", &extents);
			handdisp->l[c] = x + extents.x_bearing;
			handdisp->r[c] = x + extents.x_bearing + extents.width;
			handdisp->t[c] = y + extents.y_bearing;
			handdisp->b[c] = y + extents.y_bearing + extents.height;
			if (c == handdisp->cur_focus) {
				cairo_set_source_rgb (cr, HAND_DISPLAY_FOCUS_BG);
				cairo_rectangle (cr, handdisp->l[c] - 1, handdisp->t[c] - 1,
					extents.width + 2, extents.height + 2);
				cairo_fill (cr);
			}
			cairo_set_source_rgb (cr, HAND_DISPLAY_FONT);
			cairo_move_to (cr, x, y);
			cairo_show_text (cr, "x");
			x += extents.x_advance + 4;
		}

		if (x > handdisp->want_width) { /* grow window */
			handdisp->want_width = x;
			gtk_widget_queue_resize (hand);
		}
	}

	/* show card scores */
	cairo_set_font_size (cr, 10);
	int c;
	for (c = 51; c >= 0; c--) {
		char *buf;
		if (handdisp->card_score[c] != HAND_DISPLAY_NO_SCORE) {
			buf = overtricks (handdisp->card_score[c]);
			cairo_text_extents (cr, buf, &extents);
			cairo_move_to (cr, handdisp->r[c] - extents.x_advance, handdisp->b[c]);
			cairo_set_source_rgb (cr, HAND_DISPLAY_DD_FONT);
			cairo_show_text (cr, buf);
		}
	}
}