|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 static list_struct *list_head = NULL; 00035 static list_struct *list_tail = NULL; 00037 static int old_scrollbar_pos = 0; 00038 00039 static int list_handle_key(list_struct *list, SDLKey key); 00040 00044 static void list_draw_frame(list_struct *list) 00045 { 00046 draw_frame(list->surface, list->x + list->frame_offset, LIST_ROWS_START(list) + list->frame_offset, list->width, LIST_ROWS_HEIGHT(list)); 00047 } 00048 00054 static void list_row_color(list_struct *list, int row, SDL_Rect box) 00055 { 00056 if (row & 1) 00057 { 00058 SDL_FillRect(list->surface, &box, SDL_MapRGB(list->surface->format, 0x55, 0x55, 0x55)); 00059 } 00060 else 00061 { 00062 SDL_FillRect(list->surface, &box, SDL_MapRGB(list->surface->format, 0x45, 0x45, 0x45)); 00063 } 00064 } 00065 00070 static void list_row_highlight(list_struct *list, SDL_Rect box) 00071 { 00072 SDL_FillRect(list->surface, &box, SDL_MapRGB(list->surface->format, 0x00, 0x80, 0x00)); 00073 } 00074 00079 static void list_row_selected(list_struct *list, SDL_Rect box) 00080 { 00081 SDL_FillRect(list->surface, &box, SDL_MapRGB(list->surface->format, 0x00, 0x00, 0xef)); 00082 } 00083 00090 list_struct *list_get_focused() 00091 { 00092 list_struct *tmp; 00093 00094 /* Try to find a focused list. */ 00095 for (tmp = list_head; tmp; tmp = tmp->next) 00096 { 00097 if (tmp->focus) 00098 { 00099 return tmp; 00100 } 00101 } 00102 00103 /* Try to set the focus to the servers list, if possible. */ 00104 tmp = list_exists(LIST_SERVERS); 00105 00106 if (tmp) 00107 { 00108 tmp->focus = 1; 00109 return tmp; 00110 } 00111 00112 /* Failsafe in case there are lists, but none with active focus. */ 00113 if (list_head) 00114 { 00115 list_head->focus = 1; 00116 return list_head; 00117 } 00118 00119 return NULL; 00120 } 00121 00125 void list_set_focus(list_struct *list) 00126 { 00127 list_struct *tmp; 00128 00129 /* Already focused, nothing to do. */ 00130 if (list->focus) 00131 { 00132 return; 00133 } 00134 00135 /* Remove focus from previously focused list. */ 00136 for (tmp = list_head; tmp; tmp = tmp->next) 00137 { 00138 if (tmp != list) 00139 { 00140 tmp->focus = 0; 00141 } 00142 } 00143 00144 list->focus = 1; 00145 } 00146 00152 void list_set_parent(list_struct *list, int px, int py) 00153 { 00154 list->px = px; 00155 list->py = py; 00156 } 00157 00165 list_struct *list_create(uint32 id, uint32 max_rows, uint32 cols, int spacing) 00166 { 00167 list_struct *list = calloc(1, sizeof(list_struct)); 00168 00169 if (max_rows == 0) 00170 { 00171 LOG(llevBug, "list_create(): Attempted to create a list with 0 max rows, changing to 1.\n"); 00172 max_rows = 1; 00173 } 00174 00175 /* Store the values. */ 00176 list->id = id; 00177 list->max_rows = max_rows; 00178 list->cols = cols; 00179 list->spacing = spacing; 00180 list->font = FONT_SANS10; 00181 list->surface = ScreenSurface; 00182 00183 /* Initialize defaults. */ 00184 list->frame_offset = -2; 00185 list->header_height = 12; 00186 list->row_selected = 1; 00187 list->repeat_key = -1; 00188 00189 /* Generic functions. */ 00190 list->draw_frame_func = list_draw_frame; 00191 list->row_color_func = list_row_color; 00192 list->row_highlight_func = list_row_highlight; 00193 list->row_selected_func = list_row_selected; 00194 00195 /* Initialize column data. */ 00196 list->col_widths = calloc(1, sizeof(*list->col_widths) * list->cols); 00197 list->col_spacings = calloc(1, sizeof(*list->col_spacings) * list->cols); 00198 list->col_names = calloc(1, sizeof(*list->col_names) * list->cols); 00199 list->col_centered = calloc(1, sizeof(*list->col_centered) * list->cols); 00200 00201 /* First list. */ 00202 if (!list_head) 00203 { 00204 /* As this is the first list, by default it will have the focus. */ 00205 list->focus = 1; 00206 list_head = list; 00207 list->prev = NULL; 00208 } 00209 else 00210 { 00211 list_tail->next = list; 00212 list->prev = list_tail; 00213 } 00214 00215 list_tail = list; 00216 list->next = NULL; 00217 00218 return list; 00219 } 00220 00228 void list_add(list_struct *list, uint32 row, uint32 col, const char *str) 00229 { 00230 if (!list) 00231 { 00232 return; 00233 } 00234 00235 if (col > list->cols) 00236 { 00237 LOG(llevBug, "list_add(): Attempted to add column #%u, but columns max is %u.\n", col, list->cols); 00238 return; 00239 } 00240 00241 /* Add new rows. */ 00242 if (row + 1 > list->rows) 00243 { 00244 uint32 i; 00245 00246 /* Update rows count and resize the array of rows. */ 00247 list->rows = row + 1; 00248 list->text = realloc(list->text, sizeof(*list->text) * list->rows); 00249 00250 /* Allocate columns for the new row(s). */ 00251 for (i = row; i < list->rows; i++) 00252 { 00253 list->text[i] = calloc(1, sizeof(**list->text) * list->cols); 00254 } 00255 } 00256 00257 list->text[row][col] = strdup(str); 00258 } 00259 00264 void list_remove_row(list_struct *list, uint32 row) 00265 { 00266 uint32 col, row2; 00267 00268 /* Sanity checks. */ 00269 if (!list || !list->text || row >= list->rows) 00270 { 00271 return; 00272 } 00273 00274 /* Free the columns of the row that is being removed. */ 00275 for (col = 0; col < list->cols; col++) 00276 { 00277 free(list->text[row][col]); 00278 } 00279 00280 /* If there are any rows below the one that is being removed, they 00281 * need to be moved up. */ 00282 for (row2 = row + 1; row2 < list->rows; row2++) 00283 { 00284 for (col = 0; col < list->cols; col++) 00285 { 00286 list->text[row2 - 1][col] = list->text[row2][col]; 00287 } 00288 } 00289 00290 list->rows--; 00291 list->text = realloc(list->text, sizeof(*list->text) * list->rows); 00292 } 00293 00303 void list_set_column(list_struct *list, uint32 col, int width, int spacing, const char *name, int centered) 00304 { 00305 if (col > list->cols) 00306 { 00307 LOG(llevBug, "list_set_column(): Attempted to change column #%u, but columns max is %u.\n", col, list->cols); 00308 return; 00309 } 00310 00311 /* Set width. */ 00312 if (width != -1) 00313 { 00314 list->col_widths[col] = width; 00315 list->width += width; 00316 } 00317 00318 /* Set spacing. */ 00319 if (spacing != -1) 00320 { 00321 list->col_spacings[col] = spacing; 00322 list->width += spacing; 00323 } 00324 00325 /* Set the column's name. */ 00326 if (name) 00327 { 00328 /* There shouldn't be one previously, but just in case. */ 00329 if (list->col_names[col]) 00330 { 00331 free(list->col_names[col]); 00332 } 00333 00334 list->col_names[col] = strdup(name); 00335 } 00336 00337 /* Is the column centered? */ 00338 if (centered != -1) 00339 { 00340 list->col_centered[col] = centered; 00341 } 00342 } 00343 00348 void list_set_font(list_struct *list, int font) 00349 { 00350 list->font = font; 00351 } 00352 00356 void list_scrollbar_enable(list_struct *list) 00357 { 00358 list->scrollbar = 1; 00359 } 00360 00366 static int list_scrollbar_get_size(list_struct *list, SDL_Rect *box) 00367 { 00368 uint32 col; 00369 00370 if (!list->scrollbar) 00371 { 00372 return 0; 00373 } 00374 00375 box->x = list->x + list->frame_offset + 1; 00376 box->y = LIST_ROWS_START(list) + list->frame_offset; 00377 box->w = LIST_SCROLLBAR_WIDTH; 00378 box->h = LIST_ROW_HEIGHT(list) * list->max_rows; 00379 00380 for (col = 0; col < list->cols; col++) 00381 { 00382 box->x += list->col_widths[col] + list->col_spacings[col]; 00383 } 00384 00385 return 1; 00386 } 00387 00394 static int list_slider_get_size(list_struct *list, SDL_Rect *box) 00395 { 00396 if (!list_scrollbar_get_size(list, box)) 00397 { 00398 return 0; 00399 } 00400 00401 box->x += 1; 00402 box->y += 1; 00403 box->w -= 1; 00404 box->h -= 1; 00405 00406 if (list->rows > list->max_rows) 00407 { 00408 int scroll; 00409 00410 scroll = list->max_rows + list->row_offset; 00411 list->scrollbar_h = box->h * list->max_rows / list->rows; 00412 list->scrollbar_y = ((scroll - list->max_rows) * box->h) / list->rows; 00413 00414 if (list->scrollbar_h < 1) 00415 { 00416 list->scrollbar_h = 1; 00417 } 00418 00419 if (scroll - list->max_rows > 0 && list->scrollbar_y + list->scrollbar_h < box->h) 00420 { 00421 list->scrollbar_y++; 00422 } 00423 00424 box->h = list->scrollbar_h; 00425 box->y += list->scrollbar_y; 00426 } 00427 00428 return 1; 00429 } 00430 00434 static void list_scrollbar_render(list_struct *list) 00435 { 00436 SDL_Rect scrollbar_box; 00437 int mx, my; 00438 00439 if (!list_scrollbar_get_size(list, &scrollbar_box)) 00440 { 00441 return; 00442 } 00443 00444 SDL_GetMouseState(&mx, &my); 00445 00446 draw_frame(list->surface, scrollbar_box.x, scrollbar_box.y, scrollbar_box.w, scrollbar_box.h); 00447 00448 list_slider_get_size(list, &scrollbar_box); 00449 00450 mx -= list->px; 00451 my -= list->py; 00452 00453 if (mx >= scrollbar_box.x && mx < scrollbar_box.x + scrollbar_box.w && my >= scrollbar_box.y && my < scrollbar_box.y + scrollbar_box.h) 00454 { 00455 SDL_FillRect(list->surface, &scrollbar_box, SDL_MapRGBA(list->surface->format, 175, 154, 110, 255)); 00456 } 00457 else 00458 { 00459 SDL_FillRect(list->surface, &scrollbar_box, SDL_MapRGBA(list->surface->format, 157, 139, 98, 255)); 00460 } 00461 } 00462 00468 void list_show(list_struct *list, int x, int y) 00469 { 00470 uint32 row, col; 00471 int w = 0, extra_width = 0; 00472 SDL_Rect box; 00473 00474 if (!list) 00475 { 00476 return; 00477 } 00478 00479 list->x = x; 00480 list->y = y; 00481 00482 /* Keys needing repeat? */ 00483 if (list->repeat_key != -1) 00484 { 00485 if (list->repeat_key_ticks + KEY_REPEAT_DELAY - 5 < LastTick) 00486 { 00487 while ((list->repeat_key_ticks += KEY_REPEAT_DELAY - 5) < LastTick) 00488 { 00489 list_handle_key(list, list->repeat_key); 00490 } 00491 } 00492 } 00493 00494 /* Draw a frame, if needed. */ 00495 if (list->draw_frame_func) 00496 { 00497 list->draw_frame_func(list); 00498 } 00499 00500 /* Draw the column names. */ 00501 for (col = 0; col < list->cols; col++) 00502 { 00503 extra_width = 0; 00504 00505 /* Center it? */ 00506 if (list->col_centered[col]) 00507 { 00508 extra_width = list->col_widths[col] / 2 - string_get_width(list->font, list->col_names[col], 0) / 2; 00509 } 00510 00511 /* Actually draw the column name. */ 00512 if (list->col_names[col]) 00513 { 00514 string_blt_shadow(list->surface, list->font, list->col_names[col], list->x + w + extra_width, list->y, list->focus ? COLOR_WHITE : COLOR_GRAY, COLOR_BLACK, 0, NULL); 00515 } 00516 00517 w += list->col_widths[col] + list->col_spacings[col]; 00518 } 00519 00520 /* Initialize default values for coloring rows. */ 00521 box.x = list->x + list->frame_offset; 00522 box.w = list->width; 00523 box.h = LIST_ROW_HEIGHT(list); 00524 00525 list_scrollbar_render(list); 00526 00527 /* Doing coloring of each row? */ 00528 if (list->row_color_func) 00529 { 00530 for (row = 0; row < list->max_rows; row++) 00531 { 00532 box.y = LIST_ROWS_START(list) + (row * LIST_ROW_HEIGHT(list)) + list->frame_offset; 00533 list->row_color_func(list, row, box); 00534 } 00535 } 00536 00537 /* Start printing out rows from the offset to the maximum. */ 00538 for (row = list->row_offset; row < list->rows; row++) 00539 { 00540 /* Stop if we reached maximum number of visible rows. */ 00541 if (LIST_ROW_OFFSET(row, list) == list->max_rows) 00542 { 00543 break; 00544 } 00545 00546 /* Color selected row. */ 00547 if (list->row_selected_func && (row + 1) == list->row_selected) 00548 { 00549 box.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)) + list->frame_offset; 00550 list->row_selected_func(list, box); 00551 } 00552 /* Color highlighted row. */ 00553 else if (list->row_highlight_func && (row + 1) == list->row_highlighted) 00554 { 00555 box.y = LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)) + list->frame_offset; 00556 list->row_highlight_func(list, box); 00557 } 00558 00559 w = 0; 00560 00561 /* Show all the columns. */ 00562 for (col = 0; col < list->cols; col++) 00563 { 00564 /* Is there any text to show? */ 00565 if (list->text[row][col]) 00566 { 00567 const char *text_color; 00568 SDL_Rect text_rect; 00569 00570 extra_width = 0; 00571 00572 /* Center it. */ 00573 if (list->col_centered[col]) 00574 { 00575 extra_width = list->col_widths[col] / 2 - string_get_width(list->font, list->text[row][col], TEXT_WORD_WRAP) / 2; 00576 } 00577 00578 text_color = list->focus ? COLOR_WHITE : COLOR_GRAY; 00579 00580 if (list->text_color_hook) 00581 { 00582 text_color = list->text_color_hook(list, text_color, row, col); 00583 } 00584 00585 /* Add width limit on the string. */ 00586 text_rect.w = list->col_widths[col] + list->col_spacings[col]; 00587 text_rect.h = LIST_ROW_HEIGHT(list); 00588 /* Output the text. */ 00589 string_blt_shadow(list->surface, list->font, list->text[row][col], list->x + w + extra_width, LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)), text_color, COLOR_BLACK, TEXT_WORD_WRAP | list->text_flags, &text_rect); 00590 } 00591 00592 if (list->post_column_func) 00593 { 00594 list->post_column_func(list, row, col); 00595 } 00596 00597 w += list->col_widths[col] + list->col_spacings[col]; 00598 } 00599 } 00600 } 00601 00605 void list_clear_rows(list_struct *list) 00606 { 00607 uint32 row, col; 00608 00609 if (!list || !list->text) 00610 { 00611 return; 00612 } 00613 00614 /* Free the texts. */ 00615 for (row = 0; row < list->rows; row++) 00616 { 00617 for (col = 0; col < list->cols; col++) 00618 { 00619 if (list->text[row][col]) 00620 { 00621 free(list->text[row][col]); 00622 } 00623 } 00624 00625 free(list->text[row]); 00626 } 00627 00628 free(list->text); 00629 list->text = NULL; 00630 list->rows = 0; 00631 } 00632 00636 void list_clear(list_struct *list) 00637 { 00638 list_clear_rows(list); 00639 00640 list->row_selected = 1; 00641 list->row_highlighted = 0; 00642 list->row_offset = 0; 00643 } 00644 00649 void list_offsets_ensure(list_struct *list) 00650 { 00651 if (list->row_selected >= list->rows) 00652 { 00653 list->row_selected = list->rows; 00654 } 00655 00656 if (list->rows < list->max_rows) 00657 { 00658 list->row_offset = 0; 00659 } 00660 else if (list->row_offset >= list->rows - list->max_rows) 00661 { 00662 list->row_offset = list->rows - list->max_rows; 00663 } 00664 } 00665 00670 void list_remove(list_struct *list) 00671 { 00672 uint32 col; 00673 00674 if (!list) 00675 { 00676 return; 00677 } 00678 00679 /* Remove it from the list. */ 00680 if (!list->prev) 00681 { 00682 list_head = list->next; 00683 } 00684 else 00685 { 00686 list->prev->next = list->next; 00687 } 00688 00689 if (!list->next) 00690 { 00691 list_tail = list->prev; 00692 } 00693 else 00694 { 00695 list->next->prev = list->prev; 00696 } 00697 00698 /* Removing the focused list, try to update the focus. */ 00699 if (list->focus) 00700 { 00701 list_get_focused(); 00702 } 00703 00704 list_clear(list); 00705 00706 free(list->col_widths); 00707 free(list->col_spacings); 00708 free(list->col_centered); 00709 00710 /* Free column names. */ 00711 for (col = 0; col < list->cols; col++) 00712 { 00713 if (list->col_names[col]) 00714 { 00715 free(list->col_names[col]); 00716 } 00717 } 00718 00719 free(list->col_names); 00720 free(list); 00721 } 00722 00725 void list_remove_all() 00726 { 00727 /* Loop until there is nothing left. */ 00728 while (list_head) 00729 { 00730 list_remove(list_head); 00731 } 00732 } 00733 00739 static void list_scroll(list_struct *list, int up, int scroll) 00740 { 00741 /* The actual values are unsigned. Changing them to signed here 00742 * makes it easier to check for overflows below. */ 00743 sint32 row_selected = list->row_selected, row_offset = list->row_offset; 00744 sint32 max_rows, rows; 00745 00746 /* Number of rows. */ 00747 rows = list->rows; 00748 /* Number of visible rows. */ 00749 max_rows = list->max_rows; 00750 00751 /* Scrolling upward. */ 00752 if (up) 00753 { 00754 row_selected -= scroll; 00755 00756 /* Adjust row offset if needed. */ 00757 if (row_offset > (row_selected - 1)) 00758 { 00759 row_offset -= scroll; 00760 } 00761 } 00762 /* Downward otherwise. */ 00763 else 00764 { 00765 row_selected += scroll; 00766 00767 /* Adjust row offset if needed. */ 00768 if (row_selected >= max_rows + row_offset) 00769 { 00770 row_offset += scroll; 00771 } 00772 } 00773 00774 /* Make sure row offset is within bounds. */ 00775 if (row_offset < 0 || rows < max_rows) 00776 { 00777 row_offset = 0; 00778 } 00779 else if (row_offset >= rows - max_rows) 00780 { 00781 row_offset = rows - max_rows; 00782 } 00783 00784 /* Make sure selected row is within bounds. */ 00785 if (row_selected < 1) 00786 { 00787 row_selected = 1; 00788 } 00789 else if (row_selected >= rows) 00790 { 00791 row_selected = list->rows; 00792 } 00793 00794 /* Set the values. */ 00795 list->row_selected = row_selected; 00796 list->row_offset = row_offset; 00797 } 00798 00804 static int list_handle_key(list_struct *list, SDLKey key) 00805 { 00806 if (list->key_event_func) 00807 { 00808 int ret = list->key_event_func(list, key); 00809 00810 if (ret != -1) 00811 { 00812 return ret; 00813 } 00814 } 00815 00816 switch (key) 00817 { 00818 /* Up arrow. */ 00819 case SDLK_UP: 00820 list_scroll(list, 1, 1); 00821 break; 00822 00823 /* Down arrow. */ 00824 case SDLK_DOWN: 00825 list_scroll(list, 0, 1); 00826 break; 00827 00828 /* Page up. */ 00829 case SDLK_PAGEUP: 00830 list_scroll(list, 1, list->max_rows); 00831 break; 00832 00833 /* Page down. */ 00834 case SDLK_PAGEDOWN: 00835 list_scroll(list, 0, list->max_rows); 00836 break; 00837 00838 /* Esc, let the list creator handle this if they want to. */ 00839 case SDLK_ESCAPE: 00840 if (list->handle_esc_func) 00841 { 00842 list->handle_esc_func(list); 00843 } 00844 00845 return 0; 00846 00847 /* Enter. */ 00848 case SDLK_RETURN: 00849 case SDLK_KP_ENTER: 00850 if (list->handle_enter_func) 00851 { 00852 list->handle_enter_func(list); 00853 } 00854 00855 return 0; 00856 00857 /* Unhandled key. */ 00858 default: 00859 return 0; 00860 } 00861 00862 return 1; 00863 } 00864 00870 int list_handle_keyboard(list_struct *list, SDL_KeyboardEvent *event) 00871 { 00872 if (event->type == SDL_KEYDOWN) 00873 { 00874 /* Rotate between lists using tab. */ 00875 if (event->keysym.sym == SDLK_TAB) 00876 { 00877 /* Go backwards? */ 00878 if (event->keysym.mod & KMOD_SHIFT) 00879 { 00880 /* Previous list. */ 00881 if (list->prev) 00882 { 00883 list_set_focus(list->prev); 00884 } 00885 /* Last one. */ 00886 else 00887 { 00888 list_set_focus(list_tail); 00889 } 00890 } 00891 else 00892 { 00893 /* Next list exists? */ 00894 if (list->next) 00895 { 00896 list_set_focus(list->next); 00897 } 00898 /* First one otherwise. */ 00899 else 00900 { 00901 list_set_focus(list_head); 00902 } 00903 } 00904 00905 return 1; 00906 } 00907 00908 /* Handle the key. */ 00909 if (list_handle_key(list, event->keysym.sym)) 00910 { 00911 /* Store the pressed key and ticks for repeating. */ 00912 list->repeat_key = event->keysym.sym; 00913 list->repeat_key_ticks = LastTick + KEY_REPEAT_DELAY_INIT; 00914 } 00915 00916 return 1; 00917 } 00918 /* Key was released. */ 00919 else if (event->type == SDL_KEYUP) 00920 { 00921 /* If the key is the one we stored previously, reset it. */ 00922 if (event->keysym.sym == (SDLKey) list->repeat_key) 00923 { 00924 list->repeat_key = -1; 00925 } 00926 } 00927 00928 return 0; 00929 } 00930 00935 int lists_handle_keyboard(SDL_KeyboardEvent *event) 00936 { 00937 list_struct *list = list_get_focused(); 00938 00939 /* No list exists. */ 00940 if (!list) 00941 { 00942 return 0; 00943 } 00944 00945 if (list->surface != ScreenSurface) 00946 { 00947 return 0; 00948 } 00949 00950 return list_handle_keyboard(list, event); 00951 } 00952 00961 int list_handle_mouse(list_struct *list, int mx, int my, SDL_Event *event) 00962 { 00963 uint32 row; 00964 00965 if (!LIST_MOUSE_OVER(list, mx, my) && !list->scrollbar_dragging) 00966 { 00967 return 0; 00968 } 00969 00970 /* Left mouse button was pressed, update focused list. */ 00971 if (event->type == SDL_MOUSEBUTTONDOWN) 00972 { 00973 list_set_focus(list); 00974 00975 if (event->button.button == SDL_BUTTON_LEFT) 00976 { 00977 SDL_Rect scrollbar_box; 00978 00979 if (list_slider_get_size(list, &scrollbar_box) && mx >= scrollbar_box.x && mx < scrollbar_box.x + scrollbar_box.w && my >= scrollbar_box.y && my < scrollbar_box.y + list->scrollbar_h) 00980 { 00981 old_scrollbar_pos = event->motion.y - list->scrollbar_y; 00982 list->scrollbar_dragging = 1; 00983 return 1; 00984 } 00985 } 00986 } 00987 else if (event->type == SDL_MOUSEBUTTONUP) 00988 { 00989 if (event->button.button == SDL_BUTTON_LEFT) 00990 { 00991 list->scrollbar_dragging = 0; 00992 } 00993 00994 return 1; 00995 } 00996 else if (event->type == SDL_MOUSEMOTION) 00997 { 00998 if (list->scrollbar_dragging && !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_LEFT)) 00999 { 01000 list->scrollbar_dragging = 0; 01001 return 0; 01002 } 01003 01004 if (list->scrollbar_dragging) 01005 { 01006 SDL_Rect scrollbar_box; 01007 01008 if (!list_scrollbar_get_size(list, &scrollbar_box)) 01009 { 01010 return 0; 01011 } 01012 01013 list->scrollbar_y = event->motion.y - old_scrollbar_pos; 01014 01015 if (list->scrollbar_y > scrollbar_box.h - list->scrollbar_h) 01016 { 01017 list->scrollbar_y = scrollbar_box.h - list->scrollbar_h; 01018 } 01019 01020 list->row_offset = MIN(list->rows - list->max_rows, MAX(0, list->scrollbar_y) * list->rows / scrollbar_box.h); 01021 list->row_selected = list->max_rows + list->row_offset - 1; 01022 return 1; 01023 } 01024 } 01025 01026 if (mx >= list->x + list->width) 01027 { 01028 return 1; 01029 } 01030 01031 /* No row is highlighted now. Will be switched back on as needed 01032 * below. */ 01033 list->row_highlighted = 0; 01034 01035 /* Handle mouse wheel for scrolling. */ 01036 if (event->button.button == SDL_BUTTON_WHEELUP || event->button.button == SDL_BUTTON_WHEELDOWN) 01037 { 01038 list_scroll(list, event->button.button == SDL_BUTTON_WHEELUP, 1); 01039 } 01040 01041 /* See which row the mouse is over. */ 01042 for (row = list->row_offset; row < list->rows; row++) 01043 { 01044 /* Stop if we reached maximum number of visible rows. */ 01045 if (LIST_ROW_OFFSET(row, list) == list->max_rows) 01046 { 01047 break; 01048 } 01049 01050 /* Is the mouse over this row? */ 01051 if ((uint32) my > (LIST_ROWS_START(list) + LIST_ROW_OFFSET(row, list) * LIST_ROW_HEIGHT(list)) + list->frame_offset && (uint32) my < LIST_ROWS_START(list) + (LIST_ROW_OFFSET(row, list) + 1) * LIST_ROW_HEIGHT(list)) 01052 { 01053 if (list->handle_mouse_row_func) 01054 { 01055 list->handle_mouse_row_func(list, row, event); 01056 } 01057 01058 /* Mouse click? */ 01059 if (event->type == SDL_MOUSEBUTTONDOWN && event->button.button == SDL_BUTTON_LEFT) 01060 { 01061 /* See if we clicked on this row earlier, and whether this 01062 * should be considered a double click. */ 01063 if (SDL_GetTicks() - list->click_tick < DOUBLE_CLICK_DELAY) 01064 { 01065 /* Double click, handle it as if enter was used. */ 01066 if (list->handle_enter_func) 01067 { 01068 list->handle_enter_func(list); 01069 list->click_tick = 0; 01070 } 01071 01072 /* Update selected row (in case enter handling 01073 * function did not actually jump to another GUI, 01074 * thus removing the need for this list). */ 01075 list->row_selected = row + 1; 01076 } 01077 /* Normal click. */ 01078 else 01079 { 01080 /* Update selected row and click ticks for above 01081 * double click calculation. */ 01082 list->row_selected = row + 1; 01083 list->click_tick = SDL_GetTicks(); 01084 } 01085 } 01086 /* Not a mouse click, so update highlighted row. */ 01087 else 01088 { 01089 list->row_highlighted = row + 1; 01090 } 01091 01092 break; 01093 } 01094 } 01095 01096 return 1; 01097 } 01098 01106 int lists_handle_mouse(int mx, int my, SDL_Event *event) 01107 { 01108 list_struct *tmp; 01109 01110 for (tmp = list_head; tmp; tmp = tmp->next) 01111 { 01112 if (tmp->surface == ScreenSurface && list_handle_mouse(tmp, mx, my, event)) 01113 { 01114 return 1; 01115 } 01116 } 01117 01118 return 0; 01119 } 01120 01125 list_struct *list_exists(uint32 id) 01126 { 01127 list_struct *tmp; 01128 01129 for (tmp = list_head; tmp; tmp = tmp->next) 01130 { 01131 if (tmp->id == id) 01132 { 01133 return tmp; 01134 } 01135 } 01136 01137 return NULL; 01138 } 01139 01145 static int list_compare_alpha(const void *a, const void *b) 01146 { 01147 return strcmp(((char ***) a)[0][0], ((char ***) b)[0][0]); 01148 } 01149 01155 void list_sort(list_struct *list, int type) 01156 { 01157 if (!list->text) 01158 { 01159 return; 01160 } 01161 01162 /* Alphabetical sort. */ 01163 if (type == LIST_SORT_ALPHA) 01164 { 01165 qsort((void *) list->text, list->rows, sizeof(*list->text), (void *) (int (*)()) list_compare_alpha); 01166 } 01167 } 01168 01175 int list_set_selected(list_struct *list, const char *str, uint32 col) 01176 { 01177 uint32 row; 01178 01179 for (row = 0; row < list->rows; row++) 01180 { 01181 if (!strcmp(list->text[row][col], str)) 01182 { 01183 list->row_selected = row + 1; 01184 list->row_offset = MIN(list->rows - list->max_rows, row); 01185 return 1; 01186 } 01187 } 01188 01189 return 0; 01190 }
1.7.4