From c499ad907dc2d77bf9cf40fd099b2025766b6bc6 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sat, 3 Jul 2004 17:30:28 +0000 Subject: [project @ 2004-07-03 17:30:27 by rjw] Further development of the selection and display code. svn path=/import/netsurf/; revision=1042 --- riscos/gui.c | 9 +- riscos/gui.h | 6 +- riscos/hotlist.c | 650 +++++++++++++++++++++++++++++++++++++++++-------------- riscos/window.c | 1 - 4 files changed, 499 insertions(+), 167 deletions(-) (limited to 'riscos') diff --git a/riscos/gui.c b/riscos/gui.c index d1c3ee24e..fcc3d2f26 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -751,7 +751,14 @@ void ro_gui_drag_end(wimp_dragged *drag) break; case GUI_DRAG_STATUS_RESIZE: -// ro_gui_save_drag_end(drag); + break; + + case GUI_DRAG_HOTLIST_SELECT: + ro_gui_hotlist_selection_drag_end(drag); + break; + + case GUI_DRAG_HOTLIST_MOVE: + ro_gui_hotlist_move_drag_end(drag); break; } } diff --git a/riscos/gui.h b/riscos/gui.h index 09f7e3c55..cf27ffdb1 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -46,7 +46,8 @@ typedef enum { GUI_SAVE_SOURCE, GUI_SAVE_DRAW, GUI_SAVE_TEXT, GUI_SAVE_LINK_TEXT } gui_save_type; extern gui_save_type gui_current_save_type; typedef enum { GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE, - GUI_DRAG_SAVE, GUI_DRAG_STATUS_RESIZE } gui_drag_type; + GUI_DRAG_SAVE, GUI_DRAG_STATUS_RESIZE, + GUI_DRAG_HOTLIST_SELECT, GUI_DRAG_HOTLIST_MOVE } gui_drag_type; extern gui_drag_type gui_current_drag_type; struct gui_window { @@ -178,9 +179,10 @@ void ro_gui_history_mouse_at(wimp_pointer *pointer); void ro_gui_hotlist_init(void); void ro_gui_hotlist_show(void); void ro_gui_hotlist_add(char *title, struct content *content); -void ro_gui_hotlist_visited(struct content *content); void ro_gui_hotlist_redraw(wimp_draw *redraw); void ro_gui_hotlist_click(wimp_pointer *pointer); +void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag); +void ro_gui_hotlist_move_drag_end(wimp_dragged *drag); /* in save.c */ void ro_gui_save_click(wimp_pointer *pointer); diff --git a/riscos/hotlist.c b/riscos/hotlist.c index aaacc4448..de89766fa 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -14,13 +14,13 @@ #include #include #include "oslib/colourtrans.h" -#include "oslib/osword.h" #include "oslib/wimp.h" #include "oslib/wimpspriteop.h" #include "netsurf/content/content.h" #include "netsurf/riscos/gui.h" #include "netsurf/riscos/wimp.h" #include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" #include "netsurf/utils/utils.h" #define HOTLIST_EXPAND 0 @@ -30,61 +30,67 @@ #define HOTLIST_TLINE 4 #define HOTLIST_BLINE 5 -struct hotlist_entry { +#define HOTLIST_TEXT_BUFFER 256 +struct hotlist_entry { + /** The next hotlist entry at this level, or NULL for no more */ struct hotlist_entry *next_entry; - + /** The child hotlist entry (NULL for no children). The children value must be set for this value to take effect. */ struct hotlist_entry *child_entry; - + /** The number of children (-1 for non-folders, >=0 for folders) */ int children; - + /** The title of the hotlist entry/folder */ char *title; - + /** The URL of the hotlist entry (NULL for folders) */ char *url; - + /** Whether this entry is expanded */ bool expanded; - + /** Whether this entry is selected */ bool selected; - + /** The content filetype (not for folders) */ int filetype; - + /** The number of visits */ int visits; - - /** Add/last visit dates (-1 if invalid) + + /** Add/last visit dates */ time_t add_date; time_t last_date; - + /** Position on last reformat (relative to window origin) */ int x0; int y0; int width; int height; - + /** Cached values */ int collapsed_width; int expanded_width; + + /** The width of the various lines sub-text + */ + int widths[4]; }; @@ -126,6 +132,7 @@ static char null_text_string[] = "\0"; /* Temporary workspace for plotting */ static char icon_name[12]; +static char extended_text[HOTLIST_TEXT_BUFFER]; /* Whether a reformat is pending */ @@ -154,6 +161,10 @@ static osspriteop_id sprite[6]; */ static osspriteop_trans_tab *pixel_table; +/* The drag buttons +*/ +wimp_mouse_state drag_buttons; + static void ro_gui_hotlist_load(void); static void ro_gui_hotlist_save(void); @@ -166,11 +177,14 @@ static struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char static void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry); static struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_entry *entry); static int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, bool redraw); +static void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, + int x0, int y0, int x1, int y1, + bool toggle, bool redraw); static char *last_visit_to_string(time_t last_visit); void ro_gui_hotlist_init(void) { os_error *error; - + /* Get our sprite ids for faster plotting. This could be done in a far more elegant manner, but it's late and my girlfriend will kill me if I don't go to bed soon. Sorry. @@ -202,7 +216,7 @@ void ro_gui_hotlist_init(void) { warn_user("MiscError", error->errmess); return; } - + /* Update our text icon */ text_icon.data.indirected_text.validation = null_text_string; @@ -213,7 +227,7 @@ void ro_gui_hotlist_init(void) { (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT); sprite_icon.data.indirected_sprite.area = wimpspriteop_AREA; sprite_icon.data.indirected_text.size = 12; - + /* Create our window */ error = xwimp_create_window(&hotlist_window_definition, &hotlist_window); @@ -221,14 +235,14 @@ void ro_gui_hotlist_init(void) { warn_user("WimpError", error->errmess); return; } - + /* Set the root options */ root.next_entry = NULL; root.child_entry = NULL; root.children = 0; root.expanded = true; - + /* Load the hotlist */ ro_gui_hotlist_load(); @@ -237,7 +251,7 @@ void ro_gui_hotlist_init(void) { /** * Shows the hotlist window. - */ + */ void ro_gui_hotlist_show(void) { os_error *error; int screen_width, screen_height; @@ -262,14 +276,14 @@ void ro_gui_hotlist_show(void) { open in the centre of the screen. */ if (!(state.flags & wimp_WINDOW_OPEN)) { - /* Clear the selection state - */ - ro_gui_hotlist_selection_state(root.child_entry, false, false); + /* Clear the selection state + */ + ro_gui_hotlist_selection_state(root.child_entry, false, false); /* Get the current screen size */ ro_gui_screen_size(&screen_width, &screen_height); - + /* Move to the centre */ dimension = state.visible.x1 - state.visible.x0; @@ -294,32 +308,32 @@ void ro_gui_hotlist_show(void) { void ro_gui_hotlist_load(void) { struct hotlist_entry *netsurf; struct hotlist_entry *entry; - + /* Create a folder */ netsurf = ro_gui_hotlist_create("NetSurf", NULL, 0, &root); netsurf->expanded = true; - + /* Add some content */ entry = ro_gui_hotlist_create("NetSurf homepage", "http://netsurf.sf.net", 0xfaf, netsurf); - entry->add_date = -1; + entry->add_date = (time_t)-1; entry = ro_gui_hotlist_create("NetSurf test builds", "http://netsurf.strcprstskrzkrk.co.uk", 0xfaf, netsurf); - entry->add_date = -1; + entry->add_date = (time_t)-1; } -void ro_gui_hotlist_save(void) { +void ro_gui_hotlist_save(void) { } /** * Adds a hotlist entry to the root of the tree. * - * \param title the entry title + * \param title the entry title * \param content the content to add - */ + */ void ro_gui_hotlist_add(char *title, struct content *content) { ro_gui_hotlist_create(title, content->url, ro_content_filetype(content), &root); } @@ -330,9 +344,9 @@ void ro_gui_hotlist_add(char *title, struct content *content) { * * \param content the content visited */ -void ro_gui_hotlist_visited(struct content *content) { +void hotlist_visited(struct content *content) { if ((!content) || (!content->url)) return; - ro_gui_hotlist_visited_update(content, root.child_entry); + ro_gui_hotlist_visited_update(content, root.child_entry); } @@ -340,35 +354,49 @@ void ro_gui_hotlist_visited(struct content *content) { * Informs the hotlist that some content has been visited (internal) * * \param content the content visited - * \param entry the entry to check siblings and children of + * \param entry the entry to check siblings and children of */ void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry *entry) { char *url; - + bool full = false; + /* Update the hotlist */ url = content->url; while (entry) { if (entry->url) { if (strcmp(url, entry->url) == 0) { - char *temp = last_visit_to_string(entry->last_date); - if (temp != NULL) { - LOG(("previous visit to '%s': '%s'", url, temp)); - free(temp); - } + /* Check if we're going to need a full redraw downwards + */ + full = ((entry->visits == 0) || (entry->last_date == -1)); + + /* Update our values + */ entry->visits++; entry->last_date = time(NULL); + + /* Update the entry width (extreme case - never likely to happen) + */ ro_gui_hotlist_update_entry_size(entry); + + /* Redraw the least we can get away with + */ if (entry->expanded) { - xwimp_force_redraw(hotlist_window, - entry->x0, entry->y0, - entry->x0 + entry->width, - entry->y0 + entry->height); + if (full) { + xwimp_force_redraw(hotlist_window, + 0, -16384, 16384, + entry->y0 + entry->height); + } else { + xwimp_force_redraw(hotlist_window, + entry->x0, entry->y0, + entry->x0 + entry->width, + entry->y0 + entry->height); + } } } } if (entry->child_entry) { - ro_gui_hotlist_visited_update(content, entry->child_entry); + ro_gui_hotlist_visited_update(content, entry->child_entry); } entry = entry->next_entry; } @@ -381,11 +409,11 @@ void ro_gui_hotlist_visited_update(struct content *content, struct hotlist_entry * \param title the entry title * \param url the entry url (NULL to create a folder) * \param folder the folder to add the entry into - */ + */ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, int filetype, struct hotlist_entry *folder) { struct hotlist_entry *entry; - + /* Check we have a title or a URL */ if (!title && !url) return NULL; @@ -397,7 +425,7 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, warn_user("NoMemory", 0); return NULL; } - + /* And enough for the url/title */ if (url) { @@ -405,7 +433,7 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, if (!entry->url) { warn_user("NoMemory", 0); free(entry); - return NULL; + return NULL; } strcpy(entry->url, url); } @@ -418,43 +446,43 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, warn_user("NoMemory", 0); free(entry->url); free(entry); - return NULL; + return NULL; } strcpy(entry->title, title); } else { - entry->title = entry->url; + entry->title = entry->url; } - + /* Set the children count */ if (url) { - entry->children = -1; + entry->children = -1; } else { entry->children = 0; } - + /* Set the filetype */ entry->filetype = filetype; - + /* Set the default values */ entry->visits = 0; - + /* Get our dates */ entry->add_date = time(NULL); - entry->last_date = -1; - + entry->last_date = (time_t)-1; + /* Set the expanded/selected state */ entry->expanded = false; entry->selected = false; - + /* Set the width */ ro_gui_hotlist_update_entry_size(entry); - + /* Link in as the last entry in root */ ro_gui_hotlist_link_entry(folder, entry); @@ -467,16 +495,16 @@ struct hotlist_entry *ro_gui_hotlist_create(const char *title, const char *url, * * \param parent the parent entry to link under * \param entry the entry to link - */ + */ void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entry *entry) { struct hotlist_entry *link_entry; if (!parent || !entry) return; - + /* Ensure the parent is a folder */ if (parent->children == -1) return; - + /* Get the first child entry */ link_entry = parent->child_entry; @@ -486,7 +514,7 @@ void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entr while (link_entry->next_entry) link_entry = link_entry->next_entry; link_entry->next_entry = entry; } - + /* Increment the number of children */ parent->children += 1; @@ -503,32 +531,82 @@ void ro_gui_hotlist_link_entry(struct hotlist_entry *parent, struct hotlist_entr */ void ro_gui_hotlist_update_entry_size(struct hotlist_entry *entry) { int width; - + int max_width; + int line_number = 0; + /* Get the width of the title - */ + */ xwimptextop_string_width(entry->title, strlen(entry->title) > 256 ? 256 : strlen(entry->title), &width); - entry->collapsed_width = width + 32 + 36 + 16; - + entry->collapsed_width = width; + max_width = width; + /* Get the width of the URL */ if (entry->url) { - xwimptextop_string_width(entry->url, - strlen(entry->url) > 256 ? 256 : strlen(entry->url), + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistURL"), entry->url); + if (strlen(extended_text) >= 255) { + extended_text[252] = '.'; + extended_text[253] = '.'; + extended_text[254] = '.'; + extended_text[255] = '\0'; + } + xwimptextop_string_width(extended_text, + strlen(extended_text) > 256 ? 256 : strlen(extended_text), &width); - width += 32 + 36 + 16; - if (width < entry->collapsed_width) width = entry->collapsed_width; - entry->expanded_width = width; - } else { - entry->expanded_width = width + 32 + 36 + 16; + if (width > max_width) max_width = width; + entry->widths[line_number++] = width; + } + + /* Get the width of the add date + */ + if (entry->add_date != -1) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistAdd"), ctime(&entry->add_date)); + xwimptextop_string_width(extended_text, + strlen(extended_text) > 256 ? 256 : strlen(extended_text), + &width); + if (width > max_width) max_width = width; + entry->widths[line_number++] = width; + } + + /* Get the width of the last visit + */ + if (entry->last_date != -1) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistLast"), ctime(&entry->last_date)); + xwimptextop_string_width(extended_text, + strlen(extended_text) > 256 ? 256 : strlen(extended_text), + &width); + if (width > max_width) max_width = width; + entry->widths[line_number++] = width; + } + + /* Get the width of the visit count + */ + if (entry->visits > 0) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistVisits"), entry->visits); + xwimptextop_string_width(extended_text, + strlen(extended_text) > 256 ? 256 : strlen(extended_text), + &width); + if (width > max_width) max_width = width; + entry->widths[line_number++] = width; } + + /* Increase the text width by the borders + */ + entry->expanded_width = max_width + 32 + 36 + 16; + entry->collapsed_width += 32 + 36 + 16; + reformat_pending = true; } /** * Redraws a section of the hotlist window - * + * * \param redraw the area to redraw */ void ro_gui_hotlist_redraw(wimp_draw *redraw) { @@ -536,12 +614,12 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { osbool more; unsigned int size; os_box extent = {0, 0, 0, 0};; - + /* Reset our min/max sizes */ max_width = 0; max_height = 0; - + /* Get a pixel translation table for the sprites. We only get one for all the sprites, so they must all have the same characteristics. @@ -550,7 +628,7 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, 0, colourtrans_GIVEN_SPRITE, 0, 0, &size); pixel_table = malloc(size); - if (pixel_table) { + if (pixel_table) { xcolourtrans_generate_table_for_sprite(gui_sprites, sprite[HOTLIST_EXPAND], colourtrans_CURRENT_MODE, colourtrans_CURRENT_PALETTE, pixel_table, colourtrans_GIVEN_SPRITE, 0, 0, 0); @@ -562,22 +640,22 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { */ more = wimp_redraw_window(redraw); while (more) { - clip_x0 = redraw->clip.x0; - clip_y0 = redraw->clip.y0; - clip_x1 = redraw->clip.x1; - clip_y1 = redraw->clip.y1; + clip_x0 = redraw->clip.x0; + clip_y0 = redraw->clip.y0; + clip_x1 = redraw->clip.x1; + clip_y1 = redraw->clip.y1; origin_x = redraw->box.x0 - redraw->xscroll; origin_y = redraw->box.y1 - redraw->yscroll; ro_gui_hotlist_redraw_tree(root.child_entry, 0, origin_x + 8, origin_y - 4); more = wimp_get_rectangle(redraw); } - + /* Free our memory */ if (pixel_table) free(pixel_table); pixel_table = NULL; - + /* Check if we should reformat */ if (reformat_pending) { @@ -601,8 +679,8 @@ void ro_gui_hotlist_redraw(wimp_draw *redraw) { * * \param entry the entry to draw descendants and siblings of * \param level the tree level of the entry - * \param x0 the x co-ordinate to plot from - * \param y0 the y co-ordinate to plot from + * \param x0 the x co-ordinate to plot from + * \param y0 the y co-ordinate to plot from * \returns the height of the tree */ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, int y0) { @@ -610,13 +688,13 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i int cumulative = 0; int height = 0; int box_y0; - + if (!entry) return 0; - + /* Repeatedly draw our entries */ while (entry) { - + /* Redraw the item */ height = ro_gui_hotlist_redraw_item(entry, level, x0 + 32, y0); @@ -659,7 +737,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i y0 -= 44; height -= 44; } - + /* Draw the rest of the lines */ while (height > 0) { @@ -671,7 +749,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i y0 -= 44; height -= 44; } - + } else { /* Draw a half-line for the last entry */ @@ -700,17 +778,17 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i gui_sprites, sprite[HOTLIST_COLLAPSE], x0, box_y0 - 31, osspriteop_USE_MASK | osspriteop_USE_PALETTE, - 0, pixel_table); + 0, pixel_table); } else { xosspriteop_put_sprite_scaled(osspriteop_PTR, gui_sprites, sprite[HOTLIST_EXPAND], x0, box_y0 - 31, osspriteop_USE_MASK | osspriteop_USE_PALETTE, 0, pixel_table); - - + + } - + } /* Move to the next entry @@ -718,7 +796,7 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i entry = entry->next_entry; first = false; } - + /* Return our height */ return cumulative; @@ -730,26 +808,30 @@ int ro_gui_hotlist_redraw_tree(struct hotlist_entry *entry, int level, int x0, i * * \param entry the entry to redraw * \param level the level of the entry - * \param x0 the x co-ordinate to plot at - * \param y0 the y co-ordinate to plot at + * \param x0 the x co-ordinate to plot at + * \param y0 the y co-ordinate to plot at * \return the height of the entry */ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, int y0) { int height = 44; - int index; - + int line_y0; + int line_height; + /* Set the correct height */ if ((entry->children == -1) && (entry->expanded)) { if (entry->url) height += 44; + if (entry->visits > 0) height += 44; + if (entry->add_date != -1) height += 44; + if (entry->last_date != -1) height += 44; } - + /* Check whether we need to redraw */ if ((x0 < clip_x1) && (y0 > clip_y0) && ((x0 + entry->width) > clip_x0) && ((y0 - height) < clip_y1)) { - - + + /* Update the selection state */ text_icon.flags = wimp_ICON_TEXT | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | @@ -784,11 +866,11 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i /* Get the icon sprite */ sprintf(icon_name, "small_%x", entry->filetype); - + /* Check it exists */ if (xwimpspriteop_read_sprite_info(icon_name, 0, 0, 0, 0)) { - sprintf(icon_name, "small_xxx"); + sprintf(icon_name, "small_xxx"); } } xwimp_plot_icon(&sprite_icon); @@ -798,8 +880,8 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i text_icon.data.indirected_text.text = entry->title; text_icon.extent.x0 = x0 - origin_x + 36; text_icon.extent.x1 = x0 - origin_x + entry->collapsed_width - 32; - text_icon.extent.y0 = y0 - origin_y - 44; - text_icon.extent.y1 = y0 - origin_y; + text_icon.extent.y0 = y0 - origin_y - 42; + text_icon.extent.y1 = y0 - origin_y - 2; xwimp_plot_icon(&text_icon); /* Clear the selection state @@ -810,38 +892,91 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i /* Draw our further information if expanded */ - if ((entry->children == -1) && (entry->expanded)) { + if ((entry->children == -1) && (entry->expanded) && (height > 44)) { text_icon.flags = wimp_ICON_TEXT | (wimp_COLOUR_DARK_GREY << wimp_ICON_FG_COLOUR_SHIFT) | wimp_ICON_INDIRECTED | wimp_ICON_VCENTRED; - -/* URL - Date added - Last visited - Visit count -*/ - - + text_icon.extent.y0 = y0 - origin_y - 44; + text_icon.extent.y1 = y0 - origin_y; + /* Draw the lines */ y0 -= 44; - xosspriteop_put_sprite_scaled(osspriteop_PTR, - gui_sprites, sprite[HOTLIST_TLINE], - x0 + 16, y0 - 22, - osspriteop_USE_MASK | osspriteop_USE_PALETTE, - 0, pixel_table); - xosspriteop_put_sprite_scaled(osspriteop_PTR, - gui_sprites, sprite[HOTLIST_ENTRY], - x0 + 8, y0 - 29, - osspriteop_USE_MASK | osspriteop_USE_PALETTE, - 0, pixel_table); + line_y0 = y0; + line_height = height - 44; + while (line_height > 0) { + if (line_height == 44) { + xosspriteop_put_sprite_scaled(osspriteop_PTR, + gui_sprites, sprite[HOTLIST_TLINE], + x0 + 16, line_y0 - 22, + osspriteop_USE_MASK | osspriteop_USE_PALETTE, + 0, pixel_table); + } else { + xosspriteop_put_sprite_scaled(osspriteop_PTR, + gui_sprites, sprite[HOTLIST_LINE], + x0 + 16, line_y0 - 44, + osspriteop_USE_MASK | osspriteop_USE_PALETTE, + 0, pixel_table); + + } + xosspriteop_put_sprite_scaled(osspriteop_PTR, + gui_sprites, sprite[HOTLIST_ENTRY], + x0 + 8, line_y0 - 29, + osspriteop_USE_MASK | osspriteop_USE_PALETTE, + 0, pixel_table); + line_height -= 44; + line_y0 -= 44; + } - /* Plot the text + /* Set the right extent of the icon to be big enough for anything */ - text_icon.data.indirected_text.text = entry->url; text_icon.extent.x1 = x0 - origin_x + 4096; - text_icon.extent.y0 -= 44; - text_icon.extent.y1 -= 44; - xwimp_plot_icon(&text_icon); + + /* Plot the URL text + */ + text_icon.data.indirected_text.text = extended_text; + if (entry->url) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistURL"), entry->url); + if (strlen(extended_text) >= 255) { + extended_text[252] = '.'; + extended_text[253] = '.'; + extended_text[254] = '.'; + extended_text[255] = '\0'; + } + text_icon.extent.y0 -= 44; + text_icon.extent.y1 -= 44; + xwimp_plot_icon(&text_icon); + } + + /* Plot the date added text + */ + if (entry->add_date != -1) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistAdd"), ctime(&entry->add_date)); + text_icon.extent.y0 -= 44; + text_icon.extent.y1 -= 44; + xwimp_plot_icon(&text_icon); + } + + /* Plot the last visited text + */ + if (entry->last_date != -1) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistLast"), ctime(&entry->last_date)); + text_icon.extent.y0 -= 44; + text_icon.extent.y1 -= 44; + xwimp_plot_icon(&text_icon); + } + + /* Plot the visit count text + */ + if (entry->visits > 0) { + snprintf(extended_text, HOTLIST_TEXT_BUFFER, + messages_get("HotlistVisits"), entry->visits); + text_icon.extent.y0 -= 44; + text_icon.extent.y1 -= 44; + xwimp_plot_icon(&text_icon); + } } } @@ -861,6 +996,7 @@ int ro_gui_hotlist_redraw_item(struct hotlist_entry *entry, int level, int x0, i * /param pointer the pointer state */ void ro_gui_hotlist_click(wimp_pointer *pointer) { + wimp_drag drag; struct hotlist_entry *entry; wimp_window_state state; wimp_mouse_state buttons; @@ -884,7 +1020,7 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { x = (pointer->pos.x - (state.visible.x0 - state.xscroll)); y = (pointer->pos.y - (state.visible.y1 - state.yscroll)); - + /* Find our entry */ entry = ro_gui_hotlist_find_entry(x, y, root.child_entry); @@ -895,10 +1031,14 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { y_offset = y - (entry->y0 + entry->height); if (((x_offset < 32) && (y_offset > -44)) || ((entry->children != -1) && ((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)))) { + ro_gui_hotlist_selection_state(entry->child_entry, + false, false); entry->expanded = !entry->expanded; if (x_offset >= 32) entry->selected = false; reformat_pending = true; - xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 0); + xwimp_force_redraw(hotlist_window, + 0, -16384, 16384, + entry->y0 + entry->height); } else if (x_offset >= 32) { /* Check for selection */ @@ -913,19 +1053,19 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { false, true); entry->selected = true; xwimp_force_redraw(hotlist_window, - entry->x0, entry->y0, + entry->x0, entry->y0 + entry->height - 44, entry->x0 + entry->width, - entry->y0 + entry->height); + entry->y0 + entry->height); } } else if (buttons == (wimp_CLICK_ADJUST << 8)) { entry->selected = !entry->selected; xwimp_force_redraw(hotlist_window, - entry->x0, entry->y0, + entry->x0, entry->y0 + entry->height - 44, entry->x0 + entry->width, - entry->y0 + entry->height); - + entry->y0 + entry->height); + } - + /* Check if we should open the URL */ if (((buttons == wimp_DOUBLE_SELECT) || (buttons == wimp_DOUBLE_ADJUST)) && @@ -945,37 +1085,63 @@ void ro_gui_hotlist_click(wimp_pointer *pointer) { } else { no_entry = true; } - - + + /* Handle a click without an entry */ if (no_entry) { - /* Deselect everything if we click nowhere - */ + /* Deselect everything if we click nowhere + */ if (buttons == (wimp_CLICK_SELECT << 8)) { ro_gui_hotlist_selection_state(root.child_entry, false, true); } - } + + /* Handle the start of a drag + */ + if (buttons == (wimp_CLICK_SELECT << 4) || + buttons == (wimp_CLICK_ADJUST << 4)) { + + /* Clear the current selection + */ + if (buttons == (wimp_CLICK_SELECT << 4)) { + ro_gui_hotlist_selection_state(root.child_entry, + false, true); + } + /* Start a drag box + */ + drag_buttons = buttons; + gui_current_drag_type = GUI_DRAG_HOTLIST_SELECT; + drag.w = hotlist_window; + drag.type = wimp_DRAG_USER_RUBBER; + drag.initial.x0 = pointer->pos.x; + drag.initial.x1 = pointer->pos.x; + drag.initial.y0 = pointer->pos.y; + drag.initial.y1 = pointer->pos.y; + drag.bbox.x0 = state.visible.x0; + drag.bbox.x1 = state.visible.x1; + drag.bbox.y0 = state.visible.y0; + drag.bbox.y1 = state.visible.y1; + xwimp_drag_box(&drag); + } + } } /** * Find an entry at a particular position * - * For this calculation, the entry is deemed to occupy a box from the left edge of - * the expansion image to the right extent of the widest text string for the first - * line, and a box inset by the width of a expansion button and an icon for the rest. - * - * \param x the x co-ordinate - * \param y the y co-ordinate + * \param x the x co-ordinate + * \param y the y co-ordinate * \param entry the entry to check down from (root->child_entry for the entire tree) * /return the entry occupying the positon */ struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_entry *entry) { struct hotlist_entry *find_entry; - + int inset_x = 0; + int inset_y = 0; + /* Check we have an entry (only applies if we have an empty hotlist) */ if (!entry) return NULL; @@ -983,17 +1149,30 @@ struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_ent /* Get the first child entry */ while (entry) { - /* Check this entry + /* Check if this entry could possibly match */ if ((x > entry->x0) && (y > entry->y0) && (x < (entry->x0 + entry->width)) && (y < (entry->y0 + entry->height))) { - /* The top line extends the full width + + /* The top line extends all the way left */ - if ((y - (entry->y0 + entry->height)) > -44) return entry; - if ((x - entry->x0) > (32 + 36)) return entry; - return NULL; + if (y - (entry->y0 + entry->height) > -44) { + if (x < (entry->x0 + entry->collapsed_width)) return entry; + return NULL; + } + + /* No other entry can occupy the left edge + */ + inset_x = x - entry->x0 - 32 - 36; + if (inset_x < 0) return NULL; + + /* Check the right edge against our various widths + */ + inset_y = -((y - entry->y0 - entry->height) / 44); + if (inset_x < (entry->widths[inset_y - 1] + 16)) return entry; + return NULL; } - + /* Continue onwards */ if ((entry->child_entry) && (entry->expanded)) { @@ -1009,7 +1188,7 @@ struct hotlist_entry *ro_gui_hotlist_find_entry(int x, int y, struct hotlist_ent /** * Updated the selection state of the tree * - * \param entry the entry to update all siblings and descendants of + * \param entry the entry to update all siblings and descendants of * \param selected the selection state to set * \param redraw update the icons in the Wimp * \return the number of entries that have changed @@ -1031,12 +1210,12 @@ int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, b */ entry->selected = selected; changes++; - - /* Redraw the entry + + /* Redraw the entrys first line */ if (redraw) { xwimp_force_redraw(hotlist_window, - entry->x0, entry->y0, + entry->x0, entry->y0 + entry->height - 44, entry->x0 + entry->width, entry->y0 + entry->height); } @@ -1046,13 +1225,158 @@ int ro_gui_hotlist_selection_state(struct hotlist_entry *entry, bool selected, b */ if (entry->child_entry) { changes += ro_gui_hotlist_selection_state(entry->child_entry, - selected & (entry->expanded), redraw); + selected, redraw & (entry->expanded)); } entry = entry->next_entry; } return changes; } + +/** + * Updated the selection state of the tree + * + * \param entry the entry to update all siblings and descendants of + * \param x0 the left edge of the box + * \param y0 the top edge of the box + * \param x1 the right edge of the box + * \param y1 the bottom edge of the box + * \param toggle toggle the selection state, otherwise set + * \param redraw update the icons in the Wimp + */ +void ro_gui_hotlist_selection_drag(struct hotlist_entry *entry, + int x0, int y0, int x1, int y1, + bool toggle, bool redraw) { + bool do_update; + int line; + int test_y; + + /* Check we have an entry (only applies if we have an empty hotlist) + */ + if (!entry) return; + + /* Get the first child entry + */ + while (entry) { + /* Check if this entry could possibly match + */ + if ((x1 > (entry->x0 + 32)) && (y0 > entry->y0) && (x0 < (entry->x0 + entry->width)) && + (y1 < (entry->y0 + entry->height))) { + do_update = false; + + /* Check the exact area of the title line + */ + if ((x1 > (entry->x0 + 32)) && (y0 > entry->y0 + entry->height - 44) && + (x0 < (entry->x0 + entry->collapsed_width)) && + (y1 < (entry->y0 + entry->height))) { + do_update = true; + } + + /* Check the other lines + */ + line = 1; + test_y = entry->y0 + entry->height - 44; + while (((line * 44) < entry->height) && (!do_update)) { + /* Check this line + */ + if ((x1 > (entry->x0 + 32 + 36)) && (y1 < test_y) && (y0 > test_y - 44) && + (x0 < (entry->x0 + entry->widths[line - 1] + 32 + 36 + 16))) { + do_update = true; + } + + /* Move to the next line + */ + line++; + test_y -= 44; + } + + /* Redraw the entrys first line + */ + if (do_update) { + if (toggle) { + entry->selected = !entry->selected; + } else { + entry->selected = true; + } + if (redraw) { + xwimp_force_redraw(hotlist_window, + entry->x0, entry->y0 + entry->height - 44, + entry->x0 + entry->width, + entry->y0 + entry->height); + } + } + } + + /* Continue onwards + */ + if ((entry->child_entry) && (entry->expanded)) { + ro_gui_hotlist_selection_drag(entry->child_entry, + x0, y0, x1, y1, toggle, redraw); + } + entry = entry->next_entry; + do_update = false; + } +} + + +/** + * The end of a selection drag has been reached + * + * \param drag the final drag co-ordinates + */ +void ro_gui_hotlist_selection_drag_end(wimp_dragged *drag) { + wimp_window_state state; + int x0, y0, x1, y1; + + /* Get the window state to make everything relative + */ + state.w = hotlist_window; + wimp_get_window_state(&state); + + /* Create the relative positions + */ + x0 = drag->final.x0 - state.visible.x0 - state.xscroll; + x1 = drag->final.x1 - state.visible.x0 - state.xscroll; + y0 = drag->final.y0 - state.visible.y1 - state.yscroll; + y1 = drag->final.y1 - state.visible.y1 - state.yscroll; + + /* Make sure x0 < x1 and y0 > y1 + */ + if (x0 > x1) { + x0 ^= x1; + x1 ^= x0; + x0 ^= x1; + } + if (y0 < y1) { + y0 ^= y1; + y1 ^= y0; + y0 ^= y1; + } + + /* Update the selection state + */ + if (drag_buttons == (wimp_CLICK_SELECT << 4)) { + ro_gui_hotlist_selection_drag(root.child_entry, x0, y0, x1, y1, false, true); + } else { + ro_gui_hotlist_selection_drag(root.child_entry, x0, y0, x1, y1, true, true); + } +} + + +/** + * The end of a item moving drag has been reached + * + * \param drag the final drag co-ordinates + */ +void ro_gui_hotlist_move_drag_end(wimp_dragged *drag) { + +} + + + + + + /** * Convert the time of the last visit into a human friendly string * diff --git a/riscos/window.c b/riscos/window.c index f0b787bcc..b765b361c 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -891,7 +891,6 @@ void gui_window_start_throbber(struct gui_window* g) { void gui_window_stop_throbber(gui_window* g) { ro_gui_prepare_navigate(g); - ro_gui_hotlist_visited(g->data.browser.bw->current_content); g->throbber = 0; sprintf(g->throb_buf, "throbber%u", g->throbber); ro_gui_redraw_icon(g->data.browser.toolbar->toolbar_handle, ICON_TOOLBAR_THROBBER); -- cgit v1.2.3