/**
 * \brief Setup widget demo
 *
 * Allocates memory for the application context, and creates all widgets that
 * make up its interface. If memory allocation or widget creation fails, the
 * application exits immediately.
 *
 * \return Boolean true if the application was launched successfully, false if
 *         a memory allocation occurred.
 */
bool app_widget_launch(void)
{
	struct win_window *parent;
	struct win_area area;
	struct wtk_check_box *cb;
	struct wtk_radio_group *rg;
	struct wtk_radio_button *rb;
	struct wtk_button *btn;

	/* Create a new context for the GUI */
	widget_ctx = membag_alloc(sizeof(struct widget_context));
	if (!widget_ctx) {
		return false;
	}

	/* Initialize context data. */
	widget_ctx->color_scheme = 0;
	widget_ctx->color_invert = 0;

	/* Set the background information for the GUI window */
	widget_ctx->frame_bg.type = GFX_BITMAP_SOLID;
	widget_ctx->frame_bg.data.color = APP_BACKGROUND_COLOR;

	/* Set the area for the GUI window */
	area = win_get_attributes(win_get_root())->area;
	win_inflate_area(&area, -20);

	/* Create and show the main GUI frame */
	widget_ctx->frame = wtk_basic_frame_create(
			win_get_root(), &area, &widget_ctx->frame_bg, NULL,
			widget_frame_command_handler, widget_ctx);

	if (!widget_ctx->frame) {
		goto error_frame;
	}
	parent = wtk_basic_frame_as_child(widget_ctx->frame);
	win_show(parent);

	/* Update area for the slider widget */
	area.pos.x = WIDGET_POS_X;
	area.pos.y = WIDGET_POS_Y + SLIDER_POS_Y;
	area.size.x = SLIDER_SIZE_X;
	area.size.y = SLIDER_SIZE_Y;

	/* Create slider inside frame */
	widget_ctx->slider = wtk_slider_create(parent, &area, 100, 50,
			WTK_SLIDER_HORIZONTAL | WTK_SLIDER_CMD_MOVE | WTK_SLIDER_CMD_RELEASE,
			(win_command_t)SLIDER_ID);

	if (!widget_ctx->slider) {
		goto error_widget;
	}
	win_show(wtk_slider_as_child(widget_ctx->slider));

	/* Update area for the progress bar widget */
	area.pos.x += area.size.x + SLIDER_PB_SPACING_X;
	area.size.x = PB_SIZE_X;
	area.size.y = PB_SIZE_Y;

	/* Create progress bar to the right of the slider */
	widget_ctx->pb = wtk_progress_bar_create(parent, &area, 100,
			50, GFX_COLOR_BLACK, GFX_COLOR_BLACK, WTK_PROGRESS_BAR_HORIZONTAL);

	if (!widget_ctx->pb) {
		goto error_widget;
	}
	win_show(wtk_progress_bar_as_child(widget_ctx->pb));
	app_widget_update_colors(widget_ctx);

	/* Update area for the checkbox widget */
	area.pos.x = WIDGET_POS_X;
	area.pos.y += area.size.y + CHECK_BOX_SPACING_Y;
	wtk_check_box_size_hint(&area.size, checkbox_string);

	/* Create check box below slider and progress bar */
	cb = wtk_check_box_create(parent, &area, checkbox_string,
			false, (win_command_t)CHECK_BOX_ID);

	if (!cb) {
		goto error_widget;
	}
	win_show(wtk_check_box_as_child(cb));

	/* Create a logical group for the radio buttons */
	rg = wtk_radio_group_create();
	if (!rg) {
		goto error_widget;
	}

	/* Update area for the first radio button widget */
	area.pos.y += area.size.y + RADIO_BUTTON_SPACING_Y;
	wtk_radio_button_size_hint(&area.size, rb1_string);

	/* Create first radio button widget */
	rb = wtk_radio_button_create(parent, &area, rb1_string,
			true, rg, (win_command_t)RADIO_BUTTON_1_ID);

	if (!rb) {
		goto error_widget;
	}
	win_show(wtk_radio_button_as_child(rb));

	/* Update area for the second radio button widget */
	area.pos.y += area.size.y + RADIO_BUTTON_SPACING_Y;
	wtk_radio_button_size_hint(&area.size, rb2_string);

	/* Create second radio button widget */
	rb = wtk_radio_button_create(parent, &area, rb2_string,
			false, rg, (win_command_t)RADIO_BUTTON_2_ID);

	if (!rb) {
		goto error_widget;
	}
	win_show(wtk_radio_button_as_child(rb));

	/* Update area for the button widget */
	area.pos.y += area.size.y + BUTTON_SPACING_Y;
	area.size.x = SLIDER_SIZE_X + SLIDER_PB_SPACING_X + PB_SIZE_X;
	area.size.y = BUTTON_SIZE_Y;

	/* Create button widget */
	btn = wtk_button_create(parent, &area, btn_string, (win_command_t)BUTTON_ID);
	wtk_button_size_hint(&area.size, btn_string);

	if (!btn) {
		goto error_widget;
	}
	win_show(wtk_button_as_child(btn));

	return true;

	/* Error handling to clean up allocations after an error */
error_widget:
	win_destroy(wtk_basic_frame_as_child(widget_ctx->frame));
error_frame:
	membag_free(widget_ctx);
	
	return false;
}
Beispiel #2
0
int main( int argc, char* argv[] )
{
	if( fs_init() )
		return 1;
	win_initialize( argc, argv );
	g_RS = rsl_create();
	g_RS.change_cb = runner_change_callback;
	g_winActCb = runner_action_callback;
	
	rsl_compile( &g_RS, g_scriptData, NULL );
	X_DBG( rsl_dump( &g_RS ) );
	
#if 0
	///////////////////////////////////////////////////
//	win_set_title( "Testā rešpekt" );
//	win_set_background_color( 120, 150, 180 );
//	win_set_background_image( 0 );
	
	win_ctl_resize( 2 );
	
	g_controls[0].type = WCTL_BUTTON;
	g_controls[0].x1 = 100;
	g_controls[0].y1 = 100;
	g_controls[0].x2 = 300;
	g_controls[0].y2 = 140;
	byte colors[ 24 ] =
	{
		50, 50, 50, 1,
		50, 50, 50, 1,
		50, 50, 50, 1,
		200, 200, 200, 1,
		220, 220, 220, 1,
		180, 180, 180, 1,
	};
	memcpy( g_controls[0].fgColorN, colors, 24 );
	strcpy( g_controls[0].text, "Spēlēt" );
	win_ctl_updated( 0, WCU_EVERYTHING );
	
	g_controls[1].type = WCTL_BUTTON;
	g_controls[1].x1 = 100;
	g_controls[1].y1 = 200;
	g_controls[1].x2 = 300;
	g_controls[1].y2 = 240;
	byte colors2[ 24 ] =
	{
		50, 30, 30, 1,
		60, 40, 40, 1,
		70, 50, 50, 1,
		190, 190, 210, 1,
		210, 210, 230, 1,
		170, 170, 190, 1,
	};
	memcpy( g_controls[1].fgColorN, colors2, 24 );
	strcpy( g_controls[1].text, "Instalēt" );
	win_ctl_updated( 1, WCU_EVERYTHING );
	///////////////////////////////////////////////////
#endif
	
	vl_set( &g_RS.varlist, strlitlen( "_action" ), strlitlen( "init" ) );
	rsl_run( &g_RS );
	vl_set( &g_RS.varlist, strlitlen( "_action" ), strlitlen( "" ) );
	runner_apply_changes();
	
	while( win_process( 0 ) );
	
	rsl_destroy( &g_RS );
	fs_free();
	win_destroy();
	return 0;
}
Beispiel #3
0
/**
 * This function is the window event handler for frame 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_frame_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_frame *frame = (struct wtk_frame *)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);

		/* Draw frame decorations if this is the container window. */
		if (win == frame->container) {
			/* Draw left border. */
			gfx_draw_filled_rect(clip->origin.x,
					clip->origin.y,
					WTK_FRAME_LEFTBORDER,
					area->size.y,
					WTK_FRAME_BORDER_COLOR);

			/* Draw right border. */
			gfx_draw_filled_rect(clip->origin.x +
					area->size.x -
					WTK_FRAME_RIGHTBORDER,
					clip->origin.y,
					WTK_FRAME_RIGHTBORDER,
					area->size.y,
					WTK_FRAME_BORDER_COLOR);

			/* Draw top border. */
			gfx_draw_filled_rect(clip->origin.x +
					WTK_FRAME_LEFTBORDER,
					clip->origin.y,
					area->size.x -
					WTK_FRAME_LEFTBORDER -
					WTK_FRAME_RIGHTBORDER,
					WTK_FRAME_TOPBORDER,
					WTK_FRAME_BORDER_COLOR);

			/* Draw bottom border. */
			gfx_draw_filled_rect(clip->origin.x +
					WTK_FRAME_LEFTBORDER,
					clip->origin.y + area->size.y -
					WTK_FRAME_BOTTOMBORDER,
					area->size.x -
					WTK_FRAME_LEFTBORDER -
					WTK_FRAME_RIGHTBORDER,
					WTK_FRAME_BOTTOMBORDER,
					WTK_FRAME_BORDER_COLOR);

			/* Draw title bar background. */
			gfx_draw_filled_rect(clip->origin.x +
					WTK_FRAME_LEFTBORDER,
					clip->origin.y +
					WTK_FRAME_TOPBORDER,
					area->size.x -
					WTK_FRAME_LEFTBORDER -
					WTK_FRAME_RIGHTBORDER,
					WTK_FRAME_TITLEBAR_HEIGHT,
					WTK_FRAME_TITLEBAR_COLOR);

			/* Draw caption string. */
			gfx_draw_string(frame->caption,
					clip->origin.x +
					WTK_FRAME_LEFTBORDER +
					WTK_FRAME_CAPTION_X,
					clip->origin.y +
					WTK_FRAME_TOPBORDER +
					WTK_FRAME_CAPTION_Y, &sysfont,
					GFX_COLOR_TRANSPARENT,
					WTK_FRAME_CAPTION_COLOR);
		}
		/* Draw resize handle if this is the resize window. */
		else if (win == frame->resize) {
			gfx_draw_filled_circle(clip->origin.x +
					area->size.x - 1,
					clip->origin.y + area->size.y -
					1, WTK_FRAME_RESIZE_RADIUS,
					WTK_FRAME_RESIZE_COLOR,
					GFX_QUADRANT1);
		}

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

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

		/* Handle move if this is the container window. */
		if (win == frame->container) {
			switch (event->type) {
			case WIN_POINTER_PRESS:
				wtk_handle_frame_press(frame, event);
				break;

			case WIN_POINTER_MOVE:
				wtk_handle_frame_move(frame, event);
				break;

			case WIN_POINTER_RELEASE:
				wtk_handle_frame_release(frame, event);
				break;

			default:
				break;
			}
		}
		/* Handle resize if this is the resize handle. */
		else if (win == frame->resize) {
			switch (event->type) {
			case WIN_POINTER_PRESS:
				wtk_handle_resize_press(frame, event);
				break;

			case WIN_POINTER_MOVE:
				wtk_handle_resize_move(frame, event);
				break;

			case WIN_POINTER_RELEASE:
				wtk_handle_resize_release(frame, event);
				break;

			default:
				break;
			}
		}

		/* Accept all POINTER events so that it does not
		 * propagate up the window tree to our parent in case
		 * we did not click anything useful inside the frame.
		 */
		return true;
	}

	case WIN_EVENT_DESTROY:
	{
		/* When the container window is destroyed, also destroy
		 * the rest of the non-window frame allocations.
		 */
		if (win == frame->container) {
			/* Memory allocated for windows will be
			 * automatically destroyed by the window
			 * system. We must destroy other allocations.
			 */
			membag_free(frame->caption);
			membag_free(frame);
		}

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

	case WIN_EVENT_COMMAND:
	{
		/* When commands are received either directly or
		 * propagated from child widgets and windows, send it
		 * to the frame handler.
		 */
		if (win == frame->container) {
			if (frame->frame_handler) {
				/* If the frame handler returns true,
				 * it wants us to destroy the frame.
				 * This is normally used by CLOSE
				 * buttons.
				 */
				bool shouldDestroy
					= frame->frame_handler(frame,
						(win_command_t)
						data);

				/* It is safe to destroy it here, since
				 * the event handling finished right
				 * after this handler returns, and no
				 * other references to this frame or
				 * its contents will be done.
				 */
				if (shouldDestroy) {
					win_destroy(frame->container);
				}

				/* Accept the event if there was a
				 * handler installed.
				 */
				return true;
			}
		}

		/* Reject the event if there was no handler, or this
		 * was not the container window at all.
		 */
		return false;
	}

	default:
		/* Reject unknown event types. */
		return false;
	}
}
Beispiel #4
0
/**
 * This function creates a new frame widget. It allocates required memory and
 * intializes necessary windows to create the widget. If there is not enough
 * memory, the function returns NULL.
 *
 * To destroy the widget and all its contents, and free its memory, call
 * win_destroy() on the frame's child reference, given by wtk_frame_as_child(),
 * like this: "win_destroy(wtk_frame_as_child(my_frame_ptr));".
 * The frame's internal area will equal the area parameter, but the total
 * extents will be slightly larger, to accommodate for titlebar, borders etc.
 *
 * \param parent Parent window.
 * \param area Area of the internal contents.
 * \param caption Pointer to caption string. Will be copied into widget.
 * \param allow_resize True if resize handle should be included on the frame.
 * \param frame_handler Optional command event handler, for applications.
 * \param custom_data Optional custom data link, for applications.
 *
 * \return Pointer to frame, or NULL if failed.
 */
struct wtk_frame *wtk_frame_create(struct win_window *parent,
		struct win_area const *area,
		char const *caption,
		bool allow_resize,
		wtk_frame_handler_t frame_handler, void *custom_data)
{
	struct win_attributes attr;
	struct wtk_frame *frame;

	Assert(area);
	Assert(caption);
	Assert(parent);

	/* Allocate memory for frame control data. */
	frame = membag_alloc(sizeof(struct wtk_frame));
	if (!frame) {
		goto outofmem_frame;
	}

	frame->state = WTK_FRAME_NORMAL;
	frame->frame_handler = frame_handler;
	frame->custom_data = custom_data;

	/* Allocate memory for caption string, and copy text. */
	frame->caption = membag_alloc((strlen(caption) + 1) * sizeof(char));
	if (!frame->caption) {
		goto outofmem_caption;
	}

	wtk_copy_string(frame->caption, caption);

	/* Start with valid area info, but only contents frame will keep the
	 * original area. The other frames will be resized properly at the end.
	 * All windows have the same event handler, and the same link back to
	 * the widget object.
	 */
	attr.area = *area;
	attr.event_handler = wtk_frame_handler;
	attr.custom = frame;

	/* Prepare container frame, which will contain title bar, border, size,
	 * handle etc.
	 */
	attr.background = NULL;
	attr.behavior = WIN_BEHAVIOR_RAISE_ON_PRESS;

	/* Create the container window, the proper size will be set later. */
	frame->container = win_create(parent, &attr);
	if (!frame->container) {
		goto outofmem_container;
	}

	/* Prepare the contents frame, which will contain whatever controls
	 * owned by the frame. Size will be equal to the given area parameter.
	 */
	attr.area.pos.x = WTK_FRAME_LEFTBORDER;
	attr.area.pos.y = WTK_FRAME_TOPBORDER + WTK_FRAME_TITLEBAR_HEIGHT;
	attr.background = &wtk_frame_background;
	attr.behavior = 0;

	frame->contents = win_create(frame->container, &attr);
	if (!frame->contents) {
		goto outofmem_contents;
	}

	/* Only create resize handle window if resize is allowed. */
	if (allow_resize) {
		/* Prepare resize handle. Proper position will be set later.
		 * Size is set here, though.
		 */
		attr.area.size.x = WTK_FRAME_RESIZE_WIDTH;
		attr.area.size.y = WTK_FRAME_RESIZE_HEIGHT;
		attr.background = NULL;
		attr.behavior = 0;

		frame->resize = win_create(frame->container, &attr);
		if (!frame->resize) {
			goto outofmem_resize;
		}

		win_show(frame->resize);
	} else {
		frame->resize = NULL;
	}

	/* Now, resize and rearrange according to size of contents frame, which
	 * is equal to the given area parameter.
	 */
	wtk_resize_frame(frame, area);

	/* Make sure internals are visible when frame is mapped. */
	win_show(frame->contents);

	return frame;

outofmem_resize:
	win_destroy(frame->contents);

outofmem_contents:
	win_destroy(frame->container);

outofmem_container:
	membag_free(frame->caption);

outofmem_caption:
	membag_free(frame);

outofmem_frame:
	return NULL;
}
/**
 * \brief Setup widget demo
 *
 * This function launches the widget demo.
 */
void app_widget_launch()
{
	struct win_window *win_root;
	struct win_window *parent;
	struct win_area area;
	struct wtk_label *lbl;
	struct wtk_button *btn;

	/* Get pointer to root window */
	win_root = win_get_root();

	/* Application frame */

	/* Create a background bitmap using a solid color. */
	frame_background.type = GFX_BITMAP_SOLID;
	frame_background.data.color = APP_BACKGROUND_COLOR;

	/* Set the area to fill the entire screen */
	area.pos.x = 0;
	area.pos.y = 0;
	area.size.x = gfx_get_width();
	area.size.y = gfx_get_height();

	/*
	 * Create a basic frame with a specified background and command event
	 * handler. Check the return value if an error occurred while creating
	 * the widget.
	 */
	main_frame = wtk_basic_frame_create(win_root, &area,
			&frame_background, NULL,
			widget_frame_command_handler, NULL);
	if (!main_frame) {
		goto error_frame;
	}

	/* Get a pointer to the widget's window for adding sub-widgets. */
	parent = wtk_basic_frame_as_child(main_frame);

	/*
	 * Draw the frame by showing the frame widget's window. Any
	 * child-widgets and windows will not be shown before the parent
	 * widget/window is shown.
	 */
	win_show(parent);

	/* Application label */
	area.pos.x = LABEL_POS_X;
	area.pos.y = LABEL_POS_Y;
	/* Find an optimal size for the widget. */
	wtk_label_size_hint(&area.size, demo_string);

	/*
	 * Create the label and check the return value if an error occurred
	 * while creating the label.
	 */
	lbl = wtk_label_create(parent, &area, demo_string,
			GFX_COLOR(255, 255, 255), NULL, false);
	if (!lbl) {
		goto error_widget;
	}

	/* Draw the label by showing the label widget's window. */
	win_show(wtk_label_as_child(lbl));

	/* Application slider */
	area.pos.x = SLIDER_POS_X;
	area.pos.y = SLIDER_POS_Y;
	area.size.x = SLIDER_SIZE_X;
	area.size.y = SLIDER_SIZE_Y;

	/*
	 * Create the slider and check the return value if an error occurred
	 * while creating the slider.
	 */
	slider = wtk_slider_create(parent, &area, SLIDER_MAX_VALUE,
			SLIDER_MAX_VALUE / 2,
			WTK_SLIDER_HORIZONTAL | WTK_SLIDER_CMD_RELEASE,
			(win_command_t)SLIDER_ID);
	if (!slider) {
		goto error_widget;
	}

	/* Draw the slider by showing the slider widget's window. */
	win_show(wtk_slider_as_child(slider));

	/* Application progress bar, placed right of the slider. */
	area.pos.x += area.size.x + SLIDER_PB_SPACING_X;
	area.size.x = PB_SIZE_X;
	area.size.y = PB_SIZE_Y;

	/*
	 * Create the progress bar and check the return value if an error
	 * occurred while creating the progress bar.
	 */
	progress_bar = wtk_progress_bar_create(parent, &area, SLIDER_MAX_VALUE,
			SLIDER_MAX_VALUE / 2, GFX_COLOR(255, 255, 0),
			GFX_COLOR(90, 90, 90), WTK_PROGRESS_BAR_HORIZONTAL);
	if (!progress_bar) {
		goto error_widget;
	}

	/* Draw the progress bar by showing the progress bar widget's window. */
	win_show(wtk_progress_bar_as_child(progress_bar));

	/** \todo Add code to set up button here. */

	/** \todo Add code to set up basic frame here. */

	return;

error_widget:
	/* Destroy widget and all sub-widgets. */
	win_destroy(wtk_basic_frame_as_child(main_frame));
error_frame:
	/* Wait forever if an error occurred during setup. */
	while (1) {
	}
}