1///////////////////////////////////////////////////////////////////////////// 2// Name: wx/univ/textctrl.h 3// Purpose: wxTextCtrl class 4// Author: Vadim Zeitlin 5// Modified by: 6// Created: 15.09.00 7// RCS-ID: $Id: textctrl.h 61872 2009-09-09 22:37:05Z VZ $ 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com) 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#ifndef _WX_UNIV_TEXTCTRL_H_ 13#define _WX_UNIV_TEXTCTRL_H_ 14 15class WXDLLEXPORT wxCaret; 16class WXDLLEXPORT wxTextCtrlCommandProcessor; 17 18#include "wx/scrolwin.h" // for wxScrollHelper 19 20#include "wx/univ/inphand.h" 21 22// ---------------------------------------------------------------------------- 23// wxTextCtrl actions 24// ---------------------------------------------------------------------------- 25 26// cursor movement and also selection and delete operations 27#define wxACTION_TEXT_GOTO wxT("goto") // to pos in numArg 28#define wxACTION_TEXT_FIRST wxT("first") // go to pos 0 29#define wxACTION_TEXT_LAST wxT("last") // go to last pos 30#define wxACTION_TEXT_HOME wxT("home") 31#define wxACTION_TEXT_END wxT("end") 32#define wxACTION_TEXT_LEFT wxT("left") 33#define wxACTION_TEXT_RIGHT wxT("right") 34#define wxACTION_TEXT_UP wxT("up") 35#define wxACTION_TEXT_DOWN wxT("down") 36#define wxACTION_TEXT_WORD_LEFT wxT("wordleft") 37#define wxACTION_TEXT_WORD_RIGHT wxT("wordright") 38#define wxACTION_TEXT_PAGE_UP wxT("pageup") 39#define wxACTION_TEXT_PAGE_DOWN wxT("pagedown") 40 41// clipboard operations 42#define wxACTION_TEXT_COPY wxT("copy") 43#define wxACTION_TEXT_CUT wxT("cut") 44#define wxACTION_TEXT_PASTE wxT("paste") 45 46// insert text at the cursor position: the text is in strArg of PerformAction 47#define wxACTION_TEXT_INSERT wxT("insert") 48 49// if the action starts with either of these prefixes and the rest of the 50// string is one of the movement commands, it means to select/delete text from 51// the current cursor position to the new one 52#define wxACTION_TEXT_PREFIX_SEL wxT("sel") 53#define wxACTION_TEXT_PREFIX_DEL wxT("del") 54 55// mouse selection 56#define wxACTION_TEXT_ANCHOR_SEL wxT("anchorsel") 57#define wxACTION_TEXT_EXTEND_SEL wxT("extendsel") 58#define wxACTION_TEXT_SEL_WORD wxT("wordsel") 59#define wxACTION_TEXT_SEL_LINE wxT("linesel") 60 61// undo or redo 62#define wxACTION_TEXT_UNDO wxT("undo") 63#define wxACTION_TEXT_REDO wxT("redo") 64 65// ---------------------------------------------------------------------------- 66// wxTextCtrl 67// ---------------------------------------------------------------------------- 68 69class WXDLLEXPORT wxTextCtrl : public wxTextCtrlBase, 70 public wxScrollHelper 71{ 72public: 73 // creation 74 // -------- 75 76 wxTextCtrl() : wxScrollHelper(this) { Init(); } 77 78 wxTextCtrl(wxWindow *parent, 79 wxWindowID id, 80 const wxString& value = wxEmptyString, 81 const wxPoint& pos = wxDefaultPosition, 82 const wxSize& size = wxDefaultSize, 83 long style = 0, 84 const wxValidator& validator = wxDefaultValidator, 85 const wxString& name = wxTextCtrlNameStr) 86 : wxScrollHelper(this) 87 { 88 Init(); 89 90 Create(parent, id, value, pos, size, style, validator, name); 91 } 92 93 bool Create(wxWindow *parent, 94 wxWindowID id, 95 const wxString& value = wxEmptyString, 96 const wxPoint& pos = wxDefaultPosition, 97 const wxSize& size = wxDefaultSize, 98 long style = 0, 99 const wxValidator& validator = wxDefaultValidator, 100 const wxString& name = wxTextCtrlNameStr); 101 102 virtual ~wxTextCtrl(); 103 104 // implement base class pure virtuals 105 // ---------------------------------- 106 107 virtual wxString GetValue() const; 108 109 virtual int GetLineLength(wxTextCoord lineNo) const; 110 virtual wxString GetLineText(wxTextCoord lineNo) const; 111 virtual int GetNumberOfLines() const; 112 113 virtual bool IsModified() const; 114 virtual bool IsEditable() const; 115 116 // If the return values from and to are the same, there is no selection. 117 virtual void GetSelection(wxTextPos* from, wxTextPos* to) const; 118 119 // operations 120 // ---------- 121 122 // editing 123 virtual void Clear(); 124 virtual void Replace(wxTextPos from, wxTextPos to, const wxString& value); 125 virtual void Remove(wxTextPos from, wxTextPos to); 126 127 // sets/clears the dirty flag 128 virtual void MarkDirty(); 129 virtual void DiscardEdits(); 130 131 // writing text inserts it at the current position, appending always 132 // inserts it at the end 133 virtual void WriteText(const wxString& text); 134 virtual void AppendText(const wxString& text); 135 136 // translate between the position (which is just an index in the text ctrl 137 // considering all its contents as a single strings) and (x, y) coordinates 138 // which represent (logical, i.e. unwrapped) column and line. 139 virtual wxTextPos XYToPosition(wxTextCoord x, wxTextCoord y) const; 140 virtual bool PositionToXY(wxTextPos pos, 141 wxTextCoord *x, wxTextCoord *y) const; 142 143 // wxUniv-specific: find a screen position (in client coordinates) of the 144 // given text position or of the caret 145 bool PositionToLogicalXY(wxTextPos pos, wxCoord *x, wxCoord *y) const; 146 bool PositionToDeviceXY(wxTextPos pos, wxCoord *x, wxCoord *y) const; 147 wxPoint GetCaretPosition() const; 148 149 virtual void ShowPosition(wxTextPos pos); 150 151 // Clipboard operations 152 virtual void Copy(); 153 virtual void Cut(); 154 virtual void Paste(); 155 156 // Undo/redo 157 virtual void Undo(); 158 virtual void Redo(); 159 160 virtual bool CanUndo() const; 161 virtual bool CanRedo() const; 162 163 // Insertion point 164 virtual void SetInsertionPoint(wxTextPos pos); 165 virtual void SetInsertionPointEnd(); 166 virtual wxTextPos GetInsertionPoint() const; 167 virtual wxTextPos GetLastPosition() const; 168 169 virtual void SetSelection(wxTextPos from, wxTextPos to); 170 virtual void SetEditable(bool editable); 171 172 // wxUniv-specific methods 173 // ----------------------- 174 175 // caret stuff 176 virtual void ShowCaret(bool show = true); 177 void HideCaret() { ShowCaret(false); } 178 void CreateCaret(); // for the current font size 179 180 // helpers for cursor movement 181 wxTextPos GetWordStart() const; 182 wxTextPos GetWordEnd() const; 183 184 // selection helpers 185 bool HasSelection() const 186 { return m_selStart != -1 && m_selEnd > m_selStart; } 187 void ClearSelection(); 188 void RemoveSelection(); 189 wxString GetSelectionText() const; 190 191 virtual wxTextCtrlHitTestResult HitTest(const wxPoint& pt, long *pos) const; 192 virtual wxTextCtrlHitTestResult HitTest(const wxPoint& pt, 193 wxTextCoord *col, 194 wxTextCoord *row) const; 195 196 // find the character at this position in the given line, return value as 197 // for HitTest() 198 // 199 // NB: x is the logical coord (client and unscrolled) 200 wxTextCtrlHitTestResult HitTestLine(const wxString& line, 201 wxCoord x, 202 wxTextCoord *colOut) const; 203 204 // bring the given position into view 205 void ShowHorzPosition(wxCoord pos); 206 207 // scroll the window horizontally so that the first character shown is in 208 // position pos 209 void ScrollText(wxTextCoord col); 210 211 // adjust the DC for horz text control scrolling too 212 virtual void DoPrepareDC(wxDC& dc); 213 214 // implementation only from now on 215 // ------------------------------- 216 217 // override this to take into account our scrollbar-less scrolling 218 virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const; 219 virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const; 220 221 // perform an action 222 virtual bool PerformAction(const wxControlAction& action, 223 long numArg = -1, 224 const wxString& strArg = wxEmptyString); 225 226 static wxInputHandler *GetStdInputHandler(wxInputHandler *handlerDef); 227 virtual wxInputHandler *DoGetStdInputHandler(wxInputHandler *handlerDef) 228 { 229 return GetStdInputHandler(handlerDef); 230 } 231 232 // override these methods to handle the caret 233 virtual bool SetFont(const wxFont &font); 234 virtual bool Enable(bool enable = true); 235 236 // more readable flag testing methods 237 bool IsPassword() const { return HasFlag(wxTE_PASSWORD); } 238 bool WrapLines() const { return m_wrapLines; } 239 240 // only for wxStdTextCtrlInputHandler 241 void RefreshSelection(); 242 243 // override wxScrollHelper method to prevent (auto)scrolling beyond the end 244 // of line 245 virtual bool SendAutoScrollEvents(wxScrollWinEvent& event) const; 246 247 // idle processing 248 virtual void OnInternalIdle(); 249 250protected: 251 // ensure we have correct default border 252 virtual wxBorder GetDefaultBorder() const { return wxBORDER_SUNKEN; } 253 254 // override base class methods 255 virtual void DoDrawBorder(wxDC& dc, const wxRect& rect); 256 virtual void DoDraw(wxControlRenderer *renderer); 257 258 // calc the size from the text extent 259 virtual wxSize DoGetBestClientSize() const; 260 261 // implements Set/ChangeValue() 262 virtual void DoSetValue(const wxString& value, int flags = 0); 263 264 // common part of all ctors 265 void Init(); 266 267 // drawing 268 // ------- 269 270 // draw the text in the given rectangle 271 void DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate); 272 273 // draw the line wrap marks in this rect 274 void DoDrawLineWrapMarks(wxDC& dc, const wxRect& rectUpdate); 275 276 // line/row geometry calculations 277 // ------------------------------ 278 279 // get the extent (width) of the text 280 wxCoord GetTextWidth(const wxString& text) const; 281 282 // get the logical text width (accounting for scrolling) 283 wxCoord GetTotalWidth() const; 284 285 // get total number of rows (different from number of lines if the lines 286 // can be wrapped) 287 wxTextCoord GetRowCount() const; 288 289 // find the number of rows in this line (only if WrapLines()) 290 wxTextCoord GetRowsPerLine(wxTextCoord line) const; 291 292 // get the starting row of the given line 293 wxTextCoord GetFirstRowOfLine(wxTextCoord line) const; 294 295 // get the row following this line 296 wxTextCoord GetRowAfterLine(wxTextCoord line) const; 297 298 // refresh functions 299 // ----------------- 300 301 // the text area is the part of the window in which the text can be 302 // displayed, i.e. part of it inside the margins and the real text area is 303 // the area in which the text *is* currently displayed: for example, in the 304 // multiline control case the text area can have extra space at the bottom 305 // which is not tall enough for another line and which is then not included 306 // into the real text area 307 wxRect GetRealTextArea() const; 308 309 // refresh the text in the given (in logical coords) rect 310 void RefreshTextRect(const wxRect& rect, bool textOnly = true); 311 312 // refresh the line wrap marks for the given range of lines (inclusive) 313 void RefreshLineWrapMarks(wxTextCoord rowFirst, wxTextCoord rowLast); 314 315 // refresh the text in the given range (in logical coords) of this line, if 316 // width is 0, refresh to the end of line 317 void RefreshPixelRange(wxTextCoord line, wxCoord start, wxCoord width); 318 319 // refresh the text in the given range (in text coords) in this line 320 void RefreshColRange(wxTextCoord line, wxTextPos start, size_t count); 321 322 // refresh the text from in the given line range (inclusive) 323 void RefreshLineRange(wxTextCoord lineFirst, wxTextCoord lineLast); 324 325 // refresh the text in the given range which can span multiple lines 326 // (this method accepts arguments in any order) 327 void RefreshTextRange(wxTextPos start, wxTextPos end); 328 329 // get the text to show: either the text itself or the text replaced with 330 // starts for wxTE_PASSWORD control 331 wxString GetTextToShow(const wxString& text) const; 332 333 // find the row in this line where the given position (counted from the 334 // start of line) is 335 wxTextCoord GetRowInLine(wxTextCoord line, 336 wxTextCoord col, 337 wxTextCoord *colRowStart = NULL) const; 338 339 // find the number of characters of a line before it wraps 340 // (and optionally also the real width of the line) 341 size_t GetPartOfWrappedLine(const wxChar* text, 342 wxCoord *widthReal = NULL) const; 343 344 // get the start and end of the selection for this line: if the line is 345 // outside the selection, both will be -1 and false will be returned 346 bool GetSelectedPartOfLine(wxTextCoord line, 347 wxTextPos *start, wxTextPos *end) const; 348 349 // update the text rect: the zone inside our client rect (its coords are 350 // client coords) which contains the text 351 void UpdateTextRect(); 352 353 // calculate the last visible position 354 void UpdateLastVisible(); 355 356 // move caret to the given position unconditionally 357 // (SetInsertionPoint() does nothing if the position didn't change) 358 void DoSetInsertionPoint(wxTextPos pos); 359 360 // move caret to the new position without updating the display (for 361 // internal use only) 362 void MoveInsertionPoint(wxTextPos pos); 363 364 // set the caret to its initial (default) position 365 void InitInsertionPoint(); 366 367 // get the width of the longest line in pixels 368 wxCoord GetMaxWidth() const; 369 370 // force recalculation of the max line width 371 void RecalcMaxWidth(); 372 373 // update the max width after the given line was modified 374 void UpdateMaxWidth(wxTextCoord line); 375 376 // hit testing 377 // ----------- 378 379 // HitTest2() is more efficient than 2 consecutive HitTest()s with the same 380 // line (i.e. y) and it also returns the offset of the starting position in 381 // pixels 382 // 383 // as the last hack, this function accepts either logical or device (by 384 // default) coords depending on devCoords flag 385 wxTextCtrlHitTestResult HitTest2(wxCoord y, 386 wxCoord x1, 387 wxCoord x2, 388 wxTextCoord *row, 389 wxTextCoord *colStart, 390 wxTextCoord *colEnd, 391 wxTextCoord *colRowStart, 392 bool devCoords = true) const; 393 394 // HitTest() version which takes the logical text coordinates and not the 395 // device ones 396 wxTextCtrlHitTestResult HitTestLogical(const wxPoint& pos, 397 wxTextCoord *col, 398 wxTextCoord *row) const; 399 400 // get the line and the row in this line corresponding to the given row, 401 // return true if ok and false if row is out of range 402 // 403 // NB: this function can only be called for controls which wrap lines 404 bool GetLineAndRow(wxTextCoord row, 405 wxTextCoord *line, 406 wxTextCoord *rowInLine) const; 407 408 // get the height of one line (the same for all lines) 409 wxCoord GetLineHeight() const 410 { 411 // this one should be already precalculated 412 wxASSERT_MSG( m_heightLine != -1, wxT("should have line height") ); 413 414 return m_heightLine; 415 } 416 417 // get the average char width 418 wxCoord GetAverageWidth() const { return m_widthAvg; } 419 420 // recalc the line height and char width (to call when the font changes) 421 void RecalcFontMetrics(); 422 423 // vertical scrolling helpers 424 // -------------------------- 425 426 // all these functions are for multi line controls only 427 428 // get the number of visible lines 429 size_t GetLinesPerPage() const; 430 431 // return the position above the cursor or INVALID_POS_VALUE 432 wxTextPos GetPositionAbove(); 433 434 // return the position below the cursor or INVALID_POS_VALUE 435 wxTextPos GetPositionBelow(); 436 437 // event handlers 438 // -------------- 439 void OnChar(wxKeyEvent& event); 440 void OnSize(wxSizeEvent& event); 441 442 // return the struct containing control-type dependent data 443 struct wxTextSingleLineData& SData() { return *m_data.sdata; } 444 struct wxTextMultiLineData& MData() { return *m_data.mdata; } 445 struct wxTextWrappedData& WData() { return *m_data.wdata; } 446 const wxTextSingleLineData& SData() const { return *m_data.sdata; } 447 const wxTextMultiLineData& MData() const { return *m_data.mdata; } 448 const wxTextWrappedData& WData() const { return *m_data.wdata; } 449 450 // clipboard operations (unlike the versions without Do prefix, they have a 451 // return code) 452 bool DoCut(); 453 bool DoPaste(); 454 455private: 456 // all these methods are for multiline text controls only 457 458 // update the scrollbars (only called from OnIdle) 459 void UpdateScrollbars(); 460 461 // get read only access to the lines of multiline control 462 inline const wxArrayString& GetLines() const; 463 inline size_t GetLineCount() const; 464 465 // replace a line (returns true if the number of rows in thel ine changed) 466 bool ReplaceLine(wxTextCoord line, const wxString& text); 467 468 // remove a line 469 void RemoveLine(wxTextCoord line); 470 471 // insert a line at this position 472 void InsertLine(wxTextCoord line, const wxString& text); 473 474 // calculate geometry of this line 475 void LayoutLine(wxTextCoord line, class wxWrappedLineData& lineData) const; 476 477 // calculate geometry of all lines until the given one 478 void LayoutLines(wxTextCoord lineLast) const; 479 480 // the initially specified control size 481 wxSize m_sizeInitial; 482 483 // the global control text 484 wxString m_value; 485 486 // current position 487 wxTextPos m_curPos; 488 wxTextCoord m_curCol, 489 m_curRow; 490 491 // last position (only used by GetLastPosition()) 492 wxTextPos m_posLast; 493 494 // selection 495 wxTextPos m_selAnchor, 496 m_selStart, 497 m_selEnd; 498 499 // flags 500 bool m_isModified:1, 501 m_isEditable:1, 502 m_hasCaret:1, 503 m_wrapLines:1; // can't be changed after creation 504 505 // the rectangle (in client coordinates) to draw text inside 506 wxRect m_rectText; 507 508 // the height of one line (cached value of GetCharHeight) 509 wxCoord m_heightLine; 510 511 // and the average char width (cached value of GetCharWidth) 512 wxCoord m_widthAvg; 513 514 // we have some data which depends on the kind of control (single or multi 515 // line) 516 union 517 { 518 wxTextSingleLineData *sdata; 519 wxTextMultiLineData *mdata; 520 wxTextWrappedData *wdata; 521 void *data; 522 } m_data; 523 524 // the object to which we delegate our undo/redo implementation 525 wxTextCtrlCommandProcessor *m_cmdProcessor; 526 527 DECLARE_EVENT_TABLE() 528 DECLARE_DYNAMIC_CLASS(wxTextCtrl) 529 530 friend class wxWrappedLineData; 531}; 532 533#endif // _WX_UNIV_TEXTCTRL_H_ 534 535