Let's make a button by floating window!
I made a button using floating window. You can push the button by ENTER.
How do I make it look like a button?
- Prepare two windows, front and back.
- Make the color of the back a little darker than the color of the front.
- Lower the position of the front so that it covers the back when it is pressed.
When ENTER is pressed, just move it back down and it will appear to be pressed.
Code
let g:button_window = {}
hi FrontColor guibg=#F27200
hi BackColor guibg=#AC5D24
function! s:center(str)
let width = nvim_win_get_width(0)
let shift = floor(width/2) - floor(strdisplaywidth(a:str)/2)
return repeat(' ', float2nr(shift)) . a:str
endfunction
function! s:remove_button() abort
let front_win = nvim_get_current_win()
let back_win = g:button_window[front_win]
call nvim_win_close(back_win, v:true)
call nvim_win_close(front_win, v:true)
call remove(g:button_window, front_win)
endfunction
function! s:create_window(config, ...) abort
let hi_group = a:1
let transparency = get(a:, '2', 0)
let buf = nvim_create_buf(v:false, v:true)
let win = nvim_open_win(buf, v:true, a:config)
if hi_group != ''
call nvim_win_set_option(win, 'winhighlight', hi_group)
call nvim_win_set_option(win, 'winblend', transparency)
call nvim_win_set_config(win, a:config)
endif
return win
endfunction
function! s:push() abort
let front_win = nvim_get_current_win()
let back_win = g:button_window[front_win]
let config = nvim_win_get_config(front_win)
let config.row += 1
call nvim_win_set_config(front_win, config)
sleep 100ms
redraw
let config.row -= 1
call nvim_win_set_config(front_win, config)
endfunction
function! s:main() abort
let row = 20
let col = 20
let width = 20
let height = 3
let config = { 'relative': 'editor', 'row': row, 'col': col, 'width': width, 'height': height, 'anchor': 'NW', 'style': 'minimal' }
" back window
let back_config = deepcopy(config)
let back_config.row += 1
let back_win = s:create_window(back_config, 'Normal:BackColor')
" front window
let front_win = s:create_window(config, 'Normal:FrontColor')
call setline(2, s:center('Button'))
call cursor(2, 0)
nnoremap <buffer><nowait><silent> :q :call <SID>remove_button()
nnoremap <CR> :call <SID>push()<CR>
let g:button_window[front_win] = back_win
endfunction
call s:main()
Bonus: Fire bullets with ENTER
And you can move by hjkl.
let g:button_window = {}
hi FrontColor guibg=#F27200
hi BackColor guibg=#AC5D24
function! s:center(str)
let width = nvim_win_get_width(0)
let shift = floor(width/2) - floor(strdisplaywidth(a:str)/2)
return repeat(' ', float2nr(shift)) . a:str
endfunction
function! s:move(direction, value)
let front_win = nvim_get_current_win()
let back_win = g:button_window[front_win]
for id in [front_win, back_win]
let config = nvim_win_get_config(id)
if a:direction == 'x'
let config.col += a:value
else
let config.row += a:value
endif
call nvim_win_set_config(id, config)
endfor
endfunction
function! s:remove_button() abort
let front_win = nvim_get_current_win()
let back_win = g:button_window[front_win]
call nvim_win_close(back_win, v:true)
call nvim_win_close(front_win, v:true)
call remove(g:button_window, front_win)
endfunction
function! s:create_window(config, ...) abort
let hi_group = a:1
let transparency = get(a:, '2', 0)
let buf = nvim_create_buf(v:false, v:true)
let win = nvim_open_win(buf, v:true, a:config)
if hi_group != ''
call nvim_win_set_option(win, 'winhighlight', hi_group)
call nvim_win_set_option(win, 'winblend', transparency)
call nvim_win_set_config(win, a:config)
endif
return win
endfunction
function! s:fire() abort
let front_win = nvim_get_current_win()
let conf = nvim_win_get_config(front_win)
let row = conf.row + 1
let col = conf.col + conf.width
let width = 2
let height = 1
let config = { 'relative': 'editor', 'row': row, 'col': col, 'width': width, 'height': height, 'anchor': 'NW', 'style': 'minimal', }
let ballet = s:create_window(config, 'Normal:FrontColor')
for i in range(1, 30)
let config.col += 1
call nvim_win_set_config(ballet, config)
redraw
sleep 10ms
endfor
call nvim_win_close(ballet, v:true)
endfunction
function! s:push() abort
let front_win = nvim_get_current_win()
let back_win = g:button_window[front_win]
let config = nvim_win_get_config(front_win)
let config.row += 1
call nvim_win_set_config(front_win, config)
sleep 100ms
redraw
let config.row -= 1
call nvim_win_set_config(front_win, config)
call s:fire()
endfunction
function! s:main() abort
let row = 20
let col = 20
let width = 20
let height = 3
let config = { 'relative': 'editor', 'row': row, 'col': col, 'width': width, 'height': height, 'anchor': 'NW', 'style': 'minimal' }
" back window
let back_config = deepcopy(config)
let back_config.row += 1
let back_win = s:create_window(back_config, 'Normal:BackColor')
" front window
let front_win = s:create_window(config, 'Normal:FrontColor')
call setline(2, s:center('Button'))
call cursor(2, 0)
nnoremap <buffer><nowait><silent> l :call <SID>move('x', 2)<CR>
nnoremap <buffer><nowait><silent> h :call <SID>move('x', -2)<CR>
nnoremap <buffer><nowait><silent> j :call <SID>move('y', 2)<CR>
nnoremap <buffer><nowait><silent> k :call <SID>move('y', -2)<CR>
nnoremap <buffer><nowait><silent> :q :call <SID>remove_button()
nnoremap <CR> :call <SID>push()<CR>
let g:button_window[front_win] = back_win
endfunction
call s:main()
Have a happy vim life!
Top comments (0)