Ejemplo n.º 1
0
/**
 * This function is a helper function for the wtk_frame_handler() function.
 * It is called when a pointer RELEASE event is sent to the container window.
 * This function completes the move operation if the RELEASE event was inside
 * the parent window's boundaries.
 *
 * \param frame Frame the received the event.
 * \param event Pointer event information.
 */
static void wtk_handle_frame_release(struct wtk_frame *frame,
		struct win_pointer_event const *event)
{
	bool is_inside;

	switch (frame->state) {
	/* If we were moving when released, ungrab pointer and move if
	 * release was inside parent window extents.
	 */
	case WTK_FRAME_MOVING:
		/* Ungrab pointer. */
		wtk_stop_drag(&(event->last_pos));
		win_grab_pointer(NULL);
		frame->state = WTK_FRAME_NORMAL;

		/* Check release position. */
		is_inside = win_is_inside_window(win_get_parent(frame->
				container), &(event->pos));

		/* If inside, move frame according to drag distance. */
		if (is_inside) {
			struct win_area area = *win_get_area(frame->container);
			area.pos.x += event->pos.x - wtk_drag_origin.x;
			area.pos.y += event->pos.y - wtk_drag_origin.y;
			win_set_area(frame->container, &area,
					WIN_ATTR_POSITION);
		}

		break;

	default:
		break;
	}
}
Ejemplo n.º 2
0
/**
 * This function is a helper function for the wtk_frame_handler() function.
 * It is called when a pointer RELEASE event is sent to the resize window.
 * This function completes the resize operation if the RELEASE event was inside
 * the parent window's boundaries.
 *
 * \param frame Frame the received the event.
 * \param event Pointer event information.
 */
static void wtk_handle_resize_release(struct wtk_frame *frame,
		struct win_pointer_event const *event)
{
	bool is_inside;

	switch (frame->state) {
	/* If we were resizing when released, ungrab pointer and resize
	 * if release was inside parent window extents.
	 */
	case WTK_FRAME_RESIZING:
		/* Ungrab pointer. */
		wtk_stop_drag(&(event->last_pos));
		win_grab_pointer(NULL);
		frame->state = WTK_FRAME_NORMAL;

		/* Check release position. */
		is_inside = win_is_inside_window(win_get_parent(frame->
				container), &(event->pos));

		/* If inside, resize frame according to drag distance. */
		if (is_inside) {
			struct win_area contents_area
				= *win_get_area(frame->contents);

			contents_area.size.x += event->pos.x -
					wtk_drag_origin.x;
			contents_area.size.y += event->pos.y -
					wtk_drag_origin.y;

			wtk_resize_frame(frame, &contents_area);
		}

		break;

	default:
		break;
	}
}
Ejemplo n.º 3
0
/**
 * This function is the window event handler for check box widgets.
 * It handles all events sent to the windows composing the widget.
 *
 * \param win Window receiving the event.
 * \param type The event type.
 * \param data Custom data, depending on event type.
 *
 * \return True if the event was recognized and accepted.
 */
static bool wtk_check_box_handler(struct win_window *win,
		enum win_event_type type, void const *data)
{
	struct win_command_event command;

	/* Custom data for windows of a widget points back to the widget itself. */
	struct wtk_check_box *check_box
		= (struct wtk_check_box *)win_get_custom_data(win);

	switch (type) {
	case WIN_EVENT_DRAW:
	{
		/* There should not be other windows in this widget. */
		Assert(win == check_box->container);

		/* For DRAW events, the data parameter points to the
		 * clipping region.
		 */
		struct win_clip_region const *clip
			= (struct win_clip_region const *)data;

		/* Draw check box square. */
		gfx_draw_rect(clip->origin.x + WTK_CHECKBOX_BOX_X,
				clip->origin.y + WTK_CHECKBOX_BOX_Y,
				WTK_CHECKBOX_BOX_SIZE,
				WTK_CHECKBOX_BOX_SIZE,
				WTK_CHECKBOX_BOX_COLOR);

		/* Draw check box square background. */
		if (WTK_CHECKBOX_BACKGROUND_COLOR != GFX_COLOR_TRANSPARENT) {
			gfx_draw_filled_rect(clip->origin.x +
					WTK_CHECKBOX_BOX_X + 1,
					clip->origin.y +
					WTK_CHECKBOX_BOX_Y + 1,
					WTK_CHECKBOX_BOX_SIZE - 2,
					WTK_CHECKBOX_BOX_SIZE - 2,
					WTK_CHECKBOX_BACKGROUND_COLOR);
		}

		/* Draw check box select marker if selected. */
		if (check_box->selected) {
			gfx_draw_filled_rect(clip->origin.x +
					WTK_CHECKBOX_BOX_X + 2,
					clip->origin.y +
					WTK_CHECKBOX_BOX_Y + 2,
					WTK_CHECKBOX_BOX_SIZE - 4,
					WTK_CHECKBOX_BOX_SIZE - 4,
					WTK_CHECKBOX_SELECT_COLOR);
		}

		/* Draw caption. */
		gfx_draw_string(check_box->caption,
				clip->origin.x + WTK_CHECKBOX_CAPTION_X,
				clip->origin.y + WTK_CHECKBOX_CAPTION_Y,
				&sysfont,
				GFX_COLOR_TRANSPARENT,
				WTK_CHECKBOX_CAPTION_COLOR);

		/* Always accept DRAW events, as the return value is
		 * ignored anyway for that event type.
		 */
		return true;
	}

	case WIN_EVENT_POINTER:
	{
		/* There should not be other windows in this widget. */
		Assert(win == check_box->container);

		/* For POINTER events, the data parameter points to the
		 * pointer event information.
		 */
		struct win_pointer_event const *event
			= (struct win_pointer_event const *)data;

		switch (event->type) {
		case WIN_POINTER_PRESS:

			/* When check box pressed, grab pointer and
			 * wait for release inside widget borders.
			 * Other widgets won't get pointer events
			 * before it is released, and the pointer
			 * ungrabbed by us.
			 */
			if (check_box->state == WTK_CHECKBOX_NORMAL) {
				win_grab_pointer(check_box->container);
				check_box->state = WTK_CHECKBOX_PRESSED;
				win_redraw(check_box->container);
			}

			break;

		case WIN_POINTER_RELEASE:

			/* When check box released, take action only if
			 * released inside widget extents.
			 */
			if (check_box->state == WTK_CHECKBOX_PRESSED) {
				bool is_inside;

				/* Ungrab pointer. */
				win_grab_pointer(NULL);
				check_box->state = WTK_CHECKBOX_NORMAL;
				win_redraw(check_box->container);

				/* Check release position. */
				is_inside = win_is_inside_window
							(check_box->container,
							&(event->pos));

				/* Toggle check box if inside. */
				if (is_inside) {
					wtk_check_box_toggle(check_box);

					/* Send non-zero command. */
					if (check_box->command) {
						command.sender
							= check_box->container;
						command.recipient
							= check_box->container;
						command.data
							= check_box->command;
						win_queue_command_event
							(&command);
					}
				}
			}

			break;

		default:
			break;
		}

		/* Accept all POINTER events since all acitivity inside
		 * the widget extents is relevant to us.
		 */
		return true;
	}

	case WIN_EVENT_DESTROY:
		/* There should not be other windows in this widget. */
		Assert(win == check_box->container);

		/* Memory allocated for windows will be automatically destroyed
		 * by the window system. We must destroy other allocations.
		 */
		membag_free(check_box->caption);
		membag_free(check_box);

		/* Always accept DESTROY events, as the return value is ignored
		 * anyway for that event type.
		 */
		return true;

	default:
		/* Reject unknown event types. */
		return false;
	}
}
Ejemplo n.º 4
0
/**
 * This function is the window event handler for radio button widgets.
 * It handles all events sent to the windows composing the widget.
 *
 * \param win Window receiving the event.
 * \param type The event type.
 * \param data Custom data, depending on event type.
 *
 * \return True if the event was recognized and accepted.
 */
static bool wtk_radio_button_handler(struct win_window *win,
		enum win_event_type type, void const *data)
{
	struct win_command_event command;

	/* Custom data for windows of a widget points back to the widget itself. */
	struct wtk_radio_button *radio_button
		= (struct wtk_radio_button *)win_get_custom_data(win);

	switch (type) {
	case WIN_EVENT_DRAW:
	{
		/* For DRAW events, the data parameter points to the
		 * clipping region.
		 */
		struct win_clip_region const *clip
			= (struct win_clip_region const *)data;

		/* There should not be other windows in this widget. */
		Assert(win == radio_button->container);

		/* Draw radio button circle. */
		gfx_draw_circle(clip->origin.x +
				WTK_RADIOBUTTON_BUTTON_X,
				clip->origin.y +
				WTK_RADIOBUTTON_BUTTON_Y,
				WTK_RADIOBUTTON_RADIUS,
				WTK_RADIOBUTTON_BUTTON_COLOR,
				GFX_WHOLE);

		/* Draw radio button filled circle background. */
		if (WTK_RADIOBUTTON_BACKGROUND_COLOR != GFX_COLOR_TRANSPARENT) {
			gfx_draw_filled_circle(clip->origin.x +
				WTK_RADIOBUTTON_BUTTON_X,
				clip->origin.y +
				WTK_RADIOBUTTON_BUTTON_Y,
				WTK_RADIOBUTTON_RADIUS - 1,
				WTK_RADIOBUTTON_BACKGROUND_COLOR,
				GFX_WHOLE);
		}	

		/* Draw radio button select marker if selected. */
		if (radio_button->group->selected == radio_button) {
			gfx_draw_filled_circle(clip->origin.x +
					WTK_RADIOBUTTON_BUTTON_X,
					clip->origin.y +
					WTK_RADIOBUTTON_BUTTON_Y,
					WTK_RADIOBUTTON_RADIUS - 2,
					WTK_RADIOBUTTON_SELECT_COLOR,
					GFX_WHOLE);
		}

		/* Draw caption. */
		gfx_draw_string(radio_button->caption,
				clip->origin.x +
				WTK_RADIOBUTTON_CAPTION_X,
				clip->origin.y +
				WTK_RADIOBUTTON_CAPTION_Y, &sysfont,
				GFX_COLOR_TRANSPARENT,
				WTK_RADIOBUTTON_CAPTION_COLOR);

		/* Always accept DRAW events, as the return value is
		 * ignored anyway for that event type.
		 */
		return true;
	}

	case WIN_EVENT_POINTER:
	{
		/* There should not be other windows in this widget. */
		Assert(win == radio_button->container);

		/* For POINTER events, the data parameter points to the
		 * pointer event information.
		 */
		struct win_pointer_event const *event
			= (struct win_pointer_event const *)data;

		switch (event->type) {
		case WIN_POINTER_PRESS:

			/* When radio button pressed, grab pointer and
			 * wait for release inside widget borders.
			 * Other widgets won't get pointer events
			 * before it is released, and the pointer
			 * ungrabbed by us.
			 */
			if (radio_button->state ==
					WTK_RADIOBUTTON_NORMAL) {
				win_grab_pointer(radio_button->
						container);
				radio_button->state
					= WTK_RADIOBUTTON_PRESSED;
				win_redraw(radio_button->container);
			}

			break;

		case WIN_POINTER_RELEASE:

			/* When button released, take action only if
			 * released inside widget extents.
			 */
			if (radio_button->state ==
					WTK_RADIOBUTTON_PRESSED) {
				bool is_inside;

				/* Ungrab pointer. */
				win_grab_pointer(NULL);
				radio_button->state
					= WTK_RADIOBUTTON_NORMAL;
				win_redraw(radio_button->container);

				/* Check release position. */
				is_inside = win_is_inside_window
							(radio_button->
							container,
							&(event->pos));

				/* Select this radio button if inside. */
				if (is_inside) {
					wtk_radio_button_select
						(radio_button);

					/* Send non-zero command. */
					if (radio_button->command) {
						command.sender
							= radio_button->
								container;
						command.recipient
							= radio_button->
								container;
						command.data
							= radio_button->command;
						win_queue_command_event
							(&command);
					}
				}
			}

			break;

		default:
			break;
		}

		/* Accept all POINTER events since all acitivity inside
		 * the widget extents is relevant to us.
		 */
		return true;
	}

	case WIN_EVENT_DESTROY:
		/* There should not be other windows in this widget. */
		Assert(win == radio_button->container);

		/* Memory allocated for windows will be automatically destroyed
		 * by the window system. We must destroy other allocations.
		 */
		membag_free(radio_button->caption);

		/* Destroy radio group as well if we are the last one in the
		 * group. If not, remove ourselves from the group.
		 */
		--(radio_button->group->num_references);
		if (!radio_button->group->num_references) {
			membag_free(radio_button->group);
		} else {
			if (radio_button->group->selected == radio_button) {
				radio_button->group->selected = NULL;
			}
		}

		membag_free(radio_button);

		/* Always accept DESTROY events, as the return value is ignored
		 * anyway for that event type.
		 */
		return true;

	default:
		/* Reject unknown event types. */
		return false;
	}
}
Ejemplo n.º 5
0
/**
 * This function is the window event handler for icon button widgets.
 * It handles all events sent to the windows composing the widget.
 *
 * \param win Window receiving the event.
 * \param type The event type.
 * \param data Custom data, depending on event type.
 *
 * \return True if the event was recognized and accepted.
 */
static bool wtk_icon_button_handler(struct win_window *win,
		enum win_event_type type, void const *data)
{
	struct win_command_event command;

	/* Custom data for windows of a widget points back to the widget itself. */
	struct wtk_icon_button *icon_button
		= (struct wtk_icon_button *)win_get_custom_data(win);

	switch (type) {
	case WIN_EVENT_DRAW:
	{
		/* For DRAW events, the data parameter points to the
		 * clipping region.
		 */
		struct win_clip_region const *clip
			= (struct win_clip_region const *)data;
		struct win_area const *area = win_get_area(win);

		/* There should not be other windows in this widget. */
		Assert(win == icon_button->container);

		/* Draw icon button select marker if selected. */
		if (icon_button->group->selected == icon_button) {
			gfx_draw_rect(clip->origin.x, clip->origin.y,
					area->size.x, area->size.y,
					WTK_ICONBUTTON_SELECT_COLOR);
		}

		/* Always accept DRAW events, as the return value is
		 * ignored anyway for that event type.
		 */
		return true;
	}

	case WIN_EVENT_POINTER:
	{
		/* There should not be other windows in this widget. */
		Assert(win == icon_button->container);

		/* For POINTER events, the data parameter points to the
		 * pointer event information.
		 */
		struct win_pointer_event const *event
			= (struct win_pointer_event const *)data;

		switch (event->type) {
		case WIN_POINTER_PRESS:

			/* When icon button pressed, grab pointer and
			 * wait for release inside widget borders.
			 * Other widgets won't get pointer events
			 * before it is released, and the pointer
			 * ungrabbed by us.
			 */
			if (icon_button->state ==
					WTK_ICONBUTTON_NORMAL) {
				win_grab_pointer(icon_button->container);
				icon_button->state
					= WTK_ICONBUTTON_PRESSED;
				win_redraw(icon_button->container);
			}

			break;

		case WIN_POINTER_RELEASE:

			/* When button released, take action only if
			 * released inside widget extents.
			 */
			if (icon_button->state ==
					WTK_ICONBUTTON_PRESSED) {
				bool is_inside;

				/* Ungrab pointer. */
				win_grab_pointer(NULL);
				icon_button->state
					= WTK_ICONBUTTON_NORMAL;
				win_redraw(icon_button->container);

				/* Check release position. */
				is_inside = win_is_inside_window
							(icon_button->
							container,
							&(event->pos));

				/* Select this icon button if inside. */
				if (is_inside) {
					wtk_icon_button_select
						(icon_button);

					/* Send non-zero command. */
					if (icon_button->command) {
						command.sender
							= icon_button->
								container;
						command.recipient
							= icon_button->
								container;
						command.data
							= icon_button->command;
						win_queue_command_event
							(&command);
					}
				}
			}

			break;

		default:
			break;
		}

		/* Accept all POINTER events since all activity inside
		 * the widget extents is relevant to us.
		 */
		return true;
	}

	case WIN_EVENT_DESTROY:
		/* There should not be other windows in this widget. */
		Assert(win == icon_button->container);

		/* Destroy icon group as well if we are the last one in the
		 * group. If not, remove ourselves from the group.
		 */
		--(icon_button->group->num_references);
		if (!icon_button->group->num_references) {
			membag_free(icon_button->group);
		} else {
			if (icon_button->group->selected == icon_button) {
				icon_button->group->selected = NULL;
			}
		}

		membag_free(icon_button);

		/* Always accept DESTROY events, as the return value is ignored
		 * anyway for that event type.
		 */
		return true;

	default:
		/* Reject unknown event types. */
		return false;
	}
}
Ejemplo n.º 6
0
/**
 * This function is the window event handler for button widgets.
 * It handles all events sent to the windows composing the widget.
 *
 * \param win Window receiving the event.
 * \param type The event type.
 * \param data Custom data, depending on event type.
 *
 * \return True if the event was recognized and accepted.
 */
static bool wtk_button_handler(struct win_window *win,
		enum win_event_type type, void const *data)
{
	/* Custom data for windows of a widget points back to the widget itself. */
	struct wtk_button *button
		= (struct wtk_button *)win_get_custom_data(win);

	switch (type) {
	case WIN_EVENT_DRAW:
	{
		/* For DRAW events, the data parameter points to the
		 * clipping region. */
		struct win_clip_region const *clip
			= (struct win_clip_region const *)data;
		struct win_area const *area = win_get_area(win);

		/* Preare background and caption colors depending on state of
		 * button. If pressed/highlighted, the colors are inverted. */
		gfx_color_t background_color;
		gfx_color_t caption_color;

		/* There should not be other windows in this widget. */
		Assert(win == button->container);

		switch (button->state) {
		case WTK_BUTTON_NORMAL:
			background_color = WTK_BUTTON_BACKGROUND_COLOR;
			caption_color = WTK_BUTTON_CAPTION_COLOR;
			break;

		case WTK_BUTTON_PRESSED:
			background_color = WTK_BUTTON_CAPTION_COLOR;
			caption_color = WTK_BUTTON_BACKGROUND_COLOR;
			break;

		default:
			Assert(false);
			background_color = WTK_BUTTON_BACKGROUND_COLOR;
			caption_color = WTK_BUTTON_CAPTION_COLOR;
		}

		/* Draw background. */
		gfx_draw_filled_rect(clip->origin.x, clip->origin.y,
				area->size.x, area->size.y,
				background_color);

		/* Draw border. */
		gfx_draw_rect(clip->origin.x, clip->origin.y,
				area->size.x, area->size.y,
				WTK_BUTTON_BORDER_COLOR);

		/* Draw caption. */
		gfx_draw_string_aligned(button->caption,
				clip->origin.x + (area->size.x / 2),
				clip->origin.y + (area->size.y / 2),
				&sysfont, GFX_COLOR_TRANSPARENT, caption_color,
				TEXT_POS_CENTER, TEXT_ALIGN_CENTER);

		/* Always accept DRAW events, as the return value is
		 * ignored anyway for that event type.
		 */
		return true;
	}

	case WIN_EVENT_POINTER:
	{
		/* There should not be other windows in this widget. */
		Assert(win == button->container);

		/* For POINTER events, the data parameter points to the
		 * pointer event information.
		 */
		struct win_pointer_event const *event
			= (struct win_pointer_event const *)data;

		switch (event->type) {
		case WIN_POINTER_PRESS:

			/* When button pressed, grab pointer and wait
			 * for release inside button borders. Other
			 * widgets won't get pointer events before it
			 * is released, and the pointer ungrabbed by
			 * us.
			 */
			if (button->state == WTK_BUTTON_NORMAL) {
				win_grab_pointer(button->container);
				button->state = WTK_BUTTON_PRESSED;
				win_redraw(button->container);
			}

			break;

		case WIN_POINTER_RELEASE:

			/* When button released, take action only if
			 * released inside widget extents.
			 */
			if (button->state == WTK_BUTTON_PRESSED) {
				/* Ungrab pointer. */
				win_grab_pointer(NULL);
				button->state = WTK_BUTTON_NORMAL;
				win_redraw(button->container);

				/* Check release position. */
				bool isInside = win_is_inside_window
							(button->container,
							&(event->pos));

				/* Send command event if inside. */
				if (isInside) {
					struct win_command_event
							command;
					command.sender = button->
							container;
					command.recipient
						= button->
							container;
					command.data = button->
							command;
					win_queue_command_event
						(&command);
				}
			}

			break;

		default:
			break;
		}

		/* Accept all POINTER events since all acitivity inside
		 * the widget extents is relevant to us.
		 */
		return true;
	}

	case WIN_EVENT_DESTROY:
	{
		/* There should not be other windows in this widget. */
		Assert(win == button->container);

		/* Memory allocated for windows will be automatically
		 * destroyed by the window system. We must destroy
		 * other allocations.
		 */
		membag_free(button->caption);
		membag_free(button);

		/* Always accept DESTROY events, as the return value is
		 * ignored anyway for that event type.
		 */
		return true;
	}

	default:
		/* Reject unknown event types. */
		return false;
	}
}