textctrl.h 19 KB

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