Skip to content

Commit

Permalink
Shell|libdeng2: Key event generation and dispatch to the widgets
Browse files Browse the repository at this point in the history
The keys from curses are converted to a de::String and passed to
the widgets inside a KeyEvent.

de::Event is the base class for all types of events.
  • Loading branch information
skyjake committed Jan 23, 2013
1 parent 3deb54f commit 7e3cfc0
Show file tree
Hide file tree
Showing 16 changed files with 175 additions and 11 deletions.
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/Event
@@ -0,0 +1 @@
#include "widgets/event.h"
53 changes: 53 additions & 0 deletions doomsday/libdeng2/include/de/widgets/event.h
@@ -0,0 +1,53 @@
/** @file event.h Base class for events.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDENG2_EVENT_H
#define LIBDENG2_EVENT_H

namespace de {

/**
* Base class for events.
*
* @ingroup widgets
*/
class Event
{
public:
enum {
KeyPress = 1,
KeyRelease = 2
};

public:
Event(int type_ = 0) : _type(type_) {}

virtual ~Event() {}

/**
* Returns the type code of the event.
*/
int type() const { return _type; }

private:
int _type;
};

} // namespace de

#endif // LIBDENG2_EVENT_H
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/widgets/rootwidget.h
Expand Up @@ -74,6 +74,7 @@ class RootWidget : public Widget

void initialize();
void draw();
bool handleEvent(Event const *event);

private:
struct Instance;
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libdeng2/include/de/widgets/widget.h
Expand Up @@ -21,11 +21,11 @@
#define LIBDENG2_WIDGET_H

#include "../String"
#include "../Event"

namespace de {

class RootWidget;
class Event;

class Widget
{
Expand Down
9 changes: 5 additions & 4 deletions doomsday/libdeng2/libdeng2.pro
Expand Up @@ -75,7 +75,8 @@ HEADERS += \
include/de/Rectangle \
include/de/UnixInfo \
include/de/Vector \
include/de/Version
include/de/Version \
include/de/widgets/event.h

HEADERS += \
include/de/c_wrapper.h \
Expand Down Expand Up @@ -104,14 +105,14 @@ SOURCES += \
src/error.cpp \
src/version.cpp \
src/core/app.cpp \
src/core/callbacktimer.cpp \
src/core/clock.cpp \
src/core/commandline.cpp \
src/core/config.cpp \
src/core/callbacktimer.cpp \
src/core/library.cpp \
src/core/log.cpp \
src/core/logbuffer.cpp \
src/core/unixinfo.cpp \
include/de/core/clock.cpp
src/core/unixinfo.cpp

OTHER_FILES += \
modules/Config.de \
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions doomsday/libdeng2/src/widgets/rootwidget.cpp
Expand Up @@ -123,4 +123,9 @@ void RootWidget::draw()
Rule::markRulesValid(); // All done for this frame.
}

bool RootWidget::handleEvent(Event const *event)
{
return dispatchEvent(event, &Widget::handleEvent);
}

} // namespace de
2 changes: 2 additions & 0 deletions doomsday/libdeng2/widgets.pri
Expand Up @@ -3,6 +3,7 @@ HEADERS += \
include/de/AnimationVector \
include/de/DelegateRule \
include/de/ConstantRule \
include/de/Event \
include/de/OperatorRule \
include/de/RectangleRule \
include/de/RootWidget \
Expand All @@ -12,6 +13,7 @@ HEADERS += \
include/de/widgets/animationvector.h \
include/de/widgets/constantrule.h \
include/de/widgets/delegaterule.h \
include/de/widgets/event.h \
include/de/widgets/operatorrule.h \
include/de/widgets/rectanglerule.h \
include/de/widgets/rootwidget.h \
Expand Down
3 changes: 2 additions & 1 deletion doomsday/tools/shell/shell-text/shell-text.pro
Expand Up @@ -33,7 +33,8 @@ HEADERS += \
src/logwidget.h \
src/textwidget.h \
src/textrootwidget.h \
src/commandlinewidget.h
src/commandlinewidget.h \
src/keyevent.h

SOURCES += \
src/cursesapp.cpp \
Expand Down
14 changes: 14 additions & 0 deletions doomsday/tools/shell/shell-text/src/commandlinewidget.cpp
Expand Up @@ -17,6 +17,8 @@
*/

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

using namespace de;
Expand Down Expand Up @@ -69,3 +71,15 @@ void CommandLineWidget::draw()
cv->put(pos.topLeft, TextCanvas::Char('>', attr | TextCanvas::Char::Bold));
cv->drawText(pos.topLeft + Vector2i(2, 0), d->command, attr);
}

bool CommandLineWidget::handleEvent(Event const *event)
{
DENG2_ASSERT(event->type() == Event::KeyPress);
KeyEvent const *ev = static_cast<KeyEvent const *>(event);

d->command += ev->key();
d->cursorPos++;

root().requestDraw();
return true;
}
1 change: 1 addition & 0 deletions doomsday/tools/shell/shell-text/src/commandlinewidget.h
Expand Up @@ -36,6 +36,7 @@ class CommandLineWidget : public TextWidget
de::Vector2i cursorPosition();

void draw();
bool handleEvent(de::Event const *event);

private:
struct Instance;
Expand Down
35 changes: 32 additions & 3 deletions doomsday/tools/shell/shell-text/src/cursesapp.cpp
Expand Up @@ -22,6 +22,7 @@
#include <QDebug>
#include "cursesapp.h"
#include "cursestextcanvas.h"
#include "keyevent.h"
#include "textrootwidget.h"
#include "textwidget.h"
#include <curses.h>
Expand Down Expand Up @@ -69,10 +70,11 @@ struct CursesApp::Instance
WINDOW *rootWin;
de::Vector2i rootSize;
QTimer *refreshTimer;
int unicodeCont;

TextRootWidget *rootWidget;

Instance(CursesApp &a) : self(a), rootWidget(0)
Instance(CursesApp &a) : self(a), unicodeCont(0), rootWidget(0)
{
de::Animation::setClock(&clock);
de::Clock::setAppClock(&clock);
Expand Down Expand Up @@ -187,12 +189,39 @@ struct CursesApp::Instance
}
else
{
qDebug() << "Got key" << QString("0x%1").arg(key, 0, 16).toAscii().constData();
// Convert the key code(s) into a string.
de::String keyStr;

if(unicodeCont)
{
char utf8[3] = { char(unicodeCont), char(key), 0 };
keyStr = de::String(utf8);
//qDebug() << QString("%1 %2, %3").arg(unicodeCont, 0, 16).arg(key, 0, 16)
// .arg(keyStr[0].unicode(), 0, 16);
unicodeCont = 0;
}
else
{
// Unicode continuation?
if((key >= 0x80 && key <= 0xbf) ||
(key >= 0xc2 && key <= 0xf4))
{
unicodeCont = key;
continue;
}
else
{
keyStr.append(QChar(key));
}
}

KeyEvent ev(keyStr);
rootWidget->handleEvent(&ev);
}
}

// Automatically redraw the UI if the values of layout rules have changed.
if(de::Rule::invalidRulesExist())
if(de::Rule::invalidRulesExist() || rootWidget->drawWasRequested())
{
rootWidget->draw();
}
Expand Down
3 changes: 2 additions & 1 deletion doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp
Expand Up @@ -71,7 +71,8 @@ void CursesTextCanvas::show()
(ch.attribs.testFlag(Char::Reverse)? A_REVERSE : 0) |
(ch.attribs.testFlag(Char::Underline)? A_UNDERLINE : 0));

waddch(d->window, ch.ch.unicode()); // cursor advanced
// TODO: What about Unicode output? (libncursesw?)
waddch(d->window, ch.ch.toAscii()); // cursor advanced
}
}

Expand Down
39 changes: 39 additions & 0 deletions doomsday/tools/shell/shell-text/src/keyevent.h
@@ -0,0 +1,39 @@
/** @file keyevent.h Key event.
*
* @authors Copyright © 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef KEYEVENT_H
#define KEYEVENT_H

#include <de/Event>
#include <de/String>

/**
* Key press event generated when the user presses a key on the keyboard.
*/
class KeyEvent : public de::Event
{
public:
KeyEvent(de::String const &keyStr) : Event(KeyPress), _key(keyStr) {}

de::String key() const { return _key; }

private:
de::String _key;
};

#endif // KEYEVENT_H
13 changes: 12 additions & 1 deletion doomsday/tools/shell/shell-text/src/textrootwidget.cpp
Expand Up @@ -19,7 +19,7 @@
#include "textrootwidget.h"
#include "textwidget.h"

TextRootWidget::TextRootWidget(TextCanvas *cv) : de::RootWidget(), _canvas(cv)
TextRootWidget::TextRootWidget(TextCanvas *cv) : de::RootWidget(), _canvas(cv), _drawRequest(false)
{
DENG2_ASSERT(cv != 0);
setViewSize(cv->size());
Expand All @@ -46,6 +46,16 @@ TextWidget *TextRootWidget::focus() const
return static_cast<TextWidget *>(RootWidget::focus());
}

void TextRootWidget::requestDraw()
{
_drawRequest = true;
}

bool TextRootWidget::drawWasRequested() const
{
return _drawRequest;
}

void TextRootWidget::draw()
{
RootWidget::draw();
Expand All @@ -54,4 +64,5 @@ void TextRootWidget::draw()
_canvas->setCursorPosition(focus()->cursorPosition());
}
_canvas->show();
_drawRequest = false;
}
5 changes: 5 additions & 0 deletions doomsday/tools/shell/shell-text/src/textrootwidget.h
Expand Up @@ -38,6 +38,10 @@ class TextRootWidget : public de::RootWidget

TextCanvas &rootCanvas();

void requestDraw();

bool drawWasRequested() const;

/**
* Resizes the canvas and changes the view size.
*
Expand All @@ -51,6 +55,7 @@ class TextRootWidget : public de::RootWidget

private:
TextCanvas *_canvas;
bool _drawRequest;
};

#endif // TEXTROOTWIDGET_H

0 comments on commit 7e3cfc0

Please sign in to comment.