DEV Community

Cover image for Make Button By Floating Window
Rasukarusan
Rasukarusan

Posted on

Make Button By Floating Window

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?

screenshot_ 2021-02-14 20.56.45

  • 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() 
Enter fullscreen mode Exit fullscreen mode

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() 
Enter fullscreen mode Exit fullscreen mode

Have a happy vim life!

Top comments (0)