GuiButton.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* GuiButton.cpp
  2. *
  3. * Copyright (C) 1993-2008,2010-2018 Paul Boersma,
  4. * 2007-2008 Stefan de Konink, 2010 Franz Brausse, 2013 Tom Naughton
  5. *
  6. * This code is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This code is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. * See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "GuiP.h"
  20. Thing_implement (GuiButton, GuiControl, 0);
  21. #if gtk
  22. #define iam_button GuiButton me = (GuiButton) userData
  23. #elif motif
  24. #define iam_button GuiButton me = (GuiButton) widget -> userData
  25. #elif cocoa
  26. #define iam_button GuiButton me = (GuiButton) self -> d_userData
  27. #endif
  28. #if gtk
  29. static void _GuiGtkButton_destroyCallback (GuiObject /* widget */, gpointer userData) {
  30. GuiButton me = (GuiButton) userData;
  31. trace (U"destroying GuiButton ", Melder_pointer (me));
  32. forget (me);
  33. }
  34. static void _GuiGtkButton_activateCallback (GuiObject widget, gpointer userData) {
  35. GuiButton me = (GuiButton) userData;
  36. struct structGuiButtonEvent event { me, false, false, false, false };
  37. if (my d_activateCallback) {
  38. try {
  39. my d_activateCallback (my d_activateBoss, & event);
  40. } catch (MelderError) {
  41. Melder_flushError (U"Your click on button \"", Melder_peek8to32 (GTK_WIDGET (widget) -> name), U"\" was not completely handled.");
  42. }
  43. }
  44. }
  45. #elif motif
  46. void _GuiWinButton_destroy (GuiObject widget) {
  47. iam_button;
  48. if (widget == widget -> shell -> defaultButton)
  49. widget -> shell -> defaultButton = nullptr; // remove dangling reference
  50. if (widget == widget -> shell -> cancelButton)
  51. widget -> shell -> cancelButton = nullptr; // remove dangling reference
  52. _GuiNativeControl_destroy (widget);
  53. forget (me); // NOTE: my widget is not destroyed here
  54. }
  55. void _GuiWinButton_handleClick (GuiObject widget) {
  56. iam_button;
  57. if (my d_activateCallback) {
  58. struct structGuiButtonEvent event { me, false, false, false, false };
  59. try {
  60. my d_activateCallback (my d_activateBoss, & event);
  61. } catch (MelderError) {
  62. Melder_flushError (U"Your click on button \"", widget -> name.get(), U"\" was not completely handled.");
  63. }
  64. }
  65. }
  66. bool _GuiWinButton_tryToHandleShortcutKey (GuiObject widget) {
  67. iam_button;
  68. if (my d_activateCallback) {
  69. struct structGuiButtonEvent event { me, false, false, false, false };
  70. try {
  71. my d_activateCallback (my d_activateBoss, & event);
  72. } catch (MelderError) {
  73. Melder_flushError (U"Your key click on button \"", widget -> name.get(), U"\" was not completely handled.");
  74. }
  75. return true;
  76. }
  77. return false;
  78. }
  79. #elif cocoa
  80. @implementation GuiCocoaButton {
  81. GuiButton d_userData;
  82. }
  83. - (void) dealloc { // override
  84. GuiButton me = d_userData;
  85. forget (me);
  86. trace (U"deleting a button");
  87. [super dealloc];
  88. }
  89. - (GuiThing) getUserData {
  90. return d_userData;
  91. }
  92. - (void) setUserData: (GuiThing) userData {
  93. Melder_assert (userData == nullptr || Thing_isa (userData, classGuiButton));
  94. d_userData = static_cast <GuiButton> (userData);
  95. }
  96. - (void) _guiCocoaButton_activateCallback: (id) widget {
  97. Melder_assert (self == widget); // sender (widget) and receiver (self) happen to be the same object
  98. GuiButton me = d_userData;
  99. if (my d_activateCallback) {
  100. struct structGuiButtonEvent event { me, false, false, false, false };
  101. try {
  102. my d_activateCallback (my d_activateBoss, & event);
  103. } catch (MelderError) {
  104. Melder_flushError (U"Your click on button \"", my name.get(), U"\" was not completely handled.");
  105. }
  106. }
  107. }
  108. @end
  109. #endif
  110. GuiButton GuiButton_create (GuiForm parent, int left, int right, int top, int bottom,
  111. conststring32 buttonText, GuiButton_ActivateCallback activateCallback, Thing activateBoss, uint32 flags)
  112. {
  113. autoGuiButton me = Thing_new (GuiButton);
  114. my d_shell = parent -> d_shell;
  115. my d_parent = parent;
  116. my d_activateCallback = activateCallback;
  117. my d_activateBoss = activateBoss;
  118. #if gtk
  119. my d_widget = gtk_button_new_with_label (Melder_peek32to8 (buttonText));
  120. _GuiObject_setUserData (my d_widget, me.get());
  121. my v_positionInForm (my d_widget, left, right, top, bottom, parent);
  122. if (flags & GuiButton_DEFAULT || flags & GuiButton_ATTRACTIVE) {
  123. GTK_WIDGET_SET_FLAGS (my d_widget, GTK_CAN_DEFAULT);
  124. GtkWidget *shell = gtk_widget_get_toplevel (GTK_WIDGET (my d_widget));
  125. Melder_assert (shell);
  126. gtk_window_set_default (GTK_WINDOW (shell), GTK_WIDGET (my d_widget));
  127. } else if (1) {
  128. gtk_button_set_focus_on_click (GTK_BUTTON (my d_widget), false);
  129. GTK_WIDGET_UNSET_FLAGS (my d_widget, GTK_CAN_DEFAULT);
  130. }
  131. g_signal_connect (G_OBJECT (my d_widget), "destroy", G_CALLBACK (_GuiGtkButton_destroyCallback), me.get());
  132. g_signal_connect (GTK_BUTTON (my d_widget), "clicked", G_CALLBACK (_GuiGtkButton_activateCallback), me.get());
  133. // if (flags & GuiButton_CANCEL) {
  134. // parent -> shell -> cancelButton = parent -> cancelButton = my widget;
  135. // }
  136. #elif motif
  137. my d_widget = _Gui_initializeWidget (xmPushButtonWidgetClass, parent -> d_widget, buttonText);
  138. _GuiObject_setUserData (my d_widget, me.get());
  139. my d_widget -> window = CreateWindow (L"button", Melder_peek32toW (_GuiWin_expandAmpersands (my d_widget -> name.get())),
  140. WS_CHILD
  141. | ( flags & (GuiButton_DEFAULT | GuiButton_ATTRACTIVE) ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON )
  142. | WS_CLIPSIBLINGS,
  143. my d_widget -> x, my d_widget -> y, my d_widget -> width, my d_widget -> height,
  144. my d_widget -> parent -> window, (HMENU) 1, theGui.instance, nullptr);
  145. SetWindowLongPtr (my d_widget -> window, GWLP_USERDATA, (LONG_PTR) my d_widget);
  146. SetWindowFont (my d_widget -> window, GetStockFont (ANSI_VAR_FONT), false);
  147. my v_positionInForm (my d_widget, left, right, top, bottom, parent);
  148. if (flags & GuiButton_DEFAULT || flags & GuiButton_ATTRACTIVE) {
  149. parent -> d_widget -> shell -> defaultButton = parent -> d_widget -> defaultButton = my d_widget;
  150. }
  151. if (flags & GuiButton_CANCEL) {
  152. parent -> d_widget -> shell -> cancelButton = parent -> d_widget -> cancelButton = my d_widget;
  153. }
  154. #elif cocoa
  155. GuiCocoaButton *button = [[GuiCocoaButton alloc] init];
  156. my name = Melder_dup_f (buttonText);
  157. my d_widget = (GuiObject) button;
  158. my v_positionInForm (my d_widget, left, right, top, bottom, parent);
  159. [button setUserData: me.get()];
  160. [button setButtonType: NSMomentaryPushInButton];
  161. [button setBezelStyle: NSRoundedBezelStyle];
  162. [button setImagePosition: NSNoImage];
  163. [button setBordered: YES];
  164. static NSFont *theButtonFont;
  165. if (! theButtonFont) {
  166. theButtonFont = [NSFont systemFontOfSize: 13.0];
  167. }
  168. [button setFont: theButtonFont];
  169. [button setTitle: (NSString *) Melder_peek32toCfstring (buttonText)];
  170. [button setTarget: (id) my d_widget];
  171. [button setAction: @selector (_guiCocoaButton_activateCallback:)];
  172. //[button setAutoresizingMask: NSViewNotSizable];
  173. if (flags & GuiButton_DEFAULT) {
  174. [button setKeyEquivalent: @"\r"];
  175. }
  176. if (flags & GuiButton_CANCEL) {
  177. [button setKeyEquivalent: [NSString stringWithFormat: @"%c", 27]]; // Escape key
  178. }
  179. if (flags & GuiButton_ATTRACTIVE) {
  180. //[button setKeyEquivalent: @"\r"]; // slow!
  181. [button highlight: YES]; // lasts only till it's clicked!
  182. //[button setBezelStyle: NSThickerSquareBezelStyle];
  183. //[button setFont: [NSFont boldSystemFontOfSize: 14.0]];
  184. }
  185. #endif
  186. if (flags & GuiButton_INSENSITIVE) {
  187. GuiThing_setSensitive (me.get(), false);
  188. }
  189. return me.releaseToAmbiguousOwner();
  190. }
  191. GuiButton GuiButton_createShown (GuiForm parent, int left, int right, int top, int bottom,
  192. conststring32 buttonText, GuiButton_ActivateCallback activateCallback, Thing activateBoss, uint32 flags)
  193. {
  194. GuiButton me = GuiButton_create (parent, left, right, top, bottom, buttonText, activateCallback, activateBoss, flags);
  195. GuiThing_show (me);
  196. return me;
  197. }
  198. void GuiButton_setText (GuiButton me, conststring32 text /* cattable */) {
  199. #if gtk
  200. gtk_button_set_label (GTK_BUTTON (my d_widget), Melder_peek32to8 (text));
  201. #elif motif
  202. my d_widget -> name = Melder_dup_f (text);
  203. _GuiNativeControl_setTitle (my d_widget);
  204. #elif cocoa
  205. [(NSButton *) my d_widget setTitle: (NSString *) Melder_peek32toCfstring (text)];
  206. #endif
  207. }
  208. /* End of file GuiButton.cpp */