PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Externals/wxWidgets3/src/osx/cocoa/combobox.mm

https://gitlab.com/Hexexpeck/dolphin-emulator
Objective C++ | 332 lines | 251 code | 55 blank | 26 comment | 32 complexity | c8e08d7147706b4a825b6590db737ae1 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: src/osx/cocoa/combobox.mm
  3. // Purpose: wxChoice
  4. // Author: Stefan Csomor
  5. // Modified by:
  6. // Created: 1998-01-01
  7. // Copyright: (c) Stefan Csomor
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include "wx/wxprec.h"
  11. #if wxUSE_COMBOBOX
  12. #include "wx/combobox.h"
  13. #include "wx/evtloop.h"
  14. #ifndef WX_PRECOMP
  15. #include "wx/menu.h"
  16. #include "wx/dcclient.h"
  17. #endif
  18. #include "wx/osx/cocoa/private/textimpl.h"
  19. // work in progress
  20. @interface wxNSTableDataSource : NSObject <NSComboBoxDataSource>
  21. {
  22. wxNSComboBoxControl* impl;
  23. }
  24. - (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox;
  25. - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index;
  26. @end
  27. @implementation wxNSComboBox
  28. + (void)initialize
  29. {
  30. static BOOL initialized = NO;
  31. if (!initialized)
  32. {
  33. initialized = YES;
  34. wxOSXCocoaClassAddWXMethods( self );
  35. }
  36. }
  37. - (void) dealloc
  38. {
  39. [fieldEditor release];
  40. [super dealloc];
  41. }
  42. // Over-riding NSComboBox onKeyDown method doesn't work for key events.
  43. // Ensure that we can use our own wxNSTextFieldEditor to catch key events.
  44. // See windowWillReturnFieldEditor in nonownedwnd.mm.
  45. // Key events will be caught and handled via wxNSTextFieldEditor onkey...
  46. // methods in textctrl.mm.
  47. - (void) setFieldEditor:(wxNSTextFieldEditor*) editor
  48. {
  49. if ( editor != fieldEditor )
  50. {
  51. [editor retain];
  52. [fieldEditor release];
  53. fieldEditor = editor;
  54. }
  55. }
  56. - (wxNSTextFieldEditor*) fieldEditor
  57. {
  58. return fieldEditor;
  59. }
  60. - (void)controlTextDidChange:(NSNotification *)aNotification
  61. {
  62. wxUnusedVar(aNotification);
  63. wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
  64. if ( impl && impl->ShouldSendEvents() )
  65. {
  66. wxWindow* wxpeer = (wxWindow*) impl->GetWXPeer();
  67. if ( wxpeer ) {
  68. wxCommandEvent event(wxEVT_TEXT, wxpeer->GetId());
  69. event.SetEventObject( wxpeer );
  70. event.SetString( static_cast<wxComboBox*>(wxpeer)->GetValue() );
  71. wxpeer->HandleWindowEvent( event );
  72. }
  73. }
  74. }
  75. - (void)controlTextDidEndEditing:(NSNotification *) aNotification
  76. {
  77. wxUnusedVar(aNotification);
  78. wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
  79. if ( impl )
  80. {
  81. wxNSTextFieldControl* timpl = dynamic_cast<wxNSTextFieldControl*>(impl);
  82. if ( timpl )
  83. timpl->UpdateInternalSelectionFromEditor(fieldEditor);
  84. impl->DoNotifyFocusLost();
  85. }
  86. }
  87. - (void)comboBoxWillPopUp:(NSNotification *)notification
  88. {
  89. wxUnusedVar(notification);
  90. wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
  91. if( impl && impl->ShouldSendEvents() )
  92. {
  93. wxComboBox* wxpeer = static_cast<wxComboBox*>(impl->GetWXPeer());
  94. if( wxpeer )
  95. {
  96. wxCommandEvent event(wxEVT_COMBOBOX_DROPDOWN, wxpeer->GetId());
  97. event.SetEventObject( wxpeer );
  98. wxpeer->GetEventHandler()->ProcessEvent( event );
  99. }
  100. }
  101. }
  102. - (void)comboBoxWillDismiss:(NSNotification *)notification
  103. {
  104. wxUnusedVar(notification);
  105. wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
  106. if( impl && impl->ShouldSendEvents() )
  107. {
  108. wxComboBox* wxpeer = static_cast<wxComboBox*>(impl->GetWXPeer());
  109. if( wxpeer )
  110. {
  111. wxCommandEvent event(wxEVT_COMBOBOX_CLOSEUP, wxpeer->GetId());
  112. event.SetEventObject( wxpeer );
  113. wxpeer->GetEventHandler()->ProcessEvent( event );
  114. }
  115. }
  116. }
  117. - (void)comboBoxSelectionDidChange:(NSNotification *)notification
  118. {
  119. wxUnusedVar(notification);
  120. wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
  121. if ( impl && impl->ShouldSendEvents())
  122. {
  123. wxComboBox* wxpeer = static_cast<wxComboBox*>(impl->GetWXPeer());
  124. if ( wxpeer ) {
  125. const int sel = wxpeer->GetSelection();
  126. wxCommandEvent event(wxEVT_COMBOBOX, wxpeer->GetId());
  127. event.SetEventObject( wxpeer );
  128. event.SetInt( sel );
  129. event.SetString( wxpeer->GetString(sel) );
  130. // For some reason, wxComboBox::GetValue will not return the newly selected item
  131. // while we're inside this callback, so use AddPendingEvent to make sure
  132. // GetValue() returns the right value.
  133. wxpeer->GetEventHandler()->AddPendingEvent( event );
  134. }
  135. }
  136. }
  137. @end
  138. wxNSComboBoxControl::wxNSComboBoxControl( wxComboBox *wxPeer, WXWidget w )
  139. : wxNSTextFieldControl(wxPeer, wxPeer, w)
  140. {
  141. m_comboBox = (NSComboBox*)w;
  142. }
  143. wxNSComboBoxControl::~wxNSComboBoxControl()
  144. {
  145. }
  146. void wxNSComboBoxControl::mouseEvent(WX_NSEvent event, WXWidget slf, void *_cmd)
  147. {
  148. // NSComboBox has its own event loop, which reacts very badly to our synthetic
  149. // events used to signal when a wxEvent is posted, so during that time we switch
  150. // the wxEventLoop::WakeUp implementation to a lower-level version
  151. bool reset = false;
  152. wxEventLoop* const loop = (wxEventLoop*) wxEventLoopBase::GetActive();
  153. if ( loop != NULL && [event type] == NSLeftMouseDown )
  154. {
  155. reset = true;
  156. loop->OSXUseLowLevelWakeup(true);
  157. }
  158. wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:(SEL)_cmd];
  159. superimpl(slf, (SEL)_cmd, event);
  160. if ( reset )
  161. {
  162. loop->OSXUseLowLevelWakeup(false);
  163. }
  164. }
  165. int wxNSComboBoxControl::GetSelectedItem() const
  166. {
  167. return [m_comboBox indexOfSelectedItem];
  168. }
  169. void wxNSComboBoxControl::SetSelectedItem(int item)
  170. {
  171. SendEvents(false);
  172. if ( item != wxNOT_FOUND )
  173. {
  174. wxASSERT_MSG( item >= 0 && item < [m_comboBox numberOfItems],
  175. "Inavlid item index." );
  176. [m_comboBox selectItemAtIndex: item];
  177. }
  178. else // remove current selection (if we have any)
  179. {
  180. const int sel = GetSelectedItem();
  181. if ( sel != wxNOT_FOUND )
  182. [m_comboBox deselectItemAtIndex:sel];
  183. }
  184. SendEvents(true);
  185. }
  186. int wxNSComboBoxControl::GetNumberOfItems() const
  187. {
  188. return [m_comboBox numberOfItems];
  189. }
  190. void wxNSComboBoxControl::InsertItem(int pos, const wxString& item)
  191. {
  192. [m_comboBox insertItemWithObjectValue:wxCFStringRef( item , m_wxPeer->GetFont().GetEncoding() ).AsNSString() atIndex:pos];
  193. }
  194. void wxNSComboBoxControl::RemoveItem(int pos)
  195. {
  196. SendEvents(false);
  197. [m_comboBox removeItemAtIndex:pos];
  198. SendEvents(true);
  199. }
  200. void wxNSComboBoxControl::Clear()
  201. {
  202. SendEvents(false);
  203. [m_comboBox removeAllItems];
  204. [m_comboBox setStringValue:@""];
  205. SendEvents(true);
  206. }
  207. wxString wxNSComboBoxControl::GetStringAtIndex(int pos) const
  208. {
  209. return wxCFStringRef::AsString([m_comboBox itemObjectValueAtIndex:pos], m_wxPeer->GetFont().GetEncoding());
  210. }
  211. int wxNSComboBoxControl::FindString(const wxString& text) const
  212. {
  213. NSInteger nsresult = [m_comboBox indexOfItemWithObjectValue:wxCFStringRef( text , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
  214. int result;
  215. if (nsresult == NSNotFound)
  216. result = wxNOT_FOUND;
  217. else
  218. result = (int) nsresult;
  219. return result;
  220. }
  221. void wxNSComboBoxControl::Popup()
  222. {
  223. id ax = NSAccessibilityUnignoredDescendant(m_comboBox);
  224. [ax accessibilitySetValue: [NSNumber numberWithBool: YES] forAttribute: NSAccessibilityExpandedAttribute];
  225. }
  226. void wxNSComboBoxControl::Dismiss()
  227. {
  228. id ax = NSAccessibilityUnignoredDescendant(m_comboBox);
  229. [ax accessibilitySetValue: [NSNumber numberWithBool: NO] forAttribute: NSAccessibilityExpandedAttribute];
  230. }
  231. void wxNSComboBoxControl::SetEditable(bool editable)
  232. {
  233. // TODO: unfortunately this does not work, setEditable just means the same as CB_READONLY
  234. // I don't see a way to access the text field directly
  235. // Behavior NONE <- SELECTECTABLE
  236. [m_comboBox setEditable:editable];
  237. }
  238. wxWidgetImplType* wxWidgetImpl::CreateComboBox( wxComboBox* wxpeer,
  239. wxWindowMac* WXUNUSED(parent),
  240. wxWindowID WXUNUSED(id),
  241. wxMenu* WXUNUSED(menu),
  242. const wxPoint& pos,
  243. const wxSize& size,
  244. long style,
  245. long WXUNUSED(extraStyle))
  246. {
  247. NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
  248. wxNSComboBox* v = [[wxNSComboBox alloc] initWithFrame:r];
  249. [v setNumberOfVisibleItems:13];
  250. if (style & wxCB_READONLY)
  251. [v setEditable:NO];
  252. wxNSComboBoxControl* c = new wxNSComboBoxControl( wxpeer, v );
  253. return c;
  254. }
  255. wxSize wxComboBox::DoGetBestSize() const
  256. {
  257. int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults
  258. wxSize baseSize = wxWindow::DoGetBestSize();
  259. int lbHeight = baseSize.y;
  260. int wLine;
  261. {
  262. wxClientDC dc(const_cast<wxComboBox*>(this));
  263. // Find the widest line
  264. for(unsigned int i = 0; i < GetCount(); i++)
  265. {
  266. wxString str(GetString(i));
  267. wxCoord width, height ;
  268. dc.GetTextExtent( str , &width, &height);
  269. wLine = width ;
  270. lbWidth = wxMax( lbWidth, wLine ) ;
  271. }
  272. // Add room for the popup arrow
  273. lbWidth += 2 * lbHeight ;
  274. }
  275. return wxSize( lbWidth, lbHeight );
  276. }
  277. #endif // wxUSE_COMBOBOX