Compare commits
No commits in common. "textinput" and "master" have entirely different histories.
7 changed files with 11 additions and 280 deletions
|
|
@ -7,8 +7,5 @@
|
||||||
"ncui": {
|
"ncui": {
|
||||||
"path": ".."
|
"path": ".."
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"libs": [
|
|
||||||
"form"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,7 @@ final class Simple : ScreenBase
|
||||||
|
|
||||||
override void build(ScreenContext context, Window window, WidgetContainer ui)
|
override void build(ScreenContext context, Window window, WidgetContainer ui)
|
||||||
{
|
{
|
||||||
auto textIntput = new TextInput(5, 2, 10, "Hello");
|
auto okBtn = new Button(3, 2, "OK", () => ScreenAction.push(new Simple()));
|
||||||
// auto okBtn = new Button(3, 2, "OK", () => ScreenAction.push(new Simple()));
|
|
||||||
auto okBtn = new Button(3, 2, "OK", () {
|
|
||||||
textIntput.close();
|
|
||||||
return ScreenAction.quit(ScreenResult.none());
|
|
||||||
});
|
|
||||||
auto cancelBtn = new Button(3, 9, "Cancel", () => ScreenAction.pop(ScreenResult.none()));
|
auto cancelBtn = new Button(3, 9, "Cancel", () => ScreenAction.pop(ScreenResult.none()));
|
||||||
|
|
||||||
auto disableOk = new Checkbox(4, 2,"Disable OK", false, (checked) {
|
auto disableOk = new Checkbox(4, 2,"Disable OK", false, (checked) {
|
||||||
|
|
@ -37,7 +32,6 @@ final class Simple : ScreenBase
|
||||||
_ui.add(okBtn);
|
_ui.add(okBtn);
|
||||||
_ui.add(cancelBtn);
|
_ui.add(cancelBtn);
|
||||||
_ui.add(disableOk);
|
_ui.add(disableOk);
|
||||||
_ui.add(textIntput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override ScreenAction handleGlobal(ScreenContext context, KeyEvent event)
|
override ScreenAction handleGlobal(ScreenContext context, KeyEvent event)
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,4 @@ struct NCWin
|
||||||
{
|
{
|
||||||
return _p is null;
|
return _p is null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void opAssign(NCWin rhs)
|
|
||||||
{
|
|
||||||
_p = rhs._p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void opAssign(WINDOW* rhs)
|
|
||||||
{
|
|
||||||
_p = rhs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,13 +131,12 @@ final class Session
|
||||||
private:
|
private:
|
||||||
NCWin _root;
|
NCWin _root;
|
||||||
bool _ended;
|
bool _ended;
|
||||||
SessionConfig _config;
|
|
||||||
|
|
||||||
// Применяет параметры конфигурации к активной ncurses-сессии.
|
// Применяет параметры конфигурации к активной ncurses-сессии.
|
||||||
void setup(ref const(SessionConfig) sc)
|
void setup(ref const(SessionConfig) config)
|
||||||
{
|
{
|
||||||
// Настройка режима обработки ввода терминалом.
|
// Настройка режима обработки ввода терминалом.
|
||||||
final switch (sc.mode)
|
final switch (config.mode)
|
||||||
{
|
{
|
||||||
case InputMode.raw:
|
case InputMode.raw:
|
||||||
ncuiNotErr!nocbreak();
|
ncuiNotErr!nocbreak();
|
||||||
|
|
@ -155,7 +154,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Настройка отображения вводимых символов.
|
// Настройка отображения вводимых символов.
|
||||||
final switch (sc.echo)
|
final switch (config.echo)
|
||||||
{
|
{
|
||||||
case Echo.on:
|
case Echo.on:
|
||||||
ncuiNotErr!echo();
|
ncuiNotErr!echo();
|
||||||
|
|
@ -166,15 +165,15 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Настройка видимости курсора.
|
// Настройка видимости курсора.
|
||||||
ncuiNotErr!curs_set(sc.cursor);
|
ncuiNotErr!curs_set(config.cursor);
|
||||||
// Настройка задержки при нажатии на ESC
|
// Настройка задержки при нажатии на ESC
|
||||||
ncuiNotErr!set_escdelay(sc.escDelay);
|
ncuiNotErr!set_escdelay(config.escDelay);
|
||||||
// Настройка обработки специальных клавиш
|
// Настройка обработки специальных клавиш
|
||||||
ncuiNotErr!keypad(_root, sc.keypad);
|
ncuiNotErr!keypad(_root, config.keypad);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
this(const SessionConfig sc)
|
this(const SessionConfig config)
|
||||||
{
|
{
|
||||||
// Если на этапе инициализации сработает проблема с конфигурированием сессии
|
// Если на этапе инициализации сработает проблема с конфигурированием сессии
|
||||||
scope (failure)
|
scope (failure)
|
||||||
|
|
@ -194,9 +193,7 @@ public:
|
||||||
// Установить флаг инициализации ncurses
|
// Установить флаг инициализации ncurses
|
||||||
gInitialized = true;
|
gInitialized = true;
|
||||||
// Применение конфигурации
|
// Применение конфигурации
|
||||||
setup(sc);
|
setup(config);
|
||||||
|
|
||||||
_config = sc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NCWin root()
|
NCWin root()
|
||||||
|
|
@ -204,11 +201,6 @@ public:
|
||||||
return _root;
|
return _root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property SessionConfig config()
|
|
||||||
{
|
|
||||||
return _config;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyEvent readKey(NCWin inputWindow)
|
KeyEvent readKey(NCWin inputWindow)
|
||||||
{
|
{
|
||||||
dchar ch;
|
dchar ch;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ protected:
|
||||||
WidgetContainer _ui;
|
WidgetContainer _ui;
|
||||||
bool _built;
|
bool _built;
|
||||||
|
|
||||||
bool _clearNext = true;
|
|
||||||
|
|
||||||
void ensureWindow(ScreenContext context);
|
void ensureWindow(ScreenContext context);
|
||||||
void build(ScreenContext context, Window window, WidgetContainer ui);
|
void build(ScreenContext context, Window window, WidgetContainer ui);
|
||||||
void layout(ScreenContext context, Window window, WidgetContainer ui)
|
void layout(ScreenContext context, Window window, WidgetContainer ui)
|
||||||
|
|
@ -33,12 +31,7 @@ private:
|
||||||
import deimos.ncurses : doupdate;
|
import deimos.ncurses : doupdate;
|
||||||
import ncui.lib.checks;
|
import ncui.lib.checks;
|
||||||
|
|
||||||
if (_clearNext)
|
|
||||||
{
|
|
||||||
_window.erase();
|
_window.erase();
|
||||||
_clearNext = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout(context, _window, _ui);
|
layout(context, _window, _ui);
|
||||||
_ui.render(_window, context);
|
_ui.render(_window, context);
|
||||||
_window.noutrefresh();
|
_window.noutrefresh();
|
||||||
|
|
@ -72,8 +65,6 @@ public:
|
||||||
_built = true;
|
_built = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearNext = true;
|
|
||||||
|
|
||||||
renderAll(context);
|
renderAll(context);
|
||||||
return ScreenAction.none();
|
return ScreenAction.none();
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +103,6 @@ public:
|
||||||
|
|
||||||
_window = null;
|
_window = null;
|
||||||
_built = false;
|
_built = false;
|
||||||
_clearNext = true;
|
|
||||||
_ui = new WidgetContainer();
|
_ui = new WidgetContainer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,3 @@ public import ncui.lib.logger;
|
||||||
public import ncui.widgets.container;
|
public import ncui.widgets.container;
|
||||||
public import ncui.widgets.button;
|
public import ncui.widgets.button;
|
||||||
public import ncui.widgets.checkbox;
|
public import ncui.widgets.checkbox;
|
||||||
public import ncui.widgets.textinput;
|
|
||||||
|
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
module ncui.widgets.textinput;
|
|
||||||
|
|
||||||
import deimos.form;
|
|
||||||
|
|
||||||
import ncui.widgets.widget;
|
|
||||||
import ncui.core.window;
|
|
||||||
import ncui.core.event;
|
|
||||||
import ncui.core.ncwin;
|
|
||||||
import ncui.engine.screen;
|
|
||||||
import ncui.engine.action;
|
|
||||||
import ncui.lib.checks;
|
|
||||||
|
|
||||||
import std.string : toStringz;
|
|
||||||
|
|
||||||
alias OnChange = void delegate(string text);
|
|
||||||
|
|
||||||
final class TextInput : IWidget
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
OnChange _onChange;
|
|
||||||
int _y;
|
|
||||||
int _x;
|
|
||||||
int _width;
|
|
||||||
bool _enabled = true;
|
|
||||||
|
|
||||||
FIELD* _field;
|
|
||||||
// 0: field, 1: null (терминатор для new_form)
|
|
||||||
FIELD*[2] _fields;
|
|
||||||
FORM* _form;
|
|
||||||
|
|
||||||
NCWin _window;
|
|
||||||
NCWin _subWindow;
|
|
||||||
|
|
||||||
bool _posted = false;
|
|
||||||
|
|
||||||
void ensureCreated()
|
|
||||||
{
|
|
||||||
if (_form !is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_field = new_field(1, _width, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
set_field_back(_field, A_UNDERLINE);
|
|
||||||
field_opts_off(_field, O_AUTOSKIP);
|
|
||||||
field_opts_on(_field, O_EDIT);
|
|
||||||
|
|
||||||
_fields[0] = _field;
|
|
||||||
_fields[1] = null;
|
|
||||||
|
|
||||||
_form = new_form(cast(FIELD**) _fields.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bindTo(Window window)
|
|
||||||
{
|
|
||||||
auto parent = window.handle;
|
|
||||||
|
|
||||||
if (_window.ptr == parent.ptr && !_subWindow.isNull)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_posted)
|
|
||||||
{
|
|
||||||
unpost_form(_form);
|
|
||||||
_posted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_subWindow.isNull)
|
|
||||||
{
|
|
||||||
delwin(_subWindow);
|
|
||||||
_subWindow = NCWin(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
_subWindow = derwin(parent, 1, _width, _y, _x);
|
|
||||||
_window = parent;
|
|
||||||
|
|
||||||
set_form_win(_form, parent);
|
|
||||||
set_form_sub(_form, _subWindow);
|
|
||||||
|
|
||||||
post_form(_form);
|
|
||||||
_posted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyStyle(ScreenContext context, bool focused)
|
|
||||||
{
|
|
||||||
if (focused && _enabled)
|
|
||||||
{
|
|
||||||
set_field_back(_field, A_UNDERLINE | A_REVERSE);
|
|
||||||
pos_form_cursor(_form);
|
|
||||||
|
|
||||||
import ncui.core.session : Cursor;
|
|
||||||
|
|
||||||
curs_set(Cursor.high);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set_field_back(_field, A_UNDERLINE);
|
|
||||||
curs_set(context.session.config.cursor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void driveRequest(int request)
|
|
||||||
{
|
|
||||||
form_driver_w(_form, KEY_CODE_YES, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void driveChar(dchar ch)
|
|
||||||
{
|
|
||||||
form_driver_w(_form, OK, ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
this(int y, int x, int width, string initial = string.init, OnChange onChange = null)
|
|
||||||
{
|
|
||||||
_y = y;
|
|
||||||
_x = x;
|
|
||||||
_width = width;
|
|
||||||
_onChange = onChange;
|
|
||||||
|
|
||||||
ensureCreated();
|
|
||||||
|
|
||||||
if (initial.length)
|
|
||||||
{
|
|
||||||
set_field_buffer(_field, 0, initial.toStringz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override @property bool focusable()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
override @property bool enabled()
|
|
||||||
{
|
|
||||||
return _enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
override void render(Window window, ScreenContext context, bool focused)
|
|
||||||
{
|
|
||||||
ensureCreated();
|
|
||||||
bindTo(window);
|
|
||||||
applyStyle(context, focused);
|
|
||||||
}
|
|
||||||
|
|
||||||
override ScreenAction handle(ScreenContext context, KeyEvent event)
|
|
||||||
{
|
|
||||||
if (!_enabled)
|
|
||||||
{
|
|
||||||
return ScreenAction.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
if (event.isKeyCode)
|
|
||||||
{
|
|
||||||
switch (event.ch)
|
|
||||||
{
|
|
||||||
case KEY_LEFT:
|
|
||||||
driveRequest(REQ_PREV_CHAR);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
driveRequest(REQ_NEXT_CHAR);
|
|
||||||
break;
|
|
||||||
case KEY_HOME:
|
|
||||||
driveRequest(REQ_BEG_LINE);
|
|
||||||
break;
|
|
||||||
case KEY_END:
|
|
||||||
driveRequest(REQ_END_LINE);
|
|
||||||
break;
|
|
||||||
case KEY_BACKSPACE:
|
|
||||||
driveRequest(REQ_DEL_PREV);
|
|
||||||
changed = true;
|
|
||||||
break;
|
|
||||||
case KEY_DC:
|
|
||||||
driveRequest(REQ_DEL_CHAR);
|
|
||||||
changed = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ScreenAction.none();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event.isChar)
|
|
||||||
{
|
|
||||||
// Backspace иногда приходит как символ (127 или '\b')
|
|
||||||
if (event.ch == 127 || event.ch == '\b')
|
|
||||||
{
|
|
||||||
driveRequest(REQ_DEL_PREV);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
driveChar(event.ch);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ScreenAction.none();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
if (_posted && _form !is null)
|
|
||||||
{
|
|
||||||
unpost_form(_form);
|
|
||||||
_posted = false;
|
|
||||||
}
|
|
||||||
if (_form !is null)
|
|
||||||
{
|
|
||||||
free_form(_form);
|
|
||||||
_form = null;
|
|
||||||
}
|
|
||||||
if (_field !is null)
|
|
||||||
{
|
|
||||||
free_field(_field);
|
|
||||||
_field = null;
|
|
||||||
}
|
|
||||||
if (!_subWindow.isNull)
|
|
||||||
{
|
|
||||||
delwin(_subWindow);
|
|
||||||
_subWindow = NCWin(null);
|
|
||||||
}
|
|
||||||
_window = NCWin(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue