Audacity 3.2.0
NyqBench.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 NyqBench.cpp
4
5 Leland Lucius
6
7**********************************************************************/
8
9
10
11#include <wx/defs.h>
12
13#include <wx/aboutdlg.h>
14#include <wx/filedlg.h>
15#include <wx/font.h>
16#include <wx/fontdlg.h>
17#include <wx/menu.h>
18#include <wx/msgdlg.h>
19#include <wx/settings.h>
20#include <wx/sizer.h>
21#include <wx/splitter.h>
22#include <wx/statbox.h>
23#include <wx/textctrl.h>
24#include <wx/toolbar.h>
25
26#include "ActiveProject.h"
27#include "AudioIOBase.h"
28#include "CommonCommandFlags.h"
29#include "ModuleConstants.h"
30#include "Prefs.h"
31#include "Project.h"
32#include "ShuttleGui.h"
34#include "effects/EffectUI.h"
36#include "../images/AudacityLogo.xpm"
37#include "../../src/commands/CommandContext.h"
38#include "../../src/commands/CommandManager.h"
39#include "widgets/AudacityMessageBox.h"
40
41#include "NyqBench.h"
42
43#include <iostream>
44#include <ostream>
45#include <sstream>
46
47//
48// Images are from the Tango Icon Gallery
49// http://tango.freedesktop.org/Tango_Icon_Gallery
50//
51#include "images/document-new-small.xpm"
52#include "images/document-open-small.xpm"
53#include "images/document-save-as-small.xpm"
54#include "images/document-save-small.xpm"
55#include "images/edit-clear-small.xpm"
56#include "images/edit-copy-small.xpm"
57#include "images/edit-cut-small.xpm"
58#include "images/edit-delete-small.xpm"
59#include "images/edit-find-small.xpm"
60#include "images/edit-paste-small.xpm"
61#include "images/edit-redo-small.xpm"
62#include "images/edit-select-all-small.xpm"
63#include "images/edit-undo-small.xpm"
64#include "images/go-top-small.xpm"
65#include "images/go-up-small.xpm"
66#include "images/go-previous-small.xpm"
67#include "images/go-next-small.xpm"
68#include "images/system-search-small.xpm"
69#include "images/media-playback-start-small.xpm"
70#include "images/media-playback-stop-small.xpm"
71
72#include "images/document-new-large.xpm"
73#include "images/document-open-large.xpm"
74#include "images/document-save-as-large.xpm"
75#include "images/document-save-large.xpm"
76#include "images/edit-clear-large.xpm"
77#include "images/edit-copy-large.xpm"
78#include "images/edit-cut-large.xpm"
79#include "images/edit-delete-large.xpm"
80#include "images/edit-find-large.xpm"
81#include "images/edit-paste-large.xpm"
82#include "images/edit-redo-large.xpm"
83#include "images/edit-select-all-large.xpm"
84#include "images/edit-undo-large.xpm"
85#include "images/go-top-large.xpm"
86#include "images/go-up-large.xpm"
87#include "images/go-previous-large.xpm"
88#include "images/go-next-large.xpm"
89#include "images/system-search-large.xpm"
90#include "images/media-playback-start-large.xpm"
91#include "images/media-playback-stop-large.xpm"
92
93/*
94//#define ModuleDispatchName "ModuleDispatch"
95See the example in this file. It has several cases/options in it.
96*/
97
98namespace {
100{
101 return *NyqBench::GetBench();
102}
103
105{
106 // Get here only after the module version check passes
107 using namespace MenuTable;
108 static AttachedItem sAttachment{ wxT("Tools"),
109 ( FinderScope( findme ), Section( wxT("NyquistWorkBench"),
110 Command( wxT("NyqBench"), XXO("&Nyquist Workbench..."),
112 ) )
113 };
114}
115}
116
118
119extern "C"
120{
121 static NyqBench *gBench = NULL;
122
124 // ModuleDispatch
125 // is called by Audacity to initialize/terminate the module
127 switch (type){
128 case ModuleInitialize:
130 break;
131 case AppQuiting: {
132 //It is perfectly OK for gBench to be NULL.
133 //Can happen if the menu item was never invoked.
134 //wxASSERT(gBench != NULL);
135 if (gBench) {
136 // be sure to do this while gPrefs still exists:
137 gBench->SavePrefs();
138 gBench->Destroy();
139 gBench = NULL;
140 }
141 }
142 break;
143 default:
144 break;
145 }
146 return 1;
147 }
148};
149
150//----------------------------------------------------------------------------
151// NyqTextCtrl
152//----------------------------------------------------------------------------
153
154BEGIN_EVENT_TABLE(NyqTextCtrl, wxTextCtrl)
155#if defined(__WXMAC__)
156 EVT_KEY_DOWN(NyqTextCtrl::OnKeyDown)
157#endif
158 EVT_KEY_UP(NyqTextCtrl::OnKeyUp)
159 EVT_CHAR(NyqTextCtrl::OnChar)
160 EVT_UPDATE_UI(wxID_ANY, NyqTextCtrl::OnUpdate)
162
163NyqTextCtrl::NyqTextCtrl(wxWindow *parent,
164 wxWindowID id,
165 const wxString &value,
166 const wxPoint & pos,
167 const wxSize & size,
168 int style)
169: wxTextCtrl(parent, id, value, pos, size, style)
170{
171 mLastCaretPos = -1;
172 mLeftParen = -1;
173 mRightParen = -1;
174
175 mOn.SetTextColour(*wxRED);
176 mOff.SetTextColour(*wxBLACK);
177}
178
180{
181#if defined(__WXMSW__)
182 // We do this to prevent wxMSW from selecting all text when the
183 // user tabs into the text controls.
184 wxWindowBase::SetFocusFromKbd();
185#else
186 wxTextCtrl::SetFocusFromKbd();
187#endif
188}
189
191{
192 wxTextCtrl::MarkDirty();
193 FindParens();
194}
195
196void NyqTextCtrl::OnChar(wxKeyEvent & e)
197{
198 e.Skip();
199
200 // Hide any previously highlighted parens
201 if (mLeftParen >= 0) {
202#if defined(__WXMSW__)
203 Freeze(); // Prevents selection flashing on Windows
204#endif
205
206 SetStyle(mLeftParen, mLeftParen + 1, mOff);
208 mLeftParen = -1;
209 mRightParen = -1;
210
211#if defined(__WXMSW__)
212 Thaw(); // Prevents selection flashing on Windows
213#endif
214 }
215}
216
217#if defined(__WXMAC__REMOVED_UNTIL_ITS_PROVEN_THAT_IT_IS_STILL_NEEDED)
218#include <wx/mac/uma.h>
219
220// This is hackage to correct a problem on Leopard where the
221// caret jumps up two lines when the up arrow is pressed and
222// the caret is at the beginning of the line.
223void NyqTextCtrl::OnKeyDown(wxKeyEvent & e)
224{
225 e.Skip();
226 if (UMAGetSystemVersion() >= 0x1050) {
227 if (e.GetKeyCode() == WXK_UP && e.GetModifiers() == 0) {
228 long x;
229 long y;
230
231 PositionToXY(GetInsertionPoint(), &x, &y);
232 if (x == 0 && y > 1) {
233 y--;
234 SetInsertionPoint(XYToPosition(x, y) - 1);
235 e.Skip(false);
236 }
237 }
238 }
239}
240#endif
241
242void NyqTextCtrl::OnKeyUp(wxKeyEvent & e)
243{
244 e.Skip();
245
246 int pos = GetInsertionPoint();
247 int lpos = wxMax(0, pos - 1);
248
249 wxString text = GetRange(lpos, pos);
250
251 if (text[0] == wxT('(')) {
252 wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
253 if (left != mLeftParens.end()) {
254 Colorize(lpos, left->second);
255 }
256 }
257 else if (text[0] == wxT(')')) {
258 wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
259 if (right != mRightParens.end()) {
260 Colorize(right->second, lpos);
261 }
262 }
263}
264
265void NyqTextCtrl::OnUpdate(wxUpdateUIEvent & e)
266{
267 int pos = GetInsertionPoint();
268
269 if (pos != mLastCaretPos) {
270 int lpos = wxMax(0, pos - 1);
271
272 wxString text = GetRange(lpos, pos);
273 if (text.Length() > 0) {
274 if (text[0] == wxT('(')) {
275 wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
276 if (left != mLeftParens.end()) {
277 Colorize(lpos, left->second);
278 }
279 }
280 else if (text[0] == wxT(')')) {
281 wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
282 if (right != mRightParens.end()) {
283 Colorize(right->second, lpos);
284 }
285 }
286 }
287
288 mLastCaretPos = pos;
289 }
290}
291
293{
295}
296
298{
299 wxLongToLongHashMap::const_iterator it;
300 long first = -1;
301 long second = -1;
302
303 if (mLeftParen != -1) {
304 for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
305 if (mLeftParen > it->first && mLeftParen < it->second) {
306 if (first == -1 || it->first < first) {
307 first = it->first;
308 second = it->second;
309 }
310 }
311 }
312 }
313
314 if (first != -1) {
315 MoveCursor(first, second);
316 }
317}
318
320{
321 wxLongToLongHashMap::const_iterator it;
322 long first = -1;
323 long second = -1;
324
325 if (mLeftParen != -1) {
326 for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
327 if (mLeftParen > it->first && mLeftParen < it->second) {
328 if (first == -1 || it->first > first) {
329 first = it->first;
330 second = it->second;
331 }
332 }
333 }
334 }
335
336 if (first != -1) {
337 MoveCursor(first, second);
338 }
339}
340
342{
343 wxLongToLongHashMap::const_iterator it;
344 long first = -1;
345 long second = -1;
346
347 if (mLeftParen != -1) {
348 for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
349 if (it->first < mLeftParen && it->first >= first) {
350 first = it->first;
351 second = it->second;
352 }
353 }
354 }
355
356 if (first != -1) {
357 MoveCursor(first, second);
358 }
359}
360
362{
363 wxLongToLongHashMap::const_iterator it;
364 long first = -1;
365 long second = -1;
366
367 if (mLeftParen != -1) {
368 for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
369 if (it->first > mLeftParen && (first == -1 || it->first < first)) {
370 first = it->first;
371 second = it->second;
372 }
373 }
374 }
375
376 if (first != -1) {
377 MoveCursor(first, second);
378 }
379}
380
381void NyqTextCtrl::MoveCursor(long first, long second)
382{
383 int pos = GetInsertionPoint();
384 int lpos = wxMax(0, pos - 1);
385
386 wxString text = GetRange(lpos, pos);
387
388 if (text[0] == wxT('(')) {
389 SetInsertionPoint(first + 1);
390 Colorize(first, second);
391 }
392 else if (text[0] == wxT(')')) {
393 SetInsertionPoint(second + 1);
394 Colorize(first, second);
395 }
396}
397
398void NyqTextCtrl::Colorize(long left, long right)
399{
400 // Hide any previously highlighted parens
401 if (mLeftParen >= 0) {
402#if defined(__WXMSW__)
403 Freeze(); // Prevents selection flashing on Windows
404#endif
405
406 SetStyle(mLeftParen, mLeftParen + 1, mOff);
408 mLeftParen = -1;
409 mRightParen = -1;
410
411#if defined(__WXMSW__)
412 Thaw(); // Prevents selection flashing on Windows
413#endif
414 }
415
416 mLeftParen = left;
417 mRightParen = right;
418
419 if (mLeftParen != -1) {
420 SetStyle(mLeftParen, mLeftParen + 1, mOn);
421 SetStyle(mRightParen, mRightParen + 1, mOn);
422
423 SetStyle(mLeftParen + 1, mLeftParen + 1, mOff);
424 SetStyle(mRightParen + 1, mRightParen + 1, mOff);
425 }
426}
427
429{
430 wxString text = GetValue();
431 bool inquotes = false;
432 wxArrayInt stack;
433 long len = (long) text.Length();
434 long pos;
435
436 mLeftParens.clear();
437 mRightParens.clear();
438
439 for (pos = 0; pos < len; pos++) {
440 wxChar c = text[pos];
441 switch (c)
442 {
443 case wxT('"'):
444 inquotes = !inquotes;
445 break;
446
447 case wxT(';'):
448 if (!inquotes) {
449 pos = (long)text.find(wxT('\n'), pos);
450 if (pos == (long)wxString::npos) {
451 pos = len;
452 }
453 }
454 break;
455
456 case wxT('#'):
457 if (!inquotes) {
458 long ndx = pos + 1;
459 if (ndx < len && text[(int)ndx] == wxT('|')) {
460 // Shamelessly stolen from xlread.c/pcomment()
461 wxChar lastch = -1;
462 int n = 1;
463
464 /* look for the matching delimiter (and handle nesting) */
465 while (n > 0 && ++pos < len) {
466 wxChar ch = text[(int)pos];
467 if (lastch == '|' && ch == '#') {
468 --n;
469 ch = -1;
470 }
471 else if (lastch == '#' && ch == '|') {
472 ++n;
473 ch = -1;
474 }
475 lastch = ch;
476 }
477 }
478 }
479 break;
480
481 case wxT('('):
482 if (!inquotes) {
483 stack.Add(pos);
484 }
485 break;
486
487 case wxT(')'):
488 if (!inquotes) {
489 if (stack.GetCount() > 0) {
490 int left = stack.Last();
491 stack.RemoveAt(stack.GetCount() - 1);
492
493 mLeftParens[left] = pos;
494 mRightParens[pos] = left;
495 }
496 }
497 break;
498 }
499 }
500}
501
502//----------------------------------------------------------------------------
503// NyqRedirector
504//----------------------------------------------------------------------------
505
507: mText(text)
508{
509 mOld = std::cout.rdbuf(this);
510}
511
513{
514 std::cout.flush();
515 std::cout.rdbuf(mOld);
516 if (s.length() > 0) {
517 AppendText();
518 }
519}
520
522{
523 s += (char)c;
524 if (c == '\n') {
525 AppendText();
526 }
527
528 return 0;
529}
530
532{
533 mText->AppendText(wxString(s.c_str(), wxConvISO8859_1));
534 s.clear();
535}
536
537//----------------------------------------------------------------------------
538// NyqBench
539//----------------------------------------------------------------------------
540
541enum
542{
543 ID_AUTOLOAD = 20000,
544
546
559
562
566
567BEGIN_EVENT_TABLE(NyqBench, wxFrame)
568 EVT_CLOSE(NyqBench::OnClose)
569 EVT_MOVE(NyqBench::OnMove)
570 EVT_SIZE(NyqBench::OnSize)
571
572 EVT_MENU(wxID_NEW, NyqBench::OnNew)
573 EVT_MENU(wxID_OPEN, NyqBench::OnOpen)
574 EVT_MENU(wxID_SAVE, NyqBench::OnSave)
575 EVT_MENU(wxID_SAVEAS, NyqBench::OnSaveAs)
576 EVT_MENU(wxID_REVERT_TO_SAVED, NyqBench::OnRevert)
579
580 EVT_MENU(wxID_UNDO, NyqBench::OnUndo)
581 EVT_MENU(wxID_REDO, NyqBench::OnRedo)
582 EVT_MENU(wxID_CUT, NyqBench::OnCut)
583 EVT_MENU(wxID_COPY, NyqBench::OnCopy)
584 EVT_MENU(wxID_PASTE, NyqBench::OnPaste)
585 EVT_MENU(wxID_CLEAR, NyqBench::OnClear)
586 EVT_MENU(wxID_SELECTALL, NyqBench::OnSelectAll)
587 EVT_MENU(wxID_FIND, NyqBench::OnFind)
594
602
605
606 EVT_MENU(wxID_ABOUT, NyqBench::OnAbout)
607
608 EVT_FIND(wxID_ANY, NyqBench::OnFindDialog)
609 EVT_FIND_NEXT(wxID_ANY, NyqBench::OnFindDialog)
610 EVT_FIND_REPLACE(wxID_ANY, NyqBench::OnFindDialog)
611 EVT_FIND_REPLACE_ALL(wxID_ANY, NyqBench::OnFindDialog)
612 EVT_FIND_CLOSE(wxID_ANY, NyqBench::OnFindDialog)
613
615
616 EVT_UPDATE_UI(wxID_SAVE, NyqBench::OnMenuUpdate)
617 EVT_UPDATE_UI(wxID_SAVEAS, NyqBench::OnMenuUpdate)
618 EVT_UPDATE_UI(wxID_REVERT_TO_SAVED, NyqBench::OnMenuUpdate)
619
620 EVT_UPDATE_UI(wxID_UNDO, NyqBench::OnUndoUpdate)
621 EVT_UPDATE_UI(wxID_REDO, NyqBench::OnRedoUpdate)
622 EVT_UPDATE_UI(wxID_CUT, NyqBench::OnCutUpdate)
623 EVT_UPDATE_UI(wxID_COPY, NyqBench::OnCopyUpdate)
624 EVT_UPDATE_UI(wxID_PASTE, NyqBench::OnPasteUpdate)
625 EVT_UPDATE_UI(wxID_CLEAR, NyqBench::OnClearUpdate)
626
627 EVT_UPDATE_UI(ID_SPLITH, NyqBench::OnViewUpdate)
628 EVT_UPDATE_UI(ID_SPLITV, NyqBench::OnViewUpdate)
631
632 EVT_UPDATE_UI(ID_GO, NyqBench::OnRunUpdate)
633
634 EVT_UPDATE_UI(ID_SCRIPT, NyqBench::OnScriptUpdate)
635 EVT_UPDATE_UI(ID_OUTPUT, NyqBench::OnOutputUpdate)
637
638/*static*/ NyqBench *NyqBench::GetBench()
639{
640 if (gBench == nullptr)
641 {
642 gBench = new NyqBench(NULL);
643 }
644
645 return gBench;
646}
647
648NyqBench::NyqBench(wxWindow * parent)
649: wxFrame(NULL,
650 wxID_ANY,
651 wxEmptyString,
652 wxDefaultPosition,
653 wxDefaultSize,
654 wxDEFAULT_FRAME_STYLE |
655 wxMINIMIZE_BOX |
656 wxMAXIMIZE_BOX |
657 wxRESIZE_BORDER)
658{
659 mFindDlg = NULL;
660 mRunning = false;
661 mScriptBox = NULL;
662 mOutputBox = NULL;
663 mScript = NULL;
664 mOutput = NULL;
665
666 mPath = gPrefs->Read(wxT("NyqBench/Path"), wxEmptyString);
667 mAutoLoad = (gPrefs->Read(wxT("NyqBench/AutoLoad"), 0L) != 0);
668 mAutoWrap = (gPrefs->Read(wxT("NyqBench/AutoWrap"), true) != 0);
669 mLargeIcons = (gPrefs->Read(wxT("NyqBench/LargeIcons"), 0L) != 0);
670 mSplitMode = gPrefs->Read(wxT("NyqBench/SplitMode"), wxSPLIT_VERTICAL);
671 mShowCode = (gPrefs->Read(wxT("NyqBench/ShowScript"), true) != 0);
672 mShowOutput = (gPrefs->Read(wxT("NyqBench/ShowOutput"), true) != 0);
673
674 SetIcon(wxICON(AudacityLogo));
675 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
676 ShuttleGui S(this, eIsCreating);
678 wxMenuBar *bar = new wxMenuBar();
679
680 wxMenu *menu = new wxMenu();
681 menu->Append(wxID_NEW, wxT("&New\tCtrl+N"));
682 menu->Append(wxID_OPEN, wxT("&Open...\tCtrl+O"));
683 menu->Append(wxID_SAVE, wxT("&Save...\tCtrl+S"));
684 menu->Append(wxID_SAVEAS, wxT("Save &As...\tCtrl+Shift+S"));
685 menu->AppendSeparator();
686 menu->Append(wxID_REVERT_TO_SAVED, _T("&Revert to Saved"));
687 menu->AppendSeparator();
688 menu->AppendCheckItem(ID_AUTOLOAD, _T("Auto &Load Last File"))->Check(mAutoLoad);
689 menu->AppendSeparator();
690 menu->Append(wxID_CLOSE, wxT("&Close Window\tCtrl+W"));
691 bar->Append(menu, wxT("&File"));
692
693 menu = new wxMenu();
694 menu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
695 menu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
696 menu->AppendSeparator();
697 menu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
698 menu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
699 menu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
700 menu->Append(wxID_CLEAR, _("Cle&ar\tCtrl+L"));
701 menu->AppendSeparator();
702 menu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
703 menu->AppendSeparator();
704 menu->Append(wxID_FIND, _("&Find...\tCtrl+F"));
705 menu->AppendSeparator();
706 wxMenu *sub = new wxMenu();
707 sub->Append(ID_MATCH, _("&Matching Paren\tF8"));
708 sub->Append(ID_TOP, _("&Top S-expr\tF9"));
709 sub->Append(ID_UP, _("&Higher S-expr\tF10"));
710 sub->Append(ID_PREVIOUS, _("&Previous S-expr\tF11"));
711 sub->Append(ID_NEXT, _("&Next S-expr\tF12"));
712 menu->AppendSubMenu(sub, _("&Go to"));
713 menu->AppendSeparator();
714 menu->AppendCheckItem(ID_AUTOWRAP, _T("Auto &Wrap"))->Check(mAutoWrap);
715 bar->Append(menu, wxT("&Edit"));
716
717 menu = new wxMenu();
718 menu->Append(ID_FONT, _("Select &Font..."));
719 menu->AppendSeparator();
720 menu->Append(ID_SPLITV, _("Split &Vertically"));
721 menu->Append(ID_SPLITH, _("Split &Horizontally"));
722 menu->AppendSeparator();
723 menu->AppendCheckItem(ID_TOGGLECODE, _("Show S&cript"));
724 menu->AppendCheckItem(ID_TOGGLEOUTPUT, _("Show &Output"));
725 menu->AppendSeparator();
726 sub = new wxMenu();
727 sub->AppendRadioItem(ID_LARGEICONS, _("&Large Icons"));
728 sub->AppendRadioItem(ID_SMALLICONS, _("&Small Icons"));
729 menu->AppendSubMenu(sub, _("Toolbar"));
730 bar->Append(menu, wxT("&View"));
731
732 menu = new wxMenu();
733 menu->Append(ID_GO, _("&Go\tF5"));
734 menu->Append(ID_STOP, _("&Stop\tF6"));
735 bar->Append(menu, wxT("&Run"));
736
737#if defined(__WXMAC__)
738 menu->Append(wxID_ABOUT, _("&About"));
739#else
740 menu = new wxMenu();
741 menu->Append(wxID_ABOUT, _("&About"));
742 bar->Append(menu, wxT("Help"));
743#endif
744
745 SetMenuBar(bar);
746
748
749 wxRect r;
750 r.SetX(gPrefs->Read(wxT("NyqBench/Window/X"), -1));
751 r.SetY(gPrefs->Read(wxT("NyqBench/Window/Y"), -1));
752 r.SetWidth(gPrefs->Read(wxT("NyqBench/Window/Width"), -1));
753 r.SetHeight(gPrefs->Read(wxT("NyqBench/Window/Height"), -1));
754 if (r == wxRect(-1, -1, -1, -1)) {
755 Center();
756 }
757 else {
758 SetSize(r);
759 }
760
761 bool maximized = false;
762 gPrefs->Read(wxT("NyqBench/Window/Maximized"), maximized);
763 if (maximized) {
764 Maximize();
765 }
766
767 long sashpos;
768 sashpos = gPrefs->Read(wxT("NyqBench/SplitX"), 0l);
769 if (sashpos > 0) {
770 mSplitter->SetSashPosition(sashpos);
771 }
772
773 wxString dflt = wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT).GetNativeFontInfoDesc();
774 wxString desc;
775 wxTextAttr attr;
776
777 desc = gPrefs->Read(wxT("NyqBench/ScriptFont"), dflt);
778 mScriptFont.SetNativeFontInfo(desc);
779#if defined(__WXMSW__)
780 // Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
781 // I don't know if this is something I'm doing wrong, but I'll have to look at this
782 // later if I get bored.
783 mScriptFont.SetEncoding(wxFONTENCODING_SYSTEM);
784#endif
785 attr.SetFont(mScriptFont);
786 mScript->SetDefaultStyle(attr);
787
788 desc = gPrefs->Read(wxT("NyqBench/OutputFont"), dflt);
789 mOutputFont.SetNativeFontInfo(desc);
790#if defined(__WXMSW__)
791 // Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
792 // I don't know if this is something I'm doing wrong, but I'll have to look at this
793 // later if I get bored.
794 mOutputFont.SetEncoding(wxFONTENCODING_SYSTEM);
795#endif
796 attr.SetFont(mOutputFont);
797 mOutput->SetDefaultStyle(attr);
798
799 if (mAutoLoad && !mPath.GetFullPath().IsEmpty()) {
800 LoadFile();
801 }
802
804}
805
807{
808}
809
811{
812 gPrefs->Write(wxT("NyqBench/Window/Maximized"), IsMaximized());
813 if (!IsMaximized()) {
814 wxRect r = GetRect();
815
816#if !defined(__WXMAC__)
817 if (IsIconized()) {
818 r = mLastSize;
819 }
820#endif
821
822 gPrefs->Write(wxT("NyqBench/Window/X"), r.GetX());
823 gPrefs->Write(wxT("NyqBench/Window/Y"), r.GetY());
824 gPrefs->Write(wxT("NyqBench/Window/Width"), r.GetWidth());
825 gPrefs->Write(wxT("NyqBench/Window/Height"), r.GetHeight());
826 }
827
828 gPrefs->Write(wxT("NyqBench/AutoLoad"), mAutoLoad);
829 gPrefs->Write(wxT("NyqBench/AutoWrap"), mAutoWrap);
830 gPrefs->Write(wxT("NyqBench/ScriptFont"), mScriptFont.GetNativeFontInfoDesc());
831 gPrefs->Write(wxT("NyqBench/OutputFont"), mOutputFont.GetNativeFontInfoDesc());
832 gPrefs->Write(wxT("NyqBench/LargeIcons"), mLargeIcons);
833 gPrefs->Write(wxT("NyqBench/SplitX"), mSplitter->IsSplit() ? mSplitter->GetSashPosition() : 0);
834 gPrefs->Write(wxT("NyqBench/SplitMode"), mSplitter->IsSplit() ? mSplitter->GetSplitMode() : 0);
835 gPrefs->Write(wxT("NyqBench/ShowCode"), mScript->IsShown());
836 gPrefs->Write(wxT("NyqBench/ShowOutput"), mOutput->IsShown());
837}
838
840{
841 S.StartHorizontalLay(wxEXPAND, true);
842 {
843 wxPanel *scriptp;
844 wxPanel *outputp;
845 wxStaticBoxSizer *scripts;
846 wxStaticBoxSizer *outputs;
847 wxBoxSizer *bs;
848
849 mSplitter = new wxSplitterWindow(this,
850 wxID_ANY,
851 wxDefaultPosition,
852 wxDefaultSize,
853 wxSP_LIVE_UPDATE |
854 wxSP_3DSASH |
855 wxSP_NOBORDER);
856
857 scriptp = new wxPanel(mSplitter,
858 wxID_ANY,
859 wxDefaultPosition,
860 wxDefaultSize,
861 wxNO_FULL_REPAINT_ON_RESIZE |
862 wxCLIP_CHILDREN);
863 bs = new wxBoxSizer(wxVERTICAL);
864 scriptp->SetSizer(bs);
865
866 mScriptBox = new wxStaticBox(scriptp,
867 wxID_ANY,
868 _("Script"));
869
870 scripts = new wxStaticBoxSizer(mScriptBox,
871 wxVERTICAL);
872 bs->Add(scripts, true, wxEXPAND);
873
874 mScript = new NyqTextCtrl(scriptp,
875 ID_SCRIPT,
876 wxEmptyString,
877 wxDefaultPosition,
878 wxDefaultSize,
879 wxTE_RICH2 | wxTE_RICH |
880 (mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
881 wxTE_NOHIDESEL |
882 wxTE_MULTILINE);
883 scripts->Add(mScript, true, wxEXPAND);
884
885 outputp = new wxPanel(mSplitter,
886 wxID_ANY,
887 wxDefaultPosition,
888 wxDefaultSize,
889 wxNO_FULL_REPAINT_ON_RESIZE |
890 wxCLIP_CHILDREN);
891 bs = new wxBoxSizer(wxVERTICAL);
892 outputp->SetSizer(bs);
893
894 mOutputBox = new wxStaticBox(outputp,
895 wxID_ANY,
896 _("Output"));
897 outputs = new wxStaticBoxSizer(mOutputBox,
898 wxVERTICAL);
899 bs->Add(outputs, true, wxEXPAND);
900
901 mOutput = new NyqTextCtrl(outputp,
902 ID_OUTPUT,
903 wxEmptyString,
904 wxDefaultPosition,
905 wxDefaultSize,
906 wxTE_READONLY |
907#if !defined(__WXMAC__)
908// I could not get the bloody horizontal scroll bar to appear on
909// wxMac, so we can't use wxTE_DONTWRAP as you can't easily scroll
910// left and right.
911 wxTE_DONTWRAP |
912#endif
913 wxTE_NOHIDESEL |
914 wxTE_MULTILINE);
915 outputs->Add(mOutput, true, wxEXPAND);
916
917 switch (mSplitMode)
918 {
919 case wxSPLIT_VERTICAL:
920 mSplitter->SplitVertically(scriptp, outputp, 300);
921 break;
922
923 case wxSPLIT_HORIZONTAL:
924 mSplitter->SplitHorizontally(scriptp, outputp, 300);
925 break;
926
927 default:
928 mSplitter->Initialize((mShowCode ? scriptp : outputp));
929 break;
930 }
931
932 mSplitter->SetMinimumPaneSize(50);
933
934 S.AddSpace(5, 1);
935 S.Prop(true);
936 S.Position(wxEXPAND).AddWindow(mSplitter);
937 S.AddSpace(5, 1);
938
939 mSplitter->SetMinSize(wxSize(600, 400));
940 }
941 S.EndHorizontalLay();
942
943 S.AddSpace(1, 5);
944
945 return;
946}
947
948void NyqBench::OnClose(wxCloseEvent & e)
949{
950 if (!Validate()) {
951 e.Veto();
952 }
953 else {
954 Show(false);
955 }
956}
957
958void NyqBench::OnMove(wxMoveEvent & e)
959{
960 e.Skip();
961 if (!IsIconized() && !IsMaximized()) {
962 mLastSize.SetPosition(e.GetPosition());
963 }
964}
965
966void NyqBench::OnSize(wxSizeEvent & e)
967{
968 e.Skip();
969 if (!IsIconized() && !IsMaximized()) {
970 mLastSize.SetSize(e.GetSize());
971 }
972}
973
974void NyqBench::OnCloseWindow(wxCommandEvent & e)
975{
976 Close();
977}
978
979void NyqBench::OnNew(wxCommandEvent & e)
980{
981 if (!Validate()) {
982 return;
983 }
984
985 mPath.SetFullName(wxEmptyString);
986
987 while (mScript->CanUndo()) {
988 mScript->Undo();
989 }
990
991 mScript->Clear();
992 mScript->DiscardEdits();
993
995}
996
997void NyqBench::OnOpen(wxCommandEvent & e)
998{
999 if (mScript->IsModified() && !Validate()) {
1000 return;
1001 }
1002
1003 wxFileDialog dlog(this,
1004 _("Load Nyquist script"),
1005 mPath.GetPath(),
1006 wxEmptyString,
1007 _("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
1008 wxFD_OPEN | wxRESIZE_BORDER);
1009
1010 if (dlog.ShowModal() != wxID_OK) {
1011 return;
1012 }
1013
1014 mPath = dlog.GetPath();
1015 gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
1016
1017 LoadFile();
1018
1020}
1021
1022void NyqBench::OnSave(wxCommandEvent & e)
1023{
1024 if (mScript->GetLastPosition() == 0) {
1025 return;
1026 }
1027
1028 if (mPath.GetFullPath().IsEmpty()) {
1029 OnSaveAs(e);
1030 return;
1031 }
1032
1033 if (!mScript->SaveFile(mPath.GetFullPath()))
1034 {
1035 AudacityMessageBox(XO("Script was not saved."),
1036 XO("Warning"),
1037 wxICON_EXCLAMATION,
1038 this);
1039 return;
1040 }
1041}
1042
1043void NyqBench::OnSaveAs(wxCommandEvent & e)
1044{
1045 if (mScript->GetLastPosition() == 0) {
1046 return;
1047 }
1048
1049 wxFileDialog dlog(this,
1050 _("Save Nyquist script"),
1051 mPath.GetFullPath(),
1052 wxEmptyString,
1053 _("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
1054 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
1055
1056 if (dlog.ShowModal() != wxID_OK) {
1057 return;
1058 }
1059
1060 mPath = dlog.GetPath();
1061 gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
1062
1063 if (!mScript->SaveFile(mPath.GetFullPath()))
1064 {
1065 AudacityMessageBox(XO("Script was not saved."),
1066 XO("Warning"),
1067 wxICON_EXCLAMATION,
1068 this);
1069 return;
1070 }
1071
1073}
1074
1075void NyqBench::OnAutoLoad(wxCommandEvent & e)
1076{
1077 mAutoLoad = e.IsChecked();
1078}
1079
1080void NyqBench::OnRevert(wxCommandEvent & e)
1081{
1082 if (mPath.GetFullPath().IsEmpty()) {
1083 return;
1084 }
1085
1086 if (!Validate()) {
1087 return;
1088 }
1089
1090 LoadFile();
1091}
1092
1093void NyqBench::OnUndo(wxCommandEvent & e)
1094{
1095 (FindFocus() == mScript ? mScript : mOutput)->Undo();
1096}
1097
1098void NyqBench::OnRedo(wxCommandEvent & e)
1099{
1100 (FindFocus() == mScript ? mScript : mOutput)->Redo();
1101}
1102
1103void NyqBench::OnCut(wxCommandEvent & e)
1104{
1105 (FindFocus() == mScript ? mScript : mOutput)->Cut();
1106}
1107
1108void NyqBench::OnCopy(wxCommandEvent & e)
1109{
1110 (FindFocus() == mScript ? mScript : mOutput)->Copy();
1111}
1112
1113void NyqBench::OnPaste(wxCommandEvent & e)
1114{
1115 (FindFocus() == mScript ? mScript : mOutput)->Paste();
1116}
1117
1118void NyqBench::OnClear(wxCommandEvent & e)
1119{
1120 (FindFocus() == mScript ? mScript : mOutput)->Clear();
1121}
1122
1123void NyqBench::OnSelectAll(wxCommandEvent & e)
1124{
1125 (FindFocus() == mScript ? mScript : mOutput)->SetSelection(-1, -1);
1126}
1127
1128void NyqBench::OnFind(wxCommandEvent & e)
1129{
1130 if (mFindDlg ) {
1131 delete mFindDlg;
1132 mFindDlg = NULL;
1133 }
1134 else {
1136 if (w == mScript || w == mOutput) {
1137 mFindText = w;
1138
1139 int flags = 0;
1140
1141 flags |= (gPrefs->Read(wxT("NyqBench/Find/Down"), 0L) ? wxFR_DOWN : 0);
1142 flags |= (gPrefs->Read(wxT("NyqBench/Find/Word"), 0L) ? wxFR_WHOLEWORD : 0);
1143 flags |= (gPrefs->Read(wxT("NyqBench/Find/Case"), 0L) ? wxFR_MATCHCASE : 0);
1144
1145 mFindData.SetFlags(flags);
1146
1147 mFindDlg = new wxFindReplaceDialog(this,
1148 &mFindData,
1149 _("Find dialog"),
1150 wxFR_NOWHOLEWORD);
1151 mFindDlg->Show(true);
1152 }
1153 }
1154}
1155
1156void NyqBench::OnGoMatch(wxCommandEvent & e)
1157{
1158 mScript->GoMatch();
1159}
1160
1161void NyqBench::OnGoTop(wxCommandEvent & e)
1162{
1163 mScript->GoTop();
1164}
1165
1166void NyqBench::OnGoUp(wxCommandEvent & e)
1167{
1168 mScript->GoUp();
1169}
1170
1171void NyqBench::OnGoPrev(wxCommandEvent & e)
1172{
1173 mScript->GoPrev();
1174}
1175
1176void NyqBench::OnGoNext(wxCommandEvent & e)
1177{
1178 mScript->GoNext();
1179}
1180
1181void NyqBench::OnAutoWrap(wxCommandEvent & e)
1182{
1183 mAutoWrap = e.IsChecked();
1184
1185 wxWindow *parent = mScript->GetParent();
1186 wxString text = mScript->GetValue();
1187 bool focused = wxWindow::FindFocus() == mScript;
1188 long pos = mScript->GetInsertionPoint();
1189 long from;
1190 long to;
1191 mScript->GetSelection(&from, &to);
1192
1193 wxSizer *s = mScript->GetContainingSizer();
1194 s->Detach(mScript);
1195 delete mScript;
1196
1197 mScript = new NyqTextCtrl(parent,
1198 ID_SCRIPT,
1199 wxEmptyString,
1200 wxDefaultPosition,
1201 wxDefaultSize,
1202 (mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
1203 wxTE_NOHIDESEL | wxTE_RICH2 |
1204 wxTE_MULTILINE);
1205 s->Add(mScript, 1, wxEXPAND);
1206 s->Layout();
1207
1208 mScript->ChangeValue(text);
1209 mScript->SetInsertionPoint(pos);
1210 mScript->SetSelection(from, to);
1211
1212 if (focused) {
1213 mScript->SetFocus();
1214 }
1215}
1216
1217void NyqBench::OnFont(wxCommandEvent & e)
1218{
1219 wxWindow *w = FindFocus();
1220 wxFontData data;
1221 wxFontDialog dlg(this, data);
1222
1223 if (w != mScript && w != mOutput) {
1224 return;
1225 }
1226
1227 data.SetInitialFont(w == mScript ? mScriptFont : mOutputFont);
1228
1229 if (dlg.ShowModal() == wxID_OK) {
1230 wxFontData retData = dlg.GetFontData();
1231 wxFont font = retData.GetChosenFont();
1232 wxTextAttr attr;
1233 attr.SetFont(font);
1234
1235 if (w == mScript) {
1236 mScriptFont = font;
1237 }
1238 else {
1239 mOutputFont = font;
1240 }
1241
1242 ((wxTextCtrl *)w)->SetDefaultStyle(attr);
1243 ((wxTextCtrl *)w)->SetStyle(0, ((wxTextCtrl *)w)->GetLastPosition(), attr);
1244 w->Refresh();
1245 }
1246}
1247
1248void NyqBench::OnSplitV(wxCommandEvent & e)
1249{
1250 if (mSplitter->IsSplit()) {
1251 mSplitter->Unsplit();
1252 }
1253
1254 mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
1255}
1256
1257void NyqBench::OnSplitH(wxCommandEvent & e)
1258{
1259 if (mSplitter->IsSplit()) {
1260 mSplitter->Unsplit();
1261 }
1262
1263 mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
1264}
1265
1266void NyqBench::OnToggleCode(wxCommandEvent & e)
1267{
1268 if (e.IsChecked()) {
1269 if (mSplitter->IsSplit()) {
1270 // Should never happen
1271 return;
1272 }
1273
1274 if (mSplitMode == wxSPLIT_VERTICAL) {
1275 mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
1276 }
1277 else {
1278 mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
1279 }
1280 }
1281 else {
1282 if (!mSplitter->IsSplit()) {
1283 // Should never happen
1284 return;
1285 }
1286
1287 mSplitMode = mSplitter->GetSplitMode();
1288 mSplitter->Unsplit(mScript->GetParent());
1289 }
1290}
1291
1292void NyqBench::OnToggleOutput(wxCommandEvent & e)
1293{
1294 if (e.IsChecked()) {
1295 if (mSplitter->IsSplit()) {
1296 // Should never happen
1297 return;
1298 }
1299
1300 if (mSplitMode == wxSPLIT_VERTICAL) {
1301 mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
1302 }
1303 else {
1304 mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
1305 }
1306 }
1307 else {
1308 if (!mSplitter->IsSplit()) {
1309 // Should never happen
1310 return;
1311 }
1312
1313 mSplitMode = mSplitter->GetSplitMode();
1314 mSplitter->Unsplit(mOutput->GetParent());
1315 }
1316}
1317
1318void NyqBench::OnSmallIcons(wxCommandEvent & e)
1319{
1320 RecreateToolbar(false);
1321}
1322
1323void NyqBench::OnLargeIcons(wxCommandEvent & e)
1324{
1325 RecreateToolbar(true);
1326}
1327
1328void NyqBench::OnGo(wxCommandEvent & e)
1329{
1330 auto pEffect =
1331 std::make_unique<NyquistEffect>(L"Nyquist Effect Workbench");
1332 mEffect = pEffect.get();
1333 const PluginID & ID =
1334 EffectManager::Get().RegisterEffect(std::move(pEffect));
1335
1336 mEffect->SetCommand(mScript->GetValue());
1338
1339 auto p = GetActiveProject().lock();
1340 wxASSERT(p);
1341
1342 if (p) {
1343 wxWindowDisabler disable(this);
1345
1346 mRunning = true;
1347 UpdateWindowUI();
1348
1350
1351 mRunning = false;
1352 UpdateWindowUI();
1353 }
1354
1355 Raise();
1356
1358}
1359
1360void NyqBench::OnStop(wxCommandEvent & e)
1361{
1362 mRunning = false;
1363 mEffect->Stop();
1364}
1365
1366void NyqBench::OnAbout(wxCommandEvent & e)
1367{
1368 wxAboutDialogInfo i;
1369
1370 i.AddArtist(_("Harvey Lubin (logo)"));
1371 i.AddArtist(_("Tango Icon Gallery (toolbar icons)"));
1372 i.AddDeveloper(_("Leland Lucius"));
1373 i.SetCopyright(_("(C) 2009 by Leland Lucius"));
1374 i.SetDescription(_("External Audacity module which provides a simple IDE for writing effects."));
1375 i.SetName(_("Nyquist Effect Workbench"));
1376 i.SetVersion(__TDATE__);
1377
1378 wxAboutBox(i);
1379}
1380
1381void NyqBench::OnFindDialog(wxFindDialogEvent & e)
1382{
1383 wxEventType type = e.GetEventType();
1384
1385 if (type == wxEVT_COMMAND_FIND_CLOSE) {
1386 wxFindReplaceDialog *dlg = e.GetDialog();
1387
1388 dlg->Destroy();
1389
1390 int flags = mFindData.GetFlags();
1391
1392 gPrefs->Write(wxT("NyqBench/Find/Down"), (flags & wxFR_DOWN) != 0);
1393 gPrefs->Write(wxT("NyqBench/Find/Word"), (flags & wxFR_WHOLEWORD) != 0);
1394 gPrefs->Write(wxT("NyqBench/Find/Case"), (flags & wxFR_MATCHCASE) != 0);
1395
1396 mFindDlg = NULL;
1397 mFindText = NULL;
1398
1399 return;
1400 }
1401
1402 wxString text = mFindText->GetValue();
1403
1404#if defined(__WXMSW__)
1405 // We cheat on Windows. We know that the Windows text control
1406 // uses CRLF for line endings and if we don't account for that,
1407 // the selection positions will be off.
1408 //
1409 // Not sure why I thought I needed this, but it appears not to
1410 // be. Leaving just in case.
1411 //
1412 // text.Replace(wxT("\n"), wxT("\r\n"));
1413#endif
1414
1415 size_t startpos = mFindText->GetInsertionPoint();
1416 size_t len = mFindText->GetLastPosition();
1417 size_t pos;
1418
1419 wxString find = e.GetFindString();
1420 bool down = (e.GetFlags() & wxFR_DOWN) != 0;
1421 bool mixed = (e.GetFlags() & wxFR_MATCHCASE) != 0;
1422
1423 if (!mixed) {
1424 text.MakeUpper();
1425 find.MakeUpper();
1426 }
1427
1428 if (down) {
1429 pos = text.find(find, startpos);
1430 if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos < len) {
1431 pos = text.find(find, startpos + 1);
1432 }
1433 }
1434 else {
1435 pos = text.rfind(find, startpos);
1436 if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos > 0) {
1437 pos = text.rfind(find, startpos - 1);
1438 }
1439 }
1440
1441 if (pos == wxString::npos) {
1442 AudacityMessageBox(XO("No matches found"),
1443 XO("Nyquist Effect Workbench"),
1444 wxOK | wxCENTER,
1445 e.GetDialog());
1446
1447 return;
1448 }
1449
1450 mFindText->SetInsertionPoint((long)pos);
1451
1452#if defined(__WXGTK__)
1453 // GTK's selection and intertion pointer interact where the insertion
1454 // pointer winds up after the second parameter, so we reverse them to
1455 // force the pointer at the beginning of the selection. Doing so
1456 // allows reverse find to work properly.
1457 mFindText->SetSelection((long)(pos + find.Length()), (long)pos);
1458#else
1459 mFindText->SetSelection((long)pos, (long)(pos + find.Length()));
1460#endif
1461
1462#if defined(__WXMAC__)
1463 // Doing this coaxes the text control to update the selection. Without
1464 // it the selection doesn't appear to change if the found string is within
1465 // the currently displayed text, i.e., no reposition is needed.
1466 mFindText->Show(false);
1467 mFindText->Show(true);
1468#endif
1469}
1470
1471void NyqBench::OnTextUpdate(wxCommandEvent & e)
1472{
1473 // This really shouldn't be necessary, but Paste()ing doesn't mark the
1474 // control as dirty...at least on the Mac.
1475 ((NyqTextCtrl *) e.GetEventObject())->MarkDirty();
1476}
1477
1478void NyqBench::OnMenuUpdate(wxUpdateUIEvent & e)
1479{
1480 if (e.GetId() != wxID_REVERT_TO_SAVED) {
1481 e.Enable((mScript->GetLastPosition() > 0) || mScript->IsModified());
1482 }
1483 else {
1484 e.Enable(mScript->IsModified());
1485 }
1486}
1487
1488void NyqBench::OnUndoUpdate(wxUpdateUIEvent & e)
1489{
1490 e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanUndo());
1491}
1492
1493void NyqBench::OnRedoUpdate(wxUpdateUIEvent & e)
1494{
1495 e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanRedo());
1496}
1497
1498void NyqBench::OnCutUpdate(wxUpdateUIEvent & e)
1499{
1500 e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCut());
1501}
1502
1503void NyqBench::OnCopyUpdate(wxUpdateUIEvent & e)
1504{
1505 e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCopy());
1506}
1507
1508void NyqBench::OnPasteUpdate(wxUpdateUIEvent & e)
1509{
1510 e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanPaste());
1511}
1512
1513void NyqBench::OnClearUpdate(wxUpdateUIEvent & e)
1514{
1515 e.Enable(FindFocus() == mOutput ? true : false);
1516}
1517
1518void NyqBench::OnViewUpdate(wxUpdateUIEvent & e)
1519{
1520 wxMenuBar *bar = GetMenuBar();
1521 bar->Enable(ID_SPLITV, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_VERTICAL);
1522 bar->Enable(ID_SPLITH, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_HORIZONTAL);
1523 bar->Check(ID_TOGGLECODE, mScript->GetParent()->IsShown());
1524 bar->Check(ID_TOGGLEOUTPUT, mOutput->GetParent()->IsShown());
1525 bar->Check(ID_LARGEICONS, mLargeIcons);
1526 bar->Check(ID_SMALLICONS, !mLargeIcons);
1527}
1528
1529void NyqBench::OnRunUpdate(wxUpdateUIEvent & e)
1530{
1531 auto p = GetActiveProject().lock();
1532 wxToolBar *tbar = GetToolBar();
1533 wxMenuBar *mbar = GetMenuBar();
1534
1535 auto gAudioIO = AudioIOBase::Get();
1536 if (p && gAudioIO->IsBusy()) {
1537 mbar->Enable(ID_GO, false);
1538 mbar->Enable(ID_STOP, false);
1539
1540 tbar->EnableTool(ID_GO, false);
1541 tbar->EnableTool(ID_STOP, false);
1542 }
1543 else {
1544 mbar->Enable(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
1545 mbar->Enable(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
1546
1547 tbar->EnableTool(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
1548 tbar->EnableTool(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
1549 }
1550}
1551
1552void NyqBench::OnScriptUpdate(wxUpdateUIEvent & e)
1553{
1554 if (mScriptBox && mScript && FindFocus() == mScript) {
1555 wxString label = mScriptBox->GetLabel();
1556 if (label == _("Script")) {
1557 label += wxT("*");
1558 mScriptBox->SetLabel(label);
1559 mOutputBox->SetLabel(_("Output"));
1560 }
1561 }
1562}
1563
1564void NyqBench::OnOutputUpdate(wxUpdateUIEvent & e)
1565{
1566 if (mOutputBox && mOutput && FindFocus() == mOutput) {
1567 wxString label = mOutputBox->GetLabel();
1568 if (label == _("Output")) {
1569 label += wxT("*");
1570 mOutputBox->SetLabel(label);
1571 mScriptBox->SetLabel(_("Script"));
1572 }
1573 }
1574}
1575
1577{
1578 if (mScript->GetLastPosition() > 0 && mScript->IsModified()) {
1579 int ans;
1580 ans = AudacityMessageBox(XO("Code has been modified. Are you sure?"),
1581 XO("Warning"),
1582 wxYES_NO | wxICON_QUESTION,
1583 this);
1584 if (ans == wxNO) {
1585 return false;
1586 }
1587 }
1588
1589 return true;
1590}
1591
1593{
1594 wxString name = _("Untitled");
1595
1596 if (!mPath.GetFullPath().IsEmpty()) {
1597 name = mPath.GetFullName();
1598 }
1599
1600 SetTitle(_("Nyquist Effect Workbench - ") + name);
1601}
1602
1604{
1605 mLargeIcons = large;
1606
1607 wxToolBar *tb = GetToolBar();
1608 if (tb) {
1609 delete tb;
1610 }
1611 tb = CreateToolBar();
1612
1613 wxSize sz;
1614
1615 if (!mLargeIcons) {
1616 tb->SetToolBitmapSize(wxSize(16, 16));
1617 mPics[0] = wxBitmap(document_new_small);
1618 mPics[1] = wxBitmap(document_open_small);
1619 mPics[2] = wxBitmap(document_save_as_small);
1620 mPics[3] = wxBitmap(document_save_small);
1621 mPics[4] = wxBitmap(edit_copy_small);
1622 mPics[5] = wxBitmap(edit_cut_small);
1623 mPics[6] = wxBitmap(edit_paste_small);
1624 mPics[7] = wxBitmap(edit_clear_small);
1625 mPics[8] = wxBitmap(edit_delete_small);
1626 mPics[9] = wxBitmap(edit_select_all_small);
1627 mPics[10] = wxBitmap(edit_undo_small);
1628 mPics[11] = wxBitmap(edit_redo_small);
1629 mPics[12] = wxBitmap(edit_find_small);
1630 mPics[13] = wxBitmap(system_search_small);
1631 mPics[14] = wxBitmap(go_top_small);
1632 mPics[15] = wxBitmap(go_up_small);
1633 mPics[16] = wxBitmap(go_previous_small);
1634 mPics[17] = wxBitmap(go_next_small);
1635 mPics[18] = wxBitmap(media_playback_start_small);
1636 mPics[19] = wxBitmap(media_playback_stop_small);
1637 }
1638 else {
1639 tb->SetToolBitmapSize(wxSize(32, 32));
1640 mPics[0] = wxBitmap(document_new_large);
1641 mPics[1] = wxBitmap(document_open_large);
1642 mPics[2] = wxBitmap(document_save_as_large);
1643 mPics[3] = wxBitmap(document_save_large);
1644 mPics[4] = wxBitmap(edit_copy_large);
1645 mPics[5] = wxBitmap(edit_cut_large);
1646 mPics[6] = wxBitmap(edit_paste_large);
1647 mPics[7] = wxBitmap(edit_clear_large);
1648 mPics[8] = wxBitmap(edit_delete_large);
1649 mPics[9] = wxBitmap(edit_select_all_large);
1650 mPics[10] = wxBitmap(edit_undo_large);
1651 mPics[11] = wxBitmap(edit_redo_large);
1652 mPics[12] = wxBitmap(edit_find_large);
1653 mPics[13] = wxBitmap(system_search_large);
1654 mPics[14] = wxBitmap(go_top_large);
1655 mPics[15] = wxBitmap(go_up_large);
1656 mPics[16] = wxBitmap(go_previous_large);
1657 mPics[17] = wxBitmap(go_next_large);
1658 mPics[18] = wxBitmap(media_playback_start_large);
1659 mPics[19] = wxBitmap(media_playback_stop_large);
1660 }
1661
1662 tb->SetMargins(2, 2);
1663
1664 tb->AddTool(wxID_NEW, _("New"), mPics[0], _("New script"));
1665 tb->AddTool(wxID_OPEN, _("Open"), mPics[1], _("Open script"));
1666 tb->AddTool(wxID_SAVE, _("Save"), mPics[2], _("Save script"));
1667 tb->AddTool(wxID_SAVEAS, _("Save As"), mPics[3], _("Save script as..."));
1668 tb->AddSeparator();
1669 tb->AddTool(wxID_COPY, _("Copy"), mPics[4], _("Copy to clipboard"));
1670 tb->AddTool(wxID_CUT, _("Cut"), mPics[5], _("Cut to clipboard"));
1671 tb->AddTool(wxID_PASTE, _("Paste"), mPics[6], _("Paste from clipboard"));
1672 tb->AddTool(wxID_CLEAR, _("Clear"), mPics[7], _("Clear selection"));
1673 tb->AddTool(wxID_SELECTALL, _("Select All"), mPics[9], _("Select all text"));
1674 tb->AddSeparator();
1675 tb->AddTool(wxID_UNDO, _("Undo"), mPics[10], _("Undo last change"));
1676 tb->AddTool(wxID_REDO, _("Redo"), mPics[11], _("Redo previous change"));
1677 tb->AddSeparator();
1678 tb->AddTool(wxID_FIND, _("Find"), mPics[12], _("Find text"));
1679 tb->AddSeparator();
1680 tb->AddTool(ID_MATCH, _("Match"), mPics[13], _("Go to matching paren"));
1681 tb->AddTool(ID_TOP, _("Top"), mPics[14], _("Go to top S-expr"));
1682 tb->AddTool(ID_UP, _("Up"), mPics[15], _("Go to higher S-expr"));
1683 tb->AddTool(ID_PREVIOUS, _("Previous"), mPics[16], _("Go to previous S-expr"));
1684 tb->AddTool(ID_NEXT, _("Next"), mPics[17], _("Go to next S-expr"));
1685 tb->AddSeparator();
1686 tb->AddTool(ID_GO, _("Start"), mPics[18], _("Start script"));
1687 tb->AddTool(ID_STOP, _("Stop"), mPics[19], _("Stop script"));
1688
1689 tb->Realize();
1690
1691 Layout();
1692 Fit();
1693 SetMinSize(GetSize());
1694}
1695
1697{
1698 wxString path = mPath.GetFullPath();
1699
1700 if (path.IsEmpty()) {
1701 return;
1702 }
1703
1704 wxFFile f(path);
1705 if (f.IsOpened()) {
1706 wxString t;
1707 if (f.ReadAll(&t)) {
1708//#if defined(__WXGTK__) || defined(__WXMAC__)
1709 t.Replace(wxT("\r\n"), wxT("\n"));
1710 t.Replace(wxT("\r"), wxT("\n"));
1711//#elif defined(__WXMSW__)
1712// t.Replace("\r\n", "\n");
1713//#endif
1714 mScript->SetValue(t);
1715 mScript->DiscardEdits();
1716 }
1717 }
1718
1719// mScript->LoadFile(mPath.GetFullPath());
1720}
1721
1722//----------------------------------------------------------------------------
1723// Connects Audacity menu item to an action in this dll.
1724// Only one action implemented so far.
1725//----------------------------------------------------------------------------
1727{
1728 Show();
1729}
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
Handle changing of active project and keep global project pointer.
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
END_EVENT_TABLE()
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & AudioIONotBusyFlag()
const TranslatableString name
Definition: Distortion.cpp:76
wxString PluginID
Definition: EffectManager.h:30
const TranslatableString desc
Definition: ExportPCM.cpp:55
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define _(s)
Definition: Internat.h:73
#define DLL_API
ModuleDispatchTypes
@ ModuleInitialize
@ AppQuiting
int DLL_API ModuleDispatch(ModuleDispatchTypes type)
Definition: NyqBench.cpp:126
@ ID_SPLITV
Definition: NyqBench.cpp:548
@ ID_PREVIOUS
Definition: NyqBench.cpp:557
@ ID_TOP
Definition: NyqBench.cpp:555
@ ID_STOP
Definition: NyqBench.cpp:561
@ ID_TOGGLEOUTPUT
Definition: NyqBench.cpp:551
@ ID_LARGEICONS
Definition: NyqBench.cpp:553
@ ID_GO
Definition: NyqBench.cpp:560
@ ID_MATCH
Definition: NyqBench.cpp:554
@ ID_AUTOWRAP
Definition: NyqBench.cpp:545
@ ID_SPLITH
Definition: NyqBench.cpp:549
@ ID_OUTPUT
Definition: NyqBench.cpp:564
@ ID_FONT
Definition: NyqBench.cpp:547
@ ID_UP
Definition: NyqBench.cpp:556
@ ID_NEXT
Definition: NyqBench.cpp:558
@ ID_AUTOLOAD
Definition: NyqBench.cpp:543
@ ID_SCRIPT
Definition: NyqBench.cpp:563
@ ID_SMALLICONS
Definition: NyqBench.cpp:552
@ ID_TOGGLECODE
Definition: NyqBench.cpp:550
static DEFINE_VERSION_CHECK NyqBench * gBench
Definition: NyqBench.cpp:121
FileConfig * gPrefs
Definition: Prefs.cpp:70
@ eIsCreating
Definition: ShuttleGui.h:37
TranslatableString label
Definition: TagsEditor.cpp:164
#define S(N)
Definition: ToChars.cpp:64
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:91
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
static EffectManager & Get()
const PluginID & RegisterEffect(std::unique_ptr< EffectPlugin > uEffect)
Here solely for the purpose of Nyquist Workbench until a better solution is devised.
void UnregisterEffect(const PluginID &ID)
Used only by Nyquist Workbench module.
bool mShowCode
Definition: NyqBench.h:200
wxStaticBox * mOutputBox
Definition: NyqBench.h:183
int mSplitMode
Definition: NyqBench.h:199
void OnScriptUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1552
void OnGoPrev(wxCommandEvent &e)
Definition: NyqBench.cpp:1171
void OnPasteUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1508
void OnMenuUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1478
void OnCopy(wxCommandEvent &e)
Definition: NyqBench.cpp:1108
void OnCloseWindow(wxCommandEvent &e)
Definition: NyqBench.cpp:974
wxFileName mPath
Definition: NyqBench.h:207
static NyqBench * GetBench()
Definition: NyqBench.cpp:638
void OnClearUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1513
wxFont mOutputFont
Definition: NyqBench.h:195
void OnOpen(wxCommandEvent &e)
Definition: NyqBench.cpp:997
wxFindReplaceData mFindData
Definition: NyqBench.h:189
void OnSmallIcons(wxCommandEvent &e)
Definition: NyqBench.cpp:1318
NyqTextCtrl * mOutput
Definition: NyqBench.h:185
void OnAbout(wxCommandEvent &e)
Definition: NyqBench.cpp:1366
void OnAutoWrap(wxCommandEvent &e)
Definition: NyqBench.cpp:1181
void OnFind(wxCommandEvent &e)
Definition: NyqBench.cpp:1128
virtual ~NyqBench()
Definition: NyqBench.cpp:806
void OnToggleOutput(wxCommandEvent &e)
Definition: NyqBench.cpp:1292
wxFont mScriptFont
Definition: NyqBench.h:194
void OnCutUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1498
void OnFont(wxCommandEvent &e)
Definition: NyqBench.cpp:1217
NyqTextCtrl * mScript
Definition: NyqBench.h:184
virtual bool Validate()
Definition: NyqBench.cpp:1576
void OnClose(wxCloseEvent &e)
Definition: NyqBench.cpp:948
void OnSplitH(wxCommandEvent &e)
Definition: NyqBench.cpp:1257
bool mLargeIcons
Definition: NyqBench.h:203
void OnFindDialog(wxFindDialogEvent &e)
Definition: NyqBench.cpp:1381
void OnRedoUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1493
void OnSaveAs(wxCommandEvent &e)
Definition: NyqBench.cpp:1043
NyqTextCtrl * mFindText
Definition: NyqBench.h:190
void OnRedo(wxCommandEvent &e)
Definition: NyqBench.cpp:1098
bool mAutoWrap
Definition: NyqBench.h:209
void LoadFile()
Definition: NyqBench.cpp:1696
void OnMove(wxMoveEvent &e)
Definition: NyqBench.cpp:958
void OnCopyUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1503
wxSplitterWindow * mSplitter
Definition: NyqBench.h:186
void OnLargeIcons(wxCommandEvent &e)
Definition: NyqBench.cpp:1323
void OnAutoLoad(wxCommandEvent &e)
Definition: NyqBench.cpp:1075
wxBitmap mPics[20]
Definition: NyqBench.h:197
void OnUndo(wxCommandEvent &e)
Definition: NyqBench.cpp:1093
void OnRunUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1529
void SavePrefs()
Definition: NyqBench.cpp:810
void OnOutputUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1564
void OnUndoUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1488
void OnSplitV(wxCommandEvent &e)
Definition: NyqBench.cpp:1248
void OnRevert(wxCommandEvent &e)
Definition: NyqBench.cpp:1080
void OnToggleCode(wxCommandEvent &e)
Definition: NyqBench.cpp:1266
void OnNew(wxCommandEvent &e)
Definition: NyqBench.cpp:979
void OnCut(wxCommandEvent &e)
Definition: NyqBench.cpp:1103
void OnSelectAll(wxCommandEvent &e)
Definition: NyqBench.cpp:1123
void OnViewUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:1518
void OnGoMatch(wxCommandEvent &e)
Definition: NyqBench.cpp:1156
void RecreateToolbar(bool large=false)
Definition: NyqBench.cpp:1603
void OnClear(wxCommandEvent &e)
Definition: NyqBench.cpp:1118
void ShowNyqBench(const CommandContext &)
Definition: NyqBench.cpp:1726
NyqBench(wxWindow *parent)
Definition: NyqBench.cpp:648
wxRect mLastSize
Definition: NyqBench.h:211
void OnGoUp(wxCommandEvent &e)
Definition: NyqBench.cpp:1166
void SetWindowTitle()
Definition: NyqBench.cpp:1592
wxFindReplaceDialog * mFindDlg
Definition: NyqBench.h:188
void OnGoNext(wxCommandEvent &e)
Definition: NyqBench.cpp:1176
void OnGo(wxCommandEvent &e)
Definition: NyqBench.cpp:1328
void OnStop(wxCommandEvent &e)
Definition: NyqBench.cpp:1360
bool mRunning
Definition: NyqBench.h:205
void OnPaste(wxCommandEvent &e)
Definition: NyqBench.cpp:1113
bool mAutoLoad
Definition: NyqBench.h:208
void OnSave(wxCommandEvent &e)
Definition: NyqBench.cpp:1022
NyquistEffect * mEffect
Definition: NyqBench.h:192
void OnTextUpdate(wxCommandEvent &e)
Definition: NyqBench.cpp:1471
void PopulateOrExchange(ShuttleGui &S)
Definition: NyqBench.cpp:839
void OnGoTop(wxCommandEvent &e)
Definition: NyqBench.cpp:1161
void OnSize(wxSizeEvent &e)
Definition: NyqBench.cpp:966
wxStaticBox * mScriptBox
Definition: NyqBench.h:182
bool mShowOutput
Definition: NyqBench.h:201
NyqRedirector(NyqTextCtrl *text)
Definition: NyqBench.cpp:506
virtual ~NyqRedirector()
Definition: NyqBench.cpp:512
std::string s
Definition: NyqBench.h:90
NyqTextCtrl * mText
Definition: NyqBench.h:92
int overflow(int c)
Definition: NyqBench.cpp:521
void AppendText()
Definition: NyqBench.cpp:531
std::streambuf * mOld
Definition: NyqBench.h:91
wxTextAttr mOff
Definition: NyqBench.h:70
void FindParens()
Definition: NyqBench.cpp:428
wxLongToLongHashMap mLeftParens
Definition: NyqBench.h:61
void GoTop()
Definition: NyqBench.cpp:297
wxLongToLongHashMap mRightParens
Definition: NyqBench.h:62
void OnKeyUp(wxKeyEvent &e)
Definition: NyqBench.cpp:242
void SetFocusFromKbd()
Definition: NyqBench.cpp:179
wxTextAttr mOn
Definition: NyqBench.h:69
void MoveCursor(long first, long second)
Definition: NyqBench.cpp:381
long mRightParen
Definition: NyqBench.h:65
void GoUp()
Definition: NyqBench.cpp:319
void Colorize(long left, long right)
Definition: NyqBench.cpp:398
void GoPrev()
Definition: NyqBench.cpp:341
void MarkDirty()
Definition: NyqBench.cpp:190
long mLastCaretPos
Definition: NyqBench.h:67
void GoMatch()
Definition: NyqBench.cpp:292
void GoNext()
Definition: NyqBench.cpp:361
void OnChar(wxKeyEvent &e)
Definition: NyqBench.cpp:196
long mLeftParen
Definition: NyqBench.h:64
void OnUpdate(wxUpdateUIEvent &e)
Definition: NyqBench.cpp:265
void RedirectOutput()
Definition: Nyquist.cpp:1851
void SetCommand(const wxString &cmd)
Definition: Nyquist.cpp:1856
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:625
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
Definition: BasicUI.h:343
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1263
std::unique_ptr< MenuPart > Section(const Identifier &internalName, Args &&... args)
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
CommandHandlerObject & findme(AudacityProject &)
Definition: NyqBench.cpp:99