From d21447d096a320a08b3efb2b8768fad0dcdcfd64 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Thu, 5 May 2016 22:28:51 +0100 Subject: move frontends into sub directory --- frontends/riscos/gui/status_bar.c | 625 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 625 insertions(+) create mode 100644 frontends/riscos/gui/status_bar.c (limited to 'frontends/riscos/gui/status_bar.c') diff --git a/frontends/riscos/gui/status_bar.c b/frontends/riscos/gui/status_bar.c new file mode 100644 index 000000000..cbc404658 --- /dev/null +++ b/frontends/riscos/gui/status_bar.c @@ -0,0 +1,625 @@ +/* + * Copyright 2006 Richard Wilson + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** \file + * UTF8 status bar (implementation). + */ + +#include +#include +#include +#include "swis.h" +#include "oslib/colourtrans.h" +#include "oslib/os.h" +#include "oslib/wimp.h" +#include "oslib/wimpspriteop.h" +#include "desktop/plotters.h" +#include "utils/log.h" +#include "utils/utils.h" + +#include "riscos/gui.h" +#include "riscos/wimp.h" +#include "riscos/wimp_event.h" +#include "riscos/wimputils.h" +#include "riscos/font.h" +#include "riscos/gui/progress_bar.h" +#include "riscos/gui/status_bar.h" + +#define ICON_WIDGET 0 +#define WIDGET_WIDTH 12 +#define PROGRESS_WIDTH 160 + +struct status_bar { + wimp_w w; /**< status bar window handle */ + wimp_w parent; /**< parent window handle */ + const char *text; /**< status bar text */ + struct progress_bar *pb; /**< progress bar */ + unsigned int scale; /**< current status bar scale */ + int width; /**< current status bar width */ + bool visible; /**< status bar is visible? */ +}; + +static char status_widget_text[] = ""; +static char status_widget_validation[] = "R5;Pptr_lr,8,6"; + +wimp_WINDOW(1) status_bar_definition = { + {0, 0, 1, 1}, + 0, + 0, + wimp_TOP, + wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_MOVEABLE | + wimp_WINDOW_FURNITURE_WINDOW | + wimp_WINDOW_IGNORE_XEXTENT, + wimp_COLOUR_BLACK, + wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_LIGHT_GREY, + wimp_COLOUR_VERY_LIGHT_GREY, + wimp_COLOUR_DARK_GREY, + wimp_COLOUR_MID_LIGHT_GREY, + wimp_COLOUR_CREAM, + wimp_WINDOW_NEVER3D | 0x16u /* RISC OS 5.03+ */, + {0, 0, 65535, 65535}, + 0, + 0, + wimpspriteop_AREA, + 1, + 1, + {""}, + 1, + { + { + {0, 0, 1, 1}, + wimp_ICON_TEXT | wimp_ICON_INDIRECTED | + wimp_ICON_BORDER | wimp_ICON_FILLED | + (wimp_COLOUR_LIGHT_GREY << + wimp_ICON_BG_COLOUR_SHIFT) | + (wimp_BUTTON_CLICK_DRAG << + wimp_ICON_BUTTON_TYPE_SHIFT), + { + .indirected_text = { + status_widget_text, + status_widget_validation, + 1 + } + } + } + } +}; + +static void ro_gui_status_bar_open(wimp_open *open); +static bool ro_gui_status_bar_click(wimp_pointer *pointer); +static void ro_gui_status_bar_redraw(wimp_draw *redraw); +static void ro_gui_status_bar_redraw_callback(void *handle); +static void ro_gui_status_position_progress_bar(struct status_bar *sb); + + +/** + * Create a new status bar + * + * \param parent the window to contain the status bar + * \param width the proportional width to use (0...10,000) + */ +struct status_bar *ro_gui_status_bar_create(wimp_w parent, unsigned int width) +{ + struct status_bar *sb; + os_error *error; + + sb = calloc(1, sizeof(*sb)); + if (!sb) + return NULL; + + sb->pb = ro_gui_progress_bar_create(); + if (!sb->pb) + return NULL; + + error = xwimp_create_window((wimp_window *)&status_bar_definition, + &sb->w); + if (error) { + LOG("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess); + free(sb); + return NULL; + } + sb->parent = parent; + sb->scale = width; + sb->visible = true; + + ro_gui_wimp_event_set_user_data(sb->w, sb); + ro_gui_wimp_event_register_open_window(sb->w, + ro_gui_status_bar_open); + ro_gui_wimp_event_register_mouse_click(sb->w, + ro_gui_status_bar_click); + ro_gui_wimp_event_register_redraw_window(sb->w, + ro_gui_status_bar_redraw); + ro_gui_wimp_event_set_help_prefix(sb->w, "HelpStatus"); + ro_gui_status_bar_resize(sb); + return sb; +} + + +/** + * Destroy a status bar and free all associated resources + * + * \param sb the status bar to destroy + */ +void ro_gui_status_bar_destroy(struct status_bar *sb) +{ + os_error *error; + assert(sb); + + ro_gui_wimp_event_finalise(sb->w); + error = xwimp_delete_window(sb->w); + if (error) { + LOG("xwimp_delete_window: 0x%x:%s", error->errnum, error->errmess); + } + + ro_gui_progress_bar_destroy(sb->pb); + + /* Remove any scheduled redraw callbacks */ + riscos_schedule(-1, ro_gui_status_bar_redraw_callback, (void *) sb); + + free(sb); +} + + +/** + * Get the handle of the window that represents a status bar + * + * \param sb the status bar to get the window handle of + * \return the status bar's window handle + */ +wimp_w ro_gui_status_bar_get_window(struct status_bar *sb) +{ + assert(sb); + + return sb->w; +} + + +/** + * Get the proportional width the status bar is currently using + * + * \param sb the status bar to get the width of + * \return the status bar's width (0...10,000) + */ +unsigned int ro_gui_status_bar_get_width(struct status_bar *sb) +{ + assert(sb); + + return sb->scale; +} + + +/** + * Set the visibility status of the status bar + * + * \param sb the status bar to check the visiblity of + * \param visible if the status bar should be shown or not. + * \return whether the status bar is visible + */ +void ro_gui_status_bar_set_visible(struct status_bar *sb, bool visible) +{ + assert(sb); + + sb->visible = visible; + if (visible) { + ro_gui_status_bar_resize(sb); + } else { + os_error *error = xwimp_close_window(sb->w); + if (error) { + LOG("xwimp_close_window: 0x%x:%s", error->errnum, error->errmess); + } + } +} + + +/** + * Get the visibility status of the status bar + * + * \param sb the status bar to check the visiblity of + * \return whether the status bar is visible + */ +bool ro_gui_status_bar_get_visible(struct status_bar *sb) +{ + assert(sb); + + return sb->visible; +} + + +/** + * Set the value of the progress bar + * + * \param sb the status bar to set the progress of + * \param value the value to use + */ +void ro_gui_status_bar_set_progress_value(struct status_bar *sb, + unsigned int value) +{ + assert(sb); + + ro_gui_status_bar_set_progress_range(sb, + max(value, ro_gui_progress_bar_get_range(sb->pb))); + ro_gui_progress_bar_set_value(sb->pb, value); +} + + +/** + * Set the range of the progress bar + * + * \param sb the status bar to set the range of + * \param range the range of the progress bar + */ +void ro_gui_status_bar_set_progress_range(struct status_bar *sb, + unsigned int range) +{ + unsigned int old_range; + + assert(sb); + + old_range = ro_gui_progress_bar_get_range(sb->pb); + ro_gui_progress_bar_set_range(sb->pb, range); + + LOG("Ranges are %i vs %i", old_range, range); + if ((old_range == 0) && (range != 0)) { + ro_gui_status_position_progress_bar(sb); + } else if ((old_range != 0) && (range == 0)) { + os_error *error = xwimp_close_window( + ro_gui_progress_bar_get_window(sb->pb)); + if (error) { + LOG("xwimp_close_window: 0x%x:%s", error->errnum, error->errmess); + } + } +} + + +/** + * Set the icon for the progress bar + * + * \param sb the status bar to set the icon for + * \param icon the icon to use, or NULL for no icon + */ +void ro_gui_status_bar_set_progress_icon(struct status_bar *sb, + const char *icon) +{ + assert(sb); + + ro_gui_progress_bar_set_icon(sb->pb, icon); +} + + +/** + * Set the text to display in the status bar + * + * \param sb the status bar to set the text for + * \param text the UTF8 text to display, or NULL for none + */ +void ro_gui_status_bar_set_text(struct status_bar *sb, const char *text) +{ + assert(sb); + + sb->text = text; + + /* Schedule a window redraw for 1cs' time. + * + * We do this to ensure that redraws as a result of text changes + * do not prevent other applications obtaining CPU time. + * + * The scheduled callback will be run when we receive the first + * null poll after 1cs has elapsed. It may then issue a redraw + * request to the Wimp. + * + * The scheduler ensures that only one instance of the + * { callback, handle } pair is registered at once. + */ + if (sb->visible && text != NULL) { + riscos_schedule(10, ro_gui_status_bar_redraw_callback, sb); + } +} + + +/** + * Resize a status bar following a change in the dimensions of the + * parent window. + * + * \param sb the status bar to resize + */ +void ro_gui_status_bar_resize(struct status_bar *sb) +{ + int window_width; + int status_width, status_height; + wimp_window_state state; + os_error *error; + os_box extent; + + if ((!sb) || (!sb->visible)) + return; + + /* get the window work area dimensions */ + state.w = sb->parent; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + return; + } + window_width = state.visible.x1 - state.visible.x0; + + + /* recalculate the scaled width */ + status_width = (window_width * sb->scale) / 10000; + if (status_width < WIDGET_WIDTH) + status_width = WIDGET_WIDTH; + status_height = ro_get_hscroll_height(sb->parent); + + /* resize the status/resize icons */ + if (status_width != sb->width) { + /* update the window extent */ + int redraw_left, redraw_right; + + extent.x0 = 0; + extent.y0 = 0; + extent.x1 = status_width; + extent.y1 = status_height - 4; + error = xwimp_set_extent(sb->w, &extent); + if (error) { + LOG("xwimp_set_extent: 0x%x: %s", error->errnum, error->errmess); + return; + } + + /* re-open the nested window */ + state.w = sb->w; + state.xscroll = 0; + state.yscroll = 0; + state.next = wimp_TOP; + state.visible.x0 = state.visible.x0; + state.visible.y1 = state.visible.y0 - 2; + state.visible.x1 = state.visible.x0 + status_width; + state.visible.y0 = state.visible.y1 - status_height + 4; + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), + sb->parent, + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_XORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_YORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_LS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_RS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_TS_EDGE_SHIFT); + if (error) { + LOG("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess); + return; + } + ro_gui_status_position_progress_bar(sb); + error = xwimp_resize_icon(sb->w, ICON_WIDGET, + status_width - WIDGET_WIDTH, 0, + status_width, status_height - 4); + if (error) { + LOG("xwimp_resize_icon: 0x%x: %s", error->errnum, error->errmess); + return; + } + + redraw_left = min(status_width, sb->width) - WIDGET_WIDTH - 2; + redraw_right = max(status_width, sb->width); + xwimp_force_redraw(sb->w, redraw_left, 0, + redraw_right, status_height); + sb->width = status_width; + } +} + + +/** + * Process a WIMP redraw request + * + * \param redraw the redraw request to process + */ +void ro_gui_status_bar_redraw(wimp_draw *redraw) +{ + struct status_bar *sb; + os_error *error; + osbool more; + rufl_code code; + + sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(redraw->w); + assert(sb); + + /* initialise the plotters */ + ro_plot_origin_x = 0; + ro_plot_origin_y = 0; + + /* redraw the window */ + error = xwimp_redraw_window(redraw, &more); + if (error) { + LOG("xwimp_redraw_window: 0x%x: %s", error->errnum, error->errmess); + return; + } + while (more) { + /* redraw the status text */ + if (sb->text) { + error = xcolourtrans_set_font_colours(font_CURRENT, + 0xeeeeee00, 0x00000000, 14, 0, 0, 0); + if (error) { + LOG("xcolourtrans_set_font_colours: 0x%x: %s", error->errnum, error->errmess); + return; + } + code = rufl_paint(ro_gui_desktop_font_family, + ro_gui_desktop_font_style, + ro_gui_desktop_font_size, + sb->text, strlen(sb->text), + redraw->box.x0 + 6, redraw->box.y0 + 8, + rufl_BLEND_FONT); + if (code != rufl_OK) { + if (code == rufl_FONT_MANAGER_ERROR) + LOG("rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); + else + LOG("rufl_paint: 0x%x", code); + } + } + + /* separate the widget from the text with a line */ + ro_plotters.rectangle((redraw->box.x0 + sb->width - WIDGET_WIDTH - 2) >> 1, + -redraw->box.y0 >> 1, + (redraw->box.x0 + sb->width - WIDGET_WIDTH) >> 1, + -redraw->box.y1 >> 1, + plot_style_fill_black); + + error = xwimp_get_rectangle(redraw, &more); + if (error) { + LOG("xwimp_get_rectangle: 0x%x: %s", error->errnum, error->errmess); + return; + } + } +} + +/** + * Callback for scheduled redraw + * + * \param handle Callback handle + */ +void ro_gui_status_bar_redraw_callback(void *handle) +{ + struct status_bar *sb = handle; + + wimp_force_redraw(sb->w, 0, 0, sb->width - WIDGET_WIDTH, 65536); +} + + +/** + * Process an mouse_click event for a status window. + * + * \param pointer details of the mouse click + */ +bool ro_gui_status_bar_click(wimp_pointer *pointer) +{ + wimp_drag drag; + os_error *error; + + switch (pointer->i) { + case ICON_WIDGET: + drag.w = pointer->w; + drag.type = wimp_DRAG_SYSTEM_SIZE; + drag.initial.x0 = pointer->pos.x; + drag.initial.x1 = pointer->pos.x; + drag.initial.y0 = pointer->pos.y; + drag.initial.y1 = pointer->pos.y; + error = xwimp_drag_box(&drag); + if (error) { + LOG("xwimp_drag_box: 0x%x: %s", error->errnum, error->errmess); + } + break; + } + return true; +} + + +/** + * Process an open_window request for a status window. + * + * \param open the request to process + */ +void ro_gui_status_bar_open(wimp_open *open) +{ + struct status_bar *sb; + int window_width, status_width; + wimp_window_state state; + os_error *error; + + /* get the parent width for scaling */ + sb = (struct status_bar *)ro_gui_wimp_event_get_user_data(open->w); + state.w = sb->parent; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + return; + } + window_width = state.visible.x1 - state.visible.x0; + if (window_width == 0) + window_width = 1; + status_width = open->visible.x1 - open->visible.x0; + if (status_width <= 12) + status_width = 0; + + /* store the new size */ + sb->scale = (10000 * status_width) / window_width; + if (sb->scale > 10000) + sb->scale = 10000; + ro_gui_status_bar_resize(sb); +} + + +/** + * Reposition the progress component following a change in the + * dimension of the status window. + * + * \param sb the status bar to update + */ +void ro_gui_status_position_progress_bar(struct status_bar *sb) +{ + wimp_window_state state; + os_error *error; + int left, right; + + if (!sb) + return; + if (ro_gui_progress_bar_get_range(sb->pb) == 0) + return; + + /* get the window work area dimensions */ + state.w = sb->w; + error = xwimp_get_window_state(&state); + if (error) { + LOG("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess); + return; + } + + /* calculate the dimensions */ + right = state.visible.x1 - WIDGET_WIDTH - 2; + left = max(state.visible.x0, right - PROGRESS_WIDTH); + + /* re-open the nested window */ + state.w = ro_gui_progress_bar_get_window(sb->pb); + state.xscroll = 0; + state.yscroll = 0; + state.next = wimp_TOP; + state.visible.x0 = left; + state.visible.x1 = right; + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), + sb->w, + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_XORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_YORIGIN_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_LS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_BS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_RS_EDGE_SHIFT | + wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT + << wimp_CHILD_TS_EDGE_SHIFT); + if (error) { + LOG("xwimp_open_window: 0x%x: %s", error->errnum, error->errmess); + } + + /* update the progress bar display on non-standard width */ + if ((right - left) != PROGRESS_WIDTH) + ro_gui_progress_bar_update(sb->pb, right - left, + state.visible.y1 - state.visible.y0); +} -- cgit v1.2.3