summaryrefslogtreecommitdiff
path: root/src/gui/widgets
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-08-29 09:01:27 -0600
committerJared Adams <jaxad0127@gmail.com>2010-08-29 22:19:24 -0600
commitd55c1345449a34adb3192c23fe3760bd0aae645b (patch)
tree0dfe78eba2571b2f156c14deafe375d3f3241164 /src/gui/widgets
parentb61faa43db7a48c6a6871fb94dce2de2abd79dfe (diff)
downloadmana-client-d55c1345449a34adb3192c23fe3760bd0aae645b.tar.gz
mana-client-d55c1345449a34adb3192c23fe3760bd0aae645b.tar.bz2
mana-client-d55c1345449a34adb3192c23fe3760bd0aae645b.tar.xz
mana-client-d55c1345449a34adb3192c23fe3760bd0aae645b.zip
Move handling of autocomplete and input history into TextField
Reviewed-by: Freeyorp
Diffstat (limited to 'src/gui/widgets')
-rw-r--r--src/gui/widgets/chattab.cpp6
-rw-r--r--src/gui/widgets/chattab.h7
-rw-r--r--src/gui/widgets/textfield.cpp137
-rw-r--r--src/gui/widgets/textfield.h68
4 files changed, 197 insertions, 21 deletions
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 39ea6887..8bf57508 100644
--- a/src/gui/widgets/chattab.cpp
+++ b/src/gui/widgets/chattab.cpp
@@ -21,6 +21,7 @@
#include "gui/widgets/chattab.h"
+#include "beingmanager.h"
#include "commandhandler.h"
#include "configuration.h"
#include "localplayer.h"
@@ -275,6 +276,11 @@ void ChatTab::handleCommand(const std::string &msg)
commandHandler->handleCommand(msg, this);
}
+void ChatTab::getAutoCompleteList(std::vector<std::string> &names) const
+{
+ beingManager->getPlayerNPCNameLister()->getAutoCompleteList(names);
+}
+
void ChatTab::addRow(std::string &line)
{
std::string::size_type idx = 0;
diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/chattab.h
index 7fd3931e..c2dfa1c1 100644
--- a/src/gui/widgets/chattab.h
+++ b/src/gui/widgets/chattab.h
@@ -25,6 +25,7 @@
#include "gui/chat.h"
#include "gui/widgets/tab.h"
+#include "gui/widgets/textfield.h"
class BrowserBox;
class Recorder;
@@ -45,7 +46,7 @@ enum
/**
* A tab for the chat window. This is special to ease chat handling.
*/
-class ChatTab : public Tab
+class ChatTab : public Tab, public AutoCompleteLister
{
public:
/**
@@ -111,6 +112,8 @@ class ChatTab : public Tab
const std::string &args)
{ return false; }
+ void getAutoCompleteList(std::vector<std::string> &names) const;
+
protected:
friend class ChatWindow;
friend class WhisperWindow;
@@ -121,8 +124,6 @@ class ChatTab : public Tab
virtual void handleCommand(const std::string &msg);
- virtual void getAutoCompleteList(std::vector<std::string>&) const {}
-
void addRow(std::string &line);
ScrollArea *mScrollArea;
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index 60a1f57f..3e02be98 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -25,7 +25,6 @@
#include "configuration.h"
#include "graphics.h"
-#include "gui/chat.h"
#include "gui/palette.h"
#include "gui/sdlinput.h"
#include "gui/theme.h"
@@ -34,6 +33,7 @@
#include "utils/copynpaste.h"
#include "utils/dtor.h"
+#include "utils/stringutils.h"
#include <guichan/font.hpp>
@@ -46,7 +46,8 @@ ImageRect TextField::skin;
TextField::TextField(const std::string &text, bool loseFocusOnTab):
gcn::TextField(text),
mNumeric(false),
- mAutoComplete(false)
+ mAutoComplete(NULL),
+ mHistory(NULL)
{
setFrameSize(2);
@@ -212,6 +213,42 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent)
}
} break;
+ case Key::UP:
+ {
+ if (mHistory && !mHistory->atBegining() && !mHistory->empty())
+ {
+ // Move backward through the history
+ mHistory->current--;
+ setText(*mHistory->current);
+ setCaretPosition(getText().length());
+ }
+ } break;
+
+ case Key::DOWN:
+ {
+ if (mHistory && !mHistory->atEnd())
+ {
+ // Move forward through the history
+ TextHistoryIterator prevHist = mHistory->current++;
+
+ if (!mHistory->atEnd())
+ {
+ setText(*mHistory->current);
+ setCaretPosition(getText().length());
+ }
+ else
+ {
+ setText("");
+ mHistory->current = prevHist;
+ }
+ }
+ else if (getText() != "")
+ {
+ // Always clear (easy access to useful function)
+ setText("");
+ }
+ } break;
+
case Key::DELETE:
{
unsigned sz = mText.size();
@@ -237,6 +274,19 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent)
} break;
case Key::ENTER:
+ if (mHistory)
+ {
+ mHistory->toEnd();
+
+ // If the input is different from previous, put it in the history
+ if (mHistory->empty() || !mHistory->matchesEntry(getText()))
+ {
+ mHistory->addEntry(getText());
+ }
+
+ mHistory->toEnd();
+ }
+
distributeActionEvent();
break;
@@ -249,17 +299,7 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent)
break;
case Key::TAB:
- if (mAutoComplete && mText.size() > 0)
- {
- std::vector<std::string> names;
- beingManager->getPlayerNames(names, false);
- std::string newName = chatWindow->autoComplete(names, mText);
- if (newName != "")
- {
- setText(newName);
- setCaretPosition(mText.size());
- }
- }
+ autoComplete();
if (mLoseFocusOnTab)
return;
break;
@@ -273,6 +313,77 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent)
fixScroll();
}
+void TextField::autoComplete()
+{
+ if (mAutoComplete && mText.size() > 0)
+ {
+ int caretPos = getCaretPosition();
+ int startName = 0;
+ const std::string inputText = getText();
+ std::string name = inputText.substr(0, caretPos);
+ std::string newName("");
+
+ for (int f = caretPos - 1; f > -1; f --)
+ {
+ if (isWordSeparator(inputText[f]))
+ {
+ startName = f + 1;
+ name = inputText.substr(f + 1, caretPos - f);
+ break;
+ }
+ }
+
+ if (caretPos - 1 + 1 != startName)
+ return;
+
+
+ std::vector<std::string> nameList;
+ mAutoComplete->getAutoCompleteList(nameList);
+ newName = autocomplete(nameList, name);
+
+ if (newName == "" && mHistory)
+ {
+
+ TextHistoryIterator i = mHistory->history.begin();
+ std::vector<std::string> nameList;
+
+ while (i != mHistory->history.end())
+ {
+ std::string line = *i;
+ unsigned int f = 0;
+ while (f < line.length() && !isWordSeparator(line.at(f)))
+ {
+ f++;
+ }
+ line = line.substr(0, f);
+ if (line != "")
+ {
+ nameList.push_back(line);
+ }
+ ++i;
+ }
+
+ newName = autocomplete(nameList, name);
+ }
+
+ if (newName != "")
+ {
+ if(inputText[0] == '@' || inputText[0] == '/')
+ newName = "\"" + newName + "\"";
+
+ setText(inputText.substr(0, startName) + newName
+ + inputText.substr(caretPos, inputText.length()
+ - caretPos));
+
+ if (startName > 0)
+ setCaretPosition(caretPos - name.length() + newName.length()
+ + 1);
+ else
+ setCaretPosition(caretPos - name.length() + newName.length());
+ }
+ }
+}
+
void TextField::handlePaste()
{
std::string text = getText();
diff --git a/src/gui/widgets/textfield.h b/src/gui/widgets/textfield.h
index 1e6df9d6..6e50f1e9 100644
--- a/src/gui/widgets/textfield.h
+++ b/src/gui/widgets/textfield.h
@@ -24,9 +24,48 @@
#include <guichan/widgets/textfield.hpp>
+#include <vector>
+
class ImageRect;
class TextField;
+typedef std::list<std::string> TextHistoryList;
+typedef TextHistoryList::iterator TextHistoryIterator;
+
+struct TextHistory {
+ TextHistoryList history; /**< Command history. */
+ TextHistoryIterator current; /**< History iterator. */
+
+ TextHistory()
+ { current = history.end(); }
+
+ bool empty() const
+ { return history.empty(); }
+
+ bool atBegining() const
+ { return current == history.begin(); }
+
+ bool atEnd() const
+ { return current == history.end(); }
+
+ void toBegining()
+ { current = history.begin(); }
+
+ void toEnd()
+ { current = history.end(); }
+
+ void addEntry(const std::string &text)
+ { history.push_back(text); }
+
+ bool matchesEntry(const std::string &text)
+ { return (*current) == text; }
+};
+
+class AutoCompleteLister {
+public:
+ virtual void getAutoCompleteList(std::vector<std::string>&) const {}
+};
+
/**
* A text field.
*
@@ -91,16 +130,32 @@ class TextField : public gcn::TextField
int getValue() const;
/**
- * Set if the tabulator key causes auto complete
+ * Sets the TextField's source of autocomplete. Passing null will
+ * disable autocomplete.
+ */
+ void setAutoComplete(AutoCompleteLister *lister)
+ { mAutoComplete = lister; }
+
+ /**
+ * Returns the TextField's source of autocomplete.
*/
- void setAutoComplete(bool b ) {mAutoComplete = b;}
+ AutoCompleteLister *getAutoComplete() const
+ { return mAutoComplete; }
/**
- * Returns if the tabulator key causes auto complete
+ * Sets the TextField's source of input history.
*/
- bool getAutoComplete() {return mAutoComplete;}
+ void setHistory(TextHistory *history)
+ { mHistory = history; }
+
+ /**
+ * Returns the TextField's source of input history.
+ */
+ TextHistory *getHistory() const
+ { return mHistory; }
private:
+ void autoComplete();
void handlePaste();
static int instances;
@@ -110,7 +165,10 @@ class TextField : public gcn::TextField
int mMinimum;
int mMaximum;
bool mLoseFocusOnTab;
- bool mAutoComplete;
+
+ AutoCompleteLister *mAutoComplete;
+
+ TextHistory *mHistory; /**< Text history. */
};
#endif