From 14032d12c8ff83fb9e9093edbfe289ae9d61e5c1 Mon Sep 17 00:00:00 2001 From: siemargl Date: Tue, 8 Nov 2016 00:23:52 +0000 Subject: [PATCH] tooltip widget+demo git-svn-id: svn://kolibrios.org@6689 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../box_lib/asm/trunk/tooltip_demo.asm | 187 ++++++++++ .../libraries/box_lib/trunk/bl_sys.mac | 2 +- .../libraries/box_lib/trunk/box_lib.asm | 17 +- .../libraries/box_lib/trunk/box_lib.mac | 26 +- .../libraries/box_lib/trunk/tooltip.asm | 348 ++++++++++++++++++ 5 files changed, 577 insertions(+), 3 deletions(-) create mode 100644 programs/develop/libraries/box_lib/asm/trunk/tooltip_demo.asm create mode 100644 programs/develop/libraries/box_lib/trunk/tooltip.asm diff --git a/programs/develop/libraries/box_lib/asm/trunk/tooltip_demo.asm b/programs/develop/libraries/box_lib/asm/trunk/tooltip_demo.asm new file mode 100644 index 0000000000..048f508230 --- /dev/null +++ b/programs/develop/libraries/box_lib/asm/trunk/tooltip_demo.asm @@ -0,0 +1,187 @@ +; Простой пример программы для KolibriOS +; озвучивает код нажатой клавиши +; - переделан как пример использования tooltip + +use32 ; включить 32-битный режим ассемблера +org 0x0 ; адресация с нуля + +db 'MENUET01' ; 8-байтный идентификатор MenuetOS +dd 0x01 ; версия заголовка (всегда 1) +dd START ; адрес первой команды +dd CODE_END ; размер программы +dd DATA_END ; количество памяти +dd STACK_END ; адрес вершины стэка +dd 0x0 ; адрес буфера для параметров +dd cur_dir_path ; указатель на адрес, куда помещается строка, содержащая путь до программы в момент запуска. + +include '../../../../../proc32.inc' +include '../../../../../macros.inc' +include '../../../../../KOSfuncs.inc' +include '../../../../../Dll.inc' ; malloc fn +include '../../trunk/box_lib.mac' +include '../../load_lib.mac' +;include 'proc32.inc' +;include 'macros.inc' +;include 'KOSfuncs.inc' + +;--------------------------------------------------------------------- +;--- НАЧАЛО ПРОГРАММЫ ---------------------------------------------- +;--------------------------------------------------------------------- +; этот макрос обязателен для всех компонетов, использующих heap +; кроме того, обязательно имортировать lib_init - при импорте определяются +; функции хипа для библиотеки +@use_library_mem mem.Alloc,mem.Free,mem.ReAlloc,dll.Load + +START: +;--------------------------------------------------------------------- +;--- ИНИЦИАЛИЗАЦИЯ ---------------------------------------- +;--------------------------------------------------------------------- +;mov eax, mem_alloc +;mov [mem.alloc], eax +;mov eax, mem_realloc +;mov [mem.realloc], eax +;mov eax, mem_free +;mov [mem.free], eax +mcall 68, 11 + +mcall 40, $C0000027 ; маска событий - мышь только в активном окне + +sys_load_library lib_name, cur_dir_path, lib_path, sys_path, \ + e_notfound_lib, head_f_l, myimport, e_import, head_f_i +test eax,eax +jz @f + mcall -1 ; alarm exit +@@: + + +invoke tooltip_init, redbox_tt ; only begin of list + +red: ; перерисовать окно + +call draw_window ; вызываем процедуру отрисовки окна + +;--------------------------------------------------------------------- +;--- ЦИКЛ ОБРАБОТКИ СОБЫТИЙ ---------------------------------------- +;--------------------------------------------------------------------- + +still: +mcall 23, 5 ; функция 23 - ждать события Не более чем 0.05с +test eax, eax ; нет событий - проверить рисование тултипов по таймеру +je yield +cmp eax,1 ; перерисовать окно ? +je red ; если да - на метку red +cmp eax,2 ; нажата клавиша ? +je key ; если да - на key +cmp eax,3 ; нажата кнопка ? +je button ; если да - на button +cmp eax,6 ; событие мыши +je mouse ; если да - на mouse + +jmp still ; если другое событие - в начало цикла + + +;--------------------------------------------------------------------- +yield: +invoke tooltip_test_show, redbox_tt +jmp still ; вернуться к началу цикла + +mouse: +invoke tooltip_mouse, redbox_tt +jmp still ; вернуться к началу цикла + +key: ; нажата клавиша на клавиатуре +mcall 2 ; функция 2 - считать код символа (в ah) + +jmp still ; вернуться к началу цикла + +;--------------------------------------------------------------------- + +button: +mcall 17 ; 17 - получить идентификатор нажатой кнопки + +cmp ah, 1 ; если НЕ нажата кнопка с номером 1, +jne still ; вернуться + +pexit: +invoke tooltip_delete, redbox_tt ; освобождаем память +mcall -1 ; иначе конец программы + + +;--------------------------------------------------------------------- +;--- ОПРЕДЕЛЕНИЕ И ОТРИСОВКА ОКНА ---------------------------------- +;--------------------------------------------------------------------- + +draw_window: + +mcall 12, 1 ; функция 12: сообщить ОС о начале отрисовки + +mcall 48, 3, sc,sizeof.system_colors + +mov edx, [sc.work] ; цвет фона +or edx, 0x33000000 ; и тип окна 3 +mcall 0, <200,300>, <200,150>, , ,title + +; вывод квадратиков +mcall 13, <60,50>, <50,50>, $FF0000 +mcall 13, <140,50>, <50,50>, $FF + + +mcall 12, 2 ; функция 12.2, закончили рисовать + +ret ; выходим из процедуры + + +CODE_END: ; метка конца программы; --------------------------------------------; + +; ---------------------------------------------------------------------------- ; +;--------------------------------------------------------------------- +;--- ДАННЫЕ ПРОГРАММЫ ---------------------------------------------- +;--------------------------------------------------------------------- + +sys_path db '/sys/lib/' +;sys_path db '/tmp0/1/' +lib_name db 'box_lib.obj',0 +cur_dir_path rb 4096 +lib_path rb 4096 + +e_notfound_lib db 'Sorry I cannot load library box_lib.obj',0 + +head_f_i: +head_f_l db 'System error',0 +e_import db 'Error on load import library box_lib.obj',0 + +myimport: + dd sz_lib_init ;функция запускается макросом 1 раз при подключении +;библиотеки, потому в программе метка на нее не нужна +tooltip_init dd sz_tooltip_init +tooltip_delete dd sz_tooltip_delete +tooltip_test_show dd sz_tooltip_test_show +tooltip_mouse dd sz_tooltip_mouse +get_font_size dd sz_get_font_size + dd 0 + dd 0 + +sz_lib_init db 'lib_init',0 +sz_tooltip_init db 'tooltip_init', 0 +sz_tooltip_delete db 'tooltip_delete', 0 +sz_tooltip_test_show db 'tooltip_test_show', 0 +sz_tooltip_mouse db 'tooltip_mouse', 0 +sz_get_font_size db 'get_font_size', 0 + + +;tooltip txt, next, zone_x, zone_w, zone_y, zone_h, col_txt, col_bkg, tm_wait +redbox_tt tooltip redboxtxt, blubox_tt, 60, 50, 50, 50, 0, $FFF473, 100 +blubox_tt tooltip bluboxtxt, 0, 140, 50, 50, 50, $110000FF, $FFF473, 100 + +redboxtxt db 'Red Box Tooltip', 13, 'May be multilined', 13, 13, 'Even with empty lines', 0 +bluboxtxt db 'Blue Box Tooltip', 0 + +sc system_colors + +title db 'Toooltip demo',0 + +; stack----------------------------------------------------------------------- ; + rb 4096 +STACK_END dd ? + +DATA_END: ; метка конца данных программы; ------------------------------------ ; diff --git a/programs/develop/libraries/box_lib/trunk/bl_sys.mac b/programs/develop/libraries/box_lib/trunk/bl_sys.mac index 4a4b41b67c..a46ef82cf8 100644 --- a/programs/develop/libraries/box_lib/trunk/bl_sys.mac +++ b/programs/develop/libraries/box_lib/trunk/bl_sys.mac @@ -9,4 +9,4 @@ include 'tree_list.mac' ;macro implements tree_list, image_list, list_box include 'pathshow.mac' ;macro implements pathshow include 't_edit.mac' ;macro implements text_editor include 'frame.mac' ;macro implements frame -include 'progressbar.mac' ;macro implements progressbar \ No newline at end of file +include 'progressbar.mac' ;macro implements progressbar diff --git a/programs/develop/libraries/box_lib/trunk/box_lib.asm b/programs/develop/libraries/box_lib/trunk/box_lib.asm index 63f574c506..f398f6133c 100644 --- a/programs/develop/libraries/box_lib/trunk/box_lib.asm +++ b/programs/develop/libraries/box_lib/trunk/box_lib.asm @@ -114,6 +114,9 @@ use_frame ;-------------------------------------------------- use_progressbar +;-------------------------------------------------- +include 'tooltip.asm' ;tooltip + ;input: ; eax = єърчрЄхы№ эр ЇєэъЎш■ т√фхыхэш  ярь Єш ; ebx = ... юётюсюцфхэш  ярь Єш @@ -346,6 +349,12 @@ dd szVersion_frame, 0x00010001 dd sz_progressbar_draw, progressbar_draw dd sz_progressbar_progress, progressbar_progress +dd sz_tooltip_init, tooltip_init +dd sz_tooltip_delete, tooltip_delete +dd sz_tooltip_test_show, tooltip_test_show +dd sz_tooltip_mouse, tooltip_mouse +dd sz_get_font_size, get_font_size + dd 0,0 @@ -450,4 +459,10 @@ sz_Frame_draw db 'frame_draw',0 szVersion_frame db 'version_frame',0 sz_progressbar_draw db 'progressbar_draw', 0 -sz_progressbar_progress db 'progressbar_progress', 0 \ No newline at end of file +sz_progressbar_progress db 'progressbar_progress', 0 + +sz_tooltip_init db 'tooltip_init', 0 +sz_tooltip_delete db 'tooltip_delete', 0 +sz_tooltip_test_show db 'tooltip_test_show', 0 +sz_tooltip_mouse db 'tooltip_mouse', 0 +sz_get_font_size db 'get_font_size', 0 diff --git a/programs/develop/libraries/box_lib/trunk/box_lib.mac b/programs/develop/libraries/box_lib/trunk/box_lib.mac index a863956bc4..2d89039109 100644 --- a/programs/develop/libraries/box_lib/trunk/box_lib.mac +++ b/programs/develop/libraries/box_lib/trunk/box_lib.mac @@ -530,4 +530,28 @@ FR_FILLED equ 10000b ; [x] ; FR_TEXT_POSITION FR_TEXT_POS_BOTTOM equ 1 -FR_TEXT_POS_TOP equ 0 \ No newline at end of file +FR_TEXT_POS_TOP equ 0 + +;----------------------------------------------------------------------------- + +struc tooltip txt, next, zone_x, zone_w, zone_y, zone_h, col_txt, col_bkg, tm_wait +{ + .txt dd txt ; указатель на текст asciiz, разделитель \r 13 + .next dd next ; следующиий tooltip в цепочке или 0 + .zone_y dw zone_y ; зона контроля (в 90% случаев совпадает с размером контрола) + .zone_x dw zone_x ; + .zone_h dw zone_h ; + .zone_w dw zone_w ; + .col_txt dd col_txt ; цвет текста тултипа, включая размер SysFn4 + .col_bkg dd col_bkg ; цвет фона тултипа + .tm_wait dw tm_wait ; время ожидания х10мс +;временные переменные + .font_sz dd ? ; font size + .mouse dd ? ; предыдущее положение (x, y) + .tm_strt dd ? ; время запуска таймера (входа мыши в зону) х10мс + .video dd ? ; память для сохраненного под тултипом + .video_y dw ? ; координаты запомненной области экрана, или 0 если пусто + .video_x dw ? + .video_h dw ? ; размер предрасчитывается при init + .video_w dw ? +} diff --git a/programs/develop/libraries/box_lib/trunk/tooltip.asm b/programs/develop/libraries/box_lib/trunk/tooltip.asm new file mode 100644 index 0000000000..27ba3b90eb --- /dev/null +++ b/programs/develop/libraries/box_lib/trunk/tooltip.asm @@ -0,0 +1,348 @@ +; ---------------------------------------------------------------------------- ; +; Tooltip widget +; +; Created by Siemargl, 2016 +; +; Changelist +; 161107 - initial version + test + + +; http://stackoverflow.com/questions/8976600/fasm-how-to-send-struct-to-proc +virtual at edi + ttip tooltip ?, ?, ?, ?, ?, ?, ?, ?, ? +end virtual + +; ---------------------------------------------------------------------------- ; +; инициализация всей цепочки тултипов, формирование размеров и буферов памяти +; return eax zero if fails +align 16 +proc tooltip_init uses esi edi, ttip:dword +locals + max_len dw ? ;maximum chars in line + lines dw ? ;lines in tooltip +endl + + mov edi, [ttip] + jmp .tail_call +.list_next: + ; init statics + mov [ttip.mouse], 0 + mov [ttip.tm_strt], 0 + mov [ttip.video_y], 0 + mov [ttip.video_x], 0 + mov [ttip.video], 0 + stdcall get_font_size, [ttip.col_txt] + mov [ttip.font_sz], eax + + ; count num of lines and max len + mov esi, [ttip.txt] + mov [lines], 1 ; lines + mov [max_len], 0 ; max_len +.line: + mov ecx, 0 ; len +.symb: + mov al, [esi] + cmp al, 0 + je .eos + cmp al, 13 + jne .next + inc [lines] + inc esi + cmp cx, [max_len] ; detect max + jle @f + mov [max_len], cx + @@: + jmp .line +.next: + inc ecx + inc esi + jmp .symb +.eos:; string ended, we have correct width and hight + cmp cx, [max_len] ; detect max + jle @f + mov [max_len], cx + @@: + + mov eax, [ttip.font_sz] + shr eax, 16 + imul [max_len] + mov dx, ax ; width in pixels + mov [ttip.video_w], ax + mov eax, [ttip.font_sz] ; lo word == h + and eax, $FFFF + imul ax, [lines] + mov [ttip.video_h], ax + imul [ttip.video_w] + imul eax, 3 ; eax have now width * height in pixels *3 + ; getmem + invoke mem.alloc, eax + mov [ttip.video], eax + test eax, eax + je .exitp ; malloc fails + + ; cycle list + mov edi, [ttip.next] +.tail_call: + test edi, edi + jne .list_next + xor eax, eax + inc eax ; god return +.exitp: + ret +endp + +; ---------------------------------------------------------------------------- ; +; очистка памяти всей цепочки тултипов +align 4 +proc tooltip_delete uses edi, ttip:dword + mov edi, [ttip] + jmp .tail_call +.list_next: + mov eax, [ttip.video] + test eax, eax + je @f + invoke mem.free, eax + @@: + mov edi, [ttip.next] +.tail_call: + test edi, edi + jne .list_next + ret +endp + +; ---------------------------------------------------------------------------- ; +; показ нужного из всей цепочки тултипов при бездействии (event 0) +align 4 +proc tooltip_test_show uses edi ebx, ttip:dword + mov edi, [ttip] + jmp .tail_call +.list_next: + cmp [ttip.tm_strt], 0 ; таймер 0, значит мы не в зоне + je .nextp + cmp [ttip.video_y], 0 ; тултип уже отображен + ;;; jne .redraw + jne .nextp + mcall SF_SYSTEM_GET, SSF_TIME_COUNT + movzx ebx, [ttip.tm_wait] + sub eax, ebx + cmp eax, [ttip.tm_strt] + jl .exitp ; мог быть только один + ; время оттикало, сохраняем область и рисуемся +;CopyScreen(shadow_buf, 5*skinned+x+wForm.left, GetSkinHeight()*skinned+y+wForm.top, w, h); + mcall SF_THREAD_INFO, proc_info, -1 + movzx edx, word [proc_info + 34] ; window x position + add edx, 5 + shl edx, 16 + mcall SF_STYLE_SETTINGS, SSF_GET_SKIN_HEIGHT + movzx ebx, word [proc_info + 38] ; window y position + add eax, ebx + add edx, eax ; x_y + add edx, [ttip.mouse] + add edx, 20 ; pixels below mouse + mov ecx, dword [ttip.video_h] ; w_h + mcall SF_GET_IMAGE, [ttip.video] + + mov eax, [ttip.mouse] ; сохраним позицию где рисуемся + add eax, 20 ; pixels below mouse + mov [ttip.video_y], ax + shr eax, 16 + mov [ttip.video_x], ax + .redraw: ; рисуемся относительно мыши!!! + stdcall tooltip_draw, edi + + jmp .exitp ; мог быть только один +.nextp: + mov edi, [ttip.next] +.tail_call: + test edi, edi + jne .list_next +.exitp: + ret +endp + +; рисуемся относительно мыши!!! +; internal func +proc tooltip_draw uses esi edi ebx, ttip:dword +locals + line dw ? ;line # drawing + ptr_li dd ? ;line begin +endl + mov edi, [ttip] + ; draw square + movzx ebx, [ttip.video_x] + shl ebx, 16 + mov bx, [ttip.video_w] + movzx ecx, [ttip.video_y] + shl ecx, 16 + mov cx, [ttip.video_h] + mcall SF_DRAW_RECT, , , [ttip.col_bkg] + + ; цикл по строкам + ; count num of lines and max len + mov esi, [ttip.txt] + mov [line], 0 ; line # +.line: + mov ecx, 0 ; len + mov [ptr_li], esi +.symb: + mov al, [esi] + cmp al, 0 + je @f + cmp al, 13 + jne .next + @@: + ; draw line if len > 0 + test ecx, ecx + je @f + ; draw single line + pushad + mov esi, ecx ; length + movzx ebx, [ttip.video_x] + shl ebx, 16 + mov eax, [ttip.font_sz] + and eax, $FFFF + imul ax, [line] + add ax, [ttip.video_y] + add ebx, eax + mov ecx, [ttip.col_txt] + and ecx, $37FFFFFF + mov edx, [ptr_li] + mcall SF_DRAW_TEXT + popad + @@: + cmp byte ptr esi, 0 + je .exitp + inc [line] + inc esi + jmp .line +.next: + inc ecx + inc esi + jmp .symb +.exitp: + ret +endp + +; ---------------------------------------------------------------------------- ; +; убрать тултипы при щелчке мыши или съезде из зоны. для всей цепочки тултипов при событии мыши +; если mouse_coord == -1 опросит мышь +align 4 +proc tooltip_mouse, ttip:dword +locals + mouse_coord dd ? + mouse_but dd ? +endl + pushad + ; опросим мышь и рассуем по тултипам + mcall SF_MOUSE_GET, SSF_WINDOW_POSITION + mov [mouse_coord], eax + mcall SF_MOUSE_GET, SSF_BUTTON + mov [mouse_but], eax + mov edi, [ttip] +.list_next: + test edi, edi + je .exitp + cmp [mouse_but], 0 ; при щелчке стираемся + jne @f + ; попадаем ли в зону контроля + mov eax, [mouse_coord] + mov [ttip.mouse], eax ; место где была замечена мышь! (хз зачем) + mov ecx, eax + shr ecx, 16 + cmp cx, [ttip.zone_x] ; zone_x is higher word + jl @f + cmp ax, [ttip.zone_y] + jl @f + mov cx, [ttip.zone_w] + add cx, [ttip.zone_x] + shl ecx, 16 + cmp eax, ecx ; x+w < mouse_x (mouse_y in low word ignored) + jge @f + mov cx, [ttip.zone_y] + add cx, [ttip.zone_h] + cmp ax, cx + jge @f + ; мы в зоне - засекаем старт, если его не было + cmp [ttip.tm_strt], 0 + jne .nextp + mcall SF_SYSTEM_GET, SSF_TIME_COUNT + mov [ttip.tm_strt], eax + jmp .nextp + @@: + ; если есть буфер, вернуть картинку взад, иначе идем дальше по цепочке + mov [ttip.tm_strt], 0 + cmp [ttip.video_y], 0 + je .nextp + movzx ecx, [ttip.video_w] + shl ecx, 16 + mov cx, [ttip.video_h] + movzx edx, [ttip.video_x] + shl edx, 16 + mov dx, [ttip.video_y] + mcall SF_PUT_IMAGE, [ttip.video] + mov [ttip.video_y], 0 + ;jmp exitp ; мог быть только один - отмена - обработать нужно все сбросы таймеров +.nextp: + ;mov eax, [ttip].next + ;stdcall tooltip_mouse, [ttip].next, [mouse_coord], [mouse_but] + ; tail call unroll recursion + mov edi, [ttip.next] + jmp .list_next +.exitp: + popad + ret +endp + +; ---------------------------------------------------------------------------- ; +; decrypt font size as of SysFn 4 +; returns eax = (x,y) +align 4 +proc get_font_size, color:dword ; x86 calling convention uses eax ecx edx + ;font = color >> 24; + ;int font_multipl = (font & 7) + 1; + ;if (font & 0x10) // 8x16 + ;{ + ; ed->width_sym = 8 * font_multipl; + ; ed->hight_sym = 16 * font_multipl; + ;} else // 6x9 + ;{ + ; ed->width_sym = 6 * font_multipl; + ; ed->hight_sym = 9 * font_multipl; + ;} + mov edx, [color] + shr edx, 24 ; font + + mov ecx, edx ; font_multipl + and ecx, 7 + inc ecx + + test edx, $10 + mov edx, ecx + jz @f + ; 8x16 + shl edx, 3 + 16 ; x == width + mov eax, edx + mov edx, ecx + shl edx, 4 ; y == hight + jmp .exitp + @@: + ; 6x9 + imul edx, 6 ; x == width + shl edx, 16 + mov eax, edx + mov edx, ecx + imul edx, 9 ; y == hight +.exitp: + or eax, edx + ret +endp + +CODE_END: ; метка конца программы; ---------------------------------------------------------------------------- ; +; ---------------------------------------------------------------------------- ; +;--------------------------------------------------------------------- +;--- ДАННЫЕ ПРОГРАММЫ ---------------------------------------------- +;--------------------------------------------------------------------- + +proc_info rd 1024 + +DATA_END: ; метка конца данных программы; ---------------------------------------------------------------------------- ;