~kiwec/ke

4e961b210e46c764cb5be6439670a6e6a841bced — Wolf Clément 3 years ago 8189791
Fix scrolling and input handling
M src/Buffer.cpp => src/Buffer.cpp +24 -2
@@ 1,10 1,9 @@
#include <sstream>
#include <termbox.h>
#include "Buffer.hpp"
#include "Editor.hpp"
#include "Event.hpp"
#include "Gutter.hpp"
#include "StatusBar.hpp"
#include "Syntax.hpp"

void Buffer::draw(Canvas canvas) {
	const uint clbg = 235;


@@ 235,6 234,23 @@ bool Buffer::handle_key(tb_event *ev) {
	return handled;
}

bool Buffer::handle_mouse(tb_event* ev) {
	switch(ev->key) {
	case TB_KEY_MOUSE_WHEEL_UP:
		move_up();
		move_up();
		move_up();
		return true;
	case TB_KEY_MOUSE_WHEEL_DOWN:
		move_down();
		move_down();
		move_down();
		return true;
	}

	return false;
}

void Buffer::insert(wchar_t c, bool log_events) {
	if(c == L'\n') {
		bool at_end = is_at_EOL();


@@ 350,9 366,15 @@ void Buffer::scroll(uint old_current_line_nb) {
			m_first_visible_line_nb = 1;
		else if(m_first_visible_line_nb + padding_min > current_line_nb)
			m_first_visible_line_nb = current_line_nb - padding_min;

		if(m_first_visible_line_nb < 1)
			m_first_visible_line_nb = 1;
	} else {
		// Scroll down
		if(m_first_visible_line_nb + padding_max < current_line_nb)
			m_first_visible_line_nb = current_line_nb - padding_max;
		
		if(m_first_visible_line_nb > nb_lines)
			m_first_visible_line_nb = nb_lines;
	}
}

M src/Buffer.hpp => src/Buffer.hpp +6 -4
@@ 5,13 5,12 @@
#include "Canvas.hpp"
#include "Editable.hpp"
#include "File.hpp"
#include "Input.hpp"
#include "History.hpp"
#include "Section.hpp"
#include "Syntax.hpp"

class Action;

class Buffer : public File, public Editable {
class Buffer : public File, public Editable, public InputHandler {
private:
	/// First visible line number, starts at 1 (just like the gutter)
	/// If the user scrolled down, this number will be higher


@@ 44,7 43,10 @@ public:
	void draw(Canvas canvas);

	/// Handle keypresses
	virtual bool handle_key(tb_event *ev) override;
	virtual bool handle_key(tb_event* ev) override;

	/// Handle mouse actions
	virtual bool handle_mouse(tb_event* ev) override;

	/// Returns max width of a line
	int max_line_width();

M src/Editable.cpp => src/Editable.cpp +0 -4
@@ 85,10 85,6 @@ bool Editable::handle_key(tb_event* ev) {
	return true;
}

bool Editable::handle_mouse(tb_event* ev) {
	return false;
}

bool Editable::insert(wchar_t c) {
	m_text->insert(m_pos, 1, c);
	m_pos++;

M src/Editable.hpp => src/Editable.hpp +2 -5
@@ 1,10 1,9 @@
#pragma once
#include <string>
#include <termbox.h>
#include "Input.hpp"
#include "Line.hpp"

class Editable : public InputHandler {
class Editable {
private:
	/// The text
	std::wstring* m_text;


@@ 17,7 16,6 @@ public:

	Editable() {
		m_text = new std::wstring();
		Input::add_handler(this);
	}

	Editable(std::wstring* str) : m_text(str) {}


@@ 47,8 45,7 @@ public:
	void goto_start() { m_pos = 0; }

	/// Handle keypresses
	virtual bool handle_key(tb_event* ev) override;
	virtual bool handle_mouse(tb_event* ev) override;
	bool handle_key(tb_event* ev);

	/// Insert the given character at current position
	/// Returns true if editable was modified

M src/Editor.cpp => src/Editor.cpp +3 -14
@@ 1,7 1,6 @@
#include <stdlib.h>
#include <termbox.h>
#include "Editor.hpp"
#include "Line.hpp"
#include "Prompt.hpp"
#include "Gutter.hpp"
#include "StatusBar.hpp"


@@ 74,24 73,14 @@ bool Editor::handle_key(tb_event* ev) {
		return true;
	}
	
	if(m_status.prompt->is_prompting()) {
		if(m_status.prompt->handle_key(ev)) {
			return true;
		}
	}
	
	if(m_buf->handle_key(ev)) {
		return true;
	}
	
	return false;
}

bool Editor::handle_mouse(tb_event* ev) {
	switch(ev->key) {
		case TB_KEY_MOUSE_LEFT:
			m_buf->screen_to(ev->x - Gutter::width(*m_buf) - 1, ev->y);
			return true;
	case TB_KEY_MOUSE_LEFT:
		m_buf->screen_to(ev->x - Gutter::width(*m_buf) - 1, ev->y);
		return true;
	}

	return false;

M src/Editor.hpp => src/Editor.hpp +2 -4
@@ 12,8 12,8 @@ public:
	void draw();

	/// Handle keypresses
	bool handle_key(tb_event* ev) override;
	bool handle_mouse(tb_event* ev) override;
	virtual bool handle_key(tb_event* ev) override;
	virtual bool handle_mouse(tb_event* ev) override;

	/// Open a file
	void open(std::wstring filename);


@@ 21,5 21,3 @@ public:
	/// Close the editor and clean up
	void shutdown();
};

extern Editor KE;

M src/Gutter.cpp => src/Gutter.cpp +0 -3
@@ 1,9 1,6 @@
#include <cmath>
#include "Buffer.hpp"
#include "Editor.hpp"
#include "Line.hpp"
#include "Gutter.hpp"
#include "StatusBar.hpp"

void Gutter::draw(Buffer& buf) {
	const uint fg = TB_DEFAULT;

M src/Input.hpp => src/Input.hpp +20 -12
@@ 2,13 2,31 @@
#include <stack>
#include <termbox.h>

class InputHandler;

class Input {
private:
	static InputHandler* m_head;

public:
	static void add_handler(InputHandler*);
	static void remove_handler(InputHandler*);
	static void handle(tb_event* ev, bool is_mouse);
};

class InputHandler {
private:
	InputHandler* m_next = nullptr;
	friend class Input;

protected:
	virtual ~InputHandler() {};
public:
	InputHandler() {
		Input::add_handler(this);
	}

	virtual ~InputHandler() {
		Input::remove_handler(this);
	}

	/// Handle keypresses
	/// returns true if the key was handled


@@ 18,13 36,3 @@ protected:
	/// returns true if the event was handled
	virtual bool handle_mouse(tb_event* ev) = 0;
};

class Input {
private:
	static InputHandler* m_head;

public:
	static void add_handler(InputHandler*);
	static void remove_handler(InputHandler*);
	static void handle(tb_event* ev, bool is_mouse);
};

M src/Prompt.cpp => src/Prompt.cpp +6 -0
@@ 25,6 25,8 @@ uint Prompt::get_visible_x() {
}

bool Prompt::handle_key(tb_event* ev) {
	if(!m_prompting) return false;

	switch(ev->key) {
	case TB_KEY_ENTER:
		m_prompting = false;


@@ 44,3 46,7 @@ bool Prompt::handle_key(tb_event* ev) {

	return true;
}

bool Prompt::handle_mouse(tb_event* ev) {
	return false;
}

M src/Prompt.hpp => src/Prompt.hpp +4 -2
@@ 1,10 1,11 @@
#pragma once
#include "Editable.hpp"
#include <functional>
#include <string>
#include <termbox.h>
#include "Editable.hpp"
#include "Input.hpp"

class Prompt : public Editable {
class Prompt : public Editable, public InputHandler {
private:
	std::wstring m_prompt = L"Example prompt : ";
	std::wstring m_answer;


@@ 16,6 17,7 @@ private:
public:
	void draw(int rwidth);
	virtual bool handle_key(tb_event* ev) override;
	virtual bool handle_mouse(tb_event* ev) override;

	Prompt() : Editable(&m_answer), m_prompting(false) {}


M src/StatusBar.cpp => src/StatusBar.cpp +7 -1
@@ 47,7 47,13 @@ void StatusBar::draw(Buffer& buf) {
	Canvas::print(right_str.c_str(), tb_width() - rwidth, tb_height() - 1, fg, bg);

	// Prompt
	prompt->draw(rwidth);
	if(prompt != nullptr) {
		if(prompt->is_prompting()) {
			prompt->draw(rwidth);
		} else {
			prompt = nullptr;
		}
	}
}

int StatusBar::height() {

M src/StatusBar.hpp => src/StatusBar.hpp +1 -5
@@ 10,11 10,7 @@ private:
	const int16_t bg = 220;

public:
	std::unique_ptr<Prompt> prompt;

	StatusBar() {
		prompt = std::make_unique<Prompt>();
	}
	std::unique_ptr<Prompt> prompt = nullptr;

	void draw(Buffer& buf);
	int height();

M src/main.cpp => src/main.cpp +0 -1
@@ 25,7 25,6 @@ int main(int argc, const char** argv) {

	// Start editor
	Editor editor;
	Input::add_handler(&editor);
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
	editor.open(argc == 2 ? converter.from_bytes(argv[1]) : L"");
	for(;;) {