Skip to content

Commit

Permalink
UI|Client: Reorganized the console popup menu; showing/hiding annotat…
Browse files Browse the repository at this point in the history
…ions

The console popup menu was split into a log history menu and one for
controlling the command prompt behavior. A new icon was added for the
log.

There's a new shortcut for toggling Script mode: right-click on the
prompt [Cmd/DS] button.
  • Loading branch information
skyjake committed Oct 29, 2014
1 parent 979ff5e commit a754470
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 83 deletions.
4 changes: 2 additions & 2 deletions doomsday/client/include/ui/widgets/consolewidget.h
Expand Up @@ -42,7 +42,8 @@ class ConsoleWidget : public de::GuiWidget, public de::IPersistent
public:
ConsoleWidget();

de::ButtonWidget &button();
GuiWidget &buttons();

de::CommandWidget &commandLine();
de::LogWidget &log();

Expand Down Expand Up @@ -81,7 +82,6 @@ public slots:
void commandLineFocusGained();
void commandLineFocusLost();
void focusOnCommandLine();
void openMenu();
void closeMenu();
void commandWasEntered(de::String const &);
void copyLogPathToClipboard();
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -27,10 +27,14 @@ group logo {
}
}

image alert { path = "graphics/alert.png" }
# Generic:
image fold { path = "graphics/fold.png" }
image gauge { path = "graphics/gauge.png" }
image gear { path = "graphics/gear.png" }
image alert { path = "graphics/alert.png" }

# Subsystems:
image log { path = "graphics/log.png" }
image display { path = "graphics/display.png" }
image network { path = "graphics/network.png" }
image renderer { path = "graphics/renderer.png" }
Expand All @@ -39,6 +43,7 @@ image input { path = "graphics/input.png" }
image audio { path = "graphics/audio.png" }
image updater { path = "graphics/updater.png" }

# Widgets:
image toggle.onoff {
path $= gui.dpiScaledImagePath("graphics/toggle-onoff.png")
}
Expand Down
Expand Up @@ -54,6 +54,7 @@ group sidebar {
}

group console {
rule prompt.width { constant $= UNIT * 13 }
rule width { constant $= UNIT * 125 }

group commandline {
Expand Down
200 changes: 123 additions & 77 deletions doomsday/client/src/ui/widgets/consolewidget.cpp
Expand Up @@ -48,40 +48,33 @@ static TimeDelta const LOG_OPEN_CLOSE_SPAN = 0.2;
DENG_GUI_PIMPL(ConsoleWidget),
DENG2_OBSERVES(Variable, Change)
{
ButtonWidget *button;
ConsoleCommandWidget *cmdLine;
ScriptCommandWidget *scriptCmd;
PopupMenuWidget *menu;
LogWidget *log;
GuiWidget *buttons = nullptr;
ButtonWidget *button = nullptr;
ButtonWidget *promptButton = nullptr;
LabelWidget *promptText = nullptr;
PopupMenuWidget *logMenu = nullptr;
PopupMenuWidget *promptMenu = nullptr;
ConsoleCommandWidget *cmdLine = nullptr;
ScriptCommandWidget *scriptCmd = nullptr;
LogWidget *log = nullptr;
ScalarRule *horizShift;
ScalarRule *height;
ScalarRule *width;
StyledLogSinkFormatter formatter;
bool opened = true;
bool scriptMode = false;
int grabWidth = 0;

enum GrabEdge {
NotGrabbed = 0,
RightEdge,
TopEdge
};

bool opened;
bool scriptMode;
int grabWidth;
GrabEdge grabHover;
GrabEdge grabbed;

Instance(Public *i)
: Base(i),
button(0),
cmdLine(0),
scriptCmd(0),
menu(0),
log(0),
opened(true),
scriptMode(false),
grabWidth(0),
grabHover(NotGrabbed),
grabbed(NotGrabbed)
GrabEdge grabHover = NotGrabbed;
GrabEdge grabbed = NotGrabbed;

Instance(Public *i) : Base(i)
{
horizShift = new ScalarRule(0);
width = new ScalarRule(style().rules().rule("console.width").valuei());
Expand Down Expand Up @@ -208,7 +201,9 @@ DENG2_OBSERVES(Variable, Change)
}

// Update the prompt to reflect the mode.
button->setText(yes? _E(b) "$" : _E(b) ">");
promptText->set(Background(Background::Rounded,
style().colors().colorf(yes? "altaccent" : "text"), 6));
promptText->setText(yes? _E(l)_E(F) "DS" : _E(l) "Cmd");

// Bottom of the console must follow the active command line height.
self.rule().setInput(Rule::Bottom, next->rule().top() - style().rules().rule("unit"));
Expand All @@ -219,7 +214,7 @@ DENG2_OBSERVES(Variable, Change)
}

scriptCmd->setAttribute(AnimateOpacityWhenEnabledOrDisabled, UnsetFlags);
cmdLine->setAttribute(AnimateOpacityWhenEnabledOrDisabled, UnsetFlags);
cmdLine ->setAttribute(AnimateOpacityWhenEnabledOrDisabled, UnsetFlags);

scriptCmd->show(yes);
scriptCmd->enable(yes);
Expand All @@ -236,16 +231,41 @@ DENG2_OBSERVES(Variable, Change)

emit self.commandModeChanged();
}

struct RightClick : public GuiWidget::IEventHandler
{
Instance *d;

RightClick(Instance *inst) : d(inst) {}

bool handleEvent(GuiWidget &widget, Event const &event)
{
switch(widget.handleMouseClick(event, MouseEvent::Right))
{
case MouseClickFinished:
// Toggle the script mode.
App::config().set("console.script", !d->scriptMode);
return true;

case MouseClickUnrelated:
break; // not consumed

default:
return true;
}
return false;
}
};
};

static PopupWidget *consoleShortcutPopup()
{
PopupWidget *pop = new PopupWidget;
auto *pop = new PopupWidget;
// The 'padding' widget will provide empty margins around the content.
// Popups normally do not provide any margins.
GuiWidget *padding = new GuiWidget;
auto *padding = new GuiWidget;
padding->margins().set("dialog.gap");
InputBindingWidget *bind = InputBindingWidget::newTaskBarShortcut();
auto *bind = InputBindingWidget::newTaskBarShortcut();
bind->setSizePolicy(ui::Expand, ui::Expand);
padding->add(bind);
// Place the binding inside the padding.
Expand All @@ -259,40 +279,58 @@ static PopupWidget *consoleShortcutPopup()
return pop;
}

static PopupWidget *advancedFeaturesPopup()
{
auto *menu = new PopupMenuWidget;
menu->items()
<< new ui::ActionItem(QObject::tr("Copy Log Path to Clipboard"),
new SignalAction(&ClientWindow::main().console(),
SLOT(copyLogPathToClipboard())))
<< new ui::Item(ui::Item::Annotation,
QObject::tr("The location of the log output file is copied to "
"the OS clipboard."))
<< new ui::Item(ui::Item::Separator)
<< new ui::VariableToggleItem(QObject::tr("Doomsday Script"),
App::config("console.script"))
<< new ui::Item(ui::Item::Annotation,
QObject::tr("The command prompt becomes an interactive script "
"process with access to all the runtime modules."));
return menu;
}

ConsoleWidget::ConsoleWidget() : GuiWidget("console"), d(new Instance(this))
{
d->buttons = new GuiWidget;
add(d->buttons);

// Button for opening the Log History menu.
d->button = new ButtonWidget;
d->button->setAction(new SignalAction(this, SLOT(openMenu())));
add(d->button);
d->button->setSizePolicy(ui::Expand, ui::Expand);
d->button->setImage(style().images().image("log"));
d->button->setOverrideImageSize(style().fonts().font("default").height().valuei());
d->buttons->add(d->button);

d->button->rule()
.setInput(Rule::Top, d->buttons->rule().top())
.setInput(Rule::Left, d->buttons->rule().left())
.setInput(Rule::Height, d->buttons->rule().height())
.setInput(Rule::Width, d->button->rule().height()); // square

// Button for opening the console prompt menu.
d->promptButton = new ButtonWidget;
d->promptButton->addEventHandler(new Instance::RightClick(d));
d->promptButton->add(d->promptText = new LabelWidget);
d->promptText->setFont("small");
d->promptText->margins().set("");
auto const &unit = style().rules().rule("unit");
auto const &small = style().fonts().font("small").height();
d->promptText->rule()
.setMidAnchorY(d->promptButton->rule().midY())
.setInput(Rule::Height, small + style().rules().rule("dialog.gap")*2)
.setInput(Rule::Left, d->promptButton->rule().left() + unit)
.setInput(Rule::Right, d->promptButton->rule().right() - unit);

d->promptButton->rule()
.setInput(Rule::Width, style().rules().rule("console.prompt.width"))
.setInput(Rule::Height, d->buttons->rule().height())
.setInput(Rule::Left, d->button->rule().right())
.setInput(Rule::Top, d->buttons->rule().top());
d->buttons->add(d->promptButton);

// Width of the button area is known; the task bar will define the rest.
d->buttons->rule().setInput(Rule::Width, d->button->rule().width() +
d->promptButton->rule().width());

d->cmdLine = new ConsoleCommandWidget("commandline");
d->cmdLine->setEmptyContentHint(tr("Enter commands here") /* " _E(r)_E(l)_E(t) "SHIFT-ESC" */);
add(d->cmdLine);

d->scriptCmd = new ScriptCommandWidget("script");
d->scriptCmd->setEmptyContentHint(tr("Enter scripts here"));
add(d->scriptCmd);
add(d->scriptCmd);\

d->button->setOpacity(.75f);
d->buttons->setOpacity(.75f);
d->cmdLine->setOpacity(.75f);
d->scriptCmd->setOpacity(.75f);

Expand All @@ -316,27 +354,39 @@ ConsoleWidget::ConsoleWidget() : GuiWidget("console"), d(new Instance(this))

closeLog();

// Menu for console related functions.
d->menu = new PopupMenuWidget;
d->menu->setAnchor(d->button->rule().left() + d->button->rule().width() / 2,
d->button->rule().top());

d->menu->items()
<< new ui::Item(ui::Item::Separator, tr("Log History"))
// Menu for log history related features.
d->logMenu = new PopupMenuWidget;
d->logMenu->setAnchor(d->button->rule().midX(), d->button->rule().top());
d->logMenu->items()
<< new ui::ActionItem(tr("Clear Log"), new CommandAction("clear"))
<< new ui::ActionItem(tr("Show Full Log"), new SignalAction(this, SLOT(showFullLog())))
<< new ui::ActionItem(tr("Scroll to Bottom"), new SignalAction(d->log, SLOT(scrollToBottom())))
<< new ui::VariableToggleItem(tr("Go to Bottom on Enter"), App::config("console.snap"))
<< new ui::VariableToggleItem(tr("Show Metadata"), App::config("log.showMetadata"))
<< new ui::Item(ui::Item::Annotation, tr("Time and subsystem of each entry is printed."))
<< new ui::ActionItem(tr("Go to Latest"), new SignalAction(d->log, SLOT(scrollToBottom())))
<< new ui::ActionItem(tr("Copy Path to Clipboard"),
new SignalAction(this, SLOT(copyLogPathToClipboard())))
<< new ui::Item(ui::Item::Annotation,
tr("Copies the location of the log output file to the OS clipboard."))
<< new ui::Item(ui::Item::Separator)
<< new ui::Item(ui::Item::Separator, tr("Behavior"))
<< new ui::SubwidgetItem(tr("Log Filter & Alerts..."), ui::Right, makePopup<LogSettingsDialog>)
<< new ui::VariableToggleItem(tr("Snap to Latest Entry"), App::config("console.snap"))
<< new ui::Item(ui::Item::Annotation, tr("Running a command or script causes the log to scroll down to the latest entry."))
<< new ui::VariableToggleItem(tr("Entry Metadata"), App::config("log.showMetadata"))
<< new ui::Item(ui::Item::Annotation, tr("Time and subsystem of each new entry is printed."))
<< new ui::SubwidgetItem(tr("Log Filter & Alerts..."), ui::Right, makePopup<LogSettingsDialog>);

add(d->logMenu);
d->button->setAction(new SignalAction(d->logMenu, SLOT(open())));

// Menu for console prompt behavior.
d->promptMenu = new PopupMenuWidget;
d->promptMenu->setAnchor(d->promptButton->rule().midX(), d->promptButton->rule().top());
d->promptMenu->items()
<< new ui::SubwidgetItem(tr("Shortcut Key..."), ui::Right, consoleShortcutPopup)
<< new ui::Item(ui::Item::Separator)
<< new ui::SubwidgetItem(tr("Advanced..."), ui::Right, advancedFeaturesPopup);

add(d->menu);
<< new ui::VariableToggleItem(tr("Doomsday Script"), App::config("console.script"))
<< new ui::Item(ui::Item::Annotation,
tr("The command prompt becomes an interactive script "
"process with access to all the runtime DS modules."));
add(d->promptMenu);
d->promptButton->setAction(new SignalAction(d->promptMenu, SLOT(open())));

d->setScriptMode(App::config().getb("console.script"));

Expand All @@ -352,9 +402,9 @@ ConsoleWidget::ConsoleWidget() : GuiWidget("console"), d(new Instance(this))
connect(d->scriptCmd, SIGNAL(commandEntered(de::String)), this, SLOT(commandWasEntered(de::String)));
}

ButtonWidget &ConsoleWidget::button()
GuiWidget &ConsoleWidget::buttons()
{
return *d->button;
return *d->buttons;
}

CommandWidget &ConsoleWidget::commandLine()
Expand Down Expand Up @@ -530,7 +580,7 @@ void ConsoleWidget::setFullyOpaque()
d->scriptCmd->setAttribute(AnimateOpacityWhenEnabledOrDisabled);
d->cmdLine->setAttribute(AnimateOpacityWhenEnabledOrDisabled);

d->button->setOpacity(1, .25f);
d->buttons->setOpacity(1, .25f);
d->cmdLine->setOpacity(1, .25f);
d->scriptCmd->setOpacity(1, .25f);
}
Expand All @@ -548,7 +598,7 @@ void ConsoleWidget::commandLineFocusLost()
d->scriptCmd->setAttribute(AnimateOpacityWhenEnabledOrDisabled);
d->cmdLine->setAttribute(AnimateOpacityWhenEnabledOrDisabled);

d->button->setOpacity(.75f, .25f);
d->buttons->setOpacity(.75f, .25f);
d->cmdLine->setOpacity(.75f, .25f);
d->scriptCmd->setOpacity(.75f, .25f);
closeLog();
Expand All @@ -559,14 +609,10 @@ void ConsoleWidget::focusOnCommandLine()
root().setFocus(&commandLine());
}

void ConsoleWidget::openMenu()
{
d->menu->open();
}

void ConsoleWidget::closeMenu()
{
d->menu->close();
d->logMenu->close();
d->promptMenu->close();
}

void ConsoleWidget::commandWasEntered(String const &)
Expand Down
7 changes: 4 additions & 3 deletions doomsday/client/src/ui/widgets/taskbarwidget.cpp
Expand Up @@ -337,9 +337,8 @@ TaskBarWidget::TaskBarWidget() : GuiWidget("taskbar"), d(new Instance(this))
//d->console->log().set(bg);

// Position the console button and command line in the task bar.
d->console->button().rule()
d->console->buttons().rule()
.setInput(Rule::Left, rule().left())
.setInput(Rule::Width, d->console->button().rule().height())
.setInput(Rule::Bottom, rule().bottom())
.setInput(Rule::Height, rule().height());

Expand Down Expand Up @@ -429,6 +428,8 @@ TaskBarWidget::TaskBarWidget() : GuiWidget("taskbar"), d(new Instance(this))
<< new ui::Item(ui::Item::Separator)
<< new ui::Item(ui::Item::Separator, tr("Help"))
<< new ui::ActionItem(tr("Show Tutorial"), new SignalAction(this, SLOT(showTutorial())))
<< new ui::VariableToggleItem(tr("Menu Annotations"), App::config("ui.showAnnotations"))
<< new ui::Item(ui::Item::Annotation, tr("Hides these brief descriptions about menu functions."))
<< new ui::Item(ui::Item::Separator)
<< new ui::Item(ui::Item::Separator, tr("Application"))
<< new ui::ActionItem(tr("Check for Updates..."), new CommandAction("updateandnotify"))
Expand Down Expand Up @@ -777,7 +778,7 @@ void TaskBarWidget::updateCommandLineLayout()

// The command line extends the rest of the way.
RuleRectangle &cmdRule = d->console->commandLine().rule();
cmdRule.setInput(Rule::Left, d->console->button().rule().right())
cmdRule.setInput(Rule::Left, d->console->buttons().rule().right())
.setInput(Rule::Bottom, rule().bottom())
.setInput(Rule::Right, layout.widgets().last()->as<GuiWidget>().rule().left());

Expand Down

0 comments on commit a754470

Please sign in to comment.