/**
 * \brief Launch the water tank application.
 *
 * This function allocates memory, creates the application frame and widgets,
 * initializes the timer and initiates loading of the required bitmaps.
 *
 * One basic frame is created, along with four widgets: one slider, two progress
 * bars and a command button. These are not shown until the background image has
 * been loaded.
 *
 * If the alarm light bitmaps have already been loaded, i.e., the application
 * has already been run, the application will skip directly to loading of the
 * background image.
 *
 * If memory for the application context cannot be allocated or the frame or
 * widgets cannot be created, the application will exit immediately.
 *
 * \param task Workqueue task to use for the application's worker functions.
 */
void app_tank_launch(struct workqueue_task *task)
{
	struct win_attributes    attr;
	struct win_window        *win;
	struct gfx_bitmap        bitmap;
	struct wtk_basic_frame   *frame;
	struct wtk_slider        *slider;
	struct wtk_button        *button;
	struct wtk_progress_bar  *pbar;
	struct timer             *timer;
	timer_res_t              timer_res;
	uint32_t                 timer_clk;

	assert(task);

	// Clear the screen right away.
#ifdef CONFIG_GFX_USE_CLIPPING
	gfx_set_clipping(0, 0, gfx_get_width(), gfx_get_height());
#endif /* CONFIG_GFX_USE_CLIPPING */
	gfx_draw_filled_rect(0, 0, gfx_get_width(), gfx_get_height(),
			COLOR_WIN_BACKGROUND);

	// Allocate the application context first.
	tank_ctx = membag_alloc(sizeof(struct tank_context));
	if (!tank_ctx)
		goto exit_no_context;

	// Use larger sysfont for this app.
	memcpy(&tank_ctx->old_sysfont, &sysfont, sizeof(struct font));
	sysfont.scale = 2;

	// Create a basic frame to contain the widgets.
	attr.area.pos.x = 0;
	attr.area.pos.y = 0;
	attr.area.size.x = gfx_get_width();
	attr.area.size.y = gfx_get_height();

	frame = wtk_basic_frame_create(win_get_root(), &attr.area, NULL,
			NULL, tank_frame_handler, NULL);
	if (!frame) {
		goto exit_no_frame;
	}
	tank_ctx->frame = frame;

	// Get the frame's window to use as parent for widgets.
	win = wtk_basic_frame_as_child(frame);

	// Initialize the application timer.
	timer = &tank_ctx->timer;
	timer_init(CONFIG_TIMER_ID, timer, tank_timer_callback);
	timer_res = timer_set_resolution(CONFIG_TIMER_ID, timer,
			TICK_RATE);
	timer_write_resolution(CONFIG_TIMER_ID, timer, timer_res);

	// Get the timer alarm delay to use for the configured tick rate.
	timer_clk = timer_get_resolution(CONFIG_TIMER_ID, timer, timer_res);
	tank_ctx->timer_delay = timer_clk / TICK_RATE;

	// Initialize random variable and tick count.
	tank_ctx->rand = 1;
	tank_ctx->rand_ticks = TICKS_PER_RANDOM_UPDATE;

	// Create the supply slider.
	attr.area.pos.x = WIDGET_SUPPLY_POSITION_X;
	attr.area.pos.y = WIDGET_SUPPLY_POSITION_Y;
	attr.area.size.x = WIDGET_SUPPLY_SIZE_X;
	attr.area.size.y = WIDGET_SUPPLY_SIZE_Y;

	slider = wtk_slider_create(win, &attr.area, VALUE_SUPPLY_MAXIMUM,
			VALUE_SUPPLY_INITIAL, WTK_SLIDER_VERTICAL |
					WTK_SLIDER_INVERT, CMD_NONE);
	if (!slider) {
		goto exit_no_widget;
	}
	tank_ctx->supply = slider;
	win_show(wtk_slider_as_child(slider));

	// Create the tank level progress bar.
	attr.area.pos.x = WIDGET_LEVEL_POSITION_X;
	attr.area.pos.y = WIDGET_LEVEL_POSITION_Y;
	attr.area.size.x = WIDGET_LEVEL_SIZE_X;
	attr.area.size.y = WIDGET_LEVEL_SIZE_Y;

	pbar = wtk_progress_bar_create(win, &attr.area, VALUE_LEVEL_MAXIMUM,
			VALUE_LEVEL_INITIAL, COLOR_LEVEL_FILL,
			COLOR_LEVEL_BACKGROUND, WTK_PROGRESS_BAR_VERTICAL |
					WTK_PROGRESS_BAR_INVERT);
	if (!pbar) {
		goto exit_no_widget;
	}
	tank_ctx->level = pbar;
	win_show(wtk_progress_bar_as_child(pbar));

	// Create the demand progress bar.
	attr.area.pos.x = WIDGET_DEMAND_POSITION_X;
	attr.area.pos.y = WIDGET_DEMAND_POSITION_Y;
	attr.area.size.x = WIDGET_DEMAND_SIZE_X;
	attr.area.size.y = WIDGET_DEMAND_SIZE_Y;

	pbar = wtk_progress_bar_create(win, &attr.area, VALUE_DEMAND_MAXIMUM,
			VALUE_DEMAND_INITIAL, COLOR_DEMAND_NORMAL,
			COLOR_DEMAND_BACKGROUND, WTK_PROGRESS_BAR_VERTICAL |
					WTK_PROGRESS_BAR_INVERT);
	if (!pbar) {
		goto exit_no_widget;
	}
	tank_ctx->demand = pbar;
	win_show(wtk_progress_bar_as_child(pbar));

	// Create the exit button with the standard settings.
	attr.area.pos.x = APP_EXIT_BUTTON_POS_X;
	attr.area.pos.y = APP_EXIT_BUTTON_POS_Y;
	attr.area.size.x = APP_EXIT_BUTTON_SIZE_X;
	attr.area.size.y = APP_EXIT_BUTTON_SIZE_Y;

	button = wtk_button_create(win, &attr.area, APP_EXIT_BUTTON_TEXT,
			(win_command_t)CMD_EXIT);
	if (!button) {
		goto exit_no_widget;
	}
	win_show(wtk_button_as_child(button));

	// Set the tank alarm to trigger initial drawing of alarm light.
	tank_ctx->level_alarm = true;
	tank_ctx->flow_alarm = false;
	tank_ctx->task = task;

	/* Initialize bitmap data and set initial application loader state:
	 * If the alarm light bitmaps have already been loaded, skip right to
	 * loading of the application background bitmap.
	 */
	bitmap.width = BITMAP_LIGHT_SIZE_X;
	bitmap.height = BITMAP_LIGHT_SIZE_Y;
	bitmap.type = BITMAP_HUGEMEM;
	tank_ctx->bitmaps[BITMAP_RED_LIGHT] = bitmap;
	tank_ctx->bitmaps[BITMAP_GREEN_LIGHT] = bitmap;

	if (tank_bitmap_data[BITMAP_GREEN_LIGHT]) {
		tank_ctx->loader_state = LOAD_BACKGROUND;
		tank_ctx->bitmaps[BITMAP_RED_LIGHT].data.hugemem =
				tank_bitmap_data[BITMAP_RED_LIGHT];
		tank_ctx->bitmaps[BITMAP_GREEN_LIGHT].data.hugemem =
				tank_bitmap_data[BITMAP_GREEN_LIGHT];
	} else {
		tank_ctx->loader_state = LOAD_RED_LIGHT;
	}
	workqueue_task_set_work_func(task, tank_loader);
	workqueue_add_task(&main_workqueue, task);
	return;

	// Handle allocation errors.
exit_no_widget:
	win_destroy(wtk_basic_frame_as_child(tank_ctx->frame));
exit_no_frame:
	memcpy(&sysfont, &tank_ctx->old_sysfont, sizeof(struct font));
	membag_free(tank_ctx);
exit_no_context:
	app_desktop_restart();
	return;
}
Beispiel #2
0
/**
 * \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 #3
0
/**
 * \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_button *button;

	/* 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->frame_bg.type = GFX_BITMAP_SOLID;
	widget_ctx->frame_bg.data.color = GFX_COLOR(220, 220, 220);

	/* 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);

	/* Set the background information for the plot widget */
	widget_ctx->plot_bg.type = GFX_BITMAP_SOLID;
	widget_ctx->plot_bg.data.color = GFX_COLOR_WHITE;

	/* Adjust area for the plot widget */
	area.size.y -= 80;
	area.size.x -= 40;

	/* Create and show the plot widget with vertical axis marks */
	widget_ctx->plot = wtk_plot_create(parent, &area, 100, 10, GFX_COLOR_RED,
			&widget_ctx->plot_bg, WTK_PLOT_LEFT_TO_RIGHT);
	if (!widget_ctx->plot) {
		goto error_widget;
	}
	wtk_plot_set_grid(widget_ctx->plot, WTK_PLOT_TICKS_VERTICAL,
			10, 0, 10, 0, GFX_COLOR_BLUE, GFX_COLOR_GREEN);
	win_show(wtk_plot_as_child(widget_ctx->plot));
	
	/* Adjust area for the slider widget */
	area.pos.y += area.size.y + 10;
	area.size.y = 40;
	area.size.x -= 60;
	
	/* Create and show the slider widget */
	widget_ctx->slider = wtk_slider_create(parent, &area, 100, 0,
			WTK_SLIDER_HORIZONTAL, (win_command_t)SLIDER_ID);	
	if (!widget_ctx->slider) {
		goto error_widget;
	}
	win_show(wtk_slider_as_child(widget_ctx->slider));	
	
	/* Adjust area for the button widget */
	area.pos.x += area.size.x + 10;
	area.size.x = 50;
	
	/* Create and show the button widget */
	button = wtk_button_create(parent, &area, "Add", (win_command_t)BUTTON_ID);	
	if (!button) {
		goto error_widget;
	}
	win_show(wtk_button_as_child(button));

	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;
}
/**
 * \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) {
	}
}