From a8d7e1170ce1d45b98ee1e2c62fa2520562e75a0 Mon Sep 17 00:00:00 2001 From: skyjake Date: Mon, 5 Aug 2013 13:53:41 +0300 Subject: [PATCH] libshell|AbstractLineEditor: Adjusted behavior of autocompletion The first press of Tab only sends the autocompletion notification if there is no unambiguous completion available. Further presses send the notification and then on subsequent presses start cycling through the possible completions. The objective here is to avoid showing the autocompletion popup unnecessarily/too early. --- .../include/ui/widgets/consolecommandwidget.h | 2 +- .../src/ui/widgets/consolecommandwidget.cpp | 2 +- .../include/de/shell/abstractlineeditor.h | 2 +- doomsday/libshell/src/abstractlineeditor.cpp | 66 +++++++++++++------ 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/doomsday/client/include/ui/widgets/consolecommandwidget.h b/doomsday/client/include/ui/widgets/consolecommandwidget.h index 6dbc97bd30..ca2bc8a088 100644 --- a/doomsday/client/include/ui/widgets/consolecommandwidget.h +++ b/doomsday/client/include/ui/widgets/consolecommandwidget.h @@ -43,7 +43,7 @@ class ConsoleCommandWidget : public LineEditWidget bool handleEvent(de::Event const &event); protected: - void autoCompletionBegan(); + void autoCompletionBegan(de::String const &prefix); void autoCompletionEnded(bool accepted); signals: diff --git a/doomsday/client/src/ui/widgets/consolecommandwidget.cpp b/doomsday/client/src/ui/widgets/consolecommandwidget.cpp index bfd2f9692f..06bd88e577 100644 --- a/doomsday/client/src/ui/widgets/consolecommandwidget.cpp +++ b/doomsday/client/src/ui/widgets/consolecommandwidget.cpp @@ -162,7 +162,7 @@ bool ConsoleCommandWidget::handleEvent(Event const &event) return false; } -void ConsoleCommandWidget::autoCompletionBegan() +void ConsoleCommandWidget::autoCompletionBegan(String const &) { // Prepare a list of annotated completions to show in the popup. QStringList const compls = suggestedCompletions(); diff --git a/doomsday/libshell/include/de/shell/abstractlineeditor.h b/doomsday/libshell/include/de/shell/abstractlineeditor.h index 673ef53019..30e51dd594 100644 --- a/doomsday/libshell/include/de/shell/abstractlineeditor.h +++ b/doomsday/libshell/include/de/shell/abstractlineeditor.h @@ -127,7 +127,7 @@ class LIBSHELL_PUBLIC AbstractLineEditor : public ITextEditor virtual void numberOfLinesChanged(int lineCount) = 0; virtual void cursorMoved() = 0; virtual void contentChanged() = 0; - virtual void autoCompletionBegan(); + virtual void autoCompletionBegan(String const &wordBase); virtual void autoCompletionEnded(bool accepted); enum LineWrapUpdateBehavior { diff --git a/doomsday/libshell/src/abstractlineeditor.cpp b/doomsday/libshell/src/abstractlineeditor.cpp index 4004ba5ef3..a7aeb1c7b9 100644 --- a/doomsday/libshell/src/abstractlineeditor.cpp +++ b/doomsday/libshell/src/abstractlineeditor.cpp @@ -50,12 +50,16 @@ DENG2_PIMPL(AbstractLineEditor) }; Completion completion; QStringList suggestions; + bool suggesting; + bool completionNotified; Instance(Public *i, ILineWrapping *lineWraps) : Base(i), cursor(0), echoMode(NormalEchoMode), - wraps(lineWraps) + wraps(lineWraps), + suggesting(false), + completionNotified(false) { // Initialize line wrapping. completion.reset(); @@ -158,11 +162,8 @@ DENG2_PIMPL(AbstractLineEditor) void doBackspace() { - if(suggestingCompletion()) - { - rejectCompletion(); + if(rejectCompletion()) return; - } if(!text.isEmpty() && cursor > 0) { @@ -264,17 +265,23 @@ DENG2_PIMPL(AbstractLineEditor) bool suggestingCompletion() const { - return completion.size > 0; + return suggesting; + //return completion.size > 0; } - String wordBehindCursor() const + String wordBehindPos(int pos) const { String word; - int i = cursor - 1; + int i = pos - 1; while(i >= 0 && lexicon.isWordChar(text[i])) word.prepend(text[i--]); return word; } + String wordBehindCursor() const + { + return wordBehindPos(cursor); + } + QStringList completionsForBase(String base, String &commonPrefix) const { bool first = true; @@ -306,6 +313,7 @@ DENG2_PIMPL(AbstractLineEditor) { if(!suggestingCompletion()) { + completionNotified = false; String const base = wordBehindCursor(); if(!base.isEmpty()) { @@ -322,26 +330,37 @@ DENG2_PIMPL(AbstractLineEditor) text.insert(cursor, commonPrefix); cursor += completion.size; rewrapNow(); - self.autoCompletionBegan(); + suggesting = true; return true; } if(!suggestions.isEmpty()) { - completion.ordinal = (forwardCycle? 0 : suggestions.size() - 1); - String comp = suggestions[completion.ordinal]; - comp.remove(0, base.size()); + completion.ordinal = -1; //(forwardCycle? 0 : suggestions.size() - 1); + /*String comp = suggestions[completion.ordinal]; + comp.remove(0, base.size());*/ completion.pos = cursor; - completion.size = comp.size(); - text.insert(cursor, comp); - cursor += completion.size; - rewrapNow(); - self.autoCompletionBegan(); + completion.size = 0; //comp.size(); + //text.insert(cursor, comp); + //cursor += completion.size; + //rewrapNow(); + suggesting = true; + // Notify immediately. + self.autoCompletionBegan(base); + completionNotified = true; return true; } } } else { + if(!completionNotified) + { + // Time to notify now. + self.autoCompletionBegan(wordBehindPos(completion.pos)); + completionNotified = true; + return true; + } + // Replace the current completion with another suggestion. cursor = completion.pos; String const base = wordBehindCursor(); @@ -371,6 +390,7 @@ DENG2_PIMPL(AbstractLineEditor) completion.size = comp.size(); cursor = completion.pos + completion.size; rewrapNow(); + return true; } return false; @@ -386,6 +406,8 @@ DENG2_PIMPL(AbstractLineEditor) { completion.reset(); suggestions.clear(); + suggesting = false; + completionNotified = false; } void acceptCompletion() @@ -397,14 +419,20 @@ DENG2_PIMPL(AbstractLineEditor) self.autoCompletionEnded(true); } - void rejectCompletion() + bool rejectCompletion() { + if(!suggestingCompletion()) return false; + + int oldCursor = cursor; + text.remove(completion.pos, completion.size); cursor = completion.pos; resetCompletion(); rewrapNow(); self.autoCompletionEnded(false); + + return cursor != oldCursor; // cursor was moved as part of the rejection } }; @@ -609,7 +637,7 @@ ILineWrapping &AbstractLineEditor::lineWraps() return *d->wraps; } -void AbstractLineEditor::autoCompletionBegan() +void AbstractLineEditor::autoCompletionBegan(String const &) {} void AbstractLineEditor::autoCompletionEnded(bool /*accepted*/)