From a75447092564ac94f14376776db95664ad6a3806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Wed, 29 Oct 2014 20:19:31 +0200 Subject: [PATCH] UI|Client: Reorganized the console popup menu; showing/hiding annotations 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. --- .../client/include/ui/widgets/consolewidget.h | 4 +- .../defaultstyle.pack/graphics/log.png | Bin 0 -> 2696 bytes .../defaultstyle.pack/images.dei | 7 +- .../defaultstyle.pack/rules.dei | 1 + .../client/src/ui/widgets/consolewidget.cpp | 200 +++++++++++------- .../client/src/ui/widgets/taskbarwidget.cpp | 7 +- 6 files changed, 136 insertions(+), 83 deletions(-) create mode 100644 doomsday/client/net.dengine.client.pack/defaultstyle.pack/graphics/log.png diff --git a/doomsday/client/include/ui/widgets/consolewidget.h b/doomsday/client/include/ui/widgets/consolewidget.h index 9b45d42911..6c77fe4384 100644 --- a/doomsday/client/include/ui/widgets/consolewidget.h +++ b/doomsday/client/include/ui/widgets/consolewidget.h @@ -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(); @@ -81,7 +82,6 @@ public slots: void commandLineFocusGained(); void commandLineFocusLost(); void focusOnCommandLine(); - void openMenu(); void closeMenu(); void commandWasEntered(de::String const &); void copyLogPathToClipboard(); diff --git a/doomsday/client/net.dengine.client.pack/defaultstyle.pack/graphics/log.png b/doomsday/client/net.dengine.client.pack/defaultstyle.pack/graphics/log.png new file mode 100644 index 0000000000000000000000000000000000000000..1afa8c547f567fc4bf292b3c4a6c3b2c3fd9c6a6 GIT binary patch literal 2696 zcmZ`*4OmiV8$Ot&k@n%HOH1X1TbU*ZrU9a$KuJ?nw5k1Ah*%_Y1P+OsNlq>6%B)Py z&slvn%bZ%dVsmBGw$jSBPc3znnpw8|NzHxvn>(N@KCe30bvW<)Joo)P&;7hV7g<5v zwdUx>XaE4rIesi2@@42=(|O46d6BdY`515W3Ge}ci-#6W@aH0PP~gW40Dz=r0H8_- zfHB0RdI10mR{(gq6#%FO0I(>&s5+R2IOfOuMaTib{-*9lNq$#&Bk^RS&~P|Bz@I9B z;_&=vC`yP|#>FFO0H7(U$S_U_^Fd{tSR$t?y>NO26&dTy1RSV`z_DJq@PHtY3CV<@ zJAM`373YlxL69bkj-m2cYi8)k%nP?2hU2LOLPA0UKEVwS$+i)Q6bgmlN+OU*E(pR! zo+yF&N*9UTVLHe^aacmRKqiWZMUVv4#pOpq3fK#W(-%MqHl`wYdiamt zAeL?+sX-#8P#n$@AK zKlh0@dW?Q`GXTt0aacZ~N>ty!y~MU`%iGtwJ+XtW*)AJzpJ8O$qd^`p-hNeFYYVizX!3t###3;FeSBlt#(|jg3<~tr*xPl@dMO-4zR;zA<+C{+vaJ3`(_*aFgCBP}S9O_WFAk*2g@% za=e76v9bCi*sf8|Xo_V8X5`ed=l868v1D9mi*m=XWsDVkM#=L7V-tsxE)r1-7AzQl z{rWY5!AQmDyT#DX3rdnkc=p!TIm_v%qx@CjSS)s`b$hO*v-Y{ll1Y-6_sqX=+~_{? z1WPjJ#B914QYRW6l!CEe=eTe*0 zMeK3!-Rpunb)dHZ)pmc=&%3Py_te+dJIVW()2fOS)J&_(Cob1kj^H+SJY;8JZauu% zsWs|8JS2QRkvwMl;!dH~BMA;UXdecG!^hR(D{EL4M_irGbU2#Hs_lYt*iel&gnJU z2<^@s-Qll!^k|bPHnyj$zrWv(zvk!;ti64Wy*f@{^vj;CtSoxx&NJ)(CzdnHCJv@N zs#va3qH_Q{Z+ddNLi2>YdtqeNW*b}E3F5+y=B+treK@b$aDk!K{8o$q#62k6mdquk ztW{&XFOJxEHdlLQ_gR`gK9FF(q{;kRi>vkWpa*#>GX1byapoSsl}iqqU~OzlF<-S; zVfH^eWxO%pCFRf?l5JM*oK8FUh}aSeC{C%oQgB4E+MlFw;= z&7#Ld#oW=AZDB2_-G#pi6kaE|>y~sKczD)#muJtFvLMie#(kQoW>#{P-G5Ha`}&LG z+9vmE?uP8a;J2pEV> z&T^kCMbv9W(i;nctWYvv%i1;F%WI{SSDGRBg5s}%zap7zm8x7()H#q=ln_3Ork#Zc z(kin75yQvBlM7Zl#QOb|uK=#@DFU>wB3%_B8f{%}4xLR)ugz83AO2R}(wSBfYI)=H o6GJDMU19n3z$x}*>innsetText(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")); @@ -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); @@ -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. @@ -259,30 +279,48 @@ 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" */); @@ -290,9 +328,9 @@ ConsoleWidget::ConsoleWidget() : GuiWidget("console"), d(new Instance(this)) 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); @@ -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) + << 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); + + 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")); @@ -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() @@ -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); } @@ -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(); @@ -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 &) diff --git a/doomsday/client/src/ui/widgets/taskbarwidget.cpp b/doomsday/client/src/ui/widgets/taskbarwidget.cpp index 43522de3b5..e68d17de2e 100644 --- a/doomsday/client/src/ui/widgets/taskbarwidget.cpp +++ b/doomsday/client/src/ui/widgets/taskbarwidget.cpp @@ -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()); @@ -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")) @@ -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().rule().left());