Menus can be placed anywhere on the screen, and takes a style parameter

This paves the way for insert mode completion menu using the current
prompt menu system.
This commit is contained in:
Maxime Coste 2012-09-30 15:18:37 +02:00
parent f230feec7f
commit 5b6cb500fc
5 changed files with 53 additions and 25 deletions

View File

@ -69,7 +69,8 @@ public:
: ClientMode(context.client()),
m_callback(callback), m_choice_count(choices.size()), m_selected(0)
{
context.ui().menu_show(choices);
DisplayCoord menu_pos{ context.window().dimensions().line, 0_char };
context.ui().menu_show(choices, menu_pos, MenuStyle::Prompt);
}
void on_key(const Key& key, Context& context) override
@ -253,7 +254,8 @@ public:
return;
context.ui().menu_hide();
context.ui().menu_show(candidates);
DisplayCoord menu_pos{ context.window().dimensions().line, 0_char };
context.ui().menu_show(candidates, menu_pos, MenuStyle::Prompt);
String prefix = m_result.substr(m_completions.start,
m_completions.end - m_completions.start);
if (not contains(candidates, prefix))

View File

@ -666,7 +666,8 @@ public:
void print_status(const String& , CharCount) override {}
void draw_window(Window&) override {}
void menu_show(const memoryview<String>&) override {}
void menu_show(const memoryview<String>&,
const DisplayCoord&, MenuStyle) override {}
void menu_select(int) override {}
void menu_hide() override {}

View File

@ -71,7 +71,6 @@ static void set_color(Color fg_color, Color bg_color)
NCursesUI::NCursesUI()
: m_menu(nullptr)
{
// setlocale(LC_ALL, "");
initscr();
@ -94,6 +93,17 @@ NCursesUI::~NCursesUI()
endwin();
}
static void redraw(WINDOW* menu_win)
{
wnoutrefresh(stdscr);
if (menu_win)
{
redrawwin(menu_win);
wnoutrefresh(menu_win);
}
doupdate();
}
void NCursesUI::draw_window(Window& window)
{
int max_x,max_y;
@ -101,19 +111,10 @@ void NCursesUI::draw_window(Window& window)
max_y -= 1;
int status_y = max_y;
if (m_menu)
{
int rows;
int cols;
menu_format(m_menu, &rows, &cols);
max_y -= rows;
}
window.set_dimensions(DisplayCoord(LineCount(max_y), max_x));
window.update_display_buffer();
int line_index = 0;
int last_line = INT_MAX;
for (const DisplayLine& line : window.display_buffer().lines())
{
move(line_index, 0);
@ -161,7 +162,8 @@ void NCursesUI::draw_window(Window& window)
move(status_y, max_x - (int)status_line.length());
addstr(status_line.c_str());
last_status_length = (int)status_line.length();
refresh();
redraw(m_menu_win);
}
Key NCursesUI::get_key()
@ -219,12 +221,14 @@ void NCursesUI::print_status(const String& status, CharCount cursor_pos)
addch(' ');
set_attribute(A_REVERSE, 0);
}
refresh();
redraw(m_menu_win);
}
void NCursesUI::menu_show(const memoryview<String>& choices)
void NCursesUI::menu_show(const memoryview<String>& choices,
const DisplayCoord& anchor, MenuStyle style)
{
assert(m_menu == nullptr);
assert(m_menu_win == nullptr);
m_choices = std::vector<String>(choices.begin(), choices.end());
CharCount longest = 0;
for (int i = 0; i < m_choices.size(); ++i)
@ -237,19 +241,26 @@ void NCursesUI::menu_show(const memoryview<String>& choices)
int max_x,max_y;
getmaxyx(stdscr, max_y, max_x);
max_x -= (int)anchor.column;
int columns = max_x / std::min(max_x, (int)longest);
int columns = (style == MenuStyle::Prompt) ?
(max_x / std::min(max_x, (int)longest)) : 1;
int lines = std::min(10, (int)ceilf((float)m_choices.size()/columns));
m_menu_pos = { anchor.line+1, anchor.column };
if (m_menu_pos.line + lines >= max_y)
m_menu_pos.line = anchor.line - lines;
m_menu_size = { lines, columns == 1 ? longest : max_x };
m_menu = new_menu(&m_items[0]);
int pos_y = max_y - lines - 1;
set_menu_sub(m_menu, derwin(stdscr, max_y - pos_y - 1, max_x, pos_y, 0));
m_menu_win = newwin((int)m_menu_size.line, (int)m_menu_size.column,
(int)m_menu_pos.line, (int)m_menu_pos.column);
set_menu_win(m_menu, m_menu_win);
set_menu_format(m_menu, lines, columns);
set_menu_mark(m_menu, nullptr);
set_menu_fore(m_menu, COLOR_PAIR(m_menu_fg));
set_menu_back(m_menu, COLOR_PAIR(m_menu_bg));
post_menu(m_menu);
refresh();
}
void NCursesUI::menu_select(int selected)
@ -262,7 +273,6 @@ void NCursesUI::menu_select(int selected)
}
else
set_menu_fore(m_menu, COLOR_PAIR(m_menu_bg));
refresh();
}
void NCursesUI::menu_hide()
@ -275,8 +285,9 @@ void NCursesUI::menu_hide()
if (item)
free_item(item);
m_menu = nullptr;
delwin(m_menu_win);
m_menu_win = nullptr;
m_items.clear();
refresh();
}
}

View File

@ -5,6 +5,7 @@
#include <menu.h>
#include "user_interface.hh"
#include "display_buffer.hh"
namespace Kakoune
{
@ -23,14 +24,19 @@ public:
Key get_key() override;
void menu_show(const memoryview<String>& choices) override;
void menu_show(const memoryview<String>& choices,
const DisplayCoord& anchor, MenuStyle style) override;
void menu_select(int selected) override;
void menu_hide() override;
private:
MENU* m_menu;
MENU* m_menu = nullptr;
WINDOW* m_menu_win = nullptr;
std::vector<ITEM*> m_items;
std::vector<String> m_choices;
DisplayCoord m_menu_pos;
DisplayCoord m_menu_size;
int m_menu_fg;
int m_menu_bg;
};

View File

@ -11,13 +11,21 @@ namespace Kakoune
class String;
class Window;
class DisplayCoord;
enum class MenuStyle
{
Prompt,
Inline
};
class UserInterface : public SafeCountable
{
public:
virtual ~UserInterface() {}
virtual void print_status(const String& status, CharCount cursor_pos = -1) = 0;
virtual void menu_show(const memoryview<String>& choices) = 0;
virtual void menu_show(const memoryview<String>& choices,
const DisplayCoord& anchor, MenuStyle style) = 0;
virtual void menu_select(int selected) = 0;
virtual void menu_hide() = 0;
virtual void draw_window(Window& window) = 0;