remove print_status from UserInterface, pass status line to draw

Client store the current status line. This way calls to print status
do not force the user interface to display directly.
This commit is contained in:
Maxime Coste 2013-09-16 19:15:13 +01:00
parent 49903523a7
commit 06e06d6ea6
10 changed files with 72 additions and 83 deletions

View File

@ -182,7 +182,7 @@ public:
if (key == Key(Key::Modifiers::Control, 'm')) if (key == Key(Key::Modifiers::Control, 'm'))
{ {
context().ui().menu_hide(); context().ui().menu_hide();
context().ui().print_status(DisplayLine{}); context().print_status(DisplayLine{});
reset_normal_mode(); reset_normal_mode();
int selected = m_selected - m_choices.begin(); int selected = m_selected - m_choices.begin();
m_callback(selected, MenuEvent::Validate, context()); m_callback(selected, MenuEvent::Validate, context());
@ -195,7 +195,7 @@ public:
m_edit_filter = false; m_edit_filter = false;
m_filter = boost::regex(".*"); m_filter = boost::regex(".*");
m_filter_editor.reset(""); m_filter_editor.reset("");
context().ui().print_status(DisplayLine{}); context().print_status(DisplayLine{});
} }
else else
{ {
@ -246,7 +246,7 @@ public:
{ {
auto display_line = m_filter_editor.build_display_line(); auto display_line = m_filter_editor.build_display_line();
display_line.insert(display_line.begin(), { "filter:"_str, get_color("Prompt") }); display_line.insert(display_line.begin(), { "filter:"_str, get_color("Prompt") });
context().ui().print_status(display_line); context().print_status(display_line);
} }
} }
@ -320,7 +320,7 @@ public:
history.erase(it); history.erase(it);
history.push_back(line); history.push_back(line);
} }
context().ui().print_status(DisplayLine{}); context().print_status(DisplayLine{});
context().ui().menu_hide(); context().ui().menu_hide();
reset_normal_mode(); reset_normal_mode();
// call callback after reset_normal_mode so that callback // call callback after reset_normal_mode so that callback
@ -330,7 +330,7 @@ public:
} }
else if (key == Key::Escape or key == Key { Key::Modifiers::Control, 'c' }) else if (key == Key::Escape or key == Key { Key::Modifiers::Control, 'c' })
{ {
context().ui().print_status(DisplayLine{}); context().print_status(DisplayLine{});
context().ui().menu_hide(); context().ui().menu_hide();
reset_normal_mode(); reset_normal_mode();
m_callback(line, PromptEvent::Abort, context()); m_callback(line, PromptEvent::Abort, context());
@ -453,7 +453,7 @@ private:
{ {
auto display_line = m_line_editor.build_display_line(); auto display_line = m_line_editor.build_display_line();
display_line.insert(display_line.begin(), { m_prompt, m_prompt_colors }); display_line.insert(display_line.begin(), { m_prompt, m_prompt_colors });
context().ui().print_status(display_line); context().print_status(display_line);
} }
PromptCallback m_callback; PromptCallback m_callback;
@ -1019,4 +1019,47 @@ void Client::stop_recording()
m_recording_reg = 0; m_recording_reg = 0;
} }
void Client::print_status(DisplayLine status_line)
{
m_status_line = std::move(status_line);
m_context.window().forget_timestamp();
}
static DisplayLine generate_mode_line(Client& client)
{
auto& context = client.context();
auto pos = context.editor().main_selection().last();
auto col = context.buffer()[pos.line].char_count_to(pos.column);
std::ostringstream oss;
oss << context.buffer().display_name()
<< " " << (int)pos.line+1 << ":" << (int)col+1;
if (context.buffer().is_modified())
oss << " [+]";
if (context.client().is_recording())
oss << " [recording]";
if (context.buffer().flags() & Buffer::Flags::New)
oss << " [new file]";
oss << " [" << context.editor().selections().size() << " sel]";
if (context.editor().is_editing())
oss << " [insert]";
oss << " - " << client.name();
return { oss.str(), get_color("StatusLine") };
}
void Client::redraw_ifn()
{
if (m_context.window().timestamp() != m_context.buffer().timestamp())
{
DisplayCoord dimensions = m_context.ui().dimensions();
if (dimensions == DisplayCoord{0,0})
return;
m_context.window().set_dimensions(dimensions);
m_context.window().update_display_buffer();;
m_context.ui().draw(m_context.window().display_buffer(),
m_status_line, generate_mode_line(*this));
}
}
} }

View File

@ -8,6 +8,7 @@
#include "keys.hh" #include "keys.hh"
#include "string.hh" #include "string.hh"
#include "utils.hh" #include "utils.hh"
#include "display_buffer.hh"
namespace Kakoune namespace Kakoune
{ {
@ -78,6 +79,10 @@ public:
const String& name() const { return m_name; } const String& name() const { return m_name; }
void set_name(String name) { m_name = std::move(name); } void set_name(String name) { m_name = std::move(name); }
void print_status(DisplayLine status_line);
void redraw_ifn();
UserInterface& ui() const { return *m_ui; } UserInterface& ui() const { return *m_ui; }
private: private:
Context m_context; Context m_context;
@ -87,6 +92,7 @@ private:
std::vector<std::unique_ptr<InputMode>> m_mode_trash; std::vector<std::unique_ptr<InputMode>> m_mode_trash;
String m_name; String m_name;
DisplayLine m_status_line;
using Insertion = std::pair<InsertMode, std::vector<Key>>; using Insertion = std::pair<InsertMode, std::vector<Key>>;
Insertion m_last_insert = {InsertMode::Insert, {}}; Insertion m_last_insert = {InsertMode::Insert, {}};

View File

@ -151,45 +151,10 @@ Client& ClientManager::get_client(const String& name)
throw runtime_error("no client named: " + name); throw runtime_error("no client named: " + name);
} }
static DisplayLine generate_status_line(Client& client)
{
auto& context = client.context();
auto pos = context.editor().main_selection().last();
auto col = context.buffer()[pos.line].char_count_to(pos.column);
std::ostringstream oss;
oss << context.buffer().display_name()
<< " " << (int)pos.line+1 << ":" << (int)col+1;
if (context.buffer().is_modified())
oss << " [+]";
if (context.client().is_recording())
oss << " [recording]";
if (context.buffer().flags() & Buffer::Flags::New)
oss << " [new file]";
oss << " [" << context.editor().selections().size() << " sel]";
if (context.editor().is_editing())
oss << " [insert]";
oss << " - " << client.name();
return { oss.str(), get_color("StatusLine") };
}
void ClientManager::redraw_clients() const void ClientManager::redraw_clients() const
{ {
for (auto& client : m_clients) for (auto& client : m_clients)
{ client->redraw_ifn();
Context& context = client->context();
if (context.window().timestamp() != context.buffer().timestamp())
{
DisplayCoord dimensions = context.ui().dimensions();
if (dimensions == DisplayCoord{0,0})
return;
context.window().set_dimensions(dimensions);
context.window().update_display_buffer();;
context.ui().draw(context.window().display_buffer(),
generate_status_line(*client));
}
}
} }
} }

View File

@ -540,8 +540,6 @@ void declare_option(CommandParameters params, Context& context)
class DraftUI : public UserInterface class DraftUI : public UserInterface
{ {
public: public:
void print_status(const DisplayLine&) override {}
void menu_show(memoryview<String>, DisplayCoord, ColorPair, ColorPair, MenuStyle) override {} void menu_show(memoryview<String>, DisplayCoord, ColorPair, ColorPair, MenuStyle) override {}
void menu_select(int) override {} void menu_select(int) override {}
void menu_hide() override {} void menu_hide() override {}
@ -549,7 +547,7 @@ public:
void info_show(const String&, DisplayCoord, ColorPair, MenuStyle) override {} void info_show(const String&, DisplayCoord, ColorPair, MenuStyle) override {}
void info_hide() override {} void info_hide() override {}
void draw(const DisplayBuffer&, const DisplayLine&) override {} void draw(const DisplayBuffer&, const DisplayLine&, const DisplayLine&) override {}
DisplayCoord dimensions() override { return {0,0}; } DisplayCoord dimensions() override { return {0,0}; }
bool is_key_available() override { return false; } bool is_key_available() override { return false; }
Key get_key() override { return 'a'; } Key get_key() override { return 'a'; }
@ -571,8 +569,7 @@ void context_wrap(CommandParameters params, Context& context, Func func)
{ {
Editor& editor = real_context.editor(); Editor& editor = real_context.editor();
Client client(std::unique_ptr<UserInterface>(new DraftUI()), editor, Client client(std::unique_ptr<UserInterface>(new DraftUI()), editor,
real_context.has_client() ? real_context.has_client() ? real_context.client().name() : "");
real_context.client().name() : "");
DynamicSelectionList sels{editor.buffer(), editor.selections()}; DynamicSelectionList sels{editor.buffer(), editor.selections()};
auto restore_sels = on_scope_end([&]{ editor.select(sels); }); auto restore_sels = on_scope_end([&]{ editor.select(sels); });
func(parser, client.context()); func(parser, client.context());

View File

@ -75,10 +75,10 @@ HookManager& Context::hooks() const
return GlobalHooks::instance(); return GlobalHooks::instance();
} }
void Context::print_status(const DisplayLine& status) const void Context::print_status(DisplayLine status) const
{ {
if (has_ui()) if (has_client())
ui().print_status(status); client().print_status(std::move(status));
} }
void Context::push_jump() void Context::push_jump()

View File

@ -49,7 +49,7 @@ struct Context
OptionManager& options() const; OptionManager& options() const;
HookManager& hooks() const; HookManager& hooks() const;
void print_status(const DisplayLine& status) const; void print_status(DisplayLine status) const;
void push_jump(); void push_jump();
const DynamicSelectionList& jump_forward(); const DynamicSelectionList& jump_forward();

View File

@ -240,6 +240,7 @@ void NCursesUI::draw_line(const DisplayLine& line, CharCount col_index) const
} }
void NCursesUI::draw(const DisplayBuffer& display_buffer, void NCursesUI::draw(const DisplayBuffer& display_buffer,
const DisplayLine& status_line,
const DisplayLine& mode_line) const DisplayLine& mode_line)
{ {
LineCount line_index = 0; LineCount line_index = 0;
@ -265,10 +266,10 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer,
move((int)m_dimensions.line, 0); move((int)m_dimensions.line, 0);
clrtoeol(); clrtoeol();
draw_line(m_status_line, 0); draw_line(status_line, 0);
CharCount status_len = mode_line.length(); CharCount status_len = mode_line.length();
// only draw mode_line if it does not overlap one status line // only draw mode_line if it does not overlap one status line
if (m_dimensions.column - m_status_line.length() > status_len + 1) if (m_dimensions.column - status_line.length() > status_len + 1)
{ {
CharCount col = m_dimensions.column - status_len; CharCount col = m_dimensions.column - status_len;
move((int)m_dimensions.line, (int)col); move((int)m_dimensions.line, (int)col);
@ -358,15 +359,6 @@ Key NCursesUI::get_key()
return Key::Invalid; return Key::Invalid;
} }
void NCursesUI::print_status(const DisplayLine& status)
{
m_status_line = status;
move((int)m_dimensions.line, 0);
clrtoeol();
draw_line(status, 0);
redraw();
}
void NCursesUI::draw_menu() void NCursesUI::draw_menu()
{ {
// menu show may have not created the window if it did not fit. // menu show may have not created the window if it did not fit.

View File

@ -20,8 +20,8 @@ public:
NCursesUI& operator=(const NCursesUI&) = delete; NCursesUI& operator=(const NCursesUI&) = delete;
void draw(const DisplayBuffer& display_buffer, void draw(const DisplayBuffer& display_buffer,
const DisplayLine& status_line,
const DisplayLine& mode_line) override; const DisplayLine& mode_line) override;
void print_status(const DisplayLine& status) override;
bool is_key_available() override; bool is_key_available() override;
Key get_key() override; Key get_key() override;
@ -49,8 +49,6 @@ private:
DisplayCoord m_dimensions; DisplayCoord m_dimensions;
void update_dimensions(); void update_dimensions();
DisplayLine m_status_line;
NCursesWin* m_menu_win = nullptr; NCursesWin* m_menu_win = nullptr;
std::vector<String> m_choices; std::vector<String> m_choices;
ColorPair m_menu_fg; ColorPair m_menu_fg;

View File

@ -20,7 +20,6 @@ namespace Kakoune
enum class RemoteUIMsg enum class RemoteUIMsg
{ {
PrintStatus,
MenuShow, MenuShow,
MenuSelect, MenuSelect,
MenuHide, MenuHide,
@ -217,8 +216,6 @@ public:
RemoteUI(int socket); RemoteUI(int socket);
~RemoteUI(); ~RemoteUI();
void print_status(const DisplayLine& status) override;
void menu_show(memoryview<String> choices, void menu_show(memoryview<String> choices,
DisplayCoord anchor, ColorPair fg, ColorPair bg, DisplayCoord anchor, ColorPair fg, ColorPair bg,
MenuStyle style) override; MenuStyle style) override;
@ -230,6 +227,7 @@ public:
void info_hide() override; void info_hide() override;
void draw(const DisplayBuffer& display_buffer, void draw(const DisplayBuffer& display_buffer,
const DisplayLine& status_line,
const DisplayLine& mode_line) override; const DisplayLine& mode_line) override;
bool is_key_available() override; bool is_key_available() override;
@ -257,13 +255,6 @@ RemoteUI::~RemoteUI()
close(m_socket_watcher.fd()); close(m_socket_watcher.fd());
} }
void RemoteUI::print_status(const DisplayLine& status)
{
Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::PrintStatus);
msg.write(status);
}
void RemoteUI::menu_show(memoryview<String> choices, void RemoteUI::menu_show(memoryview<String> choices,
DisplayCoord anchor, ColorPair fg, ColorPair bg, DisplayCoord anchor, ColorPair fg, ColorPair bg,
MenuStyle style) MenuStyle style)
@ -308,11 +299,13 @@ void RemoteUI::info_hide()
} }
void RemoteUI::draw(const DisplayBuffer& display_buffer, void RemoteUI::draw(const DisplayBuffer& display_buffer,
const DisplayLine& status_line,
const DisplayLine& mode_line) const DisplayLine& mode_line)
{ {
Message msg(m_socket_watcher.fd()); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::Draw); msg.write(RemoteUIMsg::Draw);
msg.write(display_buffer); msg.write(display_buffer);
msg.write(status_line);
msg.write(mode_line); msg.write(mode_line);
} }
@ -385,12 +378,6 @@ void RemoteClient::process_next_message()
RemoteUIMsg msg = read<RemoteUIMsg>(socket); RemoteUIMsg msg = read<RemoteUIMsg>(socket);
switch (msg) switch (msg)
{ {
case RemoteUIMsg::PrintStatus:
{
auto status = read<DisplayLine>(socket);
m_ui->print_status(status);
break;
}
case RemoteUIMsg::MenuShow: case RemoteUIMsg::MenuShow:
{ {
auto choices = read_vector<String>(socket); auto choices = read_vector<String>(socket);
@ -422,8 +409,9 @@ void RemoteClient::process_next_message()
case RemoteUIMsg::Draw: case RemoteUIMsg::Draw:
{ {
auto display_buffer = read<DisplayBuffer>(socket); auto display_buffer = read<DisplayBuffer>(socket);
auto status_line = read<DisplayLine>(socket);
auto mode_line = read<DisplayLine>(socket); auto mode_line = read<DisplayLine>(socket);
m_ui->draw(display_buffer, mode_line); m_ui->draw(display_buffer, status_line, mode_line);
break; break;
} }
} }

View File

@ -26,7 +26,6 @@ class UserInterface : public SafeCountable
{ {
public: public:
virtual ~UserInterface() {} virtual ~UserInterface() {}
virtual void print_status(const DisplayLine& status) = 0;
virtual void menu_show(memoryview<String> choices, virtual void menu_show(memoryview<String> choices,
DisplayCoord anchor, ColorPair fg, ColorPair bg, DisplayCoord anchor, ColorPair fg, ColorPair bg,
@ -39,6 +38,7 @@ public:
virtual void info_hide() = 0; virtual void info_hide() = 0;
virtual void draw(const DisplayBuffer& display_buffer, virtual void draw(const DisplayBuffer& display_buffer,
const DisplayLine& status_line,
const DisplayLine& mode_line) = 0; const DisplayLine& mode_line) = 0;
virtual DisplayCoord dimensions() = 0; virtual DisplayCoord dimensions() = 0;
virtual bool is_key_available() = 0; virtual bool is_key_available() = 0;