lltexteditor.h

Go to the documentation of this file.
00001 
00032 // Text editor widget to let users enter a a multi-line ASCII document//
00033 
00034 #ifndef LL_LLTEXTEDITOR_H
00035 #define LL_LLTEXTEDITOR_H
00036 
00037 #include "llrect.h"
00038 #include "llkeywords.h"
00039 #include "lluictrl.h"
00040 #include "llframetimer.h"
00041 #include "lldarray.h"
00042 #include "llstyle.h"
00043 #include "lleditmenuhandler.h"
00044 #include "lldarray.h"
00045 
00046 class LLFontGL;
00047 class LLScrollbar;
00048 class LLViewBorder;
00049 class LLKeywordToken;
00050 class LLTextCmd;
00051 class LLUICtrlFactory;
00052 
00053 //
00054 // Constants
00055 //
00056 
00057 const llwchar FIRST_EMBEDDED_CHAR = 0x100000;
00058 const llwchar LAST_EMBEDDED_CHAR =  0x10ffff;
00059 const S32 MAX_EMBEDDED_ITEMS = LAST_EMBEDDED_CHAR - FIRST_EMBEDDED_CHAR + 1;
00060 
00061 //
00062 // Classes
00063 //
00064 class LLTextSegment;
00065 class LLTextCmd;
00066 
00067 class LLTextEditor : public LLUICtrl, LLEditMenuHandler
00068 {
00069         friend class LLTextCmd;
00070 public:
00071         LLTextEditor(const LLString& name,
00072                                  const LLRect& rect,
00073                                  S32 max_length,
00074                                  const LLString &default_text, 
00075                                  const LLFontGL* glfont = NULL,
00076                                  BOOL allow_embedded_items = FALSE);
00077 
00078         virtual ~LLTextEditor();
00079 
00080         virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEXT_EDITOR; }
00081         virtual LLString getWidgetTag() const;
00082 
00083         virtual LLXMLNodePtr getXML(bool save_children = true) const;
00084         static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
00085         void    setTextEditorParameters(LLXMLNodePtr node);
00086         void    setParseHTML(BOOL parsing) {mParseHTML=parsing;}
00087 
00088         // mousehandler overrides
00089         virtual BOOL    handleMouseDown(S32 x, S32 y, MASK mask);
00090         virtual BOOL    handleMouseUp(S32 x, S32 y, MASK mask);
00091         virtual BOOL    handleHover(S32 x, S32 y, MASK mask);
00092         virtual BOOL    handleScrollWheel(S32 x, S32 y, S32 clicks);
00093         virtual BOOL    handleDoubleClick(S32 x, S32 y, MASK mask );
00094         virtual BOOL    handleKeyHere(KEY key, MASK mask, BOOL called_from_parent );
00095         virtual BOOL    handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent);
00096 
00097         virtual BOOL    handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect);
00098         virtual BOOL    handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
00099                                                                           EDragAndDropType cargo_type, void *cargo_data,
00100                                                                           EAcceptance *accept, LLString& tooltip_msg);
00101         virtual void    onMouseCaptureLost();
00102 
00103 
00104         // view overrides
00105         virtual void    reshape(S32 width, S32 height, BOOL called_from_parent);
00106         virtual void    draw();
00107         virtual void    onFocusLost();
00108         virtual void    setEnabled(BOOL enabled);
00109 
00110         // uictrl overrides
00111         virtual void    onTabInto();
00112         virtual void    clear();
00113         virtual void    setFocus( BOOL b );
00114         virtual BOOL    acceptsTextInput() const;
00115         virtual BOOL    isDirty() const;
00116 
00117         // LLEditMenuHandler interface
00118         virtual void    undo();
00119         virtual BOOL    canUndo();
00120 
00121         virtual void    redo();
00122         virtual BOOL    canRedo();
00123 
00124         virtual void    cut();
00125         virtual BOOL    canCut();
00126 
00127         virtual void    copy();
00128         virtual BOOL    canCopy();
00129 
00130         virtual void    paste();
00131         virtual BOOL    canPaste();
00132         
00133         virtual void    doDelete();
00134         virtual BOOL    canDoDelete();
00135 
00136         virtual void    selectAll();
00137         virtual BOOL    canSelectAll();
00138 
00139         virtual void    deselect();
00140         virtual BOOL    canDeselect();
00141 
00142         void                    selectNext(const LLString& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
00143         BOOL                    replaceText(const LLString& search_text, const LLString& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
00144         void                    replaceTextAll(const LLString& search_text, const LLString& replace_text, BOOL case_insensitive);
00145         
00146         // Undo/redo stack
00147         void                    blockUndo();
00148 
00149         // Text editing
00150         virtual void    makePristine();
00151         BOOL                    isPristine() const;
00152 
00153         // inserts text at cursor
00154         void                    insertText(const LLString &text);
00155         // appends text at end
00156         void                    appendText(const LLString &wtext, bool allow_undo, bool prepend_newline,
00157                                                            const LLStyle* segment_style = NULL);
00158 
00159         void                    appendColoredText(const LLString &wtext, bool allow_undo, 
00160                                                                           bool prepend_newline,
00161                                                                           const LLColor4 &color,
00162                                                                           const LLString& font_name = LLString::null);
00163         // if styled text starts a line, you need to prepend a newline.
00164         void                    appendStyledText(const LLString &new_text, bool allow_undo, 
00165                                                                          bool prepend_newline,
00166                                                                          const LLStyle* style);
00167 
00168         // Removes text from the end of document
00169         // Does not change highlight or cursor position.
00170         void                    removeTextFromEnd(S32 num_chars);
00171 
00172         BOOL                    tryToRevertToPristineState();
00173 
00174         void                    setCursor(S32 row, S32 column);
00175         void                    setCursorPos(S32 offset);
00176         void                    setCursorAndScrollToEnd();
00177 
00178         void                    getCurrentLineAndColumn( S32* line, S32* col, BOOL include_wordwrap );
00179 
00180         void                    loadKeywords(const LLString& filename,
00181                                                                  const LLDynamicArray<const char*>& funcs,
00182                                                                  const LLDynamicArray<const char*>& tooltips,
00183                                                                  const LLColor3& func_color);
00184 
00185         void                    setCursorColor(const LLColor4& c)                       { mCursorColor = c; }
00186         void                    setFgColor( const LLColor4& c )                         { mFgColor = c; }
00187         void                    setReadOnlyFgColor( const LLColor4& c )         { mReadOnlyFgColor = c; }
00188         void                    setWriteableBgColor( const LLColor4& c )        { mWriteableBgColor = c; }
00189         void                    setReadOnlyBgColor( const LLColor4& c )         { mReadOnlyBgColor = c; }
00190 
00191         void                    setTrackColor( const LLColor4& color );
00192         void                    setThumbColor( const LLColor4& color );
00193         void                    setHighlightColor( const LLColor4& color );
00194         void                    setShadowColor( const LLColor4& color );
00195 
00196         // Hacky methods to make it into a word-wrapping, potentially scrolling,
00197         // read-only text box.
00198         void                    setBorderVisible(BOOL b);
00199         void                    setTakesNonScrollClicks(BOOL b);
00200         void                    setHideScrollbarForShortDocs(BOOL b);
00201 
00202         void                    setWordWrap( BOOL b );
00203         void                    setTabToNextField(BOOL b)                               { mTabToNextField = b; }
00204         void                    setCommitOnFocusLost(BOOL b)                    { mCommitOnFocusLost = b; }
00205 
00206         // If takes focus, will take keyboard focus on click.
00207         void                    setTakesFocus(BOOL b)                                   { mTakesFocus = b; }
00208 
00209         // Hack to handle Notecards
00210         virtual BOOL    importBuffer(const LLString& buffer );
00211         virtual BOOL    exportBuffer(LLString& buffer );
00212 
00213         void                    setSourceID(const LLUUID& id)                   { mSourceID = id; }
00214         void                    setAcceptCallingCardNames(BOOL enable)  { mAcceptCallingCardNames = enable; }
00215 
00216         void                    setHandleEditKeysDirectly( BOOL b )     { mHandleEditKeysDirectly = b; }
00217 
00218         // Callbacks
00219         static void             setLinkColor(LLColor4 color) { mLinkColor = color; }
00220         static void             setURLCallbacks(void (*callback1) (const char* url), 
00221                                                                         bool (*callback2) (const std::string& url),      
00222                                                                         bool (*callback3) (const std::string& url)      ) 
00223                                                                         { mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;}
00224 
00225         void                    setOnScrollEndCallback(void (*callback)(void*), void* userdata);
00226 
00227         // new methods
00228         void                    setValue(const LLSD& value);
00229         LLSD                    getValue() const;
00230 
00231         const LLString& getText() const;
00232         
00233         // Non-undoable
00234         void                    setText(const LLStringExplicit &utf8str);
00235         void                    setWText(const LLWString &wtext);
00236         
00237         S32                             getMaxLength() const                    { return mMaxTextLength; }
00238 
00239         // Change cursor
00240         void                    startOfLine();
00241         void                    endOfLine();
00242         void                    endOfDoc();
00243         
00244         // Getters
00245         const LLWString& getWText() const;
00246         llwchar                 getWChar(S32 pos);
00247         LLWString               getWSubString(S32 pos, S32 len);
00248         
00249         LLTextSegment*  getCurrentSegment();
00250         LLTextSegment*  getPreviousSegment();
00251         void getSelectedSegments(std::vector<LLTextSegment*>& segments);
00252 
00253 protected:
00254         S32                             getLength() const;
00255         void                    getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp );
00256 
00257         void                    drawBackground();
00258         void                    drawSelectionBackground();
00259         void                    drawCursor();
00260         void                    drawText();
00261         void                    drawClippedSegment(const LLWString &wtext, S32 seg_start, S32 seg_end, F32 x, F32 y, S32 selection_left, S32 selection_right, const LLStyle& color, F32* right_x);
00262 
00263         void                    updateLineStartList(S32 startpos = 0);
00264         void                    updateScrollFromCursor();
00265         void                    updateTextRect();
00266         void                    updateSegments();
00267         void                    pruneSegments();
00268 
00269         void                    assignEmbedded(const LLString &s);
00270         void                    truncate();
00271         
00272         static BOOL             isPartOfWord(llwchar c);
00273 
00274         void                    removeCharOrTab();
00275         void                    setCursorAtLocalPos(S32 x, S32 y, BOOL round);
00276         S32                             getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round );
00277 
00278         void                    indentSelectedLines( S32 spaces );
00279         S32                             indentLine( S32 pos, S32 spaces );
00280         void                    unindentLineBeforeCloseBrace();
00281 
00282         S32                             getSegmentIdxAtOffset(S32 offset);
00283         LLTextSegment*  getSegmentAtLocalPos(S32 x, S32 y);
00284         LLTextSegment*  getSegmentAtOffset(S32 offset);
00285 
00286         void                    reportBadKeystroke();
00287 
00288         BOOL                    handleNavigationKey(const KEY key, const MASK mask);
00289         BOOL                    handleSpecialKey(const KEY key, const MASK mask, BOOL* return_key_hit);
00290         BOOL                    handleSelectionKey(const KEY key, const MASK mask);
00291         BOOL                    handleControlKey(const KEY key, const MASK mask);
00292         BOOL                    handleEditKey(const KEY key, const MASK mask);
00293 
00294         BOOL                    hasSelection() { return (mSelectionStart !=mSelectionEnd); }
00295         BOOL                    selectionContainsLineBreaks();
00296         void                    startSelection();
00297         void                    endSelection();
00298         void                    deleteSelection(BOOL transient_operation);
00299 
00300         S32                             prevWordPos(S32 cursorPos) const;
00301         S32                             nextWordPos(S32 cursorPos) const;
00302 
00303         S32                     getLineCount();
00304         S32                     getLineStart( S32 line );
00305         void                    getLineAndOffset(S32 pos, S32* linep, S32* offsetp);
00306         S32                             getPos(S32 line, S32 offset);
00307 
00308         void                    changePage(S32 delta);
00309         void                    changeLine(S32 delta);
00310 
00311         void                    autoIndent();
00312 
00313         S32                     execute(LLTextCmd* cmd);
00314         
00315         void                    findEmbeddedItemSegments();
00316         
00317         virtual BOOL    handleMouseUpOverSegment(S32 x, S32 y, MASK mask);
00318         virtual llwchar pasteEmbeddedItem(llwchar ext_char);
00319         virtual void    bindEmbeddedChars(const LLFontGL* font);
00320         virtual void    unbindEmbeddedChars(const LLFontGL* font);
00321         
00322         S32                             findHTMLToken(const LLString &line, S32 pos, BOOL reverse);
00323         BOOL                    findHTML(const LLString &line, S32 *begin, S32 *end);
00324 
00325 protected:
00326         // Undoable operations
00327         void                    addChar(llwchar c); // at mCursorPos
00328         S32                             addChar(S32 pos, llwchar wc);
00329         S32                             overwriteChar(S32 pos, llwchar wc);
00330         void                    removeChar();
00331         S32                     removeChar(S32 pos);
00332         S32                             insert(const S32 pos, const LLWString &wstr, const BOOL group_with_next_op);
00333         S32                             remove(const S32 pos, const S32 length, const BOOL group_with_next_op);
00334         S32                             append(const LLWString &wstr, const BOOL group_with_next_op);
00335         
00336         // direct operations
00337         S32                             insertStringNoUndo(S32 pos, const LLWString &wstr); // returns num of chars actually inserted
00338         S32                     removeStringNoUndo(S32 pos, S32 length);
00339         S32                             overwriteCharNoUndo(S32 pos, llwchar wc);
00340         
00341 public:
00342         LLKeywords              mKeywords;
00343         static LLColor4 mLinkColor;
00344         static void                     (*mURLcallback) (const char* url);
00345         static bool                     (*mSecondlifeURLcallback) (const std::string& url);
00346         static bool                     (*mSecondlifeURLcallbackRightClick) (const std::string& url);
00347 protected:
00348         LLWString               mWText;
00349         mutable LLString mUTF8Text;
00350         mutable BOOL    mTextIsUpToDate;
00351         
00352         S32                             mMaxTextLength;         // Maximum length mText is allowed to be
00353 
00354         const LLFontGL* mGLFont;
00355 
00356         LLScrollbar*    mScrollbar;
00357         LLViewBorder*   mBorder;
00358 
00359         BOOL                    mBaseDocIsPristine;
00360         LLTextCmd*              mPristineCmd;
00361 
00362         LLTextCmd*              mLastCmd;
00363 
00364         typedef std::deque<LLTextCmd*> undo_stack_t;
00365         undo_stack_t    mUndoStack;
00366 
00367         S32                             mCursorPos;                             // I-beam is just after the mCursorPos-th character.
00368         S32                             mDesiredXPixel;                 // X pixel position where the user wants the cursor to be
00369         LLRect                  mTextRect;                              // The rect in which text is drawn.  Excludes borders.
00370         // List of offsets and segment index of the start of each line.  Always has at least one node (0).
00371         struct line_info
00372         {
00373                 line_info(S32 segment, S32 offset) : mSegment(segment), mOffset(offset) {}
00374                 S32 mSegment;
00375                 S32 mOffset;
00376         };
00377         struct line_info_compare
00378         {
00379                 bool operator()(const line_info& a, const line_info& b) const
00380                 {
00381                         if (a.mSegment < b.mSegment)
00382                                 return true;
00383                         else if (a.mSegment > b.mSegment)
00384                                 return false;
00385                         else
00386                                 return a.mOffset < b.mOffset;
00387                 }
00388         };
00389         typedef std::vector<line_info> line_list_t;
00390         line_list_t mLineStartList;
00391         
00392         // Are we in the middle of a drag-select?  To figure out if there is a current
00393         // selection, call hasSelection().
00394         BOOL                    mIsSelecting;
00395 
00396         S32                             mSelectionStart;
00397         S32                             mSelectionEnd;
00398 
00399         void                    (*mOnScrollEndCallback)(void*);
00400         void                    *mOnScrollEndData;
00401 
00402         typedef std::vector<LLTextSegment *> segment_list_t;
00403         segment_list_t mSegments;
00404         LLTextSegment*  mHoverSegment;
00405         LLFrameTimer    mKeystrokeTimer;
00406 
00407         LLColor4                mCursorColor;
00408 
00409         LLColor4                mFgColor;
00410         LLColor4                mReadOnlyFgColor;
00411         LLColor4                mWriteableBgColor;
00412         LLColor4                mReadOnlyBgColor;
00413         LLColor4                mFocusBgColor;
00414 
00415         BOOL                    mReadOnly;
00416         BOOL                    mWordWrap;
00417 
00418         BOOL                    mTabToNextField;                // if true, tab moves focus to next field, else inserts spaces
00419         BOOL                    mCommitOnFocusLost;
00420         BOOL                    mTakesFocus;
00421         BOOL                    mHideScrollbarForShortDocs;
00422         BOOL                    mTakesNonScrollClicks;
00423 
00424         BOOL                    mAllowEmbeddedItems;
00425 
00426         BOOL                    mAcceptCallingCardNames;
00427 
00428         LLUUID                  mSourceID;
00429 
00430         BOOL                    mHandleEditKeysDirectly;  // If true, the standard edit keys (Ctrl-X, Delete, etc,) are handled here instead of routed by the menu system
00431 
00432         // Use these to determine if a click on an embedded item is a drag 
00433         // or not.
00434         S32                             mMouseDownX;
00435         S32                             mMouseDownY;
00436 
00437         S32                             mLastSelectionX;
00438         S32                             mLastSelectionY;
00439 
00440         BOOL                    mParseHTML;
00441         LLString                mHTML;
00442 
00443         LLCoordGL               mLastIMEPosition;               // Last position of the IME editor
00444 };
00445 
00446 class LLTextSegment
00447 {
00448 public:
00449         // for creating a compare value
00450         LLTextSegment(S32 start);
00451         LLTextSegment( const LLStyle& style, S32 start, S32 end );
00452         LLTextSegment( const LLColor4& color, S32 start, S32 end, BOOL is_visible);
00453         LLTextSegment( const LLColor4& color, S32 start, S32 end );
00454         LLTextSegment( const LLColor3& color, S32 start, S32 end );
00455 
00456         S32                                     getStart()                                                      { return mStart; }
00457         S32                                     getEnd()                                                        { return mEnd; }
00458         void                            setEnd( S32 end )                                       { mEnd = end; }
00459         const LLColor4&         getColor()                                                      { return mStyle.getColor(); }
00460         void                            setColor(const LLColor4 &color)         { mStyle.setColor(color); }
00461         const LLStyle&          getStyle()                                                      { return mStyle; }
00462         void                            setStyle(const LLStyle &style)          { mStyle = style; }
00463         void                            setIsDefault(BOOL b)                            { mIsDefault = b; }
00464         BOOL                            getIsDefault()                                          { return mIsDefault; }
00465 
00466         void                            setToken( LLKeywordToken* token )       { mToken = token; }
00467         LLKeywordToken*         getToken()                                                      { return mToken; }
00468         BOOL                            getToolTip( LLString& msg );
00469 
00470         void                            dump();
00471 
00472         struct compare
00473         {
00474                 bool operator()(const LLTextSegment* a, const LLTextSegment* b) const
00475                 {
00476                         return a->mStart < b->mStart;
00477                 }
00478         };
00479         
00480 private:
00481         LLStyle     mStyle;
00482         S32                     mStart;
00483         S32                     mEnd;
00484         LLKeywordToken* mToken;
00485         BOOL            mIsDefault;
00486 };
00487 
00488 class LLTextCmd
00489 {
00490 public:
00491         LLTextCmd( S32 pos, BOOL group_with_next )
00492                 : mPos(pos),
00493                   mGroupWithNext(group_with_next)
00494         {
00495         }
00496         virtual                 ~LLTextCmd() {}
00497         virtual BOOL    execute(LLTextEditor* editor, S32* delta) = 0;
00498         virtual S32             undo(LLTextEditor* editor) = 0;
00499         virtual S32             redo(LLTextEditor* editor) = 0;
00500         virtual BOOL    canExtend(S32 pos);
00501         virtual void    blockExtensions();
00502         virtual BOOL    extendAndExecute( LLTextEditor* editor, S32 pos, llwchar c, S32* delta );
00503         virtual BOOL    hasExtCharValue( llwchar value );
00504 
00505         // Define these here so they can access LLTextEditor through the friend relationship
00506         S32                             insert(LLTextEditor* editor, S32 pos, const LLWString &wstr);
00507         S32                     remove(LLTextEditor* editor, S32 pos, S32 length);
00508         S32                             overwrite(LLTextEditor* editor, S32 pos, llwchar wc);
00509         
00510         BOOL                    groupWithNext() { return mGroupWithNext; }
00511         
00512 protected:
00513         S32                     mPos;
00514         BOOL            mGroupWithNext;
00515 };
00516 
00517 
00518 #endif  // LL_TEXTEDITOR_

Generated on Thu Jul 1 06:09:18 2010 for Second Life Viewer by  doxygen 1.4.7