Skip to content

Commit

Permalink
libshell|Shell: Widget behavior improvements
Browse files Browse the repository at this point in the history
Focus navigation with unhandled Up and Down keys.

Enter is no longer a shortcut in LocalServerDialog. Selection position
is restored when updating the menu with found servers.
  • Loading branch information
skyjake committed Feb 5, 2013
1 parent a6c0a76 commit 2b6d103
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 42 deletions.
4 changes: 2 additions & 2 deletions doomsday/libshell/include/de/shell/lineeditwidget.h
Expand Up @@ -60,9 +60,9 @@ class LIBSHELL_PUBLIC LineEditWidget : public TextWidget

/**
* Enables or disables the signal emitted when the edit widget receives an
* Enter key.
* Enter key. By default, a signal is emitted.
*
* @param enterHandled @c true to enable signal, @c false to disable.
* @param enterSignal @c true to enable signal, @c false to disable.
*/
void setSignalOnEnter(int enterSignal);

Expand Down
6 changes: 6 additions & 0 deletions doomsday/libshell/include/de/shell/menuwidget.h
Expand Up @@ -87,8 +87,14 @@ class LIBSHELL_PUBLIC MenuWidget : public TextWidget

Action &itemAction(int pos) const;

int findLabel(String const &label) const;

bool hasLabel(String const &label) const;

void setCursor(int pos);

void setCursorByLabel(String const &label);

int cursor() const;

/**
Expand Down
4 changes: 2 additions & 2 deletions doomsday/libshell/src/choicewidget.cpp
Expand Up @@ -149,9 +149,9 @@ bool ChoiceWidget::handleEvent(Event const *ev)
{
KeyEvent const *event = static_cast<KeyEvent const *>(ev);
if(!event->text().isEmpty() ||
event->key() == Qt::Key_Enter ||
event->key() == Qt::Key_Enter /*||
event->key() == Qt::Key_Up ||
event->key() == Qt::Key_Down)
event->key() == Qt::Key_Down*/)
{
DENG2_ASSERT(!isOpen());
if(event->text().isEmpty())
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libshell/src/lineeditwidget.cpp
Expand Up @@ -39,7 +39,7 @@ struct LineEditWidget::Instance

Instance(LineEditWidget &cli)
: self(cli),
signalOnEnter(false),
signalOnEnter(true),
cursor(0)
{
// Initial height of the command line (1 row).
Expand Down
76 changes: 55 additions & 21 deletions doomsday/libshell/src/menuwidget.cpp
Expand Up @@ -200,12 +200,41 @@ Action &MenuWidget::itemAction(int pos) const
return *d->items[pos].action;
}

int MenuWidget::findLabel(String const &label) const
{
for(int i = 0; i < d->items.size(); ++i)
{
if(!d->items[i].action->label().compareWithoutCase(label))
return i;
}
return -1;
}

bool MenuWidget::hasLabel(String const &label) const
{
return findLabel(label) >= 0;
}

void MenuWidget::setCursor(int pos)
{
d->cursor = pos;
d->cursor = de::min(pos, itemCount() - 1);
redraw();
}

void MenuWidget::setCursorByLabel(String const &label)
{
int idx = findLabel(label);
if(idx >= 0)
{
setCursor(idx);
}
else
{
// Try to reselect the previous item by index.
setCursor(d->cursor);
}
}

int MenuWidget::cursor() const
{
return d->cursor;
Expand Down Expand Up @@ -329,22 +358,9 @@ bool MenuWidget::handleEvent(Event const *event)

if(event->type() != Event::KeyPress) return false;

// Check registered actions (shortcuts).
if(TextWidget::handleEvent(event))
{
close();
return true;
}

KeyEvent const *ev = static_cast<KeyEvent const *>(event);

if(ev->text() == " ")
{
itemAction(d->cursor).trigger();
close();
return true;
}

// Check menu-related control keys.
if(ev->text().isEmpty())
{
switch(ev->key())
Expand Down Expand Up @@ -393,15 +409,33 @@ bool MenuWidget::handleEvent(Event const *event)
return true;

default:
if(d->closable)
{
// Any other control key closes the menu.
close();
return true;
}
break;
}
}

if(ev->text() == " ")
{
itemAction(d->cursor).trigger();
close();
return true;
}

// Check registered actions (shortcuts), focus navigation.
if(TextWidget::handleEvent(event))
{
close();
return true;
}

if(ev->text().isEmpty())
{
if(d->closable)
{
// Any other control key closes the menu.
close();
return true;
}
}
else
{
// Look for an item that begins with the letter.
Expand Down
40 changes: 26 additions & 14 deletions doomsday/libshell/src/textwidget.cpp
Expand Up @@ -38,6 +38,26 @@ struct TextWidget::Instance
delete rule;
foreach(Action *act, actions) delete act;
}

/**
* Navigates focus to another widget, assuming this widget currently has
* focus. Used in focus cycle navigation.
*
* @param name Name of the widget to change focus to.
*
* @return Focus changed successfully.
*/
bool navigateFocus(TextRootWidget &root, String const &name)
{
Widget *w = root.find(name);
if(w)
{
root.setFocus(w);
root.requestDraw();
return true;
}
return false;
}
};

TextWidget::TextWidget(String const &name) : Widget(name), d(new Instance)
Expand Down Expand Up @@ -129,25 +149,17 @@ bool TextWidget::handleEvent(Event const *event)
}

// Focus navigation.
if(keyEvent->key() == Qt::Key_Tab && hasFocus() && !focusNext().isEmpty())
if((keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Down) &&
hasFocus() && !focusNext().isEmpty())
{
Widget *next = root().find(focusNext());
if(next)
{
root().setFocus(next);
root().requestDraw();
if(d->navigateFocus(root(), focusNext()))
return true;
}
}
if(keyEvent->key() == Qt::Key_Backtab && hasFocus() && !focusPrev().isEmpty())
if((keyEvent->key() == Qt::Key_Backtab || keyEvent->key() == Qt::Key_Up) &&
hasFocus() && !focusPrev().isEmpty())
{
Widget *prev = root().find(focusPrev());
if(prev)
{
root().setFocus(prev);
root().requestDraw();
if(d->navigateFocus(root(), focusPrev()))
return true;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions doomsday/tools/shell/shell-text/src/localserverdialog.cpp
Expand Up @@ -96,14 +96,14 @@ LocalServerDialog::LocalServerDialog() : d(new Instance)
.setInput(Rule::Top, d->choice->rule().bottom() + 1);

lineEdit().rule()
.setInput(Rule::Top, d->port->rule().bottom() + 1);
.setInput(Rule::Top, d->port->rule().bottom());

rule().setInput(Rule::Height,
label().rule() .height() +
d->choice->rule().height() +
d->port->rule() .height() +
lineEdit().rule().height() +
menu().rule() .height() + 4);
menu().rule() .height() + 3);

setDescription(tr("Specify the settings for starting a new local server."));

Expand Down
Expand Up @@ -30,6 +30,7 @@ OpenConnectionDialog::OpenConnectionDialog(String const &name) : shell::InputDia
"\"10.0.1.1:13209\"."));

setPrompt(tr("Address: "));
lineEdit().setSignalOnEnter(false); // let menu handle it
lineEdit().setText(PersistentData::get("OpenConnection.address"));

setAcceptLabel(tr("Connect to server"));
Expand Down
5 changes: 5 additions & 0 deletions doomsday/tools/shell/shell-text/src/shellapp.cpp
Expand Up @@ -221,6 +221,8 @@ void ShellApp::askToStartLocalServer()

void ShellApp::updateMenuWithFoundServers()
{
String oldSel = d->menu->itemAction(d->menu->cursor()).label();

// Remove old servers.
for(int i = 2; i < d->menu->itemCount() - 3; ++i)
{
Expand All @@ -241,6 +243,9 @@ void ShellApp::updateMenuWithFoundServers()

d->menu->insertItem(pos++, new Action(label, this, SLOT(connectToFoundServer())));
}

// Update cursor position after changing menu items.
d->menu->setCursorByLabel(oldSel);
}

void ShellApp::connectToFoundServer()
Expand Down

0 comments on commit 2b6d103

Please sign in to comment.