From 6a2fc8cfb3a7fae75451a0183fe9575b16a9181e Mon Sep 17 00:00:00 2001 From: David Brown <dbrown@gitlab.riscosopen.org> Date: Wed, 27 Aug 1997 17:03:38 +0000 Subject: [PATCH] Revised selection model --- c/Hotlist | 281 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 220 insertions(+), 61 deletions(-) diff --git a/c/Hotlist b/c/Hotlist index 205366a..ba8d4e1 100644 --- a/c/Hotlist +++ b/c/Hotlist @@ -64,8 +64,7 @@ static hotlist_item * hotlist_newitem; /* When ever a new ite static int menu_itemno = 0; /* Item over which menu was pressed */ -static hotlist_item * selected_parent = NULL; /* The parent directory of all selected items */ -static int number_selected = 0; /* The number of items selected */ +static int menu_select = 0; /* 1 if an item had to be selected when the menu was opened */ static unsigned int last_selected_item = 0xffffffff; /* The last item which was selected */ static int hotlist_dragging = 0; /* Holds a set of values for different dragging cases (see Hotlist.h) */ @@ -128,6 +127,10 @@ static hotlist_item * _hotlist_find_selected_item (hotlist_item * list); static hotlist_item * hotlist_find_selected_item (void); static void _hotlist_count_displayed_items (hotlist_item * list); static unsigned int hotlist_count_displayed_items (hotlist_item * list); +static void _hotlist_count_selected_items (hotlist_item * list); +static unsigned int hotlist_count_selected_items (void); +static unsigned int hotlist_contents_selected(hotlist_item *item); +static unsigned int hotlist_no_contents_selected(hotlist_item *item); static void _hotlist_draw (hotlist_item * list, unsigned int first_item, unsigned int last_item, unsigned int indent); static void hotlist_draw (hotlist_item * list, unsigned int first_item, unsigned int last_item); static void _hotlist_get_max_width (hotlist_item * list, unsigned int indent); @@ -842,13 +845,36 @@ static void hotlist_delete_item(hotlist_item * item) static _kernel_oserror * hotlist_move_item(hotlist_item * source, hotlist_item * target, unsigned int position) { - /* Unlink item from directory structure */ + hotlist_item *newdir, *tempptr; + if (!(source->type == hl_directory && !hotlist_contents_selected(source->data.directory_content))) + { + /* Unlink item from directory structure */ - hotlist_unlink(source); + hotlist_unlink(source); - /* Link into new position in directory structure */ + /* Link into new position in directory structure */ - return hotlist_link(source, target, position); + return hotlist_link(source, target, position); + } + else + { + /* Special case - moving a directory whose contents are only partially selected */ + /* we can't move a directory whose contents are only partially to be moved, */ + /* there would be no where to leave the items which were not moved. */ + RetError(hotlist_new_directory(target, source->name, position, &newdir)); + source = source->data.directory_content; + while(source) + { + tempptr = source->next; + if (source->flags & HOTLIST_G_IS_SELECTED) + { + hotlist_move_item(source, newdir, HOTLIST_POSITION_END); /* move items into new directory */ + source->flags &= ~HOTLIST_G_IS_SELECTED; + } + source = tempptr; + } + } + return NULL; } /*************************************************/ @@ -915,7 +941,10 @@ static _kernel_oserror * hotlist_copy_item(hotlist_item * source, hotlist_item * while (content) { - RetError(hotlist_copy_item(content, newdir, HOTLIST_POSITION_END, NULL)); + if (content->flags & HOTLIST_G_IS_SELECTED) + { + RetError(hotlist_copy_item(content, newdir, HOTLIST_POSITION_END, NULL)); + } content = content->next; } @@ -1620,6 +1649,9 @@ static void hotlist_directory_open_close(hotlist_item *item, unsigned int itemno hotlist_get_entry_sizes(&item_height, &item_dir_width, &item_url_width); item->flags ^= HOTLIST_D_IS_OPEN; + + hotlist_clear_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + hotlist_window_preopen(already_open); show_error(window_get_wimp_handle(0, hotlist_windowid, &window_handle)); @@ -1683,7 +1715,6 @@ static void hotlist_clear_selection(void) { hotlist_clear_flags(hotlist_root->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); hotlist_redraw_now(); - number_selected = 0; } /*************************************************/ @@ -1733,7 +1764,6 @@ static _kernel_oserror * hotlist_process_click_on_item(unsigned int itemno, break; } item->flags &= ~HOTLIST_G_IS_SELECTED; - number_selected--; hotlist_redraw_items(itemno, itemno); } break; /* Double click select */ @@ -1753,7 +1783,6 @@ static _kernel_oserror * hotlist_process_click_on_item(unsigned int itemno, break; } item->flags &= ~HOTLIST_G_IS_SELECTED; - number_selected--; hotlist_redraw_items(itemno, itemno); } break; /* Double click adjust */ @@ -1766,9 +1795,7 @@ static _kernel_oserror * hotlist_process_click_on_item(unsigned int itemno, if (!(item->flags & HOTLIST_G_IS_SELECTED)) { item->flags |= HOTLIST_G_IS_SELECTED; - number_selected++; - selected_parent = item->parent; last_selected_item = itemno; } hotlist_start_drag(); @@ -1783,30 +1810,33 @@ static _kernel_oserror * hotlist_process_click_on_item(unsigned int itemno, else { hotlist_clear_selection(); - item->flags |= HOTLIST_G_IS_SELECTED; - selected_parent = item->parent; - number_selected++; - hotlist_redraw_items(itemno, itemno); + item->flags |= HOTLIST_G_IS_SELECTED | HOTLIST_G_REDRAW_NOW; + if (item->type == hl_directory) + { + hotlist_set_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + } + hotlist_redraw_now(); } last_selected_item = itemno; break; case 256: /* Click adjust */ - if (selected_parent != item->parent && item->type != hl_url) hotlist_clear_selection(); item->flags ^= HOTLIST_G_IS_SELECTED; - if (item->flags & HOTLIST_G_IS_SELECTED) - { - number_selected++; - } - else + item->flags |= HOTLIST_G_REDRAW_NOW; + last_selected_item = itemno; + if (item->type == hl_directory) { - number_selected--; + if (item->flags & HOTLIST_G_IS_SELECTED) + { + hotlist_set_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + } + else + { + hotlist_clear_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + } } - hotlist_redraw_items(itemno, itemno); - selected_parent = item->parent; - last_selected_item = itemno; + hotlist_redraw_now(); break; - } return NULL; @@ -1998,10 +2028,10 @@ static int hotlist_mouse_click_handler(int event_code, WimpPollBlock *event, IdB static int hotlist_menuclose_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle) { ObjectId submenu_id; - if (number_selected == -1) + if (menu_select) { hotlist_clear_selection(); - number_selected = 0; + menu_select = 0; } show_error(menu_get_sub_menu_show(0, id_block->self_id, HOTLIST_URL_MENUITEM, &submenu_id)); if (submenu_id) show_error(toolbox_delete_object(0, submenu_id)); @@ -2017,7 +2047,7 @@ void hotlist_setmenu_details(ObjectId menuid) char entrytext[32]; ObjectId submenu_id; - switch(number_selected) + switch(hotlist_count_selected_items()) { case 0: menu_set_entry_text(0, menuid, HOTLIST_URL_MENUITEM, "URL ''"); @@ -2094,7 +2124,7 @@ static int hotlist_menuopen_handler(int event_code, ToolboxEvent * event, IdBloc menu_itemno = -pointerblock.y / item_height; } - if (number_selected == 0) + if (hotlist_count_selected_items() == 0) { item = hotlist_find_item(hotlist_root->data.directory_content, menu_itemno); @@ -2106,8 +2136,7 @@ static int hotlist_menuopen_handler(int event_code, ToolboxEvent * event, IdBloc if (item && pointerblock.x >= xmin && pointerblock.x <= xmax) { item->flags |= HOTLIST_G_IS_SELECTED; - selected_parent = item->parent; - number_selected = -1; + menu_select = 1; hotlist_redraw_items(menu_itemno, menu_itemno); } } @@ -2759,6 +2788,10 @@ _kernel_oserror * hotlist_initialise(void) HotlistNewRenameDirectoryCancel, hotlist_reset_directory_handler, NULL)); + +hotlist_load("InetDBase:hotlist\n"); +hotlist_open(Toolbox_ShowObject_Default, 0, 0); + return NULL; } @@ -2827,11 +2860,10 @@ static int hotlist_menu_selectall_handler(int event_code, ToolboxEvent *event, I if (item && item->parent) { item = item->parent->data.directory_content; - number_selected = 0; while(item) { item->flags |= HOTLIST_G_IS_SELECTED | HOTLIST_G_REDRAW_NOW; - number_selected++; + if (item->type == hl_directory) hotlist_set_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); item = item->next; } hotlist_redraw_now(); @@ -2919,13 +2951,12 @@ static int hotlist_menu_delete_handler(int event_code, ToolboxEvent *event, IdBl noitems = hotlist_count_displayed_items(hotlist_root->data.directory_content); - if (!number_selected) return 0; + if (!hotlist_count_selected_items()) return 0; while((item = hotlist_find_selected_item())!=NULL) { hotlist_delete_item(item); } - number_selected = 0; hotlist_redraw_items(0, noitems); hotlist_window_preopen(already_open); toolbox_hide_object(0, id_block->ancestor_id); @@ -3340,7 +3371,7 @@ static _kernel_oserror *_hotlist_start_drag(void) hotlist_get_shape(&xmin, &xmax, item); item = item->next; - if (number_selected > 1) + if (hotlist_count_selected_items() > 1) { while(item) { @@ -3371,7 +3402,20 @@ static _kernel_oserror *_hotlist_start_drag(void) if (_kernel_osbyte(161, 28, 0) & (1<<(8+1))) /* solid drag */ { - if (number_selected == 1) + item = hotlist_find_selected_item(); + + if ( + (hotlist_count_selected_items() == 1 && item->type == hl_url) || + ( + hotlist_count_selected_items() == 1 && + item->type == hl_directory && + ( + !(item->flags & HOTLIST_D_IS_OPEN) || + hotlist_no_contents_selected(item->data.directory_content) || + item->data.directory_content == NULL + ) + ) + ) { box.dragging_box.xmin = xmin-xorigin; /* box shape */ box.dragging_box.ymin = bottom-yorigin; @@ -3578,6 +3622,8 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, /* Check to see if moving the selection to this position is acceptable -----------------------*/ + /* This section is not sufficient for the new selection model ///////// */ + tempitem = sourceitem; while(tempitem) { @@ -3604,8 +3650,12 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, if (!shift) { /* Move selected items */ + hotlist_move_item(sourceitem, targetitem, position); /* Move first item to specified position */ /* before/after/in target */ + + if (sourceitem->type == hl_directory) hotlist_clear_flags(sourceitem->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + targetitem = sourceitem; while((sourceitem = hotlist_find_selected_item()) != NULL) @@ -3613,14 +3663,19 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, sourceitem->flags &= ~HOTLIST_G_IS_SELECTED; hotlist_move_item(sourceitem, targetitem, HOTLIST_POSITION_AFTER); /* Move all subsequent items to follow */ /* first moved item */ + if (sourceitem->type == hl_directory) hotlist_clear_flags(sourceitem->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); targetitem = sourceitem; } } else { /* Copy selected items */ + + hotlist_copy_item(sourceitem, targetitem, position, &targetitem); /* Copy first item to specified position */ /* before/after/in target */ + if (sourceitem->type == hl_directory) hotlist_clear_flags(sourceitem->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + while((sourceitem = hotlist_find_selected_item()) != NULL) { sourceitem->flags &= ~HOTLIST_G_IS_SELECTED; @@ -3628,12 +3683,10 @@ static int hotlist_drag_completed_handler(int event_code, WimpPollBlock *event, targetitem, /* first copied item */ HOTLIST_POSITION_AFTER, &targetitem); + if (sourceitem->type == hl_directory) hotlist_clear_flags(sourceitem->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); } } - number_selected = 0; - selected_parent = NULL; - bottom2 = hotlist_count_displayed_items(hotlist_root->data.directory_content); if (bottom2 > bottom) bottom = bottom2; hotlist_redraw_items(top, bottom); @@ -3840,6 +3893,16 @@ _kernel_oserror *hotlist_selection_box_start(void) return NULL; } +/*************************************************/ +/* hotlist_null_drag_select_handler() */ +/* */ +/* This function is called as a null handler, */ +/* it is responsible for selecting for selecting */ +/* and deselecting items within and outside of */ +/* the rubber box drag started by */ +/* hotlist_selection_box_start */ +/*************************************************/ + int hotlist_null_drag_select_handler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle) { WimpGetPointerInfoBlock pointerblock; @@ -3889,34 +3952,28 @@ int hotlist_null_drag_select_handler(int event_code, WimpPollBlock *event, IdBlo if (itemno >= item_min && itemno <= item_max) { hotlist_get_shape(&itemxmin, &itemxmax, item); - if (number_selected == 0) + if ((!(maxx < itemxmin || minx > itemxmax))) { - if (!(maxx < itemxmin || minx > itemxmax) && (!(item->flags & HOTLIST_G_IS_SELECTED))) + if (!(item->flags & HOTLIST_G_IS_SELECTED)) { item->flags |= HOTLIST_G_IS_SELECTED; hotlist_redraw_items(itemno, itemno); - selected_parent = item->parent; - number_selected++; + if (item->type == hl_directory && !(item->flags & HOTLIST_D_IS_OPEN)) /* If directory is closed select everything in it */ + { + hotlist_set_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED); + hotlist_clear_flags(item->data.directory_content, hl_ALL, HOTLIST_G_REDRAW_NOW); + } } } else { - if (!(maxx < itemxmin || minx > itemxmax)) - { - if ((selected_parent == item->parent || item->type == hl_url) && (!(item->flags & HOTLIST_G_IS_SELECTED))) - { - item->flags |= HOTLIST_G_IS_SELECTED; - hotlist_redraw_items(itemno, itemno); - number_selected++; - } - } - else + if (item->flags & HOTLIST_G_IS_SELECTED) { - if (item->flags & HOTLIST_G_IS_SELECTED) + item->flags &= ~HOTLIST_G_IS_SELECTED; + hotlist_redraw_items(itemno, itemno); + if (item->type == hl_directory && !(item->flags & HOTLIST_D_IS_OPEN)) /* If directory is closed unselect everything in it */ { - item->flags &= ~HOTLIST_G_IS_SELECTED; - hotlist_redraw_items(itemno, itemno); - number_selected--; + hotlist_clear_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED | HOTLIST_G_REDRAW_NOW); } } } @@ -3927,7 +3984,10 @@ int hotlist_null_drag_select_handler(int event_code, WimpPollBlock *event, IdBlo { item->flags &= ~HOTLIST_G_IS_SELECTED; hotlist_redraw_items(itemno, itemno); - number_selected--; + if (item->type == hl_directory && !(item->flags & HOTLIST_D_IS_OPEN)) /* If directory is closed unselect everything in it */ + { + hotlist_clear_flags(item->data.directory_content, hl_ALL, HOTLIST_G_IS_SELECTED | HOTLIST_G_REDRAW_NOW); + } } } } @@ -3935,3 +3995,102 @@ int hotlist_null_drag_select_handler(int event_code, WimpPollBlock *event, IdBlo return 0; } + + +/*************************************************/ +/* _hotlist_count_selected_items() */ +/* */ +/* This routine does all the work for */ +/* hotlist_count_selected_items() */ +/*************************************************/ + +static void _hotlist_count_selected_items(hotlist_item *list) +{ + while(list) + { + if (list->flags & HOTLIST_G_IS_SELECTED) + { + item_number++; + } + else /* Only recurse through directories which are not selected */ + { + if (list->type == hl_directory) + { + _hotlist_count_selected_items(list->data.directory_content); + } + } + list = list->next; + } +} + +/*************************************************/ +/* hotlist_count_selected_items() */ +/* */ +/* This routine counts the number of selected */ +/* items */ +/* */ +/* Parameters: Pointer to a hotlist_item */ +/* */ +/* Returns: the number of selected items */ +/*************************************************/ + +static unsigned int hotlist_count_selected_items(void) +{ + item_number = 0; + _hotlist_count_selected_items(hotlist_root->data.directory_content); + return item_number; +} + +/*************************************************/ +/* hotlist_contents_selected() */ +/* */ +/* Checks if all items and subdirectories are */ +/* selected */ +/* */ +/* Parameters: Pointer to the first hotlist_item */ +/* to check */ +/* */ +/* Returns: 1 if all items are selected */ +/* 0 if there are unselected items */ +/*************************************************/ + +static unsigned int hotlist_contents_selected(hotlist_item *item) +{ + while(item) + { + if (!item->flags & HOTLIST_G_IS_SELECTED) return 0; + if (item->type == hl_directory) + { + if (!hotlist_contents_selected(item->data.directory_content)) return 0; + } + item = item->next; + } + return 1; +} + +/*************************************************/ +/* hotlist_no_contents_selected() */ +/* */ +/* Checks if all items and subdirectories are */ +/* selected */ +/* */ +/* Parameters: Pointer to the first hotlist_item */ +/* to check */ +/* */ +/* Returns: 1 if all items are selected */ +/* 0 if there are unselected items */ +/*************************************************/ + +static unsigned int hotlist_no_contents_selected(hotlist_item *item) +{ + while(item) + { + if (item->flags & HOTLIST_G_IS_SELECTED) return 0; + if (item->type == hl_directory) + { + if (!hotlist_no_contents_selected(item->data.directory_content)) return 0; + } + item = item->next; + } + return 1; +} -- GitLab