Example #1
0
void ro_treeview_redraw_loop(wimp_draw *redraw, ro_treeview *tv, osbool more)
{
	os_error *error;
	struct redraw_context ctx = {
		.interactive = true,
		.background_images = true,
		.plot = &ro_plotters
	};

	while (more) {
		ro_plot_origin_x = redraw->box.x0 - redraw->xscroll;
		ro_plot_origin_y = redraw->box.y1 - redraw->yscroll;

		if (tv != NULL && tv->tree != NULL) {
			struct rect clip;
			tree_draw(tv->tree, tv->origin.x/2, -(tv->origin.y/2),
					(redraw->clip.x0
					-(ro_plot_origin_x+tv->origin.x))/2,
					((ro_plot_origin_y+tv->origin.y)
					-redraw->clip.y1)/2,
					(redraw->clip.x1 - redraw->clip.x0)/2,
					(redraw->clip.y1 - redraw->clip.y0)/2,
					&ctx);

			/* Put the graphcis window back how the Wimp set it. */
			clip.x0 = (redraw->clip.x0 - ro_plot_origin_x) / 2;
			clip.y0 = (ro_plot_origin_y - redraw->clip.y1) / 2;
			clip.x1 = (redraw->clip.x1 - ro_plot_origin_x) / 2;
			clip.y1 = (ro_plot_origin_y - redraw->clip.y0) / 2;
			ro_plotters.clip(&clip);
	 	}

		error = xwimp_get_rectangle(redraw, &more);
		if (error) {
			LOG(("xwimp_redraw_window: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}
	}
}

/**
 * Callback to notify us of a new overall tree size.
 *
 * \param  tree		The tree being resized.
 * \param  width	The new width of the window.
 * \param  height	The new height of the window.
 * \param  *pw		The treeview object to be resized.
 */

void ro_treeview_resized(struct tree *tree, int width, int height,
		void *pw)
{
	if (pw != NULL) {
		ro_treeview		*tv = (ro_treeview *) pw;

		/* Store the width and height in terms of RISC OS work area. */

		tv->size.x = width * 2;
		tv->size.y = -(height * 2);

		/* Resize the window. */

		ro_treeview_set_window_extent(tv, tv->size.x, tv->size.y);
	}
}

/**
 * Callback to request that a section of the tree is scrolled into view.
 *
 * \param  y			The Y coordinate of top of the area in NS units.
 * \param  height		The height of the area in NS units.
 * \param  *pw			The treeview object affected.
 */

void ro_treeview_scroll_visible(int y, int height, void *pw)
{
	if (pw != NULL) {
		ro_treeview		*tv = (ro_treeview *) pw;
		os_error		*error;
		wimp_window_state	state;
		int			visible_t, visible_b;
		int			request_t, request_b;

		state.w = tv->w;
		error = xwimp_get_window_state(&state);
		if (error) {
			LOG(("xwimp_get_window_state: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}

		/* Work out top and bottom of both the currently visible and
		 * the required areas, in terms of the RO work area.
		 */

		 visible_t = state.yscroll;
		 visible_b = state.yscroll
		 		- (state.visible.y1 - state.visible.y0);

		 request_t = -(2 * y);// - tv->origin.y;
		 request_b = -(2 * (y + height));// - tv->origin.y;

		 /* If the area is outside the visible window, then scroll it
		  * in to view.
		  */

		 if (request_t > visible_t || request_b < visible_b) {
		 	if (request_t > visible_t) {
		 		state.yscroll = request_t;
		 	} else if (request_b < visible_b) {
		 		state.yscroll = request_b + tv->origin.y
		 			+ (state.visible.y1 - state.visible.y0);

		 		/* If the required area is bigger than the
		 		 * visible extent, then align to the top and
		 		 * let the bottom disappear out of view.
		 		 */

		 		if (state.yscroll < request_t)
		 			state.yscroll = request_t;
		 	}

		 	error = xwimp_open_window((wimp_open *) &state);
		 	if (error) {
				LOG(("xwimp_open_window: 0x%x: %s",
						error->errnum, error->errmess));
				warn_user("WimpError", error->errmess);
				return;
			}
		}
	}
}

/**
 * Callback to return the tree window dimensions to the treeview system.
 *
 * \param  *width		Return the window width.
 * \param  *height		Return the window height.
 * \param  *pw			The treeview object to use.
 */

void ro_treeview_get_window_dimensions(int *width, int *height,
		void *pw)
{
	if (pw != NULL && (width != NULL || height != NULL)) {
		ro_treeview		*tv = (ro_treeview *) pw;
		os_error		*error;
		wimp_window_state	state;

		state.w = tv->w;
		error = xwimp_get_window_state(&state);
		if (error) {
			LOG(("xwimp_get_window_state: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}

		if (width != NULL)
			*width = (state.visible.x1 - state.visible.x0) / 2;

		if (height != NULL)
			*height = (state.visible.y1 - state.visible.y0) / 2;
	}
}

/**
 * Resize the RISC OS window extent of a treeview.
 *
 * \param  *tv			The RISC OS treeview object to resize.
 * \param  width		The new width of the work area, in RO units.
 * \param  height		The new height of the work area, in RO units.
 */

void ro_treeview_set_window_extent(ro_treeview *tv, int width, int height)
{
	if (tv != NULL) {
		os_error		*error;
		os_box			extent;
		wimp_window_state	state;
		int			new_x, new_y;
		int			visible_x, visible_y;
		int			new_x_scroll, new_y_scroll;

		/* Calculate the new window extents, in RISC OS units. */

		new_x = width + tv->origin.x;
		new_y = height + tv->origin.y;

		/* Get details of the existing window, and start to sanity
		 * check the new extents.
		 */

		state.w = tv->w;
		error = xwimp_get_window_state(&state);
		if (error) {
			LOG(("xwimp_get_window_state: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}

		/* If the extent is smaller than the current visible area,
		 * then extend it so that it matches the visible area.
		 */

		if (new_x < (state.visible.x1 - state.visible.x0))
			new_x = state.visible.x1 - state.visible.x0;

		if (new_y > (state.visible.y0 - state.visible.y1))
			new_y = state.visible.y0 - state.visible.y1;

		/* Calculate the maximum visible coordinates of the existing
		 * window.
		 */

		visible_x = state.xscroll +
				(state.visible.x1 - state.visible.x0);
		visible_y = state.yscroll +
				(state.visible.y0 - state.visible.y1);

		/* If the window is currently open, and the exising visible
		 * area is bigger than the new extent, then we need to reopen
		 * the window in an appropriare position before setting the
		 * new extent.
		 */

		if ((state.flags & wimp_WINDOW_OPEN) &&
				(visible_x > new_x || visible_y < new_y)) {
			new_x_scroll = state.xscroll;
			new_y_scroll = state.yscroll;

			if (visible_x > new_x)
				new_x_scroll = new_x - (state.visible.x1
						- state.visible.x0);

			if (visible_y < new_y)
				new_y_scroll = new_y - (state.visible.y0
						- state.visible.y1);

			if (new_x_scroll < 0) {
				state.visible.x1 -= new_x_scroll;
				state.xscroll = 0;
			} else {
				state.xscroll = new_x_scroll;
			}

			if (new_y_scroll > 0) {
				state.visible.y0 += new_y_scroll;
				state.yscroll = 0;
			} else {
				state.yscroll = new_y_scroll;
			}

			error = xwimp_open_window((wimp_open *) &state);
			if (error) {
				LOG(("xwimp_get_window_state: 0x%x: %s",
						error->errnum, error->errmess));
				warn_user("WimpError", error->errmess);
				return;
			}

			/* \todo -- Not sure if we need to reattach the
			 * toolbar here: the nested wimp seems to take care
			 * of it for us?
			 */
		}

		/* Now that the new extent fits into the visible window, we
		 * can resize the work area.  If we succeed, the values are
		 * recorded to save having to ask the Wimp for them
		 * each time.
		 */

		extent.x0 = 0;
		extent.y0 = new_y;
		extent.x1 = new_x;
		extent.y1 = 0;

		error = xwimp_set_extent(tv->w, &extent);
		if (error) {
			LOG(("xwimp_set_extent: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}

		tv->extent.x = new_x;
		tv->extent.y = new_y;
	}
}

/**
 * Handle RISC OS Window Open events for a treeview window.
 *
 * \param  *open		Pointer to the Window Open Event block.
 */

static void ro_treeview_open(wimp_open *open)
{
	ro_treeview	*tv;
	os_error	*error;
	os_box		extent;
	int		width, height;

	tv = (ro_treeview *) ro_gui_wimp_event_get_user_data(open->w);
	if (tv == NULL) {
		LOG(("NULL treeview block for window: ox%x",
				(unsigned int) open->w));
		return;
	}

	/* Calculate the window work area.  It must be at least the same as
	 * the current visible area of the window, and needs to contain the
	 * tree as defined by size.x + offset.x and size.y + offset.y (note
	 * that the offset.y should be set to cover any toolbar, so we can
	 * ignore the size of that).
	 */

	width = open->visible.x1 - open->visible.x0;
	height = open->visible.y0 - open->visible.y1;

	if (tv->size.x != 0 && width < (tv->origin.x + tv->size.x))
		width = (tv->origin.x + tv->size.x);

	if (tv->size.y != 0 && height > (tv->size.y + tv->origin.y))
		height = (tv->size.y + tv->origin.y);

	if (width != tv->extent.x || height != tv->extent.y) {
		extent.x0 = 0;
		extent.y0 = height;
		extent.x1 = width;
		extent.y1 = 0;

		error = xwimp_set_extent(tv->w, &extent);
		if (error) {
			LOG(("xwimp_set_extent: 0x%x: %s",
					error->errnum, error->errmess));
			warn_user("WimpError", error->errmess);
			return;
		}

		tv->extent.x = width;
		tv->extent.y = height;
	}

	/* \todo -- Might need to add vertical scrollbar hiding back in here? */

	error = xwimp_open_window(open);
	if (error) {
		LOG(("xwimp_open_window: 0x%x: %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}

	if (tv->tb)
		ro_toolbar_process(tv->tb, -1, false);
}
Example #2
0
void ro_gui_options_theme_load(void)
{
	os_error *error;
	os_box extent = { 0, 0, 0, 0 };
	struct theme_descriptor *descriptor;
	struct toolbar_display *link;
	struct toolbar_display *toolbar_display;
	struct toolbar *toolbar;
	wimp_icon_create new_icon;
	wimp_window_state state;
	int parent_width, nested_y, min_extent, base_extent;
	int item_height;
	int *radio_icons, *radio_set;
	int theme_count;

	/* delete our old list and get/open a new one */
	ro_gui_options_theme_free();
	theme_list = ro_gui_theme_get_available();
	ro_gui_theme_open(theme_list, true);

	/* create toolbars for each theme */
	theme_count = 0;
	descriptor = theme_list;
	while (descriptor != NULL) {
		/* try to create a toolbar */
		toolbar = ro_toolbar_create(descriptor, NULL,
				THEME_STYLE_BROWSER_TOOLBAR,
				TOOLBAR_FLAGS_DISPLAY, NULL, NULL, NULL);
		if (toolbar != NULL) {
			ro_toolbar_add_buttons(toolbar, brower_toolbar_buttons,
					       nsoption_charp(toolbar_browser));
			ro_toolbar_add_url(toolbar);
			ro_toolbar_add_throbber(toolbar);
			ro_toolbar_rebuild(toolbar);
			toolbar_display = calloc(sizeof(struct toolbar_display), 1);
			if (!toolbar_display) {
				LOG(("No memory for calloc()"));
				warn_user("NoMemory", 0);
				return;
			}
			toolbar_display->toolbar = toolbar;
			toolbar_display->descriptor = descriptor;
			if (!toolbars) {
				toolbars = toolbar_display;
			} else {
				link = toolbars;
				while (link->next) link = link->next;
				link->next = toolbar_display;
			}
			theme_count++;
		}
		descriptor = descriptor->next;
	}

	/* nest the toolbars */
	state.w = theme_pane;
	error = xwimp_get_window_state(&state);
	if (error) {
		LOG(("xwimp_get_window_state: 0x%x: %s",
			error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
		return;
	}

	parent_width = state.visible.x1 - state.visible.x0;
	min_extent = state.visible.y0 - state.visible.y1;
	nested_y = 0;
	base_extent = state.visible.y1 - state.yscroll;
	extent.x1 = parent_width;
	link = toolbars;
	new_icon.w = theme_pane;
	new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED |
			wimp_ICON_VCENTRED |
			(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
			(wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
	while (link) {
		/* update the toolbar */
		item_height = 44 + 44 + 16;
		if (link->next) item_height += 16;
		ro_toolbar_process(link->toolbar, parent_width, false);
		extent.y0 = nested_y -
				ro_toolbar_height(link->toolbar) -
				item_height;
		if (link->next) extent.y0 -= 16;
		if (extent.y0 > min_extent) extent.y0 = min_extent;
		xwimp_set_extent(theme_pane, &extent);

		/* create the descriptor icons and separator line */
		new_icon.icon.extent.x0 = 8;
		new_icon.icon.extent.x1 = parent_width - 8;
		new_icon.icon.flags &= ~wimp_ICON_BORDER;
		new_icon.icon.flags |= wimp_ICON_SPRITE;
		new_icon.icon.extent.y1 = nested_y -
				ro_toolbar_height(link->toolbar) - 8;
		new_icon.icon.extent.y0 = nested_y -
				ro_toolbar_height(link->toolbar) - 52;
		new_icon.icon.data.indirected_text_and_sprite.text =
			(char *)&link->descriptor->name;
		new_icon.icon.data.indirected_text_and_sprite.size =
			strlen(link->descriptor->name) + 1;
		new_icon.icon.data.indirected_text_and_sprite.validation =
				theme_radio_validation;
		new_icon.icon.flags |= (wimp_BUTTON_RADIO <<
				wimp_ICON_BUTTON_TYPE_SHIFT);
		xwimp_create_icon(&new_icon, &link->icon_number);
		new_icon.icon.flags &= ~wimp_ICON_SPRITE;
		new_icon.icon.extent.x0 = 52;
		new_icon.icon.extent.y1 -= 44;
		new_icon.icon.extent.y0 -= 44;
		new_icon.icon.data.indirected_text.text =
			(char *)&link->descriptor->author;
		new_icon.icon.data.indirected_text.size =
			strlen(link->descriptor->author) + 1;
		new_icon.icon.data.indirected_text.validation =
				theme_null_validation;
		new_icon.icon.flags &= ~(wimp_BUTTON_RADIO <<
				wimp_ICON_BUTTON_TYPE_SHIFT);
		xwimp_create_icon(&new_icon, 0);
		if (link->next) {
			new_icon.icon.flags |= wimp_ICON_BORDER;
			new_icon.icon.extent.x0 = -8;
			new_icon.icon.extent.x1 = parent_width + 8;
			new_icon.icon.extent.y1 -= 52;
			new_icon.icon.extent.y0 = new_icon.icon.extent.y1 - 8;
			new_icon.icon.data.indirected_text.text =
					theme_null_validation;
			new_icon.icon.data.indirected_text.validation =
					theme_line_validation;
			new_icon.icon.data.indirected_text.size = 1;
			xwimp_create_icon(&new_icon, 0);
		}

		/* nest the toolbar window */
		state.w = ro_toolbar_get_window(link->toolbar);
		state.yscroll = 0;
		state.visible.y1 = nested_y + base_extent;
		state.visible.y0 = state.visible.y1 -
				ro_toolbar_height(link->toolbar) + 2;
		xwimp_open_window_nested(PTR_WIMP_OPEN(&state), theme_pane,
				wimp_CHILD_LINKS_PARENT_WORK_AREA
						<< wimp_CHILD_BS_EDGE_SHIFT |
				wimp_CHILD_LINKS_PARENT_WORK_AREA
						<< wimp_CHILD_TS_EDGE_SHIFT);

		/* continue processing */
		nested_y -= ro_toolbar_height(link->toolbar) +
				item_height;
		link = link->next;
	}

	/* set the icons as radios */
	radio_icons = (int *)calloc(theme_count + 1, sizeof(int));
	radio_set = radio_icons;
	for (link = toolbars; link; link = link->next)
		*radio_set++ = link->icon_number;
	*radio_set = -1;
	ro_gui_wimp_event_register_radio(theme_pane, radio_icons);

	/* update our display */
	xwimp_force_redraw(theme_pane, 0, -16384, 16384, 16384);
}