123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- /**
- * @file lllineeditor.h
- * @brief Text editor widget to let users enter/edit a single line.
- *
- * Features:
- * Text entry of a single line (text, delete, left and right arrow, insert, return).
- * Callbacks either on every keystroke or just on the return key.
- * Focus (allow multiple text entry widgets)
- * Clipboard (cut, copy, and paste)
- * Horizontal scrolling to allow strings longer than widget size allows
- * Pre-validation (limit which keys can be used)
- * Optional line history so previous entries can be recalled by CTRL UP/DOWN
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #ifndef LL_LLLINEEDITOR_H
- #define LL_LLLINEEDITOR_H
- #include "llcolor4.h"
- #include "lleditmenuhandler.h"
- #include "llframetimer.h"
- #include "llpreeditor.h"
- #include "lluictrl.h"
- #include "llviewborder.h"
- class LLButton;
- class LLLineEditorRollback;
- class LLFontGL;
- class LLMenuItemCallGL;
- typedef bool (*LLLinePrevalidateFunc)(const LLWString& wstr);
- class LLLineEditor : public LLUICtrl, public LLEditMenuHandler,
- protected LLPreeditor
- {
- protected:
- LOG_CLASS(LLLineEditor);
- public:
- LLLineEditor(const std::string& name, const LLRect& rect,
- const std::string& default_text = LLStringUtil::null,
- const LLFontGL* glfont = NULL, S32 max_length_bytes = 254,
- void (*commit_callback)(LLUICtrl*, void*) = NULL,
- void (*keystroke_callback)(LLLineEditor*, void*) = NULL,
- void (*focus_lost_callback)(LLFocusableElement*,
- void*) = NULL,
- void* userdata = NULL,
- LLLinePrevalidateFunc prevalidate_func = NULL,
- LLViewBorder::EBevel border_bevel = LLViewBorder::BEVEL_IN,
- LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
- S32 border_thickness = 1);
- ~LLLineEditor() override;
- const std::string& getTag() const override;
- LLXMLNodePtr getXML(bool save_children = true) const override;
- void setColorParameters(LLXMLNodePtr nodep);
- static LLView* fromXML(LLXMLNodePtr nodep, LLView* parentp,
- LLUICtrlFactory*);
- static void cleanupLineEditor();
- // Mouse handler overrides
- bool handleMouseDown(S32 x, S32 y, MASK mask) override;
- bool handleMouseUp(S32 x, S32 y, MASK mask) override;
- bool handleRightMouseDown(S32 x, S32 y, MASK mask) override;
- bool handleHover(S32 x, S32 y, MASK mask) override;
- bool handleDoubleClick(S32 x,S32 y,MASK mask) override;
- bool handleMiddleMouseDown(S32 x,S32 y,MASK mask) override;
- bool handleKeyHere(KEY key, MASK mask) override;
- bool handleUnicodeCharHere(llwchar uni_char) override;
- void onMouseCaptureLost() override;
- // Returns true if user changed value at all
- LL_INLINE virtual bool isSpellDirty() const { return mText.getString() != mPrevSpelledText; }
- // Clear dirty state
- LL_INLINE virtual void resetSpellDirty() { mPrevSpelledText = mText.getString(); }
- struct SpellMenuBind
- {
- LLLineEditor* mOrigin;
- LLMenuItemCallGL* mMenuItem;
- std::string mWord;
- S32 mWordPositionStart;
- S32 mWordPositionEnd;
- };
- std::vector<S32> getMisspelledWordsPositions();
- virtual void spellReplace(SpellMenuBind* data);
- virtual void insert(std::string what, S32 where);
- // LLEditMenuHandler overrides
- void cut() override;
- bool canCut() const override;
- void copy() override;
- bool canCopy() const override;
- void paste() override;
- bool canPaste() const override;
- void doDelete() override;
- bool canDoDelete() const override;
- void selectAll() override;
- LL_INLINE bool canSelectAll() const override { return true; }
- void deselect() override;
- LL_INLINE bool canDeselect() const override { return hasSelection(); }
- // New methods
- virtual void updatePrimary();
- virtual void copyPrimary();
- virtual void pastePrimary();
- virtual bool canPastePrimary() const;
- // LLView overrides
- void draw() override;
- void reshape(S32 width, S32 height, bool call_from_parent = true) override;
- void onFocusReceived() override;
- void onFocusLost() override;
- void setEnabled(bool enabled) override;
- LL_INLINE bool setTextArg(const std::string& key,
- const std::string& text) override
- {
- mText.setArg(key, text);
- return true;
- }
- LL_INLINE bool setLabelArg(const std::string& key,
- const std::string& text) override
- {
- mLabel.setArg(key, text);
- return true;
- }
- // LLUICtrl overrides
- void clear() override;
- void onTabInto() override;
- void setFocus(bool b) override;
- void setRect(const LLRect& rect) override;
- LL_INLINE bool acceptsTextInput() const override { return true; }
- void onCommit() override;
- // Returns true if user changed value at all
- LL_INLINE bool isDirty() const override { return mText.getString() != mPrevText; }
- // Clear dirty state
- LL_INLINE void resetDirty() override { mPrevText = mText.getString(); }
- // Assumes UTF8 text
- LL_INLINE void setValue(const LLSD& value) override { setText(value.asString()); }
- LL_INLINE LLSD getValue() const override { return LLSD(getText()); }
- // New methods
- LL_INLINE void setLabel(const std::string& label) { mLabel = label; }
- void setText(const std::string& new_text);
- LL_INLINE const std::string& getText() const { return mText.getString(); }
- LL_INLINE const LLWString& getWText() const override { return mText.getWString(); }
- // trimmed text with paragraphs converted to newlines
- LLWString getConvertedText() const;
- LL_INLINE S32 getLength() const { return mText.length(); }
- LL_INLINE S32 getCursor() const { return mCursorPos; }
- void setCursor(S32 pos);
- void setCursorToEnd();
- void resetScrollPosition();
- // Selects characters 'start' to 'end'.
- void setSelection(S32 start, S32 end);
- LL_INLINE void setCommitOnFocusLost(bool b) { mCommitOnFocusLost = b; }
- LL_INLINE void setRevertOnEsc(bool b) { mRevertOnEsc = b; }
- LL_INLINE void setCursorColor(const LLColor4& c) { mCursorColor = c; }
- LL_INLINE const LLColor4& getCursorColor() const { return mCursorColor; }
- LL_INLINE void setFgColor(const LLColor4& c) { mFgColor = c; }
- LL_INLINE void setReadOnlyFgColor(const LLColor4& c) { mReadOnlyFgColor = c; }
- LL_INLINE void setTentativeFgColor(const LLColor4& c) { mTentativeFgColor = c; }
- LL_INLINE void setWriteableBgColor(const LLColor4& c) { mWriteableBgColor = c; }
- LL_INLINE void setReadOnlyBgColor(const LLColor4& c) { mReadOnlyBgColor = c; }
- LL_INLINE void setFocusBgColor(const LLColor4& c) { mFocusBgColor = c; }
- LL_INLINE void setSpellCheck(bool b) { mSpellCheck = b; }
- LL_INLINE const LLColor4& getFgColor() const { return mFgColor; }
- LL_INLINE const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor; }
- LL_INLINE const LLColor4& getTentativeFgColor() const { return mTentativeFgColor; }
- LL_INLINE const LLColor4& getWriteableBgColor() const { return mWriteableBgColor; }
- LL_INLINE const LLColor4& getReadOnlyBgColor() const { return mReadOnlyBgColor; }
- LL_INLINE const LLColor4& getFocusBgColor() const { return mFocusBgColor; }
- LL_INLINE bool getSpellCheck() { return mSpellCheck; }
- LL_INLINE void setIgnoreArrowKeys(bool b) { mIgnoreArrowKeys = b; }
- LL_INLINE void setIgnoreTab(bool b) { mIgnoreTab = b; }
- LL_INLINE void setPassDelete(bool b) { mPassDelete = b; }
- void setDrawAsterixes(bool b);
- LL_INLINE bool getDrawAsterixes() { return mDrawAsterixes; }
- // Get the cursor position of the beginning/end of the prev/next word in
- // the text
- S32 prevWordPos(S32 cursor_pos) const;
- S32 nextWordPos(S32 cursor_pos) const;
- bool getWordBoundriesAt(S32 at, S32* word_begin, S32* word_length) const;
- LL_INLINE bool hasSelection() const { return mSelectionStart != mSelectionEnd; }
- void startSelection();
- void endSelection();
- void extendSelection(S32 new_cursor_pos);
- void deleteSelection();
- LL_INLINE void setHandleEditKeysDirectly(bool b) { mHandleEditKeysDirectly = b; }
- void setSelectAllonFocusReceived(bool b);
- void setKeystrokeCallback(void (*keystroke_callback)(LLLineEditor*,
- void*));
- void setScrolledCallback(void (*scrolled_callback)(LLLineEditor*, void*),
- void* userdata);
- void setOnHandleKeyCallback(bool (*callback)(KEY, MASK, LLLineEditor*,
- void*),
- void* userdata);
- void setMaxTextLength(S32 max_text_length);
- // Used to specify room for children before or after text.
- void setTextPadding(S32 left, S32 right);
- // Prevalidation controls which keystrokes can affect the editor
- void setPrevalidate(bool (*func)(const LLWString&));
- static bool prevalidateFloat(const LLWString& str);
- static bool prevalidateInt(const LLWString& str);
- static bool prevalidatePositiveS32(const LLWString& str);
- static bool prevalidateNonNegativeS32(const LLWString& str);
- static bool prevalidateAlphaNum(const LLWString& str);
- static bool prevalidateAlphaNumSpace(const LLWString& str);
- static bool prevalidatePrintableNotPipe(const LLWString& str);
- static bool prevalidatePrintableNoSpace(const LLWString& str);
- static bool prevalidateASCII(const LLWString& str);
- static bool postvalidateFloat(const std::string& str);
- // Line history support:
- // Switches line history on or off
- LL_INLINE void setEnableLineHistory(bool enabled) { mHaveHistory = enabled; }
- // Stores current line in history
- void updateHistory();
- LL_INLINE void setReplaceNewlinesWithSpaces(bool b) { mReplaceNewlinesWithSpaces = b; }
- private:
- void pasteHelper(bool is_primary);
- void removeChar();
- void addChar(llwchar c);
- S32 calculateCursorFromMouse(S32 local_mouse_x);
- void setCursorAtLocalPos(S32 local_mouse_x);
- S32 findPixelNearestPos(S32 cursor_offset = 0) const;
- void reportBadKeystroke();
- bool handleSpecialKey(KEY key, MASK mask);
- bool handleSelectionKey(KEY key, MASK mask);
- bool handleControlKey(KEY key, MASK mask);
- S32 handleCommitKey(KEY key, MASK mask);
- void updateAllowingLanguageInput();
- bool hasPreeditString() const;
- // Implementation (overrides) of LLPreeditor
- void resetPreedit() override;
- void updatePreedit(const LLWString& preedit_string,
- const segment_lengths_t& preedit_segment_lengths,
- const standouts_t& preedit_standouts,
- S32 caret_position) override;
- void markAsPreedit(S32 position, S32 length) override;
- void getPreeditRange(S32* position, S32* length) const override;
- void getSelectionRange(S32* position, S32* length) const override;
- bool getPreeditLocation(S32 query_position, LLCoordGL* coord,
- LLRect* bounds, LLRect* control) const override;
- S32 getPreeditFontSize() const override;
- // Private helper class
- class LLLineEditorRollback
- {
- public:
- LLLineEditorRollback(LLLineEditor* ed)
- : mCursorPos(ed->mCursorPos),
- mScrollHPos(ed->mScrollHPos),
- mIsSelecting(ed->mIsSelecting),
- mSelectionStart(ed->mSelectionStart),
- mSelectionEnd(ed->mSelectionEnd)
- {
- mText = ed->getText();
- }
- void doRollback(LLLineEditor* ed)
- {
- ed->mCursorPos = mCursorPos;
- ed->mScrollHPos = mScrollHPos;
- ed->mIsSelecting = mIsSelecting;
- ed->mSelectionStart = mSelectionStart;
- ed->mSelectionEnd = mSelectionEnd;
- ed->mText = mText;
- ed->mPrevText = mText;
- }
- LL_INLINE std::string getText() { return mText; }
- private:
- std::string mText;
- S32 mCursorPos;
- S32 mScrollHPos;
- bool mIsSelecting;
- S32 mSelectionStart;
- S32 mSelectionEnd;
- };
- // Utility on top of LLUI::getUIImage, looks up a named image in a given
- // XML node and returns it if possible or returns a given default image if
- // anything in the process fails.
- static LLUIImagePtr parseImage(std::string name, LLXMLNodePtr from,
- LLUIImagePtr def);
- // Context menu actions
- static void spellCorrect(void* data);
- static void spellShow(void* data);
- static void spellAdd(void* data);
- static void spellIgnore(void* data);
- void drawMisspelled(LLRect background);
- protected:
- LLUIString mText; // The string being edited.
- std::string mPrevText; // Saved string for 'ESC' revert
- // Text label that is visible when no user text provided
- LLUIString mLabel;
- // Spell checking
- // Saved string so we know whether to respell or not
- std::string mPrevSpelledText;
- // Where all the misspelled words are
- std::vector<S32> mMisspellLocations;
- // The position of the first character, stored so we know when to update
- S32 mSpellCheckStart;
- // The location of the last character
- S32 mSpellCheckEnd;
- // Set in xui as "spell_check". Default value for a field
- bool mSpellCheck;
- // Whether to highlight misspelled words or not
- bool mShowMisspelled;
- LLFrameTimer mSpellTimer;
- // To keep track of what we have to remove before rebuilding the context
- // menu
- std::vector<SpellMenuBind*> mSuggestionMenuItems;
- // Line history support:
- typedef std::vector<std::string> line_history_t;
- line_history_t mLineHistory; // Line history storage
- // Currently browsed history line
- line_history_t::iterator mCurrentHistoryLine;
- // Flag for enabled line history
- bool mHaveHistory;
- // Selection for clipboard operations
- bool mIsSelecting;
- S32 mSelectionStart;
- S32 mSelectionEnd;
- S32 mLastSelectionX;
- S32 mLastSelectionY;
- S32 mLastSelectionStart;
- S32 mLastSelectionEnd;
- LLViewBorder* mBorder;
- const LLFontGL* mGLFont;
- // Max length of the UTF8 string in bytes
- S32 mMaxLengthBytes;
- // I-beam is just after the mCursorPos-th character.
- S32 mCursorPos;
- // Horizontal offset from the start of mText. Used for scrolling.
- S32 mScrollHPos;
- LLFrameTimer mScrollTimer;
- // Used to reserve space before the beginning of the text for children
- S32 mTextPadLeft;
- // Used to reserve space after the end of the text for children
- S32 mTextPadRight;
- S32 mMinHPixels;
- S32 mMaxHPixels;
- bool mCommitOnFocusLost;
- bool mRevertOnEsc;
- void (*mKeystrokeCallback)(LLLineEditor* caller,
- void* userdata);
- void (*mScrolledCallback)(LLLineEditor* caller,
- void* userdata);
- void* mScrolledCallbackData;
- bool (*mOnHandleKeyCallback)(KEY, MASK,
- LLLineEditor*, void*);
- void* mOnHandleKeyData;
- bool (*mPrevalidateFunc)(const LLWString& str);
- LLFrameTimer mKeystrokeTimer;
- LLColor4 mCursorColor;
- LLColor4 mFgColor;
- LLColor4 mReadOnlyFgColor;
- LLColor4 mTentativeFgColor;
- LLColor4 mWriteableBgColor;
- LLColor4 mReadOnlyBgColor;
- LLColor4 mFocusBgColor;
- S32 mBorderThickness;
- LLWString mPreeditWString;
- LLWString mPreeditOverwrittenWString;
- std::vector<S32> mPreeditPositions;
- LLPreeditor::standouts_t mPreeditStandouts;
- bool mIgnoreArrowKeys;
- bool mIgnoreTab;
- bool mDrawAsterixes;
- // If true, the standard edit keys (Ctrl-X, Delete, etc) are handled here
- // instead of routed by the menu system:
- bool mHandleEditKeysDirectly;
- bool mSelectAllonFocusReceived;
- bool mPassDelete;
- bool mReadOnly;
- private:
- // If false, will replace pasted newlines with paragraph symbol.
- bool mReplaceNewlinesWithSpaces;
- // Instances that by default point to the statics but can be overidden in
- // XML.
- LLUIImagePtr mImage;
- // Global instance used as default for member instance above.
- static LLUIImagePtr sImage;
- };
- // A line editor with a button to clear it and a callback to call on every edit
- // event.
- class LLSearchEditor final : public LLUICtrl, public LLEditMenuHandler
- {
- public:
- LLSearchEditor(const std::string& name, const LLRect& rect,
- S32 max_length);
- void draw() override;
- const std::string& getTag() const override;
- LLXMLNodePtr getXML(bool save_children = true) const override;
- static LLView* fromXML(LLXMLNodePtr nodep, LLView* parentp,
- LLUICtrlFactory*);
- LL_INLINE void setText(const std::string& new_text) { mSearchLineEditor->setText(new_text); }
- LL_INLINE const std::string& getText() const { return mSearchLineEditor->getText(); }
- void setSearchCallback(void (*cb)(const std::string&, void*),
- void* userdata);
- // LLUICtrl overrides since we want the callback to apply to the input line
- void setCommitCallback(void (*cb)(LLUICtrl*, void*));
- void setCallbackUserData(void* data)
- {
- mCommitCallbackUserData = data;
- }
- LL_INLINE void setValue(const LLSD& value) override { mSearchLineEditor->setValue(value); }
- LL_INLINE LLSD getValue() const override { return mSearchLineEditor->getValue(); }
- LL_INLINE bool setTextArg(const std::string& key,
- const std::string& text) override
- {
- return mSearchLineEditor->setTextArg(key, text);
- }
- LL_INLINE bool setLabelArg(const std::string& key,
- const std::string& text) override
- {
- return mSearchLineEditor->setLabelArg(key, text);
- }
- void clear() override;
- private:
- // These are wrappers around the LLSearchEditor commits
- static void onSearchEditCommit(LLUICtrl* ctrl, void* data);
- static void onSearchEditKeystroke(LLLineEditor* caller, void* data);
- static void onClearSearch(void* user_data);
- private:
- LLLineEditor* mSearchLineEditor;
- LLButton* mClearSearchButton;
- void (*mLineCommitCallback)(LLUICtrl* ctrl, void* user_data);
- void (*mSearchCallback)(const std::string& search_string,
- void* user_data);
- void* mCommitCallbackUserData;
- };
- #endif // LL_LINEEDITOR_
|