PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Externals/wxWidgets3/src/common/textentrycmn.cpp

https://gitlab.com/Hexexpeck/dolphin-emulator
C++ | 472 lines | 272 code | 96 blank | 104 comment | 28 complexity | 5f955959f31397f43d9dc20520502d80 MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: src/common/textentrycmn.cpp
  3. // Purpose: wxTextEntryBase implementation
  4. // Author: Vadim Zeitlin
  5. // Created: 2007-09-26
  6. // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
  7. // Licence: wxWindows licence
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // ============================================================================
  10. // declarations
  11. // ============================================================================
  12. // ----------------------------------------------------------------------------
  13. // headers
  14. // ----------------------------------------------------------------------------
  15. // for compilers that support precompilation, includes "wx.h".
  16. #include "wx/wxprec.h"
  17. #ifdef __BORLANDC__
  18. #pragma hdrstop
  19. #endif
  20. #if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
  21. #ifndef WX_PRECOMP
  22. #include "wx/window.h"
  23. #include "wx/dataobj.h"
  24. #endif //WX_PRECOMP
  25. #include "wx/textentry.h"
  26. #include "wx/textcompleter.h"
  27. #include "wx/clipbrd.h"
  28. // ----------------------------------------------------------------------------
  29. // wxTextEntryHintData
  30. // ----------------------------------------------------------------------------
  31. class WXDLLIMPEXP_CORE wxTextEntryHintData
  32. {
  33. public:
  34. wxTextEntryHintData(wxTextEntryBase *entry, wxWindow *win)
  35. : m_entry(entry),
  36. m_win(win),
  37. m_text(m_entry->GetValue())
  38. {
  39. win->Bind(wxEVT_SET_FOCUS, &wxTextEntryHintData::OnSetFocus, this);
  40. win->Bind(wxEVT_KILL_FOCUS, &wxTextEntryHintData::OnKillFocus, this);
  41. win->Bind(wxEVT_TEXT, &wxTextEntryHintData::OnTextChanged, this);
  42. }
  43. // default dtor is ok
  44. // Get the real text of the control such as it was before we replaced it
  45. // with the hint.
  46. const wxString& GetText() const { return m_text; }
  47. // Set the hint to show, shouldn't be empty normally.
  48. //
  49. // This should be called after creating a new wxTextEntryHintData object
  50. // and may be called more times in the future.
  51. void SetHintString(const wxString& hint)
  52. {
  53. m_hint = hint;
  54. if ( !m_win->HasFocus() )
  55. ShowHintIfAppropriate();
  56. //else: The new hint will be shown later when we lose focus.
  57. }
  58. const wxString& GetHintString() const { return m_hint; }
  59. // This is called whenever the text control contents changes.
  60. //
  61. // We call it ourselves when this change generates an event but it's also
  62. // necessary to call it explicitly from wxTextEntry::ChangeValue() as it,
  63. // by design, does not generate any events.
  64. void HandleTextUpdate(const wxString& text)
  65. {
  66. m_text = text;
  67. // If we're called because of a call to Set or ChangeValue(), the
  68. // control may still have the hint text colour, reset it in this case.
  69. RestoreTextColourIfNecessary();
  70. }
  71. private:
  72. // Show the hint in the window if we should do it, i.e. if the window
  73. // doesn't have any text of its own.
  74. void ShowHintIfAppropriate()
  75. {
  76. // Never overwrite existing window text.
  77. if ( !m_text.empty() )
  78. return;
  79. // Save the old text colour and set a more inconspicuous one for the
  80. // hint.
  81. m_colFg = m_win->GetForegroundColour();
  82. m_win->SetForegroundColour(*wxLIGHT_GREY);
  83. m_entry->DoSetValue(m_hint, wxTextEntryBase::SetValue_NoEvent);
  84. }
  85. // Restore the original text colour if we had changed it to show the hint
  86. // and not restored it yet.
  87. void RestoreTextColourIfNecessary()
  88. {
  89. if ( m_colFg.IsOk() )
  90. {
  91. m_win->SetForegroundColour(m_colFg);
  92. m_colFg = wxColour();
  93. }
  94. }
  95. void OnSetFocus(wxFocusEvent& event)
  96. {
  97. // If we had been showing the hint before, remove it now and restore
  98. // the normal colour.
  99. if ( m_text.empty() )
  100. {
  101. RestoreTextColourIfNecessary();
  102. m_entry->DoSetValue(wxString(), wxTextEntryBase::SetValue_NoEvent);
  103. }
  104. event.Skip();
  105. }
  106. void OnKillFocus(wxFocusEvent& event)
  107. {
  108. // Restore the hint if the user didn't enter anything.
  109. ShowHintIfAppropriate();
  110. event.Skip();
  111. }
  112. void OnTextChanged(wxCommandEvent& event)
  113. {
  114. // Update the stored window text.
  115. //
  116. // Notice that we can't use GetValue() nor wxCommandEvent::GetString()
  117. // which uses it internally because this would just forward back to us
  118. // so go directly to the private method which returns the real control
  119. // contents.
  120. HandleTextUpdate(m_entry->DoGetValue());
  121. event.Skip();
  122. }
  123. // the text control we're associated with (as its interface and its window)
  124. wxTextEntryBase * const m_entry;
  125. wxWindow * const m_win;
  126. // the original foreground colour of m_win before we changed it
  127. wxColour m_colFg;
  128. // The hint passed to wxTextEntry::SetHint(), never empty.
  129. wxString m_hint;
  130. // The real text of the window.
  131. wxString m_text;
  132. wxDECLARE_NO_COPY_CLASS(wxTextEntryHintData);
  133. };
  134. // ============================================================================
  135. // wxTextEntryBase implementation
  136. // ============================================================================
  137. wxTextEntryBase::~wxTextEntryBase()
  138. {
  139. delete m_hintData;
  140. }
  141. // ----------------------------------------------------------------------------
  142. // text accessors
  143. // ----------------------------------------------------------------------------
  144. wxString wxTextEntryBase::GetValue() const
  145. {
  146. return m_hintData ? m_hintData->GetText() : DoGetValue();
  147. }
  148. wxString wxTextEntryBase::GetRange(long from, long to) const
  149. {
  150. wxString sel;
  151. wxString value = GetValue();
  152. if ( from < to && (long)value.length() >= to )
  153. {
  154. sel = value.substr(from, to - from);
  155. }
  156. return sel;
  157. }
  158. // ----------------------------------------------------------------------------
  159. // text operations
  160. // ----------------------------------------------------------------------------
  161. void wxTextEntryBase::ChangeValue(const wxString& value)
  162. {
  163. DoSetValue(value, SetValue_NoEvent);
  164. // As we didn't generate any events for wxTextEntryHintData to catch,
  165. // notify it explicitly about our changed contents.
  166. if ( m_hintData )
  167. m_hintData->HandleTextUpdate(value);
  168. }
  169. void wxTextEntryBase::AppendText(const wxString& text)
  170. {
  171. SetInsertionPointEnd();
  172. WriteText(text);
  173. }
  174. void wxTextEntryBase::DoSetValue(const wxString& value, int flags)
  175. {
  176. if ( value != DoGetValue() )
  177. {
  178. EventsSuppressor noeventsIf(this, !(flags & SetValue_SendEvent));
  179. SelectAll();
  180. WriteText(value);
  181. SetInsertionPoint(0);
  182. }
  183. else // Same value, no need to do anything.
  184. {
  185. // Except that we still need to generate the event for consistency with
  186. // the normal case when the text does change.
  187. if ( flags & SetValue_SendEvent )
  188. SendTextUpdatedEvent(GetEditableWindow());
  189. }
  190. }
  191. void wxTextEntryBase::Replace(long from, long to, const wxString& value)
  192. {
  193. {
  194. EventsSuppressor noevents(this);
  195. Remove(from, to);
  196. }
  197. SetInsertionPoint(from);
  198. WriteText(value);
  199. }
  200. // ----------------------------------------------------------------------------
  201. // selection
  202. // ----------------------------------------------------------------------------
  203. bool wxTextEntryBase::HasSelection() const
  204. {
  205. long from, to;
  206. GetSelection(&from, &to);
  207. return from < to;
  208. }
  209. void wxTextEntryBase::RemoveSelection()
  210. {
  211. long from, to;
  212. GetSelection(& from, & to);
  213. if (from != -1 && to != -1)
  214. Remove(from, to);
  215. }
  216. wxString wxTextEntryBase::GetStringSelection() const
  217. {
  218. long from, to;
  219. GetSelection(&from, &to);
  220. return GetRange(from, to);
  221. }
  222. // ----------------------------------------------------------------------------
  223. // clipboard
  224. // ----------------------------------------------------------------------------
  225. bool wxTextEntryBase::CanCopy() const
  226. {
  227. return HasSelection();
  228. }
  229. bool wxTextEntryBase::CanCut() const
  230. {
  231. return CanCopy() && IsEditable();
  232. }
  233. bool wxTextEntryBase::CanPaste() const
  234. {
  235. if ( IsEditable() )
  236. {
  237. #if wxUSE_CLIPBOARD
  238. // check if there is any text on the clipboard
  239. if ( wxTheClipboard->IsSupported(wxDF_TEXT)
  240. #if wxUSE_UNICODE
  241. || wxTheClipboard->IsSupported(wxDF_UNICODETEXT)
  242. #endif // wxUSE_UNICODE
  243. )
  244. {
  245. return true;
  246. }
  247. #endif // wxUSE_CLIPBOARD
  248. }
  249. return false;
  250. }
  251. // ----------------------------------------------------------------------------
  252. // input restrictions
  253. // ----------------------------------------------------------------------------
  254. #ifndef wxHAS_NATIVE_TEXT_FORCEUPPER
  255. namespace
  256. {
  257. // Poor man's lambda: helper for binding ConvertToUpperCase() to the event
  258. struct ForceUpperFunctor
  259. {
  260. explicit ForceUpperFunctor(wxTextEntryBase* entry)
  261. : m_entry(entry)
  262. {
  263. }
  264. void operator()(wxCommandEvent& event)
  265. {
  266. event.Skip();
  267. m_entry->ConvertToUpperCase();
  268. }
  269. wxTextEntryBase* const m_entry;
  270. };
  271. } // anonymous namespace
  272. #endif // !wxHAS_NATIVE_TEXT_FORCEUPPER
  273. void wxTextEntryBase::ConvertToUpperCase()
  274. {
  275. const wxString& valueOld = GetValue();
  276. const wxString& valueNew = valueOld.Upper();
  277. if ( valueNew != valueOld )
  278. {
  279. long from, to;
  280. GetSelection(&from, &to);
  281. ChangeValue(valueNew);
  282. SetSelection(from, to);
  283. }
  284. }
  285. void wxTextEntryBase::ForceUpper()
  286. {
  287. // Do nothing if this method is never called because a native override is
  288. // provided: this is just a tiny size-saving optimization, nothing else.
  289. #ifndef wxHAS_NATIVE_TEXT_FORCEUPPER
  290. wxWindow* const win = GetEditableWindow();
  291. wxCHECK_RET( win, wxS("can't be called before creating the window") );
  292. // Convert the current control contents to upper case
  293. ConvertToUpperCase();
  294. // And ensure that any text entered in the future is converted too
  295. win->Bind(wxEVT_TEXT, ForceUpperFunctor(this));
  296. #endif // !wxHAS_NATIVE_TEXT_FORCEUPPER
  297. }
  298. // ----------------------------------------------------------------------------
  299. // hints support
  300. // ----------------------------------------------------------------------------
  301. bool wxTextEntryBase::SetHint(const wxString& hint)
  302. {
  303. if ( !hint.empty() )
  304. {
  305. if ( !m_hintData )
  306. m_hintData = new wxTextEntryHintData(this, GetEditableWindow());
  307. m_hintData->SetHintString(hint);
  308. }
  309. else if ( m_hintData )
  310. {
  311. // Setting empty hint removes any currently set one.
  312. delete m_hintData;
  313. m_hintData = NULL;
  314. }
  315. //else: Setting empty hint when we don't have any doesn't do anything.
  316. return true;
  317. }
  318. wxString wxTextEntryBase::GetHint() const
  319. {
  320. return m_hintData ? m_hintData->GetHintString() : wxString();
  321. }
  322. // ----------------------------------------------------------------------------
  323. // margins support
  324. // ----------------------------------------------------------------------------
  325. bool wxTextEntryBase::DoSetMargins(const wxPoint& WXUNUSED(pt))
  326. {
  327. return false;
  328. }
  329. wxPoint wxTextEntryBase::DoGetMargins() const
  330. {
  331. return wxPoint(-1, -1);
  332. }
  333. // ----------------------------------------------------------------------------
  334. // events
  335. // ----------------------------------------------------------------------------
  336. /* static */
  337. bool wxTextEntryBase::SendTextUpdatedEvent(wxWindow *win)
  338. {
  339. wxCHECK_MSG( win, false, "can't send an event without a window" );
  340. wxCommandEvent event(wxEVT_TEXT, win->GetId());
  341. // do not do this as it could be very inefficient if the text control
  342. // contains a lot of text and we're not using ref-counted wxString
  343. // implementation -- instead, event.GetString() will query the control for
  344. // its current text if needed
  345. //event.SetString(win->GetValue());
  346. event.SetEventObject(win);
  347. return win->HandleWindowEvent(event);
  348. }
  349. // ----------------------------------------------------------------------------
  350. // auto-completion stubs
  351. // ----------------------------------------------------------------------------
  352. wxTextCompleter::~wxTextCompleter()
  353. {
  354. }
  355. bool wxTextCompleterSimple::Start(const wxString& prefix)
  356. {
  357. m_index = 0;
  358. m_completions.clear();
  359. GetCompletions(prefix, m_completions);
  360. return !m_completions.empty();
  361. }
  362. wxString wxTextCompleterSimple::GetNext()
  363. {
  364. if ( m_index == m_completions.size() )
  365. return wxString();
  366. return m_completions[m_index++];
  367. }
  368. bool wxTextEntryBase::DoAutoCompleteCustom(wxTextCompleter *completer)
  369. {
  370. // We don't do anything here but we still need to delete the completer for
  371. // consistency with the ports that do implement this method and take
  372. // ownership of the pointer.
  373. delete completer;
  374. return false;
  375. }
  376. #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX