mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-30 15:49:41 +02:00
... and deduce whether to exclude from macros inside NewIdentifier, simplifying argument lists further Also fix the localization of "..." added to names by PluginMenus.cpp
1787 lines
48 KiB
C++
Executable File
1787 lines
48 KiB
C++
Executable File
/**********************************************************************
|
|
|
|
NyqBench.cpp
|
|
|
|
Leland Lucius
|
|
|
|
**********************************************************************/
|
|
|
|
#include "Audacity.h"
|
|
|
|
#include <wx/defs.h>
|
|
|
|
#include <wx/aboutdlg.h>
|
|
#include <wx/filedlg.h>
|
|
#include <wx/font.h>
|
|
#include <wx/fontdlg.h>
|
|
#include <wx/menu.h>
|
|
#include <wx/msgdlg.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/splitter.h>
|
|
#include <wx/statbox.h>
|
|
#include <wx/textctrl.h>
|
|
#include <wx/toolbar.h>
|
|
|
|
#include "AudioIOBase.h"
|
|
#include "CommonCommandFlags.h"
|
|
#include "LabelTrack.h"
|
|
#include "ModuleManager.h"
|
|
#include "Prefs.h"
|
|
#include "Project.h"
|
|
#include "ShuttleGui.h"
|
|
#include "effects/EffectManager.h"
|
|
#include "effects/nyquist/Nyquist.h"
|
|
#include "../images/AudacityLogo.xpm"
|
|
#include "../../src/commands/CommandContext.h"
|
|
#include "widgets/AudacityMessageBox.h"
|
|
|
|
#include "NyqBench.h"
|
|
|
|
#include <iostream>
|
|
#include <ostream>
|
|
#include <sstream>
|
|
|
|
//
|
|
// Images are from the Tango Icon Gallery
|
|
// http://tango.freedesktop.org/Tango_Icon_Gallery
|
|
//
|
|
#include "images/document-new-small.xpm"
|
|
#include "images/document-open-small.xpm"
|
|
#include "images/document-save-as-small.xpm"
|
|
#include "images/document-save-small.xpm"
|
|
#include "images/edit-clear-small.xpm"
|
|
#include "images/edit-copy-small.xpm"
|
|
#include "images/edit-cut-small.xpm"
|
|
#include "images/edit-delete-small.xpm"
|
|
#include "images/edit-find-small.xpm"
|
|
#include "images/edit-paste-small.xpm"
|
|
#include "images/edit-redo-small.xpm"
|
|
#include "images/edit-select-all-small.xpm"
|
|
#include "images/edit-undo-small.xpm"
|
|
#include "images/go-top-small.xpm"
|
|
#include "images/go-up-small.xpm"
|
|
#include "images/go-previous-small.xpm"
|
|
#include "images/go-next-small.xpm"
|
|
#include "images/system-search-small.xpm"
|
|
#include "images/media-playback-start-small.xpm"
|
|
#include "images/media-playback-stop-small.xpm"
|
|
|
|
#include "images/document-new-large.xpm"
|
|
#include "images/document-open-large.xpm"
|
|
#include "images/document-save-as-large.xpm"
|
|
#include "images/document-save-large.xpm"
|
|
#include "images/edit-clear-large.xpm"
|
|
#include "images/edit-copy-large.xpm"
|
|
#include "images/edit-cut-large.xpm"
|
|
#include "images/edit-delete-large.xpm"
|
|
#include "images/edit-find-large.xpm"
|
|
#include "images/edit-paste-large.xpm"
|
|
#include "images/edit-redo-large.xpm"
|
|
#include "images/edit-select-all-large.xpm"
|
|
#include "images/edit-undo-large.xpm"
|
|
#include "images/go-top-large.xpm"
|
|
#include "images/go-up-large.xpm"
|
|
#include "images/go-previous-large.xpm"
|
|
#include "images/go-next-large.xpm"
|
|
#include "images/system-search-large.xpm"
|
|
#include "images/media-playback-start-large.xpm"
|
|
#include "images/media-playback-stop-large.xpm"
|
|
|
|
#if defined(__WXMSW__)
|
|
#include <wx/init.h>
|
|
# if defined(__WXDEBUG__)
|
|
# define D "d"
|
|
# else
|
|
# define D ""
|
|
# endif
|
|
# if wxCHECK_VERSION(3, 1, 0)
|
|
# define V "31"
|
|
# elif wxCHECK_VERSION(3, 0, 0)
|
|
# define V "30"
|
|
# else
|
|
# define V "28"
|
|
# endif
|
|
|
|
# pragma comment(lib, "wxbase" V "u" D)
|
|
# pragma comment(lib, "wxbase" V "u" D "_net")
|
|
# pragma comment(lib, "wxmsw" V "u" D "_adv")
|
|
# pragma comment(lib, "wxmsw" V "u" D "_core")
|
|
# pragma comment(lib, "wxmsw" V "u" D "_html")
|
|
# pragma comment(lib, "wxpng" D)
|
|
# pragma comment(lib, "wxzlib" D)
|
|
# pragma comment(lib, "wxjpeg" D)
|
|
# pragma comment(lib, "wxtiff" D)
|
|
|
|
# undef V
|
|
# undef D
|
|
|
|
#endif //(__WXMSW__)
|
|
/*
|
|
There are several functions that can be used in a GUI module.
|
|
|
|
//#define versionFnName "GetVersionString"
|
|
If the version is wrong, the module will be rejected.
|
|
That is it will be loaded and then unloaded.
|
|
|
|
//#define ModuleDispatchName "ModuleDispatch"
|
|
The most useful function. See the example in this
|
|
file. It has several cases/options in it.
|
|
|
|
//#define scriptFnName "RegScriptServerFunc"
|
|
This function is run from a non gui thread. It was originally
|
|
created for the benefit of mod-script-pipe.
|
|
|
|
//#define mainPanelFnName "MainPanelFunc"
|
|
This function is the hijacking function, to take over Audacity
|
|
and replace the main project window with our own wxFrame.
|
|
|
|
*/
|
|
|
|
extern "C"
|
|
{
|
|
static NyqBench *gBench = NULL;
|
|
|
|
static CommandHandlerObject &findme(AudacityProject&)
|
|
{
|
|
return *NyqBench::GetBench();
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
#define DLL_API _declspec(dllexport)
|
|
#else
|
|
#define DLL_API __attribute__ ((visibility("default")))
|
|
#endif
|
|
|
|
extern DLL_API const wxChar * GetVersionString();
|
|
// GetVersionString
|
|
// REQUIRED for the module to be accepted by Audacity.
|
|
// Without it Audacity will see a version number mismatch.
|
|
const wxChar * GetVersionString()
|
|
{
|
|
// For now, the versions must match exactly for Audacity to
|
|
// agree to load the module.
|
|
return AUDACITY_VERSION_STRING;
|
|
}
|
|
|
|
extern int DLL_API ModuleDispatch(ModuleDispatchTypes type);
|
|
// ModuleDispatch
|
|
// is called by Audacity to initialize/terminmate the module,
|
|
// and ask if it has anything for the menus.
|
|
int ModuleDispatch(ModuleDispatchTypes type){
|
|
switch (type){
|
|
case AppQuiting: {
|
|
//It is perfectly OK for gBench to be NULL.
|
|
//Can happen if the menu item was never invoked.
|
|
//wxASSERT(gBench != NULL);
|
|
if (gBench) {
|
|
gBench->Destroy();
|
|
gBench = NULL;
|
|
}
|
|
}
|
|
break;
|
|
case ProjectInitialized:
|
|
case MenusRebuilt: {
|
|
AudacityProject *p = GetActiveProject();
|
|
wxASSERT(p != NULL);
|
|
CommandManager *c = &CommandManager::Get( *p );
|
|
wxASSERT(c != NULL);
|
|
|
|
wxMenuBar * pBar = GetProjectFrame( *p ).GetMenuBar();
|
|
wxASSERT(pBar != NULL );
|
|
wxMenu * pMenu = pBar->GetMenu( 9 ); // Menu 9 is the Tools Menu.
|
|
wxASSERT( pMenu != NULL );
|
|
|
|
c->SetCurrentMenu(pMenu);
|
|
c->AddSeparator();
|
|
c->AddItem(wxT("NyqBench"),
|
|
XO("&Nyquist Workbench..."),
|
|
findme,
|
|
static_cast<CommandFunctorPointer>(&NyqBench::ShowNyqBench),
|
|
AudioIONotBusyFlag);
|
|
|
|
c->ClearCurrentMenu();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqTextCtrl
|
|
//----------------------------------------------------------------------------
|
|
|
|
BEGIN_EVENT_TABLE(NyqTextCtrl, wxTextCtrl)
|
|
#if defined(__WXMAC__)
|
|
EVT_KEY_DOWN(NyqTextCtrl::OnKeyDown)
|
|
#endif
|
|
EVT_KEY_UP(NyqTextCtrl::OnKeyUp)
|
|
EVT_CHAR(NyqTextCtrl::OnChar)
|
|
EVT_UPDATE_UI(wxID_ANY, NyqTextCtrl::OnUpdate)
|
|
END_EVENT_TABLE()
|
|
|
|
NyqTextCtrl::NyqTextCtrl(wxWindow *parent,
|
|
wxWindowID id,
|
|
const wxString &value,
|
|
const wxPoint & pos,
|
|
const wxSize & size,
|
|
int style)
|
|
: wxTextCtrl(parent, id, value, pos, size, style)
|
|
{
|
|
mLastCaretPos = -1;
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
mOn.SetTextColour(*wxRED);
|
|
mOff.SetTextColour(*wxBLACK);
|
|
}
|
|
|
|
void NyqTextCtrl::SetFocusFromKbd()
|
|
{
|
|
#if defined(__WXMSW__)
|
|
// We do this to prevent wxMSW from selecting all text when the
|
|
// user tabs into the text controls.
|
|
wxWindowBase::SetFocusFromKbd();
|
|
#else
|
|
wxTextCtrl::SetFocusFromKbd();
|
|
#endif
|
|
}
|
|
|
|
void NyqTextCtrl::MarkDirty()
|
|
{
|
|
wxTextCtrl::MarkDirty();
|
|
FindParens();
|
|
}
|
|
|
|
void NyqTextCtrl::OnChar(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
|
|
// Hide any previously highlighted parens
|
|
if (mLeftParen >= 0) {
|
|
#if defined(__WXMSW__)
|
|
Freeze(); // Prevents selection flashing on Windows
|
|
#endif
|
|
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOff);
|
|
SetStyle(mLeftParens[mLeftParen], mLeftParens[mLeftParen] + 1, mOff);
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
#if defined(__WXMSW__)
|
|
Thaw(); // Prevents selection flashing on Windows
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if defined(__WXMAC__REMOVED_UNTIL_ITS_PROVEN_THAT_IT_IS_STILL_NEEDED)
|
|
#include <wx/mac/uma.h>
|
|
|
|
// This is hackage to correct a problem on Leopard where the
|
|
// caret jumps up two lines when the up arrow is pressed and
|
|
// the caret is at the beginning of the line.
|
|
void NyqTextCtrl::OnKeyDown(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (UMAGetSystemVersion() >= 0x1050) {
|
|
if (e.GetKeyCode() == WXK_UP && e.GetModifiers() == 0) {
|
|
long x;
|
|
long y;
|
|
|
|
PositionToXY(GetInsertionPoint(), &x, &y);
|
|
if (x == 0 && y > 1) {
|
|
y--;
|
|
SetInsertionPoint(XYToPosition(x, y) - 1);
|
|
e.Skip(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void NyqTextCtrl::OnKeyUp(wxKeyEvent & e)
|
|
{
|
|
e.Skip();
|
|
|
|
int pos = GetInsertionPoint();
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
|
|
if (text[0] == wxT('(')) {
|
|
wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
|
|
if (left != mLeftParens.end()) {
|
|
Colorize(lpos, left->second);
|
|
}
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
|
|
if (right != mRightParens.end()) {
|
|
Colorize(right->second, lpos);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::OnUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
int pos = GetInsertionPoint();
|
|
|
|
if (pos != mLastCaretPos) {
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
if (text.Length() > 0) {
|
|
if (text[0] == wxT('(')) {
|
|
wxLongToLongHashMap::const_iterator left = mLeftParens.find(lpos);
|
|
if (left != mLeftParens.end()) {
|
|
Colorize(lpos, left->second);
|
|
}
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
wxLongToLongHashMap::const_iterator right = mRightParens.find(lpos);
|
|
if (right != mRightParens.end()) {
|
|
Colorize(right->second, lpos);
|
|
}
|
|
}
|
|
}
|
|
|
|
mLastCaretPos = pos;
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoMatch()
|
|
{
|
|
MoveCursor(mRightParen, mLeftParen);
|
|
}
|
|
|
|
void NyqTextCtrl::GoTop()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (mLeftParen > it->first && mLeftParen < it->second) {
|
|
if (first == -1 || it->first < first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoUp()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (mLeftParen > it->first && mLeftParen < it->second) {
|
|
if (first == -1 || it->first > first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoPrev()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (it->first < mLeftParen && it->first >= first) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::GoNext()
|
|
{
|
|
wxLongToLongHashMap::const_iterator it;
|
|
long first = -1;
|
|
long second = -1;
|
|
|
|
if (mLeftParen != -1) {
|
|
for (it = mLeftParens.begin(); it != mLeftParens.end(); it++) {
|
|
if (it->first > mLeftParen && (first == -1 || it->first < first)) {
|
|
first = it->first;
|
|
second = it->second;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (first != -1) {
|
|
MoveCursor(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::MoveCursor(long first, long second)
|
|
{
|
|
int pos = GetInsertionPoint();
|
|
int lpos = wxMax(0, pos - 1);
|
|
|
|
wxString text = GetRange(lpos, pos);
|
|
|
|
if (text[0] == wxT('(')) {
|
|
SetInsertionPoint(first + 1);
|
|
Colorize(first, second);
|
|
}
|
|
else if (text[0] == wxT(')')) {
|
|
SetInsertionPoint(second + 1);
|
|
Colorize(first, second);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::Colorize(long left, long right)
|
|
{
|
|
// Hide any previously highlighted parens
|
|
if (mLeftParen >= 0) {
|
|
#if defined(__WXMSW__)
|
|
Freeze(); // Prevents selection flashing on Windows
|
|
#endif
|
|
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOff);
|
|
SetStyle(mLeftParens[mLeftParen], mLeftParens[mLeftParen] + 1, mOff);
|
|
mLeftParen = -1;
|
|
mRightParen = -1;
|
|
|
|
#if defined(__WXMSW__)
|
|
Thaw(); // Prevents selection flashing on Windows
|
|
#endif
|
|
}
|
|
|
|
mLeftParen = left;
|
|
mRightParen = right;
|
|
|
|
if (mLeftParen != -1) {
|
|
SetStyle(mLeftParen, mLeftParen + 1, mOn);
|
|
SetStyle(mRightParen, mRightParen + 1, mOn);
|
|
|
|
SetStyle(mLeftParen + 1, mLeftParen + 1, mOff);
|
|
SetStyle(mRightParen + 1, mRightParen + 1, mOff);
|
|
}
|
|
}
|
|
|
|
void NyqTextCtrl::FindParens()
|
|
{
|
|
wxString text = GetValue();
|
|
bool inquotes = false;
|
|
wxArrayInt stack;
|
|
long len = (long) text.Length();
|
|
long pos;
|
|
|
|
mLeftParens.clear();
|
|
mRightParens.clear();
|
|
|
|
for (pos = 0; pos < len; pos++) {
|
|
wxChar c = text[pos];
|
|
switch (c)
|
|
{
|
|
case wxT('"'):
|
|
inquotes = !inquotes;
|
|
break;
|
|
|
|
case wxT(';'):
|
|
if (!inquotes) {
|
|
pos = (long)text.find(wxT('\n'), pos);
|
|
if (pos == (long)wxString::npos) {
|
|
pos = len;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case wxT('#'):
|
|
if (!inquotes) {
|
|
long ndx = pos + 1;
|
|
if (ndx < len && text[(int)ndx] == wxT('|')) {
|
|
// Shamelessly stolen from xlread.c/pcomment()
|
|
wxChar lastch = -1;
|
|
int n = 1;
|
|
|
|
/* look for the matching delimiter (and handle nesting) */
|
|
while (n > 0 && ++pos < len) {
|
|
wxChar ch = text[(int)pos];
|
|
if (lastch == '|' && ch == '#') {
|
|
--n;
|
|
ch = -1;
|
|
}
|
|
else if (lastch == '#' && ch == '|') {
|
|
++n;
|
|
ch = -1;
|
|
}
|
|
lastch = ch;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case wxT('('):
|
|
if (!inquotes) {
|
|
stack.Add(pos);
|
|
}
|
|
break;
|
|
|
|
case wxT(')'):
|
|
if (!inquotes) {
|
|
if (stack.GetCount() > 0) {
|
|
int left = stack.Last();
|
|
stack.RemoveAt(stack.GetCount() - 1);
|
|
|
|
mLeftParens[left] = pos;
|
|
mRightParens[pos] = left;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqRedirector
|
|
//----------------------------------------------------------------------------
|
|
|
|
NyqRedirector::NyqRedirector(NyqTextCtrl *text)
|
|
: mText(text)
|
|
{
|
|
mOld = std::cout.rdbuf(this);
|
|
}
|
|
|
|
NyqRedirector::~NyqRedirector()
|
|
{
|
|
std::cout.flush();
|
|
std::cout.rdbuf(mOld);
|
|
if (s.length() > 0) {
|
|
AppendText();
|
|
}
|
|
}
|
|
|
|
int NyqRedirector::overflow(int c)
|
|
{
|
|
s += (char)c;
|
|
if (c == '\n') {
|
|
AppendText();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void NyqRedirector::AppendText()
|
|
{
|
|
mText->AppendText(wxString(s.c_str(), wxConvISO8859_1));
|
|
s.clear();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// NyqBench
|
|
//----------------------------------------------------------------------------
|
|
|
|
enum
|
|
{
|
|
ID_AUTOLOAD = 20000,
|
|
|
|
ID_AUTOWRAP,
|
|
|
|
ID_FONT,
|
|
ID_SPLITV,
|
|
ID_SPLITH,
|
|
ID_TOGGLECODE,
|
|
ID_TOGGLEOUTPUT,
|
|
ID_SMALLICONS,
|
|
ID_LARGEICONS,
|
|
ID_MATCH,
|
|
ID_TOP,
|
|
ID_UP,
|
|
ID_PREVIOUS,
|
|
ID_NEXT,
|
|
|
|
ID_GO,
|
|
ID_STOP,
|
|
|
|
ID_SCRIPT,
|
|
ID_OUTPUT
|
|
};
|
|
|
|
BEGIN_EVENT_TABLE(NyqBench, wxFrame)
|
|
EVT_CLOSE(NyqBench::OnClose)
|
|
EVT_MOVE(NyqBench::OnMove)
|
|
EVT_SIZE(NyqBench::OnSize)
|
|
|
|
EVT_MENU(wxID_NEW, NyqBench::OnNew)
|
|
EVT_MENU(wxID_OPEN, NyqBench::OnOpen)
|
|
EVT_MENU(wxID_SAVE, NyqBench::OnSave)
|
|
EVT_MENU(wxID_SAVEAS, NyqBench::OnSaveAs)
|
|
EVT_MENU(wxID_REVERT_TO_SAVED, NyqBench::OnRevert)
|
|
EVT_MENU(ID_AUTOLOAD, NyqBench::OnAutoLoad)
|
|
EVT_MENU(wxID_CLOSE, NyqBench::OnCloseWindow)
|
|
|
|
EVT_MENU(wxID_UNDO, NyqBench::OnUndo)
|
|
EVT_MENU(wxID_REDO, NyqBench::OnRedo)
|
|
EVT_MENU(wxID_CUT, NyqBench::OnCut)
|
|
EVT_MENU(wxID_COPY, NyqBench::OnCopy)
|
|
EVT_MENU(wxID_PASTE, NyqBench::OnPaste)
|
|
EVT_MENU(wxID_CLEAR, NyqBench::OnClear)
|
|
EVT_MENU(wxID_SELECTALL, NyqBench::OnSelectAll)
|
|
EVT_MENU(wxID_FIND, NyqBench::OnFind)
|
|
EVT_MENU(ID_MATCH, NyqBench::OnGoMatch)
|
|
EVT_MENU(ID_TOP, NyqBench::OnGoTop)
|
|
EVT_MENU(ID_UP, NyqBench::OnGoUp)
|
|
EVT_MENU(ID_PREVIOUS, NyqBench::OnGoPrev)
|
|
EVT_MENU(ID_NEXT, NyqBench::OnGoNext)
|
|
EVT_MENU(ID_AUTOWRAP, NyqBench::OnAutoWrap)
|
|
|
|
EVT_MENU(ID_FONT, NyqBench::OnFont)
|
|
EVT_MENU(ID_SPLITV, NyqBench::OnSplitV)
|
|
EVT_MENU(ID_SPLITH, NyqBench::OnSplitH)
|
|
EVT_MENU(ID_TOGGLECODE, NyqBench::OnToggleCode)
|
|
EVT_MENU(ID_TOGGLEOUTPUT, NyqBench::OnToggleOutput)
|
|
EVT_MENU(ID_SMALLICONS, NyqBench::OnSmallIcons)
|
|
EVT_MENU(ID_LARGEICONS, NyqBench::OnLargeIcons)
|
|
|
|
EVT_MENU(ID_GO, NyqBench::OnGo)
|
|
EVT_MENU(ID_STOP, NyqBench::OnStop)
|
|
|
|
EVT_MENU(wxID_ABOUT, NyqBench::OnAbout)
|
|
|
|
EVT_FIND(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_NEXT(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_REPLACE(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_REPLACE_ALL(wxID_ANY, NyqBench::OnFindDialog)
|
|
EVT_FIND_CLOSE(wxID_ANY, NyqBench::OnFindDialog)
|
|
|
|
EVT_TEXT(ID_SCRIPT, NyqBench::OnTextUpdate)
|
|
|
|
EVT_UPDATE_UI(wxID_SAVE, NyqBench::OnMenuUpdate)
|
|
EVT_UPDATE_UI(wxID_SAVEAS, NyqBench::OnMenuUpdate)
|
|
EVT_UPDATE_UI(wxID_REVERT_TO_SAVED, NyqBench::OnMenuUpdate)
|
|
|
|
EVT_UPDATE_UI(wxID_UNDO, NyqBench::OnUndoUpdate)
|
|
EVT_UPDATE_UI(wxID_REDO, NyqBench::OnRedoUpdate)
|
|
EVT_UPDATE_UI(wxID_CUT, NyqBench::OnCutUpdate)
|
|
EVT_UPDATE_UI(wxID_COPY, NyqBench::OnCopyUpdate)
|
|
EVT_UPDATE_UI(wxID_PASTE, NyqBench::OnPasteUpdate)
|
|
EVT_UPDATE_UI(wxID_CLEAR, NyqBench::OnClearUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_SPLITH, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_SPLITV, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_TOGGLECODE, NyqBench::OnViewUpdate)
|
|
EVT_UPDATE_UI(ID_TOGGLEOUTPUT, NyqBench::OnViewUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_GO, NyqBench::OnRunUpdate)
|
|
|
|
EVT_UPDATE_UI(ID_SCRIPT, NyqBench::OnScriptUpdate)
|
|
EVT_UPDATE_UI(ID_OUTPUT, NyqBench::OnOutputUpdate)
|
|
END_EVENT_TABLE()
|
|
|
|
/*static*/ NyqBench *NyqBench::GetBench()
|
|
{
|
|
if (gBench == nullptr)
|
|
{
|
|
gBench = new NyqBench(NULL);
|
|
}
|
|
|
|
return gBench;
|
|
}
|
|
|
|
NyqBench::NyqBench(wxWindow * parent)
|
|
: wxFrame(NULL,
|
|
wxID_ANY,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxDEFAULT_FRAME_STYLE |
|
|
wxMINIMIZE_BOX |
|
|
wxMAXIMIZE_BOX |
|
|
wxRESIZE_BORDER)
|
|
{
|
|
mFindDlg = NULL;
|
|
mRunning = false;
|
|
mScriptBox = NULL;
|
|
mOutputBox = NULL;
|
|
mScript = NULL;
|
|
mOutput = NULL;
|
|
|
|
mPath = gPrefs->Read(wxT("NyqBench/Path"), wxEmptyString);
|
|
mAutoLoad = (gPrefs->Read(wxT("NyqBench/AutoLoad"), 0L) != 0);
|
|
mAutoWrap = (gPrefs->Read(wxT("NyqBench/AutoWrap"), true) != 0);
|
|
mLargeIcons = (gPrefs->Read(wxT("NyqBench/LargeIcons"), 0L) != 0);
|
|
mSplitMode = gPrefs->Read(wxT("NyqBench/SplitMode"), wxSPLIT_VERTICAL);
|
|
mShowCode = (gPrefs->Read(wxT("NyqBench/ShowScript"), true) != 0);
|
|
mShowOutput = (gPrefs->Read(wxT("NyqBench/ShowOutput"), true) != 0);
|
|
|
|
SetIcon(wxICON(AudacityLogo));
|
|
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
|
|
ShuttleGui S(this, eIsCreating);
|
|
PopulateOrExchange(S);
|
|
wxMenuBar *bar = new wxMenuBar();
|
|
|
|
wxMenu *menu = new wxMenu();
|
|
menu->Append(wxID_NEW, wxT("&New\tCtrl+N"));
|
|
menu->Append(wxID_OPEN, wxT("&Open...\tCtrl+O"));
|
|
menu->Append(wxID_SAVE, wxT("&Save...\tCtrl+S"));
|
|
menu->Append(wxID_SAVEAS, wxT("Save &As...\tCtrl+Shift+S"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_REVERT_TO_SAVED, _T("&Revert to Saved"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_AUTOLOAD, _T("Auto &Load Last File"))->Check(mAutoLoad);
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_CLOSE, wxT("&Close Window\tCtrl+W"));
|
|
bar->Append(menu, wxT("&File"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
|
|
menu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
|
|
menu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
|
|
menu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
|
|
menu->Append(wxID_CLEAR, _("Cle&ar\tCtrl+L"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
|
|
menu->AppendSeparator();
|
|
menu->Append(wxID_FIND, _("&Find...\tCtrl+F"));
|
|
menu->AppendSeparator();
|
|
wxMenu *sub = new wxMenu();
|
|
sub->Append(ID_MATCH, _("&Matching Paren\tF8"));
|
|
sub->Append(ID_TOP, _("&Top S-expr\tF9"));
|
|
sub->Append(ID_UP, _("&Higher S-expr\tF10"));
|
|
sub->Append(ID_PREVIOUS, _("&Previous S-expr\tF11"));
|
|
sub->Append(ID_NEXT, _("&Next S-expr\tF12"));
|
|
menu->AppendSubMenu(sub, _("&Go to"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_AUTOWRAP, _T("Auto &Wrap"))->Check(mAutoWrap);
|
|
bar->Append(menu, wxT("&Edit"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(ID_FONT, _("Select &Font..."));
|
|
menu->AppendSeparator();
|
|
menu->Append(ID_SPLITV, _("Split &Vertically"));
|
|
menu->Append(ID_SPLITH, _("Split &Horizontally"));
|
|
menu->AppendSeparator();
|
|
menu->AppendCheckItem(ID_TOGGLECODE, _("Show S&cript"));
|
|
menu->AppendCheckItem(ID_TOGGLEOUTPUT, _("Show &Output"));
|
|
menu->AppendSeparator();
|
|
sub = new wxMenu();
|
|
sub->AppendRadioItem(ID_LARGEICONS, _("&Large Icons"));
|
|
sub->AppendRadioItem(ID_SMALLICONS, _("&Small Icons"));
|
|
menu->AppendSubMenu(sub, _("Toolbar"));
|
|
bar->Append(menu, wxT("&View"));
|
|
|
|
menu = new wxMenu();
|
|
menu->Append(ID_GO, _("&Go\tF5"));
|
|
menu->Append(ID_STOP, _("&Stop\tF6"));
|
|
bar->Append(menu, wxT("&Run"));
|
|
|
|
#if defined(__WXMAC__)
|
|
menu->Append(wxID_ABOUT, _("&About"));
|
|
#else
|
|
menu = new wxMenu();
|
|
menu->Append(wxID_ABOUT, _("&About"));
|
|
bar->Append(menu, wxT("Help"));
|
|
#endif
|
|
|
|
SetMenuBar(bar);
|
|
|
|
RecreateToolbar(mLargeIcons);
|
|
|
|
wxRect r;
|
|
r.SetX(gPrefs->Read(wxT("NyqBench/Window/X"), -1));
|
|
r.SetY(gPrefs->Read(wxT("NyqBench/Window/Y"), -1));
|
|
r.SetWidth(gPrefs->Read(wxT("NyqBench/Window/Width"), -1));
|
|
r.SetHeight(gPrefs->Read(wxT("NyqBench/Window/Height"), -1));
|
|
if (r == wxRect(-1, -1, -1, -1)) {
|
|
Center();
|
|
}
|
|
else {
|
|
SetSize(r);
|
|
}
|
|
|
|
bool maximized = false;
|
|
gPrefs->Read(wxT("NyqBench/Window/Maximized"), maximized);
|
|
if (maximized) {
|
|
Maximize();
|
|
}
|
|
|
|
long sashpos;
|
|
sashpos = gPrefs->Read(wxT("NyqBench/SplitX"), 0l);
|
|
if (sashpos > 0) {
|
|
mSplitter->SetSashPosition(sashpos);
|
|
}
|
|
|
|
wxString dflt = wxSystemSettings::GetFont(wxSYS_SYSTEM_FONT).GetNativeFontInfoDesc();
|
|
wxString desc;
|
|
wxTextAttr attr;
|
|
|
|
desc = gPrefs->Read(wxT("NyqBench/ScriptFont"), dflt);
|
|
mScriptFont.SetNativeFontInfo(desc);
|
|
#if defined(__WXMSW__)
|
|
// Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
|
|
// I don't know if this is something I'm doing wrong, but I'll have to look at this
|
|
// later if I get bored.
|
|
mScriptFont.SetEncoding(wxFONTENCODING_SYSTEM);
|
|
#endif
|
|
attr.SetFont(mScriptFont);
|
|
mScript->SetDefaultStyle(attr);
|
|
|
|
desc = gPrefs->Read(wxT("NyqBench/OutputFont"), dflt);
|
|
mOutputFont.SetNativeFontInfo(desc);
|
|
#if defined(__WXMSW__)
|
|
// Force SYSTEM encoding to prevent conversion to Unicode in wxTextCtrl::DoWriteText().
|
|
// I don't know if this is something I'm doing wrong, but I'll have to look at this
|
|
// later if I get bored.
|
|
mOutputFont.SetEncoding(wxFONTENCODING_SYSTEM);
|
|
#endif
|
|
attr.SetFont(mOutputFont);
|
|
mOutput->SetDefaultStyle(attr);
|
|
|
|
if (mAutoLoad && !mPath.GetFullPath().IsEmpty()) {
|
|
LoadFile();
|
|
}
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
NyqBench::~NyqBench()
|
|
{
|
|
gPrefs->Write(wxT("NyqBench/Window/Maximized"), IsMaximized());
|
|
if (!IsMaximized()) {
|
|
wxRect r = GetRect();
|
|
|
|
#if !defined(__WXMAC__)
|
|
if (IsIconized()) {
|
|
r = mLastSize;
|
|
}
|
|
#endif
|
|
|
|
gPrefs->Write(wxT("NyqBench/Window/X"), r.GetX());
|
|
gPrefs->Write(wxT("NyqBench/Window/Y"), r.GetY());
|
|
gPrefs->Write(wxT("NyqBench/Window/Width"), r.GetWidth());
|
|
gPrefs->Write(wxT("NyqBench/Window/Height"), r.GetHeight());
|
|
}
|
|
|
|
gPrefs->Write(wxT("NyqBench/AutoLoad"), mAutoLoad);
|
|
gPrefs->Write(wxT("NyqBench/AutoWrap"), mAutoWrap);
|
|
gPrefs->Write(wxT("NyqBench/ScriptFont"), mScriptFont.GetNativeFontInfoDesc());
|
|
gPrefs->Write(wxT("NyqBench/OutputFont"), mOutputFont.GetNativeFontInfoDesc());
|
|
gPrefs->Write(wxT("NyqBench/LargeIcons"), mLargeIcons);
|
|
gPrefs->Write(wxT("NyqBench/SplitX"), mSplitter->IsSplit() ? mSplitter->GetSashPosition() : 0);
|
|
gPrefs->Write(wxT("NyqBench/SplitMode"), mSplitter->IsSplit() ? mSplitter->GetSplitMode() : 0);
|
|
gPrefs->Write(wxT("NyqBench/ShowCode"), mScript->IsShown());
|
|
gPrefs->Write(wxT("NyqBench/ShowOutput"), mOutput->IsShown());
|
|
}
|
|
|
|
void NyqBench::PopulateOrExchange(ShuttleGui & S)
|
|
{
|
|
S.StartHorizontalLay(wxEXPAND, true);
|
|
{
|
|
wxPanel *scriptp;
|
|
wxPanel *outputp;
|
|
wxStaticBoxSizer *scripts;
|
|
wxStaticBoxSizer *outputs;
|
|
wxBoxSizer *bs;
|
|
|
|
mSplitter = new wxSplitterWindow(this,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxSP_LIVE_UPDATE |
|
|
wxSP_3DSASH |
|
|
wxSP_NOBORDER);
|
|
|
|
scriptp = new wxPanel(mSplitter,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxNO_FULL_REPAINT_ON_RESIZE |
|
|
wxCLIP_CHILDREN);
|
|
bs = new wxBoxSizer(wxVERTICAL);
|
|
scriptp->SetSizer(bs);
|
|
|
|
mScriptBox = new wxStaticBox(scriptp,
|
|
wxID_ANY,
|
|
_("Script"));
|
|
|
|
scripts = new wxStaticBoxSizer(mScriptBox,
|
|
wxVERTICAL);
|
|
bs->Add(scripts, true, wxEXPAND);
|
|
|
|
mScript = new NyqTextCtrl(scriptp,
|
|
ID_SCRIPT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxTE_RICH2 | wxTE_RICH |
|
|
(mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
|
|
wxTE_NOHIDESEL |
|
|
wxTE_MULTILINE);
|
|
scripts->Add(mScript, true, wxEXPAND);
|
|
|
|
outputp = new wxPanel(mSplitter,
|
|
wxID_ANY,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxNO_FULL_REPAINT_ON_RESIZE |
|
|
wxCLIP_CHILDREN);
|
|
bs = new wxBoxSizer(wxVERTICAL);
|
|
outputp->SetSizer(bs);
|
|
|
|
mOutputBox = new wxStaticBox(outputp,
|
|
wxID_ANY,
|
|
_("Output"));
|
|
outputs = new wxStaticBoxSizer(mOutputBox,
|
|
wxVERTICAL);
|
|
bs->Add(outputs, true, wxEXPAND);
|
|
|
|
mOutput = new NyqTextCtrl(outputp,
|
|
ID_OUTPUT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
wxTE_READONLY |
|
|
#if !defined(__WXMAC__)
|
|
// I could not get the bloody horizontal scroll bar to appear on
|
|
// wxMac, so we can't use wxTE_DONTWRAP as you can't easily scroll
|
|
// left and right.
|
|
wxTE_DONTWRAP |
|
|
#endif
|
|
wxTE_NOHIDESEL |
|
|
wxTE_MULTILINE);
|
|
outputs->Add(mOutput, true, wxEXPAND);
|
|
|
|
switch (mSplitMode)
|
|
{
|
|
case wxSPLIT_VERTICAL:
|
|
mSplitter->SplitVertically(scriptp, outputp, 300);
|
|
break;
|
|
|
|
case wxSPLIT_HORIZONTAL:
|
|
mSplitter->SplitHorizontally(scriptp, outputp, 300);
|
|
break;
|
|
|
|
default:
|
|
mSplitter->Initialize((mShowCode ? scriptp : outputp));
|
|
break;
|
|
}
|
|
|
|
mSplitter->SetMinimumPaneSize(50);
|
|
|
|
S.AddSpace(5, 1);
|
|
S.Prop(true);
|
|
S.Position(wxEXPAND).AddWindow(mSplitter);
|
|
S.AddSpace(5, 1);
|
|
|
|
mSplitter->SetMinSize(wxSize(600, 400));
|
|
}
|
|
S.EndHorizontalLay();
|
|
|
|
S.AddSpace(1, 5);
|
|
|
|
return;
|
|
}
|
|
|
|
void NyqBench::OnClose(wxCloseEvent & e)
|
|
{
|
|
if (!Validate()) {
|
|
e.Veto();
|
|
}
|
|
else {
|
|
Show(false);
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnMove(wxMoveEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (!IsIconized() && !IsMaximized()) {
|
|
mLastSize.SetPosition(e.GetPosition());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSize(wxSizeEvent & e)
|
|
{
|
|
e.Skip();
|
|
if (!IsIconized() && !IsMaximized()) {
|
|
mLastSize.SetSize(e.GetSize());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnCloseWindow(wxCommandEvent & e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void NyqBench::OnNew(wxCommandEvent & e)
|
|
{
|
|
if (!Validate()) {
|
|
return;
|
|
}
|
|
|
|
mPath.SetFullName(wxEmptyString);
|
|
|
|
while (mScript->CanUndo()) {
|
|
mScript->Undo();
|
|
}
|
|
|
|
mScript->Clear();
|
|
mScript->DiscardEdits();
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnOpen(wxCommandEvent & e)
|
|
{
|
|
if (mScript->IsModified() && !Validate()) {
|
|
return;
|
|
}
|
|
|
|
wxFileDialog dlog(this,
|
|
_("Load Nyquist script"),
|
|
mPath.GetPath(),
|
|
wxEmptyString,
|
|
_("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
|
|
wxFD_OPEN | wxRESIZE_BORDER);
|
|
|
|
if (dlog.ShowModal() != wxID_OK) {
|
|
return;
|
|
}
|
|
|
|
mPath = dlog.GetPath();
|
|
gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
|
|
|
|
LoadFile();
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnSave(wxCommandEvent & e)
|
|
{
|
|
if (mScript->GetLastPosition() == 0) {
|
|
return;
|
|
}
|
|
|
|
if (mPath.GetFullPath().IsEmpty()) {
|
|
OnSaveAs(e);
|
|
return;
|
|
}
|
|
|
|
if (!mScript->SaveFile(mPath.GetFullPath()))
|
|
{
|
|
AudacityMessageBox(_("Script was not saved."),
|
|
_("Warning"),
|
|
wxICON_EXCLAMATION,
|
|
this);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSaveAs(wxCommandEvent & e)
|
|
{
|
|
if (mScript->GetLastPosition() == 0) {
|
|
return;
|
|
}
|
|
|
|
wxFileDialog dlog(this,
|
|
_("Save Nyquist script"),
|
|
mPath.GetFullPath(),
|
|
wxEmptyString,
|
|
_("Nyquist scripts (*.ny)|*.ny|Lisp scripts (*.lsp)|*.lsp|All files|*"),
|
|
wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
|
|
|
|
if (dlog.ShowModal() != wxID_OK) {
|
|
return;
|
|
}
|
|
|
|
mPath = dlog.GetPath();
|
|
gPrefs->Write(wxT("NyqBench/Path"), mPath.GetFullPath());
|
|
|
|
if (!mScript->SaveFile(mPath.GetFullPath()))
|
|
{
|
|
AudacityMessageBox(_("Script was not saved."),
|
|
_("Warning"),
|
|
wxICON_EXCLAMATION,
|
|
this);
|
|
return;
|
|
}
|
|
|
|
SetWindowTitle();
|
|
}
|
|
|
|
void NyqBench::OnAutoLoad(wxCommandEvent & e)
|
|
{
|
|
mAutoLoad = e.IsChecked();
|
|
}
|
|
|
|
void NyqBench::OnRevert(wxCommandEvent & e)
|
|
{
|
|
if (mPath.GetFullPath().IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
if (!Validate()) {
|
|
return;
|
|
}
|
|
|
|
LoadFile();
|
|
}
|
|
|
|
void NyqBench::OnUndo(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Undo();
|
|
}
|
|
|
|
void NyqBench::OnRedo(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Redo();
|
|
}
|
|
|
|
void NyqBench::OnCut(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Cut();
|
|
}
|
|
|
|
void NyqBench::OnCopy(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Copy();
|
|
}
|
|
|
|
void NyqBench::OnPaste(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Paste();
|
|
}
|
|
|
|
void NyqBench::OnClear(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->Clear();
|
|
}
|
|
|
|
void NyqBench::OnSelectAll(wxCommandEvent & e)
|
|
{
|
|
(FindFocus() == mScript ? mScript : mOutput)->SetSelection(-1, -1);
|
|
}
|
|
|
|
void NyqBench::OnFind(wxCommandEvent & e)
|
|
{
|
|
if (mFindDlg ) {
|
|
delete mFindDlg;
|
|
mFindDlg = NULL;
|
|
}
|
|
else {
|
|
NyqTextCtrl *w = (NyqTextCtrl *) FindFocus();
|
|
if (w == mScript || w == mOutput) {
|
|
mFindText = w;
|
|
|
|
int flags = 0;
|
|
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Down"), 0L) ? wxFR_DOWN : 0);
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Word"), 0L) ? wxFR_WHOLEWORD : 0);
|
|
flags |= (gPrefs->Read(wxT("NyqBench/Find/Case"), 0L) ? wxFR_MATCHCASE : 0);
|
|
|
|
mFindData.SetFlags(flags);
|
|
|
|
mFindDlg = new wxFindReplaceDialog(this,
|
|
&mFindData,
|
|
_("Find dialog"),
|
|
wxFR_NOWHOLEWORD);
|
|
mFindDlg->Show(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnGoMatch(wxCommandEvent & e)
|
|
{
|
|
mScript->GoMatch();
|
|
}
|
|
|
|
void NyqBench::OnGoTop(wxCommandEvent & e)
|
|
{
|
|
mScript->GoTop();
|
|
}
|
|
|
|
void NyqBench::OnGoUp(wxCommandEvent & e)
|
|
{
|
|
mScript->GoUp();
|
|
}
|
|
|
|
void NyqBench::OnGoPrev(wxCommandEvent & e)
|
|
{
|
|
mScript->GoPrev();
|
|
}
|
|
|
|
void NyqBench::OnGoNext(wxCommandEvent & e)
|
|
{
|
|
mScript->GoNext();
|
|
}
|
|
|
|
void NyqBench::OnAutoWrap(wxCommandEvent & e)
|
|
{
|
|
mAutoWrap = e.IsChecked();
|
|
|
|
wxWindow *parent = mScript->GetParent();
|
|
wxString text = mScript->GetValue();
|
|
bool focused = wxWindow::FindFocus() == mScript;
|
|
long pos = mScript->GetInsertionPoint();
|
|
long from;
|
|
long to;
|
|
mScript->GetSelection(&from, &to);
|
|
|
|
wxSizer *s = mScript->GetContainingSizer();
|
|
s->Detach(mScript);
|
|
delete mScript;
|
|
|
|
mScript = new NyqTextCtrl(parent,
|
|
ID_SCRIPT,
|
|
wxEmptyString,
|
|
wxDefaultPosition,
|
|
wxDefaultSize,
|
|
(mAutoWrap ? wxTE_BESTWRAP : wxTE_DONTWRAP) |
|
|
wxTE_NOHIDESEL | wxTE_RICH2 |
|
|
wxTE_MULTILINE);
|
|
s->Add(mScript, 1, wxEXPAND);
|
|
s->Layout();
|
|
|
|
mScript->ChangeValue(text);
|
|
mScript->SetInsertionPoint(pos);
|
|
mScript->SetSelection(from, to);
|
|
|
|
if (focused) {
|
|
mScript->SetFocus();
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnFont(wxCommandEvent & e)
|
|
{
|
|
wxWindow *w = FindFocus();
|
|
wxFontData data;
|
|
wxFontDialog dlg(this, data);
|
|
|
|
if (w != mScript && w != mOutput) {
|
|
return;
|
|
}
|
|
|
|
data.SetInitialFont(w == mScript ? mScriptFont : mOutputFont);
|
|
|
|
if (dlg.ShowModal() == wxID_OK) {
|
|
wxFontData retData = dlg.GetFontData();
|
|
wxFont font = retData.GetChosenFont();
|
|
wxTextAttr attr;
|
|
attr.SetFont(font);
|
|
|
|
if (w == mScript) {
|
|
mScriptFont = font;
|
|
}
|
|
else {
|
|
mOutputFont = font;
|
|
}
|
|
|
|
((wxTextCtrl *)w)->SetDefaultStyle(attr);
|
|
((wxTextCtrl *)w)->SetStyle(0, ((wxTextCtrl *)w)->GetLastPosition(), attr);
|
|
w->Refresh();
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSplitV(wxCommandEvent & e)
|
|
{
|
|
if (mSplitter->IsSplit()) {
|
|
mSplitter->Unsplit();
|
|
}
|
|
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
|
|
void NyqBench::OnSplitH(wxCommandEvent & e)
|
|
{
|
|
if (mSplitter->IsSplit()) {
|
|
mSplitter->Unsplit();
|
|
}
|
|
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
|
|
void NyqBench::OnToggleCode(wxCommandEvent & e)
|
|
{
|
|
if (e.IsChecked()) {
|
|
if (mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
if (mSplitMode == wxSPLIT_VERTICAL) {
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
else {
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
}
|
|
else {
|
|
if (!mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
mSplitMode = mSplitter->GetSplitMode();
|
|
mSplitter->Unsplit(mScript->GetParent());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnToggleOutput(wxCommandEvent & e)
|
|
{
|
|
if (e.IsChecked()) {
|
|
if (mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
if (mSplitMode == wxSPLIT_VERTICAL) {
|
|
mSplitter->SplitVertically(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
else {
|
|
mSplitter->SplitHorizontally(mScript->GetParent(), mOutput->GetParent());
|
|
}
|
|
}
|
|
else {
|
|
if (!mSplitter->IsSplit()) {
|
|
// Should never happen
|
|
return;
|
|
}
|
|
|
|
mSplitMode = mSplitter->GetSplitMode();
|
|
mSplitter->Unsplit(mOutput->GetParent());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnSmallIcons(wxCommandEvent & e)
|
|
{
|
|
RecreateToolbar(false);
|
|
}
|
|
|
|
void NyqBench::OnLargeIcons(wxCommandEvent & e)
|
|
{
|
|
RecreateToolbar(true);
|
|
}
|
|
|
|
void NyqBench::OnGo(wxCommandEvent & e)
|
|
{
|
|
// No need to delete...EffectManager will do it
|
|
mEffect = new NyquistEffect(wxT("Nyquist Effect Workbench"));
|
|
const PluginID & ID = EffectManager::Get().RegisterEffect(mEffect);
|
|
|
|
mEffect->SetCommand(mScript->GetValue());
|
|
mEffect->RedirectOutput();
|
|
|
|
AudacityProject *p = GetActiveProject();
|
|
wxASSERT(p != NULL);
|
|
|
|
if (p) {
|
|
wxWindowDisabler disable(this);
|
|
NyqRedirector redir((NyqTextCtrl *)mOutput);
|
|
|
|
mRunning = true;
|
|
UpdateWindowUI();
|
|
|
|
EffectManager::DoEffect(ID, CommandContext(*p), 0);
|
|
|
|
mRunning = false;
|
|
UpdateWindowUI();
|
|
}
|
|
|
|
Raise();
|
|
|
|
EffectManager::Get().UnregisterEffect(ID);
|
|
}
|
|
|
|
void NyqBench::OnStop(wxCommandEvent & e)
|
|
{
|
|
mRunning = false;
|
|
mEffect->Stop();
|
|
}
|
|
|
|
void NyqBench::OnAbout(wxCommandEvent & e)
|
|
{
|
|
wxAboutDialogInfo i;
|
|
|
|
i.AddArtist(_("Harvey Lubin (logo)"));
|
|
i.AddArtist(_("Tango Icon Gallery (toolbar icons)"));
|
|
i.AddDeveloper(_("Leland Lucius"));
|
|
i.SetCopyright(_("(C) 2009 by Leland Lucius"));
|
|
i.SetDescription(_("External Audacity module which provides a simple IDE for writing effects."));
|
|
i.SetName(_("Nyquist Effect Workbench"));
|
|
i.SetVersion(__TDATE__);
|
|
|
|
wxAboutBox(i);
|
|
}
|
|
|
|
void NyqBench::OnFindDialog(wxFindDialogEvent & e)
|
|
{
|
|
wxEventType type = e.GetEventType();
|
|
|
|
if (type == wxEVT_COMMAND_FIND_CLOSE) {
|
|
wxFindReplaceDialog *dlg = e.GetDialog();
|
|
|
|
dlg->Destroy();
|
|
|
|
int flags = mFindData.GetFlags();
|
|
|
|
gPrefs->Write(wxT("NyqBench/Find/Down"), (flags & wxFR_DOWN) != 0);
|
|
gPrefs->Write(wxT("NyqBench/Find/Word"), (flags & wxFR_WHOLEWORD) != 0);
|
|
gPrefs->Write(wxT("NyqBench/Find/Case"), (flags & wxFR_MATCHCASE) != 0);
|
|
|
|
mFindDlg = NULL;
|
|
mFindText = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
wxString text = mFindText->GetValue();
|
|
|
|
#if defined(__WXMSW__)
|
|
// We cheat on Windows. We know that the Windows text control
|
|
// uses CRLF for line endings and if we don't account for that,
|
|
// the selection positions will be off.
|
|
//
|
|
// Not sure why I thought I needed this, but it appears not to
|
|
// be. Leaving just in case.
|
|
//
|
|
// text.Replace(wxT("\n"), wxT("\r\n"));
|
|
#endif
|
|
|
|
size_t startpos = mFindText->GetInsertionPoint();
|
|
size_t len = mFindText->GetLastPosition();
|
|
size_t pos;
|
|
|
|
wxString find = e.GetFindString();
|
|
bool down = (e.GetFlags() & wxFR_DOWN) != 0;
|
|
bool mixed = (e.GetFlags() & wxFR_MATCHCASE) != 0;
|
|
|
|
if (!mixed) {
|
|
text.MakeUpper();
|
|
find.MakeUpper();
|
|
}
|
|
|
|
if (down) {
|
|
pos = text.find(find, startpos);
|
|
if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos < len) {
|
|
pos = text.find(find, startpos + 1);
|
|
}
|
|
}
|
|
else {
|
|
pos = text.rfind(find, startpos);
|
|
if (type == wxEVT_COMMAND_FIND_NEXT && pos == startpos && pos > 0) {
|
|
pos = text.rfind(find, startpos - 1);
|
|
}
|
|
}
|
|
|
|
if (pos == wxString::npos) {
|
|
AudacityMessageBox(_("No matches found"),
|
|
_("Nyquist Effect Workbench"),
|
|
wxOK | wxCENTER,
|
|
e.GetDialog());
|
|
|
|
return;
|
|
}
|
|
|
|
mFindText->SetInsertionPoint((long)pos);
|
|
|
|
#if defined(__WXGTK__)
|
|
// GTK's selection and intertion pointer interact where the insertion
|
|
// pointer winds up after the second parameter, so we reverse them to
|
|
// force the pointer at the beginning of the selection. Doing so
|
|
// allows reverse find to work properly.
|
|
mFindText->SetSelection((long)(pos + find.Length()), (long)pos);
|
|
#else
|
|
mFindText->SetSelection((long)pos, (long)(pos + find.Length()));
|
|
#endif
|
|
|
|
#if defined(__WXMAC__)
|
|
// Doing this coaxes the text control to update the selection. Without
|
|
// it the selection doesn't appear to change if the found string is within
|
|
// the currently displayed text, i.e., no reposition is needed.
|
|
mFindText->Show(false);
|
|
mFindText->Show(true);
|
|
#endif
|
|
}
|
|
|
|
void NyqBench::OnTextUpdate(wxCommandEvent & e)
|
|
{
|
|
// This really shouldn't be necessary, but Paste()ing doesn't mark the
|
|
// control as dirty...at least on the Mac.
|
|
((NyqTextCtrl *) e.GetEventObject())->MarkDirty();
|
|
}
|
|
|
|
void NyqBench::OnMenuUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (e.GetId() != wxID_REVERT_TO_SAVED) {
|
|
e.Enable((mScript->GetLastPosition() > 0) || mScript->IsModified());
|
|
}
|
|
else {
|
|
e.Enable(mScript->IsModified());
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnUndoUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanUndo());
|
|
}
|
|
|
|
void NyqBench::OnRedoUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanRedo());
|
|
}
|
|
|
|
void NyqBench::OnCutUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCut());
|
|
}
|
|
|
|
void NyqBench::OnCopyUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanCopy());
|
|
}
|
|
|
|
void NyqBench::OnPasteUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable((FindFocus() == mScript ? mScript : mOutput)->CanPaste());
|
|
}
|
|
|
|
void NyqBench::OnClearUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
e.Enable(FindFocus() == mOutput ? true : false);
|
|
}
|
|
|
|
void NyqBench::OnViewUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
wxMenuBar *bar = GetMenuBar();
|
|
bar->Enable(ID_SPLITV, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_VERTICAL);
|
|
bar->Enable(ID_SPLITH, !mSplitter->IsSplit() || mSplitter->GetSplitMode() != wxSPLIT_HORIZONTAL);
|
|
bar->Check(ID_TOGGLECODE, mScript->GetParent()->IsShown());
|
|
bar->Check(ID_TOGGLEOUTPUT, mOutput->GetParent()->IsShown());
|
|
bar->Check(ID_LARGEICONS, mLargeIcons);
|
|
bar->Check(ID_SMALLICONS, !mLargeIcons);
|
|
}
|
|
|
|
void NyqBench::OnRunUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
AudacityProject *p = GetActiveProject();
|
|
wxToolBar *tbar = GetToolBar();
|
|
wxMenuBar *mbar = GetMenuBar();
|
|
|
|
auto gAudioIO = AudioIOBase::Get();
|
|
if (p && gAudioIO->IsBusy()) {
|
|
mbar->Enable(ID_GO, false);
|
|
mbar->Enable(ID_STOP, false);
|
|
|
|
tbar->EnableTool(ID_GO, false);
|
|
tbar->EnableTool(ID_STOP, false);
|
|
}
|
|
else {
|
|
mbar->Enable(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
|
|
mbar->Enable(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
|
|
|
|
tbar->EnableTool(ID_GO, (mScript->GetLastPosition() > 0) && !mRunning);
|
|
tbar->EnableTool(ID_STOP, (mScript->GetLastPosition() > 0) && mRunning);
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnScriptUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (mScriptBox && mScript && FindFocus() == mScript) {
|
|
wxString label = mScriptBox->GetLabel();
|
|
if (label == _("Script")) {
|
|
label += wxT("*");
|
|
mScriptBox->SetLabel(label);
|
|
mOutputBox->SetLabel(_("Output"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void NyqBench::OnOutputUpdate(wxUpdateUIEvent & e)
|
|
{
|
|
if (mOutputBox && mOutput && FindFocus() == mOutput) {
|
|
wxString label = mOutputBox->GetLabel();
|
|
if (label == _("Output")) {
|
|
label += wxT("*");
|
|
mOutputBox->SetLabel(label);
|
|
mScriptBox->SetLabel(_("Script"));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool NyqBench::Validate()
|
|
{
|
|
if (mScript->GetLastPosition() > 0 && mScript->IsModified()) {
|
|
int ans;
|
|
ans = AudacityMessageBox(_("Code has been modified. Are you sure?"),
|
|
_("Warning"),
|
|
wxYES_NO | wxICON_QUESTION,
|
|
this);
|
|
if (ans == wxNO) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void NyqBench::SetWindowTitle()
|
|
{
|
|
wxString name = _("Untitled");
|
|
|
|
if (!mPath.GetFullPath().IsEmpty()) {
|
|
name = mPath.GetFullName();
|
|
}
|
|
|
|
SetTitle(_("Nyquist Effect Workbench - ") + name);
|
|
}
|
|
|
|
void NyqBench::RecreateToolbar(bool large)
|
|
{
|
|
mLargeIcons = large;
|
|
|
|
wxToolBar *tb = GetToolBar();
|
|
if (tb) {
|
|
delete tb;
|
|
}
|
|
tb = CreateToolBar();
|
|
|
|
wxSize sz;
|
|
|
|
if (!mLargeIcons) {
|
|
tb->SetToolBitmapSize(wxSize(16, 16));
|
|
mPics[0] = wxBitmap(document_new_small);
|
|
mPics[1] = wxBitmap(document_open_small);
|
|
mPics[2] = wxBitmap(document_save_as_small);
|
|
mPics[3] = wxBitmap(document_save_small);
|
|
mPics[4] = wxBitmap(edit_copy_small);
|
|
mPics[5] = wxBitmap(edit_cut_small);
|
|
mPics[6] = wxBitmap(edit_paste_small);
|
|
mPics[7] = wxBitmap(edit_clear_small);
|
|
mPics[8] = wxBitmap(edit_delete_small);
|
|
mPics[9] = wxBitmap(edit_select_all_small);
|
|
mPics[10] = wxBitmap(edit_undo_small);
|
|
mPics[11] = wxBitmap(edit_redo_small);
|
|
mPics[12] = wxBitmap(edit_find_small);
|
|
mPics[13] = wxBitmap(system_search_small);
|
|
mPics[14] = wxBitmap(go_top_small);
|
|
mPics[15] = wxBitmap(go_up_small);
|
|
mPics[16] = wxBitmap(go_previous_small);
|
|
mPics[17] = wxBitmap(go_next_small);
|
|
mPics[18] = wxBitmap(media_playback_start_small);
|
|
mPics[19] = wxBitmap(media_playback_stop_small);
|
|
}
|
|
else {
|
|
tb->SetToolBitmapSize(wxSize(32, 32));
|
|
mPics[0] = wxBitmap(document_new_large);
|
|
mPics[1] = wxBitmap(document_open_large);
|
|
mPics[2] = wxBitmap(document_save_as_large);
|
|
mPics[3] = wxBitmap(document_save_large);
|
|
mPics[4] = wxBitmap(edit_copy_large);
|
|
mPics[5] = wxBitmap(edit_cut_large);
|
|
mPics[6] = wxBitmap(edit_paste_large);
|
|
mPics[7] = wxBitmap(edit_clear_large);
|
|
mPics[8] = wxBitmap(edit_delete_large);
|
|
mPics[9] = wxBitmap(edit_select_all_large);
|
|
mPics[10] = wxBitmap(edit_undo_large);
|
|
mPics[11] = wxBitmap(edit_redo_large);
|
|
mPics[12] = wxBitmap(edit_find_large);
|
|
mPics[13] = wxBitmap(system_search_large);
|
|
mPics[14] = wxBitmap(go_top_large);
|
|
mPics[15] = wxBitmap(go_up_large);
|
|
mPics[16] = wxBitmap(go_previous_large);
|
|
mPics[17] = wxBitmap(go_next_large);
|
|
mPics[18] = wxBitmap(media_playback_start_large);
|
|
mPics[19] = wxBitmap(media_playback_stop_large);
|
|
}
|
|
|
|
tb->SetMargins(2, 2);
|
|
|
|
tb->AddTool(wxID_NEW, _("New"), mPics[0], _("New script"));
|
|
tb->AddTool(wxID_OPEN, _("Open"), mPics[1], _("Open script"));
|
|
tb->AddTool(wxID_SAVE, _("Save"), mPics[2], _("Save script"));
|
|
tb->AddTool(wxID_SAVEAS, _("Save As"), mPics[3], _("Save script as..."));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_COPY, _("Copy"), mPics[4], _("Copy to clipboard"));
|
|
tb->AddTool(wxID_CUT, _("Cut"), mPics[5], _("Cut to clipboard"));
|
|
tb->AddTool(wxID_PASTE, _("Paste"), mPics[6], _("Paste from clipboard"));
|
|
tb->AddTool(wxID_CLEAR, _("Clear"), mPics[7], _("Clear selection"));
|
|
tb->AddTool(wxID_SELECTALL, _("Select All"), mPics[9], _("Select all text"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_UNDO, _("Undo"), mPics[10], _("Undo last change"));
|
|
tb->AddTool(wxID_REDO, _("Redo"), mPics[11], _("Redo previous change"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(wxID_FIND, _("Find"), mPics[12], _("Find text"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(ID_MATCH, _("Match"), mPics[13], _("Go to matching paren"));
|
|
tb->AddTool(ID_TOP, _("Top"), mPics[14], _("Go to top S-expr"));
|
|
tb->AddTool(ID_UP, _("Up"), mPics[15], _("Go to higher S-expr"));
|
|
tb->AddTool(ID_PREVIOUS, _("Previous"), mPics[16], _("Go to previous S-expr"));
|
|
tb->AddTool(ID_NEXT, _("Next"), mPics[17], _("Go to next S-expr"));
|
|
tb->AddSeparator();
|
|
tb->AddTool(ID_GO, _("Start"), mPics[18], _("Start script"));
|
|
tb->AddTool(ID_STOP, _("Stop"), mPics[19], _("Stop script"));
|
|
|
|
tb->Realize();
|
|
|
|
Layout();
|
|
Fit();
|
|
SetMinSize(GetSize());
|
|
}
|
|
|
|
void NyqBench::LoadFile()
|
|
{
|
|
wxString path = mPath.GetFullPath();
|
|
|
|
if (path.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
wxFFile f(path);
|
|
if (f.IsOpened()) {
|
|
wxString t;
|
|
if (f.ReadAll(&t)) {
|
|
//#if defined(__WXGTK__) || defined(__WXMAC__)
|
|
t.Replace(wxT("\r\n"), wxT("\n"));
|
|
t.Replace(wxT("\r"), wxT("\n"));
|
|
//#elif defined(__WXMSW__)
|
|
// t.Replace("\r\n", "\n");
|
|
//#endif
|
|
mScript->SetValue(t);
|
|
mScript->DiscardEdits();
|
|
}
|
|
}
|
|
|
|
// mScript->LoadFile(mPath.GetFullPath());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Connects Audacity menu item to an action in this dll.
|
|
// Only one action implemented so far.
|
|
//----------------------------------------------------------------------------
|
|
void NyqBench::ShowNyqBench(const CommandContext &)
|
|
{
|
|
Show();
|
|
}
|