OTMultiEditor.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* OTMultiEditor.cpp
  2. *
  3. * Copyright (C) 2005-2018 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. * a selection of changes:
  20. * pb 2005/07/04 created
  21. * pb 2007/10/01 constraint plasticity
  22. * pb 2011/03/01 multiple update rules
  23. */
  24. #include "OTMultiEditor.h"
  25. #include "EditorM.h"
  26. #include "machine.h"
  27. Thing_implement (OTMultiEditor, HyperPage, 0);
  28. static void menu_cb_evaluate (OTMultiEditor me, EDITOR_ARGS_FORM) {
  29. EDITOR_FORM (U"Evaluate", nullptr)
  30. REAL (evaluationNoise, U"Evaluation noise", U"2.0")
  31. EDITOR_OK
  32. EDITOR_DO
  33. Editor_save (me, U"Evaluate");
  34. OTMulti_newDisharmonies ((OTMulti) my data, evaluationNoise);
  35. Graphics_updateWs (my graphics.get());
  36. Editor_broadcastDataChanged (me);
  37. EDITOR_END
  38. }
  39. static void menu_cb_evaluate_noise_2_0 (OTMultiEditor me, EDITOR_ARGS_DIRECT) {
  40. Editor_save (me, U"Evaluate (noise 2.0)");
  41. OTMulti_newDisharmonies ((OTMulti) my data, 2.0);
  42. Graphics_updateWs (my graphics.get());
  43. Editor_broadcastDataChanged (me);
  44. }
  45. static void menu_cb_evaluate_tinyNoise (OTMultiEditor me, EDITOR_ARGS_DIRECT) {
  46. Editor_save (me, U"Evaluate (tiny noise)");
  47. OTMulti_newDisharmonies ((OTMulti) my data, 1e-9);
  48. Graphics_updateWs (my graphics.get());
  49. Editor_broadcastDataChanged (me);
  50. }
  51. static void menu_cb_editRanking (OTMultiEditor me, EDITOR_ARGS_FORM) {
  52. EDITOR_FORM (U"Edit ranking", nullptr)
  53. MUTABLE_LABEL (constraintLabel, U"")
  54. REAL (rankingValue, U"Ranking value", U"100.0")
  55. REAL (disharmony, U"Disharmony", U"100.0")
  56. EDITOR_OK
  57. OTMulti grammar = (OTMulti) my data;
  58. OTConstraint constraint;
  59. if (my selectedConstraint < 1 || my selectedConstraint > grammar -> numberOfConstraints)
  60. Melder_throw (U"Select a constraint first.");
  61. constraint = & grammar -> constraints [grammar -> index [my selectedConstraint]];
  62. SET_STRING (constraintLabel, constraint -> name.get())
  63. SET_REAL (rankingValue, constraint -> ranking)
  64. SET_REAL (disharmony, constraint -> disharmony)
  65. EDITOR_DO
  66. OTMulti grammar = (OTMulti) my data;
  67. OTConstraint constraint = & grammar -> constraints [grammar -> index [my selectedConstraint]];
  68. Editor_save (me, U"Edit ranking");
  69. constraint -> ranking = rankingValue;
  70. constraint -> disharmony = disharmony;
  71. OTMulti_sort (grammar);
  72. Graphics_updateWs (my graphics.get());
  73. Editor_broadcastDataChanged (me);
  74. EDITOR_END
  75. }
  76. static void menu_cb_learnOne (OTMultiEditor me, EDITOR_ARGS_FORM) {
  77. EDITOR_FORM (U"Learn one", U"OTGrammar: Learn one...")
  78. OPTIONMENU_ENUM (kOTGrammar_rerankingStrategy, updateRule,
  79. U"Update rule", kOTGrammar_rerankingStrategy::SYMMETRIC_ALL)
  80. OPTIONMENU (direction, U"Direction", 3)
  81. OPTION (U"forward")
  82. OPTION (U"backward")
  83. OPTION (U"bidirectionally")
  84. REAL (plasticity, U"Plasticity", U"0.1")
  85. REAL (relativePlasticitySpreading, U"Rel. plasticity spreading", U"0.1")
  86. EDITOR_OK
  87. EDITOR_DO
  88. Editor_save (me, U"Learn one");
  89. my form1 = GuiText_getString (my form1Text);
  90. my form2 = GuiText_getString (my form2Text);
  91. OTMulti_learnOne ((OTMulti) my data, my form1.get(), my form2.get(),
  92. updateRule, direction,
  93. plasticity, relativePlasticitySpreading);
  94. Graphics_updateWs (my graphics.get());
  95. Editor_broadcastDataChanged (me);
  96. EDITOR_END
  97. }
  98. static void menu_cb_removeConstraint (OTMultiEditor me, EDITOR_ARGS_DIRECT) {
  99. OTMulti grammar = (OTMulti) my data;
  100. if (my selectedConstraint < 1 || my selectedConstraint > grammar -> numberOfConstraints)
  101. Melder_throw (U"Select a constraint first.");
  102. OTConstraint constraint = & grammar -> constraints [grammar -> index [my selectedConstraint]];
  103. Editor_save (me, U"Remove constraint");
  104. OTMulti_removeConstraint (grammar, constraint -> name.get());
  105. Graphics_updateWs (my graphics.get());
  106. Editor_broadcastDataChanged (me);
  107. }
  108. static void menu_cb_resetAllRankings (OTMultiEditor me, EDITOR_ARGS_FORM) {
  109. EDITOR_FORM (U"Reset all rankings", nullptr)
  110. REAL (ranking, U"Ranking", U"100.0")
  111. EDITOR_OK
  112. EDITOR_DO
  113. Editor_save (me, U"Reset all rankings");
  114. OTMulti_reset ((OTMulti) my data, ranking);
  115. Graphics_updateWs (my graphics.get());
  116. Editor_broadcastDataChanged (me);
  117. EDITOR_END
  118. }
  119. static void menu_cb_OTLearningTutorial (OTMultiEditor, EDITOR_ARGS_DIRECT) {
  120. Melder_help (U"OT learning");
  121. }
  122. static void do_limit (OTMultiEditor me) {
  123. my form1 = GuiText_getString (my form1Text);
  124. my form2 = GuiText_getString (my form2Text);
  125. Graphics_updateWs (my graphics.get());
  126. }
  127. static void gui_button_cb_limit (OTMultiEditor me, GuiButtonEvent /* event */) {
  128. do_limit (me);
  129. }
  130. void structOTMultiEditor :: v_createChildren () {
  131. OTMultiEditor_Parent :: v_createChildren ();
  132. #if defined (macintosh)
  133. #define STRING_SPACING 8
  134. #else
  135. #define STRING_SPACING 2
  136. #endif
  137. int height = Machine_getTextHeight (), y = Machine_getMenuBarHeight () + 4;
  138. GuiButton_createShown (our windowForm, 4, 124, y, y + height,
  139. U"Partial forms:", gui_button_cb_limit, this, GuiButton_DEFAULT);
  140. form1Text = GuiText_createShown (our windowForm,
  141. 124 + STRING_SPACING, 274 + STRING_SPACING, y, y + Gui_TEXTFIELD_HEIGHT, 0);
  142. form2Text = GuiText_createShown (our windowForm,
  143. 274 + 2 * STRING_SPACING, 424 + 2 * STRING_SPACING, y, y + Gui_TEXTFIELD_HEIGHT, 0);
  144. }
  145. void structOTMultiEditor :: v_createMenus () {
  146. OTMultiEditor_Parent :: v_createMenus ();
  147. Editor_addCommand (this, U"Edit", U"-- edit ot --", 0, nullptr);
  148. Editor_addCommand (this, U"Edit", U"Evaluate...", 0, menu_cb_evaluate);
  149. Editor_addCommand (this, U"Edit", U"Evaluate (noise 2.0)", '2', menu_cb_evaluate_noise_2_0);
  150. Editor_addCommand (this, U"Edit", U"Evaluate (tiny noise)", '9', menu_cb_evaluate_tinyNoise);
  151. Editor_addCommand (this, U"Edit", U"Edit ranking...", 'E', menu_cb_editRanking);
  152. Editor_addCommand (this, U"Edit", U"Reset all rankings...", 'R', menu_cb_resetAllRankings);
  153. Editor_addCommand (this, U"Edit", U"Learn one...", '1', menu_cb_learnOne);
  154. Editor_addCommand (this, U"Edit", U"-- remove --", 0, nullptr);
  155. Editor_addCommand (this, U"Edit", U"Remove constraint", 0, menu_cb_removeConstraint);
  156. }
  157. void structOTMultiEditor :: v_createHelpMenuItems (EditorMenu menu) {
  158. OTMultiEditor_Parent :: v_createHelpMenuItems (menu);
  159. EditorMenu_addCommand (menu, U"OT learning tutorial", 0, menu_cb_OTLearningTutorial);
  160. }
  161. static OTMulti drawTableau_grammar;
  162. static conststring32 drawTableau_form1, drawTableau_form2;
  163. static bool drawTableau_constraintsAreDrawnVertically;
  164. static void drawTableau (Graphics g) {
  165. OTMulti_drawTableau (drawTableau_grammar, g, drawTableau_form1, drawTableau_form2, drawTableau_constraintsAreDrawnVertically, true);
  166. }
  167. void structOTMultiEditor :: v_draw () {
  168. OTMulti grammar = (OTMulti) data;
  169. static MelderString buffer { };
  170. double rowHeight = 0.25, tableauHeight = 2 * rowHeight;
  171. Graphics_clearWs (graphics.get());
  172. HyperPage_listItem (this, U"\t\t %%ranking value\t %disharmony\t %plasticity");
  173. for (integer icons = 1; icons <= grammar -> numberOfConstraints; icons ++) {
  174. OTConstraint constraint = & grammar -> constraints [grammar -> index [icons]];
  175. MelderString_copy (& buffer, U"\t", ( icons == selectedConstraint ? U"♠︎ " : U" " ), U"@@", icons,
  176. U"|", constraint -> name.get(), U"@\t ", Melder_fixed (constraint -> ranking, 3),
  177. U"\t ", Melder_fixed (constraint -> disharmony, 3),
  178. U"\t ", Melder_fixed (constraint -> plasticity, 6)
  179. );
  180. HyperPage_listItem (this, buffer.string);
  181. }
  182. Graphics_setAtSignIsLink (graphics.get(), false);
  183. drawTableau_grammar = grammar;
  184. for (integer icand = 1; icand <= grammar -> numberOfCandidates; icand ++) {
  185. if (OTMulti_candidateMatches (grammar, icand, our form1.get(), our form2.get())) {
  186. tableauHeight += rowHeight;
  187. }
  188. }
  189. drawTableau_form1 = our form1.get(); // BUG: dangle
  190. drawTableau_form2 = our form2.get();
  191. drawTableau_constraintsAreDrawnVertically = d_constraintsAreDrawnVertically;
  192. HyperPage_picture (this, 20, tableauHeight, drawTableau);
  193. Graphics_setAtSignIsLink (graphics.get(), true);
  194. }
  195. int structOTMultiEditor :: v_goToPage (conststring32 title) {
  196. if (! title) return 1;
  197. selectedConstraint = Melder_atoi (title);
  198. return 1;
  199. }
  200. autoOTMultiEditor OTMultiEditor_create (conststring32 title, OTMulti grammar) {
  201. try {
  202. autoOTMultiEditor me = Thing_new (OTMultiEditor);
  203. my data = grammar;
  204. my form1 = Melder_dup (U"");
  205. my form2 = Melder_dup (U"");
  206. HyperPage_init (me.get(), title, grammar);
  207. return me;
  208. } catch (MelderError) {
  209. Melder_throw (U"OTMulti window not created.");
  210. }
  211. }
  212. /* End of file OTMultiEditor.cpp */