You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
8.9KB

  1. #include "global_pre.hpp"
  2. #include "rack.hpp"
  3. using namespace rack;
  4. #include "asset.hpp"
  5. #include "componentlibrary.hpp"
  6. #include "plugin.hpp"
  7. #include "TSOSCConfigWidget.hpp"
  8. #include "trowaSoftUtilities.hpp"
  9. //#include "TSSequencerModuleBase.hpp"
  10. #include "TSOSCCommon.hpp"
  11. #include <string>
  12. #include "trowaSoftComponents.hpp"
  13. #include "global_ui.hpp"
  14. #define START_Y 15
  15. /// TODO: DISABLE WHEN NOT VISIBLE
  16. void TSOSCClientItem::onAction(EventAction &e) {
  17. parentButton->selectedOSCClient = this->oscClient;
  18. return;
  19. }
  20. TSOSCClientSelectBtn::TSOSCClientSelectBtn() {
  21. font = Font::load(assetPlugin(plugin, TROWA_MONOSPACE_FONT));
  22. fontSize = 14.0f;
  23. backgroundColor = FORMS_DEFAULT_BG_COLOR;
  24. color = FORMS_DEFAULT_TEXT_COLOR;
  25. textOffset = Vec(5, 3);
  26. borderWidth = 1;
  27. borderColor = FORMS_DEFAULT_BORDER_COLOR;
  28. return;
  29. }
  30. // On button click, create drop down menu.
  31. void TSOSCClientSelectBtn::onAction(EventAction &e) {
  32. if (visible)
  33. {
  34. Menu *menu = rack::global_ui->ui.gScene->createMenu();
  35. menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
  36. menu->box.size.x = box.size.x;
  37. for (unsigned int i = 0; i < OSCClient::NUM_OSC_CLIENTS; i++) {
  38. TSOSCClientItem *option = new TSOSCClientItem(this);
  39. option->oscClient = static_cast<OSCClient>(i);
  40. option->text = OSCClientStr[i];
  41. menu->addChild(option);
  42. }
  43. }
  44. return;
  45. }
  46. void TSOSCClientSelectBtn::step() {
  47. text = stringEllipsize(OSCClientStr[selectedOSCClient], 15);
  48. }
  49. void TSOSCClientSelectBtn::draw(NVGcontext *vg) {
  50. if (visible)
  51. {
  52. nvgScissor(vg, 0, 0, box.size.x, box.size.y);
  53. // Background
  54. nvgBeginPath(vg);
  55. nvgRoundedRect(vg, 0, 0, box.size.x, box.size.y, 5.0);
  56. nvgFillColor(vg, backgroundColor);
  57. nvgFill(vg);
  58. // Border
  59. if (borderWidth > 0) {
  60. nvgStrokeWidth(vg, borderWidth);
  61. nvgStrokeColor(vg, borderColor);
  62. nvgStroke(vg);
  63. }
  64. nvgResetScissor(vg);
  65. if (font->handle >= 0) {
  66. nvgScissor(vg, 0, 0, box.size.x - 5, box.size.y);
  67. nvgFillColor(vg, color);
  68. nvgFontFaceId(vg, font->handle);
  69. nvgTextLetterSpacing(vg, 0.0);
  70. nvgFontSize(vg, fontSize);
  71. nvgText(vg, textOffset.x, textOffset.y, text.c_str(), NULL);
  72. nvgResetScissor(vg);
  73. bndUpDownArrow(vg, box.size.x - 10, 10, 5, color);
  74. }
  75. //ChoiceButton::draw(vg);
  76. }
  77. return;
  78. }
  79. TSOSCConfigWidget::TSOSCConfigWidget(Module* mod, int btnSaveId, int btnAutoReconnectId, OSCClient selectedClient) : TSOSCConfigWidget(mod, btnSaveId, btnAutoReconnectId, selectedClient, "", 1000, 1001)
  80. {
  81. return;
  82. }
  83. TSOSCConfigWidget::TSOSCConfigWidget(Module* mod, int btnSaveId, int btnAutoReconnectId, std::string ipAddress, uint16_t txPort, uint16_t rxPort,
  84. bool showClient, OSCClient selectedClient, bool showNamespace, std::string oscNamespace)
  85. {
  86. this->module = mod;
  87. font = Font::load(assetPlugin(plugin, TROWA_LABEL_FONT));
  88. this->showClientSelect = showClient;
  89. this->showNamespace = showNamespace;
  90. statusMsg2 = "";
  91. this->box.size = Vec(400, 50);
  92. int height = 20;
  93. visible = true;
  94. int x, y;
  95. int dx = 4;
  96. int i = 0;
  97. x = 6;
  98. y = START_Y;
  99. tbIpAddress = new TSTextField(TSTextField::TextType::IpAddress, 15);
  100. tbIpAddress->box.size = Vec(105, height); //115
  101. tbIpAddress->box.pos = Vec(x, y);
  102. tbIpAddress->visible = visible;
  103. tbIpAddress->text = ipAddress;
  104. tbIpAddress->placeholder = "127.0.0.1";
  105. tbIpAddress->id = i;
  106. addChild(tbIpAddress);
  107. textBoxes[i++] = tbIpAddress;
  108. x += tbIpAddress->box.size.x + dx;
  109. tbTxPort = new TSTextField(TSTextField::TextType::DigitsOnly, 5);
  110. tbTxPort->box.size = Vec(50, height);
  111. tbTxPort->box.pos = Vec(x, y);
  112. tbTxPort->visible = visible;
  113. tbTxPort->text = std::to_string(txPort);
  114. tbTxPort->id = i;
  115. addChild(tbTxPort);
  116. textBoxes[i++] = tbTxPort;
  117. x += tbTxPort->box.size.x + dx;
  118. tbRxPort = new TSTextField(TSTextField::TextType::DigitsOnly, 5);
  119. tbRxPort->box.size = Vec(50, height);
  120. tbRxPort->box.pos = Vec(x, y);
  121. tbRxPort->visible = visible;
  122. tbRxPort->text = std::to_string(rxPort);
  123. tbRxPort->id = i;
  124. addChild(tbRxPort);
  125. textBoxes[i++] = tbRxPort;
  126. x += tbRxPort->box.size.x + dx;
  127. // OSC Client Type:
  128. // (since touchOSC needs special handling, Lemur probably does too)
  129. btnClientSelect = new TSOSCClientSelectBtn();
  130. btnClientSelect->selectedOSCClient = selectedClient;
  131. btnClientSelect->box.size = Vec(78, height);
  132. btnClientSelect->box.pos = Vec(x, y);
  133. btnClientSelect->visible = this->showClientSelect && visible;
  134. addChild(btnClientSelect);
  135. if (this->showClientSelect)
  136. x += btnClientSelect->box.size.x + dx + 3;
  137. // Namespace
  138. tbNamespace = new TSTextField(TSTextField::TextType::Any, 20);
  139. tbNamespace->box.size = Vec(78, height);
  140. tbNamespace->box.pos = Vec(x, y);
  141. tbNamespace->visible = this->showNamespace && visible;
  142. tbNamespace->text = oscNamespace;
  143. tbNamespace->id = i;
  144. tbNamespace->placeholder = "namespace";
  145. addChild(tbNamespace);
  146. if (this->showNamespace)
  147. {
  148. textBoxes[i++] = tbNamespace;
  149. xNamespace = x; // Save this so we can label it
  150. x += tbNamespace->box.size.x + dx + 3;
  151. }
  152. // Button Enable/Disable
  153. Vec btnSize = Vec(36, height);
  154. this->btnSave = new TS_PadBtn();
  155. this->btnSave->module = module;
  156. this->btnSave->paramId = btnSaveId;
  157. this->btnSave->box.size = btnSize;
  158. this->btnSave->box.pos = Vec(x, y);
  159. addChild(btnSave);
  160. // Checkbox for Auto-reconnect:
  161. this->ckAutoReconnect = new TS_ScreenCheckBox(Vec(50, 12), module, btnAutoReconnectId, "Auto Con", 0.f, 1.f, 0.f);
  162. this->ckAutoReconnect->box.pos = Vec(x + 4, y - 13);
  163. this->ckAutoReconnect->checkBoxWidth = 10;
  164. this->ckAutoReconnect->checkBoxHeight = 10;
  165. this->ckAutoReconnect->fontSize = 9;
  166. this->ckAutoReconnect->borderWidth = 0;
  167. this->ckAutoReconnect->padding = 1;
  168. this->ckAutoReconnect->color = textColor;
  169. addChild(ckAutoReconnect);
  170. numTextFields = i;
  171. for (i = 0; i < numTextFields; i++)
  172. {
  173. int prevIx = (i > 0) ? i - 1 : numTextFields - 1;
  174. int nextIx = (i < numTextFields - 1) ? i + 1 : 0;
  175. textBoxes[i]->nextField = textBoxes[nextIx];
  176. textBoxes[i]->prevField = textBoxes[prevIx];
  177. }
  178. return;
  179. }
  180. TSOSCConfigWidget::TSOSCConfigWidget(Module* mod, int btnSaveId, int btnAutoReconnectId, OSCClient selectedClient, std::string ipAddress, uint16_t txPort, uint16_t rxPort)
  181. : TSOSCConfigWidget(mod, btnSaveId, btnAutoReconnectId, ipAddress, txPort, rxPort, true, selectedClient, false, std::string(""))
  182. {
  183. return;
  184. }
  185. void TSOSCConfigWidget::step() {
  186. // Check for enable/disable data massaging
  187. if (autoReconnectTrigger.process(module->params[ckAutoReconnect->paramId].value)) {
  188. ckAutoReconnect->checked = !ckAutoReconnect->checked;
  189. }
  190. Widget::step();
  191. return;
  192. }
  193. // Callback for tabbing between our text boxes.
  194. void TSOSCConfigWidget::onTabField(int id)
  195. {
  196. int focusIx = (id + 1) % 3;
  197. textBoxes[focusIx]->requestFocus();
  198. return;
  199. }
  200. // Callback for shift-tabbing between our text boxes.
  201. // This doesn't work since in C++ I can't figure out how to get a damn pointer to a member function...
  202. void TSOSCConfigWidget::onShiftTabField(int id)
  203. {
  204. int focusIx = id - 1;
  205. if (focusIx < 0)
  206. focusIx = 2;
  207. textBoxes[focusIx]->requestFocus();
  208. return;
  209. }
  210. void TSOSCConfigWidget::draw(NVGcontext *vg) {
  211. if (!visible)
  212. {
  213. return;
  214. }
  215. nvgFontSize(vg, fontSize);
  216. nvgFontFaceId(vg, font->handle);
  217. // Screen:
  218. nvgBeginPath(vg);
  219. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 5.0);
  220. nvgFillColor(vg, backgroundColor);
  221. nvgFill(vg);
  222. nvgStrokeWidth(vg, 1.0);
  223. nvgStrokeColor(vg, borderColor);
  224. nvgStroke(vg);
  225. // Draw labels
  226. nvgFillColor(vg, textColor);
  227. nvgFontSize(vg, fontSize);
  228. nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BOTTOM);
  229. float y = START_Y - 1;
  230. float x;
  231. const char* labels[] = { "OSC IP Address", "Out Port", "In Port" };
  232. for (int i = 0; i < TSOSC_NUM_TXTFIELDS; i++)
  233. {
  234. x = textBoxes[i]->box.pos.x + 2;
  235. nvgText(vg, x, y, labels[i], NULL);
  236. }
  237. if (xNamespace > -1)
  238. {
  239. nvgText(vg, xNamespace + 1, y, "Namespace", NULL);
  240. }
  241. // Current status:
  242. x = box.size.x - 8;
  243. nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM);
  244. nvgFillColor(vg, statusColor);
  245. nvgText(vg, x, y, statusMsg.c_str(), NULL);
  246. // Status 2
  247. y += textBoxes[0]->box.size.y + 2;
  248. if (!statusMsg2.empty())
  249. {
  250. nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP);
  251. nvgText(vg, x, y, statusMsg2.c_str(), NULL);
  252. }
  253. // Draw Messages:
  254. x = textBoxes[0]->box.pos.x + 2;
  255. nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
  256. if (!errorMsg.empty())
  257. {
  258. nvgFillColor(vg, errorColor);
  259. nvgText(vg, x, y, errorMsg.c_str(), NULL);
  260. }
  261. else if (!successMsg.empty())
  262. {
  263. nvgFillColor(vg, successColor);
  264. nvgText(vg, x, y, successMsg.c_str(), NULL);
  265. }
  266. else
  267. {
  268. nvgFillColor(vg, textColor);
  269. nvgText(vg, x, y, "Open Sound Control Configuration", NULL);
  270. }
  271. OpaqueWidget::draw(vg);
  272. // Quick and dirty -- Draw labels on buttons:
  273. nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
  274. y = btnSave->box.pos.y + btnSave->box.size.y / 2.0 + 1;
  275. // Save:
  276. x = btnSave->box.pos.x + btnSave->box.size.x / 2.0 + 7;
  277. if (btnActionEnable)
  278. {
  279. nvgFillColor(vg, COLOR_TS_GREEN);
  280. nvgText(vg, x, y, "ENABLE", NULL);
  281. }
  282. else
  283. {
  284. nvgFillColor(vg, COLOR_TS_ORANGE);
  285. nvgText(vg, x, y, "DISABLE", NULL);
  286. }
  287. return;
  288. }
  289. void onTabField(int id)
  290. {
  291. return;
  292. }
  293. void onShiftTabField(int id)
  294. {
  295. return;
  296. }