sliders H & V

This commit is contained in:
Frater 2026-02-07 00:20:32 +01:00
commit ac89c58ddb
4 changed files with 360 additions and 93 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -195,17 +195,30 @@ build_interface:
mov word [gs:si + widget.x], 10
mov word [gs:si + widget.y], 100
mov word [gs:si + widget.w], 150
mov word [gs:si + widget.h], 20
mov word [gs:si + widget.text_ofs], str_drag
mov word [gs:si + widget.text_seg], cs
mov word [gs:si + widget.h], 12
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
mov byte [gs:si + widget.attr_mode], 1 ; Horizontal
mov byte [gs:si + widget.attr_mode], SLIDER_HORIZONTAL
mov word [gs:si + widget.attr_min], 10 ; X Min
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
mov word [gs:si + widget.attr_val], 10 ; Position initiale
mov byte [gs:si + widget.thumb_pct], 15 ; Curseur fait 15% de la largeur
; mov word [gs:si + widget.event_drag], on_drag_slider
; Créer Slider (Drag)
call gui_alloc_widget
jc .mem_full
mov word [gs:si + widget.x], 400
mov word [gs:si + widget.y], 10
mov word [gs:si + widget.w], 16
mov word [gs:si + widget.h], 150
mov byte [gs:si + widget.type], WIDGET_TYPE_SLIDER
mov byte [gs:si + widget.attr_mode], SLIDER_VERTICAL
mov word [gs:si + widget.attr_min], 10 ; X Min
mov word [gs:si + widget.attr_max], 140 ; X Max (Widget.x + W - ThumbW)
mov word [gs:si + widget.attr_val], 140 ; Position initiale
mov byte [gs:si + widget.thumb_pct], 25 ; Curseur fait 15% de la largeur
; mov word [gs:si + widget.event_drag], on_drag_slider
.mem_full:
ret
@ -216,7 +229,6 @@ str_hello db "Hello", 0
str_option1 db "option 1", 0
str_option2 db "option 2", 0
str_option3 db "option 3", 0
str_drag db "->", 0
; -----------------------------------------------------------
; timer ISR (IRQ -> INT)

View file

@ -71,15 +71,13 @@
%define TXT_MODE 4
%define PUTCH 5
%define WRITE 6
%define LINE_VERT 7
%define LINE_HORIZ 8
%define RECTANGLE 9
%define RECTANGLE_FILL 10
%define RECTANGLE_ROUND 11
%define MOUSE_HIDE 12
%define MOUSE_SHOW 13
%define MOUSE_MOVE 14
%define LINE 15
%define LINE 7
%define RECTANGLE 8
%define RECTANGLE_FILL 9
%define RECTANGLE_ROUND 10
%define MOUSE_HIDE 11
%define MOUSE_SHOW 12
%define MOUSE_MOVE 13
; ------------------------------------------------------------
; COMMENTAIRE SUR LA MÉTHODE D'APPEL
@ -100,15 +98,14 @@ graph_driver:
dw cga_set_writemode ; mode texte
dw cga_putc ; dessin d'un caractère
dw cga_write ; dessin d'une chaine de caractère
dw cga_line_vertical ; dessin d'une ligne verticale
dw cga_line_horizontal ; dessin d'une ligne horizontale
dw cga_line ; dessin d'une ligne (Bresenham) avec décision horizontale/verticale
dw cga_draw_rect ; dessin d'un rectangle
dw cga_fill_rect ; dessin d'un rectangle plein
dw cga_draw_rounded_frame ; dessin d'un rectangle arrondi
dw cga_mouse_hide ; déplacement du curseur
dw cga_mouse_show ; déplacement du curseur
dw cga_mouse_cursor_move ; déplacement du curseur
dw cga_line ; dessin d'une ligne (Bresenham)
; =============================================================================
; SECTION : PATTERNS & FILL
@ -790,6 +787,7 @@ cga_line_horizontal:
%undef .x1
%undef .x2
%undef .y
; ------------------------------------------------------------
; cga_line (x1, y1, x2, y2, color)
; Algorithme de Bresenham pour tracer une ligne arbitraire
@ -803,6 +801,8 @@ cga_line_horizontal:
cga_line:
push bp
mov bp, sp
pusha ; Sauvegarde de tous les registres (AX, BX, CX, DX, SI, DI)
push es ; Sauvegarde ES
; --- Optimisation : Lignes H/V ---
mov ax, .y1
@ -812,15 +812,24 @@ cga_line:
cmp ax, .x2
je .do_vert
sub sp, 10 ; Variables locales: dx, dy, sx, sy, err
pusha
push es
; --- Bresenham ---
mov ax, VIDEO_SEG
mov es, ax
call cga_mouse_hide
sub sp, 10 ; Variables locales: dx, dy, sx, sy, err
; --- Definitions locales ---
; BP pointe sur l'ancien BP.
; PUSHA (16 octets) + PUSH ES (2 octets) = 18 octets
; Les variables locales commencent donc à BP-18
%define .dx word [bp-20]
%define .dy word [bp-22]
%define .sx word [bp-24]
%define .sy word [bp-26]
%define .err word [bp-28]
; --- Initialisation Bresenham ---
; dx = abs(x2 - x1), sx = sign(x2 - x1)
mov ax, .x2
@ -830,8 +839,8 @@ cga_line:
neg ax
neg bx ; sx = -1
.calc_dx:
mov [bp-2], ax ; save dx
mov [bp-6], bx ; save sx
mov .dx, ax ; save dx
mov .sx, bx ; save sx
; dy = abs(y2 - y1), sy = sign(y2 - y1)
mov ax, .y2
@ -841,13 +850,13 @@ cga_line:
neg ax
neg bx ; sy = -1
.calc_dy:
mov [bp-4], ax ; save dy
mov [bp-8], bx ; save sy
mov .dy, ax ; save dy
mov .sy, bx ; save sy
; err = dx - dy
mov ax, [bp-2] ; dx
sub ax, [bp-4] ; dy
mov [bp-10], ax ; err
mov ax, .dx ; dx
sub ax, .dy ; dy
mov .err, ax ; err
; Coordonnées courantes
mov cx, .x1
@ -878,32 +887,30 @@ cga_line:
je .done
.step:
mov ax, [bp-10] ; e2 = err
mov ax, .err ; e2 = err
shl ax, 1 ; e2 = 2*err
mov bx, [bp-4] ; dy
mov bx, .dy ; dy
neg bx ; -dy
cmp ax, bx
jle .check_y
add word [bp-10], bx ; err += -dy
add cx, [bp-6] ; x += sx
add .err, bx ; err += -dy
add cx, .sx ; x += sx
.check_y:
mov bx, [bp-2] ; dx
mov bx, .dx ; dx
cmp ax, bx
jge .loop ; if e2 >= dx, skip y step
add word [bp-10], bx ; err += dx
add dx, [bp-8] ; y += sy
add .err, bx ; err += dx
add dx, .sy ; y += sy
jmp .loop
.done:
call cga_mouse_show
pop es
popa
leave
ret
add sp, 10 ; Libération variables locales
jmp .exit
.do_horiz:
push word [bp+12] ; color
@ -912,8 +919,7 @@ cga_line:
push word [bp+4] ; x1
call cga_line_horizontal
add sp, 8
pop bp
ret
jmp .exit
.do_vert:
push word [bp+12] ; color
@ -922,13 +928,23 @@ cga_line:
push word [bp+4] ; x
call cga_line_vertical
add sp, 8
.exit:
pop es
popa
pop bp
ret
%undef .x1
%undef .y1
%undef .x2
%undef .y2
%undef .color
%undef .dx
%undef .dy
%undef .sx
%undef .sy
%undef .err
; ------------------------------------------------------------
; cga_draw_rect

View file

@ -20,6 +20,10 @@
;
; =============================================================================
;
; https://github.com/buserror/libmui
;
; --- Configuration ---
%define GUI_RAM_SEG 0x0A00 ; Segment de données UI
%define GUI_MAX_WIDGETS 32 ; Nombre max de widgets simultanés
@ -44,6 +48,9 @@
; --- Widgets attributs ---
%define BUTTON_OK 1
%define SLIDER_HORIZONTAL 1
%define SLIDER_VERTICAL 2
; --- Structure d'un OBJET (Bouton, etc) ---
struc widget
.state resb 1 ; État (0=libre, >0=utilisé)
@ -371,55 +378,157 @@ gui_logic_slider:
mov byte [gs:si + widget.state], GUI_STATE_PRESSED
; Calcul de l'ancrage
; --- CALCUL TAILLE THUMB POUR HIT TEST ---
; On doit savoir si le clic est SUR le curseur ou SUR la piste
push ax
push bx
push dx
xor ax, ax
xor bx, bx
cmp byte [gs:si + widget.attr_mode], 2
je .calc_v
; --- Horizontal ---
mov ax, [gs:si + widget.w]
mov bl, [gs:si + widget.thumb_pct]
mul bx
mov bx, 100
div bx ; AX = Thumb Width
; Check collision avec le thumb actuel
mov bx, [gs:si + widget.attr_val]
cmp cx, bx
jb .click_outside_h ; Click avant le thumb
add bx, ax
cmp cx, bx
ja .click_outside_h ; Click après le thumb
; Click DANS le thumb : Anchor = MouseX - AttrVal
mov ax, cx
sub ax, [gs:si + widget.attr_val]
mov [gs:si + widget.attr_anchor], ax
cmp byte [gs:si + widget.attr_mode], 2
jne .do_drag
jmp .init_done
.click_outside_h:
; Click HORS du thumb : On centre le thumb sur la souris
shr ax, 1
mov [gs:si + widget.attr_anchor], ax
jmp .init_done
.calc_v:
; --- Vertical ---
mov ax, [gs:si + widget.h]
mov bl, [gs:si + widget.thumb_pct]
mul bx
mov bx, 100
div bx ; AX = Thumb Height
; Check collision avec le thumb actuel
mov bx, [gs:si + widget.attr_val]
cmp dx, bx
jb .click_outside_v
add bx, ax
cmp dx, bx
ja .click_outside_v
; Click DANS le thumb
mov ax, dx
sub ax, [gs:si + widget.attr_val]
mov [gs:si + widget.attr_anchor], ax
jmp .init_done
.click_outside_v:
; Click HORS du thumb
shr ax, 1
mov [gs:si + widget.attr_anchor], ax
.init_done:
pop dx
pop bx
pop ax
.do_drag:
; --- LOGIQUE DE DÉPLACEMENT ---
; On calcule les limites dynamiquement pour éviter que le curseur ne sorte
push ax
push bx
push dx
xor ax, ax
xor bx, bx
cmp byte [gs:si + widget.attr_mode], 1
je .drag_h
cmp byte [gs:si + widget.attr_mode], 2
je .drag_v
pop dx
pop bx
pop ax
xor ax, ax
ret
.drag_h:
; 1. Thumb Width -> AX
mov ax, [gs:si + widget.w]
mov bl, [gs:si + widget.thumb_pct]
mul bx
mov bx, 100
div bx ; AX = Thumb Width
; 2. Max Pos = X + W - ThumbWidth
mov bx, [gs:si + widget.x]
add bx, [gs:si + widget.w]
sub bx, ax ; BX = Max Pos
; 3. Min Pos = X
mov dx, [gs:si + widget.x] ; DX = Min Pos
; 4. Target Pos = MouseX - Anchor
mov ax, cx
sub ax, [gs:si + widget.attr_anchor] ; Nouvelle pos = MouseX - Anchor
; Clamp Min
cmp ax, [gs:si + widget.attr_min]
jge .chk_max_h
mov ax, [gs:si + widget.attr_min]
.chk_max_h:
; Clamp Max
cmp ax, [gs:si + widget.attr_max]
jle .apply_pos
mov ax, [gs:si + widget.attr_max]
jmp .apply_pos
sub ax, [gs:si + widget.attr_anchor]
jmp .apply_clamp
.drag_v:
mov ax, dx
sub ax, [gs:si + widget.attr_anchor]
; Clamp Min
cmp ax, [gs:si + widget.attr_min]
jge .chk_max_v
mov ax, [gs:si + widget.attr_min]
; 1. Thumb Height -> AX
mov ax, [gs:si + widget.h]
mov bl, [gs:si + widget.thumb_pct]
mul bx
mov bx, 100
div bx ; AX = Thumb Height
.chk_max_v:
; Clamp Max
cmp ax, [gs:si + widget.attr_max]
jle .apply_pos
mov ax, [gs:si + widget.attr_max]
; 2. Max Pos = Y + H - ThumbHeight
mov bx, [gs:si + widget.y]
add bx, [gs:si + widget.h]
sub bx, ax ; BX = Max Pos
; 3. Min Pos = Y
mov dx, [gs:si + widget.y] ; DX = Min Pos
; 4. Target Pos = MouseY - Anchor
; MouseY est sur la pile (push dx initial), on le recupere via SP
mov bp, sp
mov ax, [bp] ; [bp] = Saved DX (MouseY)
sub ax, [gs:si + widget.attr_anchor]
.apply_clamp:
; AX = Target, DX = Min, BX = Max
cmp ax, dx
jge .chk_max
mov ax, dx
jmp .apply_pos
.chk_max:
cmp ax, bx
jle .apply_pos
mov ax, bx
.apply_pos:
pop dx
pop bx
add sp, 2 ; Clean AX from stack
cmp ax, [gs:si + widget.attr_val]
je .no_change
mov [gs:si + widget.attr_val], ax
@ -471,7 +580,6 @@ gui_logic_checkbox:
ret
; Dessine le widget pointé par SI
gui_draw_single_widget:
pusha
@ -525,23 +633,36 @@ gui_draw_single_widget:
.case_5:
.done:
GFX MOUSE_SHOW ; On réaffiche la souris APRES, capturant le widget fini
popa
ret
; --- Locals Mapping ---
%define .thumb_x1 word [bp-2]
%define .thumb_y1 word [bp-4]
%define .thumb_x2 word [bp-6]
%define .thumb_y2 word [bp-8]
%define .track_x1 word [bp-10]
%define .track_y1 word [bp-12]
%define .track_x2 word [bp-14]
%define .track_y2 word [bp-16]
draw_slider:
push bp
mov bp, sp
sub sp, 16 ; Reserve space for locals
; Save track coords (Arguments passed in AX, BX, CX, DX)
mov .track_x1, ax
mov .track_y1, bx
mov .track_x2, cx
mov .track_y2, dx
; 1. Dessiner la piste (Track)
GFX RECTANGLE_FILL, ax, bx, cx, dx, PATTERN_WHITE_LIGHT
GFX RECTANGLE, ax, bx, cx, dx, 0
GFX RECTANGLE_FILL, .track_x1, .track_y1, .track_x2, .track_y2, PATTERN_WHITE_LIGHT
GFX RECTANGLE, .track_x1, .track_y1, .track_x2, .track_y2, 0
; 2. Calculer la taille du curseur (Thumb)
push ax ; Sauvegarde coords track (X1, Y1, X2, Y2)
push bx
push cx
push dx
cmp byte [gs:si + widget.attr_mode], 2
je .calc_v
@ -553,12 +674,34 @@ draw_slider:
mov bx, 100
div bx ; AX = Thumb Width
mov bx, [gs:si + widget.y] ; BX = Y1
mov dx, bx
add dx, [gs:si + widget.h] ; DX = Y2
mov cx, [gs:si + widget.attr_val] ; CX = X1
add ax, cx ; AX = X1 + Width = X2
xchg ax, cx ; AX = X1, CX = X2
; Thumb X1 = attr_val
mov cx, [gs:si + widget.attr_val]
; --- CLAMP X1 (Fix Overflow) ---
; Max X1 = TrackX2 - ThumbW
mov dx, .track_x2
sub dx, ax ; DX = Max X1
cmp cx, dx
jle .chk_min_x
mov cx, dx
.chk_min_x:
cmp cx, .track_x1
jge .ok_x1
mov cx, .track_x1
.ok_x1:
mov .thumb_x1, cx
; Thumb X2 = X1 + Width
add cx, ax
mov .thumb_x2, cx
; Thumb Y1 = Track Y1
mov ax, .track_y1
mov .thumb_y1, ax
; Thumb Y2 = Track Y2
mov ax, .track_y2
mov .thumb_y2, ax
jmp .draw_thumb
.calc_v:
@ -570,23 +713,119 @@ draw_slider:
mov bx, 100
div bx ; AX = Thumb Height
mov bx, [gs:si + widget.attr_val] ; BX = Y1
mov dx, bx
add dx, ax ; DX = Y2
mov ax, [gs:si + widget.x] ; AX = X1
mov cx, ax
add cx, [gs:si + widget.w] ; CX = X2
; Thumb Y1 = attr_val
mov cx, [gs:si + widget.attr_val]
; --- CLAMP Y1 (Fix Overflow) ---
; Max Y1 = TrackY2 - ThumbH
mov dx, .track_y2
sub dx, ax ; DX = Max Y1
cmp cx, dx
jle .chk_min_y
mov cx, dx
.chk_min_y:
cmp cx, .track_y1
jge .ok_y1
mov cx, .track_y1
.ok_y1:
mov .thumb_y1, cx
; Thumb Y2 = Y1 + Height
add cx, ax
mov .thumb_y2, cx
; Thumb X1 = Track X1
mov ax, .track_x1
mov .thumb_x1, ax
; Thumb X2 = Track X2
mov ax, .track_x2
mov .thumb_x2, ax
.draw_thumb:
; 3. Dessiner le curseur (Thumb)
GFX RECTANGLE_FILL, ax, bx, cx, dx, PATTERN_WHITE
GFX RECTANGLE, ax, bx, cx, dx, 0
add sp, 8 ; Nettoyer la pile des push ax..dx
GFX TXT_MODE, GFX_TXT_BLACK_TRANSPARENT
call draw_text
GFX RECTANGLE_FILL, .thumb_x1, .thumb_y1, .thumb_x2, .thumb_y2, PATTERN_WHITE
GFX RECTANGLE, .thumb_x1, .thumb_y1, .thumb_x2, .thumb_y2, 0
; --- Grip Lines (3 lignes pour un look moderne) ---
cmp byte [gs:si + widget.attr_mode], 2
je .grip_v
; --- Grip Horizontal (Lignes verticales) ---
; Center X
mov ax, .thumb_x1
add ax, .thumb_x2
shr ax, 1 ; AX = Center X
; Y bounds (padding 3px)
mov bx, .thumb_y1
add bx, 3
mov dx, .thumb_y2
sub dx, 3
; Center Line
GFX LINE, ax, bx, ax, dx, 0
; Left Line
mov cx, ax
sub cx, 2
cmp cx, .thumb_x1
jle .skip_left
GFX LINE, cx, bx, cx, dx, 0
.skip_left:
; Right Line
mov cx, ax
add cx, 2
cmp cx, .thumb_x2
jge .grip_done
GFX LINE, cx, bx, cx, dx, 0
jmp .grip_done
.grip_v:
; --- Grip Vertical (Lignes horizontales) ---
; Center Y
mov bx, .thumb_y1
add bx, .thumb_y2
shr bx, 1 ; BX = Center Y
; X bounds (padding 3px)
mov ax, .thumb_x1
add ax, 3
mov cx, .thumb_x2
sub cx, 3
; Center Line
GFX LINE, ax, bx, cx, bx, 0
; Top Line
mov dx, bx
sub dx, 2
cmp dx, .thumb_y1
jle .skip_top
GFX LINE, ax, dx, cx, dx, 0
.skip_top:
; Bottom Line
mov dx, bx
add dx, 2
cmp dx, .thumb_y2
jge .grip_done
GFX LINE, ax, dx, cx, dx, 0
.grip_done:
leave
ret
; Clean up defines
%undef .thumb_x1
%undef .thumb_y1
%undef .thumb_x2
%undef .thumb_y2
%undef .track_x1
%undef .track_y1
%undef .track_x2
%undef .track_y2
draw_button:
; Dispatch selon état