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); }
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); }