From b1c01233f3f66adc22b78283d0e179e1e281ddca Mon Sep 17 00:00:00 2001 From: skyjake Date: Thu, 30 May 2013 12:01:11 +0300 Subject: [PATCH] Client: Interaction between console and log widgets When new log entries arrive, the console widget's height increases accordingly. Added a content Y offset to the log widget to allow syncing it with height increases. --- doomsday/client/client.pro | 8 ++-- .../client/include/ui/widgets/consolewidget.h | 12 +++++- .../client/include/ui/widgets/logwidget.h | 4 ++ doomsday/client/src/ui/clientwindow.cpp | 3 +- .../client/src/ui/widgets/consolewidget.cpp | 39 +++++++++++++++++-- .../client/src/ui/widgets/labelwidget.cpp | 4 +- doomsday/client/src/ui/widgets/logwidget.cpp | 26 +++++++++++-- .../client/src/ui/widgets/taskbarwidget.cpp | 34 +++------------- 8 files changed, 84 insertions(+), 46 deletions(-) diff --git a/doomsday/client/client.pro b/doomsday/client/client.pro index d51a2fe129..42ae05613c 100644 --- a/doomsday/client/client.pro +++ b/doomsday/client/client.pro @@ -360,6 +360,7 @@ DENG_HEADERS += \ include/ui/widgets/busywidget.h \ include/ui/widgets/buttonwidget.h \ include/ui/widgets/consolecommandwidget.h \ + include/ui/widgets/consolewidget.h \ include/ui/widgets/gltextcomposer.h \ include/ui/widgets/guirootwidget.h \ include/ui/widgets/guiwidget.h \ @@ -389,8 +390,7 @@ INCLUDEPATH += \ HEADERS += \ $$DENG_API_HEADERS \ - $$DENG_HEADERS \ - include/ui/widgets/consolewidget.h + $$DENG_HEADERS # Platform-specific sources. win32 { @@ -637,6 +637,7 @@ SOURCES += \ src/ui/widgets/busywidget.cpp \ src/ui/widgets/buttonwidget.cpp \ src/ui/widgets/consolecommandwidget.cpp \ + src/ui/widgets/consolewidget.cpp \ src/ui/widgets/gltextcomposer.cpp \ src/ui/widgets/guirootwidget.cpp \ src/ui/widgets/guiwidget.cpp \ @@ -657,8 +658,7 @@ SOURCES += \ src/updater/updaterdialog.cpp \ src/updater/updatersettings.cpp \ src/updater/updatersettingsdialog.cpp \ - src/uri.cpp \ - src/ui/widgets/consolewidget.cpp + src/uri.cpp !deng_nosdlmixer:!deng_nosdl { HEADERS += include/audio/sys_audiod_sdlmixer.h diff --git a/doomsday/client/include/ui/widgets/consolewidget.h b/doomsday/client/include/ui/widgets/consolewidget.h index 0fd5ebeec9..cf6dbb49c8 100644 --- a/doomsday/client/include/ui/widgets/consolewidget.h +++ b/doomsday/client/include/ui/widgets/consolewidget.h @@ -19,15 +19,22 @@ #ifndef DENG_CLIENT_CONSOLEWIDGET_H #define DENG_CLIENT_CONSOLEWIDGET_H +#include + #include "guiwidget.h" #include "consolecommandwidget.h" #include "logwidget.h" /** * Console command line and message history. + * + * ConsoleWidget expects to be bottom-left anchored. It resizes its height + * automatically. The user can drag the right edge to resize the widget. */ -class ConsoleWidget : public GuiWidget +class ConsoleWidget : public QObject, public GuiWidget { + Q_OBJECT + public: ConsoleWidget(); @@ -37,6 +44,9 @@ class ConsoleWidget : public GuiWidget // Events. bool handleEvent(de::Event const &event); +protected slots: + void logContentHeightIncreased(int delta); + protected: void glInit(); void glDeinit(); diff --git a/doomsday/client/include/ui/widgets/logwidget.h b/doomsday/client/include/ui/widgets/logwidget.h index af6e1aa41c..04b6d73644 100644 --- a/doomsday/client/include/ui/widgets/logwidget.h +++ b/doomsday/client/include/ui/widgets/logwidget.h @@ -21,6 +21,7 @@ #include #include +#include #include "guiwidget.h" @@ -69,6 +70,8 @@ class LogWidget : public QObject, public GuiWidget */ void scroll(int to); + void setContentYOffset(de::Animation const &anim); + // Events. void viewResized(); void update(); @@ -87,6 +90,7 @@ protected slots: signals: void scrollPositionChanged(int pos); void scrollMaxChanged(int maximum); + void contentHeightIncreased(int delta); protected: void glInit(); diff --git a/doomsday/client/src/ui/clientwindow.cpp b/doomsday/client/src/ui/clientwindow.cpp index a1770b4393..e23aafd659 100644 --- a/doomsday/client/src/ui/clientwindow.cpp +++ b/doomsday/client/src/ui/clientwindow.cpp @@ -89,8 +89,7 @@ DENG2_OBSERVES(Canvas, FocusChange) ConsoleWidget *console = new ConsoleWidget; console->rule() .setInput(Rule::Bottom, taskBar->rule().top()) - .setInput(Rule::Left, root.viewLeft()) - .setInput(Rule::Top, root.viewTop()); + .setInput(Rule::Left, root.viewLeft()); root.add(console); root.setFocus(&console->commandLine()); diff --git a/doomsday/client/src/ui/widgets/consolewidget.cpp b/doomsday/client/src/ui/widgets/consolewidget.cpp index cb0b2bd07b..2ae87bad8a 100644 --- a/doomsday/client/src/ui/widgets/consolewidget.cpp +++ b/doomsday/client/src/ui/widgets/consolewidget.cpp @@ -22,18 +22,28 @@ #include "ui/widgets/consolecommandwidget.h" #include "ui/widgets/logwidget.h" +#include +#include + using namespace de; DENG2_PIMPL(ConsoleWidget) { ConsoleCommandWidget *cmdLine; LogWidget *log; + ScalarRule *height; Instance(Public *i) : Base(i), cmdLine(0), log(0) { + height = new ScalarRule(0); + } + + ~Instance() + { + releaseRef(height); } void glInit() @@ -45,7 +55,7 @@ DENG2_PIMPL(ConsoleWidget) } }; -ConsoleWidget::ConsoleWidget() : GuiWidget("taskbar"), d(new Instance(this)) +ConsoleWidget::ConsoleWidget() : GuiWidget("Console"), d(new Instance(this)) { Rule const &gap = style().rules().rule("gap"); @@ -74,11 +84,15 @@ ConsoleWidget::ConsoleWidget() : GuiWidget("taskbar"), d(new Instance(this)) .setInput(Rule::Left, rule().left()) .setInput(Rule::Right, rule().right()) .setInput(Rule::Bottom, d->cmdLine->rule().top()) - .setInput(Rule::Top, rule().top()); + .setInput(Rule::Top, OperatorRule::maximum(rule().top(), Const(0))); add(d->log); + connect(d->log, SIGNAL(contentHeightIncreased(int)), this, SLOT(logContentHeightIncreased(int))); + // Width of the console is defined by the style. - rule().setInput(Rule::Width, style().rules().rule("console.width")); + rule() + .setInput(Rule::Width, style().rules().rule("console.width")) + .setInput(Rule::Height, d->cmdLine->rule().height() + *d->height); } ConsoleCommandWidget &ConsoleWidget::commandLine() @@ -102,7 +116,24 @@ void ConsoleWidget::glDeinit() d->glDeinit(); } -bool ConsoleWidget::handleEvent(const Event &event) +bool ConsoleWidget::handleEvent(Event const &event) { + if(event.type() == Event::KeyPress) + { + KeyEvent const &key = static_cast(event); + if(key.qtKey() == Qt::Key_F5) + { + d->height->set(0); + d->log->scrollToBottom(); + return true; + } + } return false; } + +void ConsoleWidget::logContentHeightIncreased(int delta) +{ + d->height->set(d->height->scalar().target() + delta, .25f); + // Sync the log content with the height animation. + d->log->setContentYOffset(Animation::range(Animation::EaseIn, delta, 0, .25f)); +} diff --git a/doomsday/client/src/ui/widgets/labelwidget.cpp b/doomsday/client/src/ui/widgets/labelwidget.cpp index 061101f9b9..135e0233c3 100644 --- a/doomsday/client/src/ui/widgets/labelwidget.cpp +++ b/doomsday/client/src/ui/widgets/labelwidget.cpp @@ -252,9 +252,8 @@ public Font::RichFormat::IStyle // Figure out how much room is left for the image. Rectanglef const rect = layout.image; - /* // Fit the image. - if(imageFit.testFlag(FitToWidth)) + if(!imageFit.testFlag(FitToWidth)) { layout.image.setWidth(image.width()); } @@ -262,7 +261,6 @@ public Font::RichFormat::IStyle { layout.image.setHeight(image.height()); } - */ // Should the original aspect ratio be preserved? if(imageFit & OriginalAspectRatio) diff --git a/doomsday/client/src/ui/widgets/logwidget.cpp b/doomsday/client/src/ui/widgets/logwidget.cpp index f192df75a0..200a718609 100644 --- a/doomsday/client/src/ui/widgets/logwidget.cpp +++ b/doomsday/client/src/ui/widgets/logwidget.cpp @@ -307,6 +307,7 @@ DENG2_PIMPL(LogWidget), public Font::RichFormat::IStyle int lastMaxScroll; Rangei visibleRange; Animation scrollOpacity; + Animation contentOffset; // Style. Font const *font; @@ -542,6 +543,8 @@ DENG2_PIMPL(LogWidget), public Font::RichFormat::IStyle void fetchNewCachedEntries() { + int oldHeight = totalHeight; + while(CacheEntry *cached = sink.nextCachedEntry()) { // Find a suitable place according to the original index in the sink; @@ -564,6 +567,11 @@ DENG2_PIMPL(LogWidget), public Font::RichFormat::IStyle emit self.scrollPositionChanged(visibleOffset.target()); } } + + if(totalHeight > oldHeight) + { + emit self.contentHeightIncreased(totalHeight - oldHeight); + } } void rewrapCache() @@ -698,7 +706,7 @@ DENG2_PIMPL(LogWidget), public Font::RichFormat::IStyle VertexBuf::Builder verts; // Copy all visible entries to the buffer. - for(int idx = cache.size() - 1; yBottom > 0 && idx >= 0; --idx) + for(int idx = cache.size() - 1; yBottom > -contentOffset && idx >= 0; --idx) { CacheEntry *entry = cache[idx]; yBottom -= entry->height(); @@ -759,13 +767,13 @@ DENG2_PIMPL(LogWidget), public Font::RichFormat::IStyle // First draw the shadow of the text. uMvpMatrix = projMatrix * - Matrix4f::translate(Vector2f(pos.topLeft + Vector2i(margin, 0))); + Matrix4f::translate(Vector2f(pos.topLeft + Vector2i(margin, contentOffset))); uShadowColor = Vector4f(0, 0, 0, 1); contents.draw(); // Draw the text itself. uMvpMatrix = projMatrix * - Matrix4f::translate(Vector2f(pos.topLeft + Vector2i(margin, -2))); + Matrix4f::translate(Vector2f(pos.topLeft + Vector2i(margin, contentOffset - 2))); uShadowColor = Vector4f(1, 1, 1, 1); contents.draw(); @@ -820,6 +828,18 @@ void LogWidget::scroll(int to) d->visibleOffset = de::max(0, to); } +void LogWidget::setContentYOffset(Animation const &anim) +{ + if(d->visibleOffset > 0) + { + d->contentOffset = 0; + } + else + { + d->contentOffset = anim; + } +} + void LogWidget::viewResized() { d->updateProjection(); diff --git a/doomsday/client/src/ui/widgets/taskbarwidget.cpp b/doomsday/client/src/ui/widgets/taskbarwidget.cpp index 0d7bdf7f54..5d3743e1ee 100644 --- a/doomsday/client/src/ui/widgets/taskbarwidget.cpp +++ b/doomsday/client/src/ui/widgets/taskbarwidget.cpp @@ -79,44 +79,20 @@ DENG2_PIMPL(TaskBarWidget) } }; -TaskBarWidget::TaskBarWidget() : GuiWidget("taskbar"), d(new Instance(this)) +TaskBarWidget::TaskBarWidget() : GuiWidget("TaskBar"), d(new Instance(this)) { + Rule const &gap = style().rules().rule("gap"); + LabelWidget *logo = new LabelWidget; logo->setImage(style().images().image("logo.px128")); - //logo->setSizePolicy(LabelWidget::Filled, LabelWidget::Filled); logo->rule() .setInput(Rule::Height, rule().height()) .setInput(Rule::Width, rule().height()) - .setInput(Rule::Right, rule().right()) + .setInput(Rule::Right, rule().right() - gap) .setInput(Rule::Bottom, rule().bottom()); add(logo); - Rule const &gap = style().rules().rule("gap"); - - /* - ButtonWidget *consoleButton = new ButtonWidget; - consoleButton->setText(DENG2_STR_ESCAPE("b") ">"); - consoleButton->setWidthPolicy(ButtonWidget::Expand); - consoleButton->rule() - .setInput(Rule::Left, rule().left() + gap) - .setInput(Rule::Top, rule().top() + gap) - .setInput(Rule::Width, style().fonts().font("default").height() + gap * 2) - .setInput(Rule::Height, consoleButton->rule().width()); - add(consoleButton); - - // The task bar has a number of child widgets. - d->cmdLine = new ConsoleCommandWidget("commandline"); - d->cmdLine->rule() - .setInput(Rule::Left, consoleButton->rule().right() + gap) - .setInput(Rule::Bottom, rule().bottom() - gap) - .setInput(Rule::Right, rule().right() - gap); - add(d->cmdLine); - - rule().setInput(Rule::Height, d->cmdLine->rule().height() + gap * 2); - - // Height of the taskbar is defined by the style. - //rule().setInput(Rule::Height, style().rules().rule("taskbar.height"));*/ - + // Taskbar height depends on the font size. rule().setInput(Rule::Height, style().fonts().font("default").height() + gap * 2); }