Skip to content

Commit

Permalink
Shell: Working on the command line widget
Browse files Browse the repository at this point in the history
The command line widget has focus initially. It now draws a simple
line of text for the prompt.
  • Loading branch information
skyjake committed Jan 23, 2013
1 parent c5c5e3e commit 3deb54f
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 57 deletions.
36 changes: 30 additions & 6 deletions doomsday/tools/shell/shell-text/src/commandlinewidget.cpp
Expand Up @@ -17,31 +17,55 @@
*/

#include "commandlinewidget.h"
#include <de/String>

using namespace de;

struct CommandLineWidget::Instance
{
Instance()
{}
ConstantRule *height;
String command;
int cursorPos;

Instance() : cursorPos(0)
{
// Initial height of the command line (1 row).
height = new ConstantRule(1);
}

~Instance()
{}
{
releaseRef(height);
}
};

CommandLineWidget::CommandLineWidget(de::String const &name) : TextWidget(name), d(new Instance)
{
rule().setInput(RectangleRule::Height, d->height);
}

CommandLineWidget::~CommandLineWidget()
{
delete d;
}

Vector2i CommandLineWidget::cursorPosition()
{
de::Rectanglei pos = rule().recti();
return pos.topLeft + Vector2i(2 + d->cursorPos);
}

void CommandLineWidget::draw()
{
if(!targetCanvas()) return;
TextCanvas *cv = targetCanvas();
if(!cv) return;

de::Rectanglei pos = rule().recti();

targetCanvas()->fill(pos, TextCanvas::Char('+'));
}
TextCanvas::Char::Attribs attr = TextCanvas::Char::Reverse;
TextCanvas::Char bg(' ', attr);

cv->fill(pos, bg);
cv->put(pos.topLeft, TextCanvas::Char('>', attr | TextCanvas::Char::Bold));
cv->drawText(pos.topLeft + Vector2i(2, 0), d->command, attr);
}
8 changes: 8 additions & 0 deletions doomsday/tools/shell/shell-text/src/commandlinewidget.h
Expand Up @@ -24,9 +24,17 @@
class CommandLineWidget : public TextWidget
{
public:
/**
* The height rule of the widget is set up during construction.
*
* @param name Widget name.
*/
CommandLineWidget(de::String const &name = "");

virtual ~CommandLineWidget();

de::Vector2i cursorPosition();

void draw();

private:
Expand Down
11 changes: 11 additions & 0 deletions doomsday/tools/shell/shell-text/src/cursesapp.cpp
Expand Up @@ -23,6 +23,7 @@
#include "cursesapp.h"
#include "cursestextcanvas.h"
#include "textrootwidget.h"
#include "textwidget.h"
#include <curses.h>
#include <stdio.h>
#include <de/Clock>
Expand Down Expand Up @@ -161,6 +162,9 @@ struct CursesApp::Instance

// The root widget will update the UI.
rootWidget->setViewSize(size);

// We must redraw all characters since wclear was called.
rootWidget->rootCanvas().markDirty();
}
else if(key & KEY_CODE_YES)
{
Expand Down Expand Up @@ -192,6 +196,13 @@ struct CursesApp::Instance
{
rootWidget->draw();
}

if(rootWidget->focus())
{
de::Vector2i p = rootWidget->focus()->cursorPosition();
wmove(rootWin, p.y, p.x);
wrefresh(rootWin);
}
}

void windowWasResized() // called from signal handler
Expand Down
43 changes: 26 additions & 17 deletions doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp
Expand Up @@ -18,13 +18,28 @@

#include "cursestextcanvas.h"

struct CursesTextCanvas::Instance
{
WINDOW *window;
Coord origin;
de::Vector2i cursorPos;

Instance(WINDOW *window, Coord const &originInWindow)
: window(window), origin(originInWindow)
{}
};

CursesTextCanvas::CursesTextCanvas(Size const &size, WINDOW *window, Coord const &originInWindow)
: TextCanvas(size), _window(window), _origin(originInWindow)
: TextCanvas(size), d(new Instance(window, originInWindow))
{}

void CursesTextCanvas::setCursorPosition(const de::Vector2i &pos)
{
d->cursorPos = pos;
}

void CursesTextCanvas::show()
{
bool somethingDrawn = false;
Size const dims = size();

// All dirty characters are drawn.
Expand All @@ -37,7 +52,7 @@ void CursesTextCanvas::show()
Coord const pos(col, row);
Char const &ch = at(pos);

if(!ch.attrib.dirty)
if(!ch.isDirty())
{
needMove = true;
continue;
Expand All @@ -46,29 +61,23 @@ void CursesTextCanvas::show()
if(needMove)
{
// Advance cursor.
wmove(_window, _origin.y + row, _origin.x + col);
wmove(d->window, d->origin.y + row, d->origin.x + col);
needMove = false;
}

// Set attributes.
wattrset(_window,
(ch.attrib.bold? A_BOLD : 0) |
(ch.attrib.reverse? A_REVERSE : 0) |
(ch.attrib.underline? A_UNDERLINE : 0));

waddch(_window, ch.ch.unicode()); // cursor advanced
wattrset(d->window,
(ch.attribs.testFlag(Char::Bold)? A_BOLD : 0) |
(ch.attribs.testFlag(Char::Reverse)? A_REVERSE : 0) |
(ch.attribs.testFlag(Char::Underline)? A_UNDERLINE : 0));

somethingDrawn = true;
waddch(d->window, ch.ch.unicode()); // cursor advanced
}
}

wmove(_window, 0, 0);

// Mark everything clean.
TextCanvas::show();

if(somethingDrawn)
{
wrefresh(_window);
}
wmove(d->window, d->cursorPos.y, d->cursorPos.x);
wrefresh(d->window);
}
6 changes: 4 additions & 2 deletions doomsday/tools/shell/shell-text/src/cursestextcanvas.h
Expand Up @@ -27,11 +27,13 @@ class CursesTextCanvas : public TextCanvas
public:
CursesTextCanvas(Size const &size, WINDOW *window, Coord const &originInWindow = Coord(0, 0));

void setCursorPosition(de::Vector2i const &pos);

void show();

private:
WINDOW *_window;
Coord _origin;
struct Instance;
Instance *d;
};

#endif // CURSESTEXTCANVAS_H
17 changes: 6 additions & 11 deletions doomsday/tools/shell/shell-text/src/shellapp.cpp
Expand Up @@ -27,21 +27,16 @@ struct ShellApp::Instance
ShellApp &self;
LogWidget *log;
CommandLineWidget *cli;
ConstantRule *cliHeight;

Instance(ShellApp &a) : self(a)
{
RootWidget &root = self.rootWidget();

// Initial height of the command line (1 row).
cliHeight = new ConstantRule(1);

cli = new CommandLineWidget;
cli->rule()
.setInput(RectangleRule::Left, root.viewLeft())
.setInput(RectangleRule::Width, root.viewWidth())
.setInput(RectangleRule::Bottom, root.viewBottom())
.setInput(RectangleRule::Height, cliHeight);
.setInput(RectangleRule::Bottom, root.viewBottom());

log = new LogWidget;
log->rule()
Expand All @@ -50,14 +45,14 @@ struct ShellApp::Instance
.setInput(RectangleRule::Top, root.viewTop())
.setInput(RectangleRule::Bottom, cli->rule().top());

root.add(cli); // takes ownership
root.add(log); // takes ownership
root.add(cli);
root.add(log);

root.setFocus(cli);
}

~Instance()
{
releaseRef(cliHeight);
}
{}
};

ShellApp::ShellApp(int &argc, char **argv)
Expand Down
35 changes: 34 additions & 1 deletion doomsday/tools/shell/shell-text/src/textcanvas.cpp
Expand Up @@ -90,7 +90,11 @@ struct TextCanvas::Instance
Line &line = lines[row];
for(int col = 0; col < line.size(); ++col)
{
line[col].attrib.dirty = markDirty;
Char &c = line[col];
if(markDirty)
c.attribs |= Char::Dirty;
else
c.attribs &= ~Char::Dirty;
}
}
}
Expand Down Expand Up @@ -133,6 +137,11 @@ bool TextCanvas::isValid(const Coord &pos) const
return (pos.x >= 0 && pos.y >= 0 && pos.x < d->size.x && pos.y < d->size.y);
}

void TextCanvas::markDirty()
{
d->markAllAsDirty(true);
}

void TextCanvas::fill(de::Rectanglei const &rect, Char const &ch)
{
for(int y = rect.top(); y < rect.bottom(); ++y)
Expand All @@ -145,6 +154,27 @@ void TextCanvas::fill(de::Rectanglei const &rect, Char const &ch)
}
}

void TextCanvas::put(de::Vector2i const &pos, Char const &ch)
{
if(isValid(pos))
{
at(pos) = ch;
}
}

void TextCanvas::drawText(de::Vector2i const &pos, de::String const &text, Char::Attribs const &attribs)
{
de::Vector2i p = pos;
DENG2_FOR_EACH_CONST(de::String, i, text)
{
if(isValid(p))
{
at(p) = Char(*i, attribs);
}
p.x += 1;
}
}

void TextCanvas::blit(TextCanvas &dest, Coord const &topLeft) const
{
for(int y = 0; y < d->size.y; ++y)
Expand All @@ -165,3 +195,6 @@ void TextCanvas::show()
{
d->markAllAsDirty(false);
}

void TextCanvas::setCursorPosition(const de::Vector2i &)
{}

0 comments on commit 3deb54f

Please sign in to comment.